diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index f03573e31..eee21c18e 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -1,24 +1,24 @@ //////////////////////////////////////////////////////////////// // -// Chromatic Aberration Auto-correction +// Chromatic Aberration Auto-correction // -// copyright (c) 2008-2010 Emil Martinec +// copyright (c) 2008-2010 Emil Martinec // // // code dated: November 26, 2010 // -// CA_correct_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// CA_correct_RT.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -45,969 +45,1103 @@ int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* // //============================================================================== - double fMaxElem; - double fAcc; + double fMaxElem; + double fAcc; - int i, j, k, m; + int i, j, k, m; - for(k=0; k<(nDim-1); k++) {// base row of matrix - // search of line with max element - fMaxElem = fabsf( pfMatr[k*nDim + k] ); - m = k; - for (i=k+1; i=0; k--) { - pfSolution[k] = pfVect[k]; - for(i=(k+1); i= 0; k--) { + pfSolution[k] = pfVect[k]; + + for(i = (k + 1); i < nDim; i++) { + pfSolution[k] -= (pfMatr[k * nDim + i] * pfSolution[i]); + } + + pfSolution[k] = pfSolution[k] / pfMatr[k * nDim + k]; + } + + return 0; } //end of linear equation solver //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::CA_correct_RT(double cared, double cablue) { +void RawImageSource::CA_correct_RT(double cared, double cablue) +{ // multithreaded by Ingo Weyrich -#define TS 128 // Tile size -#define TSH 64 // Half Tile size +#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;} } - // 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"); - return; - } - - volatile double progress = 0.0; - if(plistener) plistener->setProgress (progress); + // 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"); + return; + } - bool autoCA = (cared==0 && cablue==0); - // local variables - int width=W, height=H; - //temporary array to store simple interpolation of G - float (*Gtmp); - Gtmp = (float (*)) calloc ((height)*(width), sizeof *Gtmp); + volatile double progress = 0.0; - // 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); + if(plistener) { + plistener->setProgress (progress); + } - 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]; + bool autoCA = (cared == 0 && cablue == 0); + // local variables + int width = W, height = H; + //temporary array to store simple interpolation of G + float (*Gtmp); + Gtmp = (float (*)) calloc ((height) * (width), sizeof * Gtmp); - // Because we can't break parallel processing, we need a switch do handle the errors - bool processpasstwo = true; + // 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); - //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 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]; + + // Because we can't break parallel processing, we need a switch do handle the errors + bool processpasstwo = true; + + //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 - const int border=8; - const int border2=16; + 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 vz1, hz1; - int vblsz, hblsz; - vblsz=ceil((float)(height+border2)/(TS-border2)+2+vz1); - hblsz=ceil((float)(width+border2)/(TS-border2)+2+hz1); + if((height + border2) % (TS - border2) == 0) { + vz1 = 1; + } else { + vz1 = 0; + } - 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))); + if((width + border2) % (TS - border2) == 0) { + hz1 = 1; + } else { + hz1 = 0; + } - double fitparams[3][2][16]; + int vblsz, hblsz; + vblsz = ceil((float)(height + border2) / (TS - border2) + 2 + vz1); + hblsz = ceil((float)(width + border2) / (TS - border2) + 2 + hz1); - //order of 2d polynomial fit (polyord), and numpar=polyord^2 - int polyord=4, numpar=16; + 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))); -#pragma omp parallel shared(Gtmp,width,height,blockave,blocksqave,blockdenom,blockvar,blockwt,blockshifts,fitparams,polyord,numpar) -{ - int progresscounter = 0; + double fitparams[3][2][16]; - 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; + //order of 2d polynomial fit (polyord), and numpar=polyord^2 + int polyord = 4, numpar = 16; - float eps=1e-5f, eps2=1e-10f; //tolerance to avoid dividing by zero + #pragma omp parallel shared(Gtmp,width,height,blockave,blocksqave,blockdenom,blockvar,blockwt,blockshifts,fitparams,polyord,numpar) + { + int progresscounter = 0; - //adaptive weights for green interpolation - float wtu, wtd, wtl, wtr; - //local quadratic fit to shift data within a tile - float coeff[2][3][3]; - //measured CA shift parameters for a tile - float CAshift[2][3]; - //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]; + 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; - //low and high pass 1D filters of G in vertical/horizontal directions - float glpfh, glpfv; + float eps = 1e-5f, eps2 = 1e-10f; //tolerance to avoid dividing by zero - //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 + //adaptive weights for green interpolation + float wtu, wtd, wtl, wtr; + //local quadratic fit to shift data within a tile + float coeff[2][3][3]; + //measured CA shift parameters for a tile + float CAshift[2][3]; + //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]; - //block CA shift values and weight assigned to block + //low and high pass 1D filters of G in vertical/horizontal directions + float glpfh, glpfv; - 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 + //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); + /* 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; + char *data; + data = buffer; // buffers aligned to size of cacheline -// 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); - - - if (autoCA) { - // Main algorithm: Tile loop -#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;} - - // 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[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; rr0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr0 && ccmax0) { - for (rr=0; rr-1 && row-1 && col>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]))); - rbhpfh[indx>>1] = fabsf(fabsf((rgb[1][indx]-rgb[c][indx])-(rgb[1][indx+4]-rgb[c][indx+4])) + - 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]); - } - areawt[0][0]=areawt[1][0]=1; - areawt[0][2]=areawt[1][2]=1; - - // 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=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) { - -// 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 - - //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]); - - 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]); - - 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; - - //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]); - - 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]); - - 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; - - // 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 (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) { - - - 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 - - //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])); - - 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]++; - } - - //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])); - - 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]++; - } - - // 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]) ; - } else { - CAshift[j][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]); - - //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; - } - }//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]); - } - if(plistener) { - progresscounter++; - if(progresscounter % 8 == 0) -#pragma omp critical - { - progress+=(double)(8.0*(TS-border2)*(TS-border2))/(2*height*width); - if (progress>1.0) - { - progress=1.0; - } - plistener->setProgress(progress); - } - } - - } - - //end of diagnostic pass -#pragma omp critical -{ - 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]; - } -} -#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]); - } else { - processpasstwo = false; - printf ("blockdenom vanishes \n"); - break; - } - } - //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; vblock4.0*blockvar[0][c] || SQR(bstemp[1])>4.0*blockvar[1][c]) - continue; - numblox[c]++; - for (dir=0; dir<2; dir++) { - for (i=0; iheight) {rrmax=height-top;} else {rrmax=rr1;} - if (right>width) {ccmax=width-left;} else {ccmax=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; - 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]; - } - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //fill borders - if (rrmin>0) { - for (rr=0; rr0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr0 && ccmax0) { - for (rr=0; rr-1 && row-1 && col0) { - 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; - } - - } - - - 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 - - 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 - //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; - } - - 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) { - - //if (rgb[indx][c]>clip_pt || Gtmp[indx]>clip_pt) continue; - - grbdiffold = rgb[1][indx]-rgb[c][indx]; - - //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]; - //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; - - //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point - RBint=rgb[1][indx]-grbdiffint; - - if (fabsf(RBint-rgb[c][indx])<0.25f*(RBint+rgb[c][indx])) { - if (fabsf(grbdiffold)>fabsf(grbdiffint) ) { - rgb[c][indx]=RBint; - } - } 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])); - - 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]); - - //now determine R/B at grid points using interpolated color 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 (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 (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 - } - } - - if(plistener) { - progresscounter++; - if(progresscounter % 8 == 0) -#pragma omp critical - { - progress+=(double)(8.0*(TS-border2)*(TS-border2))/(2*height*width); - if (progress>1.0) - { - progress=1.0; - } - plistener->setProgress(progress); - } - } - - } - -#pragma omp barrier +// 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); + + + if (autoCA) { + // Main algorithm: Tile loop + #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; + } + + // 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[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]; + } + } + + 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 + } + } + + 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]; + } + } + + 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 + } + } + + //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 + } + } + + 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 + } + } + + 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 + } + } + + 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 + } + } + + //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); + + 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 + 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 && col > -1 && col < width) { + Gtmp[row * width + col] = rgb[1][indx]; + } + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + 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) { + + + 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]))); + rbhpfh[indx >> 1] = fabsf(fabsf((rgb[1][indx] - rgb[c][indx]) - (rgb[1][indx + 4] - rgb[c][indx + 4])) + + 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]); + } + + areawt[0][0] = areawt[1][0] = 1; + areawt[0][2] = areawt[1][2] = 1; + + // 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 = 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) { + +// 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 + + //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]); + + 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]); + + 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; + + //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]); + + 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]); + + 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; + + // 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 (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) { + + + 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 + + //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])); + + 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]++; + } + + //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])); + + 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]++; + } + + // 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]) ; + } else { + CAshift[j][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]); + + //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; + } + }//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]); + } + + if(plistener) { + progresscounter++; + + if(progresscounter % 8 == 0) + #pragma omp critical + { + progress += (double)(8.0 * (TS - border2) * (TS - border2)) / (2 * height * width); + + if (progress > 1.0) { + progress = 1.0; + } + + plistener->setProgress(progress); + } + } + + } + + //end of diagnostic pass + #pragma omp critical + { + 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]; + } + } + #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]); + } else { + processpasstwo = false; + printf ("blockdenom vanishes \n"); + break; + } + } + + //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++) { + 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++) { + blockshifts[hblock][c][i] = blockshifts[2 * hblsz + hblock][c][i]; + blockshifts[(vblsz - 1)*hblsz + hblock][c][i] = blockshifts[(vblsz - 3) * hblsz + hblock][c][i]; + } + } + } + + //end of filling border pixels of blockshift array + + //initialize fit arrays + double polymat[3][2][256], shiftmat[3][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 (i = 0; i < 16; i++) { + shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[2][0][i] = shiftmat[2][1][i] = 0; + } + + int numblox[3] = {0, 0, 0}; + + float bstemp[2]; + + for (vblock = 1; vblock < vblsz - 1; vblock++) + for (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++) { + 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]; + p[3] = blockshifts[(vblock) * hblsz + hblock - 1][c][dir]; + p[4] = blockshifts[(vblock) * hblsz + hblock][c][dir]; + p[5] = blockshifts[(vblock) * hblsz + hblock + 1][c][dir]; + 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]); + 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]) { + 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]; + } + + shiftmat[c][dir][(polyord * i + j)] += (float)pow((double)vblock, i) * pow((double)hblock, j) * bstemp[dir] * blockwt[vblock * hblsz + hblock]; + } + + //if (c==0 && dir==0) {printf("i= %d j= %d shiftmat= %f \n",i,j,shiftmat[c][dir][(polyord*i+j)]);} + }//monomials + }//dir + + }//c + }//blocks + + numblox[1] = min(numblox[0], numblox[2]); + + //if too few data points, restrict the order of the fit to linear + if (numblox[1] < 32) { + polyord = 2; + numpar = 4; + + if (numblox[1] < 10) { + + printf ("numblox = %d \n", numblox[1]); + processpasstwo = false; + } + } + + 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); + processpasstwo = false; + } + } + + } + + //fitparams[polyord*i+j] gives the coefficients of (vblock^i hblock^j) in a polynomial fit for i,j<=4 + } + //end of initialization for CA correction pass + //only executed if cared and cablue are zero + } + + // Main algorithm: Tile loop + 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; + + //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; + } + + // 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; + 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]; + } + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //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]; + } + } + + 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]; + } + } + + 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]; + } + } + + 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)]; + } + } + + //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]; + } + } + + 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)]; + } + } + + 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)]; + } + } + + 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)]; + } + } + + //end of border fill + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + 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); + + 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])); + + //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 && col > -1 && col < width) { + Gtmp[row * width + col] = rgb[1][indx]; + } + } + + 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; + } 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++) { + //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]; + } + + 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); + }//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) { + + //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]; + + 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]; + + + 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; + } + + } + + + 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 + + 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 + //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; + } + + 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) { + + //if (rgb[indx][c]>clip_pt || Gtmp[indx]>clip_pt) continue; + + grbdiffold = rgb[1][indx] - rgb[c][indx]; + + //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]; + //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; + + //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point + RBint = rgb[1][indx] - grbdiffint; + + if (fabsf(RBint - rgb[c][indx]) < 0.25f * (RBint + rgb[c][indx])) { + if (fabsf(grbdiffold) > fabsf(grbdiffint) ) { + rgb[c][indx] = RBint; + } + } 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])); + + 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]); + + //now determine R/B at grid points using interpolated color 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 (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 (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 + } + } + + if(plistener) { + progresscounter++; + + if(progresscounter % 8 == 0) + #pragma omp critical + { + progress += (double)(8.0 * (TS - border2) * (TS - border2)) / (2 * height * width); + + if (progress > 1.0) { + progress = 1.0; + } + + plistener->setProgress(progress); + } + } + + } + + #pragma omp barrier // copy temporary image matrix back to image matrix -#pragma omp for - for(row=0;row>1;col> 1; col < width; col += 2, indx++) { + rawData[row][col] = RawDataTmp[indx]; + } + + } + + // clean up + free(buffer); -} + } - free(Gtmp); - free(buffer1); - free(RawDataTmp); - if(plistener) - plistener->setProgress(1.0); + free(Gtmp); + free(buffer1); + free(RawDataTmp); + + if(plistener) { + plistener->setProgress(1.0); + } #undef TS #undef TSH diff --git a/rtengine/EdgePreserveLab.cc b/rtengine/EdgePreserveLab.cc index 36cb7d5c3..1f063ec0c 100644 --- a/rtengine/EdgePreserveLab.cc +++ b/rtengine/EdgePreserveLab.cc @@ -13,215 +13,250 @@ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -EdgePreserveLab::EdgePreserveLab(unsigned int width, unsigned int height){ - w = width; - h = height; - n = w*h; +EdgePreserveLab::EdgePreserveLab(unsigned int width, unsigned int height) +{ + w = width; + h = height; + n = w * h; - //Initialize the matrix just once at construction. - A = new MultiDiagonalSymmetricMatrix(n, 5); - if(!( - A->CreateDiagonal(0, 0) && - A->CreateDiagonal(1, 1) && - A->CreateDiagonal(2, w - 1) && - A->CreateDiagonal(3, w) && - A->CreateDiagonal(4, w + 1))){ - delete A; - A = NULL; - printf("Error in EdgePreserveLab construction: out of memory.\n"); - }else{ - a0 = A->Diagonals[0]; - a_1 = A->Diagonals[1]; - a_w1 = A->Diagonals[2]; - a_w = A->Diagonals[3]; - a_w_1 = A->Diagonals[4]; - } + //Initialize the matrix just once at construction. + A = new MultiDiagonalSymmetricMatrix(n, 5); + + if(!( + A->CreateDiagonal(0, 0) && + A->CreateDiagonal(1, 1) && + A->CreateDiagonal(2, w - 1) && + A->CreateDiagonal(3, w) && + A->CreateDiagonal(4, w + 1))) { + delete A; + A = NULL; + printf("Error in EdgePreserveLab construction: out of memory.\n"); + } else { + a0 = A->Diagonals[0]; + a_1 = A->Diagonals[1]; + a_w1 = A->Diagonals[2]; + a_w = A->Diagonals[3]; + a_w_1 = A->Diagonals[4]; + } } -EdgePreserveLab::~EdgePreserveLab(){ - delete A; +EdgePreserveLab::~EdgePreserveLab() +{ + delete A; } -float *EdgePreserveLab::CreateBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, float *Blur, bool UseBlurForEdgeStop){ - if(Blur == NULL) - UseBlurForEdgeStop = false, //Use source if there's no supplied Blur. - Blur = new float[3*n]; - if(LScale == 0.0f){ - memcpy(Blur, Source, 3*n*sizeof(float)); - return Blur; - } +float *EdgePreserveLab::CreateBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, float *Blur, bool UseBlurForEdgeStop) +{ + if(Blur == NULL) + UseBlurForEdgeStop = false, //Use source if there's no supplied Blur. + Blur = new float[3 * n]; - //Create the edge stopping function a, rotationally symmetric and just one instead of (ax, ay). Maybe don't need Blur yet, so use its memory. - float *a, *b, *g; - if(UseBlurForEdgeStop) a = new float[n], g = Blur; - else a = Blur, g = Source; - //b = new float[n]; - - unsigned int x, y, i; - unsigned int w1 = w - 1, h1 = h - 1; - float eps = 0.0001f; - float scL = powf(100.0f,LScale); - float scab = powf(200.0f,abScale); - - float * var = new float[w*h]; - rtengine::boxvar(g, var, 1, 1, w, h); + if(LScale == 0.0f) { + memcpy(Blur, Source, 3 * n * sizeof(float)); + return Blur; + } + + //Create the edge stopping function a, rotationally symmetric and just one instead of (ax, ay). Maybe don't need Blur yet, so use its memory. + float *a, *b, *g; + + if(UseBlurForEdgeStop) { + a = new float[n], g = Blur; + } else { + a = Blur, g = Source; + } + + //b = new float[n]; + + unsigned int x, y, i; + unsigned int w1 = w - 1, h1 = h - 1; + float eps = 0.0001f; + float scL = powf(100.0f, LScale); + float scab = powf(200.0f, abScale); + + float * var = new float[w * h]; + rtengine::boxvar(g, var, 1, 1, w, h); #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(y = 0; y < h1; y++){ - float *rg = &g[w*y]; - for(x = 0; x < w1; x++){ - //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. - /*float gx = (fabs((rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]))); - float gy = (fabs((rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]))); - - //TODO: combine this with gx, gy if not needing separate quantities - float hx = (fabs((rg[x + 1 + n] - rg[x + n]) + (rg[x + w + 1 + n] - rg[x + w + n])) + \ - fabs((rg[x + 1 + 2*n] - rg[x + 2*n]) + (rg[x + w + 1 + 2*n] - rg[x + w + 2*n]))); - float hy = (fabs((rg[x + w + n] - rg[x + n]) + (rg[x + w + 1 + n] - rg[x + 1 + n])) + \ - fabs((rg[x + w + 2*n] - rg[x + 2*n]) + (rg[x + w + 1 + 2*n] - rg[x + 1 + 2*n]))); - */ - //float gradtot = (gx+gy+hx+hy); - //gradhisto[MAX(0,MIN(32767,(int)gradtot))] ++; - - //Apply power to the magnitude of the gradient to get the edge stopping function. - //a[x + w*y] = scL*expf(-100.0f*(gx + gy + hx + hy)/(EdgeStoppingLuma)); - //a[x + w*y] = scL*expf(-var[y*w+x]/SQR(0.02*EdgeStoppingLuma));///(0.1+rg[x]); - a[x + w*y] = scL*expf(-50.0f*sqrt(var[y*w+x])/(EdgeStoppingLuma+eps));///(0.1+rg[x]); - //b[x + w*y] = (scab)*expf(-20.0f*(gx + gy + Lave*(hx + hy))/(EdgeStoppingChroma)); - //b[x + w*y] = (scab)*expf(-400.0f*SQR(gx + gy + Lave*(hx + hy))/SQR(EdgeStoppingChroma));; + for(y = 0; y < h1; y++) { + float *rg = &g[w * y]; - } - } + for(x = 0; x < w1; x++) { + //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. + /*float gx = (fabs((rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]))); + float gy = (fabs((rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]))); - /* Now setup the linear problem. I use the Maxima CAS, here's code for making an FEM formulation for the smoothness term: - p(x, y) := (1 - x)*(1 - y); - P(m, n) := A[m][n]*p(x, y) + A[m + 1][n]*p(1 - x, y) + A[m + 1][n + 1]*p(1 - x, 1 - y) + A[m][n + 1]*p(x, 1 - y); - Integrate(f) := integrate(integrate(f, x, 0, 1), y, 0, 1); + //TODO: combine this with gx, gy if not needing separate quantities + float hx = (fabs((rg[x + 1 + n] - rg[x + n]) + (rg[x + w + 1 + n] - rg[x + w + n])) + \ + fabs((rg[x + 1 + 2*n] - rg[x + 2*n]) + (rg[x + w + 1 + 2*n] - rg[x + w + 2*n]))); + float hy = (fabs((rg[x + w + n] - rg[x + n]) + (rg[x + w + 1 + n] - rg[x + 1 + n])) + \ + fabs((rg[x + w + 2*n] - rg[x + 2*n]) + (rg[x + w + 1 + 2*n] - rg[x + 1 + 2*n]))); + */ + //float gradtot = (gx+gy+hx+hy); + //gradhisto[MAX(0,MIN(32767,(int)gradtot))] ++; - Integrate(diff(P(u, v), x)*diff(p(x, y), x) + diff(P(u, v), y)*diff(p(x, y), y)); - Integrate(diff(P(u - 1, v), x)*diff(p(1 - x, y), x) + diff(P(u - 1, v), y)*diff(p(1 - x, y), y)); - Integrate(diff(P(u - 1, v - 1), x)*diff(p(1 - x, 1 - y), x) + diff(P(u - 1, v - 1), y)*diff(p(1 - x, 1 - y), y)); - Integrate(diff(P(u, v - 1), x)*diff(p(x, 1 - y), x) + diff(P(u, v - 1), y)*diff(p(x, 1 - y), y)); - So yeah. Use the numeric results of that to fill the matrix A.*/ - memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); - memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); - memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); - memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); + //Apply power to the magnitude of the gradient to get the edge stopping function. + //a[x + w*y] = scL*expf(-100.0f*(gx + gy + hx + hy)/(EdgeStoppingLuma)); + //a[x + w*y] = scL*expf(-var[y*w+x]/SQR(0.02*EdgeStoppingLuma));///(0.1+rg[x]); + a[x + w * y] = scL * expf(-50.0f * sqrt(var[y * w + x]) / (EdgeStoppingLuma + eps)); ///(0.1+rg[x]); + + //b[x + w*y] = (scab)*expf(-20.0f*(gx + gy + Lave*(hx + hy))/(EdgeStoppingChroma)); + //b[x + w*y] = (scab)*expf(-400.0f*SQR(gx + gy + Lave*(hx + hy))/SQR(EdgeStoppingChroma));; + + } + } + + /* Now setup the linear problem. I use the Maxima CAS, here's code for making an FEM formulation for the smoothness term: + p(x, y) := (1 - x)*(1 - y); + P(m, n) := A[m][n]*p(x, y) + A[m + 1][n]*p(1 - x, y) + A[m + 1][n + 1]*p(1 - x, 1 - y) + A[m][n + 1]*p(x, 1 - y); + Integrate(f) := integrate(integrate(f, x, 0, 1), y, 0, 1); + + Integrate(diff(P(u, v), x)*diff(p(x, y), x) + diff(P(u, v), y)*diff(p(x, y), y)); + Integrate(diff(P(u - 1, v), x)*diff(p(1 - x, y), x) + diff(P(u - 1, v), y)*diff(p(1 - x, y), y)); + Integrate(diff(P(u - 1, v - 1), x)*diff(p(1 - x, 1 - y), x) + diff(P(u - 1, v - 1), y)*diff(p(1 - x, 1 - y), y)); + Integrate(diff(P(u, v - 1), x)*diff(p(x, 1 - y), x) + diff(P(u, v - 1), y)*diff(p(x, 1 - y), y)); + So yeah. Use the numeric results of that to fill the matrix A.*/ + memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); + memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); + memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); + memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); //TODO: OMP here? - for(i = y = 0; y != h; y++){ - for(x = 0; x != w; x++, i++){ - float ac; - a0[i] = 1.0; + for(i = y = 0; y != h; y++) { + for(x = 0; x != w; x++, i++) { + float ac; + a0[i] = 1.0; - //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. - if(x > 0 && y > 0) - ac = a[i - w - 1]/6.0f, - a_w_1[i - w - 1] -= 2.0f*ac, a_w[i - w] -= ac, - a_1[i - 1] -= ac, a0[i] += 4.0f*ac; + //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. + if(x > 0 && y > 0) + ac = a[i - w - 1] / 6.0f, + a_w_1[i - w - 1] -= 2.0f * ac, a_w[i - w] -= ac, + a_1[i - 1] -= ac, a0[i] += 4.0f * ac; - if(x < w1 && y > 0) - ac = a[i - w]/6.0f, - a_w[i - w] -= ac, a_w1[i - w + 1] -= 2.0f*ac, - a0[i] += 4.0f*ac; + if(x < w1 && y > 0) + ac = a[i - w] / 6.0f, + a_w[i - w] -= ac, a_w1[i - w + 1] -= 2.0f * ac, + a0[i] += 4.0f * ac; - if(x > 0 && y < h1) - ac = a[i - 1]/6.0f, - a_1[i - 1] -= ac, a0[i] += 4.0f*ac; + if(x > 0 && y < h1) + ac = a[i - 1] / 6.0f, + a_1[i - 1] -= ac, a0[i] += 4.0f * ac; - if(x < w1 && y < h1) - a0[i] += 4.0f*a[i]/6.0f; - } - } - if(UseBlurForEdgeStop) delete[] a; - + if(x < w1 && y < h1) { + a0[i] += 4.0f * a[i] / 6.0f; + } + } + } - //Solve & return. - A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). - if(!UseBlurForEdgeStop) memcpy(Blur, Source, 3*n*sizeof(float)); - // blur L channel - SparseConjugateGradient(A->PassThroughVectorProduct, Source, n, false, Blur, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - - //reset A for ab channels - /*memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); - memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); - memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); - memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); - for(i = y = 0; y != h; y++){ - for(x = 0; x != w; x++, i++){ - float ac; - a0[i] = 1.0; - - //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. - if(x > 0 && y > 0) - ac = b[i - w - 1]/6.0f, - a_w_1[i - w - 1] -= 2.0f*ac, a_w[i - w] -= ac, - a_1[i - 1] -= ac, a0[i] += 4.0f*ac; - - if(x < w1 && y > 0) - ac = b[i - w]/6.0f, - a_w[i - w] -= ac, a_w1[i - w + 1] -= 2.0f*ac, - a0[i] += 4.0f*ac; - - if(x > 0 && y < h1) - ac = b[i - 1]/6.0f, - a_1[i - 1] -= ac, a0[i] += 4.0f*ac; - - if(x < w1 && y < h1) - a0[i] += 4.0f*b[i]/6.0f; - } - }*/ - /*if(UseBlurForEdgeStop)*/ //delete[] b; - - // blur ab channels - //A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). - //SparseConjugateGradient(A->PassThroughVectorProduct, Source+n, n, false, Blur+n, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - //SparseConjugateGradient(A->PassThroughVectorProduct, Source+2*n, n, false, Blur+2*n, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - - A->KillIncompleteCholeskyFactorization(); - return Blur; + if(UseBlurForEdgeStop) { + delete[] a; + } + + + //Solve & return. + A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). + + if(!UseBlurForEdgeStop) { + memcpy(Blur, Source, 3 * n * sizeof(float)); + } + + // blur L channel + SparseConjugateGradient(A->PassThroughVectorProduct, Source, n, false, Blur, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); + + //reset A for ab channels + /*memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); + memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); + memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); + memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); + for(i = y = 0; y != h; y++){ + for(x = 0; x != w; x++, i++){ + float ac; + a0[i] = 1.0; + + //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. + if(x > 0 && y > 0) + ac = b[i - w - 1]/6.0f, + a_w_1[i - w - 1] -= 2.0f*ac, a_w[i - w] -= ac, + a_1[i - 1] -= ac, a0[i] += 4.0f*ac; + + if(x < w1 && y > 0) + ac = b[i - w]/6.0f, + a_w[i - w] -= ac, a_w1[i - w + 1] -= 2.0f*ac, + a0[i] += 4.0f*ac; + + if(x > 0 && y < h1) + ac = b[i - 1]/6.0f, + a_1[i - 1] -= ac, a0[i] += 4.0f*ac; + + if(x < w1 && y < h1) + a0[i] += 4.0f*b[i]/6.0f; + } + }*/ + /*if(UseBlurForEdgeStop)*/ //delete[] b; + + // blur ab channels + //A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). + //SparseConjugateGradient(A->PassThroughVectorProduct, Source+n, n, false, Blur+n, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); + //SparseConjugateGradient(A->PassThroughVectorProduct, Source+2*n, n, false, Blur+2*n, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); + + A->KillIncompleteCholeskyFactorization(); + return Blur; } -float *EdgePreserveLab::CreateIteratedBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, unsigned int Reweightings, float *Blur){ - //Simpler outcome? - if(Reweightings == 0) return CreateBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Blur); +float *EdgePreserveLab::CreateIteratedBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, unsigned int Reweightings, float *Blur) +{ + //Simpler outcome? + if(Reweightings == 0) { + return CreateBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Blur); + } - //Create a blur here, initialize. - if(Blur == NULL) Blur = new float[3*n]; - memcpy(Blur, Source, 3*n*sizeof(float)); + //Create a blur here, initialize. + if(Blur == NULL) { + Blur = new float[3 * n]; + } - //Iteratively improve the blur. - Reweightings++; - for(unsigned int i = 0; i != Reweightings; i++) - CreateBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Blur, true); + memcpy(Blur, Source, 3 * n * sizeof(float)); - return Blur; + //Iteratively improve the blur. + Reweightings++; + + for(unsigned int i = 0; i != Reweightings; i++) { + CreateBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Blur, true); + } + + return Blur; } -float *EdgePreserveLab::CompressDynamicRange(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, float CompressionExponent, float DetailBoost, unsigned int Iterates, unsigned int Reweightings, float *Compressed){ - //We're working with luminance, which does better logarithmic. - unsigned int i; - //for(i = 0; i != n; i++) - // Source[i] = logf(Source[i] + 0.0001f); - - //Blur. Also setup memory for Compressed (we can just use u since each element of u is used in one calculation). - float *u = CreateIteratedBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Reweightings); - if(Compressed == NULL) Compressed = u; - - //Apply compression, detail boost, unlogging. Compression is done on the logged data and detail boost on unlogged. - for(i = 0; i != n; i++){ - //float ce = expf(Source[i] + u[i]*(CompressionExponent - 1.0f)) - 0.0001f; - //float ue = expf(u[i]) - 0.0001f; - //Source[i] = expf(Source[i]) - 0.0001f; - //Compressed[i] = ce + DetailBoost*(Source[i] - ue); - Compressed[i] = u[i];//ue;//for testing, to display blur - } - - if(Compressed != u) delete[] u; - return Compressed; +float *EdgePreserveLab::CompressDynamicRange(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, float CompressionExponent, float DetailBoost, unsigned int Iterates, unsigned int Reweightings, float *Compressed) +{ + //We're working with luminance, which does better logarithmic. + unsigned int i; + //for(i = 0; i != n; i++) + // Source[i] = logf(Source[i] + 0.0001f); + + //Blur. Also setup memory for Compressed (we can just use u since each element of u is used in one calculation). + float *u = CreateIteratedBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Reweightings); + + if(Compressed == NULL) { + Compressed = u; + } + + //Apply compression, detail boost, unlogging. Compression is done on the logged data and detail boost on unlogged. + for(i = 0; i != n; i++) { + //float ce = expf(Source[i] + u[i]*(CompressionExponent - 1.0f)) - 0.0001f; + //float ue = expf(u[i]) - 0.0001f; + //Source[i] = expf(Source[i]) - 0.0001f; + //Compressed[i] = ce + DetailBoost*(Source[i] - ue); + Compressed[i] = u[i];//ue;//for testing, to display blur + } + + if(Compressed != u) { + delete[] u; + } + + return Compressed; } diff --git a/rtengine/EdgePreserveLab.h b/rtengine/EdgePreserveLab.h index 70e97442c..e365956c5 100644 --- a/rtengine/EdgePreserveLab.h +++ b/rtengine/EdgePreserveLab.h @@ -6,37 +6,37 @@ image. As a byproduct it contains a lot of linear algebra which can be useful fo you want to solve in rectangles on rectangular grids. Anyway. Basically, this is an implementation of what's presented in the following papers: - Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation - An Iterative Solution Method for Linear Systems of Which the Coefficient Matrix is a Symetric M-Matrix - Color correction for tone mapping - Wikipedia, the free encyclopedia + Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation + An Iterative Solution Method for Linear Systems of Which the Coefficient Matrix is a Symetric M-Matrix + Color correction for tone mapping + Wikipedia, the free encyclopedia First one is most of what matters, next two are details, last everything else. I did a few things differently, especially: - Reformulated the minimization with finite elements instead of finite differences. This results in better conditioning, - slightly better accuracy (less artifacts), the possibility of a better picked edge stopping function, but more memory consumption. + Reformulated the minimization with finite elements instead of finite differences. This results in better conditioning, + slightly better accuracy (less artifacts), the possibility of a better picked edge stopping function, but more memory consumption. - A single rotationally invariant edge stopping function is used instead of two non-invariant ones. + A single rotationally invariant edge stopping function is used instead of two non-invariant ones. - Incomplete Cholseky factorization instead of Szeliski's LAHBF. Slower, but not subject to any patents. + Incomplete Cholseky factorization instead of Szeliski's LAHBF. Slower, but not subject to any patents. - For tone mapping, original images are decomposed instead of their logarithms, and just one decomposition is made; - I find that this way works plenty good (theirs isn't better or worse... just different) and is simpler. + For tone mapping, original images are decomposed instead of their logarithms, and just one decomposition is made; + I find that this way works plenty good (theirs isn't better or worse... just different) and is simpler. Written by ben_pcc in Portland, Oregon, USA; code modified by Emil Martinec. - // EdgePreserveLab.h and EdgePreserveLab.cpp are free software: + // EdgePreserveLab.h and EdgePreserveLab.cpp are 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. + // under the terms of the GNU General Public License as published by + // the Free Software Foundation, either version 3 of the License, or + // (at your option) any later version. // - // This program is distributed in the hope that it will be useful, - // but WITHOUT ANY WARRANTY; without even the implied warranty of - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - // GNU General Public License for more details. + // This program is distributed in the hope that it will be useful, + // but WITHOUT ANY WARRANTY; without even the implied warranty of + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + // GNU General Public License for more details. // - // You should have received a copy of the GNU General Public License - // along with this program. If not, see . + // You should have received a copy of the GNU General Public License + // along with this program. If not, see . */ @@ -47,30 +47,31 @@ Written by ben_pcc in Portland, Oregon, USA; code modified by Emil Martinec. #include #include "EdgePreservingDecomposition.h" -class EdgePreserveLab{ +class EdgePreserveLab +{ public: - EdgePreserveLab(unsigned int width, unsigned int height); - ~EdgePreserveLab(); + EdgePreserveLab(unsigned int width, unsigned int height); + ~EdgePreserveLab(); - //Create an edge preserving blur of Source. Will create and return, or fill into Blur if not NULL. In place not ok. - //If UseBlurForEdgeStop is true, supplied not NULL Blur is used to calculate the edge stopping function instead of Source. - float *CreateBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, float *Blur = NULL, bool UseBlurForEdgeStop = false); + //Create an edge preserving blur of Source. Will create and return, or fill into Blur if not NULL. In place not ok. + //If UseBlurForEdgeStop is true, supplied not NULL Blur is used to calculate the edge stopping function instead of Source. + float *CreateBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, float *Blur = NULL, bool UseBlurForEdgeStop = false); - //Iterates CreateBlur such that the smoothness term approaches a specific norm via iteratively reweighted least squares. In place not ok. - float *CreateIteratedBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, unsigned int Reweightings, float *Blur = NULL); + //Iterates CreateBlur such that the smoothness term approaches a specific norm via iteratively reweighted least squares. In place not ok. + float *CreateIteratedBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, unsigned int Reweightings, float *Blur = NULL); - /*Lowers global contrast while preserving or boosting local contrast. Can fill into Compressed. The smaller Compression - the more compression is applied, with Compression = 1 giving no effect and above 1 the opposite effect. You can totally - use Compression = 1 and play with DetailBoost for some really sweet unsharp masking. If working on luma/grey, consider giving it a logarithm. - In place calculation to save memory (Source == Compressed) is totally ok. Reweightings > 0 invokes CreateIteratedBlur instead of CreateBlur. */ - float *CompressDynamicRange(float *Source, float LScale = 1.0f, float abScale = 5.0f, float EdgeStoppingLuma = 1.0f, float EdgeStoppingChroma = 1.0f, - float CompressionExponent = 0.8f, float DetailBoost = 0.1f, unsigned int Iterates = 20, - unsigned int Reweightings = 0, float *Compressed = NULL); + /*Lowers global contrast while preserving or boosting local contrast. Can fill into Compressed. The smaller Compression + the more compression is applied, with Compression = 1 giving no effect and above 1 the opposite effect. You can totally + use Compression = 1 and play with DetailBoost for some really sweet unsharp masking. If working on luma/grey, consider giving it a logarithm. + In place calculation to save memory (Source == Compressed) is totally ok. Reweightings > 0 invokes CreateIteratedBlur instead of CreateBlur. */ + float *CompressDynamicRange(float *Source, float LScale = 1.0f, float abScale = 5.0f, float EdgeStoppingLuma = 1.0f, float EdgeStoppingChroma = 1.0f, + float CompressionExponent = 0.8f, float DetailBoost = 0.1f, unsigned int Iterates = 20, + unsigned int Reweightings = 0, float *Compressed = NULL); private: - MultiDiagonalSymmetricMatrix *A; //The equations are simple enough to not mandate a matrix class, but fast solution NEEDS a complicated preconditioner. - unsigned int w, h, n; + MultiDiagonalSymmetricMatrix *A; //The equations are simple enough to not mandate a matrix class, but fast solution NEEDS a complicated preconditioner. + unsigned int w, h, n; - //Convenient access to the data in A. - float *a0, *a_1, *a_w, *a_w_1, *a_w1; + //Convenient access to the data in A. + float *a0, *a_1, *a_w, *a_w_1, *a_w1; }; diff --git a/rtengine/EdgePreservingDecomposition.cc b/rtengine/EdgePreservingDecomposition.cc index 55022eb12..927bfac2d 100644 --- a/rtengine/EdgePreservingDecomposition.cc +++ b/rtengine/EdgePreservingDecomposition.cc @@ -19,637 +19,773 @@ definite problems only, which is what unconstrained smooth optimization pretty m Parameter pass can be passed through, containing whatever info you like it to contain (matrix info?). Takes less memory with OkToModify_b = true, and Preconditioner = NULL. */ float *SparseConjugateGradient(void Ax(float *Product, float *x, void *Pass), float *b, int n, bool OkToModify_b, - float *x, float RMSResidual, void *Pass, int MaximumIterates, void Preconditioner(float *Product, float *x, void *Pass)){ - int iterate, i; - - char* buffer = (char*)malloc(2*n*sizeof(float)+128); - float *r = (float*)(buffer+64); - //Start r and x. - if(x == NULL){ - x = new float[n]; - - memset(x, 0, sizeof(float)*n); //Zero initial guess if x == NULL. - memcpy(r, b, sizeof(float)*n); - }else{ - Ax(r, x, Pass); -#ifdef _OPENMP -#pragma omp parallel for // removed schedule(dynamic,10) -#endif - for(int ii = 0; ii < n; ii++) - r[ii] = b[ii] - r[ii]; //r = b - A x. - } - //s is preconditionment of r. Without, direct to r. - float *s = r, rs = 0.0f; - if(Preconditioner != NULL){ - s = new float[n]; - - Preconditioner(s, r, Pass); - } -#ifdef _OPENMP -#pragma omp parallel for reduction(+:rs) // removed schedule(dynamic,10) -#endif - for(int ii = 0; ii < n; ii++) { - rs += r[ii]*s[ii]; - } - //Search direction d. - float *d = (float*)(buffer + n*sizeof(float) + 128); - - memcpy(d, s, sizeof(float)*n); - - //Store calculations of Ax in this. - float *ax = b; - if(!OkToModify_b) ax = new float[n]; - - //Start iterating! - if(MaximumIterates == 0) MaximumIterates = n; - for(iterate = 0; iterate < MaximumIterates; iterate++){ - //Get step size alpha, store ax while at it. - float ab = 0.0f; - Ax(ax, d, Pass); -#ifdef _OPENMP -#pragma omp parallel for reduction(+:ab) -#endif - for(int ii = 0; ii < n; ii++) - ab += d[ii]*ax[ii]; - - if(ab == 0.0f) break; //So unlikely. It means perfectly converged or singular, stop either way. - ab = rs/ab; - - //Update x and r with this step size. - float rms = 0.0; -#ifdef _OPENMP -#pragma omp parallel for reduction(+:rms) -#endif - for(int ii = 0; ii < n; ii++){ - x[ii] += ab*d[ii]; - r[ii] -= ab*ax[ii]; //"Fast recursive formula", use explicit r = b - Ax occasionally? - rms += r[ii]*r[ii]; - } - rms = sqrtf(rms/n); - //Quit? This probably isn't the best stopping condition, but ok. - if(rms < RMSResidual) break; - - if(Preconditioner != NULL) Preconditioner(s, r, Pass); - - //Get beta. - ab = rs; - rs = 0.0f; - -#ifdef _OPENMP -#pragma omp parallel -#endif + float *x, float RMSResidual, void *Pass, int MaximumIterates, void Preconditioner(float *Product, float *x, void *Pass)) { - float c = 0.0f; - float t; - float temp; + int iterate, i; + + char* buffer = (char*)malloc(2 * n * sizeof(float) + 128); + float *r = (float*)(buffer + 64); + + //Start r and x. + if(x == NULL) { + x = new float[n]; + + memset(x, 0, sizeof(float)*n); //Zero initial guess if x == NULL. + memcpy(r, b, sizeof(float)*n); + } else { + Ax(r, x, Pass); #ifdef _OPENMP -#pragma omp for reduction(+:rs) // Summation with error correction + #pragma omp parallel for // removed schedule(dynamic,10) #endif - for(int ii = 0; ii < n; ii++) { - temp = r[ii]*s[ii]; - t = rs + temp; - if( fabsf(rs) >= fabsf(temp) ) - c += ((rs-t) + temp); - else - c += ((temp-t)+rs); - rs = t; - } + + for(int ii = 0; ii < n; ii++) { + r[ii] = b[ii] - r[ii]; //r = b - A x. + } + } + + //s is preconditionment of r. Without, direct to r. + float *s = r, rs = 0.0f; + + if(Preconditioner != NULL) { + s = new float[n]; + + Preconditioner(s, r, Pass); + } + #ifdef _OPENMP -#pragma omp critical + #pragma omp parallel for reduction(+:rs) // removed schedule(dynamic,10) #endif - rs += c; -} - ab = rs/ab; + for(int ii = 0; ii < n; ii++) { + rs += r[ii] * s[ii]; + } - //Update search direction p. + //Search direction d. + float *d = (float*)(buffer + n * sizeof(float) + 128); + + memcpy(d, s, sizeof(float)*n); + + //Store calculations of Ax in this. + float *ax = b; + + if(!OkToModify_b) { + ax = new float[n]; + } + + //Start iterating! + if(MaximumIterates == 0) { + MaximumIterates = n; + } + + for(iterate = 0; iterate < MaximumIterates; iterate++) { + //Get step size alpha, store ax while at it. + float ab = 0.0f; + Ax(ax, d, Pass); #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for reduction(+:ab) #endif - for(int ii = 0; ii < n; ii++) - d[ii] = s[ii] + ab*d[ii]; + + for(int ii = 0; ii < n; ii++) { + ab += d[ii] * ax[ii]; + } + + if(ab == 0.0f) { + break; //So unlikely. It means perfectly converged or singular, stop either way. + } + + ab = rs / ab; + + //Update x and r with this step size. + float rms = 0.0; +#ifdef _OPENMP + #pragma omp parallel for reduction(+:rms) +#endif + + for(int ii = 0; ii < n; ii++) { + x[ii] += ab * d[ii]; + r[ii] -= ab * ax[ii]; //"Fast recursive formula", use explicit r = b - Ax occasionally? + rms += r[ii] * r[ii]; + } + + rms = sqrtf(rms / n); + + //Quit? This probably isn't the best stopping condition, but ok. + if(rms < RMSResidual) { + break; + } + + if(Preconditioner != NULL) { + Preconditioner(s, r, Pass); + } + + //Get beta. + ab = rs; + rs = 0.0f; + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float c = 0.0f; + float t; + float temp; +#ifdef _OPENMP + #pragma omp for reduction(+:rs) // Summation with error correction +#endif + + for(int ii = 0; ii < n; ii++) { + temp = r[ii] * s[ii]; + t = rs + temp; + + if( fabsf(rs) >= fabsf(temp) ) { + c += ((rs - t) + temp); + } else { + c += ((temp - t) + rs); + } + + rs = t; + } + +#ifdef _OPENMP + #pragma omp critical +#endif + rs += c; + } + + ab = rs / ab; + + //Update search direction p. +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int ii = 0; ii < n; ii++) { + d[ii] = s[ii] + ab * d[ii]; + } - } + } - if(iterate == MaximumIterates) - if(iterate != n && RMSResidual != 0.0f) - printf("Warning: MaximumIterates (%u) reached in SparseConjugateGradient.\n", MaximumIterates); + if(iterate == MaximumIterates) + if(iterate != n && RMSResidual != 0.0f) { + printf("Warning: MaximumIterates (%u) reached in SparseConjugateGradient.\n", MaximumIterates); + } - if(ax != b) delete[] ax; - if(s != r) delete[] s; - free(buffer); - return x; + if(ax != b) { + delete[] ax; + } + + if(s != r) { + delete[] s; + } + + free(buffer); + return x; } -MultiDiagonalSymmetricMatrix::MultiDiagonalSymmetricMatrix(int Dimension, int NumberOfDiagonalsInLowerTriangle){ - n = Dimension; - m = NumberOfDiagonalsInLowerTriangle; - IncompleteCholeskyFactorization = NULL; +MultiDiagonalSymmetricMatrix::MultiDiagonalSymmetricMatrix(int Dimension, int NumberOfDiagonalsInLowerTriangle) +{ + n = Dimension; + m = NumberOfDiagonalsInLowerTriangle; + IncompleteCholeskyFactorization = NULL; - Diagonals = new float *[m]; - StartRows = new int [m+1]; - memset(Diagonals, 0, sizeof(float *)*m); - memset(StartRows, 0, sizeof(int)*(m+1)); - StartRows[m] = n+1; + Diagonals = new float *[m]; + StartRows = new int [m + 1]; + memset(Diagonals, 0, sizeof(float *)*m); + memset(StartRows, 0, sizeof(int) * (m + 1)); + StartRows[m] = n + 1; } -MultiDiagonalSymmetricMatrix::~MultiDiagonalSymmetricMatrix(){ - if(DiagBuffer != NULL) - free(buffer); - else - for(int i=0;i try to allocate smaller blocks - DiagBuffer = NULL; - else { - DiagBuffer = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); - } - } - if(index >= m){ - printf("Error in MultiDiagonalSymmetricMatrix::CreateDiagonal: invalid index.\n"); - return false; - } - if(index > 0) - if(StartRow <= StartRows[index - 1]){ - printf("Error in MultiDiagonalSymmetricMatrix::CreateDiagonal: each StartRow must exceed the previous.\n"); - return false; - } +bool MultiDiagonalSymmetricMatrix::CreateDiagonal(int index, int StartRow) +{ + // Changed memory allocation for diagonals to avoid L1 conflict misses + // Falls back to original version if big block could not be allocated + int padding = 4096 - ((n * m * sizeof(float)) % 4096); - if(DiagBuffer != NULL) - Diagonals[index] = (float*)(DiagBuffer+(index*(n+padding)*sizeof(float))+((index+16)*64)); - else { - Diagonals[index] = new float[DiagonalLength(StartRow)]; - if(Diagonals[index] == NULL) { - printf("Error in MultiDiagonalSymmetricMatrix::CreateDiagonal: memory allocation failed. Out of memory?\n"); - return false; - } - memset(Diagonals[index], 0, sizeof(float)*DiagonalLength(StartRow)); - } - - StartRows[index] = StartRow; - return true; + if(index == 0) { + buffer = (char*)calloc( (n + padding) * m * sizeof(float) + (m + 16) * 64 + 63, 1); + + if(buffer == NULL) + // no big memory block available => try to allocate smaller blocks + { + DiagBuffer = NULL; + } else { + DiagBuffer = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); + } + } + + if(index >= m) { + printf("Error in MultiDiagonalSymmetricMatrix::CreateDiagonal: invalid index.\n"); + return false; + } + + if(index > 0) + if(StartRow <= StartRows[index - 1]) { + printf("Error in MultiDiagonalSymmetricMatrix::CreateDiagonal: each StartRow must exceed the previous.\n"); + return false; + } + + if(DiagBuffer != NULL) { + Diagonals[index] = (float*)(DiagBuffer + (index * (n + padding) * sizeof(float)) + ((index + 16) * 64)); + } else { + Diagonals[index] = new float[DiagonalLength(StartRow)]; + + if(Diagonals[index] == NULL) { + printf("Error in MultiDiagonalSymmetricMatrix::CreateDiagonal: memory allocation failed. Out of memory?\n"); + return false; + } + + memset(Diagonals[index], 0, sizeof(float)*DiagonalLength(StartRow)); + } + + StartRows[index] = StartRow; + return true; } -inline int MultiDiagonalSymmetricMatrix::FindIndex(int StartRow) { - //There's GOT to be a better way to do this. "Bidirectional map?" - // Issue 1895 : Changed start of loop from zero to one - // m is small (5 or 6) - for(int i = 1; i < m; i++) - if(StartRows[i] == StartRow) - return i; - return -1; +inline int MultiDiagonalSymmetricMatrix::FindIndex(int StartRow) +{ + //There's GOT to be a better way to do this. "Bidirectional map?" + // Issue 1895 : Changed start of loop from zero to one + // m is small (5 or 6) + for(int i = 1; i < m; i++) + if(StartRows[i] == StartRow) { + return i; + } + + return -1; } -bool MultiDiagonalSymmetricMatrix::LazySetEntry(float value, int row, int column){ - //On the strict upper triangle? Swap, this is ok due to symmetry. - int i, sr; - if(column > row) - i = column, - column = row, - row = i; - if(row >= n) return false; - sr = row - column; +bool MultiDiagonalSymmetricMatrix::LazySetEntry(float value, int row, int column) +{ + //On the strict upper triangle? Swap, this is ok due to symmetry. + int i, sr; - //Locate the relevant diagonal. - i = FindIndex(sr); - if(i < 0) return false; + if(column > row) + i = column, + column = row, + row = i; - Diagonals[i][column] = value; - return true; + if(row >= n) { + return false; + } + + sr = row - column; + + //Locate the relevant diagonal. + i = FindIndex(sr); + + if(i < 0) { + return false; + } + + Diagonals[i][column] = value; + return true; } -SSEFUNCTION void MultiDiagonalSymmetricMatrix::VectorProduct(float* RESTRICT Product, float* RESTRICT x){ +SSEFUNCTION void MultiDiagonalSymmetricMatrix::VectorProduct(float* RESTRICT Product, float* RESTRICT x) +{ - int srm = StartRows[m-1]; - int lm = DiagonalLength(srm); + int srm = StartRows[m - 1]; + int lm = DiagonalLength(srm); #ifdef _OPENMP #ifdef __SSE2__ - const int chunkSize = (lm-srm)/(omp_get_num_procs()*32); + const int chunkSize = (lm - srm) / (omp_get_num_procs() * 32); #else - const int chunkSize = (lm-srm)/(omp_get_num_procs()*8); + const int chunkSize = (lm - srm) / (omp_get_num_procs() * 8); #endif #endif -#pragma omp parallel -{ - // First fill the big part in the middle - // This can be done without intermediate stores to memory and it can be parallelized too + #pragma omp parallel + { + // First fill the big part in the middle + // This can be done without intermediate stores to memory and it can be parallelized too #ifdef _OPENMP -#pragma omp for schedule(dynamic,chunkSize) nowait + #pragma omp for schedule(dynamic,chunkSize) nowait #endif #ifdef __SSE2__ - for(int j=srm;j0;i--) { - int s = StartRows[i]; - prodv += (LVFU(Diagonals[i][j - s])*LVFU(x[j - s])) + (LVFU(Diagonals[i][j])*LVFU(x[j + s])); - } - _mm_storeu_ps(&Product[j],prodv); - } + + for(int j = srm; j < lm - 3; j += 4) { + __m128 prodv = LVFU(Diagonals[0][j]) * LVFU(x[j]); + + for(int i = m - 1; i > 0; i--) { + int s = StartRows[i]; + prodv += (LVFU(Diagonals[i][j - s]) * LVFU(x[j - s])) + (LVFU(Diagonals[i][j]) * LVFU(x[j + s])); + } + + _mm_storeu_ps(&Product[j], prodv); + } + #else - for(int j=srm;j0;i--) { - int s = StartRows[i]; - prod += (Diagonals[i][j - s]*x[j - s]) + (Diagonals[i][j]*x[j + s]); - } - Product[j] = prod; - } + + for(int j = srm; j < lm; j++) { + float prod = Diagonals[0][j] * x[j]; + + for(int i = m - 1; i > 0; i--) { + int s = StartRows[i]; + prod += (Diagonals[i][j - s] * x[j - s]) + (Diagonals[i][j] * x[j + s]); + } + + Product[j] = prod; + } #endif -#pragma omp single -{ + #pragma omp single + { #ifdef __SSE2__ - for(int j=lm-((lm-srm)%4);j0;i--) { - int s = StartRows[i]; - prod += (Diagonals[i][j - s]*x[j - s]) + (Diagonals[i][j]*x[j + s]); - } - Product[j] = prod; - } + + for(int j = lm - ((lm - srm) % 4); j < lm; j++) { + float prod = Diagonals[0][j] * x[j]; + + for(int i = m - 1; i > 0; i--) { + int s = StartRows[i]; + prod += (Diagonals[i][j - s] * x[j - s]) + (Diagonals[i][j] * x[j + s]); + } + + Product[j] = prod; + } + #endif - // Fill remaining area - // Loop over the stored diagonals. - for(int i = 0; i < m; i++){ - int sr = StartRows[i]; - float *a = Diagonals[i]; //One fewer dereference. - int l = DiagonalLength(sr); - if(sr == 0) { - for(int j = 0; j < srm; j++) - Product[j] = a[j]*x[j]; //Separate, fairly simple treatment for the main diagonal. - for(int j = lm; j < l; j++) - Product[j] = a[j]*x[j]; //Separate, fairly simple treatment for the main diagonal. - } else { + + // Fill remaining area + // Loop over the stored diagonals. + for(int i = 0; i < m; i++) { + int sr = StartRows[i]; + float *a = Diagonals[i]; //One fewer dereference. + int l = DiagonalLength(sr); + + if(sr == 0) { + for(int j = 0; j < srm; j++) { + Product[j] = a[j] * x[j]; //Separate, fairly simple treatment for the main diagonal. + } + + for(int j = lm; j < l; j++) { + Product[j] = a[j] * x[j]; //Separate, fairly simple treatment for the main diagonal. + } + } else { // Split the loop in 3 parts, so now the big one in the middle can be parallelized without race conditions - // updates 0 to sr - 1. Because sr is small (in the range of image-width) no benefit by omp - for(int j=0;jCreateDiagonal(0, 0); //There's always a main diagonal in this type of decomposition. - mic=1; - for(int ii = 1; ii < m; ii++){ - //Set j to the number of diagonals to be created corresponding to a diagonal on this source matrix... - j = rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); + if(StartRows[0] != 0) { + printf("Error in MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization: main diagonal required to exist for this math.\n"); + return false; + } - //...and create those diagonals. I want to take a moment to tell you about how much I love minimalistic loops: very much. - while(j-- != 0) - if(!ic->CreateDiagonal(mic++, StartRows[ii] - j)){ - //Beware of out of memory, possible for large, sparse problems if you ask for too much fill. - printf("Error in MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization: Out of memory. Ask for less fill?\n"); - delete ic; - return false; - } - } + //How many diagonals in the decomposition? + MaxFillAbove++; //Conceptually, now "fill" includes an existing diagonal. Simpler in the math that follows. + int i, j, mic, fp; + mic = 1; + fp = 1; - //It's all initialized? Uhkay. Do the actual math then. - int sss, ss, s; - int k, MaxStartRow = StartRows[m - 1]; //Handy number. - float **l = ic->Diagonals; - float *d = ic->Diagonals[0]; //Describes D in LDLt. - int icm = ic->m; - int icn = ic->n; - int* RESTRICT icStartRows = ic->StartRows; + for(int ii = 1; ii < m; ii++) { + fp = rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); //Guarunteed positive since StartRows must be created in increasing order. + mic = mic + fp; + } - //Loop over the columns. + //Initialize the decomposition - setup memory, start rows, etc. - // create array for quicker access to ic->StartRows - struct s_diagmap { - int sss; - int ss; - int k; - }; + MultiDiagonalSymmetricMatrix *ic = new MultiDiagonalSymmetricMatrix(n, mic); + ic->CreateDiagonal(0, 0); //There's always a main diagonal in this type of decomposition. + mic = 1; + + for(int ii = 1; ii < m; ii++) { + //Set j to the number of diagonals to be created corresponding to a diagonal on this source matrix... + j = rtengine::min(StartRows[ii] - StartRows[ii - 1], MaxFillAbove); + + //...and create those diagonals. I want to take a moment to tell you about how much I love minimalistic loops: very much. + while(j-- != 0) + if(!ic->CreateDiagonal(mic++, StartRows[ii] - j)) { + //Beware of out of memory, possible for large, sparse problems if you ask for too much fill. + printf("Error in MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization: Out of memory. Ask for less fill?\n"); + delete ic; + return false; + } + } + + //It's all initialized? Uhkay. Do the actual math then. + int sss, ss, s; + int k, MaxStartRow = StartRows[m - 1]; //Handy number. + float **l = ic->Diagonals; + float *d = ic->Diagonals[0]; //Describes D in LDLt. + int icm = ic->m; + int icn = ic->n; + int* RESTRICT icStartRows = ic->StartRows; + + //Loop over the columns. + + // create array for quicker access to ic->StartRows + struct s_diagmap { + int sss; + int ss; + int k; + }; - // Pass one: count number of needed entries - int entrycount = 0; - for(int i=1;iFindIndex( icStartRows[i] + icStartRows[j]) > 0) - entrycount ++; - } - } + // Pass one: count number of needed entries + int entrycount = 0; - // now we can create the array - struct s_diagmap* RESTRICT DiagMap = new s_diagmap[entrycount]; - // we also need the maxvalues - int entrynumber = 0; - int index; - int* RESTRICT MaxIndizes = new int[icm]; + for(int i = 1; i < icm; i++) { + for(int j = 1; j < icm; j++) { + if(ic->FindIndex( icStartRows[i] + icStartRows[j]) > 0) { + entrycount ++; + } + } + } - for(int i=1;iFindIndex( icStartRows[i] + icStartRows[j]); - if(index > 0) { - DiagMap[entrynumber].ss = j; - DiagMap[entrynumber].sss = index; - DiagMap[entrynumber].k = icStartRows[j]; - entrynumber ++; - } - } - MaxIndizes[i] = entrynumber - 1; - } + // now we can create the array + struct s_diagmap* RESTRICT DiagMap = new s_diagmap[entrycount]; + // we also need the maxvalues + int entrynumber = 0; + int index; + int* RESTRICT MaxIndizes = new int[icm]; - int* RESTRICT findmap = new int[icm]; - for(int j=0;jFindIndex( icStartRows[i] + icStartRows[j]); - //This is a loop over k from 1 to j, inclusive. We'll cover that by looping over the index of the diagonals (s), and get k from it. - //The first diagonal is d (k = 0), so skip that and have s start at 1. Cover all available s but stop if k exceeds j. - s=1; - k=icStartRows[s]; - while(k<=j) { - d[j] -= l[s][j - k]*l[s][j - k]*d[j - k]; - s++; - k=icStartRows[s]; - } - if(UNLIKELY(d[j] == 0.0f)){ - printf("Error in MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization: division by zero. Matrix not decomposable.\n"); - delete ic; - delete[] DiagMap; - delete[] MaxIndizes; - delete[] findmap; - return false; - } - float id = 1.0f/d[j]; - //Now, calculate l from top down along this column. + if(index > 0) { + DiagMap[entrynumber].ss = j; + DiagMap[entrynumber].sss = index; + DiagMap[entrynumber].k = icStartRows[j]; + entrynumber ++; + } + } - int mapindex = 0; - int jMax = icn - j; - for(s = 1; s < icm; s++){ - if(icStartRows[s] >= jMax) - break; //Possible values of j are limited - - float temp = 0.0f; - while(mapindex <= MaxIndizes[s] && ( k = DiagMap[mapindex].k) <= j) { - temp -= l[DiagMap[mapindex].sss][j - k]*l[DiagMap[mapindex].ss][j - k]*d[j - k]; - mapindex ++; - } - sss = findmap[s]; - l[s][j] = id * (sss < 0 ? temp : (Diagonals[sss][j] + temp)); - } - } - delete[] DiagMap; - delete[] MaxIndizes; - delete[] findmap; - IncompleteCholeskyFactorization = ic; - return true; + MaxIndizes[i] = entrynumber - 1; + } + + int* RESTRICT findmap = new int[icm]; + + for(int j = 0; j < icm; j++) { + findmap[j] = FindIndex( icStartRows[j]); + } + + for(j = 0; j < n; j++) { + //Calculate d for this column. + d[j] = Diagonals[0][j]; + + //This is a loop over k from 1 to j, inclusive. We'll cover that by looping over the index of the diagonals (s), and get k from it. + //The first diagonal is d (k = 0), so skip that and have s start at 1. Cover all available s but stop if k exceeds j. + s = 1; + k = icStartRows[s]; + + while(k <= j) { + d[j] -= l[s][j - k] * l[s][j - k] * d[j - k]; + s++; + k = icStartRows[s]; + } + + if(UNLIKELY(d[j] == 0.0f)) { + printf("Error in MultiDiagonalSymmetricMatrix::CreateIncompleteCholeskyFactorization: division by zero. Matrix not decomposable.\n"); + delete ic; + delete[] DiagMap; + delete[] MaxIndizes; + delete[] findmap; + return false; + } + + float id = 1.0f / d[j]; + //Now, calculate l from top down along this column. + + int mapindex = 0; + int jMax = icn - j; + + for(s = 1; s < icm; s++) { + if(icStartRows[s] >= jMax) { + break; //Possible values of j are limited + } + + float temp = 0.0f; + + while(mapindex <= MaxIndizes[s] && ( k = DiagMap[mapindex].k) <= j) { + temp -= l[DiagMap[mapindex].sss][j - k] * l[DiagMap[mapindex].ss][j - k] * d[j - k]; + mapindex ++; + } + + sss = findmap[s]; + l[s][j] = id * (sss < 0 ? temp : (Diagonals[sss][j] + temp)); + } + } + + delete[] DiagMap; + delete[] MaxIndizes; + delete[] findmap; + IncompleteCholeskyFactorization = ic; + return true; } -void MultiDiagonalSymmetricMatrix::KillIncompleteCholeskyFactorization(void){ - delete IncompleteCholeskyFactorization; +void MultiDiagonalSymmetricMatrix::KillIncompleteCholeskyFactorization(void) +{ + delete IncompleteCholeskyFactorization; } -void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* RESTRICT b){ - //We want to solve L D Lt x = b where D is a diagonal matrix described by Diagonals[0] and L is a unit lower triagular matrix described by the rest of the diagonals. - //Let D Lt x = y. Then, first solve L y = b. - float* RESTRICT *d = IncompleteCholeskyFactorization->Diagonals; - int* RESTRICT s = IncompleteCholeskyFactorization->StartRows; - int M = IncompleteCholeskyFactorization->m, N = IncompleteCholeskyFactorization->n; - int i, j; - - if(M != DIAGONALSP1){ // can happen in theory - for(j = 0; j < N; j++){ - float sub = b[j]; // using local var to reduce memory writes, gave a big speedup - i = 1; - int c = j - s[i]; - while(c >= 0) { - sub -= d[i][c]*x[c]; - i++; - c = j - s[i]; - } - x[j] = sub; // only one memory-write per j - } - } else { // that's the case almost every time - for(j = 0; j <= s[M-1]; j++){ - float sub = b[j]; // using local var to reduce memory writes, gave a big speedup - i = 1; - int c = j - s[1]; - while(c >= 0) { - sub -= d[i][c]*x[c]; - i++; - c = j - s[i]; - } - x[j] = sub; // only one memory-write per j - } - for(j = s[M-1]+1; j0;i--){ // using a constant upperbound allows the compiler to unroll this loop (gives a good speedup) - sub -= d[i][j-s[i]]*x[j-s[i]]; - } - x[j] = sub; // only one memory-write per j - } - } +void MultiDiagonalSymmetricMatrix::CholeskyBackSolve(float* RESTRICT x, float* RESTRICT b) +{ + //We want to solve L D Lt x = b where D is a diagonal matrix described by Diagonals[0] and L is a unit lower triagular matrix described by the rest of the diagonals. + //Let D Lt x = y. Then, first solve L y = b. + float* RESTRICT *d = IncompleteCholeskyFactorization->Diagonals; + int* RESTRICT s = IncompleteCholeskyFactorization->StartRows; + int M = IncompleteCholeskyFactorization->m, N = IncompleteCholeskyFactorization->n; + int i, j; - //Now, solve x from D Lt x = y -> Lt x = D^-1 y + if(M != DIAGONALSP1) { // can happen in theory + for(j = 0; j < N; j++) { + float sub = b[j]; // using local var to reduce memory writes, gave a big speedup + i = 1; + int c = j - s[i]; + + while(c >= 0) { + sub -= d[i][c] * x[c]; + i++; + c = j - s[i]; + } + + x[j] = sub; // only one memory-write per j + } + } else { // that's the case almost every time + for(j = 0; j <= s[M - 1]; j++) { + float sub = b[j]; // using local var to reduce memory writes, gave a big speedup + i = 1; + int c = j - s[1]; + + while(c >= 0) { + sub -= d[i][c] * x[c]; + i++; + c = j - s[i]; + } + + x[j] = sub; // only one memory-write per j + } + + for(j = s[M - 1] + 1; j < N; j++) { + float sub = b[j]; // using local var to reduce memory writes, gave a big speedup + + for(int i = DIAGONALSP1 - 1; i > 0; i--) { // using a constant upperbound allows the compiler to unroll this loop (gives a good speedup) + sub -= d[i][j - s[i]] * x[j - s[i]]; + } + + x[j] = sub; // only one memory-write per j + } + } + + //Now, solve x from D Lt x = y -> Lt x = D^-1 y // Took this one out of the while, so it can be parallelized now, which speeds up, because division is expensive #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(j = 0; j < N; j++) - x[j] = x[j]/d[0][j]; - if(M != DIAGONALSP1){ // can happen in theory - while(j-- > 0){ - float sub = x[j]; // using local var to reduce memory writes, gave a big speedup - i=1; - int c = j+s[1]; - while(c < N) { - sub -= d[i][j]*x[c]; - i++; - c = j+s[i]; - } - x[j] = sub; // only one memory-write per j - } - } else { // that's the case almost every time - for(j=N-1;j>=(N-1)-s[M-1];j--) { - float sub = x[j]; // using local var to reduce memory writes, gave a big speedup - i=1; - int c = j+s[1]; - while(c < N) { - sub -= d[i][j]*x[j+s[i]]; - i++; - c = j+s[i]; - } - x[j] = sub; // only one memory-write per j - } - for(j=(N-2)-s[M-1];j>=0;j--) { - float sub = x[j]; // using local var to reduce memory writes, gave a big speedup - for(int i=DIAGONALSP1-1;i>0;i--){ // using a constant upperbound allows the compiler to unroll this loop (gives a good speedup) - sub -= d[i][j]*x[j + s[i]]; - } - x[j] = sub; // only one memory-write per j - } - } + for(j = 0; j < N; j++) { + x[j] = x[j] / d[0][j]; + } + + if(M != DIAGONALSP1) { // can happen in theory + while(j-- > 0) { + float sub = x[j]; // using local var to reduce memory writes, gave a big speedup + i = 1; + int c = j + s[1]; + + while(c < N) { + sub -= d[i][j] * x[c]; + i++; + c = j + s[i]; + } + + x[j] = sub; // only one memory-write per j + } + } else { // that's the case almost every time + for(j = N - 1; j >= (N - 1) - s[M - 1]; j--) { + float sub = x[j]; // using local var to reduce memory writes, gave a big speedup + i = 1; + int c = j + s[1]; + + while(c < N) { + sub -= d[i][j] * x[j + s[i]]; + i++; + c = j + s[i]; + } + + x[j] = sub; // only one memory-write per j + } + + for(j = (N - 2) - s[M - 1]; j >= 0; j--) { + float sub = x[j]; // using local var to reduce memory writes, gave a big speedup + + for(int i = DIAGONALSP1 - 1; i > 0; i--) { // using a constant upperbound allows the compiler to unroll this loop (gives a good speedup) + sub -= d[i][j] * x[j + s[i]]; + } + + x[j] = sub; // only one memory-write per j + } + } } -EdgePreservingDecomposition::EdgePreservingDecomposition(int width, int height){ - w = width; - h = height; - n = w*h; - - //Initialize the matrix just once at construction. - A = new MultiDiagonalSymmetricMatrix(n, DIAGONALS); - if(!( - A->CreateDiagonal(0, 0) && - A->CreateDiagonal(1, 1) && - A->CreateDiagonal(2, w - 1) && - A->CreateDiagonal(3, w) && - A->CreateDiagonal(4, w + 1))){ - delete A; - A = NULL; - printf("Error in EdgePreservingDecomposition construction: out of memory.\n"); - }else{ - a0 = A->Diagonals[0]; - a_1 = A->Diagonals[1]; - a_w1 = A->Diagonals[2]; - a_w = A->Diagonals[3]; - a_w_1 = A->Diagonals[4]; - } -} - -EdgePreservingDecomposition::~EdgePreservingDecomposition(){ - delete A; -} - -SSEFUNCTION float *EdgePreservingDecomposition::CreateBlur(float *Source, float Scale, float EdgeStopping, int Iterates, float *Blur, bool UseBlurForEdgeStop){ - - if(Blur == NULL) - UseBlurForEdgeStop = false, //Use source if there's no supplied Blur. - Blur = new float[n]; - - if(Scale == 0.0f){ - memcpy(Blur, Source, n*sizeof(float)); - return Blur; - } - - //Create the edge stopping function a, rotationally symmetric and just one instead of (ax, ay). Maybe don't need Blur yet, so use its memory. - float* RESTRICT a; - float* RESTRICT g; - if(UseBlurForEdgeStop) a = new float[n], g = Blur; - else a = Blur, g = Source; - - int i; - int w1 = w - 1, h1 = h - 1; -// float eps = 0.02f; - const float sqreps = 0.0004f; // removed eps*eps from inner loop - - -#ifdef _OPENMP -#pragma omp parallel -#endif +EdgePreservingDecomposition::EdgePreservingDecomposition(int width, int height) { -#ifdef __SSE2__ - int x; - __m128 gxv,gyv; - __m128 Scalev = _mm_set1_ps( Scale ); - __m128 sqrepsv = _mm_set1_ps( sqreps ); - __m128 EdgeStoppingv = _mm_set1_ps( -EdgeStopping ); - __m128 zd5v = _mm_set1_ps( 0.5f ); -#endif -#ifdef _OPENMP -#pragma omp for -#endif - for(int y = 0; y < h1; y++){ - float *rg = &g[w*y]; -#ifdef __SSE2__ - for(x = 0; x < w1-3; x+=4){ - //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. - gxv = (LVFU(rg[x + 1]) - LVFU(rg[x])) + (LVFU(rg[x + w + 1]) - LVFU(rg[x + w])); - gyv = (LVFU(rg[x + w]) - LVFU(rg[x])) + (LVFU(rg[x + w + 1]) - LVFU(rg[x + 1])); - //Apply power to the magnitude of the gradient to get the edge stopping function. - _mm_storeu_ps( &a[x + w*y], Scalev * pow_F((zd5v*_mm_sqrt_ps(gxv*gxv + gyv*gyv + sqrepsv)), EdgeStoppingv) ); - } - for(; x < w1; x++){ - //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. - float gx = (rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]); - float gy = (rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]); - //Apply power to the magnitude of the gradient to get the edge stopping function. - a[x + w*y] = Scale*pow_F(0.5f*sqrtf(gx*gx + gy*gy + sqreps), -EdgeStopping); - } -#else - for(int x = 0; x < w1; x++){ - //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. - float gx = (rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]); - float gy = (rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]); + w = width; + h = height; + n = w * h; - //Apply power to the magnitude of the gradient to get the edge stopping function. - a[x + w*y] = Scale*pow_F(0.5f*sqrtf(gx*gx + gy*gy + sqreps), -EdgeStopping); - } -#endif - } + //Initialize the matrix just once at construction. + A = new MultiDiagonalSymmetricMatrix(n, DIAGONALS); + + if(!( + A->CreateDiagonal(0, 0) && + A->CreateDiagonal(1, 1) && + A->CreateDiagonal(2, w - 1) && + A->CreateDiagonal(3, w) && + A->CreateDiagonal(4, w + 1))) { + delete A; + A = NULL; + printf("Error in EdgePreservingDecomposition construction: out of memory.\n"); + } else { + a0 = A->Diagonals[0]; + a_1 = A->Diagonals[1]; + a_w1 = A->Diagonals[2]; + a_w = A->Diagonals[3]; + a_w_1 = A->Diagonals[4]; + } } +EdgePreservingDecomposition::~EdgePreservingDecomposition() +{ + delete A; +} - /* Now setup the linear problem. I use the Maxima CAS, here's code for making an FEM formulation for the smoothness term: - p(x, y) := (1 - x)*(1 - y); - P(m, n) := A[m][n]*p(x, y) + A[m + 1][n]*p(1 - x, y) + A[m + 1][n + 1]*p(1 - x, 1 - y) + A[m][n + 1]*p(x, 1 - y); - Integrate(f) := integrate(integrate(f, x, 0, 1), y, 0, 1); +SSEFUNCTION float *EdgePreservingDecomposition::CreateBlur(float *Source, float Scale, float EdgeStopping, int Iterates, float *Blur, bool UseBlurForEdgeStop) +{ - Integrate(diff(P(u, v), x)*diff(p(x, y), x) + diff(P(u, v), y)*diff(p(x, y), y)); - Integrate(diff(P(u - 1, v), x)*diff(p(1 - x, y), x) + diff(P(u - 1, v), y)*diff(p(1 - x, y), y)); - Integrate(diff(P(u - 1, v - 1), x)*diff(p(1 - x, 1 - y), x) + diff(P(u - 1, v - 1), y)*diff(p(1 - x, 1 - y), y)); - Integrate(diff(P(u, v - 1), x)*diff(p(x, 1 - y), x) + diff(P(u, v - 1), y)*diff(p(x, 1 - y), y)); - So yeah. Use the numeric results of that to fill the matrix A.*/ + if(Blur == NULL) + UseBlurForEdgeStop = false, //Use source if there's no supplied Blur. + Blur = new float[n]; - memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); - memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); - memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); - memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); + if(Scale == 0.0f) { + memcpy(Blur, Source, n * sizeof(float)); + return Blur; + } + + //Create the edge stopping function a, rotationally symmetric and just one instead of (ax, ay). Maybe don't need Blur yet, so use its memory. + float* RESTRICT a; + float* RESTRICT g; + + if(UseBlurForEdgeStop) { + a = new float[n], g = Blur; + } else { + a = Blur, g = Source; + } + + int i; + int w1 = w - 1, h1 = h - 1; +// float eps = 0.02f; + const float sqreps = 0.0004f; // removed eps*eps from inner loop + + +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + int x; + __m128 gxv, gyv; + __m128 Scalev = _mm_set1_ps( Scale ); + __m128 sqrepsv = _mm_set1_ps( sqreps ); + __m128 EdgeStoppingv = _mm_set1_ps( -EdgeStopping ); + __m128 zd5v = _mm_set1_ps( 0.5f ); +#endif +#ifdef _OPENMP + #pragma omp for +#endif + + for(int y = 0; y < h1; y++) { + float *rg = &g[w * y]; +#ifdef __SSE2__ + + for(x = 0; x < w1 - 3; x += 4) { + //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. + gxv = (LVFU(rg[x + 1]) - LVFU(rg[x])) + (LVFU(rg[x + w + 1]) - LVFU(rg[x + w])); + gyv = (LVFU(rg[x + w]) - LVFU(rg[x])) + (LVFU(rg[x + w + 1]) - LVFU(rg[x + 1])); + //Apply power to the magnitude of the gradient to get the edge stopping function. + _mm_storeu_ps( &a[x + w * y], Scalev * pow_F((zd5v * _mm_sqrt_ps(gxv * gxv + gyv * gyv + sqrepsv)), EdgeStoppingv) ); + } + + for(; x < w1; x++) { + //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. + float gx = (rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]); + float gy = (rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]); + //Apply power to the magnitude of the gradient to get the edge stopping function. + a[x + w * y] = Scale * pow_F(0.5f * sqrtf(gx * gx + gy * gy + sqreps), -EdgeStopping); + } + +#else + + for(int x = 0; x < w1; x++) { + //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. + float gx = (rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]); + float gy = (rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]); + + //Apply power to the magnitude of the gradient to get the edge stopping function. + a[x + w * y] = Scale * pow_F(0.5f * sqrtf(gx * gx + gy * gy + sqreps), -EdgeStopping); + } + +#endif + } + } + + + /* Now setup the linear problem. I use the Maxima CAS, here's code for making an FEM formulation for the smoothness term: + p(x, y) := (1 - x)*(1 - y); + P(m, n) := A[m][n]*p(x, y) + A[m + 1][n]*p(1 - x, y) + A[m + 1][n + 1]*p(1 - x, 1 - y) + A[m][n + 1]*p(x, 1 - y); + Integrate(f) := integrate(integrate(f, x, 0, 1), y, 0, 1); + + Integrate(diff(P(u, v), x)*diff(p(x, y), x) + diff(P(u, v), y)*diff(p(x, y), y)); + Integrate(diff(P(u - 1, v), x)*diff(p(1 - x, y), x) + diff(P(u - 1, v), y)*diff(p(1 - x, y), y)); + Integrate(diff(P(u - 1, v - 1), x)*diff(p(1 - x, 1 - y), x) + diff(P(u - 1, v - 1), y)*diff(p(1 - x, 1 - y), y)); + Integrate(diff(P(u, v - 1), x)*diff(p(x, 1 - y), x) + diff(P(u, v - 1), y)*diff(p(x, 1 - y), y)); + So yeah. Use the numeric results of that to fill the matrix A.*/ + + memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); + memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); + memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); + memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); // checked for race condition here @@ -662,153 +798,198 @@ SSEFUNCTION float *EdgePreservingDecomposition::CreateBlur(float *Source, float // So, there should be no race conditions #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int y = 0; y < h; y++){ - int i = y*w; - for(int x = 0; x < w; x++, i++){ - float ac,a0temp; - a0temp = 0.25f; - //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. - if(x > 0 && y > 0) { - ac = a[i - w - 1]/6.0f; - a_w_1[i - w - 1] -= 2.0f*ac; - a_w[i - w] -= ac; - a_1[i - 1] -= ac; - a0temp += ac; - } - if(x < w1 && y > 0) { - ac = a[i - w]/6.0f; - a_w[i - w] -= ac; - a_w1[i - w + 1] -= 2.0f*ac; - a0temp += ac; - } - if(x > 0 && y < h1) { - ac = a[i - 1]/6.0f; - a_1[i - 1] -= ac; - a0temp += ac; - } - if(x < w1 && y < h1) - a0temp += a[i]/6.0f; - a0[i] = 4.0f*a0temp; - } - } + for(int y = 0; y < h; y++) { + int i = y * w; - if(UseBlurForEdgeStop) delete[] a; - //Solve & return. - bool success=A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). - if(!success) { - fprintf(stderr,"Error: Tonemapping has failed.\n"); - memset(Blur, 0, sizeof(float)*n); // On failure, set the blur to zero. This is subsequently exponentiated in CompressDynamicRange. + for(int x = 0; x < w; x++, i++) { + float ac, a0temp; + a0temp = 0.25f; + + //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. + if(x > 0 && y > 0) { + ac = a[i - w - 1] / 6.0f; + a_w_1[i - w - 1] -= 2.0f * ac; + a_w[i - w] -= ac; + a_1[i - 1] -= ac; + a0temp += ac; + } + + if(x < w1 && y > 0) { + ac = a[i - w] / 6.0f; + a_w[i - w] -= ac; + a_w1[i - w + 1] -= 2.0f * ac; + a0temp += ac; + } + + if(x > 0 && y < h1) { + ac = a[i - 1] / 6.0f; + a_1[i - 1] -= ac; + a0temp += ac; + } + + if(x < w1 && y < h1) { + a0temp += a[i] / 6.0f; + } + + a0[i] = 4.0f * a0temp; + } + } + + if(UseBlurForEdgeStop) { + delete[] a; + } + + //Solve & return. + bool success = A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). + + if(!success) { + fprintf(stderr, "Error: Tonemapping has failed.\n"); + memset(Blur, 0, sizeof(float)*n); // On failure, set the blur to zero. This is subsequently exponentiated in CompressDynamicRange. + return Blur; + } + + if(!UseBlurForEdgeStop) { + memcpy(Blur, Source, n * sizeof(float)); + } + + SparseConjugateGradient(A->PassThroughVectorProduct, Source, n, false, Blur, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); + A->KillIncompleteCholeskyFactorization(); return Blur; - } - if(!UseBlurForEdgeStop) memcpy(Blur, Source, n*sizeof(float)); - SparseConjugateGradient(A->PassThroughVectorProduct, Source, n, false, Blur, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - A->KillIncompleteCholeskyFactorization(); - return Blur; } -float *EdgePreservingDecomposition::CreateIteratedBlur(float *Source, float Scale, float EdgeStopping, int Iterates, int Reweightings, float *Blur){ - //Simpler outcome? - if(Reweightings == 0) return CreateBlur(Source, Scale, EdgeStopping, Iterates, Blur); +float *EdgePreservingDecomposition::CreateIteratedBlur(float *Source, float Scale, float EdgeStopping, int Iterates, int Reweightings, float *Blur) +{ + //Simpler outcome? + if(Reweightings == 0) { + return CreateBlur(Source, Scale, EdgeStopping, Iterates, Blur); + } - //Create a blur here, initialize. - if(Blur == NULL) Blur = new float[n]; - memcpy(Blur, Source, n*sizeof(float)); + //Create a blur here, initialize. + if(Blur == NULL) { + Blur = new float[n]; + } - //Iteratively improve the blur. - Reweightings++; - for(int i = 0; i < Reweightings; i++) - CreateBlur(Source, Scale, EdgeStopping, Iterates, Blur, true); + memcpy(Blur, Source, n * sizeof(float)); - return Blur; + //Iteratively improve the blur. + Reweightings++; + + for(int i = 0; i < Reweightings; i++) { + CreateBlur(Source, Scale, EdgeStopping, Iterates, Blur, true); + } + + return Blur; } -SSEFUNCTION float *EdgePreservingDecomposition::CompressDynamicRange(float *Source, float Scale, float EdgeStopping, float CompressionExponent, float DetailBoost, int Iterates, int Reweightings, float *Compressed){ - if(w<300 && h<300) // set number of Reweightings to zero for small images (thumbnails). We could try to find a better solution here. - Reweightings = 0; - - //Small number intended to prevent division by zero. This is different from the eps in CreateBlur. - const float eps = 0.0001f; +SSEFUNCTION float *EdgePreservingDecomposition::CompressDynamicRange(float *Source, float Scale, float EdgeStopping, float CompressionExponent, float DetailBoost, int Iterates, int Reweightings, float *Compressed) +{ + if(w < 300 && h < 300) { // set number of Reweightings to zero for small images (thumbnails). We could try to find a better solution here. + Reweightings = 0; + } - //We're working with luminance, which does better logarithmic. + //Small number intended to prevent division by zero. This is different from the eps in CreateBlur. + const float eps = 0.0001f; + + //We're working with luminance, which does better logarithmic. #ifdef __SSE2__ #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - __m128 epsv = _mm_set1_ps( eps ); + { + __m128 epsv = _mm_set1_ps( eps ); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int ii = 0; ii < n-3; ii+=4) - _mm_storeu_ps( &Source[ii], xlogf(LVFU(Source[ii]) + epsv)); -} - for(int ii = n-(n%4); ii < n; ii++) - Source[ii] = xlogf(Source[ii] + eps); + + for(int ii = 0; ii < n - 3; ii += 4) { + _mm_storeu_ps( &Source[ii], xlogf(LVFU(Source[ii]) + epsv)); + } + } + + for(int ii = n - (n % 4); ii < n; ii++) { + Source[ii] = xlogf(Source[ii] + eps); + } #else #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int ii = 0; ii < n; ii++) - Source[ii] = xlogf(Source[ii] + eps); -#endif - - //Blur. Also setup memory for Compressed (we can just use u since each element of u is used in one calculation). - float *u = CreateIteratedBlur(Source, Scale, EdgeStopping, Iterates, Reweightings); - if(Compressed == NULL) Compressed = u; - //Apply compression, detail boost, unlogging. Compression is done on the logged data and detail boost on unlogged. -// float temp = CompressionExponent - 1.0f; - float temp; - if(DetailBoost>0.f) { - float betemp=expf(-(2.f-DetailBoost+0.694f))-1.f;//0.694 = log(2) - temp = 1.2f*xlogf( -betemp); - } - else temp= CompressionExponent - 1.0f; + for(int ii = 0; ii < n; ii++) { + Source[ii] = xlogf(Source[ii] + eps); + } + +#endif + + //Blur. Also setup memory for Compressed (we can just use u since each element of u is used in one calculation). + float *u = CreateIteratedBlur(Source, Scale, EdgeStopping, Iterates, Reweightings); + + if(Compressed == NULL) { + Compressed = u; + } + + //Apply compression, detail boost, unlogging. Compression is done on the logged data and detail boost on unlogged. +// float temp = CompressionExponent - 1.0f; + float temp; + + if(DetailBoost > 0.f) { + float betemp = expf(-(2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + temp = 1.2f * xlogf( -betemp); + } else { + temp = CompressionExponent - 1.0f; + } + #ifdef __SSE2__ #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - __m128 cev, uev, sourcev; - __m128 epsv = _mm_set1_ps( eps ); - __m128 DetailBoostv = _mm_set1_ps( DetailBoost ); - __m128 tempv = _mm_set1_ps( temp ); + { + __m128 cev, uev, sourcev; + __m128 epsv = _mm_set1_ps( eps ); + __m128 DetailBoostv = _mm_set1_ps( DetailBoost ); + __m128 tempv = _mm_set1_ps( temp ); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < n-3; i+=4){ - cev = xexpf(LVFU(Source[i]) + LVFU(u[i])*(tempv)) - epsv; - uev = xexpf(LVFU(u[i])) - epsv; - sourcev = xexpf(LVFU(Source[i])) - epsv; - _mm_storeu_ps( &Source[i], sourcev); - _mm_storeu_ps( &Compressed[i], cev + DetailBoostv * (sourcev - uev) ); - } -} - for(int i=n-(n%4); i < n; i++){ - float ce = xexpf(Source[i] + u[i]*(temp)) - eps; - float ue = xexpf(u[i]) - eps; - Source[i] = xexpf(Source[i]) - eps; - Compressed[i] = ce + DetailBoost*(Source[i] - ue); - } - + + for(int i = 0; i < n - 3; i += 4) { + cev = xexpf(LVFU(Source[i]) + LVFU(u[i]) * (tempv)) - epsv; + uev = xexpf(LVFU(u[i])) - epsv; + sourcev = xexpf(LVFU(Source[i])) - epsv; + _mm_storeu_ps( &Source[i], sourcev); + _mm_storeu_ps( &Compressed[i], cev + DetailBoostv * (sourcev - uev) ); + } + } + + for(int i = n - (n % 4); i < n; i++) { + float ce = xexpf(Source[i] + u[i] * (temp)) - eps; + float ue = xexpf(u[i]) - eps; + Source[i] = xexpf(Source[i]) - eps; + Compressed[i] = ce + DetailBoost * (Source[i] - ue); + } + #else #ifdef _OPENMP -#pragma omp parallel for -#endif - for(int i = 0; i < n; i++){ - float ce = xexpf(Source[i] + u[i]*(temp)) - eps; - float ue = xexpf(u[i]) - eps; - Source[i] = xexpf(Source[i]) - eps; - Compressed[i] = ce + DetailBoost*(Source[i] - ue); - } + #pragma omp parallel for #endif - if(Compressed != u) delete[] u; - return Compressed; + for(int i = 0; i < n; i++) { + float ce = xexpf(Source[i] + u[i] * (temp)) - eps; + float ue = xexpf(u[i]) - eps; + Source[i] = xexpf(Source[i]) - eps; + Compressed[i] = ce + DetailBoost * (Source[i] - ue); + } + +#endif + + if(Compressed != u) { + delete[] u; + } + + return Compressed; } diff --git a/rtengine/EdgePreservingDecomposition.h b/rtengine/EdgePreservingDecomposition.h index ff118408b..558caa5db 100644 --- a/rtengine/EdgePreservingDecomposition.h +++ b/rtengine/EdgePreservingDecomposition.h @@ -6,40 +6,40 @@ image. As a byproduct it contains a lot of linear algebra which can be useful fo you want to solve in rectangles on rectangular grids. Anyway. Basically, this is an implementation of what's presented in the following papers: - Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation - An Iterative Solution Method for Linear Systems of Which the Coefficient Matrix is a Symetric M-Matrix - Color correction for tone mapping - Wikipedia, the free encyclopedia + Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation + An Iterative Solution Method for Linear Systems of Which the Coefficient Matrix is a Symetric M-Matrix + Color correction for tone mapping + Wikipedia, the free encyclopedia First one is most of what matters, next two are details, last everything else. I did a few things differently, especially: - Reformulated the minimization with finite elements instead of finite differences. This results in better conditioning, - slightly better accuracy (less artifacts), the possibility of a better picked edge stopping function, but more memory consumption. + Reformulated the minimization with finite elements instead of finite differences. This results in better conditioning, + slightly better accuracy (less artifacts), the possibility of a better picked edge stopping function, but more memory consumption. - A single rotationally invariant edge stopping function is used instead of two non-invariant ones. + A single rotationally invariant edge stopping function is used instead of two non-invariant ones. - Incomplete Cholseky factorization instead of Szeliski's LAHBF. Slower, but not subject to any patents. + Incomplete Cholseky factorization instead of Szeliski's LAHBF. Slower, but not subject to any patents. - For tone mapping, original images are decomposed instead of their logarithms, and just one decomposition is made; - I find that this way works plenty good (theirs isn't better or worse... just different) and is simpler. + For tone mapping, original images are decomposed instead of their logarithms, and just one decomposition is made; + I find that this way works plenty good (theirs isn't better or worse... just different) and is simpler. Written by ben_pcc in Portland, Oregon, USA. Some history: - Late April 2010, I develop interest in this stuff because photos of my ceramics lack local contrast. - Mid 2010, it works but is too slow to be useful. - Fall 2010, various unsuccessful attempts at speeding up are tried. - Early December 2010, I get off the path of least resistance and write a matrix storage class with incomplete Cholesky decomposition. - 31 December 2010, the FEM reformulation works very well. - 1 January 2011, I'm cleaning up this file and readying it for initial release. - 12 - 14 November 2011, further cleanup, improvements, bug fixes, integration into Raw Therapee. + Late April 2010, I develop interest in this stuff because photos of my ceramics lack local contrast. + Mid 2010, it works but is too slow to be useful. + Fall 2010, various unsuccessful attempts at speeding up are tried. + Early December 2010, I get off the path of least resistance and write a matrix storage class with incomplete Cholesky decomposition. + 31 December 2010, the FEM reformulation works very well. + 1 January 2011, I'm cleaning up this file and readying it for initial release. + 12 - 14 November 2011, further cleanup, improvements, bug fixes, integration into Raw Therapee. It's likely that I'll take apart and rerelease contents of this file (in the distant future) as most of it isn't edge preserving decomposition and rather supporting material. SparseConjugateGradient alone is a workhorse I and a few others have been exploiting for a few years. EdgePreservingDecomposition.h and EdgePreservingDecomposition.cpp are released under the following licence: - � It's free. - � You may not incorporate this code as part of proprietary or commercial software, but via freeware you may use its output for profit. - � You may modify and redistribute, but keep this big comment block intact and not for profit in any way unless I give specific permission. - � If you're unsure about anything else, treat as public domain. - � Don't be a dick. + � It's free. + � You may not incorporate this code as part of proprietary or commercial software, but via freeware you may use its output for profit. + � You may modify and redistribute, but keep this big comment block intact and not for profit in any way unless I give specific permission. + � If you're unsure about anything else, treat as public domain. + � Don't be a dick. My email address is my screen name followed by @yahoo.com. I'm also known as ben_s or nonbasketless. Enjoy! */ @@ -56,83 +56,88 @@ My email address is my screen name followed by @yahoo.com. I'm also known as ben float *SparseConjugateGradient(void Ax(float *Product, float *x, void *Pass), float *b, int n, bool OkToModify_b = true, float *x = NULL, float RMSResidual = 0.0f, void *Pass = NULL, int MaximumIterates = 0, void Preconditioner(float *Product, float *x, void *Pass) = NULL); //Storage and use class for symmetric matrices, the nonzero contents of which are confined to diagonals. -class MultiDiagonalSymmetricMatrix{ +class MultiDiagonalSymmetricMatrix +{ public: - MultiDiagonalSymmetricMatrix(int Dimension, int NumberOfDiagonalsInLowerTriangle); - ~MultiDiagonalSymmetricMatrix(); + MultiDiagonalSymmetricMatrix(int Dimension, int NumberOfDiagonalsInLowerTriangle); + ~MultiDiagonalSymmetricMatrix(); - /* Storage of matrix data, and a function to create memory for Diagonals[index]. - Here's the storage scheme, designed to be simple both on paper and in C++: + /* Storage of matrix data, and a function to create memory for Diagonals[index]. + Here's the storage scheme, designed to be simple both on paper and in C++: - Let's say you have some diagonal. The StartRows is the row on which, at the left edge of the matrix, the diagonal "starts", - and StartRows must strictly increase with its index. The main diagonal for example has start row 0, its subdiagonal has 1, etc. - Then, Diagonal[j] is the matrix entry on the diagonal at column j. For efficiency, you're expected to learn this and fill in - public Diagonals manually. Symmetric matrices are represented by this class, and all symmetry is handled internally, you - only every worry or think about the lower trianglular (including main diagonal) part of the matrix. - */ - float **Diagonals; - char *buffer; - char *DiagBuffer; - int *StartRows; - bool CreateDiagonal(int index, int StartRow); - int n, m; //The matrix is n x n, with m diagonals on the lower triangle. Don't change these. They should be private but aren't for convenience. - inline int DiagonalLength(int StartRow){ //Gives number of elements in a diagonal. - return n - StartRow; - }; + Let's say you have some diagonal. The StartRows is the row on which, at the left edge of the matrix, the diagonal "starts", + and StartRows must strictly increase with its index. The main diagonal for example has start row 0, its subdiagonal has 1, etc. + Then, Diagonal[j] is the matrix entry on the diagonal at column j. For efficiency, you're expected to learn this and fill in + public Diagonals manually. Symmetric matrices are represented by this class, and all symmetry is handled internally, you + only every worry or think about the lower trianglular (including main diagonal) part of the matrix. + */ + float **Diagonals; + char *buffer; + char *DiagBuffer; + int *StartRows; + bool CreateDiagonal(int index, int StartRow); + int n, m; //The matrix is n x n, with m diagonals on the lower triangle. Don't change these. They should be private but aren't for convenience. + inline int DiagonalLength(int StartRow) //Gives number of elements in a diagonal. + { + return n - StartRow; + }; - //Not efficient, but you can use it if you're lazy, or for early tests. Returns false if the row + column falls on no loaded diagonal, true otherwise. - bool LazySetEntry(float value, int row, int column); + //Not efficient, but you can use it if you're lazy, or for early tests. Returns false if the row + column falls on no loaded diagonal, true otherwise. + bool LazySetEntry(float value, int row, int column); - //Calculates the matrix-vector product of the matrix represented by this class onto the vector x. - void VectorProduct(float *Product, float *x); + //Calculates the matrix-vector product of the matrix represented by this class onto the vector x. + void VectorProduct(float *Product, float *x); - //Given the start row, attempts to find the corresponding index, or -1 if the StartRow doesn't exist. - inline int FindIndex(int StartRow) __attribute__((always_inline)); + //Given the start row, attempts to find the corresponding index, or -1 if the StartRow doesn't exist. + inline int FindIndex(int StartRow) __attribute__((always_inline)); - //This is the same as above, but designed to take this class as a pass through variable. By this way you can feed - //the meat of this class into an independent function, such as SparseConjugateGradient. - static void PassThroughVectorProduct(float *Product, float *x, void *Pass){ - (static_cast(Pass))->VectorProduct(Product, x); - }; + //This is the same as above, but designed to take this class as a pass through variable. By this way you can feed + //the meat of this class into an independent function, such as SparseConjugateGradient. + static void PassThroughVectorProduct(float *Product, float *x, void *Pass) + { + (static_cast(Pass))->VectorProduct(Product, x); + }; - /* CreateIncompleteCholeskyFactorization creates another matrix which is an incomplete (or complete if MaxFillAbove is big enough) - LDLt factorization of this matrix. Storage is like this: the first diagonal is the diagonal matrix D and the remaining diagonals - describe all of L except its main diagonal, which is a bunch of ones. Read up on the LDLt Cholesky factorization for what all this means. - Note that VectorProduct is nonsense. More useful to you is CholeskyBackSolve which fills x, where LDLt x = b. */ - bool CreateIncompleteCholeskyFactorization(int MaxFillAbove = 0); - void KillIncompleteCholeskyFactorization(void); - void CholeskyBackSolve(float *x, float *b); - MultiDiagonalSymmetricMatrix *IncompleteCholeskyFactorization; + /* CreateIncompleteCholeskyFactorization creates another matrix which is an incomplete (or complete if MaxFillAbove is big enough) + LDLt factorization of this matrix. Storage is like this: the first diagonal is the diagonal matrix D and the remaining diagonals + describe all of L except its main diagonal, which is a bunch of ones. Read up on the LDLt Cholesky factorization for what all this means. + Note that VectorProduct is nonsense. More useful to you is CholeskyBackSolve which fills x, where LDLt x = b. */ + bool CreateIncompleteCholeskyFactorization(int MaxFillAbove = 0); + void KillIncompleteCholeskyFactorization(void); + void CholeskyBackSolve(float *x, float *b); + MultiDiagonalSymmetricMatrix *IncompleteCholeskyFactorization; - static void PassThroughCholeskyBackSolve(float *Product, float *x, void *Pass){ - (static_cast(Pass))->CholeskyBackSolve(Product, x); - }; + static void PassThroughCholeskyBackSolve(float *Product, float *x, void *Pass) + { + (static_cast(Pass))->CholeskyBackSolve(Product, x); + }; }; -class EdgePreservingDecomposition{ +class EdgePreservingDecomposition +{ public: - EdgePreservingDecomposition(int width, int height); - ~EdgePreservingDecomposition(); + EdgePreservingDecomposition(int width, int height); + ~EdgePreservingDecomposition(); - //Create an edge preserving blur of Source. Will create and return, or fill into Blur if not NULL. In place not ok. - //If UseBlurForEdgeStop is true, supplied not NULL Blur is used to calculate the edge stopping function instead of Source. - float *CreateBlur(float *Source, float Scale, float EdgeStopping, int Iterates, float *Blur = NULL, bool UseBlurForEdgeStop = false); + //Create an edge preserving blur of Source. Will create and return, or fill into Blur if not NULL. In place not ok. + //If UseBlurForEdgeStop is true, supplied not NULL Blur is used to calculate the edge stopping function instead of Source. + float *CreateBlur(float *Source, float Scale, float EdgeStopping, int Iterates, float *Blur = NULL, bool UseBlurForEdgeStop = false); - //Iterates CreateBlur such that the smoothness term approaches a specific norm via iteratively reweighted least squares. In place not ok. - float *CreateIteratedBlur(float *Source, float Scale, float EdgeStopping, int Iterates, int Reweightings, float *Blur = NULL); + //Iterates CreateBlur such that the smoothness term approaches a specific norm via iteratively reweighted least squares. In place not ok. + float *CreateIteratedBlur(float *Source, float Scale, float EdgeStopping, int Iterates, int Reweightings, float *Blur = NULL); - /*Lowers global contrast while preserving or boosting local contrast. Can fill into Compressed. The smaller Compression - the more compression is applied, with Compression = 1 giving no effect and above 1 the opposite effect. You can totally - use Compression = 1 and play with DetailBoost for some really sweet unsharp masking. If working on luma/grey, consider giving it a logarithm. - In place calculation to save memory (Source == Compressed) is totally ok. Reweightings > 0 invokes CreateIteratedBlur instead of CreateBlur. */ - float *CompressDynamicRange(float *Source, float Scale = 1.0f, float EdgeStopping = 1.4f, float CompressionExponent = 0.8f, float DetailBoost = 0.1f, int Iterates = 20, int Reweightings = 0, float *Compressed = NULL); + /*Lowers global contrast while preserving or boosting local contrast. Can fill into Compressed. The smaller Compression + the more compression is applied, with Compression = 1 giving no effect and above 1 the opposite effect. You can totally + use Compression = 1 and play with DetailBoost for some really sweet unsharp masking. If working on luma/grey, consider giving it a logarithm. + In place calculation to save memory (Source == Compressed) is totally ok. Reweightings > 0 invokes CreateIteratedBlur instead of CreateBlur. */ + float *CompressDynamicRange(float *Source, float Scale = 1.0f, float EdgeStopping = 1.4f, float CompressionExponent = 0.8f, float DetailBoost = 0.1f, int Iterates = 20, int Reweightings = 0, float *Compressed = NULL); private: - MultiDiagonalSymmetricMatrix *A; //The equations are simple enough to not mandate a matrix class, but fast solution NEEDS a complicated preconditioner. - int w, h, n; + MultiDiagonalSymmetricMatrix *A; //The equations are simple enough to not mandate a matrix class, but fast solution NEEDS a complicated preconditioner. + int w, h, n; - //Convenient access to the data in A. - float * RESTRICT a0, * RESTRICT a_1, * RESTRICT a_w, * RESTRICT a_w_1, * RESTRICT a_w1; + //Convenient access to the data in A. + float * RESTRICT a0, * RESTRICT a_1, * RESTRICT a_w, * RESTRICT a_w_1, * RESTRICT a_w1; }; diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index d2d9249ea..71c65cfb0 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -1,24 +1,24 @@ //////////////////////////////////////////////////////////////// // -// CFA denoise by wavelet transform, FT filtering +// CFA denoise by wavelet transform, FT filtering // -// copyright (c) 2008-2012 Emil Martinec +// copyright (c) 2008-2012 Emil Martinec // // // code dated: March 9, 2012 // -// FTblockDN.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// FTblockDN.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -41,10 +41,10 @@ #include #endif -#define TS 64 // Tile size -#define offset 25 // shift between tiles -#define fTS ((TS/2+1)) // second dimension of Fourier tiles -#define blkrad 1 // radius of block averaging +#define TS 64 // Tile size +#define offset 25 // shift between tiles +#define fTS ((TS/2+1)) // second dimension of Fourier tiles +#define blkrad 1 // radius of block averaging #define epsilon 0.001f/(TS*TS) //tolerance @@ -90,1568 +90,1978 @@ PIX_SORT(pp[10], pp[12]) ; PIX_SORT(pp[6], pp[10]) ; PIX_SORT(pp[6], pp[17]) ;\ PIX_SORT(pp[12], pp[17]) ; PIX_SORT(pp[7], pp[17]) ; PIX_SORT(pp[7], pp[10]) ;\ PIX_SORT(pp[12], pp[18]) ; PIX_SORT(pp[7], pp[12]) ; PIX_SORT(pp[10], pp[18]) ;\ PIX_SORT(pp[12], pp[20]) ; PIX_SORT(pp[10], pp[20]) ; PIX_SORT(pp[10], pp[12]) ;\ -median=pp[12];} +median=pp[12];} #define ELEM_FLOAT_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; } -namespace rtengine { +namespace rtengine +{ - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - /* - Structure of the algorithm: +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/* + Structure of the algorithm: - 1. Compute an initial denoise of the image via undecimated wavelet transform - and universal thresholding modulated by user input. - 2. Decompose the residual image into TSxTS size tiles, shifting by 'offset' each step - (so roughly each pixel is in (TS/offset)^2 tiles); Discrete Cosine transform the tiles. - 3. Filter the DCT data to pick out patterns missed by the wavelet denoise - 4. Inverse DCT the denoised tile data and combine the tiles into a denoised output image. + 1. Compute an initial denoise of the image via undecimated wavelet transform + and universal thresholding modulated by user input. + 2. Decompose the residual image into TSxTS size tiles, shifting by 'offset' each step + (so roughly each pixel is in (TS/offset)^2 tiles); Discrete Cosine transform the tiles. + 3. Filter the DCT data to pick out patterns missed by the wavelet denoise + 4. Inverse DCT the denoised tile data and combine the tiles into a denoised output image. - */ + */ - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% extern const Settings* settings; // Median calculation using quicksort -float fq_sort2(float arr[], int n) +float fq_sort2(float arr[], int n) { int low = 0; - int high = n-1; + int high = n - 1; int median = (low + high) / 2; for (;;) { - if (high <= low) + if (high <= low) { return arr[median] ; - if (high == low + 1) { - if (arr[low] > arr[high]) - ELEM_FLOAT_SWAP(arr[low], arr[high]) ; - return arr[median] ; } - int middle = (low + high) / 2; - if (arr[middle] > arr[high]) ELEM_FLOAT_SWAP(arr[middle], arr[high]) ; - if (arr[low] > arr[high]) ELEM_FLOAT_SWAP(arr[low], arr[high]) ; - if (arr[middle] > arr[low]) ELEM_FLOAT_SWAP(arr[middle], arr[low]) ; + if (high == low + 1) { + if (arr[low] > arr[high]) { + ELEM_FLOAT_SWAP(arr[low], arr[high]) ; + } - ELEM_FLOAT_SWAP(arr[middle], arr[low+1]) ; - int ll = low + 1; - int hh = high; + return arr[median] ; + } - for (;;) { - do ll++; while (arr[low] > arr[ll]) ; - do hh--; while (arr[hh] > arr[low]) ; + int middle = (low + high) / 2; - if (hh < ll) - break; + if (arr[middle] > arr[high]) { + ELEM_FLOAT_SWAP(arr[middle], arr[high]) ; + } - ELEM_FLOAT_SWAP(arr[ll], arr[hh]) ; - } + if (arr[low] > arr[high]) { + ELEM_FLOAT_SWAP(arr[low], arr[high]) ; + } - ELEM_FLOAT_SWAP(arr[low], arr[hh]) ; + if (arr[middle] > arr[low]) { + ELEM_FLOAT_SWAP(arr[middle], arr[low]) ; + } - if (hh <= median) - low = ll; - if (hh >= median) - high = hh - 1; + ELEM_FLOAT_SWAP(arr[middle], arr[low + 1]) ; + int ll = low + 1; + int hh = high; + + for (;;) { + do { + ll++; + } while (arr[low] > arr[ll]) ; + + do { + hh--; + } while (arr[hh] > arr[low]) ; + + if (hh < ll) { + break; + } + + ELEM_FLOAT_SWAP(arr[ll], arr[hh]) ; + } + + ELEM_FLOAT_SWAP(arr[low], arr[hh]) ; + + if (hh <= median) { + low = ll; + } + + if (hh >= median) { + high = hh - 1; + } } - } +} float media(float *elements, int N) { - // Order elements (only half of them) - for (int i = 0; i < (N >> 1) + 1; ++i) - { - // Find position of minimum element - int min = i; - for (int j = i + 1; j < N; ++j) - if (elements[j] < elements[min]) - min = j; - // Put found minimum element in its place - float temp = elements[i]; - elements[i] = elements[min]; - elements[min] = temp; - } - // Get result - the middle element - return elements[N >> 1]; + // Order elements (only half of them) + for (int i = 0; i < (N >> 1) + 1; ++i) { + // Find position of minimum element + int min = i; + + for (int j = i + 1; j < N; ++j) + if (elements[j] < elements[min]) { + min = j; + } + + // Put found minimum element in its place + float temp = elements[i]; + elements[i] = elements[min]; + elements[min] = temp; + } + + // Get result - the middle element + return elements[N >> 1]; } void ImProcFunctions::Median_Denoise( float **src, float **dst, const int width, const int height, const mediantype medianType, const int iterations, const int numThreads, float **buffer) { - int border=1, numElements, middleElement; - switch(medianType) { - case MED_3X3SOFT: - case MED_3X3STRONG: - border = 1; - break; - case MED_5X5SOFT: - border = 2; - break; - case MED_5X5STRONG: - border = 2; - break; - case MED_7X7: - border = 3; - numElements = 49; - middleElement = 24; - break; - default: // includes MED_9X9 - border = 4; - numElements = 81; - middleElement = 40; - } + int border = 1, numElements, middleElement; - float **allocBuffer = NULL; - float **medBuffer[2]; - medBuffer[0] = src; - // we need a buffer if src == dst or if (src != dst && iterations > 1) - if(src == dst || (src != dst && iterations>1)) { - if(buffer == NULL) { // we didn't get a buufer => create one - allocBuffer = new float*[height]; - for (int i=0; i use it - medBuffer[1] = buffer; - } - } else { // we can write directly into destination - medBuffer[1] = dst; - } + switch(medianType) { + case MED_3X3SOFT: + case MED_3X3STRONG: + border = 1; + break; - float ** medianIn, ** medianOut; - int BufferIndex = 0; - for(int iteration=1;iteration<=iterations;iteration++){ - medianIn = medBuffer[BufferIndex]; - medianOut = medBuffer[BufferIndex^1]; + case MED_5X5SOFT: + border = 2; + break; - if(iteration == 1) { // upper border - for (int i=0; i 1) + if(src == dst || (src != dst && iterations > 1)) { + if(buffer == NULL) { // we didn't get a buufer => create one + allocBuffer = new float*[height]; + + for (int i = 0; i < height; i++) { + allocBuffer[i] = new float[width]; + } + + medBuffer[1] = allocBuffer; + } else { // we got a buffer => use it + medBuffer[1] = buffer; + } + } else { // we can write directly into destination + medBuffer[1] = dst; + } + + float ** medianIn, ** medianOut; + int BufferIndex = 0; + + for(int iteration = 1; iteration <= iterations; iteration++) { + medianIn = medBuffer[BufferIndex]; + medianOut = medBuffer[BufferIndex ^ 1]; + + if(iteration == 1) { // upper border + for (int i = 0; i < border; i++) + for (int j = 0; j < width; j++) { + medianOut[i][j] = medianIn[i][j]; + } + } #ifdef _OPENMP -#pragma omp parallel for num_threads(numThreads) if(numThreads>1) + #pragma omp parallel for num_threads(numThreads) if(numThreads>1) #endif - for (int i=border; i1) + #pragma omp parallel for num_threads(numThreads) if(numThreads>1) #endif - for(int i = border; i < height-border; i++ ) { - for(int j = border; j < width-border; j++) { - dst[i][j] = medianOut[i][j]; - } - } - } - if(allocBuffer != NULL) { // we allocated memory, so let's free it now - for (int i=0; icopyData(dst); - if(calclum) { - delete calclum; - calclum = NULL; - } - - return; - } - - static MyMutex FftwMutex; - MyMutex::MyLock lock(FftwMutex); - - const nrquality nrQuality = (dnparams.smethod == "shal") ? QUALITY_STANDARD : QUALITY_HIGH;//shrink method - const float qhighFactor = (nrQuality == QUALITY_HIGH) ? 1.f/(float) settings->nrhigh : 1.0f; - const bool useNoiseCCurve = (noiseCCurve && noiseCCurve.getSum() > 5.f ); - const bool useNoiseLCurve = (noiseLCurve && noiseLCurve.getSum() >= 7.f ); - const bool autoch = (settings->leveldnautsimpl==1 && (dnparams.Cmethod=="AUT" || dnparams.Cmethod=="PRE")) || (settings->leveldnautsimpl==0 && (dnparams.C2method=="AUTO" || dnparams.C2method=="PREV")); + if (dnparams.luma == 0 && dnparams.chroma == 0 && !dnparams.median && !noiseLCurve && !noiseCCurve) { + //nothing to do; copy src to dst or do nothing in case src == dst + if(src != dst) { + src->copyData(dst); + } - float** lumcalc; - float* lumcalcBuffer; - float** ccalc; - float* ccalcBuffer; - - bool ponder=false; - float ponderCC=1.f; - if(settings->leveldnautsimpl==1 && params->dirpyrDenoise.Cmethod=="PON") {ponder=true;ponderCC=0.5f;} - if(settings->leveldnautsimpl==1 && params->dirpyrDenoise.Cmethod=="PRE") {ponderCC=0.5f;} - if(settings->leveldnautsimpl==0 && params->dirpyrDenoise.Cmethod=="PREV") {ponderCC=0.5f;} + if(calclum) { + delete calclum; + calclum = NULL; + } - int metchoice=0; - if(dnparams.methodmed=="Lonly") metchoice=1; - else if(dnparams.methodmed=="Lab") metchoice=2; - else if(dnparams.methodmed=="ab") metchoice=3; - else if(dnparams.methodmed=="Lpab") metchoice=4; + return; + } - const bool denoiseMethodRgb = (dnparams.dmethod == "RGB"); - // init luma noisevarL - const float noiseluma=(float) dnparams.luma; - const float noisevarL = (useNoiseLCurve && (denoiseMethodRgb || !isRAW)) ? (float) (SQR(((noiseluma+1.0)/125.0)*(10.+ (noiseluma+1.0)/25.0))) : (float) (SQR((noiseluma/125.0)*(1.0+ noiseluma/25.0))); - const bool denoiseLuminance = (noisevarL > 0.00001f); - //printf("NL=%f \n",noisevarL); - if(useNoiseLCurve || useNoiseCCurve) { - int hei=calclum->height; - int wid=calclum->width; - TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); + static MyMutex FftwMutex; + MyMutex::MyLock lock(FftwMutex); - const float wpi[3][3] = { - {static_cast(wprofi[0][0]),static_cast(wprofi[0][1]),static_cast(wprofi[0][2])}, - {static_cast(wprofi[1][0]),static_cast(wprofi[1][1]),static_cast(wprofi[1][2])}, - {static_cast(wprofi[2][0]),static_cast(wprofi[2][1]),static_cast(wprofi[2][2])} - }; - lumcalcBuffer = new float[hei*wid]; - lumcalc = new float*[(hei)]; - for (int i=0; inrhigh : 1.0f; + const bool useNoiseCCurve = (noiseCCurve && noiseCCurve.getSum() > 5.f ); + const bool useNoiseLCurve = (noiseLCurve && noiseLCurve.getSum() >= 7.f ); + const bool autoch = (settings->leveldnautsimpl == 1 && (dnparams.Cmethod == "AUT" || dnparams.Cmethod == "PRE")) || (settings->leveldnautsimpl == 0 && (dnparams.C2method == "AUTO" || dnparams.C2method == "PREV")); + + float** lumcalc; + float* lumcalcBuffer; + float** ccalc; + float* ccalcBuffer; + + bool ponder = false; + float ponderCC = 1.f; + + if(settings->leveldnautsimpl == 1 && params->dirpyrDenoise.Cmethod == "PON") { + ponder = true; + ponderCC = 0.5f; + } + + if(settings->leveldnautsimpl == 1 && params->dirpyrDenoise.Cmethod == "PRE") { + ponderCC = 0.5f; + } + + if(settings->leveldnautsimpl == 0 && params->dirpyrDenoise.Cmethod == "PREV") { + ponderCC = 0.5f; + } + + int metchoice = 0; + + if(dnparams.methodmed == "Lonly") { + metchoice = 1; + } else if(dnparams.methodmed == "Lab") { + metchoice = 2; + } else if(dnparams.methodmed == "ab") { + metchoice = 3; + } else if(dnparams.methodmed == "Lpab") { + metchoice = 4; + } + + const bool denoiseMethodRgb = (dnparams.dmethod == "RGB"); + // init luma noisevarL + const float noiseluma = (float) dnparams.luma; + const float noisevarL = (useNoiseLCurve && (denoiseMethodRgb || !isRAW)) ? (float) (SQR(((noiseluma + 1.0) / 125.0) * (10. + (noiseluma + 1.0) / 25.0))) : (float) (SQR((noiseluma / 125.0) * (1.0 + noiseluma / 25.0))); + const bool denoiseLuminance = (noisevarL > 0.00001f); + + //printf("NL=%f \n",noisevarL); + if(useNoiseLCurve || useNoiseCCurve) { + int hei = calclum->height; + int wid = calclum->width; + TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); + + const float wpi[3][3] = { + {static_cast(wprofi[0][0]), static_cast(wprofi[0][1]), static_cast(wprofi[0][2])}, + {static_cast(wprofi[1][0]), static_cast(wprofi[1][1]), static_cast(wprofi[1][2])}, + {static_cast(wprofi[2][0]), static_cast(wprofi[2][1]), static_cast(wprofi[2][2])} + }; + lumcalcBuffer = new float[hei * wid]; + lumcalc = new float*[(hei)]; + + for (int i = 0; i < hei; i++) { + lumcalc[i] = lumcalcBuffer + (i * wid); + } + + ccalcBuffer = new float[hei * wid]; + ccalc = new float*[(hei)]; + + for (int i = 0; i < hei; i++) { + ccalc[i] = ccalcBuffer + (i * wid); + } + + float cn100Precalc; + + if(useNoiseCCurve) { + cn100Precalc = SQR(1.f + ponderCC * (4.f * noiseCCurve[100.f / 60.f])); + } - float cn100Precalc; - if(useNoiseCCurve) - cn100Precalc = SQR(1.f + ponderCC*(4.f*noiseCCurve[100.f / 60.f])); #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) -#endif - for(int ii=0;iir(ii,jj); - float GL = calclum->g(ii,jj); - float BL = calclum->b(ii,jj); - // determine luminance and chrominance for noisecurves - float XL,YL,ZL; - Color::rgbxyz(RL,GL,BL,XL,YL,ZL,wpi); - Color::XYZ2Lab(XL, YL, ZL, LLum, AAum, BBum); - if(useNoiseLCurve) { - float epsi = 0.01f; - if(LLum<2.f) - LLum = 2.f;//avoid divided by zero - if(LLum>32768.f) - LLum = 32768.f; // not strictly necessary - float kinterm = epsi + noiseLCurve[xdivf(LLum,15)*500.f]; - kinterm *= 100.f; - kinterm += noiseluma; - lumcalc[ii][jj] = SQR((kinterm/125.f)*(1.f+kinterm/25.f)); - } - if(useNoiseCCurve) { - float cN = sqrtf(SQR(AAum)+SQR(BBum)); - if(cN > 100) - ccalc[ii][jj] = SQR(1.f + ponderCC*(4.f*noiseCCurve[cN / 60.f])); - else - ccalc[ii][jj] = cn100Precalc; - } - } - } - delete calclum; - calclum = NULL; - } - - const short int imheight=src->height, imwidth=src->width; - - if (dnparams.luma!=0 || dnparams.chroma!=0 || dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly" ) { - // gamma transform for input data - float gam = dnparams.gamma; - float gamthresh = 0.001f; - if(!isRAW) {//reduce gamma under 1 for Lab mode ==> TIF and JPG - if(gam < 1.9f) - gam = 1.f - (1.9f-gam)/3.f;//minimum gamma 0.7 - else if (gam >= 1.9f && gam <= 3.f) - gam = (1.4f/1.1f)*gam - 1.41818f; - } - float gamslope = exp(log((double)gamthresh)/gam)/gamthresh; - - LUTf gamcurve(65536,LUT_CLIP_BELOW); - if(denoiseMethodRgb) { - for (int i=0; i<65536; i++) { - gamcurve[i] = (Color::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) * 32768.0f; - } - } else { - for (int i=0; i<65536; i++) { - gamcurve[i] = (Color::gamman((double)i/65535.0,gam)) * 32768.0f; - } - } - - // inverse gamma transform for output data - float igam = 1.f/gam; - float igamthresh = gamthresh*gamslope; - float igamslope = 1.f/gamslope; - - LUTf igamcurve(65536,LUT_CLIP_BELOW); - if(denoiseMethodRgb) { - for (int i=0; i<65536; i++) { - igamcurve[i] = (Color::gamma((float)i/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); - } - } else { - for (int i=0; i<65536; i++) { - igamcurve[i] = (Color::gamman((float)i/32768.0f,igam) * 65535.0f); - } - } - - const float gain = pow (2.0f, float(expcomp)); - float noisevar_Ldetail = SQR((float)(SQR(100.-dnparams.Ldetail) + 50.*(100.-dnparams.Ldetail)) * TS * 0.5f); - if(settings->verbose) - printf("Denoise Lab=%i\n",settings->denoiselabgamma); - - // To avoid branches in loops we access the gammatabs by pointers - // modify arbitrary data for Lab..I have test : nothing, gamma 2.6 11 - gamma 4 5 - gamma 5.5 10 - // we can put other as gamma g=2.6 slope=11, etc. - // but noting to do with real gamma !!!: it's only for data Lab # data RGB - // finally I opted fot gamma55 and with options we can change - - LUTf *denoisegamtab; - LUTf *denoiseigamtab; - switch(settings->denoiselabgamma) { - case 0: denoisegamtab = &(Color::gammatab_26_11); - denoiseigamtab = &(Color::igammatab_26_11); - break; - case 1: denoisegamtab = &(Color::gammatab_4); - denoiseigamtab = &(Color::igammatab_4); - break; - default: denoisegamtab = &(Color::gammatab_55); - denoiseigamtab = &(Color::igammatab_55); - break; - } - - array2D tilemask_in(TS,TS); - array2D tilemask_out(TS,TS); - if(denoiseLuminance) { - const int border = MAX(2,TS/16); - for (int i=0; iTS/2 ? i-TS+1 : i)); - float vmask = (i1TS/2 ? j-TS+1 : j)); - tilemask_in[i][j] = (vmask * (j1leveldnti ==0) { - tilesize = 1024; - overlap = 128; -} -if(settings->leveldnti ==1) { - tilesize = 768; - overlap = 96; -} - int numTries = 0; - if(ponder) - printf("Tiled denoise processing caused by Automatic Multizone mode\n"); - bool memoryAllocationFailed = false; - -do { - numTries++; - if(numTries == 2) - printf("1st denoise pass failed due to insufficient memory, starting 2nd (tiled) pass now...\n"); - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - - Tile_calc (tilesize, overlap, (options.rgbDenoiseThreadLimit == 0 && !ponder) ? (numTries == 1 ? 0 : 2) : 2, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - memoryAllocationFailed = false; - const int numtiles = numtiles_W * numtiles_H; - - //output buffer - Imagefloat * dsttmp; - if(numtiles == 1) - dsttmp = dst; - else { - dsttmp = new Imagefloat(imwidth,imheight); -#ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i=0;ir(i,j) = 0.f; - dsttmp->g(i,j) = 0.f; - dsttmp->b(i,j) = 0.f; + + for(int ii = 0; ii < hei; ii++) { + for(int jj = 0; jj < wid; jj++) { + float LLum, AAum, BBum; + + float RL = calclum->r(ii, jj); + float GL = calclum->g(ii, jj); + float BL = calclum->b(ii, jj); + // determine luminance and chrominance for noisecurves + float XL, YL, ZL; + Color::rgbxyz(RL, GL, BL, XL, YL, ZL, wpi); + Color::XYZ2Lab(XL, YL, ZL, LLum, AAum, BBum); + + if(useNoiseLCurve) { + float epsi = 0.01f; + + if(LLum < 2.f) { + LLum = 2.f; //avoid divided by zero + } + + if(LLum > 32768.f) { + LLum = 32768.f; // not strictly necessary + } + + float kinterm = epsi + noiseLCurve[xdivf(LLum, 15) * 500.f]; + kinterm *= 100.f; + kinterm += noiseluma; + lumcalc[ii][jj] = SQR((kinterm / 125.f) * (1.f + kinterm / 25.f)); + } + + if(useNoiseCCurve) { + float cN = sqrtf(SQR(AAum) + SQR(BBum)); + + if(cN > 100) { + ccalc[ii][jj] = SQR(1.f + ponderCC * (4.f * noiseCCurve[cN / 60.f])); + } else { + ccalc[ii][jj] = cn100Precalc; + } + } } - } + } - //now we have tile dimensions, overlaps - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + delete calclum; + calclum = NULL; + } - // According to FFTW-Doc 'it is safe to execute the same plan in parallel by multiple threads', so we now create 4 plans - // outside the parallel region and use them inside the parallel region. + const short int imheight = src->height, imwidth = src->width; - // calculate max size of numblox_W. - int max_numblox_W = ceil(((float)(MIN(imwidth,tilewidth)))/(offset))+2*blkrad; - // calculate min size of numblox_W. - int min_numblox_W = ceil(((float)((MIN(imwidth,((numtiles_W - 1) * tileWskip) + tilewidth) ) - ((numtiles_W - 1) * tileWskip)))/(offset))+2*blkrad; + if (dnparams.luma != 0 || dnparams.chroma != 0 || dnparams.methodmed == "Lab" || dnparams.methodmed == "Lonly" ) { + // gamma transform for input data + float gam = dnparams.gamma; + float gamthresh = 0.001f; - // these are needed only for creation of the plans and will be freed before entering the parallel loop - fftwf_plan plan_forward_blox[2]; - fftwf_plan plan_backward_blox[2]; + if(!isRAW) {//reduce gamma under 1 for Lab mode ==> TIF and JPG + if(gam < 1.9f) { + gam = 1.f - (1.9f - gam) / 3.f; //minimum gamma 0.7 + } else if (gam >= 1.9f && gam <= 3.f) { + gam = (1.4f / 1.1f) * gam - 1.41818f; + } + } - if(denoiseLuminance) { - float *Lbloxtmp = (float*) fftwf_malloc(max_numblox_W*TS*TS*sizeof (float)); - float *fLbloxtmp = (float*) fftwf_malloc(max_numblox_W*TS*TS*sizeof (float)); + float gamslope = exp(log((double)gamthresh) / gam) / gamthresh; - int nfwd[2]={TS,TS}; + LUTf gamcurve(65536, LUT_CLIP_BELOW); - //for DCT: - fftw_r2r_kind fwdkind[2] = {FFTW_REDFT10, FFTW_REDFT10}; - fftw_r2r_kind bwdkind[2] = {FFTW_REDFT01, FFTW_REDFT01}; + if(denoiseMethodRgb) { + for (int i = 0; i < 65536; i++) { + gamcurve[i] = (Color::gamma((double)i / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) * 32768.0f; + } + } else { + for (int i = 0; i < 65536; i++) { + gamcurve[i] = (Color::gamman((double)i / 65535.0, gam)) * 32768.0f; + } + } - // Creating the plans with FFTW_MEASURE instead of FFTW_ESTIMATE speeds up the execute a bit - plan_forward_blox[0] = fftwf_plan_many_r2r(2, nfwd, max_numblox_W, Lbloxtmp, NULL, 1, TS*TS, fLbloxtmp, NULL, 1, TS*TS, fwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); - plan_backward_blox[0] = fftwf_plan_many_r2r(2, nfwd, max_numblox_W, fLbloxtmp, NULL, 1, TS*TS, Lbloxtmp, NULL, 1, TS*TS, bwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); - plan_forward_blox[1] = fftwf_plan_many_r2r(2, nfwd, min_numblox_W, Lbloxtmp, NULL, 1, TS*TS, fLbloxtmp, NULL, 1, TS*TS, fwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); - plan_backward_blox[1] = fftwf_plan_many_r2r(2, nfwd, min_numblox_W, fLbloxtmp, NULL, 1, TS*TS, Lbloxtmp, NULL, 1, TS*TS, bwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); - fftwf_free ( Lbloxtmp ); - fftwf_free ( fLbloxtmp ); - } + // inverse gamma transform for output data + float igam = 1.f / gam; + float igamthresh = gamthresh * gamslope; + float igamslope = 1.f / gamslope; + + LUTf igamcurve(65536, LUT_CLIP_BELOW); + + if(denoiseMethodRgb) { + for (int i = 0; i < 65536; i++) { + igamcurve[i] = (Color::gamma((float)i / 32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); + } + } else { + for (int i = 0; i < 65536; i++) { + igamcurve[i] = (Color::gamman((float)i / 32768.0f, igam) * 65535.0f); + } + } + + const float gain = pow (2.0f, float(expcomp)); + float noisevar_Ldetail = SQR((float)(SQR(100. - dnparams.Ldetail) + 50.*(100. - dnparams.Ldetail)) * TS * 0.5f); + + if(settings->verbose) { + printf("Denoise Lab=%i\n", settings->denoiselabgamma); + } + + // To avoid branches in loops we access the gammatabs by pointers + // modify arbitrary data for Lab..I have test : nothing, gamma 2.6 11 - gamma 4 5 - gamma 5.5 10 + // we can put other as gamma g=2.6 slope=11, etc. + // but noting to do with real gamma !!!: it's only for data Lab # data RGB + // finally I opted fot gamma55 and with options we can change + + LUTf *denoisegamtab; + LUTf *denoiseigamtab; + + switch(settings->denoiselabgamma) { + case 0: + denoisegamtab = &(Color::gammatab_26_11); + denoiseigamtab = &(Color::igammatab_26_11); + break; + + case 1: + denoisegamtab = &(Color::gammatab_4); + denoiseigamtab = &(Color::igammatab_4); + break; + + default: + denoisegamtab = &(Color::gammatab_55); + denoiseigamtab = &(Color::igammatab_55); + break; + } + + array2D tilemask_in(TS, TS); + array2D tilemask_out(TS, TS); + + if(denoiseLuminance) { + const int border = MAX(2, TS / 16); + + for (int i = 0; i < TS; i++) { + float i1 = abs((i > TS / 2 ? i - TS + 1 : i)); + float vmask = (i1 < border ? SQR(sin((M_PI * i1) / (2 * border))) : 1.0f); + float vmask2 = (i1 < 2 * border ? SQR(sin((M_PI * i1) / (2 * border))) : 1.0f); + + for (int j = 0; j < TS; j++) { + float j1 = abs((j > TS / 2 ? j - TS + 1 : j)); + tilemask_in[i][j] = (vmask * (j1 < border ? SQR(sin((M_PI * j1) / (2 * border))) : 1.0f)) + epsilon; + tilemask_out[i][j] = (vmask2 * (j1 < 2 * border ? SQR(sin((M_PI * j1) / (2 * border))) : 1.0f)) + epsilon; + + } + } + } + + int tilesize; + int overlap; + + if(settings->leveldnti == 0) { + tilesize = 1024; + overlap = 128; + } + + if(settings->leveldnti == 1) { + tilesize = 768; + overlap = 96; + } + + int numTries = 0; + + if(ponder) { + printf("Tiled denoise processing caused by Automatic Multizone mode\n"); + } + + bool memoryAllocationFailed = false; + + do { + numTries++; + + if(numTries == 2) { + printf("1st denoise pass failed due to insufficient memory, starting 2nd (tiled) pass now...\n"); + } + + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + + Tile_calc (tilesize, overlap, (options.rgbDenoiseThreadLimit == 0 && !ponder) ? (numTries == 1 ? 0 : 2) : 2, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + memoryAllocationFailed = false; + const int numtiles = numtiles_W * numtiles_H; + + //output buffer + Imagefloat * dsttmp; + + if(numtiles == 1) { + dsttmp = dst; + } else { + dsttmp = new Imagefloat(imwidth, imheight); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < imheight; i++) + for(int j = 0; j < imwidth; j++) { + dsttmp->r(i, j) = 0.f; + dsttmp->g(i, j) = 0.f; + dsttmp->b(i, j) = 0.f; + } + } + + //now we have tile dimensions, overlaps + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // According to FFTW-Doc 'it is safe to execute the same plan in parallel by multiple threads', so we now create 4 plans + // outside the parallel region and use them inside the parallel region. + + // calculate max size of numblox_W. + int max_numblox_W = ceil(((float)(MIN(imwidth, tilewidth))) / (offset)) + 2 * blkrad; + // calculate min size of numblox_W. + int min_numblox_W = ceil(((float)((MIN(imwidth, ((numtiles_W - 1) * tileWskip) + tilewidth) ) - ((numtiles_W - 1) * tileWskip))) / (offset)) + 2 * blkrad; + + // these are needed only for creation of the plans and will be freed before entering the parallel loop + fftwf_plan plan_forward_blox[2]; + fftwf_plan plan_backward_blox[2]; + + if(denoiseLuminance) { + float *Lbloxtmp = (float*) fftwf_malloc(max_numblox_W * TS * TS * sizeof (float)); + float *fLbloxtmp = (float*) fftwf_malloc(max_numblox_W * TS * TS * sizeof (float)); + + int nfwd[2] = {TS, TS}; + + //for DCT: + fftw_r2r_kind fwdkind[2] = {FFTW_REDFT10, FFTW_REDFT10}; + fftw_r2r_kind bwdkind[2] = {FFTW_REDFT01, FFTW_REDFT01}; + + // Creating the plans with FFTW_MEASURE instead of FFTW_ESTIMATE speeds up the execute a bit + plan_forward_blox[0] = fftwf_plan_many_r2r(2, nfwd, max_numblox_W, Lbloxtmp, NULL, 1, TS * TS, fLbloxtmp, NULL, 1, TS * TS, fwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); + plan_backward_blox[0] = fftwf_plan_many_r2r(2, nfwd, max_numblox_W, fLbloxtmp, NULL, 1, TS * TS, Lbloxtmp, NULL, 1, TS * TS, bwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); + plan_forward_blox[1] = fftwf_plan_many_r2r(2, nfwd, min_numblox_W, Lbloxtmp, NULL, 1, TS * TS, fLbloxtmp, NULL, 1, TS * TS, fwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); + plan_backward_blox[1] = fftwf_plan_many_r2r(2, nfwd, min_numblox_W, fLbloxtmp, NULL, 1, TS * TS, Lbloxtmp, NULL, 1, TS * TS, bwdkind, FFTW_MEASURE || FFTW_DESTROY_INPUT ); + fftwf_free ( Lbloxtmp ); + fftwf_free ( fLbloxtmp ); + } #ifndef _OPENMP - int numthreads = 1; + int numthreads = 1; #else - // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles - int numthreads = MIN(numtiles,omp_get_max_threads()); - if(options.rgbDenoiseThreadLimit > 0) - numthreads = MIN(numthreads,options.rgbDenoiseThreadLimit); -#ifdef _RT_NESTED_OPENMP - denoiseNestedLevels = omp_get_max_threads() / numthreads; - bool oldNested = omp_get_nested(); - if(denoiseNestedLevels < 2) - denoiseNestedLevels = 1; - else - omp_set_nested(true); - if(options.rgbDenoiseThreadLimit > 0) - while(denoiseNestedLevels*numthreads > options.rgbDenoiseThreadLimit) - denoiseNestedLevels--; -#endif - if(settings->verbose) - printf("RGB_denoise uses %d main thread(s) and up to %d nested thread(s) for each main thread\n",numthreads,denoiseNestedLevels); -#endif - float *LbloxArray[denoiseNestedLevels*numthreads]; - float *fLbloxArray[denoiseNestedLevels*numthreads]; + // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles + int numthreads = MIN(numtiles, omp_get_max_threads()); - if(numtiles > 1 && denoiseLuminance) - for(int i=0;iworkingSpaceInverseMatrix (params->icm.working); - //inverse matrix user select - 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])} - }; - - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); - - 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])} - }; - - - // begin tile processing of image -#ifdef _OPENMP -#pragma omp parallel num_threads(numthreads) if(numthreads>1) -#endif - { - int pos; - float* noisevarlum; - float* noisevarchrom; - if(numtiles == 1 && isRAW && (useNoiseCCurve || useNoiseLCurve)) { - noisevarlum = lumcalcBuffer; - noisevarchrom = ccalcBuffer; - } else { - noisevarlum = new float[((tileheight+1)/2)*((tilewidth+1)/2)]; - noisevarchrom = new float[((tileheight+1)/2)*((tilewidth+1)/2)]; - } - -#ifdef _OPENMP -#pragma omp for schedule(dynamic) collapse(2) -#endif - - for (int tiletop=0; tiletop 0.) intermred=(dnparams.redchro/10.); else intermred= (float) dnparams.redchro/7.0;//increase slower than linear for more sensit - if(dnparams.bluechro > 0.) intermblue=(dnparams.bluechro/10.); else intermblue= (float) dnparams.bluechro/7.0;//increase slower than linear for more sensit - if(ponder && kall==2){interm_med=ch_M[pos]/10.f; intermred=max_r[pos]/10.f;intermblue=max_b[pos]/10.f;} - if(ponder && kall==0){interm_med=0.01f; intermred=0.f;intermblue=0.f;} - realred = interm_med + intermred; if (realred < 0.f) realred=0.001f; - realblue = interm_med + intermblue; if (realblue < 0.f) realblue=0.001f; - const float noisevarab_r = SQR(realred); - const float noisevarab_b = SQR(realblue); - - //input L channel - array2D *Lin; - //wavelet denoised image - LabImage * labdn = new LabImage(width,height); - - //fill tile from image; convert RGB to "luma/chroma" - const float maxNoiseVarab = max(noisevarab_b,noisevarab_r); - if (isRAW) {//image is raw; use channel differences for chroma channels - - if(!denoiseMethodRgb){//lab mode - //modification Jacques feb 2013 and july 2014 -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif - for (int i=tiletop; ir(i,j); - float G_ = gain*src->g(i,j); - float B_ = gain*src->b(i,j); - - R_ = (*denoiseigamtab)[R_]; - G_ = (*denoiseigamtab)[G_]; - B_ = (*denoiseigamtab)[B_]; - - //apply gamma noise standard (slider) - R_ = R_<65535.0f ? gamcurve[R_] : (Color::gammanf(R_/65535.f, gam)*32768.0f); - G_ = G_<65535.0f ? gamcurve[G_] : (Color::gammanf(G_/65535.f, gam)*32768.0f); - B_ = B_<65535.0f ? gamcurve[B_] : (Color::gammanf(B_/65535.f, gam)*32768.0f); - - //true conversion xyz=>Lab - float X,Y,Z; - Color::rgbxyz(R_,G_,B_,X,Y,Z,wp); - - //convert to Lab - float L,a,b; - Color::XYZ2Lab(X, Y, Z, L, a, b); - - labdn->L[i1][j1] = L; - labdn->a[i1][j1] = a; - labdn->b[i1][j1] = b; - - if(((i1|j1)&1) == 0) { - if(numTries == 1) { - noisevarlum[(i1>>1)*width2+(j1>>1)] = useNoiseLCurve ? lumcalc[i>>1][j>>1] : noisevarL; - noisevarchrom[(i1>>1)*width2+(j1>>1)] = useNoiseCCurve ? maxNoiseVarab*ccalc[i>>1][j>>1] : 1.f; - } else { - noisevarlum[(i1>>1)*width2+(j1>>1)] = lumcalc[i>>1][j>>1]; - noisevarchrom[(i1>>1)*width2+(j1>>1)] = ccalc[i>>1][j>>1]; - } - } - //end chroma - } - } - } else {//RGB mode -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif - for (int i=tiletop; ir(i,j); - float Y = gain*src->g(i,j); - float Z = gain*src->b(i,j); - //conversion colorspace to determine luminance with no gamma - X = X<65535.0f ? gamcurve[X] : (Color::gamma((double)X/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); - Y = Y<65535.0f ? gamcurve[Y] : (Color::gamma((double)Y/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); - Z = Z<65535.0f ? gamcurve[Z] : (Color::gamma((double)Z/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); - //end chroma - labdn->L[i1][j1] = Y; - labdn->a[i1][j1] = (X-Y); - labdn->b[i1][j1] = (Y-Z); - - if(((i1|j1)&1) == 0) { - if(numTries == 1) { - noisevarlum[(i1>>1)*width2+(j1>>1)] = useNoiseLCurve ? lumcalc[i>>1][j>>1] : noisevarL; - noisevarchrom[(i1>>1)*width2+(j1>>1)] = useNoiseCCurve ? maxNoiseVarab*ccalc[i>>1][j>>1] : 1.f; - } else { - noisevarlum[(i1>>1)*width2+(j1>>1)] = lumcalc[i>>1][j>>1]; - noisevarchrom[(i1>>1)*width2+(j1>>1)] = ccalc[i>>1][j>>1]; - } - } - } - } - } - } else {//image is not raw; use Lab parametrization -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif - for (int i=tiletop; ir(i,j) ;//for denoise curves - float gLum=src->g(i,j) ; - float bLum=src->b(i,j) ; - - //use gamma sRGB, not good if TIF (JPG) Output profil not with gamma sRGB (eg : gamma =1.0, or 1.8...) - //very difficult to solve ! - // solution ==> save TIF with gamma sRGB and re open - float rtmp = Color::igammatab_srgb[ src->r(i,j) ]; - float gtmp = Color::igammatab_srgb[ src->g(i,j) ]; - float btmp = Color::igammatab_srgb[ src->b(i,j) ]; - //modification Jacques feb 2013 - // gamma slider different from raw - rtmp = rtmp<65535.0f ? gamcurve[rtmp] : (Color::gamman((double)rtmp/65535.0, gam)*32768.0f); - gtmp = gtmp<65535.0f ? gamcurve[gtmp] : (Color::gamman((double)gtmp/65535.0, gam)*32768.0f); - btmp = btmp<65535.0f ? gamcurve[btmp] : (Color::gamman((double)btmp/65535.0, gam)*32768.0f); - - float X,Y,Z; - Color::rgbxyz(rtmp,gtmp,btmp,X,Y,Z,wp); - - //convert Lab - Color::XYZ2Lab(X, Y, Z, L, a, b); - labdn->L[i1][j1] = L; - labdn->a[i1][j1] = a; - labdn->b[i1][j1] = b; - - if(((i1|j1)&1) == 0) { - float Llum,alum,blum; - if(useNoiseLCurve || useNoiseCCurve) { - float XL,YL,ZL; - Color::rgbxyz(rLum,gLum,bLum,XL,YL,ZL,wp); - Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum); - } - - if(useNoiseLCurve) { - float kN = Llum; - float epsi=0.01f; - if(kN<2.f) kN=2.f; - if(kN>32768.f) kN=32768.f; - float kinterm=epsi + noiseLCurve[xdivf(kN,15)*500.f]; - float ki=kinterm*100.f; - ki+=noiseluma; - noisevarlum[(i1>>1)*width2+(j1>>1)]=SQR((ki/125.f)*(1.f+ki/25.f)); - } else { - noisevarlum[(i1>>1)*width2+(j1>>1)] = noisevarL; - } - if(useNoiseCCurve) { - float aN=alum; - float bN=blum; - float cN=sqrtf(SQR(aN)+SQR(bN)); - if(cN < 100.f) - cN=100.f;//avoid divided by zero ??? - float Cinterm=1.f + ponderCC*4.f*noiseCCurve[cN/60.f]; - noisevarchrom[(i1>>1)*width2+(j1>>1)]= maxNoiseVarab*SQR(Cinterm); - } else { - noisevarchrom[(i1>>1)*width2+(j1>>1)] = 1.f; - } - } - } - } - } - - //now perform basic wavelet denoise - //arguments 4 and 5 of wavelet decomposition are max number of wavelet decomposition levels; - //and whether to subsample the image after wavelet filtering. Subsampling is coded as - //binary 1 or 0 for each level, eg subsampling = 0 means no subsampling, 1 means subsample - //the first level only, 7 means subsample the first three levels, etc. - //actual implementation only works with subsampling set to 1 - float interm_medT = (float) dnparams.chroma/10.0; - bool execwavelet = true; - if(!denoiseLuminance && interm_medT < 0.05f && dnparams.median && (dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly")) - execwavelet=false;//do not exec wavelet if sliders luminance and chroma are very small and median need - //we considered user don't want wavelet - if(settings->leveldnautsimpl==1 && dnparams.Cmethod!="MAN") - execwavelet=true; - if(settings->leveldnautsimpl==0 && dnparams.C2method!="MANU") - execwavelet=true; - if(execwavelet) {//gain time if user choose only median sliders L <=1 slider chrom master < 1 - wavelet_decomposition* Ldecomp; - wavelet_decomposition* adecomp; - - int levwav=5; - float maxreal = max(realred, realblue); - //increase the level of wavelet if user increase much or very much sliders - if( maxreal < 8.f) levwav=5; - else if( maxreal < 10.f)levwav=6; - else if( maxreal < 15.f)levwav=7; - else levwav=8;//maximum ==> I have increase Maxlevel in cplx_wavelet_dec.h from 8 to 9 - if(nrQuality == QUALITY_HIGH) - levwav += settings->nrwavlevel;//increase level for enhanced mode - if(levwav>8) levwav=8; - int minsizetile=min(tilewidth, tileheight); - int maxlev2=8; - if(minsizetile < 256) maxlev2 = 7; - if(minsizetile < 128) maxlev2 = 6; - if(minsizetile < 64) maxlev2 = 5; - levwav=min(maxlev2,levwav); - - // if (settings->verbose) printf("levwavelet=%i noisevarA=%f noisevarB=%f \n",levwav, noisevarab_r, noisevarab_b ); - Ldecomp = new wavelet_decomposition (labdn->L[0], labdn->W, labdn->H, levwav, 1, 1, max(1,denoiseNestedLevels)); - if(Ldecomp->memoryAllocationFailed) { - memoryAllocationFailed = true; - } - float madL[8][3]; - if(!memoryAllocationFailed) { - // precalculate madL, because it's used in adecomp and bdecomp - int maxlvl = Ldecomp->maxlevel(); -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for schedule(dynamic) collapse(2) num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif - for (int lvl=0; lvllevel_W(lvl); - int Hlvl_L = Ldecomp->level_H(lvl); - - float ** WavCoeffs_L = Ldecomp->level_coeffs(lvl); - - if(!denoiseMethodRgb) { - madL[lvl][dir-1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L*Hlvl_L)); - } else { - madL[lvl][dir-1] = SQR(MadRgb(WavCoeffs_L[dir], Wlvl_L*Hlvl_L)); - } - } - } - } - - float chresid = 0.f; - float chresidtemp=0.f; - float chmaxresid = 0.f; - float chmaxresidtemp = 0.f; - - adecomp = new wavelet_decomposition (labdn->a[0], labdn->W, labdn->H,levwav, 1, 1, max(1,denoiseNestedLevels)); - if(adecomp->memoryAllocationFailed) { - memoryAllocationFailed = true; - } - if(!memoryAllocationFailed) { - if(nrQuality==QUALITY_STANDARD) { - if(!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb ))//enhance mode - memoryAllocationFailed = true; - } else /*if(nrQuality==QUALITY_HIGH)*/ { - if(!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb ))//enhance mode - memoryAllocationFailed = true; - if(!memoryAllocationFailed) - if(!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb )) - memoryAllocationFailed = true; - } - } - if(!memoryAllocationFailed) { - if(kall == 0) { - Noise_residualAB(*adecomp, chresid, chmaxresid, denoiseMethodRgb); - chresidtemp=chresid; - chmaxresidtemp= chmaxresid; - } - adecomp->reconstruct(labdn->a[0]); - } - delete adecomp; - if(!memoryAllocationFailed) { - wavelet_decomposition* bdecomp = new wavelet_decomposition (labdn->b[0], labdn->W, labdn->H, levwav, 1, 1, max(1,denoiseNestedLevels)); - if(bdecomp->memoryAllocationFailed) { - memoryAllocationFailed = true; - } - if(!memoryAllocationFailed) { - if(nrQuality==QUALITY_STANDARD) { - if(!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb ))//enhance mode - memoryAllocationFailed = true; - } else /*if(nrQuality==QUALITY_HIGH)*/ { - if(!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb ))//enhance mode - memoryAllocationFailed = true; - if(!memoryAllocationFailed) - if(!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb )) - memoryAllocationFailed = true; - } - } - if(!memoryAllocationFailed) { - if(kall == 0) { - Noise_residualAB(*bdecomp, chresid, chmaxresid, denoiseMethodRgb); - chresid += chresidtemp; - chmaxresid += chmaxresidtemp; - chresid = sqrt(chresid/(6*(levwav))); - highresi = chresid + 0.66f*(sqrt(chmaxresid) - chresid);//evaluate sigma - nresi = chresid; - } - bdecomp->reconstruct(labdn->b[0]); - } - delete bdecomp; - if(!memoryAllocationFailed) { - if(denoiseLuminance) { - int edge=0; - if(nrQuality==QUALITY_STANDARD) { - if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, NULL, edge))//enhance mode - memoryAllocationFailed = true; - } else /*if(nrQuality==QUALITY_HIGH)*/ { - if(!WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL))//enhance mode - memoryAllocationFailed = true; - if(!memoryAllocationFailed) - if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, NULL, edge)) - memoryAllocationFailed = true; - } - if(!memoryAllocationFailed) { - // copy labdn->L to Lin before it gets modified by reconstruction - Lin = new array2D(width,height); -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif - for(int i=0;iL[i][j]; - - Ldecomp->reconstruct(labdn->L[0]); - } - } - } - } - delete Ldecomp; - } - - if(!memoryAllocationFailed) { - if( (metchoice==1 || metchoice==2 || metchoice==3 || metchoice==4) && dnparams.median) { - float** tmL; - int wid=labdn->W; - int hei=labdn->H; - tmL = new float*[hei]; - for (int i=0; iL, labdn->L, wid, hei, medianTypeL, dnparams.passes, denoiseNestedLevels, tmL); - if(metchoice==2 || metchoice==3 || metchoice==4) { - Median_Denoise( labdn->a, labdn->a, wid, hei, medianTypeAB, dnparams.passes, denoiseNestedLevels, tmL); - Median_Denoise( labdn->b, labdn->b, wid, hei, medianTypeAB, dnparams.passes, denoiseNestedLevels, tmL); - } - - for (int i=0; i Ldetail(width,height,ARRAY2D_CLEAR_DATA); - //pixel weight - array2D totwt(width,height,ARRAY2D_CLEAR_DATA);//weight for combining DCT blocks - if(numtiles == 1) - for(int i=0;i1) -#endif -{ -#ifdef _RT_NESTED_OPENMP - int subThread = masterThread * denoiseNestedLevels + omp_get_thread_num(); -#else - int subThread = 0; -#endif - float blurbuffer[TS*TS] ALIGNED64; - float *Lblox = LbloxArray[subThread]; - float *fLblox = fLbloxArray[subThread]; - float pBuf[width + TS + 2*blkrad*offset] ALIGNED16; - float nbrwt[TS*TS] ALIGNED64; -#ifdef _RT_NESTED_OPENMP -#pragma omp for -#endif - for (int vblk=0; vblk=height) { - rr = MAX(0,2*height-2-row); - } - - for (int j=0; jW; j++) { - datarow[j] = ((*Lin)[rr][j]-labdn->L[rr][j]); - } - - for (int j=-blkrad*offset; j<0; j++) { - datarow[j] = datarow[MIN(-j,width-1)]; - } - for (int j=width; j=0 && top+i1) -#endif - for (int i=0; iL[i][j] += Ldetail[i][j]/totwt[i][j]; //note that labdn initially stores the denoised hipass data - } - } - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // transform denoised "Lab" to output RGB - - //calculate mask for feathering output tile overlaps - float Vmask[height+1] ALIGNED16; - float Hmask[width+1] ALIGNED16; - float newGain; - if(numtiles > 1) { - for (int i=0; i0) Vmask[i] = mask; - if (tilebottom0) Hmask[i] = mask/newGain; - if (tilerightxyz - float L = labdn->L[i1][j1]; - float a = labdn->a[i1][j1]; - float b = labdn->b[i1][j1]; - float c_h=SQR(a)+SQR(b); - if(c_h>9000000.f){ - a *= 1.f + qhighFactor*realred; - b *= 1.f + qhighFactor*realblue; - } - //convert XYZ - float X,Y,Z; - Color::Lab2XYZ(L, a, b, X, Y, Z); - //apply inverse gamma noise - float r_,g_,b_; - Color::xyz2rgb(X,Y,Z,r_,g_,b_,wip); - //inverse gamma standard (slider) - r_ = r_<32768.f ? igamcurve[r_] : (Color::gammanf(r_/32768.f, igam) * 65535.f); - g_ = g_<32768.f ? igamcurve[g_] : (Color::gammanf(g_/32768.f, igam) * 65535.f); - b_ = b_<32768.f ? igamcurve[b_] : (Color::gammanf(b_/32768.f, igam) * 65535.f); - - //readapt arbitrary gamma (inverse from beginning) - r_ = (*denoisegamtab)[r_]; - g_ = (*denoisegamtab)[g_]; - b_ = (*denoisegamtab)[b_]; - - if(numtiles == 1) { - dsttmp->r(i,j) = newGain*r_; - dsttmp->g(i,j) = newGain*g_; - dsttmp->b(i,j) = newGain*b_; - } else { - float factor = Vmask[i1]*Hmask[j1]; - dsttmp->r(i,j) += factor*r_; - dsttmp->g(i,j) += factor*g_; - dsttmp->b(i,j) += factor*b_; - } - } - } - } else {//RGB mode -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(denoiseNestedLevels) -#endif - for (int i=tiletop; ia[i1][j1])+SQR(labdn->b[i1][j1])); - if(c_h>3000.f){ - labdn->a[i1][j1]*=1.f + qhighFactor*realred/100.f; - labdn->b[i1][j1]*=1.f + qhighFactor*realblue/100.f; - } - float Y = labdn->L[i1][j1]; - float X = (labdn->a[i1][j1]) + Y; - float Z = Y - (labdn->b[i1][j1]); - - - X = X<32768.0f ? igamcurve[X] : (Color::gamma((float)X/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); - Y = Y<32768.0f ? igamcurve[Y] : (Color::gamma((float)Y/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); - Z = Z<32768.0f ? igamcurve[Z] : (Color::gamma((float)Z/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); - - if(numtiles == 1) { - dsttmp->r(i,j) = newGain*X; - dsttmp->g(i,j) = newGain*Y; - dsttmp->b(i,j) = newGain*Z; - } else { - float factor = Vmask[i1]*Hmask[j1]; - dsttmp->r(i,j) += factor*X; - dsttmp->g(i,j) += factor*Y; - dsttmp->b(i,j) += factor*Z; - } - } - } - - } - } else { -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(denoiseNestedLevels) -#endif - for (int i=tiletop; iL[i1][j1]; - float a = labdn->a[i1][j1]; - float b = labdn->b[i1][j1]; - float c_h=sqrt(SQR(a)+SQR(b)); - if(c_h>3000.f){ - a*=1.f + qhighFactor*realred/100.f; - b*=1.f + qhighFactor*realblue/100.f; - } - - float X,Y,Z; - Color::Lab2XYZ(L, a, b, X, Y, Z); - - float r_,g_,b_; - Color::xyz2rgb(X,Y,Z,r_,g_,b_,wip); - //gamma slider is different from Raw - r_ = r_<32768.0f ? igamcurve[r_] : (Color::gamman((float)r_/32768.0f, igam) * 65535.0f); - g_ = g_<32768.0f ? igamcurve[g_] : (Color::gamman((float)g_/32768.0f, igam) * 65535.0f); - b_ = b_<32768.0f ? igamcurve[b_] : (Color::gamman((float)b_/32768.0f, igam) * 65535.0f); - - if(numtiles == 1) { - dsttmp->r(i,j) = newGain*r_; - dsttmp->g(i,j) = newGain*g_; - dsttmp->b(i,j) = newGain*b_; - } else { - float factor = Vmask[i1]*Hmask[j1]; - dsttmp->r(i,j) += factor*r_; - dsttmp->g(i,j) += factor*g_; - dsttmp->b(i,j) += factor*b_; - } - } - } - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - } - delete labdn; - if(denoiseLuminance) - delete Lin; - - }//end of tile row - }//end of tile loop - if(numtiles > 1 || !isRAW || (!useNoiseCCurve && !useNoiseLCurve)) { - delete [] noisevarlum; - delete [] noisevarchrom; - } - - } - if(denoiseLuminance) { - for(int i=0;i1) { - if(!memoryAllocationFailed) - dsttmp->copyData(dst); - else if(dst != src) - src->copyData(dst); - delete dsttmp; - } - if (!isRAW && !memoryAllocationFailed) {//restore original image gamma -#ifdef _OPENMP -#pragma omp parallel for -#endif - for(int i=0;iheight;i++) - for(int j=0;jwidth;j++) { - dst->r(i,j) = Color::gammatab_srgb[ dst->r(i,j) ]; - dst->g(i,j) = Color::gammatab_srgb[ dst->g(i,j) ]; - dst->b(i,j) = Color::gammatab_srgb[ dst->b(i,j) ]; + if(options.rgbDenoiseThreadLimit > 0) { + numthreads = MIN(numthreads, options.rgbDenoiseThreadLimit); } - } - if(denoiseLuminance) { - // destroy the plans - fftwf_destroy_plan( plan_forward_blox[0] ); - fftwf_destroy_plan( plan_backward_blox[0] ); - fftwf_destroy_plan( plan_forward_blox[1] ); - fftwf_destroy_plan( plan_backward_blox[1] ); - fftwf_cleanup(); - } -} while(memoryAllocationFailed && numTries < 2 && (options.rgbDenoiseThreadLimit == 0) && !ponder); -if(memoryAllocationFailed) - printf("tiled denoise failed due to isufficient memory. Output is not denoised!\n"); +#ifdef _RT_NESTED_OPENMP + denoiseNestedLevels = omp_get_max_threads() / numthreads; + bool oldNested = omp_get_nested(); -} + if(denoiseNestedLevels < 2) { + denoiseNestedLevels = 1; + } else { + omp_set_nested(true); + } + + if(options.rgbDenoiseThreadLimit > 0) + while(denoiseNestedLevels * numthreads > options.rgbDenoiseThreadLimit) { + denoiseNestedLevels--; + } + +#endif + + if(settings->verbose) { + printf("RGB_denoise uses %d main thread(s) and up to %d nested thread(s) for each main thread\n", numthreads, denoiseNestedLevels); + } + +#endif + float *LbloxArray[denoiseNestedLevels * numthreads]; + float *fLbloxArray[denoiseNestedLevels * numthreads]; + + if(numtiles > 1 && denoiseLuminance) + for(int i = 0; i < denoiseNestedLevels * numthreads; i++) { + LbloxArray[i] = (float*) fftwf_malloc(max_numblox_W * TS * TS * sizeof(float)); + fLbloxArray[i] = (float*) fftwf_malloc(max_numblox_W * TS * TS * sizeof(float)); + } + + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + //inverse matrix user select + 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])} + }; + + TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + + 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])} + }; + + + // begin tile processing of image +#ifdef _OPENMP + #pragma omp parallel num_threads(numthreads) if(numthreads>1) +#endif + { + int pos; + float* noisevarlum; + float* noisevarchrom; + + if(numtiles == 1 && isRAW && (useNoiseCCurve || useNoiseLCurve)) { + noisevarlum = lumcalcBuffer; + noisevarchrom = ccalcBuffer; + } else { + noisevarlum = new float[((tileheight + 1) / 2) * ((tilewidth + 1) / 2)]; + noisevarchrom = new float[((tileheight + 1) / 2) * ((tilewidth + 1) / 2)]; + } + +#ifdef _OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int tiletop = 0; tiletop < imheight; tiletop += tileHskip) { + for (int tileleft = 0; tileleft < imwidth ; tileleft += tileWskip) { + //printf("titop=%d tileft=%d\n",tiletop/tileHskip, tileleft/tileWskip); + pos = (tiletop / tileHskip) * numtiles_W + tileleft / tileWskip ; + int tileright = MIN(imwidth, tileleft + tilewidth); + int tilebottom = MIN(imheight, tiletop + tileheight); + int width = tileright - tileleft; + int height = tilebottom - tiletop; + int width2 = (width + 1) / 2; + float realred, realblue; + float interm_med = (float) dnparams.chroma / 10.0; + float intermred, intermblue; + + if(dnparams.redchro > 0.) { + intermred = (dnparams.redchro / 10.); + } else { + intermred = (float) dnparams.redchro / 7.0; //increase slower than linear for more sensit + } + + if(dnparams.bluechro > 0.) { + intermblue = (dnparams.bluechro / 10.); + } else { + intermblue = (float) dnparams.bluechro / 7.0; //increase slower than linear for more sensit + } + + if(ponder && kall == 2) { + interm_med = ch_M[pos] / 10.f; + intermred = max_r[pos] / 10.f; + intermblue = max_b[pos] / 10.f; + } + + if(ponder && kall == 0) { + interm_med = 0.01f; + intermred = 0.f; + intermblue = 0.f; + } + + realred = interm_med + intermred; + + if (realred < 0.f) { + realred = 0.001f; + } + + realblue = interm_med + intermblue; + + if (realblue < 0.f) { + realblue = 0.001f; + } + + const float noisevarab_r = SQR(realred); + const float noisevarab_b = SQR(realblue); + + //input L channel + array2D *Lin; + //wavelet denoised image + LabImage * labdn = new LabImage(width, height); + + //fill tile from image; convert RGB to "luma/chroma" + const float maxNoiseVarab = max(noisevarab_b, noisevarab_r); + + if (isRAW) {//image is raw; use channel differences for chroma channels + + if(!denoiseMethodRgb) { //lab mode + //modification Jacques feb 2013 and july 2014 +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + + for (int j = tileleft; j < tileright; j++) { + int j1 = j - tileleft; + float R_ = gain * src->r(i, j); + float G_ = gain * src->g(i, j); + float B_ = gain * src->b(i, j); + + R_ = (*denoiseigamtab)[R_]; + G_ = (*denoiseigamtab)[G_]; + B_ = (*denoiseigamtab)[B_]; + + //apply gamma noise standard (slider) + R_ = R_ < 65535.0f ? gamcurve[R_] : (Color::gammanf(R_ / 65535.f, gam) * 32768.0f); + G_ = G_ < 65535.0f ? gamcurve[G_] : (Color::gammanf(G_ / 65535.f, gam) * 32768.0f); + B_ = B_ < 65535.0f ? gamcurve[B_] : (Color::gammanf(B_ / 65535.f, gam) * 32768.0f); + + //true conversion xyz=>Lab + float X, Y, Z; + Color::rgbxyz(R_, G_, B_, X, Y, Z, wp); + + //convert to Lab + float L, a, b; + Color::XYZ2Lab(X, Y, Z, L, a, b); + + labdn->L[i1][j1] = L; + labdn->a[i1][j1] = a; + labdn->b[i1][j1] = b; + + if(((i1 | j1) & 1) == 0) { + if(numTries == 1) { + noisevarlum[(i1 >> 1)*width2 + (j1 >> 1)] = useNoiseLCurve ? lumcalc[i >> 1][j >> 1] : noisevarL; + noisevarchrom[(i1 >> 1)*width2 + (j1 >> 1)] = useNoiseCCurve ? maxNoiseVarab * ccalc[i >> 1][j >> 1] : 1.f; + } else { + noisevarlum[(i1 >> 1)*width2 + (j1 >> 1)] = lumcalc[i >> 1][j >> 1]; + noisevarchrom[(i1 >> 1)*width2 + (j1 >> 1)] = ccalc[i >> 1][j >> 1]; + } + } + + //end chroma + } + } + } else {//RGB mode +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + + for (int j = tileleft; j < tileright; j++) { + int j1 = j - tileleft; + + float X = gain * src->r(i, j); + float Y = gain * src->g(i, j); + float Z = gain * src->b(i, j); + //conversion colorspace to determine luminance with no gamma + X = X < 65535.0f ? gamcurve[X] : (Color::gamma((double)X / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 32768.0f); + Y = Y < 65535.0f ? gamcurve[Y] : (Color::gamma((double)Y / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 32768.0f); + Z = Z < 65535.0f ? gamcurve[Z] : (Color::gamma((double)Z / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 32768.0f); + //end chroma + labdn->L[i1][j1] = Y; + labdn->a[i1][j1] = (X - Y); + labdn->b[i1][j1] = (Y - Z); + + if(((i1 | j1) & 1) == 0) { + if(numTries == 1) { + noisevarlum[(i1 >> 1)*width2 + (j1 >> 1)] = useNoiseLCurve ? lumcalc[i >> 1][j >> 1] : noisevarL; + noisevarchrom[(i1 >> 1)*width2 + (j1 >> 1)] = useNoiseCCurve ? maxNoiseVarab * ccalc[i >> 1][j >> 1] : 1.f; + } else { + noisevarlum[(i1 >> 1)*width2 + (j1 >> 1)] = lumcalc[i >> 1][j >> 1]; + noisevarchrom[(i1 >> 1)*width2 + (j1 >> 1)] = ccalc[i >> 1][j >> 1]; + } + } + } + } + } + } else {//image is not raw; use Lab parametrization +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + + for (int j = tileleft; j < tileright; j++) { + int j1 = j - tileleft; + float L, a, b; + float rLum = src->r(i, j) ; //for denoise curves + float gLum = src->g(i, j) ; + float bLum = src->b(i, j) ; + + //use gamma sRGB, not good if TIF (JPG) Output profil not with gamma sRGB (eg : gamma =1.0, or 1.8...) + //very difficult to solve ! + // solution ==> save TIF with gamma sRGB and re open + float rtmp = Color::igammatab_srgb[ src->r(i, j) ]; + float gtmp = Color::igammatab_srgb[ src->g(i, j) ]; + float btmp = Color::igammatab_srgb[ src->b(i, j) ]; + //modification Jacques feb 2013 + // gamma slider different from raw + rtmp = rtmp < 65535.0f ? gamcurve[rtmp] : (Color::gamman((double)rtmp / 65535.0, gam) * 32768.0f); + gtmp = gtmp < 65535.0f ? gamcurve[gtmp] : (Color::gamman((double)gtmp / 65535.0, gam) * 32768.0f); + btmp = btmp < 65535.0f ? gamcurve[btmp] : (Color::gamman((double)btmp / 65535.0, gam) * 32768.0f); + + float X, Y, Z; + Color::rgbxyz(rtmp, gtmp, btmp, X, Y, Z, wp); + + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, a, b); + labdn->L[i1][j1] = L; + labdn->a[i1][j1] = a; + labdn->b[i1][j1] = b; + + if(((i1 | j1) & 1) == 0) { + float Llum, alum, blum; + + if(useNoiseLCurve || useNoiseCCurve) { + float XL, YL, ZL; + Color::rgbxyz(rLum, gLum, bLum, XL, YL, ZL, wp); + Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum); + } + + if(useNoiseLCurve) { + float kN = Llum; + float epsi = 0.01f; + + if(kN < 2.f) { + kN = 2.f; + } + + if(kN > 32768.f) { + kN = 32768.f; + } + + float kinterm = epsi + noiseLCurve[xdivf(kN, 15) * 500.f]; + float ki = kinterm * 100.f; + ki += noiseluma; + noisevarlum[(i1 >> 1)*width2 + (j1 >> 1)] = SQR((ki / 125.f) * (1.f + ki / 25.f)); + } else { + noisevarlum[(i1 >> 1)*width2 + (j1 >> 1)] = noisevarL; + } + + if(useNoiseCCurve) { + float aN = alum; + float bN = blum; + float cN = sqrtf(SQR(aN) + SQR(bN)); + + if(cN < 100.f) { + cN = 100.f; //avoid divided by zero ??? + } + + float Cinterm = 1.f + ponderCC * 4.f * noiseCCurve[cN / 60.f]; + noisevarchrom[(i1 >> 1)*width2 + (j1 >> 1)] = maxNoiseVarab * SQR(Cinterm); + } else { + noisevarchrom[(i1 >> 1)*width2 + (j1 >> 1)] = 1.f; + } + } + } + } + } + + //now perform basic wavelet denoise + //arguments 4 and 5 of wavelet decomposition are max number of wavelet decomposition levels; + //and whether to subsample the image after wavelet filtering. Subsampling is coded as + //binary 1 or 0 for each level, eg subsampling = 0 means no subsampling, 1 means subsample + //the first level only, 7 means subsample the first three levels, etc. + //actual implementation only works with subsampling set to 1 + float interm_medT = (float) dnparams.chroma / 10.0; + bool execwavelet = true; + + if(!denoiseLuminance && interm_medT < 0.05f && dnparams.median && (dnparams.methodmed == "Lab" || dnparams.methodmed == "Lonly")) { + execwavelet = false; //do not exec wavelet if sliders luminance and chroma are very small and median need + } + + //we considered user don't want wavelet + if(settings->leveldnautsimpl == 1 && dnparams.Cmethod != "MAN") { + execwavelet = true; + } + + if(settings->leveldnautsimpl == 0 && dnparams.C2method != "MANU") { + execwavelet = true; + } + + if(execwavelet) {//gain time if user choose only median sliders L <=1 slider chrom master < 1 + wavelet_decomposition* Ldecomp; + wavelet_decomposition* adecomp; + + int levwav = 5; + float maxreal = max(realred, realblue); + + //increase the level of wavelet if user increase much or very much sliders + if( maxreal < 8.f) { + levwav = 5; + } else if( maxreal < 10.f) { + levwav = 6; + } else if( maxreal < 15.f) { + levwav = 7; + } else { + levwav = 8; //maximum ==> I have increase Maxlevel in cplx_wavelet_dec.h from 8 to 9 + } + + if(nrQuality == QUALITY_HIGH) { + levwav += settings->nrwavlevel; //increase level for enhanced mode + } + + if(levwav > 8) { + levwav = 8; + } + + int minsizetile = min(tilewidth, tileheight); + int maxlev2 = 8; + + if(minsizetile < 256) { + maxlev2 = 7; + } + + if(minsizetile < 128) { + maxlev2 = 6; + } + + if(minsizetile < 64) { + maxlev2 = 5; + } + + levwav = min(maxlev2, levwav); + + // if (settings->verbose) printf("levwavelet=%i noisevarA=%f noisevarB=%f \n",levwav, noisevarab_r, noisevarab_b ); + Ldecomp = new wavelet_decomposition (labdn->L[0], labdn->W, labdn->H, levwav, 1, 1, max(1, denoiseNestedLevels)); + + if(Ldecomp->memoryAllocationFailed) { + memoryAllocationFailed = true; + } + + float madL[8][3]; + + if(!memoryAllocationFailed) { + // precalculate madL, because it's used in adecomp and bdecomp + int maxlvl = Ldecomp->maxlevel(); +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for schedule(dynamic) collapse(2) num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + + for (int lvl = 0; lvl < maxlvl; lvl++) { + for (int dir = 1; dir < 4; dir++) { + // compute median absolute deviation (MAD) of detail coefficients as robust noise estimator + int Wlvl_L = Ldecomp->level_W(lvl); + int Hlvl_L = Ldecomp->level_H(lvl); + + float ** WavCoeffs_L = Ldecomp->level_coeffs(lvl); + + if(!denoiseMethodRgb) { + madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); + } else { + madL[lvl][dir - 1] = SQR(MadRgb(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); + } + } + } + } + + float chresid = 0.f; + float chresidtemp = 0.f; + float chmaxresid = 0.f; + float chmaxresidtemp = 0.f; + + adecomp = new wavelet_decomposition (labdn->a[0], labdn->W, labdn->H, levwav, 1, 1, max(1, denoiseNestedLevels)); + + if(adecomp->memoryAllocationFailed) { + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) { + if(nrQuality == QUALITY_STANDARD) { + if(!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb )) { //enhance mode + memoryAllocationFailed = true; + } + } else { /*if(nrQuality==QUALITY_HIGH)*/ + if(!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb )) { //enhance mode + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) + if(!WaveletDenoiseAllAB(*Ldecomp, *adecomp, noisevarchrom, madL, noisevarab_r, useNoiseCCurve, autoch, denoiseMethodRgb )) { + memoryAllocationFailed = true; + } + } + } + + if(!memoryAllocationFailed) { + if(kall == 0) { + Noise_residualAB(*adecomp, chresid, chmaxresid, denoiseMethodRgb); + chresidtemp = chresid; + chmaxresidtemp = chmaxresid; + } + + adecomp->reconstruct(labdn->a[0]); + } + + delete adecomp; + + if(!memoryAllocationFailed) { + wavelet_decomposition* bdecomp = new wavelet_decomposition (labdn->b[0], labdn->W, labdn->H, levwav, 1, 1, max(1, denoiseNestedLevels)); + + if(bdecomp->memoryAllocationFailed) { + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) { + if(nrQuality == QUALITY_STANDARD) { + if(!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb )) { //enhance mode + memoryAllocationFailed = true; + } + } else { /*if(nrQuality==QUALITY_HIGH)*/ + if(!WaveletDenoiseAll_BiShrinkAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb )) { //enhance mode + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) + if(!WaveletDenoiseAllAB(*Ldecomp, *bdecomp, noisevarchrom, madL, noisevarab_b, useNoiseCCurve, autoch, denoiseMethodRgb )) { + memoryAllocationFailed = true; + } + } + } + + if(!memoryAllocationFailed) { + if(kall == 0) { + Noise_residualAB(*bdecomp, chresid, chmaxresid, denoiseMethodRgb); + chresid += chresidtemp; + chmaxresid += chmaxresidtemp; + chresid = sqrt(chresid / (6 * (levwav))); + highresi = chresid + 0.66f * (sqrt(chmaxresid) - chresid); //evaluate sigma + nresi = chresid; + } + + bdecomp->reconstruct(labdn->b[0]); + } + + delete bdecomp; + + if(!memoryAllocationFailed) { + if(denoiseLuminance) { + int edge = 0; + + if(nrQuality == QUALITY_STANDARD) { + if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, NULL, edge)) { //enhance mode + memoryAllocationFailed = true; + } + } else { /*if(nrQuality==QUALITY_HIGH)*/ + if(!WaveletDenoiseAll_BiShrinkL(*Ldecomp, noisevarlum, madL)) { //enhance mode + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) + if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, NULL, edge)) { + memoryAllocationFailed = true; + } + } + + if(!memoryAllocationFailed) { + // copy labdn->L to Lin before it gets modified by reconstruction + Lin = new array2D(width, height); +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + + for(int i = 0; i < height; i++) + for(int j = 0; j < width; j++) { + (*Lin)[i][j] = labdn->L[i][j]; + } + + Ldecomp->reconstruct(labdn->L[0]); + } + } + } + } + + delete Ldecomp; + } + + if(!memoryAllocationFailed) { + if( (metchoice == 1 || metchoice == 2 || metchoice == 3 || metchoice == 4) && dnparams.median) { + float** tmL; + int wid = labdn->W; + int hei = labdn->H; + tmL = new float*[hei]; + + for (int i = 0; i < hei; i++) { + tmL[i] = new float[wid]; + } + + mediantype medianTypeL = MED_3X3SOFT; + mediantype medianTypeAB = MED_3X3SOFT; + + if(dnparams.medmethod == "soft") { + if(metchoice != 4) { + medianTypeL = medianTypeAB = MED_3X3SOFT; + } else { + medianTypeL = MED_3X3SOFT; + medianTypeAB = MED_3X3SOFT; + } + } else if(dnparams.medmethod == "33") { + if(metchoice != 4) { + medianTypeL = medianTypeAB = MED_3X3STRONG; + } else { + medianTypeL = MED_3X3SOFT; + medianTypeAB = MED_3X3STRONG; + } + } else if(dnparams.medmethod == "55soft") { + if(metchoice != 4) { + medianTypeL = medianTypeAB = MED_5X5SOFT; + } else { + medianTypeL = MED_3X3SOFT; + medianTypeAB = MED_5X5SOFT; + } + } else if(dnparams.medmethod == "55") { + if(metchoice != 4) { + medianTypeL = medianTypeAB = MED_5X5STRONG; + } else { + medianTypeL = MED_3X3STRONG; + medianTypeAB = MED_5X5STRONG; + } + } else if(dnparams.medmethod == "77") { + if(metchoice != 4) { + medianTypeL = medianTypeAB = MED_7X7; + } else { + medianTypeL = MED_3X3STRONG; + medianTypeAB = MED_7X7; + } + } else if(dnparams.medmethod == "99") { + if(metchoice != 4) { + medianTypeL = medianTypeAB = MED_9X9; + } else { + medianTypeL = MED_5X5SOFT; + medianTypeAB = MED_9X9; + } + } + + if (metchoice == 1 || metchoice == 2 || metchoice == 4) { + Median_Denoise( labdn->L, labdn->L, wid, hei, medianTypeL, dnparams.passes, denoiseNestedLevels, tmL); + } + + if(metchoice == 2 || metchoice == 3 || metchoice == 4) { + Median_Denoise( labdn->a, labdn->a, wid, hei, medianTypeAB, dnparams.passes, denoiseNestedLevels, tmL); + Median_Denoise( labdn->b, labdn->b, wid, hei, medianTypeAB, dnparams.passes, denoiseNestedLevels, tmL); + } + + for (int i = 0; i < hei; i++) { + delete [] tmL[i]; + } + + delete [] tmL; + } + + //wavelet denoised L channel + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // now do detail recovery using block DCT to detect + // patterns missed by wavelet denoise + // blocks are not the same thing as tiles! + + // calculation for detail recovery blocks + const int numblox_W = ceil(((float)(width)) / (offset)) + 2 * blkrad; + const int numblox_H = ceil(((float)(height)) / (offset)) + 2 * blkrad; + + + + // end of tiling calc + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // Main detail recovery algorithm: Block loop + //DCT block data storage + + if(denoiseLuminance /*&& execwavelet*/) { + //residual between input and denoised L channel + array2D Ldetail(width, height, ARRAY2D_CLEAR_DATA); + //pixel weight + array2D totwt(width, height, ARRAY2D_CLEAR_DATA); //weight for combining DCT blocks + + if(numtiles == 1) + for(int i = 0; i < denoiseNestedLevels * numthreads; i++) { + LbloxArray[i] = (float*) fftwf_malloc(max_numblox_W * TS * TS * sizeof(float)); + fLbloxArray[i] = (float*) fftwf_malloc(max_numblox_W * TS * TS * sizeof(float)); + } + +#ifdef _RT_NESTED_OPENMP + int masterThread = omp_get_thread_num(); +#endif +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + { +#ifdef _RT_NESTED_OPENMP + int subThread = masterThread * denoiseNestedLevels + omp_get_thread_num(); +#else + int subThread = 0; +#endif + float blurbuffer[TS * TS] ALIGNED64; + float *Lblox = LbloxArray[subThread]; + float *fLblox = fLbloxArray[subThread]; + float pBuf[width + TS + 2 * blkrad * offset] ALIGNED16; + float nbrwt[TS * TS] ALIGNED64; +#ifdef _RT_NESTED_OPENMP + #pragma omp for +#endif + + for (int vblk = 0; vblk < numblox_H; vblk++) { + + int top = (vblk - blkrad) * offset; + float * datarow = pBuf + blkrad * offset; + + for (int i = 0; i < TS; i++) { + int row = top + i; + int rr = row; + + if (row < 0) { + rr = MIN(-row, height - 1); + } else if (row >= height) { + rr = MAX(0, 2 * height - 2 - row); + } + + for (int j = 0; j < labdn->W; j++) { + datarow[j] = ((*Lin)[rr][j] - labdn->L[rr][j]); + } + + for (int j = -blkrad * offset; j < 0; j++) { + datarow[j] = datarow[MIN(-j, width - 1)]; + } + + for (int j = width; j < width + TS + blkrad * offset; j++) { + datarow[j] = datarow[MAX(0, 2 * width - 2 - j)]; + }//now we have a padded data row + + //now fill this row of the blocks with Lab high pass data + for (int hblk = 0; hblk < numblox_W; hblk++) { + int left = (hblk - blkrad) * offset; + int indx = (hblk) * TS; //index of block in malloc + + if(top + i >= 0 && top + i < height) { + int j; + + for (j = 0; j < min((-left), TS); j++) { + Lblox[(indx + i)*TS + j] = tilemask_in[i][j] * datarow[left + j]; // luma data + } + + for (; j < min(TS, width - left); j++) { + Lblox[(indx + i)*TS + j] = tilemask_in[i][j] * datarow[left + j]; // luma data + totwt[top + i][left + j] += tilemask_in[i][j] * tilemask_out[i][j]; + } + + for (; j < TS; j++) { + Lblox[(indx + i)*TS + j] = tilemask_in[i][j] * datarow[left + j]; // luma data + } + } else { + for (int j = 0; j < TS; j++) { + Lblox[(indx + i)*TS + j] = tilemask_in[i][j] * datarow[left + j]; // luma data + } + } + + } + + }//end of filling block row + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //fftwf_print_plan (plan_forward_blox); + if(numblox_W == max_numblox_W) { + fftwf_execute_r2r(plan_forward_blox[0], Lblox, fLblox); // DCT an entire row of tiles + } else { + fftwf_execute_r2r(plan_forward_blox[1], Lblox, fLblox); // DCT an entire row of tiles + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // now process the vblk row of blocks for noise reduction + + + for (int hblk = 0; hblk < numblox_W; hblk++) { + RGBtile_denoise (fLblox, hblk, noisevar_Ldetail, nbrwt, blurbuffer ); + }//end of horizontal block loop + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //now perform inverse FT of an entire row of blocks + if(numblox_W == max_numblox_W) { + fftwf_execute_r2r(plan_backward_blox[0], fLblox, Lblox); //for DCT + } else { + fftwf_execute_r2r(plan_backward_blox[1], fLblox, Lblox); //for DCT + } + + int topproc = (vblk - blkrad) * offset; + + //add row of blocks to output image tile + RGBoutput_tile_row (Lblox, Ldetail, tilemask_out, height, width, topproc ); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + }//end of vertical block loop + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + //may want to include masking threshold for large hipass data to preserve edges/detail + labdn->L[i][j] += Ldetail[i][j] / totwt[i][j]; //note that labdn initially stores the denoised hipass data + } + } + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // transform denoised "Lab" to output RGB + + //calculate mask for feathering output tile overlaps + float Vmask[height + 1] ALIGNED16; + float Hmask[width + 1] ALIGNED16; + float newGain; + + if(numtiles > 1) { + for (int i = 0; i < height; i++) { + Vmask[i] = 1; + } + + newGain = 1.f; + + if(isRAW) { + newGain = gain; + } + + for (int j = 0; j < width; j++) { + Hmask[j] = 1.f / newGain; + } + + for (int i = 0; i < overlap; i++) { + float mask = SQR(xsinf((M_PI * i) / (2 * overlap))); + + if (tiletop > 0) { + Vmask[i] = mask; + } + + if (tilebottom < imheight) { + Vmask[height - i] = mask; + } + + if (tileleft > 0) { + Hmask[i] = mask / newGain; + } + + if (tileright < imwidth) { + Hmask[width - i] = mask / newGain; + } + } + } else { + newGain = isRAW ? 1.f / gain : 1.f;; + } + + //convert back to RGB and write to destination array + if (isRAW) { + if(!denoiseMethodRgb) {//Lab mode + realred /= 100.f; + realblue /= 100.f; + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for schedule(dynamic,16) num_threads(denoiseNestedLevels) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + + for (int j = tileleft; j < tileright; j++) { + int j1 = j - tileleft; + //modification Jacques feb 2013 + //true conversion Lab==>xyz + float L = labdn->L[i1][j1]; + float a = labdn->a[i1][j1]; + float b = labdn->b[i1][j1]; + float c_h = SQR(a) + SQR(b); + + if(c_h > 9000000.f) { + a *= 1.f + qhighFactor * realred; + b *= 1.f + qhighFactor * realblue; + } + + //convert XYZ + float X, Y, Z; + Color::Lab2XYZ(L, a, b, X, Y, Z); + //apply inverse gamma noise + float r_, g_, b_; + Color::xyz2rgb(X, Y, Z, r_, g_, b_, wip); + //inverse gamma standard (slider) + r_ = r_ < 32768.f ? igamcurve[r_] : (Color::gammanf(r_ / 32768.f, igam) * 65535.f); + g_ = g_ < 32768.f ? igamcurve[g_] : (Color::gammanf(g_ / 32768.f, igam) * 65535.f); + b_ = b_ < 32768.f ? igamcurve[b_] : (Color::gammanf(b_ / 32768.f, igam) * 65535.f); + + //readapt arbitrary gamma (inverse from beginning) + r_ = (*denoisegamtab)[r_]; + g_ = (*denoisegamtab)[g_]; + b_ = (*denoisegamtab)[b_]; + + if(numtiles == 1) { + dsttmp->r(i, j) = newGain * r_; + dsttmp->g(i, j) = newGain * g_; + dsttmp->b(i, j) = newGain * b_; + } else { + float factor = Vmask[i1] * Hmask[j1]; + dsttmp->r(i, j) += factor * r_; + dsttmp->g(i, j) += factor * g_; + dsttmp->b(i, j) += factor * b_; + } + } + } + } else {//RGB mode +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + + for (int j = tileleft; j < tileright; j++) { + int j1 = j - tileleft; + float c_h = sqrt(SQR(labdn->a[i1][j1]) + SQR(labdn->b[i1][j1])); + + if(c_h > 3000.f) { + labdn->a[i1][j1] *= 1.f + qhighFactor * realred / 100.f; + labdn->b[i1][j1] *= 1.f + qhighFactor * realblue / 100.f; + } + + float Y = labdn->L[i1][j1]; + float X = (labdn->a[i1][j1]) + Y; + float Z = Y - (labdn->b[i1][j1]); + + + X = X < 32768.0f ? igamcurve[X] : (Color::gamma((float)X / 32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); + Y = Y < 32768.0f ? igamcurve[Y] : (Color::gamma((float)Y / 32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); + Z = Z < 32768.0f ? igamcurve[Z] : (Color::gamma((float)Z / 32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); + + if(numtiles == 1) { + dsttmp->r(i, j) = newGain * X; + dsttmp->g(i, j) = newGain * Y; + dsttmp->b(i, j) = newGain * Z; + } else { + float factor = Vmask[i1] * Hmask[j1]; + dsttmp->r(i, j) += factor * X; + dsttmp->g(i, j) += factor * Y; + dsttmp->b(i, j) += factor * Z; + } + } + } + + } + } else { +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(denoiseNestedLevels) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + + for (int j = tileleft; j < tileright; j++) { + int j1 = j - tileleft; + //modification Jacques feb 2013 + float L = labdn->L[i1][j1]; + float a = labdn->a[i1][j1]; + float b = labdn->b[i1][j1]; + float c_h = sqrt(SQR(a) + SQR(b)); + + if(c_h > 3000.f) { + a *= 1.f + qhighFactor * realred / 100.f; + b *= 1.f + qhighFactor * realblue / 100.f; + } + + float X, Y, Z; + Color::Lab2XYZ(L, a, b, X, Y, Z); + + float r_, g_, b_; + Color::xyz2rgb(X, Y, Z, r_, g_, b_, wip); + //gamma slider is different from Raw + r_ = r_ < 32768.0f ? igamcurve[r_] : (Color::gamman((float)r_ / 32768.0f, igam) * 65535.0f); + g_ = g_ < 32768.0f ? igamcurve[g_] : (Color::gamman((float)g_ / 32768.0f, igam) * 65535.0f); + b_ = b_ < 32768.0f ? igamcurve[b_] : (Color::gamman((float)b_ / 32768.0f, igam) * 65535.0f); + + if(numtiles == 1) { + dsttmp->r(i, j) = newGain * r_; + dsttmp->g(i, j) = newGain * g_; + dsttmp->b(i, j) = newGain * b_; + } else { + float factor = Vmask[i1] * Hmask[j1]; + dsttmp->r(i, j) += factor * r_; + dsttmp->g(i, j) += factor * g_; + dsttmp->b(i, j) += factor * b_; + } + } + } + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + } + + delete labdn; + + if(denoiseLuminance) { + delete Lin; + } + + }//end of tile row + }//end of tile loop + + if(numtiles > 1 || !isRAW || (!useNoiseCCurve && !useNoiseLCurve)) { + delete [] noisevarlum; + delete [] noisevarchrom; + } + + } + + if(denoiseLuminance) { + for(int i = 0; i < denoiseNestedLevels * numthreads; i++) { + fftwf_free(LbloxArray[i]); + fftwf_free(fLbloxArray[i]); + } + } + +#ifdef _RT_NESTED_OPENMP + omp_set_nested(oldNested); +#endif + + //copy denoised image to output + if(numtiles > 1) { + if(!memoryAllocationFailed) { + dsttmp->copyData(dst); + } else if(dst != src) { + src->copyData(dst); + } + + delete dsttmp; + } + + if (!isRAW && !memoryAllocationFailed) {//restore original image gamma +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < dst->height; i++) + for(int j = 0; j < dst->width; j++) { + dst->r(i, j) = Color::gammatab_srgb[ dst->r(i, j) ]; + dst->g(i, j) = Color::gammatab_srgb[ dst->g(i, j) ]; + dst->b(i, j) = Color::gammatab_srgb[ dst->b(i, j) ]; + } + } + + if(denoiseLuminance) { + // destroy the plans + fftwf_destroy_plan( plan_forward_blox[0] ); + fftwf_destroy_plan( plan_backward_blox[0] ); + fftwf_destroy_plan( plan_forward_blox[1] ); + fftwf_destroy_plan( plan_backward_blox[1] ); + fftwf_cleanup(); + } + } while(memoryAllocationFailed && numTries < 2 && (options.rgbDenoiseThreadLimit == 0) && !ponder); + + if(memoryAllocationFailed) { + printf("tiled denoise failed due to isufficient memory. Output is not denoised!\n"); + } + + } //median 3x3 in complement on RGB -if(dnparams.methodmed=="RGB" && dnparams.median) { + if(dnparams.methodmed == "RGB" && dnparams.median) { //printf("RGB den\n"); - int wid=dst->width, hei=dst->height; - float** tm; - tm = new float*[hei]; - for (int i=0; iwidth, hei = dst->height; + float** tm; + tm = new float*[hei]; - Imagefloat *source; - if (dnparams.luma==0 && dnparams.chroma==0) - source = dst; - else - source = src; + for (int i = 0; i < hei; i++) { + tm[i] = new float[wid]; + } - int methmed=0; - int border = 1; - if(dnparams.rgbmethod=="soft") - methmed=0; - else if(dnparams.rgbmethod=="33") - methmed=1; - else if(dnparams.rgbmethod=="55") { - methmed = 3; - border = 2; - } - else if(dnparams.rgbmethod=="55soft") { - methmed = 2; - border = 2; - } + Imagefloat *source; -for(int iteration=1;iteration<=dnparams.passes;iteration++){ + if (dnparams.luma == 0 && dnparams.chroma == 0) { + source = dst; + } else { + source = src; + } -#pragma omp parallel -{ - if(methmed < 2) { -#pragma omp for - for (int i=1; ir(i,j),source->r(i-1,j),source->r(i+1,j),source->r(i,j+1),source->r(i,j-1),tm[i][j]);//3x3 soft - } - else - for (int j=1; jr(i,j),source->r(i-1,j),source->r(i+1,j),source->r(i,j+1),source->r(i,j-1),source->r(i-1,j-1),source->r(i-1,j+1),source->r(i+1,j-1),source->r(i+1,j+1),tm[i][j]);//3x3 - } - } - } else { -#pragma omp for - for (int i=2; ir(i,j),source->r(i-1,j),source->r(i+1,j),source->r(i,j+1),source->r(i,j-1),source->r(i-1,j-1),source->r(i-1,j+1),source->r(i+1,j-1),source->r(i+1,j+1), - source->r(i-2,j),source->r(i+2,j),source->r(i,j+2),source->r(i,j-2),source->r(i-2,j-2),source->r(i-2,j+2),source->r(i+2,j-2),source->r(i+2,j+2), - source->r(i-2,j+1),source->r(i+2,j+1),source->r(i-1,j+2),source->r(i-1,j-2),source->r(i-2,j-1),source->r(i+2,j-1),source->r(i+1,j+2),source->r(i+1,j-2), - tm[i][j]);//5x5 - } - } else - for (int j=2; jr(i,j);pp[1]=source->r(i-1,j); pp[2]=source->r(i+1,j);pp[3]=source->r(i,j+1);pp[4]=source->r(i,j-1);pp[5]=source->r(i-1,j-1);pp[6]=source->r(i-1,j+1); - pp[7]=source->r(i+1,j-1);pp[8]=source->r(i+1,j+1);pp[9]=source->r(i+2,j);pp[10]=source->r(i-2,j);pp[11]=source->r(i,j+2);pp[12]=source->r(i,j-2); - fq_sort2(pp,13); - tm[i][j]=pp[6];//5x5 soft - } - } - } + int methmed = 0; + int border = 1; + + if(dnparams.rgbmethod == "soft") { + methmed = 0; + } else if(dnparams.rgbmethod == "33") { + methmed = 1; + } else if(dnparams.rgbmethod == "55") { + methmed = 3; + border = 2; + } else if(dnparams.rgbmethod == "55soft") { + methmed = 2; + border = 2; + } + + for(int iteration = 1; iteration <= dnparams.passes; iteration++) { + + #pragma omp parallel + { + if(methmed < 2) + { + #pragma omp for + + for (int i = 1; i < hei - 1; i++) { + float pp[9], temp; + + if(methmed == 0) + for (int j = 1; j < wid - 1; j++) { + med2(source->r(i, j), source->r(i - 1, j), source->r(i + 1, j), source->r(i, j + 1), source->r(i, j - 1), tm[i][j]); //3x3 soft + } + else + for (int j = 1; j < wid - 1; j++) { + med3(source->r(i, j), source->r(i - 1, j), source->r(i + 1, j), source->r(i, j + 1), source->r(i, j - 1), source->r(i - 1, j - 1), source->r(i - 1, j + 1), source->r(i + 1, j - 1), source->r(i + 1, j + 1), tm[i][j]); //3x3 + } + } + } else { + #pragma omp for + + for (int i = 2; i < hei - 2; i++) + { + float pp[25]; + + if(methmed == 3) { + float temp; + + for (int j = 2; j < wid - 2; j++) { + med5(source->r(i, j), source->r(i - 1, j), source->r(i + 1, j), source->r(i, j + 1), source->r(i, j - 1), source->r(i - 1, j - 1), source->r(i - 1, j + 1), source->r(i + 1, j - 1), source->r(i + 1, j + 1), + source->r(i - 2, j), source->r(i + 2, j), source->r(i, j + 2), source->r(i, j - 2), source->r(i - 2, j - 2), source->r(i - 2, j + 2), source->r(i + 2, j - 2), source->r(i + 2, j + 2), + source->r(i - 2, j + 1), source->r(i + 2, j + 1), source->r(i - 1, j + 2), source->r(i - 1, j - 2), source->r(i - 2, j - 1), source->r(i + 2, j - 1), source->r(i + 1, j + 2), source->r(i + 1, j - 2), + tm[i][j]);//5x5 + } + } else + for (int j = 2; j < wid - 2; j++) { + pp[0] = source->r(i, j); + pp[1] = source->r(i - 1, j); + pp[2] = source->r(i + 1, j); + pp[3] = source->r(i, j + 1); + pp[4] = source->r(i, j - 1); + pp[5] = source->r(i - 1, j - 1); + pp[6] = source->r(i - 1, j + 1); + pp[7] = source->r(i + 1, j - 1); + pp[8] = source->r(i + 1, j + 1); + pp[9] = source->r(i + 2, j); + pp[10] = source->r(i - 2, j); + pp[11] = source->r(i, j + 2); + pp[12] = source->r(i, j - 2); + fq_sort2(pp, 13); + tm[i][j] = pp[6]; //5x5 soft + } + } + } #ifdef _OPENMP -#pragma omp for nowait + #pragma omp for nowait #endif - for(int i = border; i < hei-border; i++ ) { - for(int j = border; j < wid-border; j++) { - dst->r(i,j) = tm[i][j]; - } - } - if(methmed < 2) { -#pragma omp for - for (int i=1; ib(i,j),source->b(i-1,j),source->b(i+1,j),source->b(i,j+1),source->b(i,j-1),tm[i][j]); - } - else - for (int j=1; jb(i,j),source->b(i-1,j),source->b(i+1,j),source->b(i,j+1),source->b(i,j-1),source->b(i-1,j-1),source->b(i-1,j+1),source->b(i+1,j-1),source->b(i+1,j+1),tm[i][j]); - } - } - } else { -#pragma omp for - for (int i=2; ib(i,j),source->b(i-1,j),source->b(i+1,j),source->b(i,j+1),source->b(i,j-1),source->b(i-1,j-1),source->b(i-1,j+1),source->b(i+1,j-1),source->b(i+1,j+1), - source->b(i-2,j),source->b(i+2,j),source->b(i,j+2),source->b(i,j-2),source->b(i-2,j-2),source->b(i-2,j+2),source->b(i+2,j-2),source->b(i+2,j+2), - source->b(i-2,j+1),source->b(i+2,j+1),source->b(i-1,j+2),source->b(i-1,j-2),source->b(i-2,j-1),source->b(i+2,j-1),source->b(i+1,j+2),source->b(i+1,j-2), - tm[i][j]);//5x5 - } - } else - for (int j=2; jb(i,j);pp[1]=source->b(i-1,j); pp[2]=source->b(i+1,j);pp[3]=source->b(i,j+1);pp[4]=source->b(i,j-1);pp[5]=source->b(i-1,j-1);pp[6]=source->b(i-1,j+1); - pp[7]=source->b(i+1,j-1);pp[8]=source->b(i+1,j+1);pp[9]=source->b(i+2,j);pp[10]=source->b(i-2,j);pp[11]=source->b(i,j+2);pp[12]=source->b(i,j-2); - fq_sort2(pp,13); - tm[i][j]=pp[6];//5x5 soft - } - } - } + for(int i = border; i < hei - border; i++ ) + { + for(int j = border; j < wid - border; j++) { + dst->r(i, j) = tm[i][j]; + } + } + + if(methmed < 2) + { + #pragma omp for + + for (int i = 1; i < hei - 1; i++) { + float pp[9], temp; + + if(methmed == 0) + for (int j = 1; j < wid - 1; j++) { + med2(source->b(i, j), source->b(i - 1, j), source->b(i + 1, j), source->b(i, j + 1), source->b(i, j - 1), tm[i][j]); + } + else + for (int j = 1; j < wid - 1; j++) { + med3(source->b(i, j), source->b(i - 1, j), source->b(i + 1, j), source->b(i, j + 1), source->b(i, j - 1), source->b(i - 1, j - 1), source->b(i - 1, j + 1), source->b(i + 1, j - 1), source->b(i + 1, j + 1), tm[i][j]); + } + } + } else { + #pragma omp for + + for (int i = 2; i < hei - 2; i++) + { + float pp[25]; + + if(methmed == 3) { + float temp; + + for (int j = 2; j < wid - 2; j++) { + med5(source->b(i, j), source->b(i - 1, j), source->b(i + 1, j), source->b(i, j + 1), source->b(i, j - 1), source->b(i - 1, j - 1), source->b(i - 1, j + 1), source->b(i + 1, j - 1), source->b(i + 1, j + 1), + source->b(i - 2, j), source->b(i + 2, j), source->b(i, j + 2), source->b(i, j - 2), source->b(i - 2, j - 2), source->b(i - 2, j + 2), source->b(i + 2, j - 2), source->b(i + 2, j + 2), + source->b(i - 2, j + 1), source->b(i + 2, j + 1), source->b(i - 1, j + 2), source->b(i - 1, j - 2), source->b(i - 2, j - 1), source->b(i + 2, j - 1), source->b(i + 1, j + 2), source->b(i + 1, j - 2), + tm[i][j]);//5x5 + } + } else + for (int j = 2; j < wid - 2; j++) { + pp[0] = source->b(i, j); + pp[1] = source->b(i - 1, j); + pp[2] = source->b(i + 1, j); + pp[3] = source->b(i, j + 1); + pp[4] = source->b(i, j - 1); + pp[5] = source->b(i - 1, j - 1); + pp[6] = source->b(i - 1, j + 1); + pp[7] = source->b(i + 1, j - 1); + pp[8] = source->b(i + 1, j + 1); + pp[9] = source->b(i + 2, j); + pp[10] = source->b(i - 2, j); + pp[11] = source->b(i, j + 2); + pp[12] = source->b(i, j - 2); + fq_sort2(pp, 13); + tm[i][j] = pp[6]; //5x5 soft + } + } + } #ifdef _OPENMP -#pragma omp for nowait + #pragma omp for nowait #endif - for(int i = border; i < hei-border; i++ ) { - for(int j = border; j < wid-border; j++) { - dst->b(i,j) = tm[i][j]; - } - } + + for(int i = border; i < hei - border; i++ ) + { + for(int j = border; j < wid - border; j++) { + dst->b(i, j) = tm[i][j]; + } + } - if(methmed < 2) { -#pragma omp for - for (int i=1; ig(i,j),source->g(i-1,j),source->g(i+1,j),source->g(i,j+1),source->g(i,j-1),tm[i][j]); - } - else - for (int j=1; jg(i,j),source->g(i-1,j),source->g(i+1,j),source->g(i,j+1),source->g(i,j-1),source->g(i-1,j-1),source->g(i-1,j+1),source->g(i+1,j-1),source->g(i+1,j+1),tm[i][j]); - } - } - } else { -#pragma omp for - for (int i=2; ig(i,j),source->g(i-1,j),source->g(i+1,j),source->g(i,j+1),source->g(i,j-1),source->g(i-1,j-1),source->g(i-1,j+1),source->g(i+1,j-1),source->g(i+1,j+1), - source->g(i-2,j),source->g(i+2,j),source->g(i,j+2),source->g(i,j-2),source->g(i-2,j-2),source->g(i-2,j+2),source->g(i+2,j-2),source->g(i+2,j+2), - source->g(i-2,j+1),source->g(i+2,j+1),source->g(i-1,j+2),source->g(i-1,j-2),source->g(i-2,j-1),source->g(i+2,j-1),source->g(i+1,j+2),source->g(i+1,j-2), - tm[i][j]);//5x5 - } - } else - for (int j=2; jg(i,j);pp[1]=source->g(i-1,j); pp[2]=source->g(i+1,j);pp[3]=source->g(i,j+1);pp[4]=source->g(i,j-1);pp[5]=source->g(i-1,j-1);pp[6]=source->g(i-1,j+1); - pp[7]=source->g(i+1,j-1);pp[8]=source->g(i+1,j+1);pp[9]=source->g(i+2,j);pp[10]=source->g(i-2,j);pp[11]=source->g(i,j+2);pp[12]=source->g(i,j-2); - fq_sort2(pp,13); - tm[i][j]=pp[6];//5x5 soft - } - } - } + if(methmed < 2) + { + #pragma omp for + + for (int i = 1; i < hei - 1; i++) { + float pp[9], temp; + + if(methmed == 0) + for (int j = 1; j < wid - 1; j++) { + med2(source->g(i, j), source->g(i - 1, j), source->g(i + 1, j), source->g(i, j + 1), source->g(i, j - 1), tm[i][j]); + } + else + for (int j = 1; j < wid - 1; j++) { + med3(source->g(i, j), source->g(i - 1, j), source->g(i + 1, j), source->g(i, j + 1), source->g(i, j - 1), source->g(i - 1, j - 1), source->g(i - 1, j + 1), source->g(i + 1, j - 1), source->g(i + 1, j + 1), tm[i][j]); + } + } + } else { + #pragma omp for + + for (int i = 2; i < hei - 2; i++) + { + float pp[25]; + + if(methmed == 3) { + float temp; + + for (int j = 2; j < wid - 2; j++) { + med5(source->g(i, j), source->g(i - 1, j), source->g(i + 1, j), source->g(i, j + 1), source->g(i, j - 1), source->g(i - 1, j - 1), source->g(i - 1, j + 1), source->g(i + 1, j - 1), source->g(i + 1, j + 1), + source->g(i - 2, j), source->g(i + 2, j), source->g(i, j + 2), source->g(i, j - 2), source->g(i - 2, j - 2), source->g(i - 2, j + 2), source->g(i + 2, j - 2), source->g(i + 2, j + 2), + source->g(i - 2, j + 1), source->g(i + 2, j + 1), source->g(i - 1, j + 2), source->g(i - 1, j - 2), source->g(i - 2, j - 1), source->g(i + 2, j - 1), source->g(i + 1, j + 2), source->g(i + 1, j - 2), + tm[i][j]);//5x5 + } + } else + for (int j = 2; j < wid - 2; j++) { + pp[0] = source->g(i, j); + pp[1] = source->g(i - 1, j); + pp[2] = source->g(i + 1, j); + pp[3] = source->g(i, j + 1); + pp[4] = source->g(i, j - 1); + pp[5] = source->g(i - 1, j - 1); + pp[6] = source->g(i - 1, j + 1); + pp[7] = source->g(i + 1, j - 1); + pp[8] = source->g(i + 1, j + 1); + pp[9] = source->g(i + 2, j); + pp[10] = source->g(i - 2, j); + pp[11] = source->g(i, j + 2); + pp[12] = source->g(i, j - 2); + fq_sort2(pp, 13); + tm[i][j] = pp[6]; //5x5 soft + } + } + } #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = border; i < hei-border; i++ ) { - for(int j = border; j < wid-border; j++) { - dst->g(i,j) = tm[i][j]; - } - } -} -} - for (int i=0; ig(i, j) = tm[i][j]; + } + } + } + } + + for (int i = 0; i < hei; i++) { + delete [] tm[i]; + } + + delete [] tm; + + } + + //end median + if(noiseLCurve || useNoiseCCurve) { + delete [] lumcalcBuffer; + delete [] lumcalc; + delete [] ccalcBuffer; + delete [] ccalc; + } //#ifdef _DEBUG - if (settings->verbose) { - t2e.set(); - printf("Denoise performed in %d usec:\n", t2e.etime(t1e)); - } + if (settings->verbose) { + t2e.set(); + printf("Denoise performed in %d usec:\n", t2e.etime(t1e)); + } + //#endif }//end of main RGB_denoise @@ -1662,59 +2072,63 @@ for(int iteration=1;iteration<=dnparams.passes;iteration++){ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SSEFUNCTION void ImProcFunctions::RGBtile_denoise (float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer ) //for DCT - { - int blkstart = hblproc*TS*TS; +SSEFUNCTION void ImProcFunctions::RGBtile_denoise (float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer ) //for DCT +{ + int blkstart = hblproc * TS * TS; - boxabsblur(fLblox+blkstart, nbrwt, 3, 3, TS, TS, blurbuffer);//blur neighbor weights for more robust estimation //for DCT + boxabsblur(fLblox + blkstart, nbrwt, 3, 3, TS, TS, blurbuffer); //blur neighbor weights for more robust estimation //for DCT #ifdef __SSE2__ - __m128 tempv; - __m128 noisevar_Ldetailv = _mm_set1_ps( noisevar_Ldetail ); - __m128 onev = _mm_set1_ps( 1.0f ); - for (int n=0; nmaxresid ) maxresid=madC; - } - } - - chresid = resid; - chmaxresid = maxresid; + int Wlvl_ab = WaveletCoeffs_ab.level_W(lvl); + int Hlvl_ab = WaveletCoeffs_ab.level_H(lvl); + + float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); + + for (int dir = 1; dir < 4; dir++) { + if(denoiseMethodRgb) { + madC = SQR(MadRgb(WavCoeffs_ab[dir], Wlvl_ab * Hlvl_ab)); + } else { + madC = SQR(Mad(WavCoeffs_ab[dir], Wlvl_ab * Hlvl_ab)); + } + + resid += madC; + + if(madC > maxresid ) { + maxresid = madC; + } + } + } + + chresid = resid; + chmaxresid = maxresid; } -SSEFUNCTION bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]) { - int maxlvl = min(WaveletCoeffs_L.maxlevel(),5); - const float eps = 0.01f; - - int maxWL = 0, maxHL = 0; - for (int lvl=0; lvl maxWL) - maxWL = WaveletCoeffs_L.level_W(lvl); - if(WaveletCoeffs_L.level_H(lvl) > maxHL) - maxHL = WaveletCoeffs_L.level_H(lvl); - } - bool memoryAllocationFailed = false; -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif +SSEFUNCTION bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]) { - float *buffer[3]; - buffer[0] = new (std::nothrow) float[maxWL*maxHL+32]; - buffer[1] = new (std::nothrow) float[maxWL*maxHL+64]; - buffer[2] = new (std::nothrow) float[maxWL*maxHL+96]; - if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL) { - memoryAllocationFailed = true; - } - - if(!memoryAllocationFailed) { - + int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5); + const float eps = 0.01f; + + int maxWL = 0, maxHL = 0; + + for (int lvl = 0; lvl < maxlvl; lvl++) { + if(WaveletCoeffs_L.level_W(lvl) > maxWL) { + maxWL = WaveletCoeffs_L.level_W(lvl); + } + + if(WaveletCoeffs_L.level_H(lvl) > maxHL) { + maxHL = WaveletCoeffs_L.level_H(lvl); + } + } + + bool memoryAllocationFailed = false; #ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) + #pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) #endif - for (int lvl=maxlvl-1; lvl>=0; lvl--) {//for levels less than max, use level diff to make edge mask - for (int dir=1; dir<4; dir++) { - int Wlvl_L = WaveletCoeffs_L.level_W(lvl); - int Hlvl_L = WaveletCoeffs_L.level_H(lvl); - - float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); - if (lvl==maxlvl-1) { - float vari[4]; - int edge=0; - ShrinkAllL(WaveletCoeffs_L, buffer, lvl, dir, noisevarlum, madL[lvl], NULL, edge ); - } else { - //simple wavelet shrinkage - float * sfave = buffer[0]+32; - float * sfaved = buffer[2]+96; - float * blurBuffer = buffer[1]+64; + { + float *buffer[3]; + buffer[0] = new (std::nothrow) float[maxWL * maxHL + 32]; + buffer[1] = new (std::nothrow) float[maxWL * maxHL + 64]; + buffer[2] = new (std::nothrow) float[maxWL * maxHL + 96]; - float mad_Lr = madL[lvl][dir-1]; + if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL) { + memoryAllocationFailed = true; + } - float levelFactor = mad_Lr*5.f/(lvl+1); + if(!memoryAllocationFailed) { + +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int lvl = maxlvl - 1; lvl >= 0; lvl--) { //for levels less than max, use level diff to make edge mask + for (int dir = 1; dir < 4; dir++) { + int Wlvl_L = WaveletCoeffs_L.level_W(lvl); + int Hlvl_L = WaveletCoeffs_L.level_H(lvl); + + float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); + + if (lvl == maxlvl - 1) { + float vari[4]; + int edge = 0; + ShrinkAllL(WaveletCoeffs_L, buffer, lvl, dir, noisevarlum, madL[lvl], NULL, edge ); + } else { + //simple wavelet shrinkage + float * sfave = buffer[0] + 32; + float * sfaved = buffer[2] + 96; + float * blurBuffer = buffer[1] + 64; + + float mad_Lr = madL[lvl][dir - 1]; + + float levelFactor = mad_Lr * 5.f / (lvl + 1); #ifdef __SSE2__ - __m128 mad_Lv; - __m128 ninev = _mm_set1_ps( 9.0f ); - __m128 epsv = _mm_set1_ps(eps); - __m128 mag_Lv; - __m128 levelFactorv = _mm_set1_ps(levelFactor); - int coeffloc_L; - for (coeffloc_L=0; coeffloc_L=0;i--) - if(buffer[i] != NULL) - delete [] buffer[i]; + __m128 sfavev; + __m128 sf_Lv; -} - return (!memoryAllocationFailed); + for (coeffloc_L = 0; coeffloc_L < Hlvl_L * Wlvl_L - 3; coeffloc_L += 4) { + sfavev = LVFU(sfaved[coeffloc_L]); + sf_Lv = LVFU(sfave[coeffloc_L]); + _mm_storeu_ps(&WavCoeffs_L[dir][coeffloc_L], LVFU(WavCoeffs_L[dir][coeffloc_L]) * (SQRV(sfavev) + SQRV(sf_Lv)) / (sfavev + sf_Lv + epsv)); + //use smoothed shrinkage unless local shrinkage is much less + } + + // few remaining pixels + for (; coeffloc_L < Hlvl_L * Wlvl_L; coeffloc_L++) { + float sf_L = sfave[coeffloc_L]; + //use smoothed shrinkage unless local shrinkage is much less + WavCoeffs_L[dir][coeffloc_L] *= (SQR(sfaved[coeffloc_L]) + SQR(sf_L)) / (sfaved[coeffloc_L] + sf_L + eps); + }//now luminance coeffs are denoised + +#else + + for (int i = 0; i < Hlvl_L; i++) + for (int j = 0; j < Wlvl_L; j++) { + int coeffloc_L = i * Wlvl_L + j; + float sf_L = sfave[coeffloc_L]; + //use smoothed shrinkage unless local shrinkage is much less + WavCoeffs_L[dir][coeffloc_L] *= (SQR(sfaved[coeffloc_L]) + SQR(sf_L)) / (sfaved[coeffloc_L] + sf_L + eps); + }//now luminance coeffs are denoised + +#endif + } + } + } + } + + for(int i = 2; i >= 0; i--) + if(buffer[i] != NULL) { + delete [] buffer[i]; + } + + } + return (!memoryAllocationFailed); } -SSEFUNCTION bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, - float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb) - { - int maxlvl = WaveletCoeffs_L.maxlevel(); - if(autoch && noisevar_ab <=0.001f) noisevar_ab=0.02f; - - float madab[8][3]; - - int maxWL = 0, maxHL = 0; - for (int lvl=0; lvl maxWL) - maxWL = WaveletCoeffs_L.level_W(lvl); - if(WaveletCoeffs_L.level_H(lvl) > maxHL) - maxHL = WaveletCoeffs_L.level_H(lvl); - } - bool memoryAllocationFailed = false; -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif +SSEFUNCTION bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, + float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb) { - float *buffer[3]; - buffer[0] = new (std::nothrow) float[maxWL*maxHL+32]; - buffer[1] = new (std::nothrow) float[maxWL*maxHL+64]; - buffer[2] = new (std::nothrow) float[maxWL*maxHL+96]; - if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL) { - memoryAllocationFailed = true; - } - - if(!memoryAllocationFailed) { - + int maxlvl = WaveletCoeffs_L.maxlevel(); + + if(autoch && noisevar_ab <= 0.001f) { + noisevar_ab = 0.02f; + } + + float madab[8][3]; + + int maxWL = 0, maxHL = 0; + + for (int lvl = 0; lvl < maxlvl; lvl++) { + if(WaveletCoeffs_L.level_W(lvl) > maxWL) { + maxWL = WaveletCoeffs_L.level_W(lvl); + } + + if(WaveletCoeffs_L.level_H(lvl) > maxHL) { + maxHL = WaveletCoeffs_L.level_H(lvl); + } + } + + bool memoryAllocationFailed = false; +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) +#endif + { + float *buffer[3]; + buffer[0] = new (std::nothrow) float[maxWL * maxHL + 32]; + buffer[1] = new (std::nothrow) float[maxWL * maxHL + 64]; + buffer[2] = new (std::nothrow) float[maxWL * maxHL + 96]; + + if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL) { + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) { + #ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) + #pragma omp for schedule(dynamic) collapse(2) #endif - for (int lvl=0; lvl=0; lvl--) {//for levels less than max, use level diff to make edge mask - for (int dir=1; dir<4; dir++) { - int Wlvl_ab = WaveletCoeffs_ab.level_W(lvl); - int Hlvl_ab = WaveletCoeffs_ab.level_H(lvl); - float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); - float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); - if (lvl==maxlvl-1) { - ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], madab[lvl], true); - } else { - //simple wavelet shrinkage + for (int lvl = maxlvl - 1; lvl >= 0; lvl--) { //for levels less than max, use level diff to make edge mask + for (int dir = 1; dir < 4; dir++) { + int Wlvl_ab = WaveletCoeffs_ab.level_W(lvl); + int Hlvl_ab = WaveletCoeffs_ab.level_H(lvl); - float mad_Lr = madL[lvl][dir-1]; - float mad_abr = useNoiseCCurve ? noisevar_ab*madab[lvl][dir-1] : SQR(noisevar_ab)*madab[lvl][dir-1]; + float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); + float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); + + if (lvl == maxlvl - 1) { + ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl], madab[lvl], true); + } else { + //simple wavelet shrinkage + + float mad_Lr = madL[lvl][dir - 1]; + float mad_abr = useNoiseCCurve ? noisevar_ab * madab[lvl][dir - 1] : SQR(noisevar_ab) * madab[lvl][dir - 1]; + + if (noisevar_ab > 0.001f) { - if (noisevar_ab>0.001f) { - #ifdef __SSE2__ - __m128 onev = _mm_set1_ps(1.f); - __m128 mad_abrv = _mm_set1_ps(mad_abr); - __m128 rmad_Lm9v = onev / _mm_set1_ps(mad_Lr * 9.f); - __m128 mad_abv; - __m128 mag_Lv, mag_abv; - __m128 tempabv; - int coeffloc_ab; - for (coeffloc_ab=0; coeffloc_ab=0;i--) - if(buffer[i] != NULL) - delete [] buffer[i]; + } + } + } + } + for(int i = 2; i >= 0; i--) + if(buffer[i] != NULL) { + delete [] buffer[i]; + } + + } + return (!memoryAllocationFailed); } - return (!memoryAllocationFailed); - } - bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge)//mod JD +bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge)//mod JD - { - - int maxlvl = min(WaveletCoeffs_L.maxlevel(),5); - if(edge==1) maxlvl=4;//for refine denoise edge wavelet - int maxWL = 0, maxHL = 0; - for (int lvl=0; lvl maxWL) - maxWL = WaveletCoeffs_L.level_W(lvl); - if(WaveletCoeffs_L.level_H(lvl) > maxHL) - maxHL = WaveletCoeffs_L.level_H(lvl); - } - bool memoryAllocationFailed = false; -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif { - float *buffer[4]; - buffer[0] = new (std::nothrow) float[maxWL*maxHL+32]; - buffer[1] = new (std::nothrow) float[maxWL*maxHL+64]; - buffer[2] = new (std::nothrow) float[maxWL*maxHL+96]; - buffer[3] = new (std::nothrow) float[maxWL*maxHL+128]; - if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL || buffer[3] == NULL) { - memoryAllocationFailed = true; - } - - if(!memoryAllocationFailed) { + + int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5); + + if(edge == 1) { + maxlvl = 4; //for refine denoise edge wavelet + } + + int maxWL = 0, maxHL = 0; + + for (int lvl = 0; lvl < maxlvl; lvl++) { + if(WaveletCoeffs_L.level_W(lvl) > maxWL) { + maxWL = WaveletCoeffs_L.level_W(lvl); + } + + if(WaveletCoeffs_L.level_H(lvl) > maxHL) { + maxHL = WaveletCoeffs_L.level_H(lvl); + } + } + + bool memoryAllocationFailed = false; #ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) + #pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) #endif - for (int lvl=0; lvl=0;i--) - if(buffer[i] != NULL) - delete [] buffer[i]; + { + float *buffer[4]; + buffer[0] = new (std::nothrow) float[maxWL * maxHL + 32]; + buffer[1] = new (std::nothrow) float[maxWL * maxHL + 64]; + buffer[2] = new (std::nothrow) float[maxWL * maxHL + 96]; + buffer[3] = new (std::nothrow) float[maxWL * maxHL + 128]; + + if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL || buffer[3] == NULL) { + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) { +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int lvl = 0; lvl < maxlvl; lvl++) { + for (int dir = 1; dir < 4; dir++) { + ShrinkAllL(WaveletCoeffs_L, buffer, lvl, dir, noisevarlum, madL[lvl], vari, edge); + } + } + } + + for(int i = 3; i >= 0; i--) + if(buffer[i] != NULL) { + delete [] buffer[i]; + } + } + return (!memoryAllocationFailed); } - return (!memoryAllocationFailed); - } - - - bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, - float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)//mod JD - { - int maxlvl = WaveletCoeffs_L.maxlevel(); - int maxWL = 0, maxHL = 0; - for (int lvl=0; lvl maxWL) - maxWL = WaveletCoeffs_L.level_W(lvl); - if(WaveletCoeffs_L.level_H(lvl) > maxHL) - maxHL = WaveletCoeffs_L.level_H(lvl); - } - bool memoryAllocationFailed = false; -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) -#endif +bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, + float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)//mod JD + { - float *buffer[3]; - buffer[0] = new (std::nothrow) float[maxWL*maxHL+32]; - buffer[1] = new (std::nothrow) float[maxWL*maxHL+64]; - buffer[2] = new (std::nothrow) float[maxWL*maxHL+96]; - if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL) { - memoryAllocationFailed = true; - } - - if(!memoryAllocationFailed) { + + int maxlvl = WaveletCoeffs_L.maxlevel(); + int maxWL = 0, maxHL = 0; + + for (int lvl = 0; lvl < maxlvl; lvl++) { + if(WaveletCoeffs_L.level_W(lvl) > maxWL) { + maxWL = WaveletCoeffs_L.level_W(lvl); + } + + if(WaveletCoeffs_L.level_H(lvl) > maxHL) { + maxHL = WaveletCoeffs_L.level_H(lvl); + } + } + + bool memoryAllocationFailed = false; #ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) + #pragma omp parallel num_threads(denoiseNestedLevels) if(denoiseNestedLevels>1) #endif - for (int lvl=0; lvl=0;i--) - if(buffer[i] != NULL) - delete [] buffer[i]; + { + float *buffer[3]; + buffer[0] = new (std::nothrow) float[maxWL * maxHL + 32]; + buffer[1] = new (std::nothrow) float[maxWL * maxHL + 64]; + buffer[2] = new (std::nothrow) float[maxWL * maxHL + 96]; + + if(buffer[0] == NULL || buffer[1] == NULL || buffer[2] == NULL) { + memoryAllocationFailed = true; + } + + if(!memoryAllocationFailed) { +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int lvl = 0; lvl < maxlvl; lvl++) { + for (int dir = 1; dir < 4; dir++) { + ShrinkAllAB(WaveletCoeffs_L, WaveletCoeffs_ab, buffer, lvl, dir, noisevarchrom, noisevar_ab, useNoiseCCurve, autoch, denoiseMethodRgb, madL[lvl]); + } + } + } + + for(int i = 2; i >= 0; i--) + if(buffer[i] != NULL) { + delete [] buffer[i]; + } + } + return (!memoryAllocationFailed); } - return (!memoryAllocationFailed); - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SSEFUNCTION void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, - float *noisevarlum, float * madL, float * vari, int edge ) +SSEFUNCTION void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, + float *noisevarlum, float * madL, float * vari, int edge ) - { - //simple wavelet shrinkage - const float eps = 0.01f; - - float * sfave = buffer[0]+32; - float * sfaved = buffer[1]+64; - float * blurBuffer = buffer[2]+96; +{ + //simple wavelet shrinkage + const float eps = 0.01f; - int W_L = WaveletCoeffs_L.level_W(level); - int H_L = WaveletCoeffs_L.level_H(level); + float * sfave = buffer[0] + 32; + float * sfaved = buffer[1] + 64; + float * blurBuffer = buffer[2] + 96; - float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(level); -// printf("OK lev=%d\n",level); - float mad_L = madL[dir-1] ; - if(edge==1) { - noisevarlum = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer - for (int i=0; i0.001f) { - madab = useNoiseCCurve ? madab : madab * noisevar_ab; #ifdef __SSE2__ - __m128 onev = _mm_set1_ps(1.f); - __m128 mad_abrv = _mm_set1_ps(madab); + __m128 sfv; - __m128 rmadLm9v = onev / _mm_set1_ps(mad_L * 9.f); - __m128 mad_abv ; - __m128 mag_Lv, mag_abv; - int coeffloc_ab; - for (coeffloc_ab=0; coeffloc_ab 0.001f) { + madab = useNoiseCCurve ? madab : madab * noisevar_ab; #ifdef __SSE2__ - __m128 epsv = _mm_set1_ps(eps); - __m128 sfabv; - __m128 sfaveabv; - for (coeffloc_ab=0; coeffloc_ab -0.8f && noisevarhue[i][j] < 2.0f && noisevarchrom[i][j] > 10000.f) {//saturated red yellow - red_yel += noisevarchrom[i][j]; - nry++; - } - if(noisevarhue[i][j] > 0.f && noisevarhue[i][j] < 1.6f && noisevarchrom[i][j] < 10000.f) {//skin - skin_c += noisevarchrom[i][j]; - nsk++; - } - lume += noisevarlum[i][j]; - nL++; - devL += SQR(noisevarlum[i][j]-(lume/nL)); - } - } - if(nc>0) { - chromina=chro/nc; - sigma=sqrt(dev/nc); - nsknc=(float)nsk/(float)nc; - } else { - nsknc=(float)nsk; - } - if(nL>0) { - lumema=lume/nL; - sigma_L=sqrt(devL/nL); - } - if(nry>0) - redyel=red_yel/nry; - if(nsk>0) - skinc=skin_c/nsk; - } + //use smoothed shrinkage unless local shrinkage is much less + _mm_storeu_ps( &WavCoeffs_ab[dir][coeffloc_ab], LVFU(WavCoeffs_ab[dir][coeffloc_ab]) * (SQRV(sfaveabv) + SQRV(sfabv)) / (sfaveabv + sfabv + epsv)); + } - const float reduc = (schoice == 2) ? (float) settings->nrhigh : 1.f; - for (int dir=1; dir<4; dir++) { - float mada, madb; - if(!denoiseMethodRgb) - mada = SQR(Mad(WavCoeffs_a[dir], W_ab*H_ab)); - else - mada = SQR(MadRgb(WavCoeffs_a[dir], W_ab*H_ab)); - chred += mada; - if(mada > maxchred) - maxchred = mada; - if(mada < minchred) - minchred = mada; - maxredaut = sqrt(reduc*maxchred); - minredaut = sqrt(reduc*minchred); + // few remaining pixels + for (; coeffloc_ab < H_ab * W_ab; coeffloc_ab++) { + //modification Jacques feb 2013 + float sfab = sfaveab[coeffloc_ab]; - if(!denoiseMethodRgb) - madb = SQR(Mad(WavCoeffs_b[dir], W_ab*H_ab)); - else - madb = SQR(MadRgb(WavCoeffs_b[dir], W_ab*H_ab)); - chblue += madb; - if(madb > maxchblue) - maxchblue = madb; - if(madb < minchblue) - minchblue = madb; - maxblueaut = sqrt(reduc*maxchblue); - minblueaut = sqrt(reduc*minchblue); - - chau += (mada+madb); - nb++; - //here evaluation of automatic - chaut = sqrt(reduc*chau/(nb + nb)); - redaut = sqrt(reduc*chred/nb); - blueaut = sqrt(reduc*chblue/nb); - Nb = nb; - } + //use smoothed shrinkage unless local shrinkage is much less + WavCoeffs_ab[dir][coeffloc_ab] *= (SQR(sfaveabd[coeffloc_ab]) + SQR(sfab)) / (sfaveabd[coeffloc_ab] + sfab + eps); + }//now chrominance coefficients are denoised + +#else + + for (int i = 0; i < H_ab; i++) { + for (int j = 0; j < W_ab; j++) { + int coeffloc_ab = i * W_ab + j; + float sfab = sfaveab[coeffloc_ab]; + + //use smoothed shrinkage unless local shrinkage is much less + WavCoeffs_ab[dir][coeffloc_ab] *= (SQR(sfaveabd[coeffloc_ab]) + SQR(sfab)) / (sfaveabd[coeffloc_ab] + sfab + eps); + }//now chrominance coefficients are denoised + } + +#endif + } + +} + +SSEFUNCTION void ImProcFunctions::ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b, int level, + int W_ab, int H_ab, int skip_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, + float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, bool autoch, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, + float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread) +{ + + //simple wavelet shrinkage + if(lvl == 1) { //only one time + float chro = 0.f; + float dev = 0.f; + float devL = 0.f; + int nc = 0; + int nL = 0; + int nry = 0; + float lume = 0.f; + float red_yel = 0.f; + float skin_c = 0.f; + int nsk = 0; + + for (int i = 0; i < H_ab; i++) { + for (int j = 0; j < W_ab; j++) { + chro += noisevarchrom[i][j]; + nc++; + dev += SQR(noisevarchrom[i][j] - (chro / nc)); + + if(noisevarhue[i][j] > -0.8f && noisevarhue[i][j] < 2.0f && noisevarchrom[i][j] > 10000.f) {//saturated red yellow + red_yel += noisevarchrom[i][j]; + nry++; + } + + if(noisevarhue[i][j] > 0.f && noisevarhue[i][j] < 1.6f && noisevarchrom[i][j] < 10000.f) {//skin + skin_c += noisevarchrom[i][j]; + nsk++; + } + + lume += noisevarlum[i][j]; + nL++; + devL += SQR(noisevarlum[i][j] - (lume / nL)); + } + } + + if(nc > 0) { + chromina = chro / nc; + sigma = sqrt(dev / nc); + nsknc = (float)nsk / (float)nc; + } else { + nsknc = (float)nsk; + } + + if(nL > 0) { + lumema = lume / nL; + sigma_L = sqrt(devL / nL); + } + + if(nry > 0) { + redyel = red_yel / nry; + } + + if(nsk > 0) { + skinc = skin_c / nsk; + } + } + + const float reduc = (schoice == 2) ? (float) settings->nrhigh : 1.f; + + for (int dir = 1; dir < 4; dir++) { + float mada, madb; + + if(!denoiseMethodRgb) { + mada = SQR(Mad(WavCoeffs_a[dir], W_ab * H_ab)); + } else { + mada = SQR(MadRgb(WavCoeffs_a[dir], W_ab * H_ab)); + } + + chred += mada; + + if(mada > maxchred) { + maxchred = mada; + } + + if(mada < minchred) { + minchred = mada; + } + + maxredaut = sqrt(reduc * maxchred); + minredaut = sqrt(reduc * minchred); + + if(!denoiseMethodRgb) { + madb = SQR(Mad(WavCoeffs_b[dir], W_ab * H_ab)); + } else { + madb = SQR(MadRgb(WavCoeffs_b[dir], W_ab * H_ab)); + } + + chblue += madb; + + if(madb > maxchblue) { + maxchblue = madb; + } + + if(madb < minchblue) { + minchblue = madb; + } + + maxblueaut = sqrt(reduc * maxchblue); + minblueaut = sqrt(reduc * minchblue); + + chau += (mada + madb); + nb++; + //here evaluation of automatic + chaut = sqrt(reduc * chau / (nb + nb)); + redaut = sqrt(reduc * chred / nb); + blueaut = sqrt(reduc * chblue / nb); + Nb = nb; + } } void ImProcFunctions::WaveletDenoiseAll_info(int levwav, wavelet_decomposition &WaveletCoeffs_a, - wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut,int schoice, bool autoch, - float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread ){ + wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, bool autoch, + float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread ) +{ - int maxlvl = levwav; - for (int lvl=0; lvl TIF and JPG - if(gam <1.9f) - gam=1.f - (1.9f-gam)/3.f;//minimum gamma 0.7 - else if (gam >= 1.9f && gam <= 3.f) - gam=(1.4f/1.1f)*gam - 1.41818f; - } - gamslope = exp(log((double)gamthresh)/gam)/gamthresh; - bool denoiseMethodRgb = (dnparams.dmethod=="RGB"); - if(denoiseMethodRgb) { - for (int i=0; i<65536; i++) { - gamcurve[i] = (Color::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) * 32768.0f; - } - } - else { - for (int i=0; i<65536; i++) { - gamcurve[i] = (Color::gamman((double)i/65535.0,gam)) * 32768.0f; - } - } + ShrinkAll_info(WavCoeffs_a, WavCoeffs_b, lvl, Wlvl_ab, Hlvl_ab, + skip_ab, noisevarlum, noisevarchrom, noisevarhue, width, height, noisevar_abr, noisevar_abb, noi, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, + autoch, schoice, lvl, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, maxchred, maxchblue, minchred, minchblue, nb, chau, chred, chblue, denoiseMethodRgb, multiThread ); + + } } -void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc) { +void ImProcFunctions::RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope) +{ + gam = dnparams.gamma; + gamthresh = 0.001f; - float reducdelta=1.f; - if (params->dirpyrDenoise.smethod == "shalbi") - reducdelta = (float)settings->nrhigh; + if(!isRAW) {//reduce gamma under 1 for Lab mode ==> TIF and JPG + if(gam < 1.9f) { + gam = 1.f - (1.9f - gam) / 3.f; //minimum gamma 0.7 + } else if (gam >= 1.9f && gam <= 3.f) { + gam = (1.4f / 1.1f) * gam - 1.41818f; + } + } - chaut = (chaut*Nb-maxmax)/(Nb-1);//suppress maximum for chaut calcul - if ((redyel > 5000.f || skinc > 1000.f) && nsknc < 0.4f && chromina > 3000.f) - chaut *= 0.45f;//reduct action in red zone, except skin for high / med chroma - else if ((redyel>12000.f || skinc > 1200.f) && nsknc < 0.3f && chromina > 3000.f) - chaut *= 0.3f; - - if (mode==0 || mode==2) {//Preview or Auto multizone - if (chromina > 10000.f) chaut *= 0.7f;//decrease action for high chroma (visible noise) - else if (chromina > 6000.f) chaut *= 0.9f; - else if (chromina < 3000.f) chaut *= 1.2f;//increase action in low chroma==> 1.2 /==>2.0 ==> curve CC - else if (chromina < 2000.f) chaut *= 1.5f;//increase action in low chroma==> 1.5 / ==>2.7 - - if (lumema < 2500.f) chaut *= 1.3f;//increase action for low light - else if (lumema < 5000.f) chaut *= 1.2f; - else if (lumema > 20000.f) chaut *= 0.9f;//decrease for high light - } else if (mode == 1) {//auto ==> less coefficient because interaction - if (chromina > 10000.f) chaut *= 0.8f;//decrease action for high chroma (visible noise) - else if (chromina > 6000.f) chaut *= 0.9f; - else if (chromina < 3000.f) chaut *= 1.5f;//increase action in low chroma - else if (chromina < 2000.f) chaut *= 2.2f;//increase action in low chroma - if (lumema < 2500.f) chaut *= 1.2f;//increase action for low light - else if (lumema < 5000.f) chaut *= 1.1f; - else if (lumema > 20000.f) chaut *= 0.9f;//decrease for high light - } + gamslope = exp(log((double)gamthresh) / gam) / gamthresh; + bool denoiseMethodRgb = (dnparams.dmethod == "RGB"); - if(levaut==0) {//Low denoise - if(chaut > 300.f) - chaut = 0.714286f*chaut + 85.71428f; - } - - delta = maxmax-chaut; - delta *= reducdelta; - - if (lissage==1 || lissage==2) { - if (chaut < 200.f && delta < 200.f ) delta *= 0.95f; - else if (chaut < 200.f && delta < 400.f ) delta *= 0.5f; - else if (chaut < 200.f && delta >= 400.f ) delta = 200.f; - else if (chaut < 400.f && delta < 400.f ) delta *= 0.4f; - else if (chaut < 400.f && delta >= 400.f ) delta = 120.f; - else if (chaut < 550.f) delta *= 0.15f; - else if (chaut < 650.f) delta *= 0.1f; - else if (chaut >= 650.f) delta *= 0.07f; - if (mode==0 || mode==2) {//Preview or Auto multizone - if (chromina < 6000.f) delta *= 1.4f;//increase maxi - if (lumema < 5000.f) delta *= 1.4f; - } - else if (mode==1) {//Auto - if (chromina < 6000.f) delta *= 1.2f;//increase maxi - if (lumema < 5000.f) delta *= 1.2f; - } - } - if (lissage==0) { - if (chaut < 200.f && delta < 200.f ) delta *= 0.95f; - else if (chaut < 200.f && delta < 400.f ) delta *= 0.7f; - else if (chaut < 200.f && delta >= 400.f ) delta = 280.f; - else if (chaut < 400.f && delta < 400.f ) delta *= 0.6f; - else if (chaut < 400.f && delta >= 400.f ) delta = 200.f; - else if (chaut < 550.f) delta *= 0.3f; - else if (chaut < 650.f) delta *= 0.2f; - else if (chaut >= 650.f) delta *= 0.15f; - if (mode==0 || mode==2) {//Preview or Auto multizone - if (chromina < 6000.f) delta *= 1.4f;//increase maxi - if (lumema < 5000.f) delta *= 1.4f; - } - else if (mode==1) {//Auto - if (chromina < 6000.f) delta *= 1.2f;//increase maxi - if (lumema < 5000.f) delta *= 1.2f; - } - } - + if(denoiseMethodRgb) { + for (int i = 0; i < 65536; i++) { + gamcurve[i] = (Color::gamma((double)i / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) * 32768.0f; + } + } else { + for (int i = 0; i < 65536; i++) { + gamcurve[i] = (Color::gamman((double)i / 65535.0, gam)) * 32768.0f; + } + } } - + +void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc) +{ + + float reducdelta = 1.f; + + if (params->dirpyrDenoise.smethod == "shalbi") { + reducdelta = (float)settings->nrhigh; + } + + chaut = (chaut * Nb - maxmax) / (Nb - 1); //suppress maximum for chaut calcul + + if ((redyel > 5000.f || skinc > 1000.f) && nsknc < 0.4f && chromina > 3000.f) { + chaut *= 0.45f; //reduct action in red zone, except skin for high / med chroma + } else if ((redyel > 12000.f || skinc > 1200.f) && nsknc < 0.3f && chromina > 3000.f) { + chaut *= 0.3f; + } + + if (mode == 0 || mode == 2) { //Preview or Auto multizone + if (chromina > 10000.f) { + chaut *= 0.7f; //decrease action for high chroma (visible noise) + } else if (chromina > 6000.f) { + chaut *= 0.9f; + } else if (chromina < 3000.f) { + chaut *= 1.2f; //increase action in low chroma==> 1.2 /==>2.0 ==> curve CC + } else if (chromina < 2000.f) { + chaut *= 1.5f; //increase action in low chroma==> 1.5 / ==>2.7 + } + + if (lumema < 2500.f) { + chaut *= 1.3f; //increase action for low light + } else if (lumema < 5000.f) { + chaut *= 1.2f; + } else if (lumema > 20000.f) { + chaut *= 0.9f; //decrease for high light + } + } else if (mode == 1) {//auto ==> less coefficient because interaction + if (chromina > 10000.f) { + chaut *= 0.8f; //decrease action for high chroma (visible noise) + } else if (chromina > 6000.f) { + chaut *= 0.9f; + } else if (chromina < 3000.f) { + chaut *= 1.5f; //increase action in low chroma + } else if (chromina < 2000.f) { + chaut *= 2.2f; //increase action in low chroma + } + + if (lumema < 2500.f) { + chaut *= 1.2f; //increase action for low light + } else if (lumema < 5000.f) { + chaut *= 1.1f; + } else if (lumema > 20000.f) { + chaut *= 0.9f; //decrease for high light + } + } + + if(levaut == 0) { //Low denoise + if(chaut > 300.f) { + chaut = 0.714286f * chaut + 85.71428f; + } + } + + delta = maxmax - chaut; + delta *= reducdelta; + + if (lissage == 1 || lissage == 2) { + if (chaut < 200.f && delta < 200.f ) { + delta *= 0.95f; + } else if (chaut < 200.f && delta < 400.f ) { + delta *= 0.5f; + } else if (chaut < 200.f && delta >= 400.f ) { + delta = 200.f; + } else if (chaut < 400.f && delta < 400.f ) { + delta *= 0.4f; + } else if (chaut < 400.f && delta >= 400.f ) { + delta = 120.f; + } else if (chaut < 550.f) { + delta *= 0.15f; + } else if (chaut < 650.f) { + delta *= 0.1f; + } else if (chaut >= 650.f) { + delta *= 0.07f; + } + + if (mode == 0 || mode == 2) { //Preview or Auto multizone + if (chromina < 6000.f) { + delta *= 1.4f; //increase maxi + } + + if (lumema < 5000.f) { + delta *= 1.4f; + } + } else if (mode == 1) { //Auto + if (chromina < 6000.f) { + delta *= 1.2f; //increase maxi + } + + if (lumema < 5000.f) { + delta *= 1.2f; + } + } + } + + if (lissage == 0) { + if (chaut < 200.f && delta < 200.f ) { + delta *= 0.95f; + } else if (chaut < 200.f && delta < 400.f ) { + delta *= 0.7f; + } else if (chaut < 200.f && delta >= 400.f ) { + delta = 280.f; + } else if (chaut < 400.f && delta < 400.f ) { + delta *= 0.6f; + } else if (chaut < 400.f && delta >= 400.f ) { + delta = 200.f; + } else if (chaut < 550.f) { + delta *= 0.3f; + } else if (chaut < 650.f) { + delta *= 0.2f; + } else if (chaut >= 650.f) { + delta *= 0.15f; + } + + if (mode == 0 || mode == 2) { //Preview or Auto multizone + if (chromina < 6000.f) { + delta *= 1.4f; //increase maxi + } + + if (lumema < 5000.f) { + delta *= 1.4f; + } + } else if (mode == 1) { //Auto + if (chromina < 6000.f) { + delta *= 1.2f; //increase maxi + } + + if (lumema < 5000.f) { + delta *= 1.2f; + } + } + } + +} + SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread) { - if ((settings->leveldnautsimpl==1 && dnparams.Cmethod == "MAN") || (settings->leveldnautsimpl==0 && dnparams.C2method == "MANU")) { - //nothing to do - return; - } + if ((settings->leveldnautsimpl == 1 && dnparams.Cmethod == "MAN") || (settings->leveldnautsimpl == 0 && dnparams.C2method == "MANU")) { + //nothing to do + return; + } - int hei,wid; - float** lumcalc; - float** acalc; - float** bcalc; - hei=provicalc->height; - wid=provicalc->width; - TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); + int hei, wid; + float** lumcalc; + float** acalc; + float** bcalc; + hei = provicalc->height; + wid = provicalc->width; + TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); - const float wpi[3][3] = { - {static_cast(wprofi[0][0]),static_cast(wprofi[0][1]),static_cast(wprofi[0][2])}, - {static_cast(wprofi[1][0]),static_cast(wprofi[1][1]),static_cast(wprofi[1][2])}, - {static_cast(wprofi[2][0]),static_cast(wprofi[2][1]),static_cast(wprofi[2][2])} - }; + const float wpi[3][3] = { + {static_cast(wprofi[0][0]), static_cast(wprofi[0][1]), static_cast(wprofi[0][2])}, + {static_cast(wprofi[1][0]), static_cast(wprofi[1][1]), static_cast(wprofi[1][2])}, + {static_cast(wprofi[2][0]), static_cast(wprofi[2][1]), static_cast(wprofi[2][2])} + }; - lumcalc = new float*[hei]; - for (int i=0; ir(ii,jj); - float GL = provicalc->g(ii,jj); - float BL = provicalc->b(ii,jj); - // determine luminance for noisecurve - float XL,YL,ZL; - Color::rgbxyz(RL,GL,BL,XL,YL,ZL,wpi); - Color::XYZ2Lab(XL, YL, ZL, LLum, AAum, BBum); - lumcalc[ii][jj]=LLum; - acalc[ii][jj]=AAum; - bcalc[ii][jj]=BBum; - } - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + for(int ii = 0; ii < hei; ii++) { + for(int jj = 0; jj < wid; jj++) { + float LLum, AAum, BBum; + float RL = provicalc->r(ii, jj); + float GL = provicalc->g(ii, jj); + float BL = provicalc->b(ii, jj); + // determine luminance for noisecurve + float XL, YL, ZL; + Color::rgbxyz(RL, GL, BL, XL, YL, ZL, wpi); + Color::XYZ2Lab(XL, YL, ZL, LLum, AAum, BBum); + lumcalc[ii][jj] = LLum; + acalc[ii][jj] = AAum; + bcalc[ii][jj] = BBum; + } + } - const int imheight=src->height, imwidth=src->width; + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - bool denoiseMethodRgb = (dnparams.dmethod == "RGB"); + const int imheight = src->height, imwidth = src->width; - const float gain = pow (2.0f, float(expcomp)); - - int tilesize; - int overlap; - if(settings->leveldnti == 0) { - tilesize = 1024; - overlap = 128; - } - if(settings->leveldnti == 1) { - tilesize = 768; - overlap = 96; - } + bool denoiseMethodRgb = (dnparams.dmethod == "RGB"); - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + const float gain = pow (2.0f, float(expcomp)); - //always no Tiles - int kall=0; - Tile_calc (tilesize, overlap, kall, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + int tilesize; + int overlap; - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if(settings->leveldnti == 0) { + tilesize = 1024; + overlap = 128; + } - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); - 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])} - }; + if(settings->leveldnti == 1) { + tilesize = 768; + overlap = 96; + } - float chau=0.f; - float chred=0.f; - float chblue=0.f; - float maxchred=0.f; - float maxchblue=0.f; - float minchred =100000000.f; - float minchblue=100000000.f; - int nb=0; - int comptlevel=0; + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - // To avoid branches in loops we access the gammatabs by pointers - LUTf *denoiseigamtab; - switch(settings->denoiselabgamma) { - case 0: denoiseigamtab = &(Color::igammatab_26_11); - break; - case 1: denoiseigamtab = &(Color::igammatab_4); - break; - default: denoiseigamtab = &(Color::igammatab_55); - break; - } + //always no Tiles + int kall = 0; + Tile_calc (tilesize, overlap, kall, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + 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])} + }; + + float chau = 0.f; + float chred = 0.f; + float chblue = 0.f; + float maxchred = 0.f; + float maxchblue = 0.f; + float minchred = 100000000.f; + float minchblue = 100000000.f; + int nb = 0; + int comptlevel = 0; + + // To avoid branches in loops we access the gammatabs by pointers + LUTf *denoiseigamtab; + + switch(settings->denoiselabgamma) { + case 0: + denoiseigamtab = &(Color::igammatab_26_11); + break; + + case 1: + denoiseigamtab = &(Color::igammatab_4); + break; + + default: + denoiseigamtab = &(Color::igammatab_55); + break; + } - for (int tiletop=0; tiletop 0.) - intermred = (dnparams.redchro/10.); - else - intermred = (float) dnparams.redchro/7.0;//increase slower than linear for more sensit - if(dnparams.bluechro > 0.) - intermblue =(dnparams.bluechro/10.); - else - intermblue = (float) dnparams.bluechro/7.0;//increase slower than linear for more sensit - realred = interm_med + intermred; - if (realred < 0.f) - realred = 0.001f; - realblue = interm_med + intermblue; - if (realblue < 0.f) - realblue = 0.001f; - //TODO: implement using AlignedBufferMP - //fill tile from image; convert RGB to "luma/chroma" + int tileright = MIN(imwidth, tileleft + tilewidth); + int tilebottom = MIN(imheight, tiletop + tileheight); + int width = tileright - tileleft; + int height = tilebottom - tiletop; + LabImage * labdn = new LabImage(width, height); + float** noisevarlum = new float*[(height + 1) / 2]; - if (isRAW) {//image is raw; use channel differences for chroma channels + for (int i = 0; i < (height + 1) / 2; i++) { + noisevarlum[i] = new float[(width + 1) / 2]; + } + + float** noisevarchrom = new float*[(height + 1) / 2]; + + for (int i = 0; i < (height + 1) / 2; i++) { + noisevarchrom[i] = new float[(width + 1) / 2]; + } + + float** noisevarhue = new float*[(height + 1) / 2]; + + for (int i = 0; i < (height + 1) / 2; i++) { + noisevarhue[i] = new float[(width + 1) / 2]; + } + + // init luma noisevarL + float noisevarab_b, noisevarab_r; + + float realred, realblue; + float interm_med = (float) dnparams.chroma / 10.0; + float intermred, intermblue; + + if(dnparams.redchro > 0.) { + intermred = (dnparams.redchro / 10.); + } else { + intermred = (float) dnparams.redchro / 7.0; //increase slower than linear for more sensit + } + + if(dnparams.bluechro > 0.) { + intermblue = (dnparams.bluechro / 10.); + } else { + intermblue = (float) dnparams.bluechro / 7.0; //increase slower than linear for more sensit + } + + realred = interm_med + intermred; + + if (realred < 0.f) { + realred = 0.001f; + } + + realblue = interm_med + intermblue; + + if (realblue < 0.f) { + realblue = 0.001f; + } + + //TODO: implement using AlignedBufferMP + //fill tile from image; convert RGB to "luma/chroma" + + if (isRAW) {//image is raw; use channel differences for chroma channels #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for if(multiThread) + #pragma omp parallel for if(multiThread) #endif - for (int i=tiletop; i>1][j>>1]); - bNv = LVFU(bcalc[i>>1][j>>1]); - _mm_storeu_ps(&noisevarhue[i1>>1][j1>>1], xatan2f(bNv,aNv)); - _mm_storeu_ps(&noisevarchrom[i1>>1][j1>>1], _mm_max_ps(c100v,_mm_sqrt_ps(SQRV(aNv)+SQRV(bNv)))); - } - for (; j>1][j>>1]; - float bN = bcalc[i>>1][j>>1]; - float cN = sqrtf(SQR(aN)+SQR(bN)); - noisevarhue[i1>>1][j1>>1] = xatan2f(bN,aN); - if(cN < 100.f) - cN=100.f;//avoid divided by zero - noisevarchrom[i1>>1][j1>>1] = cN; - } + __m128 aNv, bNv; + __m128 c100v = _mm_set1_ps(100.f); + int j; + + for (j = tileleft; j < tileright - 7; j += 8) { + int j1 = j - tileleft; + aNv = LVFU(acalc[i >> 1][j >> 1]); + bNv = LVFU(bcalc[i >> 1][j >> 1]); + _mm_storeu_ps(&noisevarhue[i1 >> 1][j1 >> 1], xatan2f(bNv, aNv)); + _mm_storeu_ps(&noisevarchrom[i1 >> 1][j1 >> 1], _mm_max_ps(c100v, _mm_sqrt_ps(SQRV(aNv) + SQRV(bNv)))); + } + + for (; j < tileright; j += 2) { + int j1 = j - tileleft; + float aN = acalc[i >> 1][j >> 1]; + float bN = bcalc[i >> 1][j >> 1]; + float cN = sqrtf(SQR(aN) + SQR(bN)); + noisevarhue[i1 >> 1][j1 >> 1] = xatan2f(bN, aN); + + if(cN < 100.f) { + cN = 100.f; //avoid divided by zero + } + + noisevarchrom[i1 >> 1][j1 >> 1] = cN; + } + #else - for (int j=tileleft; j>1][j>>1]; - float bN = bcalc[i>>1][j>>1]; - float cN = sqrtf(SQR(aN)+SQR(bN)); - float hN = xatan2f(bN,aN); - if(cN < 100.f) - cN = 100.f;//avoid divided by zero - noisevarchrom[i1>>1][j1>>1] = cN; - noisevarhue[i1>>1][j1>>1] = hN; - } + + for (int j = tileleft; j < tileright; j += 2) { + int j1 = j - tileleft; + float aN = acalc[i >> 1][j >> 1]; + float bN = bcalc[i >> 1][j >> 1]; + float cN = sqrtf(SQR(aN) + SQR(bN)); + float hN = xatan2f(bN, aN); + + if(cN < 100.f) { + cN = 100.f; //avoid divided by zero + } + + noisevarchrom[i1 >> 1][j1 >> 1] = cN; + noisevarhue[i1 >> 1][j1 >> 1] = hN; + } + #endif - } -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for if(multiThread) -#endif - for (int i=tiletop; i>1][j>>1]; - Llum = Llum < 2.f ? 2.f : Llum; //avoid divided by zero ? - Llum = Llum > 32768.f ? 32768.f : Llum; // not strictly necessary - noisevarlum[i1>>1][j1>>1]= Llum; - } - } - if (!denoiseMethodRgb){//lab mode, modification Jacques feb 2013 and july 2014 + } #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for if(multiThread) + #pragma omp parallel for if(multiThread) #endif - for (int i=tiletop; ir(i,j); - float G_ = gain*src->g(i,j); - float B_ = gain*src->b(i,j); - R_ = (*denoiseigamtab)[R_]; - G_ = (*denoiseigamtab)[G_]; - B_ = (*denoiseigamtab)[B_]; + for (int i = tiletop; i < tilebottom; i += 2) { + int i1 = i - tiletop; - //apply gamma noise standard (slider) - R_ = R_<65535.0f ? gamcurve[R_] : (Color::gamman((double)R_/65535.0, gam)*32768.0f); - G_ = G_<65535.0f ? gamcurve[G_] : (Color::gamman((double)G_/65535.0, gam)*32768.0f); - B_ = B_<65535.0f ? gamcurve[B_] : (Color::gamman((double)B_/65535.0, gam)*32768.0f); - //true conversion xyz=>Lab - float X,Y,Z; - Color::rgbxyz(R_,G_,B_,X,Y,Z,wp); + for (int j = tileleft; j < tileright; j += 2) { + int j1 = j - tileleft; + float Llum = lumcalc[i >> 1][j >> 1]; + Llum = Llum < 2.f ? 2.f : Llum; //avoid divided by zero ? + Llum = Llum > 32768.f ? 32768.f : Llum; // not strictly necessary + noisevarlum[i1 >> 1][j1 >> 1] = Llum; + } + } - //convert to Lab - float L,a,b; - Color::XYZ2Lab(X, Y, Z, L, a, b); - - labdn->a[i1][j1] = a; - labdn->b[i1][j1] = b; - } - } - } - else {//RGB mode - - for (int i=tiletop/*, i1=0*/; ir(i,j); - float Y = gain*src->g(i,j); - float Z = gain*src->b(i,j); - - X = X<65535.0f ? gamcurve[X] : (Color::gamma((double)X/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); - Y = Y<65535.0f ? gamcurve[Y] : (Color::gamma((double)Y/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); - Z = Z<65535.0f ? gamcurve[Z] : (Color::gamma((double)Z/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); - - labdn->a[i1][j1] = (X-Y); - labdn->b[i1][j1] = (Y-Z); - } - } - } - - } else {//image is not raw; use Lab parametrization - for (int i=tiletop/*, i1=0*/; ir(i,j) ;//for luminance denoise curve - float gLum=src->g(i,j) ; - float bLum=src->b(i,j) ; - - //use gamma sRGB, not good if TIF (JPG) Output profil not with gamma sRGB (eg : gamma =1.0, or 1.8...) - //very difficult to solve ! - // solution ==> save TIF with gamma sRGB and re open - float rtmp = Color::igammatab_srgb[ src->r(i,j) ]; - float gtmp = Color::igammatab_srgb[ src->g(i,j) ]; - float btmp = Color::igammatab_srgb[ src->b(i,j) ]; - //modification Jacques feb 2013 - // gamma slider different from raw - rtmp = rtmp<65535.0f ? gamcurve[rtmp] : (Color::gamman((double)rtmp/65535.0, gam)*32768.0f); - gtmp = gtmp<65535.0f ? gamcurve[gtmp] : (Color::gamman((double)gtmp/65535.0, gam)*32768.0f); - btmp = btmp<65535.0f ? gamcurve[btmp] : (Color::gamman((double)btmp/65535.0, gam)*32768.0f); - - float X,Y,Z; - Color::rgbxyz(rtmp,gtmp,btmp,X,Y,Z,wp); - - //convert Lab - Color::XYZ2Lab(X, Y, Z, L, a, b); - - if(((i1|j1)&1) == 0) { - float Llum,alum,blum; - float XL,YL,ZL; - Color::rgbxyz(rLum,gLum,bLum,XL,YL,ZL,wp); - Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum); - float kN=Llum; - if(kN<2.f) kN=2.f; - if(kN>32768.f) kN=32768.f; - noisevarlum[i1>>1][j1>>1]=kN; - float aN=alum; - float bN=blum; - float hN=xatan2f(bN,aN); - float cN=sqrt(SQR(aN)+SQR(bN)); - if(cN < 100.f) cN=100.f;//avoid divided by zero - noisevarchrom[i1>>1][j1>>1]=cN; - noisevarhue[i1>>1][j1>>1]=hN; - } - labdn->a[i1][j1] = a; - labdn->b[i1][j1] = b; - } - } - } - int datalen = labdn->W * labdn->H; - - //now perform basic wavelet denoise - //last two arguments of wavelet decomposition are max number of wavelet decomposition levels; - //and whether to subsample the image after wavelet filtering. Subsampling is coded as - //binary 1 or 0 for each level, eg subsampling = 0 means no subsampling, 1 means subsample - //the first level only, 7 means subsample the first three levels, etc. - noisevarab_r = SQR(realred) + 0.01f; - noisevarab_b = SQR(realblue) + 0.01f; - - wavelet_decomposition* adecomp; - wavelet_decomposition* bdecomp; - - int schoice = 0;//shrink method - if (dnparams.smethod == "shalbi") - schoice=2; - - const int levwav=5; #ifdef _RT_NESTED_OPENMP -#pragma omp parallel sections if(multiThread) + #pragma omp parallel for if(multiThread) #endif -{ -#ifdef _RT_NESTED_OPENMP -#pragma omp section -#endif -{ - adecomp = new wavelet_decomposition (labdn->data+datalen, labdn->W, labdn->H, levwav, 1 ); -} -#ifdef _RT_NESTED_OPENMP -#pragma omp section -#endif -{ - bdecomp = new wavelet_decomposition (labdn->data+2*datalen, labdn->W, labdn->H, levwav, 1 ); -} -} - bool autoch = dnparams.autochroma; - if(comptlevel==0) WaveletDenoiseAll_info(levwav, *adecomp, *bdecomp, noisevarlum, noisevarchrom, noisevarhue, width, height, noisevarab_r, noisevarab_b, labdn, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, schoice, autoch, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc,maxchred, maxchblue, minchred, minchblue, nb,chau ,chred, chblue, denoiseMethodRgb, multiThread);//enhance mode - comptlevel+=1; - float chresid,chmaxredresid,chmaxblueresid; - nresi=chresid; - highresi=chresid + 0.66f*(max(chmaxredresid,chmaxblueresid) - chresid);//evaluate sigma - delete adecomp; - delete bdecomp; - delete labdn; - for (int i=0; i<(height+1)/2; i++) - delete [] noisevarlum[i]; - delete [] noisevarlum; - for (int i=0; i<(height+1)/2; i++) - delete [] noisevarchrom[i]; - delete [] noisevarchrom; - for (int i=0; i<(height+1)/2; i++) - delete [] noisevarhue[i]; - delete [] noisevarhue; - - }//end of tile row - }//end of tile loop - for (int i=0; ir(i, j); + float G_ = gain * src->g(i, j); + float B_ = gain * src->b(i, j); + + R_ = (*denoiseigamtab)[R_]; + G_ = (*denoiseigamtab)[G_]; + B_ = (*denoiseigamtab)[B_]; + + //apply gamma noise standard (slider) + R_ = R_ < 65535.0f ? gamcurve[R_] : (Color::gamman((double)R_ / 65535.0, gam) * 32768.0f); + G_ = G_ < 65535.0f ? gamcurve[G_] : (Color::gamman((double)G_ / 65535.0, gam) * 32768.0f); + B_ = B_ < 65535.0f ? gamcurve[B_] : (Color::gamman((double)B_ / 65535.0, gam) * 32768.0f); + //true conversion xyz=>Lab + float X, Y, Z; + Color::rgbxyz(R_, G_, B_, X, Y, Z, wp); + + //convert to Lab + float L, a, b; + Color::XYZ2Lab(X, Y, Z, L, a, b); + + labdn->a[i1][j1] = a; + labdn->b[i1][j1] = b; + } + } + } else { //RGB mode + + for (int i = tiletop/*, i1=0*/; i < tilebottom; i++/*, i1++*/) { + int i1 = i - tiletop; + + for (int j = tileleft/*, j1=0*/; j < tileright; j++/*, j1++*/) { + int j1 = j - tileleft; + + float X = gain * src->r(i, j); + float Y = gain * src->g(i, j); + float Z = gain * src->b(i, j); + + X = X < 65535.0f ? gamcurve[X] : (Color::gamma((double)X / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 32768.0f); + Y = Y < 65535.0f ? gamcurve[Y] : (Color::gamma((double)Y / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 32768.0f); + Z = Z < 65535.0f ? gamcurve[Z] : (Color::gamma((double)Z / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 32768.0f); + + labdn->a[i1][j1] = (X - Y); + labdn->b[i1][j1] = (Y - Z); + } + } + } + + } else {//image is not raw; use Lab parametrization + for (int i = tiletop/*, i1=0*/; i < tilebottom; i++/*, i1++*/) { + int i1 = i - tiletop; + + for (int j = tileleft/*, j1=0*/; j < tileright; j++/*, j1++*/) { + int j1 = j - tileleft; + float L, a, b; + float rLum = src->r(i, j) ; //for luminance denoise curve + float gLum = src->g(i, j) ; + float bLum = src->b(i, j) ; + + //use gamma sRGB, not good if TIF (JPG) Output profil not with gamma sRGB (eg : gamma =1.0, or 1.8...) + //very difficult to solve ! + // solution ==> save TIF with gamma sRGB and re open + float rtmp = Color::igammatab_srgb[ src->r(i, j) ]; + float gtmp = Color::igammatab_srgb[ src->g(i, j) ]; + float btmp = Color::igammatab_srgb[ src->b(i, j) ]; + //modification Jacques feb 2013 + // gamma slider different from raw + rtmp = rtmp < 65535.0f ? gamcurve[rtmp] : (Color::gamman((double)rtmp / 65535.0, gam) * 32768.0f); + gtmp = gtmp < 65535.0f ? gamcurve[gtmp] : (Color::gamman((double)gtmp / 65535.0, gam) * 32768.0f); + btmp = btmp < 65535.0f ? gamcurve[btmp] : (Color::gamman((double)btmp / 65535.0, gam) * 32768.0f); + + float X, Y, Z; + Color::rgbxyz(rtmp, gtmp, btmp, X, Y, Z, wp); + + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, a, b); + + if(((i1 | j1) & 1) == 0) { + float Llum, alum, blum; + float XL, YL, ZL; + Color::rgbxyz(rLum, gLum, bLum, XL, YL, ZL, wp); + Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum); + float kN = Llum; + + if(kN < 2.f) { + kN = 2.f; + } + + if(kN > 32768.f) { + kN = 32768.f; + } + + noisevarlum[i1 >> 1][j1 >> 1] = kN; + float aN = alum; + float bN = blum; + float hN = xatan2f(bN, aN); + float cN = sqrt(SQR(aN) + SQR(bN)); + + if(cN < 100.f) { + cN = 100.f; //avoid divided by zero + } + + noisevarchrom[i1 >> 1][j1 >> 1] = cN; + noisevarhue[i1 >> 1][j1 >> 1] = hN; + } + + labdn->a[i1][j1] = a; + labdn->b[i1][j1] = b; + } + } + } + + int datalen = labdn->W * labdn->H; + + //now perform basic wavelet denoise + //last two arguments of wavelet decomposition are max number of wavelet decomposition levels; + //and whether to subsample the image after wavelet filtering. Subsampling is coded as + //binary 1 or 0 for each level, eg subsampling = 0 means no subsampling, 1 means subsample + //the first level only, 7 means subsample the first three levels, etc. + noisevarab_r = SQR(realred) + 0.01f; + noisevarab_b = SQR(realblue) + 0.01f; + + wavelet_decomposition* adecomp; + wavelet_decomposition* bdecomp; + + int schoice = 0;//shrink method + + if (dnparams.smethod == "shalbi") { + schoice = 2; + } + + const int levwav = 5; +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel sections if(multiThread) +#endif + { +#ifdef _RT_NESTED_OPENMP + #pragma omp section +#endif + { + adecomp = new wavelet_decomposition (labdn->data + datalen, labdn->W, labdn->H, levwav, 1 ); + } +#ifdef _RT_NESTED_OPENMP + #pragma omp section +#endif + { + bdecomp = new wavelet_decomposition (labdn->data + 2 * datalen, labdn->W, labdn->H, levwav, 1 ); + } + } + bool autoch = dnparams.autochroma; + + if(comptlevel == 0) { + WaveletDenoiseAll_info(levwav, *adecomp, *bdecomp, noisevarlum, noisevarchrom, noisevarhue, width, height, noisevarab_r, noisevarab_b, labdn, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, schoice, autoch, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, maxchred, maxchblue, minchred, minchblue, nb, chau , chred, chblue, denoiseMethodRgb, multiThread); //enhance mode + } + + comptlevel += 1; + float chresid, chmaxredresid, chmaxblueresid; + nresi = chresid; + highresi = chresid + 0.66f * (max(chmaxredresid, chmaxblueresid) - chresid); //evaluate sigma + delete adecomp; + delete bdecomp; + delete labdn; + + for (int i = 0; i < (height + 1) / 2; i++) { + delete [] noisevarlum[i]; + } + + delete [] noisevarlum; + + for (int i = 0; i < (height + 1) / 2; i++) { + delete [] noisevarchrom[i]; + } + + delete [] noisevarchrom; + + for (int i = 0; i < (height + 1) / 2; i++) { + delete [] noisevarhue[i]; + } + + delete [] noisevarhue; + + }//end of tile row + }//end of tile loop + + for (int i = 0; i < hei; i++) { + delete [] lumcalc[i]; + } + + delete [] lumcalc; + + for (int i = 0; i < hei; i++) { + delete [] acalc[i]; + } + + delete [] acalc; + + for (int i = 0; i < hei; i++) { + delete [] bcalc[i]; + } + + delete [] bcalc; #undef TS #undef fTS diff --git a/rtengine/LUT.h b/rtengine/LUT.h index c60765cf9..b6eb1a05c 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -23,15 +23,15 @@ * * Usage: * - * LUT name (size); - * LUT name (size, flags); + * LUT name (size); + * LUT name (size, flags); * - * creates an array which is valid within the normal C/C++ scope "{ ... }" + * creates an array which is valid within the normal C/C++ scope "{ ... }" * * access to elements is a simple as: * - * LUT my_lut (10); - * float value = my_lut[3]; + * LUT my_lut (10); + * float value = my_lut[3]; * float value = my_lut[2.5]; // this will interpolate * * when using a float type index it will interpolate the lookup values @@ -41,7 +41,7 @@ * LUT_CLIP_BELOW * * example: - * LUT my_lut (10,LUT_CLIP_BELOW); + * LUT my_lut (10,LUT_CLIP_BELOW); * float value = my_lut[22.5]; // this will extrapolate * float value = my_lut[-22.5]; // this will not extrapolate * @@ -49,7 +49,7 @@ * * shotcuts: * - * LUTf stands for LUT + * LUTf stands for LUT * LUTi stands for LUT * LUTu stands for LUT */ @@ -78,350 +78,398 @@ #include "rt_math.h" template -class LUT { +class LUT +{ protected: - // list of variables ordered to improve cache speed - unsigned int maxs; - float maxsf; - T * data; - unsigned int clip; - unsigned int size; - unsigned int upperBound; // always equals size-1, parameter created for performance reason + // list of variables ordered to improve cache speed + unsigned int maxs; + float maxsf; + T * data; + unsigned int clip; + unsigned int size; + unsigned int upperBound; // always equals size-1, parameter created for performance reason private: - unsigned int owner; + unsigned int owner; #if defined( __SSE2__ ) && defined( __x86_64__ ) - __m128 maxsv __attribute__ ((aligned (16))); - __m128 sizev __attribute__ ((aligned (16))); - __m128i maxsiv __attribute__ ((aligned (16))); - __m128i sizeiv __attribute__ ((aligned (16))); + __m128 maxsv __attribute__ ((aligned (16))); + __m128 sizev __attribute__ ((aligned (16))); + __m128i maxsiv __attribute__ ((aligned (16))); + __m128i sizeiv __attribute__ ((aligned (16))); #endif public: - /// convenience flag! If one doesn't want to delete the buffer but want to flag it to be recomputed... - /// The user have to handle it itself, even if some method can (re)initialize it - bool dirty; + /// convenience flag! If one doesn't want to delete the buffer but want to flag it to be recomputed... + /// The user have to handle it itself, even if some method can (re)initialize it + bool dirty; - LUT(int s, int flags = 0xfffffff) { - #ifndef NDEBUG - if (s<=0) - printf("s<=0!\n"); - assert (s>0); - #endif - dirty = true; - clip = flags; - data = new T[s]; - owner = 1; - size = s; - upperBound = size-1; - maxs=size-2; - maxsf = (float)maxs; -#if defined( __SSE2__ ) && defined( __x86_64__ ) - maxsv = _mm_set1_ps( maxs ); - maxsiv = _mm_cvttps_epi32( maxsv ); - sizeiv = _mm_set1_epi32( (int)(size-1) ); - sizev = _mm_set1_ps( size-1 ); + LUT(int s, int flags = 0xfffffff) + { +#ifndef NDEBUG + + if (s <= 0) { + printf("s<=0!\n"); + } + + assert (s > 0); #endif - } - void operator ()(int s, int flags = 0xfffffff) { - #ifndef NDEBUG - if (s<=0) - printf("s<=0!\n"); - assert (s>0); - #endif - if (owner&&data) - delete[] data; - dirty = true; // Assumption! - clip = flags; - data = new T[s]; - owner = 1; - size = s; - upperBound = size-1; - maxs=size-2; - maxsf = (float)maxs; + dirty = true; + clip = flags; + data = new T[s]; + owner = 1; + size = s; + upperBound = size - 1; + maxs = size - 2; + maxsf = (float)maxs; #if defined( __SSE2__ ) && defined( __x86_64__ ) - maxsv = _mm_set1_ps( maxs ); - maxsiv = _mm_cvttps_epi32( maxsv ); - sizeiv = _mm_set1_epi32( (int)(size-1) ); - sizev = _mm_set1_ps( size-1 ); + maxsv = _mm_set1_ps( maxs ); + maxsiv = _mm_cvttps_epi32( maxsv ); + sizeiv = _mm_set1_epi32( (int)(size - 1) ); + sizev = _mm_set1_ps( size - 1 ); #endif - } + } + void operator ()(int s, int flags = 0xfffffff) + { +#ifndef NDEBUG - LUT(int s, T * source, int flags = 0xfffffff) { - #ifndef NDEBUG - if (s<=0) - printf("s<=0!\n"); - assert (s>0); - if (source==NULL) - printf("source is NULL!\n"); - assert (source != NULL); - #endif - dirty = false; // Assumption - clip = flags; - data = new T[s]; - owner = 1; - size = s; - upperBound = size-1; - maxs=size-2; - maxsf = (float)maxs; -#if defined( __SSE2__ ) && defined( __x86_64__ ) - maxsv = _mm_set1_ps( size - 2); - maxsiv = _mm_cvttps_epi32( maxsv ); - sizeiv = _mm_set1_epi32( (int)(size-1) ); - sizev = _mm_set1_ps( size-1 ); -#endif - for (int i = 0; i < s; i++) { - data[i] = source[i]; - } - } + if (s <= 0) { + printf("s<=0!\n"); + } - LUT() { - data = NULL; - reset(); - } - - ~LUT() { - if (owner) { - delete[] data; - #ifndef NDEBUG - data=(T*)0xBAADF00D; - #endif - } - } - - void setClip(int flags) { - clip = flags; - } - - /** @brief Get the number of element in the LUT (i.e. dimension of the array) - * For a LUT(500), it will return 500 - * @return number of element in the array - */ - int getSize() { - return size; - } - - /** @brief Get the highest value possible (i.e. dimension of the array) - * For a LUT(500), it will return 499, because 500 elements, starting from 0, goes up to 499 - * @return number of element in the array - */ - int getUpperBound() { - return size>0 ? upperBound : 0; - } - - LUT & operator=(LUT &rhs) { - if (this != &rhs) { - if (rhs.size>this->size) - { - delete [] this->data; - this->data=NULL; - } - if (this->data==NULL) this->data=new T[rhs.size]; - this->clip=rhs.clip; - this->owner=1; - memcpy(this->data,rhs.data,rhs.size*sizeof(T)); - this->size=rhs.size; - this->upperBound=rhs.upperBound; - this->maxs=this->size-2; - this->maxsf = (float)this->maxs; -#if defined( __SSE2__ ) && defined( __x86_64__ ) - this->maxsv = _mm_set1_ps( this->size - 2); - this->maxsiv = _mm_cvttps_epi32( this->maxsv ); - this->sizeiv = _mm_set1_epi32( (int)(this->size-1) ); - this->sizev = _mm_set1_ps( this->size-1 ); -#endif - } - - return *this; - } - // use with integer indices - T& operator[](int index) const { - return data[ rtengine::LIM(index, 0, upperBound) ]; - } - -#if defined( __SSE2__ ) && defined( __x86_64__ ) - __m128 operator[](__m128 indexv ) const { -// printf("don't use this operator. It's not ready for production"); - return _mm_setzero_ps(); - - // convert floats to ints - __m128i idxv = _mm_cvttps_epi32( indexv ); - __m128 tempv, resultv, p1v, p2v; - vmask maxmask = vmaskf_gt(indexv, maxsv); - idxv = _mm_castps_si128(vself(maxmask, maxsv, _mm_castsi128_ps(idxv))); - vmask minmask = vmaskf_lt(indexv, _mm_setzero_ps()); - idxv = _mm_castps_si128(vself(minmask, _mm_setzero_ps(), _mm_castsi128_ps(idxv))); - // access the LUT 4 times and shuffle the values into p1v and p2v - - int idx; - - // get 4th value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(3,3,3,3))); - tempv = LVFU(data[idx]); - p1v = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(0,0,0,0)); - p2v = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1,1,1,1)); - // now p1v is 3 3 3 3 - // p2v is 3 3 3 3 - - // get 3rd value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(2,2,2,2))); - tempv = LVFU(data[idx]); - p1v = _mm_move_ss( p1v, tempv); - tempv = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1,1,1,1)); - p2v = _mm_move_ss( p2v, tempv); - // now p1v is 3 3 3 2 - // p2v is 3 3 3 2 - - // get 2nd value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(1,1,1,1))); - tempv = LVFU(data[idx]); - p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(1,0,1,0)); - p2v = _mm_shuffle_ps( p2v, p2v, _MM_SHUFFLE(1,0,1,0)); - // now p1v is 3 2 3 2 - // now p2v is 3 2 3 2 - p1v = _mm_move_ss( p1v, tempv ); - // now p1v is 3 2 3 1 - tempv = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1,1,1,1)); - p2v = _mm_move_ss( p2v, tempv); - // now p1v is 3 2 3 1 - - // get 1st value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(0,0,0,0))); - tempv = LVFU(data[idx]); - p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(3,2,0,0)); - // now p1v is 3 2 1 1 - p2v = _mm_shuffle_ps( p2v, p2v, _MM_SHUFFLE(3,2,0,0)); - // now p2v is 3 2 1 1 - p1v = _mm_move_ss( p1v, tempv ); - // now p1v is 3 2 1 0 - tempv = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1,1,1,1)); - p2v = _mm_move_ss( p2v, tempv); - // now p2v is 3 2 1 0 - - __m128 diffv = indexv - _mm_cvtepi32_ps ( idxv ); - diffv = vself(vorm(maxmask,minmask), _mm_setzero_ps(), diffv); - resultv = p1v + p2v * diffv; - return resultv ; - } - - __m128 operator[](__m128i idxv ) const - { - __m128 tempv, p1v; - tempv = _mm_cvtepi32_ps(idxv); - tempv = _mm_min_ps( tempv, sizev ); - idxv = _mm_cvttps_epi32(_mm_max_ps( tempv, _mm_setzero_ps( ) )); - // access the LUT 4 times and shuffle the values into p1v - - int idx; - - // get 4th value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(3,3,3,3))); - tempv = _mm_load_ss(&data[idx]); - p1v = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(0,0,0,0)); - // now p1v is 3 3 3 3 - - // get 3rd value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(2,2,2,2))); - tempv = _mm_load_ss(&data[idx]); - p1v = _mm_move_ss( p1v, tempv); - // now p1v is 3 3 3 2 - - // get 2nd value - idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv,_MM_SHUFFLE(1,1,1,1))); - tempv = _mm_load_ss(&data[idx]); - p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(1,0,1,0)); - // now p1v is 3 2 3 2 - p1v = _mm_move_ss( p1v, tempv ); - // now p1v is 3 2 3 1 - - // get 1st value - idx = _mm_cvtsi128_si32 (idxv); - tempv = _mm_load_ss(&data[idx]); - p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(3,2,0,0)); - // now p1v is 3 2 1 1 - p1v = _mm_move_ss( p1v, tempv ); - // now p1v is 3 2 1 0 - - return p1v; - } + assert (s > 0); #endif - // use with float indices - T operator[](float index) const { - int idx = (int)index; // don't use floor! The difference in negative space is no problems here - if (index<0.f) - { - if (clip & LUT_CLIP_BELOW) - return data[0]; - idx=0; - } - else if (index > maxsf) - { - if (clip & LUT_CLIP_ABOVE) - return data[upperBound]; - idx =maxs; - } - float diff = index - (float) idx; - T p1 = data[idx]; - T p2 = data[idx + 1]-p1; - return (p1 + p2*diff); - } + if (owner && data) { + delete[] data; + } - // Return the value for "index" that is in the [0-1] range. - T getVal01 (float index) const { - index *= float(upperBound); - int idx = (int)index; // don't use floor! The difference in negative space is no problems here - if (index<0.f) - { - if (clip & LUT_CLIP_BELOW) - return data[0]; - idx=0; - } - else if (index > maxsf) - { - if (clip & LUT_CLIP_ABOVE) - return data[upperBound]; - idx =maxs; - } - float diff = index - (float) idx; - T p1 = data[idx]; - T p2 = data[idx + 1]-p1; - return (p1 + p2*diff); - } + dirty = true; // Assumption! + clip = flags; + data = new T[s]; + owner = 1; + size = s; + upperBound = size - 1; + maxs = size - 2; + maxsf = (float)maxs; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + maxsv = _mm_set1_ps( maxs ); + maxsiv = _mm_cvttps_epi32( maxsv ); + sizeiv = _mm_set1_epi32( (int)(size - 1) ); + sizev = _mm_set1_ps( size - 1 ); +#endif + } + + LUT(int s, T * source, int flags = 0xfffffff) + { +#ifndef NDEBUG + + if (s <= 0) { + printf("s<=0!\n"); + } + + assert (s > 0); + + if (source == NULL) { + printf("source is NULL!\n"); + } + + assert (source != NULL); +#endif + dirty = false; // Assumption + clip = flags; + data = new T[s]; + owner = 1; + size = s; + upperBound = size - 1; + maxs = size - 2; + maxsf = (float)maxs; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + maxsv = _mm_set1_ps( size - 2); + maxsiv = _mm_cvttps_epi32( maxsv ); + sizeiv = _mm_set1_epi32( (int)(size - 1) ); + sizev = _mm_set1_ps( size - 1 ); +#endif + + for (int i = 0; i < s; i++) { + data[i] = source[i]; + } + } + + LUT() + { + data = NULL; + reset(); + } + + ~LUT() + { + if (owner) { + delete[] data; +#ifndef NDEBUG + data = (T*)0xBAADF00D; +#endif + } + } + + void setClip(int flags) + { + clip = flags; + } + + /** @brief Get the number of element in the LUT (i.e. dimension of the array) + * For a LUT(500), it will return 500 + * @return number of element in the array + */ + int getSize() + { + return size; + } + + /** @brief Get the highest value possible (i.e. dimension of the array) + * For a LUT(500), it will return 499, because 500 elements, starting from 0, goes up to 499 + * @return number of element in the array + */ + int getUpperBound() + { + return size > 0 ? upperBound : 0; + } + + LUT & operator=(LUT &rhs) + { + if (this != &rhs) { + if (rhs.size > this->size) { + delete [] this->data; + this->data = NULL; + } + + if (this->data == NULL) { + this->data = new T[rhs.size]; + } + + this->clip = rhs.clip; + this->owner = 1; + memcpy(this->data, rhs.data, rhs.size * sizeof(T)); + this->size = rhs.size; + this->upperBound = rhs.upperBound; + this->maxs = this->size - 2; + this->maxsf = (float)this->maxs; +#if defined( __SSE2__ ) && defined( __x86_64__ ) + this->maxsv = _mm_set1_ps( this->size - 2); + this->maxsiv = _mm_cvttps_epi32( this->maxsv ); + this->sizeiv = _mm_set1_epi32( (int)(this->size - 1) ); + this->sizev = _mm_set1_ps( this->size - 1 ); +#endif + } + + return *this; + } + // use with integer indices + T& operator[](int index) const + { + return data[ rtengine::LIM(index, 0, upperBound) ]; + } + +#if defined( __SSE2__ ) && defined( __x86_64__ ) + __m128 operator[](__m128 indexv ) const + { +// printf("don't use this operator. It's not ready for production"); + return _mm_setzero_ps(); + + // convert floats to ints + __m128i idxv = _mm_cvttps_epi32( indexv ); + __m128 tempv, resultv, p1v, p2v; + vmask maxmask = vmaskf_gt(indexv, maxsv); + idxv = _mm_castps_si128(vself(maxmask, maxsv, _mm_castsi128_ps(idxv))); + vmask minmask = vmaskf_lt(indexv, _mm_setzero_ps()); + idxv = _mm_castps_si128(vself(minmask, _mm_setzero_ps(), _mm_castsi128_ps(idxv))); + // access the LUT 4 times and shuffle the values into p1v and p2v + + int idx; + + // get 4th value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(3, 3, 3, 3))); + tempv = LVFU(data[idx]); + p1v = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(0, 0, 0, 0)); + p2v = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1, 1, 1, 1)); + // now p1v is 3 3 3 3 + // p2v is 3 3 3 3 + + // get 3rd value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(2, 2, 2, 2))); + tempv = LVFU(data[idx]); + p1v = _mm_move_ss( p1v, tempv); + tempv = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1, 1, 1, 1)); + p2v = _mm_move_ss( p2v, tempv); + // now p1v is 3 3 3 2 + // p2v is 3 3 3 2 + + // get 2nd value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(1, 1, 1, 1))); + tempv = LVFU(data[idx]); + p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(1, 0, 1, 0)); + p2v = _mm_shuffle_ps( p2v, p2v, _MM_SHUFFLE(1, 0, 1, 0)); + // now p1v is 3 2 3 2 + // now p2v is 3 2 3 2 + p1v = _mm_move_ss( p1v, tempv ); + // now p1v is 3 2 3 1 + tempv = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1, 1, 1, 1)); + p2v = _mm_move_ss( p2v, tempv); + // now p1v is 3 2 3 1 + + // get 1st value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(0, 0, 0, 0))); + tempv = LVFU(data[idx]); + p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(3, 2, 0, 0)); + // now p1v is 3 2 1 1 + p2v = _mm_shuffle_ps( p2v, p2v, _MM_SHUFFLE(3, 2, 0, 0)); + // now p2v is 3 2 1 1 + p1v = _mm_move_ss( p1v, tempv ); + // now p1v is 3 2 1 0 + tempv = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(1, 1, 1, 1)); + p2v = _mm_move_ss( p2v, tempv); + // now p2v is 3 2 1 0 + + __m128 diffv = indexv - _mm_cvtepi32_ps ( idxv ); + diffv = vself(vorm(maxmask, minmask), _mm_setzero_ps(), diffv); + resultv = p1v + p2v * diffv; + return resultv ; + } + + __m128 operator[](__m128i idxv ) const + { + __m128 tempv, p1v; + tempv = _mm_cvtepi32_ps(idxv); + tempv = _mm_min_ps( tempv, sizev ); + idxv = _mm_cvttps_epi32(_mm_max_ps( tempv, _mm_setzero_ps( ) )); + // access the LUT 4 times and shuffle the values into p1v + + int idx; + + // get 4th value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(3, 3, 3, 3))); + tempv = _mm_load_ss(&data[idx]); + p1v = _mm_shuffle_ps(tempv, tempv, _MM_SHUFFLE(0, 0, 0, 0)); + // now p1v is 3 3 3 3 + + // get 3rd value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(2, 2, 2, 2))); + tempv = _mm_load_ss(&data[idx]); + p1v = _mm_move_ss( p1v, tempv); + // now p1v is 3 3 3 2 + + // get 2nd value + idx = _mm_cvtsi128_si32 (_mm_shuffle_epi32(idxv, _MM_SHUFFLE(1, 1, 1, 1))); + tempv = _mm_load_ss(&data[idx]); + p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(1, 0, 1, 0)); + // now p1v is 3 2 3 2 + p1v = _mm_move_ss( p1v, tempv ); + // now p1v is 3 2 3 1 + + // get 1st value + idx = _mm_cvtsi128_si32 (idxv); + tempv = _mm_load_ss(&data[idx]); + p1v = _mm_shuffle_ps( p1v, p1v, _MM_SHUFFLE(3, 2, 0, 0)); + // now p1v is 3 2 1 1 + p1v = _mm_move_ss( p1v, tempv ); + // now p1v is 3 2 1 0 + + return p1v; + } +#endif + + // use with float indices + T operator[](float index) const + { + int idx = (int)index; // don't use floor! The difference in negative space is no problems here + + if (index < 0.f) { + if (clip & LUT_CLIP_BELOW) { + return data[0]; + } + + idx = 0; + } else if (index > maxsf) { + if (clip & LUT_CLIP_ABOVE) { + return data[upperBound]; + } + + idx = maxs; + } + + float diff = index - (float) idx; + T p1 = data[idx]; + T p2 = data[idx + 1] - p1; + return (p1 + p2 * diff); + } + + // Return the value for "index" that is in the [0-1] range. + T getVal01 (float index) const + { + index *= float(upperBound); + int idx = (int)index; // don't use floor! The difference in negative space is no problems here + + if (index < 0.f) { + if (clip & LUT_CLIP_BELOW) { + return data[0]; + } + + idx = 0; + } else if (index > maxsf) { + if (clip & LUT_CLIP_ABOVE) { + return data[upperBound]; + } + + idx = maxs; + } + + float diff = index - (float) idx; + T p1 = data[idx]; + T p2 = data[idx + 1] - p1; + return (p1 + p2 * diff); + } #ifndef NDEBUG - // Debug facility ; dump the content of the LUT in a file. No control of the filename is done - void dump(Glib::ustring fname) { - if (size) { - Glib::ustring fname_ = fname + ".xyz"; // TopSolid'Design "plot" file format - std::ofstream f (fname_.c_str()); - f << "$" << std::endl; - for (unsigned int iter=0; iter0; - } + operator bool (void) const + { + return size > 0; + } - void clear(void) { - if (data && size) - memset(data, 0, size * sizeof(T)); - } + void clear(void) + { + if (data && size) { + memset(data, 0, size * sizeof(T)); + } + } - void reset(void) { - if (data) delete[] data; - dirty = true; - data = NULL; - owner = 1; - size = 0; - upperBound=0; - maxs=0; + void reset(void) + { + if (data) { + delete[] data; + } + + dirty = true; + data = NULL; + owner = 1; + size = 0; + upperBound = 0; + maxs = 0; } }; @@ -432,54 +480,69 @@ public: /** @brief LUT subclass handling hue values specifically. The array has a fixed size of float values and have to be in the [0.; 1.] range in both axis (no error checking implemented) */ -class HueLUT : public LUTf { - public: - HueLUT() : LUTf() {} - HueLUT(bool createArray) : LUTf() { - if (createArray) - this->operator () (501, LUT_CLIP_BELOW|LUT_CLIP_ABOVE); - } +class HueLUT : public LUTf +{ +public: + HueLUT() : LUTf() {} + HueLUT(bool createArray) : LUTf() + { + if (createArray) { + this->operator () (501, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); + } + } - void create() { - this->operator () (501, LUT_CLIP_BELOW|LUT_CLIP_ABOVE); - } + void create() + { + this->operator () (501, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); + } - // use with integer indices - float& operator[](int index) const { - return data[ rtengine::LIM(index, 0, upperBound) ]; - } + // use with integer indices + float& operator[](int index) const + { + return data[ rtengine::LIM(index, 0, upperBound) ]; + } - // use with float indices in the [0.;1.] range - float operator[](float index) const { - int idx = int(index*500.f); // don't use floor! The difference in negative space is no problems here - if (index<0.f) - return data[0]; - else if (index > 1.f) - return data[upperBound]; + // use with float indices in the [0.;1.] range + float operator[](float index) const + { + int idx = int(index * 500.f); // don't use floor! The difference in negative space is no problems here - float balance = index - float(idx/500.f); - float h1 = data[idx]; - float h2 = data[idx + 1]; + if (index < 0.f) { + return data[0]; + } else if (index > 1.f) { + return data[upperBound]; + } - if (h1==h2) - return h1; - if ((h1 > h2) && (h1-h2 > 0.5f)){ - h1 -= 1.f; - float value = h1 + balance * (h2-h1); - if (value < 0.f) - value += 1.f; - return value; - } - else if (h2-h1 > 0.5f) { - h2 -= 1.f; - float value = h1 + balance * (h2-h1); - if (value < 0.f) - value += 1.f; - return value; - } - else - return h1 + balance * (h2-h1); - } + float balance = index - float(idx / 500.f); + float h1 = data[idx]; + float h2 = data[idx + 1]; + + if (h1 == h2) { + return h1; + } + + if ((h1 > h2) && (h1 - h2 > 0.5f)) { + h1 -= 1.f; + float value = h1 + balance * (h2 - h1); + + if (value < 0.f) { + value += 1.f; + } + + return value; + } else if (h2 - h1 > 0.5f) { + h2 -= 1.f; + float value = h1 + balance * (h2 - h1); + + if (value < 0.f) { + value += 1.f; + } + + return value; + } else { + return h1 + balance * (h2 - h1); + } + } }; diff --git a/rtengine/PF_correct_RT.cc b/rtengine/PF_correct_RT.cc index 9da12afea..130a683d8 100644 --- a/rtengine/PF_correct_RT.cc +++ b/rtengine/PF_correct_RT.cc @@ -1,25 +1,25 @@ //////////////////////////////////////////////////////////////// // -// Chromatic Aberration Auto-correction +// Chromatic Aberration Auto-correction // -// copyright (c) 2008-2010 Emil Martinec +// copyright (c) 2008-2010 Emil Martinec // // // code dated: November 24, 2010 // optimized: September 2013, Ingo Weyrich // -// PF_correct_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// PF_correct_RT.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -38,119 +38,143 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; SSEFUNCTION void ImProcFunctions::PF_correct_RT(LabImage * src, LabImage * dst, double radius, int thresh) { - const int halfwin = ceil(2*radius)+1; + const int halfwin = ceil(2 * radius) + 1; - FlatCurve* chCurve = NULL; - if (params->defringe.huecurve.size() && FlatCurveType(params->defringe.huecurve.at(0)) > FCT_Linear) - chCurve = new FlatCurve(params->defringe.huecurve); + FlatCurve* chCurve = NULL; - // local variables - const int width=src->W, height=src->H; - //temporary array to store chromaticity - float (*fringe); - fringe = (float (*)) malloc (height * width * sizeof(*fringe)); + if (params->defringe.huecurve.size() && FlatCurveType(params->defringe.huecurve.at(0)) > FCT_Linear) { + chCurve = new FlatCurve(params->defringe.huecurve); + } - LabImage * tmp1; - tmp1 = new LabImage(width, height); + // local variables + const int width = src->W, height = src->H; + //temporary array to store chromaticity + float (*fringe); + fringe = (float (*)) malloc (height * width * sizeof(*fringe)); + + LabImage * tmp1; + tmp1 = new LabImage(width, height); #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - AlignedBufferMP buffer(max(src->W,src->H)); - gaussHorizontal (src->a, tmp1->a, buffer, src->W, src->H, radius); - gaussHorizontal (src->b, tmp1->b, buffer, src->W, src->H, radius); - gaussVertical (tmp1->a, tmp1->a, buffer, src->W, src->H, radius); - gaussVertical (tmp1->b, tmp1->b, buffer, src->W, src->H, radius); - } + { + AlignedBufferMP buffer(max(src->W, src->H)); + gaussHorizontal (src->a, tmp1->a, buffer, src->W, src->H, radius); + gaussHorizontal (src->b, tmp1->b, buffer, src->W, src->H, radius); + gaussVertical (tmp1->a, tmp1->a, buffer, src->W, src->H, radius); + gaussVertical (tmp1->b, tmp1->b, buffer, src->W, src->H, radius); + } -float chromave=0.0f; + float chromave = 0.0f; #ifdef __SSE2__ - if( chCurve ) { + + if( chCurve ) { // vectorized precalculation of the atan2 values #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - int j; + { + int j; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++ ) { - for(j = 0; j < width-3; j+=4) - _mm_storeu_ps(&fringe[i*width+j], xatan2f(LVFU(src->b[i][j]),LVFU(src->a[i][j]))); - for(; j < width; j++) - fringe[i*width+j]=xatan2f(src->b[i][j],src->a[i][j]); - } - } - } + + for(int i = 0; i < height; i++ ) + { + for(j = 0; j < width - 3; j += 4) { + _mm_storeu_ps(&fringe[i * width + j], xatan2f(LVFU(src->b[i][j]), LVFU(src->a[i][j]))); + } + + for(; j < width; j++) { + fringe[i * width + j] = xatan2f(src->b[i][j], src->a[i][j]); + } + } + } + } + #endif #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - float chromaChfactor = 1.0f; + { + float chromaChfactor = 1.0f; #ifdef _OPENMP -#pragma omp for reduction(+:chromave) + #pragma omp for reduction(+:chromave) #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - if (chCurve) { + + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + if (chCurve) { #ifdef __SSE2__ - // use the precalculated atan values - float HH=fringe[i*width+j]; + // use the precalculated atan values + float HH = fringe[i * width + j]; #else - // no precalculated values without SSE => calculate - float HH=xatan2f(src->b[i][j],src->a[i][j]); + // no precalculated values without SSE => calculate + float HH = xatan2f(src->b[i][j], src->a[i][j]); #endif - float chparam = float((chCurve->getVal((Color::huelab_to_huehsv2(HH)))-0.5f) * 2.0f);//get C=f(H) - if(chparam > 0.f) chparam /=2.f; // reduced action if chparam > 0 - chromaChfactor=1.0f+chparam; - } - float chroma = SQR(chromaChfactor*(src->a[i][j]-tmp1->a[i][j]))+SQR(chromaChfactor*(src->b[i][j]-tmp1->b[i][j]));//modulate chroma function hue - chromave += chroma; - fringe[i*width+j]=chroma; - } - } -} + float chparam = float((chCurve->getVal((Color::huelab_to_huehsv2(HH))) - 0.5f) * 2.0f); //get C=f(H) - chromave /= (height*width); - float threshfactor = SQR(thresh/33.f)*chromave*5.0f; + if(chparam > 0.f) { + chparam /= 2.f; // reduced action if chparam > 0 + } + + chromaChfactor = 1.0f + chparam; + } + + float chroma = SQR(chromaChfactor * (src->a[i][j] - tmp1->a[i][j])) + SQR(chromaChfactor * (src->b[i][j] - tmp1->b[i][j])); //modulate chroma function hue + chromave += chroma; + fringe[i * width + j] = chroma; + } + } + } + + chromave /= (height * width); + float threshfactor = SQR(thresh / 33.f) * chromave * 5.0f; // now chromave is calculated, so we postprocess fringe to reduce the number of divisions in future #ifdef __SSE2__ #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - __m128 sumv = _mm_set1_ps( chromave ); - __m128 onev = _mm_set1_ps( 1.0f ); + { + __m128 sumv = _mm_set1_ps( chromave ); + __m128 onev = _mm_set1_ps( 1.0f ); #ifdef _OPENMP -#pragma omp for -#endif - for(int j=0; j < width*height-3; j+=4) - _mm_storeu_ps( &fringe[j], onev/(LVFU(fringe[j])+sumv)); -} - for(int j=width*height - (width*height)%4; j < width*height; j++) - fringe[j] = 1.f/(fringe[j]+chromave); -#else -#ifdef _OPENMP -#pragma omp parallel for -#endif - for(int j = 0; j < width*height; j++) - fringe[j] = 1.f/(fringe[j]+chromave); + #pragma omp for #endif - // because we changed the values of fringe we also have to recalculate threshfactor - threshfactor = 1.0f/(threshfactor + chromave); + for(int j = 0; j < width * height - 3; j += 4) { + _mm_storeu_ps( &fringe[j], onev / (LVFU(fringe[j]) + sumv)); + } + } + + for(int j = width * height - (width * height) % 4; j < width * height; j++) { + fringe[j] = 1.f / (fringe[j] + chromave); + } + +#else +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int j = 0; j < width * height; j++) { + fringe[j] = 1.f / (fringe[j] + chromave); + } + +#endif + + // because we changed the values of fringe we also have to recalculate threshfactor + threshfactor = 1.0f / (threshfactor + chromave); // Issue 1674: // often, CA isn't evenly distributed, e.g. a lot in contrasty regions and none in the sky. @@ -159,272 +183,327 @@ float chromave=0.0f; // choice for the chunk_size than 16 // Issue 1972: Split this loop in three parts to avoid most of the min and max-operations #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++ ) { - int j; - for(j = 0; j < halfwin-1; j++) { - tmp1->a[i][j] = src->a[i][j]; - tmp1->b[i][j] = src->b[i][j]; - //test for pixel darker than some fraction of neighborhood ave, near an edge, more saturated than average - /*if (100*tmp1->L[i][j]>50*src->L[i][j] && \*/ - /*1000*abs(tmp1->L[i][j]-src->L[i][j])>thresh*(tmp1->L[i][j]+src->L[i][j]) && \*/ - if (fringe[i*width+j]a[i1][j1]; - btot += wt*src->b[i1][j1]; - norm += wt; - } - tmp1->a[i][j] = atot/norm; - tmp1->b[i][j] = btot/norm; - } - } - for(; j < width-halfwin+1; j++) { - tmp1->a[i][j] = src->a[i][j]; - tmp1->b[i][j] = src->b[i][j]; - //test for pixel darker than some fraction of neighborhood ave, near an edge, more saturated than average - /*if (100*tmp1->L[i][j]>50*src->L[i][j] && \*/ - /*1000*abs(tmp1->L[i][j]-src->L[i][j])>thresh*(tmp1->L[i][j]+src->L[i][j]) && \*/ - if (fringe[i*width+j]a[i1][j1]; - btot += wt*src->b[i1][j1]; - norm += wt; - } - tmp1->a[i][j] = atot/norm; - tmp1->b[i][j] = btot/norm; - } - } - for(; j < width; j++) { - tmp1->a[i][j] = src->a[i][j]; - tmp1->b[i][j] = src->b[i][j]; - //test for pixel darker than some fraction of neighborhood ave, near an edge, more saturated than average - /*if (100*tmp1->L[i][j]>50*src->L[i][j] && \*/ - /*1000*abs(tmp1->L[i][j]-src->L[i][j])>thresh*(tmp1->L[i][j]+src->L[i][j]) && \*/ - if (fringe[i*width+j]a[i1][j1]; - btot += wt*src->b[i1][j1]; - norm += wt; - } - tmp1->a[i][j] = atot/norm; - tmp1->b[i][j] = btot/norm; - } - } - }//end of ab channel averaging - if(src != dst) + for(int i = 0; i < height; i++ ) { + int j; + + for(j = 0; j < halfwin - 1; j++) { + tmp1->a[i][j] = src->a[i][j]; + tmp1->b[i][j] = src->b[i][j]; + + //test for pixel darker than some fraction of neighborhood ave, near an edge, more saturated than average + /*if (100*tmp1->L[i][j]>50*src->L[i][j] && \*/ + /*1000*abs(tmp1->L[i][j]-src->L[i][j])>thresh*(tmp1->L[i][j]+src->L[i][j]) && \*/ + if (fringe[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = 0; j1 < j + halfwin; j1++) { + //neighborhood average of pixels weighted by chrominance + wt = fringe[i1 * width + j1]; + atot += wt * src->a[i1][j1]; + btot += wt * src->b[i1][j1]; + norm += wt; + } + + tmp1->a[i][j] = atot / norm; + tmp1->b[i][j] = btot / norm; + } + } + + for(; j < width - halfwin + 1; j++) { + tmp1->a[i][j] = src->a[i][j]; + tmp1->b[i][j] = src->b[i][j]; + + //test for pixel darker than some fraction of neighborhood ave, near an edge, more saturated than average + /*if (100*tmp1->L[i][j]>50*src->L[i][j] && \*/ + /*1000*abs(tmp1->L[i][j]-src->L[i][j])>thresh*(tmp1->L[i][j]+src->L[i][j]) && \*/ + if (fringe[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < j + halfwin; j1++) { + //neighborhood average of pixels weighted by chrominance + wt = fringe[i1 * width + j1]; + atot += wt * src->a[i1][j1]; + btot += wt * src->b[i1][j1]; + norm += wt; + } + + tmp1->a[i][j] = atot / norm; + tmp1->b[i][j] = btot / norm; + } + } + + for(; j < width; j++) { + tmp1->a[i][j] = src->a[i][j]; + tmp1->b[i][j] = src->b[i][j]; + + //test for pixel darker than some fraction of neighborhood ave, near an edge, more saturated than average + /*if (100*tmp1->L[i][j]>50*src->L[i][j] && \*/ + /*1000*abs(tmp1->L[i][j]-src->L[i][j])>thresh*(tmp1->L[i][j]+src->L[i][j]) && \*/ + if (fringe[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < width; j1++) { + //neighborhood average of pixels weighted by chrominance + wt = fringe[i1 * width + j1]; + atot += wt * src->a[i1][j1]; + btot += wt * src->b[i1][j1]; + norm += wt; + } + + tmp1->a[i][j] = atot / norm; + tmp1->b[i][j] = btot / norm; + } + } + }//end of ab channel averaging + + if(src != dst) #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - dst->L[i][j] = src->L[i][j]; - } - } + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + dst->L[i][j] = src->L[i][j]; + } + } #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - dst->a[i][j] = tmp1->a[i][j]; - dst->b[i][j] = tmp1->b[i][j]; - } - } + + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + dst->a[i][j] = tmp1->a[i][j]; + dst->b[i][j] = tmp1->b[i][j]; + } + } - delete tmp1; - if(chCurve) delete chCurve; - free(fringe); + delete tmp1; + + if(chCurve) { + delete chCurve; + } + + free(fringe); } SSEFUNCTION void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double radius, int thresh) { - const int halfwin = ceil(2*radius)+1; + const int halfwin = ceil(2 * radius) + 1; - FlatCurve* chCurve = NULL; - if (params->defringe.huecurve.size() && FlatCurveType(params->defringe.huecurve.at(0)) > FCT_Linear) - chCurve = new FlatCurve(params->defringe.huecurve); + FlatCurve* chCurve = NULL; - // local variables - const int width=src->W, height=src->H; - const float piid=3.14159265f/180.f; - const float eps2=0.01f; + if (params->defringe.huecurve.size() && FlatCurveType(params->defringe.huecurve.at(0)) > FCT_Linear) { + chCurve = new FlatCurve(params->defringe.huecurve); + } - //temporary array to store chromaticity - float (*fringe); - fringe = (float (*)) malloc (height * width * sizeof(*fringe)); + // local variables + const int width = src->W, height = src->H; + const float piid = 3.14159265f / 180.f; + const float eps2 = 0.01f; - float** sraa; - sraa = new float*[height]; - for (int i=0; ih_p[i][j])); - _mm_storeu_ps(&sraa[i][j],LVFU(src->C_p[i][j])*sincosvalv.y); - _mm_storeu_ps(&srbb[i][j],LVFU(src->C_p[i][j])*sincosvalv.x); - } - for (; jh_p[i][j]); - sraa[i][j]=src->C_p[i][j]*sincosval.y; - srbb[i][j]=src->C_p[i][j]*sincosval.x; - } + + for (j = 0; j < width - 3; j += 4) { + sincosvalv = xsincosf(piidv * LVFU(src->h_p[i][j])); + _mm_storeu_ps(&sraa[i][j], LVFU(src->C_p[i][j])*sincosvalv.y); + _mm_storeu_ps(&srbb[i][j], LVFU(src->C_p[i][j])*sincosvalv.x); + } + + for (; j < width; j++) { + sincosval = xsincosf(piid * src->h_p[i][j]); + sraa[i][j] = src->C_p[i][j] * sincosval.y; + srbb[i][j] = src->C_p[i][j] * sincosval.x; + } + #else - for (int j=0; jh_p[i][j]); - sraa[i][j]=src->C_p[i][j]*sincosval.y; - srbb[i][j]=src->C_p[i][j]*sincosval.x; - } + + for (int j = 0; j < width; j++) { + sincosval = xsincosf(piid * src->h_p[i][j]); + sraa[i][j] = src->C_p[i][j] * sincosval.y; + srbb[i][j] = src->C_p[i][j] * sincosval.x; + } + #endif - } -} + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - AlignedBufferMP buffer(max(src->W,src->H)); - gaussHorizontal (sraa, tmaa, buffer, src->W, src->H, radius); - gaussHorizontal (srbb, tmbb, buffer, src->W, src->H, radius); - gaussVertical (tmaa, tmaa, buffer, src->W, src->H, radius); - gaussVertical (tmbb, tmbb, buffer, src->W, src->H, radius); - } + { + AlignedBufferMP buffer(max(src->W, src->H)); + gaussHorizontal (sraa, tmaa, buffer, src->W, src->H, radius); + gaussHorizontal (srbb, tmbb, buffer, src->W, src->H, radius); + gaussVertical (tmaa, tmaa, buffer, src->W, src->H, radius); + gaussVertical (tmbb, tmbb, buffer, src->W, src->H, radius); + } -float chromave=0.0f; + float chromave = 0.0f; #ifdef __SSE2__ -if( chCurve ) { + + if( chCurve ) { // vectorized precalculation of the atan2 values #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; + { + int j; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++ ) { - for(j = 0; j < width-3; j+=4) - _mm_storeu_ps(&fringe[i*width+j], xatan2f(LVFU(srbb[i][j]),LVFU(sraa[i][j]))); - for(; j < width; j++) - fringe[i*width+j]=xatan2f(srbb[i][j],sraa[i][j]); - } -} -} + + for(int i = 0; i < height; i++ ) + { + for(j = 0; j < width - 3; j += 4) { + _mm_storeu_ps(&fringe[i * width + j], xatan2f(LVFU(srbb[i][j]), LVFU(sraa[i][j]))); + } + + for(; j < width; j++) { + fringe[i * width + j] = xatan2f(srbb[i][j], sraa[i][j]); + } + } + } + } + #endif #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - float chromaChfactor = 1.0f; + { + float chromaChfactor = 1.0f; #ifdef _OPENMP -#pragma omp for reduction(+:chromave) + #pragma omp for reduction(+:chromave) #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - if (chCurve) { + + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + if (chCurve) { #ifdef __SSE2__ - // use the precalculated atan values - float HH=fringe[i*width+j]; + // use the precalculated atan values + float HH = fringe[i * width + j]; #else - // no precalculated values without SSE => calculate - float HH=xatan2f(srbb[i][j],sraa[i][j]); + // no precalculated values without SSE => calculate + float HH = xatan2f(srbb[i][j], sraa[i][j]); #endif - float chparam = float((chCurve->getVal((Color::huelab_to_huehsv2(HH)))-0.5f) * 2.0f);//get C=f(H) - if(chparam > 0.f) chparam /=2.f; // reduced action if chparam > 0 - chromaChfactor=1.0f+chparam; - } - float chroma = SQR(chromaChfactor*(sraa[i][j]-tmaa[i][j]))+SQR(chromaChfactor*(srbb[i][j]-tmbb[i][j]));//modulate chroma function hue - chromave += chroma; - fringe[i*width+j]=chroma; - } - } -} + float chparam = float((chCurve->getVal((Color::huelab_to_huehsv2(HH))) - 0.5f) * 2.0f); //get C=f(H) - chromave /= (height*width); - float threshfactor = SQR(thresh/33.f)*chromave*5.0f; // Calculated once to eliminate mult inside the next loop + if(chparam > 0.f) { + chparam /= 2.f; // reduced action if chparam > 0 + } + + chromaChfactor = 1.0f + chparam; + } + + float chroma = SQR(chromaChfactor * (sraa[i][j] - tmaa[i][j])) + SQR(chromaChfactor * (srbb[i][j] - tmbb[i][j])); //modulate chroma function hue + chromave += chroma; + fringe[i * width + j] = chroma; + } + } + } + + chromave /= (height * width); + float threshfactor = SQR(thresh / 33.f) * chromave * 5.0f; // Calculated once to eliminate mult inside the next loop // now chromave is calculated, so we postprocess fringe to reduce the number of divisions in future #ifdef __SSE2__ #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - __m128 sumv = _mm_set1_ps( chromave + eps2 ); - __m128 onev = _mm_set1_ps( 1.0f ); + { + __m128 sumv = _mm_set1_ps( chromave + eps2 ); + __m128 onev = _mm_set1_ps( 1.0f ); #ifdef _OPENMP -#pragma omp for -#endif - for(int j=0; j < width*height-3; j+=4) - _mm_storeu_ps( &fringe[j], onev/(LVFU(fringe[j])+sumv)); -} - for(int j=width*height - (width*height)%4; j < width*height; j++) - fringe[j] = 1.f/(fringe[j]+chromave+eps2); -#else -#ifdef _OPENMP -#pragma omp parallel for -#endif - for(int j = 0; j < width*height; j++) - fringe[j] = 1.f/(fringe[j]+chromave+eps2); + #pragma omp for #endif - // because we changed the values of fringe we also have to recalculate threshfactor - threshfactor = 1.0f/(threshfactor + chromave + eps2); + for(int j = 0; j < width * height - 3; j += 4) { + _mm_storeu_ps( &fringe[j], onev / (LVFU(fringe[j]) + sumv)); + } + } + + for(int j = width * height - (width * height) % 4; j < width * height; j++) { + fringe[j] = 1.f / (fringe[j] + chromave + eps2); + } + +#else +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int j = 0; j < width * height; j++) { + fringe[j] = 1.f / (fringe[j] + chromave + eps2); + } + +#endif + + // because we changed the values of fringe we also have to recalculate threshfactor + threshfactor = 1.0f / (threshfactor + chromave + eps2); // Issue 1674: // often, CA isn't evenly distributed, e.g. a lot in contrasty regions and none in the sky. @@ -433,1057 +512,1392 @@ if( chCurve ) { // choice for the chunk_size than 16 // Issue 1972: Split this loop in three parts to avoid most of the min and max-operations #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++ ) { - int j; - for(j = 0; j < halfwin-1; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; - if (fringe[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - for(; j < width-halfwin+1; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; + for(int i = 0; i < height; i++ ) { + int j; - if (fringe[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - for(; j < width; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; + for(j = 0; j < halfwin - 1; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; - if (fringe[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - } //end of ab channel averaging + if (fringe[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = 0; j1 < j + halfwin; j1++) { + //neighborhood average of pixels weighted by chrominance + wt = fringe[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + + for(; j < width - halfwin + 1; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; + + if (fringe[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < j + halfwin; j1++) { + //neighborhood average of pixels weighted by chrominance + wt = fringe[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + + for(; j < width; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; + + if (fringe[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < width; j1++) { + //neighborhood average of pixels weighted by chrominance + wt = fringe[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + } //end of ab channel averaging #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef __SSE2__ - int j; - __m128 interav, interbv; - __m128 piidv = _mm_set1_ps(piid); + int j; + __m128 interav, interbv; + __m128 piidv = _mm_set1_ps(piid); #endif #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++ ) { + + for(int i = 0; i < height; i++ ) { #ifdef __SSE2__ - for(j = 0; j < width-3; j+=4) { - _mm_storeu_ps( &dst->sh_p[i][j], LVFU(src->sh_p[i][j])); - interav = LVFU(tmaa[i][j]); - interbv = LVFU(tmbb[i][j]); - _mm_storeu_ps(&dst->h_p[i][j],(xatan2f(interbv,interav))/piidv); - _mm_storeu_ps(&dst->C_p[i][j],_mm_sqrt_ps(SQRV(interbv)+SQRV(interav))); - } - for(; j < width; j++) { - dst->sh_p[i][j] = src->sh_p[i][j]; - float intera = tmaa[i][j]; - float interb = tmbb[i][j]; - dst->h_p[i][j]=(xatan2f(interb,intera))/piid; - dst->C_p[i][j]=sqrt(SQR(interb)+SQR(intera)); - } + + for(j = 0; j < width - 3; j += 4) { + _mm_storeu_ps( &dst->sh_p[i][j], LVFU(src->sh_p[i][j])); + interav = LVFU(tmaa[i][j]); + interbv = LVFU(tmbb[i][j]); + _mm_storeu_ps(&dst->h_p[i][j], (xatan2f(interbv, interav)) / piidv); + _mm_storeu_ps(&dst->C_p[i][j], _mm_sqrt_ps(SQRV(interbv) + SQRV(interav))); + } + + for(; j < width; j++) { + dst->sh_p[i][j] = src->sh_p[i][j]; + float intera = tmaa[i][j]; + float interb = tmbb[i][j]; + dst->h_p[i][j] = (xatan2f(interb, intera)) / piid; + dst->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); + } + #else - for(int j = 0; j < width; j++) { - dst->sh_p[i][j] = src->sh_p[i][j]; - float intera = tmaa[i][j]; - float interb = tmbb[i][j]; - dst->h_p[i][j]=(xatan2f(interb,intera))/piid; - dst->C_p[i][j]=sqrt(SQR(interb)+SQR(intera)); - } + + for(int j = 0; j < width; j++) { + dst->sh_p[i][j] = src->sh_p[i][j]; + float intera = tmaa[i][j]; + float interb = tmbb[i][j]; + dst->h_p[i][j] = (xatan2f(interb, intera)) / piid; + dst->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); + } + #endif - } -} + } + } - for (int i=0; iW, height=src->H; - const float piid=3.14159265f/180.f; - float shfabs, shmed; + const int width = src->W, height = src->H; + const float piid = 3.14159265f / 180.f; + float shfabs, shmed; - int i1, j1, tot; - const float eps = 1.0f; - const float eps2 = 0.01f; - float shsum, dirsh, norm, sum; + int i1, j1, tot; + const float eps = 1.0f; + const float eps2 = 0.01f; + float shsum, dirsh, norm, sum; - float** sraa; - sraa = new float*[height]; - for (int i=0; ih_p[i][j])); - _mm_storeu_ps(&sraa[i][j],LVFU(src->C_p[i][j])*sincosvalv.y); - _mm_storeu_ps(&srbb[i][j],LVFU(src->C_p[i][j])*sincosvalv.x); - } - for (; jh_p[i][j]); - sraa[i][j]=src->C_p[i][j]*sincosval.y; - srbb[i][j]=src->C_p[i][j]*sincosval.x; - } + + for (j = 0; j < width - 3; j += 4) { + sincosvalv = xsincosf(piidv * LVFU(src->h_p[i][j])); + _mm_storeu_ps(&sraa[i][j], LVFU(src->C_p[i][j])*sincosvalv.y); + _mm_storeu_ps(&srbb[i][j], LVFU(src->C_p[i][j])*sincosvalv.x); + } + + for (; j < width; j++) { + sincosval = xsincosf(piid * src->h_p[i][j]); + sraa[i][j] = src->C_p[i][j] * sincosval.y; + srbb[i][j] = src->C_p[i][j] * sincosval.x; + } + #else - for (int j=0; jh_p[i][j]); - sraa[i][j]=src->C_p[i][j]*sincosval.y; - srbb[i][j]=src->C_p[i][j]*sincosval.x; - } + + for (int j = 0; j < width; j++) { + sincosval = xsincosf(piid * src->h_p[i][j]); + sraa[i][j] = src->C_p[i][j] * sincosval.y; + srbb[i][j] = src->C_p[i][j] * sincosval.x; + } + #endif - } -} + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - AlignedBufferMP buffer(max(src->W,src->H)); - //chroma a and b - if(mode==2) {//choice of gaussian blur - gaussHorizontal (sraa, tmaa, buffer, src->W, src->H, radius); - gaussHorizontal (srbb, tmbb, buffer, src->W, src->H, radius); - gaussVertical (tmaa, tmaa, buffer, src->W, src->H, radius); - gaussVertical (tmbb, tmbb, buffer, src->W, src->H, radius); - } - //luma sh_p - gaussHorizontal (src->sh_p, tmL, buffer, src->W, src->H, 2.0);//low value to avoid artifacts - gaussVertical (tmL, tmL, buffer, src->W, src->H, 2.0); - } + { + AlignedBufferMP buffer(max(src->W, src->H)); -if(mode==1){ //choice of median -#pragma omp parallel - { - int ip,in,jp,jn; - float pp[9],temp; -#pragma omp for nowait //nowait because next loop inside this parallel region is independent on this one - for (int i=0; iheight-3) {in=i-2;} else {in=i+2;} - for (int j=0; jwidth-3) {jn=j-2;} else {jn=j+2;} - med3(sraa[ip][jp],sraa[ip][j],sraa[ip][jn],sraa[i][jp],sraa[i][j],sraa[i][jn],sraa[in][jp],sraa[in][j],sraa[in][jn],tmaa[i][j]); - } - } -#pragma omp for - for (int i=0; iheight-3) {in=i-2;} else {in=i+2;} - for (int j=0; jwidth-3) {jn=j-2;} else {jn=j+2;} - med3(srbb[ip][jp],srbb[ip][j],srbb[ip][jn],srbb[i][jp],srbb[i][j],srbb[i][jn],srbb[in][jp],srbb[in][j],srbb[in][jn],tmbb[i][j]); - } - } - } -} + //chroma a and b + if(mode == 2) { //choice of gaussian blur + gaussHorizontal (sraa, tmaa, buffer, src->W, src->H, radius); + gaussHorizontal (srbb, tmbb, buffer, src->W, src->H, radius); + gaussVertical (tmaa, tmaa, buffer, src->W, src->H, radius); + gaussVertical (tmbb, tmbb, buffer, src->W, src->H, radius); + } -//luma badpixels - const float sh_thr = 4.5f;//low value for luma sh_p to avoid artifacts - const float shthr = sh_thr / 24.0f; + //luma sh_p + gaussHorizontal (src->sh_p, tmL, buffer, src->W, src->H, 2.0);//low value to avoid artifacts + gaussVertical (tmL, tmL, buffer, src->W, src->H, 2.0); + } + + if(mode == 1) { //choice of median + #pragma omp parallel + { + int ip, in, jp, jn; + float pp[9], temp; + #pragma omp for nowait //nowait because next loop inside this parallel region is independent on this one + + for (int i = 0; i < height; i++) { + if (i < 2) { + ip = i + 2; + } else { + ip = i - 2; + } + + if (i > height - 3) { + in = i - 2; + } else { + in = i + 2; + } + + for (int j = 0; j < width; j++) { + if (j < 2) { + jp = j + 2; + } else { + jp = j - 2; + } + + if (j > width - 3) { + jn = j - 2; + } else { + jn = j + 2; + } + + med3(sraa[ip][jp], sraa[ip][j], sraa[ip][jn], sraa[i][jp], sraa[i][j], sraa[i][jn], sraa[in][jp], sraa[in][j], sraa[in][jn], tmaa[i][j]); + } + } + + #pragma omp for + + for (int i = 0; i < height; i++) { + if (i < 2) { + ip = i + 2; + } else { + ip = i - 2; + } + + if (i > height - 3) { + in = i - 2; + } else { + in = i + 2; + } + + for (int j = 0; j < width; j++) { + if (j < 2) { + jp = j + 2; + } else { + jp = j - 2; + } + + if (j > width - 3) { + jn = j - 2; + } else { + jn = j + 2; + } + + med3(srbb[ip][jp], srbb[ip][j], srbb[ip][jn], srbb[i][jp], srbb[i][j], srbb[i][jn], srbb[in][jp], srbb[in][j], srbb[in][jn], tmbb[i][j]); + } + } + } + } + +//luma badpixels + const float sh_thr = 4.5f;//low value for luma sh_p to avoid artifacts + const float shthr = sh_thr / 24.0f; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; + { + int j; #ifdef __SSE2__ - __m128 shfabsv, shmedv; - __m128 shthrv = _mm_set1_ps(shthr); - __m128 onev = _mm_set1_ps(1.0f); + __m128 shfabsv, shmedv; + __m128 shthrv = _mm_set1_ps(shthr); + __m128 onev = _mm_set1_ps(1.0f); #endif // __SSE2__ #ifdef _OPENMP -#pragma omp for private(shfabs, shmed,i1,j1) + #pragma omp for private(shfabs, shmed,i1,j1) #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - shfabs = fabs(src->sh_p[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++ ) { - shmed += fabs(src->sh_p[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } - + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + shfabs = fabs(src->sh_p[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++ ) { + shmed += fabs(src->sh_p[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + #ifdef __SSE2__ - for (; j < width-5; j+=4) { - shfabsv = vabsf(LVFU(src->sh_p[i][j])-LVFU(tmL[i][j])); - shmedv = _mm_setzero_ps(); - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - shmedv += vabsf(LVFU(src->sh_p[i1][j1])-LVFU(tmL[i1][j1])); - } - _mm_storeu_ps( &badpix[i*width+j], vself(vmaskf_gt(shfabsv,(shmedv - shfabsv)*shthrv), onev, _mm_setzero_ps())); - } - for (; j < width-2; j++) { - shfabs = fabs(src->sh_p[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - shmed += fabs(src->sh_p[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } + + for (; j < width - 5; j += 4) { + shfabsv = vabsf(LVFU(src->sh_p[i][j]) - LVFU(tmL[i][j])); + shmedv = _mm_setzero_ps(); + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + shmedv += vabsf(LVFU(src->sh_p[i1][j1]) - LVFU(tmL[i1][j1])); + } + + _mm_storeu_ps( &badpix[i * width + j], vself(vmaskf_gt(shfabsv, (shmedv - shfabsv)*shthrv), onev, _mm_setzero_ps())); + } + + for (; j < width - 2; j++) { + shfabs = fabs(src->sh_p[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + shmed += fabs(src->sh_p[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + #else - for (; j < width-2; j++) { - shfabs = fabs(src->sh_p[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - shmed += fabs(src->sh_p[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } + + for (; j < width - 2; j++) { + shfabs = fabs(src->sh_p[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + shmed += fabs(src->sh_p[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + #endif - for (; j < width; j++) { - shfabs = fabs(src->sh_p[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1sh_p[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } - } -} + + for (; j < width; j++) { + shfabs = fabs(src->sh_p[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + shmed += fabs(src->sh_p[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; + { + int j; #ifdef _OPENMP -#pragma omp for private(shsum,norm,dirsh,sum,i1,j1) schedule(dynamic,16) + #pragma omp for private(shsum,norm,dirsh,sum,i1,j1) schedule(dynamic,16) #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - if (!badpix[i*width+j]) continue; - norm=0.0f; - shsum=0.0f; - sum=0.0f; - tot=0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (badpix[i1*width+j1]) continue; - sum += src->sh_p[i1][j1]; - tot++; - dirsh = 1.f/(SQR(src->sh_p[i1][j1]-src->sh_p[i][j])+eps); - shsum += dirsh*src->sh_p[i1][j1]; - norm += dirsh; - } - if (norm > 0.f) { - src->sh_p[i][j]=shsum/norm; - } - else { - if(tot > 0) src->sh_p[i][j]=sum / tot; - } - } - for (; j < width-2; j++) { - if (!badpix[i*width+j]) continue; - norm=0.0f; - shsum=0.0f; - sum=0.0f; - tot=0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (badpix[i1*width+j1]) continue; - sum += src->sh_p[i1][j1]; - tot++; - dirsh = 1.f/(SQR(src->sh_p[i1][j1]-src->sh_p[i][j])+eps); - shsum += dirsh*src->sh_p[i1][j1]; - norm += dirsh; - } - if (norm > 0.f) { - src->sh_p[i][j]=shsum/norm; - } - else { - if(tot > 0) src->sh_p[i][j]=sum / tot; - } - } - for (; j < width; j++) { - if (!badpix[i*width+j]) continue; - norm=0.0f; - shsum=0.0f; - sum=0.0f; - tot=0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1sh_p[i1][j1]; - tot++; - dirsh = 1.f/(SQR(src->sh_p[i1][j1]-src->sh_p[i][j])+eps); - shsum += dirsh*src->sh_p[i1][j1]; - norm += dirsh; - } - if (norm > 0.f) { - src->sh_p[i][j]=shsum/norm; - } - else { - if(tot > 0) src->sh_p[i][j]=sum / tot; - } - } - } -} -// end luma badpixels + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + if (!badpix[i * width + j]) { + continue; + } + + norm = 0.0f; + shsum = 0.0f; + sum = 0.0f; + tot = 0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (badpix[i1 * width + j1]) { + continue; + } + + sum += src->sh_p[i1][j1]; + tot++; + dirsh = 1.f / (SQR(src->sh_p[i1][j1] - src->sh_p[i][j]) + eps); + shsum += dirsh * src->sh_p[i1][j1]; + norm += dirsh; + } + + if (norm > 0.f) { + src->sh_p[i][j] = shsum / norm; + } else { + if(tot > 0) { + src->sh_p[i][j] = sum / tot; + } + } + } + + for (; j < width - 2; j++) { + if (!badpix[i * width + j]) { + continue; + } + + norm = 0.0f; + shsum = 0.0f; + sum = 0.0f; + tot = 0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (badpix[i1 * width + j1]) { + continue; + } + + sum += src->sh_p[i1][j1]; + tot++; + dirsh = 1.f / (SQR(src->sh_p[i1][j1] - src->sh_p[i][j]) + eps); + shsum += dirsh * src->sh_p[i1][j1]; + norm += dirsh; + } + + if (norm > 0.f) { + src->sh_p[i][j] = shsum / norm; + } else { + if(tot > 0) { + src->sh_p[i][j] = sum / tot; + } + } + } + + for (; j < width; j++) { + if (!badpix[i * width + j]) { + continue; + } + + norm = 0.0f; + shsum = 0.0f; + sum = 0.0f; + tot = 0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (badpix[i1 * width + j1]) { + continue; + } + + sum += src->sh_p[i1][j1]; + tot++; + dirsh = 1.f / (SQR(src->sh_p[i1][j1] - src->sh_p[i][j]) + eps); + shsum += dirsh * src->sh_p[i1][j1]; + norm += dirsh; + } + + if (norm > 0.f) { + src->sh_p[i][j] = shsum / norm; + } else { + if(tot > 0) { + src->sh_p[i][j] = sum / tot; + } + } + } + } + } +// end luma badpixels // begin chroma badpixels -float chrommed=0.f; + float chrommed = 0.f; #ifdef _OPENMP -#pragma omp parallel for reduction(+:chrommed) + #pragma omp parallel for reduction(+:chrommed) #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - float chroma =SQR(sraa[i][j]-tmaa[i][j])+SQR(srbb[i][j]-tmbb[i][j]); - chrommed += chroma; - badpix[i*width+j]=chroma; - } - } - chrommed /= (height*width); - float threshfactor = (thresh*chrommed)/33.f; + + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + float chroma = SQR(sraa[i][j] - tmaa[i][j]) + SQR(srbb[i][j] - tmbb[i][j]); + chrommed += chroma; + badpix[i * width + j] = chroma; + } + } + + chrommed /= (height * width); + float threshfactor = (thresh * chrommed) / 33.f; // now chrommed is calculated, so we postprocess badpix to reduce the number of divisions in future #ifdef __SSE2__ #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; - __m128 sumv = _mm_set1_ps( chrommed + eps2 ); - __m128 onev = _mm_set1_ps( 1.0f ); + { + int j; + __m128 sumv = _mm_set1_ps( chrommed + eps2 ); + __m128 onev = _mm_set1_ps( 1.0f ); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - for(; j < width-halfwin; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; + for(int i = 0; i < height; i++ ) { + for(j = 0; j < halfwin; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; - if (badpix[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - for(; j < width; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; + if (badpix[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; - if (badpix[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - } -} + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = 0; j1 < j + halfwin; j1++) { + wt = badpix[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + + for(; j < width - halfwin; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; + + if (badpix[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < j + halfwin; j1++) { + wt = badpix[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + + for(; j < width; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; + + if (badpix[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < width; j1++) { + wt = badpix[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - float intera = tmaa[i][j]; - float interb = tmbb[i][j]; - float CC=sqrt(SQR(interb)+SQR(intera)); - if(hotbad==0) { - if(CC < chrom && skinprot !=0.f){ - dst->h_p[i][j]=(xatan2f(interb,intera))/piid; - dst->C_p[i][j]=sqrt(SQR(interb)+SQR(intera)); - } - } - else { - dst->h_p[i][j]=(xatan2f(interb,intera))/piid; - dst->C_p[i][j]=sqrt(SQR(interb)+SQR(intera)); - } - } - } -} - if(src != dst) { + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + float intera = tmaa[i][j]; + float interb = tmbb[i][j]; + float CC = sqrt(SQR(interb) + SQR(intera)); + + if(hotbad == 0) { + if(CC < chrom && skinprot != 0.f) { + dst->h_p[i][j] = (xatan2f(interb, intera)) / piid; + dst->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); + } + } else { + dst->h_p[i][j] = (xatan2f(interb, intera)) / piid; + dst->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); + } + } + } + } + + if(src != dst) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int i = 0; i < height; i++ ) - for(int j = 0; j < width; j++) - dst->sh_p[i][j] = src->sh_p[i][j]; - } + + for(int i = 0; i < height; i++ ) + for(int j = 0; j < width; j++) { + dst->sh_p[i][j] = src->sh_p[i][j]; + } + } - for (int i=0; iverbose ) - printf("Ciecam badpixels:- %d usec\n", t2.etime(t1)); - - + + if( settings->verbose ) { + printf("Ciecam badpixels:- %d usec\n", t2.etime(t1)); + } + + } SSEFUNCTION void ImProcFunctions::BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom) { - const int halfwin = ceil(2*radius)+1; - MyTime t1,t2; + const int halfwin = ceil(2 * radius) + 1; + MyTime t1, t2; t1.set(); - const int width=src->W, height=src->H; -// const float piid=3.14159265f/180.f; - float shfabs, shmed; + const int width = src->W, height = src->H; +// const float piid=3.14159265f/180.f; + float shfabs, shmed; - int i1, j1, tot; - const float eps = 1.0f; - const float eps2 = 0.01f; - float shsum, dirsh, norm, sum; + int i1, j1, tot; + const float eps = 1.0f; + const float eps2 = 0.01f; + float shsum, dirsh, norm, sum; - float** sraa; - sraa = new float*[height]; - for (int i=0; ia[i][j])); - _mm_storeu_ps(&srbb[i][j],LVFU(src->b[i][j])); - } - for (; ja[i][j]; - srbb[i][j]=src->b[i][j]; - } + + for (j = 0; j < width - 3; j += 4) { + _mm_storeu_ps(&sraa[i][j], LVFU(src->a[i][j])); + _mm_storeu_ps(&srbb[i][j], LVFU(src->b[i][j])); + } + + for (; j < width; j++) { + sraa[i][j] = src->a[i][j]; + srbb[i][j] = src->b[i][j]; + } + #else - for (int j=0; ja[i][j]; - srbb[i][j]=src->b[i][j]; - } + + for (int j = 0; j < width; j++) { + sraa[i][j] = src->a[i][j]; + srbb[i][j] = src->b[i][j]; + } + #endif - } -} + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - AlignedBufferMP buffer(max(src->W,src->H)); - //chroma a and b - if(mode>=2) {//choice of gaussian blur - gaussHorizontal (sraa, tmaa, buffer, src->W, src->H, radius); - gaussHorizontal (srbb, tmbb, buffer, src->W, src->H, radius); - gaussVertical (tmaa, tmaa, buffer, src->W, src->H, radius); - gaussVertical (tmbb, tmbb, buffer, src->W, src->H, radius); - } - //luma sh_p - gaussHorizontal (src->L, tmL, buffer, src->W, src->H, 2.0);//low value to avoid artifacts - gaussVertical (tmL, tmL, buffer, src->W, src->H, 2.0); - } + { + AlignedBufferMP buffer(max(src->W, src->H)); -if(mode==1){ //choice of median -#pragma omp parallel - { - int ip,in,jp,jn; - float pp[9],temp; -#pragma omp for nowait //nowait because next loop inside this parallel region is independent on this one - for (int i=0; iheight-3) {in=i-2;} else {in=i+2;} - for (int j=0; jwidth-3) {jn=j-2;} else {jn=j+2;} - med3(sraa[ip][jp],sraa[ip][j],sraa[ip][jn],sraa[i][jp],sraa[i][j],sraa[i][jn],sraa[in][jp],sraa[in][j],sraa[in][jn],tmaa[i][j]); - } - } -#pragma omp for - for (int i=0; iheight-3) {in=i-2;} else {in=i+2;} - for (int j=0; jwidth-3) {jn=j-2;} else {jn=j+2;} - med3(srbb[ip][jp],srbb[ip][j],srbb[ip][jn],srbb[i][jp],srbb[i][j],srbb[i][jn],srbb[in][jp],srbb[in][j],srbb[in][jn],tmbb[i][j]); - } - } - } -} + //chroma a and b + if(mode >= 2) { //choice of gaussian blur + gaussHorizontal (sraa, tmaa, buffer, src->W, src->H, radius); + gaussHorizontal (srbb, tmbb, buffer, src->W, src->H, radius); + gaussVertical (tmaa, tmaa, buffer, src->W, src->H, radius); + gaussVertical (tmbb, tmbb, buffer, src->W, src->H, radius); + } -//luma badpixels - const float sh_thr = 4.5f;//low value for luma sh_p to avoid artifacts - const float shthr = sh_thr / 24.0f; + //luma sh_p + gaussHorizontal (src->L, tmL, buffer, src->W, src->H, 2.0);//low value to avoid artifacts + gaussVertical (tmL, tmL, buffer, src->W, src->H, 2.0); + } + + if(mode == 1) { //choice of median + #pragma omp parallel + { + int ip, in, jp, jn; + float pp[9], temp; + #pragma omp for nowait //nowait because next loop inside this parallel region is independent on this one + + for (int i = 0; i < height; i++) { + if (i < 2) { + ip = i + 2; + } else { + ip = i - 2; + } + + if (i > height - 3) { + in = i - 2; + } else { + in = i + 2; + } + + for (int j = 0; j < width; j++) { + if (j < 2) { + jp = j + 2; + } else { + jp = j - 2; + } + + if (j > width - 3) { + jn = j - 2; + } else { + jn = j + 2; + } + + med3(sraa[ip][jp], sraa[ip][j], sraa[ip][jn], sraa[i][jp], sraa[i][j], sraa[i][jn], sraa[in][jp], sraa[in][j], sraa[in][jn], tmaa[i][j]); + } + } + + #pragma omp for + + for (int i = 0; i < height; i++) { + if (i < 2) { + ip = i + 2; + } else { + ip = i - 2; + } + + if (i > height - 3) { + in = i - 2; + } else { + in = i + 2; + } + + for (int j = 0; j < width; j++) { + if (j < 2) { + jp = j + 2; + } else { + jp = j - 2; + } + + if (j > width - 3) { + jn = j - 2; + } else { + jn = j + 2; + } + + med3(srbb[ip][jp], srbb[ip][j], srbb[ip][jn], srbb[i][jp], srbb[i][j], srbb[i][jn], srbb[in][jp], srbb[in][j], srbb[in][jn], tmbb[i][j]); + } + } + } + } + +//luma badpixels + const float sh_thr = 4.5f;//low value for luma sh_p to avoid artifacts + const float shthr = sh_thr / 24.0f; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; + { + int j; #ifdef __SSE2__ - __m128 shfabsv, shmedv; - __m128 shthrv = _mm_set1_ps(shthr); - __m128 onev = _mm_set1_ps(1.0f); + __m128 shfabsv, shmedv; + __m128 shthrv = _mm_set1_ps(shthr); + __m128 onev = _mm_set1_ps(1.0f); #endif // __SSE2__ #ifdef _OPENMP -#pragma omp for private(shfabs, shmed,i1,j1) + #pragma omp for private(shfabs, shmed,i1,j1) #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - shfabs = fabs(src->L[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++ ) { - shmed += fabs(src->L[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } - + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + shfabs = fabs(src->L[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++ ) { + shmed += fabs(src->L[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + #ifdef __SSE2__ - for (; j < width-5; j+=4) { - shfabsv = vabsf(LVFU(src->L[i][j])-LVFU(tmL[i][j])); - shmedv = _mm_setzero_ps(); - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - shmedv += vabsf(LVFU(src->L[i1][j1])-LVFU(tmL[i1][j1])); - } - _mm_storeu_ps( &badpix[i*width+j], vself(vmaskf_gt(shfabsv,(shmedv - shfabsv)*shthrv), onev, _mm_setzero_ps())); - } - for (; j < width-2; j++) { - shfabs = fabs(src->L[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - shmed += fabs(src->L[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } + + for (; j < width - 5; j += 4) { + shfabsv = vabsf(LVFU(src->L[i][j]) - LVFU(tmL[i][j])); + shmedv = _mm_setzero_ps(); + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + shmedv += vabsf(LVFU(src->L[i1][j1]) - LVFU(tmL[i1][j1])); + } + + _mm_storeu_ps( &badpix[i * width + j], vself(vmaskf_gt(shfabsv, (shmedv - shfabsv)*shthrv), onev, _mm_setzero_ps())); + } + + for (; j < width - 2; j++) { + shfabs = fabs(src->L[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + shmed += fabs(src->L[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + #else - for (; j < width-2; j++) { - shfabs = fabs(src->L[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - shmed += fabs(src->L[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } + + for (; j < width - 2; j++) { + shfabs = fabs(src->L[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + shmed += fabs(src->L[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + #endif - for (; j < width; j++) { - shfabs = fabs(src->L[i][j]-tmL[i][j]); - shmed=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1L[i1][j1]-tmL[i1][j1]); - } - badpix[i*width+j] = (shfabs>((shmed-shfabs)*shthr)); - } - } -} + + for (; j < width; j++) { + shfabs = fabs(src->L[i][j] - tmL[i][j]); + shmed = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + shmed += fabs(src->L[i1][j1] - tmL[i1][j1]); + } + + badpix[i * width + j] = (shfabs > ((shmed - shfabs) * shthr)); + } + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; + { + int j; #ifdef _OPENMP -#pragma omp for private(shsum,norm,dirsh,sum,i1,j1) schedule(dynamic,16) + #pragma omp for private(shsum,norm,dirsh,sum,i1,j1) schedule(dynamic,16) #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - if (!badpix[i*width+j]) continue; - norm=0.0f; - shsum=0.0f; - sum=0.0f; - tot=0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (badpix[i1*width+j1]) continue; - sum += src->L[i1][j1]; - tot++; - dirsh = 1.f/(SQR(src->L[i1][j1]-src->L[i][j])+eps); - shsum += dirsh*src->L[i1][j1]; - norm += dirsh; - } - if (norm > 0.f) { - src->L[i][j]=shsum/norm; - } - else { - if(tot > 0) src->L[i][j]=sum / tot; - } - } - for (; j < width-2; j++) { - if (!badpix[i*width+j]) continue; - norm=0.0f; - shsum=0.0f; - sum=0.0f; - tot=0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (badpix[i1*width+j1]) continue; - sum += src->L[i1][j1]; - tot++; - dirsh = 1.f/(SQR(src->L[i1][j1]-src->L[i][j])+eps); - shsum += dirsh*src->L[i1][j1]; - norm += dirsh; - } - if (norm > 0.f) { - src->L[i][j]=shsum/norm; - } - else { - if(tot > 0) src->L[i][j]=sum / tot; - } - } - for (; j < width; j++) { - if (!badpix[i*width+j]) continue; - norm=0.0f; - shsum=0.0f; - sum=0.0f; - tot=0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1L[i1][j1]; - tot++; - dirsh = 1.f/(SQR(src->L[i1][j1]-src->L[i][j])+eps); - shsum += dirsh*src->L[i1][j1]; - norm += dirsh; - } - if (norm > 0.f) { - src->L[i][j]=shsum/norm; - } - else { - if(tot > 0) src->L[i][j]=sum / tot; - } - } - } -} -// end luma badpixels -if(mode==3) { + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + if (!badpix[i * width + j]) { + continue; + } + + norm = 0.0f; + shsum = 0.0f; + sum = 0.0f; + tot = 0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (badpix[i1 * width + j1]) { + continue; + } + + sum += src->L[i1][j1]; + tot++; + dirsh = 1.f / (SQR(src->L[i1][j1] - src->L[i][j]) + eps); + shsum += dirsh * src->L[i1][j1]; + norm += dirsh; + } + + if (norm > 0.f) { + src->L[i][j] = shsum / norm; + } else { + if(tot > 0) { + src->L[i][j] = sum / tot; + } + } + } + + for (; j < width - 2; j++) { + if (!badpix[i * width + j]) { + continue; + } + + norm = 0.0f; + shsum = 0.0f; + sum = 0.0f; + tot = 0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (badpix[i1 * width + j1]) { + continue; + } + + sum += src->L[i1][j1]; + tot++; + dirsh = 1.f / (SQR(src->L[i1][j1] - src->L[i][j]) + eps); + shsum += dirsh * src->L[i1][j1]; + norm += dirsh; + } + + if (norm > 0.f) { + src->L[i][j] = shsum / norm; + } else { + if(tot > 0) { + src->L[i][j] = sum / tot; + } + } + } + + for (; j < width; j++) { + if (!badpix[i * width + j]) { + continue; + } + + norm = 0.0f; + shsum = 0.0f; + sum = 0.0f; + tot = 0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (badpix[i1 * width + j1]) { + continue; + } + + sum += src->L[i1][j1]; + tot++; + dirsh = 1.f / (SQR(src->L[i1][j1] - src->L[i][j]) + eps); + shsum += dirsh * src->L[i1][j1]; + norm += dirsh; + } + + if (norm > 0.f) { + src->L[i][j] = shsum / norm; + } else { + if(tot > 0) { + src->L[i][j] = sum / tot; + } + } + } + } + } +// end luma badpixels + + if(mode == 3) { // begin chroma badpixels -float chrommed=0.f; + float chrommed = 0.f; #ifdef _OPENMP -#pragma omp parallel for reduction(+:chrommed) + #pragma omp parallel for reduction(+:chrommed) #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - float chroma =SQR(sraa[i][j]-tmaa[i][j])+SQR(srbb[i][j]-tmbb[i][j]); - chrommed += chroma; - badpix[i*width+j]=chroma; - } - } - chrommed /= (height*width); - float threshfactor = (thresh*chrommed)/33.f; + + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + float chroma = SQR(sraa[i][j] - tmaa[i][j]) + SQR(srbb[i][j] - tmbb[i][j]); + chrommed += chroma; + badpix[i * width + j] = chroma; + } + } + + chrommed /= (height * width); + float threshfactor = (thresh * chrommed) / 33.f; // now chrommed is calculated, so we postprocess badpix to reduce the number of divisions in future #ifdef __SSE2__ #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; - __m128 sumv = _mm_set1_ps( chrommed + eps2 ); - __m128 onev = _mm_set1_ps( 1.0f ); + { + int j; + __m128 sumv = _mm_set1_ps( chrommed + eps2 ); + __m128 onev = _mm_set1_ps( 1.0f ); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - for(; j < width-halfwin; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; + for(int i = 0; i < height; i++ ) { + for(j = 0; j < halfwin; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; - if (badpix[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - for(; j < width; j++) { - tmaa[i][j] = sraa[i][j]; - tmbb[i][j] = srbb[i][j]; + if (badpix[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; - if (badpix[i*width+j] 0.f){ - tmaa[i][j] = (atot/norm); - tmbb[i][j] = (btot/norm); - } - } - } - } -} + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = 0; j1 < j + halfwin; j1++) { + wt = badpix[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + + for(; j < width - halfwin; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; + + if (badpix[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < j + halfwin; j1++) { + wt = badpix[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + + for(; j < width; j++) { + tmaa[i][j] = sraa[i][j]; + tmbb[i][j] = srbb[i][j]; + + if (badpix[i * width + j] < threshfactor) { + float atot = 0.f; + float btot = 0.f; + float norm = 0.f; + float wt; + + for (int i1 = max(0, i - halfwin + 1); i1 < min(height, i + halfwin); i1++) + for (int j1 = j - halfwin + 1; j1 < width; j1++) { + wt = badpix[i1 * width + j1]; + atot += wt * sraa[i1][j1]; + btot += wt * srbb[i1][j1]; + norm += wt; + } + + if(norm > 0.f) { + tmaa[i][j] = (atot / norm); + tmbb[i][j] = (btot / norm); + } + } + } + } + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++ ) { - for(int j = 0; j < width; j++) { - float intera = tmaa[i][j]; - float interb = tmbb[i][j]; - float CC=sqrt(SQR(interb/327.68)+SQR(intera/327.68f)); - if(CC < chrom && skinprot !=0.f){ - dst->a[i][j]=intera; - dst->b[i][j]=interb; - } - } - } -} -} - if(src != dst) { + + for(int i = 0; i < height; i++ ) { + for(int j = 0; j < width; j++) { + float intera = tmaa[i][j]; + float interb = tmbb[i][j]; + float CC = sqrt(SQR(interb / 327.68) + SQR(intera / 327.68f)); + + if(CC < chrom && skinprot != 0.f) { + dst->a[i][j] = intera; + dst->b[i][j] = interb; + } + } + } + } + } + + if(src != dst) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int i = 0; i < height; i++ ) - for(int j = 0; j < width; j++) - dst->L[i][j] = src->L[i][j]; - } + + for(int i = 0; i < height; i++ ) + for(int j = 0; j < width; j++) { + dst->L[i][j] = src->L[i][j]; + } + } - for (int i=0; iverbose ) - printf("Lab artifacts:- %d usec\n", t2.etime(t1)); - - + + if( settings->verbose ) { + printf("Lab artifacts:- %d usec\n", t2.etime(t1)); + } + + } } diff --git a/rtengine/StopWatch.h b/rtengine/StopWatch.h index 468f0817c..fa043aa24 100644 --- a/rtengine/StopWatch.h +++ b/rtengine/StopWatch.h @@ -7,7 +7,7 @@ * 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 @@ -20,36 +20,50 @@ */ #ifndef STOPWATCH_H -#define STOPWATCH_H +#define STOPWATCH_H #include #include "mytime.h" -class StopWatch { +class StopWatch +{ public: - StopWatch( ) { stopped = false; } - StopWatch( const char* msg) { message = msg; start(); stopped = false; } - ~StopWatch() { if(!stopped) stop(); } + StopWatch( ) + { + stopped = false; + } + StopWatch( const char* msg) + { + message = msg; + start(); + stopped = false; + } + ~StopWatch() + { + if(!stopped) { + stop(); + } + } void start() { - startTime.set(); + startTime.set(); }; void stop() { - stopTime.set(); - long elapsedTime = stopTime.etime(startTime) / 1000; - std::cout << message << " took " << elapsedTime << " ms" < class AlignedBuffer { +template class AlignedBuffer +{ private: void* real ; @@ -37,23 +38,29 @@ public: T* data ; bool inUse; - /** @brief Allocate aligned memory - * @param size Number of elements of size T to allocate, i.e. allocated size will be sizeof(T)*size ; set it to 0 if you want to defer the allocation - * @param align Expressed in bytes; SSE instructions need 128 bits alignment, which mean 16 bytes, which is the default value - */ - AlignedBuffer (size_t size=0, size_t align=16) : real(NULL), alignment(align), allocatedSize(0), unitSize(0), data(NULL), inUse(false) { - if (size) + /** @brief Allocate aligned memory + * @param size Number of elements of size T to allocate, i.e. allocated size will be sizeof(T)*size ; set it to 0 if you want to defer the allocation + * @param align Expressed in bytes; SSE instructions need 128 bits alignment, which mean 16 bytes, which is the default value + */ + AlignedBuffer (size_t size = 0, size_t align = 16) : real(NULL), alignment(align), allocatedSize(0), unitSize(0), data(NULL), inUse(false) + { + if (size) { resize(size); + } } - ~AlignedBuffer () { - if (real) free(real); + ~AlignedBuffer () + { + if (real) { + free(real); + } } /** @brief Return true if there's no memory allocated */ - bool isEmpty() { - return allocatedSize==0; + bool isEmpty() + { + return allocatedSize == 0; } /** @brief Allocate the the "size" amount of elements of "structSize" length each @@ -61,39 +68,44 @@ public: * @param structSize if non null, will let you override the default struct's size (unit: byte) * @return True is everything went fine, including freeing memory when size==0, false if the allocation failed */ - bool resize(size_t size, int structSize=0) { + bool resize(size_t size, int structSize = 0) + { if (allocatedSize != size) { if (!size) { // The user want to free the memory - if (real) free(real); + if (real) { + free(real); + } + real = NULL; data = NULL; inUse = false; allocatedSize = 0; unitSize = 0; - } - else { + } else { unitSize = structSize ? structSize : sizeof(T); size_t oldAllocatedSize = allocatedSize; - allocatedSize = size*unitSize; + allocatedSize = size * unitSize; // realloc were used here to limit memory fragmentation, specially when the size was smaller than the previous one. // But realloc copies the content to the eventually new location, which is unnecessary. To avoid this performance penalty, // we're freeing the memory and allocate it again if the new size is bigger. - if (allocatedSize < oldAllocatedSize) - real = realloc(real, allocatedSize+alignment); - else { - if (real) free (real); - real = malloc(allocatedSize+alignment); + if (allocatedSize < oldAllocatedSize) { + real = realloc(real, allocatedSize + alignment); + } else { + if (real) { + free (real); + } + + real = malloc(allocatedSize + alignment); } if (real) { //data = (T*)( (uintptr_t)real + (alignment-((uintptr_t)real)%alignment) ); - data = (T*)( ( uintptr_t(real) + uintptr_t(alignment-1)) / alignment * alignment); + data = (T*)( ( uintptr_t(real) + uintptr_t(alignment - 1)) / alignment * alignment); inUse = true; - } - else { + } else { allocatedSize = 0; unitSize = 0; data = NULL; @@ -102,10 +114,12 @@ public: } } } + return true; } - void swap(AlignedBuffer &other) { + void swap(AlignedBuffer &other) + { void *tmpReal = other.real; other.real = real; real = tmpReal; @@ -127,49 +141,57 @@ public: inUse = tmpInUse; } - unsigned int getSize() { - return unitSize ? allocatedSize/unitSize : 0; + unsigned int getSize() + { + return unitSize ? allocatedSize / unitSize : 0; } }; // Multi processor version, use with OpenMP -template class AlignedBufferMP { +template class AlignedBufferMP +{ private: MyMutex mtx; std::vector*> buffers; size_t size; public: - AlignedBufferMP(size_t sizeP) { - size=sizeP; + AlignedBufferMP(size_t sizeP) + { + size = sizeP; } - ~AlignedBufferMP() { - for (size_t i=0;i* acquire() { + AlignedBuffer* acquire() + { MyMutex::MyLock lock(mtx); // Find available buffer - for (size_t i=0;iinUse) { - buffers[i]->inUse=true; + buffers[i]->inUse = true; return buffers[i]; } } // Add new buffer if nothing is free - AlignedBuffer* buffer=new AlignedBuffer(size); + AlignedBuffer* buffer = new AlignedBuffer(size); buffers.push_back(buffer); return buffer; } - void release(AlignedBuffer* buffer) { - MyMutex::MyLock lock(mtx); + void release(AlignedBuffer* buffer) + { + MyMutex::MyLock lock(mtx); - buffer->inUse=false; + buffer->inUse = false; } }; #endif diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index 016e8e458..10a3687e6 100644 --- a/rtengine/amaze_demosaic_RT.cc +++ b/rtengine/amaze_demosaic_RT.cc @@ -1,26 +1,26 @@ //////////////////////////////////////////////////////////////// // -// AMaZE demosaic algorithm +// AMaZE demosaic algorithm // (Aliasing Minimization and Zipper Elimination) // -// copyright (c) 2008-2010 Emil Martinec +// copyright (c) 2008-2010 Emil Martinec // // incorporating ideas of Luis Sanz Rodrigues and Paul Lee // // code dated: May 27, 2010 // -// amaze_interpolate_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// amaze_interpolate_RT.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -32,1387 +32,1619 @@ #include "sleef.c" #include "opthelper.h" -namespace rtengine { +namespace rtengine +{ -SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { +SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) +{ #define HCLIP(x) x //is this still necessary??? - //min(clip_pt,x) + //min(clip_pt,x) - int width=winw, height=winh; + int width = winw, height = winh; - const float clip_pt = 1/initialGain; - const float clip_pt8 = 0.8f/initialGain; + const float clip_pt = 1 / initialGain; + const float clip_pt8 = 0.8f / initialGain; -#define TS 160 // Tile size; the image is processed in square tiles to lower memory requirements and facilitate multi-threading -#define TSH 80 // half of Tile size +#define TS 160 // Tile size; the image is processed in square tiles to lower memory requirements and facilitate multi-threading +#define TSH 80 // half of Tile size - // local variables + // local variables - //offset of R pixel within a Bayer quartet - int ex, ey; + //offset of R pixel within a Bayer quartet + int ex, ey; - //shifts of pointer value to access pixels in vertical and diagonal directions - static const int v1=TS, v2=2*TS, v3=3*TS, p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3; + //shifts of pointer value to access pixels in vertical and diagonal directions + static const int v1 = TS, v2 = 2 * TS, v3 = 3 * TS, p1 = -TS + 1, p2 = -2 * TS + 2, p3 = -3 * TS + 3, m1 = TS + 1, m2 = 2 * TS + 2, m3 = 3 * TS + 3; - //tolerance to avoid dividing by zero - static const float eps=1e-5, epssq=1e-10; //tolerance to avoid dividing by zero + //tolerance to avoid dividing by zero + static const float eps = 1e-5, epssq = 1e-10; //tolerance to avoid dividing by zero - //adaptive ratios threshold - static const float arthresh=0.75; - //nyquist texture test threshold - static const float nyqthresh=0.5; + //adaptive ratios threshold + static const float arthresh = 0.75; + //nyquist texture test threshold + static const float nyqthresh = 0.5; - //gaussian on 5x5 quincunx, sigma=1.2 - static const float gaussodd[4] = {0.14659727707323927f, 0.103592713382435f, 0.0732036125103057f, 0.0365543548389495f}; - //gaussian on 5x5, sigma=1.2 - static const float gaussgrad[6] = {0.07384411893421103f, 0.06207511968171489f, 0.0521818194747806f, - 0.03687419286733595f, 0.03099732204057846f, 0.018413194161458882f}; - //gaussian on 5x5 alt quincunx, sigma=1.5 - static const float gausseven[2] = {0.13719494435797422f, 0.05640252782101291f}; - //guassian on quincunx grid - static const float gquinc[4] = {0.169917f, 0.108947f, 0.069855f, 0.0287182f}; + //gaussian on 5x5 quincunx, sigma=1.2 + static const float gaussodd[4] = {0.14659727707323927f, 0.103592713382435f, 0.0732036125103057f, 0.0365543548389495f}; + //gaussian on 5x5, sigma=1.2 + static const float gaussgrad[6] = {0.07384411893421103f, 0.06207511968171489f, 0.0521818194747806f, + 0.03687419286733595f, 0.03099732204057846f, 0.018413194161458882f + }; + //gaussian on 5x5 alt quincunx, sigma=1.5 + static const float gausseven[2] = {0.13719494435797422f, 0.05640252782101291f}; + //guassian on quincunx grid + static const float gquinc[4] = {0.169917f, 0.108947f, 0.069855f, 0.0287182f}; - volatile double progress = 0.0; + volatile double progress = 0.0; - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Issue 1676 // Moved from inside the parallel section - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze])); - plistener->setProgress (0.0); - } - struct s_hv { - float h; - float v; - }; + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze])); + plistener->setProgress (0.0); + } -#pragma omp parallel -{ - int progresscounter=0; - //position of top/left corner of the tile - int top, left; - // beginning of storage block for tile - char *buffer; - // green values - float (*rgbgreen); + struct s_hv { + float h; + float v; + }; - // sum of square of horizontal gradient and square of vertical gradient - float (*delhvsqsum); - // gradient based directional weights for interpolation - float (*dirwts0); - float (*dirwts1); + #pragma omp parallel + { + int progresscounter = 0; + //position of top/left corner of the tile + int top, left; + // beginning of storage block for tile + char *buffer; + // green values + float (*rgbgreen); - // vertically interpolated color differences G-R, G-B - float (*vcd); - // horizontally interpolated color differences - float (*hcd); - // alternative vertical interpolation - float (*vcdalt); - // alternative horizontal interpolation - float (*hcdalt); - // square of average color difference - float (*cddiffsq); - // weight to give horizontal vs vertical interpolation - float (*hvwt); - // final interpolated color difference - float (*Dgrb)[TS*TSH]; -// float (*Dgrb)[2]; - // gradient in plus (NE/SW) direction - float (*delp); - // gradient in minus (NW/SE) direction - float (*delm); - // diagonal interpolation of R+B - float (*rbint); - // horizontal and vertical curvature of interpolated G (used to refine interpolation in Nyquist texture regions) - s_hv (*Dgrb2); - // difference between up/down interpolations of G - float (*dgintv); - // difference between left/right interpolations of G - float (*dginth); - // diagonal (plus) color difference R-B or G1-G2 -// float (*Dgrbp1); - // diagonal (minus) color difference R-B or G1-G2 -// float (*Dgrbm1); - float (*Dgrbsq1m); - float (*Dgrbsq1p); -// s_mp (*Dgrbsq1); - // square of diagonal color difference -// float (*Dgrbpsq1); - // square of diagonal color difference -// float (*Dgrbmsq1); - // tile raw data - float (*cfa); - // relative weight for combining plus and minus diagonal interpolations - float (*pmwt); - // interpolated color difference R-B in minus and plus direction - float (*rbm); - float (*rbp); + // sum of square of horizontal gradient and square of vertical gradient + float (*delhvsqsum); + // gradient based directional weights for interpolation + float (*dirwts0); + float (*dirwts1); - // nyquist texture flag 1=nyquist, 0=not nyquist - char (*nyquist); + // vertically interpolated color differences G-R, G-B + float (*vcd); + // horizontally interpolated color differences + float (*hcd); + // alternative vertical interpolation + float (*vcdalt); + // alternative horizontal interpolation + float (*hcdalt); + // square of average color difference + float (*cddiffsq); + // weight to give horizontal vs vertical interpolation + float (*hvwt); + // final interpolated color difference + float (*Dgrb)[TS * TSH]; +// float (*Dgrb)[2]; + // gradient in plus (NE/SW) direction + float (*delp); + // gradient in minus (NW/SE) direction + float (*delm); + // diagonal interpolation of R+B + float (*rbint); + // horizontal and vertical curvature of interpolated G (used to refine interpolation in Nyquist texture regions) + s_hv (*Dgrb2); + // difference between up/down interpolations of G + float (*dgintv); + // difference between left/right interpolations of G + float (*dginth); + // diagonal (plus) color difference R-B or G1-G2 +// float (*Dgrbp1); + // diagonal (minus) color difference R-B or G1-G2 +// float (*Dgrbm1); + float (*Dgrbsq1m); + float (*Dgrbsq1p); +// s_mp (*Dgrbsq1); + // square of diagonal color difference +// float (*Dgrbpsq1); + // square of diagonal color difference +// float (*Dgrbmsq1); + // tile raw data + float (*cfa); + // relative weight for combining plus and minus diagonal interpolations + float (*pmwt); + // interpolated color difference R-B in minus and plus direction + float (*rbm); + float (*rbp); + + // nyquist texture flag 1=nyquist, 0=not nyquist + char (*nyquist); #define CLF 1 - // assign working space - buffer = (char *) calloc(22*sizeof(float)*TS*TS + sizeof(char)*TS*TSH+23*CLF*64 + 63, 1); - char *data; - data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); + // assign working space + buffer = (char *) calloc(22 * sizeof(float) * TS * TS + sizeof(char) * TS * TSH + 23 * CLF * 64 + 63, 1); + char *data; + data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); - //merror(buffer,"amaze_interpolate()"); - rgbgreen = (float (*)) data; //pointers to array - delhvsqsum = (float (*)) ((char*)rgbgreen + sizeof(float)*TS*TS + CLF*64); - dirwts0 = (float (*)) ((char*)delhvsqsum + sizeof(float)*TS*TS + CLF*64); - dirwts1 = (float (*)) ((char*)dirwts0 + sizeof(float)*TS*TS + CLF*64); - vcd = (float (*)) ((char*)dirwts1 + sizeof(float)*TS*TS + CLF*64); - hcd = (float (*)) ((char*)vcd + sizeof(float)*TS*TS + CLF*64); - vcdalt = (float (*)) ((char*)hcd + sizeof(float)*TS*TS + CLF*64); - hcdalt = (float (*)) ((char*)vcdalt + sizeof(float)*TS*TS + CLF*64); - cddiffsq = (float (*)) ((char*)hcdalt + sizeof(float)*TS*TS + CLF*64); - hvwt = (float (*)) ((char*)cddiffsq + sizeof(float)*TS*TS + CLF*64); - Dgrb = (float (*)[TS*TSH]) ((char*)hvwt + sizeof(float)*TS*TSH + CLF*64); - delp = (float (*)) ((char*)Dgrb + sizeof(float)*TS*TS + CLF*64); - delm = (float (*)) ((char*)delp + sizeof(float)*TS*TSH + CLF*64); - rbint = (float (*)) ((char*)delm + sizeof(float)*TS*TSH + CLF*64); - Dgrb2 = (s_hv (*)) ((char*)rbint + sizeof(float)*TS*TSH + CLF*64); - dgintv = (float (*)) ((char*)Dgrb2 + sizeof(float)*TS*TS + CLF*64); - dginth = (float (*)) ((char*)dgintv + sizeof(float)*TS*TS + CLF*64); - Dgrbsq1m = (float (*)) ((char*)dginth + sizeof(float)*TS*TS + CLF*64); - Dgrbsq1p = (float (*)) ((char*)Dgrbsq1m + sizeof(float)*TS*TSH + CLF*64); - cfa = (float (*)) ((char*)Dgrbsq1p + sizeof(float)*TS*TSH + CLF*64); - pmwt = (float (*)) ((char*)cfa + sizeof(float)*TS*TS + CLF*64); - rbm = (float (*)) ((char*)pmwt + sizeof(float)*TS*TSH + CLF*64); - rbp = (float (*)) ((char*)rbm + sizeof(float)*TS*TSH + CLF*64); + //merror(buffer,"amaze_interpolate()"); + rgbgreen = (float (*)) data; //pointers to array + delhvsqsum = (float (*)) ((char*)rgbgreen + sizeof(float) * TS * TS + CLF * 64); + dirwts0 = (float (*)) ((char*)delhvsqsum + sizeof(float) * TS * TS + CLF * 64); + dirwts1 = (float (*)) ((char*)dirwts0 + sizeof(float) * TS * TS + CLF * 64); + vcd = (float (*)) ((char*)dirwts1 + sizeof(float) * TS * TS + CLF * 64); + hcd = (float (*)) ((char*)vcd + sizeof(float) * TS * TS + CLF * 64); + vcdalt = (float (*)) ((char*)hcd + sizeof(float) * TS * TS + CLF * 64); + hcdalt = (float (*)) ((char*)vcdalt + sizeof(float) * TS * TS + CLF * 64); + cddiffsq = (float (*)) ((char*)hcdalt + sizeof(float) * TS * TS + CLF * 64); + hvwt = (float (*)) ((char*)cddiffsq + sizeof(float) * TS * TS + CLF * 64); + Dgrb = (float (*)[TS * TSH]) ((char*)hvwt + sizeof(float) * TS * TSH + CLF * 64); + delp = (float (*)) ((char*)Dgrb + sizeof(float) * TS * TS + CLF * 64); + delm = (float (*)) ((char*)delp + sizeof(float) * TS * TSH + CLF * 64); + rbint = (float (*)) ((char*)delm + sizeof(float) * TS * TSH + CLF * 64); + Dgrb2 = (s_hv (*)) ((char*)rbint + sizeof(float) * TS * TSH + CLF * 64); + dgintv = (float (*)) ((char*)Dgrb2 + sizeof(float) * TS * TS + CLF * 64); + dginth = (float (*)) ((char*)dgintv + sizeof(float) * TS * TS + CLF * 64); + Dgrbsq1m = (float (*)) ((char*)dginth + sizeof(float) * TS * TS + CLF * 64); + Dgrbsq1p = (float (*)) ((char*)Dgrbsq1m + sizeof(float) * TS * TSH + CLF * 64); + cfa = (float (*)) ((char*)Dgrbsq1p + sizeof(float) * TS * TSH + CLF * 64); + pmwt = (float (*)) ((char*)cfa + sizeof(float) * TS * TS + CLF * 64); + rbm = (float (*)) ((char*)pmwt + sizeof(float) * TS * TSH + CLF * 64); + rbp = (float (*)) ((char*)rbm + sizeof(float) * TS * TSH + CLF * 64); - nyquist = (char (*)) ((char*)rbp + sizeof(float)*TS*TSH + CLF*64); + nyquist = (char (*)) ((char*)rbp + sizeof(float) * TS * TSH + CLF * 64); #undef CLF - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //determine GRBG coset; (ey,ex) is the offset of the R subarray - if (FC(0,0)==1) {//first pixel is G - if (FC(0,1)==0) {ey=0; ex=1;} else {ey=1; ex=0;} - } else {//first pixel is R or B - if (FC(0,0)==0) {ey=0; ex=0;} else {ey=1; ex=1;} - } + //determine GRBG coset; (ey,ex) is the offset of the R subarray + if (FC(0, 0) == 1) { //first pixel is G + if (FC(0, 1) == 0) { + ey = 0; + ex = 1; + } else { + ey = 1; + ex = 0; + } + } else {//first pixel is R or B + if (FC(0, 0) == 0) { + ey = 0; + ex = 0; + } else { + ey = 1; + ex = 1; + } + } - // Main algorithm: Tile loop - //#pragma omp parallel for shared(rawData,height,width,red,green,blue) private(top,left) schedule(dynamic) - //code is openmp ready; just have to pull local tile variable declarations inside the tile loop + // Main algorithm: Tile loop + //#pragma omp parallel for shared(rawData,height,width,red,green,blue) private(top,left) schedule(dynamic) + //code is openmp ready; just have to pull local tile variable declarations inside the tile loop // Issue 1676 // use collapse(2) to collapse the 2 loops to one large loop, so there is better scaling -#pragma omp for schedule(dynamic) collapse(2) nowait - for (top=winy-16; top < winy+height; top += TS-32) - for (left=winx-16; left < winx+width; left += TS-32) { - memset(nyquist, 0, sizeof(char)*TS*TSH); - memset(rbint, 0, sizeof(float)*TS*TSH); - //location of tile bottom edge - int bottom = min(top+TS,winy+height+16); - //location of tile right edge - int right = min(left+TS, winx+width+16); - //tile width (=TS except for right edge of image) - int rr1 = bottom - top; - //tile height (=TS except for bottom edge of image) - int cc1 = right - left; + #pragma omp for schedule(dynamic) collapse(2) nowait - //tile vars - //counters for pixel location in the image - int row, col; - //min and max row/column in the tile - int rrmin, rrmax, ccmin, ccmax; - //counters for pixel location within the tile - int rr, cc; - //color index 0=R, 1=G, 2=B - int c; - //pointer counters within the tile - int indx, indx1; - //dummy indices - int i, j; + for (top = winy - 16; top < winy + height; top += TS - 32) + for (left = winx - 16; left < winx + width; left += TS - 32) { + memset(nyquist, 0, sizeof(char)*TS * TSH); + memset(rbint, 0, sizeof(float)*TS * TSH); + //location of tile bottom edge + int bottom = min(top + TS, winy + height + 16); + //location of tile right edge + int right = min(left + TS, winx + width + 16); + //tile width (=TS except for right edge of image) + int rr1 = bottom - top; + //tile height (=TS except for bottom edge of image) + int cc1 = right - left; - //color ratios in up/down/left/right directions - float cru, crd, crl, crr; - //adaptive weights for vertical/horizontal/plus/minus directions - float vwt, hwt, pwt, mwt; - //vertical and horizontal G interpolations - float Gintv, Ginth; - //G interpolated in vert/hor directions using adaptive ratios - float guar, gdar, glar, grar; - //G interpolated in vert/hor directions using Hamilton-Adams method - float guha, gdha, glha, grha; - //interpolated G from fusing left/right or up/down - float Ginthar, Ginthha, Gintvar, Gintvha; - //color difference (G-R or G-B) variance in up/down/left/right directions - float Dgrbvvaru, Dgrbvvard, Dgrbhvarl, Dgrbhvarr; - - float uave, dave, lave, rave; + //tile vars + //counters for pixel location in the image + int row, col; + //min and max row/column in the tile + int rrmin, rrmax, ccmin, ccmax; + //counters for pixel location within the tile + int rr, cc; + //color index 0=R, 1=G, 2=B + int c; + //pointer counters within the tile + int indx, indx1; + //dummy indices + int i, j; - //color difference variances in vertical and horizontal directions - float vcdvar, hcdvar, vcdvar1, hcdvar1, hcdaltvar, vcdaltvar; - //adaptive interpolation weight using variance of color differences - float varwt; // 639 - 644 - //adaptive interpolation weight using difference of left-right and up-down G interpolations - float diffwt; // 640 - 644 - //alternative adaptive weight for combining horizontal/vertical interpolations - float hvwtalt; // 745 - 748 - //interpolation of G in four directions - float gu, gd, gl, gr; - //variance of G in vertical/horizontal directions - float gvarh, gvarv; + //color ratios in up/down/left/right directions + float cru, crd, crl, crr; + //adaptive weights for vertical/horizontal/plus/minus directions + float vwt, hwt, pwt, mwt; + //vertical and horizontal G interpolations + float Gintv, Ginth; + //G interpolated in vert/hor directions using adaptive ratios + float guar, gdar, glar, grar; + //G interpolated in vert/hor directions using Hamilton-Adams method + float guha, gdha, glha, grha; + //interpolated G from fusing left/right or up/down + float Ginthar, Ginthha, Gintvar, Gintvha; + //color difference (G-R or G-B) variance in up/down/left/right directions + float Dgrbvvaru, Dgrbvvard, Dgrbhvarl, Dgrbhvarr; - //Nyquist texture test - float nyqtest; // 658 - 681 - //accumulators for Nyquist texture interpolation - float sumh, sumv, sumsqh, sumsqv, areawt; + float uave, dave, lave, rave; - //color ratios in diagonal directions - float crse, crnw, crne, crsw; - //color differences in diagonal directions - float rbse, rbnw, rbne, rbsw; - //adaptive weights for combining diagonal interpolations - float wtse, wtnw, wtsw, wtne; - //alternate weight for combining diagonal interpolations - float pmwtalt; // 885 - 888 - //variance of R-B in plus/minus directions - float rbvarm; // 843 - 848 + //color difference variances in vertical and horizontal directions + float vcdvar, hcdvar, vcdvar1, hcdvar1, hcdaltvar, vcdaltvar; + //adaptive interpolation weight using variance of color differences + float varwt; // 639 - 644 + //adaptive interpolation weight using difference of left-right and up-down G interpolations + float diffwt; // 640 - 644 + //alternative adaptive weight for combining horizontal/vertical interpolations + float hvwtalt; // 745 - 748 + //interpolation of G in four directions + float gu, gd, gl, gr; + //variance of G in vertical/horizontal directions + float gvarh, gvarv; - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //Nyquist texture test + float nyqtest; // 658 - 681 + //accumulators for Nyquist texture interpolation + float sumh, sumv, sumsqh, sumsqv, areawt; - // rgb from input CFA data - // rgb values should be floating point number between 0 and 1 - // after white balance multipliers are applied - // a 16 pixel border is added to each side of the image + //color ratios in diagonal directions + float crse, crnw, crne, crsw; + //color differences in diagonal directions + float rbse, rbnw, rbne, rbsw; + //adaptive weights for combining diagonal interpolations + float wtse, wtnw, wtsw, wtne; + //alternate weight for combining diagonal interpolations + float pmwtalt; // 885 - 888 + //variance of R-B in plus/minus directions + float rbvarm; // 843 - 848 - // bookkeeping for borders - if (top(winy+height)) {rrmax=winy+height-top;} else {rrmax=rr1;} - if (right>(winx+width)) {ccmax=winx+width-left;} else {ccmax=cc1;} + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // rgb from input CFA data + // rgb values should be floating point number between 0 and 1 + // after white balance multipliers are applied + // a 16 pixel border is added to each side of the image + + // bookkeeping for borders + if (top < winy) { + rrmin = 16; + } else { + rrmin = 0; + } + + if (left < winx) { + ccmin = 16; + } else { + ccmin = 0; + } + + if (bottom > (winy + height)) { + rrmax = winy + height - top; + } else { + rrmax = rr1; + } + + if (right > (winx + width)) { + ccmax = winx + width - left; + } else { + ccmax = cc1; + } #ifdef __SSE2__ - const __m128 c65535v = _mm_set1_ps( 65535.0f ); - __m128 tempv; - for (rr=rrmin; rr < rrmax; rr++){ - for (row=rr+top, cc=ccmin; cc < ccmax-3; cc+=4) { - indx1=rr*TS+cc; - tempv = LVFU(rawData[row][cc+left]) / c65535v; - _mm_store_ps( &cfa[indx1], tempv ); - _mm_store_ps( &rgbgreen[indx1], tempv ); - } - for (; cc < ccmax; cc++) { - indx1=rr*TS+cc; - cfa[indx1] = (rawData[row][cc+left])/65535.0f; - if(FC(rr,cc)==1) - rgbgreen[indx1] = cfa[indx1]; - - } - - } - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //fill borders - if (rrmin>0) { - for (rr=0; rr<16; rr++) - for (cc=ccmin,row = 32-rr+top; cc0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr<16; rr++) - for (cc=0; cc<16; cc+=4) { - indx1 = (rr)*TS+cc; - tempv = LVFU(rawData[winy+32-rr][winx+32-cc]) / c65535v; - _mm_store_ps( &cfa[indx1], tempv ); - _mm_store_ps( &rgbgreen[indx1], tempv ); - } - } - if (rrmax0 && ccmax0) { - for (rr=0; rr<16; rr++) - for (cc=0; cc<16; cc++) { - cfa[(rrmax+rr)*TS+cc] = (rawData[(winy+height-rr-2)][(winx+32-cc)])/65535.0f; - if(FC(rr,cc)==1) - rgbgreen[(rrmax+rr)*TS+cc] = cfa[(rrmax+rr)*TS+cc]; - } - } - -#else - for (rr=rrmin; rr < rrmax; rr++) - for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { - indx1=rr*TS+cc; - cfa[indx1] = (rawData[row][cc+left])/65535.0f; - if(FC(rr,cc)==1) - rgbgreen[indx1] = cfa[indx1]; - - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //fill borders - if (rrmin>0) { - for (rr=0; rr<16; rr++) - for (cc=ccmin,row = 32-rr+top; cc0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr<16; rr++) - for (cc=0; cc<16; cc++) { - cfa[(rr)*TS+cc] = (rawData[winy+32-rr][winx+32-cc])/65535.0f; - if(FC(rr,cc)==1) - rgbgreen[(rr)*TS+cc] = cfa[(rr)*TS+cc]; - } - } - if (rrmax0 && ccmax0) { - for (rr=0; rr<16; rr++) - for (cc=0; cc<16; cc++) { - cfa[(rrmax+rr)*TS+cc] = (rawData[(winy+height-rr-2)][(winx+32-cc)])/65535.0f; - if(FC(rr,cc)==1) - rgbgreen[(rrmax+rr)*TS+cc] = cfa[(rrmax+rr)*TS+cc]; - } - } -#endif - - //end of border fill - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#ifdef __SSE2__ - __m128 delhv,delvv; - const __m128 epsv = _mm_set1_ps( eps ); - - for (rr=2; rr < rr1-2; rr++) { - for (cc=0, indx=(rr)*TS+cc; cc < cc1; cc+=4, indx+=4) { - delhv = vabsf( LVFU( cfa[indx+1] ) - LVFU( cfa[indx-1] ) ); - delvv = vabsf( LVF( cfa[indx+v1] ) - LVF( cfa[indx-v1] ) ); - _mm_store_ps( &dirwts1[indx], epsv + vabsf( LVFU( cfa[indx+2] ) - LVF( cfa[indx] )) + vabsf( LVF( cfa[indx] ) - LVFU( cfa[indx-2] )) + delhv ); - delhv = delhv * delhv; - _mm_store_ps( &dirwts0[indx], epsv + vabsf( LVF( cfa[indx+v2] ) - LVF( cfa[indx] )) + vabsf( LVF( cfa[indx] ) - LVF( cfa[indx-v2] )) + delvv ); - delvv = delvv * delvv; - _mm_store_ps( &delhvsqsum[indx], delhv + delvv); - } - } -#else - // horizontal and vedrtical gradient - float delh,delv; - for (rr=2; rr < rr1-2; rr++) - for (cc=2, indx=(rr)*TS+cc; cc < cc1-2; cc++, indx++) { - delh = fabsf(cfa[indx+1]-cfa[indx-1]); - delv = fabsf(cfa[indx+v1]-cfa[indx-v1]); - dirwts0[indx] = eps+fabsf(cfa[indx+v2]-cfa[indx])+fabsf(cfa[indx]-cfa[indx-v2])+delv; - dirwts1[indx] = eps+fabsf(cfa[indx+2]-cfa[indx])+fabsf(cfa[indx]-cfa[indx-2])+delh;//+fabsf(cfa[indx+2]-cfa[indx-2]); - delhvsqsum[indx] = SQR(delh) + SQR(delv); - } -#endif - -#ifdef __SSE2__ - __m128 Dgrbsq1pv, Dgrbsq1mv,temp2v; - for (rr=6; rr < rr1-6; rr++){ - if((FC(rr,2)&1)==0) { - for (cc=6, indx=(rr)*TS+cc; cc < cc1-6; cc+=8, indx+=8) { - tempv = LC2VFU(cfa[indx+1]); - Dgrbsq1pv = (SQRV(tempv-LC2VFU(cfa[indx+1-p1]))+SQRV(tempv-LC2VFU(cfa[indx+1+p1]))); - _mm_storeu_ps( &delp[indx>>1], vabsf(LC2VFU(cfa[indx+p1])-LC2VFU(cfa[indx-p1]))); - _mm_storeu_ps( &delm[indx>>1], vabsf(LC2VFU(cfa[indx+m1])-LC2VFU(cfa[indx-m1]))); - Dgrbsq1mv = (SQRV(tempv-LC2VFU(cfa[indx+1-m1]))+SQRV(tempv-LC2VFU(cfa[indx+1+m1]))); - _mm_storeu_ps( &Dgrbsq1m[indx>>1], Dgrbsq1mv ); - _mm_storeu_ps( &Dgrbsq1p[indx>>1], Dgrbsq1pv ); - } - } - else { - for (cc=6, indx=(rr)*TS+cc; cc < cc1-6; cc+=8, indx+=8) { - tempv = LC2VFU(cfa[indx]); - Dgrbsq1pv = (SQRV(tempv-LC2VFU(cfa[indx-p1]))+SQRV(tempv-LC2VFU(cfa[indx+p1]))); - _mm_storeu_ps( &delp[indx>>1], vabsf(LC2VFU(cfa[indx+1+p1])-LC2VFU(cfa[indx+1-p1]))); - _mm_storeu_ps( &delm[indx>>1], vabsf(LC2VFU(cfa[indx+1+m1])-LC2VFU(cfa[indx+1-m1]))); - Dgrbsq1mv = (SQRV(tempv-LC2VFU(cfa[indx-m1]))+SQRV(tempv-LC2VFU(cfa[indx+m1]))); - _mm_storeu_ps( &Dgrbsq1m[indx>>1], Dgrbsq1mv ); - _mm_storeu_ps( &Dgrbsq1p[indx>>1], Dgrbsq1pv ); - } - } - } -#else - for (rr=6; rr < rr1-6; rr++){ - if((FC(rr,2)&1)==0) { - for (cc=6, indx=(rr)*TS+cc; cc < cc1-6; cc+=2, indx+=2) { - delp[indx>>1] = fabsf(cfa[indx+p1]-cfa[indx-p1]); - delm[indx>>1] = fabsf(cfa[indx+m1]-cfa[indx-m1]); - Dgrbsq1p[indx>>1]=(SQR(cfa[indx+1]-cfa[indx+1-p1])+SQR(cfa[indx+1]-cfa[indx+1+p1])); - Dgrbsq1m[indx>>1]=(SQR(cfa[indx+1]-cfa[indx+1-m1])+SQR(cfa[indx+1]-cfa[indx+1+m1])); - } - } - else { - for (cc=6, indx=(rr)*TS+cc; cc < cc1-6; cc+=2, indx+=2) { - Dgrbsq1p[indx>>1]=(SQR(cfa[indx]-cfa[indx-p1])+SQR(cfa[indx]-cfa[indx+p1])); - Dgrbsq1m[indx>>1]=(SQR(cfa[indx]-cfa[indx-m1])+SQR(cfa[indx]-cfa[indx+m1])); - delp[indx>>1] = fabsf(cfa[indx+1+p1]-cfa[indx+1-p1]); - delm[indx>>1] = fabsf(cfa[indx+1+m1]-cfa[indx+1-m1]); - } - } - } -#endif - - // end of tile initialization - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //interpolate vertical and horizontal color differences - -#ifdef __SSE2__ - __m128 sgnv,cruv,crdv,crlv,crrv,guhav,gdhav,glhav,grhav,hwtv,vwtv,Gintvhav,Ginthhav,guarv,gdarv,glarv,grarv; - vmask clipmask; - if( !(FC(4,4)&1) ) - sgnv = _mm_set_ps( 1.0f, -1.0f, 1.0f, -1.0f ); - else - sgnv = _mm_set_ps( -1.0f, 1.0f, -1.0f, 1.0f ); - - __m128 zd5v = _mm_set1_ps( 0.5f ); - __m128 onev = _mm_set1_ps( 1.0f ); - __m128 arthreshv = _mm_set1_ps( arthresh ); - __m128 clip_pt8v = _mm_set1_ps( clip_pt8 ); - - for (rr=4; rr clip_pt8 || Gintvha > clip_pt8 || Ginthha > clip_pt8) { - //use HA if highlights are (nearly) clipped - guar=guha; gdar=gdha; glar=glha; grar=grha; - vcd[indx]=vcdalt[indx]; hcd[indx]=hcdalt[indx]; - } - - //differences of interpolations in opposite directions - dgintv[indx]=min(SQR(guha-gdha),SQR(guar-gdar)); - dginth[indx]=min(SQR(glha-grha),SQR(glar-grar)); - - } - - - } -#endif - -#ifdef __SSE2__ - __m128 hcdvarv, vcdvarv; - __m128 hcdaltvarv,vcdaltvarv,hcdv,vcdv,hcdaltv,vcdaltv,sgn3v,Ginthv,Gintvv,hcdoldv,vcdoldv; - __m128 threev = _mm_set1_ps( 3.0f ); - __m128 clip_ptv = _mm_set1_ps( clip_pt ); - __m128 nsgnv; - vmask hcdmask, vcdmask,tempmask; - - if( !(FC(4,4)&1) ) - sgnv = _mm_set_ps( 1.0f, -1.0f, 1.0f, -1.0f ); - else - sgnv = _mm_set_ps( -1.0f, 1.0f, -1.0f, 1.0f ); - - sgn3v = threev * sgnv; - for (rr=4; rr0) { - if (3.0f*hcd[indx] > (Ginth+cfa[indx])) { - hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx]; - } else { - hwt = 1.0f -3.0f*hcd[indx]/(eps+Ginth+cfa[indx]); - hcd[indx]=hwt*hcd[indx] + (1.0f-hwt)*(-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx]); - } - } - if (vcd[indx]>0) { - if (3.0f*vcd[indx] > (Gintv+cfa[indx])) { - vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; - } else { - vwt = 1.0f -3.0f*vcd[indx]/(eps+Gintv+cfa[indx]); - vcd[indx]=vwt*vcd[indx] + (1.0f-vwt)*(-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]); - } - } - - if (Ginth > clip_pt) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for RT implementation - if (Gintv > clip_pt) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; - //if (Ginth > pre_mul[c]) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for dcraw implementation - //if (Gintv > pre_mul[c]) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; - - } else {//R or B site - - Ginth = hcd[indx]+cfa[indx];//interpolated G - Gintv = vcd[indx]+cfa[indx]; - - if (hcd[indx]<0) { - if (3.0f*hcd[indx] < -(Ginth+cfa[indx])) { - hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx]; - } else { - hwt = 1.0f +3.0f*hcd[indx]/(eps+Ginth+cfa[indx]); - hcd[indx]=hwt*hcd[indx] + (1.0f-hwt)*(ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx]); - } - } - if (vcd[indx]<0) { - if (3.0f*vcd[indx] < -(Gintv+cfa[indx])) { - vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; - } else { - vwt = 1.0f +3.0f*vcd[indx]/(eps+Gintv+cfa[indx]); - vcd[indx]=vwt*vcd[indx] + (1.0f-vwt)*(ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]); - } - } - - if (Ginth > clip_pt) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for RT implementation - if (Gintv > clip_pt) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; - //if (Ginth > pre_mul[c]) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for dcraw implementation - //if (Gintv > pre_mul[c]) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; - cddiffsq[indx] = SQR(vcd[indx]-hcd[indx]); - } - c = !c; - } - } -#endif - -#ifdef __SSE2__ - __m128 uavev,davev,lavev,ravev,Dgrbvvaruv,Dgrbvvardv,Dgrbhvarlv,Dgrbhvarrv,varwtv,diffwtv,vcdvar1v,hcdvar1v; - __m128 epssqv = _mm_set1_ps( epssq ); - vmask decmask; - for (rr=6; rr>1], vself( decmask, varwtv, diffwtv)); - } - } -#else - for (rr=6; rr0 && fabsf(0.5-diffwt)>1]=varwt;} else {hvwt[indx>>1]=diffwt;} - - //hvwt[indx]=varwt; - } - } - -#endif - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // Nyquist test - for (rr=6; rr0) - nyquist[indx>>1]=1;//nyquist=1 for nyquist region - } - - unsigned int nyquisttemp; - for (rr=8; rr>1]+nyquist[(indx-m1)>>1]+nyquist[(indx+p1)>>1]+ - nyquist[(indx-2)>>1]+nyquist[indx>>1]+nyquist[(indx+2)>>1]+ - nyquist[(indx-p1)>>1]+nyquist[(indx+m1)>>1]+nyquist[(indx+v2)>>1]); - //if most of your neighbors are named Nyquist, it's likely that you're one too - if (nyquisttemp>4) nyquist[indx>>1]=1; - //or not - if (nyquisttemp<4) nyquist[indx>>1]=0; - } - } - // end of Nyquist test - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // in areas of Nyquist texture, do area interpolation - for (rr=8; rr>1]) { - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // area interpolation - - sumh=sumv=sumsqh=sumsqv=areawt=0; - for (i=-6; i<7; i+=2) - for (j=-6; j<7; j+=2) { - indx1=(rr+i)*TS+cc+j; - if (nyquist[indx1>>1]) { - sumh += cfa[indx1]-xdiv2f(cfa[indx1-1]+cfa[indx1+1]); - sumv += cfa[indx1]-xdiv2f(cfa[indx1-v1]+cfa[indx1+v1]); - sumsqh += xdiv2f(SQR(cfa[indx1]-cfa[indx1-1])+SQR(cfa[indx1]-cfa[indx1+1])); - sumsqv += xdiv2f(SQR(cfa[indx1]-cfa[indx1-v1])+SQR(cfa[indx1]-cfa[indx1+v1])); - areawt +=1; - } - } - - //horizontal and vertical color differences, and adaptive weight - hcdvar=epssq+fabsf(areawt*sumsqh-sumh*sumh); - vcdvar=epssq+fabsf(areawt*sumsqv-sumv*sumv); - hvwt[indx>>1]=hcdvar/(vcdvar+hcdvar); - - // end of area interpolation - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - } - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //populate G at R/B sites - for (rr=8; rr>1]+hvwt[(indx+p1)>>1]+hvwt[(indx-p1)>>1]+hvwt[(indx+m1)>>1],2); -// hvwtalt = 0.25*(hvwt[(indx-m1)>>1]+hvwt[(indx+p1)>>1]+hvwt[(indx-p1)>>1]+hvwt[(indx+m1)>>1]); -// vo=fabsf(0.5-hvwt[indx>>1]); -// ve=fabsf(0.5-hvwtalt); - if (fabsf(0.5-hvwt[indx>>1])>1]=hvwtalt;}//a better result was obtained from the neighbors -// if (vo>1]=hvwtalt;}//a better result was obtained from the neighbors - - - - Dgrb[0][indx>>1] = (hcd[indx]*(1.0f-hvwt[indx>>1]) + vcd[indx]*hvwt[indx>>1]);//evaluate color differences - //if (hvwt[indx]<0.5) Dgrb[indx][0]=hcd[indx]; - //if (hvwt[indx]>0.5) Dgrb[indx][0]=vcd[indx]; - rgbgreen[indx] = cfa[indx] + Dgrb[0][indx>>1];//evaluate G (finally!) - - //local curvature in G (preparation for nyquist refinement step) - if (nyquist[indx>>1]) { - Dgrb2[indx>>1].h = SQR(rgbgreen[indx] - xdiv2f(rgbgreen[indx-1]+rgbgreen[indx+1])); - Dgrb2[indx>>1].v = SQR(rgbgreen[indx] - xdiv2f(rgbgreen[indx-v1]+rgbgreen[indx+v1])); - } else { - Dgrb2[indx>>1].h = Dgrb2[indx>>1].v = 0; - } - } - - //end of standard interpolation - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // refine Nyquist areas using G curvatures - - for (rr=8; rr>1]) { - //local averages (over Nyquist pixels only) of G curvature squared - gvarh = epssq + (gquinc[0]*Dgrb2[indx>>1].h+ - gquinc[1]*(Dgrb2[(indx-m1)>>1].h+Dgrb2[(indx+p1)>>1].h+Dgrb2[(indx-p1)>>1].h+Dgrb2[(indx+m1)>>1].h)+ - gquinc[2]*(Dgrb2[(indx-v2)>>1].h+Dgrb2[(indx-2)>>1].h+Dgrb2[(indx+2)>>1].h+Dgrb2[(indx+v2)>>1].h)+ - gquinc[3]*(Dgrb2[(indx-m2)>>1].h+Dgrb2[(indx+p2)>>1].h+Dgrb2[(indx-p2)>>1].h+Dgrb2[(indx+m2)>>1].h)); - gvarv = epssq + (gquinc[0]*Dgrb2[indx>>1].v+ - gquinc[1]*(Dgrb2[(indx-m1)>>1].v+Dgrb2[(indx+p1)>>1].v+Dgrb2[(indx-p1)>>1].v+Dgrb2[(indx+m1)>>1].v)+ - gquinc[2]*(Dgrb2[(indx-v2)>>1].v+Dgrb2[(indx-2)>>1].v+Dgrb2[(indx+2)>>1].v+Dgrb2[(indx+v2)>>1].v)+ - gquinc[3]*(Dgrb2[(indx-m2)>>1].v+Dgrb2[(indx+p2)>>1].v+Dgrb2[(indx-p2)>>1].v+Dgrb2[(indx+m2)>>1].v)); - //use the results as weights for refined G interpolation - Dgrb[0][indx>>1] = (hcd[indx]*gvarv + vcd[indx]*gvarh)/(gvarv+gvarh); - rgbgreen[indx] = cfa[indx] + Dgrb[0][indx>>1]; - } - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // diagonal interpolation correction - -#ifdef __SSE2__ - __m128 rbsev,rbnwv,rbnev,rbswv,cfav,rbmv,rbpv,temp1v,wtv; - __m128 wtsev, wtnwv, wtnev, wtswv, rbvarmv; - __m128 gausseven0v = _mm_set1_ps(gausseven[0]); - __m128 gausseven1v = _mm_set1_ps(gausseven[1]); - __m128 twov = _mm_set1_ps(2.0f); -#endif - for (rr=8; rr>1; cc>1])+LVFU(delm[(indx+m2)>>1]);//same as for wtu,wtd,wtl,wtr - wtnwv= temp1v+LVFU(delm[(indx-m1)>>1])+LVFU(delm[(indx-m2)>>1]); - - rbmv = (wtsev*rbnwv+wtnwv*rbsev)/(wtsev+wtnwv); - - temp1v = ULIMV(rbmv ,LC2VFU(cfa[indx-m1]),LC2VFU(cfa[indx+m1])); - wtv = twov * (cfav-rbmv)/(epsv+rbmv+cfav); - temp2v = wtv * rbmv + (onev-wtv)*temp1v; - - temp2v = vself(vmaskf_lt(rbmv + rbmv, cfav), temp1v, temp2v); - temp2v = vself(vmaskf_lt(rbmv, cfav), temp2v, rbmv); - _mm_storeu_ps(&rbm[indx1], vself(vmaskf_gt(temp2v, clip_ptv), ULIMV(temp2v ,LC2VFU(cfa[indx-m1]),LC2VFU(cfa[indx+m1])), temp2v )); - - - temp1v = LC2VFU(cfa[indx+p1]); - temp2v = LC2VFU(cfa[indx+p2]); - rbnev = (temp1v + temp1v) / (epsv + cfav + temp2v ); - rbnev = vself(vmaskf_lt(vabsf(onev - rbnev), arthreshv), cfav * rbnev, temp1v + zd5v * (cfav - temp2v)); - - temp1v = LC2VFU(cfa[indx-p1]); - temp2v = LC2VFU(cfa[indx-p2]); - rbswv = (temp1v + temp1v) / (epsv + cfav + temp2v ); - rbswv = vself(vmaskf_lt(vabsf(onev - rbswv), arthreshv), cfav * rbswv, temp1v + zd5v * (cfav - temp2v)); - - temp1v = epsv + LVFU(delp[indx1]); - wtnev= temp1v+LVFU(delp[(indx+p1)>>1])+LVFU(delp[(indx+p2)>>1]); - wtswv= temp1v+LVFU(delp[(indx-p1)>>1])+LVFU(delp[(indx-p2)>>1]); - - rbpv = (wtnev*rbswv+wtswv*rbnev)/(wtnev+wtswv); - - temp1v = ULIMV(rbpv ,LC2VFU(cfa[indx-p1]),LC2VFU(cfa[indx+p1])); - wtv = twov * (cfav-rbpv)/(epsv+rbpv+cfav); - temp2v = wtv * rbpv + (onev-wtv)*temp1v; - - temp2v = vself(vmaskf_lt(rbpv + rbpv, cfav), temp1v, temp2v); - temp2v = vself(vmaskf_lt(rbpv, cfav), temp2v, rbpv); - _mm_storeu_ps(&rbp[indx1], vself(vmaskf_gt(temp2v, clip_ptv), ULIMV(temp2v ,LC2VFU(cfa[indx-p1]),LC2VFU(cfa[indx+p1])), temp2v )); - - - - rbvarmv = epssqv + (gausseven0v*(LVFU(Dgrbsq1m[(indx-v1)>>1])+LVFU(Dgrbsq1m[(indx-1)>>1])+LVFU(Dgrbsq1m[(indx+1)>>1])+LVFU(Dgrbsq1m[(indx+v1)>>1])) + - gausseven1v*(LVFU(Dgrbsq1m[(indx-v2-1)>>1])+LVFU(Dgrbsq1m[(indx-v2+1)>>1])+LVFU(Dgrbsq1m[(indx-2-v1)>>1])+LVFU(Dgrbsq1m[(indx+2-v1)>>1])+ - LVFU(Dgrbsq1m[(indx-2+v1)>>1])+LVFU(Dgrbsq1m[(indx+2+v1)>>1])+LVFU(Dgrbsq1m[(indx+v2-1)>>1])+LVFU(Dgrbsq1m[(indx+v2+1)>>1]))); - _mm_storeu_ps(&pmwt[indx1] , rbvarmv/((epssqv + (gausseven0v*(LVFU(Dgrbsq1p[(indx-v1)>>1])+LVFU(Dgrbsq1p[(indx-1)>>1])+LVFU(Dgrbsq1p[(indx+1)>>1])+LVFU(Dgrbsq1p[(indx+v1)>>1])) + - gausseven1v*(LVFU(Dgrbsq1p[(indx-v2-1)>>1])+LVFU(Dgrbsq1p[(indx-v2+1)>>1])+LVFU(Dgrbsq1p[(indx-2-v1)>>1])+LVFU(Dgrbsq1p[(indx+2-v1)>>1])+ - LVFU(Dgrbsq1p[(indx-2+v1)>>1])+LVFU(Dgrbsq1p[(indx+2+v1)>>1])+LVFU(Dgrbsq1p[(indx+v2-1)>>1])+LVFU(Dgrbsq1p[(indx+v2+1)>>1]))))+rbvarmv)); - - } + const __m128 c65535v = _mm_set1_ps( 65535.0f ); + __m128 tempv; + + for (rr = rrmin; rr < rrmax; rr++) { + for (row = rr + top, cc = ccmin; cc < ccmax - 3; cc += 4) { + indx1 = rr * TS + cc; + tempv = LVFU(rawData[row][cc + left]) / c65535v; + _mm_store_ps( &cfa[indx1], tempv ); + _mm_store_ps( &rgbgreen[indx1], tempv ); + } + + for (; cc < ccmax; cc++) { + indx1 = rr * TS + cc; + cfa[indx1] = (rawData[row][cc + left]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[indx1] = cfa[indx1]; + } + + } + + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //fill borders + if (rrmin > 0) { + for (rr = 0; rr < 16; rr++) + for (cc = ccmin, row = 32 - rr + top; cc < ccmax; cc++) { + cfa[rr * TS + cc] = (rawData[row][cc + left]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[rr * TS + cc] = cfa[rr * TS + cc]; + } + } + } + + if (rrmax < rr1) { + for (rr = 0; rr < 16; rr++) + for (cc = ccmin; cc < ccmax; cc += 4) { + indx1 = (rrmax + rr) * TS + cc; + tempv = LVFU(rawData[(winy + height - rr - 2)][left + cc]) / c65535v; + _mm_store_ps( &cfa[indx1], tempv ); + _mm_store_ps( &rgbgreen[indx1], tempv ); + } + } + + if (ccmin > 0) { + for (rr = rrmin; rr < rrmax; rr++) + for (cc = 0, row = rr + top; cc < 16; cc++) { + cfa[rr * TS + cc] = (rawData[row][32 - cc + left]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[rr * TS + cc] = cfa[rr * TS + cc]; + } + } + } + + if (ccmax < cc1) { + for (rr = rrmin; rr < rrmax; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[rr * TS + ccmax + cc] = (rawData[(top + rr)][(winx + width - cc - 2)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[rr * TS + ccmax + cc] = cfa[rr * TS + ccmax + cc]; + } + } + } + + //also, fill the image corners + if (rrmin > 0 && ccmin > 0) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc += 4) { + indx1 = (rr) * TS + cc; + tempv = LVFU(rawData[winy + 32 - rr][winx + 32 - cc]) / c65535v; + _mm_store_ps( &cfa[indx1], tempv ); + _mm_store_ps( &rgbgreen[indx1], tempv ); + } + } + + if (rrmax < rr1 && ccmax < cc1) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc += 4) { + indx1 = (rrmax + rr) * TS + ccmax + cc; + tempv = LVFU(rawData[(winy + height - rr - 2)][(winx + width - cc - 2)]) / c65535v; + _mm_storeu_ps( &cfa[indx1], tempv ); + _mm_storeu_ps( &rgbgreen[indx1], tempv ); + } + } + + if (rrmin > 0 && ccmax < cc1) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc++) { + + cfa[(rr)*TS + ccmax + cc] = (rawData[(winy + 32 - rr)][(winx + width - cc - 2)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[(rr)*TS + ccmax + cc] = cfa[(rr) * TS + ccmax + cc]; + } + } + } + + if (rrmax < rr1 && ccmin > 0) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[(rrmax + rr)*TS + cc] = (rawData[(winy + height - rr - 2)][(winx + 32 - cc)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[(rrmax + rr)*TS + cc] = cfa[(rrmax + rr) * TS + cc]; + } + } + } #else - for (cc=8+(FC(rr,2)&1),indx=rr*TS+cc,indx1=indx>>1; cc>1]+delm[(indx+m2)>>1];//same as for wtu,wtd,wtl,wtr - wtnw= eps+delm[indx1]+delm[(indx-m1)>>1]+delm[(indx-m2)>>1]; - wtne= eps+delp[indx1]+delp[(indx+p1)>>1]+delp[(indx+p2)>>1]; - wtsw= eps+delp[indx1]+delp[(indx-p1)>>1]+delp[(indx-p2)>>1]; + } + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //fill borders + if (rrmin > 0) { + for (rr = 0; rr < 16; rr++) + for (cc = ccmin, row = 32 - rr + top; cc < ccmax; cc++) { + cfa[rr * TS + cc] = (rawData[row][cc + left]) / 65535.0f; - rbm[indx1] = (wtse*rbnw+wtnw*rbse)/(wtse+wtnw); - rbp[indx1] = (wtne*rbsw+wtsw*rbne)/(wtne+wtsw); -/* - rbvarp = epssq + (gausseven[0]*(Dgrbsq1[indx-v1].p+Dgrbsq1[indx-1].p+Dgrbsq1[indx+1].p+Dgrbsq1[indx+v1].p) + - gausseven[1]*(Dgrbsq1[indx-v2-1].p+Dgrbsq1[indx-v2+1].p+Dgrbsq1[indx-2-v1].p+Dgrbsq1[indx+2-v1].p+ - Dgrbsq1[indx-2+v1].p+Dgrbsq1[indx+2+v1].p+Dgrbsq1[indx+v2-1].p+Dgrbsq1[indx+v2+1].p)); -*/ - rbvarm = epssq + (gausseven[0]*(Dgrbsq1m[(indx-v1)>>1]+Dgrbsq1m[(indx-1)>>1]+Dgrbsq1m[(indx+1)>>1]+Dgrbsq1m[(indx+v1)>>1]) + - gausseven[1]*(Dgrbsq1m[(indx-v2-1)>>1]+Dgrbsq1m[(indx-v2+1)>>1]+Dgrbsq1m[(indx-2-v1)>>1]+Dgrbsq1m[(indx+2-v1)>>1]+ - Dgrbsq1m[(indx-2+v1)>>1]+Dgrbsq1m[(indx+2+v1)>>1]+Dgrbsq1m[(indx+v2-1)>>1]+Dgrbsq1m[(indx+v2+1)>>1])); - pmwt[indx1] = rbvarm/((epssq + (gausseven[0]*(Dgrbsq1p[(indx-v1)>>1]+Dgrbsq1p[(indx-1)>>1]+Dgrbsq1p[(indx+1)>>1]+Dgrbsq1p[(indx+v1)>>1]) + - gausseven[1]*(Dgrbsq1p[(indx-v2-1)>>1]+Dgrbsq1p[(indx-v2+1)>>1]+Dgrbsq1p[(indx-2-v1)>>1]+Dgrbsq1p[(indx+2-v1)>>1]+ - Dgrbsq1p[(indx-2+v1)>>1]+Dgrbsq1p[(indx+2+v1)>>1]+Dgrbsq1p[(indx+v2-1)>>1]+Dgrbsq1p[(indx+v2+1)>>1])))+rbvarm); + if(FC(rr, cc) == 1) { + rgbgreen[rr * TS + cc] = cfa[rr * TS + cc]; + } + } + } - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //bound the interpolation in regions of high saturation - if (rbp[indx1] clip_pt) rbp[indx1]=ULIM(rbp[indx1],cfa[indx-p1],cfa[indx+p1]);//for RT implementation - if (rbm[indx1] > clip_pt) rbm[indx1]=ULIM(rbm[indx1],cfa[indx-m1],cfa[indx+m1]); - //c=2-FC(rr,cc);//for dcraw implementation - //if (rbp[indx] > pre_mul[c]) rbp[indx]=ULIM(rbp[indx],cfa[indx-p1],cfa[indx+p1]); - //if (rbm[indx] > pre_mul[c]) rbm[indx]=ULIM(rbm[indx],cfa[indx-m1],cfa[indx+m1]); - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if(FC(rr, cc) == 1) { + rgbgreen[(rrmax + rr)*TS + cc] = cfa[(rrmax + rr) * TS + cc]; + } + } + } + + if (ccmin > 0) { + for (rr = rrmin; rr < rrmax; rr++) + for (cc = 0, row = rr + top; cc < 16; cc++) { + cfa[rr * TS + cc] = (rawData[row][32 - cc + left]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[rr * TS + cc] = cfa[rr * TS + cc]; + } + } + } + + if (ccmax < cc1) { + for (rr = rrmin; rr < rrmax; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[rr * TS + ccmax + cc] = (rawData[(top + rr)][(winx + width - cc - 2)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[rr * TS + ccmax + cc] = cfa[rr * TS + ccmax + cc]; + } + } + } + + //also, fill the image corners + if (rrmin > 0 && ccmin > 0) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[(rr)*TS + cc] = (rawData[winy + 32 - rr][winx + 32 - cc]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[(rr)*TS + cc] = cfa[(rr) * TS + cc]; + } + } + } + + if (rrmax < rr1 && ccmax < cc1) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[(rrmax + rr)*TS + ccmax + cc] = (rawData[(winy + height - rr - 2)][(winx + width - cc - 2)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[(rrmax + rr)*TS + ccmax + cc] = cfa[(rrmax + rr) * TS + ccmax + cc]; + } + } + } + + if (rrmin > 0 && ccmax < cc1) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[(rr)*TS + ccmax + cc] = (rawData[(winy + 32 - rr)][(winx + width - cc - 2)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[(rr)*TS + ccmax + cc] = cfa[(rr) * TS + ccmax + cc]; + } + } + } + + if (rrmax < rr1 && ccmin > 0) { + for (rr = 0; rr < 16; rr++) + for (cc = 0; cc < 16; cc++) { + cfa[(rrmax + rr)*TS + cc] = (rawData[(winy + height - rr - 2)][(winx + 32 - cc)]) / 65535.0f; + + if(FC(rr, cc) == 1) { + rgbgreen[(rrmax + rr)*TS + cc] = cfa[(rrmax + rr) * TS + cc]; + } + } + } - //rbint[indx] = 0.5*(cfa[indx] + (rbp*rbvarm+rbm*rbvarp)/(rbvarp+rbvarm));//this is R+B, interpolated - } #endif - } + //end of border fill + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #ifdef __SSE2__ - __m128 pmwtaltv; - __m128 zd25v = _mm_set1_ps(0.25f); -#endif - for (rr=10; rr>1; cc>1])+LVFU(pmwt[(indx+p1)>>1])+LVFU(pmwt[(indx-p1)>>1])+LVFU(pmwt[(indx+m1)>>1])); - tempv = LVFU(pmwt[indx1]); - tempv = vself(vmaskf_lt(vabsf(zd5v-tempv), vabsf(zd5v-pmwtaltv)), pmwtaltv, tempv); - _mm_storeu_ps( &pmwt[indx1], tempv); - _mm_storeu_ps( &rbint[indx1], zd5v * (LC2VFU(cfa[indx]) + LVFU(rbm[indx1]) * (onev - tempv) + LVFU(rbp[indx1]) * tempv)); - } + for (rr = 2; rr < rr1 - 2; rr++) { + for (cc = 0, indx = (rr) * TS + cc; cc < cc1; cc += 4, indx += 4) { + delhv = vabsf( LVFU( cfa[indx + 1] ) - LVFU( cfa[indx - 1] ) ); + delvv = vabsf( LVF( cfa[indx + v1] ) - LVF( cfa[indx - v1] ) ); + _mm_store_ps( &dirwts1[indx], epsv + vabsf( LVFU( cfa[indx + 2] ) - LVF( cfa[indx] )) + vabsf( LVF( cfa[indx] ) - LVFU( cfa[indx - 2] )) + delhv ); + delhv = delhv * delhv; + _mm_store_ps( &dirwts0[indx], epsv + vabsf( LVF( cfa[indx + v2] ) - LVF( cfa[indx] )) + vabsf( LVF( cfa[indx] ) - LVF( cfa[indx - v2] )) + delvv ); + delvv = delvv * delvv; + _mm_store_ps( &delhvsqsum[indx], delhv + delvv); + } + } #else - for (cc=10+(FC(rr,2)&1),indx=rr*TS+cc,indx1=indx>>1; cc>1]+pmwt[(indx+p1)>>1]+pmwt[(indx-p1)>>1]+pmwt[(indx+m1)>>1],2); - if (fabsf(0.5-pmwt[indx1])>1; cc>1])>1]) ) - continue; - - //now interpolate G vertically/horizontally using R+B values - //unfortunately, since G interpolation cannot be done diagonally this may lead to color shifts - //color ratios for G interpolation - - cru = cfa[indx-v1]*2.0/(eps+rbint[indx1]+rbint[(indx1-v1)]); - crd = cfa[indx+v1]*2.0/(eps+rbint[indx1]+rbint[(indx1+v1)]); - crl = cfa[indx-1]*2.0/(eps+rbint[indx1]+rbint[(indx1-1)]); - crr = cfa[indx+1]*2.0/(eps+rbint[indx1]+rbint[(indx1+1)]); - - //interpolated G via adaptive ratios or Hamilton-Adams in each cardinal direction - if (fabsf(1.0f-cru) clip_pt) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]);//for RT implementation - if (Gintv > clip_pt) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); - //c=FC(rr,cc);//for dcraw implementation - //if (Ginth > pre_mul[c]) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]); - //if (Gintv > pre_mul[c]) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - rgbgreen[indx] = Ginth*(1.0f-hvwt[indx1]) + Gintv*hvwt[indx1]; - //rgb[indx][1] = 0.5*(rgb[indx][1]+0.25*(rgb[indx-v1][1]+rgb[indx+v1][1]+rgb[indx-1][1]+rgb[indx+1][1])); - Dgrb[0][indx>>1] = rgbgreen[indx]-cfa[indx]; - - //rgb[indx][2-FC(rr,cc)]=2*rbint[indx]-cfa[indx]; - } - //end of diagonal interpolation correction - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //fancy chrominance interpolation - //(ey,ex) is location of R site - for (rr=13-ey; rr>1; cc>1])-LVFU(Dgrb[c][(indx+m1)>>1]))+vabsf(LVFU(Dgrb[c][(indx-m1)>>1])-LVFU(Dgrb[c][(indx-m3)>>1]))+vabsf(LVFU(Dgrb[c][(indx+m1)>>1])-LVFU(Dgrb[c][(indx-m3)>>1]))); - wtnev=onev/(epsv+vabsf(LVFU(Dgrb[c][(indx+p1)>>1])-LVFU(Dgrb[c][(indx-p1)>>1]))+vabsf(LVFU(Dgrb[c][(indx+p1)>>1])-LVFU(Dgrb[c][(indx+p3)>>1]))+vabsf(LVFU(Dgrb[c][(indx-p1)>>1])-LVFU(Dgrb[c][(indx+p3)>>1]))); - wtswv=onev/(epsv+vabsf(LVFU(Dgrb[c][(indx-p1)>>1])-LVFU(Dgrb[c][(indx+p1)>>1]))+vabsf(LVFU(Dgrb[c][(indx-p1)>>1])-LVFU(Dgrb[c][(indx+m3)>>1]))+vabsf(LVFU(Dgrb[c][(indx+p1)>>1])-LVFU(Dgrb[c][(indx-p3)>>1]))); - wtsev=onev/(epsv+vabsf(LVFU(Dgrb[c][(indx+m1)>>1])-LVFU(Dgrb[c][(indx-m1)>>1]))+vabsf(LVFU(Dgrb[c][(indx+m1)>>1])-LVFU(Dgrb[c][(indx-p3)>>1]))+vabsf(LVFU(Dgrb[c][(indx-m1)>>1])-LVFU(Dgrb[c][(indx+m3)>>1]))); + __m128 Dgrbsq1pv, Dgrbsq1mv, temp2v; - //Dgrb[indx][c]=(wtnw*Dgrb[indx-m1][c]+wtne*Dgrb[indx+p1][c]+wtsw*Dgrb[indx-p1][c]+wtse*Dgrb[indx+m1][c])/(wtnw+wtne+wtsw+wtse); - - _mm_storeu_ps(&Dgrb[c][indx>>1], (wtnwv*(oned325v*LVFU(Dgrb[c][(indx-m1)>>1])-zd175v*LVFU(Dgrb[c][(indx-m3)>>1])-zd075v*LVFU(Dgrb[c][(indx-m1-2)>>1])-zd075v*LVFU(Dgrb[c][(indx-m1-v2)>>1]) )+ - wtnev*(oned325v*LVFU(Dgrb[c][(indx+p1)>>1])-zd175v*LVFU(Dgrb[c][(indx+p3)>>1])-zd075v*LVFU(Dgrb[c][(indx+p1+2)>>1])-zd075v*LVFU(Dgrb[c][(indx+p1+v2)>>1]) )+ - wtswv*(oned325v*LVFU(Dgrb[c][(indx-p1)>>1])-zd175v*LVFU(Dgrb[c][(indx-p3)>>1])-zd075v*LVFU(Dgrb[c][(indx-p1-2)>>1])-zd075v*LVFU(Dgrb[c][(indx-p1-v2)>>1]) )+ - wtsev*(oned325v*LVFU(Dgrb[c][(indx+m1)>>1])-zd175v*LVFU(Dgrb[c][(indx+m3)>>1])-zd075v*LVFU(Dgrb[c][(indx+m1+2)>>1])-zd075v*LVFU(Dgrb[c][(indx+m1+v2)>>1]) ))/(wtnwv+wtnev+wtswv+wtsev)); - } + for (rr = 6; rr < rr1 - 6; rr++) { + if((FC(rr, 2) & 1) == 0) { + for (cc = 6, indx = (rr) * TS + cc; cc < cc1 - 6; cc += 8, indx += 8) { + tempv = LC2VFU(cfa[indx + 1]); + Dgrbsq1pv = (SQRV(tempv - LC2VFU(cfa[indx + 1 - p1])) + SQRV(tempv - LC2VFU(cfa[indx + 1 + p1]))); + _mm_storeu_ps( &delp[indx >> 1], vabsf(LC2VFU(cfa[indx + p1]) - LC2VFU(cfa[indx - p1]))); + _mm_storeu_ps( &delm[indx >> 1], vabsf(LC2VFU(cfa[indx + m1]) - LC2VFU(cfa[indx - m1]))); + Dgrbsq1mv = (SQRV(tempv - LC2VFU(cfa[indx + 1 - m1])) + SQRV(tempv - LC2VFU(cfa[indx + 1 + m1]))); + _mm_storeu_ps( &Dgrbsq1m[indx >> 1], Dgrbsq1mv ); + _mm_storeu_ps( &Dgrbsq1p[indx >> 1], Dgrbsq1pv ); + } + } else { + for (cc = 6, indx = (rr) * TS + cc; cc < cc1 - 6; cc += 8, indx += 8) { + tempv = LC2VFU(cfa[indx]); + Dgrbsq1pv = (SQRV(tempv - LC2VFU(cfa[indx - p1])) + SQRV(tempv - LC2VFU(cfa[indx + p1]))); + _mm_storeu_ps( &delp[indx >> 1], vabsf(LC2VFU(cfa[indx + 1 + p1]) - LC2VFU(cfa[indx + 1 - p1]))); + _mm_storeu_ps( &delm[indx >> 1], vabsf(LC2VFU(cfa[indx + 1 + m1]) - LC2VFU(cfa[indx + 1 - m1]))); + Dgrbsq1mv = (SQRV(tempv - LC2VFU(cfa[indx - m1])) + SQRV(tempv - LC2VFU(cfa[indx + m1]))); + _mm_storeu_ps( &Dgrbsq1m[indx >> 1], Dgrbsq1mv ); + _mm_storeu_ps( &Dgrbsq1p[indx >> 1], Dgrbsq1pv ); + } + } + } #else - for (cc=14+(FC(rr,2)&1),indx=rr*TS+cc,c=1-FC(rr,cc)/2; cc>1]-Dgrb[c][(indx+m1)>>1])+fabsf(Dgrb[c][(indx-m1)>>1]-Dgrb[c][(indx-m3)>>1])+fabsf(Dgrb[c][(indx+m1)>>1]-Dgrb[c][(indx-m3)>>1])); - wtne=1.0f/(eps+fabsf(Dgrb[c][(indx+p1)>>1]-Dgrb[c][(indx-p1)>>1])+fabsf(Dgrb[c][(indx+p1)>>1]-Dgrb[c][(indx+p3)>>1])+fabsf(Dgrb[c][(indx-p1)>>1]-Dgrb[c][(indx+p3)>>1])); - wtsw=1.0f/(eps+fabsf(Dgrb[c][(indx-p1)>>1]-Dgrb[c][(indx+p1)>>1])+fabsf(Dgrb[c][(indx-p1)>>1]-Dgrb[c][(indx+m3)>>1])+fabsf(Dgrb[c][(indx+p1)>>1]-Dgrb[c][(indx-p3)>>1])); - wtse=1.0f/(eps+fabsf(Dgrb[c][(indx+m1)>>1]-Dgrb[c][(indx-m1)>>1])+fabsf(Dgrb[c][(indx+m1)>>1]-Dgrb[c][(indx-p3)>>1])+fabsf(Dgrb[c][(indx-m1)>>1]-Dgrb[c][(indx+m3)>>1])); - //Dgrb[indx][c]=(wtnw*Dgrb[indx-m1][c]+wtne*Dgrb[indx+p1][c]+wtsw*Dgrb[indx-p1][c]+wtse*Dgrb[indx+m1][c])/(wtnw+wtne+wtsw+wtse); + for (rr = 6; rr < rr1 - 6; rr++) { + if((FC(rr, 2) & 1) == 0) { + for (cc = 6, indx = (rr) * TS + cc; cc < cc1 - 6; cc += 2, indx += 2) { + delp[indx >> 1] = fabsf(cfa[indx + p1] - cfa[indx - p1]); + delm[indx >> 1] = fabsf(cfa[indx + m1] - cfa[indx - m1]); + Dgrbsq1p[indx >> 1] = (SQR(cfa[indx + 1] - cfa[indx + 1 - p1]) + SQR(cfa[indx + 1] - cfa[indx + 1 + p1])); + Dgrbsq1m[indx >> 1] = (SQR(cfa[indx + 1] - cfa[indx + 1 - m1]) + SQR(cfa[indx + 1] - cfa[indx + 1 + m1])); + } + } else { + for (cc = 6, indx = (rr) * TS + cc; cc < cc1 - 6; cc += 2, indx += 2) { + Dgrbsq1p[indx >> 1] = (SQR(cfa[indx] - cfa[indx - p1]) + SQR(cfa[indx] - cfa[indx + p1])); + Dgrbsq1m[indx >> 1] = (SQR(cfa[indx] - cfa[indx - m1]) + SQR(cfa[indx] - cfa[indx + m1])); + delp[indx >> 1] = fabsf(cfa[indx + 1 + p1] - cfa[indx + 1 - p1]); + delm[indx >> 1] = fabsf(cfa[indx + 1 + m1] - cfa[indx + 1 - m1]); + } + } + } - Dgrb[c][indx>>1]=(wtnw*(1.325f*Dgrb[c][(indx-m1)>>1]-0.175f*Dgrb[c][(indx-m3)>>1]-0.075f*Dgrb[c][(indx-m1-2)>>1]-0.075f*Dgrb[c][(indx-m1-v2)>>1] )+ - wtne*(1.325f*Dgrb[c][(indx+p1)>>1]-0.175f*Dgrb[c][(indx+p3)>>1]-0.075f*Dgrb[c][(indx+p1+2)>>1]-0.075f*Dgrb[c][(indx+p1+v2)>>1] )+ - wtsw*(1.325f*Dgrb[c][(indx-p1)>>1]-0.175f*Dgrb[c][(indx-p3)>>1]-0.075f*Dgrb[c][(indx-p1-2)>>1]-0.075f*Dgrb[c][(indx-p1-v2)>>1] )+ - wtse*(1.325f*Dgrb[c][(indx+m1)>>1]-0.175f*Dgrb[c][(indx+m3)>>1]-0.075f*Dgrb[c][(indx+m1+2)>>1]-0.075f*Dgrb[c][(indx+m1+v2)>>1] ))/(wtnw+wtne+wtsw+wtse); - } #endif - float temp; - for (rr=16; rr>1])+(1.0f-hvwt[(indx+1)>>1])+(1.0f-hvwt[(indx-1)>>1])+(hvwt[(indx+v1)>>1])); - red[row][col]=65535.0f*(rgbgreen[indx]- ((hvwt[(indx-v1)>>1])*Dgrb[0][(indx-v1)>>1]+(1.0f-hvwt[(indx+1)>>1])*Dgrb[0][(indx+1)>>1]+(1.0f-hvwt[(indx-1)>>1])*Dgrb[0][(indx-1)>>1]+(hvwt[(indx+v1)>>1])*Dgrb[0][(indx+v1)>>1])* - temp); - blue[row][col]=65535.0f*(rgbgreen[indx]- ((hvwt[(indx-v1)>>1])*Dgrb[1][(indx-v1)>>1]+(1.0f-hvwt[(indx+1)>>1])*Dgrb[1][(indx+1)>>1]+(1.0f-hvwt[(indx-1)>>1])*Dgrb[1][(indx-1)>>1]+(hvwt[(indx+v1)>>1])*Dgrb[1][(indx+v1)>>1])* - temp); - indx++; - col++; - red[row][col]=65535.0f*(rgbgreen[indx]-Dgrb[0][indx>>1]); - blue[row][col]=65535.0f*(rgbgreen[indx]-Dgrb[1][indx>>1]); - } - if(cc1&1) { // width of tile is odd - col = cc + left; - temp = 1.0f/((hvwt[(indx-v1)>>1])+(1.0f-hvwt[(indx+1)>>1])+(1.0f-hvwt[(indx-1)>>1])+(hvwt[(indx+v1)>>1])); - red[row][col]=65535.0f*(rgbgreen[indx]- ((hvwt[(indx-v1)>>1])*Dgrb[0][(indx-v1)>>1]+(1.0f-hvwt[(indx+1)>>1])*Dgrb[0][(indx+1)>>1]+(1.0f-hvwt[(indx-1)>>1])*Dgrb[0][(indx-1)>>1]+(hvwt[(indx+v1)>>1])*Dgrb[0][(indx+v1)>>1])* - temp); - blue[row][col]=65535.0f*(rgbgreen[indx]- ((hvwt[(indx-v1)>>1])*Dgrb[1][(indx-v1)>>1]+(1.0f-hvwt[(indx+1)>>1])*Dgrb[1][(indx+1)>>1]+(1.0f-hvwt[(indx-1)>>1])*Dgrb[1][(indx-1)>>1]+(hvwt[(indx+v1)>>1])*Dgrb[1][(indx+v1)>>1])* - temp); - } - } - else { - for (cc=16,indx=rr*TS+cc,row=rr+top; cc>1]); - blue[row][col]=65535.0f*(rgbgreen[indx]-Dgrb[1][indx>>1]); + // end of tile initialization + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - indx++; - col++; - temp = 1.0f/((hvwt[(indx-v1)>>1])+(1.0f-hvwt[(indx+1)>>1])+(1.0f-hvwt[(indx-1)>>1])+(hvwt[(indx+v1)>>1])); - red[row][col]=65535.0f*(rgbgreen[indx]- ((hvwt[(indx-v1)>>1])*Dgrb[0][(indx-v1)>>1]+(1.0f-hvwt[(indx+1)>>1])*Dgrb[0][(indx+1)>>1]+(1.0f-hvwt[(indx-1)>>1])*Dgrb[0][(indx-1)>>1]+(hvwt[(indx+v1)>>1])*Dgrb[0][(indx+v1)>>1])* - temp); - blue[row][col]=65535.0f*(rgbgreen[indx]- ((hvwt[(indx-v1)>>1])*Dgrb[1][(indx-v1)>>1]+(1.0f-hvwt[(indx+1)>>1])*Dgrb[1][(indx+1)>>1]+(1.0f-hvwt[(indx-1)>>1])*Dgrb[1][(indx-1)>>1]+(hvwt[(indx+v1)>>1])*Dgrb[1][(indx+v1)>>1])* - temp); - } - if(cc1&1) { // width of tile is odd - col = cc + left; - red[row][col]=65535.0f*(rgbgreen[indx]-Dgrb[0][indx>>1]); - blue[row][col]=65535.0f*(rgbgreen[indx]-Dgrb[1][indx>>1]); - } - } - } + //interpolate vertical and horizontal color differences - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // copy smoothed results back to image matrix - for (rr=16; rr < rr1-16; rr++){ #ifdef __SSE2__ - for (row=rr+top, cc=16; cc < cc1-19; cc+=4) { - _mm_storeu_ps(&green[row][cc + left], LVF(rgbgreen[rr*TS+cc]) * c65535v); - } + __m128 sgnv, cruv, crdv, crlv, crrv, guhav, gdhav, glhav, grhav, hwtv, vwtv, Gintvhav, Ginthhav, guarv, gdarv, glarv, grarv; + vmask clipmask; + + if( !(FC(4, 4) & 1) ) { + sgnv = _mm_set_ps( 1.0f, -1.0f, 1.0f, -1.0f ); + } else { + sgnv = _mm_set_ps( -1.0f, 1.0f, -1.0f, 1.0f ); + } + + __m128 zd5v = _mm_set1_ps( 0.5f ); + __m128 onev = _mm_set1_ps( 1.0f ); + __m128 arthreshv = _mm_set1_ps( arthresh ); + __m128 clip_pt8v = _mm_set1_ps( clip_pt8 ); + + for (rr = 4; rr < rr1 - 4; rr++) { + sgnv = -sgnv; + + for (cc = 4, indx = rr * TS + cc; cc < cc1 - 7; cc += 4, indx += 4) { + //color ratios in each cardinal direction + cruv = LVF(cfa[indx - v1]) * (LVF(dirwts0[indx - v2]) + LVF(dirwts0[indx])) / (LVF(dirwts0[indx - v2]) * (epsv + LVF(cfa[indx])) + LVF(dirwts0[indx]) * (epsv + LVF(cfa[indx - v2]))); + crdv = LVF(cfa[indx + v1]) * (LVF(dirwts0[indx + v2]) + LVF(dirwts0[indx])) / (LVF(dirwts0[indx + v2]) * (epsv + LVF(cfa[indx])) + LVF(dirwts0[indx]) * (epsv + LVF(cfa[indx + v2]))); + crlv = LVFU(cfa[indx - 1]) * (LVFU(dirwts1[indx - 2]) + LVF(dirwts1[indx])) / (LVFU(dirwts1[indx - 2]) * (epsv + LVF(cfa[indx])) + LVF(dirwts1[indx]) * (epsv + LVFU(cfa[indx - 2]))); + crrv = LVFU(cfa[indx + 1]) * (LVFU(dirwts1[indx + 2]) + LVF(dirwts1[indx])) / (LVFU(dirwts1[indx + 2]) * (epsv + LVF(cfa[indx])) + LVF(dirwts1[indx]) * (epsv + LVFU(cfa[indx + 2]))); + + guhav = LVF(cfa[indx - v1]) + zd5v * (LVF(cfa[indx]) - LVF(cfa[indx - v2])); + gdhav = LVF(cfa[indx + v1]) + zd5v * (LVF(cfa[indx]) - LVF(cfa[indx + v2])); + glhav = LVFU(cfa[indx - 1]) + zd5v * (LVF(cfa[indx]) - LVFU(cfa[indx - 2])); + grhav = LVFU(cfa[indx + 1]) + zd5v * (LVF(cfa[indx]) - LVFU(cfa[indx + 2])); + + guarv = vself(vmaskf_lt(vabsf(onev - cruv), arthreshv), LVF(cfa[indx]) * cruv, guhav); + gdarv = vself(vmaskf_lt(vabsf(onev - crdv), arthreshv), LVF(cfa[indx]) * crdv, gdhav); + glarv = vself(vmaskf_lt(vabsf(onev - crlv), arthreshv), LVF(cfa[indx]) * crlv, glhav); + grarv = vself(vmaskf_lt(vabsf(onev - crrv), arthreshv), LVF(cfa[indx]) * crrv, grhav); + + hwtv = LVFU(dirwts1[indx - 1]) / (LVFU(dirwts1[indx - 1]) + LVFU(dirwts1[indx + 1])); + vwtv = LVF(dirwts0[indx - v1]) / (LVF(dirwts0[indx + v1]) + LVF(dirwts0[indx - v1])); + + //interpolated G via adaptive weights of cardinal evaluations + Ginthhav = hwtv * grhav + (onev - hwtv) * glhav; + Gintvhav = vwtv * gdhav + (onev - vwtv) * guhav; + //interpolated color differences + + _mm_store_ps( &hcdalt[indx], sgnv * (Ginthhav - LVF(cfa[indx]))); + _mm_store_ps( &vcdalt[indx], sgnv * (Gintvhav - LVF(cfa[indx]))); + + clipmask = vorm( vorm( vmaskf_gt( LVF(cfa[indx]), clip_pt8v ), vmaskf_gt( Gintvhav, clip_pt8v ) ), vmaskf_gt( Ginthhav, clip_pt8v )); + guarv = vself( clipmask, guhav, guarv); + gdarv = vself( clipmask, gdhav, gdarv); + glarv = vself( clipmask, glhav, glarv); + grarv = vself( clipmask, grhav, grarv); + _mm_store_ps( &vcd[indx], vself( clipmask, LVF(vcdalt[indx]), sgnv * ((vwtv * gdarv + (onev - vwtv)*guarv) - LVF(cfa[indx])))); + _mm_store_ps( &hcd[indx], vself( clipmask, LVF(hcdalt[indx]), sgnv * ((hwtv * grarv + (onev - hwtv)*glarv) - LVF(cfa[indx])))); + //differences of interpolations in opposite directions + + _mm_store_ps(&dgintv[indx], _mm_min_ps(SQRV(guhav - gdhav), SQRV(guarv - gdarv))); + _mm_store_ps(&dginth[indx], _mm_min_ps(SQRV(glhav - grhav), SQRV(glarv - grarv))); + + } + } + #else - for (row=rr+top, cc=16; cc < cc1-16; cc++) { - col = cc + left; - indx=rr*TS+cc; - green[row][col] = ((65535.0f*rgbgreen[indx])); + bool fcswitch; + + for (rr = 4; rr < rr1 - 4; rr++) { + for (cc = 4, indx = rr * TS + cc, fcswitch = FC(rr, cc) & 1; cc < cc1 - 4; cc++, indx++) { + + //color ratios in each cardinal direction + cru = cfa[indx - v1] * (dirwts0[indx - v2] + dirwts0[indx]) / (dirwts0[indx - v2] * (eps + cfa[indx]) + dirwts0[indx] * (eps + cfa[indx - v2])); + crd = cfa[indx + v1] * (dirwts0[indx + v2] + dirwts0[indx]) / (dirwts0[indx + v2] * (eps + cfa[indx]) + dirwts0[indx] * (eps + cfa[indx + v2])); + crl = cfa[indx - 1] * (dirwts1[indx - 2] + dirwts1[indx]) / (dirwts1[indx - 2] * (eps + cfa[indx]) + dirwts1[indx] * (eps + cfa[indx - 2])); + crr = cfa[indx + 1] * (dirwts1[indx + 2] + dirwts1[indx]) / (dirwts1[indx + 2] * (eps + cfa[indx]) + dirwts1[indx] * (eps + cfa[indx + 2])); + + guha = HCLIP(cfa[indx - v1]) + xdiv2f(cfa[indx] - cfa[indx - v2]); + gdha = HCLIP(cfa[indx + v1]) + xdiv2f(cfa[indx] - cfa[indx + v2]); + glha = HCLIP(cfa[indx - 1]) + xdiv2f(cfa[indx] - cfa[indx - 2]); + grha = HCLIP(cfa[indx + 1]) + xdiv2f(cfa[indx] - cfa[indx + 2]); + + if (fabsf(1.0f - cru) < arthresh) { + guar = cfa[indx] * cru; + } else { + guar = guha; + } + + if (fabsf(1.0f - crd) < arthresh) { + gdar = cfa[indx] * crd; + } else { + gdar = gdha; + } + + if (fabsf(1.0f - crl) < arthresh) { + glar = cfa[indx] * crl; + } else { + glar = glha; + } + + if (fabsf(1.0f - crr) < arthresh) { + grar = cfa[indx] * crr; + } else { + grar = grha; + } + + hwt = dirwts1[indx - 1] / (dirwts1[indx - 1] + dirwts1[indx + 1]); + vwt = dirwts0[indx - v1] / (dirwts0[indx + v1] + dirwts0[indx - v1]); + + //interpolated G via adaptive weights of cardinal evaluations + Gintvha = vwt * gdha + (1.0f - vwt) * guha; + Ginthha = hwt * grha + (1.0f - hwt) * glha; + + //interpolated color differences + if (fcswitch) { + vcd[indx] = cfa[indx] - (vwt * gdar + (1.0f - vwt) * guar); + hcd[indx] = cfa[indx] - (hwt * grar + (1.0f - hwt) * glar); + vcdalt[indx] = cfa[indx] - Gintvha; + hcdalt[indx] = cfa[indx] - Ginthha; + } else { + //interpolated color differences + vcd[indx] = (vwt * gdar + (1.0f - vwt) * guar) - cfa[indx]; + hcd[indx] = (hwt * grar + (1.0f - hwt) * glar) - cfa[indx]; + vcdalt[indx] = Gintvha - cfa[indx]; + hcdalt[indx] = Ginthha - cfa[indx]; + } + + fcswitch = !fcswitch; + + if (cfa[indx] > clip_pt8 || Gintvha > clip_pt8 || Ginthha > clip_pt8) { + //use HA if highlights are (nearly) clipped + guar = guha; + gdar = gdha; + glar = glha; + grar = grha; + vcd[indx] = vcdalt[indx]; + hcd[indx] = hcdalt[indx]; + } + + //differences of interpolations in opposite directions + dgintv[indx] = min(SQR(guha - gdha), SQR(guar - gdar)); + dginth[indx] = min(SQR(glha - grha), SQR(glar - grar)); + + } + + + } - //for dcraw implementation - //for (c=0; c<3; c++){ - // image[indx][c] = CLIP((int)(65535.0f*rgb[rr*TS+cc][c] + 0.5f)); - //} - } #endif - } - //end of main loop - if(plistener) { - progresscounter++; - if(progresscounter % 4 == 0) { -#pragma omp critical -{ - progress+=(double)4*((TS-32)*(TS-32))/(height*width); - if (progress>1.0) - { - progress=1.0; - } - plistener->setProgress(progress); -} - } - } - } +#ifdef __SSE2__ + __m128 hcdvarv, vcdvarv; + __m128 hcdaltvarv, vcdaltvarv, hcdv, vcdv, hcdaltv, vcdaltv, sgn3v, Ginthv, Gintvv, hcdoldv, vcdoldv; + __m128 threev = _mm_set1_ps( 3.0f ); + __m128 clip_ptv = _mm_set1_ps( clip_pt ); + __m128 nsgnv; + vmask hcdmask, vcdmask, tempmask; - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if( !(FC(4, 4) & 1) ) { + sgnv = _mm_set_ps( 1.0f, -1.0f, 1.0f, -1.0f ); + } else { + sgnv = _mm_set_ps( -1.0f, 1.0f, -1.0f, 1.0f ); + } + + sgn3v = threev * sgnv; + + for (rr = 4; rr < rr1 - 4; rr++) { + nsgnv = sgnv; + sgnv = -sgnv; + sgn3v = -sgn3v; + + for (cc = 4, indx = rr * TS + cc, c = FC(rr, cc) & 1; cc < cc1 - 4; cc += 4, indx += 4) { + hcdv = LVF( hcd[indx] ); + hcdvarv = threev * (SQRV(LVFU(hcd[indx - 2])) + SQRV(hcdv) + SQRV(LVFU(hcd[indx + 2]))) - SQRV(LVFU(hcd[indx - 2]) + hcdv + LVFU(hcd[indx + 2])); + hcdaltv = LVF( hcdalt[indx] ); + hcdaltvarv = threev * (SQRV(LVFU(hcdalt[indx - 2])) + SQRV(hcdaltv) + SQRV(LVFU(hcdalt[indx + 2]))) - SQRV(LVFU(hcdalt[indx - 2]) + hcdaltv + LVFU(hcdalt[indx + 2])); + vcdv = LVF( vcd[indx] ); + vcdvarv = threev * (SQRV(LVF(vcd[indx - v2])) + SQRV(vcdv) + SQRV(LVF(vcd[indx + v2]))) - SQRV(LVF(vcd[indx - v2]) + vcdv + LVF(vcd[indx + v2])); + vcdaltv = LVF( vcdalt[indx] ); + vcdaltvarv = threev * (SQRV(LVF(vcdalt[indx - v2])) + SQRV(vcdaltv) + SQRV(LVF(vcdalt[indx + v2]))) - SQRV(LVF(vcdalt[indx - v2]) + vcdaltv + LVF(vcdalt[indx + v2])); + //choose the smallest variance; this yields a smoother interpolation + hcdv = vself( vmaskf_lt( hcdaltvarv, hcdvarv ), hcdaltv, hcdv); + vcdv = vself( vmaskf_lt( vcdaltvarv, vcdvarv ), vcdaltv, vcdv); + + Ginthv = sgnv * hcdv + LVF( cfa[indx] ); + temp2v = sgn3v * hcdv; + hwtv = onev + temp2v / ( epsv + Ginthv + LVF( cfa[indx])); + hcdmask = vmaskf_gt( nsgnv * hcdv, ZEROV ); + hcdoldv = hcdv; + tempv = nsgnv * (LVF(cfa[indx]) - ULIMV( Ginthv, LVFU(cfa[indx - 1]), LVFU(cfa[indx + 1]) )); + hcdv = vself( vmaskf_lt( (temp2v), -(LVF(cfa[indx]) + Ginthv)), tempv, hwtv * hcdv + (onev - hwtv) * tempv); + hcdv = vself( hcdmask, hcdv, hcdoldv ); + hcdv = vself( vmaskf_gt( Ginthv, clip_ptv), tempv, hcdv); + _mm_store_ps( &hcd[indx], hcdv); + + Gintvv = sgnv * vcdv + LVF( cfa[indx] ); + temp2v = sgn3v * vcdv; + vwtv = onev + temp2v / ( epsv + Gintvv + LVF( cfa[indx])); + vcdmask = vmaskf_gt( nsgnv * vcdv, ZEROV ); + vcdoldv = vcdv; + tempv = nsgnv * (LVF(cfa[indx]) - ULIMV( Gintvv, LVF(cfa[indx - v1]), LVF(cfa[indx + v1]) )); + vcdv = vself( vmaskf_lt( (temp2v), -(LVF(cfa[indx]) + Gintvv)), tempv, vwtv * vcdv + (onev - vwtv) * tempv); + vcdv = vself( vcdmask, vcdv, vcdoldv ); + vcdv = vself( vmaskf_gt( Gintvv, clip_ptv), tempv, vcdv); + _mm_store_ps( &vcd[indx], vcdv); + _mm_storeu_ps(&cddiffsq[indx], SQRV(vcdv - hcdv)); + } + + } + +#else + + for (rr = 4; rr < rr1 - 4; rr++) { + //for (cc=4+(FC(rr,2)&1),indx=rr*TS+cc,c=FC(rr,cc); cc 0) { + if (3.0f * hcd[indx] > (Ginth + cfa[indx])) { + hcd[indx] = -ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]) + cfa[indx]; + } else { + hwt = 1.0f - 3.0f * hcd[indx] / (eps + Ginth + cfa[indx]); + hcd[indx] = hwt * hcd[indx] + (1.0f - hwt) * (-ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]) + cfa[indx]); + } + } + + if (vcd[indx] > 0) { + if (3.0f * vcd[indx] > (Gintv + cfa[indx])) { + vcd[indx] = -ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]) + cfa[indx]; + } else { + vwt = 1.0f - 3.0f * vcd[indx] / (eps + Gintv + cfa[indx]); + vcd[indx] = vwt * vcd[indx] + (1.0f - vwt) * (-ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]) + cfa[indx]); + } + } + + if (Ginth > clip_pt) { + hcd[indx] = -ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]) + cfa[indx]; //for RT implementation + } + + if (Gintv > clip_pt) { + vcd[indx] = -ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]) + cfa[indx]; + } + + //if (Ginth > pre_mul[c]) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for dcraw implementation + //if (Gintv > pre_mul[c]) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; + + } else {//R or B site + + Ginth = hcd[indx] + cfa[indx]; //interpolated G + Gintv = vcd[indx] + cfa[indx]; + + if (hcd[indx] < 0) { + if (3.0f * hcd[indx] < -(Ginth + cfa[indx])) { + hcd[indx] = ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]) - cfa[indx]; + } else { + hwt = 1.0f + 3.0f * hcd[indx] / (eps + Ginth + cfa[indx]); + hcd[indx] = hwt * hcd[indx] + (1.0f - hwt) * (ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]) - cfa[indx]); + } + } + + if (vcd[indx] < 0) { + if (3.0f * vcd[indx] < -(Gintv + cfa[indx])) { + vcd[indx] = ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]) - cfa[indx]; + } else { + vwt = 1.0f + 3.0f * vcd[indx] / (eps + Gintv + cfa[indx]); + vcd[indx] = vwt * vcd[indx] + (1.0f - vwt) * (ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]) - cfa[indx]); + } + } + + if (Ginth > clip_pt) { + hcd[indx] = ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]) - cfa[indx]; //for RT implementation + } + + if (Gintv > clip_pt) { + vcd[indx] = ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]) - cfa[indx]; + } + + //if (Ginth > pre_mul[c]) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for dcraw implementation + //if (Gintv > pre_mul[c]) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; + cddiffsq[indx] = SQR(vcd[indx] - hcd[indx]); + } + + c = !c; + } + } + +#endif + +#ifdef __SSE2__ + __m128 uavev, davev, lavev, ravev, Dgrbvvaruv, Dgrbvvardv, Dgrbhvarlv, Dgrbhvarrv, varwtv, diffwtv, vcdvar1v, hcdvar1v; + __m128 epssqv = _mm_set1_ps( epssq ); + vmask decmask; + + for (rr = 6; rr < rr1 - 6; rr++) { + for (cc = 6 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 6; cc += 8, indx += 8) { + //compute color difference variances in cardinal directions + tempv = LC2VFU(vcd[indx]); + uavev = tempv + LC2VFU(vcd[indx - v1]) + LC2VFU(vcd[indx - v2]) + LC2VFU(vcd[indx - v3]); + davev = tempv + LC2VFU(vcd[indx + v1]) + LC2VFU(vcd[indx + v2]) + LC2VFU(vcd[indx + v3]); + Dgrbvvaruv = SQRV(tempv - uavev) + SQRV(LC2VFU(vcd[indx - v1]) - uavev) + SQRV(LC2VFU(vcd[indx - v2]) - uavev) + SQRV(LC2VFU(vcd[indx - v3]) - uavev); + Dgrbvvardv = SQRV(tempv - davev) + SQRV(LC2VFU(vcd[indx + v1]) - davev) + SQRV(LC2VFU(vcd[indx + v2]) - davev) + SQRV(LC2VFU(vcd[indx + v3]) - davev); + + hwtv = LC2VFU(dirwts1[indx - 1]) / (LC2VFU(dirwts1[indx - 1]) + LC2VFU(dirwts1[indx + 1])); + vwtv = LC2VFU(dirwts0[indx - v1]) / (LC2VFU(dirwts0[indx + v1]) + LC2VFU(dirwts0[indx - v1])); + + tempv = LC2VFU(hcd[indx]); + lavev = tempv + LC2VFU(hcd[indx - 1]) + LC2VFU(hcd[indx - 2]) + LC2VFU(hcd[indx - 3]); + ravev = tempv + LC2VFU(hcd[indx + 1]) + LC2VFU(hcd[indx + 2]) + LC2VFU(hcd[indx + 3]); + Dgrbhvarlv = SQRV(tempv - lavev) + SQRV(LC2VFU(hcd[indx - 1]) - lavev) + SQRV(LC2VFU(hcd[indx - 2]) - lavev) + SQRV(LC2VFU(hcd[indx - 3]) - lavev); + Dgrbhvarrv = SQRV(tempv - ravev) + SQRV(LC2VFU(hcd[indx + 1]) - ravev) + SQRV(LC2VFU(hcd[indx + 2]) - ravev) + SQRV(LC2VFU(hcd[indx + 3]) - ravev); + + + vcdvarv = epssqv + vwtv * Dgrbvvardv + (onev - vwtv) * Dgrbvvaruv; + hcdvarv = epssqv + hwtv * Dgrbhvarrv + (onev - hwtv) * Dgrbhvarlv; + + //compute fluctuations in up/down and left/right interpolations of colors + Dgrbvvaruv = (LC2VFU(dgintv[indx])) + (LC2VFU(dgintv[indx - v1])) + (LC2VFU(dgintv[indx - v2])); + Dgrbvvardv = (LC2VFU(dgintv[indx])) + (LC2VFU(dgintv[indx + v1])) + (LC2VFU(dgintv[indx + v2])); + Dgrbhvarlv = (LC2VFU(dginth[indx])) + (LC2VFU(dginth[indx - 1])) + (LC2VFU(dginth[indx - 2])); + Dgrbhvarrv = (LC2VFU(dginth[indx])) + (LC2VFU(dginth[indx + 1])) + (LC2VFU(dginth[indx + 2])); + + vcdvar1v = epssqv + vwtv * Dgrbvvardv + (onev - vwtv) * Dgrbvvaruv; + hcdvar1v = epssqv + hwtv * Dgrbhvarrv + (onev - hwtv) * Dgrbhvarlv; + + //determine adaptive weights for G interpolation + varwtv = hcdvarv / (vcdvarv + hcdvarv); + diffwtv = hcdvar1v / (vcdvar1v + hcdvar1v); + + //if both agree on interpolation direction, choose the one with strongest directional discrimination; + //otherwise, choose the u/d and l/r difference fluctuation weights + decmask = vandm( vmaskf_gt( (zd5v - varwtv) * (zd5v - diffwtv), ZEROV ), vmaskf_lt( vabsf( zd5v - diffwtv), vabsf( zd5v - varwtv) ) ); + _mm_storeu_ps( &hvwt[indx >> 1], vself( decmask, varwtv, diffwtv)); + } + } + +#else + + for (rr = 6; rr < rr1 - 6; rr++) { + for (cc = 6 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 6; cc += 2, indx += 2) { + + //compute color difference variances in cardinal directions + + uave = vcd[indx] + vcd[indx - v1] + vcd[indx - v2] + vcd[indx - v3]; + dave = vcd[indx] + vcd[indx + v1] + vcd[indx + v2] + vcd[indx + v3]; + lave = hcd[indx] + hcd[indx - 1] + hcd[indx - 2] + hcd[indx - 3]; + rave = hcd[indx] + hcd[indx + 1] + hcd[indx + 2] + hcd[indx + 3]; + + Dgrbvvaru = SQR(vcd[indx] - uave) + SQR(vcd[indx - v1] - uave) + SQR(vcd[indx - v2] - uave) + SQR(vcd[indx - v3] - uave); + Dgrbvvard = SQR(vcd[indx] - dave) + SQR(vcd[indx + v1] - dave) + SQR(vcd[indx + v2] - dave) + SQR(vcd[indx + v3] - dave); + Dgrbhvarl = SQR(hcd[indx] - lave) + SQR(hcd[indx - 1] - lave) + SQR(hcd[indx - 2] - lave) + SQR(hcd[indx - 3] - lave); + Dgrbhvarr = SQR(hcd[indx] - rave) + SQR(hcd[indx + 1] - rave) + SQR(hcd[indx + 2] - rave) + SQR(hcd[indx + 3] - rave); + + hwt = dirwts1[indx - 1] / (dirwts1[indx - 1] + dirwts1[indx + 1]); + vwt = dirwts0[indx - v1] / (dirwts0[indx + v1] + dirwts0[indx - v1]); + + vcdvar = epssq + vwt * Dgrbvvard + (1.0f - vwt) * Dgrbvvaru; + hcdvar = epssq + hwt * Dgrbhvarr + (1.0f - hwt) * Dgrbhvarl; + + //compute fluctuations in up/down and left/right interpolations of colors + Dgrbvvaru = (dgintv[indx]) + (dgintv[indx - v1]) + (dgintv[indx - v2]); + Dgrbvvard = (dgintv[indx]) + (dgintv[indx + v1]) + (dgintv[indx + v2]); + Dgrbhvarl = (dginth[indx]) + (dginth[indx - 1]) + (dginth[indx - 2]); + Dgrbhvarr = (dginth[indx]) + (dginth[indx + 1]) + (dginth[indx + 2]); + + vcdvar1 = epssq + vwt * Dgrbvvard + (1.0f - vwt) * Dgrbvvaru; + hcdvar1 = epssq + hwt * Dgrbhvarr + (1.0f - hwt) * Dgrbhvarl; + + //determine adaptive weights for G interpolation + varwt = hcdvar / (vcdvar + hcdvar); + diffwt = hcdvar1 / (vcdvar1 + hcdvar1); + + //if both agree on interpolation direction, choose the one with strongest directional discrimination; + //otherwise, choose the u/d and l/r difference fluctuation weights + if ((0.5 - varwt) * (0.5 - diffwt) > 0 && fabsf(0.5 - diffwt) < fabsf(0.5 - varwt)) { + hvwt[indx >> 1] = varwt; + } else { + hvwt[indx >> 1] = diffwt; + } + + //hvwt[indx]=varwt; + } + } + +#endif + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // Nyquist test + for (rr = 6; rr < rr1 - 6; rr++) + for (cc = 6 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 6; cc += 2, indx += 2) { + + //nyquist texture test: ask if difference of vcd compared to hcd is larger or smaller than RGGB gradients + nyqtest = (gaussodd[0] * cddiffsq[indx] + + gaussodd[1] * (cddiffsq[(indx - m1)] + cddiffsq[(indx + p1)] + + cddiffsq[(indx - p1)] + cddiffsq[(indx + m1)]) + + gaussodd[2] * (cddiffsq[(indx - v2)] + cddiffsq[(indx - 2)] + + cddiffsq[(indx + 2)] + cddiffsq[(indx + v2)]) + + gaussodd[3] * (cddiffsq[(indx - m2)] + cddiffsq[(indx + p2)] + + cddiffsq[(indx - p2)] + cddiffsq[(indx + m2)])); + + nyqtest -= nyqthresh * (gaussgrad[0] * (delhvsqsum[indx]) + + gaussgrad[1] * (delhvsqsum[indx - v1] + delhvsqsum[indx + 1] + + delhvsqsum[indx - 1] + delhvsqsum[indx + v1]) + + gaussgrad[2] * (delhvsqsum[indx - m1] + delhvsqsum[indx + p1] + + delhvsqsum[indx - p1] + delhvsqsum[indx + m1]) + + gaussgrad[3] * (delhvsqsum[indx - v2] + delhvsqsum[indx - 2] + + delhvsqsum[indx + 2] + delhvsqsum[indx + v2]) + + gaussgrad[4] * (delhvsqsum[indx - 2 * TS - 1] + delhvsqsum[indx - 2 * TS + 1] + + delhvsqsum[indx - TS - 2] + delhvsqsum[indx - TS + 2] + + delhvsqsum[indx + TS - 2] + delhvsqsum[indx + TS + 2] + + delhvsqsum[indx + 2 * TS - 1] + delhvsqsum[indx + 2 * TS + 1]) + + gaussgrad[5] * (delhvsqsum[indx - m2] + delhvsqsum[indx + p2] + + delhvsqsum[indx - p2] + delhvsqsum[indx + m2])); + + + if (nyqtest > 0) { + nyquist[indx >> 1] = 1; //nyquist=1 for nyquist region + } + } + + unsigned int nyquisttemp; + + for (rr = 8; rr < rr1 - 8; rr++) { + for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 8; cc += 2, indx += 2) { + + nyquisttemp = (nyquist[(indx - v2) >> 1] + nyquist[(indx - m1) >> 1] + nyquist[(indx + p1) >> 1] + + nyquist[(indx - 2) >> 1] + nyquist[indx >> 1] + nyquist[(indx + 2) >> 1] + + nyquist[(indx - p1) >> 1] + nyquist[(indx + m1) >> 1] + nyquist[(indx + v2) >> 1]); + + //if most of your neighbors are named Nyquist, it's likely that you're one too + if (nyquisttemp > 4) { + nyquist[indx >> 1] = 1; + } + + //or not + if (nyquisttemp < 4) { + nyquist[indx >> 1] = 0; + } + } + } + + // end of Nyquist test + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // in areas of Nyquist texture, do area interpolation + for (rr = 8; rr < rr1 - 8; rr++) + for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 8; cc += 2, indx += 2) { + + if (nyquist[indx >> 1]) { + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // area interpolation + + sumh = sumv = sumsqh = sumsqv = areawt = 0; + + for (i = -6; i < 7; i += 2) + for (j = -6; j < 7; j += 2) { + indx1 = (rr + i) * TS + cc + j; + + if (nyquist[indx1 >> 1]) { + sumh += cfa[indx1] - xdiv2f(cfa[indx1 - 1] + cfa[indx1 + 1]); + sumv += cfa[indx1] - xdiv2f(cfa[indx1 - v1] + cfa[indx1 + v1]); + sumsqh += xdiv2f(SQR(cfa[indx1] - cfa[indx1 - 1]) + SQR(cfa[indx1] - cfa[indx1 + 1])); + sumsqv += xdiv2f(SQR(cfa[indx1] - cfa[indx1 - v1]) + SQR(cfa[indx1] - cfa[indx1 + v1])); + areawt += 1; + } + } + + //horizontal and vertical color differences, and adaptive weight + hcdvar = epssq + fabsf(areawt * sumsqh - sumh * sumh); + vcdvar = epssq + fabsf(areawt * sumsqv - sumv * sumv); + hvwt[indx >> 1] = hcdvar / (vcdvar + hcdvar); + + // end of area interpolation + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + } + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //populate G at R/B sites + for (rr = 8; rr < rr1 - 8; rr++) + for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 8; cc += 2, indx += 2) { + + //first ask if one gets more directional discrimination from nearby B/R sites + hvwtalt = xdivf(hvwt[(indx - m1) >> 1] + hvwt[(indx + p1) >> 1] + hvwt[(indx - p1) >> 1] + hvwt[(indx + m1) >> 1], 2); + +// hvwtalt = 0.25*(hvwt[(indx-m1)>>1]+hvwt[(indx+p1)>>1]+hvwt[(indx-p1)>>1]+hvwt[(indx+m1)>>1]); +// vo=fabsf(0.5-hvwt[indx>>1]); +// ve=fabsf(0.5-hvwtalt); + if (fabsf(0.5 - hvwt[indx >> 1]) < fabsf(0.5 - hvwtalt)) { + hvwt[indx >> 1] = hvwtalt; //a better result was obtained from the neighbors + } + +// if (vo>1]=hvwtalt;}//a better result was obtained from the neighbors - // clean up - free(buffer); -} - if(plistener) - plistener->setProgress(1.0); + Dgrb[0][indx >> 1] = (hcd[indx] * (1.0f - hvwt[indx >> 1]) + vcd[indx] * hvwt[indx >> 1]); //evaluate color differences + //if (hvwt[indx]<0.5) Dgrb[indx][0]=hcd[indx]; + //if (hvwt[indx]>0.5) Dgrb[indx][0]=vcd[indx]; + rgbgreen[indx] = cfa[indx] + Dgrb[0][indx >> 1]; //evaluate G (finally!) + + //local curvature in G (preparation for nyquist refinement step) + if (nyquist[indx >> 1]) { + Dgrb2[indx >> 1].h = SQR(rgbgreen[indx] - xdiv2f(rgbgreen[indx - 1] + rgbgreen[indx + 1])); + Dgrb2[indx >> 1].v = SQR(rgbgreen[indx] - xdiv2f(rgbgreen[indx - v1] + rgbgreen[indx + v1])); + } else { + Dgrb2[indx >> 1].h = Dgrb2[indx >> 1].v = 0; + } + } + + //end of standard interpolation + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // done + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // refine Nyquist areas using G curvatures + + for (rr = 8; rr < rr1 - 8; rr++) + for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc; cc < cc1 - 8; cc += 2, indx += 2) { + + if (nyquist[indx >> 1]) { + //local averages (over Nyquist pixels only) of G curvature squared + gvarh = epssq + (gquinc[0] * Dgrb2[indx >> 1].h + + gquinc[1] * (Dgrb2[(indx - m1) >> 1].h + Dgrb2[(indx + p1) >> 1].h + Dgrb2[(indx - p1) >> 1].h + Dgrb2[(indx + m1) >> 1].h) + + gquinc[2] * (Dgrb2[(indx - v2) >> 1].h + Dgrb2[(indx - 2) >> 1].h + Dgrb2[(indx + 2) >> 1].h + Dgrb2[(indx + v2) >> 1].h) + + gquinc[3] * (Dgrb2[(indx - m2) >> 1].h + Dgrb2[(indx + p2) >> 1].h + Dgrb2[(indx - p2) >> 1].h + Dgrb2[(indx + m2) >> 1].h)); + gvarv = epssq + (gquinc[0] * Dgrb2[indx >> 1].v + + gquinc[1] * (Dgrb2[(indx - m1) >> 1].v + Dgrb2[(indx + p1) >> 1].v + Dgrb2[(indx - p1) >> 1].v + Dgrb2[(indx + m1) >> 1].v) + + gquinc[2] * (Dgrb2[(indx - v2) >> 1].v + Dgrb2[(indx - 2) >> 1].v + Dgrb2[(indx + 2) >> 1].v + Dgrb2[(indx + v2) >> 1].v) + + gquinc[3] * (Dgrb2[(indx - m2) >> 1].v + Dgrb2[(indx + p2) >> 1].v + Dgrb2[(indx - p2) >> 1].v + Dgrb2[(indx + m2) >> 1].v)); + //use the results as weights for refined G interpolation + Dgrb[0][indx >> 1] = (hcd[indx] * gvarv + vcd[indx] * gvarh) / (gvarv + gvarh); + rgbgreen[indx] = cfa[indx] + Dgrb[0][indx >> 1]; + } + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // diagonal interpolation correction + +#ifdef __SSE2__ + __m128 rbsev, rbnwv, rbnev, rbswv, cfav, rbmv, rbpv, temp1v, wtv; + __m128 wtsev, wtnwv, wtnev, wtswv, rbvarmv; + __m128 gausseven0v = _mm_set1_ps(gausseven[0]); + __m128 gausseven1v = _mm_set1_ps(gausseven[1]); + __m128 twov = _mm_set1_ps(2.0f); +#endif + + for (rr = 8; rr < rr1 - 8; rr++) { +#ifdef __SSE2__ + + for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc, indx1 = indx >> 1; cc < cc1 - 8; cc += 8, indx += 8, indx1 += 4) { + + //diagonal color ratios + cfav = LC2VFU(cfa[indx]); + + temp1v = LC2VFU(cfa[indx + m1]); + temp2v = LC2VFU(cfa[indx + m2]); + rbsev = (temp1v + temp1v) / (epsv + cfav + temp2v ); + rbsev = vself(vmaskf_lt(vabsf(onev - rbsev), arthreshv), cfav * rbsev, temp1v + zd5v * (cfav - temp2v)); + + temp1v = LC2VFU(cfa[indx - m1]); + temp2v = LC2VFU(cfa[indx - m2]); + rbnwv = (temp1v + temp1v) / (epsv + cfav + temp2v ); + rbnwv = vself(vmaskf_lt(vabsf(onev - rbnwv), arthreshv), cfav * rbnwv, temp1v + zd5v * (cfav - temp2v)); + + temp1v = epsv + LVFU(delm[indx1]); + wtsev = temp1v + LVFU(delm[(indx + m1) >> 1]) + LVFU(delm[(indx + m2) >> 1]); //same as for wtu,wtd,wtl,wtr + wtnwv = temp1v + LVFU(delm[(indx - m1) >> 1]) + LVFU(delm[(indx - m2) >> 1]); + + rbmv = (wtsev * rbnwv + wtnwv * rbsev) / (wtsev + wtnwv); + + temp1v = ULIMV(rbmv , LC2VFU(cfa[indx - m1]), LC2VFU(cfa[indx + m1])); + wtv = twov * (cfav - rbmv) / (epsv + rbmv + cfav); + temp2v = wtv * rbmv + (onev - wtv) * temp1v; + + temp2v = vself(vmaskf_lt(rbmv + rbmv, cfav), temp1v, temp2v); + temp2v = vself(vmaskf_lt(rbmv, cfav), temp2v, rbmv); + _mm_storeu_ps(&rbm[indx1], vself(vmaskf_gt(temp2v, clip_ptv), ULIMV(temp2v , LC2VFU(cfa[indx - m1]), LC2VFU(cfa[indx + m1])), temp2v )); + + + temp1v = LC2VFU(cfa[indx + p1]); + temp2v = LC2VFU(cfa[indx + p2]); + rbnev = (temp1v + temp1v) / (epsv + cfav + temp2v ); + rbnev = vself(vmaskf_lt(vabsf(onev - rbnev), arthreshv), cfav * rbnev, temp1v + zd5v * (cfav - temp2v)); + + temp1v = LC2VFU(cfa[indx - p1]); + temp2v = LC2VFU(cfa[indx - p2]); + rbswv = (temp1v + temp1v) / (epsv + cfav + temp2v ); + rbswv = vself(vmaskf_lt(vabsf(onev - rbswv), arthreshv), cfav * rbswv, temp1v + zd5v * (cfav - temp2v)); + + temp1v = epsv + LVFU(delp[indx1]); + wtnev = temp1v + LVFU(delp[(indx + p1) >> 1]) + LVFU(delp[(indx + p2) >> 1]); + wtswv = temp1v + LVFU(delp[(indx - p1) >> 1]) + LVFU(delp[(indx - p2) >> 1]); + + rbpv = (wtnev * rbswv + wtswv * rbnev) / (wtnev + wtswv); + + temp1v = ULIMV(rbpv , LC2VFU(cfa[indx - p1]), LC2VFU(cfa[indx + p1])); + wtv = twov * (cfav - rbpv) / (epsv + rbpv + cfav); + temp2v = wtv * rbpv + (onev - wtv) * temp1v; + + temp2v = vself(vmaskf_lt(rbpv + rbpv, cfav), temp1v, temp2v); + temp2v = vself(vmaskf_lt(rbpv, cfav), temp2v, rbpv); + _mm_storeu_ps(&rbp[indx1], vself(vmaskf_gt(temp2v, clip_ptv), ULIMV(temp2v , LC2VFU(cfa[indx - p1]), LC2VFU(cfa[indx + p1])), temp2v )); + + + + rbvarmv = epssqv + (gausseven0v * (LVFU(Dgrbsq1m[(indx - v1) >> 1]) + LVFU(Dgrbsq1m[(indx - 1) >> 1]) + LVFU(Dgrbsq1m[(indx + 1) >> 1]) + LVFU(Dgrbsq1m[(indx + v1) >> 1])) + + gausseven1v * (LVFU(Dgrbsq1m[(indx - v2 - 1) >> 1]) + LVFU(Dgrbsq1m[(indx - v2 + 1) >> 1]) + LVFU(Dgrbsq1m[(indx - 2 - v1) >> 1]) + LVFU(Dgrbsq1m[(indx + 2 - v1) >> 1]) + + LVFU(Dgrbsq1m[(indx - 2 + v1) >> 1]) + LVFU(Dgrbsq1m[(indx + 2 + v1) >> 1]) + LVFU(Dgrbsq1m[(indx + v2 - 1) >> 1]) + LVFU(Dgrbsq1m[(indx + v2 + 1) >> 1]))); + _mm_storeu_ps(&pmwt[indx1] , rbvarmv / ((epssqv + (gausseven0v * (LVFU(Dgrbsq1p[(indx - v1) >> 1]) + LVFU(Dgrbsq1p[(indx - 1) >> 1]) + LVFU(Dgrbsq1p[(indx + 1) >> 1]) + LVFU(Dgrbsq1p[(indx + v1) >> 1])) + + gausseven1v * (LVFU(Dgrbsq1p[(indx - v2 - 1) >> 1]) + LVFU(Dgrbsq1p[(indx - v2 + 1) >> 1]) + LVFU(Dgrbsq1p[(indx - 2 - v1) >> 1]) + LVFU(Dgrbsq1p[(indx + 2 - v1) >> 1]) + + LVFU(Dgrbsq1p[(indx - 2 + v1) >> 1]) + LVFU(Dgrbsq1p[(indx + 2 + v1) >> 1]) + LVFU(Dgrbsq1p[(indx + v2 - 1) >> 1]) + LVFU(Dgrbsq1p[(indx + v2 + 1) >> 1])))) + rbvarmv)); + + } + +#else + + for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc, indx1 = indx >> 1; cc < cc1 - 8; cc += 2, indx += 2, indx1++) { + + //diagonal color ratios + crse = xmul2f(cfa[indx + m1]) / (eps + cfa[indx] + (cfa[indx + m2])); + crnw = xmul2f(cfa[indx - m1]) / (eps + cfa[indx] + (cfa[indx - m2])); + crne = xmul2f(cfa[indx + p1]) / (eps + cfa[indx] + (cfa[indx + p2])); + crsw = xmul2f(cfa[indx - p1]) / (eps + cfa[indx] + (cfa[indx - p2])); + + //assign B/R at R/B sites + if (fabsf(1.0f - crse) < arthresh) { + rbse = cfa[indx] * crse; //use this if more precise diag interp is necessary + } else { + rbse = (cfa[indx + m1]) + xdiv2f(cfa[indx] - cfa[indx + m2]); + } + + if (fabsf(1.0f - crnw) < arthresh) { + rbnw = cfa[indx] * crnw; + } else { + rbnw = (cfa[indx - m1]) + xdiv2f(cfa[indx] - cfa[indx - m2]); + } + + if (fabsf(1.0f - crne) < arthresh) { + rbne = cfa[indx] * crne; + } else { + rbne = (cfa[indx + p1]) + xdiv2f(cfa[indx] - cfa[indx + p2]); + } + + if (fabsf(1.0f - crsw) < arthresh) { + rbsw = cfa[indx] * crsw; + } else { + rbsw = (cfa[indx - p1]) + xdiv2f(cfa[indx] - cfa[indx - p2]); + } + + wtse = eps + delm[indx1] + delm[(indx + m1) >> 1] + delm[(indx + m2) >> 1]; //same as for wtu,wtd,wtl,wtr + wtnw = eps + delm[indx1] + delm[(indx - m1) >> 1] + delm[(indx - m2) >> 1]; + wtne = eps + delp[indx1] + delp[(indx + p1) >> 1] + delp[(indx + p2) >> 1]; + wtsw = eps + delp[indx1] + delp[(indx - p1) >> 1] + delp[(indx - p2) >> 1]; + + + rbm[indx1] = (wtse * rbnw + wtnw * rbse) / (wtse + wtnw); + rbp[indx1] = (wtne * rbsw + wtsw * rbne) / (wtne + wtsw); + /* + rbvarp = epssq + (gausseven[0]*(Dgrbsq1[indx-v1].p+Dgrbsq1[indx-1].p+Dgrbsq1[indx+1].p+Dgrbsq1[indx+v1].p) + + gausseven[1]*(Dgrbsq1[indx-v2-1].p+Dgrbsq1[indx-v2+1].p+Dgrbsq1[indx-2-v1].p+Dgrbsq1[indx+2-v1].p+ + Dgrbsq1[indx-2+v1].p+Dgrbsq1[indx+2+v1].p+Dgrbsq1[indx+v2-1].p+Dgrbsq1[indx+v2+1].p)); + */ + rbvarm = epssq + (gausseven[0] * (Dgrbsq1m[(indx - v1) >> 1] + Dgrbsq1m[(indx - 1) >> 1] + Dgrbsq1m[(indx + 1) >> 1] + Dgrbsq1m[(indx + v1) >> 1]) + + gausseven[1] * (Dgrbsq1m[(indx - v2 - 1) >> 1] + Dgrbsq1m[(indx - v2 + 1) >> 1] + Dgrbsq1m[(indx - 2 - v1) >> 1] + Dgrbsq1m[(indx + 2 - v1) >> 1] + + Dgrbsq1m[(indx - 2 + v1) >> 1] + Dgrbsq1m[(indx + 2 + v1) >> 1] + Dgrbsq1m[(indx + v2 - 1) >> 1] + Dgrbsq1m[(indx + v2 + 1) >> 1])); + pmwt[indx1] = rbvarm / ((epssq + (gausseven[0] * (Dgrbsq1p[(indx - v1) >> 1] + Dgrbsq1p[(indx - 1) >> 1] + Dgrbsq1p[(indx + 1) >> 1] + Dgrbsq1p[(indx + v1) >> 1]) + + gausseven[1] * (Dgrbsq1p[(indx - v2 - 1) >> 1] + Dgrbsq1p[(indx - v2 + 1) >> 1] + Dgrbsq1p[(indx - 2 - v1) >> 1] + Dgrbsq1p[(indx + 2 - v1) >> 1] + + Dgrbsq1p[(indx - 2 + v1) >> 1] + Dgrbsq1p[(indx + 2 + v1) >> 1] + Dgrbsq1p[(indx + v2 - 1) >> 1] + Dgrbsq1p[(indx + v2 + 1) >> 1]))) + rbvarm); + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //bound the interpolation in regions of high saturation + if (rbp[indx1] < cfa[indx]) { + if (xmul2f(rbp[indx1]) < cfa[indx]) { + rbp[indx1] = ULIM(rbp[indx1] , cfa[indx - p1], cfa[indx + p1]); + } else { + pwt = xmul2f(cfa[indx] - rbp[indx1]) / (eps + rbp[indx1] + cfa[indx]); + rbp[indx1] = pwt * rbp[indx1] + (1.0f - pwt) * ULIM(rbp[indx1], cfa[indx - p1], cfa[indx + p1]); + } + } + + if (rbm[indx1] < cfa[indx]) { + if (xmul2f(rbm[indx1]) < cfa[indx]) { + rbm[indx1] = ULIM(rbm[indx1] , cfa[indx - m1], cfa[indx + m1]); + } else { + mwt = xmul2f(cfa[indx] - rbm[indx1]) / (eps + rbm[indx1] + cfa[indx]); + rbm[indx1] = mwt * rbm[indx1] + (1.0f - mwt) * ULIM(rbm[indx1], cfa[indx - m1], cfa[indx + m1]); + } + } + + if (rbp[indx1] > clip_pt) { + rbp[indx1] = ULIM(rbp[indx1], cfa[indx - p1], cfa[indx + p1]); //for RT implementation + } + + if (rbm[indx1] > clip_pt) { + rbm[indx1] = ULIM(rbm[indx1], cfa[indx - m1], cfa[indx + m1]); + } + + //c=2-FC(rr,cc);//for dcraw implementation + //if (rbp[indx] > pre_mul[c]) rbp[indx]=ULIM(rbp[indx],cfa[indx-p1],cfa[indx+p1]); + //if (rbm[indx] > pre_mul[c]) rbm[indx]=ULIM(rbm[indx],cfa[indx-m1],cfa[indx+m1]); + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //rbint[indx] = 0.5*(cfa[indx] + (rbp*rbvarm+rbm*rbvarp)/(rbvarp+rbvarm));//this is R+B, interpolated + } + +#endif + } + +#ifdef __SSE2__ + __m128 pmwtaltv; + __m128 zd25v = _mm_set1_ps(0.25f); +#endif + + for (rr = 10; rr < rr1 - 10; rr++) +#ifdef __SSE2__ + for (cc = 10 + (FC(rr, 2) & 1), indx = rr * TS + cc, indx1 = indx >> 1; cc < cc1 - 10; cc += 8, indx += 8, indx1 += 4) { + + //first ask if one gets more directional discrimination from nearby B/R sites + pmwtaltv = zd25v * (LVFU(pmwt[(indx - m1) >> 1]) + LVFU(pmwt[(indx + p1) >> 1]) + LVFU(pmwt[(indx - p1) >> 1]) + LVFU(pmwt[(indx + m1) >> 1])); + tempv = LVFU(pmwt[indx1]); + tempv = vself(vmaskf_lt(vabsf(zd5v - tempv), vabsf(zd5v - pmwtaltv)), pmwtaltv, tempv); + _mm_storeu_ps( &pmwt[indx1], tempv); + _mm_storeu_ps( &rbint[indx1], zd5v * (LC2VFU(cfa[indx]) + LVFU(rbm[indx1]) * (onev - tempv) + LVFU(rbp[indx1]) * tempv)); + } + +#else + + for (cc = 10 + (FC(rr, 2) & 1), indx = rr * TS + cc, indx1 = indx >> 1; cc < cc1 - 10; cc += 2, indx += 2, indx1++) { + + //first ask if one gets more directional discrimination from nearby B/R sites + pmwtalt = xdivf(pmwt[(indx - m1) >> 1] + pmwt[(indx + p1) >> 1] + pmwt[(indx - p1) >> 1] + pmwt[(indx + m1) >> 1], 2); + + if (fabsf(0.5 - pmwt[indx1]) < fabsf(0.5 - pmwtalt)) { + pmwt[indx1] = pmwtalt; //a better result was obtained from the neighbors + } + + rbint[indx1] = xdiv2f(cfa[indx] + rbm[indx1] * (1.0f - pmwt[indx1]) + rbp[indx1] * pmwt[indx1]); //this is R+B, interpolated + } + +#endif + + for (rr = 12; rr < rr1 - 12; rr++) + for (cc = 12 + (FC(rr, 2) & 1), indx = rr * TS + cc, indx1 = indx >> 1; cc < cc1 - 12; cc += 2, indx += 2, indx1++) { + + if (fabsf(0.5 - pmwt[indx >> 1]) < fabsf(0.5 - hvwt[indx >> 1]) ) { + continue; + } + + //now interpolate G vertically/horizontally using R+B values + //unfortunately, since G interpolation cannot be done diagonally this may lead to color shifts + //color ratios for G interpolation + + cru = cfa[indx - v1] * 2.0 / (eps + rbint[indx1] + rbint[(indx1 - v1)]); + crd = cfa[indx + v1] * 2.0 / (eps + rbint[indx1] + rbint[(indx1 + v1)]); + crl = cfa[indx - 1] * 2.0 / (eps + rbint[indx1] + rbint[(indx1 - 1)]); + crr = cfa[indx + 1] * 2.0 / (eps + rbint[indx1] + rbint[(indx1 + 1)]); + + //interpolated G via adaptive ratios or Hamilton-Adams in each cardinal direction + if (fabsf(1.0f - cru) < arthresh) { + gu = rbint[indx1] * cru; + } else { + gu = cfa[indx - v1] + xdiv2f(rbint[indx1] - rbint[(indx1 - v1)]); + } + + if (fabsf(1.0f - crd) < arthresh) { + gd = rbint[indx1] * crd; + } else { + gd = cfa[indx + v1] + xdiv2f(rbint[indx1] - rbint[(indx1 + v1)]); + } + + if (fabsf(1.0f - crl) < arthresh) { + gl = rbint[indx1] * crl; + } else { + gl = cfa[indx - 1] + xdiv2f(rbint[indx1] - rbint[(indx1 - 1)]); + } + + if (fabsf(1.0f - crr) < arthresh) { + gr = rbint[indx1] * crr; + } else { + gr = cfa[indx + 1] + xdiv2f(rbint[indx1] - rbint[(indx1 + 1)]); + } + + //gu=rbint[indx]*cru; + //gd=rbint[indx]*crd; + //gl=rbint[indx]*crl; + //gr=rbint[indx]*crr; + + //interpolated G via adaptive weights of cardinal evaluations + Gintv = (dirwts0[indx - v1] * gd + dirwts0[indx + v1] * gu) / (dirwts0[indx + v1] + dirwts0[indx - v1]); + Ginth = (dirwts1[indx - 1] * gr + dirwts1[indx + 1] * gl) / (dirwts1[indx - 1] + dirwts1[indx + 1]); + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //bound the interpolation in regions of high saturation + if (Gintv < rbint[indx1]) { + if (2 * Gintv < rbint[indx1]) { + Gintv = ULIM(Gintv , cfa[indx - v1], cfa[indx + v1]); + } else { + vwt = 2.0 * (rbint[indx1] - Gintv) / (eps + Gintv + rbint[indx1]); + Gintv = vwt * Gintv + (1.0f - vwt) * ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]); + } + } + + if (Ginth < rbint[indx1]) { + if (2 * Ginth < rbint[indx1]) { + Ginth = ULIM(Ginth , cfa[indx - 1], cfa[indx + 1]); + } else { + hwt = 2.0 * (rbint[indx1] - Ginth) / (eps + Ginth + rbint[indx1]); + Ginth = hwt * Ginth + (1.0f - hwt) * ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]); + } + } + + if (Ginth > clip_pt) { + Ginth = ULIM(Ginth, cfa[indx - 1], cfa[indx + 1]); //for RT implementation + } + + if (Gintv > clip_pt) { + Gintv = ULIM(Gintv, cfa[indx - v1], cfa[indx + v1]); + } + + //c=FC(rr,cc);//for dcraw implementation + //if (Ginth > pre_mul[c]) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]); + //if (Gintv > pre_mul[c]) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + rgbgreen[indx] = Ginth * (1.0f - hvwt[indx1]) + Gintv * hvwt[indx1]; + //rgb[indx][1] = 0.5*(rgb[indx][1]+0.25*(rgb[indx-v1][1]+rgb[indx+v1][1]+rgb[indx-1][1]+rgb[indx+1][1])); + Dgrb[0][indx >> 1] = rgbgreen[indx] - cfa[indx]; + + //rgb[indx][2-FC(rr,cc)]=2*rbint[indx]-cfa[indx]; + } + + //end of diagonal interpolation correction + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //fancy chrominance interpolation + //(ey,ex) is location of R site + for (rr = 13 - ey; rr < rr1 - 12; rr += 2) + for (cc = 13 - ex, indx1 = (rr * TS + cc) >> 1; cc < cc1 - 12; cc += 2, indx1++) { //B coset + Dgrb[1][indx1] = Dgrb[0][indx1]; //split out G-B from G-R + Dgrb[0][indx1] = 0; + } + +#ifdef __SSE2__ +// __m128 wtnwv,wtnev,wtswv,wtsev; + __m128 oned325v = _mm_set1_ps( 1.325f ); + __m128 zd175v = _mm_set1_ps( 0.175f ); + __m128 zd075v = _mm_set1_ps( 0.075f ); +#endif + + for (rr = 14; rr < rr1 - 14; rr++) +#ifdef __SSE2__ + for (cc = 14 + (FC(rr, 2) & 1), indx = rr * TS + cc, c = 1 - FC(rr, cc) / 2; cc < cc1 - 14; cc += 8, indx += 8) { + wtnwv = onev / (epsv + vabsf(LVFU(Dgrb[c][(indx - m1) >> 1]) - LVFU(Dgrb[c][(indx + m1) >> 1])) + vabsf(LVFU(Dgrb[c][(indx - m1) >> 1]) - LVFU(Dgrb[c][(indx - m3) >> 1])) + vabsf(LVFU(Dgrb[c][(indx + m1) >> 1]) - LVFU(Dgrb[c][(indx - m3) >> 1]))); + wtnev = onev / (epsv + vabsf(LVFU(Dgrb[c][(indx + p1) >> 1]) - LVFU(Dgrb[c][(indx - p1) >> 1])) + vabsf(LVFU(Dgrb[c][(indx + p1) >> 1]) - LVFU(Dgrb[c][(indx + p3) >> 1])) + vabsf(LVFU(Dgrb[c][(indx - p1) >> 1]) - LVFU(Dgrb[c][(indx + p3) >> 1]))); + wtswv = onev / (epsv + vabsf(LVFU(Dgrb[c][(indx - p1) >> 1]) - LVFU(Dgrb[c][(indx + p1) >> 1])) + vabsf(LVFU(Dgrb[c][(indx - p1) >> 1]) - LVFU(Dgrb[c][(indx + m3) >> 1])) + vabsf(LVFU(Dgrb[c][(indx + p1) >> 1]) - LVFU(Dgrb[c][(indx - p3) >> 1]))); + wtsev = onev / (epsv + vabsf(LVFU(Dgrb[c][(indx + m1) >> 1]) - LVFU(Dgrb[c][(indx - m1) >> 1])) + vabsf(LVFU(Dgrb[c][(indx + m1) >> 1]) - LVFU(Dgrb[c][(indx - p3) >> 1])) + vabsf(LVFU(Dgrb[c][(indx - m1) >> 1]) - LVFU(Dgrb[c][(indx + m3) >> 1]))); + + //Dgrb[indx][c]=(wtnw*Dgrb[indx-m1][c]+wtne*Dgrb[indx+p1][c]+wtsw*Dgrb[indx-p1][c]+wtse*Dgrb[indx+m1][c])/(wtnw+wtne+wtsw+wtse); + + _mm_storeu_ps(&Dgrb[c][indx >> 1], (wtnwv * (oned325v * LVFU(Dgrb[c][(indx - m1) >> 1]) - zd175v * LVFU(Dgrb[c][(indx - m3) >> 1]) - zd075v * LVFU(Dgrb[c][(indx - m1 - 2) >> 1]) - zd075v * LVFU(Dgrb[c][(indx - m1 - v2) >> 1]) ) + + wtnev * (oned325v * LVFU(Dgrb[c][(indx + p1) >> 1]) - zd175v * LVFU(Dgrb[c][(indx + p3) >> 1]) - zd075v * LVFU(Dgrb[c][(indx + p1 + 2) >> 1]) - zd075v * LVFU(Dgrb[c][(indx + p1 + v2) >> 1]) ) + + wtswv * (oned325v * LVFU(Dgrb[c][(indx - p1) >> 1]) - zd175v * LVFU(Dgrb[c][(indx - p3) >> 1]) - zd075v * LVFU(Dgrb[c][(indx - p1 - 2) >> 1]) - zd075v * LVFU(Dgrb[c][(indx - p1 - v2) >> 1]) ) + + wtsev * (oned325v * LVFU(Dgrb[c][(indx + m1) >> 1]) - zd175v * LVFU(Dgrb[c][(indx + m3) >> 1]) - zd075v * LVFU(Dgrb[c][(indx + m1 + 2) >> 1]) - zd075v * LVFU(Dgrb[c][(indx + m1 + v2) >> 1]) )) / (wtnwv + wtnev + wtswv + wtsev)); + } + +#else + + for (cc = 14 + (FC(rr, 2) & 1), indx = rr * TS + cc, c = 1 - FC(rr, cc) / 2; cc < cc1 - 14; cc += 2, indx += 2) { + wtnw = 1.0f / (eps + fabsf(Dgrb[c][(indx - m1) >> 1] - Dgrb[c][(indx + m1) >> 1]) + fabsf(Dgrb[c][(indx - m1) >> 1] - Dgrb[c][(indx - m3) >> 1]) + fabsf(Dgrb[c][(indx + m1) >> 1] - Dgrb[c][(indx - m3) >> 1])); + wtne = 1.0f / (eps + fabsf(Dgrb[c][(indx + p1) >> 1] - Dgrb[c][(indx - p1) >> 1]) + fabsf(Dgrb[c][(indx + p1) >> 1] - Dgrb[c][(indx + p3) >> 1]) + fabsf(Dgrb[c][(indx - p1) >> 1] - Dgrb[c][(indx + p3) >> 1])); + wtsw = 1.0f / (eps + fabsf(Dgrb[c][(indx - p1) >> 1] - Dgrb[c][(indx + p1) >> 1]) + fabsf(Dgrb[c][(indx - p1) >> 1] - Dgrb[c][(indx + m3) >> 1]) + fabsf(Dgrb[c][(indx + p1) >> 1] - Dgrb[c][(indx - p3) >> 1])); + wtse = 1.0f / (eps + fabsf(Dgrb[c][(indx + m1) >> 1] - Dgrb[c][(indx - m1) >> 1]) + fabsf(Dgrb[c][(indx + m1) >> 1] - Dgrb[c][(indx - p3) >> 1]) + fabsf(Dgrb[c][(indx - m1) >> 1] - Dgrb[c][(indx + m3) >> 1])); + + //Dgrb[indx][c]=(wtnw*Dgrb[indx-m1][c]+wtne*Dgrb[indx+p1][c]+wtsw*Dgrb[indx-p1][c]+wtse*Dgrb[indx+m1][c])/(wtnw+wtne+wtsw+wtse); + + Dgrb[c][indx >> 1] = (wtnw * (1.325f * Dgrb[c][(indx - m1) >> 1] - 0.175f * Dgrb[c][(indx - m3) >> 1] - 0.075f * Dgrb[c][(indx - m1 - 2) >> 1] - 0.075f * Dgrb[c][(indx - m1 - v2) >> 1] ) + + wtne * (1.325f * Dgrb[c][(indx + p1) >> 1] - 0.175f * Dgrb[c][(indx + p3) >> 1] - 0.075f * Dgrb[c][(indx + p1 + 2) >> 1] - 0.075f * Dgrb[c][(indx + p1 + v2) >> 1] ) + + wtsw * (1.325f * Dgrb[c][(indx - p1) >> 1] - 0.175f * Dgrb[c][(indx - p3) >> 1] - 0.075f * Dgrb[c][(indx - p1 - 2) >> 1] - 0.075f * Dgrb[c][(indx - p1 - v2) >> 1] ) + + wtse * (1.325f * Dgrb[c][(indx + m1) >> 1] - 0.175f * Dgrb[c][(indx + m3) >> 1] - 0.075f * Dgrb[c][(indx + m1 + 2) >> 1] - 0.075f * Dgrb[c][(indx + m1 + v2) >> 1] )) / (wtnw + wtne + wtsw + wtse); + } + +#endif + float temp; + + for (rr = 16; rr < rr1 - 16; rr++) { + if((FC(rr, 2) & 1) == 1) { + for (cc = 16, indx = rr * TS + cc, row = rr + top; cc < cc1 - 16 - (cc1 & 1); cc += 2, indx++) { + col = cc + left; + temp = 1.0f / ((hvwt[(indx - v1) >> 1]) + (1.0f - hvwt[(indx + 1) >> 1]) + (1.0f - hvwt[(indx - 1) >> 1]) + (hvwt[(indx + v1) >> 1])); + red[row][col] = 65535.0f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.0f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.0f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp); + blue[row][col] = 65535.0f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.0f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.0f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp); + + indx++; + col++; + red[row][col] = 65535.0f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); + blue[row][col] = 65535.0f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + } + + if(cc1 & 1) { // width of tile is odd + col = cc + left; + temp = 1.0f / ((hvwt[(indx - v1) >> 1]) + (1.0f - hvwt[(indx + 1) >> 1]) + (1.0f - hvwt[(indx - 1) >> 1]) + (hvwt[(indx + v1) >> 1])); + red[row][col] = 65535.0f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.0f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.0f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp); + blue[row][col] = 65535.0f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.0f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.0f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp); + } + } else { + for (cc = 16, indx = rr * TS + cc, row = rr + top; cc < cc1 - 16 - (cc1 & 1); cc += 2, indx++) { + col = cc + left; + red[row][col] = 65535.0f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); + blue[row][col] = 65535.0f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + + indx++; + col++; + temp = 1.0f / ((hvwt[(indx - v1) >> 1]) + (1.0f - hvwt[(indx + 1) >> 1]) + (1.0f - hvwt[(indx - 1) >> 1]) + (hvwt[(indx + v1) >> 1])); + red[row][col] = 65535.0f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[0][(indx - v1) >> 1] + (1.0f - hvwt[(indx + 1) >> 1]) * Dgrb[0][(indx + 1) >> 1] + (1.0f - hvwt[(indx - 1) >> 1]) * Dgrb[0][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[0][(indx + v1) >> 1]) * + temp); + blue[row][col] = 65535.0f * (rgbgreen[indx] - ((hvwt[(indx - v1) >> 1]) * Dgrb[1][(indx - v1) >> 1] + (1.0f - hvwt[(indx + 1) >> 1]) * Dgrb[1][(indx + 1) >> 1] + (1.0f - hvwt[(indx - 1) >> 1]) * Dgrb[1][(indx - 1) >> 1] + (hvwt[(indx + v1) >> 1]) * Dgrb[1][(indx + v1) >> 1]) * + temp); + } + + if(cc1 & 1) { // width of tile is odd + col = cc + left; + red[row][col] = 65535.0f * (rgbgreen[indx] - Dgrb[0][indx >> 1]); + blue[row][col] = 65535.0f * (rgbgreen[indx] - Dgrb[1][indx >> 1]); + } + } + } + + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // copy smoothed results back to image matrix + for (rr = 16; rr < rr1 - 16; rr++) { +#ifdef __SSE2__ + + for (row = rr + top, cc = 16; cc < cc1 - 19; cc += 4) { + _mm_storeu_ps(&green[row][cc + left], LVF(rgbgreen[rr * TS + cc]) * c65535v); + } + +#else + + for (row = rr + top, cc = 16; cc < cc1 - 16; cc++) { + col = cc + left; + indx = rr * TS + cc; + green[row][col] = ((65535.0f * rgbgreen[indx])); + + //for dcraw implementation + //for (c=0; c<3; c++){ + // image[indx][c] = CLIP((int)(65535.0f*rgb[rr*TS+cc][c] + 0.5f)); + //} + } + +#endif + } + + //end of main loop + + if(plistener) { + progresscounter++; + + if(progresscounter % 4 == 0) { + #pragma omp critical + { + progress += (double)4 * ((TS - 32) * (TS - 32)) / (height * width); + + if (progress > 1.0) + { + progress = 1.0; + } + + plistener->setProgress(progress); + } + } + } + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + // clean up + free(buffer); + } + + if(plistener) { + plistener->setProgress(1.0); + } + + + // done #undef TS diff --git a/rtengine/array2D.h b/rtengine/array2D.h index b80f1d1e8..93734a421 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -22,35 +22,35 @@ * * Usage: * - * array2D name (X-size,Y-size); - * array2D name (X-size,Y-size type ** data); + * array2D name (X-size,Y-size); + * array2D name (X-size,Y-size type ** data); * - * creates an array which is valid within the normal C/C++ scope "{ ... }" + * creates an array which is valid within the normal C/C++ scope "{ ... }" * * access to elements is a simple as: * - * array2D my_array (10,10); // creates 10x10 array of floats - * value = my_array[3][5]; - * my_array[4][6]=value; + * array2D my_array (10,10); // creates 10x10 array of floats + * value = my_array[3][5]; + * my_array[4][6]=value; * * or copy an existing 2D array * - * float ** mydata; - * array2D my_array (10,10,mydata); + * float ** mydata; + * array2D my_array (10,10,mydata); * * - * Useful extra pointers + * Useful extra pointers * - * ** my_array gives access to the pointer for access with [][] - * * my_array gives access to the flat stored data. + * ** my_array gives access to the pointer for access with [][] + * * my_array gives access to the flat stored data. * - * Advanced usage: - * array2D my_array ; // empty container. - * my_array(10,10) ; // resize to 10x10 array - * my_array(10,10,ARRAY2D_CLEAR_DATA) ; // resize to 10x10 and clear data - * my_array(10,10,ARRAY2D_CLEAR_DATA|ARRAY2D_LOCK_DATA) ; same but set a lock on changes + * Advanced usage: + * array2D my_array ; // empty container. + * my_array(10,10) ; // resize to 10x10 array + * my_array(10,10,ARRAY2D_CLEAR_DATA) ; // resize to 10x10 and clear data + * my_array(10,10,ARRAY2D_CLEAR_DATA|ARRAY2D_LOCK_DATA) ; same but set a lock on changes * - * !! locked arrays cannot be resized and cannot be unlocked again !! + * !! locked arrays cannot be resized and cannot be unlocked again !! */ #ifndef ARRAY2D_H_ #define ARRAY2D_H_ @@ -58,214 +58,266 @@ #include // flags for use -#define ARRAY2D_LOCK_DATA 1 -#define ARRAY2D_CLEAR_DATA 2 -#define ARRAY2D_BYREFERENCE 4 -#define ARRAY2D_VERBOSE 8 +#define ARRAY2D_LOCK_DATA 1 +#define ARRAY2D_CLEAR_DATA 2 +#define ARRAY2D_BYREFERENCE 4 +#define ARRAY2D_VERBOSE 8 #include #include template -class array2D { +class array2D +{ private: - int x, y, owner, flags; - T ** ptr; - T * data; - bool lock; // useful lock to ensure data is not changed anymore. - void ar_realloc(int w, int h) { - if ((ptr) && ((h > y) || (4 * h < y))) { - delete[] ptr; - ptr = NULL; - } - if ((data) && (((h * w) > (x * y)) || ((h * w) < ((x * y) / 4)))) { - delete[] data; - data = NULL; - } - if (ptr == NULL) - ptr = new T*[h]; - if (data == NULL) - data = new T[h * w]; + int x, y, owner, flags; + T ** ptr; + T * data; + bool lock; // useful lock to ensure data is not changed anymore. + void ar_realloc(int w, int h) + { + if ((ptr) && ((h > y) || (4 * h < y))) { + delete[] ptr; + ptr = NULL; + } - x = w; - y = h; - for (int i = 0; i < h; i++) - ptr[i] = data + w * i; - owner = 1; - } + if ((data) && (((h * w) > (x * y)) || ((h * w) < ((x * y) / 4)))) { + delete[] data; + data = NULL; + } + + if (ptr == NULL) { + ptr = new T*[h]; + } + + if (data == NULL) { + data = new T[h * w]; + } + + x = w; + y = h; + + for (int i = 0; i < h; i++) { + ptr[i] = data + w * i; + } + + owner = 1; + } public: - // use as empty declaration, resize before use! - // very useful as a member object - array2D() : - x(0), y(0), owner(0), ptr(NULL), data(NULL), lock(0) { - //printf("got empty array2D init\n"); - } + // use as empty declaration, resize before use! + // very useful as a member object + array2D() : + x(0), y(0), owner(0), ptr(NULL), data(NULL), lock(0) + { + //printf("got empty array2D init\n"); + } - // creator type1 - array2D(int w, int h, unsigned int flgs = 0) { - flags = flgs; - lock = flags & ARRAY2D_LOCK_DATA; - data = new T[h * w]; - owner = 1; - x = w; - y = h; - ptr = new T*[h]; - for (int i = 0; i < h; i++) - ptr[i] = data + i * w; - if (flags & ARRAY2D_CLEAR_DATA) - memset(data, 0, w * h * sizeof(T)); - } + // creator type1 + array2D(int w, int h, unsigned int flgs = 0) + { + flags = flgs; + lock = flags & ARRAY2D_LOCK_DATA; + data = new T[h * w]; + owner = 1; + x = w; + y = h; + ptr = new T*[h]; - // creator type 2 - array2D(int w, int h, T ** source, unsigned int flgs = 0) { - flags = flgs; - //if (lock) { printf("array2D attempt to overwrite data\n");raise(SIGSEGV);} - lock |= flags & ARRAY2D_LOCK_DATA; - // when by reference - // TODO: improve this code with ar_realloc() - owner = (flags & ARRAY2D_BYREFERENCE) ? 0 : 1; - if (owner) - data = new T[h * w]; - else - data = NULL; - x = w; - y = h; - ptr = new T*[h]; - for (int i = 0; i < h; i++) { - if (owner) { - ptr[i] = data + i * w; - for (int j = 0; j < w; j++) - ptr[i][j] = source[i][j]; - } else - ptr[i] = source[i]; - } - } + for (int i = 0; i < h; i++) { + ptr[i] = data + i * w; + } - // destructor - ~array2D() { + if (flags & ARRAY2D_CLEAR_DATA) { + memset(data, 0, w * h * sizeof(T)); + } + } - if (flags & ARRAY2D_VERBOSE) - printf(" deleting array2D size %dx%d \n", x, y); + // creator type 2 + array2D(int w, int h, T ** source, unsigned int flgs = 0) + { + flags = flgs; + //if (lock) { printf("array2D attempt to overwrite data\n");raise(SIGSEGV);} + lock |= flags & ARRAY2D_LOCK_DATA; + // when by reference + // TODO: improve this code with ar_realloc() + owner = (flags & ARRAY2D_BYREFERENCE) ? 0 : 1; - if ((owner) && (data)) - delete[] data; - if (ptr) - delete[] ptr; - } + if (owner) { + data = new T[h * w]; + } else { + data = NULL; + } - // use with indices - T * operator[](int index) { - assert((index>=0) && (index < y)); - return ptr[index]; - } + x = w; + y = h; + ptr = new T*[h]; - // use as pointer to T** - operator T**() { - return ptr; - } + for (int i = 0; i < h; i++) { + if (owner) { + ptr[i] = data + i * w; - // use as pointer to data - operator T*() { - // only if owner this will return a valid pointer - return data; - } + for (int j = 0; j < w; j++) { + ptr[i][j] = source[i][j]; + } + } else { + ptr[i] = source[i]; + } + } + } + + // destructor + ~array2D() + { + + if (flags & ARRAY2D_VERBOSE) { + printf(" deleting array2D size %dx%d \n", x, y); + } + + if ((owner) && (data)) { + delete[] data; + } + + if (ptr) { + delete[] ptr; + } + } + + // use with indices + T * operator[](int index) + { + assert((index >= 0) && (index < y)); + return ptr[index]; + } + + // use as pointer to T** + operator T**() + { + return ptr; + } + + // use as pointer to data + operator T*() + { + // only if owner this will return a valid pointer + return data; + } - // useful within init of parent object - // or use as resize of 2D array - void operator()(int w, int h, unsigned int flgs = 0) { - flags = flgs; - if (flags & ARRAY2D_VERBOSE) { - printf("got init request %dx%d flags=%u\n", w, h, flags); - printf("previous was data %p ptr %p \n", data, ptr); - } - if (lock) // our object was locked so don't allow a change. - { - printf("got init request but object was locked!\n"); - raise( SIGSEGV); - } - lock = flags & ARRAY2D_LOCK_DATA; + // useful within init of parent object + // or use as resize of 2D array + void operator()(int w, int h, unsigned int flgs = 0) + { + flags = flgs; - ar_realloc(w,h); - if (flags & ARRAY2D_CLEAR_DATA) - memset(data, 0, w * h * sizeof(T)); - } + if (flags & ARRAY2D_VERBOSE) { + printf("got init request %dx%d flags=%u\n", w, h, flags); + printf("previous was data %p ptr %p \n", data, ptr); + } - // import from flat data - void operator()(int w, int h, T* copy, unsigned int flgs = 0) { - flags = flgs; - if (flags & ARRAY2D_VERBOSE) { - printf("got init request %dx%d flags=%u\n", w, h, flags); - printf("previous was data %p ptr %p \n", data, ptr); - } - if (lock) // our object was locked so don't allow a change. - { - printf("got init request but object was locked!\n"); - raise( SIGSEGV); - } - lock = flags & ARRAY2D_LOCK_DATA; + if (lock) { // our object was locked so don't allow a change. + printf("got init request but object was locked!\n"); + raise( SIGSEGV); + } - ar_realloc(w,h); - memcpy(data, copy, w * h * sizeof(T)); - } - int width() { - return x; - } - int height() { - return y; - } + lock = flags & ARRAY2D_LOCK_DATA; - operator bool() { - return (x > 0 && y > 0); - } + ar_realloc(w, h); - array2D & operator=( array2D & rhs) { - if (this != &rhs) + if (flags & ARRAY2D_CLEAR_DATA) { + memset(data, 0, w * h * sizeof(T)); + } + } - { - if (!owner) // we can only copy same size data - { - if ((x != rhs.x) || (y != rhs.y)) { - printf(" assignment error in array2D\n"); - printf(" sizes differ and not owner\n"); - raise( SIGSEGV); - } + // import from flat data + void operator()(int w, int h, T* copy, unsigned int flgs = 0) + { + flags = flgs; - } else { - ar_realloc(rhs.x, rhs.y); - } - // we could have been created from a different - // array format where each row is created by 'new' - for (int i=0;i 0 && y > 0); + } + + array2D & operator=( array2D & rhs) + { + if (this != &rhs) + + { + if (!owner) { // we can only copy same size data + if ((x != rhs.x) || (y != rhs.y)) { + printf(" assignment error in array2D\n"); + printf(" sizes differ and not owner\n"); + raise( SIGSEGV); + } + + } else { + ar_realloc(rhs.x, rhs.y); + } + + // we could have been created from a different + // array format where each row is created by 'new' + for (int i = 0; i < y; i++) { + memcpy(ptr[i], rhs.ptr[i], x * sizeof(T)); + } + } + + return *this; + } }; template -class multi_array2D { +class multi_array2D +{ private: - array2D list[num]; + array2D list[num]; public: - multi_array2D(int x, int y, int flags = 0) { - for (size_t i = 0; i < num; i++) - list[i](x, y, flags); - } + multi_array2D(int x, int y, int flags = 0) + { + for (size_t i = 0; i < num; i++) { + list[i](x, y, flags); + } + } - ~multi_array2D() { - //printf("trying to delete the list of array2D objects\n"); - } + ~multi_array2D() + { + //printf("trying to delete the list of array2D objects\n"); + } - array2D & operator[](int index) { - if (static_cast(index) >= num) { - printf("index %0u is out of range[0..%0lu]", index, num - 1); - raise( SIGSEGV); - } - return list[index]; - } + array2D & operator[](int index) + { + if (static_cast(index) >= num) { + printf("index %0u is out of range[0..%0lu]", index, num - 1); + raise( SIGSEGV); + } + + return list[index]; + } }; #endif /* array2D_H_ */ diff --git a/rtengine/bilateral2.h b/rtengine/bilateral2.h index 1743965a0..925414fd4 100644 --- a/rtengine/bilateral2.h +++ b/rtengine/bilateral2.h @@ -7,7 +7,7 @@ * 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 @@ -50,7 +50,7 @@ using namespace rtengine; int cstart = b; \ int cend = W-b; -#define BL_FREE buffer[i][j] = v; }}; +#define BL_FREE buffer[i][j] = v; }}; #define BL_END(b) for (int i=0; i=rend || j>=cend) \ @@ -59,18 +59,18 @@ using namespace rtengine; dst[i][j] = buffer[i][j]; #define BL_OPER3(a11,a12,a21,a22) for (int i=rstart; i void bilateral05 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(318,1) - #pragma omp for - BL_OPER3(1,7,7,55) +template void bilateral05 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(318, 1) + #pragma omp for + BL_OPER3(1, 7, 7, 55) BL_FREE -#pragma omp for + #pragma omp for BL_END(1) } // sigma = 0.6 -template void bilateral06 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(768,1) - #pragma omp for - BL_OPER3(1,4,4,16) +template void bilateral06 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(768, 1) + #pragma omp for + BL_OPER3(1, 4, 4, 16) BL_FREE -#pragma omp for + #pragma omp for BL_END(1) } // sigma = 0.7 -template void bilateral07 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(366,2) - #pragma omp for - BL_OPER5(0,0,1,0,8,21,1,21,59) +template void bilateral07 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(366, 2) + #pragma omp for + BL_OPER5(0, 0, 1, 0, 8, 21, 1, 21, 59) BL_FREE -#pragma omp for + #pragma omp for BL_END(2) } // sigma = 0.8 -template void bilateral08 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(753,2) - #pragma omp for - BL_OPER5(0,0,1,0,5,10,1,10,23) +template void bilateral08 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(753, 2) + #pragma omp for + BL_OPER5(0, 0, 1, 0, 5, 10, 1, 10, 23) BL_FREE -#pragma omp for + #pragma omp for BL_END(2) } // sigma = 0.9 -template void bilateral09 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(595,2) - #pragma omp for - BL_OPER5(0,1,2,1,6,12,2,12,22) +template void bilateral09 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(595, 2) + #pragma omp for + BL_OPER5(0, 1, 2, 1, 6, 12, 2, 12, 22) BL_FREE -#pragma omp for + #pragma omp for BL_END(2) } // sigma = 1.0 -template void bilateral10 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral10 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(910,2) - #pragma omp for - BL_OPER5(0,1,2,1,4,7,2,7,12) + BL_BEGIN(910, 2) + #pragma omp for + BL_OPER5(0, 1, 2, 1, 4, 7, 2, 7, 12) BL_FREE -#pragma omp for + #pragma omp for BL_END(2) } // sigma = 1.1 -template void bilateral11 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(209,3) - #pragma omp for - BL_OPER7(0,0,1,1,0,2,5,8,1,5,18,27,1,8,27,41) +template void bilateral11 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(209, 3) + #pragma omp for + BL_OPER7(0, 0, 1, 1, 0, 2, 5, 8, 1, 5, 18, 27, 1, 8, 27, 41) BL_FREE -#pragma omp for + #pragma omp for BL_END(3) } // sigma = 1.2 -template void bilateral12 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(322,3) - #pragma omp for - BL_OPER7(0,0,1,1,0,1,4,6,1,4,11,16,1,6,16,23) +template void bilateral12 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(322, 3) + #pragma omp for + BL_OPER7(0, 0, 1, 1, 0, 1, 4, 6, 1, 4, 11, 16, 1, 6, 16, 23) BL_FREE -#pragma omp for + #pragma omp for BL_END(3) } // sigma = 1.3 -template void bilateral13 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(336,3) - #pragma omp for - BL_OPER7(0,0,1,1,0,2,4,6,1,4,11,14,1,6,14,19) +template void bilateral13 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(336, 3) + #pragma omp for + BL_OPER7(0, 0, 1, 1, 0, 2, 4, 6, 1, 4, 11, 14, 1, 6, 14, 19) BL_FREE -#pragma omp for + #pragma omp for BL_END(3) } // sigma = 1.4 -template void bilateral14 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(195,3) - #pragma omp for - BL_OPER7(0,1,2,3,1,4,8,10,2,8,17,21,3,10,21,28) +template void bilateral14 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(195, 3) + #pragma omp for + BL_OPER7(0, 1, 2, 3, 1, 4, 8, 10, 2, 8, 17, 21, 3, 10, 21, 28) BL_FREE -#pragma omp for - BL_END(3) + #pragma omp for + BL_END(3) } // sigma = 1.5 -template void bilateral15 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(132,4) - #pragma omp for - BL_OPER9(0,0,0,1,1,0,1,2,4,5,0,2,6,12,14,1,4,12,22,28,1,5,14,28,35) +template void bilateral15 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(132, 4) + #pragma omp for + BL_OPER9(0, 0, 0, 1, 1, 0, 1, 2, 4, 5, 0, 2, 6, 12, 14, 1, 4, 12, 22, 28, 1, 5, 14, 28, 35) BL_FREE -#pragma omp for - BL_END(4) + #pragma omp for + BL_END(4) } // sigma = 1.6 -template void bilateral16 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(180,4) - #pragma omp for - BL_OPER9(0,0,0,1,1,0,1,2,3,4,0,2,5,9,10,1,3,9,15,19,1,4,10,19,23) +template void bilateral16 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(180, 4) + #pragma omp for + BL_OPER9(0, 0, 0, 1, 1, 0, 1, 2, 3, 4, 0, 2, 5, 9, 10, 1, 3, 9, 15, 19, 1, 4, 10, 19, 23) BL_FREE -#pragma omp for - BL_END(4) + #pragma omp for + BL_END(4) } // sigma = 1.7 -template void bilateral17 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(195,4) - #pragma omp for - BL_OPER9(0,0,1,1,1,0,1,2,3,4,1,2,5,8,9,1,3,8,13,16,1,4,9,16,19) +template void bilateral17 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(195, 4) + #pragma omp for + BL_OPER9(0, 0, 1, 1, 1, 0, 1, 2, 3, 4, 1, 2, 5, 8, 9, 1, 3, 8, 13, 16, 1, 4, 9, 16, 19) BL_FREE -#pragma omp for - BL_END(4) + #pragma omp for + BL_END(4) } // sigma = 1.8 -template void bilateral18 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(151,4) - #pragma omp for - BL_OPER9(0,0,1,2,2,0,1,3,5,5,1,3,6,10,12,2,5,10,16,19,2,5,12,19,22) +template void bilateral18 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(151, 4) + #pragma omp for + BL_OPER9(0, 0, 1, 2, 2, 0, 1, 3, 5, 5, 1, 3, 6, 10, 12, 2, 5, 10, 16, 19, 2, 5, 12, 19, 22) BL_FREE -#pragma omp for - BL_END(4) + #pragma omp for + BL_END(4) } // sigma = 1.9 -template void bilateral19 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { - - BL_BEGIN(151,4) - #pragma omp for - BL_OPER9(0,0,1,2,2,0,1,3,4,5,1,3,5,8,9,2,4,8,12,14,2,5,9,14,16) +template void bilateral19 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ + + BL_BEGIN(151, 4) + #pragma omp for + BL_OPER9(0, 0, 1, 2, 2, 0, 1, 3, 4, 5, 1, 3, 5, 8, 9, 2, 4, 8, 12, 14, 2, 5, 9, 14, 16) BL_FREE -#pragma omp for - BL_END(4) + #pragma omp for + BL_END(4) } // sigma = 2 -template void bilateral20 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral20 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(116,5) - #pragma omp for - BL_OPER11(0,0,0,1,1,1,0,0,1,2,3,3,0,1,2,4,7,7,1,2,4,8,12,14,1,3,7,12,18,20,1,3,7,14,20,23) + BL_BEGIN(116, 5) + #pragma omp for + BL_OPER11(0, 0, 0, 1, 1, 1, 0, 0, 1, 2, 3, 3, 0, 1, 2, 4, 7, 7, 1, 2, 4, 8, 12, 14, 1, 3, 7, 12, 18, 20, 1, 3, 7, 14, 20, 23) BL_FREE -#pragma omp for - BL_END(5) + #pragma omp for + BL_END(5) } // sigma = 2.1 -template void bilateral21 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral21 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(127,5) - #pragma omp for - BL_OPER11(0,0,0,1,1,1,0,0,1,2,3,3,0,1,2,4,6,7,1,2,4,8,11,12,1,3,6,11,15,17,1,3,7,12,17,19) + BL_BEGIN(127, 5) + #pragma omp for + BL_OPER11(0, 0, 0, 1, 1, 1, 0, 0, 1, 2, 3, 3, 0, 1, 2, 4, 6, 7, 1, 2, 4, 8, 11, 12, 1, 3, 6, 11, 15, 17, 1, 3, 7, 12, 17, 19) BL_FREE -#pragma omp for + #pragma omp for BL_END(5) } // sigma = 2.2 -template void bilateral22 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral22 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(109,5) - #pragma omp for - BL_OPER11(0,0,0,1,1,2,0,1,2,3,3,4,1,2,3,5,7,8,1,3,5,9,12,13,1,3,7,12,16,18,2,4,8,13,18,20) + BL_BEGIN(109, 5) + #pragma omp for + BL_OPER11(0, 0, 0, 1, 1, 2, 0, 1, 2, 3, 3, 4, 1, 2, 3, 5, 7, 8, 1, 3, 5, 9, 12, 13, 1, 3, 7, 12, 16, 18, 2, 4, 8, 13, 18, 20) BL_FREE -#pragma omp for + #pragma omp for BL_END(5) } // sigma = 2.3 -template void bilateral23 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral23 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(132,5) - #pragma omp for - BL_OPER11(0,0,1,1,1,1,0,1,1,2,3,3,1,1,3,5,6,7,1,2,5,7,10,11,1,3,6,10,13,14,1,3,7,11,14,16) + BL_BEGIN(132, 5) + #pragma omp for + BL_OPER11(0, 0, 1, 1, 1, 1, 0, 1, 1, 2, 3, 3, 1, 1, 3, 5, 6, 7, 1, 2, 5, 7, 10, 11, 1, 3, 6, 10, 13, 14, 1, 3, 7, 11, 14, 16) BL_FREE -#pragma omp for + #pragma omp for BL_END(5) } // sigma = 2.4 -template void bilateral24 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral24 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(156,5) - #pragma omp for - BL_OPER11(0,0,1,1,1,1,0,1,1,2,3,3,1,1,3,4,5,6,1,2,4,6,8,9,1,3,5,8,10,11,1,3,6,9,11,12) + BL_BEGIN(156, 5) + #pragma omp for + BL_OPER11(0, 0, 1, 1, 1, 1, 0, 1, 1, 2, 3, 3, 1, 1, 3, 4, 5, 6, 1, 2, 4, 6, 8, 9, 1, 3, 5, 8, 10, 11, 1, 3, 6, 9, 11, 12) BL_FREE -#pragma omp for + #pragma omp for BL_END(5) } // sigma = 2.5 -template void bilateral25 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { +template void bilateral25 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) +{ - BL_BEGIN(173,5) - #pragma omp for - BL_OPER11(0,0,1,1,1,1,0,1,1,2,3,3,1,1,2,4,5,5,1,2,4,5,7,7,1,3,5,7,9,9,1,3,5,7,9,10) + BL_BEGIN(173, 5) + #pragma omp for + BL_OPER11(0, 0, 1, 1, 1, 1, 0, 1, 1, 2, 3, 3, 1, 1, 2, 4, 5, 5, 1, 2, 4, 5, 7, 7, 1, 3, 5, 7, 9, 9, 1, 3, 5, 7, 9, 10) BL_FREE -#pragma omp for + #pragma omp for BL_END(5) } // main bilateral filter -template void bilateral (T** src, T** dst, T** buffer, int W, int H, double sigma, double sens, bool multiThread) { +template void bilateral (T** src, T** dst, T** buffer, int W, int H, double sigma, double sens, bool multiThread) +{ //parallel if (multiThread) - if (sigma<0.45) + if (sigma < 0.45) #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<0.65) - bilateral06 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<0.75) - bilateral07 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<0.85) - bilateral08 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<0.95) - bilateral09 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.05) - bilateral10 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.15) - bilateral11 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.25) - bilateral12 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.35) - bilateral13 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.45) - bilateral14 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.55) - bilateral15 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.65) - bilateral16 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.75) - bilateral17 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.85) - bilateral18 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<1.95) - bilateral19 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<2.05) - bilateral20 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<2.15) - bilateral21 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<2.25) - bilateral22 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<2.35) - bilateral23 (src, dst, buffer, W, H, sens, multiThread); - else if (sigma<2.45) - bilateral24 (src, dst, buffer, W, H, sens, multiThread); - else - bilateral25 (src, dst, buffer, W, H, sens, multiThread); + else if (sigma < 0.55) { + bilateral05 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 0.65) { + bilateral06 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 0.75) { + bilateral07 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 0.85) { + bilateral08 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 0.95) { + bilateral09 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.05) { + bilateral10 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.15) { + bilateral11 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.25) { + bilateral12 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.35) { + bilateral13 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.45) { + bilateral14 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.55) { + bilateral15 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.65) { + bilateral16 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.75) { + bilateral17 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.85) { + bilateral18 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 1.95) { + bilateral19 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 2.05) { + bilateral20 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 2.15) { + bilateral21 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 2.25) { + bilateral22 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 2.35) { + bilateral23 (src, dst, buffer, W, H, sens, multiThread); + } else if (sigma < 2.45) { + bilateral24 (src, dst, buffer, W, H, sens, multiThread); + } else { + bilateral25 (src, dst, buffer, W, H, sens, multiThread); + } } // START OF EXPERIMENTAL CODE: O(1) bilateral box filter @@ -441,16 +464,17 @@ template void bilateral (T** src, T** dst, T** buffer, int W, #define BINBIT 7 //bit depth of histogram -- there are 2^BINBIT discrete levels #define TRANSBIT 9 //bit shift = 16-BINBIT taking short ints to bit depth BINBIT -template void bilateral (T** src, T** dst, int W, int H, int sigmar, double sigmas, int row_from, int row_to) { +template void bilateral (T** src, T** dst, int W, int H, int sigmar, double sigmas, int row_from, int row_to) +{ // range weights /*LUTf ec(0x20000); - for (int i=0; i<0x20000; i++) + for (int i=0; i<0x20000; i++) ec[i] = exp(-(double)(i-0x10000)*(double)(i-0x10000) / (2.0*sigmar*sigmar)); */ // histogram - LUTu hist (1< void bilateral (T** src, T** dst, int W, int H, int sigmar, do buff_final[i] = real_buff_final + i*W; memset (buff_final[i], 0, W*sizeof(float)); }*/ - - array2D buff_final(W,H,ARRAY2D_CLEAR_DATA); - + + array2D buff_final(W, H, ARRAY2D_CLEAR_DATA); + int r = sigmas; - + // calculate histogram at the beginning of the row rhist.clear(); - for (int x = MAX(0,row_from-r); x<=MIN(H,row_from+r); x++) - for (int y = 0; y>TRANSBIT]++; - sigmar*=2; + for (int x = MAX(0, row_from - r); x <= MIN(H, row_from + r); x++) + for (int y = 0; y < r + 1; y++) { + rhist[((int)src[x][y]) >> TRANSBIT]++; + } + + sigmar *= 2; + + for (int i = row_from; i < row_to; i++) { - for (int i=row_from; ir) - for (int x = 0; x<=MIN(H,r); x++) - rhist[((int)src[i-r-1][x])>>TRANSBIT]--; - if (i>TRANSBIT]++; - - hist=rhist; - for (int j=0; j r) + for (int x = 0; x <= MIN(H, r); x++) { + rhist[((int)src[i - r - 1][x]) >> TRANSBIT]--; + } + + if (i < H - r) + for (int x = 0; x <= MIN(H, r); x++) { + rhist[((int)src[i + r][x]) >> TRANSBIT]++; + } + + hist = rhist; + + for (int j = 0; j < W; j++) { + // subtract pixels at the left and add pixels at the right - if (j>r) - for (int x=MAX(0,i-r); x<=MIN(i+r,H-1); x++) - hist[(int)(src[x][j-r-1])>>TRANSBIT]--; - if (j>TRANSBIT]++; + if (j > r) + for (int x = MAX(0, i - r); x <= MIN(i + r, H - 1); x++) { + hist[(int)(src[x][j - r - 1]) >> TRANSBIT]--; + } + + if (j < W - r) + for (int x = MAX(0, i - r); x <= MIN(i + r, H - 1); x++) { + hist[((int)src[x][j + r]) >> TRANSBIT]++; + } // calculate pixel value float totwt = 0.0, weight; - for (int k=0; k<=(sigmar>>TRANSBIT); k++) { - float w = 1.0 - (double)k/(sigmar>>TRANSBIT); - int v = (int)(src[i][j])>>TRANSBIT; - //float frac = ((float)(src[i][j]-(v<= 0) { - weight = hist [v-k/*+frac*/] * w; - totwt += weight; - buff_final[i][j] += weight * (src[i][j]-(k<> TRANSBIT); k++) { + float w = 1.0 - (double)k / (sigmar >> TRANSBIT); + int v = (int)(src[i][j]) >> TRANSBIT; + + //float frac = ((float)(src[i][j]-(v<= 0) { + weight = hist [v - k/*+frac*/] * w; + totwt += weight; + buff_final[i][j] += weight * (src[i][j] - (k << TRANSBIT)); } - if (v+k < (1< -#include +#include #include #include "alignedbuffer.h" #ifdef _OPENMP @@ -33,488 +33,574 @@ //using namespace rtengine; -namespace rtengine { +namespace rtengine +{ // classical filtering if the support window is small: -template void boxblur (T** src, A** dst, int radx, int rady, int W, int H) { - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) - - AlignedBuffer* buffer = new AlignedBuffer (W*H); - float* temp = buffer->data; - - if (radx==0) { +template void boxblur (T** src, A** dst, int radx, int rady, int W, int H) +{ + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //box blur image; box range = (radx,rady) + + AlignedBuffer* buffer = new AlignedBuffer (W * H); + float* temp = buffer->data; + + if (radx == 0) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row=0; row SSEFUNCTION void boxblur (T* src, A* dst, A* buffer, int radx, int rady, int W, int H) { +template SSEFUNCTION void boxblur (T* src, A* dst, A* buffer, int radx, int rady, int W, int H) +{ //printf("boxblur\n"); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) - - float* temp = buffer; - if (radx==0) { - for (int row=0; row= 0; row--) { - int len = radx + 1; - float tempval = (float)src[row*W]; - for (int j=1; j<=radx; j++) { - tempval += (float)src[row*W+j]; - } - tempval = tempval/len; - temp[row*W] = tempval; - for (int col=1; col<=radx; col++) { - tempval = (tempval*len + src[row*W+col+radx])/(len+1); - temp[row*W+col] = tempval; - len ++; - } - float reclen = 1.f/len; - for (int col = radx+1; col < W-radx; col++) { - tempval = tempval + ((float)(src[row*W+col+radx] - src[row*W+col-radx-1]))*reclen; - temp[row*W+col] = tempval; - } - for (int col=W-radx; col= 0; row--) { + int len = radx + 1; + float tempval = (float)src[row * W]; + + for (int j = 1; j <= radx; j++) { + tempval += (float)src[row * W + j]; + } + + tempval = tempval / len; + temp[row * W] = tempval; + + for (int col = 1; col <= radx; col++) { + tempval = (tempval * len + src[row * W + col + radx]) / (len + 1); + temp[row * W + col] = tempval; + len ++; + } + + float reclen = 1.f / len; + + for (int col = radx + 1; col < W - radx; col++) { + tempval = tempval + ((float)(src[row * W + col + radx] - src[row * W + col - radx - 1])) * reclen; + temp[row * W + col] = tempval; + } + + for (int col = W - radx; col < W; col++) { + tempval = (tempval * len - src[row * W + col - radx - 1]) / (len - 1); + temp[row * W + col] = tempval; + len --; + } + } + } + + if (rady == 0) { + for (int row = 0; row < H; row++) + for (int col = 0; col < W; col++) { + dst[row * W + col] = temp[row * W + col]; + } + } else { + //vertical blur #ifdef __SSE2__ - __m128 leninitv = _mm_set1_ps( (float)(rady+1)); - __m128 onev = _mm_set1_ps( 1.0f ); - __m128 tempv,temp1v,lenv,lenp1v,lenm1v,rlenv; - int col; - for (col = 0; col < W-7; col+=8) { - lenv = leninitv; - tempv = LVFU(temp[0*W+col]); - temp1v = LVFU(temp[0*W+col+4]); - for (int i=1; i<=rady; i++) { - tempv = tempv + LVFU(temp[i*W+col]); - temp1v = temp1v + LVFU(temp[i*W+col+4]); - } - tempv = tempv/lenv; - temp1v = temp1v/lenv; - _mm_storeu_ps( &dst[0*W+col], tempv); - _mm_storeu_ps( &dst[0*W+col+4], temp1v); - for (int row=1; row<=rady; row++) { - lenp1v = lenv + onev; - tempv = (tempv*lenv + LVFU(temp[(row+rady)*W+col]))/lenp1v; - temp1v = (temp1v*lenv + LVFU(temp[(row+rady)*W+col+4]))/lenp1v; - _mm_storeu_ps( &dst[row*W+col], tempv); - _mm_storeu_ps( &dst[row*W+col+4], temp1v); - lenv = lenp1v; - } - rlenv = onev / lenv; - for (int row = rady+1; row < H-rady; row++) { - tempv = tempv +(LVFU(temp[(row+rady)*W+col])-LVFU(temp[(row-rady-1)*W+col]))*rlenv ; - temp1v = temp1v +(LVFU(temp[(row+rady)*W+col+4])-LVFU(temp[(row-rady-1)*W+col+4]))*rlenv ; - _mm_storeu_ps( &dst[row*W+col], tempv); - _mm_storeu_ps( &dst[row*W+col+4], temp1v); - } - for (int row=H-rady; row void boxvar (T* src, T* dst, int radx, int rady, int W, int H) { - - AlignedBuffer buffer1(W*H); - AlignedBuffer buffer2(W*H); - float* tempave = buffer1.data; - float* tempsqave = buffer2.data; - - AlignedBufferMP buffer3(H); +template void boxvar (T* src, T* dst, int radx, int rady, int W, int H) +{ - //float image_ave = 0; - - //box blur image channel; box size = 2*box+1 - //horizontal blur + AlignedBuffer buffer1(W * H); + AlignedBuffer buffer2(W * H); + float* tempave = buffer1.data; + float* tempsqave = buffer2.data; + + AlignedBufferMP buffer3(H); + + //float image_ave = 0; + + //box blur image channel; box size = 2*box+1 + //horizontal blur #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row = 0; row < H; row++) { - int len = radx + 1; - tempave[row*W+0] = src[row*W+0]/len; - tempsqave[row*W+0] = SQR(src[row*W+0])/len; - for (int j=1; j<=radx; j++) { - tempave[row*W+0] += src[row*W+j]/len; - tempsqave[row*W+0] += SQR(src[row*W+j])/len; - } - for (int col=1; col<=radx; col++) { - tempave[row*W+col] = (tempave[row*W+col-1]*len + src[row*W+col+radx])/(len+1); - tempsqave[row*W+col] = (tempsqave[row*W+col-1]*len + SQR(src[row*W+col+radx]))/(len+1); - len ++; - } - for (int col = radx+1; col < W-radx; col++) { - tempave[row*W+col] = tempave[row*W+col-1] + (src[row*W+col+radx] - src[row*W+col-radx-1])/len; - tempsqave[row*W+col] = tempsqave[row*W+col-1] + (SQR(src[row*W+col+radx]) - SQR(src[row*W+col-radx-1]))/len; - } - for (int col=W-radx; col* pBuf3 = buffer3.acquire(); - T* tempave2=(T*)pBuf3->data; - - int len = rady + 1; - tempave2[0] = tempave[0*W+col]/len; - dst[0*W+col] = tempsqave[0*W+col]/len; - for (int i=1; i<=rady; i++) { - tempave2[0] += tempave[i*W+col]/len; - dst[0*W+col] += tempsqave[i*W+col]/len; - } - for (int row=1; row<=rady; row++) { - tempave2[row] = (tempave2[(row-1)]*len + tempave[(row+rady)*W+col])/(len+1); - dst[row*W+col] = (dst[(row-1)*W+col]*len + tempsqave[(row+rady)*W+col])/(len+1); - len ++; - } - for (int row = rady+1; row < H-rady; row++) { - tempave2[row] = tempave2[(row-1)] + (tempave[(row+rady)*W+col] - tempave[(row-rady-1)*W+col])/len; - dst[row*W+col] = dst[(row-1)*W+col] + (tempsqave[(row+rady)*W+col] - tempsqave[(row-rady-1)*W+col])/len; - } - for (int row=H-rady; row* pBuf3 = buffer3.acquire(); + T* tempave2 = (T*)pBuf3->data; + + int len = rady + 1; + tempave2[0] = tempave[0 * W + col] / len; + dst[0 * W + col] = tempsqave[0 * W + col] / len; + + for (int i = 1; i <= rady; i++) { + tempave2[0] += tempave[i * W + col] / len; + dst[0 * W + col] += tempsqave[i * W + col] / len; + } + + for (int row = 1; row <= rady; row++) { + tempave2[row] = (tempave2[(row - 1)] * len + tempave[(row + rady) * W + col]) / (len + 1); + dst[row * W + col] = (dst[(row - 1) * W + col] * len + tempsqave[(row + rady) * W + col]) / (len + 1); + len ++; + } + + for (int row = rady + 1; row < H - rady; row++) { + tempave2[row] = tempave2[(row - 1)] + (tempave[(row + rady) * W + col] - tempave[(row - rady - 1) * W + col]) / len; + dst[row * W + col] = dst[(row - 1) * W + col] + (tempsqave[(row + rady) * W + col] - tempsqave[(row - rady - 1) * W + col]) / len; + } + + for (int row = H - rady; row < H; row++) { + tempave2[row] = (tempave2[(row - 1)] * len - tempave[(row - rady - 1) * W + col]) / (len - 1); + dst[row * W + col] = (dst[(row - 1) * W + col] * len - tempsqave[(row - rady - 1) * W + col]) / (len - 1); + len --; + } + + //now finish off + for (int row = 0; row < H; row++) { + dst[row * W + col] = fabs(dst[row * W + col] - SQR(tempave2[row])); + //image_ave += src[row*W+col]; + } + + buffer3.release(pBuf3); + } + + //image_ave /= (W*H); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -template void boxdev (T* src, T* dst, int radx, int rady, int W, int H) { - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) - - AlignedBuffer* buffer1 = new AlignedBuffer (W*H); - float* temp = buffer1->data; - - AlignedBuffer* buffer2 = new AlignedBuffer (W*H); - float* tempave = buffer2->data; - - if (radx==0) { -#ifdef _OPENMP -#pragma omp parallel for -#endif - for (int row=0; row void boxdev (T* src, T* dst, int radx, int rady, int W, int H) +{ - - if (radx==0) { + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) + + AlignedBuffer* buffer1 = new AlignedBuffer (W * H); + float* temp = buffer1->data; + + AlignedBuffer* buffer2 = new AlignedBuffer (W * H); + float* tempave = buffer2->data; + + if (radx == 0) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row=0; row void boxdev (T* src, T* dst, int radx, int rady, int W, int //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -template void boxsqblur (T* src, A* dst, int radx, int rady, int W, int H) { - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) - - AlignedBuffer* buffer = new AlignedBuffer (W*H); - float* temp = buffer->data; - - if (radx==0) { +template void boxsqblur (T* src, A* dst, int radx, int rady, int W, int H) +{ + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) + + AlignedBuffer* buffer = new AlignedBuffer (W * H); + float* temp = buffer->data; + + if (radx == 0) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row=0; row void boxcorrelate (T* src, A* dst, int dx, int dy, int radx, int rady, int W, int H) { - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) - - AlignedBuffer* buffer = new AlignedBuffer (W*H); - float* temp = buffer->data; - - if (radx==0) { - for (int row=0; row0 ? (src[row*W+col])*(src[rr*W+cc]) : 0; - } - } - } else { - //horizontal blur - for (int row = 0; row < H; row++) { - int len = radx + 1; - int rr = min(H-1,max(0,row+dy)); - int cc = min(W-1,max(0,0+dx)); - temp[row*W+0] = ((float)src[row*W+0])*(src[rr*W+cc])/len; - for (int j=1; j<=radx; j++) { - int cc = min(W-1,max(0,j+dx)); - temp[row*W+0] += ((float)src[row*W+j])*(src[rr*W+cc])/len; - } - for (int col=1; col<=radx; col++) { - int cc = min(W-1,max(0,col+dx+radx)); - temp[row*W+col] = (temp[row*W+col-1]*len + (src[row*W+col+radx])*(src[rr*W+cc]))/(len+1); - len ++; - } - for (int col = radx+1; col < W-radx; col++) { - int cc = min(W-1,max(0,col+dx+radx)); - int cc1 = min(W-1,max(0,col+dx-radx-1)); - temp[row*W+col] = temp[row*W+col-1] + ((float)((src[row*W+col+radx])*(src[rr*W+cc]) - - (src[row*W+col-radx-1])*(src[rr*W+cc1])))/len; - } - for (int col=W-radx; col void boxcorrelate (T* src, A* dst, int dx, int dy, int radx, int rady, int W, int H) +{ + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) + + AlignedBuffer* buffer = new AlignedBuffer (W * H); + float* temp = buffer->data; + + if (radx == 0) { + for (int row = 0; row < H; row++) { + int rr = min(H - 1, max(0, row + dy)); + + for (int col = 0; col < W; col++) { + int cc = min(W - 1, max(0, col + dx)); + temp[row * W + col] = dy > 0 ? (src[row * W + col]) * (src[rr * W + cc]) : 0; + } + } + } else { + //horizontal blur + for (int row = 0; row < H; row++) { + int len = radx + 1; + int rr = min(H - 1, max(0, row + dy)); + int cc = min(W - 1, max(0, 0 + dx)); + temp[row * W + 0] = ((float)src[row * W + 0]) * (src[rr * W + cc]) / len; + + for (int j = 1; j <= radx; j++) { + int cc = min(W - 1, max(0, j + dx)); + temp[row * W + 0] += ((float)src[row * W + j]) * (src[rr * W + cc]) / len; + } + + for (int col = 1; col <= radx; col++) { + int cc = min(W - 1, max(0, col + dx + radx)); + temp[row * W + col] = (temp[row * W + col - 1] * len + (src[row * W + col + radx]) * (src[rr * W + cc])) / (len + 1); + len ++; + } + + for (int col = radx + 1; col < W - radx; col++) { + int cc = min(W - 1, max(0, col + dx + radx)); + int cc1 = min(W - 1, max(0, col + dx - radx - 1)); + temp[row * W + col] = temp[row * W + col - 1] + ((float)((src[row * W + col + radx]) * (src[rr * W + cc]) - + (src[row * W + col - radx - 1]) * (src[rr * W + cc1]))) / len; + } + + for (int col = W - radx; col < W; col++) { + int cc1 = min(W - 1, max(0, col + dx - radx - 1)); + temp[row * W + col] = (temp[row * W + col - 1] * len - (src[row * W + col - radx - 1]) * (src[rr * W + cc1])) / (len - 1); + len --; + } + } + } + + if (rady == 0) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row=0; row SSEFUNCTION void boxabsblur (T* src, A* dst, int radx, int rady, int W, int H, float * temp) { +template SSEFUNCTION void boxabsblur (T* src, A* dst, int radx, int rady, int W, int H, float * temp) +{ - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1) - - if (radx==0) { - for (int row=0; rownext and ->prev pointers are always zero on return from Duplicate. */ /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); +extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated); extern void cJSON_Minify(char *json); /* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) /* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) #ifdef __cplusplus } diff --git a/rtengine/calc_distort.cc b/rtengine/calc_distort.cc index 90ac64954..80d61d654 100644 --- a/rtengine/calc_distort.cc +++ b/rtengine/calc_distort.cc @@ -1,7 +1,7 @@ /********************************************************************** Finds the N_FEATURES best features in an image, and tracks these features to the next image. Saves the feature -locations (before and after tracking) to text files and to PPM files, +locations (before and after tracking) to text files and to PPM files, and prints the features to the screen. **********************************************************************/ @@ -21,13 +21,14 @@ and prints the features to the screen. #ifdef DEBUG_IMG void drawDotXY(unsigned char* img, int ncols, int nrows, int x, int y, int color) { - img[x+y*ncols] = color; + img[x + y * ncols] = color; } void drawDot(unsigned char* img, int ncols, int nrows, double r0, double r10, int color) { - if (r0>=0 && r0<1 && r10 >=0.8 && r10 <1.2) - drawDotXY (img, ncols, nrows, (int)(r0*ncols), (int)((r10-0.8)*2.5*nrows), color); + if (r0 >= 0 && r0 < 1 && r10 >= 0.8 && r10 < 1.2) { + drawDotXY (img, ncols, nrows, (int)(r0 * ncols), (int)((r10 - 0.8) * 2.5 * nrows), color); + } } #endif @@ -36,13 +37,13 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow KLT_TrackingContext tc; KLT_FeatureList fl; KLT_FeatureTable ft; - int i,n; + int i, n; double radius, wc, hc; - double r0[N_FEATURES*nfactor]; - memset(r0,0,N_FEATURES*nfactor*sizeof(double)); - double r10[N_FEATURES*nfactor]; - memset(r10,0,N_FEATURES*nfactor*sizeof(double)); + double r0[N_FEATURES * nfactor]; + memset(r0, 0, N_FEATURES * nfactor * sizeof(double)); + double r10[N_FEATURES * nfactor]; + memset(r10, 0, N_FEATURES * nfactor * sizeof(double)); tc = KLTCreateTrackingContext(); //tc->mindist = 20; @@ -51,12 +52,12 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow tc->step_factor = 2.0; tc->max_iterations = 20; //KLTPrintTrackingContext(tc); - fl = KLTCreateFeatureList(N_FEATURES*nfactor); - ft = KLTCreateFeatureTable(2, N_FEATURES*nfactor); + fl = KLTCreateFeatureList(N_FEATURES * nfactor); + ft = KLTCreateFeatureTable(2, N_FEATURES * nfactor); - radius = sqrt(ncols*ncols+nrows*nrows)/2.0; - wc=((double)ncols)/2.0-0.5; - hc=((double)nrows)/2.0-0.5; + radius = sqrt(ncols * ncols + nrows * nrows) / 2.0; + wc = ((double)ncols) / 2.0 - 0.5; + hc = ((double)nrows) / 2.0 - 0.5; KLTSelectGoodFeatures(tc, img1, ncols, nrows, fl); KLTStoreFeatureList(fl, ft, 0); @@ -65,31 +66,36 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow KLTStoreFeatureList(fl, ft, 1); // add a shade to img2, we want to draw something on top of it. - for (i=0;ifeature[i][1]->val>=0) { - double x0,y0,x1,y1; - x0=ft->feature[i][0]->x; - y0=ft->feature[i][0]->y; - x1=ft->feature[i][1]->x; - y1=ft->feature[i][1]->y; - r0[n]=sqrt((x0-wc)*(x0-wc)+(y0-hc)*(y0-hc))/radius; + // find the best comp and scale when assume r1 = r0*(1.0-comp+(r0*comp))*scale; + n = 0; + double total_r10 = 0.0, total_r0 = 0.0; + + for (i = 0; i < N_FEATURES * nfactor; i++) { + if (ft->feature[i][1]->val >= 0) { + double x0, y0, x1, y1; + x0 = ft->feature[i][0]->x; + y0 = ft->feature[i][0]->y; + x1 = ft->feature[i][1]->x; + y1 = ft->feature[i][1]->y; + + r0[n] = sqrt((x0 - wc) * (x0 - wc) + (y0 - hc) * (y0 - hc)) / radius; + // dots too close to the center tends to have big diviation and create noise, extract them - if (r0[n]feature[i][0]->x=-1.0; - ft->feature[i][0]->y=-1.0; + ft->feature[i][0]->x = -1.0; + ft->feature[i][0]->y = -1.0; } } @@ -105,25 +111,28 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow double Sxy = 0.0; double Syy = 0.0; - for (i=0;i= 0 ? delta : -delta; #ifdef DEBUG_IMG @@ -140,7 +149,7 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow total_delta += delta; } - printf ("distortion amount=%lf scale=%lf deviation=%lf, rxy=%lf\n", a, b, total_delta/n, rxy); + printf ("distortion amount=%lf scale=%lf deviation=%lf, rxy=%lf\n", a, b, total_delta / n, rxy); if (new_n < 5) { printf ("Not sufficient features.\n"); @@ -148,73 +157,97 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow return -1; } - printf ("Removed %d outstading data points\n", n-new_n); + printf ("Removed %d outstading data points\n", n - new_n); avg_r10 = total_r10 / new_n; avg_r0 = total_r0 / new_n; Sxx = 0.0; Sxy = 0.0; Syy = 0.0; - for (i=0;i=0.8 && val <1.2) { - if (img2[i+((int)((val-0.8)*2.5*nrows))*ncols] != 255) - img2[i+((int)((val-0.8)*2.5*nrows))*ncols] = 0; + for (i = 0; i < ncols; i++) { + double val = (1.0 - a + ((i / (double)ncols) * a)) * b; + + if (val >= 0.8 && val < 1.2) { + if (img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] != 255) { + img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] = 0; + } } + val += DELTA_1; - if (val >=0.8 && val <1.2) { - if (img2[i+((int)((val-0.8)*2.5*nrows))*ncols] != 255) - img2[i+((int)((val-0.8)*2.5*nrows))*ncols] = 8; + + if (val >= 0.8 && val < 1.2) { + if (img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] != 255) { + img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] = 8; + } } - val -= DELTA_1*2; - if (val >=0.8 && val <1.2) { - if (img2[i+((int)((val-0.8)*2.5*nrows))*ncols] != 255) - img2[i+((int)((val-0.8)*2.5*nrows))*ncols] = 8; + + val -= DELTA_1 * 2; + + if (val >= 0.8 && val < 1.2) { + if (img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] != 255) { + img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] = 8; + } } - val += DELTA_1+DELTA_2; - if (val >=0.8 && val <1.2) { - if (img2[i+((int)((val-0.8)*2.5*nrows))*ncols] != 255) - img2[i+((int)((val-0.8)*2.5*nrows))*ncols] = 16; + + val += DELTA_1 + DELTA_2; + + if (val >= 0.8 && val < 1.2) { + if (img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] != 255) { + img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] = 16; + } } - val -= DELTA_2*2; - if (val >=0.8 && val <1.2) { - if (img2[i+((int)((val-0.8)*2.5*nrows))*ncols] != 255) - img2[i+((int)((val-0.8)*2.5*nrows))*ncols] = 16; + + val -= DELTA_2 * 2; + + if (val >= 0.8 && val < 1.2) { + if (img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] != 255) { + img2[i + ((int)((val - 0.8) * 2.5 * nrows))*ncols] = 16; + } } } KLTExtractFeatureList(fl, ft, 0); - KLTWriteFeatureListToPPM(fl,img1,ncols,nrows,"/tmp/feat0.ppm"); + KLTWriteFeatureListToPPM(fl, img1, ncols, nrows, "/tmp/feat0.ppm"); KLTExtractFeatureList(fl, ft, 1); - KLTWriteFeatureListToPPM(fl,img2,ncols,nrows,"/tmp/feat1.ppm"); + KLTWriteFeatureListToPPM(fl, img2, ncols, nrows, "/tmp/feat1.ppm"); #endif // calculate deviation - for (i=0;i= 0 ? delta : -delta; total_delta += delta; } - printf ("distortion amount=%lf scale=%lf deviation=%lf, rxy=%lf\n", a, b, total_delta/n, rxy); + printf ("distortion amount=%lf scale=%lf deviation=%lf, rxy=%lf\n", a, b, total_delta / n, rxy); if (total_delta / new_n > DELTA_2) { printf ("Deviation is too big.\n"); @@ -228,7 +261,7 @@ int calcDistortion(unsigned char* img1, unsigned char* img2, int ncols, int nrow return -3; } - printf ("distortion amount=%lf scale=%lf deviation=%lf, rxy=%lf\n", a, b, total_delta/n, rxy); + printf ("distortion amount=%lf scale=%lf deviation=%lf, rxy=%lf\n", a, b, total_delta / n, rxy); distortion = a; return 1; } diff --git a/rtengine/calc_distort.h b/rtengine/calc_distort.h index 5ecff8d2f..711bf9515 100644 --- a/rtengine/calc_distort.h +++ b/rtengine/calc_distort.h @@ -1,4 +1,4 @@ #ifndef CALC_DISTORTION__H #define CALC_DISTORTION__H - int calcDistortion (unsigned char* img1, unsigned char* img2, int ncols, int nrows, int nfactor, double &distortion); +int calcDistortion (unsigned char* img1, unsigned char* img2, int ncols, int nrows, int nfactor, double &distortion); #endif diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 6fc200a31..80d73ea2e 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -15,16 +15,17 @@ #include #include -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; CameraConst::CameraConst() { - memset(dcraw_matrix, 0, sizeof(dcraw_matrix)); - memset(raw_crop, 0, sizeof(raw_crop)); - memset(raw_mask, 0, sizeof(raw_mask)); - white_max = 0; + memset(dcraw_matrix, 0, sizeof(dcraw_matrix)); + memset(raw_crop, 0, sizeof(raw_crop)); + memset(raw_mask, 0, sizeof(raw_mask)); + white_max = 0; } CameraConst::~CameraConst() @@ -34,539 +35,648 @@ CameraConst::~CameraConst() bool CameraConst::parseApertureScaling(CameraConst *cc, void *ji_) { - cJSON *ji = (cJSON *)ji_; - if (ji->type != cJSON_Array) { - fprintf(stderr, "\"ranges\":\"aperture_scaling\" must be an array\n"); - return false; - } - for (ji = ji->child; ji != NULL; ji = ji->next) { - cJSON *js = cJSON_GetObjectItem(ji, "aperture"); - if (!js) { - fprintf(stderr, "missing \"ranges\":\"aperture_scaling\":\"aperture\" object item.\n"); - return false; - } else if (js->type != cJSON_Number) { - fprintf(stderr, "\"ranges\":\"aperture_scaling\":\"aperture\" must be a number.\n"); - return false; - } - float aperture = (float)js->valuedouble; - js = cJSON_GetObjectItem(ji, "scale_factor"); - if (!js) { - fprintf(stderr, "missing \"ranges\":\"aperture_scaling\":\"scale_factor\" object item.\n"); - return false; - } else if (js->type != cJSON_Number) { - fprintf(stderr, "\"ranges\":\"aperture_scaling\":\"scale_factor\" must be a number.\n"); - return false; - } - float scale_factor = (float)js->valuedouble; - cc->mApertureScaling.insert(std::pair(aperture, scale_factor)); - } - return true; + cJSON *ji = (cJSON *)ji_; + + if (ji->type != cJSON_Array) { + fprintf(stderr, "\"ranges\":\"aperture_scaling\" must be an array\n"); + return false; + } + + for (ji = ji->child; ji != NULL; ji = ji->next) { + cJSON *js = cJSON_GetObjectItem(ji, "aperture"); + + if (!js) { + fprintf(stderr, "missing \"ranges\":\"aperture_scaling\":\"aperture\" object item.\n"); + return false; + } else if (js->type != cJSON_Number) { + fprintf(stderr, "\"ranges\":\"aperture_scaling\":\"aperture\" must be a number.\n"); + return false; + } + + float aperture = (float)js->valuedouble; + js = cJSON_GetObjectItem(ji, "scale_factor"); + + if (!js) { + fprintf(stderr, "missing \"ranges\":\"aperture_scaling\":\"scale_factor\" object item.\n"); + return false; + } else if (js->type != cJSON_Number) { + fprintf(stderr, "\"ranges\":\"aperture_scaling\":\"scale_factor\" must be a number.\n"); + return false; + } + + float scale_factor = (float)js->valuedouble; + cc->mApertureScaling.insert(std::pair(aperture, scale_factor)); + } + + return true; } bool CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_) { - cJSON *ji = (cJSON *)ji_; + cJSON *ji = (cJSON *)ji_; - if (ji->type == cJSON_Number) { - struct camera_const_levels lvl; - lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = ji->valueint; - cc->mLevels[bw].insert(std::pair(0, lvl)); - return true; - } else if (ji->type != cJSON_Array) { - fprintf(stderr, "\"ranges\":\"%s\" must be a number or an array\n", bw ? "white" : "black"); - return false; - } + if (ji->type == cJSON_Number) { + struct camera_const_levels lvl; + lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = ji->valueint; + cc->mLevels[bw].insert(std::pair(0, lvl)); + return true; + } else if (ji->type != cJSON_Array) { + fprintf(stderr, "\"ranges\":\"%s\" must be a number or an array\n", bw ? "white" : "black"); + return false; + } - if (ji->child->type == cJSON_Number) { - struct camera_const_levels lvl; - int i; - cJSON *js; - for (js = ji->child, i = 0; js != NULL && i < 4; js = js->next, i++) { - lvl.levels[i] = js->valueint; - } - if (i == 3) { - lvl.levels[3] = lvl.levels[1]; // G2 = G1 - } else if (i == 1) { - lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0]; - } else if (i != 4 || js != NULL) { - fprintf(stderr, "\"ranges\":\"%s\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black"); - return false; - } - cc->mLevels[bw].insert(std::pair(0, lvl)); - return true; - } + if (ji->child->type == cJSON_Number) { + struct camera_const_levels lvl; + int i; + cJSON *js; - for (ji = ji->child; ji != NULL; ji = ji->next) { - int iso[1000] = { 0 }; - int iso_count = 0; - cJSON *js = cJSON_GetObjectItem(ji, "iso"); - if (!js) { - fprintf(stderr, "missing \"ranges\":\"%s\":\"iso\" object item.\n", bw ? "white" : "black"); - return false; - } else if (js->type == cJSON_Number) { - iso[0] = js->valueint; - iso_count = 1; - } else if (js->type == cJSON_Array) { - int i; - for (js = js->child, i = 0; js != NULL && i < 1000; js = js->next, i++) { - if (js->type != cJSON_Number) { - fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be a number or an array of numbers.\n", bw ? "white" : "black"); - return false; - } - iso[i] = js->valueint; - } - iso_count = i; - } else { - fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be an array or a number.\n", bw ? "white" : "black"); - return false; - } - js = cJSON_GetObjectItem(ji, "levels"); - if (!js) { - fprintf(stderr, "missing \"ranges\":\"%s\":\"levels\".\n", bw ? "white" : "black"); - return false; - } - struct camera_const_levels lvl; - if (js->type == cJSON_Number) { - lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = js->valueint; - } else if (js->type == cJSON_Array) { - int i; - for (js = js->child, i = 0; js != NULL && i < 4; js = js->next, i++) { - if (js->type != cJSON_Number) { - fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black"); - return false; - } - lvl.levels[i] = js->valueint; - } - if (i == 3) { - lvl.levels[3] = lvl.levels[1]; // G2 = G1 - } else if (i == 1) { - lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0]; - } else if (i != 4 || js != NULL) { - fprintf(stderr, "\"ranges\":\"%s\":\"levels\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black"); - return false; - } - } else { - fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black"); - return false; - } - for (int i = 0; i < iso_count; i++) { - cc->mLevels[bw].insert(std::pair(iso[i], lvl)); - } - } - return true; + for (js = ji->child, i = 0; js != NULL && i < 4; js = js->next, i++) { + lvl.levels[i] = js->valueint; + } + + if (i == 3) { + lvl.levels[3] = lvl.levels[1]; // G2 = G1 + } else if (i == 1) { + lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0]; + } else if (i != 4 || js != NULL) { + fprintf(stderr, "\"ranges\":\"%s\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black"); + return false; + } + + cc->mLevels[bw].insert(std::pair(0, lvl)); + return true; + } + + for (ji = ji->child; ji != NULL; ji = ji->next) { + int iso[1000] = { 0 }; + int iso_count = 0; + cJSON *js = cJSON_GetObjectItem(ji, "iso"); + + if (!js) { + fprintf(stderr, "missing \"ranges\":\"%s\":\"iso\" object item.\n", bw ? "white" : "black"); + return false; + } else if (js->type == cJSON_Number) { + iso[0] = js->valueint; + iso_count = 1; + } else if (js->type == cJSON_Array) { + int i; + + for (js = js->child, i = 0; js != NULL && i < 1000; js = js->next, i++) { + if (js->type != cJSON_Number) { + fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be a number or an array of numbers.\n", bw ? "white" : "black"); + return false; + } + + iso[i] = js->valueint; + } + + iso_count = i; + } else { + fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be an array or a number.\n", bw ? "white" : "black"); + return false; + } + + js = cJSON_GetObjectItem(ji, "levels"); + + if (!js) { + fprintf(stderr, "missing \"ranges\":\"%s\":\"levels\".\n", bw ? "white" : "black"); + return false; + } + + struct camera_const_levels lvl; + + if (js->type == cJSON_Number) { + lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = js->valueint; + } else if (js->type == cJSON_Array) { + int i; + + for (js = js->child, i = 0; js != NULL && i < 4; js = js->next, i++) { + if (js->type != cJSON_Number) { + fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black"); + return false; + } + + lvl.levels[i] = js->valueint; + } + + if (i == 3) { + lvl.levels[3] = lvl.levels[1]; // G2 = G1 + } else if (i == 1) { + lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0]; + } else if (i != 4 || js != NULL) { + fprintf(stderr, "\"ranges\":\"%s\":\"levels\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black"); + return false; + } + } else { + fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black"); + return false; + } + + for (int i = 0; i < iso_count; i++) { + cc->mLevels[bw].insert(std::pair(iso[i], lvl)); + } + } + + return true; } CameraConst * CameraConst::parseEntry(void *cJSON_, const char *make_model) { - CameraConst *cc = 0; - cJSON *js, *ji, *jranges; - js = (cJSON *)cJSON_; + CameraConst *cc = 0; + cJSON *js, *ji, *jranges; + js = (cJSON *)cJSON_; - cc = new CameraConst; - cc->make_model = Glib::ustring(make_model); + cc = new CameraConst; + cc->make_model = Glib::ustring(make_model); - ji = cJSON_GetObjectItem(js, "dcraw_matrix"); - if (ji) { - if (ji->type != cJSON_Array) { - fprintf(stderr, "\"dcraw_matrix\" must be an array\n"); - goto parse_error; - } - int i; - for (i = 0, ji = ji->child; i < 12 && ji != NULL; i++, ji = ji->next) { - if (ji->type != cJSON_Number) { - fprintf(stderr, "\"dcraw_matrix\" array must contain numbers\n"); - goto parse_error; - } - cc->dcraw_matrix[i] = (short)ji->valueint; - } - } - ji = cJSON_GetObjectItem(js, "raw_crop"); - if (ji) { - if (ji->type != cJSON_Array) { - fprintf(stderr, "\"raw_crop\" must be an array\n"); - goto parse_error; - } - int i; - for (i = 0, ji = ji->child; i < 4 && ji != NULL; i++, ji = ji->next) { - if (ji->type != cJSON_Number) { - fprintf(stderr, "\"raw_crop\" array must contain numbers\n"); - goto parse_error; - } - cc->raw_crop[i] = ji->valueint; - } - if (i != 4 || ji != NULL) { - fprintf(stderr, "\"raw_crop\" must contain 4 numbers\n"); - goto parse_error; - } - } - ji = cJSON_GetObjectItem(js, "masked_areas"); - if (ji) { - if (ji->type != cJSON_Array) { - fprintf(stderr, "\"masked_areas\" must be an array\n"); - goto parse_error; - } - int i; - for (i = 0, ji = ji->child; i < 8 * 4 && ji != NULL; i++, ji = ji->next) { - if (ji->type != cJSON_Number) { - fprintf(stderr, "\"masked_areas\" array must contain numbers\n"); - goto parse_error; - } - cc->raw_mask[i/4][i%4] = ji->valueint; - } - if (i % 4 != 0) { - fprintf(stderr, "\"masked_areas\" array length must be divisable by 4\n"); - goto parse_error; - } - } - jranges = cJSON_GetObjectItem(js, "ranges"); - if (jranges) { - ji = cJSON_GetObjectItem(jranges, "black"); - if (ji) { - if (!parseLevels(cc, 0, ji)) { - goto parse_error; - } - } - ji = cJSON_GetObjectItem(jranges, "white"); - if (ji) { - if (!parseLevels(cc, 1, ji)) { - goto parse_error; - } - } - ji = cJSON_GetObjectItem(jranges, "white_max"); - if (ji) { - if (ji->type != cJSON_Number) { - fprintf(stderr, "\"ranges\":\"white_max\" must be a number\n"); - goto parse_error; - } - cc->white_max = (int)ji->valueint; - } - ji = cJSON_GetObjectItem(jranges, "aperture_scaling"); - if (ji) { - if (!parseApertureScaling(cc, ji)) { - goto parse_error; - } - } - } - for (int bw = 0; bw < 2; bw++) { - struct camera_const_levels lvl; - if (!cc->get_Levels(lvl, bw, 0, 0)) { - std::map::iterator it; - it = cc->mLevels[bw].begin(); - if (it != cc->mLevels[bw].end()) { - // insert levels with lowest iso as the default (iso 0) - struct camera_const_levels lvl = it->second; - cc->mLevels[bw].insert(std::pair(0, lvl)); - } - } - } - return cc; + ji = cJSON_GetObjectItem(js, "dcraw_matrix"); + + if (ji) { + if (ji->type != cJSON_Array) { + fprintf(stderr, "\"dcraw_matrix\" must be an array\n"); + goto parse_error; + } + + int i; + + for (i = 0, ji = ji->child; i < 12 && ji != NULL; i++, ji = ji->next) { + if (ji->type != cJSON_Number) { + fprintf(stderr, "\"dcraw_matrix\" array must contain numbers\n"); + goto parse_error; + } + + cc->dcraw_matrix[i] = (short)ji->valueint; + } + } + + ji = cJSON_GetObjectItem(js, "raw_crop"); + + if (ji) { + if (ji->type != cJSON_Array) { + fprintf(stderr, "\"raw_crop\" must be an array\n"); + goto parse_error; + } + + int i; + + for (i = 0, ji = ji->child; i < 4 && ji != NULL; i++, ji = ji->next) { + if (ji->type != cJSON_Number) { + fprintf(stderr, "\"raw_crop\" array must contain numbers\n"); + goto parse_error; + } + + cc->raw_crop[i] = ji->valueint; + } + + if (i != 4 || ji != NULL) { + fprintf(stderr, "\"raw_crop\" must contain 4 numbers\n"); + goto parse_error; + } + } + + ji = cJSON_GetObjectItem(js, "masked_areas"); + + if (ji) { + if (ji->type != cJSON_Array) { + fprintf(stderr, "\"masked_areas\" must be an array\n"); + goto parse_error; + } + + int i; + + for (i = 0, ji = ji->child; i < 8 * 4 && ji != NULL; i++, ji = ji->next) { + if (ji->type != cJSON_Number) { + fprintf(stderr, "\"masked_areas\" array must contain numbers\n"); + goto parse_error; + } + + cc->raw_mask[i / 4][i % 4] = ji->valueint; + } + + if (i % 4 != 0) { + fprintf(stderr, "\"masked_areas\" array length must be divisable by 4\n"); + goto parse_error; + } + } + + jranges = cJSON_GetObjectItem(js, "ranges"); + + if (jranges) { + ji = cJSON_GetObjectItem(jranges, "black"); + + if (ji) { + if (!parseLevels(cc, 0, ji)) { + goto parse_error; + } + } + + ji = cJSON_GetObjectItem(jranges, "white"); + + if (ji) { + if (!parseLevels(cc, 1, ji)) { + goto parse_error; + } + } + + ji = cJSON_GetObjectItem(jranges, "white_max"); + + if (ji) { + if (ji->type != cJSON_Number) { + fprintf(stderr, "\"ranges\":\"white_max\" must be a number\n"); + goto parse_error; + } + + cc->white_max = (int)ji->valueint; + } + + ji = cJSON_GetObjectItem(jranges, "aperture_scaling"); + + if (ji) { + if (!parseApertureScaling(cc, ji)) { + goto parse_error; + } + } + } + + for (int bw = 0; bw < 2; bw++) { + struct camera_const_levels lvl; + + if (!cc->get_Levels(lvl, bw, 0, 0)) { + std::map::iterator it; + it = cc->mLevels[bw].begin(); + + if (it != cc->mLevels[bw].end()) { + // insert levels with lowest iso as the default (iso 0) + struct camera_const_levels lvl = it->second; + cc->mLevels[bw].insert(std::pair(0, lvl)); + } + } + } + + return cc; parse_error: - return 0; + return 0; } bool CameraConst::has_dcrawMatrix(void) { - return dcraw_matrix[0] != 0; + return dcraw_matrix[0] != 0; } void -CameraConst::update_dcrawMatrix(const short *other) { - if (!other) - return; +CameraConst::update_dcrawMatrix(const short *other) +{ + if (!other) { + return; + } - for (int i=0; i<12; ++i) - dcraw_matrix[i] = other[i]; + for (int i = 0; i < 12; ++i) { + dcraw_matrix[i] = other[i]; + } } const short * CameraConst::get_dcrawMatrix(void) { - if (!has_dcrawMatrix()) { - return 0; - } - return dcraw_matrix; + if (!has_dcrawMatrix()) { + return 0; + } + + return dcraw_matrix; } bool CameraConst::has_rawCrop(void) { - return raw_crop[0] != 0 || raw_crop[1] != 0 || raw_crop[2] != 0 || raw_crop[3] != 0; + return raw_crop[0] != 0 || raw_crop[1] != 0 || raw_crop[2] != 0 || raw_crop[3] != 0; } void CameraConst::get_rawCrop(int& left_margin, int& top_margin, int& width, int& height) { - left_margin = raw_crop[0]; - top_margin = raw_crop[1]; - width = raw_crop[2]; - height = raw_crop[3]; + left_margin = raw_crop[0]; + top_margin = raw_crop[1]; + width = raw_crop[2]; + height = raw_crop[3]; } bool CameraConst::has_rawMask(int idx) { - if (idx < 0 || idx > 7) - return false; - return (raw_mask[idx][0] | raw_mask[idx][1] | raw_mask[idx][2] | raw_mask[idx][3]) != 0; + if (idx < 0 || idx > 7) { + return false; + } + + return (raw_mask[idx][0] | raw_mask[idx][1] | raw_mask[idx][2] | raw_mask[idx][3]) != 0; } void CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& right) { - top = left = bottom = right = 0; - if (idx < 0 || idx > 7) - return; - top = raw_mask[idx][0]; - left = raw_mask[idx][1]; - bottom = raw_mask[idx][2]; - right = raw_mask[idx][3]; + top = left = bottom = right = 0; + + if (idx < 0 || idx > 7) { + return; + } + + top = raw_mask[idx][0]; + left = raw_mask[idx][1]; + bottom = raw_mask[idx][2]; + right = raw_mask[idx][3]; } void -CameraConst::update_Levels(const CameraConst *other) { - if (!other) - return; +CameraConst::update_Levels(const CameraConst *other) +{ + if (!other) { + return; + } - if (other->mLevels[0].size()) { - mLevels[0].clear(); - mLevels[0] = other->mLevels[0]; - } - if (other->mLevels[1].size()) { - mLevels[1].clear(); - mLevels[1] = other->mLevels[1]; - } - if (other->mApertureScaling.size()) { - mApertureScaling.clear(); - mApertureScaling = other->mApertureScaling; - } - if (other->white_max) - white_max = other->white_max; + if (other->mLevels[0].size()) { + mLevels[0].clear(); + mLevels[0] = other->mLevels[0]; + } -// for (std::map::iterator i=other->mLevels[0].begin(); i!=other->mLevels[0].end(); i++) { -// } + if (other->mLevels[1].size()) { + mLevels[1].clear(); + mLevels[1] = other->mLevels[1]; + } + + if (other->mApertureScaling.size()) { + mApertureScaling.clear(); + mApertureScaling = other->mApertureScaling; + } + + if (other->white_max) { + white_max = other->white_max; + } + +// for (std::map::iterator i=other->mLevels[0].begin(); i!=other->mLevels[0].end(); i++) { +// } } bool CameraConst::get_Levels(struct camera_const_levels & lvl, int bw, int iso, float fnumber) { - std::map::iterator it; - it = mLevels[bw].find(iso); - if (it == mLevels[bw].end()) { - std::map::iterator best_it = mLevels[bw].begin(); - if (iso > 0) { - for (it = mLevels[bw].begin(); it != mLevels[bw].end(); it++) { - if (abs(it->first - iso) <= abs(best_it->first - iso)) { - best_it = it; - } else { - break; - } - } - } - it = best_it; - if (it == mLevels[bw].end()) { - return false; - } - } - lvl = it->second; + std::map::iterator it; + it = mLevels[bw].find(iso); - if (bw == 1 && fnumber > 0 && mApertureScaling.size() > 0) { - std::map::iterator it; - it = mApertureScaling.find(fnumber); - if (it == mApertureScaling.end()) { - // fnumber may be an exact aperture, eg 1.414, or a rounded eg 1.4. In our map we - // should have rounded numbers so we translate and retry the lookup + if (it == mLevels[bw].end()) { + std::map::iterator best_it = mLevels[bw].begin(); - // table with traditional 1/3 stop f-number rounding used by most cameras, we only - // have in the range 0.7 - 10.0, but aperture scaling rarely happen past f/4.0 - const float fn_tab[8][3] = { - { 0.7, 0.8, 0.9 }, - { 1.0, 1.1, 1.2 }, - { 1.4, 1.6, 1.8 }, - { 2.0, 2.2, 2.5 }, - { 2.8, 3.2, 3.5 }, - { 4.0, 4.5, 5.0 }, - { 5.6, 6.3, 7.1 }, - { 8.0, 9.0, 10.0 } - }; - for (int avh = 0; avh < 8; avh++) { - for (int k = 0; k < 3; k++) { - float av = (avh-1) + (float)k / 3; - float aperture = sqrtf(powf(2, av)); - if (fnumber > aperture*0.97 && fnumber < aperture/0.97) { - fnumber = fn_tab[avh][k]; - it = mApertureScaling.find(fnumber); - avh = 7; - break; - } - } - } - } - float scaling = 1.0; - if (it == mApertureScaling.end()) { - std::map::reverse_iterator it; - for (it = mApertureScaling.rbegin(); it != mApertureScaling.rend(); it++) { - if (it->first > fnumber) { - scaling = it->second; - } else { - break; - } - } - } else { - scaling = it->second; - } - if (scaling > 1.0) { - for (int i = 0; i < 4; i++) { - lvl.levels[i] *= scaling; - if (white_max > 0 && lvl.levels[i] > white_max) { - lvl.levels[i] = white_max; - } - } - } - } - return true; + if (iso > 0) { + for (it = mLevels[bw].begin(); it != mLevels[bw].end(); it++) { + if (abs(it->first - iso) <= abs(best_it->first - iso)) { + best_it = it; + } else { + break; + } + } + } + + it = best_it; + + if (it == mLevels[bw].end()) { + return false; + } + } + + lvl = it->second; + + if (bw == 1 && fnumber > 0 && mApertureScaling.size() > 0) { + std::map::iterator it; + it = mApertureScaling.find(fnumber); + + if (it == mApertureScaling.end()) { + // fnumber may be an exact aperture, eg 1.414, or a rounded eg 1.4. In our map we + // should have rounded numbers so we translate and retry the lookup + + // table with traditional 1/3 stop f-number rounding used by most cameras, we only + // have in the range 0.7 - 10.0, but aperture scaling rarely happen past f/4.0 + const float fn_tab[8][3] = { + { 0.7, 0.8, 0.9 }, + { 1.0, 1.1, 1.2 }, + { 1.4, 1.6, 1.8 }, + { 2.0, 2.2, 2.5 }, + { 2.8, 3.2, 3.5 }, + { 4.0, 4.5, 5.0 }, + { 5.6, 6.3, 7.1 }, + { 8.0, 9.0, 10.0 } + }; + + for (int avh = 0; avh < 8; avh++) { + for (int k = 0; k < 3; k++) { + float av = (avh - 1) + (float)k / 3; + float aperture = sqrtf(powf(2, av)); + + if (fnumber > aperture * 0.97 && fnumber < aperture / 0.97) { + fnumber = fn_tab[avh][k]; + it = mApertureScaling.find(fnumber); + avh = 7; + break; + } + } + } + } + + float scaling = 1.0; + + if (it == mApertureScaling.end()) { + std::map::reverse_iterator it; + + for (it = mApertureScaling.rbegin(); it != mApertureScaling.rend(); it++) { + if (it->first > fnumber) { + scaling = it->second; + } else { + break; + } + } + } else { + scaling = it->second; + } + + if (scaling > 1.0) { + for (int i = 0; i < 4; i++) { + lvl.levels[i] *= scaling; + + if (white_max > 0 && lvl.levels[i] > white_max) { + lvl.levels[i] = white_max; + } + } + } + } + + return true; } int CameraConst::get_BlackLevel(const int idx, const int iso_speed) { - assert(idx >= 0 && idx <= 3); - struct camera_const_levels lvl; - if (!get_Levels(lvl, 0, iso_speed, 0.0)) { - return -1; - } - return lvl.levels[idx]; + assert(idx >= 0 && idx <= 3); + struct camera_const_levels lvl; + + if (!get_Levels(lvl, 0, iso_speed, 0.0)) { + return -1; + } + + return lvl.levels[idx]; } int CameraConst::get_WhiteLevel(const int idx, const int iso_speed, const float fnumber) { - assert(idx >= 0 && idx <= 3); - struct camera_const_levels lvl; - if (!get_Levels(lvl, 1, iso_speed, fnumber)) { - return -1; - } - return lvl.levels[idx]; + assert(idx >= 0 && idx <= 3); + struct camera_const_levels lvl; + + if (!get_Levels(lvl, 1, iso_speed, fnumber)) { + return -1; + } + + return lvl.levels[idx]; } bool CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) { - // read the file into a single long string - const char *filename = filename_.c_str(); - FILE *stream = fopen(filename, "rt"); - if (stream == NULL) { - fprintf(stderr, "Could not open camera constants file \"%s\": %s\n", filename, strerror(errno)); - return false; - } - size_t bufsize = 4096; - size_t datasize = 0, ret; - char *buf = (char *)malloc(bufsize); - while ((ret = fread(&buf[datasize], 1, bufsize - datasize, stream)) != 0) { - datasize += ret; - if (datasize == bufsize) { - bufsize += 4096; - buf = (char *)realloc(buf, bufsize); - } - } - if (!feof(stream)) { - fclose(stream); - free(buf); - fprintf(stderr, "Failed to read camera constants file \"%s\"\n", filename); - return false; - } - fclose(stream); - buf = (char *)realloc(buf, datasize + 1); - buf[datasize] = '\0'; + // read the file into a single long string + const char *filename = filename_.c_str(); + FILE *stream = fopen(filename, "rt"); - // remove comments - cJSON_Minify(buf); + if (stream == NULL) { + fprintf(stderr, "Could not open camera constants file \"%s\": %s\n", filename, strerror(errno)); + return false; + } - // parse - cJSON *jsroot = cJSON_Parse(buf); - if (!jsroot) { - char str[128]; - const char *ep = cJSON_GetErrorPtr() - 10; - if ((uintptr_t)ep < (uintptr_t)buf) { - ep = buf; - } - strncpy(str, ep, sizeof(str)); - str[sizeof(str)-1] = '\0'; - fprintf(stderr, "JSON parse error in file \"%s\" near '%s'\n", filename, str); - free(buf); - return false; - } - free(buf); - /*{ - char *js_str = cJSON_Print(jsroot); - printf("%s\n", js_str); - free(js_str); - }*/ - cJSON *js = cJSON_GetObjectItem(jsroot, "camera_constants"); - if (!js) { - fprintf(stderr, "missing \"camera_constants\" object item\n"); - goto parse_error; - } - for (js = js->child; js != NULL; js = js->next) { - cJSON *ji = cJSON_GetObjectItem(js, "make_model"); - if (!ji) { - fprintf(stderr, "missing \"make_model\" object item\n"); - goto parse_error; - } - bool is_array = false; - if (ji->type == cJSON_Array) { - ji = ji->child; - is_array = true; - } - while (ji != NULL) { - if (ji->type != cJSON_String) { - fprintf(stderr, "\"make_model\" must be a string or an array of strings\n"); - goto parse_error; - } - CameraConst *cc = CameraConst::parseEntry((void *)js, ji->valuestring); - if (!cc) { - goto parse_error; - } - Glib::ustring make_model(ji->valuestring); - make_model = make_model.uppercase(); - std::map::iterator existingccIter = mCameraConstants.find(make_model); + size_t bufsize = 4096; + size_t datasize = 0, ret; + char *buf = (char *)malloc(bufsize); - if (existingccIter == mCameraConstants.end()) { - // add the new CamConst to the map - mCameraConstants.insert(std::pair(make_model, cc)); - if (settings->verbose) { - printf("Add camera constants for \"%s\"\n", make_model.c_str()); - } - } else { - // The CameraConst already exist for this camera make/model -> we merge the values - CameraConst *existingcc = existingccIter->second; + while ((ret = fread(&buf[datasize], 1, bufsize - datasize, stream)) != 0) { + datasize += ret; - // updating the dcraw matrix - existingcc->update_dcrawMatrix(cc->get_dcrawMatrix()); - // deleting all the existing levels, replaced by the new ones - existingcc->update_Levels(cc); - if (settings->verbose) { - printf("Merging camera constants for \"%s\"\n", make_model.c_str()); - } - } - if (is_array) { - ji = ji->next; - } else { - ji = NULL; - } - } - } - cJSON_Delete(jsroot); - return true; + if (datasize == bufsize) { + bufsize += 4096; + buf = (char *)realloc(buf, bufsize); + } + } + + if (!feof(stream)) { + fclose(stream); + free(buf); + fprintf(stderr, "Failed to read camera constants file \"%s\"\n", filename); + return false; + } + + fclose(stream); + buf = (char *)realloc(buf, datasize + 1); + buf[datasize] = '\0'; + + // remove comments + cJSON_Minify(buf); + + // parse + cJSON *jsroot = cJSON_Parse(buf); + + if (!jsroot) { + char str[128]; + const char *ep = cJSON_GetErrorPtr() - 10; + + if ((uintptr_t)ep < (uintptr_t)buf) { + ep = buf; + } + + strncpy(str, ep, sizeof(str)); + str[sizeof(str) - 1] = '\0'; + fprintf(stderr, "JSON parse error in file \"%s\" near '%s'\n", filename, str); + free(buf); + return false; + } + + free(buf); + /*{ + char *js_str = cJSON_Print(jsroot); + printf("%s\n", js_str); + free(js_str); + }*/ + cJSON *js = cJSON_GetObjectItem(jsroot, "camera_constants"); + + if (!js) { + fprintf(stderr, "missing \"camera_constants\" object item\n"); + goto parse_error; + } + + for (js = js->child; js != NULL; js = js->next) { + cJSON *ji = cJSON_GetObjectItem(js, "make_model"); + + if (!ji) { + fprintf(stderr, "missing \"make_model\" object item\n"); + goto parse_error; + } + + bool is_array = false; + + if (ji->type == cJSON_Array) { + ji = ji->child; + is_array = true; + } + + while (ji != NULL) { + if (ji->type != cJSON_String) { + fprintf(stderr, "\"make_model\" must be a string or an array of strings\n"); + goto parse_error; + } + + CameraConst *cc = CameraConst::parseEntry((void *)js, ji->valuestring); + + if (!cc) { + goto parse_error; + } + + Glib::ustring make_model(ji->valuestring); + make_model = make_model.uppercase(); + std::map::iterator existingccIter = mCameraConstants.find(make_model); + + if (existingccIter == mCameraConstants.end()) { + // add the new CamConst to the map + mCameraConstants.insert(std::pair(make_model, cc)); + + if (settings->verbose) { + printf("Add camera constants for \"%s\"\n", make_model.c_str()); + } + } else { + // The CameraConst already exist for this camera make/model -> we merge the values + CameraConst *existingcc = existingccIter->second; + + // updating the dcraw matrix + existingcc->update_dcrawMatrix(cc->get_dcrawMatrix()); + // deleting all the existing levels, replaced by the new ones + existingcc->update_Levels(cc); + + if (settings->verbose) { + printf("Merging camera constants for \"%s\"\n", make_model.c_str()); + } + } + + if (is_array) { + ji = ji->next; + } else { + ji = NULL; + } + } + } + + cJSON_Delete(jsroot); + return true; parse_error: - fprintf(stderr, "failed to parse camera constants file \"%s\"\n", filename); - mCameraConstants.clear(); - cJSON_Delete(jsroot); - return false; + fprintf(stderr, "failed to parse camera constants file \"%s\"\n", filename); + mCameraConstants.clear(); + cJSON_Delete(jsroot); + return false; } CameraConstantsStore::CameraConstantsStore() @@ -577,37 +687,42 @@ static CameraConstantsStore *global_instance; void CameraConstantsStore::initCameraConstants(Glib::ustring baseDir, Glib::ustring userSettingsDir) { - if (global_instance) { - // should only be called once during init. - abort(); - } - global_instance = new CameraConstantsStore(); - global_instance->parse_camera_constants_file(Glib::build_filename(baseDir, "camconst.json")); + if (global_instance) { + // should only be called once during init. + abort(); + } - Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json")); - if (safe_file_test(userFile, Glib::FILE_TEST_EXISTS)) - global_instance->parse_camera_constants_file(userFile); + global_instance = new CameraConstantsStore(); + global_instance->parse_camera_constants_file(Glib::build_filename(baseDir, "camconst.json")); + + Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json")); + + if (safe_file_test(userFile, Glib::FILE_TEST_EXISTS)) { + global_instance->parse_camera_constants_file(userFile); + } } CameraConstantsStore * CameraConstantsStore::getInstance(void) { - return global_instance; + return global_instance; } CameraConst * CameraConstantsStore::get(const char make[], const char model[]) { - Glib::ustring key(make); - key += " "; - key += model; - key = key.uppercase(); - std::map::iterator it; - it = mCameraConstants.find(key); - if (it == mCameraConstants.end()) { - return 0; - } - return it->second; + Glib::ustring key(make); + key += " "; + key += model; + key = key.uppercase(); + std::map::iterator it; + it = mCameraConstants.find(key); + + if (it == mCameraConstants.end()) { + return 0; + } + + return it->second; } } // namespace rtengine diff --git a/rtengine/camconst.h b/rtengine/camconst.h index cb04c4c49..a591f09fe 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -7,14 +7,16 @@ #include #include -namespace rtengine { +namespace rtengine +{ struct camera_const_levels { - int levels[4]; + int levels[4]; }; -class CameraConst { - private: +class CameraConst +{ +private: Glib::ustring make_model; short dcraw_matrix[12]; int raw_crop[4]; @@ -29,7 +31,7 @@ class CameraConst { static bool parseApertureScaling(CameraConst *cc, void *ji); bool get_Levels(struct camera_const_levels & lvl, int bw, int iso, float fnumber); - public: +public: static CameraConst *parseEntry(void *cJSON, const char *make_model); bool has_dcrawMatrix(void); void update_dcrawMatrix(const short *other); @@ -43,14 +45,15 @@ class CameraConst { void update_Levels(const CameraConst *other); }; -class CameraConstantsStore { - private: +class CameraConstantsStore +{ +private: std::map mCameraConstants; CameraConstantsStore(); bool parse_camera_constants_file(Glib::ustring filename); - public: +public: static void initCameraConstants(Glib::ustring baseDir, Glib::ustring userSettingsDir); static CameraConstantsStore *getInstance(void); CameraConst *get(const char make[], const char model[]); diff --git a/rtengine/cfa_linedn_RT.cc b/rtengine/cfa_linedn_RT.cc index 3bb8aaeae..78da79bb5 100644 --- a/rtengine/cfa_linedn_RT.cc +++ b/rtengine/cfa_linedn_RT.cc @@ -1,24 +1,24 @@ //////////////////////////////////////////////////////////////// // -// CFA line denoise by DCT filtering +// CFA line denoise by DCT filtering // -// copyright (c) 2008-2010 Emil Martinec -// parallelized 2013 by Ingo Weyrich +// copyright (c) 2008-2010 Emil Martinec +// parallelized 2013 by Ingo Weyrich // // code dated: June 7, 2010 // -// cfa_linedn_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// cfa_linedn_RT.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -28,7 +28,7 @@ #include "rawimagesource.h" #include "rt_math.h" -#define TS 224 // Tile size of 224 instead of 512 speeds up processing +#define TS 224 // Tile size of 224 instead of 512 speeds up processing #define CLASS @@ -41,201 +41,228 @@ using namespace rtengine; void RawImageSource::CLASS cfa_linedn(float noise) { - // local variables - int height=H, width=W; - - const float clip_pt = 0.8*initialGain* 65535.0; - - float eps=1e-5; //tolerance to avoid dividing by zero - - const float gauss[5] = {0.20416368871516755, 0.18017382291138087, 0.1238315368057753, 0.0662822452863612, 0.02763055063889883}; - const float rolloff[8] = {0, 0.135335, 0.249352, 0.411112, 0.606531, 0.800737, 0.945959, 1}; //gaussian with sigma=3 - const float window[8] = {0, .25, .75, 1, 1, .75, .25, 0}; //sine squared + // local variables + int height = H, width = W; - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - if (plistener) { - plistener->setProgressStr ("Line Denoise..."); - plistener->setProgress (0.0); - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - float noisevar=SQR(3*noise*65535); // _noise_ (as a fraction of saturation) is input to the algorithm - float noisevarm4 = 4.0f * noisevar; - volatile double progress = 0.0; - float* RawDataTmp = (float*)malloc( width*height*sizeof(float)); -#pragma omp parallel - { - - // allocate memory and assure the arrays don't have same 64 byte boundary to avoid L1 conflict misses - char *buffer = (char*)malloc(4 * TS * TS * sizeof(float)+ 3*64); - float *cfain = (float*)(buffer); - float *cfablur =(float*)(buffer+(TS*TS*sizeof(float))+ 1 * 64); - float *cfadiff =(float*)(buffer+(2*TS*TS*sizeof(float))+ 2 * 64); - float *cfadn =(float*)(buffer+(3*TS*TS*sizeof(float))+ 3 * 64); + const float clip_pt = 0.8 * initialGain * 65535.0; + + float eps = 1e-5; //tolerance to avoid dividing by zero + + const float gauss[5] = {0.20416368871516755, 0.18017382291138087, 0.1238315368057753, 0.0662822452863612, 0.02763055063889883}; + const float rolloff[8] = {0, 0.135335, 0.249352, 0.411112, 0.606531, 0.800737, 0.945959, 1}; //gaussian with sigma=3 + const float window[8] = {0, .25, .75, 1, 1, .75, .25, 0}; //sine squared + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if (plistener) { + plistener->setProgressStr ("Line Denoise..."); + plistener->setProgress (0.0); + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + float noisevar = SQR(3 * noise * 65535); // _noise_ (as a fraction of saturation) is input to the algorithm + float noisevarm4 = 4.0f * noisevar; + volatile double progress = 0.0; + float* RawDataTmp = (float*)malloc( width * height * sizeof(float)); + #pragma omp parallel + { + + // allocate memory and assure the arrays don't have same 64 byte boundary to avoid L1 conflict misses + char *buffer = (char*)malloc(4 * TS * TS * sizeof(float) + 3 * 64); + float *cfain = (float*)(buffer); + float *cfablur = (float*)(buffer + (TS * TS * sizeof(float)) + 1 * 64); + float *cfadiff = (float*)(buffer + (2 * TS * TS * sizeof(float)) + 2 * 64); + float *cfadn = (float*)(buffer + (3 * TS * TS * sizeof(float)) + 3 * 64); - float linehvar[4], linevvar[4], noisefactor[4][8][2], coeffsq; - float dctblock[4][8][8]; + float linehvar[4], linevvar[4], noisefactor[4][8][2], coeffsq; + float dctblock[4][8][8]; -#pragma omp for - for(int i=0;i(linehvar[0]+linehvar[1])) {//horizontal lines - for (int i=1; i<8; i++) { - dctblock[0][0][i] *= 0.5f*(noisefactor[0][i][1]+noisefactor[1][i][1]);//or should we use MIN??? - dctblock[1][0][i] *= 0.5f*(noisefactor[0][i][1]+noisefactor[1][i][1]);//or should we use MIN??? - } - } - if (noisevarm4>(linehvar[2]+linehvar[3])) {//horizontal lines - for (int i=1; i<8; i++) { - dctblock[2][0][i] *= 0.5f*(noisefactor[2][i][1]+noisefactor[3][i][1]);//or should we use MIN??? - dctblock[3][0][i] *= 0.5f*(noisefactor[2][i][1]+noisefactor[3][i][1]);//or should we use MIN??? - } - } - - //vertical lines - if (noisevarm4>(linevvar[0]+linevvar[2])) {//vertical lines - for (int i=1; i<8; i++) { - dctblock[0][i][0] *= 0.5f*(noisefactor[0][i][0]+noisefactor[2][i][0]);//or should we use MIN??? - dctblock[2][i][0] *= 0.5f*(noisefactor[0][i][0]+noisefactor[2][i][0]);//or should we use MIN??? - } - } - if (noisevarm4>(linevvar[1]+linevvar[3])) {//vertical lines - for (int i=1; i<8; i++) { - dctblock[1][i][0] *= 0.5f*(noisefactor[1][i][0]+noisefactor[3][i][0]);//or should we use MIN??? - dctblock[3][i][0] *= 0.5f*(noisefactor[1][i][0]+noisefactor[3][i][0]);//or should we use MIN??? - } - } - - for (int ey=0; ey<2; ey++) // (ex,ey) specify RGGB subarray - for (int ex=0; ex<2; ex++) { - ddct8x8s(1, dctblock[2*ey+ex]); //inverse DCT - //multiply by window fn and add to output (cfadn) - for (int i=0; i<8; i++) - for (int j=0; j<8; j++) { - cfadn[(rr+2*i+ey)*TS+cc+2*j+ex] += window[i]*window[j]*dctblock[2*ey+ex][i][j]; - } - } - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // copy smoothed results to temporary buffer - for (int rr=16; rr < numrows-16; rr++) { - int row = rr + top; - for (int col=16+left, indx=rr*TS+16; indx < rr*TS+numcols-16; indx++, col++) { - if (rawData[row][col]1.0) - { - progress=1.0; - } - plistener->setProgress(progress); - } - - } - // clean up - free(buffer); + int bottom = min(top + TS, height); + int right = min(left + TS, width); + int numrows = bottom - top; + int numcols = right - left; + int indx1; + + // load CFA data; data should be in linear gamma space, before white balance multipliers are applied + for (int rr = top; rr < top + numrows; rr++) + for (int cc = left, indx = (rr - top) * TS; cc < left + numcols; cc++, indx++) { + cfain[indx] = rawData[rr][cc]; + } + + //pad the block to a multiple of 16 on both sides + + if (numcols < TS) { + indx1 = numcols % 16; + + for (int i = 0; i < (16 - indx1); i++) + for (int rr = 0; rr < numrows; rr++) { + cfain[(rr)*TS + numcols + i] = cfain[(rr) * TS + numcols - i - 1]; + } + + numcols += 16 - indx1; + } + + if (numrows < TS) { + indx1 = numrows % 16; + + for (int i = 0; i < (16 - indx1); i++) + for (int cc = 0; cc < numcols; cc++) { + cfain[(numrows + i)*TS + cc] = cfain[(numrows - i - 1) * TS + cc]; + } + + numrows += 16 - indx1; + } + + //The cleaning algorithm starts here + + //gaussian blur of CFA data + for (int rr = 8; rr < numrows - 8; rr++) { + for (int indx = rr * TS; indx < rr * TS + numcols; indx++) { + cfablur[indx] = gauss[0] * cfain[indx]; + + for (int i = 1; i < 5; i++) { + cfablur[indx] += gauss[i] * (cfain[indx - (2 * i) * TS] + cfain[indx + (2 * i) * TS]); + } + } + + for (int indx = rr * TS + 8; indx < rr * TS + numcols - 8; indx++) { + cfadn[indx] = gauss[0] * cfablur[indx]; + + for (int i = 1; i < 5; i++) { + cfadn[indx] += gauss[i] * (cfablur[indx - 2 * i] + cfablur[indx + 2 * i]); + } + + cfadiff[indx] = cfain[indx] - cfadn[indx]; // hipass cfa data + } + } + + //begin block DCT + for (int rr = 8; rr < numrows - 22; rr += 8) // (rr,cc) shift by 8 to overlap blocks + for (int cc = 8; cc < numcols - 22; cc += 8) { + for (int ey = 0; ey < 2; ey++) // (ex,ey) specify RGGB subarray + for (int ex = 0; ex < 2; ex++) { + //grab an 8x8 block of a given RGGB channel + for (int i = 0; i < 8; i++) + for (int j = 0; j < 8; j++) { + dctblock[2 * ey + ex][i][j] = cfadiff[(rr + 2 * i + ey) * TS + cc + 2 * j + ex]; + } + + ddct8x8s(-1, dctblock[2 * ey + ex]); //forward DCT + } + + for (int ey = 0; ey < 2; ey++) // (ex,ey) specify RGGB subarray + for (int ex = 0; ex < 2; ex++) { + linehvar[2 * ey + ex] = linevvar[2 * ey + ex] = 0; + + for (int i = 4; i < 8; i++) { + linehvar[2 * ey + ex] += SQR(dctblock[2 * ey + ex][0][i]); + linevvar[2 * ey + ex] += SQR(dctblock[2 * ey + ex][i][0]); + } + + //Wiener filter for line denoising; roll off low frequencies + for (int i = 1; i < 8; i++) { + coeffsq = SQR(dctblock[2 * ey + ex][i][0]); //vertical + noisefactor[2 * ey + ex][i][0] = coeffsq / (coeffsq + rolloff[i] * noisevar + eps); + coeffsq = SQR(dctblock[2 * ey + ex][0][i]); //horizontal + noisefactor[2 * ey + ex][i][1] = coeffsq / (coeffsq + rolloff[i] * noisevar + eps); + // noisefactor labels are [RGGB subarray][row/col position][0=vert,1=hor] + } + } + + //horizontal lines + if (noisevarm4 > (linehvar[0] + linehvar[1])) { //horizontal lines + for (int i = 1; i < 8; i++) { + dctblock[0][0][i] *= 0.5f * (noisefactor[0][i][1] + noisefactor[1][i][1]); //or should we use MIN??? + dctblock[1][0][i] *= 0.5f * (noisefactor[0][i][1] + noisefactor[1][i][1]); //or should we use MIN??? + } + } + + if (noisevarm4 > (linehvar[2] + linehvar[3])) { //horizontal lines + for (int i = 1; i < 8; i++) { + dctblock[2][0][i] *= 0.5f * (noisefactor[2][i][1] + noisefactor[3][i][1]); //or should we use MIN??? + dctblock[3][0][i] *= 0.5f * (noisefactor[2][i][1] + noisefactor[3][i][1]); //or should we use MIN??? + } + } + + //vertical lines + if (noisevarm4 > (linevvar[0] + linevvar[2])) { //vertical lines + for (int i = 1; i < 8; i++) { + dctblock[0][i][0] *= 0.5f * (noisefactor[0][i][0] + noisefactor[2][i][0]); //or should we use MIN??? + dctblock[2][i][0] *= 0.5f * (noisefactor[0][i][0] + noisefactor[2][i][0]); //or should we use MIN??? + } + } + + if (noisevarm4 > (linevvar[1] + linevvar[3])) { //vertical lines + for (int i = 1; i < 8; i++) { + dctblock[1][i][0] *= 0.5f * (noisefactor[1][i][0] + noisefactor[3][i][0]); //or should we use MIN??? + dctblock[3][i][0] *= 0.5f * (noisefactor[1][i][0] + noisefactor[3][i][0]); //or should we use MIN??? + } + } + + for (int ey = 0; ey < 2; ey++) // (ex,ey) specify RGGB subarray + for (int ex = 0; ex < 2; ex++) { + ddct8x8s(1, dctblock[2 * ey + ex]); //inverse DCT + + //multiply by window fn and add to output (cfadn) + for (int i = 0; i < 8; i++) + for (int j = 0; j < 8; j++) { + cfadn[(rr + 2 * i + ey)*TS + cc + 2 * j + ex] += window[i] * window[j] * dctblock[2 * ey + ex][i][j]; + } + } + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // copy smoothed results to temporary buffer + for (int rr = 16; rr < numrows - 16; rr++) { + int row = rr + top; + + for (int col = 16 + left, indx = rr * TS + 16; indx < rr * TS + numcols - 16; indx++, col++) { + if (rawData[row][col] < clip_pt && cfadn[indx] < clip_pt) { + RawDataTmp[row * width + col] = CLIP((int)(cfadn[indx] + 0.5f)); + } + } + } + + if(plistener) { + progress += (double)((TS - 32) * (TS - 32)) / (height * width); + + if (progress > 1.0) { + progress = 1.0; + } + + plistener->setProgress(progress); + } + + } + + // clean up + free(buffer); // copy temporary buffer back to image matrix -#pragma omp for - for(int i=0;i Normalized 8x8 IDCT - C[k1][k2] = (1/4) * sum_j1=0^7 sum_j2=0^7 - a[j1][j2] * s[j1] * s[j2] * - cos(pi*j1*(k1+1/2)/8) * + C[k1][k2] = (1/4) * sum_j1=0^7 sum_j2=0^7 + a[j1][j2] * s[j1] * s[j2] * + cos(pi*j1*(k1+1/2)/8) * cos(pi*j2*(k2+1/2)/8), 0<=k1<8, 0<=k2<8 (s[0] = 1/sqrt(2), s[j] = 1, j > 0) Normalized 8x8 DCT - C[k1][k2] = (1/4) * s[k1] * s[k2] * sum_j1=0^7 sum_j2=0^7 - a[j1][j2] * - cos(pi*(j1+1/2)*k1/8) * + C[k1][k2] = (1/4) * s[k1] * s[k2] * sum_j1=0^7 sum_j2=0^7 + a[j1][j2] * + cos(pi*(j1+1/2)*k1/8) * cos(pi*(j2+1/2)*k2/8), 0<=k1<8, 0<=k2<8 (s[0] = 1/sqrt(2), s[j] = 1, j > 0) [usage] @@ -307,7 +334,7 @@ void RawImageSource::ddct8x8s(int isgn, float a[8][8]) int j; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; float xr, xi; - + if (isgn < 0) { for (j = 0; j <= 7; j++) { x0r = a[0][j] + a[7][j]; @@ -337,6 +364,7 @@ void RawImageSource::ddct8x8s(int isgn, float a[8][8]) a[3][j] = C8_3R * x3r - C8_3I * x3i; a[5][j] = C8_3R * x3i + C8_3I * x3r; } + for (j = 0; j <= 7; j++) { x0r = a[j][0] + a[j][7]; x1r = a[j][0] - a[j][7]; @@ -394,6 +422,7 @@ void RawImageSource::ddct8x8s(int isgn, float a[8][8]) a[6][j] = x2i - x3r; a[1][j] = x2i + x3r; } + for (j = 0; j <= 7; j++) { x1r = C8_1R * a[j][1] + C8_1I * a[j][7]; x1i = C8_1R * a[j][7] - C8_1I * a[j][1]; diff --git a/rtengine/ciecam02.cc b/rtengine/ciecam02.cc index 9924ecf86..47b24eba0 100644 --- a/rtengine/ciecam02.cc +++ b/rtengine/ciecam02.cc @@ -41,13 +41,19 @@ extern const Settings* settings; void Ciecam02::curvecolor(double satind, double satval, double &sres, double parsat) { - if (satind >=0.0) { - sres = (1.-(satind)/100.)*satval+(satind)/100.*(1.-SQR(SQR(1.-min(satval,1.0)))); - if (sres>parsat) { sres=parsat; } - if (sres<0.) { sres=0.; } + if (satind >= 0.0) { + sres = (1. - (satind) / 100.) * satval + (satind) / 100.*(1. - SQR(SQR(1. - min(satval, 1.0)))); + + if (sres > parsat) { + sres = parsat; + } + + if (sres < 0.) { + sres = 0.; + } } else { if (satind < -0.1) { - sres = satval*(1.+(satind)/100.); + sres = satval * (1. + (satind) / 100.); } } } @@ -58,13 +64,14 @@ void Ciecam02::curvecolorfloat(float satind, float satval, float &sres, float pa if (satval >= 1.f) { // The calculation below goes wrong direction when satval > 1 sres = satval; } else { - sres = (1.f-(satind)/100.f)*satval+(satind)/100.f*(1.f-SQR(SQR(1.f-min(satval,1.0f)))); + sres = (1.f - (satind) / 100.f) * satval + (satind) / 100.f * (1.f - SQR(SQR(1.f - min(satval, 1.0f)))); } - if (sres>parsat) { - sres = max(parsat,satval); + + if (sres > parsat) { + sres = max(parsat, satval); } } else if (satind < 0.f) { - sres = satval*(1.f+(satind)/100.f); + sres = satval * (1.f + (satind) / 100.f); } else { // satind == 0 means we don't want to change the value at all sres = satval; } @@ -72,11 +79,11 @@ void Ciecam02::curvecolorfloat(float satind, float satval, float &sres, float pa void Ciecam02::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu & histogram ) { - LUTf dcurve(65536,0); - int skip=1; + LUTf dcurve(65536, 0); + int skip = 1; // check if brightness curve is needed - if (br>0.00001 || br<-0.00001) { + if (br > 0.00001 || br < -0.00001) { std::vector brightcurvePoints; brightcurvePoints.resize(9); @@ -85,26 +92,27 @@ void Ciecam02::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu & brightcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range brightcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range - if (br>0) { + if (br > 0) { brightcurvePoints.at(3) = 0.1; // toe point - brightcurvePoints.at(4) = 0.1+br/150.0; //value at toe point + brightcurvePoints.at(4) = 0.1 + br / 150.0; //value at toe point brightcurvePoints.at(5) = 0.7; // shoulder point - brightcurvePoints.at(6) = min(1.0,0.7+br/300.0); //value at shoulder point + brightcurvePoints.at(6) = min(1.0, 0.7 + br / 300.0); //value at shoulder point } else { - brightcurvePoints.at(3) = 0.1-br/150.0; // toe point + brightcurvePoints.at(3) = 0.1 - br / 150.0; // toe point brightcurvePoints.at(4) = 0.1; // value at toe point - brightcurvePoints.at(5) = min(1.0,0.7-br/300.0); // shoulder point + brightcurvePoints.at(5) = min(1.0, 0.7 - br / 300.0); // shoulder point brightcurvePoints.at(6) = 0.7; // value at shoulder point } + brightcurvePoints.at(7) = 1.; // white point brightcurvePoints.at(8) = 1.; // value at white point - DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); + DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip); // Applying brightness curve - for (int i=0; i<32768; i++) { + for (int i = 0; i < 32768; i++) { // change to [0,1] range float val = (float)i / 32767.0; @@ -115,27 +123,30 @@ void Ciecam02::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu & // store result in a temporary array dcurve[i] = CLIPD(val); } + delete brightcurve; } else { - // for (int i=0; i<32768; i++) { // L values range up to 32767, higher values are for highlight overflow - for (int i=0; i<(32768*db); i++) { // L values range up to 32767, higher values are for highlight overflow + // for (int i=0; i<32768; i++) { // L values range up to 32767, higher values are for highlight overflow + for (int i = 0; i < (32768 * db); i++) { // L values range up to 32767, higher values are for highlight overflow // set the identity curve in the temporary array - dcurve[i] = (float)i / (db*32768.0f); + dcurve[i] = (float)i / (db * 32768.0f); } } - if (contr>0.00001 || contr<-0.00001) { + if (contr > 0.00001 || contr < -0.00001) { // compute mean luminance of the image with the curve applied int sum = 0; float avg = 0; + //float sqavg = 0; - for (int i=0; i<32768; i++) { + for (int i = 0; i < 32768; i++) { avg += dcurve[i] * histogram[i];//approximation for average : usage of L (lab) instead of J sum += histogram[i]; } + avg /= sum; std::vector contrastcurvePoints; contrastcurvePoints.resize(9); @@ -144,19 +155,19 @@ void Ciecam02::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu & contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range - contrastcurvePoints.at(3) = avg-avg*(0.6-contr/250.0); // toe point - contrastcurvePoints.at(4) = avg-avg*(0.6+contr/250.0); // value at toe point + contrastcurvePoints.at(3) = avg - avg * (0.6 - contr / 250.0); // toe point + contrastcurvePoints.at(4) = avg - avg * (0.6 + contr / 250.0); // value at toe point - contrastcurvePoints.at(5) = avg+(1-avg)*(0.6-contr/250.0); // shoulder point - contrastcurvePoints.at(6) = avg+(1-avg)*(0.6+contr/250.0); // value at shoulder point + contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point + contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point contrastcurvePoints.at(7) = 1.; // white point contrastcurvePoints.at(8) = 1.; // value at white point - DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS/skip); + DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); // apply contrast enhancement - for (int i=0; i<(32768*db); i++) { + for (int i = 0; i < (32768 * db); i++) { dcurve[i] = contrastcurve->getVal (dcurve[i]); } @@ -164,16 +175,18 @@ void Ciecam02::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu & } // for (int i=0; i<32768; i++) outCurve[i] = 32768.0*dcurve[i]; - for (int i=0; i<(db*32768); i++) { outCurve[i] = db*32768.0*dcurve[i]; } + for (int i = 0; i < (db * 32768); i++) { + outCurve[i] = db * 32768.0 * dcurve[i]; + } } void Ciecam02::curveJfloat (float br, float contr, int db, LUTf & outCurve, LUTu & histogram ) { - LUTf dcurve(65536,0); - int skip=1; + LUTf dcurve(65536, 0); + int skip = 1; // check if brightness curve is needed - if (br>0.00001f || br<-0.00001f) { + if (br > 0.00001f || br < -0.00001f) { std::vector brightcurvePoints; brightcurvePoints.resize(9); @@ -182,26 +195,27 @@ void Ciecam02::curveJfloat (float br, float contr, int db, LUTf & outCurve, LUTu brightcurvePoints.at(1) = 0.f; // black point. Value in [0 ; 1] range brightcurvePoints.at(2) = 0.f; // black point. Value in [0 ; 1] range - if (br>0) { + if (br > 0) { brightcurvePoints.at(3) = 0.1f; // toe point - brightcurvePoints.at(4) = 0.1f+br/150.0f; //value at toe point + brightcurvePoints.at(4) = 0.1f + br / 150.0f; //value at toe point brightcurvePoints.at(5) = 0.7f; // shoulder point - brightcurvePoints.at(6) = min(1.0f,0.7f+br/300.0f); //value at shoulder point + brightcurvePoints.at(6) = min(1.0f, 0.7f + br / 300.0f); //value at shoulder point } else { - brightcurvePoints.at(3) = 0.1f-br/150.0f; // toe point + brightcurvePoints.at(3) = 0.1f - br / 150.0f; // toe point brightcurvePoints.at(4) = 0.1f; // value at toe point - brightcurvePoints.at(5) = min(1.0f,0.7f-br/300.0f); // shoulder point + brightcurvePoints.at(5) = min(1.0f, 0.7f - br / 300.0f); // shoulder point brightcurvePoints.at(6) = 0.7f; // value at shoulder point } + brightcurvePoints.at(7) = 1.f; // white point brightcurvePoints.at(8) = 1.f; // value at white point - DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); + DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip); // Applying brightness curve - for (int i=0; i<32768; i++) { + for (int i = 0; i < 32768; i++) { // change to [0,1] range float val = (float)i / 32767.0f; @@ -212,27 +226,30 @@ void Ciecam02::curveJfloat (float br, float contr, int db, LUTf & outCurve, LUTu // store result in a temporary array dcurve[i] = CLIPD(val); } + delete brightcurve; } else { - // for (int i=0; i<32768; i++) { // L values range up to 32767, higher values are for highlight overflow - for (int i=0; i<(32768*db); i++) { // L values range up to 32767, higher values are for highlight overflow + // for (int i=0; i<32768; i++) { // L values range up to 32767, higher values are for highlight overflow + for (int i = 0; i < (32768 * db); i++) { // L values range up to 32767, higher values are for highlight overflow // set the identity curve in the temporary array - dcurve[i] = (float)i / (db*32768.0f); + dcurve[i] = (float)i / (db * 32768.0f); } } - if (contr>0.00001f || contr<-0.00001f) { + if (contr > 0.00001f || contr < -0.00001f) { // compute mean luminance of the image with the curve applied int sum = 0; float avg = 0; + //float sqavg = 0; - for (int i=0; i<32768; i++) { + for (int i = 0; i < 32768; i++) { avg += dcurve[i] * histogram[i];//approximation for average : usage of L (lab) instead of J sum += histogram[i]; } + avg /= sum; //printf("avg=%f\n",avg); std::vector contrastcurvePoints; @@ -242,19 +259,19 @@ void Ciecam02::curveJfloat (float br, float contr, int db, LUTf & outCurve, LUTu contrastcurvePoints.at(1) = 0.f; // black point. Value in [0 ; 1] range contrastcurvePoints.at(2) = 0.f; // black point. Value in [0 ; 1] range - contrastcurvePoints.at(3) = avg-avg*(0.6f-contr/250.0f); // toe point - contrastcurvePoints.at(4) = avg-avg*(0.6f+contr/250.0f); // value at toe point + contrastcurvePoints.at(3) = avg - avg * (0.6f - contr / 250.0f); // toe point + contrastcurvePoints.at(4) = avg - avg * (0.6f + contr / 250.0f); // value at toe point - contrastcurvePoints.at(5) = avg+(1-avg)*(0.6f-contr/250.0f); // shoulder point - contrastcurvePoints.at(6) = avg+(1-avg)*(0.6f+contr/250.0f); // value at shoulder point + contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6f - contr / 250.0f); // shoulder point + contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6f + contr / 250.0f); // value at shoulder point contrastcurvePoints.at(7) = 1.f; // white point contrastcurvePoints.at(8) = 1.f; // value at white point - DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS/skip); + DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); // apply contrast enhancement - for (int i=0; i<(32768*db); i++) { + for (int i = 0; i < (32768 * db); i++) { dcurve[i] = contrastcurve->getVal (dcurve[i]); } @@ -262,7 +279,9 @@ void Ciecam02::curveJfloat (float br, float contr, int db, LUTf & outCurve, LUTu } // for (int i=0; i<32768; i++) outCurve[i] = 32768.0*dcurve[i]; - for (int i=0; i<(db*32768); i++) { outCurve[i] = db*32768.0f*dcurve[i]; } + for (int i = 0; i < (db * 32768); i++) { + outCurve[i] = db * 32768.0f * dcurve[i]; + } } /** @@ -330,7 +349,7 @@ double Ciecam02::achromatic_response_to_white( double x, double y, double z, dou double rc, gc, bc; double rp, gp, bp; double rpa, gpa, bpa; - gamu=1; + gamu = 1; xyz_to_cat02( r, g, b, x, y, z, gamu ); rc = r * (((y * d) / r) + (1.0 - d)); @@ -338,10 +357,11 @@ double Ciecam02::achromatic_response_to_white( double x, double y, double z, dou bc = b * (((y * d) / b) + (1.0 - d)); cat02_to_hpe( rp, gp, bp, rc, gc, bc, gamu ); - if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk - rp=MAXR(rp,0.0); - gp=MAXR(gp,0.0); - bp=MAXR(bp,0.0); + + if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk + rp = MAXR(rp, 0.0); + gp = MAXR(gp, 0.0); + bp = MAXR(bp, 0.0); } rpa = nonlinear_adaptation( rp, fl ); @@ -357,7 +377,7 @@ float Ciecam02::achromatic_response_to_whitefloat( float x, float y, float z, fl float rc, gc, bc; float rp, gp, bp; float rpa, gpa, bpa; - gamu=1; + gamu = 1; xyz_to_cat02float( r, g, b, x, y, z, gamu ); rc = r * (((y * d) / r) + (1.0f - d)); @@ -365,10 +385,11 @@ float Ciecam02::achromatic_response_to_whitefloat( float x, float y, float z, fl bc = b * (((y * d) / b) + (1.0f - d)); cat02_to_hpefloat( rp, gp, bp, rc, gc, bc, gamu ); - if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk - rp=MAXR(rp,0.0f); - gp=MAXR(gp,0.0f); - bp=MAXR(bp,0.0f); + + if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk + rp = MAXR(rp, 0.0f); + gp = MAXR(gp, 0.0f); + bp = MAXR(bp, 0.0f); } rpa = nonlinear_adaptationfloat( rp, fl ); @@ -380,16 +401,17 @@ float Ciecam02::achromatic_response_to_whitefloat( float x, float y, float z, fl void Ciecam02::xyz_to_cat02( double &r, double &g, double &b, double x, double y, double z, int gamu ) { - gamu=1; - if (gamu==0) { + gamu = 1; + + if (gamu == 0) { r = ( 0.7328 * x) + (0.4296 * y) - (0.1624 * z); g = (-0.7036 * x) + (1.6975 * y) + (0.0061 * z); b = ( 0.0030 * x) + (0.0136 * y) + (0.9834 * z); - } else if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk + } else if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk //r = ( 0.7328 * x) + (0.4296 * y) - (0.1624 * z); //g = (-0.7036 * x) + (1.6975 * y) + (0.0061 * z); //b = ( 0.0000 * x) + (0.0000 * y) + (1.0000 * z); - r = ( 1.007245 * x) + (0.011136* y) - (0.018381 * z);//Changjun Li + r = ( 1.007245 * x) + (0.011136 * y) - (0.018381 * z); //Changjun Li g = (-0.318061 * x) + (1.314589 * y) + (0.003471 * z); b = ( 0.0000 * x) + (0.0000 * y) + (1.0000 * z); } @@ -397,16 +419,17 @@ void Ciecam02::xyz_to_cat02( double &r, double &g, double &b, double x, double y void Ciecam02::xyz_to_cat02float( float &r, float &g, float &b, float x, float y, float z, int gamu ) { - gamu=1; - if (gamu==0) { + gamu = 1; + + if (gamu == 0) { r = ( 0.7328f * x) + (0.4296f * y) - (0.1624f * z); g = (-0.7036f * x) + (1.6975f * y) + (0.0061f * z); b = ( 0.0030f * x) + (0.0136f * y) + (0.9834f * z); - } else if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk + } else if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk //r = ( 0.7328 * x) + (0.4296 * y) - (0.1624 * z); //g = (-0.7036 * x) + (1.6975 * y) + (0.0061 * z); //b = ( 0.0000 * x) + (0.0000 * y) + (1.0000 * z); - r = ( 1.007245f * x) + (0.011136f* y) - (0.018381f * z);//Changjun Li + r = ( 1.007245f * x) + (0.011136f * y) - (0.018381f * z); //Changjun Li g = (-0.318061f * x) + (1.314589f * y) + (0.003471f * z); b = ( 0.0000f * x) + (0.0000f * y) + (1.0000f * z); } @@ -423,17 +446,18 @@ void Ciecam02::xyz_to_cat02float( vfloat &r, vfloat &g, vfloat &b, vfloat x, vfl void Ciecam02::cat02_to_xyz( double &x, double &y, double &z, double r, double g, double b, int gamu ) { - gamu=1; - if (gamu==0) { + gamu = 1; + + if (gamu == 0) { x = ( 1.096124 * r) - (0.278869 * g) + (0.182745 * b); y = ( 0.454369 * r) + (0.473533 * g) + (0.072098 * b); z = (-0.009628 * r) - (0.005698 * g) + (1.015326 * b); - } else if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk + } else if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk //x = ( 1.0978566 * r) - (0.277843 * g) + (0.179987 * b); //y = ( 0.455053 * r) + (0.473938 * g) + (0.0710096* b); //z = ( 0.000000 * r) - (0.000000 * g) + (1.000000 * b); - x = ( 0.99015849 * r) - (0.00838772* g) + (0.018229217 * b);//Changjun Li - y = ( 0.239565979 * r) + (0.758664642 * g) + (0.001770137* b); + x = ( 0.99015849 * r) - (0.00838772 * g) + (0.018229217 * b); //Changjun Li + y = ( 0.239565979 * r) + (0.758664642 * g) + (0.001770137 * b); z = ( 0.000000 * r) - (0.000000 * g) + (1.000000 * b); } } @@ -441,17 +465,18 @@ void Ciecam02::cat02_to_xyz( double &x, double &y, double &z, double r, double g #ifndef __SSE2__ void Ciecam02::cat02_to_xyzfloat( float &x, float &y, float &z, float r, float g, float b, int gamu ) { - gamu=1; - if (gamu==0) { + gamu = 1; + + if (gamu == 0) { x = ( 1.096124f * r) - (0.278869f * g) + (0.182745f * b); y = ( 0.454369f * r) + (0.473533f * g) + (0.072098f * b); z = (-0.009628f * r) - (0.005698f * g) + (1.015326f * b); - } else if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk + } else if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk //x = ( 1.0978566 * r) - (0.277843 * g) + (0.179987 * b); //y = ( 0.455053 * r) + (0.473938 * g) + (0.0710096* b); //z = ( 0.000000 * r) - (0.000000 * g) + (1.000000 * b); - x = ( 0.99015849f * r) - (0.00838772f* g) + (0.018229217f * b);//Changjun Li - y = ( 0.239565979f * r) + (0.758664642f * g) + (0.001770137f* b); + x = ( 0.99015849f * r) - (0.00838772f * g) + (0.018229217f * b); //Changjun Li + y = ( 0.239565979f * r) + (0.758664642f * g) + (0.001770137f * b); z = ( 0.000000f * r) - (0.000000f * g) + (1.000000f * b); } } @@ -459,8 +484,8 @@ void Ciecam02::cat02_to_xyzfloat( float &x, float &y, float &z, float r, float g void Ciecam02::cat02_to_xyzfloat( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloat g, vfloat b ) { //gamut correction M.H.Brill S.Susstrunk - x = ( F2V(0.99015849f) * r) - (F2V(0.00838772f)* g) + (F2V(0.018229217f) * b);//Changjun Li - y = ( F2V(0.239565979f) * r) + (F2V(0.758664642f) * g) + (F2V(0.001770137f)* b); + x = ( F2V(0.99015849f) * r) - (F2V(0.00838772f) * g) + (F2V(0.018229217f) * b); //Changjun Li + y = ( F2V(0.239565979f) * r) + (F2V(0.758664642f) * g) + (F2V(0.001770137f) * b); z = b; } #endif @@ -490,29 +515,31 @@ void Ciecam02::hpe_to_xyzfloat( vfloat &x, vfloat &y, vfloat &z, vfloat r, vfloa void Ciecam02::cat02_to_hpe( double &rh, double &gh, double &bh, double r, double g, double b, int gamu ) { - gamu=1; - if (gamu==0) { + gamu = 1; + + if (gamu == 0) { rh = ( 0.7409792 * r) + (0.2180250 * g) + (0.0410058 * b); gh = ( 0.2853532 * r) + (0.6242014 * g) + (0.0904454 * b); bh = (-0.0096280 * r) - (0.0056980 * g) + (1.0153260 * b); - } else if (gamu==1) { //Changjun Li - rh = ( 0.550930835 * r) + (0.519435987* g) - ( 0.070356303* b); + } else if (gamu == 1) { //Changjun Li + rh = ( 0.550930835 * r) + (0.519435987 * g) - ( 0.070356303 * b); gh = ( 0.055954056 * r) + (0.89973132 * g) + (0.044315524 * b); - bh = (0.0 * r) - (0.0* g) + (1.0 * b); + bh = (0.0 * r) - (0.0 * g) + (1.0 * b); } } void Ciecam02::cat02_to_hpefloat( float &rh, float &gh, float &bh, float r, float g, float b, int gamu ) { - gamu=1; - if (gamu==0) { + gamu = 1; + + if (gamu == 0) { rh = ( 0.7409792f * r) + (0.2180250f * g) + (0.0410058f * b); gh = ( 0.2853532f * r) + (0.6242014f * g) + (0.0904454f * b); bh = (-0.0096280f * r) - (0.0056980f * g) + (1.0153260f * b); - } else if (gamu==1) { //Changjun Li - rh = ( 0.550930835f * r) + (0.519435987f* g) - ( 0.070356303f* b); + } else if (gamu == 1) { //Changjun Li + rh = ( 0.550930835f * r) + (0.519435987f * g) - ( 0.070356303f * b); gh = ( 0.055954056f * r) + (0.89973132f * g) + (0.044315524f * b); - bh = (0.0f * r) - (0.0f* g) + (1.0f * b); + bh = (0.0f * r) - (0.0f * g) + (1.0f * b); } } @@ -520,7 +547,7 @@ void Ciecam02::cat02_to_hpefloat( float &rh, float &gh, float &bh, float r, floa void Ciecam02::cat02_to_hpefloat( vfloat &rh, vfloat &gh, vfloat &bh, vfloat r, vfloat g, vfloat b) { //Changjun Li - rh = ( F2V(0.550930835f) * r) + (F2V(0.519435987f)* g) - ( F2V(0.070356303f)* b); + rh = ( F2V(0.550930835f) * r) + (F2V(0.519435987f) * g) - ( F2V(0.070356303f) * b); gh = ( F2V(0.055954056f) * r) + (F2V(0.89973132f) * g) + (F2V(0.044315524f) * b); bh = b; } @@ -570,12 +597,13 @@ void Ciecam02::calculate_ab( double &aa, double &bb, double h, double e, double double sinh = sin( hrad ); double cosh = cos( hrad ); double x = (a / nbb) + 0.305; - double p3 = 21.0/20.0; + double p3 = 21.0 / 20.0; + if ( fabs( sinh ) >= fabs( cosh ) ) { bb = ((0.32787 * x) * (2.0 + p3)) / ((e / (t * sinh)) - - // ((0.32145 - 0.63507 - (p3 * 0.15681)) * (cosh / sinh)) - - // (0.20527 - 0.18603 - (p3 * 4.49038))); + // ((0.32145 - 0.63507 - (p3 * 0.15681)) * (cosh / sinh)) - + // (0.20527 - 0.18603 - (p3 * 4.49038))); ((-0.31362 - (p3 * 0.15681)) * (cosh / sinh)) - (0.01924 - (p3 * 4.49038))); @@ -583,8 +611,8 @@ void Ciecam02::calculate_ab( double &aa, double &bb, double h, double e, double } else { aa = ((0.32787 * x) * (2.0 + p3)) / ((e / (t * cosh)) - - // (0.32145 - 0.63507 - (p3 * 0.15681)) - - // ((0.20527 - 0.18603 - (p3 * 4.49038)) * (sinh / cosh))); + // (0.32145 - 0.63507 - (p3 * 0.15681)) - + // ((0.20527 - 0.18603 - (p3 * 4.49038)) * (sinh / cosh))); (-0.31362 - (p3 * 0.15681)) - ((0.01924 - (p3 * 4.49038)) * (sinh / cosh))); @@ -600,14 +628,16 @@ void Ciecam02::calculate_abfloat( float &aa, float &bb, float h, float e, float float x = (a / nbb) + 0.305f; float p3 = 1.05f; bool swapValues = fabs( sinh ) > fabs( cosh ); + if (swapValues) { - std::swap(sinh,cosh); + std::swap(sinh, cosh); } + float c1 = 1.f; float c2 = sinh / cosh; if (swapValues) { - std::swap(c1,c2); + std::swap(c1, c2); } float div = ((e / (t * cosh)) - (-0.31362f - (p3 * 0.15681f)) * c1 - ((0.01924f - (p3 * 4.49038f)) * (c2))); @@ -624,7 +654,7 @@ void Ciecam02::calculate_abfloat( float &aa, float &bb, float h, float e, float bb = (aa * sinh) / cosh; if (swapValues) { - std::swap(aa,bb); + std::swap(aa, bb); } } #else @@ -638,9 +668,9 @@ void Ciecam02::calculate_abfloat( vfloat &aa, vfloat &bb, vfloat h, vfloat e, vf vmask swapMask = vmaskf_gt(vabsf(sinh), vabsf(cosh)); vswap(swapMask, sinh, cosh); vfloat c1 = F2V(1.f); - vfloat c2 = sinh/cosh; + vfloat c2 = sinh / cosh; vswap(swapMask, c1, c2); - + vfloat div = ((e / (t * cosh)) - (F2V(-0.31362f) - (p3 * F2V(0.15681f))) * c1 - ((F2V(0.01924f) - (p3 * F2V(4.49038f))) * (c2))); // for large values of t the above calculation can change its sign which results in a hue shift of 180 degree // so we have to check the sign to avoid this shift. @@ -663,16 +693,25 @@ void Ciecam02::initcam1(double gamu, double yb, double pilotd, double f, double double &cz, double &aw, double &wh, double &pfl, double &fl, double &c) { n = yb / yw; - if (pilotd==2.0) { d = d_factor( f, la ); } - else { d=pilotd; } + + if (pilotd == 2.0) { + d = d_factor( f, la ); + } else { + d = pilotd; + } + fl = calculate_fl_from_la_ciecam02( la ); nbb = ncb = 0.725 * pow( 1.0 / n, 0.2 ); cz = 1.48 + sqrt( n ); aw = achromatic_response_to_white( xw, yw, zw, d, fl, nbb, gamu ); - wh =( 4.0 / c ) * ( aw + 4.0 ) * pow( fl, 0.25 ); + wh = ( 4.0 / c ) * ( aw + 4.0 ) * pow( fl, 0.25 ); pfl = pow( fl, 0.25 ); #ifdef _DEBUG - if (settings->verbose) { printf("Source double d=%f aw=%f fl=%f wh=%f\n",d,aw,fl,wh); } + + if (settings->verbose) { + printf("Source double d=%f aw=%f fl=%f wh=%f\n", d, aw, fl, wh); + } + #endif } @@ -680,16 +719,25 @@ void Ciecam02::initcam1float(float gamu, float yb, float pilotd, float f, float float &cz, float &aw, float &wh, float &pfl, float &fl, float &c) { n = yb / yw; - if (pilotd==2.0) { d = d_factorfloat( f, la ); } - else { d=pilotd; } + + if (pilotd == 2.0) { + d = d_factorfloat( f, la ); + } else { + d = pilotd; + } + fl = calculate_fl_from_la_ciecam02float( la ); nbb = ncb = 0.725f * pow_F( 1.0f / n, 0.2f ); cz = 1.48f + sqrt( n ); aw = achromatic_response_to_whitefloat( xw, yw, zw, d, fl, nbb, gamu ); - wh =( 4.0f / c ) * ( aw + 4.0f ) * pow_F( fl, 0.25f ); + wh = ( 4.0f / c ) * ( aw + 4.0f ) * pow_F( fl, 0.25f ); pfl = pow_F( fl, 0.25f ); #ifdef _DEBUG - if (settings->verbose) { printf("Source float d=%f aw=%f fl=%f wh=%f c=%f awc=%f\n",d,aw,fl,wh,c,(4.f/c)*(aw+4.f)); } + + if (settings->verbose) { + printf("Source float d=%f aw=%f fl=%f wh=%f c=%f awc=%f\n", d, aw, fl, wh, c, (4.f / c) * (aw + 4.f)); + } + #endif } @@ -703,7 +751,11 @@ void Ciecam02::initcam2(double gamu, double yb, double f, double la, double xw, cz = 1.48 + sqrt( n ); aw = achromatic_response_to_white( xw, yw, zw, d, fl, nbb, gamu ); #ifdef _DEBUG - if (settings->verbose) { printf("Viewing double d=%f aw=%f fl=%f n=%f\n",d,aw,fl,n); } + + if (settings->verbose) { + printf("Viewing double d=%f aw=%f fl=%f n=%f\n", d, aw, fl, n); + } + #endif } @@ -717,11 +769,15 @@ void Ciecam02::initcam2float(float gamu, float yb, float f, float la, float xw, cz = 1.48f + sqrt( n ); aw = achromatic_response_to_whitefloat( xw, yw, zw, d, fl, nbb, gamu ); #ifdef _DEBUG - if (settings->verbose) { printf("Viewing float d=%f aw=%f fl=%f n=%f\n",d,aw,fl,n); } + + if (settings->verbose) { + printf("Viewing float d=%f aw=%f fl=%f n=%f\n", d, aw, fl, n); + } + #endif } -void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, double &M, double &s,double &aw, double &fl, double &wh, +void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, double &M, double &s, double &aw, double &fl, double &wh, double x, double y, double z, double xw, double yw, double zw, double yb, double la, double f, double c, double nc, double pilotd, int gamu , double n, double nbb, double ncb, double pfl, double cz, double d) { @@ -733,7 +789,7 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, double a, ca, cb; double e, t; double myh; - gamu=1; + gamu = 1; xyz_to_cat02( r, g, b, x, y, z, gamu ); xyz_to_cat02( rw, gw, bw, xw, yw, zw, gamu ); rc = r * (((yw * d) / rw) + (1.0 - d)); @@ -741,11 +797,13 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, bc = b * (((yw * d) / bw) + (1.0 - d)); cat02_to_hpe( rp, gp, bp, rc, gc, bc, gamu ); - if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk - rp=MAXR(rp,0.0); - gp=MAXR(gp,0.0); - bp=MAXR(bp,0.0); + + if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk + rp = MAXR(rp, 0.0); + gp = MAXR(gp, 0.0); + bp = MAXR(bp, 0.0); } + rpa = nonlinear_adaptation( rp, fl ); gpa = nonlinear_adaptation( gp, fl ); bpa = nonlinear_adaptation( bp, fl ); @@ -754,7 +812,11 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, cb = (1.0 / 9.0) * (rpa + gpa - (2.0 * bpa)); myh = (180.0 / M_PI) * atan2( cb, ca ); - if ( myh < 0.0 ) { myh += 360.0; } + + if ( myh < 0.0 ) { + myh += 360.0; + } + //we can also calculate H, if necessary...but it's using time...for what usage ? /*double temp; if(myh<20.14) { @@ -779,7 +841,11 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, } */ a = ((2.0 * rpa) + gpa + ((1.0 / 20.0) * bpa) - 0.305) * nbb; - if (gamu==1) { a=MAXR(a,0.0); }//gamut correction M.H.Brill S.Susstrunk + + if (gamu == 1) { + a = MAXR(a, 0.0); //gamut correction M.H.Brill S.Susstrunk + } + J = 100.0 * pow( a / aw, c * cz ); e = ((12500.0 / 13.0) * nc * ncb) * (cos( ((myh * M_PI) / 180.0) + 2.0 ) + 3.8); @@ -794,7 +860,7 @@ void Ciecam02::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, h = myh; } -void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, float &M, float &s,float &aw, float &fl, float &wh, +void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, float &M, float &s, float &aw, float &fl, float &wh, float x, float y, float z, float xw, float yw, float zw, float yb, float la, float f, float c, float nc, float pilotd, int gamu, float pow1, float nbb, float ncb, float pfl, float cz, float d) @@ -807,7 +873,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, float a, ca, cb; float e, t; float myh; - gamu=1; + gamu = 1; xyz_to_cat02float( r, g, b, x, y, z, gamu ); xyz_to_cat02float( rw, gw, bw, xw, yw, zw, gamu ); rc = r * (((yw * d) / rw) + (1.0 - d)); @@ -815,11 +881,13 @@ void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, bc = b * (((yw * d) / bw) + (1.0 - d)); cat02_to_hpefloat( rp, gp, bp, rc, gc, bc, gamu ); - if (gamu==1) { //gamut correction M.H.Brill S.Susstrunk - rp=MAXR(rp,0.0f); - gp=MAXR(gp,0.0f); - bp=MAXR(bp,0.0f); + + if (gamu == 1) { //gamut correction M.H.Brill S.Susstrunk + rp = MAXR(rp, 0.0f); + gp = MAXR(gp, 0.0f); + bp = MAXR(bp, 0.0f); } + rpa = nonlinear_adaptationfloat( rp, fl ); gpa = nonlinear_adaptationfloat( gp, fl ); bpa = nonlinear_adaptationfloat( bp, fl ); @@ -828,13 +896,15 @@ void Ciecam02::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q, cb = (0.11111111f) * (rpa + gpa - (2.0f * bpa)); myh = xatan2f( cb, ca ); + if ( myh < 0.0f ) { myh += (2.f * M_PI); } a = ((2.0f * rpa) + gpa + (0.05f * bpa) - 0.305f) * nbb; - if (gamu==1) { - a=MAXR(a,0.0f); //gamut correction M.H.Brill S.Susstrunk + + if (gamu == 1) { + a = MAXR(a, 0.0f); //gamut correction M.H.Brill S.Susstrunk } J = pow_F( a / aw, c * cz * 0.5f); @@ -874,9 +944,9 @@ void Ciecam02::xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, vfloat cat02_to_hpefloat( rp, gp, bp, rc, gc, bc); //gamut correction M.H.Brill S.Susstrunk - rp = _mm_max_ps(rp,ZEROV); - gp = _mm_max_ps(gp,ZEROV); - bp = _mm_max_ps(bp,ZEROV); + rp = _mm_max_ps(rp, ZEROV); + gp = _mm_max_ps(gp, ZEROV); + bp = _mm_max_ps(bp, ZEROV); rpa = nonlinear_adaptationfloat( rp, fl ); gpa = nonlinear_adaptationfloat( gp, fl ); bpa = nonlinear_adaptationfloat( bp, fl ); @@ -891,7 +961,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, vfloat myh = vself(vmaskf_lt(myh, ZEROV), temp, myh); a = ((rpa + rpa) + gpa + (F2V(0.05f) * bpa) - F2V(0.305f)) * nbb; - a = _mm_max_ps(a,ZEROV); //gamut correction M.H.Brill S.Susstrunk + a = _mm_max_ps(a, ZEROV); //gamut correction M.H.Brill S.Susstrunk J = pow_F( a / aw, c * cz * F2V(0.5f)); @@ -903,7 +973,7 @@ void Ciecam02::xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, vfloat Q = wh * J; J *= J * F2V(100.0f); M = C * pfl; - Q = _mm_max_ps(Q,F2V(0.0001f)); // avoid division by zero + Q = _mm_max_ps(Q, F2V(0.0001f)); // avoid division by zero s = F2V(100.0f) * _mm_sqrt_ps( M / Q ); h = (myh * F2V(180.f)) / F2V(M_PI); } @@ -920,7 +990,7 @@ void Ciecam02::jch2xyz_ciecam02( double &x, double &y, double &z, double J, doub double rw, gw, bw; double a, ca, cb; double e, t; - gamu=1; + gamu = 1; xyz_to_cat02( rw, gw, bw, xw, yw, zw, gamu ); e = ((12500.0 / 13.0) * nc * ncb) * (cos( ((h * M_PI) / 180.0) + 2.0 ) + 3.8); a = pow( J / 100.0, 1.0 / (c * cz) ) * aw; @@ -954,7 +1024,7 @@ void Ciecam02::jch2xyz_ciecam02float( float &x, float &y, float &z, float J, flo float rw, gw, bw; float a, ca, cb; float e, t; - gamu=1; + gamu = 1; xyz_to_cat02float( rw, gw, bw, xw, yw, zw, gamu ); e = ((961.53846f) * nc * ncb) * (xcosf( ((h * M_PI) / 180.0f) + 2.0f ) + 3.8f); a = pow_F( J / 100.0f, 1.0f / (c * cz) ) * aw; @@ -1015,15 +1085,27 @@ void Ciecam02::jch2xyz_ciecam02float( vfloat &x, vfloat &y, vfloat &z, vfloat J, double Ciecam02::nonlinear_adaptation( double c, double fl ) { double p; - if (c<0.0) { p = pow( (-1.0*fl * c) / 100.0, 0.42 ); return ((-1.0*400.0 * p) / (27.13 + p)) + 0.1;} - else {p = pow( (fl * c) / 100.0, 0.42 ); return ((400.0 * p) / (27.13 + p)) + 0.1;} + + if (c < 0.0) { + p = pow( (-1.0 * fl * c) / 100.0, 0.42 ); + return ((-1.0 * 400.0 * p) / (27.13 + p)) + 0.1; + } else { + p = pow( (fl * c) / 100.0, 0.42 ); + return ((400.0 * p) / (27.13 + p)) + 0.1; + } } float Ciecam02::nonlinear_adaptationfloat( float c, float fl ) { float p; - if (c<0.0f) { p = pow_F( (-1.0f*fl * c) / 100.0f, 0.42f ); return ((-1.0f*400.0f * p) / (27.13f + p)) + 0.1f;} - else {p = pow_F( (fl * c) / 100.0f, 0.42f ); return ((400.0f * p) / (27.13f + p)) + 0.1f;} + + if (c < 0.0f) { + p = pow_F( (-1.0f * fl * c) / 100.0f, 0.42f ); + return ((-1.0f * 400.0f * p) / (27.13f + p)) + 0.1f; + } else { + p = pow_F( (fl * c) / 100.0f, 0.42f ); + return ((400.0f * p) / (27.13f + p)) + 0.1f; + } } #ifdef __SSE2__ @@ -1031,8 +1113,8 @@ vfloat Ciecam02::nonlinear_adaptationfloat( vfloat c, vfloat fl ) { vfloat c100 = F2V(100.f); vfloat czd42 = F2V(0.42f); - vfloat c400 = vmulsignf(F2V(400.f),c); - fl = vmulsignf(fl,c); + vfloat c400 = vmulsignf(F2V(400.f), c); + fl = vmulsignf(fl, c); vfloat p = pow_F( (fl * c) / c100, czd42 ); vfloat c27d13 = F2V(27.13); vfloat czd1 = F2V(0.1f); @@ -1043,23 +1125,31 @@ vfloat Ciecam02::nonlinear_adaptationfloat( vfloat c, vfloat fl ) double Ciecam02::inverse_nonlinear_adaptation( double c, double fl ) { int c1; - if (c-0.1 < 0.0) { c1=-1; } - else { c1=1; } - return c1*(100.0 / fl) * pow( (27.13 * fabs( c - 0.1 )) / (400.0 - fabs( c - 0.1 )), 1.0 / 0.42 ); + + if (c - 0.1 < 0.0) { + c1 = -1; + } else { + c1 = 1; + } + + return c1 * (100.0 / fl) * pow( (27.13 * fabs( c - 0.1 )) / (400.0 - fabs( c - 0.1 )), 1.0 / 0.42 ); } #ifndef __SSE2__ float Ciecam02::inverse_nonlinear_adaptationfloat( float c, float fl ) { c -= 0.1f; + if (c < 0.f) { fl *= -1.f; + if (c < -399.99f) { // avoid nan values c = -399.99f; } } else if (c > 399.99f) { // avoid nan values c = 399.99f; } + return (100.0f / fl) * pow_F( (27.13f * fabsf( c )) / (400.0f - fabsf( c )), 2.38095238f ); } @@ -1067,7 +1157,7 @@ float Ciecam02::inverse_nonlinear_adaptationfloat( float c, float fl ) vfloat Ciecam02::inverse_nonlinear_adaptationfloat( vfloat c, vfloat fl ) { c -= F2V(0.1f); - fl = vmulsignf(fl,c); + fl = vmulsignf(fl, c); c = vabsf(c); c = _mm_min_ps( c, F2V(399.99f)); return (F2V(100.0f) / fl) * pow_F( (F2V(27.13f) * c) / (F2V(400.0f) - c), F2V(2.38095238f) ); diff --git a/rtengine/ciecam02.h b/rtengine/ciecam02.h index c3dd0c745..b598f4678 100644 --- a/rtengine/ciecam02.h +++ b/rtengine/ciecam02.h @@ -90,7 +90,7 @@ public: float J, float C, float h, float xw, float yw, float zw, float yb, float la, - float f, float c, float nc,int gamu,float n, float nbb, float ncb, float fl, float cz, float d, float aw ); + float f, float c, float nc, int gamu, float n, float nbb, float ncb, float fl, float cz, float d, float aw ); #else static void jch2xyz_ciecam02float( vfloat &x, vfloat &y, vfloat &z, vfloat J, vfloat C, vfloat h, @@ -114,14 +114,14 @@ public: float &cz, float &aw, float &fl); static void xyz2jchqms_ciecam02( double &J, double &C, double &h, - double &Q, double &M, double &s,double &aw, double &fl, double &wh, + double &Q, double &M, double &s, double &aw, double &fl, double &wh, double x, double y, double z, double xw, double yw, double zw, double yb, double la, - double f, double c, double nc, double pilotd,int gamu , double n, double nbb, double ncb, double pfl, double cz, double d ); + double f, double c, double nc, double pilotd, int gamu , double n, double nbb, double ncb, double pfl, double cz, double d ); static void xyz2jchqms_ciecam02float( float &J, float &C, float &h, - float &Q, float &M, float &s,float &aw, float &fl, float &wh, + float &Q, float &M, float &s, float &aw, float &fl, float &wh, float x, float y, float z, float xw, float yw, float zw, float yb, float la, @@ -129,7 +129,7 @@ public: #ifdef __SSE2__ static void xyz2jchqms_ciecam02float( vfloat &J, vfloat &C, vfloat &h, - vfloat &Q, vfloat &M, vfloat &s,vfloat aw, vfloat fl, vfloat wh, + vfloat &Q, vfloat &M, vfloat &s, vfloat aw, vfloat fl, vfloat wh, vfloat x, vfloat y, vfloat z, vfloat xw, vfloat yw, vfloat zw, vfloat yb, vfloat la, diff --git a/rtengine/cieimage.cc b/rtengine/cieimage.cc index ae66f92b8..87954e1f0 100644 --- a/rtengine/cieimage.cc +++ b/rtengine/cieimage.cc @@ -1,76 +1,114 @@ #include "cieimage.h" #include -namespace rtengine { +namespace rtengine +{ -CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) { +CieImage::CieImage (int w, int h) : fromImage(false), W(w), H(h) +{ J_p = new float*[H]; Q_p = new float*[H]; M_p = new float*[H]; C_p = new float*[H]; sh_p = new float*[H]; - // ch_p = new float*[H]; + // ch_p = new float*[H]; h_p = new float*[H]; // Initialize the pointers to zero - for (unsigned int c=0; c<6; ++c) + for (unsigned int c = 0; c < 6; ++c) { data[c] = NULL; + } // Trying to allocate all in one block - data[0] = new (std::nothrow) float [W*H*6]; + data[0] = new (std::nothrow) float [W * H * 6]; if (data[0]) { float * index = data[0]; - for (int i=0; idata, W*H*6*sizeof(float)); - else + { + memcpy(data, Img->data, W * H * 6 * sizeof(float)); + } else + // Separate allocation - for (unsigned int c=0; c<6; ++c) - memcpy(data[c], Img->data[c], W*H*sizeof(float)); + for (unsigned int c = 0; c < 6; ++c) { + memcpy(data[c], Img->data[c], W * H * sizeof(float)); + } } } diff --git a/rtengine/cieimage.h b/rtengine/cieimage.h index 0688ad053..a97622325 100644 --- a/rtengine/cieimage.h +++ b/rtengine/cieimage.h @@ -21,28 +21,30 @@ #include "image16.h" -namespace rtengine { +namespace rtengine +{ -class CieImage { +class CieImage +{ private: - bool fromImage; + bool fromImage; public: - int W, H; - float * data[6]; - float** J_p; - float** Q_p; - float** M_p; - float** C_p; - float** sh_p; -// float** ch_p; - float** h_p; + int W, H; + float * data[6]; + float** J_p; + float** Q_p; + float** M_p; + float** C_p; + float** sh_p; +// float** ch_p; + float** h_p; - CieImage (int w, int h); - ~CieImage (); + CieImage (int w, int h); + ~CieImage (); - //Copies image data in Img into this instance. - void CopyFrom(CieImage *Img); + //Copies image data in Img into this instance. + void CopyFrom(CieImage *Img); }; } diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc index c43bc8138..b36fd7dfb 100644 --- a/rtengine/clutstore.cc +++ b/rtengine/clutstore.cc @@ -17,27 +17,32 @@ CLUTStore::CLUTStore() CLUT* CLUTStore::getClut( const Glib::ustring& filename ) { CLUT *result = 0; - m_mutex.lock(); - Cluts::iterator cluts_it = m_cluts.find(filename); - if (cluts_it == m_cluts.end()) { - if (m_cluts.size() >= options.clutCacheSize) { - // Evict a "random" entry from cache - Cluts::iterator victim_it = m_cluts.begin(); - if (--victim_it->second.first == -1) { - delete victim_it->second.second; - m_cluts.erase(victim_it); - } - } - cluts_it = m_cluts.insert(std::make_pair(filename, std::make_pair(0, new HaldCLUT))).first; - cluts_it->second.second->load( filename ); + m_mutex.lock(); + Cluts::iterator cluts_it = m_cluts.find(filename); + + if (cluts_it == m_cluts.end()) { + if (m_cluts.size() >= options.clutCacheSize) { + // Evict a "random" entry from cache + Cluts::iterator victim_it = m_cluts.begin(); + + if (--victim_it->second.first == -1) { + delete victim_it->second.second; + m_cluts.erase(victim_it); + } + } + + cluts_it = m_cluts.insert(std::make_pair(filename, std::make_pair(0, new HaldCLUT))).first; + cluts_it->second.second->load( filename ); } + if (cluts_it->second.second->isValid()) { result = cluts_it->second.second; ++cluts_it->second.first; } else { - delete cluts_it->second.second; - m_cluts.erase(cluts_it); - } + delete cluts_it->second.second; + m_cluts.erase(cluts_it); + } + m_mutex.unlock(); return result; @@ -45,33 +50,38 @@ CLUT* CLUTStore::getClut( const Glib::ustring& filename ) void CLUTStore::releaseClut( const CLUT* clut ) { - m_mutex.lock(); - for (Cluts::iterator cluts_it = m_cluts.begin(); cluts_it != m_cluts.end(); ++cluts_it) { - if (cluts_it->second.second == clut) { - if (--cluts_it->second.first == -1) { - delete cluts_it->second.second; - m_cluts.erase(cluts_it); - } - break; - } - } - m_mutex.unlock(); + m_mutex.lock(); + + for (Cluts::iterator cluts_it = m_cluts.begin(); cluts_it != m_cluts.end(); ++cluts_it) { + if (cluts_it->second.second == clut) { + if (--cluts_it->second.first == -1) { + delete cluts_it->second.second; + m_cluts.erase(cluts_it); + } + + break; + } + } + + m_mutex.unlock(); } void CLUTStore::clearCache() { - m_mutex.lock(); - for (Cluts::iterator cluts_it = m_cluts.begin(); cluts_it != m_cluts.end();) { - if (--cluts_it->second.first == -1) { - delete cluts_it->second.second; - Cluts::iterator tmp = cluts_it; - ++cluts_it; - m_cluts.erase(tmp); - } else { - ++cluts_it; - } - } - m_mutex.unlock(); + m_mutex.lock(); + + for (Cluts::iterator cluts_it = m_cluts.begin(); cluts_it != m_cluts.end();) { + if (--cluts_it->second.first == -1) { + delete cluts_it->second.second; + Cluts::iterator tmp = cluts_it; + ++cluts_it; + m_cluts.erase(tmp); + } else { + ++cluts_it; + } + } + + m_mutex.unlock(); } void rtengine::splitClutFilename( Glib::ustring filename, Glib::ustring &name, Glib::ustring &extension, Glib::ustring &profileName ) @@ -80,11 +90,13 @@ void rtengine::splitClutFilename( Glib::ustring filename, Glib::ustring &name, G name = filename; //remove dirs size_t lastSlashPos = filename.find_last_of( "/" ); + if ( lastSlashPos == Glib::ustring::npos ) { lastSlashPos = filename.find_last_of( "\\" ); } size_t lastDotPos = filename.find_last_of( '.' ); + if ( lastDotPos != Glib::ustring::npos ) { name = filename.substr( 0, lastDotPos ); extension = filename.substr( lastDotPos + 1, Glib::ustring::npos ); @@ -92,8 +104,10 @@ void rtengine::splitClutFilename( Glib::ustring filename, Glib::ustring &name, G profileName = "sRGB"; // sRGB by default static std::vector workingProfiles = rtengine::getWorkingProfiles(); + for ( std::vector::iterator it = workingProfiles.begin(); it != workingProfiles.end(); ++it ) { Glib::ustring ¤tProfile = *it; + if ( std::search( name.rbegin(), name.rend(), currentProfile.rbegin(), currentProfile.rend() ) == name.rbegin() ) { profileName = currentProfile; name = name.substr( 0, name.size() - currentProfile.size() ); @@ -105,9 +119,9 @@ void rtengine::splitClutFilename( Glib::ustring filename, Glib::ustring &name, G //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: HaldCLUT::HaldCLUT() -: m_clutImage( 0 ), - m_level (0), - m_profile( "sRGB" ) + : m_clutImage( 0 ), + m_level (0), + m_profile( "sRGB" ) { } @@ -121,12 +135,13 @@ HaldCLUT::~HaldCLUT() void HaldCLUT::load( Glib::ustring filename ) { - m_clutImage = loadFile( filename, "", m_level ); - Glib::ustring name, ext; - splitClutFilename( filename, name, ext, m_profile ); - if ( m_clutImage ) { - m_filename = filename; - } + m_clutImage = loadFile( filename, "", m_level ); + Glib::ustring name, ext; + splitClutFilename( filename, name, ext, m_profile ); + + if ( m_clutImage ) { + m_filename = filename; + } } Glib::ustring HaldCLUT::profile() const @@ -138,6 +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) ) { return result; } @@ -146,10 +162,13 @@ Imagefloat* HaldCLUT::loadFile( Glib::ustring filename, Glib::ustring workingCol imgSrc.getFullSize (fw, fh, TR_NONE); bool valid = false; + //test on Hald format, copypasted from http://www.quelsolaar.com/technology/clut.html if ( fw == fh ) { outLevel = 1; + for(; outLevel * outLevel * outLevel < fw; outLevel++); + if( !( outLevel * outLevel * outLevel > fw ) ) { valid = true; } @@ -164,12 +183,15 @@ Imagefloat* HaldCLUT::loadFile( Glib::ustring filename, Glib::ustring workingCol icm.working = workingColorSpace; imgSrc.getImage (currWB, TR_NONE, baseImg, pp, procparams::ToneCurveParams(), icm, procparams::RAWParams()); + if ( !workingColorSpace.empty() ) { imgSrc.convertColorSpace(baseImg, icm, currWB); } + result = baseImg; } - return result; + + return result; } void HaldCLUT::loadClut( Imagefloat *img, RawClut &outClut ) @@ -179,6 +201,7 @@ void HaldCLUT::loadClut( Imagefloat *img, RawClut &outClut ) int x_size = img->getW(); outClut.resize( x_size * y_size * 3 ); int clutIdx = 0; + //int level = m_level * m_level; (unused) for(int y = 0; y < y_size; y++) { for(int x = 0; x < x_size; x++) { @@ -195,10 +218,11 @@ Imagefloat* HaldCLUT::generateIdentImage( int level ) { int imageWidth = level * level * level; Imagefloat *resultImg = new Imagefloat( imageWidth, imageWidth ); - + int cubeSideSize = level * level; float step = MAXVALF / (cubeSideSize - 1); int pos = 0; + for( int b = 0; b < cubeSideSize; ++b ) { for ( int g = 0; g < cubeSideSize; ++g ) { for ( int r = 0; r < cubeSideSize; ++r ) { @@ -211,6 +235,7 @@ Imagefloat* HaldCLUT::generateIdentImage( int level ) } } } + return resultImg; } @@ -241,22 +266,34 @@ void HaldCLUT::correct( const HaldCLUT::RawClut& clut, int level, float rr, floa level = level * level; red = rr * (float)(level - 1); - if(red > level - 2) + + if(red > level - 2) { red = (float)level - 2; - if(red < 0) + } + + if(red < 0) { red = 0; + } green = gg * (float)(level - 1); - if(green > level - 2) + + if(green > level - 2) { green = (float)level - 2; - if(green < 0) + } + + if(green < 0) { green = 0; + } blue = bb * (float)(level - 1); - if(blue > level - 2) + + if(blue > level - 2) { blue = (float)level - 2; - if(blue < 0) + } + + if(blue < 0) { blue = 0; + } r = rr * (float)(level - 1) - red; g = gg * (float)(level - 1) - green; @@ -319,22 +356,34 @@ void HaldCLUT::correct( Imagefloat &clutImage, int level, float rr, float gg, fl int imageSideSize = clutImage.getW(); red = rr * (float)(level - 1); - if(red > level - 2) + + if(red > level - 2) { red = (float)level - 2; - if(red < 0) + } + + if(red < 0) { red = 0; + } green = gg * (float)(level - 1); - if(green > level - 2) + + if(green > level - 2) { green = (float)level - 2; - if(green < 0) + } + + if(green < 0) { green = 0; + } blue = bb * (float)(level - 1); - if(blue > level - 2) + + if(blue > level - 2) { blue = (float)level - 2; - if(blue < 0) + } + + if(blue < 0) { blue = 0; + } r = rr * (float)(level - 1) - red; g = gg * (float)(level - 1) - green; diff --git a/rtengine/clutstore.h b/rtengine/clutstore.h index 679c8531c..de080b737 100644 --- a/rtengine/clutstore.h +++ b/rtengine/clutstore.h @@ -7,7 +7,8 @@ #include #include -namespace rtengine { +namespace rtengine +{ // simple CLUT interface class CLUT @@ -37,9 +38,9 @@ public: static Imagefloat* loadFile( Glib::ustring filename, Glib::ustring workingColorSpace, int &outLevel ); private: - + void loadClut( Imagefloat *img, RawClut &outClut ); - + Imagefloat *m_clutImage; int m_level; Glib::ustring m_filename; @@ -51,26 +52,27 @@ class CLUTStore { public: CLUTStore(); - + CLUT* getClut( const Glib::ustring& filename ); void releaseClut( const CLUT* clut ); - void clearCache(); + void clearCache(); private: - typedef std::map > Cluts; - - Cluts m_cluts; + typedef std::map > Cluts; + + Cluts m_cluts; MyMutex m_mutex; }; void splitClutFilename( Glib::ustring filename, Glib::ustring &name, Glib::ustring &extension, Glib::ustring &profileName ); -}; //namespace rtengine +}; //namespace rtengine extern rtengine::CLUTStore clutStore; -namespace rtengine { +namespace rtengine +{ //support class for automate call of clutStore.releaseClut() class ClutPtr @@ -78,16 +80,28 @@ class ClutPtr public: ClutPtr() : m_point( 0 ) {} explicit ClutPtr(CLUT *p) : m_point( p ) {} - ~ClutPtr() { clutStore.releaseClut( m_point ); } - const CLUT* operator-> () const { return m_point; } - operator bool() const { return m_point != 0; } - void set( CLUT *p ) { m_point = p; } + ~ClutPtr() + { + clutStore.releaseClut( m_point ); + } + const CLUT* operator-> () const + { + return m_point; + } + operator bool() const + { + return m_point != 0; + } + void set( CLUT *p ) + { + m_point = p; + } private: ClutPtr& operator=(ClutPtr const& cp ); CLUT *m_point; }; -}; //namespace rtengine +}; //namespace rtengine #endif diff --git a/rtengine/color.cc b/rtengine/color.cc index 476c369cb..c2bdcc9dd 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -26,1993 +26,3633 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ - extern const Settings* settings; - - cmsToneCurve* Color::linearGammaTRC; - LUTf Color::cachef; - LUTf Color::gamma2curve; +extern const Settings* settings; - LUTf Color::gammatab; - LUTf Color::igammatab_srgb; - LUTf Color::gammatab_srgb; - // LUTf Color::igammatab_709; -// LUTf Color::gammatab_709; - LUTf Color::igammatab_55; - LUTf Color::gammatab_55; - LUTf Color::igammatab_4; - LUTf Color::gammatab_4; - - LUTf Color::igammatab_26_11; - LUTf Color::gammatab_26_11; - LUTf Color::igammatab_24_17; - LUTf Color::gammatab_24_17a; - LUTf Color::gammatab_13_2; +cmsToneCurve* Color::linearGammaTRC; +LUTf Color::cachef; +LUTf Color::gamma2curve; - // Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. - // The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent - // and a gamma (slope of log output versus log input) changing from 1.0 through about 2.3. - const double Color::sRGBGamma = 2.2; - const double Color::sRGBGammaCurve = 2.4; +LUTf Color::gammatab; +LUTf Color::igammatab_srgb; +LUTf Color::gammatab_srgb; +// LUTf Color::igammatab_709; +// LUTf Color::gammatab_709; +LUTf Color::igammatab_55; +LUTf Color::gammatab_55; +LUTf Color::igammatab_4; +LUTf Color::gammatab_4; - const double Color::eps_max=580.40756; //(MAXVALF* 216.0f/24389.0); - const double Color::eps=216.0f/24389.0;//0.008856 - const double Color::kappa=24389.0/27.0;//903.29630; +LUTf Color::igammatab_26_11; +LUTf Color::gammatab_26_11; +LUTf Color::igammatab_24_17; +LUTf Color::gammatab_24_17a; +LUTf Color::gammatab_13_2; - const float Color::D50x=0.9642f; //0.96422; - const float Color::D50z=0.8249f; //0.82521; - const double Color::u0=4.0*D50x/(D50x+15+3*D50z); - const double Color::v0=9.0/(D50x+15+3*D50z); - const double Color::epskap=8.0; - /* - * Munsell Lch correction - * Copyright (c) 2011 Jacques Desmis +// Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. +// The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent +// and a gamma (slope of log output versus log input) changing from 1.0 through about 2.3. +const double Color::sRGBGamma = 2.2; +const double Color::sRGBGammaCurve = 2.4; + +const double Color::eps_max = 580.40756; //(MAXVALF* 216.0f/24389.0); +const double Color::eps = 216.0f / 24389.0; //0.008856 +const double Color::kappa = 24389.0 / 27.0; //903.29630; + +const float Color::D50x = 0.9642f; //0.96422; +const float Color::D50z = 0.8249f; //0.82521; +const double Color::u0 = 4.0 * D50x / (D50x + 15 + 3 * D50z); +const double Color::v0 = 9.0 / (D50x + 15 + 3 * D50z); +const double Color::epskap = 8.0; +/* + * Munsell Lch correction + * Copyright (c) 2011 Jacques Desmis +*/ +// Munsell Lch LUTf : 195 LUT +// about 70% data are corrected with significative corrections +// almost all data are taken for BG, YR, G excepted a few extreme values with a slight correction +// No LUTf for BG and Y : low corrections +// Only between 5B and 5PB for L > 40 : under very low corrections for L < 40 + +//give hue in function of L and C : Munsell correction +LUTf Color::_4P10, Color::_4P20, Color::_4P30, Color::_4P40, Color::_4P50, Color::_4P60; +LUTf Color::_1P10, Color::_1P20, Color::_1P30, Color::_1P40, Color::_1P50, Color::_1P60; +LUTf Color::_10PB10, Color::_10PB20, Color::_10PB30, Color::_10PB40, Color::_10PB50, Color::_10PB60; +LUTf Color::_9PB10, Color::_9PB20, Color::_9PB30, Color::_9PB40, Color::_9PB50, Color::_9PB60, Color::_9PB70, Color::_9PB80; +LUTf Color::_75PB10, Color::_75PB20, Color::_75PB30, Color::_75PB40, Color::_75PB50, Color::_75PB60, Color::_75PB70, Color::_75PB80; +LUTf Color::_6PB10, Color::_6PB20, Color::_6PB30, Color::_6PB40, Color::_6PB50, Color::_6PB60, Color::_6PB70, Color::_6PB80; +LUTf Color::_45PB10, Color::_45PB20, Color::_45PB30, Color::_45PB40, Color::_45PB50, Color::_45PB60, Color::_45PB70, Color::_45PB80; +LUTf Color::_3PB10, Color::_3PB20, Color::_3PB30, Color::_3PB40, Color::_3PB50, Color::_3PB60, Color::_3PB70, Color::_3PB80; +LUTf Color::_15PB10, Color::_15PB20, Color::_15PB30, Color::_15PB40, Color::_15PB50, Color::_15PB60, Color::_15PB70, Color::_15PB80; +LUTf Color::_05PB40, Color::_05PB50, Color::_05PB60, Color::_05PB70, Color::_05PB80; +LUTf Color::_10B40, Color::_10B50, Color::_10B60, Color::_10B70, Color::_10B80; +LUTf Color::_9B40, Color::_9B50, Color::_9B60, Color::_9B70, Color::_9B80; +LUTf Color::_7B40, Color::_7B50, Color::_7B60, Color::_7B70, Color::_7B80; +LUTf Color::_5B40, Color::_5B50, Color::_5B60, Color::_5B70, Color::_5B80; +LUTf Color::_10YR20, Color::_10YR30, Color::_10YR40, Color::_10YR50, Color::_10YR60, Color::_10YR70, Color::_10YR80, Color::_10YR90; +LUTf Color::_85YR20, Color::_85YR30, Color::_85YR40, Color::_85YR50, Color::_85YR60, Color::_85YR70, Color::_85YR80, Color::_85YR90; +LUTf Color::_7YR30, Color::_7YR40, Color::_7YR50, Color::_7YR60, Color::_7YR70, Color::_7YR80; +LUTf Color::_55YR30, Color::_55YR40, Color::_55YR50, Color::_55YR60, Color::_55YR70, Color::_55YR80, Color::_55YR90; +LUTf Color::_4YR30, Color::_4YR40, Color::_4YR50, Color::_4YR60, Color::_4YR70, Color::_4YR80; +LUTf Color::_25YR30, Color::_25YR40, Color::_25YR50, Color::_25YR60, Color::_25YR70; +LUTf Color::_10R30, Color::_10R40, Color::_10R50, Color::_10R60, Color::_10R70; +LUTf Color::_9R30, Color::_9R40, Color::_9R50, Color::_9R60, Color::_9R70; +LUTf Color::_7R30, Color::_7R40, Color::_7R50, Color::_7R60, Color::_7R70; +LUTf Color::_5R10, Color::_5R20, Color::_5R30; +LUTf Color::_25R10, Color::_25R20, Color::_25R30; +LUTf Color::_10RP10, Color::_10RP20, Color::_10RP30; +LUTf Color::_7G30, Color::_7G40, Color::_7G50, Color::_7G60, Color::_7G70, Color::_7G80; +LUTf Color::_5G30, Color::_5G40, Color::_5G50, Color::_5G60, Color::_5G70, Color::_5G80; +LUTf Color::_25G30, Color::_25G40, Color::_25G50, Color::_25G60, Color::_25G70, Color::_25G80; +LUTf Color::_1G30, Color::_1G40, Color::_1G50, Color::_1G60, Color::_1G70, Color::_1G80; +LUTf Color::_10GY30, Color::_10GY40, Color::_10GY50, Color::_10GY60, Color::_10GY70, Color::_10GY80; +LUTf Color::_75GY30, Color::_75GY40, Color::_75GY50, Color::_75GY60, Color::_75GY70, Color::_75GY80; +LUTf Color::_5GY30, Color::_5GY40, Color::_5GY50, Color::_5GY60, Color::_5GY70, Color::_5GY80; + +#ifdef _DEBUG +MunsellDebugInfo::MunsellDebugInfo() +{ + reinitValues(); +} +void MunsellDebugInfo::reinitValues() +{ + maxdhue[0] = maxdhue[1] = maxdhue[2] = maxdhue[3] = 0.0f; + maxdhuelum[0] = maxdhuelum[1] = maxdhuelum[2] = maxdhuelum[3] = 0.0f; + depass = depassLum = 0; +} +#endif + + +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); + + 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); + + for (int i = 0; i < 65536; i++) { + gammatab_srgb[i] = (65535.0 * gamma2 (i / 65535.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)); */ - // Munsell Lch LUTf : 195 LUT - // about 70% data are corrected with significative corrections - // almost all data are taken for BG, YR, G excepted a few extreme values with a slight correction - // No LUTf for BG and Y : low corrections - // Only between 5B and 5PB for L > 40 : under very low corrections for L < 40 - - //give hue in function of L and C : Munsell correction - LUTf Color::_4P10, Color::_4P20, Color::_4P30, Color::_4P40, Color::_4P50, Color::_4P60; - LUTf Color::_1P10, Color::_1P20, Color::_1P30, Color::_1P40, Color::_1P50, Color::_1P60; - LUTf Color::_10PB10, Color::_10PB20, Color::_10PB30, Color::_10PB40, Color::_10PB50, Color::_10PB60; - LUTf Color::_9PB10, Color::_9PB20, Color::_9PB30, Color::_9PB40, Color::_9PB50, Color::_9PB60, Color::_9PB70, Color::_9PB80; - LUTf Color::_75PB10, Color::_75PB20, Color::_75PB30, Color::_75PB40, Color::_75PB50, Color::_75PB60, Color::_75PB70, Color::_75PB80; - LUTf Color::_6PB10, Color::_6PB20, Color::_6PB30, Color::_6PB40, Color::_6PB50, Color::_6PB60, Color::_6PB70, Color::_6PB80; - LUTf Color::_45PB10, Color::_45PB20, Color::_45PB30, Color::_45PB40, Color::_45PB50, Color::_45PB60, Color::_45PB70, Color::_45PB80; - LUTf Color::_3PB10, Color::_3PB20, Color::_3PB30, Color::_3PB40, Color::_3PB50, Color::_3PB60, Color::_3PB70, Color::_3PB80; - LUTf Color::_15PB10, Color::_15PB20, Color::_15PB30, Color::_15PB40, Color::_15PB50, Color::_15PB60, Color::_15PB70, Color::_15PB80; - LUTf Color::_05PB40, Color::_05PB50, Color::_05PB60, Color::_05PB70, Color::_05PB80; - LUTf Color::_10B40, Color::_10B50, Color::_10B60, Color::_10B70, Color::_10B80; - LUTf Color::_9B40, Color::_9B50, Color::_9B60, Color::_9B70, Color::_9B80; - LUTf Color::_7B40, Color::_7B50, Color::_7B60, Color::_7B70, Color::_7B80; - LUTf Color::_5B40, Color::_5B50, Color::_5B60, Color::_5B70, Color::_5B80; - LUTf Color::_10YR20, Color::_10YR30, Color::_10YR40, Color::_10YR50, Color::_10YR60, Color::_10YR70, Color::_10YR80, Color::_10YR90; - LUTf Color::_85YR20, Color::_85YR30, Color::_85YR40, Color::_85YR50, Color::_85YR60, Color::_85YR70, Color::_85YR80, Color::_85YR90; - LUTf Color::_7YR30, Color::_7YR40, Color::_7YR50, Color::_7YR60, Color::_7YR70, Color::_7YR80; - LUTf Color::_55YR30, Color::_55YR40, Color::_55YR50, Color::_55YR60, Color::_55YR70, Color::_55YR80, Color::_55YR90; - LUTf Color::_4YR30, Color::_4YR40, Color::_4YR50, Color::_4YR60, Color::_4YR70, Color::_4YR80; - LUTf Color::_25YR30, Color::_25YR40, Color::_25YR50, Color::_25YR60, Color::_25YR70; - LUTf Color::_10R30, Color::_10R40, Color::_10R50, Color::_10R60, Color::_10R70; - LUTf Color::_9R30, Color::_9R40, Color::_9R50, Color::_9R60, Color::_9R70; - LUTf Color::_7R30, Color::_7R40, Color::_7R50, Color::_7R60, Color::_7R70; - LUTf Color::_5R10, Color::_5R20, Color::_5R30; - LUTf Color::_25R10, Color::_25R20, Color::_25R30; - LUTf Color::_10RP10, Color::_10RP20, Color::_10RP30; - LUTf Color::_7G30, Color::_7G40, Color::_7G50, Color::_7G60, Color::_7G70, Color::_7G80; - LUTf Color::_5G30, Color::_5G40, Color::_5G50, Color::_5G60, Color::_5G70, Color::_5G80; - LUTf Color::_25G30, Color::_25G40, Color::_25G50, Color::_25G60, Color::_25G70, Color::_25G80; - LUTf Color::_1G30, Color::_1G40, Color::_1G50, Color::_1G60, Color::_1G70, Color::_1G80; - LUTf Color::_10GY30, Color::_10GY40, Color::_10GY50, Color::_10GY60, Color::_10GY70, Color::_10GY80; - LUTf Color::_75GY30, Color::_75GY40, Color::_75GY50, Color::_75GY60, Color::_75GY70, Color::_75GY80; - LUTf Color::_5GY30, Color::_5GY40, Color::_5GY50, Color::_5GY60, Color::_5GY70, Color::_5GY80; - -#ifdef _DEBUG - MunsellDebugInfo::MunsellDebugInfo() { - reinitValues(); + for (int i = 0; i < 65536; i++) { + gammatab_55[i] = (65535.0 * gamma55 (i / 65535.0)); } - void MunsellDebugInfo::reinitValues() { - maxdhue[0]=maxdhue[1]=maxdhue[2]=maxdhue[3]=0.0f; - maxdhuelum[0]=maxdhuelum[1]=maxdhuelum[2]=maxdhuelum[3]=0.0f; - depass=depassLum=0; - } -#endif + for (int i = 0; i < 65536; i++) { + igammatab_55[i] = (65535.0 * igamma55 (i / 65535.0)); + } - void Color::init () { + for (int i = 0; i < 65536; i++) { + gammatab_4[i] = (65535.0 * gamma4 (i / 65535.0)); + } - int maxindex = 65536; - cachef(maxindex,LUT_CLIP_BELOW); + for (int i = 0; i < 65536; i++) { + igammatab_4[i] = (65535.0 * igamma4 (i / 65535.0)); + } - gamma2curve(maxindex,LUT_CLIP_BELOW|LUT_CLIP_ABOVE); + for (int i = 0; i < 65536; i++) { + gammatab_13_2[i] = (65535.0 * gamma13_2 (i / 65535.0)); + } - for (int i=0; ieps_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 < 65536; i++) { + gammatab_26_11[i] = (65535.0 * gamma26_11 (i / 65535.0)); + } + + for (int i = 0; i < 65536; i++) { + igammatab_26_11[i] = (65535.0 * igamma26_11 (i / 65535.0)); + } + + for (int i = 0; i < 65536; i++) { + float j = (float)i / 65535.0f; + gammatab_24_17a[i] = gamma24_17(j); + } + + for (int i = 0; i < 65536; i++) { + igammatab_24_17[i] = (65535.0 * igamma24_17 (i / 65535.0)); + } + + /*FILE* f = fopen ("c.txt", "wt"); + for (int i=0; i<256; i++) + 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 () +{ + if (linearGammaTRC) { + cmsFreeToneCurve(linearGammaTRC); + } +} + +void Color::rgb2hsl(float r, float g, float b, float &h, float &s, float &l) +{ + + double var_R = double(r) / 65535.0; + double var_G = double(g) / 65535.0; + double var_B = double(b) / 65535.0; + + double m = min(var_R, var_G, var_B); + double M = max(var_R, var_G, var_B); + double C = M - m; + + double l_ = (M + m) / 2.; + l = float(l_); + + if (C < 0.00001 && C > -0.00001) { // no fabs, slow! + h = 0.f; + s = 0.f; + } else { + double h_; + + if (l_ <= 0.5) { + s = float( (M - m) / (M + m) ); + } else { + s = float( (M - m) / (2.0 - M - m) ); } - for (int i=0; i-0.00001) { // no fabs, slow! - h = 0.f; - s = 0.f; - } - else { - double h_; - if (l_ <= 0.5) - s = float( (M-m) / (M+m) ); - else - s = float( (M-m) / (2.0-M-m) ); - - if ( var_R == M ) h_ = (var_G - var_B)/C; - else if ( var_G == M ) h_ = 2. + (var_B - var_R)/C; - else h_ = 4. + (var_R - var_G)/C; - h = float(h_ /= 6.0); - - if ( h < 0.f ) h += 1.f; - if ( h > 1.f ) h -= 1.f; - } - } - - double Color::hue2rgb(double p, double q, double t){ - if (t < 0.) t += 6.; - else if( t > 6.) t -= 6.; - - if (t < 1.) return p + (q - p) * t; - else if (t < 3.) return q; - else if (t < 4.) return p + (q - p) * (4. - t); - else return p; - } - - void Color::hsl2rgb (float h, float s, float l, float &r, float &g, float &b) { - - if (s == 0) - r = g = b = 65535.0f * l; // achromatic - else { - double m2; - double h_ = double(h); - double s_ = double(s); - double l_ = double(l); - - if (l <= 0.5f) - m2 = l_ * (1.0 + s_); - else { - m2 = l_ + s_ - l_ * s_; - } - - double m1 = 2.0 * l_ - m2; - - r = float(65535.0 * hue2rgb (m1, m2, h_ * 6.0 + 2.0)); - g = float(65535.0 * hue2rgb (m1, m2, h_ * 6.0)); - b = float(65535.0 * hue2rgb (m1, m2, h_ * 6.0 - 2.0)); - } - } - - void Color::hsl2rgb01 (float h, float s, float l, float &r, float &g, float &b) { - - if (s == 0) - r = g = b = l; // achromatic - else { - double m2; - double h_ = double(h); - double s_ = double(s); - double l_ = double(l); - - if (l <= 0.5f) - m2 = l_ * (1.0 + s_); - else { - m2 = l_ + s_ - l_ * s_; - } - - double m1 = 2.0 * l_ - m2; - - r = float(hue2rgb (m1, m2, h_ * 6.0 + 2.0)); - g = float(hue2rgb (m1, m2, h_ * 6.0)); - b = float(hue2rgb (m1, m2, h_ * 6.0 - 2.0)); - } - } - - void Color::rgb2hsv(float r, float g, float b, float &h, float &s, float &v) { - double var_R = r / 65535.0; - double var_G = g / 65535.0; - double var_B = b / 65535.0; - - double var_Min = min(var_R,var_G,var_B); - double var_Max = max(var_R,var_G,var_B); - double del_Max = var_Max - var_Min; - v = var_Max; - if (del_Max<0.00001 && del_Max>-0.00001) { // no fabs, slow! - h = 0; - s = 0; - } - else { - s = del_Max/var_Max; - - if ( var_R == var_Max ) h = (var_G - var_B)/del_Max; - else if ( var_G == var_Max ) h = 2.0 + (var_B - var_R)/del_Max; - else if ( var_B == var_Max ) h = 4.0 + (var_R - var_G)/del_Max; - h /= 6.0; - - if ( h < 0 ) h += 1; - if ( h > 1 ) h -= 1; - } - } - - void Color::hsv2rgb (float h, float s, float v, float &r, float &g, float &b) { - - float h1 = h*6.f; // sector 0 to 5 - int i = (int)h1; // floor() is very slow, and h1 is always >0 - float f = h1 - i; // fractional part of h - - float p = v * ( 1.f - s ); - float q = v * ( 1.f - s * f ); - float t = v * ( 1.f - s * ( 1.f - f ) ); - - float r1,g1,b1; - - if (i==1) {r1 = q; g1 = v; b1 = p;} - else if (i==2) {r1 = p; g1 = v; b1 = t;} - else if (i==3) {r1 = p; g1 = q; b1 = v;} - else if (i==4) {r1 = t; g1 = p; b1 = v;} - else if (i==5) {r1 = v; g1 = p; b1 = q;} - else /*i==(0|6)*/ {r1 = v; g1 = t; b1 = p;} - - r = ((r1)*65535.0f); - g = ((g1)*65535.0f); - b = ((b1)*65535.0f); - } - - // Function copied for speed concerns - // Not exactly the same as above ; this one return a result in the [0.0 ; 1.0] range - void Color::hsv2rgb01 (float h, float s, float v, float &r, float &g, float &b) { - float h1 = h*6; // sector 0 to 5 - int i = int(h1); - float f = h1 - i; // fractional part of h - - float p = v * ( 1 - s ); - float q = v * ( 1 - s * f ); - float t = v * ( 1 - s * ( 1 - f ) ); - - if (i==1) {r = q; g = v; b = p;} - else if (i==2) {r = p; g = v; b = t;} - else if (i==3) {r = p; g = q; b = v;} - else if (i==4) {r = t; g = p; b = v;} - else if (i==5) {r = v; g = p; b = q;} - else /*(i==0|6)*/ {r = v; g = t; b = p;} - } - - void Color::hsv2rgb (float h, float s, float v, int &r, int &g, int &b) { - - float h1 = h*6; // sector 0 to 5 - int i = floor( h1 ); - float f = h1 - i; // fractional part of h - - float p = v * ( 1 - s ); - float q = v * ( 1 - s * f ); - float t = v * ( 1 - s * ( 1 - f ) ); - - float r1,g1,b1; - - if (i==0) {r1 = v; g1 = t; b1 = p;} - else if (i==1) {r1 = q; g1 = v; b1 = p;} - else if (i==2) {r1 = p; g1 = v; b1 = t;} - else if (i==3) {r1 = p; g1 = q; b1 = v;} - else if (i==4) {r1 = t; g1 = p; b1 = v;} - else if (i==5) {r1 = v; g1 = p; b1 = q;} - - r = (int)( r1 * 65535); - g = (int)( g1 * 65535); - b = (int)( b1 * 65535); - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void Color::xyz2srgb (float x, float y, float z, float &r, float &g, float &b) { - - //Transform to output color. Standard sRGB is D65, but internal representation is D50 - //Note that it is only at this point that we should have need of clipping color data - - /*float x65 = d65_d50[0][0]*x + d65_d50[0][1]*y + d65_d50[0][2]*z ; - float y65 = d65_d50[1][0]*x + d65_d50[1][1]*y + d65_d50[1][2]*z ; - float z65 = d65_d50[2][0]*x + d65_d50[2][1]*y + d65_d50[2][2]*z ; - - r = sRGB_xyz[0][0]*x65 + sRGB_xyz[0][1]*y65 + sRGB_xyz[0][2]*z65; - g = sRGB_xyz[1][0]*x65 + sRGB_xyz[1][1]*y65 + sRGB_xyz[1][2]*z65; - b = sRGB_xyz[2][0]*x65 + sRGB_xyz[2][1]*y65 + sRGB_xyz[2][2]*z65;*/ - - /*r = sRGBd65_xyz[0][0]*x + sRGBd65_xyz[0][1]*y + sRGBd65_xyz[0][2]*z ; - g = sRGBd65_xyz[1][0]*x + sRGBd65_xyz[1][1]*y + sRGBd65_xyz[1][2]*z ; - b = sRGBd65_xyz[2][0]*x + sRGBd65_xyz[2][1]*y + sRGBd65_xyz[2][2]*z ;*/ - - r = ((sRGB_xyz[0][0]*x + sRGB_xyz[0][1]*y + sRGB_xyz[0][2]*z)) ; - g = ((sRGB_xyz[1][0]*x + sRGB_xyz[1][1]*y + sRGB_xyz[1][2]*z)) ; - b = ((sRGB_xyz[2][0]*x + sRGB_xyz[2][1]*y + sRGB_xyz[2][2]*z)) ; - - } - void Color::xyz2Prophoto (float x, float y, float z, float &r, float &g, float &b) { - r = ((prophoto_xyz[0][0]*x + prophoto_xyz[0][1]*y + prophoto_xyz[0][2]*z)) ; - g = ((prophoto_xyz[1][0]*x + prophoto_xyz[1][1]*y + prophoto_xyz[1][2]*z)) ; - b = ((prophoto_xyz[2][0]*x + prophoto_xyz[2][1]*y + prophoto_xyz[2][2]*z)) ; - } - void Color::Prophotoxyz (float r, float g, float b, float &x, float &y, float &z) { - x = ((xyz_prophoto[0][0]*r + xyz_prophoto[0][1]*g + xyz_prophoto[0][2]*b)) ; - y = ((xyz_prophoto[1][0]*r + xyz_prophoto[1][1]*g + xyz_prophoto[1][2]*b)) ; - z = ((xyz_prophoto[2][0]*r + xyz_prophoto[2][1]*g + xyz_prophoto[2][2]*b)) ; - } - - void Color::rgbxyz (float r, float g, float b, float &x, float &y, float &z, const double xyz_rgb[3][3]) { - x = ((xyz_rgb[0][0]*r + xyz_rgb[0][1]*g + xyz_rgb[0][2]*b)) ; - y = ((xyz_rgb[1][0]*r + xyz_rgb[1][1]*g + xyz_rgb[1][2]*b)) ; - z = ((xyz_rgb[2][0]*r + xyz_rgb[2][1]*g + xyz_rgb[2][2]*b)) ; - } - - void Color::rgbxyz (float r, float g, float b, float &x, float &y, float &z, const float xyz_rgb[3][3]) { - x = ((xyz_rgb[0][0]*r + xyz_rgb[0][1]*g + xyz_rgb[0][2]*b)) ; - y = ((xyz_rgb[1][0]*r + xyz_rgb[1][1]*g + xyz_rgb[1][2]*b)) ; - z = ((xyz_rgb[2][0]*r + xyz_rgb[2][1]*g + xyz_rgb[2][2]*b)) ; - } - - void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]) { - //Transform to output color. Standard sRGB is D65, but internal representation is D50 - //Note that it is only at this point that we should have need of clipping color data - - /*float x65 = d65_d50[0][0]*x + d65_d50[0][1]*y + d65_d50[0][2]*z ; - float y65 = d65_d50[1][0]*x + d65_d50[1][1]*y + d65_d50[1][2]*z ; - float z65 = d65_d50[2][0]*x + d65_d50[2][1]*y + d65_d50[2][2]*z ; - - r = sRGB_xyz[0][0]*x65 + sRGB_xyz[0][1]*y65 + sRGB_xyz[0][2]*z65; - g = sRGB_xyz[1][0]*x65 + sRGB_xyz[1][1]*y65 + sRGB_xyz[1][2]*z65; - b = sRGB_xyz[2][0]*x65 + sRGB_xyz[2][1]*y65 + sRGB_xyz[2][2]*z65;*/ - - /*r = sRGBd65_xyz[0][0]*x + sRGBd65_xyz[0][1]*y + sRGBd65_xyz[0][2]*z ; - g = sRGBd65_xyz[1][0]*x + sRGBd65_xyz[1][1]*y + sRGBd65_xyz[1][2]*z ; - b = sRGBd65_xyz[2][0]*x + sRGBd65_xyz[2][1]*y + sRGBd65_xyz[2][2]*z ;*/ - - r = ((rgb_xyz[0][0]*x + rgb_xyz[0][1]*y + rgb_xyz[0][2]*z)) ; - g = ((rgb_xyz[1][0]*x + rgb_xyz[1][1]*y + rgb_xyz[1][2]*z)) ; - b = ((rgb_xyz[2][0]*x + rgb_xyz[2][1]*y + rgb_xyz[2][2]*z)) ; - } - - // same for float - void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3]) { - r = ((rgb_xyz[0][0]*x + rgb_xyz[0][1]*y + rgb_xyz[0][2]*z)) ; - g = ((rgb_xyz[1][0]*x + rgb_xyz[1][1]*y + rgb_xyz[1][2]*z)) ; - b = ((rgb_xyz[2][0]*x + rgb_xyz[2][1]*y + rgb_xyz[2][2]*z)) ; - } - - void Color::trcGammaBW (float &r, float &g, float &b, float gammabwr, float gammabwg, float gammabwb) { - // correct gamma for black and white image : pseudo TRC curve of ICC profil - b/=65535.0f; - b= pow (max(b,0.0f), gammabwb); - b *=65535.0f; - r/=65535.0f; - r= pow (max(r,0.0f), gammabwr); - r *=65535.0f; - g/=65535.0f; - g= pow (max(g,0.0f), gammabwg); - g *=65535.0f; - } - - /** @brief Compute the B&W constants for the B&W processing and its tool's GUI - * - * @param setting BlackWhite::setting - * @param setting BlackWhite::filter - */ - void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::ustring &filter, const Glib::ustring &algo, float &filcor, float &mixerRed, float &mixerGreen, - float &mixerBlue, float mixerOrange, float mixerYellow, float mixerCyan, float mixerPurple, float mixerMagenta, - bool autoc, bool complement, float &kcorec, double &rrm, double &ggm, double &bbm) - { - float somm; - float som = mixerRed+mixerGreen+mixerBlue; - // rM = mixerRed, gM = mixerGreen, bM = mixerBlue ! - //presets - if (setting=="RGB-Abs" || setting=="ROYGCBPM-Abs") - kcorec=som/100.f; - - if (!autoc) { - //if (setting=="RGB-Abs" || setting=="ROYGCBPM-Abs") {} //Keep the RGB mixer values as is! - //else if(setting=="RGB-Rel" || setting=="ROYGCBPM-Rel") {} //Keep the RGB mixer values as is! - if (setting=="NormalContrast") { mixerRed=43.f ; mixerGreen=33.f; mixerBlue=30.f; } - else if(setting=="Panchromatic") { mixerRed=33.3f; mixerGreen=33.3f; mixerBlue=33.3f; } - else if(setting=="HyperPanchromatic") { mixerRed=41.f ; mixerGreen=25.f; mixerBlue=34.f; } - else if(setting=="LowSensitivity") { mixerRed=27.f ; mixerGreen=27.f; mixerBlue=46.f; } - else if(setting=="HighSensitivity") { mixerRed=30.f ; mixerGreen=28.f; mixerBlue=42.f; } - else if(setting=="Orthochromatic") { mixerRed=0.f ; mixerGreen=42.f; mixerBlue=58.f; } - else if(setting=="HighContrast") { mixerRed=40.f ; mixerGreen=34.f; mixerBlue=60.f; } - else if(setting=="Luminance") { mixerRed=30.f ; mixerGreen=59.f; mixerBlue=11.f; } - else if(setting=="Landscape") { mixerRed=66.f ; mixerGreen=24.f; mixerBlue=10.f; } - else if(setting=="Portrait") { mixerRed=54.f ; mixerGreen=44.f; mixerBlue=12.f; } - else if(setting=="InfraRed") { mixerRed=-40.f; mixerGreen=200.f; mixerBlue=-17.f; } - } - - rrm=mixerRed; - ggm=mixerGreen; - bbm=mixerBlue; - - somm=mixerRed+mixerGreen+mixerBlue; - mixerRed=mixerRed/somm; mixerGreen=mixerGreen/somm; mixerBlue=mixerBlue/somm; - float koymcp=0.f; - - if(setting=="ROYGCBPM-Abs" || setting=="ROYGCBPM-Rel") { - float obM=0.f; - float ogM=0.f; - float orM=0.f; - - float ybM=0.f; - float yrM=0.f; - float ygM=0.f; - - float mgM=0.f; - float mrM=0.f; - float mbM=0.f; - - float pgM=0.f; - float prM=0.f; - float pbM=0.f; - - float crM=0.f; - float cgM=0.f; - float cbM=0.f; - //printf("mixred=%f\n",mixerRed); - - float fcompl = 1.f; - if(complement && algo=="SP") fcompl = 3.f;//special - else if(complement && algo=="LI") fcompl = 1.5f;//linear - // ponderate filters: report to R=G=B=33 - // I ponder RGB channel, not only orange or yellow or cyan, etc...it's my choice ! - if(mixerOrange != 33) { - if (algo=="SP") {//special - if (mixerOrange >= 33) orM = fcompl*(mixerOrange*0.67f - 22.11f)/100.f; else orM = fcompl*(-0.3f*mixerOrange +9.9f)/100.f; - if (mixerOrange >= 33) ogM = fcompl*(-0.164f*mixerOrange+5.412f)/100.f; else ogM = fcompl*(0.4f*mixerOrange-13.2f)/100.f; - } - else if (algo=="LI") {//linear - orM = fcompl*(mixerOrange - 33.f)/100.f; - ogM = fcompl*(0.5f*mixerOrange-16.5f)/100.f; - } - if(complement) obM =(-0.492f*mixerOrange+16.236f)/100.f; - mixerRed += orM; - mixerGreen += ogM; - mixerBlue += obM; - koymcp += (orM+ogM+obM); - // printf("mixred+ORange=%f\n",mixerRed); - - } - if(mixerYellow != 33) { - if (algo=="SP") yrM = fcompl*(-0.134f*mixerYellow+4.422f)/100.f;//22.4 - else if (algo=="LI")yrM = fcompl*(0.5f*mixerYellow-16.5f)/100.f;//22.4 - ygM = fcompl*(0.5f *mixerYellow-16.5f )/100.f; - if(complement) ybM =(-0.492f*mixerYellow+16.236f)/100.f; - mixerRed += yrM; - mixerGreen += ygM; - mixerBlue += ybM; - koymcp += (yrM+ygM+ybM); - } - if(mixerMagenta != 33) { - if (algo=="SP"){ - if(mixerMagenta >= 33) mrM = fcompl*( 0.67f *mixerMagenta-22.11f)/100.f; else mrM = fcompl*(-0.3f*mixerMagenta +9.9f)/100.f; - if(mixerMagenta >= 33) mbM = fcompl*(-0.164f*mixerMagenta+5.412f)/100.f; else mbM = fcompl*( 0.4f*mixerMagenta-13.2f)/100.f; - } - else if (algo=="LI"){ - mrM = fcompl*(mixerMagenta-33.f)/100.f; - mbM = fcompl*(0.5f*mixerMagenta-16.5f)/100.f; - } - if(complement) mgM =(-0.492f*mixerMagenta+16.236f)/100.f; - mixerRed += mrM; - mixerGreen += mgM; - mixerBlue += mbM; - koymcp += (mrM+mgM+mbM); - } - if(mixerPurple != 33) { - if (algo=="SP") prM = fcompl*(-0.134f*mixerPurple+4.422f)/100.f; - else if (algo=="LI")prM = fcompl*(0.5f*mixerPurple-16.5f)/100.f; - pbM = fcompl*(0.5f*mixerPurple-16.5f)/100.f; - if(complement) pgM = (-0.492f*mixerPurple+16.236f)/100.f; - mixerRed += prM; - mixerGreen += pgM; - mixerBlue += pbM; - koymcp += (prM+pgM+pbM); - } - if(mixerCyan != 33) { - if (algo=="SP")cgM = fcompl*(-0.134f*mixerCyan +4.422f)/100.f; - else if (algo=="LI")cgM = fcompl*(0.5f*mixerCyan -16.5f)/100.f; - cbM = fcompl*(0.5f*mixerCyan-16.5f)/100.f; - if(complement) crM = (-0.492f*mixerCyan+16.236f)/100.f; - mixerRed += crM; - mixerGreen += cgM; - mixerBlue += cbM; - koymcp += (crM+cgM+cbM); - } - } - if(setting=="ROYGCBPM-Abs") - kcorec = koymcp+som/100.f; - //Color filters - float filred,filgreen,filblue; - filred=1.f;filgreen=1.f;filblue=1.f;filcor=1.f; - if (filter=="None") {filred=1.f; filgreen=1.f; filblue=1.f; filcor=1.f;} - else if (filter=="Red") {filred=1.f; filgreen=0.05f;filblue=0.f; filcor=1.08f;} - else if (filter=="Orange") {filred=1.f; filgreen=0.6f; filblue=0.f; filcor=1.35f;} - else if (filter=="Yellow") {filred=1.f; filgreen=1.f; filblue=0.05f;filcor=1.23f;} - else if (filter=="YellowGreen") {filred=0.6f; filgreen=1.f; filblue=0.3f;filcor=1.32f;} - else if (filter=="Green") {filred=0.2f; filgreen=1.f; filblue=0.3f;filcor=1.41f;} - else if (filter=="Cyan") {filred=0.05f;filgreen=1.f; filblue=1.f; filcor=1.23f;} - else if (filter=="Blue") {filred=0.f; filgreen=0.05f;filblue=1.f; filcor=1.20f;} - else if (filter=="Purple") {filred=1.f; filgreen=0.05f;filblue=1.f; filcor=1.23f;} - mixerRed = mixerRed * filred; - mixerGreen = mixerGreen * filgreen; - mixerBlue = mixerBlue * filblue; - - mixerRed = filcor*mixerRed / (mixerRed + mixerGreen + mixerBlue); - mixerGreen = filcor*mixerGreen / (mixerRed + mixerGreen + mixerBlue); - mixerBlue = filcor*mixerBlue / (mixerRed + mixerGreen + mixerBlue); - - if(filter!="None") { - som = mixerRed+mixerGreen+mixerBlue; - if(setting=="RGB-Abs" || setting=="ROYGCBPM-Abs") kcorec = kcorec*som; - } - - } - - void Color::interpolateRGBColor (const float balance, const float r1, const float g1, const float b1, const float r2, const float g2, const float b2, int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo) { - float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z; - float L1, L2, a_1, b_1, a_2, b_2, a, b; - float c1, c2, h1, h2; - float RR,GG,BB; - float Lr; - - // converting color 1 to Lch - Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); - Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1); - Color::Lab2Lch(a_1, b_1, c1, h1); - Lr=L1/327.68f;//for gamutlch - //gamut control on r1 g1 b1 - #ifndef NDEBUG - bool neg=false; - bool more_rgb=false; - - //gamut control : Lab values are in gamut - Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); - #else - Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); - #endif - - L1=Lr*327.68f; - - // converting color 2 to Lch - Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb); - Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2); - Color::Lab2Lch(a_2, b_2, c2, h2); - - Lr=L2/327.68f;//for gamutlch - //gamut control on r2 g2 b2 - #ifndef NDEBUG - neg=false; - more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(h2,Lr,c2, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); - #else - Color::gamutLchonly(h2,Lr,c2, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); - #endif - L2=Lr*327.68f; - - // interpolating Lch values - if (toDo & CHANNEL_LIGHTNESS) { L1 = L1 + (L2-L1)*balance;if(L1<0.f) L1=0.f;}//do not allow negative L - if (toDo & CHANNEL_CHROMATICITY) {c1 = c1 + (c2-c1)*balance;if(c1<0.f) c1=0.f; if(c1>180.f) c1=180.f;}//limit C to reasonable value - if (toDo & CHANNEL_HUE) h1 = interpolatePolarHue_PI(h1, h2, balance); - - // here I have put gamut control with gamutlchonly on final process - Lr=L1/327.68f;//for gamutlch - #ifndef NDEBUG - neg=false; - more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); - #else - //gamut control : Lab values are in gamut - Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); - #endif - //convert CH ==> ab - L1=Lr*327.68f; - - // converting back to rgb - Color::Lch2Lab(c1, h1, a, b); - Color::Lab2XYZ(L1, a, b, X, Y, Z); - Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz); - } - - - void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int algm, const float balance, int twoc, int metchrom, - bool chr, bool lum, float chromat, float luma, const float r1, const float g1, const float b1, - const float xl, const float yl, const float zl, const float x2, const float y2, const float z2, - int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo) - { - float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z,XL,YL,ZL; - float L1, L2, LL, a_1, b_1, a_2, b_2, a, b,a_L,b_L; - float c1, c2, h1, h2,cL,hL; - float RR,GG,BB; - float Lr; - float slc=0.f; - float hh=0.f; - float ll=0.f; - float sh=0.f; - bool LCH=false; - - float ha,hb,hc,ba; - float c_1,h_1; - // converting color 1 to Lab (image) - Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); - if(algm == 1) {//use H interpolate - Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1); - //Color::Lab2Lch(a_1, b_1, c_1, h_1) ; - } - // converting color l lab(low) first color - if(twoc==0) { // 2 colours - //Color::rgbxyz(rl, gl, bl, XL, YL, ZL, xyz_rgb); - XL=xl; - YL=yl; - ZL=zl; - if(algm <= 1) {//use H interpolate - Color::XYZ2Lab(XL, YL, ZL, LL, a_L, b_L); - } - } - - // converting color 2 to lab (universal or high) - X2=x2; - Y2=y2; - Z2=z2; - float c_2,h_2; - if(algm == 1 ) { - Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2); - //Color::Lab2Lch(a_2, b_2, c_2, h_2) ; - } - float bal,balH,cal,calH,calm; - bal=balH=balance; - cal=calH=calm=1.f-chromat; - float med=(iphigh+iplow)/2.f; - float medH=(iphigh+iplow)/2.f; - float medL=(iphigh+iplow)/2.f; - - med=1.f;medH=0.f;//new algo for 2 colors - float calan; - calan=chromat; - - float calby; - calby=luma; - - if(twoc==0) { // 2 colours - calan=chromat; - - //calculate new balance in function of (arbitrary) "med".. I hope no error !! - if (realL > iplow && realL<=med) bal = realL*balance/(iplow-med) - med*balance/(iplow-med); - else if (realL <= iplow) bal = realL*balance/iplow; - - if (realL > medH && realL <= iphigh) balH = realL*balance/(iphigh-medH) - medH*balance/(iphigh-medH); - else if (realL > iphigh) balH = realL*balance*(iphigh-1.f) - balance*(iphigh-1.f); - - //calculate new balance chroma - if (realL > iplow && realL<=med) cal = realL*calan/(iplow-med) - med*calan/(iplow-med); - else if (realL <= iplow) cal = realL*calan/iplow; - - if (realL > medH && realL <= iphigh) calH = realL*calan/(iphigh-medH) - medH*calan/(iphigh-medH); - else if (realL > iphigh) calH = realL*calan;//*(iphigh-1.f) - calan*(iphigh-1.f);//it is better without transition in highlight - } - - float hX=0.f; - float hLL,hH,ccL,ccH,llH,aaH,bbH; - - if(algm <=1){ - if(twoc==0 && metchrom==3) { // 2 colours only with special "ab" - if(algm==1) { - aaH=a_1 + (a_2-a_1)*calH;bbH=b_1 + (b_2-b_1)*calH;//pass to line after - a_1=aaH + (a_L-aaH)*cal*balance;b_1=bbH + (b_L-bbH)*cal*balance; - } - } - else if(twoc==1) { - if(metchrom==0) { - a_1=a_1 + (a_2-a_1)*balance; - b_1=b_1 + (b_2-b_1)*balance; - } - else if(metchrom==1){ - a_1=a_1 + (a_2-a_1)*calan*balance; - b_1=b_1 + (b_2-b_1)*calan*balance; - } - else if(metchrom==2) { - a_1=a_1 + (a_2-a_1)*calan*balance; - b_1=b_1 + (b_2-b_1)*calby*balance; - } - } - } - else - h1=hX; - - Color::Lab2XYZ(L1, a_1, b_1, X, Y, Z); - - Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz);// ro go bo in gamut - } - - void Color::calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4, double &gamma5) { - //from Dcraw (D.Coffin) - int i; - double g[6], bnd[2]={0,0}; - - g[0] = pwr; - g[1] = ts; - g[2] = g[3] = g[4] = 0; - bnd[g[1] >= 1] = 1; - if (g[1] && (g[1]-1)*(g[0]-1) <= 0) { - for (i=0; i < 48; i++) { - g[2] = (bnd[0] + bnd[1])/2; - if (g[0]) - bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2]; - else - bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2]; - } - g[3] = g[2] / g[1]; - if (g[0]) g[4] = g[2] * (1/g[0] - 1); - } - if (g[0]) - g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) + (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1; - else - g[5] = 1 / (g[1]*SQR(g[3])/2 + 1 - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1; - if (!mode--) { - gamma0=g[0];gamma1=g[1];gamma2=g[2];gamma3=g[3];gamma4=g[4];gamma5=g[5]; - return; - } - } - - void Color::Lab2XYZ(float L, float a, float b, float &x, float &y, float &z) { - float LL=L/327.68f; - float aa=a/327.68f; - float bb=b/327.68f; - float fy = (0.00862069f * LL) + 0.137932f; // (L+16)/116 - float fx = (0.002f * aa) + fy; - float fz = fy - (0.005f * bb); - x = 65535.0f*f2xyz(fx)*D50x; - z = 65535.0f*f2xyz(fz)*D50z; - y=(LL>epskap) ? 65535.0f*fy*fy*fy : 65535.0f*LL/kappa; - } - -#ifdef __SSE2__ - void Color::Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, vfloat &z) { - vfloat c327d68 = F2V(327.68f); - L /= c327d68; - a /= c327d68; - b /= c327d68; - vfloat fy = F2V(0.00862069f) * L + F2V(0.137932f); - vfloat fx = F2V(0.002f) * a + fy; - vfloat fz = fy - (F2V(0.005f) * b); - vfloat c65535 = F2V(65535.f); - x = c65535*f2xyz(fx)*F2V(D50x); - z = c65535*f2xyz(fz)*F2V(D50z); - vfloat res1 = fy*fy*fy; - vfloat res2 = L / F2V(kappa); - y = vself(vmaskf_gt(L, F2V(epskap)), res1, res2); - y *= c65535; - } -#endif // __SSE2__ - - void Color::XYZ2Lab(float X, float Y, float Z, float &L, float &a, float &b) { - - float x = X/D50x; - float z = Z/D50z; - float y= Y; - float fx,fy,fz; - - fx = (x<=65535.0f ? cachef[x] : (327.68f*xcbrtf(x/MAXVALF))); - fy = (y<=65535.0f ? cachef[y] : (327.68f*xcbrtf(y/MAXVALF))); - fz = (z<=65535.0f ? cachef[z] : (327.68f*xcbrtf(z/MAXVALF))); - - L = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; - a = (500.0f * (fx - fy) ); - b = (200.0f * (fy - fz) ); - } - - void Color::Lab2Yuv(float L, float a, float b, float &Y, float &u, float &v) { - float fy = (0.00862069 * L/327.68) + 0.137932; // (L+16)/116 - float fx = (0.002 * a/327.68) + fy; - float fz = fy - (0.005 * b/327.68); - float LL=L/327.68; - - float X = 65535.0*f2xyz(fx)*D50x; - // Y = 65535.0*f2xyz(fy); - float Z = 65535.0*f2xyz(fz)*D50z; - Y=(LL/327.68f>epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/kappa; - - u = 4.0*X/(X+15*Y+3*Z)-u0; - v = 9.0*Y/(X+15*Y+3*Z)-v0; - } - - void Color::Yuv2Lab(float Yin, float u, float v, float &L, float &a, float &b, double wp[3][3]) { - float u1 = u + u0; - float v1 = v + v0; - - float Y = Yin; - float X = (9*u1*Y)/(4*v1*D50x); - float Z = (12 - 3*u1 - 20*v1)*Y/(4*v1*D50z); - - 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 ))); - - L = (116.0 * fy - 5242.88); //5242.88=16.0*327.68; - a = (500.0 * (fx - fy) ); - b = (200.0 * (fy - fz) ); - } - - void Color::Lab2Lch(float a, float b, float &c, float &h) { - c = (sqrtf(a*a+b*b))/327.68f; - h = xatan2f(b, a); - } - - void Color::Lch2Lab(float c, float h, float &a, float &b) { - float2 sincosval = xsincosf(h); - a = 327.68f * c * sincosval.y; - b = 327.68f * c * sincosval.x; - } - - void Color::Luv2Lch(float u, float v, float &c, float &h) { - c = sqrtf(u*u+v*v); - h = xatan2f(v, u); //WARNING: should we care of division by zero here? - if (h < 0.f) + if ( h < 0.f ) { h += 1.f; - } - - void Color::Lch2Luv(float c, float h, float &u, float &v) { - float2 sincosval = xsincosf(h); - u = c * sincosval.x; - v = c * sincosval.y; - } - - // NOT TESTED - void Color::XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v) { - - X /= 65535.f; - Y /= 65535.f; - Z /= 65535.f; - - if (Y > float(eps)) - L = 116.f * pow(Y, 1.f/3.f) -16.f; - else - L = float(kappa) * Y; - u = 13.f * L * float(u0); - v = 13.f * L * float(v0); - } - - // NOT TESTED - void Color::Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z) { - if (L > float(epskap)) { - float t = (L+16.f) / 116.f; - Y = t*t*t; - } - else - Y = L/float(kappa); - - float a = ((52.f*L) / (u+13.f*L*float(u0)) -1.f) / 3.f; - float d = Y * (((39*L) / (v+13*float(v0))) -5.f); - float b = -5.f*Y; - X = (d-b) / (a+1.f/3.f); - - Z = X*a+b; - - X *= 65535.f; - Y *= 65535.f; - Z *= 65535.f; - } - - /* - * Gamut mapping algorithm - * Copyright (c) 2010-2011 Emil Martinec - * - * Solutions to scaling u and v to XYZ paralleliped boundaries - * Some equations: - * - * fu(X,Y,Z) = 4 X/(X + 15 Y + 3 Z); - * fv(X,Y,Z) = 9 Y/(X + 15 Y + 3 Z); - * - * take the plane spanned by X=a*Xr+b*Xg+c*Xb etc with one of a,b,c equal to 0 or 1, - * and itersect with the line u0+lam*u, or in other words solve - * - * u0+lam*u=fu(X,Y,Z) - * v0+lam*v=fv(X,Y,Z) - * - * The value of lam is the scale factor that takes the color to the gamut boundary - * columns of the matrix p=xyz_rgb are RGB tristimulus primaries in XYZ - * c is the color fixed on the boundary; and m=0 for c=0, m=1 for c=255 - */ - void Color::gamutmap(float &X, float &Y, float &Z, const double p[3][3]) - { - float u = 4*X/(X+15*Y+3*Z)-u0; - float v = 9*Y/(X+15*Y+3*Z)-v0; - - float lam[3][2]; - float lam_min = 1.0; - - for (int c=0; c<3; c++) - for (int m=0; m<2; m++) { - - int c1=(c+1)%3; - int c2=(c+2)%3; - - lam[c][m] = (-(p[0][c1]*p[1][c]*((-12 + 3*u0 + 20*v0)*Y + 4*m*65535*v0*p[2][c2])) + - p[0][c]*p[1][c1]*((-12 + 3*u0 + 20*v0)*Y + 4*m*65535*v0*p[2][c2]) - - 4*v0*p[0][c1]*(Y - m*65535*p[1][c2])*p[2][c] + 4*v0*p[0][c]*(Y - m*65535*p[1][c2])*p[2][c1] - - (4*m*65535*v0*p[0][c2] - 9*u0*Y)*(p[1][c1]*p[2][c] - p[1][c]*p[2][c1])); - - lam[c][m] /= (3*u*Y*(p[0][c1]*p[1][c] - p[1][c1]*(p[0][c] + 3*p[2][c]) + 3*p[1][c]*p[2][c1]) + - 4*v*(p[0][c1]*(5*Y*p[1][c] + m*65535*p[1][c]*p[2][c2] + Y*p[2][c] - m*65535*p[1][c2]*p[2][c]) - - p[0][c]*(5*Y*p[1][c1] + m*65535*p[1][c1]*p[2][c2] + Y*p[2][c1] - m*65535*p[1][c2]*p[2][c1]) + - m*65535*p[0][c2]*(p[1][c1]*p[2][c] - p[1][c]*p[2][c1]))); - - if (lam[c][m]0) lam_min=lam[c][m]; - - } - - u = u*lam_min + u0; - v = v*lam_min + v0; - - X = (9*u*Y)/(4*v); - Z = (12 - 3*u - 20*v)*Y/(4*v); - } - - void Color::skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s) - { - float factorskin, factorsat,factor, factorskinext, interm; - float scale = 100.0f/100.1f;//reduction in normal zone - float scaleext=1.0f;//reduction in transition zone - float protect_redh; - float deltaHH=0.3f;//HH value transition : I have choice 0.3 radians - float HH; - bool doskin=false; - //rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear - if ((float)h>8.6f && (float)h<=74.f ) {HH=(1.15f/65.4f)*(float)h-0.0012f; doskin=true;}//H > 0.15 H<1.3 - else if((float)h>0.f && (float)h<=8.6f ) {HH=(0.19f/8.6f )*(float)h-0.04f; doskin=true;}//H>-0.04 H < 0.15 - else if((float)h>355.f && (float)h<=360.f) {HH=(0.11f/5.0f )*(float)h-7.96f; doskin=true;}//H>-0.15 <-0.04 - else if((float)h>74.f && (float)h<95.f ) {HH=(0.30f/21.0f)*(float)h+0.24285f; doskin=true;}//H>1.3 H<1.6 - - if(doskin) - { - float chromapro=sres/Sp; - if(sk==1){//in C mode to adapt dred to J - if (J<16.0) dred = 40.0f; - else if(J<22.0) dred = (4.1666f)*(float)J -26.6f; - else if(J<60.0) dred = 55.0f; - else if(J<70.0) dred = -1.5f*(float)J +145.0f; - else dred = 40.0f; - } - if(chromapro>0.0) Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor - if(chromapro>1.0) {interm=(chromapro-1.0f)*100.0f; - factorskin= 1.0f+(interm*scale)/100.0f; - factorskinext=1.0f+(interm*scaleext)/100.0f;} - else { - factorskin= chromapro ; - factorskinext= chromapro ; - } - factorsat=chromapro; - factor=factorsat; - Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition - s*=factor; - } - else s=ko*sres; - - } - void Color::skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s) - { - float HH; - bool doskin=false; - //rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear - if ((float)h>8.6f && (float)h<=74.f ) {HH=(1.15f/65.4f)*(float)h-0.0012f; doskin=true;}//H > 0.15 H<1.3 - else if((float)h>0.f && (float)h<=8.6f ) {HH=(0.19f/8.6f )*(float)h-0.04f; doskin=true;}//H>-0.04 H < 0.15 - else if((float)h>355.f && (float)h<=360.f) {HH=(0.11f/5.0f )*(float)h-7.96f; doskin=true;}//H>-0.15 <-0.04 - else if((float)h>74.f && (float)h<95.f ) {HH=(0.30f/21.0f)*(float)h+0.24285f; doskin=true;}//H>1.3 H<1.6 - - if(doskin) - { - float factorskin, factorsat,factor, factorskinext; - float protect_redh; - float deltaHH=0.3f;//HH value transition : I have choice 0.3 radians - float chromapro=sres/Sp; - if(sk==1){//in C mode to adapt dred to J - if (J<16.0) dred = 40.0f; - else if(J<22.0) dred = (4.1666f)*(float)J -26.6f; - else if(J<60.0) dred = 55.0f; - else if(J<70.0) dred = -1.5f*(float)J +145.0f; - else dred = 40.0f; - } - if(chromapro>1.0) { - float scale = 0.999000999f; // 100.0f/100.1f; reduction in normal zone - float scaleext=1.0f;//reduction in transition zone - Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor - float interm=(chromapro-1.0f); - factorskin= 1.0f+(interm*scale); - factorskinext=1.0f+(interm*scaleext); - } - else { - factorskin= chromapro ; - factorskinext= chromapro ; - } - factorsat=chromapro; - factor=factorsat; - Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition - s*=factor; - } - else s=ko*sres; - - } - - - - - - - void Color::scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext) - { - if(rstprotection<99.9999f) { - if(param > limit) - scale = rstprotection/100.1f; - if((HH< (1.3f+deltaHH) && HH >=1.3f)) - // scaleext=HH*(1.0f-scale)/deltaHH + 1.0f - (1.3f+deltaHH)*(1.0f-scale)/deltaHH; //transition for Hue (red - yellow) - // optimized formula - scaleext=(HH*(1.0f-scale) + deltaHH - (1.3f+deltaHH)*(1.0f-scale))/deltaHH; //transition for Hue (red - yellow) - else if((HH< 0.15f && HH >(0.15f-deltaHH))) - // scaleext=HH*(scale-1.0f)/deltaHH + 1.0f - (0.15f-deltaHH)*(scale-1.0f)/deltaHH; //transition for hue (red purple) - // optimized formula - scaleext=(HH*(scale-1.0f) + deltaHH - (0.15f-deltaHH)*(scale-1.0f))/deltaHH; //transition for hue (red purple) - } - } - - void Color::transitred (const float HH, float const Chprov1, const float dred, const float factorskin, const float protect_red, const float factorskinext, const float deltaHH, const float factorsat, float &factor) - { - if(HH>=0.15f && HH<1.3f) { - if (Chprov1(0.15f-deltaHH) || HH<(1.3f+deltaHH) ) { - if (Chprov1 < dred) - factor = factorskinext;// C=dred=55 => real max of skin tones - else if (Chprov1 < (dred+protect_red))// transition - // factor = (factorsat-factorskinext)/protect_red*Chprov1+factorsat-(dred+protect_red)*(factorsat-factorskinext)/protect_red; - // optimized formula - factor = ((factorsat-factorskinext)*Chprov1 + factorsat*protect_red - (dred+protect_red)*(factorsat-factorskinext))/protect_red; - } - } - - /* - * AllMunsellLch correction - * Copyright (c) 2012 Jacques Desmis - * - * This function corrects the color (hue) for changes in chromaticity and luminance - * to use in a "for" or "do while" statement - * - * Parameters: - * bool lumaMuns : true => luminance correction (for delta L > 10) and chroma correction ; false : only chroma - * float Lprov1 , Loldd : luminance after and before - * float HH: hue before - * float Chprov1, CC : chroma after and before - * float coorectionHuechroma : correction Hue for chromaticity (saturation) - * float correctlum : correction Hue for luminance (brigtness, contrast,...) - * MunsellDebugInfo* munsDbgInfo: (Debug target only) object to collect information. - */ -#ifdef _DEBUG - void Color::AllMunsellLch(bool lumaMuns, float Lprov1,float Loldd,float HH,float Chprov1,float CC,float &correctionHuechroma,float &correctlum, MunsellDebugInfo* munsDbgInfo) -#else - void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHuechroma, float &correctlum) -#endif - { - - bool contin1,contin2; - float correctionHue=0.0,correctionHueLum=0.0; - bool correctL; - if(CC >= 6.0 && CC < 140) { //if C > 140 we say C=140 (only in Prophoto ...with very large saturation) - static const float huelimit[8]={-2.48,-0.55,0.44,1.52,1.87,3.09,-0.27,0.44};//limits hue of blue-purple, red-yellow, green-yellow, red-purple - if (Chprov1 > 140.f) - Chprov1=139.f; //limits of LUTf - if (Chprov1 < 6.f) - Chprov1=6.f; - for(int zo=1;zo<=4;zo++) { - if(HH>huelimit[2*zo-2] && HHmaxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); -} - } - if(absCorrectionHue > 0.45) -#pragma omp atomic - munsDbgInfo->depass++; //verify if no bug in calculation -#endif - correctionHuechroma=correctionHue; //preserve - if(lumaMuns) { - float correctlumprov=0.f; - float correctlumprov2=0.f; - if(correctL) { - //for Munsell luminance correction - correctlumprov=correctionHueLum; - contin1=true; - correctL=false; - } - correctionHueLum=0.0; - correctionHue=0.0; - if(fabs(Lprov1-Loldd) > 6.0) { - // correction if delta L significative..Munsell luminance - MunsellLch (Loldd, HH,Chprov1, Chprov1, correctionHue, zo, correctionHueLum, correctL); - - if(correctL) { - correctlumprov2=correctionHueLum; - contin2=true; - correctL=false; - } - correctionHueLum=0.0; - - if(contin1==true && contin2==true) - correctlum=correctlumprov2-correctlumprov; -#ifdef _DEBUG - float absCorrectLum = fabs(correctlum); - if(correctlum !=0.0) { - int idx=zo-1; -#pragma omp critical (maxdhuelum) -{ - munsDbgInfo->maxdhuelum[idx] = MAX(munsDbgInfo->maxdhuelum[idx],absCorrectLum); -} - } - if(absCorrectLum > 0.35) -#pragma omp atomic - munsDbgInfo->depassLum++; //verify if no bug in calculation -#endif - } - } - } - } - } -#ifdef _DEBUG - if (correctlum < -0.35f) correctlum =-0.35f; - else if(correctlum > 0.35f) correctlum = 0.35f; - if (correctionHuechroma<-0.45f) correctionHuechroma=-0.45f; - else if(correctionHuechroma> 0.45f) correctionHuechroma= 0.45f; -#endif + if ( h > 1.f ) { + h -= 1.f; + } + } +} +double Color::hue2rgb(double p, double q, double t) +{ + if (t < 0.) { + t += 6.; + } else if( t > 6.) { + t -= 6.; } - /* - * GamutLchonly correction - * Copyright (c)2012 Jacques Desmis and Jean-Christophe Frisch - * - * This function puts the data (Lab) in the gamut of "working profile": - * it returns the corrected values of the chromaticity and luminance - * - * float HH : hue - * float Lprov1 : input luminance value, sent back corrected - * float Chprov1: input chroma value, sent back corrected - * float R,G,B : red, green and blue value of the corrected color - * double wip : working profile - * bool isHLEnabled : if "highlight reconstruction " is enabled - * float coef : a float number between [0.95 ; 1.0[... the nearest it is from 1.0, the more precise it will be... and the longer too as more iteration will be necessary) - * bool neg and moreRGB : only in DEBUG mode to calculate iterations for negatives values and > 65535 - */ -#ifdef _DEBUG - void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) -#else - void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) -#endif - { - const float ClipLevel = 65535.0f; - bool inGamut; -#ifdef _DEBUG - neg=false, more_rgb=false; -#endif - float2 sincosval = xsincosf(HH); - do { - inGamut=true; + if (t < 1.) { + return p + (q - p) * t; + } else if (t < 3.) { + return q; + } else if (t < 4.) { + return p + (q - p) * (4. - t); + } else { + return p; + } +} - //Lprov1=LL; - float aprov1=Chprov1*sincosval.y; - float bprov1=Chprov1*sincosval.x; +void Color::hsl2rgb (float h, float s, float l, float &r, float &g, float &b) +{ - //conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction - float fy = (0.00862069f *Lprov1 )+ 0.137932f; - float fx = (0.002f * aprov1) + fy; - float fz = fy - (0.005f * bprov1); + if (s == 0) { + r = g = b = 65535.0f * l; // achromatic + } else { + double m2; + double h_ = double(h); + double s_ = double(s); + double l_ = double(l); - float x_ = 65535.0f * f2xyz(fx)*D50x; - // float y_ = 65535.0f * f2xyz(fy); - float z_ = 65535.0f * f2xyz(fz)*D50z; - float y_=(Lprov1>epskap) ? 65535.0*fy*fy*fy : 65535.0*Lprov1/kappa; + if (l <= 0.5f) { + m2 = l_ * (1.0 + s_); + } else { + m2 = l_ + s_ - l_ * s_; + } - xyz2rgb(x_,y_,z_,R,G,B,wip); + double m1 = 2.0 * l_ - m2; - // gamut control before saturation to put Lab values in future gamut, but not RGB - if (R<0.0f || G<0.0f || B<0.0f) { -#ifdef _DEBUG - neg=true; -#endif - if (Lprov1 < 0.1f) Lprov1 = 0.1f; - //gamut for L with ultra blue : we can improve the algorithm ... thinner, and other color ??? - if(HH < -0.9f && HH > -1.55f ) {//ultra blue - if(Chprov1 > 160.f) if (Lprov1 < 5.f) Lprov1 = 5.f;//very very very very high chroma - if(Chprov1 > 140.f) if (Lprov1 < 3.5f) Lprov1 = 3.5f; - if(Chprov1 > 120.f) if (Lprov1 < 2.f) Lprov1 = 2.f; - if(Chprov1 > 105.f) if (Lprov1 < 1.f) Lprov1 = 1.f; - if(Chprov1 > 90.f) if (Lprov1 < 0.7f) Lprov1 = 0.7f; - if(Chprov1 > 50.f) if (Lprov1 < 0.5f) Lprov1 = 0.5f; - if(Chprov1 > 20.f) if (Lprov1 < 0.4f) Lprov1 = 0.4f; - } - Chprov1 *= higherCoef; // decrease the chromaticity value - if (Chprov1 <= 3.0f) - Lprov1 += lowerCoef; - inGamut = false; - } else if (!isHLEnabled && (R>ClipLevel || G>ClipLevel || B>ClipLevel)) { + r = float(65535.0 * hue2rgb (m1, m2, h_ * 6.0 + 2.0)); + g = float(65535.0 * hue2rgb (m1, m2, h_ * 6.0)); + b = float(65535.0 * hue2rgb (m1, m2, h_ * 6.0 - 2.0)); + } +} - // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut -#ifdef _DEBUG - more_rgb=true; -#endif - if (Lprov1 > 99.999f) - Lprov1 = 99.98f; - Chprov1 *= higherCoef; - if (Chprov1 <= 3.0f) - Lprov1 -= lowerCoef; - inGamut = false; - } - } - while (!inGamut); - //end first gamut control +void Color::hsl2rgb01 (float h, float s, float l, float &r, float &g, float &b) +{ + + if (s == 0) { + r = g = b = l; // achromatic + } else { + double m2; + double h_ = double(h); + double s_ = double(s); + double l_ = double(l); + + if (l <= 0.5f) { + m2 = l_ * (1.0 + s_); + } else { + m2 = l_ + s_ - l_ * s_; + } + + double m1 = 2.0 * l_ - m2; + + r = float(hue2rgb (m1, m2, h_ * 6.0 + 2.0)); + g = float(hue2rgb (m1, m2, h_ * 6.0)); + b = float(hue2rgb (m1, m2, h_ * 6.0 - 2.0)); + } +} + +void Color::rgb2hsv(float r, float g, float b, float &h, float &s, float &v) +{ + double var_R = r / 65535.0; + double var_G = g / 65535.0; + double var_B = b / 65535.0; + + double var_Min = min(var_R, var_G, var_B); + double var_Max = max(var_R, var_G, var_B); + double del_Max = var_Max - var_Min; + v = var_Max; + + if (del_Max < 0.00001 && del_Max > -0.00001) { // no fabs, slow! + h = 0; + s = 0; + } else { + s = del_Max / var_Max; + + if ( var_R == var_Max ) { + h = (var_G - var_B) / del_Max; + } else if ( var_G == var_Max ) { + h = 2.0 + (var_B - var_R) / del_Max; + } else if ( var_B == var_Max ) { + h = 4.0 + (var_R - var_G) / del_Max; + } + + h /= 6.0; + + if ( h < 0 ) { + h += 1; + } + + if ( h > 1 ) { + h -= 1; + } + } +} + +void Color::hsv2rgb (float h, float s, float v, float &r, float &g, float &b) +{ + + float h1 = h * 6.f; // sector 0 to 5 + int i = (int)h1; // floor() is very slow, and h1 is always >0 + float f = h1 - i; // fractional part of h + + float p = v * ( 1.f - s ); + float q = v * ( 1.f - s * f ); + float t = v * ( 1.f - s * ( 1.f - f ) ); + + float r1, g1, b1; + + if (i == 1) { + r1 = q; + g1 = v; + b1 = p; + } else if (i == 2) { + r1 = p; + g1 = v; + b1 = t; + } else if (i == 3) { + r1 = p; + g1 = q; + b1 = v; + } else if (i == 4) { + r1 = t; + g1 = p; + b1 = v; + } else if (i == 5) { + r1 = v; + g1 = p; + b1 = q; + } else { /*i==(0|6)*/ + r1 = v; + g1 = t; + b1 = p; } - /* - * GamutLchonly correction - * Copyright (c)2012 Jacques Desmis and Jean-Christophe Frisch - * - * This function puts the data (Lab) in the gamut of "working profile": - * it returns the corrected values of the chromaticity and luminance - * - * float HH : hue - * float2 sincosval : sin and cos of HH - * float Lprov1 : input luminance value, sent back corrected - * float Chprov1: input chroma value, sent back corrected - * float R,G,B : red, green and blue value of the corrected color - * double wip : working profile - * bool isHLEnabled : if "highlight reconstruction " is enabled - * float coef : a float number between [0.95 ; 1.0[... the nearest it is from 1.0, the more precise it will be... and the longer too as more iteration will be necessary) - * bool neg and moreRGB : only in DEBUG mode to calculate iterations for negatives values and > 65535 - */ -#ifdef _DEBUG - void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) -#else - void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) -#endif - { - const float ClipLevel = 65535.0f; - bool inGamut; -#ifdef _DEBUG - neg=false, more_rgb=false; -#endif - do { - inGamut=true; + r = ((r1) * 65535.0f); + g = ((g1) * 65535.0f); + b = ((b1) * 65535.0f); +} - //Lprov1=LL; - float aprov1=Chprov1*sincosval.y; - float bprov1=Chprov1*sincosval.x; +// Function copied for speed concerns +// Not exactly the same as above ; this one return a result in the [0.0 ; 1.0] range +void Color::hsv2rgb01 (float h, float s, float v, float &r, float &g, float &b) +{ + float h1 = h * 6; // sector 0 to 5 + int i = int(h1); + float f = h1 - i; // fractional part of h - //conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction - float fy = (0.00862069f *Lprov1 )+ 0.137932f; - float fx = (0.002f * aprov1) + fy; - float fz = fy - (0.005f * bprov1); + float p = v * ( 1 - s ); + float q = v * ( 1 - s * f ); + float t = v * ( 1 - s * ( 1 - f ) ); - float x_ = 65535.0f * f2xyz(fx)*D50x; - // float y_ = 65535.0f * f2xyz(fy); - float z_ = 65535.0f * f2xyz(fz)*D50z; - float y_=(Lprov1>epskap) ? 65535.0*fy*fy*fy : 65535.0*Lprov1/kappa; + if (i == 1) { + r = q; + g = v; + b = p; + } else if (i == 2) { + r = p; + g = v; + b = t; + } else if (i == 3) { + r = p; + g = q; + b = v; + } else if (i == 4) { + r = t; + g = p; + b = v; + } else if (i == 5) { + r = v; + g = p; + b = q; + } else { /*(i==0|6)*/ + r = v; + g = t; + b = p; + } +} - xyz2rgb(x_,y_,z_,R,G,B,wip); +void Color::hsv2rgb (float h, float s, float v, int &r, int &g, int &b) +{ - // gamut control before saturation to put Lab values in future gamut, but not RGB - if (R<0.0f || G<0.0f || B<0.0f) { -#ifdef _DEBUG - neg=true; -#endif - if (Lprov1 < 0.1f) Lprov1 = 0.1f; - //gamut for L with ultra blue : we can improve the algorithm ... thinner, and other color ??? - if(HH < -0.9f && HH > -1.55f ) {//ultra blue - if(Chprov1 > 160.f) if (Lprov1 < 5.f) Lprov1 = 5.f;//very very very very high chroma - if(Chprov1 > 140.f) if (Lprov1 < 3.5f) Lprov1 = 3.5f; - if(Chprov1 > 120.f) if (Lprov1 < 2.f) Lprov1 = 2.f; - if(Chprov1 > 105.f) if (Lprov1 < 1.f) Lprov1 = 1.f; - if(Chprov1 > 90.f) if (Lprov1 < 0.7f) Lprov1 = 0.7f; - if(Chprov1 > 50.f) if (Lprov1 < 0.5f) Lprov1 = 0.5f; - if(Chprov1 > 20.f) if (Lprov1 < 0.4f) Lprov1 = 0.4f; - } - Chprov1 *= higherCoef; // decrease the chromaticity value - if (Chprov1 <= 3.0f) - Lprov1 += lowerCoef; - inGamut = false; - } else if (!isHLEnabled && (R>ClipLevel || G>ClipLevel || B>ClipLevel)) { + float h1 = h * 6; // sector 0 to 5 + int i = floor( h1 ); + float f = h1 - i; // fractional part of h - // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut -#ifdef _DEBUG - more_rgb=true; -#endif - if (Lprov1 > 99.999f) - Lprov1 = 99.98f; - Chprov1 *= higherCoef; - if (Chprov1 <= 3.0f) - Lprov1 -= lowerCoef; - inGamut = false; - } - } - while (!inGamut); - //end first gamut control + float p = v * ( 1 - s ); + float q = v * ( 1 - s * f ); + float t = v * ( 1 - s * ( 1 - f ) ); + + float r1, g1, b1; + + if (i == 0) { + r1 = v; + g1 = t; + b1 = p; + } else if (i == 1) { + r1 = q; + g1 = v; + b1 = p; + } else if (i == 2) { + r1 = p; + g1 = v; + b1 = t; + } else if (i == 3) { + r1 = p; + g1 = q; + b1 = v; + } else if (i == 4) { + r1 = t; + g1 = p; + b1 = v; + } else if (i == 5) { + r1 = v; + g1 = p; + b1 = q; } + r = (int)( r1 * 65535); + g = (int)( g1 * 65535); + b = (int)( b1 * 65535); +} -#ifdef _DEBUG - void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) -#else - void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) -#endif - { - const float ClipLevel = 65535.0f; - bool inGamut; -#ifdef _DEBUG - neg=false, more_rgb=false; -#endif - do { - inGamut=true; +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //Lprov1=LL; - float aprov1=Chprov1*sincosval.y; - float bprov1=Chprov1*sincosval.x; +void Color::xyz2srgb (float x, float y, float z, float &r, float &g, float &b) +{ - //conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction - float fy = (0.00862069f *Lprov1 )+ 0.137932f; - float fx = (0.002f * aprov1) + fy; - float fz = fy - (0.005f * bprov1); + //Transform to output color. Standard sRGB is D65, but internal representation is D50 + //Note that it is only at this point that we should have need of clipping color data - float x_ = 65535.0f * f2xyz(fx)*D50x; - // float y_ = 65535.0f * f2xyz(fy); - float z_ = 65535.0f * f2xyz(fz)*D50z; - float y_=(Lprov1>epskap) ? 65535.0*fy*fy*fy : 65535.0*Lprov1/kappa; + /*float x65 = d65_d50[0][0]*x + d65_d50[0][1]*y + d65_d50[0][2]*z ; + float y65 = d65_d50[1][0]*x + d65_d50[1][1]*y + d65_d50[1][2]*z ; + float z65 = d65_d50[2][0]*x + d65_d50[2][1]*y + d65_d50[2][2]*z ; - float R,G,B; - xyz2rgb(x_,y_,z_,R,G,B,wip); + r = sRGB_xyz[0][0]*x65 + sRGB_xyz[0][1]*y65 + sRGB_xyz[0][2]*z65; + g = sRGB_xyz[1][0]*x65 + sRGB_xyz[1][1]*y65 + sRGB_xyz[1][2]*z65; + b = sRGB_xyz[2][0]*x65 + sRGB_xyz[2][1]*y65 + sRGB_xyz[2][2]*z65;*/ - // gamut control before saturation to put Lab values in future gamut, but not RGB - if (R<0.0f || G<0.0f || B<0.0f) { -#ifdef _DEBUG - neg=true; -#endif - if (Lprov1 < 0.01f) - Lprov1 = 0.01f; - Chprov1 *= higherCoef; // decrease the chromaticity value - if (Chprov1 <= 3.0f) - Lprov1 += lowerCoef; - inGamut = false; - } else if (!isHLEnabled && (R>ClipLevel || G>ClipLevel || B>ClipLevel)) { + /*r = sRGBd65_xyz[0][0]*x + sRGBd65_xyz[0][1]*y + sRGBd65_xyz[0][2]*z ; + g = sRGBd65_xyz[1][0]*x + sRGBd65_xyz[1][1]*y + sRGBd65_xyz[1][2]*z ; + b = sRGBd65_xyz[2][0]*x + sRGBd65_xyz[2][1]*y + sRGBd65_xyz[2][2]*z ;*/ - // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut -#ifdef _DEBUG - more_rgb=true; -#endif - if (Lprov1 > 99.999f) - Lprov1 = 99.98f; - Chprov1 *= higherCoef; - if (Chprov1 <= 3.0f) - Lprov1 -= lowerCoef; - inGamut = false; - } - } - while (!inGamut); - //end first gamut control + r = ((sRGB_xyz[0][0] * x + sRGB_xyz[0][1] * y + sRGB_xyz[0][2] * z)) ; + g = ((sRGB_xyz[1][0] * x + sRGB_xyz[1][1] * y + sRGB_xyz[1][2] * z)) ; + b = ((sRGB_xyz[2][0] * x + sRGB_xyz[2][1] * y + sRGB_xyz[2][2] * z)) ; + +} +void Color::xyz2Prophoto (float x, float y, float z, float &r, float &g, float &b) +{ + r = ((prophoto_xyz[0][0] * x + prophoto_xyz[0][1] * y + prophoto_xyz[0][2] * z)) ; + g = ((prophoto_xyz[1][0] * x + prophoto_xyz[1][1] * y + prophoto_xyz[1][2] * z)) ; + b = ((prophoto_xyz[2][0] * x + prophoto_xyz[2][1] * y + prophoto_xyz[2][2] * z)) ; +} +void Color::Prophotoxyz (float r, float g, float b, float &x, float &y, float &z) +{ + x = ((xyz_prophoto[0][0] * r + xyz_prophoto[0][1] * g + xyz_prophoto[0][2] * b)) ; + y = ((xyz_prophoto[1][0] * r + xyz_prophoto[1][1] * g + xyz_prophoto[1][2] * b)) ; + z = ((xyz_prophoto[2][0] * r + xyz_prophoto[2][1] * g + xyz_prophoto[2][2] * b)) ; +} + +void Color::rgbxyz (float r, float g, float b, float &x, float &y, float &z, const double xyz_rgb[3][3]) +{ + x = ((xyz_rgb[0][0] * r + xyz_rgb[0][1] * g + xyz_rgb[0][2] * b)) ; + y = ((xyz_rgb[1][0] * r + xyz_rgb[1][1] * g + xyz_rgb[1][2] * b)) ; + z = ((xyz_rgb[2][0] * r + xyz_rgb[2][1] * g + xyz_rgb[2][2] * b)) ; +} + +void Color::rgbxyz (float r, float g, float b, float &x, float &y, float &z, const float xyz_rgb[3][3]) +{ + x = ((xyz_rgb[0][0] * r + xyz_rgb[0][1] * g + xyz_rgb[0][2] * b)) ; + y = ((xyz_rgb[1][0] * r + xyz_rgb[1][1] * g + xyz_rgb[1][2] * b)) ; + z = ((xyz_rgb[2][0] * r + xyz_rgb[2][1] * g + xyz_rgb[2][2] * b)) ; +} + +void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]) +{ + //Transform to output color. Standard sRGB is D65, but internal representation is D50 + //Note that it is only at this point that we should have need of clipping color data + + /*float x65 = d65_d50[0][0]*x + d65_d50[0][1]*y + d65_d50[0][2]*z ; + float y65 = d65_d50[1][0]*x + d65_d50[1][1]*y + d65_d50[1][2]*z ; + float z65 = d65_d50[2][0]*x + d65_d50[2][1]*y + d65_d50[2][2]*z ; + + r = sRGB_xyz[0][0]*x65 + sRGB_xyz[0][1]*y65 + sRGB_xyz[0][2]*z65; + g = sRGB_xyz[1][0]*x65 + sRGB_xyz[1][1]*y65 + sRGB_xyz[1][2]*z65; + b = sRGB_xyz[2][0]*x65 + sRGB_xyz[2][1]*y65 + sRGB_xyz[2][2]*z65;*/ + + /*r = sRGBd65_xyz[0][0]*x + sRGBd65_xyz[0][1]*y + sRGBd65_xyz[0][2]*z ; + g = sRGBd65_xyz[1][0]*x + sRGBd65_xyz[1][1]*y + sRGBd65_xyz[1][2]*z ; + b = sRGBd65_xyz[2][0]*x + sRGBd65_xyz[2][1]*y + sRGBd65_xyz[2][2]*z ;*/ + + r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ; + g = ((rgb_xyz[1][0] * x + rgb_xyz[1][1] * y + rgb_xyz[1][2] * z)) ; + b = ((rgb_xyz[2][0] * x + rgb_xyz[2][1] * y + rgb_xyz[2][2] * z)) ; +} + +// same for float +void Color::xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3]) +{ + r = ((rgb_xyz[0][0] * x + rgb_xyz[0][1] * y + rgb_xyz[0][2] * z)) ; + g = ((rgb_xyz[1][0] * x + rgb_xyz[1][1] * y + rgb_xyz[1][2] * z)) ; + b = ((rgb_xyz[2][0] * x + rgb_xyz[2][1] * y + rgb_xyz[2][2] * z)) ; +} + +void Color::trcGammaBW (float &r, float &g, float &b, float gammabwr, float gammabwg, float gammabwb) +{ + // correct gamma for black and white image : pseudo TRC curve of ICC profil + b /= 65535.0f; + b = pow (max(b, 0.0f), gammabwb); + b *= 65535.0f; + r /= 65535.0f; + r = pow (max(r, 0.0f), gammabwr); + r *= 65535.0f; + g /= 65535.0f; + g = pow (max(g, 0.0f), gammabwg); + g *= 65535.0f; +} + +/** @brief Compute the B&W constants for the B&W processing and its tool's GUI + * + * @param setting BlackWhite::setting + * @param setting BlackWhite::filter + */ +void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::ustring &filter, const Glib::ustring &algo, float &filcor, float &mixerRed, float &mixerGreen, + float &mixerBlue, float mixerOrange, float mixerYellow, float mixerCyan, float mixerPurple, float mixerMagenta, + bool autoc, bool complement, float &kcorec, double &rrm, double &ggm, double &bbm) +{ + float somm; + float som = mixerRed + mixerGreen + mixerBlue; + + // rM = mixerRed, gM = mixerGreen, bM = mixerBlue ! + //presets + if (setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { + kcorec = som / 100.f; } - /* - * LabGamutMunsell - * Copyright (c) 2012 Jacques Desmis - * - * This function is the overall Munsell's corrections, but only on global statement: I think it's better to use local statement with AllMunsellLch - * not for use in a "for" or "do while" loop - * they are named accordingly : gamutLchonly and AllMunsellLch - * it can be used before and after treatment (saturation, gamma, luminance, ...) - * - * Parameters: - * float *labL : RT Lab L channel data - * float *laba : RT Lab a channel data - * float *labb : RT Lab b channel data - * bool corMunsell : performs Munsell correction - * bool lumaMuns : (used only if corMuns=true) - * true: apply luma + chroma Munsell correction if delta L > 10; - * false: only chroma correction only - * bool gamut : performs gamutLch - * const double wip[3][3]: matrix for working profile - * bool multiThread : parallelize the loop - */ -SSEFUNCTION void Color::LabGamutMunsell(float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3], bool multiThread ) { -#ifdef _DEBUG - MyTime t1e,t2e; - t1e.set(); - int negat=0, moreRGB=0; - MunsellDebugInfo* MunsDebugInfo=NULL; - if (corMunsell) - MunsDebugInfo = new MunsellDebugInfo(); -#endif - float correctlum = 0.f; - float correctionHuechroma = 0.f; -#ifdef __SSE2__ - // precalculate H and C using SSE - float HHBuffer[N]; - float CCBuffer[N]; - __m128 c327d68v = _mm_set1_ps(327.68f); - __m128 av,bv; - int k; - for (k=0; k= 33) { + orM = fcompl * (mixerOrange * 0.67f - 22.11f) / 100.f; } else { - HH+=correctlum; //hue Munsell luminance correction - sincosval = xsincosf(HH+correctionHuechroma); + orM = fcompl * (-0.3f * mixerOrange + 9.9f) / 100.f; } - laba[j] = Chprov1*sincosval.y*327.68f; - labb[j] = Chprov1*sincosval.x*327.68f; + + if (mixerOrange >= 33) { + ogM = fcompl * (-0.164f * mixerOrange + 5.412f) / 100.f; + } else { + ogM = fcompl * (0.4f * mixerOrange - 13.2f) / 100.f; + } + } else if (algo == "LI") { //linear + orM = fcompl * (mixerOrange - 33.f) / 100.f; + ogM = fcompl * (0.5f * mixerOrange - 16.5f) / 100.f; } -#ifdef _DEBUG - t2e.set(); - if (settings->verbose) { - printf("Color::LabGamutMunsell (correction performed in %d usec):\n", t2e.etime(t1e)); - printf(" Gamut : G1negat=%iiter G165535=%iiter \n",negat,moreRGB); - if (MunsDebugInfo) { - printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass); - printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhuelum[0] ,MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum); - } - else { - printf(" Munsell correction wasn't requested\n"); + if(complement) { + obM = (-0.492f * mixerOrange + 16.236f) / 100.f; } + + mixerRed += orM; + mixerGreen += ogM; + mixerBlue += obM; + koymcp += (orM + ogM + obM); + // printf("mixred+ORange=%f\n",mixerRed); + } - if (MunsDebugInfo) - delete MunsDebugInfo; + + if(mixerYellow != 33) { + if (algo == "SP") { + yrM = fcompl * (-0.134f * mixerYellow + 4.422f) / 100.f; //22.4 + } else if (algo == "LI") { + yrM = fcompl * (0.5f * mixerYellow - 16.5f) / 100.f; //22.4 + } + + ygM = fcompl * (0.5f * mixerYellow - 16.5f ) / 100.f; + + if(complement) { + ybM = (-0.492f * mixerYellow + 16.236f) / 100.f; + } + + mixerRed += yrM; + mixerGreen += ygM; + mixerBlue += ybM; + koymcp += (yrM + ygM + ybM); + } + + if(mixerMagenta != 33) { + if (algo == "SP") { + if(mixerMagenta >= 33) { + mrM = fcompl * ( 0.67f * mixerMagenta - 22.11f) / 100.f; + } else { + mrM = fcompl * (-0.3f * mixerMagenta + 9.9f) / 100.f; + } + + if(mixerMagenta >= 33) { + mbM = fcompl * (-0.164f * mixerMagenta + 5.412f) / 100.f; + } else { + mbM = fcompl * ( 0.4f * mixerMagenta - 13.2f) / 100.f; + } + } else if (algo == "LI") { + mrM = fcompl * (mixerMagenta - 33.f) / 100.f; + mbM = fcompl * (0.5f * mixerMagenta - 16.5f) / 100.f; + } + + if(complement) { + mgM = (-0.492f * mixerMagenta + 16.236f) / 100.f; + } + + mixerRed += mrM; + mixerGreen += mgM; + mixerBlue += mbM; + koymcp += (mrM + mgM + mbM); + } + + if(mixerPurple != 33) { + if (algo == "SP") { + prM = fcompl * (-0.134f * mixerPurple + 4.422f) / 100.f; + } else if (algo == "LI") { + prM = fcompl * (0.5f * mixerPurple - 16.5f) / 100.f; + } + + pbM = fcompl * (0.5f * mixerPurple - 16.5f) / 100.f; + + if(complement) { + pgM = (-0.492f * mixerPurple + 16.236f) / 100.f; + } + + mixerRed += prM; + mixerGreen += pgM; + mixerBlue += pbM; + koymcp += (prM + pgM + pbM); + } + + if(mixerCyan != 33) { + if (algo == "SP") { + cgM = fcompl * (-0.134f * mixerCyan + 4.422f) / 100.f; + } else if (algo == "LI") { + cgM = fcompl * (0.5f * mixerCyan - 16.5f) / 100.f; + } + + cbM = fcompl * (0.5f * mixerCyan - 16.5f) / 100.f; + + if(complement) { + crM = (-0.492f * mixerCyan + 16.236f) / 100.f; + } + + mixerRed += crM; + mixerGreen += cgM; + mixerBlue += cbM; + koymcp += (crM + cgM + cbM); + } + } + + if(setting == "ROYGCBPM-Abs") { + kcorec = koymcp + som / 100.f; + } + + //Color filters + float filred, filgreen, filblue; + filred = 1.f; + filgreen = 1.f; + filblue = 1.f; + filcor = 1.f; + + if (filter == "None") { + filred = 1.f; + filgreen = 1.f; + filblue = 1.f; + filcor = 1.f; + } else if (filter == "Red") { + filred = 1.f; + filgreen = 0.05f; + filblue = 0.f; + filcor = 1.08f; + } else if (filter == "Orange") { + filred = 1.f; + filgreen = 0.6f; + filblue = 0.f; + filcor = 1.35f; + } else if (filter == "Yellow") { + filred = 1.f; + filgreen = 1.f; + filblue = 0.05f; + filcor = 1.23f; + } else if (filter == "YellowGreen") { + filred = 0.6f; + filgreen = 1.f; + filblue = 0.3f; + filcor = 1.32f; + } else if (filter == "Green") { + filred = 0.2f; + filgreen = 1.f; + filblue = 0.3f; + filcor = 1.41f; + } else if (filter == "Cyan") { + filred = 0.05f; + filgreen = 1.f; + filblue = 1.f; + filcor = 1.23f; + } else if (filter == "Blue") { + filred = 0.f; + filgreen = 0.05f; + filblue = 1.f; + filcor = 1.20f; + } else if (filter == "Purple") { + filred = 1.f; + filgreen = 0.05f; + filblue = 1.f; + filcor = 1.23f; + } + + mixerRed = mixerRed * filred; + mixerGreen = mixerGreen * filgreen; + mixerBlue = mixerBlue * filblue; + + mixerRed = filcor * mixerRed / (mixerRed + mixerGreen + mixerBlue); + mixerGreen = filcor * mixerGreen / (mixerRed + mixerGreen + mixerBlue); + mixerBlue = filcor * mixerBlue / (mixerRed + mixerGreen + mixerBlue); + + if(filter != "None") { + som = mixerRed + mixerGreen + mixerBlue; + + if(setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { + kcorec = kcorec * som; + } + } + +} + +void Color::interpolateRGBColor (const float balance, const float r1, const float g1, const float b1, const float r2, const float g2, const float b2, int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo) +{ + float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z; + float L1, L2, a_1, b_1, a_2, b_2, a, b; + float c1, c2, h1, h2; + float RR, GG, BB; + float Lr; + + // converting color 1 to Lch + Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); + Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1); + Color::Lab2Lch(a_1, b_1, c1, h1); + Lr = L1 / 327.68f; //for gamutlch + //gamut control on r1 g1 b1 +#ifndef NDEBUG + bool neg = false; + bool more_rgb = false; + + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); +#else + Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); #endif + L1 = Lr * 327.68f; + + // converting color 2 to Lch + Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb); + Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2); + Color::Lab2Lch(a_2, b_2, c2, h2); + + Lr = L2 / 327.68f; //for gamutlch + //gamut control on r2 g2 b2 +#ifndef NDEBUG + neg = false; + more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(h2, Lr, c2, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); +#else + Color::gamutLchonly(h2, Lr, c2, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); +#endif + L2 = Lr * 327.68f; + + // interpolating Lch values + if (toDo & CHANNEL_LIGHTNESS) { + L1 = L1 + (L2 - L1) * balance; //do not allow negative L + + if(L1 < 0.f) { + L1 = 0.f; + } } - /* - * MunsellLch correction - * Copyright (c) 2012 Jacques Desmis - * - * Find the right LUT and calculate the correction - */ - void Color::MunsellLch (float lum, float hue, float chrom, float memChprov, float &correction, int zone, float &lbe, bool &correctL) { + if (toDo & CHANNEL_CHROMATICITY) { + c1 = c1 + (c2 - c1) * balance; //limit C to reasonable value - int x = int(memChprov); - int y = int(chrom); - - //begin PB correction + sky - if(zone==1) { - if(lum > 5.0) { - if(lum <15.0) { - if( (hue >= (_15PB10[x] - 0.035)) && (hue < (_15PB10[x] + 0.052) && x<=45)) {if(y>49) y=49;correction = _15PB10[y] - _15PB10[x] ;lbe=_15PB10[y];correctL=true;} - else if (( hue>=( _3PB10[x] -0.052)) && (hue < (_45PB10[x] + _3PB10[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _3PB10[y] - _3PB10[x]; lbe =_3PB10[y];correctL=true;} - else if (( hue>=(_45PB10[x] + _3PB10[x])/2.0) && (hue < (_45PB10[x] +0.052)) && x <= 85) {if(y>89) y=89;correction = _45PB10[y] - _45PB10[x] ;lbe=_45PB10[y];correctL=true;} - else if (( hue>=(_6PB10[x] -0.052) && (hue < (_6PB10[x] + _75PB10[x])/2.0))) {correction = _6PB10[y] - _6PB10[x] ;lbe=_6PB10[y];correctL=true;} - else if (( hue>=(_6PB10[x] + _75PB10[x])/2.0) && (hue < (_9PB10[x] + _75PB10[x])/2.0)) {correction = _75PB10[y] - _75PB10[x] ;lbe=_75PB10[y];correctL=true;} - else if (( hue>=(_9PB10[x] + _75PB10[x])/2.0) && (hue < (_9PB10[x] + _10PB10[x])/2.0)) {correction = _9PB10[y] - _9PB10[x] ; lbe=_9PB10[y];correctL=true;} - else if (( hue>=(_10PB10[x] + _9PB10[x])/2.0) && (hue < (_1P10[x] + _10PB10[x])/2.0)) {correction = _10PB10[y] - _10PB10[x] ;lbe=_10PB10[y];correctL=true;} - else if (( hue>=(_10PB10[x] + _1P10[x])/2.0) && (hue < (_1P10[x] + _4P10[x])/2.0)) {correction = _1P10[y] - _1P10[x];lbe=_1P10[y];correctL=true;} - else if (( hue>=(_1P10[x] + _4P10[x])/2.0) && (hue < (0.035 + _4P10[x])/2.0)) {correction = _4P10[y] - _4P10[x] ;lbe=_4P10[y];correctL=true;} - } - else if (lum <25.0) { - if( (hue >= (_15PB20[x] - 0.035)) && (hue < (_15PB20[x] + _3PB20[x])/2.0) && x<=85) {if(y>89) y=89;correction = _15PB20[y] - _15PB20[x] ;lbe= _15PB20[y];correctL=true;} - else if (( hue>=(_15PB20[x] + _3PB20[x])/2.0) && (hue < (_45PB20[x] + _3PB20[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _3PB20[y] - _3PB20[x] ;lbe= _3PB20[y];correctL=true;} - else if (( hue>=(_45PB20[x] + _3PB20[x])/2.0) && (hue < ( _45PB20[x] + 0.052)) && x <= 85) {if(y>89) y=89;correction = _45PB20[y] - _45PB20[x] ;lbe=_45PB20[y];correctL=true;} - else if (( hue>=(_45PB20[x] + 0.052)) && (hue < (_6PB20[x] + _75PB20[x])/2.0)) {correction = _6PB20[y] - _6PB20[x];lbe=_6PB20[y];correctL=true;} - else if (( hue>=(_6PB20[x] + _75PB20[x])/2.0) && (hue < (_9PB20[x] + _75PB20[x])/2.0)) {correction = _75PB20[y] - _75PB20[x] ;lbe=_75PB20[y];correctL=true;} - else if (( hue>=(_9PB20[x] + _75PB20[x])/2.0) && (hue < (_9PB20[x] + _10PB20[x])/2.0)) {correction = _9PB20[y] - _9PB20[x] ;lbe= _9PB20[y];correctL=true; } - else if (( hue>=(_10PB20[x] + _9PB20[x])/2.0) && (hue < (_1P20[x] + _10PB20[x])/2.0)) {correction = _10PB20[y] - _10PB20[x] ;lbe= _10PB20[y];correctL=true;} - else if (( hue>=(_10PB20[x] + _1P20[x])/2.0) && (hue < (_1P20[x] + _4P20[x])/2.0)) {correction = _1P20[y] - _1P20[x] ; lbe=_1P20[y];correctL=true;} - else if (( hue>=(_1P20[x] + _4P20[x])/2.0) && (hue < (0.035 + _4P20[x])/2.0)) {correction = _4P20[y] - _4P20[x] ; lbe=_4P20[y];correctL=true;} - } - else if (lum <35.0) { - if( (hue >= (_15PB30[x] - 0.035)) && (hue < (_15PB30[x] + _3PB30[x])/2.0) && x<=85 ) {if(y>89) y=89;correction = _15PB30[y] - _15PB30[x] ;lbe=_15PB30[y];correctL=true;} - else if (( hue>=(_15PB30[x] + _3PB30[x])/2.0) && (hue < (_45PB30[x] + _3PB30[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _3PB30[y] - _3PB30[x] ;lbe=_3PB30[y];correctL=true;} - else if (( hue>=(_45PB30[x] + _3PB30[x])/2.0) && (hue < (_45PB30[x]+0.052)) && x <= 85) {if(y>89) y=89;correction = _45PB30[y] - _45PB30[x] ;lbe= _45PB30[y];correctL=true;} - else if (( hue>=( _45PB30[x]+ 0.052)) && (hue < (_6PB30[x] + _75PB30[x])/2.0)) {correction = _6PB30[y] - _6PB30[x] ; lbe=_6PB30[y];correctL=true;} - else if (( hue>=(_6PB30[x] + _75PB30[x])/2.0) && (hue < (_9PB30[x] + _75PB30[x])/2.0)) {correction = _75PB30[y] - _75PB30[x] ;lbe= _75PB30[y] ;correctL=true;} - else if (( hue>=(_9PB30[x] + _75PB30[x])/2.0) && (hue < (_9PB30[x] + _10PB30[x])/2.0)) {correction = _9PB30[y] - _9PB30[x] ;lbe=_9PB30[y]; correctL=true;} - else if (( hue>=(_10PB30[x] + _9PB30[x])/2.0) && (hue < (_1P30[x] + _10PB30[x])/2.0)) {correction = _10PB30[y] - _10PB30[x] ;lbe=_10PB30[y];correctL=true;} - else if (( hue>=(_10PB30[x] + _1P30[x])/2.0) && (hue < (_1P30[x] + _4P30[x])/2.0)) {correction = _1P30[y] - _1P30[x] ;lbe=_1P30[y];correctL=true; } - else if (( hue>=(_1P30[x] + _4P30[x])/2.0) && (hue < (0.035 + _4P30[x])/2.0)) {correction = _4P30[y] - _4P30[x] ;lbe=_4P30[y];correctL=true;} - } - else if (lum <45.0) { - if( (hue <= (_05PB40[x] + _15PB40[x])/2.0) && (hue > (_05PB40[x] + _10B40[x])/2.0) && x<75 ) {if(y>75) y=75; correction = _05PB40[y] - _05PB40[x] ;lbe=_05PB40[y];correctL=true;} - else if( (hue <= (_05PB40[x] + _10B40[x])/2.0) && (hue >(_10B40[x] + _9B40[x])/2.0) && x<70 ) {if(y>70) y=70;correction = _10B40[y] - _10B40[x] ;lbe=_10B40[y];correctL=true;} - else if( (hue <= (_10B40[x] + _9B40[x])/2.0) && (hue >(_9B40[x] + _7B40[x])/2.0) && x<70 ) {if(y>70) y=70;correction = _9B40[y] - _9B40[x] ;lbe=_9B40[y];correctL=true;} - else if( (hue <= (_9B40[x] + _7B40[x])/2.0) && (hue >(_5B40[x] + _7B40[x])/2.0) && x<70 ) {if(y>70) y=70;correction = _7B40[y] - _7B40[x] ;lbe= _7B40[y];correctL=true;} - else if (( hue<=(_5B40[x] + _7B40[x])/2.0) && (hue > (_5B40[x]-0.035)) && x < 70) {if(y>70) y=70; correction = _5B40[y] - _5B40[x] ;lbe= _5B40[y];correctL=true;} // - - else if( (hue >= (_15PB40[x] - 0.035)) && (hue < (_15PB40[x] + _3PB40[x])/2.0) && x<=85 ) {if(y>89) y=89;correction = _15PB40[y] - _15PB40[x] ; lbe= _15PB40[y];correctL=true;} - else if (( hue>=(_15PB40[x] + _3PB40[x])/2.0) && (hue < (_45PB40[x] + _3PB40[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _3PB40[y] - _3PB40[x] ;lbe=_3PB40[y];correctL=true;} - else if (( hue>=(_45PB40[x] + _3PB40[x])/2.0) && (hue < (_45PB40[x]+0.052)) && x <= 85) {if(y>89) y=89;correction = _45PB40[y] - _45PB40[x] ;lbe=_45PB40[y] ;correctL=true;} - else if (( hue>=(_45PB40[x]+0.052)) && (hue < (_6PB40[x] + _75PB40[x])/2.0)) {correction = _6PB40[y] - _6PB40[x] ;lbe=_6PB40[y];correctL=true; } - else if (( hue>=(_6PB40[x] + _75PB40[x])/2.0) && (hue < (_9PB40[x] + _75PB40[x])/2.0)) {correction = _75PB40[y] - _75PB40[x] ; lbe=_75PB40[y];correctL=true;} - else if (( hue>=(_9PB40[x] + _75PB40[x])/2.0) && (hue < (_9PB40[x] + _10PB40[x])/2.0)) {correction = _9PB40[y] - _9PB40[x] ;lbe= _9PB40[y]; correctL=true;} - else if (( hue>=(_10PB40[x] + _9PB40[x])/2.0) && (hue < (_1P40[x] + _10PB40[x])/2.0)) {correction = _10PB40[y] - _10PB40[x] ;lbe=_10PB40[y];correctL=true;} - else if (( hue>=(_10PB40[x] + _1P40[x])/2.0) && (hue < (_1P40[x] + _4P40[x])/2.0)) {correction = _1P40[y] - _1P40[x] ;lbe=_1P40[y];correctL=true;} - else if (( hue>=(_1P40[x] + _4P40[x])/2.0) && (hue < (0.035 + _4P40[x])/2.0)) {correction = _4P40[y] - _4P40[x] ;lbe= _4P40[y];correctL=true;} - } - else if (lum <55.0) { - if( (hue <= (_05PB50[x] + _15PB50[x])/2.0) && (hue > (_05PB50[x] + _10B50[x])/2.0) && x<79 ) {if(y>79) y=79; correction = _05PB50[y] - _05PB50[x] ;lbe= _05PB50[y];correctL=true;} - else if( (hue <= (_05PB50[x] + _10B50[x])/2.0) && (hue >(_10B50[x] + _9B50[x])/2.0) && x<79 ) {if(y>79) y=79;correction = _10B50[y] - _10B50[x] ;lbe=_10B50[y];correctL=true;} - else if( (hue <= (_10B50[x] + _9B50[x])/2.0) && (hue >(_9B50[x] + _7B50[x])/2.0) && x<79 ) {if(y>79) y=79;correction = _9B50[y] - _9B50[x] ;lbe=_9B50[y];correctL=true;} - else if( (hue <= (_9B50[x] + _7B50[x])/2.0) && (hue >(_5B50[x] + _7B50[x])/2.0) && x<79 ) {if(y>79) y=79;correction = _7B50[y] - _7B50[x] ;lbe=_7B50[y];correctL=true;} - else if (( hue<=(_5B50[x] + _7B50[x])/2.0) && (hue > (_5B50[x]-0.035)) && x < 79) {if(y>79) y=79; correction = _5B50[y] - _5B50[x] ;lbe=_5B50[y];correctL=true; } // - - else if( (hue >= (_15PB50[x] - 0.035)) && (hue < (_15PB50[x] + _3PB50[x])/2.0) && x<=85 ) {if(y>89) y=89;correction = _15PB50[y] - _15PB50[x] ; lbe= _15PB50[y];correctL=true;} - else if (( hue>=(_15PB50[x] + _3PB50[x])/2.0) && (hue < (_45PB50[x] + _3PB50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _3PB50[y] - _3PB50[x] ;lbe=_3PB50[y];correctL=true;} - else if (( hue>=(_45PB50[x] + _3PB50[x])/2.0) && (hue < (_6PB50[x] + _45PB50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _45PB50[y] - _45PB50[x] ;lbe=_45PB50[y];correctL=true; } - else if (( hue>=(_6PB50[x] + _45PB50[x])/2.0) && (hue < (_6PB50[x] + _75PB50[x])/2.0) && x <=85) {if(y>89) y=89;correction = _6PB50[y] - _6PB50[x] ;lbe=_6PB50[y];correctL=true;} - else if (( hue>=(_6PB50[x] + _75PB50[x])/2.0) && (hue < (_9PB50[x] + _75PB50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _75PB50[y] - _75PB50[x] ;lbe=_75PB50[y];correctL=true;} - else if (( hue>=(_9PB50[x] + _75PB50[x])/2.0) && (hue < (_9PB50[x] + _10PB50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _9PB50[y] - _9PB50[x] ;lbe=_9PB50[y];correctL=true;} - else if (( hue>=(_10PB50[x] + _9PB50[x])/2.0) && (hue < (_1P50[x] + _10PB50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _10PB50[y] - _10PB50[x] ;lbe=_10PB50[y];correctL=true;} - else if (( hue>=(_10PB50[x] + _1P50[x])/2.0) && (hue < (_1P50[x] + _4P50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _1P50[y] - _1P50[x] ;lbe=_1P50[y];correctL=true; } - else if (( hue>=(_1P50[x] + _4P50[x])/2.0) && (hue < (0.035 + _4P50[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _4P50[y] - _4P50[x] ;lbe=_4P50[y];correctL=true;} - } - else if (lum <65.0) { - if( (hue <= (_05PB60[x] + _15PB60[x])/2.0) && (hue > (_05PB60[x] + _10B60[x])/2.0) && x<79 ) {if(y>79) y=79; correction = _05PB60[y] - _05PB60[x] ;lbe=_05PB60[y];correctL=true;} - else if( (hue <= (_05PB60[x] + _10B60[x])/2.0) && (hue >(_10B60[x] + _9B60[x])/2.0) && x<79 ) {if(y>79) y=79;correction = _10B60[y] - _10B60[x] ;lbe= _10B60[y];correctL=true;} - else if( (hue <= (_10B60[x] + _9B60[x])/2.0) && (hue >(_9B60[x] + _7B60[x])/2.0) && x<79 ) {if(y>79) y=79;correction = _9B60[y] - _9B60[x] ;lbe=_9B60[y];correctL=true;} - else if( (hue <= (_9B60[x] + _7B60[x])/2.0) && (hue >(_5B60[x] + _7B60[x])/2.0) && x<79 ) {if(y>79) y=79;correction = _7B60[y] - _7B60[x] ;lbe= _7B60[y];correctL=true;} - else if (( hue<=(_5B60[x] + _7B60[x])/2.0) && (hue > (_5B60[x]-0.035)) && x < 79) {if(y>79) y=79; correction = _5B60[y] - _5B60[x] ;lbe= _5B60[y];correctL=true;} // - - else if( (hue >= (_15PB60[x] - 0.035)) && (hue < (_15PB60[x] + _3PB60[x])/2.0) && x<=85 ) {if(y>89) y=89;correction = _15PB60[y] - _15PB60[x] ;lbe=_15PB60[y];correctL=true; } - else if (( hue>=(_15PB60[x] + _3PB60[x])/2.0) && (hue < (_45PB60[x] + _3PB60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _3PB60[y] - _3PB60[x] ;lbe=_3PB60[y];correctL=true;} - else if (( hue>=(_45PB60[x] + _3PB60[x])/2.0) && (hue < (_6PB60[x] + _45PB60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _45PB60[y] - _45PB60[x] ;lbe=_45PB60[y];correctL=true;} - else if (( hue>=(_6PB60[x] + _45PB60[x])/2.0) && (hue < (_6PB60[x] + _75PB60[x])/2.0) && x <=85) {if(y>89) y=89;correction = _6PB60[y] - _6PB60[x] ;lbe= _6PB60[y];correctL=true;} - else if (( hue>=(_6PB60[x] + _75PB60[x])/2.0) && (hue < (_9PB60[x] + _75PB60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _75PB60[y] - _75PB60[x] ;lbe= _75PB60[y];correctL=true;} - else if (( hue>=(_9PB60[x] + _75PB60[x])/2.0) && (hue < (_9PB60[x] + _10PB60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _9PB60[y] - _9PB60[x] ;lbe= _9PB60[y];correctL=true;} - else if (( hue>=(_10PB60[x] + _9PB60[x])/2.0) && (hue < (_1P60[x] + _10PB60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _10PB60[y] - _10PB60[x] ;lbe=_10PB60[y]; correctL=true;} - else if (( hue>=(_10PB60[x] + _1P60[x])/2.0) && (hue < (_1P60[x] + _4P60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _1P60[y] - _1P60[x] ; lbe= _1P60[y];correctL=true;} - else if (( hue>=(_1P60[x] + _4P60[x])/2.0) && (hue < (0.035 + _4P60[x])/2.0) && x <= 85) {if(y>89) y=89;correction = _4P60[y] - _4P60[x] ;lbe=_4P60[y];correctL=true; } - } - else if (lum < 75.0) { - if( (hue <= (_05PB70[x] + _15PB70[x])/2.0) && (hue > (_05PB70[x] + _10B70[x])/2.0) && x<50 ) {if(y>49) y=49; correction = _05PB70[y] - _05PB70[x] ;lbe=_05PB70[y];correctL=true;} - else if( (hue <= (_05PB70[x] + _10B70[x])/2.0) && (hue >(_10B70[x] + _9B70[x])/2.0) && x<50 ) {if(y>49) y=49;correction = _10B70[y] - _10B70[x] ;lbe=_10B70[y];correctL=true;} - else if( (hue <= (_10B70[x] + _9B70[x])/2.0) && (hue >(_9B70[x] + _7B70[x])/2.0) && x<50 ) {if(y>49) y=49;correction = _9B70[y] - _9B70[x] ;lbe= _9B70[y];correctL=true;} - else if( (hue <= (_9B70[x] + _7B70[x])/2.0) && (hue >(_5B70[x] + _7B70[x])/2.0) && x<50 ) {if(y>49) y=49;correction = _7B70[y] - _7B70[x] ;lbe=_7B70[y];correctL=true;} - else if (( hue<=(_5B70[x] + _7B70[x])/2.0) && (hue > (_5B70[x]-0.035)) && x < 50) {if(y>49) y=49; correction = _5B70[y] - _5B70[x] ;lbe= _5B70[y];correctL=true;} // - - else if( (hue >= (_15PB70[x] - 0.035)) && (hue < (_15PB70[x] + _3PB70[x])/2.0) && x<50 ) {if(y>49) y=49;correction = _15PB70[y] - _15PB70[x] ;lbe=_15PB70[y];correctL=true; } - else if (( hue>=(_45PB70[x] + _3PB70[x])/2.0) && (hue < (_6PB70[x] + _45PB70[x])/2.0) && x < 50) {if(y>49) y=49;correction = _45PB70[y] - _45PB70[x] ;lbe=_45PB70[y];correctL=true;} - else if (( hue>=(_6PB70[x] + _45PB70[x])/2.0) && (hue < (_6PB70[x] + _75PB70[x])/2.0) && x <50) {if(y>49) y=49;correction = _6PB70[y] - _6PB70[x] ;lbe=_6PB70[y];correctL=true;} - else if (( hue>=(_6PB70[x] + _75PB70[x])/2.0) && (hue < (_9PB70[x] + _75PB70[x])/2.0) && x <50) {if(y>49) y=49;correction = _75PB70[y] - _75PB70[x] ;lbe=_75PB70[y];correctL=true; } - else if (( hue>=(_9PB70[x] + _75PB70[x])/2.0) && (hue < (_9PB70[x] + 0.035)) && x <50) {if(y>49) y=49;correction = _9PB70[y] - _9PB70[x] ;lbe=_9PB70[y];correctL=true;} - } - else if (lum < 85.0) { - if( (hue <= (_05PB80[x] + _15PB80[x])/2.0) && (hue > (_05PB80[x] + _10B80[x])/2.0) && x<40 ) {if(y>39) y=39; correction = _05PB80[y] - _05PB80[x] ;lbe=_05PB80[y] ;correctL=true;} - else if( (hue <= (_05PB80[x] + _10B80[x])/2.0) && (hue >(_10B80[x] + _9B80[x])/2.0) && x<40 ) {if(y>39) y=39;correction = _10B80[y] - _10B80[x] ;lbe=_10B80[y];correctL=true;} - else if( (hue <= (_10B80[x] + _9B80[x])/2.0) && (hue >(_9B80[x] + _7B80[x])/2.0) && x<40 ) {if(y>39) y=39;correction = _9B80[y] - _9B80[x] ;lbe= _9B80[y];correctL=true;} - else if( (hue <= (_9B80[x] + _7B80[x])/2.0) && (hue >(_5B80[x] + _7B80[x])/2.0) && x<50 ) {if(y>49) y=49;correction = _7B80[y] - _7B80[x] ;lbe=_7B80[y];correctL=true;} - else if (( hue<=(_5B80[x] + _7B80[x])/2.0) && (hue > (_5B80[x]-0.035)) && x < 50) {if(y>49) y=49; correction = _5B80[y] - _5B80[x] ; lbe=_5B80[y];correctL=true;} // - - else if( (hue >= (_15PB80[x] - 0.035)) && (hue < (_15PB80[x] + _3PB80[x])/2.0) && x<50 ) {if(y>49) y=49;correction = _15PB80[y] - _15PB80[x] ; lbe=_15PB80[y];correctL=true;} - else if (( hue>=(_45PB80[x] + _3PB80[x])/2.0) && (hue < (_6PB80[x] + _45PB80[x])/2.0) && x < 50) {if(y>49) y=49;correction = _45PB80[y] - _45PB80[x] ;lbe= _45PB80[y];correctL=true;} - else if (( hue>=(_6PB80[x] + _45PB80[x])/2.0) && (hue < (_6PB80[x] + _75PB80[x])/2.0) && x <50) {if(y>49) y=49;correction = _6PB80[y] - _6PB80[x] ;lbe=_6PB80[y];correctL=true;} - else if (( hue>=(_6PB80[x] + _75PB80[x])/2.0) && (hue < (_9PB80[x] + _75PB80[x])/2.0) && x <50) {if(y>49) y=49;correction = _75PB80[y] - _75PB80[x] ;lbe=_75PB80[y];correctL=true; } - else if (( hue>=(_9PB80[x] + _75PB80[x])/2.0) && (hue < (_9PB80[x] + 0.035)) && x <50) {if(y>49) y=49;correction = _9PB80[y] - _9PB80[x] ;lbe=_9PB80[y]; correctL=true;} - } - } + if(c1 < 0.f) { + c1 = 0.f; } - // end PB correction - //red yellow correction - else if(zone==2) { - if(lum > 15.0) { - if(lum < 25.0) { - if( (hue <= (_10YR20[x] + 0.035)) && (hue > (_10YR20[x] + _85YR20[x])/2.0) && x<=45) {if(y>49) y=49;correction = _10YR20[y] - _10YR20[x] ;lbe=_10YR20[y];correctL=true;} - else if (( hue<=(_85YR20[x] + _10YR20[x])/2.0) && (hue > (_85YR20[x] + 0.035) && x <= 45)) {if(y>49) y=49;correction = _85YR20[y] - _85YR20[x] ;lbe= _85YR20[y];correctL=true;} - } - else if (lum <35.0) { - if( (hue <= (_10YR30[x] + 0.035)) && (hue > (_10YR30[x] + _85YR30[x])/2.0) && x < 85) {if(y>89) y=89;correction = _10YR30[y] - _10YR30[x] ;lbe=_10YR30[y];correctL=true;} - else if( (hue <= (_10YR30[x] + _85YR30[x])/2.0) && (hue >(_85YR30[x] + _7YR30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _85YR30[y] - _85YR30[x] ;lbe= _85YR30[y];correctL=true;} - else if (( hue<=(_85YR30[x] + _7YR30[x])/2.0) && (hue > (_7YR30[x] + _55YR30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _7YR30[y] - _7YR30[x] ;lbe=_7YR30[y];correctL=true;} - else if (( hue<=(_7YR30[x] + _55YR30[x])/2.0) && (hue > (_55YR30[x] + _4YR30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _55YR30[y] - _55YR30[x] ;lbe=_55YR30[y];correctL=true; } - else if (( hue<=(_55YR30[x] + _4YR30[x])/2.0) && (hue > (_4YR30[x] + _25YR30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _4YR30[y] - _4YR30[x] ;lbe= _4YR30[y];correctL=true;} - else if (( hue<=(_4YR30[x] + _25YR30[x])/2.0) && (hue > (_25YR30[x] + _10R30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _25YR30[y] - _25YR30[x] ;lbe=_25YR30[y];correctL=true;} - else if (( hue<=(_25YR30[x] + _10R30[x])/2.0) && (hue > (_10R30[x] + _9R30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10R30[y] - _10R30[x] ; lbe=_10R30[y];correctL=true;} - else if (( hue<=(_10R30[x] + _9R30[x])/2.0) && (hue > (_9R30[x] + _7R30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _9R30[y] - _9R30[x] ;lbe=_9R30[y];correctL=true;} - else if (( hue<=(_9R30[x] + _7R30[x])/2.0) && (hue > (_7R30[x] -0.035))&& x < 85) {if(y>89) y=89;correction = _7R30[y] - _7R30[x] ; lbe=_7R30[y] ;correctL=true;} - } - else if (lum <45.0) { - if( (hue <= (_10YR40[x] + 0.035)) && (hue > (_10YR40[x] + _85YR40[x])/2.0)&& x<85) {if(y>89) y=89;correction = _10YR40[y] - _10YR40[x] ;lbe=_10YR40[y];correctL=true;} - else if( (hue <= (_10YR40[x] + _85YR40[x])/2.0) && (hue >(_85YR40[x] + _7YR40[x])/2.0)&& x < 85 ) {if(y>89) y=89;correction = _85YR40[y] - _85YR40[x] ;lbe= _85YR40[y];correctL=true;} - else if (( hue<=(_85YR40[x] + _7YR40[x])/2.0) && (hue > (_7YR40[x] + _55YR40[x])/2.0) && x < 85) {if(y>89) y=89;correction = _7YR40[y] - _7YR40[x] ;lbe= _7YR40[y];correctL=true;} - else if (( hue<=(_7YR40[x] + _55YR40[x])/2.0) && (hue > (_55YR40[x] + _4YR40[x])/2.0)&& x < 85 ) {if(y>89) y=89;correction = _55YR40[y] - _55YR40[x] ;lbe=_55YR40[y];correctL=true; } - else if (( hue<=(_55YR40[x] + _4YR40[x])/2.0) && (hue > (_4YR40[x] + _25YR40[x])/2.0)&& x < 85 ) {if(y>89) y=89;correction = _4YR40[y] - _4YR40[x] ;lbe=_4YR40[y]; correctL=true;} - else if (( hue<=(_4YR40[x] + _25YR40[x])/2.0) && (hue > (_25YR40[x] + _10R40[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _25YR40[y] - _25YR40[x] ;lbe=_25YR40[y] ;correctL=true;} - else if (( hue<=(_25YR40[x] + _10R40[x])/2.0) && (hue > (_10R40[x] + _9R40[x])/2.0) && x < 85) {if(y>89) y=89;correction = _10R40[y] - _10R40[x] ; lbe=_10R40[y];correctL=true;} - else if (( hue<=(_10R40[x] + _9R40[x])/2.0) && (hue > (_9R40[x] + _7R40[x])/2.0)&& x < 85 ) {if(y>89) y=89;correction = _9R40[y] - _9R40[x] ;lbe=_9R40[y];correctL=true;} - else if (( hue<=(_9R40[x] + _7R40[x])/2.0) && (hue > (_7R40[x] -0.035))&& x < 85 ) {if(y>89) y=89;correction = _7R40[y] - _7R40[x] ; lbe=_7R40[y];correctL=true;} - } - else if (lum <55.0) { - if( (hue <= (_10YR50[x] + 0.035)) && (hue > (_10YR50[x] + _85YR50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10YR50[y] - _10YR50[x] ;lbe=_10YR50[y];correctL=true;} - else if( (hue <= (_10YR50[x] + _85YR50[x])/2.0) && (hue >(_85YR50[x] + _7YR50[x])/2.0)&& x < 85 ) {if(y>89) y=89;correction = _85YR50[y] - _85YR50[x] ;lbe=_85YR50[y];correctL=true;} - else if (( hue<=(_85YR50[x] + _7YR50[x])/2.0) && (hue > (_7YR50[x] + _55YR50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _7YR50[y] - _7YR50[x] ;lbe=_7YR50[y];correctL=true;} - else if (( hue<=(_7YR50[x] + _55YR50[x])/2.0) && (hue > (_55YR50[x] + _4YR50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _55YR50[y] - _55YR50[x] ; lbe=_55YR50[y];correctL=true;} - else if (( hue<=(_55YR50[x] + _4YR50[x])/2.0) && (hue > (_4YR50[x] + _25YR50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _4YR50[y] - _4YR50[x] ;lbe=_4YR50[y]; correctL=true;} - else if (( hue<=(_4YR50[x] + _25YR50[x])/2.0) && (hue > (_25YR50[x] + _10R50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _25YR50[y] - _25YR50[x] ;lbe=_25YR50[y];correctL=true;} - else if (( hue<=(_25YR50[x] + _10R50[x])/2.0) && (hue > (_10R50[x] + _9R50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10R50[y] - _10R50[x] ;lbe= _10R50[y]; correctL=true;} - else if (( hue<=(_10R50[x] + _9R50[x])/2.0) && (hue > (_9R50[x] + _7R50[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _9R50[y] - _9R50[x] ;lbe=_9R50[y];correctL=true;} - else if (( hue<=(_9R50[x] + _7R50[x])/2.0) && (hue > (_7R50[x] -0.035))&& x < 85) {if(y>89) y=89;correction = _7R50[y] - _7R50[x] ; lbe=_7R50[y];correctL=true;} - } - else if (lum <65.0) { - if( (hue <= (_10YR60[x] + 0.035)) && (hue > (_10YR60[x] + _85YR60[x])/2.0)) {;correction = _10YR60[y] - _10YR60[x] ;lbe= _10YR60[y];correctL=true;} - else if( (hue <= (_10YR60[x] + _85YR60[x])/2.0) && (hue >(_85YR60[x] + _7YR60[x])/2.0) ) {;correction = _85YR60[y] - _85YR60[x] ;lbe= _85YR60[y];correctL=true;} - else if (( hue<=(_85YR60[x] + _7YR60[x])/2.0) && (hue > (_7YR60[x] + _55YR60[x])/2.0)) {correction = _7YR60[y] - _7YR60[x] ;lbe=_7YR60[y];correctL=true;} - else if (( hue<=(_7YR60[x] + _55YR60[x])/2.0) && (hue > (_55YR60[x] + _4YR60[x])/2.0)) {correction = _55YR60[y] - _55YR60[x] ;lbe= _55YR60[y];correctL=true;} - else if (( hue<=(_55YR60[x] + _4YR60[x])/2.0) && (hue > (_4YR60[x] + _25YR60[x])/2.0)) {correction = _4YR60[y] - _4YR60[x] ;lbe=_4YR60[y]; correctL=true;} - else if (( hue<=(_4YR60[x] + _25YR60[x])/2.0) && (hue > (_25YR60[x] + _10R60[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _25YR60[y] - _25YR60[x] ;lbe=_25YR60[y];correctL=true;} - else if (( hue<=(_25YR60[x] + _10R60[x])/2.0) && (hue > (_10R60[x] + _9R60[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10R60[y] - _10R60[x] ;lbe= _10R60[y];correctL=true; } - else if (( hue<=(_10R60[x] + _9R60[x])/2.0) && (hue > (_9R60[x] + _7R60[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _9R60[y] - _9R60[x] ;lbe=_9R60[y];correctL=true;} - else if (( hue<=(_9R60[x] + _7R60[x])/2.0) && (hue > (_7R60[x] -0.035))&& x < 85) {if(y>89) y=89;correction = _7R60[y] - _7R60[x] ;lbe=_7R60[y]; correctL=true;} - } - else if (lum <75.0) { - if( (hue <= (_10YR70[x] + 0.035)) && (hue > (_10YR70[x] + _85YR70[x])/2.0)) {correction = _10YR70[y] - _10YR70[x] ;lbe= _10YR70[y];correctL=true;} - else if( (hue <= (_10YR70[x] + _85YR70[x])/2.0) && (hue >(_85YR70[x] + _7YR70[x])/2.0)) {correction = _85YR70[y] - _85YR70[x] ;lbe=_85YR70[y];correctL=true;} - if (( hue<=(_85YR70[x] + _7YR70[x])/2.0) && (hue > (_7YR70[x] + _55YR70[x])/2.0)) {correction = _7YR70[y] - _7YR70[x] ;lbe=_7YR70[y];correctL=true;} - else if (( hue<=(_7YR70[x] + _55YR70[x])/2.0) && (hue > (_55YR70[x] + _4YR70[x])/2.0)) {correction = _55YR70[y] - _55YR70[x] ;lbe=_55YR70[y];correctL=true; } - else if (( hue<=(_55YR70[x] + _4YR70[x])/2.0) && (hue > (_4YR70[x] + _25YR70[x])/2.0)) {correction = _4YR70[y] - _4YR70[x] ;lbe=_4YR70[y];correctL=true; } - else if (( hue<=(_4YR70[x] + _25YR70[x])/2.0) && (hue > (_25YR70[x] + _10R70[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _25YR70[y] - _25YR70[x] ;lbe= _25YR70[y];correctL=true;} - else if (( hue<=(_25YR70[x] + _10R70[x])/2.0) && (hue > (_10R70[x] + _9R70[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10R70[y] - _10R70[x] ;lbe= _10R70[y];correctL=true;} - else if (( hue<=(_10R70[x] + _9R70[x])/2.0) && (hue > (_9R70[x] + _7R70[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _9R70[y] - _9R70[x] ;lbe= _9R70[y] ;correctL=true;} - else if (( hue<=(_9R70[x] + _7R70[x])/2.0) && (hue > (_7R70[x] -0.035))&& x < 85) {if(y>89) y=89;correction = _7R70[y] - _7R70[x] ;lbe=_7R70[y];correctL=true; } - } - else if (lum <85.0) { - if( (hue <= (_10YR80[x] + 0.035)) && (hue > (_10YR80[x] + _85YR80[x])/2.0)) {correction = _10YR80[y] - _10YR80[x] ;lbe=_10YR80[y];correctL=true;} - else if( (hue <= (_10YR80[x] + _85YR80[x])/2.0) && (hue >(_85YR80[x] + _7YR80[x])/2.0)) {correction = _85YR80[y] - _85YR80[x] ;lbe= _85YR80[y];} - else if (( hue<=(_85YR80[x] + _7YR80[x])/2.0) && (hue > (_7YR80[x] + _55YR80[x])/2.0) && x<85) {if(y>89) y=89;correction = _7YR80[y] - _7YR80[x] ;lbe=_7YR80[y];correctL=true;} - else if (( hue<=(_7YR80[x] + _55YR80[x])/2.0) && (hue > (_55YR80[x] + _4YR80[x])/2.0) && x <45) {correction = _55YR80[y] - _55YR80[x] ;lbe=_55YR80[y];correctL=true; } - else if (( hue<=(_55YR80[x] + _4YR80[x])/2.0) && (hue > (_4YR80[x] - 0.035) && x<45)) {if(y>49) y=49;correction = _4YR80[y] - _4YR80[x] ; lbe=_4YR80[y] ;correctL=true;} - } - else if (lum <95.0) { - if( (hue <= (_10YR90[x] + 0.035)) && (hue > (_10YR90[x] -0.035) && x<85)) {if(y>89) y=89;correction = _10YR90[y] - _10YR90[x] ;lbe= _10YR90[y];correctL=true;} - else if ( hue<=(_85YR90[x] + 0.035) && hue > (_85YR90[x] -0.035) && x<85) {if(y>89) y=89;correction = _85YR90[y] - _85YR90[x] ;lbe=_85YR90[y];correctL=true;} - else if (( hue<=(_55YR90[x] + 0.035) && (hue > (_55YR90[x] - 0.035) && x<45))) {if(y>49) y=49;correction = _55YR90[y] - _55YR90[x] ;lbe= _55YR90[y];correctL=true; } - } - } + if(c1 > 180.f) { + c1 = 180.f; } - //end red yellow - - //Green yellow correction - else if(zone==3) { - if (lum >= 25.0) { - if (lum <35.0) { - if( (hue <= (_7G30[x] + 0.035)) && (hue > (_7G30[x] + _5G30[x])/2.0) ) {correction = _7G30[y] - _7G30[x] ;lbe=_7G30[y];correctL=true;} - else if( (hue <= (_7G30[x] + _5G30[x])/2.0) && (hue >(_5G30[x] + _25G30[x])/2.0)) {correction = _5G30[y] - _5G30[x] ;lbe= _5G30[y];correctL=true;} - else if (( hue<=(_25G30[x] + _5G30[x])/2.0) && (hue > (_25G30[x] + _1G30[x])/2.0)) {correction = _25G30[y] - _25G30[x] ;lbe=_25G30[y];correctL=true;} - else if (( hue<=(_1G30[x] + _25G30[x])/2.0) && (hue > (_1G30[x] + _10GY30[x])/2.0)) {correction = _1G30[y] - _1G30[x] ;lbe= _1G30[y];correctL=true;} - else if (( hue<=(_1G30[x] + _10GY30[x])/2.0) && (hue > (_10GY30[x] + _75GY30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10GY30[y] - _10GY30[x] ;lbe= _10GY30[y];correctL=true;} - else if (( hue<=(_10GY30[x] + _75GY30[x])/2.0) && (hue > (_75GY30[x] + _5GY30[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _75GY30[y] - _75GY30[x] ;lbe=_75GY30[y];correctL=true;} - else if (( hue<=(_5GY30[x] + _75GY30[x])/2.0) && (hue > (_5GY30[x] -0.035))&& x < 85) {if(y>89) y=89;correction = _5GY30[y] - _5GY30[x] ;lbe= _5GY30[y] ;correctL=true; } - } - else if (lum <45.0) { - if( (hue <= (_7G40[x] + 0.035)) && (hue > (_7G40[x] + _5G40[x])/2.0) ) {correction = _7G40[y] - _7G40[x] ;lbe= _7G40[y];correctL=true;} - else if( (hue <= (_7G40[x] + _5G40[x])/2.0) && (hue >(_5G40[x] + _25G40[x])/2.0)) {correction = _5G40[y] - _5G40[x] ;lbe=_5G40[y];correctL=true;} - else if (( hue<=(_25G40[x] + _5G40[x])/2.0) && (hue > (_25G40[x] + _1G40[x])/2.0)) {correction = _25G40[y] - _25G40[x] ;lbe=_25G40[y];correctL=true;} - else if (( hue<=(_1G40[x] + _25G40[x])/2.0) && (hue > (_1G40[x] + _10GY40[x])/2.0)) {correction = _1G40[y] - _1G40[x] ;lbe=_1G40[y];correctL=true; } - else if (( hue<=(_1G40[x] + _10GY40[x])/2.0) && (hue > (_10GY40[x] + _75GY40[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _10GY40[y] - _10GY40[x] ;lbe=_10GY40[y];correctL=true; } - else if (( hue<=(_10GY40[x] + _75GY40[x])/2.0) && (hue > (_75GY40[x] + _5GY40[x])/2.0)&& x < 85) {if(y>89) y=89;correction = _75GY40[y] - _75GY40[x] ;lbe=_75GY40[y];correctL=true;} - else if (( hue<=(_5GY40[x] + _75GY40[x])/2.0) && (hue > (_5GY40[x]-0.035)) && x < 85) {if(y>89) y=89; correction = _5GY40[y] - _5GY40[x] ;lbe=_5GY40[y];correctL=true; } // - } - else if (lum <55.0) { - if( (hue <= (_7G50[x] + 0.035)) && (hue > (_7G50[x] + _5G50[x])/2.0) ) {correction = _7G50[y] - _7G50[x] ;lbe=_7G50[y];correctL=true;} - else if( (hue <= (_7G50[x] + _5G50[x])/2.0) && (hue >(_5G50[x] + _25G50[x])/2.0)) {correction = _5G50[y] - _5G50[x] ;lbe=_5G50[y];correctL=true;} - else if (( hue<=(_25G50[x] + _5G50[x])/2.0) && (hue > (_25G50[x] + _1G50[x])/2.0)) {correction = _25G50[y] - _25G50[x] ;lbe= _25G50[y];correctL=true;} - else if (( hue<=(_1G50[x] + _25G50[x])/2.0) && (hue > (_1G50[x] + _10GY50[x])/2.0)) {correction = _1G50[y] - _1G50[x] ; lbe=_1G50[y];correctL=true;} - else if (( hue<=(_1G50[x] + _10GY50[x])/2.0) && (hue > (_10GY50[x] + _75GY50[x])/2.0)) {correction = _10GY50[y] - _10GY50[x] ;lbe= _10GY50[y];correctL=true;} - else if (( hue<=(_10GY50[x] + _75GY50[x])/2.0) && (hue > (_75GY50[x] + _5GY50[x])/2.0)) {correction = _75GY50[y] - _75GY50[x] ;lbe=_75GY50[y];correctL=true;} - else if (( hue<=(_5GY50[x] + _75GY50[x])/2.0) && (hue > (_5GY50[x] -0.035))) {correction = _5GY50[y] - _5GY50[x] ; lbe=_5GY50[y];correctL=true;} - } - else if (lum <65.0) { - if( (hue <= (_7G60[x] + 0.035)) && (hue > (_7G60[x] + _5G60[x])/2.0) ) {correction = _7G60[y] - _7G60[x] ;lbe=_7G60[y];correctL=true;} - else if( (hue <= (_7G60[x] + _5G60[x])/2.0) && (hue >(_5G60[x] + _25G60[x])/2.0)) {correction = _5G60[y] - _5G60[x] ;lbe=_5G60[y];correctL=true;} - else if (( hue<=(_25G60[x] + _5G60[x])/2.0) && (hue > (_25G60[x] + _1G60[x])/2.0)) {correction = _25G60[y] - _25G60[x] ;lbe=_25G60[y];correctL=true;} - else if (( hue<=(_1G60[x] + _25G60[x])/2.0) && (hue > (_1G60[x] + _10GY60[x])/2.0)) {correction = _1G60[y] - _1G60[x] ; lbe=_1G60[y];correctL=true;} - else if (( hue<=(_1G60[x] + _10GY60[x])/2.0) && (hue > (_10GY60[x] + _75GY60[x])/2.0)) {correction = _10GY60[y] - _10GY60[x] ;lbe= _10GY60[y];correctL=true;} - else if (( hue<=(_10GY60[x] + _75GY60[x])/2.0) && (hue > (_75GY60[x] + _5GY60[x])/2.0)) {correction = _75GY60[y] - _75GY60[x] ;lbe=_75GY60[y] ;correctL=true;} - else if (( hue<=(_5GY60[x] + _75GY60[x])/2.0) && (hue > (_5GY60[x] -0.035))) {correction = _5GY60[y] - _5GY60[x] ; lbe=_5GY60[y];correctL=true;} - } - else if (lum <75.0) { - if( (hue <= (_7G70[x] + 0.035)) && (hue > (_7G70[x] + _5G70[x])/2.0) ) {correction = _7G70[y] - _7G70[x] ;lbe= _7G70[y];correctL=true;} - else if( (hue <= (_7G70[x] + _5G70[x])/2.0) && (hue >(_5G70[x] + _25G70[x])/2.0)) {correction = _5G70[y] - _5G70[x] ;lbe= _5G70[y];correctL=true;} - else if (( hue<=(_25G70[x] + _5G70[x])/2.0) && (hue > (_25G70[x] + _1G70[x])/2.0)) {correction = _25G70[y] - _25G70[x] ;lbe=_25G70[y];correctL=true;} - else if (( hue<=(_1G70[x] + _25G70[x])/2.0) && (hue > (_1G70[x] + _10GY70[x])/2.0)) {correction = _1G70[y] - _1G70[x] ;lbe= _1G70[y] ;correctL=true;} - else if (( hue<=(_1G70[x] + _10GY70[x])/2.0) && (hue > (_10GY70[x] + _75GY70[x])/2.0)) {correction = _10GY70[y] - _10GY70[x] ; lbe=_10GY70[y];correctL=true;} - else if (( hue<=(_10GY70[x] + _75GY70[x])/2.0) && (hue > (_75GY70[x] + _5GY70[x])/2.0)) {correction = _75GY70[y] - _75GY70[x] ;lbe=_75GY70[y];correctL=true;} - else if (( hue<=(_5GY70[x] + _75GY70[x])/2.0) && (hue > (_5GY70[x] -0.035))) {correction = _5GY70[y] - _5GY70[x] ;lbe= _5GY70[y];correctL=true;} - } - else if (lum <85.0) { - if( (hue <= (_7G80[x] + 0.035)) && (hue > (_7G80[x] + _5G80[x])/2.0) ) {correction = _7G80[y] - _7G80[x] ;lbe=_7G80[y];correctL=true;} - else if( (hue <= (_7G80[x] + _5G80[x])/2.0) && (hue >(_5G80[x] + _25G80[x])/2.0)) {correction = _5G80[y] - _5G80[x] ;lbe=_5G80[y];correctL=true;} - else if (( hue<=(_25G80[x] + _5G80[x])/2.0) && (hue > (_25G80[x] + _1G80[x])/2.0)) {correction = _25G80[y] - _25G80[x] ;lbe=_25G80[y];correctL=true;} - else if (( hue<=(_1G80[x] + _25G80[x])/2.0) && (hue > (_1G80[x] + _10GY80[x])/2.0)) {correction = _1G80[y] - _1G80[x] ; lbe= _1G80[y];correctL=true;} - else if (( hue<=(_1G80[x] + _10GY80[x])/2.0) && (hue > (_10GY80[x] + _75GY80[x])/2.0)) {correction = _10GY80[y] - _10GY80[x] ;lbe=_10GY80[y];correctL=true; } - else if (( hue<=(_10GY80[x] + _75GY80[x])/2.0) && (hue > (_75GY80[x] + _5GY80[x])/2.0)) {correction = _75GY80[y] - _75GY80[x] ;lbe=_75GY80[y];correctL=true;} - else if (( hue<=(_5GY80[x] + _75GY80[x])/2.0) && (hue > (_5GY80[x] -0.035))) {correction = _5GY80[y] - _5GY80[x] ; lbe=_5GY80[y];correctL=true;} - } - } - } - //end green yellow - - //Red purple correction : only for L < 30 - else if(zone==4) { - if (lum > 5.0) { - if (lum < 15.0) { - if( (hue <= (_5R10[x] + 0.035)) && (hue > (_5R10[x] - 0.043)) && x<45) {if(y>44) y=44;correction = _5R10[y] - _5R10[x] ;lbe=_5R10[y];correctL=true;} - else if( (hue <= (_25R10[x] + 0.043)) && (hue >(_25R10[x] + _10RP10[x])/2.0) && x<45 ) {if(y>44) y=44;correction = _25R10[y] - _25R10[x] ;lbe= _25R10[y];correctL=true;} - else if ( (hue <=(_25R10[x] + _10RP10[x])/2.0) && (hue > (_10RP10[x] -0.035) ) && x<45){if(y>44) y=44; correction = _10RP10[y] - _10RP10[x] ;lbe=_10RP10[y];correctL=true;} - } - else if (lum <25.0) { - if( (hue <= (_5R20[x] + 0.035)) && (hue > (_5R20[x] + _25R20[x])/2.0) && x<70 ) {if(y>70) y=70;correction = _5R20[y] - _5R20[x] ;lbe= _5R20[y];correctL=true;} - else if( (hue <= (_5R20[x] + _25R20[x])/2.0) && (hue >(_10RP20[x] + _25R20[x])/2.0) && x<70) {if(y>70) y=70;correction = _25R20[y] - _25R20[x] ;lbe=_25R20[y];correctL=true;} - else if (( hue<=(_10RP20[x] + _25R20[x])/2.0) && (hue > (_10RP20[x] -0.035)) && x<70) {if(y>70) y=70; correction = _10RP20[y] - _10RP20[x] ;lbe=_10RP20[y];correctL=true;} - } - else if (lum <35.0) { - if( (hue <= (_5R30[x] + 0.035)) && (hue > (_5R30[x] + _25R30[x])/2.0) && x<85 ) {if(y>85) y=85;correction = _5R30[y] - _5R30[x] ;lbe= _5R30[y];correctL=true;} - else if( (hue <= (_5R30[x] + _25R30[x])/2.0) && (hue >(_10RP30[x] + _25R30[x])/2.0) && x< 85) {if(y>85) y=85;correction = _25R30[y] - _25R30[x] ;lbe=_25R30[y];correctL=true;} - else if (( hue<=(_10RP30[x] + _25R30[x])/2.0) && (hue > (_10RP30[x] -0.035)) && x<85) {if(y>85) y=85; correction = _10RP30[y] - _10RP30[x] ;lbe= _10RP30[y];correctL=true;} - } - } - } - //end red purple } + if (toDo & CHANNEL_HUE) { + h1 = interpolatePolarHue_PI(h1, h2, balance); + } - /* - * SkinSat - * Copyright (c)2011 Jacques Desmis - * - * skin color: mixed from NX2 skin color palette, Von Luschan, and photos of people white, - * black, yellow....there are some little exceptions...cover 99% case - * pay attention to white balance, and do not change hue and saturation, upstream of the modification - * - */ - void Color::SkinSat (float lum, float hue, float chrom, float &satreduc) { + // here I have put gamut control with gamutlchonly on final process + Lr = L1 / 327.68f; //for gamutlch +#ifndef NDEBUG + neg = false; + more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); +#endif + //convert CH ==> ab + L1 = Lr * 327.68f; - // to be adapted...by tests - float reduction=0.3f; // use "reduction" for "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1 - float extendedreduction=0.4f; // use "extendedreduction" for wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation - float extendedreduction2=0.6f; // use "extendedreduction2" for wide area for transition + // converting back to rgb + Color::Lch2Lab(c1, h1, a, b); + Color::Lab2XYZ(L1, a, b, X, Y, Z); + Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz); +} - float C9=8.0, C8=15.0, C7=12.0, C4=7.0, C3=5.0, C2=5.0, C1=5.0; - float H9=0.05, H8=0.25, H7=0.1, H4=0.02, H3=0.02, H2=0.1, H1=0.1, H10=-0.2,H11=-0.2; //H10 and H11 are curious...H11=-0.8 ?? - - if (lum >= 85.f) { - if((hue > (0.78f-H9) && hue < (1.18f+H9)) && (chrom > 8.f && chrom < (14.f+C9))) satreduc=reduction; - else if (lum >= 92.f) { - if((hue > 0.8f && hue < 1.65f) && (chrom > 7.f && chrom < (15.f))) satreduc=extendedreduction; - else if ((hue > -0.1f && hue < 1.65f) && (chrom > 7.f && chrom < (18.f))) satreduc=extendedreduction2; - } - else if ((hue > 0.7f && hue < 1.4f) && (chrom > 7.f && chrom < (26.f+C9))) satreduc=extendedreduction; - else if (lum < 92.f && (hue > 0.f && hue < 1.65f) && (chrom > 7.f && chrom < (35.f+C9))) satreduc=extendedreduction2; + +void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int algm, const float balance, int twoc, int metchrom, + bool chr, bool lum, float chromat, float luma, const float r1, const float g1, const float b1, + const float xl, const float yl, const float zl, const float x2, const float y2, const float z2, + int toDo, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo) +{ + float X1, Y1, Z1, X2, Y2, Z2, X, Y, Z, XL, YL, ZL; + float L1, L2, LL, a_1, b_1, a_2, b_2, a, b, a_L, b_L; + float c1, c2, h1, h2, cL, hL; + float RR, GG, BB; + float Lr; + float slc = 0.f; + float hh = 0.f; + float ll = 0.f; + float sh = 0.f; + bool LCH = false; + + float ha, hb, hc, ba; + float c_1, h_1; + // converting color 1 to Lab (image) + Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); + + if(algm == 1) {//use H interpolate + Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1); + //Color::Lab2Lch(a_1, b_1, c_1, h_1) ; + } + + // converting color l lab(low) first color + if(twoc == 0) { // 2 colours + //Color::rgbxyz(rl, gl, bl, XL, YL, ZL, xyz_rgb); + XL = xl; + YL = yl; + ZL = zl; + + if(algm <= 1) {//use H interpolate + Color::XYZ2Lab(XL, YL, ZL, LL, a_L, b_L); } - else if (lum >= 70.f) { - if((hue > 0.4f && hue < (1.04f+H8)) && (chrom > 8.f && chrom < (35.f+C8))) satreduc=reduction; - else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f+C9) )) satreduc=extendedreduction; - else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f+C9) )) satreduc=extendedreduction2; + } + + // converting color 2 to lab (universal or high) + X2 = x2; + Y2 = y2; + Z2 = z2; + float c_2, h_2; + + if(algm == 1 ) { + Color::XYZ2Lab(X2, Y2, Z2, L2, a_2, b_2); + //Color::Lab2Lch(a_2, b_2, c_2, h_2) ; + } + + float bal, balH, cal, calH, calm; + bal = balH = balance; + cal = calH = calm = 1.f - chromat; + float med = (iphigh + iplow) / 2.f; + float medH = (iphigh + iplow) / 2.f; + float medL = (iphigh + iplow) / 2.f; + + med = 1.f; + medH = 0.f; //new algo for 2 colors + float calan; + calan = chromat; + + float calby; + calby = luma; + + if(twoc == 0) { // 2 colours + calan = chromat; + + //calculate new balance in function of (arbitrary) "med".. I hope no error !! + if (realL > iplow && realL <= med) { + bal = realL * balance / (iplow - med) - med * balance / (iplow - med); + } else if (realL <= iplow) { + bal = realL * balance / iplow; } - else if (lum >= 52.f) { - if((hue > 0.3f && hue < (1.27f+H7)) && (chrom > 11.f && chrom < (35.f+C7))) satreduc=reduction; - else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f+C9) )) satreduc=extendedreduction; - else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f+C9) )) satreduc=extendedreduction2; + + if (realL > medH && realL <= iphigh) { + balH = realL * balance / (iphigh - medH) - medH * balance / (iphigh - medH); + } else if (realL > iphigh) { + balH = realL * balance * (iphigh - 1.f) - balance * (iphigh - 1.f); } - else if (lum >= 35.f) { - if((hue > 0.3f && hue < (1.25f+H4)) && (chrom > 13.f && chrom < (37.f+C4))) satreduc=reduction; - else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f+C9) )) satreduc=extendedreduction; - else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f+C9) )) satreduc=extendedreduction2; + + //calculate new balance chroma + if (realL > iplow && realL <= med) { + cal = realL * calan / (iplow - med) - med * calan / (iplow - med); + } else if (realL <= iplow) { + cal = realL * calan / iplow; } - else if (lum >= 20.f) { - if((hue > 0.3f && hue < (1.2f+H3)) && (chrom > 7.f && chrom <(35.f+C3) )) satreduc=reduction; - else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f+C9) )) satreduc=extendedreduction; - else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f+C9) )) satreduc=extendedreduction2; + + if (realL > medH && realL <= iphigh) { + calH = realL * calan / (iphigh - medH) - medH * calan / (iphigh - medH); + } else if (realL > iphigh) { + calH = realL * calan; //*(iphigh-1.f) - calan*(iphigh-1.f);//it is better without transition in highlight } - else if (lum > 10.f) { - if((hue > (0.f + H10) && hue < (0.95f +H2)) && (chrom > 8.f && chrom < (23.f+C2))) satreduc=reduction; - else if ((hue > (0.02f+H11) && hue < 1.f) && (chrom > 7.f && chrom < (35.f+C1) )) satreduc=extendedreduction; - else if ((hue > (0.02f+H11) && hue < 1.6f) && (chrom > 7.f && chrom < (45.f+C1) )) satreduc=extendedreduction2; + } + + float hX = 0.f; + float hLL, hH, ccL, ccH, llH, aaH, bbH; + + if(algm <= 1) { + if(twoc == 0 && metchrom == 3) { // 2 colours only with special "ab" + if(algm == 1) { + aaH = a_1 + (a_2 - a_1) * calH; + bbH = b_1 + (b_2 - b_1) * calH; //pass to line after + a_1 = aaH + (a_L - aaH) * cal * balance; + b_1 = bbH + (b_L - bbH) * cal * balance; + } + } else if(twoc == 1) { + if(metchrom == 0) { + a_1 = a_1 + (a_2 - a_1) * balance; + b_1 = b_1 + (b_2 - b_1) * balance; + } else if(metchrom == 1) { + a_1 = a_1 + (a_2 - a_1) * calan * balance; + b_1 = b_1 + (b_2 - b_1) * calan * balance; + } else if(metchrom == 2) { + a_1 = a_1 + (a_2 - a_1) * calan * balance; + b_1 = b_1 + (b_2 - b_1) * calby * balance; + } } - else { - if((hue > (0.02f + H10) && hue < (0.9f+H1)) && (chrom > 8.f && chrom < (23.f+C1))) satreduc=reduction; // no data : extrapolate - else if ((hue > (0.02f+H11) && hue < 1.f) && (chrom > 7.f && chrom < (35.f+C1) )) satreduc=extendedreduction; - else if ((hue > (0.02f+H11) && hue < 1.6f) && (chrom > 7.f && chrom < (45.f+C1) )) satreduc=extendedreduction2; - + } else { + h1 = hX; + } + + Color::Lab2XYZ(L1, a_1, b_1, X, Y, Z); + + Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz);// ro go bo in gamut +} + +void Color::calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4, double &gamma5) +{ + //from Dcraw (D.Coffin) + int i; + double g[6], bnd[2] = {0, 0}; + + g[0] = pwr; + g[1] = ts; + g[2] = g[3] = g[4] = 0; + bnd[g[1] >= 1] = 1; + + if (g[1] && (g[1] - 1) * (g[0] - 1) <= 0) { + for (i = 0; i < 48; i++) { + g[2] = (bnd[0] + bnd[1]) / 2; + + if (g[0]) { + bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2]; + } else { + bnd[g[2] / exp(1 - 1 / g[2]) < g[1]] = g[2]; + } + } + + g[3] = g[2] / g[1]; + + if (g[0]) { + g[4] = g[2] * (1 / g[0] - 1); + } + } + + if (g[0]) { + g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) + (1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) - 1; + } else { + g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] - g[2] * g[3] * (log(g[3]) - 1)) - 1; + } + + if (!mode--) { + gamma0 = g[0]; + gamma1 = g[1]; + gamma2 = g[2]; + gamma3 = g[3]; + gamma4 = g[4]; + gamma5 = g[5]; + return; + } +} + +void Color::Lab2XYZ(float L, float a, float b, float &x, float &y, float &z) +{ + float LL = L / 327.68f; + float aa = a / 327.68f; + float bb = b / 327.68f; + float fy = (0.00862069f * LL) + 0.137932f; // (L+16)/116 + float fx = (0.002f * aa) + fy; + float fz = fy - (0.005f * bb); + x = 65535.0f * f2xyz(fx) * D50x; + z = 65535.0f * f2xyz(fz) * D50z; + y = (LL > epskap) ? 65535.0f * fy * fy * fy : 65535.0f * LL / kappa; +} + +#ifdef __SSE2__ +void Color::Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, vfloat &z) +{ + vfloat c327d68 = F2V(327.68f); + L /= c327d68; + a /= c327d68; + b /= c327d68; + vfloat fy = F2V(0.00862069f) * L + F2V(0.137932f); + vfloat fx = F2V(0.002f) * a + fy; + vfloat fz = fy - (F2V(0.005f) * b); + vfloat c65535 = F2V(65535.f); + x = c65535 * f2xyz(fx) * F2V(D50x); + z = c65535 * f2xyz(fz) * F2V(D50z); + vfloat res1 = fy * fy * fy; + vfloat res2 = L / F2V(kappa); + y = vself(vmaskf_gt(L, F2V(epskap)), res1, res2); + y *= c65535; +} +#endif // __SSE2__ + +void Color::XYZ2Lab(float X, float Y, float Z, float &L, float &a, float &b) +{ + + float x = X / D50x; + float z = Z / D50z; + float y = Y; + float fx, fy, fz; + + fx = (x <= 65535.0f ? cachef[x] : (327.68f * xcbrtf(x / MAXVALF))); + fy = (y <= 65535.0f ? cachef[y] : (327.68f * xcbrtf(y / MAXVALF))); + fz = (z <= 65535.0f ? cachef[z] : (327.68f * xcbrtf(z / MAXVALF))); + + L = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; + a = (500.0f * (fx - fy) ); + b = (200.0f * (fy - fz) ); +} + +void Color::Lab2Yuv(float L, float a, float b, float &Y, float &u, float &v) +{ + float fy = (0.00862069 * L / 327.68) + 0.137932; // (L+16)/116 + float fx = (0.002 * a / 327.68) + fy; + float fz = fy - (0.005 * b / 327.68); + float LL = L / 327.68; + + float X = 65535.0 * f2xyz(fx) * D50x; + // Y = 65535.0*f2xyz(fy); + float Z = 65535.0 * f2xyz(fz) * D50z; + Y = (LL / 327.68f > epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / kappa; + + u = 4.0 * X / (X + 15 * Y + 3 * Z) - u0; + v = 9.0 * Y / (X + 15 * Y + 3 * Z) - v0; +} + +void Color::Yuv2Lab(float Yin, float u, float v, float &L, float &a, float &b, double wp[3][3]) +{ + float u1 = u + u0; + float v1 = v + v0; + + float Y = Yin; + float X = (9 * u1 * Y) / (4 * v1 * D50x); + float Z = (12 - 3 * u1 - 20 * v1) * Y / (4 * v1 * D50z); + + 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 ))); + + L = (116.0 * fy - 5242.88); //5242.88=16.0*327.68; + a = (500.0 * (fx - fy) ); + b = (200.0 * (fy - fz) ); +} + +void Color::Lab2Lch(float a, float b, float &c, float &h) +{ + c = (sqrtf(a * a + b * b)) / 327.68f; + h = xatan2f(b, a); +} + +void Color::Lch2Lab(float c, float h, float &a, float &b) +{ + float2 sincosval = xsincosf(h); + a = 327.68f * c * sincosval.y; + b = 327.68f * c * sincosval.x; +} + +void Color::Luv2Lch(float u, float v, float &c, float &h) +{ + c = sqrtf(u * u + v * v); + h = xatan2f(v, u); //WARNING: should we care of division by zero here? + + if (h < 0.f) { + h += 1.f; + } +} + +void Color::Lch2Luv(float c, float h, float &u, float &v) +{ + float2 sincosval = xsincosf(h); + u = c * sincosval.x; + v = c * sincosval.y; +} + +// NOT TESTED +void Color::XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v) +{ + + X /= 65535.f; + Y /= 65535.f; + Z /= 65535.f; + + if (Y > float(eps)) { + L = 116.f * pow(Y, 1.f / 3.f) - 16.f; + } else { + L = float(kappa) * Y; + } + + u = 13.f * L * float(u0); + v = 13.f * L * float(v0); +} + +// NOT TESTED +void Color::Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z) +{ + if (L > float(epskap)) { + float t = (L + 16.f) / 116.f; + Y = t * t * t; + } else { + Y = L / float(kappa); + } + + float a = ((52.f * L) / (u + 13.f * L * float(u0)) - 1.f) / 3.f; + float d = Y * (((39 * L) / (v + 13 * float(v0))) - 5.f); + float b = -5.f * Y; + X = (d - b) / (a + 1.f / 3.f); + + Z = X * a + b; + + X *= 65535.f; + Y *= 65535.f; + Z *= 65535.f; +} + +/* + * Gamut mapping algorithm + * Copyright (c) 2010-2011 Emil Martinec + * + * Solutions to scaling u and v to XYZ paralleliped boundaries + * Some equations: + * + * fu(X,Y,Z) = 4 X/(X + 15 Y + 3 Z); + * fv(X,Y,Z) = 9 Y/(X + 15 Y + 3 Z); + * + * take the plane spanned by X=a*Xr+b*Xg+c*Xb etc with one of a,b,c equal to 0 or 1, + * and itersect with the line u0+lam*u, or in other words solve + * + * u0+lam*u=fu(X,Y,Z) + * v0+lam*v=fv(X,Y,Z) + * + * The value of lam is the scale factor that takes the color to the gamut boundary + * columns of the matrix p=xyz_rgb are RGB tristimulus primaries in XYZ + * c is the color fixed on the boundary; and m=0 for c=0, m=1 for c=255 + */ +void Color::gamutmap(float &X, float &Y, float &Z, const double p[3][3]) +{ + float u = 4 * X / (X + 15 * Y + 3 * Z) - u0; + float v = 9 * Y / (X + 15 * Y + 3 * Z) - v0; + + float lam[3][2]; + float lam_min = 1.0; + + for (int c = 0; c < 3; c++) + for (int m = 0; m < 2; m++) { + + int c1 = (c + 1) % 3; + int c2 = (c + 2) % 3; + + lam[c][m] = (-(p[0][c1] * p[1][c] * ((-12 + 3 * u0 + 20 * v0) * Y + 4 * m * 65535 * v0 * p[2][c2])) + + p[0][c] * p[1][c1] * ((-12 + 3 * u0 + 20 * v0) * Y + 4 * m * 65535 * v0 * p[2][c2]) - + 4 * v0 * p[0][c1] * (Y - m * 65535 * p[1][c2]) * p[2][c] + 4 * v0 * p[0][c] * (Y - m * 65535 * p[1][c2]) * p[2][c1] - + (4 * m * 65535 * v0 * p[0][c2] - 9 * u0 * Y) * (p[1][c1] * p[2][c] - p[1][c] * p[2][c1])); + + lam[c][m] /= (3 * u * Y * (p[0][c1] * p[1][c] - p[1][c1] * (p[0][c] + 3 * p[2][c]) + 3 * p[1][c] * p[2][c1]) + + 4 * v * (p[0][c1] * (5 * Y * p[1][c] + m * 65535 * p[1][c] * p[2][c2] + Y * p[2][c] - m * 65535 * p[1][c2] * p[2][c]) - + p[0][c] * (5 * Y * p[1][c1] + m * 65535 * p[1][c1] * p[2][c2] + Y * p[2][c1] - m * 65535 * p[1][c2] * p[2][c1]) + + m * 65535 * p[0][c2] * (p[1][c1] * p[2][c] - p[1][c] * p[2][c1]))); + + if (lam[c][m] < lam_min && lam[c][m] > 0) { + lam_min = lam[c][m]; + } + + } + + u = u * lam_min + u0; + v = v * lam_min + v0; + + X = (9 * u * Y) / (4 * v); + Z = (12 - 3 * u - 20 * v) * Y / (4 * v); +} + +void Color::skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s) +{ + float factorskin, factorsat, factor, factorskinext, interm; + float scale = 100.0f / 100.1f; //reduction in normal zone + float scaleext = 1.0f; //reduction in transition zone + float protect_redh; + float deltaHH = 0.3f; //HH value transition : I have choice 0.3 radians + float HH; + bool doskin = false; + + //rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear + if ((float)h > 8.6f && (float)h <= 74.f ) { + HH = (1.15f / 65.4f) * (float)h - 0.0012f; //H > 0.15 H<1.3 + doskin = true; + } else if((float)h > 0.f && (float)h <= 8.6f ) { + HH = (0.19f / 8.6f ) * (float)h - 0.04f; //H>-0.04 H < 0.15 + doskin = true; + } else if((float)h > 355.f && (float)h <= 360.f) { + HH = (0.11f / 5.0f ) * (float)h - 7.96f; //H>-0.15 <-0.04 + doskin = true; + } else if((float)h > 74.f && (float)h < 95.f ) { + HH = (0.30f / 21.0f) * (float)h + 0.24285f; //H>1.3 H<1.6 + doskin = true; + } + + if(doskin) { + float chromapro = sres / Sp; + + if(sk == 1) { //in C mode to adapt dred to J + if (J < 16.0) { + dred = 40.0f; + } else if(J < 22.0) { + dred = (4.1666f) * (float)J - 26.6f; + } else if(J < 60.0) { + dred = 55.0f; + } else if(J < 70.0) { + dred = -1.5f * (float)J + 145.0f; + } else { + dred = 40.0f; + } + } + + if(chromapro > 0.0) { + Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext); //Scale factor + } + + if(chromapro > 1.0) { + interm = (chromapro - 1.0f) * 100.0f; + factorskin = 1.0f + (interm * scale) / 100.0f; + factorskinext = 1.0f + (interm * scaleext) / 100.0f; + } else { + factorskin = chromapro ; + factorskinext = chromapro ; + } + + factorsat = chromapro; + factor = factorsat; + Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition + s *= factor; + } else { + s = ko * sres; + } + +} +void Color::skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s) +{ + float HH; + bool doskin = false; + + //rough correspondence between h (JC) and H (lab) that has relatively little importance because transitions that blur the correspondence is not linear + if ((float)h > 8.6f && (float)h <= 74.f ) { + HH = (1.15f / 65.4f) * (float)h - 0.0012f; //H > 0.15 H<1.3 + doskin = true; + } else if((float)h > 0.f && (float)h <= 8.6f ) { + HH = (0.19f / 8.6f ) * (float)h - 0.04f; //H>-0.04 H < 0.15 + doskin = true; + } else if((float)h > 355.f && (float)h <= 360.f) { + HH = (0.11f / 5.0f ) * (float)h - 7.96f; //H>-0.15 <-0.04 + doskin = true; + } else if((float)h > 74.f && (float)h < 95.f ) { + HH = (0.30f / 21.0f) * (float)h + 0.24285f; //H>1.3 H<1.6 + doskin = true; + } + + if(doskin) { + float factorskin, factorsat, factor, factorskinext; + float protect_redh; + float deltaHH = 0.3f; //HH value transition : I have choice 0.3 radians + float chromapro = sres / Sp; + + if(sk == 1) { //in C mode to adapt dred to J + if (J < 16.0) { + dred = 40.0f; + } else if(J < 22.0) { + dred = (4.1666f) * (float)J - 26.6f; + } else if(J < 60.0) { + dred = 55.0f; + } else if(J < 70.0) { + dred = -1.5f * (float)J + 145.0f; + } else { + dred = 40.0f; + } + } + + if(chromapro > 1.0) { + float scale = 0.999000999f; // 100.0f/100.1f; reduction in normal zone + float scaleext = 1.0f; //reduction in transition zone + Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//Scale factor + float interm = (chromapro - 1.0f); + factorskin = 1.0f + (interm * scale); + factorskinext = 1.0f + (interm * scaleext); + } else { + factorskin = chromapro ; + factorskinext = chromapro ; + } + + factorsat = chromapro; + factor = factorsat; + Color::transitred ( HH, s, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor); //transition + s *= factor; + } else { + s = ko * sres; + } + +} + + + + + + +void Color::scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext) +{ + if(rstprotection < 99.9999f) { + if(param > limit) { + scale = rstprotection / 100.1f; + } + + if((HH < (1.3f + deltaHH) && HH >= 1.3f)) + // scaleext=HH*(1.0f-scale)/deltaHH + 1.0f - (1.3f+deltaHH)*(1.0f-scale)/deltaHH; //transition for Hue (red - yellow) + // optimized formula + { + scaleext = (HH * (1.0f - scale) + deltaHH - (1.3f + deltaHH) * (1.0f - scale)) / deltaHH; //transition for Hue (red - yellow) + } else if((HH < 0.15f && HH > (0.15f - deltaHH))) + // scaleext=HH*(scale-1.0f)/deltaHH + 1.0f - (0.15f-deltaHH)*(scale-1.0f)/deltaHH; //transition for hue (red purple) + // optimized formula + { + scaleext = (HH * (scale - 1.0f) + deltaHH - (0.15f - deltaHH) * (scale - 1.0f)) / deltaHH; //transition for hue (red purple) + } + } +} + +void Color::transitred (const float HH, float const Chprov1, const float dred, const float factorskin, const float protect_red, const float factorskinext, const float deltaHH, const float factorsat, float &factor) +{ + if(HH >= 0.15f && HH < 1.3f) { + if (Chprov1 < dred) { + factor = factorskin; + } else if(Chprov1 < (dred + protect_red)) + // factor = (factorsat-factorskin)/protect_red*Chprov1+factorsat-(dred+protect_red)*(factorsat-factorskin)/protect_red; + // optimized formula + { + factor = ((factorsat - factorskin) * Chprov1 + factorsat * protect_red - (dred + protect_red) * (factorsat - factorskin)) / protect_red; + } + } + // then test if chroma is in the extanded range + else if ( HH > (0.15f - deltaHH) || HH < (1.3f + deltaHH) ) { + if (Chprov1 < dred) { + factor = factorskinext; // C=dred=55 => real max of skin tones + } else if (Chprov1 < (dred + protect_red)) // transition + // factor = (factorsat-factorskinext)/protect_red*Chprov1+factorsat-(dred+protect_red)*(factorsat-factorskinext)/protect_red; + // optimized formula + { + factor = ((factorsat - factorskinext) * Chprov1 + factorsat * protect_red - (dred + protect_red) * (factorsat - factorskinext)) / protect_red; + } + } +} + +/* + * AllMunsellLch correction + * Copyright (c) 2012 Jacques Desmis + * + * This function corrects the color (hue) for changes in chromaticity and luminance + * to use in a "for" or "do while" statement + * + * Parameters: + * bool lumaMuns : true => luminance correction (for delta L > 10) and chroma correction ; false : only chroma + * float Lprov1 , Loldd : luminance after and before + * float HH: hue before + * float Chprov1, CC : chroma after and before + * float coorectionHuechroma : correction Hue for chromaticity (saturation) + * float correctlum : correction Hue for luminance (brigtness, contrast,...) + * MunsellDebugInfo* munsDbgInfo: (Debug target only) object to collect information. + */ +#ifdef _DEBUG +void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHuechroma, float &correctlum, MunsellDebugInfo* munsDbgInfo) +#else +void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHuechroma, float &correctlum) +#endif +{ + + bool contin1, contin2; + float correctionHue = 0.0, correctionHueLum = 0.0; + bool correctL; + + if(CC >= 6.0 && CC < 140) { //if C > 140 we say C=140 (only in Prophoto ...with very large saturation) + static const float huelimit[8] = { -2.48, -0.55, 0.44, 1.52, 1.87, 3.09, -0.27, 0.44}; //limits hue of blue-purple, red-yellow, green-yellow, red-purple + + if (Chprov1 > 140.f) { + Chprov1 = 139.f; //limits of LUTf + } + + if (Chprov1 < 6.f) { + Chprov1 = 6.f; + } + + for(int zo = 1; zo <= 4; zo++) { + if(HH > huelimit[2 * zo - 2] && HH < huelimit[2 * zo - 1]) { + //zone=zo; + contin1 = contin2 = false; + correctL = false; + MunsellLch (Lprov1, HH, Chprov1, CC, correctionHue, zo, correctionHueLum, correctL); //munsell chroma correction +#ifdef _DEBUG + float absCorrectionHue = fabs(correctionHue); + + if(correctionHue != 0.0) { + int idx = zo - 1; + #pragma omp critical (maxdhue) + { + munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); + } + } + + if(absCorrectionHue > 0.45) + #pragma omp atomic + munsDbgInfo->depass++; //verify if no bug in calculation + +#endif + correctionHuechroma = correctionHue; //preserve + + if(lumaMuns) { + float correctlumprov = 0.f; + float correctlumprov2 = 0.f; + + if(correctL) { + //for Munsell luminance correction + correctlumprov = correctionHueLum; + contin1 = true; + correctL = false; + } + + correctionHueLum = 0.0; + correctionHue = 0.0; + + if(fabs(Lprov1 - Loldd) > 6.0) { + // correction if delta L significative..Munsell luminance + MunsellLch (Loldd, HH, Chprov1, Chprov1, correctionHue, zo, correctionHueLum, correctL); + + if(correctL) { + correctlumprov2 = correctionHueLum; + contin2 = true; + correctL = false; + } + + correctionHueLum = 0.0; + + if(contin1 == true && contin2 == true) { + correctlum = correctlumprov2 - correctlumprov; + } + +#ifdef _DEBUG + float absCorrectLum = fabs(correctlum); + + if(correctlum != 0.0) { + int idx = zo - 1; + #pragma omp critical (maxdhuelum) + { + munsDbgInfo->maxdhuelum[idx] = MAX(munsDbgInfo->maxdhuelum[idx], absCorrectLum); + } + } + + if(absCorrectLum > 0.35) + #pragma omp atomic + munsDbgInfo->depassLum++; //verify if no bug in calculation + +#endif + } + } + } } } - /* - * Munsell Lch correction - * Copyright (c) 2011 Jacques Desmis - * - * data (Munsell ==> Lab) obtained with WallKillcolor and http://www.cis.rit.edu/research/mcsl2/online/munsell.php - * each LUT give Hue in function of C, for each color Munsell and Luminance - * eg: _6PB20 : color Munsell 6PB for L=20 c=5 c=45 c=85 c=125..139 when possible: interpolation betwwen values - * no value for C<5 (gray) - * low memory footprint -- maximum: 195 LUTf * 140 values - * errors due to small number of samples in LUT and linearization are very low (1 to 2%) - * errors due to a different illuminant "Daylight" than "C" are low, about 10%. For example, a theoretical correction of 0.1 radian will be made with a real correction of 0.09 or 0.11 depending on the color illuminant D50 - * errors due to the use of a very different illuminant "C", for example illuminant "A" (tungsten) are higher, about 20%. Theoretical correction of 0.52 radians will be made with a real correction of 0.42 - */ - void Color::initMunsell () { - #ifdef _DEBUG - MyTime t1e,t2e; - t1e.set(); - #endif +#ifdef _DEBUG + + if (correctlum < -0.35f) { + correctlum = -0.35f; + } else if(correctlum > 0.35f) { + correctlum = 0.35f; + } + + if (correctionHuechroma < -0.45f) { + correctionHuechroma = -0.45f; + } else if(correctionHuechroma > 0.45f) { + correctionHuechroma = 0.45f; + } + +#endif + +} + +/* + * GamutLchonly correction + * Copyright (c)2012 Jacques Desmis and Jean-Christophe Frisch + * + * This function puts the data (Lab) in the gamut of "working profile": + * it returns the corrected values of the chromaticity and luminance + * + * float HH : hue + * float Lprov1 : input luminance value, sent back corrected + * float Chprov1: input chroma value, sent back corrected + * float R,G,B : red, green and blue value of the corrected color + * double wip : working profile + * bool isHLEnabled : if "highlight reconstruction " is enabled + * float coef : a float number between [0.95 ; 1.0[... the nearest it is from 1.0, the more precise it will be... and the longer too as more iteration will be necessary) + * bool neg and moreRGB : only in DEBUG mode to calculate iterations for negatives values and > 65535 + */ +#ifdef _DEBUG +void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) +#else +void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) +#endif +{ + const float ClipLevel = 65535.0f; + bool inGamut; +#ifdef _DEBUG + neg = false, more_rgb = false; +#endif + float2 sincosval = xsincosf(HH); + + do { + inGamut = true; + + //Lprov1=LL; + float aprov1 = Chprov1 * sincosval.y; + float bprov1 = Chprov1 * sincosval.x; + + //conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction + float fy = (0.00862069f * Lprov1 ) + 0.137932f; + float fx = (0.002f * aprov1) + fy; + float fz = fy - (0.005f * bprov1); + + float x_ = 65535.0f * f2xyz(fx) * D50x; + // float y_ = 65535.0f * f2xyz(fy); + float z_ = 65535.0f * f2xyz(fz) * D50z; + float y_ = (Lprov1 > epskap) ? 65535.0 * fy * fy * fy : 65535.0 * Lprov1 / kappa; + + xyz2rgb(x_, y_, z_, R, G, B, wip); + + // gamut control before saturation to put Lab values in future gamut, but not RGB + if (R < 0.0f || G < 0.0f || B < 0.0f) { +#ifdef _DEBUG + neg = true; +#endif + + if (Lprov1 < 0.1f) { + Lprov1 = 0.1f; + } + + //gamut for L with ultra blue : we can improve the algorithm ... thinner, and other color ??? + if(HH < -0.9f && HH > -1.55f ) {//ultra blue + if(Chprov1 > 160.f) if (Lprov1 < 5.f) { + Lprov1 = 5.f; //very very very very high chroma + } + + if(Chprov1 > 140.f) if (Lprov1 < 3.5f) { + Lprov1 = 3.5f; + } + + if(Chprov1 > 120.f) if (Lprov1 < 2.f) { + Lprov1 = 2.f; + } + + if(Chprov1 > 105.f) if (Lprov1 < 1.f) { + Lprov1 = 1.f; + } + + if(Chprov1 > 90.f) if (Lprov1 < 0.7f) { + Lprov1 = 0.7f; + } + + if(Chprov1 > 50.f) if (Lprov1 < 0.5f) { + Lprov1 = 0.5f; + } + + if(Chprov1 > 20.f) if (Lprov1 < 0.4f) { + Lprov1 = 0.4f; + } + } + + Chprov1 *= higherCoef; // decrease the chromaticity value + + if (Chprov1 <= 3.0f) { + Lprov1 += lowerCoef; + } + + inGamut = false; + } else if (!isHLEnabled && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) { + + // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut +#ifdef _DEBUG + more_rgb = true; +#endif + + if (Lprov1 > 99.999f) { + Lprov1 = 99.98f; + } + + Chprov1 *= higherCoef; + + if (Chprov1 <= 3.0f) { + Lprov1 -= lowerCoef; + } + + inGamut = false; + } + } while (!inGamut); + + //end first gamut control +} + +/* + * GamutLchonly correction + * Copyright (c)2012 Jacques Desmis and Jean-Christophe Frisch + * + * This function puts the data (Lab) in the gamut of "working profile": + * it returns the corrected values of the chromaticity and luminance + * + * float HH : hue + * float2 sincosval : sin and cos of HH + * float Lprov1 : input luminance value, sent back corrected + * float Chprov1: input chroma value, sent back corrected + * float R,G,B : red, green and blue value of the corrected color + * double wip : working profile + * bool isHLEnabled : if "highlight reconstruction " is enabled + * float coef : a float number between [0.95 ; 1.0[... the nearest it is from 1.0, the more precise it will be... and the longer too as more iteration will be necessary) + * bool neg and moreRGB : only in DEBUG mode to calculate iterations for negatives values and > 65535 + */ +#ifdef _DEBUG +void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) +#else +void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) +#endif +{ + const float ClipLevel = 65535.0f; + bool inGamut; +#ifdef _DEBUG + neg = false, more_rgb = false; +#endif + + do { + inGamut = true; + + //Lprov1=LL; + float aprov1 = Chprov1 * sincosval.y; + float bprov1 = Chprov1 * sincosval.x; + + //conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction + float fy = (0.00862069f * Lprov1 ) + 0.137932f; + float fx = (0.002f * aprov1) + fy; + float fz = fy - (0.005f * bprov1); + + float x_ = 65535.0f * f2xyz(fx) * D50x; + // float y_ = 65535.0f * f2xyz(fy); + float z_ = 65535.0f * f2xyz(fz) * D50z; + float y_ = (Lprov1 > epskap) ? 65535.0 * fy * fy * fy : 65535.0 * Lprov1 / kappa; + + xyz2rgb(x_, y_, z_, R, G, B, wip); + + // gamut control before saturation to put Lab values in future gamut, but not RGB + if (R < 0.0f || G < 0.0f || B < 0.0f) { +#ifdef _DEBUG + neg = true; +#endif + + if (Lprov1 < 0.1f) { + Lprov1 = 0.1f; + } + + //gamut for L with ultra blue : we can improve the algorithm ... thinner, and other color ??? + if(HH < -0.9f && HH > -1.55f ) {//ultra blue + if(Chprov1 > 160.f) if (Lprov1 < 5.f) { + Lprov1 = 5.f; //very very very very high chroma + } + + if(Chprov1 > 140.f) if (Lprov1 < 3.5f) { + Lprov1 = 3.5f; + } + + if(Chprov1 > 120.f) if (Lprov1 < 2.f) { + Lprov1 = 2.f; + } + + if(Chprov1 > 105.f) if (Lprov1 < 1.f) { + Lprov1 = 1.f; + } + + if(Chprov1 > 90.f) if (Lprov1 < 0.7f) { + Lprov1 = 0.7f; + } + + if(Chprov1 > 50.f) if (Lprov1 < 0.5f) { + Lprov1 = 0.5f; + } + + if(Chprov1 > 20.f) if (Lprov1 < 0.4f) { + Lprov1 = 0.4f; + } + } + + Chprov1 *= higherCoef; // decrease the chromaticity value + + if (Chprov1 <= 3.0f) { + Lprov1 += lowerCoef; + } + + inGamut = false; + } else if (!isHLEnabled && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) { + + // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut +#ifdef _DEBUG + more_rgb = true; +#endif + + if (Lprov1 > 99.999f) { + Lprov1 = 99.98f; + } + + Chprov1 *= higherCoef; + + if (Chprov1 <= 3.0f) { + Lprov1 -= lowerCoef; + } + + inGamut = false; + } + } while (!inGamut); + + //end first gamut control +} + + +#ifdef _DEBUG +void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb) +#else +void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef) +#endif +{ + const float ClipLevel = 65535.0f; + bool inGamut; +#ifdef _DEBUG + neg = false, more_rgb = false; +#endif + + do { + inGamut = true; + + //Lprov1=LL; + float aprov1 = Chprov1 * sincosval.y; + float bprov1 = Chprov1 * sincosval.x; + + //conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction + float fy = (0.00862069f * Lprov1 ) + 0.137932f; + float fx = (0.002f * aprov1) + fy; + float fz = fy - (0.005f * bprov1); + + float x_ = 65535.0f * f2xyz(fx) * D50x; + // float y_ = 65535.0f * f2xyz(fy); + float z_ = 65535.0f * f2xyz(fz) * D50z; + float y_ = (Lprov1 > epskap) ? 65535.0 * fy * fy * fy : 65535.0 * Lprov1 / kappa; + + float R, G, B; + xyz2rgb(x_, y_, z_, R, G, B, wip); + + // gamut control before saturation to put Lab values in future gamut, but not RGB + if (R < 0.0f || G < 0.0f || B < 0.0f) { +#ifdef _DEBUG + neg = true; +#endif + + if (Lprov1 < 0.01f) { + Lprov1 = 0.01f; + } + + Chprov1 *= higherCoef; // decrease the chromaticity value + + if (Chprov1 <= 3.0f) { + Lprov1 += lowerCoef; + } + + inGamut = false; + } else if (!isHLEnabled && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) { + + // if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut +#ifdef _DEBUG + more_rgb = true; +#endif + + if (Lprov1 > 99.999f) { + Lprov1 = 99.98f; + } + + Chprov1 *= higherCoef; + + if (Chprov1 <= 3.0f) { + Lprov1 -= lowerCoef; + } + + inGamut = false; + } + } while (!inGamut); + + //end first gamut control +} +/* + * LabGamutMunsell + * Copyright (c) 2012 Jacques Desmis + * + * This function is the overall Munsell's corrections, but only on global statement: I think it's better to use local statement with AllMunsellLch + * not for use in a "for" or "do while" loop + * they are named accordingly : gamutLchonly and AllMunsellLch + * it can be used before and after treatment (saturation, gamma, luminance, ...) + * + * Parameters: + * float *labL : RT Lab L channel data + * float *laba : RT Lab a channel data + * float *labb : RT Lab b channel data + * bool corMunsell : performs Munsell correction + * bool lumaMuns : (used only if corMuns=true) + * true: apply luma + chroma Munsell correction if delta L > 10; + * false: only chroma correction only + * bool gamut : performs gamutLch + * const double wip[3][3]: matrix for working profile + * bool multiThread : parallelize the loop + */ +SSEFUNCTION void Color::LabGamutMunsell(float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3], bool multiThread ) +{ +#ifdef _DEBUG + MyTime t1e, t2e; + t1e.set(); + int negat = 0, moreRGB = 0; + MunsellDebugInfo* MunsDebugInfo = NULL; + + if (corMunsell) { + MunsDebugInfo = new MunsellDebugInfo(); + } + +#endif + float correctlum = 0.f; + float correctionHuechroma = 0.f; +#ifdef __SSE2__ + // precalculate H and C using SSE + float HHBuffer[N]; + float CCBuffer[N]; + __m128 c327d68v = _mm_set1_ps(327.68f); + __m128 av, bv; + int k; + + for (k = 0; k < N - 3; k += 4) { + av = LVFU(laba[k]); + bv = LVFU(labb[k]); + _mm_storeu_ps(&HHBuffer[k], xatan2f(bv, av)); + _mm_storeu_ps(&CCBuffer[k], _mm_sqrt_ps(SQRV(av) + SQRV(bv)) / c327d68v); + } + + for(; k < N; k++) { + HHBuffer[k] = xatan2f(labb[k], laba[k]); + CCBuffer[k] = sqrt(SQR(laba[k]) + SQR(labb[k])) / 327.68f; + } + +#endif // __SSE2__ + + for (int j = 0; j < N; j++) { +#ifdef __SSE2__ + float HH = HHBuffer[j]; + float Chprov1 = CCBuffer[j]; +#else + float HH = xatan2f(labb[j], laba[j]); + float Chprov1 = sqrtf(SQR(laba[j]) + SQR(labb[j])) / 327.68f; +#endif + float Lprov1 = labL[j] / 327.68f; + float Loldd = Lprov1; + float Coldd = Chprov1; + float2 sincosval; + + if(gamut) { +#ifdef _DEBUG + bool neg, more_rgb; +#endif + // According to mathematical laws we can get the sin and cos of HH by simple operations + float R, G, B; + + if(Chprov1 == 0.f) { + sincosval.y = 1.f; + sincosval.x = 0.f; + } else { + sincosval.y = laba[j] / (Chprov1 * 327.68f); + sincosval.x = labb[j] / (Chprov1 * 327.68f); + } + + //gamut control : Lab values are in gamut +#ifdef _DEBUG + gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, isHLEnabled, 0.15f, 0.96f, neg, more_rgb); +#else + gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, isHLEnabled, 0.15f, 0.96f); +#endif + +#ifdef _DEBUG + + if(neg) { + negat++; + } + + if(more_rgb) { + moreRGB++; + } + +#endif + } + + labL[j] = Lprov1 * 327.68f; + correctionHuechroma = 0.f; + correctlum = 0.f; + + if(corMunsell) +#ifdef _DEBUG + AllMunsellLch(lumaMuns, Lprov1, Loldd, HH, Chprov1, Coldd, correctionHuechroma, correctlum, MunsDebugInfo); + +#else + AllMunsellLch(lumaMuns, Lprov1, Loldd, HH, Chprov1, Coldd, correctionHuechroma, correctlum); +#endif + + if(correctlum == 0.f && correctionHuechroma == 0.f) { + if(!gamut) { + if(Coldd == 0.f) { + sincosval.y = 1.f; + sincosval.x = 0.f; + } else { + sincosval.y = laba[j] / (Coldd * 327.68f); + sincosval.x = labb[j] / (Coldd * 327.68f); + } + } + + } else { + HH += correctlum; //hue Munsell luminance correction + sincosval = xsincosf(HH + correctionHuechroma); + } + + laba[j] = Chprov1 * sincosval.y * 327.68f; + labb[j] = Chprov1 * sincosval.x * 327.68f; + } + +#ifdef _DEBUG + t2e.set(); + + if (settings->verbose) { + printf("Color::LabGamutMunsell (correction performed in %d usec):\n", t2e.etime(t1e)); + printf(" Gamut : G1negat=%iiter G165535=%iiter \n", negat, moreRGB); + + if (MunsDebugInfo) { + printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass); + printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhuelum[0] , MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum); + } else { + printf(" Munsell correction wasn't requested\n"); + } + } + + if (MunsDebugInfo) { + delete MunsDebugInfo; + } + +#endif + +} + +/* + * MunsellLch correction + * Copyright (c) 2012 Jacques Desmis + * + * Find the right LUT and calculate the correction + */ +void Color::MunsellLch (float lum, float hue, float chrom, float memChprov, float &correction, int zone, float &lbe, bool &correctL) +{ + + int x = int(memChprov); + int y = int(chrom); + + //begin PB correction + sky + if(zone == 1) { + if(lum > 5.0) { + if(lum < 15.0) { + if( (hue >= (_15PB10[x] - 0.035)) && (hue < (_15PB10[x] + 0.052) && x <= 45)) { + if(y > 49) { + y = 49; + } + + correction = _15PB10[y] - _15PB10[x] ; + lbe = _15PB10[y]; + correctL = true; + } else if (( hue >= ( _3PB10[x] - 0.052)) && (hue < (_45PB10[x] + _3PB10[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _3PB10[y] - _3PB10[x]; + lbe = _3PB10[y]; + correctL = true; + } else if (( hue >= (_45PB10[x] + _3PB10[x]) / 2.0) && (hue < (_45PB10[x] + 0.052)) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _45PB10[y] - _45PB10[x] ; + lbe = _45PB10[y]; + correctL = true; + } else if (( hue >= (_6PB10[x] - 0.052) && (hue < (_6PB10[x] + _75PB10[x]) / 2.0))) { + correction = _6PB10[y] - _6PB10[x] ; + lbe = _6PB10[y]; + correctL = true; + } else if (( hue >= (_6PB10[x] + _75PB10[x]) / 2.0) && (hue < (_9PB10[x] + _75PB10[x]) / 2.0)) { + correction = _75PB10[y] - _75PB10[x] ; + lbe = _75PB10[y]; + correctL = true; + } else if (( hue >= (_9PB10[x] + _75PB10[x]) / 2.0) && (hue < (_9PB10[x] + _10PB10[x]) / 2.0)) { + correction = _9PB10[y] - _9PB10[x] ; + lbe = _9PB10[y]; + correctL = true; + } else if (( hue >= (_10PB10[x] + _9PB10[x]) / 2.0) && (hue < (_1P10[x] + _10PB10[x]) / 2.0)) { + correction = _10PB10[y] - _10PB10[x] ; + lbe = _10PB10[y]; + correctL = true; + } else if (( hue >= (_10PB10[x] + _1P10[x]) / 2.0) && (hue < (_1P10[x] + _4P10[x]) / 2.0)) { + correction = _1P10[y] - _1P10[x]; + lbe = _1P10[y]; + correctL = true; + } else if (( hue >= (_1P10[x] + _4P10[x]) / 2.0) && (hue < (0.035 + _4P10[x]) / 2.0)) { + correction = _4P10[y] - _4P10[x] ; + lbe = _4P10[y]; + correctL = true; + } + } else if (lum < 25.0) { + if( (hue >= (_15PB20[x] - 0.035)) && (hue < (_15PB20[x] + _3PB20[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _15PB20[y] - _15PB20[x] ; + lbe = _15PB20[y]; + correctL = true; + } else if (( hue >= (_15PB20[x] + _3PB20[x]) / 2.0) && (hue < (_45PB20[x] + _3PB20[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _3PB20[y] - _3PB20[x] ; + lbe = _3PB20[y]; + correctL = true; + } else if (( hue >= (_45PB20[x] + _3PB20[x]) / 2.0) && (hue < ( _45PB20[x] + 0.052)) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _45PB20[y] - _45PB20[x] ; + lbe = _45PB20[y]; + correctL = true; + } else if (( hue >= (_45PB20[x] + 0.052)) && (hue < (_6PB20[x] + _75PB20[x]) / 2.0)) { + correction = _6PB20[y] - _6PB20[x]; + lbe = _6PB20[y]; + correctL = true; + } else if (( hue >= (_6PB20[x] + _75PB20[x]) / 2.0) && (hue < (_9PB20[x] + _75PB20[x]) / 2.0)) { + correction = _75PB20[y] - _75PB20[x] ; + lbe = _75PB20[y]; + correctL = true; + } else if (( hue >= (_9PB20[x] + _75PB20[x]) / 2.0) && (hue < (_9PB20[x] + _10PB20[x]) / 2.0)) { + correction = _9PB20[y] - _9PB20[x] ; + lbe = _9PB20[y]; + correctL = true; + } else if (( hue >= (_10PB20[x] + _9PB20[x]) / 2.0) && (hue < (_1P20[x] + _10PB20[x]) / 2.0)) { + correction = _10PB20[y] - _10PB20[x] ; + lbe = _10PB20[y]; + correctL = true; + } else if (( hue >= (_10PB20[x] + _1P20[x]) / 2.0) && (hue < (_1P20[x] + _4P20[x]) / 2.0)) { + correction = _1P20[y] - _1P20[x] ; + lbe = _1P20[y]; + correctL = true; + } else if (( hue >= (_1P20[x] + _4P20[x]) / 2.0) && (hue < (0.035 + _4P20[x]) / 2.0)) { + correction = _4P20[y] - _4P20[x] ; + lbe = _4P20[y]; + correctL = true; + } + } else if (lum < 35.0) { + if( (hue >= (_15PB30[x] - 0.035)) && (hue < (_15PB30[x] + _3PB30[x]) / 2.0) && x <= 85 ) { + if(y > 89) { + y = 89; + } + + correction = _15PB30[y] - _15PB30[x] ; + lbe = _15PB30[y]; + correctL = true; + } else if (( hue >= (_15PB30[x] + _3PB30[x]) / 2.0) && (hue < (_45PB30[x] + _3PB30[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _3PB30[y] - _3PB30[x] ; + lbe = _3PB30[y]; + correctL = true; + } else if (( hue >= (_45PB30[x] + _3PB30[x]) / 2.0) && (hue < (_45PB30[x] + 0.052)) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _45PB30[y] - _45PB30[x] ; + lbe = _45PB30[y]; + correctL = true; + } else if (( hue >= ( _45PB30[x] + 0.052)) && (hue < (_6PB30[x] + _75PB30[x]) / 2.0)) { + correction = _6PB30[y] - _6PB30[x] ; + lbe = _6PB30[y]; + correctL = true; + } else if (( hue >= (_6PB30[x] + _75PB30[x]) / 2.0) && (hue < (_9PB30[x] + _75PB30[x]) / 2.0)) { + correction = _75PB30[y] - _75PB30[x] ; + lbe = _75PB30[y] ; + correctL = true; + } else if (( hue >= (_9PB30[x] + _75PB30[x]) / 2.0) && (hue < (_9PB30[x] + _10PB30[x]) / 2.0)) { + correction = _9PB30[y] - _9PB30[x] ; + lbe = _9PB30[y]; + correctL = true; + } else if (( hue >= (_10PB30[x] + _9PB30[x]) / 2.0) && (hue < (_1P30[x] + _10PB30[x]) / 2.0)) { + correction = _10PB30[y] - _10PB30[x] ; + lbe = _10PB30[y]; + correctL = true; + } else if (( hue >= (_10PB30[x] + _1P30[x]) / 2.0) && (hue < (_1P30[x] + _4P30[x]) / 2.0)) { + correction = _1P30[y] - _1P30[x] ; + lbe = _1P30[y]; + correctL = true; + } else if (( hue >= (_1P30[x] + _4P30[x]) / 2.0) && (hue < (0.035 + _4P30[x]) / 2.0)) { + correction = _4P30[y] - _4P30[x] ; + lbe = _4P30[y]; + correctL = true; + } + } else if (lum < 45.0) { + if( (hue <= (_05PB40[x] + _15PB40[x]) / 2.0) && (hue > (_05PB40[x] + _10B40[x]) / 2.0) && x < 75 ) { + if(y > 75) { + y = 75; + } + + correction = _05PB40[y] - _05PB40[x] ; + lbe = _05PB40[y]; + correctL = true; + } else if( (hue <= (_05PB40[x] + _10B40[x]) / 2.0) && (hue > (_10B40[x] + _9B40[x]) / 2.0) && x < 70 ) { + if(y > 70) { + y = 70; + } + + correction = _10B40[y] - _10B40[x] ; + lbe = _10B40[y]; + correctL = true; + } else if( (hue <= (_10B40[x] + _9B40[x]) / 2.0) && (hue > (_9B40[x] + _7B40[x]) / 2.0) && x < 70 ) { + if(y > 70) { + y = 70; + } + + correction = _9B40[y] - _9B40[x] ; + lbe = _9B40[y]; + correctL = true; + } else if( (hue <= (_9B40[x] + _7B40[x]) / 2.0) && (hue > (_5B40[x] + _7B40[x]) / 2.0) && x < 70 ) { + if(y > 70) { + y = 70; + } + + correction = _7B40[y] - _7B40[x] ; + lbe = _7B40[y]; + correctL = true; + } else if (( hue <= (_5B40[x] + _7B40[x]) / 2.0) && (hue > (_5B40[x] - 0.035)) && x < 70) { + if(y > 70) { + y = 70; // + } + + correction = _5B40[y] - _5B40[x] ; + lbe = _5B40[y]; + correctL = true; + } + + else if( (hue >= (_15PB40[x] - 0.035)) && (hue < (_15PB40[x] + _3PB40[x]) / 2.0) && x <= 85 ) { + if(y > 89) { + y = 89; + } + + correction = _15PB40[y] - _15PB40[x] ; + lbe = _15PB40[y]; + correctL = true; + } else if (( hue >= (_15PB40[x] + _3PB40[x]) / 2.0) && (hue < (_45PB40[x] + _3PB40[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _3PB40[y] - _3PB40[x] ; + lbe = _3PB40[y]; + correctL = true; + } else if (( hue >= (_45PB40[x] + _3PB40[x]) / 2.0) && (hue < (_45PB40[x] + 0.052)) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _45PB40[y] - _45PB40[x] ; + lbe = _45PB40[y] ; + correctL = true; + } else if (( hue >= (_45PB40[x] + 0.052)) && (hue < (_6PB40[x] + _75PB40[x]) / 2.0)) { + correction = _6PB40[y] - _6PB40[x] ; + lbe = _6PB40[y]; + correctL = true; + } else if (( hue >= (_6PB40[x] + _75PB40[x]) / 2.0) && (hue < (_9PB40[x] + _75PB40[x]) / 2.0)) { + correction = _75PB40[y] - _75PB40[x] ; + lbe = _75PB40[y]; + correctL = true; + } else if (( hue >= (_9PB40[x] + _75PB40[x]) / 2.0) && (hue < (_9PB40[x] + _10PB40[x]) / 2.0)) { + correction = _9PB40[y] - _9PB40[x] ; + lbe = _9PB40[y]; + correctL = true; + } else if (( hue >= (_10PB40[x] + _9PB40[x]) / 2.0) && (hue < (_1P40[x] + _10PB40[x]) / 2.0)) { + correction = _10PB40[y] - _10PB40[x] ; + lbe = _10PB40[y]; + correctL = true; + } else if (( hue >= (_10PB40[x] + _1P40[x]) / 2.0) && (hue < (_1P40[x] + _4P40[x]) / 2.0)) { + correction = _1P40[y] - _1P40[x] ; + lbe = _1P40[y]; + correctL = true; + } else if (( hue >= (_1P40[x] + _4P40[x]) / 2.0) && (hue < (0.035 + _4P40[x]) / 2.0)) { + correction = _4P40[y] - _4P40[x] ; + lbe = _4P40[y]; + correctL = true; + } + } else if (lum < 55.0) { + if( (hue <= (_05PB50[x] + _15PB50[x]) / 2.0) && (hue > (_05PB50[x] + _10B50[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _05PB50[y] - _05PB50[x] ; + lbe = _05PB50[y]; + correctL = true; + } else if( (hue <= (_05PB50[x] + _10B50[x]) / 2.0) && (hue > (_10B50[x] + _9B50[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _10B50[y] - _10B50[x] ; + lbe = _10B50[y]; + correctL = true; + } else if( (hue <= (_10B50[x] + _9B50[x]) / 2.0) && (hue > (_9B50[x] + _7B50[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _9B50[y] - _9B50[x] ; + lbe = _9B50[y]; + correctL = true; + } else if( (hue <= (_9B50[x] + _7B50[x]) / 2.0) && (hue > (_5B50[x] + _7B50[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _7B50[y] - _7B50[x] ; + lbe = _7B50[y]; + correctL = true; + } else if (( hue <= (_5B50[x] + _7B50[x]) / 2.0) && (hue > (_5B50[x] - 0.035)) && x < 79) { + if(y > 79) { + y = 79; // + } + + correction = _5B50[y] - _5B50[x] ; + lbe = _5B50[y]; + correctL = true; + } + + else if( (hue >= (_15PB50[x] - 0.035)) && (hue < (_15PB50[x] + _3PB50[x]) / 2.0) && x <= 85 ) { + if(y > 89) { + y = 89; + } + + correction = _15PB50[y] - _15PB50[x] ; + lbe = _15PB50[y]; + correctL = true; + } else if (( hue >= (_15PB50[x] + _3PB50[x]) / 2.0) && (hue < (_45PB50[x] + _3PB50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _3PB50[y] - _3PB50[x] ; + lbe = _3PB50[y]; + correctL = true; + } else if (( hue >= (_45PB50[x] + _3PB50[x]) / 2.0) && (hue < (_6PB50[x] + _45PB50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _45PB50[y] - _45PB50[x] ; + lbe = _45PB50[y]; + correctL = true; + } else if (( hue >= (_6PB50[x] + _45PB50[x]) / 2.0) && (hue < (_6PB50[x] + _75PB50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _6PB50[y] - _6PB50[x] ; + lbe = _6PB50[y]; + correctL = true; + } else if (( hue >= (_6PB50[x] + _75PB50[x]) / 2.0) && (hue < (_9PB50[x] + _75PB50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _75PB50[y] - _75PB50[x] ; + lbe = _75PB50[y]; + correctL = true; + } else if (( hue >= (_9PB50[x] + _75PB50[x]) / 2.0) && (hue < (_9PB50[x] + _10PB50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _9PB50[y] - _9PB50[x] ; + lbe = _9PB50[y]; + correctL = true; + } else if (( hue >= (_10PB50[x] + _9PB50[x]) / 2.0) && (hue < (_1P50[x] + _10PB50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _10PB50[y] - _10PB50[x] ; + lbe = _10PB50[y]; + correctL = true; + } else if (( hue >= (_10PB50[x] + _1P50[x]) / 2.0) && (hue < (_1P50[x] + _4P50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _1P50[y] - _1P50[x] ; + lbe = _1P50[y]; + correctL = true; + } else if (( hue >= (_1P50[x] + _4P50[x]) / 2.0) && (hue < (0.035 + _4P50[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _4P50[y] - _4P50[x] ; + lbe = _4P50[y]; + correctL = true; + } + } else if (lum < 65.0) { + if( (hue <= (_05PB60[x] + _15PB60[x]) / 2.0) && (hue > (_05PB60[x] + _10B60[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _05PB60[y] - _05PB60[x] ; + lbe = _05PB60[y]; + correctL = true; + } else if( (hue <= (_05PB60[x] + _10B60[x]) / 2.0) && (hue > (_10B60[x] + _9B60[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _10B60[y] - _10B60[x] ; + lbe = _10B60[y]; + correctL = true; + } else if( (hue <= (_10B60[x] + _9B60[x]) / 2.0) && (hue > (_9B60[x] + _7B60[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _9B60[y] - _9B60[x] ; + lbe = _9B60[y]; + correctL = true; + } else if( (hue <= (_9B60[x] + _7B60[x]) / 2.0) && (hue > (_5B60[x] + _7B60[x]) / 2.0) && x < 79 ) { + if(y > 79) { + y = 79; + } + + correction = _7B60[y] - _7B60[x] ; + lbe = _7B60[y]; + correctL = true; + } else if (( hue <= (_5B60[x] + _7B60[x]) / 2.0) && (hue > (_5B60[x] - 0.035)) && x < 79) { + if(y > 79) { + y = 79; // + } + + correction = _5B60[y] - _5B60[x] ; + lbe = _5B60[y]; + correctL = true; + } + + else if( (hue >= (_15PB60[x] - 0.035)) && (hue < (_15PB60[x] + _3PB60[x]) / 2.0) && x <= 85 ) { + if(y > 89) { + y = 89; + } + + correction = _15PB60[y] - _15PB60[x] ; + lbe = _15PB60[y]; + correctL = true; + } else if (( hue >= (_15PB60[x] + _3PB60[x]) / 2.0) && (hue < (_45PB60[x] + _3PB60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _3PB60[y] - _3PB60[x] ; + lbe = _3PB60[y]; + correctL = true; + } else if (( hue >= (_45PB60[x] + _3PB60[x]) / 2.0) && (hue < (_6PB60[x] + _45PB60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _45PB60[y] - _45PB60[x] ; + lbe = _45PB60[y]; + correctL = true; + } else if (( hue >= (_6PB60[x] + _45PB60[x]) / 2.0) && (hue < (_6PB60[x] + _75PB60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _6PB60[y] - _6PB60[x] ; + lbe = _6PB60[y]; + correctL = true; + } else if (( hue >= (_6PB60[x] + _75PB60[x]) / 2.0) && (hue < (_9PB60[x] + _75PB60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _75PB60[y] - _75PB60[x] ; + lbe = _75PB60[y]; + correctL = true; + } else if (( hue >= (_9PB60[x] + _75PB60[x]) / 2.0) && (hue < (_9PB60[x] + _10PB60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _9PB60[y] - _9PB60[x] ; + lbe = _9PB60[y]; + correctL = true; + } else if (( hue >= (_10PB60[x] + _9PB60[x]) / 2.0) && (hue < (_1P60[x] + _10PB60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _10PB60[y] - _10PB60[x] ; + lbe = _10PB60[y]; + correctL = true; + } else if (( hue >= (_10PB60[x] + _1P60[x]) / 2.0) && (hue < (_1P60[x] + _4P60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _1P60[y] - _1P60[x] ; + lbe = _1P60[y]; + correctL = true; + } else if (( hue >= (_1P60[x] + _4P60[x]) / 2.0) && (hue < (0.035 + _4P60[x]) / 2.0) && x <= 85) { + if(y > 89) { + y = 89; + } + + correction = _4P60[y] - _4P60[x] ; + lbe = _4P60[y]; + correctL = true; + } + } else if (lum < 75.0) { + if( (hue <= (_05PB70[x] + _15PB70[x]) / 2.0) && (hue > (_05PB70[x] + _10B70[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _05PB70[y] - _05PB70[x] ; + lbe = _05PB70[y]; + correctL = true; + } else if( (hue <= (_05PB70[x] + _10B70[x]) / 2.0) && (hue > (_10B70[x] + _9B70[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _10B70[y] - _10B70[x] ; + lbe = _10B70[y]; + correctL = true; + } else if( (hue <= (_10B70[x] + _9B70[x]) / 2.0) && (hue > (_9B70[x] + _7B70[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _9B70[y] - _9B70[x] ; + lbe = _9B70[y]; + correctL = true; + } else if( (hue <= (_9B70[x] + _7B70[x]) / 2.0) && (hue > (_5B70[x] + _7B70[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _7B70[y] - _7B70[x] ; + lbe = _7B70[y]; + correctL = true; + } else if (( hue <= (_5B70[x] + _7B70[x]) / 2.0) && (hue > (_5B70[x] - 0.035)) && x < 50) { + if(y > 49) { + y = 49; // + } + + correction = _5B70[y] - _5B70[x] ; + lbe = _5B70[y]; + correctL = true; + } + + else if( (hue >= (_15PB70[x] - 0.035)) && (hue < (_15PB70[x] + _3PB70[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _15PB70[y] - _15PB70[x] ; + lbe = _15PB70[y]; + correctL = true; + } else if (( hue >= (_45PB70[x] + _3PB70[x]) / 2.0) && (hue < (_6PB70[x] + _45PB70[x]) / 2.0) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _45PB70[y] - _45PB70[x] ; + lbe = _45PB70[y]; + correctL = true; + } else if (( hue >= (_6PB70[x] + _45PB70[x]) / 2.0) && (hue < (_6PB70[x] + _75PB70[x]) / 2.0) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _6PB70[y] - _6PB70[x] ; + lbe = _6PB70[y]; + correctL = true; + } else if (( hue >= (_6PB70[x] + _75PB70[x]) / 2.0) && (hue < (_9PB70[x] + _75PB70[x]) / 2.0) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _75PB70[y] - _75PB70[x] ; + lbe = _75PB70[y]; + correctL = true; + } else if (( hue >= (_9PB70[x] + _75PB70[x]) / 2.0) && (hue < (_9PB70[x] + 0.035)) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _9PB70[y] - _9PB70[x] ; + lbe = _9PB70[y]; + correctL = true; + } + } else if (lum < 85.0) { + if( (hue <= (_05PB80[x] + _15PB80[x]) / 2.0) && (hue > (_05PB80[x] + _10B80[x]) / 2.0) && x < 40 ) { + if(y > 39) { + y = 39; + } + + correction = _05PB80[y] - _05PB80[x] ; + lbe = _05PB80[y] ; + correctL = true; + } else if( (hue <= (_05PB80[x] + _10B80[x]) / 2.0) && (hue > (_10B80[x] + _9B80[x]) / 2.0) && x < 40 ) { + if(y > 39) { + y = 39; + } + + correction = _10B80[y] - _10B80[x] ; + lbe = _10B80[y]; + correctL = true; + } else if( (hue <= (_10B80[x] + _9B80[x]) / 2.0) && (hue > (_9B80[x] + _7B80[x]) / 2.0) && x < 40 ) { + if(y > 39) { + y = 39; + } + + correction = _9B80[y] - _9B80[x] ; + lbe = _9B80[y]; + correctL = true; + } else if( (hue <= (_9B80[x] + _7B80[x]) / 2.0) && (hue > (_5B80[x] + _7B80[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _7B80[y] - _7B80[x] ; + lbe = _7B80[y]; + correctL = true; + } else if (( hue <= (_5B80[x] + _7B80[x]) / 2.0) && (hue > (_5B80[x] - 0.035)) && x < 50) { + if(y > 49) { + y = 49; // + } + + correction = _5B80[y] - _5B80[x] ; + lbe = _5B80[y]; + correctL = true; + } + + else if( (hue >= (_15PB80[x] - 0.035)) && (hue < (_15PB80[x] + _3PB80[x]) / 2.0) && x < 50 ) { + if(y > 49) { + y = 49; + } + + correction = _15PB80[y] - _15PB80[x] ; + lbe = _15PB80[y]; + correctL = true; + } else if (( hue >= (_45PB80[x] + _3PB80[x]) / 2.0) && (hue < (_6PB80[x] + _45PB80[x]) / 2.0) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _45PB80[y] - _45PB80[x] ; + lbe = _45PB80[y]; + correctL = true; + } else if (( hue >= (_6PB80[x] + _45PB80[x]) / 2.0) && (hue < (_6PB80[x] + _75PB80[x]) / 2.0) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _6PB80[y] - _6PB80[x] ; + lbe = _6PB80[y]; + correctL = true; + } else if (( hue >= (_6PB80[x] + _75PB80[x]) / 2.0) && (hue < (_9PB80[x] + _75PB80[x]) / 2.0) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _75PB80[y] - _75PB80[x] ; + lbe = _75PB80[y]; + correctL = true; + } else if (( hue >= (_9PB80[x] + _75PB80[x]) / 2.0) && (hue < (_9PB80[x] + 0.035)) && x < 50) { + if(y > 49) { + y = 49; + } + + correction = _9PB80[y] - _9PB80[x] ; + lbe = _9PB80[y]; + correctL = true; + } + } + } + } + // end PB correction + + //red yellow correction + else if(zone == 2) { + if(lum > 15.0) { + if(lum < 25.0) { + if( (hue <= (_10YR20[x] + 0.035)) && (hue > (_10YR20[x] + _85YR20[x]) / 2.0) && x <= 45) { + if(y > 49) { + y = 49; + } + + correction = _10YR20[y] - _10YR20[x] ; + lbe = _10YR20[y]; + correctL = true; + } else if (( hue <= (_85YR20[x] + _10YR20[x]) / 2.0) && (hue > (_85YR20[x] + 0.035) && x <= 45)) { + if(y > 49) { + y = 49; + } + + correction = _85YR20[y] - _85YR20[x] ; + lbe = _85YR20[y]; + correctL = true; + } + } else if (lum < 35.0) { + if( (hue <= (_10YR30[x] + 0.035)) && (hue > (_10YR30[x] + _85YR30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10YR30[y] - _10YR30[x] ; + lbe = _10YR30[y]; + correctL = true; + } else if( (hue <= (_10YR30[x] + _85YR30[x]) / 2.0) && (hue > (_85YR30[x] + _7YR30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _85YR30[y] - _85YR30[x] ; + lbe = _85YR30[y]; + correctL = true; + } else if (( hue <= (_85YR30[x] + _7YR30[x]) / 2.0) && (hue > (_7YR30[x] + _55YR30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7YR30[y] - _7YR30[x] ; + lbe = _7YR30[y]; + correctL = true; + } else if (( hue <= (_7YR30[x] + _55YR30[x]) / 2.0) && (hue > (_55YR30[x] + _4YR30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _55YR30[y] - _55YR30[x] ; + lbe = _55YR30[y]; + correctL = true; + } else if (( hue <= (_55YR30[x] + _4YR30[x]) / 2.0) && (hue > (_4YR30[x] + _25YR30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _4YR30[y] - _4YR30[x] ; + lbe = _4YR30[y]; + correctL = true; + } else if (( hue <= (_4YR30[x] + _25YR30[x]) / 2.0) && (hue > (_25YR30[x] + _10R30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _25YR30[y] - _25YR30[x] ; + lbe = _25YR30[y]; + correctL = true; + } else if (( hue <= (_25YR30[x] + _10R30[x]) / 2.0) && (hue > (_10R30[x] + _9R30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10R30[y] - _10R30[x] ; + lbe = _10R30[y]; + correctL = true; + } else if (( hue <= (_10R30[x] + _9R30[x]) / 2.0) && (hue > (_9R30[x] + _7R30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _9R30[y] - _9R30[x] ; + lbe = _9R30[y]; + correctL = true; + } else if (( hue <= (_9R30[x] + _7R30[x]) / 2.0) && (hue > (_7R30[x] - 0.035)) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7R30[y] - _7R30[x] ; + lbe = _7R30[y] ; + correctL = true; + } + } else if (lum < 45.0) { + if( (hue <= (_10YR40[x] + 0.035)) && (hue > (_10YR40[x] + _85YR40[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10YR40[y] - _10YR40[x] ; + lbe = _10YR40[y]; + correctL = true; + } else if( (hue <= (_10YR40[x] + _85YR40[x]) / 2.0) && (hue > (_85YR40[x] + _7YR40[x]) / 2.0) && x < 85 ) { + if(y > 89) { + y = 89; + } + + correction = _85YR40[y] - _85YR40[x] ; + lbe = _85YR40[y]; + correctL = true; + } else if (( hue <= (_85YR40[x] + _7YR40[x]) / 2.0) && (hue > (_7YR40[x] + _55YR40[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7YR40[y] - _7YR40[x] ; + lbe = _7YR40[y]; + correctL = true; + } else if (( hue <= (_7YR40[x] + _55YR40[x]) / 2.0) && (hue > (_55YR40[x] + _4YR40[x]) / 2.0) && x < 85 ) { + if(y > 89) { + y = 89; + } + + correction = _55YR40[y] - _55YR40[x] ; + lbe = _55YR40[y]; + correctL = true; + } else if (( hue <= (_55YR40[x] + _4YR40[x]) / 2.0) && (hue > (_4YR40[x] + _25YR40[x]) / 2.0) && x < 85 ) { + if(y > 89) { + y = 89; + } + + correction = _4YR40[y] - _4YR40[x] ; + lbe = _4YR40[y]; + correctL = true; + } else if (( hue <= (_4YR40[x] + _25YR40[x]) / 2.0) && (hue > (_25YR40[x] + _10R40[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _25YR40[y] - _25YR40[x] ; + lbe = _25YR40[y] ; + correctL = true; + } else if (( hue <= (_25YR40[x] + _10R40[x]) / 2.0) && (hue > (_10R40[x] + _9R40[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10R40[y] - _10R40[x] ; + lbe = _10R40[y]; + correctL = true; + } else if (( hue <= (_10R40[x] + _9R40[x]) / 2.0) && (hue > (_9R40[x] + _7R40[x]) / 2.0) && x < 85 ) { + if(y > 89) { + y = 89; + } + + correction = _9R40[y] - _9R40[x] ; + lbe = _9R40[y]; + correctL = true; + } else if (( hue <= (_9R40[x] + _7R40[x]) / 2.0) && (hue > (_7R40[x] - 0.035)) && x < 85 ) { + if(y > 89) { + y = 89; + } + + correction = _7R40[y] - _7R40[x] ; + lbe = _7R40[y]; + correctL = true; + } + } else if (lum < 55.0) { + if( (hue <= (_10YR50[x] + 0.035)) && (hue > (_10YR50[x] + _85YR50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10YR50[y] - _10YR50[x] ; + lbe = _10YR50[y]; + correctL = true; + } else if( (hue <= (_10YR50[x] + _85YR50[x]) / 2.0) && (hue > (_85YR50[x] + _7YR50[x]) / 2.0) && x < 85 ) { + if(y > 89) { + y = 89; + } + + correction = _85YR50[y] - _85YR50[x] ; + lbe = _85YR50[y]; + correctL = true; + } else if (( hue <= (_85YR50[x] + _7YR50[x]) / 2.0) && (hue > (_7YR50[x] + _55YR50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7YR50[y] - _7YR50[x] ; + lbe = _7YR50[y]; + correctL = true; + } else if (( hue <= (_7YR50[x] + _55YR50[x]) / 2.0) && (hue > (_55YR50[x] + _4YR50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _55YR50[y] - _55YR50[x] ; + lbe = _55YR50[y]; + correctL = true; + } else if (( hue <= (_55YR50[x] + _4YR50[x]) / 2.0) && (hue > (_4YR50[x] + _25YR50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _4YR50[y] - _4YR50[x] ; + lbe = _4YR50[y]; + correctL = true; + } else if (( hue <= (_4YR50[x] + _25YR50[x]) / 2.0) && (hue > (_25YR50[x] + _10R50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _25YR50[y] - _25YR50[x] ; + lbe = _25YR50[y]; + correctL = true; + } else if (( hue <= (_25YR50[x] + _10R50[x]) / 2.0) && (hue > (_10R50[x] + _9R50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10R50[y] - _10R50[x] ; + lbe = _10R50[y]; + correctL = true; + } else if (( hue <= (_10R50[x] + _9R50[x]) / 2.0) && (hue > (_9R50[x] + _7R50[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _9R50[y] - _9R50[x] ; + lbe = _9R50[y]; + correctL = true; + } else if (( hue <= (_9R50[x] + _7R50[x]) / 2.0) && (hue > (_7R50[x] - 0.035)) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7R50[y] - _7R50[x] ; + lbe = _7R50[y]; + correctL = true; + } + } else if (lum < 65.0) { + if( (hue <= (_10YR60[x] + 0.035)) && (hue > (_10YR60[x] + _85YR60[x]) / 2.0)) { + ; + correction = _10YR60[y] - _10YR60[x] ; + lbe = _10YR60[y]; + correctL = true; + } else if( (hue <= (_10YR60[x] + _85YR60[x]) / 2.0) && (hue > (_85YR60[x] + _7YR60[x]) / 2.0) ) { + ; + correction = _85YR60[y] - _85YR60[x] ; + lbe = _85YR60[y]; + correctL = true; + } else if (( hue <= (_85YR60[x] + _7YR60[x]) / 2.0) && (hue > (_7YR60[x] + _55YR60[x]) / 2.0)) { + correction = _7YR60[y] - _7YR60[x] ; + lbe = _7YR60[y]; + correctL = true; + } else if (( hue <= (_7YR60[x] + _55YR60[x]) / 2.0) && (hue > (_55YR60[x] + _4YR60[x]) / 2.0)) { + correction = _55YR60[y] - _55YR60[x] ; + lbe = _55YR60[y]; + correctL = true; + } else if (( hue <= (_55YR60[x] + _4YR60[x]) / 2.0) && (hue > (_4YR60[x] + _25YR60[x]) / 2.0)) { + correction = _4YR60[y] - _4YR60[x] ; + lbe = _4YR60[y]; + correctL = true; + } else if (( hue <= (_4YR60[x] + _25YR60[x]) / 2.0) && (hue > (_25YR60[x] + _10R60[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _25YR60[y] - _25YR60[x] ; + lbe = _25YR60[y]; + correctL = true; + } else if (( hue <= (_25YR60[x] + _10R60[x]) / 2.0) && (hue > (_10R60[x] + _9R60[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10R60[y] - _10R60[x] ; + lbe = _10R60[y]; + correctL = true; + } else if (( hue <= (_10R60[x] + _9R60[x]) / 2.0) && (hue > (_9R60[x] + _7R60[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _9R60[y] - _9R60[x] ; + lbe = _9R60[y]; + correctL = true; + } else if (( hue <= (_9R60[x] + _7R60[x]) / 2.0) && (hue > (_7R60[x] - 0.035)) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7R60[y] - _7R60[x] ; + lbe = _7R60[y]; + correctL = true; + } + } else if (lum < 75.0) { + if( (hue <= (_10YR70[x] + 0.035)) && (hue > (_10YR70[x] + _85YR70[x]) / 2.0)) { + correction = _10YR70[y] - _10YR70[x] ; + lbe = _10YR70[y]; + correctL = true; + } else if( (hue <= (_10YR70[x] + _85YR70[x]) / 2.0) && (hue > (_85YR70[x] + _7YR70[x]) / 2.0)) { + correction = _85YR70[y] - _85YR70[x] ; + lbe = _85YR70[y]; + correctL = true; + } + + if (( hue <= (_85YR70[x] + _7YR70[x]) / 2.0) && (hue > (_7YR70[x] + _55YR70[x]) / 2.0)) { + correction = _7YR70[y] - _7YR70[x] ; + lbe = _7YR70[y]; + correctL = true; + } else if (( hue <= (_7YR70[x] + _55YR70[x]) / 2.0) && (hue > (_55YR70[x] + _4YR70[x]) / 2.0)) { + correction = _55YR70[y] - _55YR70[x] ; + lbe = _55YR70[y]; + correctL = true; + } else if (( hue <= (_55YR70[x] + _4YR70[x]) / 2.0) && (hue > (_4YR70[x] + _25YR70[x]) / 2.0)) { + correction = _4YR70[y] - _4YR70[x] ; + lbe = _4YR70[y]; + correctL = true; + } else if (( hue <= (_4YR70[x] + _25YR70[x]) / 2.0) && (hue > (_25YR70[x] + _10R70[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _25YR70[y] - _25YR70[x] ; + lbe = _25YR70[y]; + correctL = true; + } else if (( hue <= (_25YR70[x] + _10R70[x]) / 2.0) && (hue > (_10R70[x] + _9R70[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10R70[y] - _10R70[x] ; + lbe = _10R70[y]; + correctL = true; + } else if (( hue <= (_10R70[x] + _9R70[x]) / 2.0) && (hue > (_9R70[x] + _7R70[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _9R70[y] - _9R70[x] ; + lbe = _9R70[y] ; + correctL = true; + } else if (( hue <= (_9R70[x] + _7R70[x]) / 2.0) && (hue > (_7R70[x] - 0.035)) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7R70[y] - _7R70[x] ; + lbe = _7R70[y]; + correctL = true; + } + } else if (lum < 85.0) { + if( (hue <= (_10YR80[x] + 0.035)) && (hue > (_10YR80[x] + _85YR80[x]) / 2.0)) { + correction = _10YR80[y] - _10YR80[x] ; + lbe = _10YR80[y]; + correctL = true; + } else if( (hue <= (_10YR80[x] + _85YR80[x]) / 2.0) && (hue > (_85YR80[x] + _7YR80[x]) / 2.0)) { + correction = _85YR80[y] - _85YR80[x] ; + lbe = _85YR80[y]; + } else if (( hue <= (_85YR80[x] + _7YR80[x]) / 2.0) && (hue > (_7YR80[x] + _55YR80[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _7YR80[y] - _7YR80[x] ; + lbe = _7YR80[y]; + correctL = true; + } else if (( hue <= (_7YR80[x] + _55YR80[x]) / 2.0) && (hue > (_55YR80[x] + _4YR80[x]) / 2.0) && x < 45) { + correction = _55YR80[y] - _55YR80[x] ; + lbe = _55YR80[y]; + correctL = true; + } else if (( hue <= (_55YR80[x] + _4YR80[x]) / 2.0) && (hue > (_4YR80[x] - 0.035) && x < 45)) { + if(y > 49) { + y = 49; + } + + correction = _4YR80[y] - _4YR80[x] ; + lbe = _4YR80[y] ; + correctL = true; + } + } else if (lum < 95.0) { + if( (hue <= (_10YR90[x] + 0.035)) && (hue > (_10YR90[x] - 0.035) && x < 85)) { + if(y > 89) { + y = 89; + } + + correction = _10YR90[y] - _10YR90[x] ; + lbe = _10YR90[y]; + correctL = true; + } else if ( hue <= (_85YR90[x] + 0.035) && hue > (_85YR90[x] - 0.035) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _85YR90[y] - _85YR90[x] ; + lbe = _85YR90[y]; + correctL = true; + } else if (( hue <= (_55YR90[x] + 0.035) && (hue > (_55YR90[x] - 0.035) && x < 45))) { + if(y > 49) { + y = 49; + } + + correction = _55YR90[y] - _55YR90[x] ; + lbe = _55YR90[y]; + correctL = true; + } + } + } + } + //end red yellow + + //Green yellow correction + else if(zone == 3) { + if (lum >= 25.0) { + if (lum < 35.0) { + if( (hue <= (_7G30[x] + 0.035)) && (hue > (_7G30[x] + _5G30[x]) / 2.0) ) { + correction = _7G30[y] - _7G30[x] ; + lbe = _7G30[y]; + correctL = true; + } else if( (hue <= (_7G30[x] + _5G30[x]) / 2.0) && (hue > (_5G30[x] + _25G30[x]) / 2.0)) { + correction = _5G30[y] - _5G30[x] ; + lbe = _5G30[y]; + correctL = true; + } else if (( hue <= (_25G30[x] + _5G30[x]) / 2.0) && (hue > (_25G30[x] + _1G30[x]) / 2.0)) { + correction = _25G30[y] - _25G30[x] ; + lbe = _25G30[y]; + correctL = true; + } else if (( hue <= (_1G30[x] + _25G30[x]) / 2.0) && (hue > (_1G30[x] + _10GY30[x]) / 2.0)) { + correction = _1G30[y] - _1G30[x] ; + lbe = _1G30[y]; + correctL = true; + } else if (( hue <= (_1G30[x] + _10GY30[x]) / 2.0) && (hue > (_10GY30[x] + _75GY30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10GY30[y] - _10GY30[x] ; + lbe = _10GY30[y]; + correctL = true; + } else if (( hue <= (_10GY30[x] + _75GY30[x]) / 2.0) && (hue > (_75GY30[x] + _5GY30[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _75GY30[y] - _75GY30[x] ; + lbe = _75GY30[y]; + correctL = true; + } else if (( hue <= (_5GY30[x] + _75GY30[x]) / 2.0) && (hue > (_5GY30[x] - 0.035)) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _5GY30[y] - _5GY30[x] ; + lbe = _5GY30[y] ; + correctL = true; + } + } else if (lum < 45.0) { + if( (hue <= (_7G40[x] + 0.035)) && (hue > (_7G40[x] + _5G40[x]) / 2.0) ) { + correction = _7G40[y] - _7G40[x] ; + lbe = _7G40[y]; + correctL = true; + } else if( (hue <= (_7G40[x] + _5G40[x]) / 2.0) && (hue > (_5G40[x] + _25G40[x]) / 2.0)) { + correction = _5G40[y] - _5G40[x] ; + lbe = _5G40[y]; + correctL = true; + } else if (( hue <= (_25G40[x] + _5G40[x]) / 2.0) && (hue > (_25G40[x] + _1G40[x]) / 2.0)) { + correction = _25G40[y] - _25G40[x] ; + lbe = _25G40[y]; + correctL = true; + } else if (( hue <= (_1G40[x] + _25G40[x]) / 2.0) && (hue > (_1G40[x] + _10GY40[x]) / 2.0)) { + correction = _1G40[y] - _1G40[x] ; + lbe = _1G40[y]; + correctL = true; + } else if (( hue <= (_1G40[x] + _10GY40[x]) / 2.0) && (hue > (_10GY40[x] + _75GY40[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _10GY40[y] - _10GY40[x] ; + lbe = _10GY40[y]; + correctL = true; + } else if (( hue <= (_10GY40[x] + _75GY40[x]) / 2.0) && (hue > (_75GY40[x] + _5GY40[x]) / 2.0) && x < 85) { + if(y > 89) { + y = 89; + } + + correction = _75GY40[y] - _75GY40[x] ; + lbe = _75GY40[y]; + correctL = true; + } else if (( hue <= (_5GY40[x] + _75GY40[x]) / 2.0) && (hue > (_5GY40[x] - 0.035)) && x < 85) { + if(y > 89) { + y = 89; // + } + + correction = _5GY40[y] - _5GY40[x] ; + lbe = _5GY40[y]; + correctL = true; + } + } else if (lum < 55.0) { + if( (hue <= (_7G50[x] + 0.035)) && (hue > (_7G50[x] + _5G50[x]) / 2.0) ) { + correction = _7G50[y] - _7G50[x] ; + lbe = _7G50[y]; + correctL = true; + } else if( (hue <= (_7G50[x] + _5G50[x]) / 2.0) && (hue > (_5G50[x] + _25G50[x]) / 2.0)) { + correction = _5G50[y] - _5G50[x] ; + lbe = _5G50[y]; + correctL = true; + } else if (( hue <= (_25G50[x] + _5G50[x]) / 2.0) && (hue > (_25G50[x] + _1G50[x]) / 2.0)) { + correction = _25G50[y] - _25G50[x] ; + lbe = _25G50[y]; + correctL = true; + } else if (( hue <= (_1G50[x] + _25G50[x]) / 2.0) && (hue > (_1G50[x] + _10GY50[x]) / 2.0)) { + correction = _1G50[y] - _1G50[x] ; + lbe = _1G50[y]; + correctL = true; + } else if (( hue <= (_1G50[x] + _10GY50[x]) / 2.0) && (hue > (_10GY50[x] + _75GY50[x]) / 2.0)) { + correction = _10GY50[y] - _10GY50[x] ; + lbe = _10GY50[y]; + correctL = true; + } else if (( hue <= (_10GY50[x] + _75GY50[x]) / 2.0) && (hue > (_75GY50[x] + _5GY50[x]) / 2.0)) { + correction = _75GY50[y] - _75GY50[x] ; + lbe = _75GY50[y]; + correctL = true; + } else if (( hue <= (_5GY50[x] + _75GY50[x]) / 2.0) && (hue > (_5GY50[x] - 0.035))) { + correction = _5GY50[y] - _5GY50[x] ; + lbe = _5GY50[y]; + correctL = true; + } + } else if (lum < 65.0) { + if( (hue <= (_7G60[x] + 0.035)) && (hue > (_7G60[x] + _5G60[x]) / 2.0) ) { + correction = _7G60[y] - _7G60[x] ; + lbe = _7G60[y]; + correctL = true; + } else if( (hue <= (_7G60[x] + _5G60[x]) / 2.0) && (hue > (_5G60[x] + _25G60[x]) / 2.0)) { + correction = _5G60[y] - _5G60[x] ; + lbe = _5G60[y]; + correctL = true; + } else if (( hue <= (_25G60[x] + _5G60[x]) / 2.0) && (hue > (_25G60[x] + _1G60[x]) / 2.0)) { + correction = _25G60[y] - _25G60[x] ; + lbe = _25G60[y]; + correctL = true; + } else if (( hue <= (_1G60[x] + _25G60[x]) / 2.0) && (hue > (_1G60[x] + _10GY60[x]) / 2.0)) { + correction = _1G60[y] - _1G60[x] ; + lbe = _1G60[y]; + correctL = true; + } else if (( hue <= (_1G60[x] + _10GY60[x]) / 2.0) && (hue > (_10GY60[x] + _75GY60[x]) / 2.0)) { + correction = _10GY60[y] - _10GY60[x] ; + lbe = _10GY60[y]; + correctL = true; + } else if (( hue <= (_10GY60[x] + _75GY60[x]) / 2.0) && (hue > (_75GY60[x] + _5GY60[x]) / 2.0)) { + correction = _75GY60[y] - _75GY60[x] ; + lbe = _75GY60[y] ; + correctL = true; + } else if (( hue <= (_5GY60[x] + _75GY60[x]) / 2.0) && (hue > (_5GY60[x] - 0.035))) { + correction = _5GY60[y] - _5GY60[x] ; + lbe = _5GY60[y]; + correctL = true; + } + } else if (lum < 75.0) { + if( (hue <= (_7G70[x] + 0.035)) && (hue > (_7G70[x] + _5G70[x]) / 2.0) ) { + correction = _7G70[y] - _7G70[x] ; + lbe = _7G70[y]; + correctL = true; + } else if( (hue <= (_7G70[x] + _5G70[x]) / 2.0) && (hue > (_5G70[x] + _25G70[x]) / 2.0)) { + correction = _5G70[y] - _5G70[x] ; + lbe = _5G70[y]; + correctL = true; + } else if (( hue <= (_25G70[x] + _5G70[x]) / 2.0) && (hue > (_25G70[x] + _1G70[x]) / 2.0)) { + correction = _25G70[y] - _25G70[x] ; + lbe = _25G70[y]; + correctL = true; + } else if (( hue <= (_1G70[x] + _25G70[x]) / 2.0) && (hue > (_1G70[x] + _10GY70[x]) / 2.0)) { + correction = _1G70[y] - _1G70[x] ; + lbe = _1G70[y] ; + correctL = true; + } else if (( hue <= (_1G70[x] + _10GY70[x]) / 2.0) && (hue > (_10GY70[x] + _75GY70[x]) / 2.0)) { + correction = _10GY70[y] - _10GY70[x] ; + lbe = _10GY70[y]; + correctL = true; + } else if (( hue <= (_10GY70[x] + _75GY70[x]) / 2.0) && (hue > (_75GY70[x] + _5GY70[x]) / 2.0)) { + correction = _75GY70[y] - _75GY70[x] ; + lbe = _75GY70[y]; + correctL = true; + } else if (( hue <= (_5GY70[x] + _75GY70[x]) / 2.0) && (hue > (_5GY70[x] - 0.035))) { + correction = _5GY70[y] - _5GY70[x] ; + lbe = _5GY70[y]; + correctL = true; + } + } else if (lum < 85.0) { + if( (hue <= (_7G80[x] + 0.035)) && (hue > (_7G80[x] + _5G80[x]) / 2.0) ) { + correction = _7G80[y] - _7G80[x] ; + lbe = _7G80[y]; + correctL = true; + } else if( (hue <= (_7G80[x] + _5G80[x]) / 2.0) && (hue > (_5G80[x] + _25G80[x]) / 2.0)) { + correction = _5G80[y] - _5G80[x] ; + lbe = _5G80[y]; + correctL = true; + } else if (( hue <= (_25G80[x] + _5G80[x]) / 2.0) && (hue > (_25G80[x] + _1G80[x]) / 2.0)) { + correction = _25G80[y] - _25G80[x] ; + lbe = _25G80[y]; + correctL = true; + } else if (( hue <= (_1G80[x] + _25G80[x]) / 2.0) && (hue > (_1G80[x] + _10GY80[x]) / 2.0)) { + correction = _1G80[y] - _1G80[x] ; + lbe = _1G80[y]; + correctL = true; + } else if (( hue <= (_1G80[x] + _10GY80[x]) / 2.0) && (hue > (_10GY80[x] + _75GY80[x]) / 2.0)) { + correction = _10GY80[y] - _10GY80[x] ; + lbe = _10GY80[y]; + correctL = true; + } else if (( hue <= (_10GY80[x] + _75GY80[x]) / 2.0) && (hue > (_75GY80[x] + _5GY80[x]) / 2.0)) { + correction = _75GY80[y] - _75GY80[x] ; + lbe = _75GY80[y]; + correctL = true; + } else if (( hue <= (_5GY80[x] + _75GY80[x]) / 2.0) && (hue > (_5GY80[x] - 0.035))) { + correction = _5GY80[y] - _5GY80[x] ; + lbe = _5GY80[y]; + correctL = true; + } + } + } + } + //end green yellow + + //Red purple correction : only for L < 30 + else if(zone == 4) { + if (lum > 5.0) { + if (lum < 15.0) { + if( (hue <= (_5R10[x] + 0.035)) && (hue > (_5R10[x] - 0.043)) && x < 45) { + if(y > 44) { + y = 44; + } + + correction = _5R10[y] - _5R10[x] ; + lbe = _5R10[y]; + correctL = true; + } else if( (hue <= (_25R10[x] + 0.043)) && (hue > (_25R10[x] + _10RP10[x]) / 2.0) && x < 45 ) { + if(y > 44) { + y = 44; + } + + correction = _25R10[y] - _25R10[x] ; + lbe = _25R10[y]; + correctL = true; + } else if ( (hue <= (_25R10[x] + _10RP10[x]) / 2.0) && (hue > (_10RP10[x] - 0.035) ) && x < 45) { + if(y > 44) { + y = 44; + } + + correction = _10RP10[y] - _10RP10[x] ; + lbe = _10RP10[y]; + correctL = true; + } + } else if (lum < 25.0) { + if( (hue <= (_5R20[x] + 0.035)) && (hue > (_5R20[x] + _25R20[x]) / 2.0) && x < 70 ) { + if(y > 70) { + y = 70; + } + + correction = _5R20[y] - _5R20[x] ; + lbe = _5R20[y]; + correctL = true; + } else if( (hue <= (_5R20[x] + _25R20[x]) / 2.0) && (hue > (_10RP20[x] + _25R20[x]) / 2.0) && x < 70) { + if(y > 70) { + y = 70; + } + + correction = _25R20[y] - _25R20[x] ; + lbe = _25R20[y]; + correctL = true; + } else if (( hue <= (_10RP20[x] + _25R20[x]) / 2.0) && (hue > (_10RP20[x] - 0.035)) && x < 70) { + if(y > 70) { + y = 70; + } + + correction = _10RP20[y] - _10RP20[x] ; + lbe = _10RP20[y]; + correctL = true; + } + } else if (lum < 35.0) { + if( (hue <= (_5R30[x] + 0.035)) && (hue > (_5R30[x] + _25R30[x]) / 2.0) && x < 85 ) { + if(y > 85) { + y = 85; + } + + correction = _5R30[y] - _5R30[x] ; + lbe = _5R30[y]; + correctL = true; + } else if( (hue <= (_5R30[x] + _25R30[x]) / 2.0) && (hue > (_10RP30[x] + _25R30[x]) / 2.0) && x < 85) { + if(y > 85) { + y = 85; + } + + correction = _25R30[y] - _25R30[x] ; + lbe = _25R30[y]; + correctL = true; + } else if (( hue <= (_10RP30[x] + _25R30[x]) / 2.0) && (hue > (_10RP30[x] - 0.035)) && x < 85) { + if(y > 85) { + y = 85; + } + + correction = _10RP30[y] - _10RP30[x] ; + lbe = _10RP30[y]; + correctL = true; + } + } + } + } + + //end red purple +} + + +/* + * SkinSat + * Copyright (c)2011 Jacques Desmis + * + * skin color: mixed from NX2 skin color palette, Von Luschan, and photos of people white, + * black, yellow....there are some little exceptions...cover 99% case + * pay attention to white balance, and do not change hue and saturation, upstream of the modification + * + */ +void Color::SkinSat (float lum, float hue, float chrom, float &satreduc) +{ + + // to be adapted...by tests + float reduction = 0.3f; // use "reduction" for "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1 + float extendedreduction = 0.4f; // use "extendedreduction" for wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation + float extendedreduction2 = 0.6f; // use "extendedreduction2" for wide area for transition + + float C9 = 8.0, C8 = 15.0, C7 = 12.0, C4 = 7.0, C3 = 5.0, C2 = 5.0, C1 = 5.0; + float H9 = 0.05, H8 = 0.25, H7 = 0.1, H4 = 0.02, H3 = 0.02, H2 = 0.1, H1 = 0.1, H10 = -0.2, H11 = -0.2; //H10 and H11 are curious...H11=-0.8 ?? + + if (lum >= 85.f) { + if((hue > (0.78f - H9) && hue < (1.18f + H9)) && (chrom > 8.f && chrom < (14.f + C9))) { + satreduc = reduction; + } else if (lum >= 92.f) { + if((hue > 0.8f && hue < 1.65f) && (chrom > 7.f && chrom < (15.f))) { + satreduc = extendedreduction; + } else if ((hue > -0.1f && hue < 1.65f) && (chrom > 7.f && chrom < (18.f))) { + satreduc = extendedreduction2; + } + } else if ((hue > 0.7f && hue < 1.4f) && (chrom > 7.f && chrom < (26.f + C9))) { + satreduc = extendedreduction; + } else if (lum < 92.f && (hue > 0.f && hue < 1.65f) && (chrom > 7.f && chrom < (35.f + C9))) { + satreduc = extendedreduction2; + } + } else if (lum >= 70.f) { + if((hue > 0.4f && hue < (1.04f + H8)) && (chrom > 8.f && chrom < (35.f + C8))) { + satreduc = reduction; + } else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f + C9) )) { + satreduc = extendedreduction; + } else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f + C9) )) { + satreduc = extendedreduction2; + } + } else if (lum >= 52.f) { + if((hue > 0.3f && hue < (1.27f + H7)) && (chrom > 11.f && chrom < (35.f + C7))) { + satreduc = reduction; + } else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f + C9) )) { + satreduc = extendedreduction; + } else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f + C9) )) { + satreduc = extendedreduction2; + } + } else if (lum >= 35.f) { + if((hue > 0.3f && hue < (1.25f + H4)) && (chrom > 13.f && chrom < (37.f + C4))) { + satreduc = reduction; + } else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f + C9) )) { + satreduc = extendedreduction; + } else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f + C9) )) { + satreduc = extendedreduction2; + } + } else if (lum >= 20.f) { + if((hue > 0.3f && hue < (1.2f + H3)) && (chrom > 7.f && chrom < (35.f + C3) )) { + satreduc = reduction; + } else if ((hue > (0.02f + H11) && hue < 1.5f) && (chrom > 7.0f && chrom < (48.f + C9) )) { + satreduc = extendedreduction; + } else if ((hue > (0.02f + H11) && hue < 1.65f) && (chrom > 7.f && chrom < (55.f + C9) )) { + satreduc = extendedreduction2; + } + } else if (lum > 10.f) { + if((hue > (0.f + H10) && hue < (0.95f + H2)) && (chrom > 8.f && chrom < (23.f + C2))) { + satreduc = reduction; + } else if ((hue > (0.02f + H11) && hue < 1.f) && (chrom > 7.f && chrom < (35.f + C1) )) { + satreduc = extendedreduction; + } else if ((hue > (0.02f + H11) && hue < 1.6f) && (chrom > 7.f && chrom < (45.f + C1) )) { + satreduc = extendedreduction2; + } + } else { + if((hue > (0.02f + H10) && hue < (0.9f + H1)) && (chrom > 8.f && chrom < (23.f + C1))) { + satreduc = reduction; // no data : extrapolate + } else if ((hue > (0.02f + H11) && hue < 1.f) && (chrom > 7.f && chrom < (35.f + C1) )) { + satreduc = extendedreduction; + } else if ((hue > (0.02f + H11) && hue < 1.6f) && (chrom > 7.f && chrom < (45.f + C1) )) { + satreduc = extendedreduction2; + } + + } + +} + +/* + * Munsell Lch correction + * Copyright (c) 2011 Jacques Desmis + * + * data (Munsell ==> Lab) obtained with WallKillcolor and http://www.cis.rit.edu/research/mcsl2/online/munsell.php + * each LUT give Hue in function of C, for each color Munsell and Luminance + * eg: _6PB20 : color Munsell 6PB for L=20 c=5 c=45 c=85 c=125..139 when possible: interpolation betwwen values + * no value for C<5 (gray) + * low memory footprint -- maximum: 195 LUTf * 140 values + * errors due to small number of samples in LUT and linearization are very low (1 to 2%) + * errors due to a different illuminant "Daylight" than "C" are low, about 10%. For example, a theoretical correction of 0.1 radian will be made with a real correction of 0.09 or 0.11 depending on the color illuminant D50 + * errors due to the use of a very different illuminant "C", for example illuminant "A" (tungsten) are higher, about 20%. Theoretical correction of 0.52 radians will be made with a real correction of 0.42 + */ +void Color::initMunsell () +{ +#ifdef _DEBUG + MyTime t1e, t2e; + t1e.set(); +#endif const int maxInd = 140; const int maxInd2 = 90; @@ -2021,177 +3661,296 @@ SSEFUNCTION void Color::LabGamutMunsell(float *labL, float *laba, float *labb, //blue for sky _5B40(maxInd2); _5B40.clear(); - for (int i=0; i5) _5B40[i] = -2.3 + 0.0025*(i-5); - else if (i<90 && i>=45) _5B40[i] = -2.2 + 0.00*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5B40[i] = -2.3 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _5B40[i] = -2.2 + 0.00 * (i - 45); } - //printf("5B %1.2f %1.2f\n",_5B40[44],_5B40[89]); + } + + //printf("5B %1.2f %1.2f\n",_5B40[44],_5B40[89]); _5B50(maxInd2); _5B50.clear(); - for (int i=0; i5) _5B50[i] = -2.34 + 0.0025*(i-5); - else if (i<90 && i>=45) _5B50[i] = -2.24+0.0003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5B50[i] = -2.34 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _5B50[i] = -2.24 + 0.0003 * (i - 45); } - //printf("5B %1.2f %1.2f\n",_5B50[44],_5B50[89]); + } + + //printf("5B %1.2f %1.2f\n",_5B50[44],_5B50[89]); _5B60(maxInd2); _5B60.clear(); - for (int i=0; i5) _5B60[i] = -2.4 + 0.003*(i-5); - else if (i<90 && i>=45) _5B60[i] = -2.28+0.0005*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5B60[i] = -2.4 + 0.003 * (i - 5); + } else if (i < 90 && i >= 45) { + _5B60[i] = -2.28 + 0.0005 * (i - 45); } - //printf("5B %1.2f %1.2f\n",_5B60[44],_5B60[89]); + } + + //printf("5B %1.2f %1.2f\n",_5B60[44],_5B60[89]); _5B70(maxInd2); _5B70.clear(); - for (int i=0; i5) _5B70[i] = -2.41 + 0.00275*(i-5); - else if (i<90 && i>=45) _5B70[i] = -2.30+0.00025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5B70[i] = -2.41 + 0.00275 * (i - 5); + } else if (i < 90 && i >= 45) { + _5B70[i] = -2.30 + 0.00025 * (i - 45); } - //printf("5B %1.2f %1.2f\n",_5B70[44],_5B70[89]); + } + + //printf("5B %1.2f %1.2f\n",_5B70[44],_5B70[89]); _5B80(maxInd3); _5B80.clear(); - for (int i=0; i5) _5B80[i] = -2.45 +0.003*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _5B80[i] = -2.45 + 0.003 * (i - 5); } - //printf("5B %1.2f\n",_5B80[49]); + } + + //printf("5B %1.2f\n",_5B80[49]); _7B40(maxInd2); _7B40.clear(); - for (int i=0; i5) _7B40[i] = -2.15 + 0.0027*(i-5); - else if (i<90 && i>=45) _7B40[i] = -2.04 + 0.00*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7B40[i] = -2.15 + 0.0027 * (i - 5); + } else if (i < 90 && i >= 45) { + _7B40[i] = -2.04 + 0.00 * (i - 45); } - //printf("7B %1.2f %1.2f\n",_7B40[44],_7B40[89]); + } + + //printf("7B %1.2f %1.2f\n",_7B40[44],_7B40[89]); _7B50(maxInd2); _7B50.clear(); - for (int i=0; i5) _7B50[i] = -2.20 + 0.003*(i-5); - else if (i<90 && i>=45) _7B50[i] = -2.08 + 0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7B50[i] = -2.20 + 0.003 * (i - 5); + } else if (i < 90 && i >= 45) { + _7B50[i] = -2.08 + 0.001 * (i - 45); } - //printf("7B %1.2f %1.2f\n",_7B50[44],_7B50[79]); + } + + //printf("7B %1.2f %1.2f\n",_7B50[44],_7B50[79]); _7B60(maxInd2); _7B60.clear(); - for (int i=0; i5) _7B60[i] = -2.26 + 0.0035*(i-5); - else if (i<90 && i>=45) _7B60[i] = -2.12 + 0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7B60[i] = -2.26 + 0.0035 * (i - 5); + } else if (i < 90 && i >= 45) { + _7B60[i] = -2.12 + 0.001 * (i - 45); } - //printf("7B %1.2f %1.2f\n",_7B60[44],_7B60[79]); + } + + //printf("7B %1.2f %1.2f\n",_7B60[44],_7B60[79]); _7B70(maxInd2); _7B70.clear(); - for (int i=0; i5) _7B70[i] = -2.28 + 0.003*(i-5); - else if (i<90 && i>=45) _7B70[i] = -2.16 + 0.0015*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7B70[i] = -2.28 + 0.003 * (i - 5); + } else if (i < 90 && i >= 45) { + _7B70[i] = -2.16 + 0.0015 * (i - 45); } - //printf("7B %1.2f %1.2f\n",_7B70[44],_7B70[64]); + } + + //printf("7B %1.2f %1.2f\n",_7B70[44],_7B70[64]); _7B80(maxInd3); _7B80.clear(); - for (int i=0; i5) _7B80[i] = -2.30 +0.0028*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _7B80[i] = -2.30 + 0.0028 * (i - 5); } - //printf("5B %1.2f\n",_7B80[49]); + } + + //printf("5B %1.2f\n",_7B80[49]); _9B40(maxInd2); _9B40.clear(); - for (int i=0; i5) _9B40[i] = -1.99 + 0.0022*(i-5); - else if (i<90 && i>=45) _9B40[i] = -1.90 + 0.0008*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9B40[i] = -1.99 + 0.0022 * (i - 5); + } else if (i < 90 && i >= 45) { + _9B40[i] = -1.90 + 0.0008 * (i - 45); } - //printf("9B %1.2f %1.2f\n",_9B40[44],_9B40[69]); + } + + //printf("9B %1.2f %1.2f\n",_9B40[44],_9B40[69]); _9B50(maxInd2); _9B50.clear(); - for (int i=0; i5) _9B50[i] = -2.04 + 0.0025*(i-5); - else if (i<90 && i>=45) _9B50[i] = -1.94 + 0.0013*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9B50[i] = -2.04 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _9B50[i] = -1.94 + 0.0013 * (i - 45); } - //printf("9B %1.2f %1.2f\n",_9B50[44],_9B50[77]); + } + + //printf("9B %1.2f %1.2f\n",_9B50[44],_9B50[77]); _9B60(maxInd2); _9B60.clear(); - for (int i=0; i5) _9B60[i] = -2.10 + 0.0033*(i-5); - else if (i<90 && i>=45) _9B60[i] = -1.97 + 0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9B60[i] = -2.10 + 0.0033 * (i - 5); + } else if (i < 90 && i >= 45) { + _9B60[i] = -1.97 + 0.001 * (i - 45); } - //printf("9B %1.2f %1.2f\n",_9B60[44],_9B60[79]); + } + + //printf("9B %1.2f %1.2f\n",_9B60[44],_9B60[79]); _9B70(maxInd2); _9B70.clear(); - for (int i=0; i5) _9B70[i] = -2.12 + 0.003*(i-5); - else if (i<90 && i>=45) _9B70[i] = -2.00 + 0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9B70[i] = -2.12 + 0.003 * (i - 5); + } else if (i < 90 && i >= 45) { + _9B70[i] = -2.00 + 0.001 * (i - 45); } - //printf("9B %1.2f %1.2f\n",_9B70[44],_9B70[54]); + } + + //printf("9B %1.2f %1.2f\n",_9B70[44],_9B70[54]); _9B80(maxInd3); _9B80.clear(); - for (int i=0; i5) _9B80[i] = -2.16 +0.0025*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _9B80[i] = -2.16 + 0.0025 * (i - 5); } - //printf("9B %1.2f\n",_9B80[49]); + } + + //printf("9B %1.2f\n",_9B80[49]); _10B40(maxInd2); _10B40.clear(); - for (int i=0; i5) _10B40[i] = -1.92 + 0.0022*(i-5); - else if (i<90 && i>=45) _10B40[i] = -1.83 + 0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10B40[i] = -1.92 + 0.0022 * (i - 5); + } else if (i < 90 && i >= 45) { + _10B40[i] = -1.83 + 0.0012 * (i - 45); } - //printf("10B %1.2f %1.2f\n",_10B40[44],_10B40[76]); + } + + //printf("10B %1.2f %1.2f\n",_10B40[44],_10B40[76]); _10B50(maxInd2); _10B50.clear(); - for (int i=0; i5) _10B50[i] = -1.95 + 0.0022*(i-5); - else if (i<90 && i>=45) _10B50[i] = -1.86 + 0.0008*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10B50[i] = -1.95 + 0.0022 * (i - 5); + } else if (i < 90 && i >= 45) { + _10B50[i] = -1.86 + 0.0008 * (i - 45); } - //printf("10B %1.2f %1.2f\n",_10B50[44],_10B50[85]); + } + + //printf("10B %1.2f %1.2f\n",_10B50[44],_10B50[85]); _10B60(maxInd2); _10B60.clear(); - for (int i=0; i5) _10B60[i] = -2.01 + 0.0027*(i-5); - else if (i<90 && i>=45) _10B60[i] = -1.90 + 0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10B60[i] = -2.01 + 0.0027 * (i - 5); + } else if (i < 90 && i >= 45) { + _10B60[i] = -1.90 + 0.0012 * (i - 45); } - //printf("10B %1.2f %1.2f\n",_10B60[44],_10B60[70]); + } + + //printf("10B %1.2f %1.2f\n",_10B60[44],_10B60[70]); _10B70(maxInd3); _10B70.clear(); - for (int i=0; i5) _10B70[i] = -2.03 +0.0025*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _10B70[i] = -2.03 + 0.0025 * (i - 5); } - //printf("10B %1.2f\n",_10B70[49]); + } + + //printf("10B %1.2f\n",_10B70[49]); _10B80(maxInd3); _10B80.clear(); - for (int i=0; i5) _10B80[i] = -2.08 +0.0032*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _10B80[i] = -2.08 + 0.0032 * (i - 5); } - //printf("10B %1.2f\n",_10B80[39]); + } + + //printf("10B %1.2f\n",_10B80[39]); _05PB40(maxInd2); _05PB40.clear(); - for (int i=0; i5) _05PB40[i] = -1.87 + 0.0022*(i-5); - else if (i<90 && i>=45) _05PB40[i] = -1.78 + 0.0015*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _05PB40[i] = -1.87 + 0.0022 * (i - 5); + } else if (i < 90 && i >= 45) { + _05PB40[i] = -1.78 + 0.0015 * (i - 45); } - //printf("05PB %1.2f %1.2f\n",_05PB40[44],_05PB40[74]); + } + + //printf("05PB %1.2f %1.2f\n",_05PB40[44],_05PB40[74]); _05PB50(maxInd2); _05PB50.clear(); - for (int i=0; i5) _05PB50[i] = -1.91 + 0.0022*(i-5); - else if (i<90 && i>=45) _05PB50[i] = -1.82 + 0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _05PB50[i] = -1.91 + 0.0022 * (i - 5); + } else if (i < 90 && i >= 45) { + _05PB50[i] = -1.82 + 0.001 * (i - 45); } - //printf("05PB %1.2f %1.2f\n",_05PB50[44],_05PB50[85]); + } + + //printf("05PB %1.2f %1.2f\n",_05PB50[44],_05PB50[85]); _05PB60(maxInd2); _05PB60.clear(); - for (int i=0; i5) _05PB60[i] = -1.96 + 0.0027*(i-5); - else if (i<90 && i>=45) _05PB60[i] = -1.85 + 0.0013*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _05PB60[i] = -1.96 + 0.0027 * (i - 5); + } else if (i < 90 && i >= 45) { + _05PB60[i] = -1.85 + 0.0013 * (i - 45); } - //printf("05PB %1.2f %1.2f\n",_05PB60[44],_05PB60[70]); + } + + //printf("05PB %1.2f %1.2f\n",_05PB60[44],_05PB60[70]); _05PB70(maxInd2); _05PB70.clear(); - for (int i=0; i5) _05PB70[i] = -1.99 + 0.0027*(i-5); - else if (i<90 && i>=45) _05PB70[i] = -1.88 + 0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _05PB70[i] = -1.99 + 0.0027 * (i - 5); + } else if (i < 90 && i >= 45) { + _05PB70[i] = -1.88 + 0.001 * (i - 45); } - //printf("05PB %1.2f %1.2f\n",_05PB70[44],_05PB70[54]); + } + + //printf("05PB %1.2f %1.2f\n",_05PB70[44],_05PB70[54]); _05PB80(maxInd3); _05PB80.clear(); - for (int i=0; i5) _05PB80[i] = -2.03 +0.003*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _05PB80[i] = -2.03 + 0.003 * (i - 5); } - //printf("05PB %1.2f\n",_05PB80[39]); + } + + //printf("05PB %1.2f\n",_05PB80[39]); @@ -2202,1383 +3961,2307 @@ SSEFUNCTION void Color::LabGamutMunsell(float *labL, float *laba, float *labb, //15PB _15PB10(maxInd3); _15PB10.clear(); - for (int i=0; i5) _15PB10[i] = -1.66 +0.0035*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _15PB10[i] = -1.66 + 0.0035 * (i - 5); } - //printf("15 %1.2f\n",_15PB10[49]); + } + + //printf("15 %1.2f\n",_15PB10[49]); _15PB20(maxInd2); _15PB20.clear(); - for (int i=0; i5) _15PB20[i] = -1.71 +0.00275*(i-5); - else if (i<90 && i>=45) _15PB20[i] = -1.60+0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _15PB20[i] = -1.71 + 0.00275 * (i - 5); + } else if (i < 90 && i >= 45) { + _15PB20[i] = -1.60 + 0.0012 * (i - 45); } - //printf("15 %1.2f %1.2f\n",_15PB20[44],_15PB20[89]); + } + + //printf("15 %1.2f %1.2f\n",_15PB20[44],_15PB20[89]); _15PB30(maxInd2); _15PB30.clear(); - for (int i=0; i5) _15PB30[i] = -1.75 +0.0025*(i-5); - else if (i<90 && i>=45) _15PB30[i] = -1.65+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _15PB30[i] = -1.75 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _15PB30[i] = -1.65 + 0.002 * (i - 45); } - //printf("15 %1.2f %1.2f\n",_15PB30[44],_15PB30[89]); + } + + //printf("15 %1.2f %1.2f\n",_15PB30[44],_15PB30[89]); _15PB40(maxInd2); _15PB40.clear(); - for (int i=0; i5) _15PB40[i] = -1.79 +0.002*(i-5); - else if (i<90 && i>=45) _15PB40[i] = -1.71+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _15PB40[i] = -1.79 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _15PB40[i] = -1.71 + 0.002 * (i - 45); } - //printf("15 %1.2f %1.2f\n",_15PB40[44],_15PB40[89]); + } + + //printf("15 %1.2f %1.2f\n",_15PB40[44],_15PB40[89]); _15PB50(maxInd2); _15PB50.clear(); - for (int i=0; i5) _15PB50[i] = -1.82 +0.002*(i-5); - else if (i<90 && i>=45) _15PB50[i] = -1.74+0.0011*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _15PB50[i] = -1.82 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _15PB50[i] = -1.74 + 0.0011 * (i - 45); } - //printf("15 %1.2f %1.2f\n",_15PB50[44],_15PB50[89]); + } + + //printf("15 %1.2f %1.2f\n",_15PB50[44],_15PB50[89]); _15PB60(maxInd2); _15PB60.clear(); - for (int i=0; i5) _15PB60[i] = -1.87 +0.0025*(i-5); - else if (i<90 && i>=45) _15PB60[i] = -1.77+0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _15PB60[i] = -1.87 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _15PB60[i] = -1.77 + 0.001 * (i - 45); } - //printf("15 %1.2f %1.2f\n",_15PB60[44],_15PB60[89]); + } + + //printf("15 %1.2f %1.2f\n",_15PB60[44],_15PB60[89]); _15PB70(maxInd3); _15PB70.clear(); - for (int i=0; i5) _15PB70[i] = -1.90 +0.0027*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _15PB70[i] = -1.90 + 0.0027 * (i - 5); } - // printf("15 %1.2f\n",_15PB70[49]); + } + + // printf("15 %1.2f\n",_15PB70[49]); _15PB80(maxInd3); _15PB80.clear(); - for (int i=0; i5) _15PB80[i] = -1.93 +0.0027*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _15PB80[i] = -1.93 + 0.0027 * (i - 5); } - //printf("15 %1.2f %1.2f\n",_15PB80[38], _15PB80[49]); + } + + //printf("15 %1.2f %1.2f\n",_15PB80[38], _15PB80[49]); //3PB _3PB10(maxInd2); _3PB10.clear(); - for (int i=0; i5) _3PB10[i] = -1.56 +0.005*(i-5); - else if (i<90 && i>=45) _3PB10[i] = -1.36+0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _3PB10[i] = -1.56 + 0.005 * (i - 5); + } else if (i < 90 && i >= 45) { + _3PB10[i] = -1.36 + 0.001 * (i - 45); } - //printf("30 %1.2f %1.2f\n",_3PB10[44],_3PB10[89]); + } + + //printf("30 %1.2f %1.2f\n",_3PB10[44],_3PB10[89]); _3PB20(maxInd2); _3PB20.clear(); - for (int i=0; i5) _3PB20[i] = -1.59 +0.00275*(i-5); - else if (i<90 && i>=45) _3PB20[i] = -1.48+0.003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _3PB20[i] = -1.59 + 0.00275 * (i - 5); + } else if (i < 90 && i >= 45) { + _3PB20[i] = -1.48 + 0.003 * (i - 45); } - //printf("30 %1.2f %1.2f\n",_3PB20[44],_3PB20[89]); + } + + //printf("30 %1.2f %1.2f\n",_3PB20[44],_3PB20[89]); _3PB30(maxInd2); _3PB30.clear(); - for (int i=0; i5) _3PB30[i] = -1.62 +0.00225*(i-5); - else if (i<90 && i>=45) _3PB30[i] = -1.53+0.0032*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _3PB30[i] = -1.62 + 0.00225 * (i - 5); + } else if (i < 90 && i >= 45) { + _3PB30[i] = -1.53 + 0.0032 * (i - 45); } - //printf("30 %1.2f %1.2f\n",_3PB30[44],_3PB30[89]); + } + + //printf("30 %1.2f %1.2f\n",_3PB30[44],_3PB30[89]); _3PB40(maxInd2); _3PB40.clear(); - for (int i=0; i5) _3PB40[i] = -1.64 +0.0015*(i-5); - else if (i<90 && i>=45) _3PB40[i] = -1.58+0.0025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _3PB40[i] = -1.64 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _3PB40[i] = -1.58 + 0.0025 * (i - 45); } - //printf("30 %1.2f %1.2f\n",_3PB40[44],_3PB40[89]); + } + + //printf("30 %1.2f %1.2f\n",_3PB40[44],_3PB40[89]); _3PB50(maxInd2); _3PB50.clear(); - for (int i=0; i5) _3PB50[i] = -1.69 +0.00175*(i-5); - else if (i<90 && i>=45) _3PB50[i] = -1.62+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _3PB50[i] = -1.69 + 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _3PB50[i] = -1.62 + 0.002 * (i - 45); } - //printf("30 %1.2f %1.2f\n",_3PB50[44],_3PB50[89]); + } + + //printf("30 %1.2f %1.2f\n",_3PB50[44],_3PB50[89]); _3PB60(maxInd2); _3PB60.clear(); - for (int i=0; i5) _3PB60[i] = -1.73 +0.002*(i-5); - else if (i<90 && i>=45) _3PB60[i] = -1.65+0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _3PB60[i] = -1.73 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _3PB60[i] = -1.65 + 0.0012 * (i - 45); } - //printf("30 %1.2f %1.2f\n",_3PB60[44],_3PB60[89]); + } + + //printf("30 %1.2f %1.2f\n",_3PB60[44],_3PB60[89]); _3PB70(maxInd3); _3PB70.clear(); - for (int i=0; i5) _3PB70[i] = -1.76 +0.002*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _3PB70[i] = -1.76 + 0.002 * (i - 5); } - //printf("30 %1.2f\n",_3PB70[49]); + } + + //printf("30 %1.2f\n",_3PB70[49]); _3PB80(maxInd3); _3PB80.clear(); - for (int i=0; i5) _3PB80[i] = -1.78 +0.0025*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _3PB80[i] = -1.78 + 0.0025 * (i - 5); } - //printf("30 %1.2f %1.2f\n",_3PB80[38], _3PB80[49]); + } + + //printf("30 %1.2f %1.2f\n",_3PB80[38], _3PB80[49]); //45PB _45PB10(maxInd2); _45PB10.clear(); - for (int i=0; i5) _45PB10[i] = -1.46 +0.0045*(i-5); - else if (i<90 && i>=45) _45PB10[i] = -1.28+0.0025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _45PB10[i] = -1.46 + 0.0045 * (i - 5); + } else if (i < 90 && i >= 45) { + _45PB10[i] = -1.28 + 0.0025 * (i - 45); } - //printf("45 %1.2f %1.2f\n",_45PB10[44],_45PB10[89]); + } + + //printf("45 %1.2f %1.2f\n",_45PB10[44],_45PB10[89]); _45PB20(maxInd2); _45PB20.clear(); - for (int i=0; i5) _45PB20[i] = -1.48 +0.00275*(i-5); - else if (i<90 && i>=45) _45PB20[i] = -1.37+0.0025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _45PB20[i] = -1.48 + 0.00275 * (i - 5); + } else if (i < 90 && i >= 45) { + _45PB20[i] = -1.37 + 0.0025 * (i - 45); } - //printf("45 %1.2f %1.2f\n",_45PB20[44],_45PB20[89]); + } + + //printf("45 %1.2f %1.2f\n",_45PB20[44],_45PB20[89]); _45PB30(maxInd2); _45PB30.clear(); - for (int i=0; i5) _45PB30[i] = -1.51 +0.00175*(i-5); - else if (i<90 && i>=45) _45PB30[i] = -1.44+0.0035*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _45PB30[i] = -1.51 + 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _45PB30[i] = -1.44 + 0.0035 * (i - 45); } - //printf("45 %1.2f %1.2f\n",_45PB30[44],_45PB30[89]); + } + + //printf("45 %1.2f %1.2f\n",_45PB30[44],_45PB30[89]); _45PB40(maxInd2); _45PB40.clear(); - for (int i=0; i5) _45PB40[i] = -1.52 +0.001*(i-5); - else if (i<90 && i>=45) _45PB40[i] = -1.48+0.003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _45PB40[i] = -1.52 + 0.001 * (i - 5); + } else if (i < 90 && i >= 45) { + _45PB40[i] = -1.48 + 0.003 * (i - 45); } - //printf("45 %1.2f %1.2f\n",_45PB40[44],_45PB40[89]); + } + + //printf("45 %1.2f %1.2f\n",_45PB40[44],_45PB40[89]); _45PB50(maxInd2); _45PB50.clear(); - for (int i=0; i5) _45PB50[i] = -1.55 +0.001*(i-5); - else if (i<90 && i>=45) _45PB50[i] = -1.51+0.0022*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _45PB50[i] = -1.55 + 0.001 * (i - 5); + } else if (i < 90 && i >= 45) { + _45PB50[i] = -1.51 + 0.0022 * (i - 45); } - //printf("45 %1.2f %1.2f\n",_45PB50[44],_45PB50[89]); + } + + //printf("45 %1.2f %1.2f\n",_45PB50[44],_45PB50[89]); _45PB60(maxInd2); _45PB60.clear(); - for (int i=0; i5) _45PB60[i] = -1.6 +0.0015*(i-5); - else if (i<90 && i>=45) _45PB60[i] = -1.54+0.001*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _45PB60[i] = -1.6 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _45PB60[i] = -1.54 + 0.001 * (i - 45); } - //printf("45 %1.2f %1.2f\n",_45PB60[44],_45PB60[89]); + } + + //printf("45 %1.2f %1.2f\n",_45PB60[44],_45PB60[89]); _45PB70(maxInd3); _45PB70.clear(); - for (int i=0; i5) _45PB70[i] = -1.63 +0.0017*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _45PB70[i] = -1.63 + 0.0017 * (i - 5); } - //printf("45 %1.2f\n",_45PB70[49]); + } + + //printf("45 %1.2f\n",_45PB70[49]); _45PB80(maxInd3); _45PB80.clear(); - for (int i=0; i5) _45PB80[i] = -1.67 +0.0025*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _45PB80[i] = -1.67 + 0.0025 * (i - 5); } - //printf("45 %1.2f %1.2f\n",_45PB80[38], _45PB80[49]); + } + + //printf("45 %1.2f %1.2f\n",_45PB80[38], _45PB80[49]); //_6PB _6PB10(maxInd); _6PB10.clear(); - for (int i=0; i140 - if (i<45 && i>5) _6PB10[i] = -1.33 +0.005*(i-5); - else if (i<85 && i>=45) _6PB10[i] = -1.13+0.0045*(i-45); - else if (i<140 && i >=85) _6PB10[i] = -0.95+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _6PB10[i] = -1.33 + 0.005 * (i - 5); + } else if (i < 85 && i >= 45) { + _6PB10[i] = -1.13 + 0.0045 * (i - 45); + } else if (i < 140 && i >= 85) { + _6PB10[i] = -0.95 + 0.0015 * (i - 85); } - //printf("60 %1.2f %1.2f %1.2f\n",_6PB10[44],_6PB10[84],_6PB10[139]); + } + + //printf("60 %1.2f %1.2f %1.2f\n",_6PB10[44],_6PB10[84],_6PB10[139]); _6PB20(maxInd); _6PB20.clear(); - for (int i=0; i140 - if (i<45 && i>5) _6PB20[i] = -1.36 +0.004*(i-5); - else if (i<85 && i>=45) _6PB20[i] = -1.20+0.00375*(i-45); - else if (i<140 && i >=85) _6PB20[i] = -1.05+0.0017*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _6PB20[i] = -1.36 + 0.004 * (i - 5); + } else if (i < 85 && i >= 45) { + _6PB20[i] = -1.20 + 0.00375 * (i - 45); + } else if (i < 140 && i >= 85) { + _6PB20[i] = -1.05 + 0.0017 * (i - 85); } - //printf("60 %1.2f %1.2f %1.2f\n",_6PB20[44],_6PB20[84],_6PB20[139]); + } + + //printf("60 %1.2f %1.2f %1.2f\n",_6PB20[44],_6PB20[84],_6PB20[139]); _6PB30(maxInd); _6PB30.clear(); - for (int i=0; i140 - if (i<45 && i>5) _6PB30[i] = -1.38 +0.00225*(i-5); - else if (i<85 && i>=45) _6PB30[i] = -1.29+0.00375*(i-45); - else if (i<140 && i >=85) _6PB30[i] = -1.14+0.002*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _6PB30[i] = -1.38 + 0.00225 * (i - 5); + } else if (i < 85 && i >= 45) { + _6PB30[i] = -1.29 + 0.00375 * (i - 45); + } else if (i < 140 && i >= 85) { + _6PB30[i] = -1.14 + 0.002 * (i - 85); } - //printf("60 %1.2f %1.2f %1.2f\n",_6PB30[44],_6PB30[84],_6PB30[139]); + } + + //printf("60 %1.2f %1.2f %1.2f\n",_6PB30[44],_6PB30[84],_6PB30[139]); _6PB40(maxInd); _6PB40.clear(); - for (int i=0; i140 - if (i<45 && i>5) _6PB40[i] = -1.39 +0.00125*(i-5); - else if (i<85 && i>=45) _6PB40[i] = -1.34+0.00275*(i-45); - else if (i<140 && i >=85) _6PB40[i] = -1.23+0.002*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _6PB40[i] = -1.39 + 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _6PB40[i] = -1.34 + 0.00275 * (i - 45); + } else if (i < 140 && i >= 85) { + _6PB40[i] = -1.23 + 0.002 * (i - 85); } - //printf("60 %1.2f %1.2f %1.2f\n",_6PB40[44],_6PB40[84],_6PB40[139]); + } + + //printf("60 %1.2f %1.2f %1.2f\n",_6PB40[44],_6PB40[84],_6PB40[139]); _6PB50(maxInd2);//limits -1.3 -1.11 _6PB50.clear(); - for (int i=0; i5) _6PB50[i] = -1.43 +0.00125*(i-5); - else if (i<90 && i>=45) _6PB50[i] = -1.38+0.00225*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _6PB50[i] = -1.43 + 0.00125 * (i - 5); + } else if (i < 90 && i >= 45) { + _6PB50[i] = -1.38 + 0.00225 * (i - 45); } - //printf("60 %1.2f %1.2f \n",_6PB50[44],_6PB50[89]); + } + + //printf("60 %1.2f %1.2f \n",_6PB50[44],_6PB50[89]); _6PB60(maxInd2);//limits -1.3 -1.11 _6PB60.clear(); - for (int i=0; i5) _6PB60[i] = -1.46 +0.0012*(i-5); - else if (i<90 && i>=45) _6PB60[i] = -1.40+0.000875*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _6PB60[i] = -1.46 + 0.0012 * (i - 5); + } else if (i < 90 && i >= 45) { + _6PB60[i] = -1.40 + 0.000875 * (i - 45); } - //printf("60 %1.2f %1.2f\n",_6PB60[44],_6PB60[89]); + } + + //printf("60 %1.2f %1.2f\n",_6PB60[44],_6PB60[89]); _6PB70(maxInd3); _6PB70.clear(); - for (int i=0; i5) _6PB70[i] = -1.49 +0.0018*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _6PB70[i] = -1.49 + 0.0018 * (i - 5); } - //printf("6 %1.2f\n",_6PB70[49]); + } + + //printf("6 %1.2f\n",_6PB70[49]); _6PB80(maxInd3); _6PB80.clear(); - for (int i=0; i5) _6PB80[i] = -1.52 +0.0022*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _6PB80[i] = -1.52 + 0.0022 * (i - 5); } - //printf("6 %1.2f %1.2f\n",_6PB80[38], _6PB80[49]); + } + + //printf("6 %1.2f %1.2f\n",_6PB80[38], _6PB80[49]); //_75PB : notation Munsell for maximum deviation blue purple _75PB10(maxInd);//limits hue -1.23 -0.71 _75PBx x=Luminance eg_75PB10 for L >5 and L<=15 _75PB10.clear(); - for (int i=0; i140 - if (i<45 && i>5) _75PB10[i] = -1.23 +0.0065*(i-5); - else if (i<85 && i>=45) _75PB10[i] = -0.97+0.00375*(i-45); - else if (i<140 && i >=85) _75PB10[i] = -0.82+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _75PB10[i] = -1.23 + 0.0065 * (i - 5); + } else if (i < 85 && i >= 45) { + _75PB10[i] = -0.97 + 0.00375 * (i - 45); + } else if (i < 140 && i >= 85) { + _75PB10[i] = -0.82 + 0.0015 * (i - 85); } - //printf("75 %1.2f %1.2f %1.2f\n",_75PB10[44],_75PB10[84],_75PB10[139]); + } + + //printf("75 %1.2f %1.2f %1.2f\n",_75PB10[44],_75PB10[84],_75PB10[139]); _75PB20(maxInd);//limits -1.24 -0.79 for L>15 <=25 _75PB20.clear(); - for (int i=0; i5) _75PB20[i] = -1.24 +0.004*(i-5); - else if (i<85 && i>=45) _75PB20[i] = -1.08+0.00425*(i-45); - else if (i<140 && i >=85) _75PB20[i] = -0.91+0.0017*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75PB20[i] = -1.24 + 0.004 * (i - 5); + } else if (i < 85 && i >= 45) { + _75PB20[i] = -1.08 + 0.00425 * (i - 45); + } else if (i < 140 && i >= 85) { + _75PB20[i] = -0.91 + 0.0017 * (i - 85); } - //printf("75 %1.2f %1.2f %1.2f\n",_75PB20[44],_75PB20[84],_75PB20[139]); + } + + //printf("75 %1.2f %1.2f %1.2f\n",_75PB20[44],_75PB20[84],_75PB20[139]); _75PB30(maxInd);//limits -1.25 -0.85 _75PB30.clear(); - for (int i=0; i5) _75PB30[i] = -1.25 +0.00275*(i-5); - else if (i<85 && i>=45) _75PB30[i] = -1.14+0.004*(i-45); - else if (i<140 && i >=85) _75PB30[i] = -0.98+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75PB30[i] = -1.25 + 0.00275 * (i - 5); + } else if (i < 85 && i >= 45) { + _75PB30[i] = -1.14 + 0.004 * (i - 45); + } else if (i < 140 && i >= 85) { + _75PB30[i] = -0.98 + 0.0015 * (i - 85); } - //printf("75 %1.2f %1.2f %1.2f\n",_75PB30[44],_75PB30[84],_75PB30[139]); + } + + //printf("75 %1.2f %1.2f %1.2f\n",_75PB30[44],_75PB30[84],_75PB30[139]); _75PB40(maxInd);//limits -1.27 -0.92 _75PB40.clear(); - for (int i=0; i5) _75PB40[i] = -1.27 +0.002*(i-5); - else if (i<85 && i>=45) _75PB40[i] = -1.19+0.003*(i-45); - else if (i<140 && i >=85) _75PB40[i] = -1.07+0.0022*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75PB40[i] = -1.27 + 0.002 * (i - 5); + } else if (i < 85 && i >= 45) { + _75PB40[i] = -1.19 + 0.003 * (i - 45); + } else if (i < 140 && i >= 85) { + _75PB40[i] = -1.07 + 0.0022 * (i - 85); } - //printf("75 %1.2f %1.2f %1.2f\n",_75PB40[44],_75PB40[84],_75PB40[139]); + } + + //printf("75 %1.2f %1.2f %1.2f\n",_75PB40[44],_75PB40[84],_75PB40[139]); _75PB50(maxInd2);//limits -1.3 -1.11 _75PB50.clear(); - for (int i=0; i5) _75PB50[i] = -1.3 +0.00175*(i-5); - else if (i<90 && i>=45) _75PB50[i] = -1.23+0.0025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _75PB50[i] = -1.3 + 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _75PB50[i] = -1.23 + 0.0025 * (i - 45); } - //printf("75 %1.2f %1.2f\n",_75PB50[44],_75PB50[89]); + } + + //printf("75 %1.2f %1.2f\n",_75PB50[44],_75PB50[89]); _75PB60(maxInd2); _75PB60.clear(); - for (int i=0; i5) _75PB60[i] = -1.32 +0.0015*(i-5); - else if (i<90 && i>=45) _75PB60[i] = -1.26+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { //limits -1.32 -1.17 + if (i < 45 && i > 5) { + _75PB60[i] = -1.32 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _75PB60[i] = -1.26 + 0.002 * (i - 45); } - //printf("75 %1.2f %1.2f \n",_75PB60[44],_75PB60[89]); + } + + //printf("75 %1.2f %1.2f \n",_75PB60[44],_75PB60[89]); _75PB70(maxInd3); _75PB70.clear(); - for (int i=0; i5) _75PB70[i] = -1.34 +0.002*(i-5); + + for (int i = 0; i < maxInd3; i++) { //limits -1.34 -1.27 + if (i < 50 && i > 5) { + _75PB70[i] = -1.34 + 0.002 * (i - 5); } + } + _75PB80(maxInd3); _75PB80.clear(); - for (int i=0; i5) _75PB80[i] = -1.35 +0.00125*(i-5); + + for (int i = 0; i < maxInd3; i++) { //limits -1.35 -1.29 + if (i < 50 && i > 5) { + _75PB80[i] = -1.35 + 0.00125 * (i - 5); } + } _9PB10(maxInd); _9PB10.clear(); - for (int i=0; i140 - if (i<45 && i>5) _9PB10[i] = -1.09 +0.00475*(i-5); - else if (i<85 && i>=45) _9PB10[i] = -0.9+0.003*(i-45); - else if (i<140 && i >=85) _9PB10[i] = -0.78+0.0013*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _9PB10[i] = -1.09 + 0.00475 * (i - 5); + } else if (i < 85 && i >= 45) { + _9PB10[i] = -0.9 + 0.003 * (i - 45); + } else if (i < 140 && i >= 85) { + _9PB10[i] = -0.78 + 0.0013 * (i - 85); } - //printf("90 %1.2f %1.2f %1.2f\n",_9PB10[44],_9PB10[84],_9PB10[139]); + } + + //printf("90 %1.2f %1.2f %1.2f\n",_9PB10[44],_9PB10[84],_9PB10[139]); _9PB20(maxInd); _9PB20.clear(); - for (int i=0; i140 - if (i<45 && i>5) _9PB20[i] = -1.12 +0.0035*(i-5); - else if (i<85 && i>=45) _9PB20[i] = -0.98+0.00325*(i-45); - else if (i<140 && i >=85) _9PB20[i] = -0.85+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _9PB20[i] = -1.12 + 0.0035 * (i - 5); + } else if (i < 85 && i >= 45) { + _9PB20[i] = -0.98 + 0.00325 * (i - 45); + } else if (i < 140 && i >= 85) { + _9PB20[i] = -0.85 + 0.0015 * (i - 85); } - //printf("90 %1.2f %1.2f %1.2f\n",_9PB20[44],_9PB20[84],_9PB20[139]); + } + + //printf("90 %1.2f %1.2f %1.2f\n",_9PB20[44],_9PB20[84],_9PB20[139]); _9PB30(maxInd); _9PB30.clear(); - for (int i=0; i140 - if (i<45 && i>5) _9PB30[i] = -1.14 +0.0028*(i-5); - else if (i<85 && i>=45) _9PB30[i] = -1.03+0.003*(i-45); - else if (i<140 && i >=85) _9PB30[i] = -0.91+0.0017*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _9PB30[i] = -1.14 + 0.0028 * (i - 5); + } else if (i < 85 && i >= 45) { + _9PB30[i] = -1.03 + 0.003 * (i - 45); + } else if (i < 140 && i >= 85) { + _9PB30[i] = -0.91 + 0.0017 * (i - 85); } - //printf("90 %1.2f %1.2f %1.2f\n",_9PB30[44],_9PB30[84],_9PB30[139]); + } + + //printf("90 %1.2f %1.2f %1.2f\n",_9PB30[44],_9PB30[84],_9PB30[139]); _9PB40(maxInd); _9PB40.clear(); - for (int i=0; i140 - if (i<45 && i>5) _9PB40[i] = -1.16 +0.002*(i-5); - else if (i<85 && i>=45) _9PB40[i] = -1.08+0.00275*(i-45); - else if (i<140 && i >=85) _9PB40[i] = -0.97+0.0016*(i-85); + + for (int i = 0; i < maxInd; i++) { //i = chromaticity 0==>140 + if (i < 45 && i > 5) { + _9PB40[i] = -1.16 + 0.002 * (i - 5); + } else if (i < 85 && i >= 45) { + _9PB40[i] = -1.08 + 0.00275 * (i - 45); + } else if (i < 140 && i >= 85) { + _9PB40[i] = -0.97 + 0.0016 * (i - 85); } - //printf("90 %1.2f %1.2f %1.2f\n",_9PB40[44],_9PB40[84],_9PB40[139]); + } + + //printf("90 %1.2f %1.2f %1.2f\n",_9PB40[44],_9PB40[84],_9PB40[139]); _9PB50(maxInd2); _9PB50.clear(); - for (int i=0; i5) _9PB50[i] = -1.19 +0.00175*(i-5); - else if (i<90 && i>=45) _9PB50[i] = -1.12+0.00225*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9PB50[i] = -1.19 + 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _9PB50[i] = -1.12 + 0.00225 * (i - 45); } - //printf("90 %1.2f %1.2f \n",_9PB50[44],_9PB50[84]); + } + + //printf("90 %1.2f %1.2f \n",_9PB50[44],_9PB50[84]); _9PB60(maxInd2); _9PB60.clear(); - for (int i=0; i5) _9PB60[i] = -1.21 +0.0015*(i-5); - else if (i<90 && i>=45) _9PB60[i] = -1.15+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9PB60[i] = -1.21 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _9PB60[i] = -1.15 + 0.002 * (i - 45); } - //printf("90 %1.2f %1.2f \n",_9PB60[44],_9PB60[89]); + } + + //printf("90 %1.2f %1.2f \n",_9PB60[44],_9PB60[89]); _9PB70(maxInd3); _9PB70.clear(); - for (int i=0; i5) _9PB70[i] = -1.23 +0.0018*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _9PB70[i] = -1.23 + 0.0018 * (i - 5); } - //printf("9 %1.2f\n",_9PB70[49]); + } + + //printf("9 %1.2f\n",_9PB70[49]); _9PB80(maxInd3); _9PB80.clear(); - for (int i=0; i5) _9PB80[i] = -1.24 +0.002*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _9PB80[i] = -1.24 + 0.002 * (i - 5); } - //printf("9 %1.2f %1.2f\n",_9PB80[38], _9PB80[49]); + } + + //printf("9 %1.2f %1.2f\n",_9PB80[38], _9PB80[49]); //10PB _10PB10(maxInd); _10PB10.clear(); - for (int i=0; i5) _10PB10[i] = -1.02 +0.00425*(i-5); - else if (i<85 && i>=45) _10PB10[i] = -0.85+0.0025*(i-45); - else if (i<140 && i >=85) _10PB10[i] = -0.75+0.0012*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10PB10[i] = -1.02 + 0.00425 * (i - 5); + } else if (i < 85 && i >= 45) { + _10PB10[i] = -0.85 + 0.0025 * (i - 45); + } else if (i < 140 && i >= 85) { + _10PB10[i] = -0.75 + 0.0012 * (i - 85); } - //printf("10 %1.2f %1.2f %1.2f\n",_10PB10[44],_10PB10[84],_10PB10[139]); + } + + //printf("10 %1.2f %1.2f %1.2f\n",_10PB10[44],_10PB10[84],_10PB10[139]); _10PB20(maxInd); _10PB20.clear(); - for (int i=0; i5) _10PB20[i] = -1.05 +0.00325*(i-5); - else if (i<85 && i>=45) _10PB20[i] = -0.92+0.00275*(i-45); - else if (i<140 && i >=85) _10PB20[i] = -0.81+0.0014*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10PB20[i] = -1.05 + 0.00325 * (i - 5); + } else if (i < 85 && i >= 45) { + _10PB20[i] = -0.92 + 0.00275 * (i - 45); + } else if (i < 140 && i >= 85) { + _10PB20[i] = -0.81 + 0.0014 * (i - 85); } - //printf("10 %1.2f %1.2f %1.2f\n",_10PB20[44],_10PB20[84],_10PB20[139]); + } + + //printf("10 %1.2f %1.2f %1.2f\n",_10PB20[44],_10PB20[84],_10PB20[139]); _10PB30(maxInd); _10PB30.clear(); - for (int i=0; i5) _10PB30[i] = -1.07 +0.00275*(i-5); - else if (i<85 && i>=45) _10PB30[i] = -0.96+0.0025*(i-45); - else if (i<140 && i >=85) _10PB30[i] = -0.86+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10PB30[i] = -1.07 + 0.00275 * (i - 5); + } else if (i < 85 && i >= 45) { + _10PB30[i] = -0.96 + 0.0025 * (i - 45); + } else if (i < 140 && i >= 85) { + _10PB30[i] = -0.86 + 0.0015 * (i - 85); } - //printf("10 %1.2f %1.2f %1.2f\n",_10PB30[44],_10PB30[84],_10PB30[139]); + } + + //printf("10 %1.2f %1.2f %1.2f\n",_10PB30[44],_10PB30[84],_10PB30[139]); _10PB40(maxInd); _10PB40.clear(); - for (int i=0; i5) _10PB40[i] = -1.09 +0.002*(i-5); - else if (i<85 && i>=45) _10PB40[i] = -1.01+0.00225*(i-45); - else if (i<140 && i >=85) _10PB40[i] = -0.92+0.0016*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10PB40[i] = -1.09 + 0.002 * (i - 5); + } else if (i < 85 && i >= 45) { + _10PB40[i] = -1.01 + 0.00225 * (i - 45); + } else if (i < 140 && i >= 85) { + _10PB40[i] = -0.92 + 0.0016 * (i - 85); } - //printf("10 %1.2f %1.2f %1.2f\n",_10PB40[44],_10PB40[84],_10PB40[139]); + } + + //printf("10 %1.2f %1.2f %1.2f\n",_10PB40[44],_10PB40[84],_10PB40[139]); _10PB50(maxInd2); _10PB50.clear(); - for (int i=0; i5) _10PB50[i] = -1.12 +0.00175*(i-5); - else if (i<90 && i>=45) _10PB50[i] = -1.05+0.00225*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10PB50[i] = -1.12 + 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _10PB50[i] = -1.05 + 0.00225 * (i - 45); } - //printf("10 %1.2f %1.2f\n",_10PB50[44],_10PB50[84]); + } + + //printf("10 %1.2f %1.2f\n",_10PB50[44],_10PB50[84]); _10PB60(maxInd2); _10PB60.clear(); - for (int i=0; i5) _10PB60[i] = -1.14 +0.0015*(i-5); - else if (i<90 && i>=45) _10PB60[i] = -1.08+0.00225*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10PB60[i] = -1.14 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _10PB60[i] = -1.08 + 0.00225 * (i - 45); } - //printf("10 %1.2f %1.2f\n",_10PB60[44],_10PB60[89]); + } + + //printf("10 %1.2f %1.2f\n",_10PB60[44],_10PB60[89]); //1P _1P10(maxInd); _1P10.clear(); - for (int i=0; i5) _1P10[i] = -0.96 +0.00375*(i-5); - else if (i<85 && i>=45) _1P10[i] = -0.81+0.00225*(i-45); - else if (i<140 && i >=85) _1P10[i] = -0.72+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1P10[i] = -0.96 + 0.00375 * (i - 5); + } else if (i < 85 && i >= 45) { + _1P10[i] = -0.81 + 0.00225 * (i - 45); + } else if (i < 140 && i >= 85) { + _1P10[i] = -0.72 + 0.001 * (i - 85); } - //printf("1P %1.2f %1.2f %1.2f\n",_1P10[44],_1P10[84],_1P10[139]); + } + + //printf("1P %1.2f %1.2f %1.2f\n",_1P10[44],_1P10[84],_1P10[139]); _1P20(maxInd); _1P20.clear(); - for (int i=0; i5) _1P20[i] = -1.0 +0.00325*(i-5); - else if (i<85 && i>=45) _1P20[i] = -0.87+0.0025*(i-45); - else if (i<140 && i >=85) _1P20[i] = -0.77+0.0012*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1P20[i] = -1.0 + 0.00325 * (i - 5); + } else if (i < 85 && i >= 45) { + _1P20[i] = -0.87 + 0.0025 * (i - 45); + } else if (i < 140 && i >= 85) { + _1P20[i] = -0.77 + 0.0012 * (i - 85); } - //printf("1P %1.2f %1.2f %1.2f\n",_1P20[44],_1P20[84],_1P20[139]); + } + + //printf("1P %1.2f %1.2f %1.2f\n",_1P20[44],_1P20[84],_1P20[139]); _1P30(maxInd); _1P30.clear(); - for (int i=0; i5) _1P30[i] = -1.02 +0.00275*(i-5); - else if (i<85 && i>=45) _1P30[i] = -0.91+0.00225*(i-45); - else if (i<140 && i >=85) _1P30[i] = -0.82+0.0011*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1P30[i] = -1.02 + 0.00275 * (i - 5); + } else if (i < 85 && i >= 45) { + _1P30[i] = -0.91 + 0.00225 * (i - 45); + } else if (i < 140 && i >= 85) { + _1P30[i] = -0.82 + 0.0011 * (i - 85); } - //printf("1P %1.2f %1.2f %1.2f\n",_1P30[44],_1P30[84],_1P30[139]); + } + + //printf("1P %1.2f %1.2f %1.2f\n",_1P30[44],_1P30[84],_1P30[139]); _1P40(maxInd); _1P40.clear(); - for (int i=0; i5) _1P40[i] = -1.04 +0.00225*(i-5); - else if (i<85 && i>=45) _1P40[i] = -0.95+0.00225*(i-45); - else if (i<140 && i >=85) _1P40[i] = -0.86+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1P40[i] = -1.04 + 0.00225 * (i - 5); + } else if (i < 85 && i >= 45) { + _1P40[i] = -0.95 + 0.00225 * (i - 45); + } else if (i < 140 && i >= 85) { + _1P40[i] = -0.86 + 0.0015 * (i - 85); } - //printf("1P %1.2f %1.2f %1.2f\n",_1P40[44],_1P40[84],_1P40[139]); + } + + //printf("1P %1.2f %1.2f %1.2f\n",_1P40[44],_1P40[84],_1P40[139]); _1P50(maxInd2); _1P50.clear(); - for (int i=0; i5) _1P50[i] = -1.06 +0.002*(i-5); - else if (i<90 && i>=45) _1P50[i] = -0.98+0.00175*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _1P50[i] = -1.06 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _1P50[i] = -0.98 + 0.00175 * (i - 45); } - //printf("1P %1.2f %1.2f \n",_1P50[44],_1P50[89]); + } + + //printf("1P %1.2f %1.2f \n",_1P50[44],_1P50[89]); _1P60(maxInd2); _1P60.clear(); - for (int i=0; i5) _1P60[i] = -1.07 +0.0015*(i-5); - else if (i<90 && i>=45) _1P60[i] = -1.01+0.00175*(i-45); - } - //printf("1P %1.2f %1.2f \n",_1P60[44],_1P60[84],_1P60[139]); - //4P + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _1P60[i] = -1.07 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _1P60[i] = -1.01 + 0.00175 * (i - 45); + } + } + + //printf("1P %1.2f %1.2f \n",_1P60[44],_1P60[84],_1P60[139]); + + //4P _4P10(maxInd); _4P10.clear(); - for (int i=0; i5) _4P10[i] = -0.78 +0.002*(i-5); - else if (i<85 && i>=45) _4P10[i] = -0.7+0.00125*(i-45); - else if (i<140 && i >=85) _4P10[i] = -0.65+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _4P10[i] = -0.78 + 0.002 * (i - 5); + } else if (i < 85 && i >= 45) { + _4P10[i] = -0.7 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _4P10[i] = -0.65 + 0.001 * (i - 85); } - //printf("4P %1.2f %1.2f %1.2f\n",_4P10[44],_4P10[84],_4P10[139]); + } + + //printf("4P %1.2f %1.2f %1.2f\n",_4P10[44],_4P10[84],_4P10[139]); _4P20(maxInd); _4P20.clear(); - for (int i=0; i5) _4P20[i] = -0.84 +0.0025*(i-5); - else if (i<85 && i>=45) _4P20[i] = -0.74+0.00175*(i-45); - else if (i<140 && i >=85) _4P20[i] = -0.67+0.00085*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _4P20[i] = -0.84 + 0.0025 * (i - 5); + } else if (i < 85 && i >= 45) { + _4P20[i] = -0.74 + 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _4P20[i] = -0.67 + 0.00085 * (i - 85); } - //printf("4P %1.2f %1.2f %1.2f\n",_4P20[44],_4P20[84],_4P20[139]); + } + + //printf("4P %1.2f %1.2f %1.2f\n",_4P20[44],_4P20[84],_4P20[139]); _4P30(maxInd); _4P30.clear(); - for (int i=0; i5) _4P30[i] = -0.85 +0.00225*(i-5); - else if (i<85 && i>=45) _4P30[i] = -0.76+0.00125*(i-45); - else if (i<140 && i >=85) _4P30[i] = -0.71+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _4P30[i] = -0.85 + 0.00225 * (i - 5); + } else if (i < 85 && i >= 45) { + _4P30[i] = -0.76 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _4P30[i] = -0.71 + 0.001 * (i - 85); } - //printf("4P %1.2f %1.2f %1.2f\n",_4P30[44],_4P30[84],_4P30[139]); + } + + //printf("4P %1.2f %1.2f %1.2f\n",_4P30[44],_4P30[84],_4P30[139]); _4P40(maxInd); _4P40.clear(); - for (int i=0; i5) _4P40[i] = -0.87 +0.00175*(i-5); - else if (i<85 && i>=45) _4P40[i] = -0.8+0.00175*(i-45); - else if (i<140 && i >=85) _4P40[i] = -0.73+0.00075*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _4P40[i] = -0.87 + 0.00175 * (i - 5); + } else if (i < 85 && i >= 45) { + _4P40[i] = -0.8 + 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _4P40[i] = -0.73 + 0.00075 * (i - 85); } - //printf("4P %1.2f %1.2f %1.2f\n",_4P40[44],_4P40[84],_4P40[139]); + } + + //printf("4P %1.2f %1.2f %1.2f\n",_4P40[44],_4P40[84],_4P40[139]); _4P50(maxInd2); _4P50.clear(); - for (int i=0; i5) _4P50[i] = -0.88 +0.0015*(i-5); - else if (i<90 && i>=45) _4P50[i] = -0.82+0.0015*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _4P50[i] = -0.88 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _4P50[i] = -0.82 + 0.0015 * (i - 45); } - //printf("4P %1.2f %1.2f \n",_4P50[44],_4P50[89]); + } + + //printf("4P %1.2f %1.2f \n",_4P50[44],_4P50[89]); _4P60(maxInd2); _4P60.clear(); - for (int i=0; i5) _4P60[i] = -0.89 +0.00125*(i-5); - else if (i<90 && i>=45) _4P60[i] = -0.84+0.00125*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _4P60[i] = -0.89 + 0.00125 * (i - 5); + } else if (i < 90 && i >= 45) { + _4P60[i] = -0.84 + 0.00125 * (i - 45); } - //printf("4P %1.2f %1.2f\n",_4P60[44],_4P60[89]); + } + + //printf("4P %1.2f %1.2f\n",_4P60[44],_4P60[89]); //red yellow correction _10YR20(maxInd2); _10YR20.clear(); - for (int i=0; i5) _10YR20[i] = 1.22 +0.002*(i-5); - else if (i<90 && i>=45) _10YR20[i] = 1.30+0.006*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10YR20[i] = 1.22 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _10YR20[i] = 1.30 + 0.006 * (i - 45); } - //printf("10YR %1.2f %1.2f\n",_10YR20[44],_10YR20[56]); + } + + //printf("10YR %1.2f %1.2f\n",_10YR20[44],_10YR20[56]); _10YR30(maxInd2); _10YR30.clear(); - for (int i=0; i5) _10YR30[i] = 1.27 +0.00175*(i-5); - else if (i<90 && i>=45) _10YR30[i] = 1.34+0.0017*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10YR30[i] = 1.27 + 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _10YR30[i] = 1.34 + 0.0017 * (i - 45); } - //printf("10YR %1.2f %1.2f\n",_10YR30[44],_10YR30[75]); + } + + //printf("10YR %1.2f %1.2f\n",_10YR30[44],_10YR30[75]); _10YR40(maxInd2); _10YR40.clear(); - for (int i=0; i5) _10YR40[i] = 1.32 +0.00025*(i-5); - else if (i<90 && i>=45) _10YR40[i] = 1.33+0.0015*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10YR40[i] = 1.32 + 0.00025 * (i - 5); + } else if (i < 90 && i >= 45) { + _10YR40[i] = 1.33 + 0.0015 * (i - 45); } - //printf("10YR %1.2f %1.2f\n",_10YR40[44],_10YR40[85]); + } + + //printf("10YR %1.2f %1.2f\n",_10YR40[44],_10YR40[85]); _10YR50(maxInd2); _10YR50.clear(); - for (int i=0; i5) _10YR50[i] = 1.35 +0.000*(i-5); - else if (i<90 && i>=45) _10YR50[i] = 1.35+0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10YR50[i] = 1.35 + 0.000 * (i - 5); + } else if (i < 90 && i >= 45) { + _10YR50[i] = 1.35 + 0.0012 * (i - 45); } - //printf("10YR %1.2f %1.2f\n",_10YR50[44],_10YR50[80]); + } + + //printf("10YR %1.2f %1.2f\n",_10YR50[44],_10YR50[80]); _10YR60(maxInd); _10YR60.clear(); - for (int i=0; i5) _10YR60[i] = 1.38 - 0.00025*(i-5); - else if (i<85 && i>=45) _10YR60[i] = 1.37+0.0005*(i-45); - else if (i<140 && i >=85) _10YR60[i] = 1.39+0.0013*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10YR60[i] = 1.38 - 0.00025 * (i - 5); + } else if (i < 85 && i >= 45) { + _10YR60[i] = 1.37 + 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _10YR60[i] = 1.39 + 0.0013 * (i - 85); } - //printf("10YR %1.2f %1.2f %1.2f\n",_10YR60[44],_10YR60[85],_10YR60[139] ); + } + + //printf("10YR %1.2f %1.2f %1.2f\n",_10YR60[44],_10YR60[85],_10YR60[139] ); _10YR70(maxInd); _10YR70.clear(); - for (int i=0; i5) _10YR70[i] = 1.41 - 0.0005*(i-5); - else if (i<85 && i>=45) _10YR70[i] = 1.39+0.000*(i-45); - else if (i<140 && i >=85) _10YR70[i] = 1.39+0.0013*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10YR70[i] = 1.41 - 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _10YR70[i] = 1.39 + 0.000 * (i - 45); + } else if (i < 140 && i >= 85) { + _10YR70[i] = 1.39 + 0.0013 * (i - 85); } - //printf("10YR %1.2f %1.2f %1.2f\n",_10YR70[44],_10YR70[85],_10YR70[139] ); + } + + //printf("10YR %1.2f %1.2f %1.2f\n",_10YR70[44],_10YR70[85],_10YR70[139] ); _10YR80(maxInd); _10YR80.clear(); - for (int i=0; i5) _10YR80[i] = 1.45 - 0.00125*(i-5); - else if (i<85 && i>=45) _10YR80[i] = 1.40+0.000*(i-45); - else if (i<140 && i >=85) _10YR80[i] = 1.40+0.00072*(i-85);//1.436 + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10YR80[i] = 1.45 - 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _10YR80[i] = 1.40 + 0.000 * (i - 45); + } else if (i < 140 && i >= 85) { + _10YR80[i] = 1.40 + 0.00072 * (i - 85); //1.436 } - //printf("10YR %1.2f %1.2f %1.2f\n",_10YR80[44],_10YR80[84],_10YR80[139] ); + } + + //printf("10YR %1.2f %1.2f %1.2f\n",_10YR80[44],_10YR80[84],_10YR80[139] ); _10YR90(maxInd2); _10YR90.clear(); - for (int i=0; i5) _10YR90[i] = 1.48 -0.001*(i-5); - else if (i<90 && i>=45) _10YR90[i] = 1.44-0.0009*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10YR90[i] = 1.48 - 0.001 * (i - 5); + } else if (i < 90 && i >= 45) { + _10YR90[i] = 1.44 - 0.0009 * (i - 45); } - //printf("10YR %1.2f %1.2f\n",_10YR90[45],_10YR90[80]); + } + + //printf("10YR %1.2f %1.2f\n",_10YR90[45],_10YR90[80]); _85YR20(maxInd3); _85YR20.clear(); - for (int i=0; i5) _85YR20[i] = 1.12 +0.004*(i-5); - } - //printf("85YR %1.2f \n",_85YR20[44]); + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _85YR20[i] = 1.12 + 0.004 * (i - 5); + } + } + + //printf("85YR %1.2f \n",_85YR20[44]); _85YR30(maxInd2); _85YR30.clear(); - for (int i=0; i5) _85YR30[i] = 1.16 + 0.0025*(i-5); - else if (i<90 && i>=45) _85YR30[i] = 1.26+0.0028*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _85YR30[i] = 1.16 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _85YR30[i] = 1.26 + 0.0028 * (i - 45); } - //printf("85YR %1.2f %1.2f\n",_85YR30[44],_85YR30[75]); + } + + //printf("85YR %1.2f %1.2f\n",_85YR30[44],_85YR30[75]); _85YR40(maxInd2); _85YR40.clear(); - for (int i=0; i5) _85YR40[i] = 1.20 + 0.0015*(i-5); - else if (i<90 && i>=45) _85YR40[i] = 1.26+0.0024*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _85YR40[i] = 1.20 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _85YR40[i] = 1.26 + 0.0024 * (i - 45); } - //printf("85YR %1.2f %1.2f\n",_85YR40[44],_85YR40[75]); + } + + //printf("85YR %1.2f %1.2f\n",_85YR40[44],_85YR40[75]); _85YR50(maxInd); _85YR50.clear(); - for (int i=0; i5) _85YR50[i] = 1.24 + 0.0005*(i-5); - else if (i<85 && i>=45) _85YR50[i] = 1.26+0.002*(i-45); - else if (i<140 && i >=85) _85YR50[i] = 1.34+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _85YR50[i] = 1.24 + 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _85YR50[i] = 1.26 + 0.002 * (i - 45); + } else if (i < 140 && i >= 85) { + _85YR50[i] = 1.34 + 0.0015 * (i - 85); } - //printf("85YR %1.2f %1.2f %1.2f\n",_85YR50[44],_85YR50[85],_85YR50[110] ); + } + + //printf("85YR %1.2f %1.2f %1.2f\n",_85YR50[44],_85YR50[85],_85YR50[110] ); _85YR60(maxInd); _85YR60.clear(); - for (int i=0; i5) _85YR60[i] = 1.27 + 0.00025*(i-5); - else if (i<85 && i>=45) _85YR60[i] = 1.28+0.0015*(i-45); - else if (i<140 && i >=85) _85YR60[i] = 1.34+0.0012*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _85YR60[i] = 1.27 + 0.00025 * (i - 5); + } else if (i < 85 && i >= 45) { + _85YR60[i] = 1.28 + 0.0015 * (i - 45); + } else if (i < 140 && i >= 85) { + _85YR60[i] = 1.34 + 0.0012 * (i - 85); } - //printf("85YR %1.2f %1.2f %1.2f\n",_85YR60[44],_85YR60[85],_85YR60[139] ); + } + + //printf("85YR %1.2f %1.2f %1.2f\n",_85YR60[44],_85YR60[85],_85YR60[139] ); _85YR70(maxInd); _85YR70.clear(); - for (int i=0; i5) _85YR70[i] = 1.31 - 0.00025*(i-5); - else if (i<85 && i>=45) _85YR70[i] = 1.30+0.0005*(i-45); - else if (i<140 && i >=85) _85YR70[i] = 1.32+0.0012*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _85YR70[i] = 1.31 - 0.00025 * (i - 5); + } else if (i < 85 && i >= 45) { + _85YR70[i] = 1.30 + 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _85YR70[i] = 1.32 + 0.0012 * (i - 85); } - //printf("85YR %1.2f %1.2f %1.2f\n",_85YR70[44],_85YR70[85],_85YR70[139] ); + } + + //printf("85YR %1.2f %1.2f %1.2f\n",_85YR70[44],_85YR70[85],_85YR70[139] ); _85YR80(maxInd); _85YR80.clear(); - for (int i=0; i5) _85YR80[i] = 1.35 - 0.00075*(i-5); - else if (i<85 && i>=45) _85YR80[i] = 1.32+0.00025*(i-45); - else if (i<140 && i >=85) _85YR80[i] = 1.33+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _85YR80[i] = 1.35 - 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _85YR80[i] = 1.32 + 0.00025 * (i - 45); + } else if (i < 140 && i >= 85) { + _85YR80[i] = 1.33 + 0.00125 * (i - 85); } - //printf("85YR %1.2f %1.2f %1.2f\n",_85YR80[44],_85YR80[85],_85YR80[139] ); + } + + //printf("85YR %1.2f %1.2f %1.2f\n",_85YR80[44],_85YR80[85],_85YR80[139] ); _85YR90(maxInd2); _85YR90.clear(); - for (int i=0; i5) _85YR90[i] = 1.39 - 0.00125*(i-5); - else if (i<90 && i>=45) _85YR90[i] = 1.34+0.00*(i-45); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _85YR90[i] = 1.39 - 0.00125 * (i - 5); + } else if (i < 90 && i >= 45) { + _85YR90[i] = 1.34 + 0.00 * (i - 45); } - //printf("85YR %1.2f %1.2f\n",_85YR90[44],_85YR90[85]); + } + + //printf("85YR %1.2f %1.2f\n",_85YR90[44],_85YR90[85]); //7YR _7YR30(maxInd2); _7YR30.clear(); - for (int i=0; i5) _7YR30[i] = 1.06 + 0.0028*(i-5); - else if (i<90 && i>=45) _7YR30[i] = 1.17+0.0045*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7YR30[i] = 1.06 + 0.0028 * (i - 5); + } else if (i < 90 && i >= 45) { + _7YR30[i] = 1.17 + 0.0045 * (i - 45); } - //printf("7YR %1.2f %1.2f\n",_7YR30[44],_7YR30[66]); + } + + //printf("7YR %1.2f %1.2f\n",_7YR30[44],_7YR30[66]); _7YR40(maxInd2); _7YR40.clear(); - for (int i=0; i5) _7YR40[i] = 1.10 + 0.0018*(i-5); - else if (i<90 && i>=45) _7YR40[i] = 1.17+0.0035*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7YR40[i] = 1.10 + 0.0018 * (i - 5); + } else if (i < 90 && i >= 45) { + _7YR40[i] = 1.17 + 0.0035 * (i - 45); } - //printf("7YR %1.2f %1.2f\n",_7YR40[44],_7YR40[89]); + } + + //printf("7YR %1.2f %1.2f\n",_7YR40[44],_7YR40[89]); _7YR50(maxInd2); _7YR50.clear(); - for (int i=0; i5) _7YR50[i] = 1.14 + 0.00125*(i-5); - else if (i<90 && i>=45) _7YR50[i] = 1.19+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7YR50[i] = 1.14 + 0.00125 * (i - 5); + } else if (i < 90 && i >= 45) { + _7YR50[i] = 1.19 + 0.002 * (i - 45); } - //printf("7YR %1.2f %1.2f\n",_7YR50[44],_7YR50[89] ); + } + + //printf("7YR %1.2f %1.2f\n",_7YR50[44],_7YR50[89] ); _7YR60(maxInd); _7YR60.clear(); - for (int i=0; i5) _7YR60[i] = 1.17 + 0.00075*(i-5); - else if (i<85 && i>=45) _7YR60[i] = 1.20+0.00175*(i-45); - else if (i<140 && i >=85) _7YR60[i] = 1.27+0.002*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7YR60[i] = 1.17 + 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _7YR60[i] = 1.20 + 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _7YR60[i] = 1.27 + 0.002 * (i - 85); } - //printf("7YR %1.2f %1.2f %1.2f\n",_7YR60[44],_7YR60[84],_7YR60[125] ); + } + + //printf("7YR %1.2f %1.2f %1.2f\n",_7YR60[44],_7YR60[84],_7YR60[125] ); _7YR70(maxInd); _7YR70.clear(); - for (int i=0; i5) _7YR70[i] = 1.20 + 0.0005*(i-5); - else if (i<85 && i>=45) _7YR70[i] = 1.22+0.00125*(i-45); - else if (i<140 && i >=85) _7YR70[i] = 1.27+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7YR70[i] = 1.20 + 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _7YR70[i] = 1.22 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _7YR70[i] = 1.27 + 0.0015 * (i - 85); } - //printf("7YR %1.2f %1.2f %1.2f\n",_7YR70[44],_7YR70[84],_7YR70[125] ); + } + + //printf("7YR %1.2f %1.2f %1.2f\n",_7YR70[44],_7YR70[84],_7YR70[125] ); _7YR80(maxInd3); _7YR80.clear(); - for (int i=0; i5) _7YR80[i] = 1.29 - 0.0008*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _7YR80[i] = 1.29 - 0.0008 * (i - 5); } - //printf("7YR %1.2f \n",_7YR80[44] ); + } + + //printf("7YR %1.2f \n",_7YR80[44] ); _55YR30(maxInd3); _55YR30.clear(); - for (int i=0; i5) _55YR30[i] = 0.96 + 0.0038*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _55YR30[i] = 0.96 + 0.0038 * (i - 5); } - //printf("55YR %1.2f \n",_55YR30[44] ); + } + + //printf("55YR %1.2f \n",_55YR30[44] ); _55YR40(maxInd2); _55YR40.clear(); - for (int i=0; i5) _55YR40[i] = 1.01 + 0.0022*(i-5); - else if (i<90 && i>=45) _55YR40[i] = 1.10+0.0037*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _55YR40[i] = 1.01 + 0.0022 * (i - 5); + } else if (i < 90 && i >= 45) { + _55YR40[i] = 1.10 + 0.0037 * (i - 45); } - //printf("55YR %1.2f %1.2f\n",_55YR40[44],_55YR40[89] ); + } + + //printf("55YR %1.2f %1.2f\n",_55YR40[44],_55YR40[89] ); _55YR50(maxInd); _55YR50.clear(); - for (int i=0; i5) _55YR50[i] = 1.06 + 0.0015*(i-5); - else if (i<85 && i>=45) _55YR50[i] = 1.12+0.00225*(i-45); - else if (i<140 && i >=85) _55YR50[i] = 1.21+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _55YR50[i] = 1.06 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _55YR50[i] = 1.12 + 0.00225 * (i - 45); + } else if (i < 140 && i >= 85) { + _55YR50[i] = 1.21 + 0.0015 * (i - 85); } - //printf("55YR %1.2f %1.2f %1.2f\n",_55YR50[44],_55YR50[84],_55YR50[125] ); + } + + //printf("55YR %1.2f %1.2f %1.2f\n",_55YR50[44],_55YR50[84],_55YR50[125] ); _55YR60(maxInd); _55YR60.clear(); - for (int i=0; i5) _55YR60[i] = 1.08 + 0.0012*(i-5); - else if (i<85 && i>=45) _55YR60[i] = 1.13+0.0018*(i-45); - else if (i<140 && i >=85) _55YR60[i] = 1.20+0.0025*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _55YR60[i] = 1.08 + 0.0012 * (i - 5); + } else if (i < 85 && i >= 45) { + _55YR60[i] = 1.13 + 0.0018 * (i - 45); + } else if (i < 140 && i >= 85) { + _55YR60[i] = 1.20 + 0.0025 * (i - 85); } - //printf("55YR %1.2f %1.2f %1.2f\n",_55YR60[44],_55YR60[84],_55YR60[125] ); + } + + //printf("55YR %1.2f %1.2f %1.2f\n",_55YR60[44],_55YR60[84],_55YR60[125] ); _55YR70(maxInd); _55YR70.clear(); - for (int i=0; i5) _55YR70[i] = 1.11 + 0.00075*(i-5); - else if (i<85 && i>=45) _55YR70[i] = 1.14+0.0012*(i-45); - else if (i<140 && i >=85) _55YR70[i] = 1.19+0.00225*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _55YR70[i] = 1.11 + 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _55YR70[i] = 1.14 + 0.0012 * (i - 45); + } else if (i < 140 && i >= 85) { + _55YR70[i] = 1.19 + 0.00225 * (i - 85); } - //printf("55YR %1.2f %1.2f %1.2f\n",_55YR70[44],_55YR70[84],_55YR70[125] ); + } + + //printf("55YR %1.2f %1.2f %1.2f\n",_55YR70[44],_55YR70[84],_55YR70[125] ); _55YR80(maxInd); _55YR80.clear(); - for (int i=0; i5) _55YR80[i] = 1.16 + 0.00*(i-5); - else if (i<85 && i>=45) _55YR80[i] = 1.16+0.00075*(i-45); - else if (i<140 && i >=85) _55YR80[i] = 1.19+0.00175*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _55YR80[i] = 1.16 + 0.00 * (i - 5); + } else if (i < 85 && i >= 45) { + _55YR80[i] = 1.16 + 0.00075 * (i - 45); + } else if (i < 140 && i >= 85) { + _55YR80[i] = 1.19 + 0.00175 * (i - 85); } - //printf("55YR %1.2f %1.2f %1.2f\n",_55YR80[44],_55YR80[84],_55YR80[125] ); + } + + //printf("55YR %1.2f %1.2f %1.2f\n",_55YR80[44],_55YR80[84],_55YR80[125] ); _55YR90(maxInd3); _55YR90.clear(); - for (int i=0; i5) _55YR90[i] = 1.19 - 0.0005*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _55YR90[i] = 1.19 - 0.0005 * (i - 5); } - //printf("55YR %1.2f \n",_55YR90[44] ); + } + + //printf("55YR %1.2f \n",_55YR90[44] ); _4YR30(maxInd2); _4YR30.clear(); - for (int i=0; i5) _4YR30[i] = 0.87 + 0.0035*(i-5); - else if (i<90 && i>=45) _4YR30[i] = 1.01+0.0043*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _4YR30[i] = 0.87 + 0.0035 * (i - 5); + } else if (i < 90 && i >= 45) { + _4YR30[i] = 1.01 + 0.0043 * (i - 45); } - //printf("4YR %1.2f %1.2f\n",_4YR30[44],_4YR30[78] ); + } + + //printf("4YR %1.2f %1.2f\n",_4YR30[44],_4YR30[78] ); _4YR40(maxInd2); _4YR40.clear(); - for (int i=0; i5) _4YR40[i] = 0.92 + 0.0025*(i-5); - else if (i<90 && i>=45) _4YR40[i] = 1.02+0.0033*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _4YR40[i] = 0.92 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _4YR40[i] = 1.02 + 0.0033 * (i - 45); } - //printf("4YR %1.2f %1.2f\n",_4YR40[44],_4YR40[74] ); + } + + //printf("4YR %1.2f %1.2f\n",_4YR40[44],_4YR40[74] ); _4YR50(maxInd2); _4YR50.clear(); - for (int i=0; i5) _4YR50[i] = 0.97 + 0.0015*(i-5); - else if (i<90 && i>=45) _4YR50[i] = 1.03+0.0025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _4YR50[i] = 0.97 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _4YR50[i] = 1.03 + 0.0025 * (i - 45); } - //printf("4YR %1.2f %1.2f\n",_4YR50[44],_4YR50[85] ); + } + + //printf("4YR %1.2f %1.2f\n",_4YR50[44],_4YR50[85] ); _4YR60(maxInd); _4YR60.clear(); - for (int i=0; i5) _4YR60[i] = 0.99 + 0.00125*(i-5); - else if (i<85 && i>=45) _4YR60[i] = 1.04+0.002*(i-45); - else if (i<140 && i >=85) _4YR60[i] = 1.12+0.003*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _4YR60[i] = 0.99 + 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _4YR60[i] = 1.04 + 0.002 * (i - 45); + } else if (i < 140 && i >= 85) { + _4YR60[i] = 1.12 + 0.003 * (i - 85); } - //printf("4YR %1.2f %1.2f %1.2f\n",_4YR60[44],_4YR60[84],_4YR60[125] ); + } + + //printf("4YR %1.2f %1.2f %1.2f\n",_4YR60[44],_4YR60[84],_4YR60[125] ); _4YR70(maxInd); _4YR70.clear(); - for (int i=0; i5) _4YR70[i] = 1.02 + 0.00075*(i-5); - else if (i<85 && i>=45) _4YR70[i] = 1.05+0.00175*(i-45); - else if (i<140 && i >=85) _4YR70[i] = 1.12+0.002*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _4YR70[i] = 1.02 + 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _4YR70[i] = 1.05 + 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _4YR70[i] = 1.12 + 0.002 * (i - 85); } - //printf("4YR %1.2f %1.2f %1.2f\n",_4YR70[44],_4YR70[84],_4YR70[125] ); + } + + //printf("4YR %1.2f %1.2f %1.2f\n",_4YR70[44],_4YR70[84],_4YR70[125] ); _4YR80(maxInd3); _4YR80.clear(); - for (int i=0; i5) _4YR80[i] = 1.09 - 0.0002*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 50 && i > 5) { + _4YR80[i] = 1.09 - 0.0002 * (i - 5); } - //printf("4YR %1.2f \n",_4YR80[41] ); + } + + //printf("4YR %1.2f \n",_4YR80[41] ); _25YR30(maxInd2); _25YR30.clear(); - for (int i=0; i5) _25YR30[i] = 0.77 + 0.004*(i-5); - else if (i<90 && i>=45) _25YR30[i] = 0.94+0.004*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25YR30[i] = 0.77 + 0.004 * (i - 5); + } else if (i < 90 && i >= 45) { + _25YR30[i] = 0.94 + 0.004 * (i - 45); } - //printf("25YR %1.2f %1.2f\n",_25YR30[44],_25YR30[74] ); + } + + //printf("25YR %1.2f %1.2f\n",_25YR30[44],_25YR30[74] ); _25YR40(maxInd2); _25YR40.clear(); - for (int i=0; i5) _25YR40[i] = 0.82 + 0.003*(i-5); - else if (i<90 && i>=45) _25YR40[i] = 0.94+0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25YR40[i] = 0.82 + 0.003 * (i - 5); + } else if (i < 90 && i >= 45) { + _25YR40[i] = 0.94 + 0.002 * (i - 45); } - //printf("25YR %1.2f %1.2f\n",_25YR40[44],_25YR40[84] ); + } + + //printf("25YR %1.2f %1.2f\n",_25YR40[44],_25YR40[84] ); _25YR50(maxInd2); _25YR50.clear(); - for (int i=0; i5) _25YR50[i] = 0.87+ 0.002*(i-5); - else if (i<90 && i>=45) _25YR50[i] = 0.95+0.003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25YR50[i] = 0.87 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _25YR50[i] = 0.95 + 0.003 * (i - 45); } - //printf("25YR %1.2f %1.2f\n",_25YR50[44],_25YR50[84] ); + } + + //printf("25YR %1.2f %1.2f\n",_25YR50[44],_25YR50[84] ); _25YR60(maxInd2); _25YR60.clear(); - for (int i=0; i5) _25YR60[i] = 0.89+ 0.0015*(i-5); - else if (i<90 && i>=45) _25YR60[i] = 0.95+0.004*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25YR60[i] = 0.89 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _25YR60[i] = 0.95 + 0.004 * (i - 45); } - //printf("25YR %1.2f %1.2f\n",_25YR60[44],_25YR60[84] ); + } + + //printf("25YR %1.2f %1.2f\n",_25YR60[44],_25YR60[84] ); _25YR70(maxInd2); _25YR70.clear(); - for (int i=0; i5) _25YR70[i] = 0.92+ 0.001*(i-5); - else if (i<90 && i>=45) _25YR70[i] = 0.96+0.003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25YR70[i] = 0.92 + 0.001 * (i - 5); + } else if (i < 90 && i >= 45) { + _25YR70[i] = 0.96 + 0.003 * (i - 45); } - //printf("25YR %1.2f %1.2f\n",_25YR70[44],_25YR70[84] ); + } + + //printf("25YR %1.2f %1.2f\n",_25YR70[44],_25YR70[84] ); _10R30(maxInd2); _10R30.clear(); - for (int i=0; i5) _10R30[i] = 0.62 + 0.00225*(i-5); - else if (i<90 && i>=45) _10R30[i] = 0.71+0.003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10R30[i] = 0.62 + 0.00225 * (i - 5); + } else if (i < 90 && i >= 45) { + _10R30[i] = 0.71 + 0.003 * (i - 45); } - //printf("10R %1.2f %1.2f\n",_10R30[44],_10R30[84] ); + } + + //printf("10R %1.2f %1.2f\n",_10R30[44],_10R30[84] ); _10R40(maxInd2); _10R40.clear(); - for (int i=0; i5) _10R40[i] = 0.66 + 0.0025*(i-5); - else if (i<90 && i>=45) _10R40[i] = 0.76+0.0035*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10R40[i] = 0.66 + 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _10R40[i] = 0.76 + 0.0035 * (i - 45); } - //printf("10R %1.2f %1.2f\n",_10R40[44],_10R40[84] ); + } + + //printf("10R %1.2f %1.2f\n",_10R40[44],_10R40[84] ); _10R50(maxInd2); _10R50.clear(); - for (int i=0; i5) _10R50[i] = 0.71 + 0.002*(i-5); - else if (i<90 && i>=45) _10R50[i] = 0.79+0.0043*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10R50[i] = 0.71 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _10R50[i] = 0.79 + 0.0043 * (i - 45); } - //printf("10R %1.2f %1.2f\n",_10R50[44],_10R50[84] ); + } + + //printf("10R %1.2f %1.2f\n",_10R50[44],_10R50[84] ); _10R60(maxInd); _10R60.clear(); - for (int i=0; i5) _10R60[i] = 0.73 + 0.00175*(i-5); - else if (i<85 && i>=45) _10R60[i] = 0.80 +0.0033*(i-45); - else if (i<140 && i >=85) _10R60[i] = 0.93+0.0018*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10R60[i] = 0.73 + 0.00175 * (i - 5); + } else if (i < 85 && i >= 45) { + _10R60[i] = 0.80 + 0.0033 * (i - 45); + } else if (i < 140 && i >= 85) { + _10R60[i] = 0.93 + 0.0018 * (i - 85); } - //printf("10R %1.2f %1.2f %1.2f\n",_10R60[44],_10R60[84],_10R60[125] ); + } + + //printf("10R %1.2f %1.2f %1.2f\n",_10R60[44],_10R60[84],_10R60[125] ); _10R70(maxInd); _10R70.clear(); - for (int i=0; i5) _10R70[i] = 0.75 + 0.0015*(i-5); - else if (i<85 && i>=45) _10R70[i] = 0.81 +0.0017*(i-45); - else if (i<140 && i >=85) _10R70[i] = 0.88+0.0025*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10R70[i] = 0.75 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _10R70[i] = 0.81 + 0.0017 * (i - 45); + } else if (i < 140 && i >= 85) { + _10R70[i] = 0.88 + 0.0025 * (i - 85); } - //printf("10R %1.2f %1.2f %1.2f\n",_10R70[44],_10R70[84],_10R70[125] ); + } + + //printf("10R %1.2f %1.2f %1.2f\n",_10R70[44],_10R70[84],_10R70[125] ); _9R30(maxInd2); _9R30.clear(); - for (int i=0; i5) _9R30[i] = 0.57 + 0.002*(i-5); - else if (i<90 && i>=45) _9R30[i] = 0.65+0.0018*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9R30[i] = 0.57 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _9R30[i] = 0.65 + 0.0018 * (i - 45); } - //printf("9R %1.2f %1.2f\n",_9R30[44],_9R30[84] ); + } + + //printf("9R %1.2f %1.2f\n",_9R30[44],_9R30[84] ); _9R40(maxInd2); _9R40.clear(); - for (int i=0; i5) _9R40[i] = 0.61 + 0.002*(i-5); - else if (i<90 && i>=45) _9R40[i] = 0.69+0.0025*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9R40[i] = 0.61 + 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _9R40[i] = 0.69 + 0.0025 * (i - 45); } - //printf("9R %1.2f %1.2f\n",_9R40[44],_9R40[84] ); + } + + //printf("9R %1.2f %1.2f\n",_9R40[44],_9R40[84] ); _9R50(maxInd); _9R50.clear(); - for (int i=0; i5) _9R50[i] = 0.66 + 0.00175*(i-5); - else if (i<85 && i>=45) _9R50[i] = 0.73 +0.0025*(i-45); - else if (i<140 && i >=85) _9R50[i] = 0.83+0.0035*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _9R50[i] = 0.66 + 0.00175 * (i - 5); + } else if (i < 85 && i >= 45) { + _9R50[i] = 0.73 + 0.0025 * (i - 45); + } else if (i < 140 && i >= 85) { + _9R50[i] = 0.83 + 0.0035 * (i - 85); } - //printf("9R %1.2f %1.2f %1.2f\n",_9R50[44],_9R50[84],_9R50[125] ); + } + + //printf("9R %1.2f %1.2f %1.2f\n",_9R50[44],_9R50[84],_9R50[125] ); _9R60(maxInd); _9R60.clear(); - for (int i=0; i5) _9R60[i] = 0.68 + 0.0015*(i-5); - else if (i<85 && i>=45) _9R60[i] = 0.74 +0.0022*(i-45); - else if (i<140 && i >=85) _9R60[i] = 0.93+0.0022*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _9R60[i] = 0.68 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _9R60[i] = 0.74 + 0.0022 * (i - 45); + } else if (i < 140 && i >= 85) { + _9R60[i] = 0.93 + 0.0022 * (i - 85); } - //printf("9R %1.2f %1.2f %1.2f\n",_9R60[44],_9R60[84],_9R60[125] ); + } + + //printf("9R %1.2f %1.2f %1.2f\n",_9R60[44],_9R60[84],_9R60[125] ); _9R70(maxInd2); _9R70.clear(); - for (int i=0; i5) _9R70[i] = 0.70 + 0.0012*(i-5); - else if (i<90 && i>=45) _9R70[i] = 0.75+0.0013*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _9R70[i] = 0.70 + 0.0012 * (i - 5); + } else if (i < 90 && i >= 45) { + _9R70[i] = 0.75 + 0.0013 * (i - 45); } - //printf("9R %1.2f %1.2f\n",_9R70[44],_9R70[84] ); + } + + //printf("9R %1.2f %1.2f\n",_9R70[44],_9R70[84] ); _7R30(maxInd2); _7R30.clear(); - for (int i=0; i5) _7R30[i] = 0.48 + 0.0015*(i-5); - else if (i<90 && i>=45) _7R30[i] = 0.54-0.0005*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7R30[i] = 0.48 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _7R30[i] = 0.54 - 0.0005 * (i - 45); } - //printf("7R %1.2f %1.2f\n",_7R30[44],_7R30[84] ); + } + + //printf("7R %1.2f %1.2f\n",_7R30[44],_7R30[84] ); _7R40(maxInd2); _7R40.clear(); - for (int i=0; i5) _7R40[i] = 0.51 + 0.0015*(i-5); - else if (i<90 && i>=45) _7R40[i] = 0.57+0.0005*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7R40[i] = 0.51 + 0.0015 * (i - 5); + } else if (i < 90 && i >= 45) { + _7R40[i] = 0.57 + 0.0005 * (i - 45); } - //printf("7R %1.2f %1.2f\n",_7R40[44],_7R40[84] ); + } + + //printf("7R %1.2f %1.2f\n",_7R40[44],_7R40[84] ); _7R50(maxInd); _7R50.clear(); - for (int i=0; i5) _7R50[i] = 0.54 + 0.0015*(i-5); - else if (i<85 && i>=45) _7R50[i] = 0.60 +0.0005*(i-45); - else if (i<140 && i >=85) _7R50[i] = 0.62+0.0025*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7R50[i] = 0.54 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _7R50[i] = 0.60 + 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _7R50[i] = 0.62 + 0.0025 * (i - 85); } - //printf("7R %1.2f %1.2f %1.2f\n",_7R50[44],_7R50[84],_7R50[125] ); + } + + //printf("7R %1.2f %1.2f %1.2f\n",_7R50[44],_7R50[84],_7R50[125] ); _7R60(maxInd); _7R60.clear(); - for (int i=0; i5) _7R60[i] = 0.58 + 0.00075*(i-5); - else if (i<85 && i>=45) _7R60[i] = 0.61 +0.00075*(i-45); - else if (i<140 && i >=85) _7R60[i] = 0.64+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7R60[i] = 0.58 + 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _7R60[i] = 0.61 + 0.00075 * (i - 45); + } else if (i < 140 && i >= 85) { + _7R60[i] = 0.64 + 0.001 * (i - 85); } - //printf("7R %1.2f %1.2f %1.2f\n",_7R60[44],_7R60[84],_7R60[107] ); + } + + //printf("7R %1.2f %1.2f %1.2f\n",_7R60[44],_7R60[84],_7R60[107] ); _7R70(maxInd2); _7R70.clear(); - for (int i=0; i5) _7R70[i] = 0.59 + 0.00075*(i-5); - else if (i<90 && i>=45) _7R70[i] = 0.62+0.00075*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _7R70[i] = 0.59 + 0.00075 * (i - 5); + } else if (i < 90 && i >= 45) { + _7R70[i] = 0.62 + 0.00075 * (i - 45); } - //printf("7R %1.2f %1.2f\n",_7R70[44],_7R70[84] ); + } + + //printf("7R %1.2f %1.2f\n",_7R70[44],_7R70[84] ); //5R 1 2 3 //5R _5R10(maxInd2); _5R10.clear(); - for (int i=0; i5) _5R10[i] = 0.10 - 0.0018*(i-5); - else if (i<90 && i>=45) _5R10[i] = 0.035-0.003*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5R10[i] = 0.10 - 0.0018 * (i - 5); + } else if (i < 90 && i >= 45) { + _5R10[i] = 0.035 - 0.003 * (i - 45); } - //printf("5R %1.2f %1.2f\n",_5R10[44],_5R10[51] ); + } + + //printf("5R %1.2f %1.2f\n",_5R10[44],_5R10[51] ); _5R20(maxInd2); _5R20.clear(); - for (int i=0; i5) _5R20[i] = 0.26 - 0.00075*(i-5); - else if (i<90 && i>=45) _5R20[i] = 0.023-0.0002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5R20[i] = 0.26 - 0.00075 * (i - 5); + } else if (i < 90 && i >= 45) { + _5R20[i] = 0.023 - 0.0002 * (i - 45); } - //printf("5R %1.2f %1.2f\n",_5R20[44],_5R20[70] ); + } + + //printf("5R %1.2f %1.2f\n",_5R20[44],_5R20[70] ); _5R30(maxInd2); _5R30.clear(); - for (int i=0; i5) _5R30[i] = 0.39 + 0.00075*(i-5); - else if (i<90 && i>=45) _5R30[i] = 0.42-0.0007*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _5R30[i] = 0.39 + 0.00075 * (i - 5); + } else if (i < 90 && i >= 45) { + _5R30[i] = 0.42 - 0.0007 * (i - 45); } - //printf("5R %1.2f %1.2f\n",_5R30[44],_5R30[85] ); + } + + //printf("5R %1.2f %1.2f\n",_5R30[44],_5R30[85] ); //25R _25R10(maxInd3); _25R10.clear(); - for (int i=0; i5) _25R10[i] = -0.03 - 0.002*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 45 && i > 5) { + _25R10[i] = -0.03 - 0.002 * (i - 5); } - //printf("25R %1.2f \n",_25R10[44]); + } + + //printf("25R %1.2f \n",_25R10[44]); _25R20(maxInd2); _25R20.clear(); - for (int i=0; i5) _25R20[i] = 0.13 - 0.0012*(i-5); - else if (i<90 && i>=45) _25R20[i] = 0.08-0.002*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25R20[i] = 0.13 - 0.0012 * (i - 5); + } else if (i < 90 && i >= 45) { + _25R20[i] = 0.08 - 0.002 * (i - 45); } - //printf("25R %1.2f %1.2f\n",_25R20[44],_25R20[69] ); - //25R30: 0.28, 0.26, 0.22 + } + + //printf("25R %1.2f %1.2f\n",_25R20[44],_25R20[69] ); + //25R30: 0.28, 0.26, 0.22 _25R30(maxInd2); _25R30.clear(); - for (int i=0; i5) _25R30[i] = 0.28 - 0.0005*(i-5); - else if (i<90 && i>=45) _25R30[i] = 0.26-0.0009*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _25R30[i] = 0.28 - 0.0005 * (i - 5); + } else if (i < 90 && i >= 45) { + _25R30[i] = 0.26 - 0.0009 * (i - 45); } - //printf("25R %1.2f %1.2f\n",_25R30[44],_25R30[85] ); + } + + //printf("25R %1.2f %1.2f\n",_25R30[44],_25R30[85] ); _10RP10(maxInd3); _10RP10.clear(); - for (int i=0; i5) _10RP10[i] = -0.16 - 0.0017*(i-5); + + for (int i = 0; i < maxInd3; i++) { + if (i < 45 && i > 5) { + _10RP10[i] = -0.16 - 0.0017 * (i - 5); } - //printf("10RP %1.2f \n",_10RP10[44]); + } + + //printf("10RP %1.2f \n",_10RP10[44]); _10RP20(maxInd2); _10RP20.clear(); - for (int i=0; i5) _10RP20[i] = 0.0 - 0.0018*(i-5); - else if (i<90 && i>=45) _10RP20[i] = -0.07-0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10RP20[i] = 0.0 - 0.0018 * (i - 5); + } else if (i < 90 && i >= 45) { + _10RP20[i] = -0.07 - 0.0012 * (i - 45); } - //printf("10RP %1.2f %1.2f\n",_10RP20[44],_10RP20[69] ); + } + + //printf("10RP %1.2f %1.2f\n",_10RP20[44],_10RP20[69] ); _10RP30(maxInd2); _10RP30.clear(); - for (int i=0; i5) _10RP30[i] = 0.15 - 0.001*(i-5); - else if (i<90 && i>=45) _10RP30[i] = 0.11-0.0012*(i-45); + + for (int i = 0; i < maxInd2; i++) { + if (i < 45 && i > 5) { + _10RP30[i] = 0.15 - 0.001 * (i - 5); + } else if (i < 90 && i >= 45) { + _10RP30[i] = 0.11 - 0.0012 * (i - 45); } - //printf("10RP %1.2f %1.2f\n",_10RP30[44],_10RP30[85] ); + } + + //printf("10RP %1.2f %1.2f\n",_10RP30[44],_10RP30[85] ); //7G _7G30(maxInd); _7G30.clear(); - for (int i=0; i5) _7G30[i] = 2.90 + 0.0027*(i-5); - else if (i<85 && i>=45) _7G30[i] = 3.01+0.0005*(i-45); - else if (i<140 && i >=85) _7G30[i] = 3.03+0.00075*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7G30[i] = 2.90 + 0.0027 * (i - 5); + } else if (i < 85 && i >= 45) { + _7G30[i] = 3.01 + 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _7G30[i] = 3.03 + 0.00075 * (i - 85); } - //printf("7G %1.2f %1.2f %1.2f\n",_7G30[44],_7G30[84],_7G30[125] ); + } + + //printf("7G %1.2f %1.2f %1.2f\n",_7G30[44],_7G30[84],_7G30[125] ); _7G40(maxInd); _7G40.clear(); - for (int i=0; i5) _7G40[i] = 2.89 + 0.00125*(i-5); - else if (i<85 && i>=45) _7G40[i] = 2.94+0.0015*(i-45); - else if (i<140 && i >=85) _7G40[i] = 3.0+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7G40[i] = 2.89 + 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _7G40[i] = 2.94 + 0.0015 * (i - 45); + } else if (i < 140 && i >= 85) { + _7G40[i] = 3.0 + 0.001 * (i - 85); } - //printf("7G %1.2f %1.2f %1.2f\n",_7G40[44],_7G40[84],_7G40[125] ); + } + + //printf("7G %1.2f %1.2f %1.2f\n",_7G40[44],_7G40[84],_7G40[125] ); _7G50(maxInd); _7G50.clear(); - for (int i=0; i5) _7G50[i] = 2.87 + 0.0015*(i-5); - else if (i<85 && i>=45) _7G50[i] = 2.93+0.00125*(i-45); - else if (i<140 && i >=85) _7G50[i] = 2.98+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7G50[i] = 2.87 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _7G50[i] = 2.93 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _7G50[i] = 2.98 + 0.001 * (i - 85); } - //printf("7G %1.2f %1.2f %1.2f\n",_7G50[44],_7G50[84],_7G50[125] ); + } + + //printf("7G %1.2f %1.2f %1.2f\n",_7G50[44],_7G50[84],_7G50[125] ); _7G60(maxInd); _7G60.clear(); - for (int i=0; i5) _7G60[i] = 2.86 + 0.00125*(i-5); - else if (i<85 && i>=45) _7G60[i] = 2.91+0.00125*(i-45); - else if (i<140 && i >=85) _7G60[i] = 2.96+0.00075*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7G60[i] = 2.86 + 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _7G60[i] = 2.91 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _7G60[i] = 2.96 + 0.00075 * (i - 85); } - //printf("7G %1.2f %1.2f %1.2f\n",_7G60[44],_7G60[84],_7G60[125] ); + } + + //printf("7G %1.2f %1.2f %1.2f\n",_7G60[44],_7G60[84],_7G60[125] ); _7G70(maxInd); _7G70.clear(); - for (int i=0; i5) _7G70[i] = 2.85 + 0.001*(i-5); - else if (i<85 && i>=45) _7G70[i] = 2.89+0.00125*(i-45); - else if (i<140 && i >=85) _7G70[i] = 2.94+0.00075*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7G70[i] = 2.85 + 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _7G70[i] = 2.89 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _7G70[i] = 2.94 + 0.00075 * (i - 85); } - //printf("7G %1.2f %1.2f %1.2f\n",_7G70[44],_7G70[84],_7G70[125] ); + } + + //printf("7G %1.2f %1.2f %1.2f\n",_7G70[44],_7G70[84],_7G70[125] ); _7G80(maxInd); _7G80.clear(); - for (int i=0; i5) _7G80[i] = 2.84 + 0.001*(i-5); - else if (i<85 && i>=45) _7G80[i] = 2.88+0.001*(i-45); - else if (i<140 && i >=85) _7G80[i] = 2.92+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _7G80[i] = 2.84 + 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _7G80[i] = 2.88 + 0.001 * (i - 45); + } else if (i < 140 && i >= 85) { + _7G80[i] = 2.92 + 0.001 * (i - 85); } - //printf("7G %1.2f %1.2f %1.2f\n",_7G80[44],_7G80[84],_7G80[125] ); + } + + //printf("7G %1.2f %1.2f %1.2f\n",_7G80[44],_7G80[84],_7G80[125] ); //5G _5G30(maxInd); _5G30.clear(); - for (int i=0; i5) _5G30[i] = 2.82 + 0.00175*(i-5); - else if (i<85 && i>=45) _5G30[i] = 2.89+0.0018*(i-45); - else if (i<140 && i >=85) _5G30[i] = 2.96+0.0012*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5G30[i] = 2.82 + 0.00175 * (i - 5); + } else if (i < 85 && i >= 45) { + _5G30[i] = 2.89 + 0.0018 * (i - 45); + } else if (i < 140 && i >= 85) { + _5G30[i] = 2.96 + 0.0012 * (i - 85); } - //printf("5G %1.2f %1.2f %1.2f\n",_5G30[44],_5G30[84],_5G30[125] ); + } + + //printf("5G %1.2f %1.2f %1.2f\n",_5G30[44],_5G30[84],_5G30[125] ); _5G40(maxInd); _5G40.clear(); - for (int i=0; i5) _5G40[i] = 2.80 + 0.0015*(i-5); - else if (i<85 && i>=45) _5G40[i] = 2.86+0.00175*(i-45); - else if (i<140 && i >=85) _5G40[i] = 2.93+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5G40[i] = 2.80 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _5G40[i] = 2.86 + 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _5G40[i] = 2.93 + 0.00125 * (i - 85); } - //printf("5G %1.2f %1.2f %1.2f\n",_5G40[44],_5G40[84],_5G40[125] ); + } + + //printf("5G %1.2f %1.2f %1.2f\n",_5G40[44],_5G40[84],_5G40[125] ); _5G50(maxInd); _5G50.clear(); - for (int i=0; i5) _5G50[i] = 2.79 + 0.001*(i-5); - else if (i<85 && i>=45) _5G50[i] = 2.84+0.0015*(i-45); - else if (i<140 && i >=85) _5G50[i] = 2.90+0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5G50[i] = 2.79 + 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _5G50[i] = 2.84 + 0.0015 * (i - 45); + } else if (i < 140 && i >= 85) { + _5G50[i] = 2.90 + 0.0015 * (i - 85); } - //printf("5G %1.2f %1.2f %1.2f\n",_5G50[44],_5G50[84],_5G50[125] ); + } + + //printf("5G %1.2f %1.2f %1.2f\n",_5G50[44],_5G50[84],_5G50[125] ); _5G60(maxInd); _5G60.clear(); - for (int i=0; i5) _5G60[i] = 2.78 + 0.001*(i-5); - else if (i<85 && i>=45) _5G60[i] = 2.82+0.00175*(i-45); - else if (i<140 && i >=85) _5G60[i] = 2.89+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5G60[i] = 2.78 + 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _5G60[i] = 2.82 + 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _5G60[i] = 2.89 + 0.001 * (i - 85); } - //printf("5G %1.2f %1.2f %1.2f\n",_5G60[44],_5G60[84],_5G60[125] ); + } + + //printf("5G %1.2f %1.2f %1.2f\n",_5G60[44],_5G60[84],_5G60[125] ); _5G70(maxInd); _5G70.clear(); - for (int i=0; i5) _5G70[i] = 2.77 + 0.001*(i-5); - else if (i<85 && i>=45) _5G70[i] = 2.81+0.00125*(i-45); - else if (i<140 && i >=85) _5G70[i] = 2.86+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5G70[i] = 2.77 + 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _5G70[i] = 2.81 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _5G70[i] = 2.86 + 0.00125 * (i - 85); } - //printf("5G %1.2f %1.2f %1.2f\n",_5G70[44],_5G70[84],_5G70[125] ); + } + + //printf("5G %1.2f %1.2f %1.2f\n",_5G70[44],_5G70[84],_5G70[125] ); _5G80(maxInd); _5G80.clear(); - for (int i=0; i5) _5G80[i] = 2.76 + 0.001*(i-5); - else if (i<85 && i>=45) _5G80[i] = 2.8+0.00125*(i-45); - else if (i<140 && i >=85) _5G80[i] = 2.85+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5G80[i] = 2.76 + 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _5G80[i] = 2.8 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _5G80[i] = 2.85 + 0.00125 * (i - 85); } - //printf("5G %1.2f %1.2f %1.2f\n",_5G80[44],_5G80[84],_5G80[125] ); + } + + //printf("5G %1.2f %1.2f %1.2f\n",_5G80[44],_5G80[84],_5G80[125] ); //25G _25G30(maxInd); _25G30.clear(); - for (int i=0; i5) _25G30[i] = 2.68 + 0.0015*(i-5); - else if (i<85 && i>=45) _25G30[i] = 2.74+0.0018*(i-45); - else if (i<140 && i >=85) _25G30[i] = 2.81+0.002*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _25G30[i] = 2.68 + 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _25G30[i] = 2.74 + 0.0018 * (i - 45); + } else if (i < 140 && i >= 85) { + _25G30[i] = 2.81 + 0.002 * (i - 85); } - //printf("25G %1.2f %1.2f %1.2f\n",_25G30[44],_25G30[84],_25G30[125] ); + } + + //printf("25G %1.2f %1.2f %1.2f\n",_25G30[44],_25G30[84],_25G30[125] ); _25G40(maxInd); _25G40.clear(); - for (int i=0; i5) _25G40[i] = 2.68 + 0.00075*(i-5); - else if (i<85 && i>=45) _25G40[i] = 2.71+0.0015*(i-45); - else if (i<140 && i >=85) _25G40[i] = 2.77+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _25G40[i] = 2.68 + 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _25G40[i] = 2.71 + 0.0015 * (i - 45); + } else if (i < 140 && i >= 85) { + _25G40[i] = 2.77 + 0.00125 * (i - 85); } - //printf("25G %1.2f %1.2f %1.2f\n",_25G40[44],_25G40[84],_25G40[125] ); + } + + //printf("25G %1.2f %1.2f %1.2f\n",_25G40[44],_25G40[84],_25G40[125] ); _25G50(maxInd); _25G50.clear(); - for (int i=0; i5) _25G50[i] = 2.65 + 0.00075*(i-5); - else if (i<85 && i>=45) _25G50[i] = 2.68+0.00125*(i-45); - else if (i<140 && i >=85) _25G50[i] = 2.73+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _25G50[i] = 2.65 + 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _25G50[i] = 2.68 + 0.00125 * (i - 45); + } else if (i < 140 && i >= 85) { + _25G50[i] = 2.73 + 0.00125 * (i - 85); } - //printf("25G %1.2f %1.2f %1.2f\n",_25G50[44],_25G50[84],_25G50[125] ); + } + + //printf("25G %1.2f %1.2f %1.2f\n",_25G50[44],_25G50[84],_25G50[125] ); _25G60(maxInd); _25G60.clear(); - for (int i=0; i5) _25G60[i] = 2.64 + 0.0005*(i-5); - else if (i<85 && i>=45) _25G60[i] = 2.66+0.001*(i-45); - else if (i<140 && i >=85) _25G60[i] = 2.70+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _25G60[i] = 2.64 + 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _25G60[i] = 2.66 + 0.001 * (i - 45); + } else if (i < 140 && i >= 85) { + _25G60[i] = 2.70 + 0.001 * (i - 85); } - //printf("25G %1.2f %1.2f %1.2f\n",_25G60[44],_25G60[84],_25G60[125] ); + } + + //printf("25G %1.2f %1.2f %1.2f\n",_25G60[44],_25G60[84],_25G60[125] ); _25G70(maxInd); _25G70.clear(); - for (int i=0; i5) _25G70[i] = 2.64 + 0.00*(i-5); - else if (i<85 && i>=45) _25G70[i] = 2.64+0.00075*(i-45); - else if (i<140 && i >=85) _25G70[i] = 2.67+0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _25G70[i] = 2.64 + 0.00 * (i - 5); + } else if (i < 85 && i >= 45) { + _25G70[i] = 2.64 + 0.00075 * (i - 45); + } else if (i < 140 && i >= 85) { + _25G70[i] = 2.67 + 0.001 * (i - 85); } - //printf("25G %1.2f %1.2f %1.2f\n",_25G70[44],_25G70[84],_25G70[125] ); + } + + //printf("25G %1.2f %1.2f %1.2f\n",_25G70[44],_25G70[84],_25G70[125] ); _25G80(maxInd); _25G80.clear(); - for (int i=0; i5) _25G80[i] = 2.63 + 0.00*(i-5); - else if (i<85 && i>=45) _25G80[i] = 2.63+0.0005*(i-45); - else if (i<140 && i >=85) _25G80[i] = 2.65+0.0005*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _25G80[i] = 2.63 + 0.00 * (i - 5); + } else if (i < 85 && i >= 45) { + _25G80[i] = 2.63 + 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _25G80[i] = 2.65 + 0.0005 * (i - 85); } - //printf("25G %1.2f %1.2f %1.2f\n",_25G80[44],_25G80[84],_25G80[125] ); + } + + //printf("25G %1.2f %1.2f %1.2f\n",_25G80[44],_25G80[84],_25G80[125] ); //1G _1G30(maxInd); _1G30.clear(); - for (int i=0; i5) _1G30[i] = 2.58 + 0.00025*(i-5); - else if (i<85 && i>=45) _1G30[i] = 2.59+0.001*(i-45); - else if (i<140 && i >=85) _1G30[i] = 2.63+0.00125*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1G30[i] = 2.58 + 0.00025 * (i - 5); + } else if (i < 85 && i >= 45) { + _1G30[i] = 2.59 + 0.001 * (i - 45); + } else if (i < 140 && i >= 85) { + _1G30[i] = 2.63 + 0.00125 * (i - 85); } - //printf("1G %1.2f %1.2f %1.2f\n",_1G30[44],_1G30[84],_1G30[125] ); + } + + //printf("1G %1.2f %1.2f %1.2f\n",_1G30[44],_1G30[84],_1G30[125] ); _1G40(maxInd); _1G40.clear(); - for (int i=0; i5) _1G40[i] = 2.56 - 0.00025*(i-5); - else if (i<85 && i>=45) _1G40[i] = 2.55+0.0005*(i-45); - else if (i<140 && i >=85) _1G40[i] = 2.57+0.0005*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1G40[i] = 2.56 - 0.00025 * (i - 5); + } else if (i < 85 && i >= 45) { + _1G40[i] = 2.55 + 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _1G40[i] = 2.57 + 0.0005 * (i - 85); } - //printf("1G %1.2f %1.2f %1.2f\n",_1G40[44],_1G40[84],_1G40[125] ); + } + + //printf("1G %1.2f %1.2f %1.2f\n",_1G40[44],_1G40[84],_1G40[125] ); _1G50(maxInd); _1G50.clear(); - for (int i=0; i5) _1G50[i] = 2.55 - 0.00025*(i-5); - else if (i<85 && i>=45) _1G50[i] = 2.54+0.00025*(i-45); - else if (i<140 && i >=85) _1G50[i] = 2.55+0.0005*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1G50[i] = 2.55 - 0.00025 * (i - 5); + } else if (i < 85 && i >= 45) { + _1G50[i] = 2.54 + 0.00025 * (i - 45); + } else if (i < 140 && i >= 85) { + _1G50[i] = 2.55 + 0.0005 * (i - 85); } - //printf("1G %1.2f %1.2f %1.2f\n",_1G50[44],_1G50[84],_1G50[125] ); + } + + //printf("1G %1.2f %1.2f %1.2f\n",_1G50[44],_1G50[84],_1G50[125] ); _1G60(maxInd); _1G60.clear(); - for (int i=0; i5) _1G60[i] = 2.54 - 0.0005*(i-5); - else if (i<85 && i>=45) _1G60[i] = 2.52+0.00025*(i-45); - else if (i<140 && i >=85) _1G60[i] = 2.53+0.00025*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1G60[i] = 2.54 - 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _1G60[i] = 2.52 + 0.00025 * (i - 45); + } else if (i < 140 && i >= 85) { + _1G60[i] = 2.53 + 0.00025 * (i - 85); } - //printf("1G %1.2f %1.2f %1.2f\n",_1G60[44],_1G60[84],_1G60[125] ); + } + + //printf("1G %1.2f %1.2f %1.2f\n",_1G60[44],_1G60[84],_1G60[125] ); _1G70(maxInd); _1G70.clear(); - for (int i=0; i5) _1G70[i] = 2.53 - 0.0005*(i-5); - else if (i<85 && i>=45) _1G70[i] = 2.51+0.0*(i-45); - else if (i<140 && i >=85) _1G70[i] = 2.51+0.00025*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1G70[i] = 2.53 - 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _1G70[i] = 2.51 + 0.0 * (i - 45); + } else if (i < 140 && i >= 85) { + _1G70[i] = 2.51 + 0.00025 * (i - 85); } - //printf("1G %1.2f %1.2f %1.2f\n",_1G70[44],_1G70[84],_1G70[125] ); + } + + //printf("1G %1.2f %1.2f %1.2f\n",_1G70[44],_1G70[84],_1G70[125] ); _1G80(maxInd); _1G80.clear(); - for (int i=0; i5) _1G80[i] = 2.52 - 0.0005*(i-5); - else if (i<85 && i>=45) _1G80[i] = 2.50+0.00*(i-45); - else if (i<140 && i >=85) _1G80[i] = 2.50+0.00*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _1G80[i] = 2.52 - 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _1G80[i] = 2.50 + 0.00 * (i - 45); + } else if (i < 140 && i >= 85) { + _1G80[i] = 2.50 + 0.00 * (i - 85); } - //printf("1G %1.2f %1.2f %1.2f\n",_1G80[44],_1G80[84],_1G80[125] ); + } + + //printf("1G %1.2f %1.2f %1.2f\n",_1G80[44],_1G80[84],_1G80[125] ); //10GY _10GY30(maxInd); _10GY30.clear(); - for (int i=0; i5) _10GY30[i] = 2.52 - 0.001*(i-5); - else if (i<85 && i>=45) _10GY30[i] = 2.48-0.002*(i-45); - else if (i<140 && i >=85) _10GY30[i] = 2.40+0.0025*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10GY30[i] = 2.52 - 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _10GY30[i] = 2.48 - 0.002 * (i - 45); + } else if (i < 140 && i >= 85) { + _10GY30[i] = 2.40 + 0.0025 * (i - 85); } - //printf("10GY %1.2f %1.2f %1.2f\n",_10GY30[44],_10GY30[84],_10GY30[125] ); + } + + //printf("10GY %1.2f %1.2f %1.2f\n",_10GY30[44],_10GY30[84],_10GY30[125] ); _10GY40(maxInd); _10GY40.clear(); - for (int i=0; i5) _10GY40[i] = 2.48 - 0.0005*(i-5); - else if (i<85 && i>=45) _10GY40[i] = 2.46-0.0005*(i-45); - else if (i<140 && i >=85) _10GY40[i] = 2.44-0.0015*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10GY40[i] = 2.48 - 0.0005 * (i - 5); + } else if (i < 85 && i >= 45) { + _10GY40[i] = 2.46 - 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _10GY40[i] = 2.44 - 0.0015 * (i - 85); } - //printf("10GY %1.2f %1.2f %1.2f\n",_10GY40[44],_10GY40[84],_10GY40[125] ); + } + + //printf("10GY %1.2f %1.2f %1.2f\n",_10GY40[44],_10GY40[84],_10GY40[125] ); _10GY50(maxInd); _10GY50.clear(); - for (int i=0; i5) _10GY50[i] = 2.48 - 0.00075*(i-5); - else if (i<85 && i>=45) _10GY50[i] = 2.45-0.00075*(i-45); - else if (i<140 && i >=85) _10GY50[i] = 2.42-0.00175*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10GY50[i] = 2.48 - 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _10GY50[i] = 2.45 - 0.00075 * (i - 45); + } else if (i < 140 && i >= 85) { + _10GY50[i] = 2.42 - 0.00175 * (i - 85); } - //printf("10GY %1.2f %1.2f %1.2f\n",_10GY50[44],_10GY50[84],_10GY50[125] ); + } + + //printf("10GY %1.2f %1.2f %1.2f\n",_10GY50[44],_10GY50[84],_10GY50[125] ); _10GY60(maxInd); _10GY60.clear(); - for (int i=0; i5) _10GY60[i] = 2.47 - 0.00125*(i-5); - else if (i<85 && i>=45) _10GY60[i] = 2.42-0.00025*(i-45); - else if (i<140 && i >=85) _10GY60[i] = 2.41-0.0005*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10GY60[i] = 2.47 - 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _10GY60[i] = 2.42 - 0.00025 * (i - 45); + } else if (i < 140 && i >= 85) { + _10GY60[i] = 2.41 - 0.0005 * (i - 85); } - //printf("10GY %1.2f %1.2f %1.2f\n",_10GY60[44],_10GY60[84],_10GY60[125] ); + } + + //printf("10GY %1.2f %1.2f %1.2f\n",_10GY60[44],_10GY60[84],_10GY60[125] ); _10GY70(maxInd); _10GY70.clear(); - for (int i=0; i5) _10GY70[i] = 2.46 - 0.001*(i-5); - else if (i<85 && i>=45) _10GY70[i] = 2.42+0.0*(i-45); - else if (i<140 && i >=85) _10GY70[i] = 2.42-0.001*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10GY70[i] = 2.46 - 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _10GY70[i] = 2.42 + 0.0 * (i - 45); + } else if (i < 140 && i >= 85) { + _10GY70[i] = 2.42 - 0.001 * (i - 85); } - //printf("10GY %1.2f %1.2f %1.2f\n",_10GY70[44],_10GY70[84],_10GY70[125] ); + } + + //printf("10GY %1.2f %1.2f %1.2f\n",_10GY70[44],_10GY70[84],_10GY70[125] ); _10GY80(maxInd); _10GY80.clear(); - for (int i=0; i5) _10GY80[i] = 2.45 - 0.00075*(i-5); - else if (i<85 && i>=45) _10GY80[i] = 2.42 - 0.0005*(i-45); - else if (i<140 && i >=85) _10GY80[i] = 2.40-0.0005*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _10GY80[i] = 2.45 - 0.00075 * (i - 5); + } else if (i < 85 && i >= 45) { + _10GY80[i] = 2.42 - 0.0005 * (i - 45); + } else if (i < 140 && i >= 85) { + _10GY80[i] = 2.40 - 0.0005 * (i - 85); } - //printf("10GY %1.2f %1.2f %1.2f\n",_10GY80[44],_10GY80[84],_10GY80[125] ); + } + + //printf("10GY %1.2f %1.2f %1.2f\n",_10GY80[44],_10GY80[84],_10GY80[125] ); //75GY _75GY30(maxInd2); _75GY30.clear(); - for (int i=0; i5) _75GY30[i] = 2.36 - 0.0025*(i-5); - else if (i<90 && i>=45) _75GY30[i] = 2.26-0.00175*(i-45); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75GY30[i] = 2.36 - 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _75GY30[i] = 2.26 - 0.00175 * (i - 45); } - //printf("75GY %1.2f %1.2f\n",_75GY30[44],_75GY30[84] ); + } + + //printf("75GY %1.2f %1.2f\n",_75GY30[44],_75GY30[84] ); _75GY40(maxInd2); _75GY40.clear(); - for (int i=0; i5) _75GY40[i] = 2.34 - 0.00175*(i-5); - else if (i<90 && i>=45) _75GY40[i] = 2.27-0.00225*(i-45); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75GY40[i] = 2.34 - 0.00175 * (i - 5); + } else if (i < 90 && i >= 45) { + _75GY40[i] = 2.27 - 0.00225 * (i - 45); } - //printf("75GY %1.2f %1.2f \n",_75GY40[44],_75GY40[84] ); + } + + //printf("75GY %1.2f %1.2f \n",_75GY40[44],_75GY40[84] ); _75GY50(maxInd); _75GY50.clear(); - for (int i=0; i5) _75GY50[i] = 2.32 - 0.0015*(i-5); - else if (i<85 && i>=45) _75GY50[i] = 2.26-0.00175*(i-45); - else if (i<140 && i >=85) _75GY50[i] = 2.19-0.00325*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75GY50[i] = 2.32 - 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _75GY50[i] = 2.26 - 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _75GY50[i] = 2.19 - 0.00325 * (i - 85); } - //printf("75GY %1.2f %1.2f %1.2f %1.2f\n",_75GY50[44],_75GY50[84],_75GY50[125],_75GY50[139] ); + } + + //printf("75GY %1.2f %1.2f %1.2f %1.2f\n",_75GY50[44],_75GY50[84],_75GY50[125],_75GY50[139] ); _75GY60(maxInd); _75GY60.clear(); - for (int i=0; i5) _75GY60[i] = 2.30 - 0.00125*(i-5); - else if (i<85 && i>=45) _75GY60[i] = 2.25-0.001*(i-45); - else if (i<140 && i >=85) _75GY60[i] = 2.21-0.0027*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75GY60[i] = 2.30 - 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _75GY60[i] = 2.25 - 0.001 * (i - 45); + } else if (i < 140 && i >= 85) { + _75GY60[i] = 2.21 - 0.0027 * (i - 85); } - //printf("75GY %1.2f %1.2f %1.2f\n",_75GY60[44],_75GY60[84],_75GY60[125] ); + } + + //printf("75GY %1.2f %1.2f %1.2f\n",_75GY60[44],_75GY60[84],_75GY60[125] ); _75GY70(maxInd); _75GY70.clear(); - for (int i=0; i5) _75GY70[i] = 2.29 - 0.00125*(i-5); - else if (i<85 && i>=45) _75GY70[i] = 2.24-0.0015*(i-45); - else if (i<140 && i >=85) _75GY70[i] = 2.18-0.00175*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75GY70[i] = 2.29 - 0.00125 * (i - 5); + } else if (i < 85 && i >= 45) { + _75GY70[i] = 2.24 - 0.0015 * (i - 45); + } else if (i < 140 && i >= 85) { + _75GY70[i] = 2.18 - 0.00175 * (i - 85); } - //printf("75GY %1.2f %1.2f %1.2f\n",_75GY70[44],_75GY70[84],_75GY70[125] ); + } + + //printf("75GY %1.2f %1.2f %1.2f\n",_75GY70[44],_75GY70[84],_75GY70[125] ); _75GY80(maxInd); _75GY80.clear(); - for (int i=0; i5) _75GY80[i] = 2.27 - 0.001*(i-5); - else if (i<85 && i>=45) _75GY80[i] = 2.23 - 0.001*(i-45); - else if (i<140 && i >=85) _75GY80[i] = 2.19-0.00175*(i-85); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _75GY80[i] = 2.27 - 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _75GY80[i] = 2.23 - 0.001 * (i - 45); + } else if (i < 140 && i >= 85) { + _75GY80[i] = 2.19 - 0.00175 * (i - 85); } - //printf("75GY %1.2f %1.2f %1.2f\n",_75GY80[44],_75GY80[84],_75GY80[125] ); + } + + //printf("75GY %1.2f %1.2f %1.2f\n",_75GY80[44],_75GY80[84],_75GY80[125] ); //55GY _5GY30(maxInd2); _5GY30.clear(); - for (int i=0; i5) _5GY30[i] = 2.16 - 0.002*(i-5); - else if (i<90 && i>=45) _5GY30[i] = 2.07-0.0025*(i-45); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5GY30[i] = 2.16 - 0.002 * (i - 5); + } else if (i < 90 && i >= 45) { + _5GY30[i] = 2.07 - 0.0025 * (i - 45); } - //printf("5GY %1.2f %1.2f\n",_5GY30[44],_5GY30[84] ); + } + + //printf("5GY %1.2f %1.2f\n",_5GY30[44],_5GY30[84] ); //5GY4: 2.14,2.04, 1.96, 1.91 //95 _5GY40(maxInd2); _5GY40.clear(); - for (int i=0; i5) _5GY40[i] = 2.14 - 0.0025*(i-5); - else if (i<90 && i>=45) _5GY40[i] = 2.04-0.003*(i-45); - } - //printf("5GY %1.2f %1.2f \n",_5GY40[44],_5GY40[84] ); - _5GY50(maxInd); - _5GY50.clear(); - for (int i=0; i5) _5GY50[i] = 2.13 - 0.00175*(i-5); - else if (i<85 && i>=45) _5GY50[i] = 2.06-0.002*(i-45); - else if (i<140 && i >=85) _5GY50[i] = 1.98-0.00225*(i-85); - } - //printf("5GY %1.2f %1.2f %1.2f\n",_5GY50[44],_5GY50[84],_5GY50[125] ); - _5GY60(maxInd); - _5GY60.clear(); - for (int i=0; i5) _5GY60[i] = 2.11 - 0.0015*(i-5); - else if (i<85 && i>=45) _5GY60[i] = 2.05-0.002*(i-45); - else if (i<140 && i >=85) _5GY60[i] = 1.97-0.00275*(i-85); - } - //printf("5GY %1.2f %1.2f %1.2f\n",_5GY60[44],_5GY60[84],_5GY60[125] ); - _5GY70(maxInd); - _5GY70.clear(); - for (int i=0; i5) _5GY70[i] = 2.09 - 0.001*(i-5); - else if (i<85 && i>=45) _5GY70[i] = 2.05-0.00175*(i-45); - else if (i<140 && i >=85) _5GY70[i] = 1.98-0.002*(i-85); - } - //printf("5GY %1.2f %1.2f %1.2f\n",_5GY70[44],_5GY70[84],_5GY70[125] ); - _5GY80(maxInd); - _5GY80.clear(); - for (int i=0; i5) _5GY80[i] = 2.07 - 0.001*(i-5); - else if (i<85 && i>=45) _5GY80[i] = 2.03 - 0.00075*(i-45); - else if (i<140 && i >=85) _5GY80[i] = 2.0-0.002*(i-85); - } - //printf("5GY %1.2f %1.2f %1.2f\n",_5GY80[44],_5GY80[84],_5GY80[125] ); - #ifdef _DEBUG - t2e.set(); - if (settings->verbose) - printf("Lutf Munsell %d usec\n", t2e.etime(t1e)); - #endif + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5GY40[i] = 2.14 - 0.0025 * (i - 5); + } else if (i < 90 && i >= 45) { + _5GY40[i] = 2.04 - 0.003 * (i - 45); + } } + //printf("5GY %1.2f %1.2f \n",_5GY40[44],_5GY40[84] ); + _5GY50(maxInd); + _5GY50.clear(); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5GY50[i] = 2.13 - 0.00175 * (i - 5); + } else if (i < 85 && i >= 45) { + _5GY50[i] = 2.06 - 0.002 * (i - 45); + } else if (i < 140 && i >= 85) { + _5GY50[i] = 1.98 - 0.00225 * (i - 85); + } + } + + //printf("5GY %1.2f %1.2f %1.2f\n",_5GY50[44],_5GY50[84],_5GY50[125] ); + _5GY60(maxInd); + _5GY60.clear(); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5GY60[i] = 2.11 - 0.0015 * (i - 5); + } else if (i < 85 && i >= 45) { + _5GY60[i] = 2.05 - 0.002 * (i - 45); + } else if (i < 140 && i >= 85) { + _5GY60[i] = 1.97 - 0.00275 * (i - 85); + } + } + + //printf("5GY %1.2f %1.2f %1.2f\n",_5GY60[44],_5GY60[84],_5GY60[125] ); + _5GY70(maxInd); + _5GY70.clear(); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5GY70[i] = 2.09 - 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _5GY70[i] = 2.05 - 0.00175 * (i - 45); + } else if (i < 140 && i >= 85) { + _5GY70[i] = 1.98 - 0.002 * (i - 85); + } + } + + //printf("5GY %1.2f %1.2f %1.2f\n",_5GY70[44],_5GY70[84],_5GY70[125] ); + _5GY80(maxInd); + _5GY80.clear(); + + for (int i = 0; i < maxInd; i++) { + if (i < 45 && i > 5) { + _5GY80[i] = 2.07 - 0.001 * (i - 5); + } else if (i < 85 && i >= 45) { + _5GY80[i] = 2.03 - 0.00075 * (i - 45); + } else if (i < 140 && i >= 85) { + _5GY80[i] = 2.0 - 0.002 * (i - 85); + } + } + + //printf("5GY %1.2f %1.2f %1.2f\n",_5GY80[44],_5GY80[84],_5GY80[125] ); + +#ifdef _DEBUG + t2e.set(); + + if (settings->verbose) { + printf("Lutf Munsell %d usec\n", t2e.etime(t1e)); + } + +#endif +} + } diff --git a/rtengine/color.h b/rtengine/color.h index 5ccd4e9fe..9601ec3f6 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -28,1281 +28,1463 @@ #include "sleef.c" #define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c) -namespace rtengine { +namespace rtengine +{ #ifdef _DEBUG -class MunsellDebugInfo { +class MunsellDebugInfo +{ public: - float maxdhuelum[4]; - float maxdhue[4]; - unsigned int depass; - unsigned int depassLum; + float maxdhuelum[4]; + float maxdhue[4]; + unsigned int depass; + unsigned int depassLum; - MunsellDebugInfo(); - void reinitValues(); + MunsellDebugInfo(); + void reinitValues(); }; #endif -class Color { +class Color +{ private: - // Jacques' 195 LUTf for Munsell Lch correction - static LUTf _4P10,_4P20,_4P30,_4P40,_4P50,_4P60; - static LUTf _1P10,_1P20,_1P30,_1P40,_1P50,_1P60; - static LUTf _5B40,_5B50,_5B60, _5B70,_5B80; - static LUTf _7B40,_7B50,_7B60, _7B70,_7B80; - static LUTf _9B40,_9B50,_9B60, _9B70,_9B80; - static LUTf _10B40,_10B50,_10B60, _10B70,_10B80; - static LUTf _05PB40,_05PB50,_05PB60, _05PB70,_05PB80; - static LUTf _10PB10,_10PB20,_10PB30,_10PB40,_10PB50,_10PB60; - static LUTf _9PB10,_9PB20,_9PB30,_9PB40,_9PB50,_9PB60,_9PB70,_9PB80; - static LUTf _75PB10,_75PB20,_75PB30,_75PB40,_75PB50,_75PB60,_75PB70,_75PB80; - static LUTf _6PB10,_6PB20,_6PB30,_6PB40,_6PB50,_6PB60,_6PB70,_6PB80; - static LUTf _45PB10,_45PB20,_45PB30,_45PB40,_45PB50,_45PB60,_45PB70,_45PB80; - static LUTf _3PB10,_3PB20,_3PB30,_3PB40,_3PB50,_3PB60,_3PB70,_3PB80; - static LUTf _15PB10,_15PB20,_15PB30,_15PB40,_15PB50,_15PB60, _15PB70,_15PB80; - static LUTf _10YR20, _10YR30, _10YR40,_10YR50,_10YR60,_10YR70,_10YR80,_10YR90; - static LUTf _85YR20, _85YR30, _85YR40,_85YR50,_85YR60,_85YR70,_85YR80,_85YR90; - static LUTf _7YR30, _7YR40,_7YR50,_7YR60,_7YR70,_7YR80; - static LUTf _55YR30, _55YR40,_55YR50,_55YR60,_55YR70,_55YR80,_55YR90; - static LUTf _4YR30, _4YR40,_4YR50,_4YR60,_4YR70,_4YR80; - static LUTf _25YR30, _25YR40,_25YR50,_25YR60,_25YR70; - static LUTf _10R30, _10R40,_10R50,_10R60,_10R70; - static LUTf _9R30, _9R40,_9R50,_9R60,_9R70; - static LUTf _7R30, _7R40,_7R50,_7R60,_7R70; - static LUTf _5R10, _5R20,_5R30; - static LUTf _25R10, _25R20,_25R30; - static LUTf _10RP10, _10RP20,_10RP30; - static LUTf _7G30, _7G40,_7G50,_7G60,_7G70,_7G80; - static LUTf _5G30, _5G40,_5G50,_5G60,_5G70,_5G80; - static LUTf _25G30, _25G40,_25G50,_25G60,_25G70,_25G80; - static LUTf _1G30, _1G40,_1G50,_1G60,_1G70,_1G80; - static LUTf _10GY30, _10GY40,_10GY50,_10GY60,_10GY70,_10GY80; - static LUTf _75GY30, _75GY40,_75GY50,_75GY60,_75GY70,_75GY80; - static LUTf _5GY30, _5GY40,_5GY50,_5GY60,_5GY70,_5GY80; + // Jacques' 195 LUTf for Munsell Lch correction + static LUTf _4P10, _4P20, _4P30, _4P40, _4P50, _4P60; + static LUTf _1P10, _1P20, _1P30, _1P40, _1P50, _1P60; + static LUTf _5B40, _5B50, _5B60, _5B70, _5B80; + static LUTf _7B40, _7B50, _7B60, _7B70, _7B80; + static LUTf _9B40, _9B50, _9B60, _9B70, _9B80; + static LUTf _10B40, _10B50, _10B60, _10B70, _10B80; + static LUTf _05PB40, _05PB50, _05PB60, _05PB70, _05PB80; + static LUTf _10PB10, _10PB20, _10PB30, _10PB40, _10PB50, _10PB60; + static LUTf _9PB10, _9PB20, _9PB30, _9PB40, _9PB50, _9PB60, _9PB70, _9PB80; + static LUTf _75PB10, _75PB20, _75PB30, _75PB40, _75PB50, _75PB60, _75PB70, _75PB80; + static LUTf _6PB10, _6PB20, _6PB30, _6PB40, _6PB50, _6PB60, _6PB70, _6PB80; + static LUTf _45PB10, _45PB20, _45PB30, _45PB40, _45PB50, _45PB60, _45PB70, _45PB80; + static LUTf _3PB10, _3PB20, _3PB30, _3PB40, _3PB50, _3PB60, _3PB70, _3PB80; + static LUTf _15PB10, _15PB20, _15PB30, _15PB40, _15PB50, _15PB60, _15PB70, _15PB80; + static LUTf _10YR20, _10YR30, _10YR40, _10YR50, _10YR60, _10YR70, _10YR80, _10YR90; + static LUTf _85YR20, _85YR30, _85YR40, _85YR50, _85YR60, _85YR70, _85YR80, _85YR90; + static LUTf _7YR30, _7YR40, _7YR50, _7YR60, _7YR70, _7YR80; + static LUTf _55YR30, _55YR40, _55YR50, _55YR60, _55YR70, _55YR80, _55YR90; + static LUTf _4YR30, _4YR40, _4YR50, _4YR60, _4YR70, _4YR80; + static LUTf _25YR30, _25YR40, _25YR50, _25YR60, _25YR70; + static LUTf _10R30, _10R40, _10R50, _10R60, _10R70; + static LUTf _9R30, _9R40, _9R50, _9R60, _9R70; + static LUTf _7R30, _7R40, _7R50, _7R60, _7R70; + static LUTf _5R10, _5R20, _5R30; + static LUTf _25R10, _25R20, _25R30; + static LUTf _10RP10, _10RP20, _10RP30; + static LUTf _7G30, _7G40, _7G50, _7G60, _7G70, _7G80; + static LUTf _5G30, _5G40, _5G50, _5G60, _5G70, _5G80; + static LUTf _25G30, _25G40, _25G50, _25G60, _25G70, _25G80; + static LUTf _1G30, _1G40, _1G50, _1G60, _1G70, _1G80; + static LUTf _10GY30, _10GY40, _10GY50, _10GY60, _10GY70, _10GY80; + static LUTf _75GY30, _75GY40, _75GY50, _75GY60, _75GY70, _75GY80; + static LUTf _5GY30, _5GY40, _5GY50, _5GY60, _5GY70, _5GY80; - // Separated from init() to keep the code clear - static void initMunsell (); - static double hue2rgb(double p, double q, double t); + // Separated from init() to keep the code clear + static void initMunsell (); + static double hue2rgb(double p, double q, double t); public: - typedef enum Channel { - CHANNEL_RED = 1<<0, - CHANNEL_GREEN = 1<<1, - CHANNEL_BLUE = 1<<2, - CHANNEL_HUE = 1<<3, - CHANNEL_SATURATION = 1<<4, - CHANNEL_VALUE = 1<<5, - CHANNEL_LIGHTNESS = 1<<6, - CHANNEL_CHROMATICITY = 1<<7 - } eChannel; + typedef enum Channel { + CHANNEL_RED = 1 << 0, + CHANNEL_GREEN = 1 << 1, + CHANNEL_BLUE = 1 << 2, + CHANNEL_HUE = 1 << 3, + CHANNEL_SATURATION = 1 << 4, + CHANNEL_VALUE = 1 << 5, + CHANNEL_LIGHTNESS = 1 << 6, + CHANNEL_CHROMATICITY = 1 << 7 + } eChannel; - typedef enum InterpolationPath { - IP_SHORTEST, /// Interpolate color using the shortest path between 2 hues - IP_LONGEST, /// Interpolate color using the longest path between 2 hues - } eInterpolationPath; + typedef enum InterpolationPath { + IP_SHORTEST, /// Interpolate color using the shortest path between 2 hues + IP_LONGEST, /// Interpolate color using the longest path between 2 hues + } eInterpolationPath; - typedef enum InterpolationDirection { - ID_UP, /// Interpolate color by increasing the hue value, crossing the upper limit - ID_DOWN /// Interpolate color by decreasing the hue value, crossing the lower limit - } eInterpolationDirection; + typedef enum InterpolationDirection { + ID_UP, /// Interpolate color by increasing the hue value, crossing the upper limit + ID_DOWN /// Interpolate color by decreasing the hue value, crossing the lower limit + } eInterpolationDirection; - const static double sRGBGamma; // standard average gamma - const static double sRGBGammaCurve; // 2.4 in the curve - const static double eps, eps_max, kappa, epskap; - const static float D50x, D50z; - const static double u0, v0; + const static double sRGBGamma; // standard average gamma + const static double sRGBGammaCurve; // 2.4 in the curve + const static double eps, eps_max, kappa, epskap; + const static float D50x, D50z; + const static double u0, v0; - static cmsToneCurve* linearGammaTRC; + static cmsToneCurve* linearGammaTRC; - static LUTf cachef; - static LUTf gamma2curve; + static LUTf cachef; + static LUTf gamma2curve; - // 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; - static LUTf gammatab_4; - - static LUTf igammatab_26_11; - static LUTf gammatab_26_11; - static LUTf igammatab_24_17; - static LUTf gammatab_24_17a; - static LUTf gammatab_13_2; - - // look-up tables for the simple exponential gamma - static LUTf gammatab; + // 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; + static LUTf gammatab_4; + + static LUTf igammatab_26_11; + static LUTf gammatab_26_11; + static LUTf igammatab_24_17; + static LUTf gammatab_24_17a; + static LUTf gammatab_13_2; + + // look-up tables for the simple exponential gamma + static LUTf gammatab; - static void init (); - static void cleanup (); + static void init (); + static void cleanup (); - /** - * @brief Extract luminance "sRGB" from red/green/blue values - * The range of the r, g and b channel has no importance ([0 ; 1] or [0 ; 65535]...) ; r,g,b can be negatives or > max, but must be in "sRGB" - * @param r red channel - * @param g green channel - * @param b blue channel - * @return luminance value - */ - // xyz_sRGBD65 : conversion matrix from XYZ to sRGB for D65 illuminant: we use diagonal values - static float rgbLuminance(float r, float g, float b) { - // WArning: The sum of xyz_sRGBd65[1][] is > 1.0 (i.e. 1.0000001), so we use our own adapted values) - // 0.2126729, 0.7151521, 0.0721750 - return r*0.2126729f + g*0.7151521f + b*0.0721750f; - } - static double rgbLuminance(double r, double g, double b) { - return r*0.2126729 + g*0.7151521 + b*0.0721750; - } + /** + * @brief Extract luminance "sRGB" from red/green/blue values + * The range of the r, g and b channel has no importance ([0 ; 1] or [0 ; 65535]...) ; r,g,b can be negatives or > max, but must be in "sRGB" + * @param r red channel + * @param g green channel + * @param b blue channel + * @return luminance value + */ + // xyz_sRGBD65 : conversion matrix from XYZ to sRGB for D65 illuminant: we use diagonal values + static float rgbLuminance(float r, float g, float b) + { + // WArning: The sum of xyz_sRGBd65[1][] is > 1.0 (i.e. 1.0000001), so we use our own adapted values) + // 0.2126729, 0.7151521, 0.0721750 + return r * 0.2126729f + g * 0.7151521f + b * 0.0721750f; + } + static double rgbLuminance(double r, double g, double b) + { + return r * 0.2126729 + g * 0.7151521 + b * 0.0721750; + } - /** - * @brief Convert red/green/blue to hue/saturation/luminance - * @param r red channel [0 ; 65535] - * @param g green channel [0 ; 65535] - * @param b blue channel [0 ; 65535] - * @param h hue channel [0 ; 1] (return value) - * @param s saturation channel [0 ; 1] (return value) - * @param l luminance channel [0; 1] (return value) - */ - static void rgb2hsl (float r, float g, float b, float &h, float &s, float &l); - - - /** - * @brief Convert hue/saturation/luminance in red/green/blue - * @param h hue channel [0 ; 1] - * @param s saturation channel [0 ; 1] - * @param l luminance channel [0 ; 1] - * @param r red channel [0 ; 65535] (return value) - * @param g green channel [0 ; 65535] (return value) - * @param b blue channel [0 ; 65535] (return value) - */ - static void hsl2rgb (float h, float s, float l, float &r, float &g, float &b); - - /** - * @brief Convert hue/saturation/luminance in red/green/blue - * @param h hue channel [0 ; 1] - * @param s saturation channel [0 ; 1] - * @param l luminance channel [0 ; 1] - * @param r red channel [0 ; 1] (return value) - * @param g green channel [0 ; 1] (return value) - * @param b blue channel [0 ; 1] (return value) - */ - static void hsl2rgb01 (float h, float s, float l, float &r, float &g, float &b); - - - /** - * @brief Convert red green blue to hue saturation value - * @param r red channel [0 ; 65535] - * @param g green channel [0 ; 65535] - * @param b blue channel [0 ; 65535] - * @param h hue channel [0 ; 1] (return value) - * @param s saturation channel [0 ; 1] (return value) - * @param v value channel [0 ; 1] (return value) - */ - static void rgb2hsv (float r, float g, float b, float &h, float &s, float &v); - - - /** - * @brief Convert hue saturation value in red green blue - * @param h hue channel [0 ; 1] - * @param s saturation channel [0 ; 1] - * @param v value channel [0 ; 1] - * @param r red channel [0 ; 65535] (return value) - * @param g green channel [0 ; 65535] (return value) - * @param b blue channel [0 ; 65535] (return value) - */ - static void hsv2rgb (float h, float s, float v, float &r, float &g, float &b); - static void hsv2rgb (float h, float s, float v, int &r, int &g, int &b); - - - /** - * @brief Convert hue saturation value in red green blue - * @param h hue channel [0 ; 1] - * @param s saturation channel [0 ; 1] - * @param v value channel [0 ; 1] - * @param r red channel [0 ; 1] (return value) - * @param g green channel [0 ; 1] (return value) - * @param b blue channel [0 ; 1] (return value) - */ - static void hsv2rgb01 (float h, float s, float v, float &r, float &g, float &b); - - - /** - * @brief Convert xyz to red/green/blue - * Color space : sRGB - illuminant D50 - use matrix sRGB_xyz[] - * @param x X coordinate [0 ; 1] or [0 ; 65535] - * @param y Y coordinate [0 ; 1] or [0 ; 65535] - * @param z Z coordinate [0 ; 1] or [0 ; 65535] - * @param r red channel [same range than xyz channel] (return value) - * @param g green channel [same range than xyz channel] (return value) - * @param b blue channel [same range than xyz channel] (return value) - */ - static void xyz2srgb (float x, float y, float z, float &r, float &g, float &b); - - - /** - * @brief Convert xyz to red/green/blue - * Color space : Prophoto - illuminant D50 - use the Prophoto_xyz[] matrix - * @param x X coordinate [0 ; 1] or [0 ; 65535] - * @param y Y coordinate [0 ; 1] or [0 ; 65535] - * @param z Z coordinate [0 ; 1] or [0 ; 65535] - * @param r red channel [same range than xyz channel] (return value) - * @param g green channel [same range than xyz channel] (return value) - * @param b blue channel [same range than xyz channel] (return value) - */ - static void xyz2Prophoto (float x, float y, float z, float &r, float &g, float &b); - - - /** - * @brief Convert rgb in xyz - * Color space : Prophoto - illuminant D50 - use matrix xyz_prophoto[] - * @param r red channel [0 ; 1] or [0 ; 65535] (return value) - * @param g green channel [0 ; 1] or [0 ; 65535] (return value) - * @param b blue channel [0 ; 1] or [0 ; 65535] (return value) - * @param x X coordinate [same range than xyz channel] - * @param y Y coordinate [same range than xyz channel] - * @param z Z coordinate [same range than xyz channel] - */ - static void Prophotoxyz (float r, float g, float b, float &x, float &y, float &z); - - - /** - * @brief Convert xyz in rgb - * Color space : undefined - use adhoc matrix: rgb_xyz[3][3] (iccmatrice.h) in function of working space - * @param x X coordinate [0 ; 1] or [0 ; 65535] - * @param y Y coordinate [0 ; 1] or [0 ; 65535] - * @param z Z coordinate [0 ; 1] or [0 ; 65535] - * @param r red channel [same range than xyz channel] (return value) - * @param g green channel [same range than xyz channel] (return value) - * @param b blue channel [same range than xyz channel] (return value) - * @param rgb_xyz[3][3] transformation matrix to use for the conversion - */ - static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]); - static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3]); - - - /** - * @brief Convert rgb in xyz - * Color space : undefined - use adhoc matrix : xyz_rgb[3][3] (iccmatrice.h) in function of working space - * @param r red channel [0 ; 1] or [0 ; 65535] - * @param g green channel [0 ; 1] or [0 ; 65535] - * @param b blue channel [0 ; 1] or [0 ; 65535] - * @param x X coordinate [same range than rgb channel] (return value) - * @param y Y coordinate [same range than rgb channel] (return value) - * @param z Z coordinate [same range than rgb channel] (return value) - * @param xyz_rgb[3][3] transformation matrix to use for the conversion - */ - static void rgbxyz (float r, float g, float b, float &x, float &y, float &z, const double xyz_rgb[3][3]); - static void rgbxyz (float r, float g, float b, float &x, float &y, float &z, const float xyz_rgb[3][3]); + /** + * @brief Convert red/green/blue to hue/saturation/luminance + * @param r red channel [0 ; 65535] + * @param g green channel [0 ; 65535] + * @param b blue channel [0 ; 65535] + * @param h hue channel [0 ; 1] (return value) + * @param s saturation channel [0 ; 1] (return value) + * @param l luminance channel [0; 1] (return value) + */ + static void rgb2hsl (float r, float g, float b, float &h, float &s, float &l); - /** - * @brief Convert Lab in xyz - * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 - * @param a channel [-42000 ; +42000] ; can be more than 42000 - * @param b channel [-42000 ; +42000] ; can be more than 42000 - * @param x X coordinate [0 ; 65535] ; can be negative! (return value) - * @param y Y coordinate [0 ; 65535] ; can be negative! (return value) - * @param z Z coordinate [0 ; 65535] ; can be negative! (return value) - */ - static void Lab2XYZ(float L, float a, float b, float &x, float &y, float &z); + /** + * @brief Convert hue/saturation/luminance in red/green/blue + * @param h hue channel [0 ; 1] + * @param s saturation channel [0 ; 1] + * @param l luminance channel [0 ; 1] + * @param r red channel [0 ; 65535] (return value) + * @param g green channel [0 ; 65535] (return value) + * @param b blue channel [0 ; 65535] (return value) + */ + static void hsl2rgb (float h, float s, float l, float &r, float &g, float &b); + + /** + * @brief Convert hue/saturation/luminance in red/green/blue + * @param h hue channel [0 ; 1] + * @param s saturation channel [0 ; 1] + * @param l luminance channel [0 ; 1] + * @param r red channel [0 ; 1] (return value) + * @param g green channel [0 ; 1] (return value) + * @param b blue channel [0 ; 1] (return value) + */ + static void hsl2rgb01 (float h, float s, float l, float &r, float &g, float &b); + + + /** + * @brief Convert red green blue to hue saturation value + * @param r red channel [0 ; 65535] + * @param g green channel [0 ; 65535] + * @param b blue channel [0 ; 65535] + * @param h hue channel [0 ; 1] (return value) + * @param s saturation channel [0 ; 1] (return value) + * @param v value channel [0 ; 1] (return value) + */ + static void rgb2hsv (float r, float g, float b, float &h, float &s, float &v); + + + /** + * @brief Convert hue saturation value in red green blue + * @param h hue channel [0 ; 1] + * @param s saturation channel [0 ; 1] + * @param v value channel [0 ; 1] + * @param r red channel [0 ; 65535] (return value) + * @param g green channel [0 ; 65535] (return value) + * @param b blue channel [0 ; 65535] (return value) + */ + static void hsv2rgb (float h, float s, float v, float &r, float &g, float &b); + static void hsv2rgb (float h, float s, float v, int &r, int &g, int &b); + + + /** + * @brief Convert hue saturation value in red green blue + * @param h hue channel [0 ; 1] + * @param s saturation channel [0 ; 1] + * @param v value channel [0 ; 1] + * @param r red channel [0 ; 1] (return value) + * @param g green channel [0 ; 1] (return value) + * @param b blue channel [0 ; 1] (return value) + */ + static void hsv2rgb01 (float h, float s, float v, float &r, float &g, float &b); + + + /** + * @brief Convert xyz to red/green/blue + * Color space : sRGB - illuminant D50 - use matrix sRGB_xyz[] + * @param x X coordinate [0 ; 1] or [0 ; 65535] + * @param y Y coordinate [0 ; 1] or [0 ; 65535] + * @param z Z coordinate [0 ; 1] or [0 ; 65535] + * @param r red channel [same range than xyz channel] (return value) + * @param g green channel [same range than xyz channel] (return value) + * @param b blue channel [same range than xyz channel] (return value) + */ + static void xyz2srgb (float x, float y, float z, float &r, float &g, float &b); + + + /** + * @brief Convert xyz to red/green/blue + * Color space : Prophoto - illuminant D50 - use the Prophoto_xyz[] matrix + * @param x X coordinate [0 ; 1] or [0 ; 65535] + * @param y Y coordinate [0 ; 1] or [0 ; 65535] + * @param z Z coordinate [0 ; 1] or [0 ; 65535] + * @param r red channel [same range than xyz channel] (return value) + * @param g green channel [same range than xyz channel] (return value) + * @param b blue channel [same range than xyz channel] (return value) + */ + static void xyz2Prophoto (float x, float y, float z, float &r, float &g, float &b); + + + /** + * @brief Convert rgb in xyz + * Color space : Prophoto - illuminant D50 - use matrix xyz_prophoto[] + * @param r red channel [0 ; 1] or [0 ; 65535] (return value) + * @param g green channel [0 ; 1] or [0 ; 65535] (return value) + * @param b blue channel [0 ; 1] or [0 ; 65535] (return value) + * @param x X coordinate [same range than xyz channel] + * @param y Y coordinate [same range than xyz channel] + * @param z Z coordinate [same range than xyz channel] + */ + static void Prophotoxyz (float r, float g, float b, float &x, float &y, float &z); + + + /** + * @brief Convert xyz in rgb + * Color space : undefined - use adhoc matrix: rgb_xyz[3][3] (iccmatrice.h) in function of working space + * @param x X coordinate [0 ; 1] or [0 ; 65535] + * @param y Y coordinate [0 ; 1] or [0 ; 65535] + * @param z Z coordinate [0 ; 1] or [0 ; 65535] + * @param r red channel [same range than xyz channel] (return value) + * @param g green channel [same range than xyz channel] (return value) + * @param b blue channel [same range than xyz channel] (return value) + * @param rgb_xyz[3][3] transformation matrix to use for the conversion + */ + static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const double rgb_xyz[3][3]); + static void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, const float rgb_xyz[3][3]); + + + /** + * @brief Convert rgb in xyz + * Color space : undefined - use adhoc matrix : xyz_rgb[3][3] (iccmatrice.h) in function of working space + * @param r red channel [0 ; 1] or [0 ; 65535] + * @param g green channel [0 ; 1] or [0 ; 65535] + * @param b blue channel [0 ; 1] or [0 ; 65535] + * @param x X coordinate [same range than rgb channel] (return value) + * @param y Y coordinate [same range than rgb channel] (return value) + * @param z Z coordinate [same range than rgb channel] (return value) + * @param xyz_rgb[3][3] transformation matrix to use for the conversion + */ + static void rgbxyz (float r, float g, float b, float &x, float &y, float &z, const double xyz_rgb[3][3]); + static void rgbxyz (float r, float g, float b, float &x, float &y, float &z, const float xyz_rgb[3][3]); + + + /** + * @brief Convert Lab in xyz + * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 + * @param a channel [-42000 ; +42000] ; can be more than 42000 + * @param b channel [-42000 ; +42000] ; can be more than 42000 + * @param x X coordinate [0 ; 65535] ; can be negative! (return value) + * @param y Y coordinate [0 ; 65535] ; can be negative! (return value) + * @param z Z coordinate [0 ; 65535] ; can be negative! (return value) + */ + static void Lab2XYZ(float L, float a, float b, float &x, float &y, float &z); #ifdef __SSE2__ static void Lab2XYZ(vfloat L, vfloat a, vfloat b, vfloat &x, vfloat &y, vfloat &z); #endif // __SSE2__ - /** - * @brief Convert xyz in Lab - * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 (return value) - * @param a channel [-42000 ; +42000] ; can be more than 42000 (return value) - * @param b channel [-42000 ; +42000] ; can be more than 42000 (return value) - */ - static void XYZ2Lab(float x, float y, float z, float &L, float &a, float &b); + /** + * @brief Convert xyz in Lab + * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 (return value) + * @param a channel [-42000 ; +42000] ; can be more than 42000 (return value) + * @param b channel [-42000 ; +42000] ; can be more than 42000 (return value) + */ + static void XYZ2Lab(float x, float y, float z, float &L, float &a, float &b); - /** - * @brief Convert Lab in Yuv - * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 - * @param a channel [-42000 ; +42000] ; can be more than 42000 - * @param b channel [-42000 ; +42000] ; can be more than 42000 - * @param Y luminance channel [0 ; 65535] (return value) - * @param u red chrominance channel [0 ; 65535] (return value) - * @param v blue chrominance channel [0 ; 65535] (return value) - */ - static void Lab2Yuv(float L, float a, float b, float &Y, float &u, float &v); + /** + * @brief Convert Lab in Yuv + * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 + * @param a channel [-42000 ; +42000] ; can be more than 42000 + * @param b channel [-42000 ; +42000] ; can be more than 42000 + * @param Y luminance channel [0 ; 65535] (return value) + * @param u red chrominance channel [0 ; 65535] (return value) + * @param v blue chrominance channel [0 ; 65535] (return value) + */ + static void Lab2Yuv(float L, float a, float b, float &Y, float &u, float &v); - /** - * @brief Convert Yuv in Lab - * @param Y luminance channel [0 ; 65535] - * @param u red chrominance channel [0 ; 65535] - * @param v blue chrominance channel [0 ; 65535] - * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 (return value) - * @param a channel [-42000 ; +42000] ; can be more than 42000 (return value) - * @param b channel [-42000 ; +42000] ; can be more than 42000 (return value) - */ - static void Yuv2Lab(float Y, float u, float v, float &L, float &a, float &b, double wp[3][3]); + /** + * @brief Convert Yuv in Lab + * @param Y luminance channel [0 ; 65535] + * @param u red chrominance channel [0 ; 65535] + * @param v blue chrominance channel [0 ; 65535] + * @param L L channel [0 ; 32768] ; L can be negative rarely or superior 32768 (return value) + * @param a channel [-42000 ; +42000] ; can be more than 42000 (return value) + * @param b channel [-42000 ; +42000] ; can be more than 42000 (return value) + */ + static void Yuv2Lab(float Y, float u, float v, float &L, float &a, float &b, double wp[3][3]); - /** - * @brief Convert the 'a' and 'b' channels of the L*a*b color space to 'c' and 'h' channels of the Lch color space (channel 'L' is identical [0 ; 32768]) - * @param a 'a' channel [-42000 ; +42000] ; can be more than 42000 - * @param b 'b' channel [-42000 ; +42000] ; can be more than 42000 - * @param c 'c' channel return value, in [0 ; 42000] ; can be more than 42000 (return value) - * @param h 'h' channel return value, in [-PI ; +PI] (return value) - */ - static void Lab2Lch(float a, float b, float &c, float &h); + /** + * @brief Convert the 'a' and 'b' channels of the L*a*b color space to 'c' and 'h' channels of the Lch color space (channel 'L' is identical [0 ; 32768]) + * @param a 'a' channel [-42000 ; +42000] ; can be more than 42000 + * @param b 'b' channel [-42000 ; +42000] ; can be more than 42000 + * @param c 'c' channel return value, in [0 ; 42000] ; can be more than 42000 (return value) + * @param h 'h' channel return value, in [-PI ; +PI] (return value) + */ + static void Lab2Lch(float a, float b, float &c, float &h); - /** - * @brief Convert 'c' and 'h' channels of the Lch color space to the 'a' and 'b' channels of the L*a*b color space (channel 'L' is identical [0 ; 32768]) - * @param c 'c' channel value, in [0 ; 42000] - * @param h 'h' channel value, in [-PI ; +PI] - * @param a 'a' channel [-42000 ; +42000] ; can be more than 42000 (return value) - * @param b 'b' channel [-42000 ; +42000] ; can be more than 42000 (return value) - */ - static void Lch2Lab(float c, float h, float &a, float &b); + /** + * @brief Convert 'c' and 'h' channels of the Lch color space to the 'a' and 'b' channels of the L*a*b color space (channel 'L' is identical [0 ; 32768]) + * @param c 'c' channel value, in [0 ; 42000] + * @param h 'h' channel value, in [-PI ; +PI] + * @param a 'a' channel [-42000 ; +42000] ; can be more than 42000 (return value) + * @param b 'b' channel [-42000 ; +42000] ; can be more than 42000 (return value) + */ + static void Lch2Lab(float c, float h, float &a, float &b); - /** - * @brief Convert the 'u' and 'v' channels of the Luv color space to 'c' and 'h' channels of the Lch color space ('L' channel is identical) - * @param u 'u' channel [unknown range!] - * @param v 'v' channel [unknown range!] - * @param c 'c' channel [unknown range!] (return value) - * @param h 'h' channel [-PI ; +PI] (return value) - */ - static void Luv2Lch(float u, float v, float &c, float &h); + /** + * @brief Convert the 'u' and 'v' channels of the Luv color space to 'c' and 'h' channels of the Lch color space ('L' channel is identical) + * @param u 'u' channel [unknown range!] + * @param v 'v' channel [unknown range!] + * @param c 'c' channel [unknown range!] (return value) + * @param h 'h' channel [-PI ; +PI] (return value) + */ + static void Luv2Lch(float u, float v, float &c, float &h); - /** - * @brief Convert 'c' and 'h' channels of the Lch color space to the 'u' and 'v' channels of the Luv color space ('L' channel is identical) - * @param c 'c' channel [unknown range!] ; can be more than 42000 - * @param h 'h' channel [-PI ; +PI] - * @param u 'u' channel [unknown range!] (return value) - * @param v 'v' channel [unknown range!] (return value) - */ - static void Lch2Luv(float c, float h, float &u, float &v); + /** + * @brief Convert 'c' and 'h' channels of the Lch color space to the 'u' and 'v' channels of the Luv color space ('L' channel is identical) + * @param c 'c' channel [unknown range!] ; can be more than 42000 + * @param h 'h' channel [-PI ; +PI] + * @param u 'u' channel [unknown range!] (return value) + * @param v 'v' channel [unknown range!] (return value) + */ + static void Lch2Luv(float c, float h, float &u, float &v); - /** - * @brief Convert the XYZ values to Luv values - * Warning: this method has never been used/tested so far - * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 - * @param L 'L' channel [0 ; 32768] (return value) - * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 (return value) - * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 (return value) - */ - static void XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v); + /** + * @brief Convert the XYZ values to Luv values + * Warning: this method has never been used/tested so far + * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 + * @param L 'L' channel [0 ; 32768] (return value) + * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 (return value) + * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 (return value) + */ + static void XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v); - /** - * @brief Convert the Luv values to XYZ values - * Warning: this method has never been used/tested so far - * @param L 'L' channel [0 ; 32768] - * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 - * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 - * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) - * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) - * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) - */ - static void Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z); + /** + * @brief Convert the Luv values to XYZ values + * Warning: this method has never been used/tested so far + * @param L 'L' channel [0 ; 32768] + * @param u 'u' channel [-42000 ; 42000] ; can be more than 42000 + * @param v 'v' channel [-42000 ; 42000] ; can be more than 42000 + * @param x X coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) + * @param y Y coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) + * @param z Z coordinate [0 ; 65535] ; can be negative or superior to 65535 (return value) + */ + static void Luv2XYZ (float L, float u, float v, float &X, float &Y, float &Z); - /** - * @brief Return "f" in function of CIE's kappa and epsilon constants - * @param f f can be fx fy fz where: - * fx=a/500 + fy a=chroma green red [-128 ; +128] - * fy=(L+16)/116 L=luminance [0 ; 100] - * fz=fy-b/200 b=chroma blue yellow [-128 ; +128] - */ - static inline double f2xyz(double f) { - const double epsilonExpInv3 = 6.0/29.0; - const double kappaInv = 27.0/24389.0; // inverse of kappa + /** + * @brief Return "f" in function of CIE's kappa and epsilon constants + * @param f f can be fx fy fz where: + * fx=a/500 + fy a=chroma green red [-128 ; +128] + * fy=(L+16)/116 L=luminance [0 ; 100] + * fz=fy-b/200 b=chroma blue yellow [-128 ; +128] + */ + static inline double f2xyz(double f) + { + const double epsilonExpInv3 = 6.0 / 29.0; + const double kappaInv = 27.0 / 24389.0; // inverse of kappa - return (f > epsilonExpInv3) ? f*f*f : (116. * f - 16.) * kappaInv; + return (f > epsilonExpInv3) ? f * f * f : (116. * f - 16.) * kappaInv; - } - static inline float f2xyz(float f) { - const float epsilonExpInv3 = 0.20689655f; // 6.0f/29.0f; - const float kappaInv = 0.0011070565f; // 27.0f/24389.0f; // inverse of kappa + } + static inline float f2xyz(float f) + { + const float epsilonExpInv3 = 0.20689655f; // 6.0f/29.0f; + const float kappaInv = 0.0011070565f; // 27.0f/24389.0f; // inverse of kappa - return (f > epsilonExpInv3) ? f*f*f : (116.f * f - 16.f) * kappaInv; - } + return (f > epsilonExpInv3) ? f * f * f : (116.f * f - 16.f) * kappaInv; + } #ifdef __SSE2__ - static inline vfloat f2xyz(vfloat f) { - const vfloat epsilonExpInv3 = F2V(0.20689655f); // 6.0f/29.0f; - const vfloat kappaInv = F2V(0.0011070565f); // 27.0f/24389.0f; // inverse of kappa - vfloat res1 = f*f*f; - vfloat res2 = (F2V(116.f) * f - F2V(16.f)) * kappaInv; - return vself(vmaskf_gt(f, epsilonExpInv3), res1, res2); - } + static inline vfloat f2xyz(vfloat f) + { + const vfloat epsilonExpInv3 = F2V(0.20689655f); // 6.0f/29.0f; + const vfloat kappaInv = F2V(0.0011070565f); // 27.0f/24389.0f; // inverse of kappa + vfloat res1 = f * f * f; + vfloat res2 = (F2V(116.f) * f - F2V(16.f)) * kappaInv; + return vself(vmaskf_gt(f, epsilonExpInv3), res1, res2); + } #endif - /** - * @brief Calculate the effective direction (up or down) to linearly interpolating 2 colors so that it follows the shortest or longest path - * @param h1 First hue [0 ; 1] - * @param h2 Second hue [0 ; 1] - * @param path Path to follow (shortest/longest) - * @return The interpolation direction - */ - static inline eInterpolationDirection getHueInterpolationDirection (double h1, double h2, eInterpolationPath path) { - if (path==IP_SHORTEST) { - if (h2>h1) { - if (h2-h1<=0.5) - return ID_UP; - else - return ID_DOWN; - } - else { - if (h1-h2<=0.5) - return ID_DOWN; - else - return ID_UP; - } - } - else { - if (h2>h1) { - if (h2-h1<=0.5) - return ID_DOWN; - else - return ID_UP; - } - else { - if (h1-h2<=0.5) - return ID_UP; - else - return ID_DOWN; - } - } - } - - - /** - * @brief Calculate a color by linearly interpolating 2 colors - * @param h1 First hue - * @param h2 Second hue - * @param balance Factor from 0 (first hue) to 1 (second hue) - * @param dir Tells which direction the interpolation have to follow. You can get the value with getHueInterpolationDirection - * @return The interpolated hue - */ - static inline double interpolateHueHSV (double h1, double h2, double balance, eInterpolationDirection dir) { - if (h1==h2) - return h1; - if (dir==ID_DOWN) { - if (h1 < h2){ - double temp = h1; - h1 = h2-1.; - h2 = temp; - balance = 1. - balance; - } - double h3 = h1 + balance * (h2-h1); - if (h3<0.) - h3 += 1.; - return h3; - } - else { - if (h1 > h2){ - h2 += 1.; - } - double h3 = h1 + balance * (h2-h1); - if (h3>1.) - h3 -= 1.; - return h3; - } - } - - /** - * @brief Interpolate 2 colors from their respective red/green/blue channels, with a balance factor - * @param balance gives weight to the first and second color [0 ; 1] - * 0. = output color == first color - * 0.5 = output color == equally mixed colors - * 1. = output color == second color - * @param r1 red channel of color 1 [0 ; 65535] - * @param g1 green channel of color 1 [0 ; 65535] - * @param b1 blue channel of color 1 [0 ; 65535] - * @param r2 red channel of color 2 [0 ; 65535] - * @param g2 green channel of color 2 [0 ; 65535] - * @param b2 blue channel of color 2 [0 ; 65535] - * @param channels bitfield of channel to interpolate (CHANNEL_LIGHTNESS|CHANNEL_CHROMATICITY|CHANNEL_HUE) - * @param xyz_rgb color space - * @param ro red channel of output color [0 ; 65535] (return value) - * @param go green channel of output color [0 ; 65535] (return value) - * @param bo blue channel of output color [0 ; 65535] (return value) - */ - static void interpolateRGBColor (const float balance, const float r1, const float g1, const float b1, const float r2, const float g2, const float b2, int channels, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo); - - /** - * @brief Interpolate 2 colors from their respective red/green/blue channels, with a balance factor - * @param realL luminance hsl [0; 1] - * @param iplow low luminance for rl [0;1] - * @param ihigh high luminance for r2 [0;1] - * @param algm algorithm [0;2] - * @param balance gives weight to the first and second color [0 ; 1] - * 0. = output color == first color - * 0.5 = output color == equally mixed colors - * 1. = output color == second color - * @param twoc 2 colors or 512 int - * @param r1 red channel of color 1 [0 ; 65535] - * @param g1 green channel of color 1 [0 ; 65535] - * @param b1 blue channel of color 1 [0 ; 65535] - * @param rl red channel of color low [0 ; 65535] - * @param gl green channel of color low [0 ; 65535] - * @param bl blue channel of color low [0 ; 65535] - - * @param r2 red channel of color 2 or high[0 ; 65535] - * @param g2 green channel of color 2 or high[0 ; 65535] - * @param b2 blue channel of color 2 [or high 0 ; 65535] - * @param channels bitfield of channel to interpolate (CHANNEL_LIGHTNESS|CHANNEL_CHROMATICITY|CHANNEL_HUE) - * @param xyz_rgb color space - * @param rgb_xyz inverse color space - * @param ro red channel of output color [0 ; 65535] (return value) - * @param go green channel of output color [0 ; 65535] (return value) - * @param bo blue channel of output color [0 ; 65535] (return value) - */ - static void interpolateRGBColor (float realL, float iplow, float iphigh, int algm, const float balance, int twoc, int metchrom, bool chr, bool lum, float chromat, float luma, const float r1, const float g1, const float b1, const float xl, const float yl, const float zl, const float x2, const float y2, const float z2, int channels, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo); - - - /** - * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [0;1] range - * Chose the shorter path from hue 1 to hue 2. - * @param h1 First hue [0; 1] - * @param h2 Second hue [0; 1] - * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 - * @return the interpolated value [0;1] - */ - /*template - static inline T interpolatePolarHue_01 (T h1, T h2, U balance) { - - if (h1==h2) - return h1; - if ((h1 > h2) && (h1-h2 > T(0.5))){ - h1 -= T(1.); - double value = h1 + T(balance) * (h2-h1); - if (value < T(0.)) - value += T(1.); - return value; - } - else if (h2-h1 > T(0.5)) { - h2 -= T(1.); - double value = h1 + T(balance) * (h2-h1); - if (value < T(0.)) - value += T(1.); - return value; - } - else - return h1 + T(balance) * (h2-h1); - }*/ - - - /** - * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [-PI ; +PI] range - * Chose the shorter path from hue 1 to hue 2. - * @param h1 First hue [-PI ; +PI] - * @param h2 Second hue [-PI ; +PI] - * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 - * @return the interpolated value [-PI ; +PI] - */ - /*template - static inline T interpolatePolarHue_PI (T h1, T h2, U balance) { - if (h1==h2) - return h1; - if ((h1 > h2) && (h1-h2 > T(M_PI))){ - h1 -= T(2*M_PI); - T value = h1 + T(balance) * (h2-h1); - if (value < T(-M_PI)) - value += T(2*M_PI); - return value; - } - else if (h2-h1 > T(M_PI)) { - h2 -= T(2*M_PI); - T value = h1 + T(balance) * (h2-h1); - if (value < T(0)) - value += T(2*M_PI); - return value; - } - else - return h1 + T(balance) * (h2-h1); - }*/ - - - /** - * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [0;1] range - * Chose the shorter path from hue 1 to hue 2. - * @param h1 First hue [0; 1] - * @param h2 Second hue [0; 1] - * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 - * @return the interpolated value [0;1] - */ - template - static inline T interpolatePolarHue_01 (T h1, T h2, U balance) { - float d = h2 - h1; - float f; - f=T(balance); - double h; - if (h1 > h2){ - std::swap(h1,h2); - d = -d; - f=1.f-f; - } - if (d < T(-M_PI) || d < T(0) || d > T(M_PI)) { //there was an inversion here !! d > T(M_PI) - h1 += T(2*M_PI); - h = h1 + f*(h2-h1); - h = std::fmod(h,2*M_PI); - } - else h = h1 + f * d; - // not strictly necessary..but in case of - if(h < T(-M_PI)) h=T(2*M_PI)-h; - if(h > T(M_PI)) h=h-T(2*M_PI); - - return h; - } - - - /** - * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [-PI ; +PI] range - * Chose the shorter path from hue 1 to hue 2. - * @param h1 First hue [-PI ; +PI] - * @param h2 Second hue [-PI ; +PI] - * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 - * @return the interpolated value [-PI ; +PI ] - */ - template - static inline T interpolatePolarHue_PI (T h1, T h2, U balance) { - float d = h2 - h1; - float f; - f=T(balance); - double h; - if (h1 > h2){ - std::swap(h1,h2); - d = -d; - f=1.f-f; - } - if (d < T(0) || d < T(0.5) || d > T(1.)) { //there was an inversion here !! d > T(M_PI) - h1 += T(1.); - h = h1 + f*(h2-h1); - h = std::fmod(h,1.); - } - else h = h1 + f * d; - // not strictly necessary..but in case of - if(h < T(0)) h=T(1.)-h; - if(h > T(1)) h=h-T(1.); - - return h; - } - - - /** - * @brief Get the gamma curves' parameters used by LCMS2 - * @param pwr gamma value [>1] - * @param ts slope [0 ; 20] - * @param mode [always 0] - * @imax imax [always 0] - * @param gamma0 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value) - * @param gamma1 used in ip2Lab2rgb [0 ; 20], can be superior to 20, but it's quite unusual(return value) - * @param gamma2 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value) - * @param gamma3 used in ip2Lab2rgb [0 ; 1], usually near 0.003(return value) - * @param gamma4 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value) - * @param gamma5 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value) - */ - static void calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4,double &gamma5); - - - /** - * @brief Used by Black and White to correct gamma for each channel red, green and blue channel - * @param r red channel input and output value [0 ; 65535] - * @param g green channel input and output value [0 ; 65535] - * @param b blue channel input and output value [0 ; 65535] - * @param gammabwr gamma value for red channel [>0] - * @param gammabwg gamma value for red channel [>0] - * @param gammabwb gamma value for red channel [>0] - */ - static void trcGammaBW (float &r, float &g, float &b, float gammabwr, float gammabwg, float gammabwb); - - - /** @brief Compute the B&W constants for the Black and White processing and its GUI - * @param setting main mode - * @param filter string of the filter effect to use - * @param algo choice between linear and special for OYCPM colors - * @param mixerRed red channel value of the channel mixer [-100 ; +200] - * @param mixerGreen green channel value of the channel mixer [-100 ; +200] - * @param mixerBlue blue channel value of the channel mixer [-100 ; +200] - * @param mixerOrange orange channel value of the channel mixer [-100 ; +200] - * @param mixerYellow yellow channel value of the channel mixer [-100 ; +200] - * @param mixerCyan cyan channel value of the channel mixer [-100 ; +200] - * @param mixerPurple purple channel value of the channel mixer [-100 ; +200] - * @param mixerMagenta magenta channel value of the channel mixer [-100 ; +200] - * @param autoc automatic mode of the channel mixer - * @param complement adjust complementary channel - * @param kcorec in absolute mode, value to correct the mixer [1 ; 3], usually near 1 (return value) - * @param rrm red channel of the mixer (return value) - * @param ggm green channel of the mixer (return value) - * @param bbm blue channel of the mixer (return value) - */ - static void computeBWMixerConstants (const Glib::ustring &setting, const Glib::ustring &filter, const Glib::ustring &algo, float &filcor, float &mixerRed, float &mixerGreen, - float &mixerBlue, float mixerOrange, float mixerYellow, float mixerCyan, float mixerPurple, float mixerMagenta, - bool autoc, bool complement, float &kcorec, double &rrm, double &ggm, double &bbm); - - - // standard srgb gamma and its inverse - - /** - * @brief sRGB gamma - * See also calcGamma above with the following values: pwr=2.4 ts=12.92 mode=0.003041 imax=0.055011 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamma2 (double x) { // g3 1+g4 - return x <= 0.003041 ? x*12.92 : 1.055011*exp(log(x)/sRGBGammaCurve)-0.055011; - } - - - /** - * @brief Inverse sRGB gamma - * See also calcGamma above with the following values: pwr=2.4 ts=12.92 mode=0.003041 imax=0.055011 - * @param x red, green or blue channel's value [0 ; 1] - * @return the inverse gamma modified's value [0 ; 1] - */ - static inline double igamma2 (double x) { //g2 - return x <= 0.039293 ? x/12.92 : exp(log((x+0.055011)/1.055011)*sRGBGammaCurve); - } - - - /** - * @brief Get the gamma value for Gamma=5.5 Slope=10 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamma55 (double x) { // g3 1+g4 - return x <= 0.013189 ? x*10.0 : 1.593503*exp(log(x)/5.5)-0.593503;// 5.5 10 - } - - - /** - * @brief Get the inverse gamma value for Gamma=5.5 Slope=10 - * @param x red, green or blue channel's value [0 ; 1] - * @return the inverse gamma modified's value [0 ; 1] - */ - static inline double igamma55 (double x) { //g2 - return x <= 0.131889 ? x/10.0 : exp(log((x+0.593503)/1.593503)*5.5); // 5.5 10 - } - - - /** - * @brief Get the gamma value for Gamma=4 Slope=5 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamma4 (double x) { // g3 1+g4 - return x <= 0.03089 ? x*5.0 : 1.478793*exp(log(x)/4.1)-0.478793;// 4 5 - } - - - /** - * @brief Get the inverse gamma value for Gamma=4 Slope=5 - * @param x red, green or blue channel's value [0 ; 1] - * @return the inverse gamma modified's value [0 ; 1] - */ - static inline double igamma4 (double x) { //g2 - return x <= 0.154449 ? x/5.0 : exp(log((x+0.478793)/1.478793)*4.1);// 4 5 - } - - - /* - * @brief Get the gamma value for Gamma=2.2 Slope=4.5 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - * - static inline double gamma709 (double x) { - return x <= 0.0176 ? x*4.5 : 1.0954*exp(log(x)/2.2)-0.0954; - } - - * @brief Get the inverse gamma value for Gamma=2.2 Slope=4.5 - * @param x red, green or blue channel's value [0 ; 1] - * @return the inverse gamma modified's value [0 ; 1] - * - static inline double igamma709 (double x) { - return x <= 0.0795 ? x/4.5 : exp(log((x+0.0954)/1.0954)*2.2); - } - */ - - - - /** - * @brief Get the gamma value for Gamma=2.4 Slope=17 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamma24_17 (double x) { - return x <= 0.001867 ? x*17.0 : 1.044445*exp(log(x)/2.4)-0.044445; - } - - - /** - * @brief Get the inverse gamma value for Gamma=2.4 Slope=17 - * @param x red, green or blue channel's value [0 ; 1] - * @return the inverse gamma modified's value [0 ; 1] - */ - static inline double igamma24_17 (double x) { - return x <= 0.031746 ? x/17.0 : exp(log((x+0.044445)/1.044445)*2.4); - } - - - /** - * @brief Get the gamma value for Gamma=2.6 Slope=11 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamma26_11 (double x) { - return x <= 0.004921 ? x*11.0 : 1.086603*exp(log(x)/2.6)-0.086603; - } - - - /** - * @brief Get the inverse gamma value for Gamma=2.6 Slope=11 - * @param x red, green or blue channel's value [0 ; 1] - * @return the inverse gamma modified's value [0 ; 1] - */ - static inline double igamma26_11 (double x) { - return x <= 0.054127 ? x/11.0 : exp(log((x+0.086603)/1.086603)*2.6); - } - /** - * @brief Get the gamma value for Gamma=1.3 Slope=2 - * @param x red, green or blue channel's value [0 ; 1] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamma13_2 (double x) { - return x <= 0.016613 ? x*2.0 : 1.009968*exp(log(x)/1.3)-0.016613; - } - - - // gamma function with adjustable parameters - //same as above with values calculate with Calcgamma above - // X range 0..1 - static inline double gamma (double x, double gamma, double start, double slope, double mul, double add){ - return (x <= start ? x*slope : exp(log(x)/gamma)*mul-add); - } - static inline double igamma (double x, double gamma, double start, double slope, double mul, double add){ - return (x <= start*slope ? x/slope : exp(log((x+add)/mul)*gamma) ); - } - - - /** - * @brief Very basic gamma - * @param x red, green or blue channel's value [0 ; 1] - * @param gamma gamma value [1 ; 5] - * @return the gamma modified's value [0 ; 1] - */ - static inline double gamman (double x, double gamma) { //standard gamma without slope... - return (x =exp(log(x)/gamma)); - } - - /** - * @brief Very basic gamma - * @param x red, green or blue channel's value [0 ; 1] - * @param gamma gamma value [1 ; 5] - * @return the gamma modified's value [0 ; 1] - */ - static inline float gammanf (float x, float gamma) { //standard gamma without slope... - return (x =xexpf(xlogf(x)/gamma)); - } - - - /** - * @brief Very simply inverse gamma - * @param x red, green or blue channel's value [0 ; 1] - * @param gamma gamma value [1 ; 5] - * @return the inverse gamma modified's value [0 ; 1] - */ - static inline double igamman (double x, double gamma){ //standard inverse gamma without slope... - return (x = exp(log(x)*gamma) ); - } - - - /** - * @brief Get the gamma value out of look-up tables - * Calculated with gamma function above. e.g. : - * for (int i=0; i<65536; i++) - * gammatab_srgb[i] = (65535.0 * gamma2 (i/65535.0)); - * @param x [0 ; 1] - * @return the gamma modified's value [0 ; 65535] - */ - static inline float gamma_srgb (char x) { return gammatab_srgb[x]; } - static inline float gamma (char x) { return gammatab[x]; } - static inline float igamma_srgb (char x) { return igammatab_srgb[x]; } - static inline float gamma_srgb (int x) { return gammatab_srgb[x]; } - static inline float gamma (int x) { return gammatab[x]; } - static inline float igamma_srgb (int x) { return igammatab_srgb[x]; } - static inline float gamma_srgb (float x) { return gammatab_srgb[x]; } - static inline float gamma (float x) { return gammatab[x]; } - static inline float igamma_srgb (float x) { return igammatab_srgb[x]; } - //static inline float gamma_srgb (double x) { return gammatab_srgb[x]; } - //static inline float gamma (double x) { return gammatab[x]; } - //static inline float igamma_srgb (double x) { return igammatab_srgb[x]; } - - - - // -------------------------------- Jacques's Munsell correction - - - /** - * @brief Corrects the color (hue) depending on chromaticity and luminance changes - * - * To use in a "for" or "do while" statement. - * - * @param lumaMuns true => luminance correction (for delta L > 10) and chroma correction ; false => only chroma - * @param Lprov1 luminance after [0 ; 100] - * @param Loldd luminance before [0 ; 100] - * @param HH hue before [-PI ; +PI] - * @param Chprov1 chroma after [0 ; 180 (can be superior)] - * @param CC chroma before [0 ; 180] - * @param corectionHuechroma hue correction depending on chromaticity (saturation), in radians [0 ; 0.45] (return value) - * @param correctlum hue correction depending on luminance (brightness, contrast,...), in radians [0 ; 0.45] (return value) - * @param munsDbgInfo (Debug target only) object to collect informations - */ - -#ifdef _DEBUG - static void AllMunsellLch (bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHueChroma, float &correctlum, MunsellDebugInfo* munsDbgInfo); -#else - static void AllMunsellLch (bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHueChroma, float &correctlum); -#endif - - - /** - * @brief Correct chromaticity and luminance so that the color stays in the working profile's gamut - * - * This function puts the data (Lab) in the gamut of "working profile": - * it returns the corrected values of the chromaticity and luminance - * - * @param HH : hue, in radians [-PI ; +PI] - * @param Lprov1 : input luminance value, sent back corrected [0 ; 100] (input & output value) - * @param Chprov1: input chroma value, sent back corrected [0 ; 180 (can be superior)] (input & output value) - * @param R red value of the corrected color [0 ; 65535 but can be negative or superior to 65535] (return value) - * @param G green value of the corrected color [0 ; 65535 but can be negative or superior to 65535] (return value) - * @param B blue value of the corrected color [0 ; 65535 but can be negative or superior to 65535] (return value) - * @param wip working profile - * @param isHLEnabled true if "Highlight Reconstruction " is enabled - * @param lowerCoef a float number between [0.95 ; 1.0[ - * The nearest it is from 1.0, the more precise it will be, and the longer too as more iteration will be necessary - * @param higherCoef a float number between [0.95 ; 1.0[ - * The nearest it is from 1.0, the more precise it will be, and the longer too as more iteration will be necessary - * @param neg (Debug target only) to calculate iterations for negatives values - * @param moreRGB (Debug target only) to calculate iterations for values >65535 - */ -#ifdef _DEBUG - static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); - static void gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); - static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); -#else - static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); - static void gamutLchonly (float HH, float2 sincosval,float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); - static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); -#endif - - - /** - * @brief Munsell gamut correction - * - * This function is the overall Munsell's corrections, but only on global statement. It may be better to use local statement with AllMunsellLch. - * They are named accordingly : gamutLchonly and AllMunsellLch - * It can be used before and after treatment (saturation, gamma, luminance, ...) - * - * @param labL L channel input and output image - * L channel's usual range is [0 ; 100], but values can be negative or >100 - * @param laba a channel input and output image - * @param labb b channel input and output image - * a and b channel's range is usually [-128 ; +128], but values can be >128 - * @param N Number of pixels to process - * @param corMunsell performs Munsell correction - * @param lumaMuns whether to apply luma correction or not (used only if corMuns=true) - * true: apply luma + chroma Munsell correction if delta L > 10; - * false: leaves luma untouched - * @param gamut performs gamutLch - * @param wip matrix for working profile - * @param multiThread whether to parallelize the loop or not - */ - static void LabGamutMunsell (float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3], bool multiThread ); - - - /* - * @brief Skin tone protection factor - * Skin colors: mixed from NX2 skin color palette, Von Luschan, and photos of white, black, yellow people... - * There are some little exceptions, but it should cover 99% case. - * Pay attention to white balance, and do not change hue and saturation, upstream of the modification - * Used by vibrance - * @param lum luma value [0 ; 100] - * @param hue hue value [-PI ; +PI] - * @param chrom chroma value [0 ; 180] - * @param satreduc [0.1 ; 1] (return value) - * @param chromx [0 or 1], actually only 0 is used - */ - static void SkinSat (float lum, float hue, float chrom, float &satreduc);//jacques Skin color - - - /** - * @brief Munsell Lch correction - * Find the right LUT and calculate the correction - * @param lum luma value [0 ; 100] - * @param hue hue value [-PI ; +PI] - * @param chrom chroma value [0 ; 180] - * @param memChprov store chroma [0 ; 180] - * @param correction correction value, in radians [0 ; 0.45] - * @param lbe hue in function of chroma, in radian [-PI ; +PI] - * @param zone [1 ; 4] 1=PB correction + sky 2=red yellow correction 3=Green yellow correction 4=Red purple correction - * @param correctL true=enable the Luminance correction - */ - static void MunsellLch (float lum, float hue, float chrom, float memChprov, float &correction, int zone, float &lbe, bool &correctL);//jacques: Munsell correction - - - // -------------------------------- end Munsell - - - static void scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext); - static void transitred (const float HH, const float Chprov1, const float dred, const float factorskin, const float protect_red, const float factorskinext, const float deltaHH, const float factorsat, float &factor); - static void skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s); - static void skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s); -// static void scaleredcdbl ( float skinprot, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext); - - static inline void SkinSatCbdl (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r) { - - static const float C9=8.f, C8=15.f, C7=12.f, C4=7.f, C3=5.f, C2=5.f, C1=5.f; - static const float H9=0.05f, H8=0.25f, H7=0.1f, H4=0.02f, H3=0.02f, H2=0.1f, H1=0.1f, H10=-0.2f,H11=-0.2f; - - // "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1, uses imolicit factor 1.0 - // wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation, uses explicit facor 0.6 - // wide area for transition, uses explicit factor 0.4 - - if (lum >= 85.0f) { - if((hue > (t_l+0.53f-H9) && hue < (t_r+H9)) && (chrom > 8.0f && chrom < (14.0f+C9))) scale = (100.f-skinprot)/100.1f; - else if (lum >= 92.0f) { - if((hue > t_l+0.4f && hue < t_r) && (chrom > 7.0f && chrom < (15.0f))) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > b_l && hue < t_r) && (chrom > 7.0f && chrom < (18.0f))) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if ((hue > t_l+0.4f && hue < t_r-0.3f) && (chrom > 7.0f && chrom < (26.0f+C9))) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > b_l+0.05f && hue < t_r) && (chrom > 7.0f && chrom < (35.0f+C9))) scale = (100.f-skinprot*0.4f)/100.1f; + /** + * @brief Calculate the effective direction (up or down) to linearly interpolating 2 colors so that it follows the shortest or longest path + * @param h1 First hue [0 ; 1] + * @param h2 Second hue [0 ; 1] + * @param path Path to follow (shortest/longest) + * @return The interpolation direction + */ + static inline eInterpolationDirection getHueInterpolationDirection (double h1, double h2, eInterpolationPath path) + { + if (path == IP_SHORTEST) { + if (h2 > h1) { + if (h2 - h1 <= 0.5) { + return ID_UP; + } else { + return ID_DOWN; + } + } else { + if (h1 - h2 <= 0.5) { + return ID_DOWN; + } else { + return ID_UP; + } + } + } else { + if (h2 > h1) { + if (h2 - h1 <= 0.5) { + return ID_DOWN; + } else { + return ID_UP; + } + } else { + if (h1 - h2 <= 0.5) { + return ID_UP; + } else { + return ID_DOWN; + } + } } - else if (lum >= 70.0f) { - if((hue > t_l+0.15f && hue < (t_r-0.2f+H8)) && (chrom > 8.0f && chrom < (35.0f+C8))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 52.0f) { - if((hue > t_l && hue < (t_r+H7)) && (chrom > 11.0f && chrom < (35.0f+C7))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 35.0f) { - if((hue > t_l && hue < (t_r+H4)) && (chrom > 13.0f && chrom < (37.0f+C4))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 20.0f) { - if((hue > t_l && hue < (t_r+H3)) && (chrom > 7.0f && chrom <(35.0f+C3) )) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 10.0f) { - if((hue > (t_l-0.25f + H10) && hue < (t_r-0.3f +H2)) && (chrom > 8.0f && chrom < (23.0f+C2))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (35.0f+C1) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.1f) && (chrom > 7.0f && chrom < (45.0f+C1) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if ((hue > (t_l -0.2f + H10) && hue < (t_r-0.3f+H1)) && (chrom > 8.0f && chrom < (23.0f+C1))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (35.0f+C1) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.1f) && (chrom > 7.0f && chrom < (45.0f+C1) )) scale = (100.f-skinprot*0.4f)/100.1f; - - //extended zone for hair, beard and if user adjust high value for skinprot - if(skinprot > 85.f && chrom < 20.f && neg) { - float modula = -0.0666f * skinprot + 6.66f; - scale *= modula; - } - } - - static inline void SkinSatCbdl2 (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r, float b_r, int basc) { - - static const float C9=8.f, C8=15.f, C7=12.f, C4=7.f, C3=5.f, C2=5.f, C1=5.f; - static const float H9=0.05f, H8=0.25f, H7=0.1f, H4=0.02f, H3=0.02f, H2=0.1f, H1=0.1f, H10=-0.2f,H11=-0.2f; - - // "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1, uses imolicit factor 1.0 - // wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation, uses explicit facor 0.6 - // wide area for transition, uses explicit factor 0.4 - if((b_l > -0.3f && b_r < 2.f) || basc==0) { //range maxi skin - if (lum >= 85.0f) { - if((hue > (t_l+0.53f-H9) && hue < (t_r+H9)) && (chrom > 8.0f && chrom < (14.0f+C9))) scale = (100.f-skinprot)/100.1f; - else if (lum >= 92.0f) { - if((hue > t_l+0.4f && hue < t_r) && (chrom > 7.0f && chrom < (15.0f))) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > b_l && hue < t_r) && (chrom > 7.0f && chrom < (18.0f))) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if ((hue > t_l+0.4f && hue < t_r-0.3f) && (chrom > 7.0f && chrom < (26.0f+C9))) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > b_l+0.05f && hue < t_r) && (chrom > 7.0f && chrom < (35.0f+C9))) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 70.0f) { - if((hue > t_l+0.15f && hue < (t_r-0.2f+H8)) && (chrom > 8.0f && chrom < (35.0f+C8))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 52.0f) { - if((hue > t_l && hue < (t_r+H7)) && (chrom > 11.0f && chrom < (35.0f+C7))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 35.0f) { - if((hue > t_l && hue < (t_r+H4)) && (chrom > 13.0f && chrom < (37.0f+C4))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 20.0f) { - if((hue > t_l && hue < (t_r+H3)) && (chrom > 7.0f && chrom <(35.0f+C3) )) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 10.0f) { - if((hue > (t_l-0.25f + H10) && hue < (t_r-0.3f +H2)) && (chrom > 8.0f && chrom < (23.0f+C2))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (35.0f+C1) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.1f) && (chrom > 7.0f && chrom < (45.0f+C1) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if ((hue > (t_l -0.2f + H10) && hue < (t_r-0.3f+H1)) && (chrom > 8.0f && chrom < (23.0f+C1))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (35.0f+C1) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.1f) && (chrom > 7.0f && chrom < (45.0f+C1) )) scale = (100.f-skinprot*0.4f)/100.1f; - - //extended zone for hair, beard and if user adjust high value for skinprot - if(skinprot > 85.f && chrom < 20.f && neg) { - float modula = -0.0666f * skinprot + 6.66f; - scale *= modula; - } - } - //end hue skin algo - else if (basc==1) {//not hue skin linear transition or mod chroma curve - if(hue >= t_l && hue <= t_r) scale = (100.f-skinprot)/100.1f; - else if(hue > b_l && hue < t_l) { - float sc=(100.f-skinprot)/100.1f; - float aa=(1.f-sc)/(b_l-t_l); - float bb=1.f-aa*b_l; - scale=aa*hue + bb; - } - else if(hue > t_r && hue < b_r) { - float sc=(100.f-skinprot)/100.1f; - float aa=(sc-1.f)/(t_r-b_r); - float bb=1.f-aa*b_r; - scale=aa*hue + bb; - } - } - } - - - - static inline void SkinSatCbdlCam (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r) { - - static const float C9=8.f, C8=15.f, C7=12.f, C4=7.f, C3=5.f, C2=5.f, C1=5.f; - static const float H9=0.05f, H8=0.25f, H7=0.1f, H4=0.02f, H3=0.02f, H2=0.1f, H1=0.1f, H10=-0.2f,H11=-0.2f; - - float HH = 0.f; - if (hue>8.6f && hue<=74.f ) {HH=(1.15f/65.4f)*hue-0.0012f;} //H > 0.15 H<1.3 - else if(hue>0.f && hue<=8.6f ) {HH=(0.19f/8.6f )*hue-0.04f;} //H>-0.04 H < 0.15 - else if(hue>355.f && hue<=360.f) {HH=(0.11f/5.0f )*hue-7.96f;} //H>-0.15 <-0.04 - else if(hue>74.f && hue<95.f ) {HH=(0.30f/21.0f)*hue+0.24285f;} //H>1.3 H<1.6 - else if(hue>=95.f && hue<137.5f) {HH= 0.01882f*hue-0.18823f;} // H>1.6 H<2.4 - else if(hue>285.f && hue<=355.f) {HH=0.1642f*hue -5.982f;} //HH>-1.3 HH <-0.15 - - hue=HH; - - // "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1, uses imolicit factor 1.0 - // wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation, uses explicit facor 0.6 - // wide area for transition, uses explicit factor 0.4 - - if (lum >= 85.0f) { - if((hue > (t_l+0.53f-H9) && hue < (t_r+H9)) && (chrom > 8.0f && chrom < (14.0f+C9))) scale = (100.f-skinprot)/100.1f; - else if (lum >= 92.0f) { - if((hue > t_l+0.4f && hue < t_r) && (chrom > 7.0f && chrom < (15.0f))) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > b_l && hue < t_r) && (chrom > 7.0f && chrom < (18.0f))) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if ((hue > t_l+0.4f && hue < t_r-0.3f) && (chrom > 7.0f && chrom < (26.0f+C9))) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > b_l+0.05f && hue < t_r) && (chrom > 7.0f && chrom < (35.0f+C9))) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 70.0f) { - if((hue > t_l+0.15f && hue < (t_r-0.2f+H8)) && (chrom > 8.0f && chrom < (35.0f+C8))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 52.0f) { - if((hue > t_l && hue < (t_r+H7)) && (chrom > 11.0f && chrom < (35.0f+C7))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 35.0f) { - if((hue > t_l && hue < (t_r+H4)) && (chrom > 13.0f && chrom < (37.0f+C4))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 20.0f) { - if((hue > t_l && hue < (t_r+H3)) && (chrom > 7.0f && chrom <(35.0f+C3) )) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (48.0f+C9) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f+C9) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if (lum >= 10.0f) { - if((hue > (t_l-0.25f + H10) && hue < (t_r-0.3f +H2)) && (chrom > 8.0f && chrom < (23.0f+C2))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (35.0f+C1) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.1f) && (chrom > 7.0f && chrom < (45.0f+C1) )) scale = (100.f-skinprot*0.4f)/100.1f; - } - else if ((hue > (t_l -0.2f + H10) && hue < (t_r-0.3f+H1)) && (chrom > 8.0f && chrom < (23.0f+C1))) scale = (100.f-skinprot)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.2f) && (chrom > 7.0f && chrom < (35.0f+C1) )) scale = (100.f-skinprot*0.6f)/100.1f; - else if ((hue > (b_l+0.07f+H11) && hue < t_r-0.1f) && (chrom > 7.0f && chrom < (45.0f+C1) )) scale = (100.f-skinprot*0.4f)/100.1f; - - //extended zone for hair, beard and if user adjust high value for skinprot - if(skinprot > 85.f && chrom < 20.f && neg) { - float modula = -0.0666f * skinprot + 6.66f; - scale *= modula; - } } - /** - * @brief Gamut correction in the XYZ color space - * @param X X channel input value and corrected output value [0 ; 65535] - * @param Y Y channel input value and corrected output value [0 ; 65535] - * @param Z Z channel input value and corrected output value [0 ; 65535] - * @param p working profile - */ - static void gamutmap(float &X, float &Y, float &Z, const double p[3][3]); + /** + * @brief Calculate a color by linearly interpolating 2 colors + * @param h1 First hue + * @param h2 Second hue + * @param balance Factor from 0 (first hue) to 1 (second hue) + * @param dir Tells which direction the interpolation have to follow. You can get the value with getHueInterpolationDirection + * @return The interpolated hue + */ + static inline double interpolateHueHSV (double h1, double h2, double balance, eInterpolationDirection dir) + { + if (h1 == h2) { + return h1; + } + + if (dir == ID_DOWN) { + if (h1 < h2) { + double temp = h1; + h1 = h2 - 1.; + h2 = temp; + balance = 1. - balance; + } + + double h3 = h1 + balance * (h2 - h1); + + if (h3 < 0.) { + h3 += 1.; + } + + return h3; + } else { + if (h1 > h2) { + h2 += 1.; + } + + double h3 = h1 + balance * (h2 - h1); + + if (h3 > 1.) { + h3 -= 1.; + } + + return h3; + } + } + + /** + * @brief Interpolate 2 colors from their respective red/green/blue channels, with a balance factor + * @param balance gives weight to the first and second color [0 ; 1] + * 0. = output color == first color + * 0.5 = output color == equally mixed colors + * 1. = output color == second color + * @param r1 red channel of color 1 [0 ; 65535] + * @param g1 green channel of color 1 [0 ; 65535] + * @param b1 blue channel of color 1 [0 ; 65535] + * @param r2 red channel of color 2 [0 ; 65535] + * @param g2 green channel of color 2 [0 ; 65535] + * @param b2 blue channel of color 2 [0 ; 65535] + * @param channels bitfield of channel to interpolate (CHANNEL_LIGHTNESS|CHANNEL_CHROMATICITY|CHANNEL_HUE) + * @param xyz_rgb color space + * @param ro red channel of output color [0 ; 65535] (return value) + * @param go green channel of output color [0 ; 65535] (return value) + * @param bo blue channel of output color [0 ; 65535] (return value) + */ + static void interpolateRGBColor (const float balance, const float r1, const float g1, const float b1, const float r2, const float g2, const float b2, int channels, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo); + + /** + * @brief Interpolate 2 colors from their respective red/green/blue channels, with a balance factor + * @param realL luminance hsl [0; 1] + * @param iplow low luminance for rl [0;1] + * @param ihigh high luminance for r2 [0;1] + * @param algm algorithm [0;2] + * @param balance gives weight to the first and second color [0 ; 1] + * 0. = output color == first color + * 0.5 = output color == equally mixed colors + * 1. = output color == second color + * @param twoc 2 colors or 512 int + * @param r1 red channel of color 1 [0 ; 65535] + * @param g1 green channel of color 1 [0 ; 65535] + * @param b1 blue channel of color 1 [0 ; 65535] + * @param rl red channel of color low [0 ; 65535] + * @param gl green channel of color low [0 ; 65535] + * @param bl blue channel of color low [0 ; 65535] + + * @param r2 red channel of color 2 or high[0 ; 65535] + * @param g2 green channel of color 2 or high[0 ; 65535] + * @param b2 blue channel of color 2 [or high 0 ; 65535] + * @param channels bitfield of channel to interpolate (CHANNEL_LIGHTNESS|CHANNEL_CHROMATICITY|CHANNEL_HUE) + * @param xyz_rgb color space + * @param rgb_xyz inverse color space + * @param ro red channel of output color [0 ; 65535] (return value) + * @param go green channel of output color [0 ; 65535] (return value) + * @param bo blue channel of output color [0 ; 65535] (return value) + */ + static void interpolateRGBColor (float realL, float iplow, float iphigh, int algm, const float balance, int twoc, int metchrom, bool chr, bool lum, float chromat, float luma, const float r1, const float g1, const float b1, const float xl, const float yl, const float zl, const float x2, const float y2, const float z2, int channels, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float &ro, float &go, float &bo); - /** - * @brief Get HSV's hue from the Lab's hue - * @param HH Lab's hue value, in radians [-PI ; +PI] - * @return HSV's hue value [0 ; 1] - */ - static inline double huelab_to_huehsv2 (float HH){ - //hr=translate Hue Lab value (-Pi +Pi) in approximative hr (hsv values) (0 1) [red 1/6 yellow 1/6 green 1/6 cyan 1/6 blue 1/6 magenta 1/6 ] - // with multi linear correspondances (I expect there is no error !!) - double hr = 0.0; - //allways put h between 0 and 1 + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [0;1] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [0; 1] + * @param h2 Second hue [0; 1] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [0;1] + */ + /*template + static inline T interpolatePolarHue_01 (T h1, T h2, U balance) { - if (HH>=0.f && HH < 0.6f ) hr=0.11666*double(HH) + 0.93; //hr 0.93 1.00 full red - else if (HH>=0.6f && HH < 1.4f ) hr=0.1125 *double(HH) - 0.0675; //hr 0.00 0.09 red yellow orange - else if (HH>=1.4f && HH < 2.f ) hr=0.2666 *double(HH) - 0.2833; //hr 0.09 0.25 orange yellow - else if (HH>=2.f && HH < 3.14159f) hr=0.1489 *double(HH) - 0.04785; //hr 0.25 0.42 yellow green green - else if (HH>=-3.14159f && HH < -2.8f ) hr=0.23419*double(HH) + 1.1557; //hr 0.42 0.50 green - else if (HH>=-2.8f && HH < -2.3f ) hr=0.16 *double(HH) + 0.948; //hr 0.50 0.58 cyan - else if (HH>=-2.3f && HH < -0.9f ) hr=0.12143*double(HH) + 0.85928; //hr 0.58 0.75 blue blue-sky - else if (HH>=-0.9f && HH < -0.1f ) hr=0.2125 *double(HH) + 0.94125; //hr 0.75 0.92 purple magenta - else if (HH>=-0.1f && HH < 0.f ) hr=0.1 *double(HH) + 0.93; //hr 0.92 0.93 red - // in case of ! - if (hr<0.0) hr += 1.0; - else if(hr>1.0) hr -= 1.0; - return (hr); - } + if (h1==h2) + return h1; + if ((h1 > h2) && (h1-h2 > T(0.5))){ + h1 -= T(1.); + double value = h1 + T(balance) * (h2-h1); + if (value < T(0.)) + value += T(1.); + return value; + } + else if (h2-h1 > T(0.5)) { + h2 -= T(1.); + double value = h1 + T(balance) * (h2-h1); + if (value < T(0.)) + value += T(1.); + return value; + } + else + return h1 + T(balance) * (h2-h1); + }*/ + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [-PI ; +PI] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [-PI ; +PI] + * @param h2 Second hue [-PI ; +PI] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [-PI ; +PI] + */ + /*template + static inline T interpolatePolarHue_PI (T h1, T h2, U balance) { + if (h1==h2) + return h1; + if ((h1 > h2) && (h1-h2 > T(M_PI))){ + h1 -= T(2*M_PI); + T value = h1 + T(balance) * (h2-h1); + if (value < T(-M_PI)) + value += T(2*M_PI); + return value; + } + else if (h2-h1 > T(M_PI)) { + h2 -= T(2*M_PI); + T value = h1 + T(balance) * (h2-h1); + if (value < T(0)) + value += T(2*M_PI); + return value; + } + else + return h1 + T(balance) * (h2-h1); + }*/ + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [0;1] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [0; 1] + * @param h2 Second hue [0; 1] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [0;1] + */ + template + static inline T interpolatePolarHue_01 (T h1, T h2, U balance) + { + float d = h2 - h1; + float f; + f = T(balance); + double h; + + if (h1 > h2) { + std::swap(h1, h2); + d = -d; + f = 1.f - f; + } + + if (d < T(-M_PI) || d < T(0) || d > T(M_PI)) { //there was an inversion here !! d > T(M_PI) + h1 += T(2 * M_PI); + h = h1 + f * (h2 - h1); + h = std::fmod(h, 2 * M_PI); + } else { + h = h1 + f * d; + } + + // not strictly necessary..but in case of + if(h < T(-M_PI)) { + h = T(2 * M_PI) - h; + } + + if(h > T(M_PI)) { + h = h - T(2 * M_PI); + } + + return h; + } + + + /** + * @brief Interpolate a hue value as the angle of a polar coordinate with hue in the [-PI ; +PI] range + * Chose the shorter path from hue 1 to hue 2. + * @param h1 First hue [-PI ; +PI] + * @param h2 Second hue [-PI ; +PI] + * @param balance Interpolation factor [0 ; 1] where 0.=h1, 1.=h2 + * @return the interpolated value [-PI ; +PI ] + */ + template + static inline T interpolatePolarHue_PI (T h1, T h2, U balance) + { + float d = h2 - h1; + float f; + f = T(balance); + double h; + + if (h1 > h2) { + std::swap(h1, h2); + d = -d; + f = 1.f - f; + } + + if (d < T(0) || d < T(0.5) || d > T(1.)) { //there was an inversion here !! d > T(M_PI) + h1 += T(1.); + h = h1 + f * (h2 - h1); + h = std::fmod(h, 1.); + } else { + h = h1 + f * d; + } + + // not strictly necessary..but in case of + if(h < T(0)) { + h = T(1.) - h; + } + + if(h > T(1)) { + h = h - T(1.); + } + + return h; + } + + + /** + * @brief Get the gamma curves' parameters used by LCMS2 + * @param pwr gamma value [>1] + * @param ts slope [0 ; 20] + * @param mode [always 0] + * @imax imax [always 0] + * @param gamma0 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value) + * @param gamma1 used in ip2Lab2rgb [0 ; 20], can be superior to 20, but it's quite unusual(return value) + * @param gamma2 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value) + * @param gamma3 used in ip2Lab2rgb [0 ; 1], usually near 0.003(return value) + * @param gamma4 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value) + * @param gamma5 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value) + */ + static void calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4, double &gamma5); + + + /** + * @brief Used by Black and White to correct gamma for each channel red, green and blue channel + * @param r red channel input and output value [0 ; 65535] + * @param g green channel input and output value [0 ; 65535] + * @param b blue channel input and output value [0 ; 65535] + * @param gammabwr gamma value for red channel [>0] + * @param gammabwg gamma value for red channel [>0] + * @param gammabwb gamma value for red channel [>0] + */ + static void trcGammaBW (float &r, float &g, float &b, float gammabwr, float gammabwg, float gammabwb); + + + /** @brief Compute the B&W constants for the Black and White processing and its GUI + * @param setting main mode + * @param filter string of the filter effect to use + * @param algo choice between linear and special for OYCPM colors + * @param mixerRed red channel value of the channel mixer [-100 ; +200] + * @param mixerGreen green channel value of the channel mixer [-100 ; +200] + * @param mixerBlue blue channel value of the channel mixer [-100 ; +200] + * @param mixerOrange orange channel value of the channel mixer [-100 ; +200] + * @param mixerYellow yellow channel value of the channel mixer [-100 ; +200] + * @param mixerCyan cyan channel value of the channel mixer [-100 ; +200] + * @param mixerPurple purple channel value of the channel mixer [-100 ; +200] + * @param mixerMagenta magenta channel value of the channel mixer [-100 ; +200] + * @param autoc automatic mode of the channel mixer + * @param complement adjust complementary channel + * @param kcorec in absolute mode, value to correct the mixer [1 ; 3], usually near 1 (return value) + * @param rrm red channel of the mixer (return value) + * @param ggm green channel of the mixer (return value) + * @param bbm blue channel of the mixer (return value) + */ + static void computeBWMixerConstants (const Glib::ustring &setting, const Glib::ustring &filter, const Glib::ustring &algo, float &filcor, float &mixerRed, float &mixerGreen, + float &mixerBlue, float mixerOrange, float mixerYellow, float mixerCyan, float mixerPurple, float mixerMagenta, + bool autoc, bool complement, float &kcorec, double &rrm, double &ggm, double &bbm); + + + // standard srgb gamma and its inverse + + /** + * @brief sRGB gamma + * See also calcGamma above with the following values: pwr=2.4 ts=12.92 mode=0.003041 imax=0.055011 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma2 (double x) // g3 1+g4 + { + return x <= 0.003041 ? x * 12.92 : 1.055011 * exp(log(x) / sRGBGammaCurve) - 0.055011; + } + + + /** + * @brief Inverse sRGB gamma + * See also calcGamma above with the following values: pwr=2.4 ts=12.92 mode=0.003041 imax=0.055011 + * @param x red, green or blue channel's value [0 ; 1] + * @return the inverse gamma modified's value [0 ; 1] + */ + static inline double igamma2 (double x) //g2 + { + return x <= 0.039293 ? x / 12.92 : exp(log((x + 0.055011) / 1.055011) * sRGBGammaCurve); + } + + + /** + * @brief Get the gamma value for Gamma=5.5 Slope=10 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma55 (double x) // g3 1+g4 + { + return x <= 0.013189 ? x * 10.0 : 1.593503 * exp(log(x) / 5.5) - 0.593503; // 5.5 10 + } + + + /** + * @brief Get the inverse gamma value for Gamma=5.5 Slope=10 + * @param x red, green or blue channel's value [0 ; 1] + * @return the inverse gamma modified's value [0 ; 1] + */ + static inline double igamma55 (double x) //g2 + { + return x <= 0.131889 ? x / 10.0 : exp(log((x + 0.593503) / 1.593503) * 5.5); // 5.5 10 + } + + + /** + * @brief Get the gamma value for Gamma=4 Slope=5 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma4 (double x) // g3 1+g4 + { + return x <= 0.03089 ? x * 5.0 : 1.478793 * exp(log(x) / 4.1) - 0.478793; // 4 5 + } + + + /** + * @brief Get the inverse gamma value for Gamma=4 Slope=5 + * @param x red, green or blue channel's value [0 ; 1] + * @return the inverse gamma modified's value [0 ; 1] + */ + static inline double igamma4 (double x) //g2 + { + return x <= 0.154449 ? x / 5.0 : exp(log((x + 0.478793) / 1.478793) * 4.1); // 4 5 + } + + + /* + * @brief Get the gamma value for Gamma=2.2 Slope=4.5 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + * + static inline double gamma709 (double x) { + return x <= 0.0176 ? x*4.5 : 1.0954*exp(log(x)/2.2)-0.0954; + } + + * @brief Get the inverse gamma value for Gamma=2.2 Slope=4.5 + * @param x red, green or blue channel's value [0 ; 1] + * @return the inverse gamma modified's value [0 ; 1] + * + static inline double igamma709 (double x) { + return x <= 0.0795 ? x/4.5 : exp(log((x+0.0954)/1.0954)*2.2); + } + */ + + + + /** + * @brief Get the gamma value for Gamma=2.4 Slope=17 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma24_17 (double x) + { + return x <= 0.001867 ? x * 17.0 : 1.044445 * exp(log(x) / 2.4) - 0.044445; + } + + + /** + * @brief Get the inverse gamma value for Gamma=2.4 Slope=17 + * @param x red, green or blue channel's value [0 ; 1] + * @return the inverse gamma modified's value [0 ; 1] + */ + static inline double igamma24_17 (double x) + { + return x <= 0.031746 ? x / 17.0 : exp(log((x + 0.044445) / 1.044445) * 2.4); + } + + + /** + * @brief Get the gamma value for Gamma=2.6 Slope=11 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma26_11 (double x) + { + return x <= 0.004921 ? x * 11.0 : 1.086603 * exp(log(x) / 2.6) - 0.086603; + } + + + /** + * @brief Get the inverse gamma value for Gamma=2.6 Slope=11 + * @param x red, green or blue channel's value [0 ; 1] + * @return the inverse gamma modified's value [0 ; 1] + */ + static inline double igamma26_11 (double x) + { + return x <= 0.054127 ? x / 11.0 : exp(log((x + 0.086603) / 1.086603) * 2.6); + } + /** + * @brief Get the gamma value for Gamma=1.3 Slope=2 + * @param x red, green or blue channel's value [0 ; 1] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamma13_2 (double x) + { + return x <= 0.016613 ? x * 2.0 : 1.009968 * exp(log(x) / 1.3) - 0.016613; + } + + + // gamma function with adjustable parameters + //same as above with values calculate with Calcgamma above + // X range 0..1 + static inline double gamma (double x, double gamma, double start, double slope, double mul, double add) + { + return (x <= start ? x*slope : exp(log(x) / gamma) * mul - add); + } + static inline double igamma (double x, double gamma, double start, double slope, double mul, double add) + { + return (x <= start * slope ? x / slope : exp(log((x + add) / mul) * gamma) ); + } + + + /** + * @brief Very basic gamma + * @param x red, green or blue channel's value [0 ; 1] + * @param gamma gamma value [1 ; 5] + * @return the gamma modified's value [0 ; 1] + */ + static inline double gamman (double x, double gamma) //standard gamma without slope... + { + return (x = exp(log(x) / gamma)); + } + + /** + * @brief Very basic gamma + * @param x red, green or blue channel's value [0 ; 1] + * @param gamma gamma value [1 ; 5] + * @return the gamma modified's value [0 ; 1] + */ + static inline float gammanf (float x, float gamma) //standard gamma without slope... + { + return (x = xexpf(xlogf(x) / gamma)); + } + + + /** + * @brief Very simply inverse gamma + * @param x red, green or blue channel's value [0 ; 1] + * @param gamma gamma value [1 ; 5] + * @return the inverse gamma modified's value [0 ; 1] + */ + static inline double igamman (double x, double gamma) //standard inverse gamma without slope... + { + return (x = exp(log(x) * gamma) ); + } + + + /** + * @brief Get the gamma value out of look-up tables + * Calculated with gamma function above. e.g. : + * for (int i=0; i<65536; i++) + * gammatab_srgb[i] = (65535.0 * gamma2 (i/65535.0)); + * @param x [0 ; 1] + * @return the gamma modified's value [0 ; 65535] + */ + static inline float gamma_srgb (char x) + { + return gammatab_srgb[x]; + } + static inline float gamma (char x) + { + return gammatab[x]; + } + static inline float igamma_srgb (char x) + { + return igammatab_srgb[x]; + } + static inline float gamma_srgb (int x) + { + return gammatab_srgb[x]; + } + static inline float gamma (int x) + { + return gammatab[x]; + } + static inline float igamma_srgb (int x) + { + return igammatab_srgb[x]; + } + static inline float gamma_srgb (float x) + { + return gammatab_srgb[x]; + } + static inline float gamma (float x) + { + return gammatab[x]; + } + static inline float igamma_srgb (float x) + { + return igammatab_srgb[x]; + } + //static inline float gamma_srgb (double x) { return gammatab_srgb[x]; } + //static inline float gamma (double x) { return gammatab[x]; } + //static inline float igamma_srgb (double x) { return igammatab_srgb[x]; } + + + + // -------------------------------- Jacques's Munsell correction + + + /** + * @brief Corrects the color (hue) depending on chromaticity and luminance changes + * + * To use in a "for" or "do while" statement. + * + * @param lumaMuns true => luminance correction (for delta L > 10) and chroma correction ; false => only chroma + * @param Lprov1 luminance after [0 ; 100] + * @param Loldd luminance before [0 ; 100] + * @param HH hue before [-PI ; +PI] + * @param Chprov1 chroma after [0 ; 180 (can be superior)] + * @param CC chroma before [0 ; 180] + * @param corectionHuechroma hue correction depending on chromaticity (saturation), in radians [0 ; 0.45] (return value) + * @param correctlum hue correction depending on luminance (brightness, contrast,...), in radians [0 ; 0.45] (return value) + * @param munsDbgInfo (Debug target only) object to collect informations + */ + +#ifdef _DEBUG + static void AllMunsellLch (bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHueChroma, float &correctlum, MunsellDebugInfo* munsDbgInfo); +#else + static void AllMunsellLch (bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHueChroma, float &correctlum); +#endif + + + /** + * @brief Correct chromaticity and luminance so that the color stays in the working profile's gamut + * + * This function puts the data (Lab) in the gamut of "working profile": + * it returns the corrected values of the chromaticity and luminance + * + * @param HH : hue, in radians [-PI ; +PI] + * @param Lprov1 : input luminance value, sent back corrected [0 ; 100] (input & output value) + * @param Chprov1: input chroma value, sent back corrected [0 ; 180 (can be superior)] (input & output value) + * @param R red value of the corrected color [0 ; 65535 but can be negative or superior to 65535] (return value) + * @param G green value of the corrected color [0 ; 65535 but can be negative or superior to 65535] (return value) + * @param B blue value of the corrected color [0 ; 65535 but can be negative or superior to 65535] (return value) + * @param wip working profile + * @param isHLEnabled true if "Highlight Reconstruction " is enabled + * @param lowerCoef a float number between [0.95 ; 1.0[ + * The nearest it is from 1.0, the more precise it will be, and the longer too as more iteration will be necessary + * @param higherCoef a float number between [0.95 ; 1.0[ + * The nearest it is from 1.0, the more precise it will be, and the longer too as more iteration will be necessary + * @param neg (Debug target only) to calculate iterations for negatives values + * @param moreRGB (Debug target only) to calculate iterations for values >65535 + */ +#ifdef _DEBUG + static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); + static void gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); + static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb); +#else + static void gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); + static void gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); + static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef); +#endif + + + /** + * @brief Munsell gamut correction + * + * This function is the overall Munsell's corrections, but only on global statement. It may be better to use local statement with AllMunsellLch. + * They are named accordingly : gamutLchonly and AllMunsellLch + * It can be used before and after treatment (saturation, gamma, luminance, ...) + * + * @param labL L channel input and output image + * L channel's usual range is [0 ; 100], but values can be negative or >100 + * @param laba a channel input and output image + * @param labb b channel input and output image + * a and b channel's range is usually [-128 ; +128], but values can be >128 + * @param N Number of pixels to process + * @param corMunsell performs Munsell correction + * @param lumaMuns whether to apply luma correction or not (used only if corMuns=true) + * true: apply luma + chroma Munsell correction if delta L > 10; + * false: leaves luma untouched + * @param gamut performs gamutLch + * @param wip matrix for working profile + * @param multiThread whether to parallelize the loop or not + */ + static void LabGamutMunsell (float *labL, float *laba, float *labb, const int N, bool corMunsell, bool lumaMuns, bool isHLEnabled, bool gamut, const double wip[3][3], bool multiThread ); + + + /* + * @brief Skin tone protection factor + * Skin colors: mixed from NX2 skin color palette, Von Luschan, and photos of white, black, yellow people... + * There are some little exceptions, but it should cover 99% case. + * Pay attention to white balance, and do not change hue and saturation, upstream of the modification + * Used by vibrance + * @param lum luma value [0 ; 100] + * @param hue hue value [-PI ; +PI] + * @param chrom chroma value [0 ; 180] + * @param satreduc [0.1 ; 1] (return value) + * @param chromx [0 or 1], actually only 0 is used + */ + static void SkinSat (float lum, float hue, float chrom, float &satreduc);//jacques Skin color + + + /** + * @brief Munsell Lch correction + * Find the right LUT and calculate the correction + * @param lum luma value [0 ; 100] + * @param hue hue value [-PI ; +PI] + * @param chrom chroma value [0 ; 180] + * @param memChprov store chroma [0 ; 180] + * @param correction correction value, in radians [0 ; 0.45] + * @param lbe hue in function of chroma, in radian [-PI ; +PI] + * @param zone [1 ; 4] 1=PB correction + sky 2=red yellow correction 3=Green yellow correction 4=Red purple correction + * @param correctL true=enable the Luminance correction + */ + static void MunsellLch (float lum, float hue, float chrom, float memChprov, float &correction, int zone, float &lbe, bool &correctL);//jacques: Munsell correction + + + // -------------------------------- end Munsell + + + static void scalered ( const float rstprotection, const float param, const float limit, const float HH, const float deltaHH, float &scale, float &scaleext); + static void transitred (const float HH, const float Chprov1, const float dred, const float factorskin, const float protect_red, const float factorskinext, const float deltaHH, const float factorsat, float &factor); + static void skinred ( double J, double h, double sres, double Sp, float dred, float protect_red, int sk, float rstprotection, float ko, double &s); + static void skinredfloat ( float J, float h, float sres, float Sp, float dred, float protect_red, int sk, float rstprotection, float ko, float &s); +// static void scaleredcdbl ( float skinprot, float param, float limit, float HH, float deltaHH, float &scale,float &scaleext); + + static inline void SkinSatCbdl (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r) + { + + static const float C9 = 8.f, C8 = 15.f, C7 = 12.f, C4 = 7.f, C3 = 5.f, C2 = 5.f, C1 = 5.f; + static const float H9 = 0.05f, H8 = 0.25f, H7 = 0.1f, H4 = 0.02f, H3 = 0.02f, H2 = 0.1f, H1 = 0.1f, H10 = -0.2f, H11 = -0.2f; + + // "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1, uses imolicit factor 1.0 + // wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation, uses explicit facor 0.6 + // wide area for transition, uses explicit factor 0.4 + + if (lum >= 85.0f) { + if((hue > (t_l + 0.53f - H9) && hue < (t_r + H9)) && (chrom > 8.0f && chrom < (14.0f + C9))) { + scale = (100.f - skinprot) / 100.1f; + } else if (lum >= 92.0f) { + if((hue > t_l + 0.4f && hue < t_r) && (chrom > 7.0f && chrom < (15.0f))) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > b_l && hue < t_r) && (chrom > 7.0f && chrom < (18.0f))) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if ((hue > t_l + 0.4f && hue < t_r - 0.3f) && (chrom > 7.0f && chrom < (26.0f + C9))) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > b_l + 0.05f && hue < t_r) && (chrom > 7.0f && chrom < (35.0f + C9))) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 70.0f) { + if((hue > t_l + 0.15f && hue < (t_r - 0.2f + H8)) && (chrom > 8.0f && chrom < (35.0f + C8))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 52.0f) { + if((hue > t_l && hue < (t_r + H7)) && (chrom > 11.0f && chrom < (35.0f + C7))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 35.0f) { + if((hue > t_l && hue < (t_r + H4)) && (chrom > 13.0f && chrom < (37.0f + C4))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 20.0f) { + if((hue > t_l && hue < (t_r + H3)) && (chrom > 7.0f && chrom < (35.0f + C3) )) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 10.0f) { + if((hue > (t_l - 0.25f + H10) && hue < (t_r - 0.3f + H2)) && (chrom > 8.0f && chrom < (23.0f + C2))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (35.0f + C1) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.1f) && (chrom > 7.0f && chrom < (45.0f + C1) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if ((hue > (t_l - 0.2f + H10) && hue < (t_r - 0.3f + H1)) && (chrom > 8.0f && chrom < (23.0f + C1))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (35.0f + C1) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.1f) && (chrom > 7.0f && chrom < (45.0f + C1) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + + //extended zone for hair, beard and if user adjust high value for skinprot + if(skinprot > 85.f && chrom < 20.f && neg) { + float modula = -0.0666f * skinprot + 6.66f; + scale *= modula; + } + } + + static inline void SkinSatCbdl2 (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r, float b_r, int basc) + { + + static const float C9 = 8.f, C8 = 15.f, C7 = 12.f, C4 = 7.f, C3 = 5.f, C2 = 5.f, C1 = 5.f; + static const float H9 = 0.05f, H8 = 0.25f, H7 = 0.1f, H4 = 0.02f, H3 = 0.02f, H2 = 0.1f, H1 = 0.1f, H10 = -0.2f, H11 = -0.2f; + + // "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1, uses imolicit factor 1.0 + // wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation, uses explicit facor 0.6 + // wide area for transition, uses explicit factor 0.4 + if((b_l > -0.3f && b_r < 2.f) || basc == 0) { //range maxi skin + if (lum >= 85.0f) { + if((hue > (t_l + 0.53f - H9) && hue < (t_r + H9)) && (chrom > 8.0f && chrom < (14.0f + C9))) { + scale = (100.f - skinprot) / 100.1f; + } else if (lum >= 92.0f) { + if((hue > t_l + 0.4f && hue < t_r) && (chrom > 7.0f && chrom < (15.0f))) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > b_l && hue < t_r) && (chrom > 7.0f && chrom < (18.0f))) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if ((hue > t_l + 0.4f && hue < t_r - 0.3f) && (chrom > 7.0f && chrom < (26.0f + C9))) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > b_l + 0.05f && hue < t_r) && (chrom > 7.0f && chrom < (35.0f + C9))) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 70.0f) { + if((hue > t_l + 0.15f && hue < (t_r - 0.2f + H8)) && (chrom > 8.0f && chrom < (35.0f + C8))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 52.0f) { + if((hue > t_l && hue < (t_r + H7)) && (chrom > 11.0f && chrom < (35.0f + C7))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 35.0f) { + if((hue > t_l && hue < (t_r + H4)) && (chrom > 13.0f && chrom < (37.0f + C4))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 20.0f) { + if((hue > t_l && hue < (t_r + H3)) && (chrom > 7.0f && chrom < (35.0f + C3) )) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 10.0f) { + if((hue > (t_l - 0.25f + H10) && hue < (t_r - 0.3f + H2)) && (chrom > 8.0f && chrom < (23.0f + C2))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (35.0f + C1) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.1f) && (chrom > 7.0f && chrom < (45.0f + C1) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if ((hue > (t_l - 0.2f + H10) && hue < (t_r - 0.3f + H1)) && (chrom > 8.0f && chrom < (23.0f + C1))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (35.0f + C1) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.1f) && (chrom > 7.0f && chrom < (45.0f + C1) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + + //extended zone for hair, beard and if user adjust high value for skinprot + if(skinprot > 85.f && chrom < 20.f && neg) { + float modula = -0.0666f * skinprot + 6.66f; + scale *= modula; + } + } + //end hue skin algo + else if (basc == 1) { //not hue skin linear transition or mod chroma curve + if(hue >= t_l && hue <= t_r) { + scale = (100.f - skinprot) / 100.1f; + } else if(hue > b_l && hue < t_l) { + float sc = (100.f - skinprot) / 100.1f; + float aa = (1.f - sc) / (b_l - t_l); + float bb = 1.f - aa * b_l; + scale = aa * hue + bb; + } else if(hue > t_r && hue < b_r) { + float sc = (100.f - skinprot) / 100.1f; + float aa = (sc - 1.f) / (t_r - b_r); + float bb = 1.f - aa * b_r; + scale = aa * hue + bb; + } + } + } + + + + static inline void SkinSatCbdlCam (float lum, float hue, float chrom, float skinprot, float &scale, bool neg, float b_l, float t_l, float t_r) + { + + static const float C9 = 8.f, C8 = 15.f, C7 = 12.f, C4 = 7.f, C3 = 5.f, C2 = 5.f, C1 = 5.f; + static const float H9 = 0.05f, H8 = 0.25f, H7 = 0.1f, H4 = 0.02f, H3 = 0.02f, H2 = 0.1f, H1 = 0.1f, H10 = -0.2f, H11 = -0.2f; + + float HH = 0.f; + + if (hue > 8.6f && hue <= 74.f ) { + HH = (1.15f / 65.4f) * hue - 0.0012f; //H > 0.15 H<1.3 + } else if(hue > 0.f && hue <= 8.6f ) { + HH = (0.19f / 8.6f ) * hue - 0.04f; //H>-0.04 H < 0.15 + } else if(hue > 355.f && hue <= 360.f) { + HH = (0.11f / 5.0f ) * hue - 7.96f; //H>-0.15 <-0.04 + } else if(hue > 74.f && hue < 95.f ) { + HH = (0.30f / 21.0f) * hue + 0.24285f; //H>1.3 H<1.6 + } else if(hue >= 95.f && hue < 137.5f) { + HH = 0.01882f * hue - 0.18823f; // H>1.6 H<2.4 + } else if(hue > 285.f && hue <= 355.f) { + HH = 0.1642f * hue - 5.982f; //HH>-1.3 HH <-0.15 + } + + hue = HH; + + // "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1, uses imolicit factor 1.0 + // wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation, uses explicit facor 0.6 + // wide area for transition, uses explicit factor 0.4 + + if (lum >= 85.0f) { + if((hue > (t_l + 0.53f - H9) && hue < (t_r + H9)) && (chrom > 8.0f && chrom < (14.0f + C9))) { + scale = (100.f - skinprot) / 100.1f; + } else if (lum >= 92.0f) { + if((hue > t_l + 0.4f && hue < t_r) && (chrom > 7.0f && chrom < (15.0f))) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > b_l && hue < t_r) && (chrom > 7.0f && chrom < (18.0f))) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if ((hue > t_l + 0.4f && hue < t_r - 0.3f) && (chrom > 7.0f && chrom < (26.0f + C9))) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > b_l + 0.05f && hue < t_r) && (chrom > 7.0f && chrom < (35.0f + C9))) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 70.0f) { + if((hue > t_l + 0.15f && hue < (t_r - 0.2f + H8)) && (chrom > 8.0f && chrom < (35.0f + C8))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 52.0f) { + if((hue > t_l && hue < (t_r + H7)) && (chrom > 11.0f && chrom < (35.0f + C7))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 35.0f) { + if((hue > t_l && hue < (t_r + H4)) && (chrom > 13.0f && chrom < (37.0f + C4))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 20.0f) { + if((hue > t_l && hue < (t_r + H3)) && (chrom > 7.0f && chrom < (35.0f + C3) )) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (48.0f + C9) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r) && (chrom > 7.0f && chrom < (55.0f + C9) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if (lum >= 10.0f) { + if((hue > (t_l - 0.25f + H10) && hue < (t_r - 0.3f + H2)) && (chrom > 8.0f && chrom < (23.0f + C2))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (35.0f + C1) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.1f) && (chrom > 7.0f && chrom < (45.0f + C1) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + } else if ((hue > (t_l - 0.2f + H10) && hue < (t_r - 0.3f + H1)) && (chrom > 8.0f && chrom < (23.0f + C1))) { + scale = (100.f - skinprot) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.2f) && (chrom > 7.0f && chrom < (35.0f + C1) )) { + scale = (100.f - skinprot * 0.6f) / 100.1f; + } else if ((hue > (b_l + 0.07f + H11) && hue < t_r - 0.1f) && (chrom > 7.0f && chrom < (45.0f + C1) )) { + scale = (100.f - skinprot * 0.4f) / 100.1f; + } + + //extended zone for hair, beard and if user adjust high value for skinprot + if(skinprot > 85.f && chrom < 20.f && neg) { + float modula = -0.0666f * skinprot + 6.66f; + scale *= modula; + } + } + + + /** + * @brief Gamut correction in the XYZ color space + * @param X X channel input value and corrected output value [0 ; 65535] + * @param Y Y channel input value and corrected output value [0 ; 65535] + * @param Z Z channel input value and corrected output value [0 ; 65535] + * @param p working profile + */ + static void gamutmap(float &X, float &Y, float &Z, const double p[3][3]); + + + /** + * @brief Get HSV's hue from the Lab's hue + * @param HH Lab's hue value, in radians [-PI ; +PI] + * @return HSV's hue value [0 ; 1] + */ + static inline double huelab_to_huehsv2 (float HH) + { + //hr=translate Hue Lab value (-Pi +Pi) in approximative hr (hsv values) (0 1) [red 1/6 yellow 1/6 green 1/6 cyan 1/6 blue 1/6 magenta 1/6 ] + // with multi linear correspondances (I expect there is no error !!) + double hr = 0.0; + //allways put h between 0 and 1 + + if (HH >= 0.f && HH < 0.6f ) { + hr = 0.11666 * double(HH) + 0.93; //hr 0.93 1.00 full red + } else if (HH >= 0.6f && HH < 1.4f ) { + hr = 0.1125 * double(HH) - 0.0675; //hr 0.00 0.09 red yellow orange + } else if (HH >= 1.4f && HH < 2.f ) { + hr = 0.2666 * double(HH) - 0.2833; //hr 0.09 0.25 orange yellow + } else if (HH >= 2.f && HH < 3.14159f) { + hr = 0.1489 * double(HH) - 0.04785; //hr 0.25 0.42 yellow green green + } else if (HH >= -3.14159f && HH < -2.8f ) { + hr = 0.23419 * double(HH) + 1.1557; //hr 0.42 0.50 green + } else if (HH >= -2.8f && HH < -2.3f ) { + hr = 0.16 * double(HH) + 0.948; //hr 0.50 0.58 cyan + } else if (HH >= -2.3f && HH < -0.9f ) { + hr = 0.12143 * double(HH) + 0.85928; //hr 0.58 0.75 blue blue-sky + } else if (HH >= -0.9f && HH < -0.1f ) { + hr = 0.2125 * double(HH) + 0.94125; //hr 0.75 0.92 purple magenta + } else if (HH >= -0.1f && HH < 0.f ) { + hr = 0.1 * double(HH) + 0.93; //hr 0.92 0.93 red + } + + // in case of ! + if (hr < 0.0) { + hr += 1.0; + } else if(hr > 1.0) { + hr -= 1.0; + } + + return (hr); + } }; diff --git a/rtengine/colorclip.h b/rtengine/colorclip.h index 0526af83d..6a3144166 100644 --- a/rtengine/colorclip.h +++ b/rtengine/colorclip.h @@ -7,7 +7,7 @@ * 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 @@ -26,65 +26,75 @@ inline double tightestroot (double L, double a, double b, double r1, double r2, // gives back the tightest >0 amplification by which color clipping occures -inline double tightestroot (double L, double a, double b, double r1, double r2, double r3) { - - double an = a/500.0, bn = b/200.0, p = (L+16.0)/116.0; +inline double tightestroot (double L, double a, double b, double r1, double r2, double r3) +{ - double coeff3 = r1*an*an*an - r3*bn*bn*bn; - double coeff2 = 3.0 * p * (r1*an*an + r3*bn*bn); - double coeff1 = 3.0 * p*p * (r1*an - r3*bn); - double coeff0 = p*p*p*(r1+r2+r3) - 1.0; + double an = a / 500.0, bn = b / 200.0, p = (L + 16.0) / 116.0; - double a1 = coeff2 / coeff3; - double a2 = coeff1 / coeff3; - double a3 = coeff0 / coeff3; + double coeff3 = r1 * an * an * an - r3 * bn * bn * bn; + double coeff2 = 3.0 * p * (r1 * an * an + r3 * bn * bn); + double coeff1 = 3.0 * p * p * (r1 * an - r3 * bn); + double coeff0 = p * p * p * (r1 + r2 + r3) - 1.0; - double Q = (a1 * a1 - 3.0 * a2) / 9.0; - double R = (2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0; - double Qcubed = Q * Q * Q; - double d = Qcubed - R * R; + double a1 = coeff2 / coeff3; + double a2 = coeff1 / coeff3; + double a3 = coeff0 / coeff3; + + double Q = (a1 * a1 - 3.0 * a2) / 9.0; + double R = (2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0; + double Qcubed = Q * Q * Q; + double d = Qcubed - R * R; // printf ("input L=%g, a=%g, b=%g\n", L, a, b); // printf ("c1=%g, c2=%g, c3=%g, c4=%g\n", coeff3, coeff2, coeff1, coeff0); - /* Three real roots */ - if (d >= 0) { - double theta = acos(R / sqrt(Qcubed)); - double sqrtQ = sqrt(Q); - double x0 = -2.0 * sqrtQ * cos( theta / 3.0) - a1 / 3.0; - double x1 = -2.0 * sqrtQ * cos((theta + 2.0 * M_PI) / 3.0) - a1 / 3.0; - double x2 = -2.0 * sqrtQ * cos((theta + 4.0 * M_PI) / 3.0) - a1 / 3.0; - + /* Three real roots */ + if (d >= 0) { + double theta = acos(R / sqrt(Qcubed)); + double sqrtQ = sqrt(Q); + double x0 = -2.0 * sqrtQ * cos( theta / 3.0) - a1 / 3.0; + double x1 = -2.0 * sqrtQ * cos((theta + 2.0 * M_PI) / 3.0) - a1 / 3.0; + double x2 = -2.0 * sqrtQ * cos((theta + 4.0 * M_PI) / 3.0) - a1 / 3.0; + // printf ("3 roots: %g, %g, %g\n", x0, x1, x2); - SORT3 (x0,x1,x2,a1,a2,a3); - if (a1>0) - return a1; - if (a2>0) - return a2; - if (a3>0) - return a3; - return -1; - } + SORT3 (x0, x1, x2, a1, a2, a3); - /* One real root */ - else { + if (a1 > 0) { + return a1; + } + + if (a2 > 0) { + return a2; + } + + if (a3 > 0) { + return a3; + } + + return -1; + } + + /* One real root */ + else { // double e = pow(sqrt(-d) + fabs(R), 1.0 / 3.0); - double e = exp (1.0 / 3.0 * log (sqrt(-d) + fabs(R))); + double e = exp (1.0 / 3.0 * log (sqrt(-d) + fabs(R))); - if (R > 0) - e = -e; + if (R > 0) { + e = -e; + } - double x0 = (e + Q / e) - a1 / 3.0; + double x0 = (e + Q / e) - a1 / 3.0; // printf ("1 root: %g\n", x0); - if (x0<0) - return -1; - else - return x0; - } + if (x0 < 0) { + return -1; + } else { + return x0; + } + } } @@ -101,10 +111,10 @@ inline double tightestroot (double L, double a, double b, double r1, double r2, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -115,45 +125,45 @@ inline double tightestroot (double L, double a, double b, double r1, double r2, * * ------------------------------------------------------------------------ * - * Solve: - * coeff[3] * x^3 + coeff[2] * x^2 + coeff[1] * x + coeff[0] = 0 + * Solve: + * coeff[3] * x^3 + coeff[2] * x^2 + coeff[1] * x + coeff[0] = 0 + * + * returns: + * 3 - 3 real roots + * 1 - 1 real root (2 complex conjugate) * - * returns: - * 3 - 3 real roots - * 1 - 1 real root (2 complex conjugate) - * *******************************************************************************/ /*long FindCubicRoots(const FLOAT coeff[4], FLOAT x[3]) { - FLOAT a1 = coeff[2] / coeff[3]; - FLOAT a2 = coeff[1] / coeff[3]; - FLOAT a3 = coeff[0] / coeff[3]; + FLOAT a1 = coeff[2] / coeff[3]; + FLOAT a2 = coeff[1] / coeff[3]; + FLOAT a3 = coeff[0] / coeff[3]; - double_t Q = (a1 * a1 - 3 * a2) / 9; - double_t R = (2 * a1 * a1 * a1 - 9 * a1 * a2 + 27 * a3) / 54; - double_t Qcubed = Q * Q * Q; - double_t d = Qcubed - R * R; + double_t Q = (a1 * a1 - 3 * a2) / 9; + double_t R = (2 * a1 * a1 * a1 - 9 * a1 * a2 + 27 * a3) / 54; + double_t Qcubed = Q * Q * Q; + double_t d = Qcubed - R * R; - // Three real roots - if (d >= 0) { - double_t theta = acos(R / sqrt(Qcubed)); - double_t sqrtQ = sqrt(Q); - x[0] = -2 * sqrtQ * cos( theta / 3) - a1 / 3; - x[1] = -2 * sqrtQ * cos((theta + 2 * pi) / 3) - a1 / 3; - x[2] = -2 * sqrtQ * cos((theta + 4 * pi) / 3) - a1 / 3; - return (3); - } + // Three real roots + if (d >= 0) { + double_t theta = acos(R / sqrt(Qcubed)); + double_t sqrtQ = sqrt(Q); + x[0] = -2 * sqrtQ * cos( theta / 3) - a1 / 3; + x[1] = -2 * sqrtQ * cos((theta + 2 * pi) / 3) - a1 / 3; + x[2] = -2 * sqrtQ * cos((theta + 4 * pi) / 3) - a1 / 3; + return (3); + } - // One real root - else { - double_t e = pow(sqrt(-d) + fabs(R), 1. / 3.); - if (R > 0) - e = -e; - x[0] = (e + Q / e) - a1 / 3.; - return (1); - } + // One real root + else { + double_t e = pow(sqrt(-d) + fabs(R), 1. / 3.); + if (R > 0) + e = -e; + x[0] = (e + Q / e) - a1 / 3.; + return (1); + } } */ #endif diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index db473ec70..e22c2fd06 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -7,7 +7,7 @@ * 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 @@ -29,315 +29,330 @@ #define CLIPQQ(a) ((a)>0?((a)<250?(a):250):0) #define MAXR(a,b) ((a) > (b) ? (a) : (b)) -namespace rtengine { +namespace rtengine +{ - extern const Settings* settings; +extern const Settings* settings; - static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis observer 2� - {0.0000000,0.000000,0.000000}, {0.0000000,0.000000,0.000000}, {0.0001299,0.0003917,0.0006061}, - {0.0002321,0.000006965,0.001086}, {0.0004149,0.00001239,0.001946}, {0.0007416,0.00002202,0.003846}, - {0.001368,0.000039,0.006450001}, {0.002236,0.000064,0.01054999}, {0.004243,0.000120,0.02005001}, - {0.007650,0.000217,0.036210}, {0.014310,0.000396,0.06785001}, {0.023190,0.000640,0.110200}, - {0.043510,0.001210,0.207400}, {0.077630,0.002180,0.371300}, {0.134380,0.004000,0.645600}, - {0.214770,0.007300,1.0390501}, {0.283900,0.011600,1.385600}, {0.328500,0.016840,1.622960}, - {0.348280,0.023000,1.747060}, {0.348060,0.029800,1.782600}, {0.336200,0.038000,1.772110}, - {0.318700,0.048000,1.744100}, {0.290800,0.060000,1.669200}, {0.251100,0.073900,1.528100}, - {0.195360,0.090980,1.287640}, {0.142100,0.112600,1.041900}, {0.095640,0.139020,0.8129501}, - {0.05795001,0.169300,0.616200}, {0.032010,0.208020,0.465180}, {0.014700,0.258600,0.353300}, - {0.004900,0.323000,0.272000}, {0.002400,0.407300,0.212300}, {0.009300,0.503000,0.158200}, - {0.029100,0.608200,0.111700}, {0.063270,0.710000,0.07824999}, {0.109600,0.793200,0.05725001}, - {0.165500,0.862000,0.042160}, {0.2257499,0.9148501,0.029840}, {0.290400,0.954000,0.020300}, - {0.359700,0.980300,0.013400}, {0.43344990,0.9949501,0.008749999}, {0.5120501,1.000000,0.005749999}, - {0.594500,0.995000,0.003900}, {0.678400,0.978600,0.002749999}, {0.762100,0.952000,0.002100}, - {0.842500,0.915400,0.001800}, {0.916300,0.870000,0.001650001}, {0.978600,0.816300,0.001400}, - {1.026300,0.757000,0.001100}, {1.056700,0.694900,0.001000}, {1.062200,0.631000,0.000800}, - {1.045600,0.566800,0.000600}, {1.002600,0.503000,0.000340}, {0.938400,0.441200,0.000240}, - {0.8544499,0.381000,0.000190}, {0.751400,0.321000,0.000100}, {0.642400,0.265000,0.00004999999}, - {0.541900,0.217000,0.000030}, {0.447900,0.175000,0.000020}, {0.360800,0.138200,0.000010}, - {0.283500,0.107000,0.000000}, {0.218700,0.081600,0.000000}, {0.164900,0.061000,0.000000}, - {0.121200,0.044580,0.000000}, {0.087400,0.032000,0.000000}, {0.063600,0.023200,0.000000}, - {0.046770,0.017000,0.000000}, {0.032900,0.011920,0.000000}, {0.022700,0.008210,0.000000}, - {0.015840,0.005723,0.000000}, {0.01135916,0.004102,0.000000}, {0.008110916,0.002929,0.000000}, - {0.005790346,0.002091,0.000000}, {0.004109457,0.001484,0.000000}, {0.002899327,0.001047,0.000000}, - {0.00204919,0.000740,0.000000}, {0.001439971,0.000520,0.000000}, {0.0009999493,0.0003611,0.000000}, - {0.0006900786,0.0002492,0.000000}, {0.0004760213,0.0001719,0.000000}, {0.0003323011,0.000120,0.000000}, - {0.0002348261,0.0000848,0.000000}, {0.0001661505,0.000060,0.000000}, {0.000117413,0.0000424,0.000000}, - {0.00008307527,0.000030,0.000000}, {0.00005870652,0.0000212,0.000000}, {0.00004150994,0.00001499,0.000000}, - {0.00002935326,0.0000106,0.000000}, {0.00002067383,0.0000074657,0.000000}, {0.00001455977,0.0000052578,0.000000}, - {0.00001025398,0.0000037029,0.000000}, {0.000007221456,0.00000260778,0.000000}, {0.000005085868,0.0000018366,0.000000}, - {0.000003581652,0.0000012934,0.000000}, {0.000002522525,0.00000091093,0.000000}, {0.000001776509,0.00000064153,0.000000}, - {0.000001251141,0.00000045181,0.000000} - }; +static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis observer 2� + {0.0000000, 0.000000, 0.000000}, {0.0000000, 0.000000, 0.000000}, {0.0001299, 0.0003917, 0.0006061}, + {0.0002321, 0.000006965, 0.001086}, {0.0004149, 0.00001239, 0.001946}, {0.0007416, 0.00002202, 0.003846}, + {0.001368, 0.000039, 0.006450001}, {0.002236, 0.000064, 0.01054999}, {0.004243, 0.000120, 0.02005001}, + {0.007650, 0.000217, 0.036210}, {0.014310, 0.000396, 0.06785001}, {0.023190, 0.000640, 0.110200}, + {0.043510, 0.001210, 0.207400}, {0.077630, 0.002180, 0.371300}, {0.134380, 0.004000, 0.645600}, + {0.214770, 0.007300, 1.0390501}, {0.283900, 0.011600, 1.385600}, {0.328500, 0.016840, 1.622960}, + {0.348280, 0.023000, 1.747060}, {0.348060, 0.029800, 1.782600}, {0.336200, 0.038000, 1.772110}, + {0.318700, 0.048000, 1.744100}, {0.290800, 0.060000, 1.669200}, {0.251100, 0.073900, 1.528100}, + {0.195360, 0.090980, 1.287640}, {0.142100, 0.112600, 1.041900}, {0.095640, 0.139020, 0.8129501}, + {0.05795001, 0.169300, 0.616200}, {0.032010, 0.208020, 0.465180}, {0.014700, 0.258600, 0.353300}, + {0.004900, 0.323000, 0.272000}, {0.002400, 0.407300, 0.212300}, {0.009300, 0.503000, 0.158200}, + {0.029100, 0.608200, 0.111700}, {0.063270, 0.710000, 0.07824999}, {0.109600, 0.793200, 0.05725001}, + {0.165500, 0.862000, 0.042160}, {0.2257499, 0.9148501, 0.029840}, {0.290400, 0.954000, 0.020300}, + {0.359700, 0.980300, 0.013400}, {0.43344990, 0.9949501, 0.008749999}, {0.5120501, 1.000000, 0.005749999}, + {0.594500, 0.995000, 0.003900}, {0.678400, 0.978600, 0.002749999}, {0.762100, 0.952000, 0.002100}, + {0.842500, 0.915400, 0.001800}, {0.916300, 0.870000, 0.001650001}, {0.978600, 0.816300, 0.001400}, + {1.026300, 0.757000, 0.001100}, {1.056700, 0.694900, 0.001000}, {1.062200, 0.631000, 0.000800}, + {1.045600, 0.566800, 0.000600}, {1.002600, 0.503000, 0.000340}, {0.938400, 0.441200, 0.000240}, + {0.8544499, 0.381000, 0.000190}, {0.751400, 0.321000, 0.000100}, {0.642400, 0.265000, 0.00004999999}, + {0.541900, 0.217000, 0.000030}, {0.447900, 0.175000, 0.000020}, {0.360800, 0.138200, 0.000010}, + {0.283500, 0.107000, 0.000000}, {0.218700, 0.081600, 0.000000}, {0.164900, 0.061000, 0.000000}, + {0.121200, 0.044580, 0.000000}, {0.087400, 0.032000, 0.000000}, {0.063600, 0.023200, 0.000000}, + {0.046770, 0.017000, 0.000000}, {0.032900, 0.011920, 0.000000}, {0.022700, 0.008210, 0.000000}, + {0.015840, 0.005723, 0.000000}, {0.01135916, 0.004102, 0.000000}, {0.008110916, 0.002929, 0.000000}, + {0.005790346, 0.002091, 0.000000}, {0.004109457, 0.001484, 0.000000}, {0.002899327, 0.001047, 0.000000}, + {0.00204919, 0.000740, 0.000000}, {0.001439971, 0.000520, 0.000000}, {0.0009999493, 0.0003611, 0.000000}, + {0.0006900786, 0.0002492, 0.000000}, {0.0004760213, 0.0001719, 0.000000}, {0.0003323011, 0.000120, 0.000000}, + {0.0002348261, 0.0000848, 0.000000}, {0.0001661505, 0.000060, 0.000000}, {0.000117413, 0.0000424, 0.000000}, + {0.00008307527, 0.000030, 0.000000}, {0.00005870652, 0.0000212, 0.000000}, {0.00004150994, 0.00001499, 0.000000}, + {0.00002935326, 0.0000106, 0.000000}, {0.00002067383, 0.0000074657, 0.000000}, {0.00001455977, 0.0000052578, 0.000000}, + {0.00001025398, 0.0000037029, 0.000000}, {0.000007221456, 0.00000260778, 0.000000}, {0.000005085868, 0.0000018366, 0.000000}, + {0.000003581652, 0.0000012934, 0.000000}, {0.000002522525, 0.00000091093, 0.000000}, {0.000001776509, 0.00000064153, 0.000000}, + {0.000001251141, 0.00000045181, 0.000000} +}; -ColorTemp::ColorTemp (double t, double g, double e, Glib::ustring m) : temp(t), green(g), equal(e), method(m) { +ColorTemp::ColorTemp (double t, double g, double e, Glib::ustring m) : temp(t), green(g), equal(e), method(m) +{ clip (temp, green, equal); } -void ColorTemp::clip (double &temp, double &green) { +void ColorTemp::clip (double &temp, double &green) +{ - if (temp < MINTEMP) + if (temp < MINTEMP) { temp = MINTEMP; - else if (temp > MAXTEMP) + } else if (temp > MAXTEMP) { temp = MAXTEMP; + } - if (green < MINGREEN) + if (green < MINGREEN) { green = MINGREEN; - else if (green > MAXGREEN) + } else if (green > MAXGREEN) { green = MAXGREEN; + } } -void ColorTemp::clip (double &temp, double &green, double &equal) { +void ColorTemp::clip (double &temp, double &green, double &equal) +{ - if (temp < MINTEMP) + if (temp < MINTEMP) { temp = MINTEMP; - else if (temp > MAXTEMP) + } else if (temp > MAXTEMP) { temp = MAXTEMP; + } - if (green < MINGREEN) + if (green < MINGREEN) { green = MINGREEN; - else if (green > MAXGREEN) + } else if (green > MAXGREEN) { green = MAXGREEN; + } - if(equal < MINEQUAL) + if(equal < MINEQUAL) { equal = MINEQUAL; - else if(equal > MAXEQUAL) + } else if(equal > MAXEQUAL) { equal = MAXEQUAL; + } } -ColorTemp::ColorTemp (double mulr, double mulg, double mulb, double e) : equal(e) { +ColorTemp::ColorTemp (double mulr, double mulg, double mulb, double e) : equal(e) +{ method = "Custom"; mul2temp (mulr, mulg, mulb, equal, temp, green); } -void ColorTemp::mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green) { +void ColorTemp::mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green) +{ - double maxtemp=double(MAXTEMP), mintemp=double(MINTEMP); + double maxtemp = double(MAXTEMP), mintemp = double(MINTEMP); double tmpr, tmpg, tmpb; - temp=(maxtemp+mintemp)/2; + temp = (maxtemp + mintemp) / 2; - while (maxtemp-mintemp>1) { + while (maxtemp - mintemp > 1) { temp2mul (temp, 1.0, equal, tmpr, tmpg, tmpb); - if (tmpb/tmpr > bmul/rmul) + + if (tmpb / tmpr > bmul / rmul) { maxtemp = temp; - else + } else { mintemp = temp; - temp=(maxtemp+mintemp)/2; + } + + temp = (maxtemp + mintemp) / 2; } - green = (tmpg/tmpr) / (gmul/rmul); - clip (temp, green); + + green = (tmpg / tmpr) / (gmul / rmul); + clip (temp, green); } // spectral data for Daylight direct Sun: I have choose 5300K because Nikon=5200K, Olympus=5300K, Panasonic=5500K, Leica=5400K, Minolta=5100K const double ColorTemp::Daylight5300_spect[97] = { - 24.82,26.27,27.72,28.97,30.22,29.71,29.19,31.95,34.71,45.49,56.26,59.97,63.68,65.30,66.92,65.39,63.86,72.59,81.32,87.53,93.73,95.15,96.56,96.55,96.54,98.13,99.73,97.70,95.66,97.19,98.72, - 98.90,99.08,98.98,98.87,101.13,103.39,102.48,101.57,102.14,102.71,101.36,100.00,98.71,97.42,97.81,98.21,95.20,92.20,93.92,95.63,96.15,96.67,96.34,96.01,94.21,92.41,93.58,94.74,93.05,91.36,92.29, - 93.21,95.25,97.28,95.30,93.32,87.92,82.51,84.29,86.06,86.94,87.81,80.24,72.68,77.32,81.96,84.88,87.79,81.01,74.22,64.41,54.60,66.55,78.51,76.35,74.20,74.79,75.38,72.48,69.58,65.11,60.64, - 63.88,67.13,68.85,70.57 + 24.82, 26.27, 27.72, 28.97, 30.22, 29.71, 29.19, 31.95, 34.71, 45.49, 56.26, 59.97, 63.68, 65.30, 66.92, 65.39, 63.86, 72.59, 81.32, 87.53, 93.73, 95.15, 96.56, 96.55, 96.54, 98.13, 99.73, 97.70, 95.66, 97.19, 98.72, + 98.90, 99.08, 98.98, 98.87, 101.13, 103.39, 102.48, 101.57, 102.14, 102.71, 101.36, 100.00, 98.71, 97.42, 97.81, 98.21, 95.20, 92.20, 93.92, 95.63, 96.15, 96.67, 96.34, 96.01, 94.21, 92.41, 93.58, 94.74, 93.05, 91.36, 92.29, + 93.21, 95.25, 97.28, 95.30, 93.32, 87.92, 82.51, 84.29, 86.06, 86.94, 87.81, 80.24, 72.68, 77.32, 81.96, 84.88, 87.79, 81.01, 74.22, 64.41, 54.60, 66.55, 78.51, 76.35, 74.20, 74.79, 75.38, 72.48, 69.58, 65.11, 60.64, + 63.88, 67.13, 68.85, 70.57 }; //spectral data for Daylight Cloudy: I have choose 6200K because Nikon=6000K, Olympus=6000K, Panasonic=6200K, Leica=6400K, Minolta=6500K const double ColorTemp::Cloudy6200_spect[97] = { - 39.50,40.57,41.63,43.85,46.08,45.38,44.69,47.20,49.71,63.06,76.41,80.59,84.77,85.91,87.05,84.14,81.23,90.29,99.35,105.47,111.58,112.23,112.87,111.74,110.62,111.41,112.20,108.98,105.76,106.32, - 106.89,106.34,105.79,104.62,103.45,105.09,106.72,105.24,103.76,103.75,103.75,101.87,100.00,98.29,96.58,96.46,96.34,92.85,89.37,90.25,91.12,91.06,90.99,90.17,89.35,87.22,85.10,85.48,85.85, - 84.03,82.20,82.45,82.69,83.92,85.15,83.14,81.13,76.65,72.17,73.27,74.36,75.65,76.95,70.34,63.74,67.98,72.22,74.88,77.54,71.59,65.65,56.82,47.99,58.53,69.06,67.27,65.47,65.96,66.44,63.92,61.41,57.52, - 53.63,56.47,59.31,60.80,62.29 + 39.50, 40.57, 41.63, 43.85, 46.08, 45.38, 44.69, 47.20, 49.71, 63.06, 76.41, 80.59, 84.77, 85.91, 87.05, 84.14, 81.23, 90.29, 99.35, 105.47, 111.58, 112.23, 112.87, 111.74, 110.62, 111.41, 112.20, 108.98, 105.76, 106.32, + 106.89, 106.34, 105.79, 104.62, 103.45, 105.09, 106.72, 105.24, 103.76, 103.75, 103.75, 101.87, 100.00, 98.29, 96.58, 96.46, 96.34, 92.85, 89.37, 90.25, 91.12, 91.06, 90.99, 90.17, 89.35, 87.22, 85.10, 85.48, 85.85, + 84.03, 82.20, 82.45, 82.69, 83.92, 85.15, 83.14, 81.13, 76.65, 72.17, 73.27, 74.36, 75.65, 76.95, 70.34, 63.74, 67.98, 72.22, 74.88, 77.54, 71.59, 65.65, 56.82, 47.99, 58.53, 69.06, 67.27, 65.47, 65.96, 66.44, 63.92, 61.41, 57.52, + 53.63, 56.47, 59.31, 60.80, 62.29 }; //spectral data for Daylight Shade: I have choose 7600K because Nikon=8000K, Olympus=7500K, Panasonic=7500K, Leica=7500K, Minolta=7500K const double ColorTemp::Shade7600_spect[97] = { - 64.42,64.46,64.51,68.35,72.20,70.22,68.24,69.79,71.35,87.49,103.64,108.68,113.72,114.12,114.53,109.54,104.55,113.59,122.63,128.52,134.41,134.02,133.63,131.02,128.41,128.08,127.75,123.16, - 118.57,117.89,117.22,115.72,114.22,111.60,108.99,109.84,110.68,108.57,106.45,105.71,104.98,102.49,100.00,97.78,95.55,94.82,94.08,90.47,86.87,86.94,87.01,86.45,85.88,84.57,83.27,80.83,78.40,78.21, - 78.03,76.22,74.42,74.15,73.89,74.41,74.92,73.01,71.09,67.26,63.42,64.01,64.60,66.10,67.60,61.83,56.06,59.94,63.82,66.27,68.71,63.49,58.26,50.30,42.34,51.64,60.95,59.45,57.95,58.35,58.76,56.57, - 54.38,51.00,47.62,50.10,52.58,53.88,55.19 + 64.42, 64.46, 64.51, 68.35, 72.20, 70.22, 68.24, 69.79, 71.35, 87.49, 103.64, 108.68, 113.72, 114.12, 114.53, 109.54, 104.55, 113.59, 122.63, 128.52, 134.41, 134.02, 133.63, 131.02, 128.41, 128.08, 127.75, 123.16, + 118.57, 117.89, 117.22, 115.72, 114.22, 111.60, 108.99, 109.84, 110.68, 108.57, 106.45, 105.71, 104.98, 102.49, 100.00, 97.78, 95.55, 94.82, 94.08, 90.47, 86.87, 86.94, 87.01, 86.45, 85.88, 84.57, 83.27, 80.83, 78.40, 78.21, + 78.03, 76.22, 74.42, 74.15, 73.89, 74.41, 74.92, 73.01, 71.09, 67.26, 63.42, 64.01, 64.60, 66.10, 67.60, 61.83, 56.06, 59.94, 63.82, 66.27, 68.71, 63.49, 58.26, 50.30, 42.34, 51.64, 60.95, 59.45, 57.95, 58.35, 58.76, 56.57, + 54.38, 51.00, 47.62, 50.10, 52.58, 53.88, 55.19 }; //spectral data for tungsten - incandescent 2856K const double ColorTemp::A2856_spect[97] = { - 4.75,5.42,6.15,6.95,7.83,8.78,9.80,10.91,12.09,13.36,14.72,16.16,17.69,19.30,21.01,22.80,24.68,26.65,28.71,30.86,33.10,35.42,37.82,40.31,42.88,45.53,48.25,51.05,53.92,56.87,59.87,62.94,66.07,69.26,72.50, - 75.80,79.14,82.53,85.95,89.42,92.91,96.44,100.00,103.58,107.18,110.80,114.43,118.07,121.72,125.38,129.03,132.68,136.33,139.97,143.60,147.21,150.81,154.39,157.95,161.48,164.99,168.47,171.92,175.34, - 178.72,182.07,185.38,188.65,191.88,195.06,198.20,201.30,204.34,207.34,210.29,213.19,216.04,218.84,221.58,224.28,226.91,229.49,232.02,234.49,236.91,239.27,241.57,243.82,246.01,248.14,250.21,252.23,254.19, - 256.10,257.95,259.74,261.47 + 4.75, 5.42, 6.15, 6.95, 7.83, 8.78, 9.80, 10.91, 12.09, 13.36, 14.72, 16.16, 17.69, 19.30, 21.01, 22.80, 24.68, 26.65, 28.71, 30.86, 33.10, 35.42, 37.82, 40.31, 42.88, 45.53, 48.25, 51.05, 53.92, 56.87, 59.87, 62.94, 66.07, 69.26, 72.50, + 75.80, 79.14, 82.53, 85.95, 89.42, 92.91, 96.44, 100.00, 103.58, 107.18, 110.80, 114.43, 118.07, 121.72, 125.38, 129.03, 132.68, 136.33, 139.97, 143.60, 147.21, 150.81, 154.39, 157.95, 161.48, 164.99, 168.47, 171.92, 175.34, + 178.72, 182.07, 185.38, 188.65, 191.88, 195.06, 198.20, 201.30, 204.34, 207.34, 210.29, 213.19, 216.04, 218.84, 221.58, 224.28, 226.91, 229.49, 232.02, 234.49, 236.91, 239.27, 241.57, 243.82, 246.01, 248.14, 250.21, 252.23, 254.19, + 256.10, 257.95, 259.74, 261.47 }; //spectral data for fluo F1 Daylight 6430K const double ColorTemp::FluoF1_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.87,2.36,2.94,3.47,5.17,19.49,6.13,6.24,7.01,7.79,8.56,43.67,16.94,10.72,11.35,11.89,12.37,12.75,13.00,13.15,13.23,13.17,13.13,12.85,12.52, - 12.20,11.83,11.50,11.22,11.05,11.03,11.18,11.53,27.74,17.05,13.55,14.33,15.01,15.52,18.29,19.55,15.48,14.91,14.15,13.22,12.19,11.12,10.03,8.95,7.96,7.02,6.20,5.42,4.73,4.15,3.64,3.20,2.81, - 2.47,2.18,1.93,1.72,1.67,1.43,1.29,1.19,1.08,0.96,0.88,0.81,0.77,0.75,0.73,0.68,0.69,0.64,0.68,0.69,0.61,0.52,0.43,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.87, 2.36, 2.94, 3.47, 5.17, 19.49, 6.13, 6.24, 7.01, 7.79, 8.56, 43.67, 16.94, 10.72, 11.35, 11.89, 12.37, 12.75, 13.00, 13.15, 13.23, 13.17, 13.13, 12.85, 12.52, + 12.20, 11.83, 11.50, 11.22, 11.05, 11.03, 11.18, 11.53, 27.74, 17.05, 13.55, 14.33, 15.01, 15.52, 18.29, 19.55, 15.48, 14.91, 14.15, 13.22, 12.19, 11.12, 10.03, 8.95, 7.96, 7.02, 6.20, 5.42, 4.73, 4.15, 3.64, 3.20, 2.81, + 2.47, 2.18, 1.93, 1.72, 1.67, 1.43, 1.29, 1.19, 1.08, 0.96, 0.88, 0.81, 0.77, 0.75, 0.73, 0.68, 0.69, 0.64, 0.68, 0.69, 0.61, 0.52, 0.43, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F2 Cool white 4230K const double ColorTemp::FluoF2_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.18,1.48,1.84,2.15,3.44,15.69,3.85,3.74,4.19,4.62,5.06,34.98,11.81,6.27,6.63,6.93,7.19,7.40,7.54,7.62,7.65,7.62,7.62,7.45,7.28,7.15,7.05,7.04,7.16,7.47,8.04,8.88,10.01,24.88,16.64,14.59,16.16,17.60,18.62,21.47,22.79,19.29,18.66,17.73,16.54,15.21,13.80,12.36,10.95,9.65,8.40,7.32,6.31,5.43,4.68,4.02,3.45, - 2.96,2.55,2.19,1.89,1.64,1.53,1.27,1.10,0.99,0.88,0.76,0.68,0.61,0.56,0.54,0.51,0.47,0.47,0.43,0.46,0.47,0.40,0.33,0.27,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.18, 1.48, 1.84, 2.15, 3.44, 15.69, 3.85, 3.74, 4.19, 4.62, 5.06, 34.98, 11.81, 6.27, 6.63, 6.93, 7.19, 7.40, 7.54, 7.62, 7.65, 7.62, 7.62, 7.45, 7.28, 7.15, 7.05, 7.04, 7.16, 7.47, 8.04, 8.88, 10.01, 24.88, 16.64, 14.59, 16.16, 17.60, 18.62, 21.47, 22.79, 19.29, 18.66, 17.73, 16.54, 15.21, 13.80, 12.36, 10.95, 9.65, 8.40, 7.32, 6.31, 5.43, 4.68, 4.02, 3.45, + 2.96, 2.55, 2.19, 1.89, 1.64, 1.53, 1.27, 1.10, 0.99, 0.88, 0.76, 0.68, 0.61, 0.56, 0.54, 0.51, 0.47, 0.47, 0.43, 0.46, 0.47, 0.40, 0.33, 0.27, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F3 White 3450K const double ColorTemp::FluoF3_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.82,1.02,1.26,1.44,2.57,14.36,2.70,2.45,2.73,3.00,3.28,31.85,9.47,4.02,4.25,4.44,4.59,4.72,4.80,4.86,4.87,4.85,4.88,4.77,4.67,4.62,4.62,4.73,4.99,5.48,6.25, - 7.34,8.78,23.82,16.14,14.59,16.63,18.49,19.95,23.11,24.69,21.41,20.85,19.93,18.67,17.22,15.65,14.04,12.45,10.95,9.51,8.27,7.11,6.09,5.22,4.45,3.80,3.23,2.75,2.33,1.99,1.70,1.55, - 1.27,1.09,0.96,0.83,0.71,0.62,0.54,0.49,0.46,0.43,0.39,0.39,0.35,0.38,0.39,0.33,0.28,0.21,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.82, 1.02, 1.26, 1.44, 2.57, 14.36, 2.70, 2.45, 2.73, 3.00, 3.28, 31.85, 9.47, 4.02, 4.25, 4.44, 4.59, 4.72, 4.80, 4.86, 4.87, 4.85, 4.88, 4.77, 4.67, 4.62, 4.62, 4.73, 4.99, 5.48, 6.25, + 7.34, 8.78, 23.82, 16.14, 14.59, 16.63, 18.49, 19.95, 23.11, 24.69, 21.41, 20.85, 19.93, 18.67, 17.22, 15.65, 14.04, 12.45, 10.95, 9.51, 8.27, 7.11, 6.09, 5.22, 4.45, 3.80, 3.23, 2.75, 2.33, 1.99, 1.70, 1.55, + 1.27, 1.09, 0.96, 0.83, 0.71, 0.62, 0.54, 0.49, 0.46, 0.43, 0.39, 0.39, 0.35, 0.38, 0.39, 0.33, 0.28, 0.21, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F4 Warm white 2940K const double ColorTemp::FluoF4_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.57,0.70,0.87,0.98,2.01,13.75,1.95,1.59,1.76,1.93,2.10,30.28,8.03,2.55,2.70,2.82,2.91,2.99,3.04,3.08,3.09,3.09,3.14,3.06,3.00,2.98,3.01, - 3.14,3.41,3.90,4.69,5.81,7.32,22.59,15.11,13.88,16.33,18.68,20.64,24.28,26.26,23.28,22.94,22.14,20.91,19.43,17.74,16.00,14.42,12.56,10.93,9.52,8.18,7.01,6.00,5.11,4.36,3.69,3.13,2.64, - 2.24,1.91,1.70,1.39,1.18,1.03,0.88,0.74,0.64,0.54,0.49,0.46,0.42,0.37,0.37,0.33,0.35,0.36,0.31,0.26,0.19,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.57, 0.70, 0.87, 0.98, 2.01, 13.75, 1.95, 1.59, 1.76, 1.93, 2.10, 30.28, 8.03, 2.55, 2.70, 2.82, 2.91, 2.99, 3.04, 3.08, 3.09, 3.09, 3.14, 3.06, 3.00, 2.98, 3.01, + 3.14, 3.41, 3.90, 4.69, 5.81, 7.32, 22.59, 15.11, 13.88, 16.33, 18.68, 20.64, 24.28, 26.26, 23.28, 22.94, 22.14, 20.91, 19.43, 17.74, 16.00, 14.42, 12.56, 10.93, 9.52, 8.18, 7.01, 6.00, 5.11, 4.36, 3.69, 3.13, 2.64, + 2.24, 1.91, 1.70, 1.39, 1.18, 1.03, 0.88, 0.74, 0.64, 0.54, 0.49, 0.46, 0.42, 0.37, 0.37, 0.33, 0.35, 0.36, 0.31, 0.26, 0.19, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F5 Daylight 6350K const double ColorTemp::FluoF5_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.87,2.35,2.92,3.45,5.10,18.91,6.00,6.11,6.85,7.58,8.31,40.76,16.06,10.32,10.91,11.40,11.83,12.17,12.40,12.54,12.58,12.52,12.47,12.20,11.89, - 11.61,11.33,11.10,10.96,10.97,11.16,11.54,12.12,27.78,17.73,14.47,15.20,15.77,16.10,18.54,19.50,15.39,14.64,13.72,12.69,11.57,10.45,9.35,8.29,7.32,6.41,5.63,4.90,4.26, - 3.72,3.25,2.83,2.49,2.19,1.93,1.71,1.52,1.43,1.26,1.13,1.05,0.96,0.85,0.78,0.72,0.68,0.67,0.65,0.61,0.62,0.59,0.62,0.64,0.55,0.47,0.40,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.87, 2.35, 2.92, 3.45, 5.10, 18.91, 6.00, 6.11, 6.85, 7.58, 8.31, 40.76, 16.06, 10.32, 10.91, 11.40, 11.83, 12.17, 12.40, 12.54, 12.58, 12.52, 12.47, 12.20, 11.89, + 11.61, 11.33, 11.10, 10.96, 10.97, 11.16, 11.54, 12.12, 27.78, 17.73, 14.47, 15.20, 15.77, 16.10, 18.54, 19.50, 15.39, 14.64, 13.72, 12.69, 11.57, 10.45, 9.35, 8.29, 7.32, 6.41, 5.63, 4.90, 4.26, + 3.72, 3.25, 2.83, 2.49, 2.19, 1.93, 1.71, 1.52, 1.43, 1.26, 1.13, 1.05, 0.96, 0.85, 0.78, 0.72, 0.68, 0.67, 0.65, 0.61, 0.62, 0.59, 0.62, 0.64, 0.55, 0.47, 0.40, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F6 Lite white 4150K const double ColorTemp::FluoF6_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.05,1.31,1.63,1.90,3.11,14.8,3.43,3.30,3.68,4.07,4.45,32.61,10.74,5.48,5.78,6.03,6.25,6.41,6.52,6.58,6.59,6.56,6.56,6.42,6.28,6.20,6.19,6.30,6.60,7.12,7.94,9.07,10.49,25.22,17.46,15.63,17.22,18.53, - 19.43,21.97,23.01,19.41,18.56,17.42,16.09,14.64,13.15,11.68,10.25,8.96,7.74,6.69,5.71,4.87,4.16,3.55,3.02,2.57,2.20,1.87,1.60,1.37,1.29,1.05,0.91,0.81,0.71,0.61,0.54,0.48,0.44, - 0.43,0.40,0.37,0.38,0.35,0.39,0.41,0.33,0.26,0.21,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.05, 1.31, 1.63, 1.90, 3.11, 14.8, 3.43, 3.30, 3.68, 4.07, 4.45, 32.61, 10.74, 5.48, 5.78, 6.03, 6.25, 6.41, 6.52, 6.58, 6.59, 6.56, 6.56, 6.42, 6.28, 6.20, 6.19, 6.30, 6.60, 7.12, 7.94, 9.07, 10.49, 25.22, 17.46, 15.63, 17.22, 18.53, + 19.43, 21.97, 23.01, 19.41, 18.56, 17.42, 16.09, 14.64, 13.15, 11.68, 10.25, 8.96, 7.74, 6.69, 5.71, 4.87, 4.16, 3.55, 3.02, 2.57, 2.20, 1.87, 1.60, 1.37, 1.29, 1.05, 0.91, 0.81, 0.71, 0.61, 0.54, 0.48, 0.44, + 0.43, 0.40, 0.37, 0.38, 0.35, 0.39, 0.41, 0.33, 0.26, 0.21, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F7 D65 Daylight simulator 6500K const double ColorTemp::FluoF7_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,2.56,3.18,3.84,4.53,6.15,19.37,7.37,7.05,7.71,8.41,9.15,44.14,17.52,11.35,12.00,12.58,13.08,13.45,13.71,13.88,13.95,13.93,13.82,13.64,13.43,13.25,13.08,12.93,12.78,12.60, - 12.44,12.33,12.26,29.52,17.05,12.44,12.58,12.72,12.83,15.46,16.75,12.83,12.67,12.43,12.19,11.89,11.60,11.35,11.12,10.95,10.76,10.42,10.11,10.04,10.02,10.11,9.87,8.65,7.27,6.44,5.83,5.41, - 5.04,4.57,4.12,3.77,3.46,3.08,2.73,2.47,2.25,2.06,1.90,1.75,1.62,1.54,1.45,1.32,1.17,0.99,0.81,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.56, 3.18, 3.84, 4.53, 6.15, 19.37, 7.37, 7.05, 7.71, 8.41, 9.15, 44.14, 17.52, 11.35, 12.00, 12.58, 13.08, 13.45, 13.71, 13.88, 13.95, 13.93, 13.82, 13.64, 13.43, 13.25, 13.08, 12.93, 12.78, 12.60, + 12.44, 12.33, 12.26, 29.52, 17.05, 12.44, 12.58, 12.72, 12.83, 15.46, 16.75, 12.83, 12.67, 12.43, 12.19, 11.89, 11.60, 11.35, 11.12, 10.95, 10.76, 10.42, 10.11, 10.04, 10.02, 10.11, 9.87, 8.65, 7.27, 6.44, 5.83, 5.41, + 5.04, 4.57, 4.12, 3.77, 3.46, 3.08, 2.73, 2.47, 2.25, 2.06, 1.90, 1.75, 1.62, 1.54, 1.45, 1.32, 1.17, 0.99, 0.81, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F8 D50 simulator Sylvania F40 Design 5000K const double ColorTemp::FluoF8_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.21,1.5,1.81,2.13,3.17,13.08,3.83,3.45,3.86,4.42,5.09,34.1,12.42,7.68,8.60,9.46,10.24,10.84,11.33,11.71,11.98,12.17,12.28,12.32,12.35,12.44,12.55,12.68,12.77,12.72, - 12.60,12.43,12.22,28.96,16.51,11.79,11.76,11.77,11.84,14.61,16.11,12.34,13.61,13.87,14.07,14.20,14.16,14.13,14.34,14.50,14.46,14.00,12.58,10.99,9.98,9.22,8.62,8.07,7.39,6.71,6.16,5.63,5.03,4.46,4.02,3.66, - 3.36,3.09,2.85,2.65,2.51,2.37,2.15,1.89,1.61,1.32,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.21, 1.5, 1.81, 2.13, 3.17, 13.08, 3.83, 3.45, 3.86, 4.42, 5.09, 34.1, 12.42, 7.68, 8.60, 9.46, 10.24, 10.84, 11.33, 11.71, 11.98, 12.17, 12.28, 12.32, 12.35, 12.44, 12.55, 12.68, 12.77, 12.72, + 12.60, 12.43, 12.22, 28.96, 16.51, 11.79, 11.76, 11.77, 11.84, 14.61, 16.11, 12.34, 13.61, 13.87, 14.07, 14.20, 14.16, 14.13, 14.34, 14.50, 14.46, 14.00, 12.58, 10.99, 9.98, 9.22, 8.62, 8.07, 7.39, 6.71, 6.16, 5.63, 5.03, 4.46, 4.02, 3.66, + 3.36, 3.09, 2.85, 2.65, 2.51, 2.37, 2.15, 1.89, 1.61, 1.32, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F9 Cool white deluxe 4150K const double ColorTemp::FluoF9_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.9,1.12,1.36,1.60,2.59,12.8,3.05,2.56,2.86,3.30,3.82,32.62,10.77,5.84,6.57,7.25,7.86,8.35,8.75,9.06,9.31,9.48,9.61,9.68,10.04,10.26,10.48,10.63,10.76,10.96, - 11.18,27.71,16.29,12.28,12.74,13.21,13.65,16.57,18.14,14.55,14.65,14.66,14.61,14.50,14.39,14.40,14.47,14.62,14.72,14.55,14.4,14.58,14.88,15.51,15.47,13.20,10.57,9.18,8.25,7.57,7.03, - 6.35,5.72,5.25,4.80,4.29,3.80,3.43,3.12,2.86,2.64,2.43,2.26,2.14,2.02,1.83,1.61,1.38,1.12,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.9, 1.12, 1.36, 1.60, 2.59, 12.8, 3.05, 2.56, 2.86, 3.30, 3.82, 32.62, 10.77, 5.84, 6.57, 7.25, 7.86, 8.35, 8.75, 9.06, 9.31, 9.48, 9.61, 9.68, 10.04, 10.26, 10.48, 10.63, 10.76, 10.96, + 11.18, 27.71, 16.29, 12.28, 12.74, 13.21, 13.65, 16.57, 18.14, 14.55, 14.65, 14.66, 14.61, 14.50, 14.39, 14.40, 14.47, 14.62, 14.72, 14.55, 14.4, 14.58, 14.88, 15.51, 15.47, 13.20, 10.57, 9.18, 8.25, 7.57, 7.03, + 6.35, 5.72, 5.25, 4.80, 4.29, 3.80, 3.43, 3.12, 2.86, 2.64, 2.43, 2.26, 2.14, 2.02, 1.83, 1.61, 1.38, 1.12, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F10 Philips TL85 - 5000K const double ColorTemp::FluoF10_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.11,0.63,0.62,0.57,1.48,12.16,2.12,2.70,3.74,5.14,6.75,34.39,14.86,10.4,10.76,10.11,9.27,8.29,7.29,7.91,16.64,16.73,10.44,5.94,3.34,2.35,1.88,1.59,1.47, - 1.80,5.71,40.98,73.69,33.61,8.24,3.38,2.47,4.86,11.45,14.79,12.16,8.97,6.52,8.81,44.12,34.55,12.09,12.15,10.52,4.43,1.95,2.19,3.19,2.77,2.29,2.00,1.52,1.35,1.47,1.79,1.74,1.02,1.14, - 3.32,4.49,2.05,0.49,0.24,0.21,0.21,0.24,0.24,0.21,0.17,0.21,0.22,0.17,0.12,0.09,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.11, 0.63, 0.62, 0.57, 1.48, 12.16, 2.12, 2.70, 3.74, 5.14, 6.75, 34.39, 14.86, 10.4, 10.76, 10.11, 9.27, 8.29, 7.29, 7.91, 16.64, 16.73, 10.44, 5.94, 3.34, 2.35, 1.88, 1.59, 1.47, + 1.80, 5.71, 40.98, 73.69, 33.61, 8.24, 3.38, 2.47, 4.86, 11.45, 14.79, 12.16, 8.97, 6.52, 8.81, 44.12, 34.55, 12.09, 12.15, 10.52, 4.43, 1.95, 2.19, 3.19, 2.77, 2.29, 2.00, 1.52, 1.35, 1.47, 1.79, 1.74, 1.02, 1.14, + 3.32, 4.49, 2.05, 0.49, 0.24, 0.21, 0.21, 0.24, 0.24, 0.21, 0.17, 0.21, 0.22, 0.17, 0.12, 0.09, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F11 Philips TL84 4150K const double ColorTemp::FluoF11_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.91,0.63,0.46,0.37,1.29,12.68,1.59,1.79,2.46,3.38,4.49,33.94,12.13,6.95,7.19,7.12,6.72,6.13,5.46,4.79,5.66,14.29,14.96,8.97,4.72,2.33,1.47,1.10,0.89,0.83,1.18,4.90,39.59, - 72.84,32.61,7.52,2.83,1.96,1.67,4.43,11.28,14.76,12.73,9.74,7.33,9.72,55.27,42.58,13.18,13.16,12.26,5.11,2.07,2.34,3.58,3.01,2.48,2.14,1.54,1.33,1.46,1.94,2.00,1.20,1.35,4.10,5.58, - 2.51,0.57,0.27,0.23,0.21,0.24,0.24,0.20,0.24,0.32,0.26,0.16,0.12,0.09,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.91, 0.63, 0.46, 0.37, 1.29, 12.68, 1.59, 1.79, 2.46, 3.38, 4.49, 33.94, 12.13, 6.95, 7.19, 7.12, 6.72, 6.13, 5.46, 4.79, 5.66, 14.29, 14.96, 8.97, 4.72, 2.33, 1.47, 1.10, 0.89, 0.83, 1.18, 4.90, 39.59, + 72.84, 32.61, 7.52, 2.83, 1.96, 1.67, 4.43, 11.28, 14.76, 12.73, 9.74, 7.33, 9.72, 55.27, 42.58, 13.18, 13.16, 12.26, 5.11, 2.07, 2.34, 3.58, 3.01, 2.48, 2.14, 1.54, 1.33, 1.46, 1.94, 2.00, 1.20, 1.35, 4.10, 5.58, + 2.51, 0.57, 0.27, 0.23, 0.21, 0.24, 0.24, 0.20, 0.24, 0.32, 0.26, 0.16, 0.12, 0.09, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for fluo F12 Philips TL83 3000K const double ColorTemp::FluoF12_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.96,0.64,0.45,0.33,1.19,12.48,1.12,0.94,1.08,1.37,1.78,29.05,7.90,2.65,2.71,2.65,2.49,2.33,2.10,1.91,3.01,10.83,11.88,6.88,3.43,1.49,0.92,0.71,0.60,0.63,1.10,4.56,34.4,65.40,29.48, - 7.16,3.08,2.47,2.27,5.09,11.96,15.32,14.27,11.86,9.28,12.31,68.53,53.02,14.67,14.38,14.71,6.46,2.57,2.75,4.18,3.44,2.81,2.42,1.64,1.36,1.49,2.14,2.34,1.42,1.61,5.04,6.98,3.19,0.71,0.30,0.26,0.23,0.28,0.28,0.21, - 0.17,0.21,0.19,0.15,0.10,0.05,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.96, 0.64, 0.45, 0.33, 1.19, 12.48, 1.12, 0.94, 1.08, 1.37, 1.78, 29.05, 7.90, 2.65, 2.71, 2.65, 2.49, 2.33, 2.10, 1.91, 3.01, 10.83, 11.88, 6.88, 3.43, 1.49, 0.92, 0.71, 0.60, 0.63, 1.10, 4.56, 34.4, 65.40, 29.48, + 7.16, 3.08, 2.47, 2.27, 5.09, 11.96, 15.32, 14.27, 11.86, 9.28, 12.31, 68.53, 53.02, 14.67, 14.38, 14.71, 6.46, 2.57, 2.75, 4.18, 3.44, 2.81, 2.42, 1.64, 1.36, 1.49, 2.14, 2.34, 1.42, 1.61, 5.04, 6.98, 3.19, 0.71, 0.30, 0.26, 0.23, 0.28, 0.28, 0.21, + 0.17, 0.21, 0.19, 0.15, 0.10, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for HMI lamp studio "Osram" 4800K (for film, spectacle, studio...) const double ColorTemp::HMI_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,9.66,11.45,13.24,14.93,16.63,17.90,19.20,20.12,21.03,23.84,26.65,26.38,26.12,26.52,27.92,31.15,34.37,34.98,35.61,35.71,35.81,34.90,34.02,34.06,34.08,34.68,35.28,34.72,34.20,33.63, - 33.05,34.70,36.35,38.01,39.48,37.29,35.10,36.22,37.28,38.76,40.24,39.56,38.90,39.35,39.79,38.90,38.01,38.05,38.10,37.45,36.64,35.82,35.00,35.06,33.13,33.85,34.55,35.26,35.77,34.92, - 34.09,33.40,32.72,32.08,31.45,26.83,22.23,21.50,20.79,21.41,22.03,11.01,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.66, 11.45, 13.24, 14.93, 16.63, 17.90, 19.20, 20.12, 21.03, 23.84, 26.65, 26.38, 26.12, 26.52, 27.92, 31.15, 34.37, 34.98, 35.61, 35.71, 35.81, 34.90, 34.02, 34.06, 34.08, 34.68, 35.28, 34.72, 34.20, 33.63, + 33.05, 34.70, 36.35, 38.01, 39.48, 37.29, 35.10, 36.22, 37.28, 38.76, 40.24, 39.56, 38.90, 39.35, 39.79, 38.90, 38.01, 38.05, 38.10, 37.45, 36.64, 35.82, 35.00, 35.06, 33.13, 33.85, 34.55, 35.26, 35.77, 34.92, + 34.09, 33.40, 32.72, 32.08, 31.45, 26.83, 22.23, 21.50, 20.79, 21.41, 22.03, 11.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for GTI lamp : Graphiclite & ColorMatch for Photography 5000K const double ColorTemp::GTI_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,3.26,4.71,6.17,12.71,19.27,20.53,21.80,19.15,16.53,28.25,39.97,48.52,57.06,43.66,30.27,30.22,30.16,31.48,32.98,34.01,35.04,35.83,36.62,37.12,37.62,37.99,38.19,38.29,38.48, - 38.82,39.16,45.40,51.63,51.83,62.04,52.41,42.80,42.95,43.09,45.64,48.20,46.23,44.27,43.74,43.22,43.30,43.41,43.10,42.78,42.03,41.29,40.29,39.29,37.89,36.58,34.92,33.27,31.47,29.68,27.90, - 26.13,24.55,22.98,21.42,19.86,18.40,16.92,14.46,13.99,12.36,11.73,5.86,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.26, 4.71, 6.17, 12.71, 19.27, 20.53, 21.80, 19.15, 16.53, 28.25, 39.97, 48.52, 57.06, 43.66, 30.27, 30.22, 30.16, 31.48, 32.98, 34.01, 35.04, 35.83, 36.62, 37.12, 37.62, 37.99, 38.19, 38.29, 38.48, + 38.82, 39.16, 45.40, 51.63, 51.83, 62.04, 52.41, 42.80, 42.95, 43.09, 45.64, 48.20, 46.23, 44.27, 43.74, 43.22, 43.30, 43.41, 43.10, 42.78, 42.03, 41.29, 40.29, 39.29, 37.89, 36.58, 34.92, 33.27, 31.47, 29.68, 27.90, + 26.13, 24.55, 22.98, 21.42, 19.86, 18.40, 16.92, 14.46, 13.99, 12.36, 11.73, 5.86, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for JudgeIII Lamp D50 const double ColorTemp::JudgeIII_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,4.08,4.25,4.43,6.90,9.40,9.75,10.11,9.30,8.54,14.90,21.16,26.01,30.83,24.90,19.00,19.00,19.00,19.56,20.13,20.28,20.44,20.64,20.85,21.05,21.24,21.65,22.11,22.85,23.58,24.00,24.43, - 27.75,31.27,33.90,36.59,30.90,25.32,25.05,24.76,26.03,27.31,25.90,24.48,23.85,23.29,23.10,22.94,23.24,23.53,24.02,24.52,23.80,23.13,24.51,25.76,27.90,29.15,24.70,20.25,16.60,12.98,11.63,10.27,9.30,8.34, - 7.60,6.91,6.25,5.67,5.15,4.68,2.34,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.08, 4.25, 4.43, 6.90, 9.40, 9.75, 10.11, 9.30, 8.54, 14.90, 21.16, 26.01, 30.83, 24.90, 19.00, 19.00, 19.00, 19.56, 20.13, 20.28, 20.44, 20.64, 20.85, 21.05, 21.24, 21.65, 22.11, 22.85, 23.58, 24.00, 24.43, + 27.75, 31.27, 33.90, 36.59, 30.90, 25.32, 25.05, 24.76, 26.03, 27.31, 25.90, 24.48, 23.85, 23.29, 23.10, 22.94, 23.24, 23.53, 24.02, 24.52, 23.80, 23.13, 24.51, 25.76, 27.90, 29.15, 24.70, 20.25, 16.60, 12.98, 11.63, 10.27, 9.30, 8.34, + 7.60, 6.91, 6.25, 5.67, 5.15, 4.68, 2.34, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data for Solux lamp : 3500K const double ColorTemp::Solux3500_spect[97] = { - 0.5268,0.93,1.3278,1.51,1.6987,2.65,3.6100,3.80,3.9927,6.08,8.1680,11.02,13.863,15.66,17.4600,18.78,20.130,21.43,22.749,24.02,25.290,27.40,29.504,31.77,34.031,36.35,38.672,40.55,42.426,44.15,45.865,47.37,48.879, - 49.71,50.531,51.2,51.872,51.9,51.928,52.97,54.015,55.93,57.846,60.25,62.650,64.36,66.065,66.72,67.369,68.81,70.260,71.37,72.487,72.53,72.578,72.51,72.447,72.46,72.471, - 72.76,73.047,74.25,75.449,76.5,77.543,78.79,80.040,80.72,81.394,82.12,82.840,83.23,83.614,83.36,83.100,82.36,81.615,80.11,78.606,75.91,73.221,69.61,66.006,62.43,58.844,56.07,53.292, - 51.07,48.839,46.93,45.013,43.54,42.070,40.61,39.150,37.79,36.425 + 0.5268, 0.93, 1.3278, 1.51, 1.6987, 2.65, 3.6100, 3.80, 3.9927, 6.08, 8.1680, 11.02, 13.863, 15.66, 17.4600, 18.78, 20.130, 21.43, 22.749, 24.02, 25.290, 27.40, 29.504, 31.77, 34.031, 36.35, 38.672, 40.55, 42.426, 44.15, 45.865, 47.37, 48.879, + 49.71, 50.531, 51.2, 51.872, 51.9, 51.928, 52.97, 54.015, 55.93, 57.846, 60.25, 62.650, 64.36, 66.065, 66.72, 67.369, 68.81, 70.260, 71.37, 72.487, 72.53, 72.578, 72.51, 72.447, 72.46, 72.471, + 72.76, 73.047, 74.25, 75.449, 76.5, 77.543, 78.79, 80.040, 80.72, 81.394, 82.12, 82.840, 83.23, 83.614, 83.36, 83.100, 82.36, 81.615, 80.11, 78.606, 75.91, 73.221, 69.61, 66.006, 62.43, 58.844, 56.07, 53.292, + 51.07, 48.839, 46.93, 45.013, 43.54, 42.070, 40.61, 39.150, 37.79, 36.425 }; //spectral data for Solux lamp : 4100K const double ColorTemp::Solux4100_spect[97] = { - 0.5717,0.70,0.8286,1.16,1.522,2.01,2.384,3.45,4.57,6.46,8.4548,11.31,14.205,16.10,17.949,19.51,21.068,22.60,24.197,25.37,26.566,28.15,29.742,30.90,32.060,33.26,34.481,34.80,35.130,35.42,35.697,36.20,36.763, - 37.90,39.004,40.26,41.494,43.10,44.690,45.80,46.900,47.45,47.885,47.75,47.635,47.00,46.410,46.22,46.058,46.70,47.344,48.65,50.005,51.02,52.045,53.55,55.075,55.98,56.823, - 56.85,56.884,56.15,55.523,54.60,53.732,52.55,51.425,50.30,49.1830,48.76,48.273,48.22,48.169,49.92,49.915,51.90,53.099,54.95,56.852,58.45,60.090,61.67,63.2530,63.55,63.834,63.55,63.468, - 62.40,61.373,59.75,58.1810,56.25,54.395,51.90,49.496,47.05,44.620 + 0.5717, 0.70, 0.8286, 1.16, 1.522, 2.01, 2.384, 3.45, 4.57, 6.46, 8.4548, 11.31, 14.205, 16.10, 17.949, 19.51, 21.068, 22.60, 24.197, 25.37, 26.566, 28.15, 29.742, 30.90, 32.060, 33.26, 34.481, 34.80, 35.130, 35.42, 35.697, 36.20, 36.763, + 37.90, 39.004, 40.26, 41.494, 43.10, 44.690, 45.80, 46.900, 47.45, 47.885, 47.75, 47.635, 47.00, 46.410, 46.22, 46.058, 46.70, 47.344, 48.65, 50.005, 51.02, 52.045, 53.55, 55.075, 55.98, 56.823, + 56.85, 56.884, 56.15, 55.523, 54.60, 53.732, 52.55, 51.425, 50.30, 49.1830, 48.76, 48.273, 48.22, 48.169, 49.92, 49.915, 51.90, 53.099, 54.95, 56.852, 58.45, 60.090, 61.67, 63.2530, 63.55, 63.834, 63.55, 63.468, + 62.40, 61.373, 59.75, 58.1810, 56.25, 54.395, 51.90, 49.496, 47.05, 44.620 }; //spectral data for Solux lamp : near Daylight (for example "mus�e d'Orsay..") - 4700K const double ColorTemp::Solux4700_spect[97] = { - 0.4590,0.83,1.2011,1.53,1.8647,2.15,2.5338,3.06,3.5809,3.99,4.4137,4.82,5.2228,5.63,6.0387,6.53,6.9944,7.55,8.0266,8.475,8.9276,8.90,9.7840,10.20,10.6390,11.00,11.3600,11.75,12.1340,12.36,12.5880,12.74,12.8790, - 13.07,13.2560,13.38,13.5220,13.41,13.3070,13.35,13.3990,13.37,13.3420,13.39,13.4220,13.65,13.2710,13.25,13.2330,13.12,13.0110,12.93,12.8470,12.805,12.7630,12.66,12.5760,12.563,12.5490, - 12.59,12.6330,12.617,12.6010,12.616,12.6310,12.6275,12.6240,12.70,12.7710,12.776,12.7810,12.786,12.7950,12.74,12.6850,12.64,12.5950,12.55,12.5420,12.43,12.3180,12.07,11.8340,11.72,11.6190,11.55,11.5020, - 11.32,11.1510,11.05,10.9530,10.80,10.6550,10.495,10.4390,10.31,10.1790 + 0.4590, 0.83, 1.2011, 1.53, 1.8647, 2.15, 2.5338, 3.06, 3.5809, 3.99, 4.4137, 4.82, 5.2228, 5.63, 6.0387, 6.53, 6.9944, 7.55, 8.0266, 8.475, 8.9276, 8.90, 9.7840, 10.20, 10.6390, 11.00, 11.3600, 11.75, 12.1340, 12.36, 12.5880, 12.74, 12.8790, + 13.07, 13.2560, 13.38, 13.5220, 13.41, 13.3070, 13.35, 13.3990, 13.37, 13.3420, 13.39, 13.4220, 13.65, 13.2710, 13.25, 13.2330, 13.12, 13.0110, 12.93, 12.8470, 12.805, 12.7630, 12.66, 12.5760, 12.563, 12.5490, + 12.59, 12.6330, 12.617, 12.6010, 12.616, 12.6310, 12.6275, 12.6240, 12.70, 12.7710, 12.776, 12.7810, 12.786, 12.7950, 12.74, 12.6850, 12.64, 12.5950, 12.55, 12.5420, 12.43, 12.3180, 12.07, 11.8340, 11.72, 11.6190, 11.55, 11.5020, + 11.32, 11.1510, 11.05, 10.9530, 10.80, 10.6550, 10.495, 10.4390, 10.31, 10.1790 }; //spectral data for Solux lamp : near Daylight 4400K - test National Gallery const double ColorTemp::NG_Solux4700_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,139,152,170,185,202,223,240,257,270,282,293,305,317,329,342,355,367,378,387,395,401,405,408,411,414,415,416,415,414,414,416,419,423,427,432,437,442,447,452, - 456,461,467,475,483,488,490,491,490,487,485,481,477,472,466,461,455,449,442,434,427,419,411,403,395,386,377,367,359,351,343,335,327,322,316,312,306,305,301,299,299,298, - 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 139, 152, 170, 185, 202, 223, 240, 257, 270, 282, 293, 305, 317, 329, 342, 355, 367, 378, 387, 395, 401, 405, 408, 411, 414, 415, 416, 415, 414, 414, 416, 419, 423, 427, 432, 437, 442, 447, 452, + 456, 461, 467, 475, 483, 488, 490, 491, 490, 487, 485, 481, 477, 472, 466, 461, 455, 449, 442, 434, 427, 419, 411, 403, 395, 386, 377, 367, 359, 351, 343, 335, 327, 322, 316, 312, 306, 305, 301, 299, 299, 298, + 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.0 }; //spectral data for LED LSI Lumelex 2040 - test National Gallery const double ColorTemp::NG_LEDLSI2040_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,1.5,1.2,0.5,0.7,0.6,1.6,1.7,7.0,16.6,35.5,64,106,162.5,230.5,272.2,249,213.4,214,227.6,231.9,233,235.2,241.4,253.7,270.3,288.5,306.2,322.3,337.6,352.5,367.2,381.7,395.9,409.6,416.2,423.2,429.7,435.8,442.8, - 451.7,464.2,480.3,501,526.3,555.9,587.5,625.4,655.1,681.7,705.3,721.5,728.5,729,719.8,702.5,676.7,646.2,611.5,571.7,530.3,488.3,445.9,404,365.2,326.8,290.8,257.6,226.9,199.8,175.2,154.2,133.8,116.4,101.5,88.5,76.6,67.3,57.9,50.7,44.2,38.2, - 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5, 1.2, 0.5, 0.7, 0.6, 1.6, 1.7, 7.0, 16.6, 35.5, 64, 106, 162.5, 230.5, 272.2, 249, 213.4, 214, 227.6, 231.9, 233, 235.2, 241.4, 253.7, 270.3, 288.5, 306.2, 322.3, 337.6, 352.5, 367.2, 381.7, 395.9, 409.6, 416.2, 423.2, 429.7, 435.8, 442.8, + 451.7, 464.2, 480.3, 501, 526.3, 555.9, 587.5, 625.4, 655.1, 681.7, 705.3, 721.5, 728.5, 729, 719.8, 702.5, 676.7, 646.2, 611.5, 571.7, 530.3, 488.3, 445.9, 404, 365.2, 326.8, 290.8, 257.6, 226.9, 199.8, 175.2, 154.2, 133.8, 116.4, 101.5, 88.5, 76.6, 67.3, 57.9, 50.7, 44.2, 38.2, + 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.0 }; //spectral data for LED CRS SP12 WWMR16 - test National Gallery const double ColorTemp::NG_CRSSP12WWMR16_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.,0.,0.,0.,0.,0.14,0.33,1.31,3.34,7.9,17.4,36.5,72.6,145.4,260.5,359.2,365.3,303.1,256.1,221.7,193.6,185.8,191.4,207.3,232.8,257.5,285.1,310.5,333.4,351.5,368.8,383.7,398.8,411.6,424.7,435.6,447.9,459.7,471.7, - 484.6,497.9,512.3,531.1,548.9,567.9,587.5,608.6,625.3,640.1,648.6,654.0,654.3,647.2,633.9,616.1,590.5,561.5,526.5,494.8,457.9,420.8,382.4,347.3,309.9,280.5,249.2,220.0,194.9,170.8,149.1,130.0,112.3,97.5,84.9,73.2,63.1,54.1,45.6,39.0,32.6,27.4, - 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0., 0., 0., 0., 0., 0.14, 0.33, 1.31, 3.34, 7.9, 17.4, 36.5, 72.6, 145.4, 260.5, 359.2, 365.3, 303.1, 256.1, 221.7, 193.6, 185.8, 191.4, 207.3, 232.8, 257.5, 285.1, 310.5, 333.4, 351.5, 368.8, 383.7, 398.8, 411.6, 424.7, 435.6, 447.9, 459.7, 471.7, + 484.6, 497.9, 512.3, 531.1, 548.9, 567.9, 587.5, 608.6, 625.3, 640.1, 648.6, 654.0, 654.3, 647.2, 633.9, 616.1, 590.5, 561.5, 526.5, 494.8, 457.9, 420.8, 382.4, 347.3, 309.9, 280.5, 249.2, 220.0, 194.9, 170.8, 149.1, 130.0, 112.3, 97.5, 84.9, 73.2, 63.1, 54.1, 45.6, 39.0, 32.6, 27.4, + 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.0 }; -//Data for flash : -// in theory, should be the spectral data of each owner flash (Nikon, Canon, Sony ...) or studio flash (Profoto. ..) +//Data for flash : +// in theory, should be the spectral data of each owner flash (Nikon, Canon, Sony ...) or studio flash (Profoto. ..) // but: 1) I did not, 2) the data vary depending on the power used ... so by default, although this is not true, I chose the values "Daylight" for temp... // CRI for flash near of 95 - 97 !! //spectral data for Flash daylight 5500K (Leica...) const double ColorTemp::Flash5500_spect[97] = { - 27.77,29.17,30.58,32.02,33.47,33.00,32.53,35.28,38.04,49.46,60.88,64.68,68.48,69.99,71.51,69.68,67.85,76.70,85.54,91.74,97.93,99.17,100.41,100.14,99.86,101.28,102.70,100.37,98.04,99.35,100.65, - 100.66,100.67,100.32,99.97,102.08,104.20,103.15,102.09,102.53,102.96,101.48,100.00,98.61,97.22,97.49,97.76,94.60,91.44,92.94,94.44,94.80,95.16,94.70,94.25,92.36,90.48,91.42,92.36,90.63, - 88.89,89.62,90.36,92.18,94.00,92.00,90.00,84.86,79.72,81.30,82.88,83.88,84.89,77.58,70.27,74.80,82.19,85.03,78.47,71.91,62.37,52.82,64.39,75.96,73.91,71.85,72.41,72.97,70.17,67.38,63.07, - 58.75,61.89,65.02,66.68,68.34 + 27.77, 29.17, 30.58, 32.02, 33.47, 33.00, 32.53, 35.28, 38.04, 49.46, 60.88, 64.68, 68.48, 69.99, 71.51, 69.68, 67.85, 76.70, 85.54, 91.74, 97.93, 99.17, 100.41, 100.14, 99.86, 101.28, 102.70, 100.37, 98.04, 99.35, 100.65, + 100.66, 100.67, 100.32, 99.97, 102.08, 104.20, 103.15, 102.09, 102.53, 102.96, 101.48, 100.00, 98.61, 97.22, 97.49, 97.76, 94.60, 91.44, 92.94, 94.44, 94.80, 95.16, 94.70, 94.25, 92.36, 90.48, 91.42, 92.36, 90.63, + 88.89, 89.62, 90.36, 92.18, 94.00, 92.00, 90.00, 84.86, 79.72, 81.30, 82.88, 83.88, 84.89, 77.58, 70.27, 74.80, 82.19, 85.03, 78.47, 71.91, 62.37, 52.82, 64.39, 75.96, 73.91, 71.85, 72.41, 72.97, 70.17, 67.38, 63.07, + 58.75, 61.89, 65.02, 66.68, 68.34 }; //spectral data for Flash daylight 6000K (Canon, Pentax, Olympus,...Standard) const double ColorTemp::Flash6000_spect[97] = { - 36.00,37.18,38.36,40.36,42.35,41.77,41.19,43.79,46.40,59.24,72.09,76.15,80.22,81.47,82.71,80.12,77.52,86.54,95.56,101.70,107.85,108.66,109.46,108.57,107.68,108.65,109.61,106.63,103.65,104.42, - 105.19,104.79,104.39,103.45,102.51,104.28,106.05,104.68,103.31,103.42,103.54,101.77,100.00,98.38,96.75,96.74,96.72,93.30,89.89,90.92,91.95,91.99,92.03,91.30,90.57,88.51,86.45,86.96, - 87.47,85.66,83.85,84.21,84.57,85.95,87.32,85.31,83.30,78.66,74.03,75.24,76.45,77.68,78.91,72.13,65.35,69.67,73.98,76.68,79.39,73.29,67.19,58.19,49.19,59.98,70.77,68.91,67.05,67.55,68.05, - 65.47,62.88,58.89,54.90,57.81,60.72,62.25,63.78 + 36.00, 37.18, 38.36, 40.36, 42.35, 41.77, 41.19, 43.79, 46.40, 59.24, 72.09, 76.15, 80.22, 81.47, 82.71, 80.12, 77.52, 86.54, 95.56, 101.70, 107.85, 108.66, 109.46, 108.57, 107.68, 108.65, 109.61, 106.63, 103.65, 104.42, + 105.19, 104.79, 104.39, 103.45, 102.51, 104.28, 106.05, 104.68, 103.31, 103.42, 103.54, 101.77, 100.00, 98.38, 96.75, 96.74, 96.72, 93.30, 89.89, 90.92, 91.95, 91.99, 92.03, 91.30, 90.57, 88.51, 86.45, 86.96, + 87.47, 85.66, 83.85, 84.21, 84.57, 85.95, 87.32, 85.31, 83.30, 78.66, 74.03, 75.24, 76.45, 77.68, 78.91, 72.13, 65.35, 69.67, 73.98, 76.68, 79.39, 73.29, 67.19, 58.19, 49.19, 59.98, 70.77, 68.91, 67.05, 67.55, 68.05, + 65.47, 62.88, 58.89, 54.90, 57.81, 60.72, 62.25, 63.78 }; //spectral data for Flash daylight 6500K (Nikon, Minolta, Panasonic, Sony...) const double ColorTemp::Flash6500_spect[97] = { - 44.86,45.72,46.59,49.16,51.74,50.83,49.92,52.26,54.60,68.65,82.69,87.06,91.42,92.39,93.37,90.00,86.63,95.72,104.81,110.88,116.96,117.36,117.76,116.29,114.82,115.35,115.89,112.33,108.78,109.06, - 109.33,108.56,107.78,106.28,104.78,106.23,107.68,106.04,104.40,104.22,104.04,102.02,100.00,98.17,96.34,96.06,95.79,92.24,88.69,89.35,90.02,89.81,89.61,88.66,87.71,85.51,83.30,83.51,83.72, - 81.88,80.05,80.14,80.24,81.27,82.30,80.31,78.31,74.03,69.74,70.69,71.63,73.00,74.37,68.00,61.62,65.76,69.91,72.51,75.11,69.36,63.61,55.02,46.43,56.63,66.83,65.11,63.40,63.86,64.32,61.90,59.47, - 55.72,51.97,54.72,57.46,58.89,60.33 + 44.86, 45.72, 46.59, 49.16, 51.74, 50.83, 49.92, 52.26, 54.60, 68.65, 82.69, 87.06, 91.42, 92.39, 93.37, 90.00, 86.63, 95.72, 104.81, 110.88, 116.96, 117.36, 117.76, 116.29, 114.82, 115.35, 115.89, 112.33, 108.78, 109.06, + 109.33, 108.56, 107.78, 106.28, 104.78, 106.23, 107.68, 106.04, 104.40, 104.22, 104.04, 102.02, 100.00, 98.17, 96.34, 96.06, 95.79, 92.24, 88.69, 89.35, 90.02, 89.81, 89.61, 88.66, 87.71, 85.51, 83.30, 83.51, 83.72, + 81.88, 80.05, 80.14, 80.24, 81.27, 82.30, 80.31, 78.31, 74.03, 69.74, 70.69, 71.63, 73.00, 74.37, 68.00, 61.62, 65.76, 69.91, 72.51, 75.11, 69.36, 63.61, 55.02, 46.43, 56.63, 66.83, 65.11, 63.40, 63.86, 64.32, 61.90, 59.47, + 55.72, 51.97, 54.72, 57.46, 58.89, 60.33 }; // Data for Color ==> CRI (Color Rendering Index and Palette @@ -347,469 +362,469 @@ const double ColorTemp::Flash6500_spect[97] = { //spectral data Colorchecker24 : Red C3 const double ColorTemp::ColorchechredC3_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0478,0.0476,0.0474,0.0472,0.0470,0.0466,0.0461,0.0460,0.0459,0.0456,0.0453,0.0451,0.0449,0.0448,0.0447,0.0446,0.0445,0.0441,0.0437,0.0432,0.0427,0.0424,0.0421,0.0419, - 0.0417,0.0415,0.0412,0.0412,0.0412,0.0413,0.0413,0.0415,0.0416,0.0421,0.0426,0.0436,0.0446,0.0469,0.0491,0.0549,0.0607,0.0773,0.0939,0.1376,0.1812,0.2568,0.3323,0.4070,0.4816,0.5308, - 0.5800,0.6059,0.6317,0.6447,0.6577,0.6653,0.6728,0.6761,0.6793,0.6820,0.6847,0.6878,0.6909,0.6945,0.6980,0.7013,0.7046,0.7065,0.7084,0.7107,0.7129,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0478, 0.0476, 0.0474, 0.0472, 0.0470, 0.0466, 0.0461, 0.0460, 0.0459, 0.0456, 0.0453, 0.0451, 0.0449, 0.0448, 0.0447, 0.0446, 0.0445, 0.0441, 0.0437, 0.0432, 0.0427, 0.0424, 0.0421, 0.0419, + 0.0417, 0.0415, 0.0412, 0.0412, 0.0412, 0.0413, 0.0413, 0.0415, 0.0416, 0.0421, 0.0426, 0.0436, 0.0446, 0.0469, 0.0491, 0.0549, 0.0607, 0.0773, 0.0939, 0.1376, 0.1812, 0.2568, 0.3323, 0.4070, 0.4816, 0.5308, + 0.5800, 0.6059, 0.6317, 0.6447, 0.6577, 0.6653, 0.6728, 0.6761, 0.6793, 0.6820, 0.6847, 0.6878, 0.6909, 0.6945, 0.6980, 0.7013, 0.7046, 0.7065, 0.7084, 0.7107, 0.7129, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Orange A2 const double ColorTemp::ColorchechOraA2_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0520,0.0530,0.0540,0.0535,0.0530,0.0532,0.0534,0.0532,0.0529,0.0529,0.0528,0.0530,0.0532,0.0537,0.0542,0.0550,0.0557,0.0565,0.0573,0.0585,0.0597,0.0613,0.0628,0.0656,0.0683,0.0793, - 0.0902,0.1085,0.1268,0.1414,0.1559,0.1645,0.1730,0.1837,0.1944,0.2184,0.2424,0.2877,0.3329,0.3923,0.4517,0.5021,0.5525,0.5739,0.5952,0.5967,0.5982,0.5962,0.5942,0.5932,0.5922,0.5927, - 0.5932,0.5938,0.5944,0.5988,0.6032,0.6105,0.6178,0.6284,0.6389,0.6498,0.6607,0.6699,0.6791,0.6839,0.6886,0.6879,0.6871,0.6886,0.6901,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0520, 0.0530, 0.0540, 0.0535, 0.0530, 0.0532, 0.0534, 0.0532, 0.0529, 0.0529, 0.0528, 0.0530, 0.0532, 0.0537, 0.0542, 0.0550, 0.0557, 0.0565, 0.0573, 0.0585, 0.0597, 0.0613, 0.0628, 0.0656, 0.0683, 0.0793, + 0.0902, 0.1085, 0.1268, 0.1414, 0.1559, 0.1645, 0.1730, 0.1837, 0.1944, 0.2184, 0.2424, 0.2877, 0.3329, 0.3923, 0.4517, 0.5021, 0.5525, 0.5739, 0.5952, 0.5967, 0.5982, 0.5962, 0.5942, 0.5932, 0.5922, 0.5927, + 0.5932, 0.5938, 0.5944, 0.5988, 0.6032, 0.6105, 0.6178, 0.6284, 0.6389, 0.6498, 0.6607, 0.6699, 0.6791, 0.6839, 0.6886, 0.6879, 0.6871, 0.6886, 0.6901, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 :yellow D3 const double ColorTemp::ColorchechYelD3_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0476,0.0482,0.0488,0.0492,0.0496,0.0498,0.0499,0.0498,0.0496,0.0501,0.0506,0.0516,0.0526,0.0547,0.0567,0.0610,0.0652,0.0733,0.0813,0.0962,0.1110,0.1333,0.1556,0.1884,0.2211, - 0.2782,0.3353,0.4023,0.4692,0.5198,0.5703,0.5976,0.6249,0.6400,0.6551,0.6667,0.6783,0.6901,0.7018,0.7095,0.7171,0.7231,0.7290,0.7329,0.7367,0.7395,0.7423,0.7447,0.7471,0.7490,0.7508, - 0.7533,0.7558,0.7578,0.7598,0.7623,0.7647,0.7654,0.7661,0.7677,0.7693,0.7720,0.7746,0.7780,0.7814,0.7845,0.7876,0.7889,0.7902,0.7920,0.7938, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0476, 0.0482, 0.0488, 0.0492, 0.0496, 0.0498, 0.0499, 0.0498, 0.0496, 0.0501, 0.0506, 0.0516, 0.0526, 0.0547, 0.0567, 0.0610, 0.0652, 0.0733, 0.0813, 0.0962, 0.1110, 0.1333, 0.1556, 0.1884, 0.2211, + 0.2782, 0.3353, 0.4023, 0.4692, 0.5198, 0.5703, 0.5976, 0.6249, 0.6400, 0.6551, 0.6667, 0.6783, 0.6901, 0.7018, 0.7095, 0.7171, 0.7231, 0.7290, 0.7329, 0.7367, 0.7395, 0.7423, 0.7447, 0.7471, 0.7490, 0.7508, + 0.7533, 0.7558, 0.7578, 0.7598, 0.7623, 0.7647, 0.7654, 0.7661, 0.7677, 0.7693, 0.7720, 0.7746, 0.7780, 0.7814, 0.7845, 0.7876, 0.7889, 0.7902, 0.7920, 0.7938, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Green E2 const double ColorTemp::ColorchechGreE2_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0560,0.0583,0.0605,0.0626,0.0646,0.0650,0.0653,0.0657,0.0661,0.0669,0.0676,0.0692,0.0708,0.0737,0.0765,0.0816,0.0867,0.0956,0.1044,0.1194,0.1344,0.1581,0.1818,0.2196,0.2574,0.3166,0.3757, - 0.4297,0.4837,0.5142,0.5446,0.5541,0.5636,0.5608,0.5579,0.5480,0.5381,0.5258,0.5135,0.4959,0.4783,0.4570,0.4356,0.4124,0.3891,0.3710,0.3529,0.3425,0.3320,0.3266,0.3211,0.3180,0.3149, - 0.3129,0.3108,0.3123,0.3137,0.3193,0.3248,0.3335,0.3422,0.3518,0.3613,0.3693,0.3772,0.3810,0.3847,0.3838,0.3829,0.3838,0.3847,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0560, 0.0583, 0.0605, 0.0626, 0.0646, 0.0650, 0.0653, 0.0657, 0.0661, 0.0669, 0.0676, 0.0692, 0.0708, 0.0737, 0.0765, 0.0816, 0.0867, 0.0956, 0.1044, 0.1194, 0.1344, 0.1581, 0.1818, 0.2196, 0.2574, 0.3166, 0.3757, + 0.4297, 0.4837, 0.5142, 0.5446, 0.5541, 0.5636, 0.5608, 0.5579, 0.5480, 0.5381, 0.5258, 0.5135, 0.4959, 0.4783, 0.4570, 0.4356, 0.4124, 0.3891, 0.3710, 0.3529, 0.3425, 0.3320, 0.3266, 0.3211, 0.3180, 0.3149, + 0.3129, 0.3108, 0.3123, 0.3137, 0.3193, 0.3248, 0.3335, 0.3422, 0.3518, 0.3613, 0.3693, 0.3772, 0.3810, 0.3847, 0.3838, 0.3829, 0.3838, 0.3847, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Green B3 const double ColorTemp::ColorchechGreB3_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0531,0.0545,0.0559,0.0563,0.0566,0.0571,0.0576,0.0576,0.0575,0.0581,0.0586,0.0596,0.0606,0.0629,0.0652,0.0699,0.0745,0.0839,0.0932,0.1101,0.1270,0.1521,0.1771,0.2098,0.2424, - 0.2789,0.3154,0.3312,0.3470,0.3431,0.3392,0.3303,0.3213,0.3089,0.2964,0.2788,0.2612,0.2442,0.2271,0.2117,0.1962,0.1815,0.1667,0.1527,0.1386,0.1284,0.1182,0.1124,0.1066,0.1035,0.1003, - 0.0987,0.0971,0.0961,0.0950,0.0950,0.0950,0.0962,0.0973,0.0994,0.1014,0.1045,0.1075,0.1106,0.1137,0.1157,0.1176,0.1175,0.1173,0.1173,0.1173, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0531, 0.0545, 0.0559, 0.0563, 0.0566, 0.0571, 0.0576, 0.0576, 0.0575, 0.0581, 0.0586, 0.0596, 0.0606, 0.0629, 0.0652, 0.0699, 0.0745, 0.0839, 0.0932, 0.1101, 0.1270, 0.1521, 0.1771, 0.2098, 0.2424, + 0.2789, 0.3154, 0.3312, 0.3470, 0.3431, 0.3392, 0.3303, 0.3213, 0.3089, 0.2964, 0.2788, 0.2612, 0.2442, 0.2271, 0.2117, 0.1962, 0.1815, 0.1667, 0.1527, 0.1386, 0.1284, 0.1182, 0.1124, 0.1066, 0.1035, 0.1003, + 0.0987, 0.0971, 0.0961, 0.0950, 0.0950, 0.0950, 0.0962, 0.0973, 0.0994, 0.1014, 0.1045, 0.1075, 0.1106, 0.1137, 0.1157, 0.1176, 0.1175, 0.1173, 0.1173, 0.1173, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Cyan F3 const double ColorTemp::ColorchechCyaF3_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0813,0.1048,0.1282,0.1611,0.1940,0.2198,0.2456,0.2575,0.2693,0.2807,0.2921,0.3079,0.3237,0.3424,0.3611,0.3820,0.4029,0.4234,0.4439,0.4547,0.4654,0.4638,0.4621,0.4482,0.4342,0.4119,0.3895, - 0.3656,0.3417,0.3160,0.2903,0.2654,0.2404,0.2167,0.1929,0.1720,0.1510,0.1368,0.1226,0.1138,0.1049,0.0993,0.0936,0.0890,0.0844,0.0810,0.0776,0.0759,0.0742,0.0733,0.0724,0.0723,0.0722,0.0727, - 0.0732,0.0745,0.0757,0.0763,0.0768,0.0764,0.0759,0.0748,0.0736,0.0723,0.0710,0.0703,0.0696,0.0707,0.0718,0.0756,0.0793,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0813, 0.1048, 0.1282, 0.1611, 0.1940, 0.2198, 0.2456, 0.2575, 0.2693, 0.2807, 0.2921, 0.3079, 0.3237, 0.3424, 0.3611, 0.3820, 0.4029, 0.4234, 0.4439, 0.4547, 0.4654, 0.4638, 0.4621, 0.4482, 0.4342, 0.4119, 0.3895, + 0.3656, 0.3417, 0.3160, 0.2903, 0.2654, 0.2404, 0.2167, 0.1929, 0.1720, 0.1510, 0.1368, 0.1226, 0.1138, 0.1049, 0.0993, 0.0936, 0.0890, 0.0844, 0.0810, 0.0776, 0.0759, 0.0742, 0.0733, 0.0724, 0.0723, 0.0722, 0.0727, + 0.0732, 0.0745, 0.0757, 0.0763, 0.0768, 0.0764, 0.0759, 0.0748, 0.0736, 0.0723, 0.0710, 0.0703, 0.0696, 0.0707, 0.0718, 0.0756, 0.0793, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Purple D2 const double ColorTemp::ColorchechPurD2_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0854,0.1047,0.1240,0.1468,0.1696,0.1826,0.1955,0.1963,0.1970,0.1910,0.1849,0.1750,0.1651,0.1541,0.1430,0.1322,0.1213,0.1117,0.1020,0.0944,0.0868,0.0809,0.0750,0.0703,0.0655, - 0.0627,0.0599,0.0583,0.0567,0.0550,0.0533,0.0525,0.0517,0.0518,0.0519,0.0523,0.0526,0.0525,0.0524,0.0520,0.0516,0.0523,0.0529,0.0560,0.0591,0.0662,0.0732,0.0828,0.0924,0.1021, - 0.1117,0.1222,0.1327,0.1469,0.1610,0.1796,0.1981,0.2173,0.2365,0.2532,0.2698,0.2826,0.2953,0.3022,0.3090,0.3126,0.3161,0.3238,0.3314,0.3504,0.3694,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0854, 0.1047, 0.1240, 0.1468, 0.1696, 0.1826, 0.1955, 0.1963, 0.1970, 0.1910, 0.1849, 0.1750, 0.1651, 0.1541, 0.1430, 0.1322, 0.1213, 0.1117, 0.1020, 0.0944, 0.0868, 0.0809, 0.0750, 0.0703, 0.0655, + 0.0627, 0.0599, 0.0583, 0.0567, 0.0550, 0.0533, 0.0525, 0.0517, 0.0518, 0.0519, 0.0523, 0.0526, 0.0525, 0.0524, 0.0520, 0.0516, 0.0523, 0.0529, 0.0560, 0.0591, 0.0662, 0.0732, 0.0828, 0.0924, 0.1021, + 0.1117, 0.1222, 0.1327, 0.1469, 0.1610, 0.1796, 0.1981, 0.2173, 0.2365, 0.2532, 0.2698, 0.2826, 0.2953, 0.3022, 0.3090, 0.3126, 0.3161, 0.3238, 0.3314, 0.3504, 0.3694, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Magenta E3 const double ColorTemp::ColorchechMagE3_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1112,0.1438,0.1763,0.2294,0.2824,0.3188,0.3552,0.3623,0.3693,0.3653,0.3612,0.3510,0.3407,0.3269,0.3130,0.2981,0.2832,0.2686,0.2539,0.2385,0.2230,0.2083,0.1935,0.1818,0.1700,0.1600,0.1499, - 0.1394,0.1288,0.1188,0.1088,0.1051,0.1014,0.1026,0.1038,0.1041,0.1043,0.1064,0.1085,0.1225,0.1364,0.1701,0.2037,0.2532,0.3027,0.3587,0.4147,0.4683,0.5219,0.5672,0.6124,0.6455,0.6785,0.7009, - 0.7232,0.7391,0.7550,0.7629,0.7707,0.7737,0.7766,0.7778,0.7790,0.7803,0.7815,0.7835,0.7854,0.7896,0.7937,0.8026,0.8114,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1112, 0.1438, 0.1763, 0.2294, 0.2824, 0.3188, 0.3552, 0.3623, 0.3693, 0.3653, 0.3612, 0.3510, 0.3407, 0.3269, 0.3130, 0.2981, 0.2832, 0.2686, 0.2539, 0.2385, 0.2230, 0.2083, 0.1935, 0.1818, 0.1700, 0.1600, 0.1499, + 0.1394, 0.1288, 0.1188, 0.1088, 0.1051, 0.1014, 0.1026, 0.1038, 0.1041, 0.1043, 0.1064, 0.1085, 0.1225, 0.1364, 0.1701, 0.2037, 0.2532, 0.3027, 0.3587, 0.4147, 0.4683, 0.5219, 0.5672, 0.6124, 0.6455, 0.6785, 0.7009, + 0.7232, 0.7391, 0.7550, 0.7629, 0.7707, 0.7737, 0.7766, 0.7778, 0.7790, 0.7803, 0.7815, 0.7835, 0.7854, 0.7896, 0.7937, 0.8026, 0.8114, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Skin A1 //use also for palette WB const double ColorTemp::ColorchechSkiA138_13_14_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0479,0.051,0.0553,0.058,0.0610,0.062,0.0626,0.0622,0.0619,0.0617,0.0616,0.0615,0.0614,0.0614,0.0615,0.0617,0.0618,0.0618,0.0619,0.0618,0.0618,0.062,0.0622,0.063,0.0638,0.066,0.0696, - 0.073,0.0767,0.078,0.0801,0.0807,0.0817,0.0831,0.0845,0.0870,0.0902,0.0955,0.1017,0.1096,0.1175,0.1250,0.1336,0.1385,0.1435,0.1455,0.1479,0.1490,0.1514,0.1547,0.1580,0.1625,0.1675, - 0.173,0.1772,0.181,0.1842,0.1846,0.1853,0.1831,0.1811,0.1788,0.1765,0.1769,0.1773,0.181,0.1834,0.1874,0.1914,0.1965,0.2018,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0479, 0.051, 0.0553, 0.058, 0.0610, 0.062, 0.0626, 0.0622, 0.0619, 0.0617, 0.0616, 0.0615, 0.0614, 0.0614, 0.0615, 0.0617, 0.0618, 0.0618, 0.0619, 0.0618, 0.0618, 0.062, 0.0622, 0.063, 0.0638, 0.066, 0.0696, + 0.073, 0.0767, 0.078, 0.0801, 0.0807, 0.0817, 0.0831, 0.0845, 0.0870, 0.0902, 0.0955, 0.1017, 0.1096, 0.1175, 0.1250, 0.1336, 0.1385, 0.1435, 0.1455, 0.1479, 0.1490, 0.1514, 0.1547, 0.1580, 0.1625, 0.1675, + 0.173, 0.1772, 0.181, 0.1842, 0.1846, 0.1853, 0.1831, 0.1811, 0.1788, 0.1765, 0.1769, 0.1773, 0.181, 0.1834, 0.1874, 0.1914, 0.1965, 0.2018, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Gray C4 L=67 //use also for palette WB const double ColorTemp::ColorchechGraC4_67_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1074,0.1380,0.1704,0.22,0.2705,0.305,0.3409,0.35,0.3601,0.3628,0.3655,0.3675,0.3698,0.371,0.3724,0.373,0.3733,0.3725,0.3715,0.3705,0.3692, - 0.369,0.3689,0.368,0.3673,0.3678,0.3684,0.37,0.3711,0.3712,0.3714,0.3714,0.3714,0.371,0.3707,0.37,0.3694,0.3697,0.3703,0.3697,0.3692,0.3688,0.3685,0.3675,0.3669,0.3657,0.3647,0.3635,0.3625,0.361, - 0.3596,0.3585,0.3579,0.357,0.3560,0.3555,0.3548,0.3535,0.3526,0.3513,0.3500,0.349,0.3475,0.3467,0.3460,0.3452,0.3444,0.3431,0.3421,0.3411,0.3403,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1074, 0.1380, 0.1704, 0.22, 0.2705, 0.305, 0.3409, 0.35, 0.3601, 0.3628, 0.3655, 0.3675, 0.3698, 0.371, 0.3724, 0.373, 0.3733, 0.3725, 0.3715, 0.3705, 0.3692, + 0.369, 0.3689, 0.368, 0.3673, 0.3678, 0.3684, 0.37, 0.3711, 0.3712, 0.3714, 0.3714, 0.3714, 0.371, 0.3707, 0.37, 0.3694, 0.3697, 0.3703, 0.3697, 0.3692, 0.3688, 0.3685, 0.3675, 0.3669, 0.3657, 0.3647, 0.3635, 0.3625, 0.361, + 0.3596, 0.3585, 0.3579, 0.357, 0.3560, 0.3555, 0.3548, 0.3535, 0.3526, 0.3513, 0.3500, 0.349, 0.3475, 0.3467, 0.3460, 0.3452, 0.3444, 0.3431, 0.3421, 0.3411, 0.3403, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : Skin B1 //use also for palette WB const double ColorTemp::ColorchechSkiB166_18_18_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0962,0.114,0.1328,0.152,0.1706,0.1755,0.1877,0.189,0.1903,0.1913,0.1923,0.1946,0.1971,0.2015,0.2064,0.215,0.2245,0.239,0.2535,0.273,0.2922,0.31,0.3274,0.337,0.3473, - 0.348,0.3489,0.335,0.3224,0.303,0.2835,0.275,0.2671,0.27,0.2728,0.2735,0.2741,0.279,0.2836,0.308,0.3334,0.375,0.4183,0.457,0.4950,0.516,0.5409,0.5515,0.5625,0.568,0.5731,0.5786, - 0.5820,0.586,0.5902,0.596,0.6025,0.611,0.6174,0.627,0.6375,0.65,0.6626,0.677,0.6910,0.704,0.7171,0.723,0.7339,0.741,0.7475, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0962, 0.114, 0.1328, 0.152, 0.1706, 0.1755, 0.1877, 0.189, 0.1903, 0.1913, 0.1923, 0.1946, 0.1971, 0.2015, 0.2064, 0.215, 0.2245, 0.239, 0.2535, 0.273, 0.2922, 0.31, 0.3274, 0.337, 0.3473, + 0.348, 0.3489, 0.335, 0.3224, 0.303, 0.2835, 0.275, 0.2671, 0.27, 0.2728, 0.2735, 0.2741, 0.279, 0.2836, 0.308, 0.3334, 0.375, 0.4183, 0.457, 0.4950, 0.516, 0.5409, 0.5515, 0.5625, 0.568, 0.5731, 0.5786, + 0.5820, 0.586, 0.5902, 0.596, 0.6025, 0.611, 0.6174, 0.627, 0.6375, 0.65, 0.6626, 0.677, 0.6910, 0.704, 0.7171, 0.723, 0.7339, 0.741, 0.7475, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorchecker24 : blue sky C1 //use also for palette WB const double ColorTemp::ColorchechBluC150_m5_m22_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1053,0.134,0.1633,0.2075,0.2518,0.283,0.3163,0.324,0.3325,0.334,0.3355,0.3352,0.3349,0.332,0.3294,0.325,0.3199,0.3127,0.3055,0.2955,0.2863,0.28,0.2737,0.267,0.2612,0.249,0.2378,0.228,0.2199, - 0.218,0.2173,0.2146,0.2118,0.20,0.1884,0.178,0.1682,0.166,0.1639,0.162,0.1613,0.158,0.1550,0.1504,0.1458,0.1415,0.1375,0.135,0.1327,0.1316,0.1305,0.1304,0.1302,0.131,0.1322,0.1342,0.1362, - 0.1367,0.1372,0.1356,0.1340,0.1311,0.1288,0.1253,0.1227,0.1205,0.1187,0.1195,0.1205,0.1255,0.1303,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1053, 0.134, 0.1633, 0.2075, 0.2518, 0.283, 0.3163, 0.324, 0.3325, 0.334, 0.3355, 0.3352, 0.3349, 0.332, 0.3294, 0.325, 0.3199, 0.3127, 0.3055, 0.2955, 0.2863, 0.28, 0.2737, 0.267, 0.2612, 0.249, 0.2378, 0.228, 0.2199, + 0.218, 0.2173, 0.2146, 0.2118, 0.20, 0.1884, 0.178, 0.1682, 0.166, 0.1639, 0.162, 0.1613, 0.158, 0.1550, 0.1504, 0.1458, 0.1415, 0.1375, 0.135, 0.1327, 0.1316, 0.1305, 0.1304, 0.1302, 0.131, 0.1322, 0.1342, 0.1362, + 0.1367, 0.1372, 0.1356, 0.1340, 0.1311, 0.1288, 0.1253, 0.1227, 0.1205, 0.1187, 0.1195, 0.1205, 0.1255, 0.1303, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorcheckerDC : blue sky N8 //use also for palette WB const double ColorTemp::ColorchechDCBluN881_m7_m14_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1371,0.17,0.2029,0.291,0.3790,0.495,0.6100,0.67,0.7249,0.737,0.7501,0.7545,0.7597,0.764,0.7677,0.7685,0.7693,0.7677,0.7662,0.763,0.7593,0.753,0.7471,0.737,0.7289,0.718,0.7077,0.705,0.6819,0.666,0.6515,0.636,0.6244, - 0.61,0.5948,0.577,0.5581,0.544,0.5293,0.522,0.5147,0.512,0.5091,0.506,0.5029,0.499,0.4950,0.494,0.4931,0.497,0.5007,0.508,0.5176,0.527,0.5359,0.542,0.5487,0.549,0.5494,0.544, - 0.5375,0.531,0.5244,0.522,0.5207,0.524,0.5264,0.532,0.5369,0.542,0.5505,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1371, 0.17, 0.2029, 0.291, 0.3790, 0.495, 0.6100, 0.67, 0.7249, 0.737, 0.7501, 0.7545, 0.7597, 0.764, 0.7677, 0.7685, 0.7693, 0.7677, 0.7662, 0.763, 0.7593, 0.753, 0.7471, 0.737, 0.7289, 0.718, 0.7077, 0.705, 0.6819, 0.666, 0.6515, 0.636, 0.6244, + 0.61, 0.5948, 0.577, 0.5581, 0.544, 0.5293, 0.522, 0.5147, 0.512, 0.5091, 0.506, 0.5029, 0.499, 0.4950, 0.494, 0.4931, 0.497, 0.5007, 0.508, 0.5176, 0.527, 0.5359, 0.542, 0.5487, 0.549, 0.5494, 0.544, + 0.5375, 0.531, 0.5244, 0.522, 0.5207, 0.524, 0.5264, 0.532, 0.5369, 0.542, 0.5505, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorcheckerSG : Skin F7 //use also for palette WB const double ColorTemp::ColorchechSGSkiF763_14_26_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0,0.0508,0.64,0.0776,0.903,0.1099,0.1128,0.1256,0.128,0.1307,0.133,0.1357,0.139,0.1425,0.148,0.1523,0.159,0.1669,0.177,0.1871,0.20,0.2118,0.2235,0.2355,0.2445,0.2537,0.259,0.2655,0.268, - 0.2700,0.2708,0.2716,0.2743,0.2770,0.2803,0.2827,0.283,0.2832,0.283,0.2828,0.295,0.3079,0.344,0.3803,0.4105,0.4409,0.455,0.4694,0.477,0.4851,0.4896,0.4962,0.501,0.5066,0.511,0.5160,0.521, - 0.5256,0.529,0.5318,0.535,0.5383,0.541,0.5451,0.549,0.5524,0.556,0.5597,0.562,0.5650,0.568,0.5709,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0508, 0.64, 0.0776, 0.903, 0.1099, 0.1128, 0.1256, 0.128, 0.1307, 0.133, 0.1357, 0.139, 0.1425, 0.148, 0.1523, 0.159, 0.1669, 0.177, 0.1871, 0.20, 0.2118, 0.2235, 0.2355, 0.2445, 0.2537, 0.259, 0.2655, 0.268, + 0.2700, 0.2708, 0.2716, 0.2743, 0.2770, 0.2803, 0.2827, 0.283, 0.2832, 0.283, 0.2828, 0.295, 0.3079, 0.344, 0.3803, 0.4105, 0.4409, 0.455, 0.4694, 0.477, 0.4851, 0.4896, 0.4962, 0.501, 0.5066, 0.511, 0.5160, 0.521, + 0.5256, 0.529, 0.5318, 0.535, 0.5383, 0.541, 0.5451, 0.549, 0.5524, 0.556, 0.5597, 0.562, 0.5650, 0.568, 0.5709, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorcheckerSG : Skin K2 85 11 17 //use also for palette WB const double ColorTemp::ColorchechSGSkiK285_11_17_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1122,0.149,0.1866,0.259,0.3318,0.393,0.4547,0.469,0.4846,0.4845,0.4844,0.4838,0.4834,0.4837,0.4840,0.4847,0.4854,0.4852,0.4849,0.4842,0.4835,0.4832,0.4828,0.485, - 0.4874,0.501,0.5150,0.536,0.5572,0.5685,0.5798,0.586,0.5932,0.5987,0.6142,0.6342,0.6541,0.683,0.7119,0.734,0.7571,0.769,0.7829,0.788,0.7932,0.795,0.7968,0.7973, - 0.7977,0.7974,0.7969,0.797,0.7972,0.7973,0.7975,0.7983,0.7990,0.7978,0.7965,0.7957,0.7949,0.7944,0.7940,0.794,0.7941,0.7943,0.7946,0.7938,0.7930,0.7929,0.7928, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1122, 0.149, 0.1866, 0.259, 0.3318, 0.393, 0.4547, 0.469, 0.4846, 0.4845, 0.4844, 0.4838, 0.4834, 0.4837, 0.4840, 0.4847, 0.4854, 0.4852, 0.4849, 0.4842, 0.4835, 0.4832, 0.4828, 0.485, + 0.4874, 0.501, 0.5150, 0.536, 0.5572, 0.5685, 0.5798, 0.586, 0.5932, 0.5987, 0.6142, 0.6342, 0.6541, 0.683, 0.7119, 0.734, 0.7571, 0.769, 0.7829, 0.788, 0.7932, 0.795, 0.7968, 0.7973, + 0.7977, 0.7974, 0.7969, 0.797, 0.7972, 0.7973, 0.7975, 0.7983, 0.7990, 0.7978, 0.7965, 0.7957, 0.7949, 0.7944, 0.7940, 0.794, 0.7941, 0.7943, 0.7946, 0.7938, 0.7930, 0.7929, 0.7928, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorcheck24 : White A4 L=96 //use also for palette WB const double ColorTemp::ColorchechWhiA496_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1267,0.172,0.2179,0.317,0.4164,0.505,0.6780,0.758,0.8397,0.865,0.8911,0.897,0.9035,0.9062,0.9092,0.9124,0.9154,0.9167,0.9180,0.9187,0.9194,0.92,0.9225,0.9217,0.9209,0.921, - 0.9212,0.9227,0.9242,0.9235,0.9227,0.9232,0.9238,0.9243,0.9248,0.9237,0.9227,0.9239,0.9252,0.924,0.9233,0.9238,0.9242,0.924,0.9239,0.9239,0.9239,0.924,0.9242,0.9239, - 0.9237,0.925,0.9264,0.9276,0.9288,0.9298,0.9308,0.9296,0.9284,0.928,0.9276,0.928,0.9284,0.9294,0.9304,0.9316,0.9328,0.9328,0.9328,0.9337,0.9345, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1267, 0.172, 0.2179, 0.317, 0.4164, 0.505, 0.6780, 0.758, 0.8397, 0.865, 0.8911, 0.897, 0.9035, 0.9062, 0.9092, 0.9124, 0.9154, 0.9167, 0.9180, 0.9187, 0.9194, 0.92, 0.9225, 0.9217, 0.9209, 0.921, + 0.9212, 0.9227, 0.9242, 0.9235, 0.9227, 0.9232, 0.9238, 0.9243, 0.9248, 0.9237, 0.9227, 0.9239, 0.9252, 0.924, 0.9233, 0.9238, 0.9242, 0.924, 0.9239, 0.9239, 0.9239, 0.924, 0.9242, 0.9239, + 0.9237, 0.925, 0.9264, 0.9276, 0.9288, 0.9298, 0.9308, 0.9296, 0.9284, 0.928, 0.9276, 0.928, 0.9284, 0.9294, 0.9304, 0.9316, 0.9328, 0.9328, 0.9328, 0.9337, 0.9345, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data Colorcheck24 : foliage Green D1 const double ColorTemp::ColorchechGreD1_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0477,0.0492,0.0507,0.0517,0.0527,0.0532,0.0537,0.054,0.0544,0.0554,0.0563,0.0573,0.0584,0.0592,0.0601,0.0607,0.0611,0.0613,0.0619,0.626,0.0634,0.0646,0.0659,0.069, - 0.0721,0.0837,0.0958,0.117,0.1386,0.156,0.1748,0.1802,0.1855,0.1795,0.1742,0.1636,0.1529,0.144,0.1351,0.13,0.1239,0.1202,0.1171,0.1138,0.1106,0.108,0.1048,0.1035, - 0.1022,0.1025,0.1030,0.1041,0.1052,0.106,0.1068,0.107,0.1073,0.1066,0.1060,0.1047,0.1035,0.1028,0.1021,0.1029,0.1034,0.105,0.1069,0.1086,0.1104,0.1127,0.1150, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0477, 0.0492, 0.0507, 0.0517, 0.0527, 0.0532, 0.0537, 0.054, 0.0544, 0.0554, 0.0563, 0.0573, 0.0584, 0.0592, 0.0601, 0.0607, 0.0611, 0.0613, 0.0619, 0.626, 0.0634, 0.0646, 0.0659, 0.069, + 0.0721, 0.0837, 0.0958, 0.117, 0.1386, 0.156, 0.1748, 0.1802, 0.1855, 0.1795, 0.1742, 0.1636, 0.1529, 0.144, 0.1351, 0.13, 0.1239, 0.1202, 0.1171, 0.1138, 0.1106, 0.108, 0.1048, 0.1035, + 0.1022, 0.1025, 0.1030, 0.1041, 0.1052, 0.106, 0.1068, 0.107, 0.1073, 0.1066, 0.1060, 0.1047, 0.1035, 0.1028, 0.1021, 0.1029, 0.1034, 0.105, 0.1069, 0.1086, 0.1104, 0.1127, 0.1150, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorchecSG : black N3 L=6 //use also for palette WB const double ColorTemp::ColorchechSGBlaN3_6_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0066,0.0069,0.0071,0.0072,0.0074,0.0073,0.0072,0.0073,0.0074,0.0074,0.0074,0.0074,0.0074,0.0073,0.0073,0.0073,0.0073,0.0072,0.0072,0.0072,0.0072,0.0071,0.0071,0.0071, - 0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0070,0.0070,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0071,0.0070, - 0.0070,0.0070,0.0070,0.0069,0.0069,0.0069,0.0068,0.0068,0.0068,0.0068,0.0068,0.0068,0.0067,0.0067,0.0067,0.0067,0.0066,0.0066,0.0066,0.0066,0.0066,0.0066,0.0066,0.0067, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0066, 0.0069, 0.0071, 0.0072, 0.0074, 0.0073, 0.0072, 0.0073, 0.0074, 0.0074, 0.0074, 0.0074, 0.0074, 0.0073, 0.0073, 0.0073, 0.0073, 0.0072, 0.0072, 0.0072, 0.0072, 0.0071, 0.0071, 0.0071, + 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0070, 0.0070, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0071, 0.0070, + 0.0070, 0.0070, 0.0070, 0.0069, 0.0069, 0.0069, 0.0068, 0.0068, 0.0068, 0.0068, 0.0068, 0.0068, 0.0067, 0.0067, 0.0067, 0.0067, 0.0066, 0.0066, 0.0066, 0.0066, 0.0066, 0.0066, 0.0066, 0.0067, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data 468 color : gray K14 L=44 //use also for palette WB const double ColorTemp::JDC468_GraK14_44_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.04240,0.0485,0.05500,0.0624,0.06930,0.084,0.09820,0.109,0.12160,0.127,0.13300,0.13490,0.13690,0.1379,0.13890,0.1396,0.14060,0.1407,0.14080,0.1423,0.14380,0.1488,0.15370,0.157,0.16040, - 0.157,0.15360,0.1482,0.14290,0.1436,0.14470,0.1454,0.14620,0.137,0.12870,0.1205,0.11250,0.116,0.11930,0.1261,0.13350,0.1367,0.13990,0.139,0.13810,0.1371,0.13610,0.1372,0.13820, - 0.1408,0.14330,0.1475,0.15170,0.1583,0.16500,0.172,0.17940,0.1836,0.18780,0.188,0.18820,0.186,0.18430,0.1801,0.17620,0.1741,0.17210,0.179,0.18420,0.1991,0.21430, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.04240, 0.0485, 0.05500, 0.0624, 0.06930, 0.084, 0.09820, 0.109, 0.12160, 0.127, 0.13300, 0.13490, 0.13690, 0.1379, 0.13890, 0.1396, 0.14060, 0.1407, 0.14080, 0.1423, 0.14380, 0.1488, 0.15370, 0.157, 0.16040, + 0.157, 0.15360, 0.1482, 0.14290, 0.1436, 0.14470, 0.1454, 0.14620, 0.137, 0.12870, 0.1205, 0.11250, 0.116, 0.11930, 0.1261, 0.13350, 0.1367, 0.13990, 0.139, 0.13810, 0.1371, 0.13610, 0.1372, 0.13820, + 0.1408, 0.14330, 0.1475, 0.15170, 0.1583, 0.16500, 0.172, 0.17940, 0.1836, 0.18780, 0.188, 0.18820, 0.186, 0.18430, 0.1801, 0.17620, 0.1741, 0.17210, 0.179, 0.18420, 0.1991, 0.21430, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data 468 color : Blue H10 - Gamut > WidegamutRGB const double ColorTemp::JDC468_BluH10_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.01590,0.028,0.03970,0.0697,0.09970,0.1526,0.20550,0.253,0.30110,0.3412,0.38180,0.423,0.46610,0.4683,0.51030,0.4999,0.49950,0.4785,0.45810,0.429,0.39950,0.374,0.35010,0.3135,0.29630, - 0.2587,0.22070,0.182,0.14450,0.1125,0.09060,0.072,0.04810,0.033,0.01740,0.0113,0.00520,0.004,0.00290,0.0028,0.00270,0.0027,0.00270,0.0027,0.00280,0.0027,0.00270,0.0028,0.00280, - 0.0029,0.00300,0.0029,0.00290,0.0029,0.0029,0.00290,0.0029,0.00290,0.0029,0.00290,0.0029,0.00290,0.0029,0.00290,0.0029,0.0031,0.00320,0.0035,0.00380,0.047,0.00560, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.01590, 0.028, 0.03970, 0.0697, 0.09970, 0.1526, 0.20550, 0.253, 0.30110, 0.3412, 0.38180, 0.423, 0.46610, 0.4683, 0.51030, 0.4999, 0.49950, 0.4785, 0.45810, 0.429, 0.39950, 0.374, 0.35010, 0.3135, 0.29630, + 0.2587, 0.22070, 0.182, 0.14450, 0.1125, 0.09060, 0.072, 0.04810, 0.033, 0.01740, 0.0113, 0.00520, 0.004, 0.00290, 0.0028, 0.00270, 0.0027, 0.00270, 0.0027, 0.00280, 0.0027, 0.00270, 0.0028, 0.00280, + 0.0029, 0.00300, 0.0029, 0.00290, 0.0029, 0.0029, 0.00290, 0.0029, 0.00290, 0.0029, 0.00290, 0.0029, 0.00290, 0.0029, 0.00290, 0.0029, 0.0031, 0.00320, 0.0035, 0.00380, 0.047, 0.00560, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 35 15 17 const double ColorTemp::ColabSkin35_15_17_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0211,0.022, 0.0225,0.0234, 0.0244,0.0294, 0.0349,0.038, 0.0411,0.0425, 0.0441,0.0455, 0.0472,0.0473, 0.0475,0.0463, 0.0452,0.0435, 0.0417,0.0397, 0.0377, - 0.0375, 0.0372,0.0412, 0.0452,0.052, 0.0603,0.0655, 0.0707,0.0722, 0.0736,0.0738, 0.0741,0.0737, 0.0731,0.0721, 0.0711,0.0707, 0.0704,0.071, 0.0717, - 0.0782, 0.0846,0.099, 0.1159,0.1298, 0.1432,0.1497, 0.1581,0.1603, 0.1644,0.1659, 0.1673,0.1679, 0.1690,0.1696, 0.1702,0.1704, 0.1705,0.1706, 0.1707,0.1707, 0.1707,0.1707, 0.1706,0.1706, 0.1707,0.1707, 0.1706,0.1712, 0.1719, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0211, 0.022, 0.0225, 0.0234, 0.0244, 0.0294, 0.0349, 0.038, 0.0411, 0.0425, 0.0441, 0.0455, 0.0472, 0.0473, 0.0475, 0.0463, 0.0452, 0.0435, 0.0417, 0.0397, 0.0377, + 0.0375, 0.0372, 0.0412, 0.0452, 0.052, 0.0603, 0.0655, 0.0707, 0.0722, 0.0736, 0.0738, 0.0741, 0.0737, 0.0731, 0.0721, 0.0711, 0.0707, 0.0704, 0.071, 0.0717, + 0.0782, 0.0846, 0.099, 0.1159, 0.1298, 0.1432, 0.1497, 0.1581, 0.1603, 0.1644, 0.1659, 0.1673, 0.1679, 0.1690, 0.1696, 0.1702, 0.1704, 0.1705, 0.1706, 0.1707, 0.1707, 0.1707, 0.1707, 0.1706, 0.1706, 0.1707, 0.1707, 0.1706, 0.1712, 0.1719, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 57 22 18 const double ColorTemp::ColabSkin57_22_18_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0647,0.0677, 0.0709,0.0754, 0.0797,0.099, 0.1181,0.1296, 0.1409,0.1469, 0.1529,0.1594, 0.1657,0.1672, 0.1683,0.1648, 0.1615,0.1561, 0.1506,0.144, 0.1375,0.136, 0.1339, - 0.1437, 0.1531,0.172, 0.1911,0.2032, 0.2153,0.2171, 0.2190,0.2176, 0.2164,0.213, 0.2095,0.2048, 0.2005,0.1985, 0.1965,0.198, 0.1997,0.2196, 0.2396,0.288, 0.3362,0.378, - 0.4209,0.444, 0.4671,0.477, 0.4865,0.491, 0.4955,0.498, 0.5007,0.5027, 0.5048,0.5055, 0.5061,0.5063, 0.5066,0.5065, 0.5063,0.506, 0.5057,0.5056, 0.5055,0.5056, 0.5057,0.5078, 0.5099, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0647, 0.0677, 0.0709, 0.0754, 0.0797, 0.099, 0.1181, 0.1296, 0.1409, 0.1469, 0.1529, 0.1594, 0.1657, 0.1672, 0.1683, 0.1648, 0.1615, 0.1561, 0.1506, 0.144, 0.1375, 0.136, 0.1339, + 0.1437, 0.1531, 0.172, 0.1911, 0.2032, 0.2153, 0.2171, 0.2190, 0.2176, 0.2164, 0.213, 0.2095, 0.2048, 0.2005, 0.1985, 0.1965, 0.198, 0.1997, 0.2196, 0.2396, 0.288, 0.3362, 0.378, + 0.4209, 0.444, 0.4671, 0.477, 0.4865, 0.491, 0.4955, 0.498, 0.5007, 0.5027, 0.5048, 0.5055, 0.5061, 0.5063, 0.5066, 0.5065, 0.5063, 0.506, 0.5057, 0.5056, 0.5055, 0.5056, 0.5057, 0.5078, 0.5099, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 40 17 17 const double ColorTemp::ColabSkin40_17_17_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0296,0.0306, 0.0317,0.0332, 0.0346,0.042, 0.0498,0.0543, 0.0588,0.061, 0.0632,0.0624, 0.0678,0.068, 0.0682,0.0663, 0.0649,0.0625, 0.0598,0.057, 0.0540,0.0535, 0.0529,0.057, - 0.0631,0.072, 0.0827,0.089, 0.0959,0.0975, 0.0994,0.0996, 0.0997,0.0988, 0.0980,0.0966, 0.0951,0.0945, 0.0939,0.0948, 0.0957,0.105, 0.1143,0.136, 0.1589,0.178, 0.1980, - 0.2095, 0.2194,0.224, 0.2283,0.2302, 0.2325,0.2337, 0.2348,0.2357, 0.2366,0.2369, 0.2371,0.2372, 0.2373,0.2373, 0.2373,0.2373, 0.2372,0.2372, 0.2372,0.2372, 0.2372,0.238, 0.2389, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0296, 0.0306, 0.0317, 0.0332, 0.0346, 0.042, 0.0498, 0.0543, 0.0588, 0.061, 0.0632, 0.0624, 0.0678, 0.068, 0.0682, 0.0663, 0.0649, 0.0625, 0.0598, 0.057, 0.0540, 0.0535, 0.0529, 0.057, + 0.0631, 0.072, 0.0827, 0.089, 0.0959, 0.0975, 0.0994, 0.0996, 0.0997, 0.0988, 0.0980, 0.0966, 0.0951, 0.0945, 0.0939, 0.0948, 0.0957, 0.105, 0.1143, 0.136, 0.1589, 0.178, 0.1980, + 0.2095, 0.2194, 0.224, 0.2283, 0.2302, 0.2325, 0.2337, 0.2348, 0.2357, 0.2366, 0.2369, 0.2371, 0.2372, 0.2373, 0.2373, 0.2373, 0.2373, 0.2372, 0.2372, 0.2372, 0.2372, 0.2372, 0.238, 0.2389, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 91 4 14 const double ColorTemp::ColabSkin91_4_14_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1430,0.16, 0.1778,0.202, 0.2303,0.301, 0.3813,0.4245, 0.4692,0.499, 0.5287,0.5635, 0.5977,0.6175, 0.6372,0.6394, 0.6418,0.638, 0.6341,0.6228, 0.6117,0.6121, 0.6125, - 0.646, 0.6807,0.742, 0.8032,0.8355, 0.8687,0.8595, 0.8510,0.828, 0.8059,0.778, 0.7490,0.721, 0.6914,0.676, 0.6608,0.657, 0.6530,0.6565, 0.7001,0.7609, 0.8219, - 0.876, 0.9297,0.9598, 0.9901,1.003, 1.0156,1.021, 1.0289,1.0346, 1.0396,1.045, 1.0513,1.0538, 1.0561,1.0559, 1.0557,1.054, 1.0523,1.049, 1.0466,1.045, 1.0436,1.0445, 1.0455,1.053, 1.0605, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1430, 0.16, 0.1778, 0.202, 0.2303, 0.301, 0.3813, 0.4245, 0.4692, 0.499, 0.5287, 0.5635, 0.5977, 0.6175, 0.6372, 0.6394, 0.6418, 0.638, 0.6341, 0.6228, 0.6117, 0.6121, 0.6125, + 0.646, 0.6807, 0.742, 0.8032, 0.8355, 0.8687, 0.8595, 0.8510, 0.828, 0.8059, 0.778, 0.7490, 0.721, 0.6914, 0.676, 0.6608, 0.657, 0.6530, 0.6565, 0.7001, 0.7609, 0.8219, + 0.876, 0.9297, 0.9598, 0.9901, 1.003, 1.0156, 1.021, 1.0289, 1.0346, 1.0396, 1.045, 1.0513, 1.0538, 1.0561, 1.0559, 1.0557, 1.054, 1.0523, 1.049, 1.0466, 1.045, 1.0436, 1.0445, 1.0455, 1.053, 1.0605, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 87 8 8 const double ColorTemp::ColabSkin87_8_8_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1433,0.161, 0.1780,0.204, 0.2305,0.306, 0.3828,0.428, 0.4722,0.502, 0.5317,0.5645, 0.5997,0.618, 0.6366,0.6368, 0.6370,0.631, 0.6251,0.6120, 0.5994,0.596, - 0.5931,0.618, 0.6420,0.705, 0.7347,0.757, 0.7785,0.765, 0.7532,0.71, 0.7062,0.677, 0.6491,0.62, 0.5922,0.577, 0.5619,0.5586, 0.5556,0.579, 0.6121, - 0.684, 0.7563,0.82, 0.8837,0.918, 0.9545,0.969, 0.9843,0.992, 0.9991,1.005, 1.0104,1.016, 1.0223,1.0248, 1.0273,1.0272, 1.0271,1.025, 1.0238,1.02, 1.0182,1.017, 1.0151,1.016, 1.0171,1.024, 1.0321, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1433, 0.161, 0.1780, 0.204, 0.2305, 0.306, 0.3828, 0.428, 0.4722, 0.502, 0.5317, 0.5645, 0.5997, 0.618, 0.6366, 0.6368, 0.6370, 0.631, 0.6251, 0.6120, 0.5994, 0.596, + 0.5931, 0.618, 0.6420, 0.705, 0.7347, 0.757, 0.7785, 0.765, 0.7532, 0.71, 0.7062, 0.677, 0.6491, 0.62, 0.5922, 0.577, 0.5619, 0.5586, 0.5556, 0.579, 0.6121, + 0.684, 0.7563, 0.82, 0.8837, 0.918, 0.9545, 0.969, 0.9843, 0.992, 0.9991, 1.005, 1.0104, 1.016, 1.0223, 1.0248, 1.0273, 1.0272, 1.0271, 1.025, 1.0238, 1.02, 1.0182, 1.017, 1.0151, 1.016, 1.0171, 1.024, 1.0321, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 89 8 21 const double ColorTemp::ColabSkin89_8_21_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1394,0.152, 0.1659,0.1855, 0.2052,0.266, 0.3277,0.363, 0.3988,0.422, 0.4450,0.472, 0.4984,0.512, 0.5270,0.5274, 0.5278,0.522, 0.5177,0.5065, 0.4960,0.4975, - 0.4995,0.535, 0.5721,0.637, 0.7016,0.7395, 0.7786,0.7777, 0.7767,0.763, 0.7485,0.728, 0.7081,0.687, 0.6649,0.653, 0.6425,0.641, 0.6391,0.665, 0.6925,0.76, - 0.8266,0.885, 0.9447,0.975, 1.0106,1.025, 1.0383,1.045, 1.0525,1.058, 1.0628,1.068, 1.0730,1.075, 1.0768,1.0768, 1.0769,1.0755, 1.0744,1.0724, 1.0704,1.069, 1.0685,1.0691, 1.0697,1.075, 1.0823, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1394, 0.152, 0.1659, 0.1855, 0.2052, 0.266, 0.3277, 0.363, 0.3988, 0.422, 0.4450, 0.472, 0.4984, 0.512, 0.5270, 0.5274, 0.5278, 0.522, 0.5177, 0.5065, 0.4960, 0.4975, + 0.4995, 0.535, 0.5721, 0.637, 0.7016, 0.7395, 0.7786, 0.7777, 0.7767, 0.763, 0.7485, 0.728, 0.7081, 0.687, 0.6649, 0.653, 0.6425, 0.641, 0.6391, 0.665, 0.6925, 0.76, + 0.8266, 0.885, 0.9447, 0.975, 1.0106, 1.025, 1.0383, 1.045, 1.0525, 1.058, 1.0628, 1.068, 1.0730, 1.075, 1.0768, 1.0768, 1.0769, 1.0755, 1.0744, 1.0724, 1.0704, 1.069, 1.0685, 1.0691, 1.0697, 1.075, 1.0823, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 75 8 4 const double ColorTemp::ColabSkin75_8_4_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1030,0.116, 0.1294,0.1495, 0.1696,0.227, 0.2847,0.319, 0.3524,0.375, 0.3977,0.423, 0.4492,0.462, 0.4770,0.4768, 0.4767,0.471, 0.4675,0.458, 0.4480,0.444, 0.4408, - 0.455, 0.4688,0.496, 0.5243,0.535, 0.5465,0.534, 0.5228,0.503, 0.4851,0.463, 0.4408,0.419, 0.3974,0.385, 0.3741,0.371, 0.3692,0.391, 0.4110,0.464, 0.5180, - 0.565, 0.6126,0.638, 0.6651,0.676, 0.6871,0.692, 0.6979,0.702, 0.7062,0.71, 0.7151,0.717, 0.7189,0.7188, 0.7187,0.717, 0.7162,0.714, 0.7119,0.7105, 0.7095,0.7097, 0.7110,0.716, 0.7223, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1030, 0.116, 0.1294, 0.1495, 0.1696, 0.227, 0.2847, 0.319, 0.3524, 0.375, 0.3977, 0.423, 0.4492, 0.462, 0.4770, 0.4768, 0.4767, 0.471, 0.4675, 0.458, 0.4480, 0.444, 0.4408, + 0.455, 0.4688, 0.496, 0.5243, 0.535, 0.5465, 0.534, 0.5228, 0.503, 0.4851, 0.463, 0.4408, 0.419, 0.3974, 0.385, 0.3741, 0.371, 0.3692, 0.391, 0.4110, 0.464, 0.5180, + 0.565, 0.6126, 0.638, 0.6651, 0.676, 0.6871, 0.692, 0.6979, 0.702, 0.7062, 0.71, 0.7151, 0.717, 0.7189, 0.7188, 0.7187, 0.717, 0.7162, 0.714, 0.7119, 0.7105, 0.7095, 0.7097, 0.7110, 0.716, 0.7223, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 75 10 33 const double ColorTemp::ColabSkin75_10_33_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0873,0.091, 0.0967,0.103, 0.1097,0.135, 0.1617,0.177, 0.1913,0.198, 0.2086,0.218, 0.2289,0.234, 0.2383,0.2375, 0.2370,0.2335, 0.2299,0.223, 0.2180,0.222, - 0.2259,0.256, 0.2860,0.338, 0.3905,0.426, 0.4613,0.47, 0.4786,0.478, 0.4772,0.471, 0.4668,0.459, 0.4522,0.449, 0.4454,0.446, 0.4467,0.464, 0.4834,0.527, - 0.5727,0.609, 0.6511,0.673, 0.6946,0.703, 0.7130,0.718, 0.7224,0.725, 0.7285,0.731, 0.7337,0.7345, 0.7351,0.7353, 0.7355,0.735, 0.7348,0.7342, 0.7337,0.7336, 0.7335,0.7335, 0.7336,0.737, 0.7395, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0873, 0.091, 0.0967, 0.103, 0.1097, 0.135, 0.1617, 0.177, 0.1913, 0.198, 0.2086, 0.218, 0.2289, 0.234, 0.2383, 0.2375, 0.2370, 0.2335, 0.2299, 0.223, 0.2180, 0.222, + 0.2259, 0.256, 0.2860, 0.338, 0.3905, 0.426, 0.4613, 0.47, 0.4786, 0.478, 0.4772, 0.471, 0.4668, 0.459, 0.4522, 0.449, 0.4454, 0.446, 0.4467, 0.464, 0.4834, 0.527, + 0.5727, 0.609, 0.6511, 0.673, 0.6946, 0.703, 0.7130, 0.718, 0.7224, 0.725, 0.7285, 0.731, 0.7337, 0.7345, 0.7351, 0.7353, 0.7355, 0.735, 0.7348, 0.7342, 0.7337, 0.7336, 0.7335, 0.7335, 0.7336, 0.737, 0.7395, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 65 33 11 const double ColorTemp::ColabSkin65_33_11_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1067,0.113, 0.1182,0.126, 0.1346,0.165, 0.2033,0.224, 0.2448,0.259, 0.2666,0.277, 0.2891,0.291, 0.2927,0.285, 0.2783,0.268, 0.2569,0.244, 0.2323,0.225, 0.2195, - 0.225, 0.2323,0.248, 0.2655,0.275, 0.2832,0.281, 0.2797,0.275, 0.2708,0.264, 0.2567,0.248, 0.2403,0.236, 0.2326,0.235, 0.2386,0.274, 0.3116,0.40, 0.4885,0.56, - 0.6435,0.688, 0.7279,0.745, 0.7633,0.772, 0.7791,0.783, 0.7883,0.792, 0.7955,0.7965, 0.7978,0.7982, 0.7989,0.7985, 0.7983,0.7975, 0.7971,0.7968, 0.7966,0.7968, 0.7970,0.801, 0.8043, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1067, 0.113, 0.1182, 0.126, 0.1346, 0.165, 0.2033, 0.224, 0.2448, 0.259, 0.2666, 0.277, 0.2891, 0.291, 0.2927, 0.285, 0.2783, 0.268, 0.2569, 0.244, 0.2323, 0.225, 0.2195, + 0.225, 0.2323, 0.248, 0.2655, 0.275, 0.2832, 0.281, 0.2797, 0.275, 0.2708, 0.264, 0.2567, 0.248, 0.2403, 0.236, 0.2326, 0.235, 0.2386, 0.274, 0.3116, 0.40, 0.4885, 0.56, + 0.6435, 0.688, 0.7279, 0.745, 0.7633, 0.772, 0.7791, 0.783, 0.7883, 0.792, 0.7955, 0.7965, 0.7978, 0.7982, 0.7989, 0.7985, 0.7983, 0.7975, 0.7971, 0.7968, 0.7966, 0.7968, 0.7970, 0.801, 0.8043, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 65 7 24 const double ColorTemp::ColabSkin65_7_24_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0619,0.066, 0.0710,0.077, 0.0840,0.106, 0.1288,0.142, 0.1546,0.163, 0.1706,0.179, 0.1893,0.194, 0.1989,0.1988, 0.1987,0.196, 0.1941,0.189, 0.1853,0.188, 0.1894, - 0.209, 0.2282,0.262, 0.2962,0.318, 0.3402,0.343, 0.3469,0.343, 0.3407,0.334, 0.3285,0.321, 0.3140,0.31, 0.3069,0.308, 0.3066,0.319, 0.3311,0.362, 0.3918,0.418, - 0.4451,0.459, 0.4747,0.481, 0.4873,0.491, 0.4937,0.496, 0.4981,0.501, 0.5022,0.503, 0.5035,0.5035, 0.5036,0.5032, 0.5029,0.5022, 0.5016,0.5013, 0.5011,0.5013, 0.5014,0.504, 0.5063, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0619, 0.066, 0.0710, 0.077, 0.0840, 0.106, 0.1288, 0.142, 0.1546, 0.163, 0.1706, 0.179, 0.1893, 0.194, 0.1989, 0.1988, 0.1987, 0.196, 0.1941, 0.189, 0.1853, 0.188, 0.1894, + 0.209, 0.2282, 0.262, 0.2962, 0.318, 0.3402, 0.343, 0.3469, 0.343, 0.3407, 0.334, 0.3285, 0.321, 0.3140, 0.31, 0.3069, 0.308, 0.3066, 0.319, 0.3311, 0.362, 0.3918, 0.418, + 0.4451, 0.459, 0.4747, 0.481, 0.4873, 0.491, 0.4937, 0.496, 0.4981, 0.501, 0.5022, 0.503, 0.5035, 0.5035, 0.5036, 0.5032, 0.5029, 0.5022, 0.5016, 0.5013, 0.5011, 0.5013, 0.5014, 0.504, 0.5063, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 57 19 6 const double ColorTemp::ColabSkin57_19_6_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0662,0.071, 0.0773,0.085, 0.0939,0.115, 0.1491,0.165, 0.1821,0.192, 0.2019,0.214, 0.2236,0.228, 0.2321,0.2298, 0.2266,0.221, 0.2161,0.208, 0.2019,0.199, - 0.1951,0.201, 0.2066,0.219, 0.2325,0.239, 0.2443,0.241, 0.2366,0.23, 0.2235,0.215, 0.2068,0.199, 0.1895,0.185, 0.1806,0.1811, 0.1816,0.20, 0.2197,0.267, 0.3135, - 0.355, 0.3960,0.418, 0.4411,0.449, 0.4600,0.4643, 0.4687,0.471, 0.4743,0.477, 0.4792,0.48, 0.4811,0.4813, 0.4815,0.481, 0.4806,0.4798, 0.4790,0.4786, 0.4782,0.4786, 0.4788,0.481, 0.4844, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0662, 0.071, 0.0773, 0.085, 0.0939, 0.115, 0.1491, 0.165, 0.1821, 0.192, 0.2019, 0.214, 0.2236, 0.228, 0.2321, 0.2298, 0.2266, 0.221, 0.2161, 0.208, 0.2019, 0.199, + 0.1951, 0.201, 0.2066, 0.219, 0.2325, 0.239, 0.2443, 0.241, 0.2366, 0.23, 0.2235, 0.215, 0.2068, 0.199, 0.1895, 0.185, 0.1806, 0.1811, 0.1816, 0.20, 0.2197, 0.267, 0.3135, + 0.355, 0.3960, 0.418, 0.4411, 0.449, 0.4600, 0.4643, 0.4687, 0.471, 0.4743, 0.477, 0.4792, 0.48, 0.4811, 0.4813, 0.4815, 0.481, 0.4806, 0.4798, 0.4790, 0.4786, 0.4782, 0.4786, 0.4788, 0.481, 0.4844, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 57 4 19 const double ColorTemp::ColabSkin57_4_19_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0430,0.047, 0.0505,0.056, 0.0614,0.077, 0.0963,0.1063, 0.1164,0.123, 0.1294,0.137, 0.1448,0.149, 0.1533,0.154, 0.1544,0.153, 0.1521,0.149, 0.1463,0.148, - 0.1496,0.164, 0.1780,0.202, 0.2273,0.242, 0.2585,0.26, 0.2616,0.258, 0.2550,0.2495, 0.2442,0.238, 0.2320,0.229, 0.2258,0.2253, 0.2247,0.232, 0.2394, - 0.258, 0.2763,0.292, 0.3087,0.318, 0.3269,0.331, 0.3346,0.337, 0.3387,0.341, 0.3417,0.343, 0.3447,0.345, 0.3457,0.3457, 0.3457,0.3455, 0.3451,0.3445, 0.3439,0.3437, 0.3435,0.3437, 0.3438,0.346, 0.3475, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0430, 0.047, 0.0505, 0.056, 0.0614, 0.077, 0.0963, 0.1063, 0.1164, 0.123, 0.1294, 0.137, 0.1448, 0.149, 0.1533, 0.154, 0.1544, 0.153, 0.1521, 0.149, 0.1463, 0.148, + 0.1496, 0.164, 0.1780, 0.202, 0.2273, 0.242, 0.2585, 0.26, 0.2616, 0.258, 0.2550, 0.2495, 0.2442, 0.238, 0.2320, 0.229, 0.2258, 0.2253, 0.2247, 0.232, 0.2394, + 0.258, 0.2763, 0.292, 0.3087, 0.318, 0.3269, 0.331, 0.3346, 0.337, 0.3387, 0.341, 0.3417, 0.343, 0.3447, 0.345, 0.3457, 0.3457, 0.3457, 0.3455, 0.3451, 0.3445, 0.3439, 0.3437, 0.3435, 0.3437, 0.3438, 0.346, 0.3475, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 57 10 28 const double ColorTemp::ColabSkin57_10_28_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0463,0.048, 0.0505,0.053, 0.0563,0.069, 0.0816,0.088, 0.0961,0.102, 0.1041,0.1085, 0.1135,0.1155, 0.1174,0.1168, 0.1161,0.114, 0.1118,0.1085, 0.1054,0.1074, 0.1094,0.124, - 0.1406,0.168, 0.1951,0.223, 0.2325,0.238, 0.2426,0.243, 0.2432,0.242, 0.2391,0.239, 0.2326,0.231, 0.2297,0.234, 0.2309,0.242, 0.2516,0.277, 0.3017,0.324, - 0.3456,0.358, 0.3700,0.375, 0.3802,0.3827, 0.3854,0.387, 0.3887,0.39, 0.3913,0.3916, 0.3920,0.3921, 0.3923,0.3921, 0.3920,0.3918, 0.3916,0.3916, 0.3915,0.3915, 0.3915,0.393, 0.3945, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0463, 0.048, 0.0505, 0.053, 0.0563, 0.069, 0.0816, 0.088, 0.0961, 0.102, 0.1041, 0.1085, 0.1135, 0.1155, 0.1174, 0.1168, 0.1161, 0.114, 0.1118, 0.1085, 0.1054, 0.1074, 0.1094, 0.124, + 0.1406, 0.168, 0.1951, 0.223, 0.2325, 0.238, 0.2426, 0.243, 0.2432, 0.242, 0.2391, 0.239, 0.2326, 0.231, 0.2297, 0.234, 0.2309, 0.242, 0.2516, 0.277, 0.3017, 0.324, + 0.3456, 0.358, 0.3700, 0.375, 0.3802, 0.3827, 0.3854, 0.387, 0.3887, 0.39, 0.3913, 0.3916, 0.3920, 0.3921, 0.3923, 0.3921, 0.3920, 0.3918, 0.3916, 0.3916, 0.3915, 0.3915, 0.3915, 0.393, 0.3945, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 40 7 19 const double ColorTemp::ColabSkin40_7_19_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0215,0.023, 0.0240,0.026, 0.0275,0.033, 0.0409,0.044, 0.0487,0.051, 0.0532,0.056, 0.0585,0.0595, 0.0608,0.0605, 0.0602,0.059, 0.0581,0.057, 0.0549,0.0555, 0.0562, - 0.061, 0.0692,0.08, 0.0922,0.099, 0.1075,0.109, 0.1107,0.11, 0.1098,0.1082, 0.1069,0.1045, 0.1031,0.102, 0.1013,0.1015, 0.1016,0.106, 0.1112,0.123, 0.1348,0.145, - 0.1554,0.161, 0.1668,0.169, 0.1716,0.1728, 0.1741,0.175, 0.1756,0.1763, 0.1769,0.1771, 0.1773,0.1773, 0.1774,0.1773, 0.1772,0.177, 0.1769,0.1769, 0.1769,0.1769, 0.1769,0.1777, 0.1784, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0215, 0.023, 0.0240, 0.026, 0.0275, 0.033, 0.0409, 0.044, 0.0487, 0.051, 0.0532, 0.056, 0.0585, 0.0595, 0.0608, 0.0605, 0.0602, 0.059, 0.0581, 0.057, 0.0549, 0.0555, 0.0562, + 0.061, 0.0692, 0.08, 0.0922, 0.099, 0.1075, 0.109, 0.1107, 0.11, 0.1098, 0.1082, 0.1069, 0.1045, 0.1031, 0.102, 0.1013, 0.1015, 0.1016, 0.106, 0.1112, 0.123, 0.1348, 0.145, + 0.1554, 0.161, 0.1668, 0.169, 0.1716, 0.1728, 0.1741, 0.175, 0.1756, 0.1763, 0.1769, 0.1771, 0.1773, 0.1773, 0.1774, 0.1773, 0.1772, 0.177, 0.1769, 0.1769, 0.1769, 0.1769, 0.1769, 0.1777, 0.1784, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 40 17 6 const double ColorTemp::ColabSkin40_17_6_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0314,0.033, 0.0359,0.039, 0.0427,0.054, 0.0668,0.074, 0.0812,0.085, 0.0895,0.094, 0.0985,0.10, 0.1015,0.0991, 0.0984,0.096, 0.0930,0.089, 0.0861,0.085, 0.0828, - 0.085, 0.0878,0.094, 0.0995,0.103, 0.1052,0.1035, 0.1026,0.10, 0.0976,0.094, 0.0911,0.088, 0.0840,0.083, 0.0805,0.081, 0.0814,0.09, 0.1006,0.124, - 0.1474,0.1685, 0.1885,0.1995, 0.2110,0.216, 0.2204,0.223, 0.2247,0.226, 0.2273,0.2284, 0.2296,0.230, 0.2304,0.2305, 0.2306,0.2305, 0.2303,0.23, 0.2297,0.2296, 0.2294,0.2295, 0.2296,0.231, 0.2321, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0314, 0.033, 0.0359, 0.039, 0.0427, 0.054, 0.0668, 0.074, 0.0812, 0.085, 0.0895, 0.094, 0.0985, 0.10, 0.1015, 0.0991, 0.0984, 0.096, 0.0930, 0.089, 0.0861, 0.085, 0.0828, + 0.085, 0.0878, 0.094, 0.0995, 0.103, 0.1052, 0.1035, 0.1026, 0.10, 0.0976, 0.094, 0.0911, 0.088, 0.0840, 0.083, 0.0805, 0.081, 0.0814, 0.09, 0.1006, 0.124, + 0.1474, 0.1685, 0.1885, 0.1995, 0.2110, 0.216, 0.2204, 0.223, 0.2247, 0.226, 0.2273, 0.2284, 0.2296, 0.230, 0.2304, 0.2305, 0.2306, 0.2305, 0.2303, 0.23, 0.2297, 0.2296, 0.2294, 0.2295, 0.2296, 0.231, 0.2321, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 40 4 11 const double ColorTemp::ColabSkin40_4_11_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0209,0.023, 0.0250,0.028, 0.0310,0.039, 0.0497,0.056, 0.0605,0.064, 0.0675,0.072, 0.0758,0.078, 0.0802,0.0803, 0.0804,0.0797, 0.0790,0.078, 0.0758,0.076, 0.0764,0.082, - 0.0875,0.098, 0.1072,0.113, 0.1189,0.1187, 0.1185,0.116, 0.1141,0.111, 0.1078,0.104, 0.1012,0.099, 0.0977,0.098, 0.0971,0.101, 0.1049,0.115, 0.1245,0.133, - 0.1417,0.147, 0.1513,0.153, 0.1554,0.1564, 0.1575,0.158, 0.1590,0.1598, 0.1606,0.1608, 0.1611,0.1611, 0.1611,0.1609, 0.1608,0.1604, 0.1601,0.160, 0.1598,0.1599, 0.1600,0.1609, 0.1619, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0209, 0.023, 0.0250, 0.028, 0.0310, 0.039, 0.0497, 0.056, 0.0605, 0.064, 0.0675, 0.072, 0.0758, 0.078, 0.0802, 0.0803, 0.0804, 0.0797, 0.0790, 0.078, 0.0758, 0.076, 0.0764, 0.082, + 0.0875, 0.098, 0.1072, 0.113, 0.1189, 0.1187, 0.1185, 0.116, 0.1141, 0.111, 0.1078, 0.104, 0.1012, 0.099, 0.0977, 0.098, 0.0971, 0.101, 0.1049, 0.115, 0.1245, 0.133, + 0.1417, 0.147, 0.1513, 0.153, 0.1554, 0.1564, 0.1575, 0.158, 0.1590, 0.1598, 0.1606, 0.1608, 0.1611, 0.1611, 0.1611, 0.1609, 0.1608, 0.1604, 0.1601, 0.160, 0.1598, 0.1599, 0.1600, 0.1609, 0.1619, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 33 6 15 const double ColorTemp::ColabSkin33_6_15_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0143,0.015, 0.0162,0.0175, 0.0189,0.023, 0.0286,0.031, 0.0342,0.036, 0.0376,0.039, 0.0415,0.0425, 0.0434,0.0432, 0.0431,0.0425, 0.0418,0.041, 0.0396,0.04, - 0.0404,0.0444, 0.0488,0.056, 0.0638,0.0689, 0.0735,0.074, 0.0752,0.0745, 0.0741,0.073, 0.0717,0.070, 0.0688,0.0681, 0.0673,0.0673, 0.0674,0.0710, 0.0737,0.0810, - 0.0889,0.0960, 0.1023,0.1065, 0.1098,0.1120, 0.1129,0.1135, 0.1145,0.1150, 0.1155,0.1160, 0.1164,0.1165, 0.1167,0.1167, 0.1168,0.1167, 0.1166,0.1165, 0.1164,0.1164, 0.1163,0.1163, 0.1164,0.1170, 0.1174, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0143, 0.015, 0.0162, 0.0175, 0.0189, 0.023, 0.0286, 0.031, 0.0342, 0.036, 0.0376, 0.039, 0.0415, 0.0425, 0.0434, 0.0432, 0.0431, 0.0425, 0.0418, 0.041, 0.0396, 0.04, + 0.0404, 0.0444, 0.0488, 0.056, 0.0638, 0.0689, 0.0735, 0.074, 0.0752, 0.0745, 0.0741, 0.073, 0.0717, 0.070, 0.0688, 0.0681, 0.0673, 0.0673, 0.0674, 0.0710, 0.0737, 0.0810, + 0.0889, 0.0960, 0.1023, 0.1065, 0.1098, 0.1120, 0.1129, 0.1135, 0.1145, 0.1150, 0.1155, 0.1160, 0.1164, 0.1165, 0.1167, 0.1167, 0.1168, 0.1167, 0.1166, 0.1165, 0.1164, 0.1164, 0.1163, 0.1163, 0.1164, 0.1170, 0.1174, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 33 15 5 const double ColorTemp::ColabSkin33_15_5_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0212,0.023, 0.0243,0.0265, 0.0289,0.037, 0.0451,0.051, 0.0549,0.058, 0.0605,0.063, 0.0666,0.0675, 0.0686,0.0672, 0.0664,0.065, 0.0627,0.0061, 0.0580,0.0565, 0.0557, - 0.057, 0.0590,0.063, 0.0666,0.069, 0.0703,0.0694, 0.0684,0.0666, 0.0651,0.063, 0.0607,0.0585, 0.0559,0.0545, 0.0535,0.0540, 0.0542,0.0610, 0.0672,0.0832, - 0.0992,0.1132, 0.1272,0.1345, 0.1425,0.1455, 0.1489,0.1505, 0.1518,0.1527, 0.1536,0.1545, 0.1552,0.1555, 0.1557,0.1558, 0.1559,0.1558, 0.1557,0.1155, 0.1552,0.1551, 0.1550,0.1551, 0.1552,0.1560, 0.1569, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0212, 0.023, 0.0243, 0.0265, 0.0289, 0.037, 0.0451, 0.051, 0.0549, 0.058, 0.0605, 0.063, 0.0666, 0.0675, 0.0686, 0.0672, 0.0664, 0.065, 0.0627, 0.0061, 0.0580, 0.0565, 0.0557, + 0.057, 0.0590, 0.063, 0.0666, 0.069, 0.0703, 0.0694, 0.0684, 0.0666, 0.0651, 0.063, 0.0607, 0.0585, 0.0559, 0.0545, 0.0535, 0.0540, 0.0542, 0.0610, 0.0672, 0.0832, + 0.0992, 0.1132, 0.1272, 0.1345, 0.1425, 0.1455, 0.1489, 0.1505, 0.1518, 0.1527, 0.1536, 0.1545, 0.1552, 0.1555, 0.1557, 0.1558, 0.1559, 0.1558, 0.1557, 0.1155, 0.1552, 0.1551, 0.1550, 0.1551, 0.1552, 0.1560, 0.1569, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 33 10 15 const double ColorTemp::ColabSkin33_10_15_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0166,0.0175, 0.0183,0.0194, 0.0207,0.0260, 0.0306,0.033, 0.0364,0.0380, 0.0396,0.0415, 0.0431,0.0437, 0.0443,0.0438, 0.0432,0.0420, 0.0409,0.0395, 0.0380,0.0380, - 0.0381,0.0415, 0.0456,0.0525, 0.0595,0.0645, 0.0686,0.0695, 0.0705,0.0702, 0.0700,0.0690, 0.0681,0.0667, 0.0655,0.065, 0.0644,0.0648, 0.0650,0.0695, 0.0739,0.0852, - 0.0955,0.1040, 0.1145,0.1196, 0.1249,0.1271, 0.1293,0.1305, 0.1314,0.1322, 0.1327,0.1332, 0.1337,0.1338, 0.1340,0.1340, 0.1341,0.1340, 0.1340,0.1339, 0.1338,0.1338, 0.1338,0.1338, 0.1338,0.1345, 0.1349, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0166, 0.0175, 0.0183, 0.0194, 0.0207, 0.0260, 0.0306, 0.033, 0.0364, 0.0380, 0.0396, 0.0415, 0.0431, 0.0437, 0.0443, 0.0438, 0.0432, 0.0420, 0.0409, 0.0395, 0.0380, 0.0380, + 0.0381, 0.0415, 0.0456, 0.0525, 0.0595, 0.0645, 0.0686, 0.0695, 0.0705, 0.0702, 0.0700, 0.0690, 0.0681, 0.0667, 0.0655, 0.065, 0.0644, 0.0648, 0.0650, 0.0695, 0.0739, 0.0852, + 0.0955, 0.1040, 0.1145, 0.1196, 0.1249, 0.1271, 0.1293, 0.1305, 0.1314, 0.1322, 0.1327, 0.1332, 0.1337, 0.1338, 0.1340, 0.1340, 0.1341, 0.1340, 0.1340, 0.1339, 0.1338, 0.1338, 0.1338, 0.1338, 0.1338, 0.1345, 0.1349, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 24 5 6 const double ColorTemp::ColabSkin24_5_6_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0086,0.0095, 0.0102,0.0112, 0.0127,0.0167, 0.0203,0.0225, 0.0248,0.0265, 0.0277,0.0295, 0.0309,0.0315, 0.0325,0.0324, 0.0323,0.0319, 0.0315,0.0307, 0.0299,0.0298, - 0.0297,0.0315, 0.0330,0.0365, 0.0392,0.0412, 0.0427,0.0424, 0.0421,0.0410, 0.0402,0.0390, 0.0377,0.0365, 0.0351,0.0345, 0.0337,0.0337, 0.0336,0.0356, 0.0374,0.0415, - 0.0470,0.0512, 0.0554,0.0575, 0.0601,0.0610, 0.0620,0.0625, 0.0630,0.0634, 0.0637,0.0640, 0.0643,0.0645, 0.0646,0.0646, 0.0646,0.0645, 0.0644,0.0643, 0.0642,0.0642, 0.0641,0.0641, 0.0641,0.0645, 0.0649, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0086, 0.0095, 0.0102, 0.0112, 0.0127, 0.0167, 0.0203, 0.0225, 0.0248, 0.0265, 0.0277, 0.0295, 0.0309, 0.0315, 0.0325, 0.0324, 0.0323, 0.0319, 0.0315, 0.0307, 0.0299, 0.0298, + 0.0297, 0.0315, 0.0330, 0.0365, 0.0392, 0.0412, 0.0427, 0.0424, 0.0421, 0.0410, 0.0402, 0.0390, 0.0377, 0.0365, 0.0351, 0.0345, 0.0337, 0.0337, 0.0336, 0.0356, 0.0374, 0.0415, + 0.0470, 0.0512, 0.0554, 0.0575, 0.0601, 0.0610, 0.0620, 0.0625, 0.0630, 0.0634, 0.0637, 0.0640, 0.0643, 0.0645, 0.0646, 0.0646, 0.0646, 0.0645, 0.0644, 0.0643, 0.0642, 0.0642, 0.0641, 0.0641, 0.0641, 0.0645, 0.0649, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 26 18 18 const double ColorTemp::ColabSkin26_18_18_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0135,0.0137, 0.0138,0.0139, 0.0140,0.0163, 0.0187,0.0202, 0.0215,0.0220, 0.0224,0.0228, 0.0231,0.0227, 0.0222,0.0212, 0.0202,0.0189, 0.0174,0.0161, 0.0146,0.0143, - 0.0140,0.0163, 0.0184,0.0224, 0.0268,0.0291, 0.0331,0.0348, 0.0358,0.0366, 0.0374,0.0378, 0.0380,0.0380, 0.0379,0.0380, 0.0381,0.0388, 0.0394,0.0440, 0.0490, - 0.0605, 0.0720,0.0821, 0.0921,0.0976, 0.1030,0.1056, 0.1076,0.1087, 0.1097,0.1103, 0.1108,0.1111, 0.1115,0.1115, 0.1116,0.1117, 0.1118,0.1118, 0.1119,0.1119, 0.1120,0.1120, 0.1121,0.1121, 0.1120,0.1123, 0.1126, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0135, 0.0137, 0.0138, 0.0139, 0.0140, 0.0163, 0.0187, 0.0202, 0.0215, 0.0220, 0.0224, 0.0228, 0.0231, 0.0227, 0.0222, 0.0212, 0.0202, 0.0189, 0.0174, 0.0161, 0.0146, 0.0143, + 0.0140, 0.0163, 0.0184, 0.0224, 0.0268, 0.0291, 0.0331, 0.0348, 0.0358, 0.0366, 0.0374, 0.0378, 0.0380, 0.0380, 0.0379, 0.0380, 0.0381, 0.0388, 0.0394, 0.0440, 0.0490, + 0.0605, 0.0720, 0.0821, 0.0921, 0.0976, 0.1030, 0.1056, 0.1076, 0.1087, 0.1097, 0.1103, 0.1108, 0.1111, 0.1115, 0.1115, 0.1116, 0.1117, 0.1118, 0.1118, 0.1119, 0.1119, 0.1120, 0.1120, 0.1121, 0.1121, 0.1120, 0.1123, 0.1126, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 24 7 5 const double ColorTemp::ColabSkin24_7_5_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0093,0.0105, 0.0111,0.0125, 0.0137,0.0180, 0.0221,0.0245, 0.0270,0.0285, 0.0301,0.0316, 0.0336,0.0345, 0.0353,0.0350, 0.0349,0.0343, 0.0338,0.0329, 0.0320,0.0317, 0.0315, - 0.0328, 0.0342,0.0368, 0.0397,0.0412, 0.0424,0.0420, 0.0415,0.0404, 0.0393,0.0379, 0.0366,0.0352, 0.0337,0.0330, 0.0323,0.0322, 0.0322,0.0344, 0.0367,0.0422, 0.0479,0.0529, - 0.0578,0.0606, 0.0633,0.0644, 0.0656,0.0662, 0.0667,0.0670, 0.0674,0.0678, 0.0681,0.0683, 0.0684,0.0684, 0.0684,0.0683, 0.0683,0.0682, 0.0680,0.0679, 0.0678,0.0678, 0.0679,0.0683, 0.0688, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0093, 0.0105, 0.0111, 0.0125, 0.0137, 0.0180, 0.0221, 0.0245, 0.0270, 0.0285, 0.0301, 0.0316, 0.0336, 0.0345, 0.0353, 0.0350, 0.0349, 0.0343, 0.0338, 0.0329, 0.0320, 0.0317, 0.0315, + 0.0328, 0.0342, 0.0368, 0.0397, 0.0412, 0.0424, 0.0420, 0.0415, 0.0404, 0.0393, 0.0379, 0.0366, 0.0352, 0.0337, 0.0330, 0.0323, 0.0322, 0.0322, 0.0344, 0.0367, 0.0422, 0.0479, 0.0529, + 0.0578, 0.0606, 0.0633, 0.0644, 0.0656, 0.0662, 0.0667, 0.0670, 0.0674, 0.0678, 0.0681, 0.0683, 0.0684, 0.0684, 0.0684, 0.0683, 0.0683, 0.0682, 0.0680, 0.0679, 0.0678, 0.0678, 0.0679, 0.0683, 0.0688, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 24 4 2 const double ColorTemp::ColabSkin20_4_2_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0064,0.0074, 0.0080,0.00903, 0.0104,0.0139, 0.0174,0.0189, 0.0216,0.0222, 0.0243,0.0258, 0.0274,0.0282, 0.0291,0.0290, 0.0290,0.0288, 0.0284,0.0278, 0.0272,0.0270, 0.0267,0.0276, - 0.0285,0.0302, 0.0320,0.0327, 0.0335,0.0328, 0.0321,0.0311, 0.0299,0.0280, 0.0272,0.0259, 0.0246,0.0239, 0.0232,0.0230, 0.0229,0.0243, 0.0256,0.0291, 0.0324,0.0354, - 0.0385,0.0401, 0.0418,0.0425, 0.0432,0.0435, 0.0439,0.0442, 0.0444,0.0447, 0.0450,0.0451, 0.0452,0.0452, 0.0452,0.0451, 0.0450,0.0449, 0.0448,0.0447, 0.0446,0.0447, 0.0447,0.0450, 0.0454, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0064, 0.0074, 0.0080, 0.00903, 0.0104, 0.0139, 0.0174, 0.0189, 0.0216, 0.0222, 0.0243, 0.0258, 0.0274, 0.0282, 0.0291, 0.0290, 0.0290, 0.0288, 0.0284, 0.0278, 0.0272, 0.0270, 0.0267, 0.0276, + 0.0285, 0.0302, 0.0320, 0.0327, 0.0335, 0.0328, 0.0321, 0.0311, 0.0299, 0.0280, 0.0272, 0.0259, 0.0246, 0.0239, 0.0232, 0.0230, 0.0229, 0.0243, 0.0256, 0.0291, 0.0324, 0.0354, + 0.0385, 0.0401, 0.0418, 0.0425, 0.0432, 0.0435, 0.0439, 0.0442, 0.0444, 0.0447, 0.0450, 0.0451, 0.0452, 0.0452, 0.0452, 0.0451, 0.0450, 0.0449, 0.0448, 0.0447, 0.0446, 0.0447, 0.0447, 0.0450, 0.0454, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 98 -2 10 const double ColorTemp::ColabSkin98_m2_10_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1627,0.1870, 0.2115,0.2480, 0.2860,0.3870, 0.4878,0.5460, 0.6050,0.6460, 0.6874,0.7355, 0.7836,0.8130, 0.8424,0.8494, 0.8543,0.8520, 0.8508,0.8390, 0.8267,0.8274, 0.8280, - 0.8680, 0.9076,0.9600, 1.0497,1.089, 1.1190,1.10, 1.0836,1.045, 1.0140,0.975, 0.9305,0.884, 0.8486,0.826, 0.8042,0.7980, 0.7895,0.8093, 0.8292,0.884, 0.9376,0.987, - 1.0341,1.059, 1.0892,1.104, 1.1125,1.1253, 1.1255,1.131, 1.1375,1.145, 1.1520,1.155, 1.1585,1.158, 1.1574,1.1548, 1.1523,1.148, 1.1439,1.141, 1.1394,1.141, 1.1423,1.151, 1.1619, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1627, 0.1870, 0.2115, 0.2480, 0.2860, 0.3870, 0.4878, 0.5460, 0.6050, 0.6460, 0.6874, 0.7355, 0.7836, 0.8130, 0.8424, 0.8494, 0.8543, 0.8520, 0.8508, 0.8390, 0.8267, 0.8274, 0.8280, + 0.8680, 0.9076, 0.9600, 1.0497, 1.089, 1.1190, 1.10, 1.0836, 1.045, 1.0140, 0.975, 0.9305, 0.884, 0.8486, 0.826, 0.8042, 0.7980, 0.7895, 0.8093, 0.8292, 0.884, 0.9376, 0.987, + 1.0341, 1.059, 1.0892, 1.104, 1.1125, 1.1253, 1.1255, 1.131, 1.1375, 1.145, 1.1520, 1.155, 1.1585, 1.158, 1.1574, 1.1548, 1.1523, 1.148, 1.1439, 1.141, 1.1394, 1.141, 1.1423, 1.151, 1.1619, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 90 -1 20 const double ColorTemp::ColabSkin90_m1_20_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1228,0.138, 0.1532,0.175, 0.1987,0.261, 0.3279,0.365, 0.4022,0.428, 0.4537,0.4842, 0.5147,0.5337, 0.5521,0.557, 0.5611,0.5602, 0.5593,0.551, 0.5438,0.548, - 0.5527,0.593, 0.6334,0.703, 0.7732,0.8135, 0.8543,0.851, 0.8474,0.829, 0.8105,0.786, 0.7613,0.736, 0.7105,0.697, 0.6835,0.679, 0.6750,0.6895, 0.7045,0.743, - 0.7832,0.818, 0.8530,0.873, 0.8929,0.899, 0.9099,0.914, 0.9197,0.924, 0.9282,0.933, 0.9380,0.9395, 0.9419,0.9416, 0.9413,0.9398, 0.9382,0.9357, 0.9332,0.9322, 0.9306,0.9315, 0.9322,0.939, 0.9452, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1228, 0.138, 0.1532, 0.175, 0.1987, 0.261, 0.3279, 0.365, 0.4022, 0.428, 0.4537, 0.4842, 0.5147, 0.5337, 0.5521, 0.557, 0.5611, 0.5602, 0.5593, 0.551, 0.5438, 0.548, + 0.5527, 0.593, 0.6334, 0.703, 0.7732, 0.8135, 0.8543, 0.851, 0.8474, 0.829, 0.8105, 0.786, 0.7613, 0.736, 0.7105, 0.697, 0.6835, 0.679, 0.6750, 0.6895, 0.7045, 0.743, + 0.7832, 0.818, 0.8530, 0.873, 0.8929, 0.899, 0.9099, 0.914, 0.9197, 0.924, 0.9282, 0.933, 0.9380, 0.9395, 0.9419, 0.9416, 0.9413, 0.9398, 0.9382, 0.9357, 0.9332, 0.9322, 0.9306, 0.9315, 0.9322, 0.939, 0.9452, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 95 0 4 const double ColorTemp::ColabSkin95_0_4_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1614,0.1865, 0.2118,0.2495, 0.2889,0.392, 0.4969,0.557, 0.6185,0.6605, 0.7035,0.749, 0.8018,0.832, 0.8605,0.865, 0.8696,0.866, 0.8633,0.849, 0.8365,0.834, - 0.8308,0.861, 0.8911,0.946, 1.0030,1.025, 1.0490,1.025, 1.0030,0.964, 0.9278,0.884, 0.8407,0.7985, 0.7565,0.734, 0.7107,0.6985, 0.6962,0.718, 0.7416,0.803, - 0.8642,0.919, 0.9733,1.001, 1.0349,1.051, 1.0609,1.068, 1.0747,1.081, 1.0872,1.095, 1.1021,1.105, 1.1089,1.1085, 1.1079,1.1055, 1.1027,1.098, 1.0940,1.091, 1.0892,1.0905, 1.0923,1.102, 1.1123, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1614, 0.1865, 0.2118, 0.2495, 0.2889, 0.392, 0.4969, 0.557, 0.6185, 0.6605, 0.7035, 0.749, 0.8018, 0.832, 0.8605, 0.865, 0.8696, 0.866, 0.8633, 0.849, 0.8365, 0.834, + 0.8308, 0.861, 0.8911, 0.946, 1.0030, 1.025, 1.0490, 1.025, 1.0030, 0.964, 0.9278, 0.884, 0.8407, 0.7985, 0.7565, 0.734, 0.7107, 0.6985, 0.6962, 0.718, 0.7416, 0.803, + 0.8642, 0.919, 0.9733, 1.001, 1.0349, 1.051, 1.0609, 1.068, 1.0747, 1.081, 1.0872, 1.095, 1.1021, 1.105, 1.1089, 1.1085, 1.1079, 1.1055, 1.1027, 1.098, 1.0940, 1.091, 1.0892, 1.0905, 1.0923, 1.102, 1.1123, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 81 2 14 const double ColorTemp::ColabSkin81_2_14_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1029,0.116, 0.1285,0.148, 0.1672,0.222, 0.2774,0.311, 0.3412,0.362, 0.3849,0.410, 0.4359,0.451, 0.4659,0.468, 0.4706,0.4685, 0.4664,0.4685, 0.4512,0.4525, 0.4536, - 0.461, 0.5076,0.551, 0.6035,0.6295, 0.6559,0.6495, 0.6442,0.627, 0.6112,0.5905, 0.5691,0.537, 0.5266,0.515, 0.5039,0.501, 0.4975,0.5125, 0.5283,0.568, 0.6087,0.643, - 0.6799,0.700, 0.7200,0.729, 0.7370,0.7415, 0.7461,0.750, 0.7536,0.759, 0.7620,0.764, 0.7655,0.7653, 0.7651,0.764, 0.7626,0.761, 0.7583,0.7572, 0.7561,0.7567, 0.7575,0.758, 0.7685, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1029, 0.116, 0.1285, 0.148, 0.1672, 0.222, 0.2774, 0.311, 0.3412, 0.362, 0.3849, 0.410, 0.4359, 0.451, 0.4659, 0.468, 0.4706, 0.4685, 0.4664, 0.4685, 0.4512, 0.4525, 0.4536, + 0.461, 0.5076, 0.551, 0.6035, 0.6295, 0.6559, 0.6495, 0.6442, 0.627, 0.6112, 0.5905, 0.5691, 0.537, 0.5266, 0.515, 0.5039, 0.501, 0.4975, 0.5125, 0.5283, 0.568, 0.6087, 0.643, + 0.6799, 0.700, 0.7200, 0.729, 0.7370, 0.7415, 0.7461, 0.750, 0.7536, 0.759, 0.7620, 0.764, 0.7655, 0.7653, 0.7651, 0.764, 0.7626, 0.761, 0.7583, 0.7572, 0.7561, 0.7567, 0.7575, 0.758, 0.7685, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 87 3 10 const double ColorTemp::ColabSkin87_3_10_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1295,0.146, 0.1639,0.190, 0.2160,0.291, 0.3626,0.405, 0.4480,0.476, 0.5066,0.541, 0.5743,0.593, 0.6136,0.616, 0.6186,0.614, 0.6119,0.601, 0.5911,0.5905, - 0.5897,0.623, 0.6460,0.697, 0.7483,0.773, 0.7992,0.788, 0.7759,0.752, 0.7287,0.699, 0.6712,0.642, 0.6141,0.598, 0.5835,0.579, 0.5750,0.596, 0.6162,0.669, - 0.7239,0.772, 0.8193,0.845, 0.8728,0.888, 0.8954,0.901, 0.9073,0.912, 0.9171,0.922, 0.9281,0.931, 0.9328,0.9325, 0.9323,0.931, 0.9289,0.926, 0.9232,0.9215, 0.9201,0.921, 0.9220,0.929, 0.9364, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1295, 0.146, 0.1639, 0.190, 0.2160, 0.291, 0.3626, 0.405, 0.4480, 0.476, 0.5066, 0.541, 0.5743, 0.593, 0.6136, 0.616, 0.6186, 0.614, 0.6119, 0.601, 0.5911, 0.5905, + 0.5897, 0.623, 0.6460, 0.697, 0.7483, 0.773, 0.7992, 0.788, 0.7759, 0.752, 0.7287, 0.699, 0.6712, 0.642, 0.6141, 0.598, 0.5835, 0.579, 0.5750, 0.596, 0.6162, 0.669, + 0.7239, 0.772, 0.8193, 0.845, 0.8728, 0.888, 0.8954, 0.901, 0.9073, 0.912, 0.9171, 0.922, 0.9281, 0.931, 0.9328, 0.9325, 0.9323, 0.931, 0.9289, 0.926, 0.9232, 0.9215, 0.9201, 0.921, 0.9220, 0.929, 0.9364, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 77 12 21 const double ColorTemp::ColabSkin77_12_21_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.1039,0.111, 0.1205,0.132, 0.1448,0.185, 0.2261,0.249, 0.2734,0.287, 0.3028,0.318, 0.3364,0.345, 0.3525,0.351, 0.3499,0.345, 0.3397,0.3295, 0.3224,0.329, 0.3234, - 0.349, 0.3729,0.418, 0.4625,0.490, 0.5173,0.5185, 0.5196,0.511, 0.5045,0.492, 0.4807,0.467, 0.4543,0.447, 0.4410,0.4409, 0.4407,0.464, 0.4872,0.544, 0.6020,0.6522, - 0.7029,0.731, 0.7588,0.771, 0.7823,0.787, 0.7939,0.798, 0.8017,0.805, 0.8090,0.8103, 0.8115,0.8117, 0.8118,0.8111, 0.8104,0.8193, 0.8081,0.8076, 0.8070,0.8073, 0.8077,0.812, 0.8162, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.1039, 0.111, 0.1205, 0.132, 0.1448, 0.185, 0.2261, 0.249, 0.2734, 0.287, 0.3028, 0.318, 0.3364, 0.345, 0.3525, 0.351, 0.3499, 0.345, 0.3397, 0.3295, 0.3224, 0.329, 0.3234, + 0.349, 0.3729, 0.418, 0.4625, 0.490, 0.5173, 0.5185, 0.5196, 0.511, 0.5045, 0.492, 0.4807, 0.467, 0.4543, 0.447, 0.4410, 0.4409, 0.4407, 0.464, 0.4872, 0.544, 0.6020, 0.6522, + 0.7029, 0.731, 0.7588, 0.771, 0.7823, 0.787, 0.7939, 0.798, 0.8017, 0.805, 0.8090, 0.8103, 0.8115, 0.8117, 0.8118, 0.8111, 0.8104, 0.8193, 0.8081, 0.8076, 0.8070, 0.8073, 0.8077, 0.812, 0.8162, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Skin 70 7 32 const double ColorTemp::ColabSkin70_7_32_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0695,0.074, 0.0777,0.084, 0.0890,0.104, 0.1321,0.144, 0.1565,0.164, 0.1713,0.1795, 0.1889,0.194, 0.1978,0.198, 0.1983,0.196, 0.1939,0.189, 0.1853,0.189, - 0.1933,0.219, 0.2458,0.291, 0.3362,0.367, 0.3974,0.405, 0.4120,0.411, 0.4101,0.406, 0.4007,0.394, 0.3877,0.385, 0.3816,0.3817, 0.3819,0.395, 0.4081,0.440, - 0.4721,0.498, 0.5284,0.544, 0.5598,0.566, 0.5730,0.577, 0.5801,0.5825, 0.5848,0.587, 0.5890,0.5895, 0.5901,0.5903, 0.5903,0.59, 0.5897,0.5892, 0.5887,0.5885, 0.5884,0.5885, 0.5886,0.5896, 0.5934, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0695, 0.074, 0.0777, 0.084, 0.0890, 0.104, 0.1321, 0.144, 0.1565, 0.164, 0.1713, 0.1795, 0.1889, 0.194, 0.1978, 0.198, 0.1983, 0.196, 0.1939, 0.189, 0.1853, 0.189, + 0.1933, 0.219, 0.2458, 0.291, 0.3362, 0.367, 0.3974, 0.405, 0.4120, 0.411, 0.4101, 0.406, 0.4007, 0.394, 0.3877, 0.385, 0.3816, 0.3817, 0.3819, 0.395, 0.4081, 0.440, + 0.4721, 0.498, 0.5284, 0.544, 0.5598, 0.566, 0.5730, 0.577, 0.5801, 0.5825, 0.5848, 0.587, 0.5890, 0.5895, 0.5901, 0.5903, 0.5903, 0.59, 0.5897, 0.5892, 0.5887, 0.5885, 0.5884, 0.5885, 0.5886, 0.5896, 0.5934, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Sky 60 0 -31 const double ColorTemp::ColabSky60_0_m31_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0752,0.094, 0.1121,0.141, 0.1699,0.243, 0.3150,0.357, 0.4015,0.432, 0.4631,0.497, 0.5325,0.553, 0.5730,0.574, 0.5758,0.572, 0.5695,0.559, 0.5503,0.539, - 0.5284,0.5175, 0.5066,0.493, 0.4800,0.459, 0.4336,0.401, 0.3684,0.333, 0.3003,0.265, 0.2313,0.199, 0.1695,0.167, 0.1349,0.129, 0.1234,0.136, 0.1489,0.184, - 0.2212,0.253, 0.2858,0.303, 0.3218,0.329, 0.3370,0.341, 0.3440,0.348, 0.3512,0.355, 0.3606,0.363, 0.3658,0.3653, 0.3649,0.3625, 0.3611,0.358, 0.3544,0.352, 0.3502,0.3512, 0.3529,0.359, 0.3660, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0752, 0.094, 0.1121, 0.141, 0.1699, 0.243, 0.3150, 0.357, 0.4015, 0.432, 0.4631, 0.497, 0.5325, 0.553, 0.5730, 0.574, 0.5758, 0.572, 0.5695, 0.559, 0.5503, 0.539, + 0.5284, 0.5175, 0.5066, 0.493, 0.4800, 0.459, 0.4336, 0.401, 0.3684, 0.333, 0.3003, 0.265, 0.2313, 0.199, 0.1695, 0.167, 0.1349, 0.129, 0.1234, 0.136, 0.1489, 0.184, + 0.2212, 0.253, 0.2858, 0.303, 0.3218, 0.329, 0.3370, 0.341, 0.3440, 0.348, 0.3512, 0.355, 0.3606, 0.363, 0.3658, 0.3653, 0.3649, 0.3625, 0.3611, 0.358, 0.3544, 0.352, 0.3502, 0.3512, 0.3529, 0.359, 0.3660, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; //spectral data ColorLab : Sky 42 0 -24 const double ColorTemp::ColabSky42_0_m24_spect[97] = { - 0.0,0.0,0.0,0.0,0.0,0.0, - 0.0336,0.041, 0.0501,0.063, 0.0761,0.103, 0.1412,0.151, 0.1799,0.193, 0.2076,0.223, 0.2387,0.248, 0.2569,0.2575, 0.2581,0.256, 0.2553,0.250, 0.2466,0.2411, - 0.2368,0.2318, 0.2268,0.2205, 0.2145,0.204, 0.1935,0.179, 0.1641,0.149, 0.1335,0.118, 0.1025,0.087, 0.0748,0.067, 0.0593,0.056, 0.0541,0.059, 0.0655,0.081, - 0.0979,0.112, 0.1269,0.134, 0.1430,0.147, 0.1497,0.151, 0.1529,0.1545, 0.1561,0.158, 0.1603,0.1616, 0.1627,0.1625, 0.1623,0.1614, 0.1605,0.159, 0.1575,0.1567, 0.1557,0.1563, 0.1569,0.159, 0.1627, - 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0336, 0.041, 0.0501, 0.063, 0.0761, 0.103, 0.1412, 0.151, 0.1799, 0.193, 0.2076, 0.223, 0.2387, 0.248, 0.2569, 0.2575, 0.2581, 0.256, 0.2553, 0.250, 0.2466, 0.2411, + 0.2368, 0.2318, 0.2268, 0.2205, 0.2145, 0.204, 0.1935, 0.179, 0.1641, 0.149, 0.1335, 0.118, 0.1025, 0.087, 0.0748, 0.067, 0.0593, 0.056, 0.0541, 0.059, 0.0655, 0.081, + 0.0979, 0.112, 0.1269, 0.134, 0.1430, 0.147, 0.1497, 0.151, 0.1529, 0.1545, 0.1561, 0.158, 0.1603, 0.1616, 0.1627, 0.1625, 0.1623, 0.1614, 0.1605, 0.159, 0.1575, 0.1567, 0.1557, 0.1563, 0.1569, 0.159, 0.1627, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; /* @@ -844,8 +859,8 @@ int ColorTemp::XYZtoCorColorTemp(double x0, double y0, double z0, double &temp) } UVT; double rt[31] = { /* reciprocal temperature (K) */ - DBL_MIN, 10.0e-6, 20.0e-6, 30.0e-6, 40.0e-6, 50.0e-6, - 60.0e-6, 70.0e-6, 80.0e-6, 90.0e-6, 100.0e-6, 125.0e-6, + DBL_MIN, 10.0e-6, 20.0e-6, 30.0e-6, 40.0e-6, 50.0e-6, + 60.0e-6, 70.0e-6, 80.0e-6, 90.0e-6, 100.0e-6, 125.0e-6, 150.0e-6, 175.0e-6, 200.0e-6, 225.0e-6, 250.0e-6, 275.0e-6, 300.0e-6, 325.0e-6, 350.0e-6, 375.0e-6, 400.0e-6, 425.0e-6, 450.0e-6, 475.0e-6, 500.0e-6, 525.0e-6, 550.0e-6, 575.0e-6, @@ -888,19 +903,29 @@ int ColorTemp::XYZtoCorColorTemp(double x0, double y0, double z0, double &temp) double us, vs, p, di, dm; int i; - if ((x0 < 1.0e-20) && (y0 < 1.0e-20) && (z0 < 1.0e-20)) - return -1; /* protect against possible divide-by-zero failure */ + + if ((x0 < 1.0e-20) && (y0 < 1.0e-20) && (z0 < 1.0e-20)) { + return -1; /* protect against possible divide-by-zero failure */ + } + us = (4.0 * x0) / (x0 + 15.0 * y0 + 3.0 * z0); vs = (6.0 * y0) / (x0 + 15.0 * y0 + 3.0 * z0); dm = 0.0; + for (i = 0; i < 31; i++) { di = (vs - uvt[i].v) - uvt[i].t * (us - uvt[i].u); - if ((i > 0) && (((di < 0.0) && (dm >= 0.0)) || ((di >= 0.0) && (dm < 0.0)))) - break; /* found lines bounding (us, vs) : i-1 and i */ + + if ((i > 0) && (((di < 0.0) && (dm >= 0.0)) || ((di >= 0.0) && (dm < 0.0)))) { + break; /* found lines bounding (us, vs) : i-1 and i */ + } + dm = di; } - if (i == 31) - return(-1); /* bad XYZ input, color temp would be less than minimum of 1666.7 degrees, or too far towards blue */ + + if (i == 31) { + return(-1); /* bad XYZ input, color temp would be less than minimum of 1666.7 degrees, or too far towards blue */ + } + di = di / sqrt(1.0 + uvt[i ].t * uvt[i ].t); dm = dm / sqrt(1.0 + uvt[i - 1].t * uvt[i - 1].t); p = dm / (dm - di); /* p = interpolation parameter, 0.0 : i-1, 1.0 : i */ @@ -909,261 +934,374 @@ int ColorTemp::XYZtoCorColorTemp(double x0, double y0, double z0, double &temp) return 0; /* success */ } -void ColorTemp::cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00,double &CAM02BB01,double &CAM02BB02,double &CAM02BB10,double &CAM02BB11,double &CAM02BB12,double &CAM02BB20,double &CAM02BB21,double &CAM02BB22, double adap ) { +void ColorTemp::cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00, double &CAM02BB01, double &CAM02BB02, double &CAM02BB10, double &CAM02BB11, double &CAM02BB12, double &CAM02BB20, double &CAM02BB21, double &CAM02BB22, double adap ) +{ // CIECAT02 - J.Desmis January 2012 review September 2012 - const double whiteD50p[3]={0.9646019585,1.0,0.8244507152};//calculate with these tools + const double whiteD50p[3] = {0.9646019585, 1.0, 0.8244507152}; //calculate with these tools - double cam_dest[3]={0.,0.,0.}; - double cam_orig[3]={0.,0.,0.}; - const double CAT02[3][3] = {{0.7328, 0.4296, -0.1624},//CAT02 2002 - {-0.7036, 1.6975, 0.0061}, - {0.0030, 0.0136, 0.9834}}; - const double INVCAT02[3][3] = {{1.09612382083551, -0.278869000218287, 0.182745179382773}, //Inverse CAT02 - {0.454369041975359, 0.4735331543070412, 0.0720978037172291}, - {-0.009627608738442936, -0.00569803121611342, 1.01532563995454}}; + double cam_dest[3] = {0., 0., 0.}; + double cam_orig[3] = {0., 0., 0.}; + const double CAT02[3][3] = {{0.7328, 0.4296, -0.1624},//CAT02 2002 + { -0.7036, 1.6975, 0.0061}, + {0.0030, 0.0136, 0.9834} + }; + const double INVCAT02[3][3] = {{1.09612382083551, -0.278869000218287, 0.182745179382773}, //Inverse CAT02 + {0.454369041975359, 0.4735331543070412, 0.0720978037172291}, + { -0.009627608738442936, -0.00569803121611342, 1.01532563995454} + }; - double inv_white_orig[3][3]={{0., 0., 0.}, - {0., 0., 0.}, - {0., 0., 0.}}; - double intermed[3][3]={{0., 0., 0.}, - {0., 0., 0.}, - {0., 0., 0.}}; + double inv_white_orig[3][3] = {{0., 0., 0.}, + {0., 0., 0.}, + {0., 0., 0.} + }; + double intermed[3][3] = {{0., 0., 0.}, + {0., 0., 0.}, + {0., 0., 0.} + }; - double intermed_2[3][3]={{0., 0., 0.}, - {0., 0., 0.}, - {0., 0., 0.}}; - double CAM02[3][3]= {{0., 0., 0.}, - {0., 0., 0.}, - {0., 0., 0.}}; - double D=adap; + double intermed_2[3][3] = {{0., 0., 0.}, + {0., 0., 0.}, + {0., 0., 0.} + }; + double CAM02[3][3] = {{0., 0., 0.}, + {0., 0., 0.}, + {0., 0., 0.} + }; + double D = adap; - //white destination Wd : RT use always D50 - cam_dest[0]=CAT02[0][0]*whiteD50p[0]+CAT02[0][1]*whiteD50p[1]+CAT02[0][2]*whiteD50p[2];//Cone reponse RoD - cam_dest[1]=CAT02[1][0]*whiteD50p[0]+CAT02[1][1]*whiteD50p[1]+CAT02[1][2]*whiteD50p[2];//GaD - cam_dest[2]=CAT02[2][0]*whiteD50p[0]+CAT02[2][1]*whiteD50p[1]+CAT02[2][2]*whiteD50p[2];//BeD + //white destination Wd : RT use always D50 + cam_dest[0] = CAT02[0][0] * whiteD50p[0] + CAT02[0][1] * whiteD50p[1] + CAT02[0][2] * whiteD50p[2]; //Cone reponse RoD + cam_dest[1] = CAT02[1][0] * whiteD50p[0] + CAT02[1][1] * whiteD50p[1] + CAT02[1][2] * whiteD50p[2]; //GaD + cam_dest[2] = CAT02[2][0] * whiteD50p[0] + CAT02[2][1] * whiteD50p[1] + CAT02[2][2] * whiteD50p[2]; //BeD - //origin white Ws : A, D65, custom, etc. - cam_orig[0]=CAT02[0][0]*Xw+CAT02[0][1]*Yw+CAT02[0][2]*Zw;//Cone reponse RoS - cam_orig[1]=CAT02[1][0]*Xw+CAT02[1][1]*Yw+CAT02[1][2]*Zw; - cam_orig[2]=CAT02[2][0]*Xw+CAT02[2][1]*Yw+CAT02[2][2]*Zw; + //origin white Ws : A, D65, custom, etc. + cam_orig[0] = CAT02[0][0] * Xw + CAT02[0][1] * Yw + CAT02[0][2] * Zw; //Cone reponse RoS + cam_orig[1] = CAT02[1][0] * Xw + CAT02[1][1] * Yw + CAT02[1][2] * Zw; + cam_orig[2] = CAT02[2][0] * Xw + CAT02[2][1] * Yw + CAT02[2][2] * Zw; - //inverse white - inv_white_orig[0][0]=1./cam_orig[0];// 1/RoS - inv_white_orig[1][1]=1./cam_orig[1];// 1/GaS - inv_white_orig[2][2]=1./cam_orig[2];// 1/BeS + //inverse white + inv_white_orig[0][0] = 1. / cam_orig[0]; // 1/RoS + inv_white_orig[1][1] = 1. / cam_orig[1]; // 1/GaS + inv_white_orig[2][2] = 1. / cam_orig[2]; // 1/BeS - //intermediates computation - for(int i=0; i< 3;i++) - for(int j=0; j<3 ; j++) - intermed[i][j]=inv_white_orig[i][i]*CAT02[i][j]; + //intermediates computation + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3 ; j++) { + intermed[i][j] = inv_white_orig[i][i] * CAT02[i][j]; + } - for(int i=0; i< 3;i++) - for(int j=0; j<3 ; j++) - intermed_2[i][j]=cam_dest[i]*intermed[i][j]; - //and CAM02 - for(int i=0; i<3; i++) - for(int j=0; j<3; j++) - for(int k=0; k<3; k++) - CAM02[i][j]+=INVCAT02[i][k]*intermed_2[k][j]; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3 ; j++) { + intermed_2[i][j] = cam_dest[i] * intermed[i][j]; + } - //adaptation jdc : slightly different from CIECAM02 : Rc=(Yw(D/Rw)+(1-D))*R , but it's work ! true at 0 and 1 - CAM02[1][1]=(CAM02[1][1]-1.0)*D + 1.0; - CAM02[0][0]=(CAM02[0][0]-1.0)*D + 1.0; - CAM02[2][2]=(CAM02[2][2]-1.0)*D + 1.0; - CAM02[0][1]*=D; - CAM02[0][2]*=D; - CAM02[1][0]*=D; - CAM02[1][2]*=D; - CAM02[2][0]*=D; - CAM02[2][1]*=D; - //CAT02 matrix with D adaptation - CAM02BB00=CAM02[0][0];CAM02BB01=CAM02[0][1];CAM02BB02=CAM02[0][2]; - CAM02BB10=CAM02[1][0];CAM02BB11=CAM02[1][1];CAM02BB12=CAM02[1][2]; - CAM02BB20=CAM02[2][0];CAM02BB21=CAM02[2][1];CAM02BB22=CAM02[2][2]; + //and CAM02 + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + for(int k = 0; k < 3; k++) { + CAM02[i][j] += INVCAT02[i][k] * intermed_2[k][j]; + } + + //adaptation jdc : slightly different from CIECAM02 : Rc=(Yw(D/Rw)+(1-D))*R , but it's work ! true at 0 and 1 + CAM02[1][1] = (CAM02[1][1] - 1.0) * D + 1.0; + CAM02[0][0] = (CAM02[0][0] - 1.0) * D + 1.0; + CAM02[2][2] = (CAM02[2][2] - 1.0) * D + 1.0; + CAM02[0][1] *= D; + CAM02[0][2] *= D; + CAM02[1][0] *= D; + CAM02[1][2] *= D; + CAM02[2][0] *= D; + CAM02[2][1] *= D; + //CAT02 matrix with D adaptation + CAM02BB00 = CAM02[0][0]; + CAM02BB01 = CAM02[0][1]; + CAM02BB02 = CAM02[0][2]; + CAM02BB10 = CAM02[1][0]; + CAM02BB11 = CAM02[1][1]; + CAM02BB12 = CAM02[1][2]; + CAM02BB20 = CAM02[2][0]; + CAM02BB21 = CAM02[2][1]; + CAM02BB22 = CAM02[2][2]; } -void ColorTemp::temp2mulxyz (double tem, double gree, std::string method ,double &Xxyz, double &Zxyz) { +void ColorTemp::temp2mulxyz (double tem, double gree, std::string method , double &Xxyz, double &Zxyz) +{ double xD, yD, x_D, y_D, interm; double x, y, z; - if (method == "Daylight" ) spectrum_to_xyz_preset(Daylight5300_spect, x, y, z); - else if(method == "Cloudy" ) spectrum_to_xyz_preset(Cloudy6200_spect, x, y, z); - else if(method == "Shade" ) spectrum_to_xyz_preset(Shade7600_spect, x, y, z); - else if(method == "Tungsten" ) spectrum_to_xyz_preset(A2856_spect, x, y, z); - else if(method == "Fluo F1" ) spectrum_to_xyz_preset(FluoF1_spect, x, y, z); - else if(method == "Fluo F2" ) spectrum_to_xyz_preset(FluoF2_spect, x, y, z); - else if(method == "Fluo F3" ) spectrum_to_xyz_preset(FluoF3_spect, x, y, z); - else if(method == "Fluo F4" ) spectrum_to_xyz_preset(FluoF4_spect, x, y, z); - else if(method == "Fluo F5" ) spectrum_to_xyz_preset(FluoF5_spect, x, y, z); - else if(method == "Fluo F6" ) spectrum_to_xyz_preset(FluoF6_spect, x, y, z); - else if(method == "Fluo F7" ) spectrum_to_xyz_preset(FluoF7_spect, x, y, z); - else if(method == "Fluo F8" ) spectrum_to_xyz_preset(FluoF8_spect, x, y, z); - else if(method == "Fluo F9" ) spectrum_to_xyz_preset(FluoF9_spect, x, y, z); - else if(method == "Fluo F10" ) spectrum_to_xyz_preset(FluoF10_spect, x, y, z); - else if(method == "Fluo F11" ) spectrum_to_xyz_preset(FluoF11_spect, x, y, z); - else if(method == "Fluo F12" ) spectrum_to_xyz_preset(FluoF12_spect, x, y, z); - else if(method == "HMI Lamp" ) spectrum_to_xyz_preset(HMI_spect, x, y, z); - else if(method == "GTI Lamp" ) spectrum_to_xyz_preset(GTI_spect, x, y, z); - else if(method == "JudgeIII Lamp" ) spectrum_to_xyz_preset(JudgeIII_spect, x, y, z); - else if(method == "Solux Lamp 3500K" ) spectrum_to_xyz_preset(Solux3500_spect, x, y, z); - else if(method == "Solux Lamp 4100K" ) spectrum_to_xyz_preset(Solux4100_spect, x, y, z); - else if(method == "Solux Lamp 4700K" ) spectrum_to_xyz_preset(Solux4700_spect, x, y, z); - else if(method == "NG Solux Lamp 4700K" ) spectrum_to_xyz_preset(NG_Solux4700_spect, x, y, z); - else if(method == "LED LSI Lumelex 2040") spectrum_to_xyz_preset(NG_LEDLSI2040_spect, x, y, z); - else if(method == "LED CRS SP12 WWMR16" ) spectrum_to_xyz_preset(NG_CRSSP12WWMR16_spect, x, y, z); - else if(method == "Flash 5500K" ) spectrum_to_xyz_preset(Flash5500_spect, x, y, z); - else if(method == "Flash 6000K" ) spectrum_to_xyz_preset(Flash6000_spect, x, y, z); - else if(method == "Flash 6500K" ) spectrum_to_xyz_preset(Flash6500_spect, x, y, z); - else { + if (method == "Daylight" ) { + spectrum_to_xyz_preset(Daylight5300_spect, x, y, z); + } else if(method == "Cloudy" ) { + spectrum_to_xyz_preset(Cloudy6200_spect, x, y, z); + } else if(method == "Shade" ) { + spectrum_to_xyz_preset(Shade7600_spect, x, y, z); + } else if(method == "Tungsten" ) { + spectrum_to_xyz_preset(A2856_spect, x, y, z); + } else if(method == "Fluo F1" ) { + spectrum_to_xyz_preset(FluoF1_spect, x, y, z); + } else if(method == "Fluo F2" ) { + spectrum_to_xyz_preset(FluoF2_spect, x, y, z); + } else if(method == "Fluo F3" ) { + spectrum_to_xyz_preset(FluoF3_spect, x, y, z); + } else if(method == "Fluo F4" ) { + spectrum_to_xyz_preset(FluoF4_spect, x, y, z); + } else if(method == "Fluo F5" ) { + spectrum_to_xyz_preset(FluoF5_spect, x, y, z); + } else if(method == "Fluo F6" ) { + spectrum_to_xyz_preset(FluoF6_spect, x, y, z); + } else if(method == "Fluo F7" ) { + spectrum_to_xyz_preset(FluoF7_spect, x, y, z); + } else if(method == "Fluo F8" ) { + spectrum_to_xyz_preset(FluoF8_spect, x, y, z); + } else if(method == "Fluo F9" ) { + spectrum_to_xyz_preset(FluoF9_spect, x, y, z); + } else if(method == "Fluo F10" ) { + spectrum_to_xyz_preset(FluoF10_spect, x, y, z); + } else if(method == "Fluo F11" ) { + spectrum_to_xyz_preset(FluoF11_spect, x, y, z); + } else if(method == "Fluo F12" ) { + spectrum_to_xyz_preset(FluoF12_spect, x, y, z); + } else if(method == "HMI Lamp" ) { + spectrum_to_xyz_preset(HMI_spect, x, y, z); + } else if(method == "GTI Lamp" ) { + spectrum_to_xyz_preset(GTI_spect, x, y, z); + } else if(method == "JudgeIII Lamp" ) { + spectrum_to_xyz_preset(JudgeIII_spect, x, y, z); + } else if(method == "Solux Lamp 3500K" ) { + spectrum_to_xyz_preset(Solux3500_spect, x, y, z); + } else if(method == "Solux Lamp 4100K" ) { + spectrum_to_xyz_preset(Solux4100_spect, x, y, z); + } else if(method == "Solux Lamp 4700K" ) { + spectrum_to_xyz_preset(Solux4700_spect, x, y, z); + } else if(method == "NG Solux Lamp 4700K" ) { + spectrum_to_xyz_preset(NG_Solux4700_spect, x, y, z); + } else if(method == "LED LSI Lumelex 2040") { + spectrum_to_xyz_preset(NG_LEDLSI2040_spect, x, y, z); + } else if(method == "LED CRS SP12 WWMR16" ) { + spectrum_to_xyz_preset(NG_CRSSP12WWMR16_spect, x, y, z); + } else if(method == "Flash 5500K" ) { + spectrum_to_xyz_preset(Flash5500_spect, x, y, z); + } else if(method == "Flash 6000K" ) { + spectrum_to_xyz_preset(Flash6000_spect, x, y, z); + } else if(method == "Flash 6500K" ) { + spectrum_to_xyz_preset(Flash6500_spect, x, y, z); + } else { // otherwise we use the Temp+Green generic solution if (tem <= INITIALBLACKBODY) { // if temperature is between 2000K and 4000K we use blackbody, because there will be no Daylight reference below 4000K... // of course, the previous version of RT used the "magical" but wrong formula of U.Fuchs (Ufraw). spectrum_to_xyz_blackbody(tem, x, y, z); - } - else { + } else { // from 4000K up to 25000K: using the D illuminant (daylight) which is standard double m1, m2; - if (tem<=7000) - x_D = -4.6070e9/(tem*tem*tem) + 2.9678e6/(tem*tem) + 0.09911e3/tem + 0.244063; - else if (tem <=25000) - x_D = -2.0064e9/(tem*tem*tem) + 1.9018e6/(tem*tem) + 0.24748e3/tem + 0.237040; - else if (tem >25000) - x_D = -2.0064e9/(tem*tem*tem) + 1.9018e6/(tem*tem) + 0.24748e3/tem + 0.237040 - ((tem-25000)/25000)*0.025;//Jacques empirical adjustemnt for very high temp (underwater !) - y_D = -3.0*x_D*x_D + 2.87*x_D - 0.275; + if (tem <= 7000) { + x_D = -4.6070e9 / (tem * tem * tem) + 2.9678e6 / (tem * tem) + 0.09911e3 / tem + 0.244063; + } else if (tem <= 25000) { + x_D = -2.0064e9 / (tem * tem * tem) + 1.9018e6 / (tem * tem) + 0.24748e3 / tem + 0.237040; + } else if (tem > 25000) { + x_D = -2.0064e9 / (tem * tem * tem) + 1.9018e6 / (tem * tem) + 0.24748e3 / tem + 0.237040 - ((tem - 25000) / 25000) * 0.025; //Jacques empirical adjustemnt for very high temp (underwater !) + } + + y_D = -3.0 * x_D * x_D + 2.87 * x_D - 0.275; //calculate D -daylight in function of s0, s1, s2 and temp ==> x_D y_D //S(lamda)=So(lambda)+m1*s1(lambda)+m2*s2(lambda) - interm=(0.0241+0.2562*x_D-0.734*y_D); - m1=(-1.3515-1.7703*x_D+5.9114*y_D)/interm; - m2=(0.03-31.4424*x_D+30.0717*y_D)/interm; + interm = (0.0241 + 0.2562 * x_D - 0.734 * y_D); + m1 = (-1.3515 - 1.7703 * x_D + 5.9114 * y_D) / interm; + m2 = (0.03 - 31.4424 * x_D + 30.0717 * y_D) / interm; spectrum_to_xyz_daylight(m1, m2, x, y, z); - xD=x;yD=y; + xD = x; + yD = y; } } - xD=x; yD=y; + xD = x; + yD = y; - double X = xD/yD; - double Z = (1.0-xD-yD)/yD; - Xxyz=X; - Zxyz=Z; + double X = xD / yD; + double Z = (1.0 - xD - yD) / yD; + Xxyz = X; + Zxyz = Z; //printf("Xxyz=%f Zxyz=%f\n",Xxyz,Zxyz); } -void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, double& gmul, double& bmul) { +void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, double& gmul, double& bmul) +{ clip (temp, green, equal); //printf("temp=%d green=%.3f equal=%.3f\n", (int)temp, (float) green, (float) equal); //variables for CRI and display Lab, and palette - bool CRI_type=false; + bool CRI_type = false; double xD, yD, x_D, y_D, interm; double m1, m2; - double xp,yp; + double xp, yp; double x, y, z, xx, yy, zz; - double Xchk[50],Ychk[50],Zchk[50]; //50 : I think it's a good limit for number of color : for CRI and Palette - double Xcam02[50],Ycam02[50],Zcam02[50]; - double Xcam02pal[50],Ycam02pal[50],Zcam02pal[50]; + double Xchk[50], Ychk[50], Zchk[50]; //50 : I think it's a good limit for number of color : for CRI and Palette + double Xcam02[50], Ycam02[50], Zcam02[50]; + double Xcam02pal[50], Ycam02pal[50], Zcam02pal[50]; - double XchkLamp[50],YchkLamp[50],ZchkLamp[50]; - double Xcam02Lamp[50],Ycam02Lamp[50],Zcam02Lamp[50]; - double Xpal[50],Ypal[50],Zpal[50]; + double XchkLamp[50], YchkLamp[50], ZchkLamp[50]; + double Xcam02Lamp[50], Ycam02Lamp[50], Zcam02Lamp[50]; + double Xpal[50], Ypal[50], Zpal[50]; double tempw; - const double epsilon=0.008856;//Lab - const double whiteD50[3]={0.9646019585,1.0,0.8244507152};//calculate with this tool : spect 5nm - double CAM02BB00,CAM02BB01,CAM02BB02,CAM02BB10,CAM02BB11,CAM02BB12,CAM02BB20,CAM02BB21,CAM02BB22;//for CIECAT02 + const double epsilon = 0.008856; //Lab + const double whiteD50[3] = {0.9646019585, 1.0, 0.8244507152}; //calculate with this tool : spect 5nm + double CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22; //for CIECAT02 - double xr[50],yr[50],zr[50]; - double fx[50],fy[50],fz[50]; - double Llamp[50],alamp[50],blamp[50]; - double Lbb[50],abb[50],bbb[50]; - double Lpal[50],apal[50],bpal[50]; + double xr[50], yr[50], zr[50]; + double fx[50], fy[50], fz[50]; + double Llamp[50], alamp[50], blamp[50]; + double Lbb[50], abb[50], bbb[50]; + double Lpal[50], apal[50], bpal[50]; - int palet=-1; - bool palette=false; + int palet = -1; + bool palette = false; // double tempalet; // correlated temperature // We first test for specially handled methods - if (method == "Daylight" ) {spectrum_to_xyz_preset(Daylight5300_spect, x, y, z);palet=0; /*tempalet=5300;*/ } - else if(method == "Cloudy" ) {spectrum_to_xyz_preset(Cloudy6200_spect, x, y, z);palet=1; /*tempalet=6200;*/ } - else if(method == "Shade" ) {spectrum_to_xyz_preset(Shade7600_spect, x, y, z);palet=2; /*tempalet=7600;*/ } - else if(method == "Tungsten" ) {spectrum_to_xyz_preset(A2856_spect, x, y, z);palet=3; /*tempalet=2856;*/ } - else if(method == "Fluo F1" ) {spectrum_to_xyz_preset(FluoF1_spect, x, y, z);palet=4; /*tempalet=6430;*/ } - else if(method == "Fluo F2" ) {spectrum_to_xyz_preset(FluoF2_spect, x, y, z);palet=5; /*tempalet=4230;*/ } - else if(method == "Fluo F3" ) {spectrum_to_xyz_preset(FluoF3_spect, x, y, z);palet=6; /*tempalet=3450;*/ } - else if(method == "Fluo F4" ) {spectrum_to_xyz_preset(FluoF4_spect, x, y, z);palet=7; /*tempalet=2940;*/ } - else if(method == "Fluo F5" ) {spectrum_to_xyz_preset(FluoF5_spect, x, y, z);palet=8; /*tempalet=6350;*/ } - else if(method == "Fluo F6" ) {spectrum_to_xyz_preset(FluoF6_spect, x, y, z);palet=9; /*tempalet=4150;*/ } - else if(method == "Fluo F7" ) {spectrum_to_xyz_preset(FluoF7_spect, x, y, z);palet=10; /*tempalet=6500;*/ } - else if(method == "Fluo F8" ) {spectrum_to_xyz_preset(FluoF8_spect, x, y, z);palet=11; /*tempalet=5020;*/ } - else if(method == "Fluo F9" ) {spectrum_to_xyz_preset(FluoF9_spect, x, y, z);palet=12; /*tempalet=4330;*/ } - else if(method == "Fluo F10" ) {spectrum_to_xyz_preset(FluoF10_spect, x, y, z);palet=13; /*tempalet=5300;*/ } - else if(method == "Fluo F11" ) {spectrum_to_xyz_preset(FluoF11_spect, x, y, z);palet=14; /*tempalet=4000;*/ } - else if(method == "Fluo F12" ) {spectrum_to_xyz_preset(FluoF12_spect, x, y, z);palet=15; /*tempalet=3000;*/ } - else if(method == "HMI Lamp" ) {spectrum_to_xyz_preset(HMI_spect, x, y, z);palet=16; /*tempalet=4760;*/ } - else if(method == "GTI Lamp" ) {spectrum_to_xyz_preset(GTI_spect, x, y, z);palet=17; /*tempalet=5000;*/ } - else if(method == "JudgeIII Lamp" ) {spectrum_to_xyz_preset(JudgeIII_spect, x, y, z);palet=18; /*tempalet=5100;*/ } - else if(method == "Solux Lamp 3500K" ) {spectrum_to_xyz_preset(Solux3500_spect, x, y, z);palet=19; /*tempalet=3480;*/ } - else if(method == "Solux Lamp 4100K" ) {spectrum_to_xyz_preset(Solux4100_spect, x, y, z);palet=20; /*tempalet=3930;*/ } - else if(method == "Solux Lamp 4700K" ) {spectrum_to_xyz_preset(Solux4700_spect, x, y, z);palet=21; /*tempalet=4700;*/ } - else if(method == "NG Solux Lamp 4700K" ) {spectrum_to_xyz_preset(NG_Solux4700_spect, x, y, z);palet=22; /*tempalet=4480;*/ } - else if(method == "LED LSI Lumelex 2040") {spectrum_to_xyz_preset(NG_LEDLSI2040_spect, x, y, z);palet=23; /*tempalet=2970;*/ } - else if(method == "LED CRS SP12 WWMR16" ) {spectrum_to_xyz_preset(NG_CRSSP12WWMR16_spect, x, y, z);palet=24; /*tempalet=3050;*/ } - else if(method == "Flash 5500K" ) {spectrum_to_xyz_preset(Flash5500_spect, x, y, z);palet=25; /*tempalet=5500;*/ } - else if(method == "Flash 6000K" ) {spectrum_to_xyz_preset(Flash6000_spect, x, y, z);palet=26; /*tempalet=6000;*/ } - else if(method == "Flash 6500K" ) {spectrum_to_xyz_preset(Flash6500_spect, x, y, z);palet=27; /*tempalet=6500;*/ } - else { + if (method == "Daylight" ) { + spectrum_to_xyz_preset(Daylight5300_spect, x, y, z); + palet = 0; /*tempalet=5300;*/ + } else if(method == "Cloudy" ) { + spectrum_to_xyz_preset(Cloudy6200_spect, x, y, z); + palet = 1; /*tempalet=6200;*/ + } else if(method == "Shade" ) { + spectrum_to_xyz_preset(Shade7600_spect, x, y, z); + palet = 2; /*tempalet=7600;*/ + } else if(method == "Tungsten" ) { + spectrum_to_xyz_preset(A2856_spect, x, y, z); + palet = 3; /*tempalet=2856;*/ + } else if(method == "Fluo F1" ) { + spectrum_to_xyz_preset(FluoF1_spect, x, y, z); + palet = 4; /*tempalet=6430;*/ + } else if(method == "Fluo F2" ) { + spectrum_to_xyz_preset(FluoF2_spect, x, y, z); + palet = 5; /*tempalet=4230;*/ + } else if(method == "Fluo F3" ) { + spectrum_to_xyz_preset(FluoF3_spect, x, y, z); + palet = 6; /*tempalet=3450;*/ + } else if(method == "Fluo F4" ) { + spectrum_to_xyz_preset(FluoF4_spect, x, y, z); + palet = 7; /*tempalet=2940;*/ + } else if(method == "Fluo F5" ) { + spectrum_to_xyz_preset(FluoF5_spect, x, y, z); + palet = 8; /*tempalet=6350;*/ + } else if(method == "Fluo F6" ) { + spectrum_to_xyz_preset(FluoF6_spect, x, y, z); + palet = 9; /*tempalet=4150;*/ + } else if(method == "Fluo F7" ) { + spectrum_to_xyz_preset(FluoF7_spect, x, y, z); + palet = 10; /*tempalet=6500;*/ + } else if(method == "Fluo F8" ) { + spectrum_to_xyz_preset(FluoF8_spect, x, y, z); + palet = 11; /*tempalet=5020;*/ + } else if(method == "Fluo F9" ) { + spectrum_to_xyz_preset(FluoF9_spect, x, y, z); + palet = 12; /*tempalet=4330;*/ + } else if(method == "Fluo F10" ) { + spectrum_to_xyz_preset(FluoF10_spect, x, y, z); + palet = 13; /*tempalet=5300;*/ + } else if(method == "Fluo F11" ) { + spectrum_to_xyz_preset(FluoF11_spect, x, y, z); + palet = 14; /*tempalet=4000;*/ + } else if(method == "Fluo F12" ) { + spectrum_to_xyz_preset(FluoF12_spect, x, y, z); + palet = 15; /*tempalet=3000;*/ + } else if(method == "HMI Lamp" ) { + spectrum_to_xyz_preset(HMI_spect, x, y, z); + palet = 16; /*tempalet=4760;*/ + } else if(method == "GTI Lamp" ) { + spectrum_to_xyz_preset(GTI_spect, x, y, z); + palet = 17; /*tempalet=5000;*/ + } else if(method == "JudgeIII Lamp" ) { + spectrum_to_xyz_preset(JudgeIII_spect, x, y, z); + palet = 18; /*tempalet=5100;*/ + } else if(method == "Solux Lamp 3500K" ) { + spectrum_to_xyz_preset(Solux3500_spect, x, y, z); + palet = 19; /*tempalet=3480;*/ + } else if(method == "Solux Lamp 4100K" ) { + spectrum_to_xyz_preset(Solux4100_spect, x, y, z); + palet = 20; /*tempalet=3930;*/ + } else if(method == "Solux Lamp 4700K" ) { + spectrum_to_xyz_preset(Solux4700_spect, x, y, z); + palet = 21; /*tempalet=4700;*/ + } else if(method == "NG Solux Lamp 4700K" ) { + spectrum_to_xyz_preset(NG_Solux4700_spect, x, y, z); + palet = 22; /*tempalet=4480;*/ + } else if(method == "LED LSI Lumelex 2040") { + spectrum_to_xyz_preset(NG_LEDLSI2040_spect, x, y, z); + palet = 23; /*tempalet=2970;*/ + } else if(method == "LED CRS SP12 WWMR16" ) { + spectrum_to_xyz_preset(NG_CRSSP12WWMR16_spect, x, y, z); + palet = 24; /*tempalet=3050;*/ + } else if(method == "Flash 5500K" ) { + spectrum_to_xyz_preset(Flash5500_spect, x, y, z); + palet = 25; /*tempalet=5500;*/ + } else if(method == "Flash 6000K" ) { + spectrum_to_xyz_preset(Flash6000_spect, x, y, z); + palet = 26; /*tempalet=6000;*/ + } else if(method == "Flash 6500K" ) { + spectrum_to_xyz_preset(Flash6500_spect, x, y, z); + palet = 27; /*tempalet=6500;*/ + } else { // otherwise we use the Temp+Green generic solution if (temp <= INITIALBLACKBODY) { // if temperature is between 2000K and 4000K we use blackbody, because there will be no Daylight reference below 4000K... // of course, the previous version of RT used the "magical" but wrong formula of U.Fuchs (Ufraw). - spectrum_to_xyz_blackbody(temp, x, y, z);palet=28; - } - else { + spectrum_to_xyz_blackbody(temp, x, y, z); + palet = 28; + } else { // from 4000K up to 25000K: using the D illuminant (daylight) which is standard - palet=29; - if (temp<=7000) - x_D = -4.6070e9/(temp*temp*temp) + 2.9678e6/(temp*temp) + 0.09911e3/temp + 0.244063; - else if (temp <=25000) - x_D = -2.0064e9/(temp*temp*temp) + 1.9018e6/(temp*temp) + 0.24748e3/temp + 0.237040; - else if (temp >25000) // above 25000 it's unknown..then I have modified to adjust for underwater - x_D = -2.0064e9/(temp*temp*temp) + 1.9018e6/(temp*temp) + 0.24748e3/temp + 0.237040 - ((temp-25000)/25000)*0.025;//Jacques empirical adjustemnt for very high temp (underwater !) + palet = 29; - y_D = (-3.0*x_D*x_D + 2.87*x_D - 0.275);//modify blue / red action + if (temp <= 7000) { + x_D = -4.6070e9 / (temp * temp * temp) + 2.9678e6 / (temp * temp) + 0.09911e3 / temp + 0.244063; + } else if (temp <= 25000) { + x_D = -2.0064e9 / (temp * temp * temp) + 1.9018e6 / (temp * temp) + 0.24748e3 / temp + 0.237040; + } else if (temp > 25000) { // above 25000 it's unknown..then I have modified to adjust for underwater + x_D = -2.0064e9 / (temp * temp * temp) + 1.9018e6 / (temp * temp) + 0.24748e3 / temp + 0.237040 - ((temp - 25000) / 25000) * 0.025; //Jacques empirical adjustemnt for very high temp (underwater !) + } + + y_D = (-3.0 * x_D * x_D + 2.87 * x_D - 0.275); //modify blue / red action //calculate D -daylight in function of s0, s1, s2 and temp ==> x_D y_D //S(lamda)=So(lambda)+m1*s1(lambda)+m2*s2(lambda) - interm=(0.0241+0.2562*x_D-0.734*y_D); - m1=(-1.3515-1.7703*x_D+5.9114*y_D)/interm; - m2=(0.03-31.4424*x_D+30.0717*y_D)/interm; + interm = (0.0241 + 0.2562 * x_D - 0.734 * y_D); + m1 = (-1.3515 - 1.7703 * x_D + 5.9114 * y_D) / interm; + m2 = (0.03 - 31.4424 * x_D + 30.0717 * y_D) / interm; spectrum_to_xyz_daylight(m1, m2, x, y, z); - xD=x;yD=y; + xD = x; + yD = y; } } - xD=x; yD=y; - float adj=1.f; - if(equal < 0.9999 || equal > 1.0001 ){ - adj=(100.f+( 1000.f-(1000.f*(float)equal) )/20.f)/100.f; + xD = x; + yD = y; + float adj = 1.f; + + if(equal < 0.9999 || equal > 1.0001 ) { + adj = (100.f + ( 1000.f - (1000.f * (float)equal) ) / 20.f) / 100.f; } + //printf("adj=%f\n",adj); - double Xwb = xD/yD; + double Xwb = xD / yD; double Ywb = 1.0; - double Zwb = (1.0-xD-yD)/yD; + double Zwb = (1.0 - xD - yD) / yD; double correl_temp; - + if (settings->verbose) { // double u=4*xD/(-2*xD+12*yD+3); // double v=6*yD/(-2*xD+12*yD+3); // printf("xD=%f yD=%f u=%f v=%f\n",xD,yD,u,v); - if(settings->CRI_color != 0) - printf("xD=%f yD=%f === Xwb=%f Ywb=%f Zwb=%f\n",xD,yD,Xwb,Ywb,Zwb); + if(settings->CRI_color != 0) { + printf("xD=%f yD=%f === Xwb=%f Ywb=%f Zwb=%f\n", xD, yD, Xwb, Ywb, Zwb); + } } /*if (isRaw) { @@ -1172,325 +1310,475 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, bmul = sRGB_xyz[2][0]*X + sRGB_xyz[2][1]*Y + sRGB_xyz[2][2]*Z; } else {*/ //recalculate channels multipliers with new values of XYZ tue to whitebalance - rmul = sRGBd65_xyz[0][0]*Xwb*adj + sRGBd65_xyz[0][1]*Ywb + sRGBd65_xyz[0][2]*Zwb/adj; // Jacques' empirical modification 5/2013 - gmul = sRGBd65_xyz[1][0]*Xwb + sRGBd65_xyz[1][1]*Ywb + sRGBd65_xyz[1][2]*Zwb; - bmul = sRGBd65_xyz[2][0]*Xwb*adj + sRGBd65_xyz[2][1]*Ywb + sRGBd65_xyz[2][2]*Zwb/adj; + rmul = sRGBd65_xyz[0][0] * Xwb * adj + sRGBd65_xyz[0][1] * Ywb + sRGBd65_xyz[0][2] * Zwb / adj; // Jacques' empirical modification 5/2013 + gmul = sRGBd65_xyz[1][0] * Xwb + sRGBd65_xyz[1][1] * Ywb + sRGBd65_xyz[1][2] * Zwb; + bmul = sRGBd65_xyz[2][0] * Xwb * adj + sRGBd65_xyz[2][1] * Ywb + sRGBd65_xyz[2][2] * Zwb / adj; //}; gmul /= green; //printf("rmul=%f gmul=%f bmul=%f\n",rmul, gmul, bmul); double max = rmul; - if (gmul>max) max = gmul; - if (bmul>max) max = bmul; + + if (gmul > max) { + max = gmul; + } + + if (bmul > max) { + max = bmul; + } + rmul /= max; gmul /= max; bmul /= max; - - if(palette) // palette of color : 32 skin, 4 grey, 4 blue sky - //calculate L a b in function of color and illuminant - //J.Desmis january 2012 - { - double x_x,y_y,z_z; - // illuminants - const double* spect_illummax[] = { - Daylight5300_spect,Cloudy6200_spect,Shade7600_spect,A2856_spect,FluoF1_spect,FluoF2_spect,FluoF3_spect,FluoF4_spect,FluoF5_spect,FluoF6_spect,FluoF7_spect, - FluoF8_spect,FluoF9_spect,FluoF10_spect,FluoF11_spect,FluoF12_spect,HMI_spect,GTI_spect,JudgeIII_spect,Solux3500_spect,Solux4100_spect,Solux4700_spect,NG_Solux4700_spect,NG_CRSSP12WWMR16_spect,NG_CRSSP12WWMR16_spect, - Flash5500_spect,Flash6000_spect,Flash6500_spect - }; - // color - const double* spec_colorpalet[] = { - ColabSkin98_m2_10_spect, ColabSkin95_0_4_spect,ColabSkin91_4_14_spect, ColabSkin90_m1_20_spect, - ColorchechSGSkiK285_11_17_spect,ColabSkin87_8_8_spect,ColabSkin87_3_10_spect,ColabSkin89_8_21_spect, - ColabSkin70_7_32_spect,ColabSkin77_12_21_spect,ColabSkin75_8_4_spect,ColabSkin75_10_33_spect, - ColorchechSkiB166_18_18_spect,ColabSkin65_7_24_spect,ColorchechSGSkiF763_14_26_spect,ColabSkin65_33_11_spect, - ColabSkin57_19_6_spect,ColabSkin57_4_19_spect,ColabSkin57_10_28_spect,ColabSkin57_22_18_spect, - ColabSkin40_17_17_spect,ColabSkin40_7_19_spect,ColabSkin40_4_11_spect,ColabSkin40_17_6_spect, - ColorchechSkiA138_13_14_spect,ColabSkin33_6_15_spect,ColabSkin35_15_17_spect,ColabSkin33_15_5_spect, - ColabSkin26_18_18_spect,ColabSkin24_7_5_spect,ColabSkin24_5_6_spect,ColabSkin20_4_2_spect, - ColabSky42_0_m24_spect,ColorchechBluC150_m5_m22_spect,ColorchechWhiA496_spect, ColorchechSGBlaN3_6_spect, - JDC468_GraK14_44_spect,ColorchechGraC4_67_spect,ColabSky60_0_m31_spect,ColorchechDCBluN881_m7_m14_spect - //ColabSkin33_10_15_spect, - //ColabSkin81_2_14_spect, - }; - - int N_col = sizeof(spec_colorpalet)/sizeof(spec_colorpalet[0]);//number of color - - if(palet < 28) { - for(int i=0;i=28) { - if(temp epsilon - if(xr[i]> epsilon) fx[i]=pow(xr[i],0.333);else fx[i]=(903.3*xr[i]+16.0)/116.0; - if(yr[i]> epsilon) fy[i]=pow(yr[i],0.333);else fy[i]=(903.3*yr[i]+16.0)/116.0; - if(zr[i]> epsilon) fz[i]=pow(zr[i],0.333);else fz[i]=(903.3*zr[i]+16.0)/116.0; - } - //Lab values in function of color and illuminant - //these values can be compared to preview values when using white-balance (skin / sky / BW) - for(int i=0;iCRI_color != 0) printf("Lpal=%2.2f apal=%2.2f bpal=%2.2f\n", Lpal[0],apal[0],bpal[0]);//sample - //} + if(palet < 28) { + for(int i = 0; i < N_col; i++) { + spectrum_to_color_xyz_preset(spec_colorpalet[i], spect_illummax[palet], x_x, y_y, z_z); + Xpal[i] = x_x; + Ypal[i] = y_y; + Zpal[i] = z_z; + } + } else if(palet >= 28) { + if(temp < INITIALBLACKBODY) { + for(int i = 0; i < N_col; i++) { + spectrum_to_color_xyz_blackbody(spec_colorpalet[i], temp, x_x, y_y, z_z); + Xpal[i] = x_x; + Ypal[i] = y_y; + Zpal[i] = z_z; + } + } else { + double m11p, m22p; + m11p = m1; + m22p = m2; - } //end palette + for(int i = 0; i < N_col; i++) { // calculate XYZ palette for illuminant and color + spectrum_to_color_xyz_daylight(spec_colorpalet[i], m11p, m22p, x_x, y_y, z_z); + Xpal[i] = x_x; + Ypal[i] = y_y; + Zpal[i] = z_z; + } + } + } - // begin CRI_RT : color rendering index RT - adaptation of CRI by J.Desmis - // CRI = 100 for Blackbody and Daylight - // calculate from spectral data values X, Y, Z , for color of colorchecker24 , SG, DC, JDC_468 - //only for lamp different of tungstene - //first calcul with illuminant (choice) - // and calcul with : blackbody at equivalent temp of lamp + xp = xD; + yp = yD; + double Xwbpal = xp / yp; //white balance + double Ywbpal = 1.0; + double Zwbpal = (1.0 - xp - yp) / yp; + //chromatic adaptation CIECAT02 at temp + double adap = 1.0; + cieCAT02(Xwbpal, Ywbpal, Zwbpal, CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22, adap); - if(settings->CRI_color != 0) //activate if CRi_color !=0 - // CRI_color-1 = dispaly Lab values of color CRI_color -1 - { - int illum; - int numero_color=settings->CRI_color - 1; + //here new value of X,Y,Z with chromatic CAM02 adaptation + for(int i = 0; i < N_col; i++) { + Xcam02pal[i] = CAM02BB00 * Xpal[i] + CAM02BB01 * Ypal[i] + CAM02BB02 * Zpal[i] ; + Ycam02pal[i] = CAM02BB10 * Xpal[i] + CAM02BB11 * Ypal[i] + CAM02BB12 * Zpal[i] ; + Zcam02pal[i] = CAM02BB20 * Xpal[i] + CAM02BB21 * Ypal[i] + CAM02BB22 * Zpal[i] ; + //printf("CoulXYZ %i X %f Y %f Z %f\n", i, Xpal[i],Ypal[i],Zpal[i]); + //printf("CoulCAM %i X %f Y %f Z %f\n", i, Xcam02pal[i],Ycam02pal[i],Zcam02pal[i]); + } - //spectral data illuminant (actually 21): only those necessary (lamp, fluorescent, LED) others CRI=100 (not Flash...) - const double* spect_illum[] = { - Daylight5300_spect,Cloudy6200_spect,Shade7600_spect,A2856_spect,FluoF1_spect,FluoF2_spect,FluoF3_spect, - FluoF4_spect,FluoF5_spect,FluoF6_spect,FluoF7_spect,FluoF8_spect,FluoF9_spect,FluoF10_spect,FluoF11_spect, - FluoF12_spect,HMI_spect,GTI_spect,JudgeIII_spect,Solux3500_spect,Solux4100_spect,Solux4700_spect, - NG_Solux4700_spect,NG_CRSSP12WWMR16_spect,NG_CRSSP12WWMR16_spect - }; - const double* spec_color[] = { - ColorchechredC3_spect, ColorchechOraA2_spect,ColorchechYelD3_spect,ColorchechGreE2_spect,ColorchechGreB3_spect, - ColorchechCyaF3_spect, ColorchechPurD2_spect,ColorchechMagE3_spect,ColorchechSkiA138_13_14_spect,ColorchechGraC4_67_spect, - ColorchechSkiB166_18_18_spect,ColorchechBluC150_m5_m22_spect,ColorchechDCBluN881_m7_m14_spect,ColorchechSGSkiF763_14_26_spect, - ColorchechSGSkiK285_11_17_spect,ColorchechWhiA496_spect, ColorchechGreD1_spect, ColorchechSGBlaN3_6_spect, - JDC468_GraK14_44_spect,JDC468_BluH10_spect - }; + //Calculate Lab + for(int i = 0; i < N_col; i++) { + xr[i] = Xcam02pal[i] / whiteD50[0]; + yr[i] = Ycam02pal[i] / whiteD50[1]; + zr[i] = Zcam02pal[i] / whiteD50[2]; - int N_c = sizeof(spec_color)/sizeof(spec_color[0]);//number of color + // xr, yr , zr > epsilon + if(xr[i] > epsilon) { + fx[i] = pow(xr[i], 0.333); + } else { + fx[i] = (903.3 * xr[i] + 16.0) / 116.0; + } - if (method == "Fluo F1") {CRI_type=true; tempw=6430; illum=1;} - else if (method == "Fluo F2") {CRI_type=true; tempw=4230; illum=2;} - else if (method == "Fluo F3") {CRI_type=true; tempw=3450; illum=3;} - else if (method == "Fluo F4") {CRI_type=true; tempw=2940; illum=4;} - else if (method == "Fluo F5") {CRI_type=true; tempw=6350; illum=5;} - else if (method == "Fluo F6") {CRI_type=true; tempw=4150; illum=6;} - else if (method == "Fluo F7") {CRI_type=true; tempw=6500; illum=7;} - else if (method == "Fluo F8") {CRI_type=true; tempw=5020; illum=8;} - else if (method == "Fluo F9") {CRI_type=true; tempw=4330; illum=9;} - else if (method == "Fluo F10") {CRI_type=true; tempw=5300; illum=10;} - else if (method == "Fluo F11") {CRI_type=true; tempw=4000; illum=11;} - else if (method == "Fluo F12") {CRI_type=true; tempw=3000; illum=12;} - else if (method == "HMI Lamp") {CRI_type=true; tempw=4760; illum=13;} - else if (method == "GTI Lamp") {CRI_type=true; tempw=5000; illum=14;} - else if (method == "JudgeIII Lamp") {CRI_type=true; tempw=5100; illum=15;} - else if (method == "Solux Lamp 3500K") {CRI_type=true; tempw=3480; illum=16;} - else if (method == "Solux Lamp 4100K") {CRI_type=true; tempw=3930; illum=17;} - else if (method == "Solux Lamp 4700K" ) {CRI_type=true; tempw=4700; illum=18;} - else if (method == "NG Solux Lamp 4700K") {CRI_type=true; tempw=4480; illum=19;} - else if (method == "LED LSI Lumelex 2040") {CRI_type=true; tempw=2970; illum=20;} - else if (method == "LED CRS SP12 WWMR16") {CRI_type=true; tempw=3050; illum=21;} - else {CRI_type=false;} + if(yr[i] > epsilon) { + fy[i] = pow(yr[i], 0.333); + } else { + fy[i] = (903.3 * yr[i] + 16.0) / 116.0; + } - if (CRI_type) { - float DeltaE[50], DeltaEs[8]; - float quadCRI=0.0f,quadCRIs=0.0f; - float CRI_RT=0.0, CRI[50]; - float CRI_RTs=0.0, CRIs[8]; + if(zr[i] > epsilon) { + fz[i] = pow(zr[i], 0.333); + } else { + fz[i] = (903.3 * zr[i] + 16.0) / 116.0; + } + } - for(int i=0;iCRI_color != 0) { + printf("Lpal=%2.2f apal=%2.2f bpal=%2.2f\n", Lpal[0], apal[0], bpal[0]); //sample + } - y_DD = -3.0*x_DD*x_DD + 2.87*x_DD - 0.275; - //calculate D -daylight in function of s0, s1, s2 and temp ==> x_D y_D - //S(lamda)=So(lambda)+m1*s1(lambda)+m2*s2(lambda) - interm2=(0.0241+0.2562*x_DD-0.734*y_DD); - m11=(-1.3515-1.7703*x_DD+5.9114*y_DD)/interm2; - m22=(0.03-31.4424*x_DD+30.0717*y_DD)/interm2; + //} - for(int i=0;iverbose) { - printf("Correlated temperature (lamp)=%i\n", (int) correl_temp); //use only for lamp...otherwise It give an information!! - } + // begin CRI_RT : color rendering index RT - adaptation of CRI by J.Desmis + // CRI = 100 for Blackbody and Daylight + // calculate from spectral data values X, Y, Z , for color of colorchecker24 , SG, DC, JDC_468 + //only for lamp different of tungstene + //first calcul with illuminant (choice) + // and calcul with : blackbody at equivalent temp of lamp - double Xwb_bb = x/y;//white balance for blackbody - double Ywb_bb = 1.0; - double Zwb_bb = (1.0-x-y)/y; + if(settings->CRI_color != 0) //activate if CRi_color !=0 + // CRI_color-1 = dispaly Lab values of color CRI_color -1 + { + int illum; + int numero_color = settings->CRI_color - 1; - //calculate Matrix CAM02 : better than Von Kries and Bradford==> for Lamp - double adap=1.0; - cieCAT02(Xwb, Ywb, Zwb, CAM02BB00,CAM02BB01,CAM02BB02,CAM02BB10,CAM02BB11,CAM02BB12,CAM02BB20,CAM02BB21,CAM02BB22,adap); - //here new value of X,Y,Z for lamp with chromatic CAM02 adaptation - for(int i=0;i epsilon - if(xr[i]> epsilon) fx[i]=pow(xr[i],0.333);else fx[i]=(903.3*xr[i]+16.0)/116.0; - if(yr[i]> epsilon) fy[i]=pow(yr[i],0.333);else fy[i]=(903.3*yr[i]+16.0)/116.0; - if(zr[i]> epsilon) fz[i]=pow(zr[i],0.333);else fz[i]=(903.3*zr[i]+16.0)/116.0; - } + //calculate XYZ for each color : for Blackbody and Daylight at tempw + if(tempw <= INITIALBLACKBODY) { + for(int i = 0; i < N_c; i++) { + spectrum_to_color_xyz_blackbody(spec_color[i], tempw, xx, yy, zz); + Xchk[i] = xx; + Ychk[i] = yy; + Zchk[i] = zz; + } - for(int i=0;i epsilon) fx[i]=pow(xr[i],0.333);else fx[i]=(903.3*xr[i]+16.0)/116.0; - if(yr[i]> epsilon) fy[i]=pow(yr[i],0.333);else fy[i]=(903.3*yr[i]+16.0)/116.0; - if(zr[i]> epsilon) fz[i]=pow(zr[i],0.333);else fz[i]=(903.3*zr[i]+16.0)/116.0; - } + y_DD = -3.0 * x_DD * x_DD + 2.87 * x_DD - 0.275; + //calculate D -daylight in function of s0, s1, s2 and temp ==> x_D y_D + //S(lamda)=So(lambda)+m1*s1(lambda)+m2*s2(lambda) + interm2 = (0.0241 + 0.2562 * x_DD - 0.734 * y_DD); + m11 = (-1.3515 - 1.7703 * x_DD + 5.9114 * y_DD) / interm2; + m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2; - for(int i=0;iCRI_color != 0) { - printf("Color Number %i\n",numero_color); - printf("L_refer=%2.2f a=%2.2f b=%2.2f\n", Lbb[numero_color],abb[numero_color],bbb[numero_color]); - printf("L_lamp=%2.2f al=%2.2f bl=%2.2f\n", Llamp[numero_color],alamp[numero_color],blamp[numero_color]); - } + spectrum_to_xyz_daylight(m11, m22, x, y, z); + } - //then calculate DeltaE CIE 1976 - for(int i=0;i<8;i++) - DeltaEs[i]=sqrt((Lbb[i]-Llamp[i])*(Lbb[i]-Llamp[i])+(abb[i]-alamp[i])*(abb[i]-alamp[i])+(bbb[i]-blamp[i])*(bbb[i]-blamp[i])); + XYZtoCorColorTemp(Xwb, Ywb, Zwb, correl_temp); - for(int i=0;i<8;i++) - CRIs[i]=100-3.0*DeltaEs[i]; //3.0 coef to adapt ==> same results than CRI "official" + if (settings->verbose) { + printf("Correlated temperature (lamp)=%i\n", (int) correl_temp); //use only for lamp...otherwise It give an information!! + } - for(int i=0;i<8;i++) - CRI_RTs+=CRIs[i]; - CRI_RTs/=8; + double Xwb_bb = x / y; //white balance for blackbody + double Ywb_bb = 1.0; + double Zwb_bb = (1.0 - x - y) / y; - for(int i=0;i<8;i++) - quadCRIs+=(CRIs[i]-CRI_RTs)*(CRIs[i]-CRI_RTs); - quadCRIs/=8; + //calculate Matrix CAM02 : better than Von Kries and Bradford==> for Lamp + double adap = 1.0; + cieCAT02(Xwb, Ywb, Zwb, CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22, adap); - for(int i=0;i same results than CRI "official" + //now calculate CAM02 for Blackbody (or Daylight) at tempx - for(int i=0;iCRI_color != 0) { - printf("CRI_standard=%i CRI:1->8=%i %i %i %i %i %i %i %i Sigma=%2.1f\n",(int) CRI_RTs, (int) CRIs[0], (int) CRIs[1],(int) CRIs[2],(int) CRIs[3],(int) CRIs[4],(int) CRIs[5],(int) CRIs[6],(int) CRIs[7],sqrt(quadCRIs)); - printf("CRI_RT_exten=%i CRI:9->20=%i %i %i %i %i %i %i %i %i %i %i %i Sigma=%2.1f\n",(int) CRI_RT,(int) CRI[8],(int) CRI[9], (int) CRI[10],(int) CRI[11],(int) CRI[12],(int) CRI[13],(int) CRI[14],(int) CRI[15],(int) CRI[16],(int) CRI[17],(int) CRI[18],(int) CRI[19],sqrt(quadCRI)); - } - } - } + //here new value of X,Y,Z for blackbody with chromatic CAM02 adaptation + + for(int i = 0; i < N_c; i++) { + Xcam02[i] = CAM02BB00 * Xchk[i] + CAM02BB01 * Ychk[i] + CAM02BB02 * Zchk[i] ; + Ycam02[i] = CAM02BB10 * Xchk[i] + CAM02BB11 * Ychk[i] + CAM02BB12 * Zchk[i] ; + Zcam02[i] = CAM02BB20 * Xchk[i] + CAM02BB21 * Ychk[i] + CAM02BB22 * Zchk[i] ; + // printf("CoulXYZ %i X %f Y %f Z %f\n", i, Xchk[i],Ychk[i],Zchk[i]); + // printf("CoulCAM %i X %f Y %f Z %f\n", i, Xcam02[i],Ycam02[i],Zcam02[i]); + } + + //now conversion to Lab + // Lamp + + for(int i = 0; i < N_c; i++) { + xr[i] = Xcam02Lamp[i] / whiteD50[0]; + yr[i] = Ycam02Lamp[i] / whiteD50[1]; + zr[i] = Zcam02Lamp[i] / whiteD50[2]; + + // xr, yr , zr > epsilon + if(xr[i] > epsilon) { + fx[i] = pow(xr[i], 0.333); + } else { + fx[i] = (903.3 * xr[i] + 16.0) / 116.0; + } + + if(yr[i] > epsilon) { + fy[i] = pow(yr[i], 0.333); + } else { + fy[i] = (903.3 * yr[i] + 16.0) / 116.0; + } + + if(zr[i] > epsilon) { + fz[i] = pow(zr[i], 0.333); + } else { + fz[i] = (903.3 * zr[i] + 16.0) / 116.0; + } + } + + for(int i = 0; i < N_c; i++) { + Llamp[i] = 116.0 * fy[i] - 16.0; + alamp[i] = 500.0 * (fx[i] - fy[i]); + blamp[i] = 200.0 * (fy[i] - fz[i]); + } + + //blackbody at tempx + for(int i = 0; i < N_c; i++) { + xr[i] = Xcam02[i] / whiteD50[0]; + yr[i] = Ycam02[i] / whiteD50[1]; + zr[i] = Zcam02[i] / whiteD50[2]; + + // + if(xr[i] > epsilon) { + fx[i] = pow(xr[i], 0.333); + } else { + fx[i] = (903.3 * xr[i] + 16.0) / 116.0; + } + + if(yr[i] > epsilon) { + fy[i] = pow(yr[i], 0.333); + } else { + fy[i] = (903.3 * yr[i] + 16.0) / 116.0; + } + + if(zr[i] > epsilon) { + fz[i] = pow(zr[i], 0.333); + } else { + fz[i] = (903.3 * zr[i] + 16.0) / 116.0; + } + } + + for(int i = 0; i < N_c; i++) { + Lbb[i] = 116.*fy[i] - 16.; + abb[i] = 500.*(fx[i] - fy[i]); + bbb[i] = 200.*(fy[i] - fz[i]); + } + + //display value to verify calculs + if(settings->CRI_color != 0) { + printf("Color Number %i\n", numero_color); + printf("L_refer=%2.2f a=%2.2f b=%2.2f\n", Lbb[numero_color], abb[numero_color], bbb[numero_color]); + printf("L_lamp=%2.2f al=%2.2f bl=%2.2f\n", Llamp[numero_color], alamp[numero_color], blamp[numero_color]); + } + + //then calculate DeltaE CIE 1976 + for(int i = 0; i < 8; i++) { + DeltaEs[i] = sqrt((Lbb[i] - Llamp[i]) * (Lbb[i] - Llamp[i]) + (abb[i] - alamp[i]) * (abb[i] - alamp[i]) + (bbb[i] - blamp[i]) * (bbb[i] - blamp[i])); + } + + for(int i = 0; i < 8; i++) { + CRIs[i] = 100 - 3.0 * DeltaEs[i]; //3.0 coef to adapt ==> same results than CRI "official" + } + + for(int i = 0; i < 8; i++) { + CRI_RTs += CRIs[i]; + } + + CRI_RTs /= 8; + + for(int i = 0; i < 8; i++) { + quadCRIs += (CRIs[i] - CRI_RTs) * (CRIs[i] - CRI_RTs); + } + + quadCRIs /= 8; + + for(int i = 0; i < N_c; i++) { + DeltaE[i] = sqrt((Lbb[i] - Llamp[i]) * (Lbb[i] - Llamp[i]) + (abb[i] - alamp[i]) * (abb[i] - alamp[i]) + (bbb[i] - blamp[i]) * (bbb[i] - blamp[i])); + } + + for(int i = 0; i < N_c; i++) { + CRI[i] = 100 - 3.0 * DeltaE[i]; //3.0 coef to adapt ==> same results than CRI "official" + } + + for(int i = 0; i < N_c; i++) { + CRI_RT += CRI[i]; + } + + CRI_RT /= N_c; + + for(int i = 0; i < N_c; i++) { + quadCRI += (CRI[i] - CRI_RT) * (CRI[i] - CRI_RT); + } + + quadCRI /= N_c; + + if(settings->CRI_color != 0) { + printf("CRI_standard=%i CRI:1->8=%i %i %i %i %i %i %i %i Sigma=%2.1f\n", (int) CRI_RTs, (int) CRIs[0], (int) CRIs[1], (int) CRIs[2], (int) CRIs[3], (int) CRIs[4], (int) CRIs[5], (int) CRIs[6], (int) CRIs[7], sqrt(quadCRIs)); + printf("CRI_RT_exten=%i CRI:9->20=%i %i %i %i %i %i %i %i %i %i %i %i Sigma=%2.1f\n", (int) CRI_RT, (int) CRI[8], (int) CRI[9], (int) CRI[10], (int) CRI[11], (int) CRI[12], (int) CRI[13], (int) CRI[14], (int) CRI[15], (int) CRI[16], (int) CRI[17], (int) CRI[18], (int) CRI[19], sqrt(quadCRI)); + } + } + } } /* Calculate Planck's radiation */ - //calculate spectral data for blackbody at temp! +//calculate spectral data for blackbody at temp! double ColorTemp::blackbody_spect(double wavelength, double temperature) { double wlm = wavelength * 1e-9; /* Wavelength in meters */ @@ -1520,12 +1808,13 @@ void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, doub int i; double lambda, X = 0, Y = 0, Z = 0, XYZ; - for (i=0, lambda=350.; lambda<830.1; i++, lambda+=5.) { + for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) { double Me = daylight_spect(lambda, _m1, _m2); X += Me * cie_colour_match_jd[i][0]; Y += Me * cie_colour_match_jd[i][1]; Z += Me * cie_colour_match_jd[i][2]; } + XYZ = (X + Y + Z); x = X / XYZ; y = Y / XYZ; @@ -1537,12 +1826,13 @@ void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, do int i; double lambda, X = 0, Y = 0, Z = 0, XYZ; - for (i=0, lambda=350.; lambda<830.1; i++, lambda+=5.) { + for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) { double Me = blackbody_spect(lambda, _temp); X += Me * cie_colour_match_jd[i][0]; Y += Me * cie_colour_match_jd[i][1]; Z += Me * cie_colour_match_jd[i][2]; } + XYZ = (X + Y + Z); x = X / XYZ; y = Y / XYZ; @@ -1570,12 +1860,13 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above I have increased the precision used by J.Walker and pass from 350nm to 830nm */ - for (i=0, lambda=350.; lambda<830.1; i++, lambda+=5.) { + for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) { double Me = get_spectral_color(lambda, spec_intens); X += Me * cie_colour_match_jd[i][0]; Y += Me * cie_colour_match_jd[i][1]; Z += Me * cie_colour_match_jd[i][2]; } + XYZ = (X + Y + Z); x = X / XYZ; y = Y / XYZ; @@ -1586,7 +1877,8 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz) { int i; - double lambda, X = 0, Y = 0, Z = 0, Yo=0; + double lambda, X = 0, Y = 0, Z = 0, Yo = 0; + for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { double Me; @@ -1598,6 +1890,7 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou Y += Mc * cie_colour_match_jd[i][1] * Me; Z += Mc * cie_colour_match_jd[i][2] * Me; } + for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { double Ms; @@ -1615,23 +1908,25 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz) { int i; - double lambda, X = 0, Y = 0, Z = 0, Yo=0; + double lambda, X = 0, Y = 0, Z = 0, Yo = 0; + for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { double Me; double Mc; Me = get_spectral_color(lambda, spec_color); - Mc = daylight_spect(lambda,_m1, _m2); + Mc = daylight_spect(lambda, _m1, _m2); X += Mc * cie_colour_match_jd[i][0] * Me; Y += Mc * cie_colour_match_jd[i][1] * Me; Z += Mc * cie_colour_match_jd[i][2] * Me; } + for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { double Ms; - Ms = daylight_spect(lambda,_m1, _m2); + Ms = daylight_spect(lambda, _m1, _m2); Yo += cie_colour_match_jd[i][1] * Ms; } @@ -1644,7 +1939,8 @@ void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double _temp, double &xx, double &yy, double &zz) { int i; - double lambda, X = 0, Y = 0, Z = 0, Yo=0; + double lambda, X = 0, Y = 0, Z = 0, Yo = 0; + for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { double Me; @@ -1656,6 +1952,7 @@ void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double Y += Mc * cie_colour_match_jd[i][1] * Me; Z += Mc * cie_colour_match_jd[i][2] * Me; } + for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) { double Ms; @@ -1673,22 +1970,25 @@ double ColorTemp::daylight_spect(double wavelength, double m1, double m2) { //Values for Daylight illuminant: s0 s1 s2 //s0 - static const double s0[97]={61.80,61.65,61.50,65.15,68.80,66.10,63.40,64.60,65.80,80.30,94.80,99.80,104.80,105.35,105.90,101.35,96.80,105.35,113.90,119.75,125.60,125.55,125.50,123.40,121.30,121.30,121.30,117.40,113.50,113.30, - 113.10,111.95,110.80,108.65,106.50,107.65,108.80,107.05,105.30,104.85,104.40,102.20,100.00,98.00,96.00,95.55,95.10,92.10,89.10,89.80,90.50,90.40,90.30,89.35,88.40,86.20,84.00,84.55,85.10, - 83.50,81.90,82.25,82.60,83.75,84.90,83.10,81.30,76.60,71.90,73.10,74.30,75.35,76.40,69.85,63.30,67.50,71.70,74.35,77.00,71.10,65.20,56.45,47.70,58.15,68.60,66.80,65.00,65.50,66.00,63.50,61.00,57.15, - 53.30,56.10,58.90,60.40,61.90}; + static const double s0[97] = {61.80, 61.65, 61.50, 65.15, 68.80, 66.10, 63.40, 64.60, 65.80, 80.30, 94.80, 99.80, 104.80, 105.35, 105.90, 101.35, 96.80, 105.35, 113.90, 119.75, 125.60, 125.55, 125.50, 123.40, 121.30, 121.30, 121.30, 117.40, 113.50, 113.30, + 113.10, 111.95, 110.80, 108.65, 106.50, 107.65, 108.80, 107.05, 105.30, 104.85, 104.40, 102.20, 100.00, 98.00, 96.00, 95.55, 95.10, 92.10, 89.10, 89.80, 90.50, 90.40, 90.30, 89.35, 88.40, 86.20, 84.00, 84.55, 85.10, + 83.50, 81.90, 82.25, 82.60, 83.75, 84.90, 83.10, 81.30, 76.60, 71.90, 73.10, 74.30, 75.35, 76.40, 69.85, 63.30, 67.50, 71.70, 74.35, 77.00, 71.10, 65.20, 56.45, 47.70, 58.15, 68.60, 66.80, 65.00, 65.50, 66.00, 63.50, 61.00, 57.15, + 53.30, 56.10, 58.90, 60.40, 61.90 + }; //s1 - static const double s1[97]={41.60,39.80,38.00,40.70,43.40,40.95,38.50,36.75,35.00,39.20,43.40,44.85,46.30,45.10,43.90,40.50,37.10,36.90,36.70,36.30,35.90,34.25,32.60,30.25,27.90,26.10,24.30,22.20,20.10,18.15,16.20,14.70, - 13.20,10.90,8.60,7.35,6.10,5.15,4.20,3.05,1.90,0.95,0.00,-0.80,-1.60,-2.55,-3.50,-3.50,-3.50,-4.65,-5.80,-6.50,-7.20,-7.90,-8.60,-9.05,-9.50,-10.20,-10.90,-10.80,-10.70,-11.35,-12.00,-13.00,-14.00, - -13.80,-13.60,-12.80,-12.00,-12.65,-13.30,-13.10,-12.90,-11.75,-10.60,-11.10,-11.60,-11.90,-12.20,-11.20,-10.20,-9.00,-7.80,-9.50,-11.20,-10.80,-10.50,-10.60,-10.15,-9.70,-9.00,-8.30, - -8.80,-9.30,-9.55,-9.80}; + static const double s1[97] = {41.60, 39.80, 38.00, 40.70, 43.40, 40.95, 38.50, 36.75, 35.00, 39.20, 43.40, 44.85, 46.30, 45.10, 43.90, 40.50, 37.10, 36.90, 36.70, 36.30, 35.90, 34.25, 32.60, 30.25, 27.90, 26.10, 24.30, 22.20, 20.10, 18.15, 16.20, 14.70, + 13.20, 10.90, 8.60, 7.35, 6.10, 5.15, 4.20, 3.05, 1.90, 0.95, 0.00, -0.80, -1.60, -2.55, -3.50, -3.50, -3.50, -4.65, -5.80, -6.50, -7.20, -7.90, -8.60, -9.05, -9.50, -10.20, -10.90, -10.80, -10.70, -11.35, -12.00, -13.00, -14.00, + -13.80, -13.60, -12.80, -12.00, -12.65, -13.30, -13.10, -12.90, -11.75, -10.60, -11.10, -11.60, -11.90, -12.20, -11.20, -10.20, -9.00, -7.80, -9.50, -11.20, -10.80, -10.50, -10.60, -10.15, -9.70, -9.00, -8.30, + -8.80, -9.30, -9.55, -9.80 + }; //s2 - static const double s2[97]={6.70,6.00,5.30,5.70,6.10,4.55,3.00,2.10,1.20,0.05,-1.10,-0.80,-0.50,-0.60,-0.70,-0.95,-1.20,-1.90,-2.60,-2.75,-2.90,-2.85,-2.80,-2.70,-2.60,-2.60,-2.60,-2.20,-1.80,-1.65,-1.50,-1.40,-1.30, - -1.25,-1.20,-1.10,-1.00,-0.75,-0.50,-0.40,-0.30,-0.15,0.00,0.10,0.20,0.35,0.50,1.30,2.10,2.65,3.65,4.10,4.40,4.70,4.90,5.10,5.90,6.70,7.00,7.30,7.95,8.60,9.20,9.80,10.00,10.20,9.25,8.30,8.95, - 9.60,9.05,8.50,7.75,7.00,7.30,7.60,7.80,8.00,7.35,6.70,5.95,5.20,6.30,7.40,7.10,6.80,6.90,7.00,6.70,6.40,5.95,5.50,5.80,6.10,6.30,6.50}; + static const double s2[97] = {6.70, 6.00, 5.30, 5.70, 6.10, 4.55, 3.00, 2.10, 1.20, 0.05, -1.10, -0.80, -0.50, -0.60, -0.70, -0.95, -1.20, -1.90, -2.60, -2.75, -2.90, -2.85, -2.80, -2.70, -2.60, -2.60, -2.60, -2.20, -1.80, -1.65, -1.50, -1.40, -1.30, + -1.25, -1.20, -1.10, -1.00, -0.75, -0.50, -0.40, -0.30, -0.15, 0.00, 0.10, 0.20, 0.35, 0.50, 1.30, 2.10, 2.65, 3.65, 4.10, 4.40, 4.70, 4.90, 5.10, 5.90, 6.70, 7.00, 7.30, 7.95, 8.60, 9.20, 9.80, 10.00, 10.20, 9.25, 8.30, 8.95, + 9.60, 9.05, 8.50, 7.75, 7.00, 7.30, 7.60, 7.80, 8.00, 7.35, 6.70, 5.95, 5.20, 6.30, 7.40, 7.10, 6.80, 6.90, 7.00, 6.70, 6.40, 5.95, 5.50, 5.80, 6.10, 6.30, 6.50 + }; - int wlm = (int) ((wavelength -350.)/5.); - return (s0[wlm]+m1*s1[wlm]+m2*s2[wlm]); + int wlm = (int) ((wavelength - 350.) / 5.); + return (s0[wlm] + m1 * s1[wlm] + m2 * s2[wlm]); } diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index 7b1686ed8..82b161b25 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -7,7 +7,7 @@ * 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 @@ -24,7 +24,8 @@ #define pow_F(a,b) (xexpf(b*xlogf(a))) -namespace rtengine { +namespace rtengine +{ #define MINTEMP 1500 #define MAXTEMP 60000 @@ -36,143 +37,175 @@ namespace rtengine { #define INITIALBLACKBODY 4000 -class ColorTemp { +class ColorTemp +{ - private: - double temp; - double green; - double equal; - std::string method; - static void clip (double &temp, double &green); - static void clip (double &temp, double &green, double &equal); +private: + double temp; + double green; + double equal; + std::string method; + static void clip (double &temp, double &green); + static void clip (double &temp, double &green, double &equal); - public: - - ColorTemp () : temp(-1.), green(-1.), equal (1.), method("Custom") {} - ColorTemp (double e) : temp(-1.), green(-1.), equal (e), method("Custom") {} - ColorTemp (double t, double g, double e, Glib::ustring m); - ColorTemp (double mulr, double mulg, double mulb, double e); +public: - void update (const double rmul, const double gmul, const double bmul, const double equal) { this->equal = equal; mul2temp (rmul, gmul, bmul, this->equal, temp, green); } - void useDefaults (const double equal) { temp = 6504; green = 1.0; this->equal = equal; } // Values copied from procparams.cc + ColorTemp () : temp(-1.), green(-1.), equal (1.), method("Custom") {} + ColorTemp (double e) : temp(-1.), green(-1.), equal (e), method("Custom") {} + ColorTemp (double t, double g, double e, Glib::ustring m); + ColorTemp (double mulr, double mulg, double mulb, double e); - inline std::string getMethod() { return method; } - inline double getTemp () { return temp; } - inline double getGreen () { return green; } - inline double getEqual () { return equal; } + void update (const double rmul, const double gmul, const double bmul, const double equal) + { + this->equal = equal; + mul2temp (rmul, gmul, bmul, this->equal, temp, green); + } + void useDefaults (const double equal) + { + temp = 6504; // Values copied from procparams.cc + green = 1.0; + this->equal = equal; + } - void getMultipliers (double &mulr, double &mulg, double &mulb) { temp2mul (temp, green, equal, mulr, mulg, mulb); } + inline std::string getMethod() + { + return method; + } + inline double getTemp () + { + return temp; + } + inline double getGreen () + { + return green; + } + inline double getEqual () + { + return equal; + } - void mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green); - void temp2mul (double temp, double green, double equal, double& rmul, double& gmul, double& bmul); - static void temp2mulxyz (double tem, double gree, std::string method, double &Xxyz, double &Zxyz); + void getMultipliers (double &mulr, double &mulg, double &mulb) + { + temp2mul (temp, green, equal, mulr, mulg, mulb); + } - int XYZtoCorColorTemp(double x0,double y0 ,double z0, double &temp); - static void cieCAT02(double Xw, double Yw, double Zw,double &CAM02BB00,double &CAM02BB01,double &CAM02BB02, double &CAM02BB10,double &CAM02BB11,double &CAM02BB12,double &CAM02BB20,double &CAM02BB21,double &CAM02BB22, double adap ); - //static void CAT02 (Imagefloat* baseImg, const ProcParams* params); - //static void ciecam_02 (LabImage* lab, const ProcParams* params); + void mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green); + void temp2mul (double temp, double green, double equal, double& rmul, double& gmul, double& bmul); + static void temp2mulxyz (double tem, double gree, std::string method, double &Xxyz, double &Zxyz); - bool operator== (const ColorTemp& other) { return fabs(temp-other.temp)<1e-10 && fabs(green-other.green)<1e-10; } - bool operator!= (const ColorTemp& other) { return !(*this==other); } + int XYZtoCorColorTemp(double x0, double y0 , double z0, double &temp); + static void cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00, double &CAM02BB01, double &CAM02BB02, double &CAM02BB10, double &CAM02BB11, double &CAM02BB12, double &CAM02BB20, double &CAM02BB21, double &CAM02BB22, double adap ); + //static void CAT02 (Imagefloat* baseImg, const ProcParams* params); + //static void ciecam_02 (LabImage* lab, const ProcParams* params); - static double blackbody_spect (double wavelength, double temperature); - static double daylight_spect (double wavelength, double m1, double m2); - static const double Cloudy6200_spect[97]; - static const double Daylight5300_spect[97]; - static const double Shade7600_spect[97]; - static const double A2856_spect[97]; - static const double FluoF1_spect[97]; - static const double FluoF2_spect[97]; - static const double FluoF3_spect[97]; - static const double FluoF4_spect[97]; - static const double FluoF5_spect[97]; - static const double FluoF6_spect[97]; - static const double FluoF7_spect[97]; - static const double FluoF8_spect[97]; - static const double FluoF9_spect[97]; - static const double FluoF10_spect[97]; - static const double FluoF11_spect[97]; - static const double FluoF12_spect[97]; - static const double HMI_spect[97]; - static const double GTI_spect[97]; - static const double JudgeIII_spect[97]; - static const double Solux3500_spect[97]; - static const double Solux4100_spect[97]; - static const double Solux4700_spect[97]; - static const double NG_Solux4700_spect[97]; - static const double NG_LEDLSI2040_spect[97]; - static const double NG_CRSSP12WWMR16_spect[97]; - static const double Flash5500_spect[97]; - static const double Flash6000_spect[97]; - static const double Flash6500_spect[97]; + bool operator== (const ColorTemp& other) + { + return fabs(temp - other.temp) < 1e-10 && fabs(green - other.green) < 1e-10; + } + bool operator!= (const ColorTemp& other) + { + return !(*this == other); + } - //spectral data 8 color Colorchecker24 - static double get_spectral_color (double wavelength, const double* array) { - int wlm = (int) ((wavelength -350.)/5.); - return (array[wlm]); - } + static double blackbody_spect (double wavelength, double temperature); + static double daylight_spect (double wavelength, double m1, double m2); + static const double Cloudy6200_spect[97]; + static const double Daylight5300_spect[97]; + static const double Shade7600_spect[97]; + static const double A2856_spect[97]; + static const double FluoF1_spect[97]; + static const double FluoF2_spect[97]; + static const double FluoF3_spect[97]; + static const double FluoF4_spect[97]; + static const double FluoF5_spect[97]; + static const double FluoF6_spect[97]; + static const double FluoF7_spect[97]; + static const double FluoF8_spect[97]; + static const double FluoF9_spect[97]; + static const double FluoF10_spect[97]; + static const double FluoF11_spect[97]; + static const double FluoF12_spect[97]; + static const double HMI_spect[97]; + static const double GTI_spect[97]; + static const double JudgeIII_spect[97]; + static const double Solux3500_spect[97]; + static const double Solux4100_spect[97]; + static const double Solux4700_spect[97]; + static const double NG_Solux4700_spect[97]; + static const double NG_LEDLSI2040_spect[97]; + static const double NG_CRSSP12WWMR16_spect[97]; + static const double Flash5500_spect[97]; + static const double Flash6000_spect[97]; + static const double Flash6500_spect[97]; - static const double ColorchechredC3_spect[97]; - static const double ColorchechOraA2_spect[97]; - static const double ColorchechYelD3_spect[97]; - static const double ColorchechGreE2_spect[97]; - static const double ColorchechGreB3_spect[97]; - static const double ColorchechCyaF3_spect[97]; - static const double ColorchechPurD2_spect[97]; - static const double ColorchechMagE3_spect[97]; - static const double ColorchechSkiA138_13_14_spect[97]; - static const double ColorchechGraC4_67_spect[97]; - static const double ColorchechSkiB166_18_18_spect[97]; - static const double ColorchechBluC150_m5_m22_spect[97]; - static const double ColorchechDCBluN881_m7_m14_spect[97];//ColorChecker DC N8 - static const double ColorchechSGSkiF763_14_26_spect[97];//ColorChecker SG F7 - static const double ColorchechSGSkiK285_11_17_spect[97];//ColorChecker SG K2 - static const double ColorchechWhiA496_spect[97]; - static const double ColorchechGreD1_spect[97]; - static const double ColorchechSGBlaN3_6_spect[97];//ColorChecker SG N3 - static const double JDC468_GraK14_44_spect[97];//468 K14 - static const double JDC468_BluH10_spect[97];//468 H10 - static const double ColabSkin35_15_17_spect[97];//Skin L 35 - static const double ColabSkin57_22_18_spect[97];//Skin L 57 - static const double ColabSkin40_17_17_spect[97];//Skin L 40 - static const double ColabSkin91_4_14_spect[97];//Skin L 91 - static const double ColabSkin87_8_8_spect[97];//Skin L 87 - static const double ColabSkin89_8_21_spect[97];//Skin L 89 - static const double ColabSkin75_8_4_spect[97];//Skin L 75 - static const double ColabSkin75_10_33_spect[97];//Skin L 75 - static const double ColabSkin65_33_11_spect[97];//Skin L 65 - static const double ColabSkin65_7_24_spect[97];//Skin L 65 - static const double ColabSkin57_19_6_spect[97];//Skin L 57 - static const double ColabSkin57_4_19_spect[97];//Skin L 57 - static const double ColabSkin57_10_28_spect[97];//Skin L 57 - static const double ColabSkin40_7_19_spect[97];//Skin L 57 - static const double ColabSkin40_17_6_spect[97];//Skin L 40 - static const double ColabSkin40_4_11_spect[97];//Skin L 40 - static const double ColabSkin33_6_15_spect[97];//Skin L 33 - static const double ColabSkin33_15_5_spect[97];//Skin L 33 - static const double ColabSkin33_10_15_spect[97];//Skin L 33 - static const double ColabSkin24_5_6_spect[97];//Skin L 24 - static const double ColabSkin26_18_18_spect[97];//Skin L 26 - static const double ColabSkin24_7_5_spect[97];//Skin L 24 - static const double ColabSkin20_4_2_spect[97];//Skin L 20 - static const double ColabSkin98_m2_10_spect[97];//Skin L 98 - static const double ColabSkin90_m1_20_spect[97];//Skin L 90 - static const double ColabSkin95_0_4_spect[97];//Skin L 95 - static const double ColabSkin81_2_14_spect[97];//Skin L 81 - static const double ColabSkin87_3_10_spect[97];//Skin L 87 - static const double ColabSkin77_12_21_spect[97];//Skin L 77 - static const double ColabSkin70_7_32_spect[97];//Skin L 77 - static const double ColabSky60_0_m31_spect[97];//Sky L=60 - static const double ColabSky42_0_m24_spect[97];//Sky L=42 + //spectral data 8 color Colorchecker24 + static double get_spectral_color (double wavelength, const double* array) + { + int wlm = (int) ((wavelength - 350.) / 5.); + return (array[wlm]); + } - static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z); - static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z); - static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z); + static const double ColorchechredC3_spect[97]; + static const double ColorchechOraA2_spect[97]; + static const double ColorchechYelD3_spect[97]; + static const double ColorchechGreE2_spect[97]; + static const double ColorchechGreB3_spect[97]; + static const double ColorchechCyaF3_spect[97]; + static const double ColorchechPurD2_spect[97]; + static const double ColorchechMagE3_spect[97]; + static const double ColorchechSkiA138_13_14_spect[97]; + static const double ColorchechGraC4_67_spect[97]; + static const double ColorchechSkiB166_18_18_spect[97]; + static const double ColorchechBluC150_m5_m22_spect[97]; + static const double ColorchechDCBluN881_m7_m14_spect[97];//ColorChecker DC N8 + static const double ColorchechSGSkiF763_14_26_spect[97];//ColorChecker SG F7 + static const double ColorchechSGSkiK285_11_17_spect[97];//ColorChecker SG K2 + static const double ColorchechWhiA496_spect[97]; + static const double ColorchechGreD1_spect[97]; + static const double ColorchechSGBlaN3_6_spect[97];//ColorChecker SG N3 + static const double JDC468_GraK14_44_spect[97];//468 K14 + static const double JDC468_BluH10_spect[97];//468 H10 + static const double ColabSkin35_15_17_spect[97];//Skin L 35 + static const double ColabSkin57_22_18_spect[97];//Skin L 57 + static const double ColabSkin40_17_17_spect[97];//Skin L 40 + static const double ColabSkin91_4_14_spect[97];//Skin L 91 + static const double ColabSkin87_8_8_spect[97];//Skin L 87 + static const double ColabSkin89_8_21_spect[97];//Skin L 89 + static const double ColabSkin75_8_4_spect[97];//Skin L 75 + static const double ColabSkin75_10_33_spect[97];//Skin L 75 + static const double ColabSkin65_33_11_spect[97];//Skin L 65 + static const double ColabSkin65_7_24_spect[97];//Skin L 65 + static const double ColabSkin57_19_6_spect[97];//Skin L 57 + static const double ColabSkin57_4_19_spect[97];//Skin L 57 + static const double ColabSkin57_10_28_spect[97];//Skin L 57 + static const double ColabSkin40_7_19_spect[97];//Skin L 57 + static const double ColabSkin40_17_6_spect[97];//Skin L 40 + static const double ColabSkin40_4_11_spect[97];//Skin L 40 + static const double ColabSkin33_6_15_spect[97];//Skin L 33 + static const double ColabSkin33_15_5_spect[97];//Skin L 33 + static const double ColabSkin33_10_15_spect[97];//Skin L 33 + static const double ColabSkin24_5_6_spect[97];//Skin L 24 + static const double ColabSkin26_18_18_spect[97];//Skin L 26 + static const double ColabSkin24_7_5_spect[97];//Skin L 24 + static const double ColabSkin20_4_2_spect[97];//Skin L 20 + static const double ColabSkin98_m2_10_spect[97];//Skin L 98 + static const double ColabSkin90_m1_20_spect[97];//Skin L 90 + static const double ColabSkin95_0_4_spect[97];//Skin L 95 + static const double ColabSkin81_2_14_spect[97];//Skin L 81 + static const double ColabSkin87_3_10_spect[97];//Skin L 87 + static const double ColabSkin77_12_21_spect[97];//Skin L 77 + static const double ColabSkin70_7_32_spect[97];//Skin L 77 + static const double ColabSky60_0_m31_spect[97];//Sky L=60 + static const double ColabSky42_0_m24_spect[97];//Sky L=42 + + static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z); + static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z); + static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z); + + static void spectrum_to_color_xyz_daylight (const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz); + static void spectrum_to_color_xyz_blackbody (const double* spec_color, double _temp, double &xx, double &yy, double &zz); + static void spectrum_to_color_xyz_preset (const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz); - static void spectrum_to_color_xyz_daylight (const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz); - static void spectrum_to_color_xyz_blackbody (const double* spec_color, double _temp, double &xx, double &yy, double &zz); - static void spectrum_to_color_xyz_preset (const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz); - }; } #endif diff --git a/rtengine/coord2d.h b/rtengine/coord2d.h index fb9fd1616..f896cd0d0 100644 --- a/rtengine/coord2d.h +++ b/rtengine/coord2d.h @@ -7,7 +7,7 @@ * 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 @@ -19,15 +19,21 @@ #ifndef __COORD2D__ #define __COORD2D__ -namespace rtengine { +namespace rtengine +{ -class Coord2D { +class Coord2D +{ - public: - double x, y; - Coord2D (double x_, double y_) : x(x_), y(y_) {} - Coord2D () {} - void set (double x_, double y_) { x = x_; y = y_; } +public: + double x, y; + Coord2D (double x_, double y_) : x(x_), y(y_) {} + Coord2D () {} + void set (double x_, double y_) + { + x = x_; + y = y_; + } }; } #endif diff --git a/rtengine/cplx_wavelet_dec.cc b/rtengine/cplx_wavelet_dec.cc index 44812d428..d9e72e6c5 100644 --- a/rtengine/cplx_wavelet_dec.cc +++ b/rtengine/cplx_wavelet_dec.cc @@ -5,7 +5,7 @@ * 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 @@ -20,19 +20,24 @@ #include "cplx_wavelet_dec.h" -namespace rtengine { - - wavelet_decomposition::~wavelet_decomposition() - { - for(int i = 0; i <= lvltot; i++) { - if(wavelet_decomp[i] != NULL) - delete wavelet_decomp[i]; - } - delete[] wavfilt_anal; - delete[] wavfilt_synth; - if(coeff0) - delete [] coeff0; - } +namespace rtengine +{ + +wavelet_decomposition::~wavelet_decomposition() +{ + for(int i = 0; i <= lvltot; i++) { + if(wavelet_decomp[i] != NULL) { + delete wavelet_decomp[i]; + } + } + + delete[] wavfilt_anal; + delete[] wavfilt_synth; + + if(coeff0) { + delete [] coeff0; + } +} }; diff --git a/rtengine/cplx_wavelet_dec.h b/rtengine/cplx_wavelet_dec.h index 1f7732afe..0ab01be57 100644 --- a/rtengine/cplx_wavelet_dec.h +++ b/rtengine/cplx_wavelet_dec.h @@ -5,7 +5,7 @@ * 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 @@ -27,218 +27,242 @@ #include "cplx_wavelet_level.h" #include "cplx_wavelet_filter_coeffs.h" -namespace rtengine { +namespace rtengine +{ - class wavelet_decomposition - { - public: +class wavelet_decomposition +{ +public: - typedef float internal_type; - float *coeff0; - bool memoryAllocationFailed; + typedef float internal_type; + float *coeff0; + bool memoryAllocationFailed; - private: +private: - static const int maxlevels = 10;//should be greater than any conceivable order of decimation + static const int maxlevels = 10;//should be greater than any conceivable order of decimation - int lvltot, subsamp; - int numThreads; - int m_w, m_h;//dimensions + int lvltot, subsamp; + int numThreads; + int m_w, m_h;//dimensions - int wavfilt_len, wavfilt_offset; - float *wavfilt_anal; - float *wavfilt_synth; + int wavfilt_len, wavfilt_offset; + float *wavfilt_anal; + float *wavfilt_synth; - wavelet_level * wavelet_decomp[maxlevels]; + wavelet_level * wavelet_decomp[maxlevels]; - public: +public: - template - wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop = 1, int numThreads = 1, int Daub4Len = 6); + template + wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop = 1, int numThreads = 1, int Daub4Len = 6); - ~wavelet_decomposition(); + ~wavelet_decomposition(); - internal_type ** level_coeffs(int level) const - { - return wavelet_decomp[level]->subbands(); - } + internal_type ** level_coeffs(int level) const + { + return wavelet_decomp[level]->subbands(); + } - int level_W(int level) const - { - return wavelet_decomp[level]->width(); - } + int level_W(int level) const + { + return wavelet_decomp[level]->width(); + } - int level_H(int level) const - { - return wavelet_decomp[level]->height(); - } + int level_H(int level) const + { + return wavelet_decomp[level]->height(); + } - int level_stride(int level) const - { - return wavelet_decomp[level]->stride(); - } + int level_stride(int level) const + { + return wavelet_decomp[level]->stride(); + } - int maxlevel() const - { - return lvltot+1; - } + int maxlevel() const + { + return lvltot + 1; + } - int subsample() const - { - return subsamp; - } - template - void reconstruct(E * dst, const float blend = 1.f); - }; + int subsample() const + { + return subsamp; + } + template + void reconstruct(E * dst, const float blend = 1.f); +}; - template - wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop, int numThreads, int Daub4Len) - : coeff0(NULL), memoryAllocationFailed(false), lvltot(0), subsamp(subsampling), numThreads(numThreads), m_w(width), m_h(height) - { +template +wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop, int numThreads, int Daub4Len) + : coeff0(NULL), memoryAllocationFailed(false), lvltot(0), subsamp(subsampling), numThreads(numThreads), m_w(width), m_h(height) +{ - //initialize wavelet filters - wavfilt_len = Daub4Len; - wavfilt_offset = Daub4_offset; - wavfilt_anal = new float[2*wavfilt_len]; - wavfilt_synth = new float[2*wavfilt_len]; + //initialize wavelet filters + wavfilt_len = Daub4Len; + wavfilt_offset = Daub4_offset; + wavfilt_anal = new float[2 * wavfilt_len]; + wavfilt_synth = new float[2 * wavfilt_len]; - if(wavfilt_len==6) { - for (int n=0; n<2; n++) { - for (int i=0; i(src, buffer[bufferindex^1], lvltot/*level*/, subsamp, m_w, m_h, \ - wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); - if(wavelet_decomp[lvltot]->memoryAllocationFailed) - memoryAllocationFailed = true; - while(lvltot < maxlvl-1) { - lvltot++; - bufferindex ^= 1; - wavelet_decomp[lvltot] = new wavelet_level(buffer[bufferindex], buffer[bufferindex^1]/*lopass*/, lvltot/*level*/, subsamp, \ - wavelet_decomp[lvltot-1]->width(), wavelet_decomp[lvltot-1]->height(), \ - wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); - if(wavelet_decomp[lvltot]->memoryAllocationFailed) - memoryAllocationFailed = true; - } - coeff0 = buffer[bufferindex^1]; - delete[] buffer[bufferindex]; - } - - template - void wavelet_decomposition::reconstruct(E * dst, const float blend) { + lvltot = 0; + E *buffer[2]; + buffer[0] = new (std::nothrow) E[(m_w / 2 + 1) * (m_h / 2 + 1)]; - if(memoryAllocationFailed) - return; - // data structure is wavcoeffs[scale][channel={lo,hi1,hi2,hi3}][pixel_array] + if(buffer[0] == NULL) { + memoryAllocationFailed = true; + return; + } - if(lvltot >= 1) { - int width = wavelet_decomp[1]->m_w; - int height = wavelet_decomp[1]->m_h; + buffer[1] = new (std::nothrow) E[(m_w / 2 + 1) * (m_h / 2 + 1)]; - E *tmpHi = new (std::nothrow) E[width*height]; - if(tmpHi == NULL) { - memoryAllocationFailed = true; - return; - } + if(buffer[1] == NULL) { + memoryAllocationFailed = true; + delete[] buffer[0]; + buffer[0] = NULL; + return; + } - for (int lvl=lvltot; lvl>0; lvl--) { - E *tmpLo = wavelet_decomp[lvl]->wavcoeffs[2]; // we can use this as buffer - wavelet_decomp[lvl]->reconstruct_level(tmpLo, tmpHi, coeff0, coeff0, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); - delete wavelet_decomp[lvl]; - wavelet_decomp[lvl] = NULL; - } - delete[] tmpHi; - } + int bufferindex = 0; - int width = wavelet_decomp[0]->m_w; - int height = wavelet_decomp[0]->m_h2; - E *tmpLo; - if(wavelet_decomp[0]->bigBlockOfMemoryUsed()) // bigBlockOfMemoryUsed means that wavcoeffs[2] points to a block of memory big enough to hold the data - tmpLo = wavelet_decomp[0]->wavcoeffs[2]; - else { // allocate new block of memory - tmpLo = new (std::nothrow) E[width*height]; - if(tmpLo == NULL) { - memoryAllocationFailed = true; - return; - } - } - E *tmpHi = new (std::nothrow) E[width*height]; - if(tmpHi == NULL) { - memoryAllocationFailed = true; - if(!wavelet_decomp[0]->bigBlockOfMemoryUsed()) - delete[] tmpLo; - return; - } + wavelet_decomp[lvltot] = new wavelet_level(src, buffer[bufferindex ^ 1], lvltot/*level*/, subsamp, m_w, m_h, \ + wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); + + if(wavelet_decomp[lvltot]->memoryAllocationFailed) { + memoryAllocationFailed = true; + } + + while(lvltot < maxlvl - 1) { + lvltot++; + bufferindex ^= 1; + wavelet_decomp[lvltot] = new wavelet_level(buffer[bufferindex], buffer[bufferindex ^ 1]/*lopass*/, lvltot/*level*/, subsamp, \ + wavelet_decomp[lvltot - 1]->width(), wavelet_decomp[lvltot - 1]->height(), \ + wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); + + if(wavelet_decomp[lvltot]->memoryAllocationFailed) { + memoryAllocationFailed = true; + } + } + + coeff0 = buffer[bufferindex ^ 1]; + delete[] buffer[bufferindex]; +} + +template +void wavelet_decomposition::reconstruct(E * dst, const float blend) +{ + + if(memoryAllocationFailed) { + return; + } + + // data structure is wavcoeffs[scale][channel={lo,hi1,hi2,hi3}][pixel_array] + + if(lvltot >= 1) { + int width = wavelet_decomp[1]->m_w; + int height = wavelet_decomp[1]->m_h; + + E *tmpHi = new (std::nothrow) E[width * height]; + + if(tmpHi == NULL) { + memoryAllocationFailed = true; + return; + } + + for (int lvl = lvltot; lvl > 0; lvl--) { + E *tmpLo = wavelet_decomp[lvl]->wavcoeffs[2]; // we can use this as buffer + wavelet_decomp[lvl]->reconstruct_level(tmpLo, tmpHi, coeff0, coeff0, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); + delete wavelet_decomp[lvl]; + wavelet_decomp[lvl] = NULL; + } + + delete[] tmpHi; + } + + int width = wavelet_decomp[0]->m_w; + int height = wavelet_decomp[0]->m_h2; + E *tmpLo; + + if(wavelet_decomp[0]->bigBlockOfMemoryUsed()) { // bigBlockOfMemoryUsed means that wavcoeffs[2] points to a block of memory big enough to hold the data + tmpLo = wavelet_decomp[0]->wavcoeffs[2]; + } else { // allocate new block of memory + tmpLo = new (std::nothrow) E[width * height]; + + if(tmpLo == NULL) { + memoryAllocationFailed = true; + return; + } + } + + E *tmpHi = new (std::nothrow) E[width * height]; + + if(tmpHi == NULL) { + memoryAllocationFailed = true; + + if(!wavelet_decomp[0]->bigBlockOfMemoryUsed()) { + delete[] tmpLo; + } + + return; + } - wavelet_decomp[0]->reconstruct_level(tmpLo, tmpHi, coeff0, dst, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset, blend); - if(!wavelet_decomp[0]->bigBlockOfMemoryUsed()) - delete[] tmpLo; - delete[] tmpHi; - delete wavelet_decomp[0]; - wavelet_decomp[0] = NULL; - delete[] coeff0; - coeff0 = NULL; - } + wavelet_decomp[0]->reconstruct_level(tmpLo, tmpHi, coeff0, dst, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset, blend); + + if(!wavelet_decomp[0]->bigBlockOfMemoryUsed()) { + delete[] tmpLo; + } + + delete[] tmpHi; + delete wavelet_decomp[0]; + wavelet_decomp[0] = NULL; + delete[] coeff0; + coeff0 = NULL; +} }; diff --git a/rtengine/cplx_wavelet_filter_coeffs.h b/rtengine/cplx_wavelet_filter_coeffs.h index 3874ba54b..ff22c9812 100644 --- a/rtengine/cplx_wavelet_filter_coeffs.h +++ b/rtengine/cplx_wavelet_filter_coeffs.h @@ -5,7 +5,7 @@ * 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 @@ -19,30 +19,36 @@ */ -namespace rtengine { +namespace rtengine +{ -const int Daub4_offset=2; +const int Daub4_offset = 2; const float Daub4_anal0[2][4] ALIGNED16 = {//analysis filter 2 Hall - {0.f, 0.f, 0.5f, 0.5f}, - {-0.5f, 0.5f, 0.f, 0.f}}; - -const float Daub4_anal[2][6] ALIGNED16 = {//Daub4 - {0.f, 0.f, 0.34150635f, 0.59150635f, 0.15849365f, -0.091506351f}, - {-0.091506351f, -0.15849365f, 0.59150635f, -0.34150635f, 0.f, 0.f}}; - -const float Daub4_anal8[2][8] ALIGNED16 = {//Daub6 - {0.f, 0.f, 0.235233605f, 0.57055846f, 0.3251825f, -0.09546721f, -0.060416105f, 0.02490875f}, - {-0.02490875f, -0.060416105f, 0.09546721f, 0.3251825f, -0.57055846f , 0.235233605f, 0.f, 0.f}}; - -const float Daub4_anal12[2][12] ALIGNED16 = {//Daub10 - {0.f, 0.f, 0.11320949f, 0.42697177f, 0.51216347f, 0.09788348f, -0.171328355f, -0.022800565f, 0.054851325f, -0.0044134f, -0.008895935f, 0.002358714f}, - {-0.002358714f, -0.008895935f, 0.0044134f, 0.054851325f, 0.022800565f , -0.171328355f, -0.09788348f, 0.51216347f, -0.42697177f, 0.11320949f, 0.f, 0.f}}; - -const float Daub4_anal16[2][16] ALIGNED16 = {//Daub 14 - {0.f, 0.f, 0.055049715f, 0.28039564f, 0.515574245f, 0.33218624f, -0.10175691f, -0.158417505f, 0.05042335f, 0.057001725f, -0.026891225f, -0.01171997f, 0.008874895f, 0.0003037575f, -0.0012739524f, 0.0002501134f}, - {-0.0002501134f, -0.0012739524f, -0.0003037575f, 0.008874895f, 0.01171997f , -0.026891225f, -0.057001725f, 0.05042335f, 0.158417505f, -0.10175691f, -0.33218624f, 0.515574245f, -0.28039564f, 0.055049715f, 0.f, 0.f}}; - -// if necessary ?? we can add D20 !! + {0.f, 0.f, 0.5f, 0.5f}, + { -0.5f, 0.5f, 0.f, 0.f} +}; + +const float Daub4_anal[2][6] ALIGNED16 = {//Daub4 + {0.f, 0.f, 0.34150635f, 0.59150635f, 0.15849365f, -0.091506351f}, + { -0.091506351f, -0.15849365f, 0.59150635f, -0.34150635f, 0.f, 0.f} +}; + +const float Daub4_anal8[2][8] ALIGNED16 = {//Daub6 + {0.f, 0.f, 0.235233605f, 0.57055846f, 0.3251825f, -0.09546721f, -0.060416105f, 0.02490875f}, + { -0.02490875f, -0.060416105f, 0.09546721f, 0.3251825f, -0.57055846f , 0.235233605f, 0.f, 0.f} +}; + +const float Daub4_anal12[2][12] ALIGNED16 = {//Daub10 + {0.f, 0.f, 0.11320949f, 0.42697177f, 0.51216347f, 0.09788348f, -0.171328355f, -0.022800565f, 0.054851325f, -0.0044134f, -0.008895935f, 0.002358714f}, + { -0.002358714f, -0.008895935f, 0.0044134f, 0.054851325f, 0.022800565f , -0.171328355f, -0.09788348f, 0.51216347f, -0.42697177f, 0.11320949f, 0.f, 0.f} +}; + +const float Daub4_anal16[2][16] ALIGNED16 = {//Daub 14 + {0.f, 0.f, 0.055049715f, 0.28039564f, 0.515574245f, 0.33218624f, -0.10175691f, -0.158417505f, 0.05042335f, 0.057001725f, -0.026891225f, -0.01171997f, 0.008874895f, 0.0003037575f, -0.0012739524f, 0.0002501134f}, + { -0.0002501134f, -0.0012739524f, -0.0003037575f, 0.008874895f, 0.01171997f , -0.026891225f, -0.057001725f, 0.05042335f, 0.158417505f, -0.10175691f, -0.33218624f, 0.515574245f, -0.28039564f, 0.055049715f, 0.f, 0.f} +}; + +// if necessary ?? we can add D20 !! }; diff --git a/rtengine/cplx_wavelet_level.h b/rtengine/cplx_wavelet_level.h index 862ba3552..cbdb5a481 100644 --- a/rtengine/cplx_wavelet_level.h +++ b/rtengine/cplx_wavelet_level.h @@ -5,7 +5,7 @@ * 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 @@ -26,628 +26,737 @@ #include "rt_math.h" #include "opthelper.h" #include "stdio.h" -namespace rtengine { - - template - class wavelet_level - { - - // level of decomposition - int lvl; - - // whether to subsample the output - bool subsamp_out; - - int numThreads; - - // spacing of filter taps - int skip; - - bool bigBlockOfMemory; - // allocation and destruction of data storage - T ** create(int n); - void destroy(T ** subbands); - - // load a row/column of input data, possibly with padding - - void AnalysisFilterHaarVertical (const T * const srcbuffer, T * dstLo, T * dstHi, const int width, const int height, const int row); - void AnalysisFilterHaarHorizontal (const T * const srcbuffer, T * dstLo, T * dstHi, const int width, const int row); - void SynthesisFilterHaarHorizontal (const T * const srcLo, const T * const srcHi, T * dst, const int width, const int height); - void SynthesisFilterHaarVertical (const T * const srcLo, const T * const srcHi, T * dst, const int width, const int height); - - void AnalysisFilterSubsampHorizontal (T * srcbuffer, T * dstLo, T * dstHi, float *filterLo, float *filterHi, - const int taps, const int offset, const int srcwidth, const int dstwidth, const int row); -#ifdef __SSE2__ - void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float (*filterLo)[4], float (*filterHi)[4], - const int taps, const int offset, const int width, const int height, const int row); -#else - void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float *filterLo, float *filterHi, - int const taps, const int offset, const int width, const int height, const int row); -#endif - void SynthesisFilterSubsampHorizontal (T * srcLo, T * srcHi, T * dst, - float *filterLo, float *filterHi, const int taps, const int offset, const int scrwidth, const int dstwidth, const int height); -#ifdef __SSE2__ - void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float (*filterLo)[4], float (*filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend); -#else - void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float *filterLo, float *filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend); -#endif - public: - bool memoryAllocationFailed; - - T ** wavcoeffs; - // full size - int m_w, m_h; - - // size of low frequency part - int m_w2, m_h2; - - template - wavelet_level(E * src, E * dst, int level, int subsamp, int w, int h, float *filterV, float *filterH, int len, int offset, int skipcrop, int numThreads) - : lvl(level), subsamp_out((subsamp>>level)&1), numThreads(numThreads), skip(1<>n)&1); - } - skip /= skipcrop; - if(skip < 1) skip=1; - - } - m_w2 = (subsamp_out ? (w+1)/2 : w); - m_h2 = (subsamp_out ? (h+1)/2 : h); - - wavcoeffs = create((m_w2)*(m_h2)); - if(!memoryAllocationFailed) - decompose_level(src, dst, filterV, filterH, len, offset); - - } - - ~wavelet_level() { - destroy(wavcoeffs); - } - - T ** subbands() const { - return wavcoeffs; - } - - T * lopass() const { - return wavcoeffs[0]; - } - - int width() const { - return m_w2; - } - - int height() const { - return m_h2; - } - - int stride() const { - return skip; - } - - bool bigBlockOfMemoryUsed() const { - return bigBlockOfMemory; - } - - template - void decompose_level(E *src, E *dst, float *filterV, float *filterH, int len, int offset); - - template - void reconstruct_level(E* tmpLo, E* tmpHi, E *src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend = 1.f); - }; - - template - T ** wavelet_level::create(int n) { - T * data = new (std::nothrow) T[3*n]; - if(data == NULL) { - bigBlockOfMemory = false; - } - T ** subbands = new T*[4]; - for(int j = 1; j < 4; j++) { - if(bigBlockOfMemory) - subbands[j] = data + n * (j-1); - else { - subbands[j] = new (std::nothrow) T[n]; - if(subbands[j] == NULL) { - printf("Couldn't allocate memory in level %d of wavelet\n",lvl); - memoryAllocationFailed = true; - } - } - } - return subbands; - } - - template - void wavelet_level::destroy(T ** subbands) { - if(subbands) { - if(bigBlockOfMemory) - delete[] subbands[1]; - else { - for(int j = 1; j < 4; j++) { - if(subbands[j] != NULL) - delete[] subbands[j]; - } - } - delete[] subbands; - } - } - - template - void wavelet_level::AnalysisFilterHaarHorizontal (const T * const RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, const int width, const int row) { - /* Basic convolution code - * Applies a Haar filter - */ - for(int i = 0; i < (width - skip); i++) { - dstLo[row*width+i] = (srcbuffer[i] + srcbuffer[i+skip]); - dstHi[row*width+i] = (srcbuffer[i] - srcbuffer[i+skip]); - } - for(int i = max(width-skip,skip); i < (width); i++) { - dstLo[row*width+i] = (srcbuffer[i] + srcbuffer[i-skip]); - dstHi[row*width+i] = (srcbuffer[i] - srcbuffer[i-skip]); - } - } - - template void wavelet_level::AnalysisFilterHaarVertical (const T * const RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, const int width, const int height, const int row) { - /* Basic convolution code - * Applies a Haar filter - */ - if(row < (height - skip)) { - for(int j=0;j=max(height-skip,skip)) { - for(int j=0;j void wavelet_level::SynthesisFilterHaarHorizontal (const T * const RESTRICT srcLo, const T * const RESTRICT srcHi, T * RESTRICT dst, const int width, const int height) { - - /* Basic convolution code - * Applies a Haar filter - * - */ -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif - for (int k=0; k void wavelet_level::SynthesisFilterHaarVertical (const T * const RESTRICT srcLo, const T * const RESTRICT srcHi, T * RESTRICT dst, const int width, const int height) { - - /* Basic convolution code - * Applies a Haar filter - * - */ -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(numThreads) if(numThreads>1) -#endif +namespace rtengine { -#ifdef _RT_NESTED_OPENMP -#pragma omp for nowait -#endif - for(int i = 0; i < skip; i++) { - for(int j=0;j - void wavelet_level::AnalysisFilterSubsampHorizontal (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float * RESTRICT filterLo, float *RESTRICT filterHi, - const int taps, const int offset, const int srcwidth, const int dstwidth, const int row) { - /* Basic convolution code - * Applies an FIR filter 'filter' with filter length 'taps', - * aligning the 'offset' element of the filter with - * the input pixel, and skipping 'skip' pixels between taps - * Output is subsampled by two - */ - // calculate coefficients - for(int i = 0; i < srcwidth; i+=2) { - float lo = 0.f, hi = 0.f; - if (LIKELY(i>skip*taps && i SSEFUNCTION void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], - const int taps, const int offset, const int width, const int height, const int row) { - - /* Basic convolution code - * Applies an FIR filter 'filter' with filter length 'taps', - * aligning the 'offset' element of the filter with - * the input pixel, and skipping 'skip' pixels between taps - * Output is subsampled by two - */ - - // calculate coefficients - if (LIKELY(row>skip*taps && row void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float * RESTRICT filterLo, float * RESTRICT filterHi, - const int taps, const int offset, const int width, const int height, const int row) { - - /* Basic convolution code - * Applies an FIR filter 'filter' with filter length 'taps', - * aligning the 'offset' element of the filter with - * the input pixel, and skipping 'skip' pixels between taps - * Output is subsampled by two - */ - - // calculate coefficients - if (LIKELY(row>skip*taps && row void wavelet_level::SynthesisFilterSubsampHorizontal (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int srcwidth, const int dstwidth, const int height) { - - /* Basic convolution code - * Applies an FIR filter 'filter' with filter length 'taps', - * aligning the 'offset' element of the filter with - * the input pixel, and skipping 'skip' pixels between taps - * Output is subsampled by two - */ - - // calculate coefficients - int shift = skip*(taps-offset-1);//align filter with data -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif - for (int k=0; k SSEFUNCTION void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend) - { - - /* Basic convolution code - * Applies an FIR filter 'filter' with filter length 'taps', - * aligning the 'offset' element of the filter with - * the input pixel, and skipping 'skip' pixels between taps - * Output is subsampled by two - */ - const float srcFactor = 1.f - blend; - // calculate coefficients - int shift=skip*(taps-offset-1);//align filter with data - __m128 fourv = _mm_set1_ps(4.f); - __m128 srcFactorv = _mm_set1_ps(srcFactor); - __m128 dstFactorv = _mm_set1_ps(blend); -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif - for(int i = 0; i < dstheight; i++) { - int i_src = (i+shift)/2; - int begin = (i+shift)%2; - //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' - if (LIKELY(i>skip*taps && i<(dstheight-skip*taps))) {//bulk - int k; - for (k=0; k void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend) - { - - /* Basic convolution code - * Applies an FIR filter 'filter' with filter length 'taps', - * aligning the 'offset' element of the filter with - * the input pixel, and skipping 'skip' pixels between taps - * Output is subsampled by two - */ - - const float srcFactor = 1.f - blend; - // calculate coefficients - int shift=skip*(taps-offset-1);//align filter with data - -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif - for(int i = 0; i < dstheight; i++) { - int i_src = (i+shift)/2; - int begin = (i+shift)%2; - //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' - if (LIKELY(i>skip*taps && i<(dstheight-skip*taps))) {//bulk - for (int k=0; k template SSEFUNCTION void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) { - - /* filter along rows and columns */ - float filterVarray[2*taps][4] ALIGNED64; - if(subsamp_out) { - for(int i=0;i<2*taps;i++) { - for(int j=0;j<4;j++) { - filterVarray[i][j] = filterV[i]; - } - } - } -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(numThreads) if(numThreads>1) -#endif +template +class wavelet_level { - T tmpLo[m_w] ALIGNED64; - T tmpHi[m_w] ALIGNED64; - if(subsamp_out) { -#ifdef _RT_NESTED_OPENMP -#pragma omp for -#endif - for(int row=0;row template void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) { + void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float *filterLo, float *filterHi, + int const taps, const int offset, const int width, const int height, const int row); +#endif + void SynthesisFilterSubsampHorizontal (T * srcLo, T * srcHi, T * dst, + float *filterLo, float *filterHi, const int taps, const int offset, const int scrwidth, const int dstwidth, const int height); +#ifdef __SSE2__ + void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float (*filterLo)[4], float (*filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend); +#else + void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float *filterLo, float *filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend); +#endif +public: + bool memoryAllocationFailed; + + T ** wavcoeffs; + // full size + int m_w, m_h; + + // size of low frequency part + int m_w2, m_h2; + + template + wavelet_level(E * src, E * dst, int level, int subsamp, int w, int h, float *filterV, float *filterH, int len, int offset, int skipcrop, int numThreads) + : lvl(level), subsamp_out((subsamp >> level) & 1), numThreads(numThreads), skip(1 << level), bigBlockOfMemory(true), memoryAllocationFailed(false), wavcoeffs(NULL), m_w(w), m_h(h), m_w2(w), m_h2(h) + { + if (subsamp) { + skip = 1; + + for (int n = 0; n < level; n++) { + skip *= 2 - ((subsamp >> n) & 1); + } + + skip /= skipcrop; + + if(skip < 1) { + skip = 1; + } + + } + + m_w2 = (subsamp_out ? (w + 1) / 2 : w); + m_h2 = (subsamp_out ? (h + 1) / 2 : h); + + wavcoeffs = create((m_w2) * (m_h2)); + + if(!memoryAllocationFailed) { + decompose_level(src, dst, filterV, filterH, len, offset); + } + + } + + ~wavelet_level() + { + destroy(wavcoeffs); + } + + T ** subbands() const + { + return wavcoeffs; + } + + T * lopass() const + { + return wavcoeffs[0]; + } + + int width() const + { + return m_w2; + } + + int height() const + { + return m_h2; + } + + int stride() const + { + return skip; + } + + bool bigBlockOfMemoryUsed() const + { + return bigBlockOfMemory; + } + + template + void decompose_level(E *src, E *dst, float *filterV, float *filterH, int len, int offset); + + template + void reconstruct_level(E* tmpLo, E* tmpHi, E *src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend = 1.f); +}; + +template +T ** wavelet_level::create(int n) +{ + T * data = new (std::nothrow) T[3 * n]; + + if(data == NULL) { + bigBlockOfMemory = false; + } + + T ** subbands = new T*[4]; + + for(int j = 1; j < 4; j++) { + if(bigBlockOfMemory) { + subbands[j] = data + n * (j - 1); + } else { + subbands[j] = new (std::nothrow) T[n]; + + if(subbands[j] == NULL) { + printf("Couldn't allocate memory in level %d of wavelet\n", lvl); + memoryAllocationFailed = true; + } + } + } + + return subbands; +} + +template +void wavelet_level::destroy(T ** subbands) +{ + if(subbands) { + if(bigBlockOfMemory) { + delete[] subbands[1]; + } else { + for(int j = 1; j < 4; j++) { + if(subbands[j] != NULL) { + delete[] subbands[j]; + } + } + } + + delete[] subbands; + } +} + +template +void wavelet_level::AnalysisFilterHaarHorizontal (const T * const RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, const int width, const int row) +{ + /* Basic convolution code + * Applies a Haar filter + */ + for(int i = 0; i < (width - skip); i++) { + dstLo[row * width + i] = (srcbuffer[i] + srcbuffer[i + skip]); + dstHi[row * width + i] = (srcbuffer[i] - srcbuffer[i + skip]); + } + + for(int i = max(width - skip, skip); i < (width); i++) { + dstLo[row * width + i] = (srcbuffer[i] + srcbuffer[i - skip]); + dstHi[row * width + i] = (srcbuffer[i] - srcbuffer[i - skip]); + } +} + +template void wavelet_level::AnalysisFilterHaarVertical (const T * const RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, const int width, const int height, const int row) +{ + /* Basic convolution code + * Applies a Haar filter + */ + if(row < (height - skip)) { + for(int j = 0; j < width; j++) { + dstLo[j] = 0.25f * (srcbuffer[row * width + j] + srcbuffer[(row + skip) * width + j]); + dstHi[j] = 0.25f * (srcbuffer[row * width + j] - srcbuffer[(row + skip) * width + j]); + } + } else if(row >= max(height - skip, skip)) { + for(int j = 0; j < width; j++) { + dstLo[j] = 0.25f * (srcbuffer[row * width + j] + srcbuffer[(row - skip) * width + j]); + dstHi[j] = 0.25f * (srcbuffer[row * width + j] - srcbuffer[(row - skip) * width + j]); + } + } +} + +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +template void wavelet_level::SynthesisFilterHaarHorizontal (const T * const RESTRICT srcLo, const T * const RESTRICT srcHi, T * RESTRICT dst, const int width, const int height) +{ + + /* Basic convolution code + * Applies a Haar filter + * + */ +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(numThreads) if(numThreads>1) +#endif + + for (int k = 0; k < height; k++) { + for(int i = 0; i < skip; i++) { + dst[k * width + i] = (srcLo[k * width + i] + srcHi[k * width + i]); + } + + for(int i = skip; i < width; i++) { + dst[k * width + i] = 0.5f * (srcLo[k * width + i] + srcHi[k * width + i] + srcLo[k * width + i - skip] - srcHi[k * width + i - skip]); + } + } +} + +template void wavelet_level::SynthesisFilterHaarVertical (const T * const RESTRICT srcLo, const T * const RESTRICT srcHi, T * RESTRICT dst, const int width, const int height) +{ + + /* Basic convolution code + * Applies a Haar filter + * + */ +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(numThreads) if(numThreads>1) +#endif + { +#ifdef _RT_NESTED_OPENMP + #pragma omp for nowait +#endif + + for(int i = 0; i < skip; i++) + { + for(int j = 0; j < width; j++) { + dst[width * i + j] = (srcLo[i * width + j] + srcHi[i * width + j]); + } + } #ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(numThreads) if(numThreads>1) + #pragma omp for #endif -{ - T tmpLo[m_w] ALIGNED64; - T tmpHi[m_w] ALIGNED64; - /* filter along rows and columns */ - if(subsamp_out) { -#ifdef _RT_NESTED_OPENMP -#pragma omp for -#endif - for(int row=0;row +void wavelet_level::AnalysisFilterSubsampHorizontal (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float * RESTRICT filterLo, float *RESTRICT filterHi, + const int taps, const int offset, const int srcwidth, const int dstwidth, const int row) +{ + /* Basic convolution code + * Applies an FIR filter 'filter' with filter length 'taps', + * aligning the 'offset' element of the filter with + * the input pixel, and skipping 'skip' pixels between taps + * Output is subsampled by two + */ + // calculate coefficients + for(int i = 0; i < srcwidth; i += 2) { + float lo = 0.f, hi = 0.f; + + if (LIKELY(i > skip * taps && i < srcwidth - skip * taps)) { //bulk + for (int j = 0, l = -skip * offset; j < taps; j++, l += skip) { + float src = srcbuffer[i - l]; + lo += filterLo[j] * src;//lopass channel + hi += filterHi[j] * src;//hipass channel + } + } else { + for (int j = 0; j < taps; j++) { + int arg = max(0, min(i + skip * (offset - j), srcwidth - 1)); //clamped BC's + lo += filterLo[j] * srcbuffer[arg];//lopass channel + hi += filterHi[j] * srcbuffer[arg];//hipass channel + } + } + + dstLo[row * dstwidth + ((i / 2))] = lo; + dstHi[row * dstwidth + ((i / 2))] = hi; + } +} + +#ifdef __SSE2__ +template SSEFUNCTION void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], + const int taps, const int offset, const int width, const int height, const int row) +{ + + /* Basic convolution code + * Applies an FIR filter 'filter' with filter length 'taps', + * aligning the 'offset' element of the filter with + * the input pixel, and skipping 'skip' pixels between taps + * Output is subsampled by two + */ + + // calculate coefficients + if (LIKELY(row > skip * taps && row < height - skip * taps)) { //bulk + int k; + + for (k = 0; k < width - 3; k += 4) { + __m128 lov = _mm_setzero_ps(); + __m128 hiv = _mm_setzero_ps(); + + for (int j = 0, l = -skip * offset; j < taps; j++, l += skip) { + __m128 srcv = LVFU(srcbuffer[(row - l) * width + k]); + lov += LVF(filterLo[j][0]) * srcv;//lopass channel + hiv += LVF(filterHi[j][0]) * srcv;//hipass channel + } + + STVF(dstLo[k], lov); + STVF(dstHi[k], hiv); + } + + for (; k < width; k++) { + float lo = 0.f, hi = 0.f; + + for (int j = 0, l = -skip * offset; j < taps; j++, l += skip) { + lo += filterLo[j][0] * srcbuffer[(row - l) * width + k]; //lopass channel + hi += filterHi[j][0] * srcbuffer[(row - l) * width + k]; //hipass channel + } + + dstLo[k] = lo; + dstHi[k] = hi; + } + } else {//boundary + int k; + + for (k = 0; k < width - 3; k += 4) { + __m128 lov = _mm_setzero_ps(); + __m128 hiv = _mm_setzero_ps(); + + for (int j = 0; j < taps; j++) { + int arg = max(0, min(row + skip * (offset - j), height - 1)) * width + k; //clamped BC's + __m128 srcv = LVFU(srcbuffer[arg]); + lov += LVF(filterLo[j][0]) * srcv;//lopass channel + hiv += LVF(filterHi[j][0]) * srcv;//hipass channel + } + + STVF(dstLo[k], lov); + STVF(dstHi[k], hiv); + } + + for (; k < width; k++) { + float lo = 0.f, hi = 0.f; + + for (int j = 0; j < taps; j++) { + int arg = max(0, min(row + skip * (offset - j), height - 1)) * width + k; //clamped BC's + lo += filterLo[j][0] * srcbuffer[arg];//lopass channel + hi += filterHi[j][0] * srcbuffer[arg];//hipass channel + } + + dstLo[k] = lo; + dstHi[k] = hi; + } + } +} +#else +template void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float * RESTRICT filterLo, float * RESTRICT filterHi, + const int taps, const int offset, const int width, const int height, const int row) +{ + + /* Basic convolution code + * Applies an FIR filter 'filter' with filter length 'taps', + * aligning the 'offset' element of the filter with + * the input pixel, and skipping 'skip' pixels between taps + * Output is subsampled by two + */ + + // calculate coefficients + if (LIKELY(row > skip * taps && row < height - skip * taps)) { //bulk + for (int k = 0; k < width; k++) { + float lo = 0.f, hi = 0.f; + + for (int j = 0, l = -skip * offset; j < taps; j++, l += skip) { + lo += filterLo[j] * srcbuffer[(row - l) * width + k]; //lopass channel + hi += filterHi[j] * srcbuffer[(row - l) * width + k]; //hipass channel + } + + dstLo[k] = lo; + dstHi[k] = hi; + } + } else {//boundary + for (int k = 0; k < width; k++) { + float lo = 0.f, hi = 0.f; + + for (int j = 0; j < taps; j++) { + int arg = max(0, min(row + skip * (offset - j), height - 1)) * width + k; //clamped BC's + lo += filterLo[j] * srcbuffer[arg];//lopass channel + hi += filterHi[j] * srcbuffer[arg];//hipass channel + } + + dstLo[k] = lo; + dstHi[k] = hi; + } + } +} +#endif + + +template void wavelet_level::SynthesisFilterSubsampHorizontal (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int srcwidth, const int dstwidth, const int height) +{ + + /* Basic convolution code + * Applies an FIR filter 'filter' with filter length 'taps', + * aligning the 'offset' element of the filter with + * the input pixel, and skipping 'skip' pixels between taps + * Output is subsampled by two + */ + + // calculate coefficients + int shift = skip * (taps - offset - 1); //align filter with data +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(numThreads) if(numThreads>1) +#endif + + for (int k = 0; k < height; k++) { + int i; + + for(i = 0; i <= min(skip * taps, dstwidth); i++) { + float tot = 0.f; + //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' + int i_src = (i + shift) / 2; + int begin = (i + shift) % 2; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + int arg = max(0, min((i_src - l), srcwidth - 1)); //clamped BC's + tot += ((filterLo[j] * srcLo[k * srcwidth + arg] + filterHi[j] * srcHi[k * srcwidth + arg])); + } + + dst[k * dstwidth + i] = tot; + } + + for(; i < min(dstwidth - skip * taps, dstwidth); i++) { + float tot = 0.f; + //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' + int i_src = (i + shift) / 2; + int begin = (i + shift) % 2; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + tot += ((filterLo[j] * srcLo[k * srcwidth + i_src - l] + filterHi[j] * srcHi[k * srcwidth + i_src - l])); + } + + dst[k * dstwidth + i] = tot; + } + + for(; i < dstwidth; i++) { + float tot = 0.f; + //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' + int i_src = (i + shift) / 2; + int begin = (i + shift) % 2; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + int arg = max(0, min((i_src - l), srcwidth - 1)); //clamped BC's + tot += ((filterLo[j] * srcLo[k * srcwidth + arg] + filterHi[j] * srcHi[k * srcwidth + arg])); + } + + dst[k * dstwidth + i] = tot; + } + } +} + +#ifdef __SSE2__ +template SSEFUNCTION void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend) +{ + + /* Basic convolution code + * Applies an FIR filter 'filter' with filter length 'taps', + * aligning the 'offset' element of the filter with + * the input pixel, and skipping 'skip' pixels between taps + * Output is subsampled by two + */ + const float srcFactor = 1.f - blend; + // calculate coefficients + int shift = skip * (taps - offset - 1); //align filter with data + __m128 fourv = _mm_set1_ps(4.f); + __m128 srcFactorv = _mm_set1_ps(srcFactor); + __m128 dstFactorv = _mm_set1_ps(blend); +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(numThreads) if(numThreads>1) +#endif + + for(int i = 0; i < dstheight; i++) { + int i_src = (i + shift) / 2; + int begin = (i + shift) % 2; + + //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' + if (LIKELY(i > skip * taps && i < (dstheight - skip * taps))) { //bulk + int k; + + for (k = 0; k < width - 3; k += 4) { + __m128 totv = _mm_setzero_ps(); + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + totv += ((LVF(filterLo[j][0]) * LVFU(srcLo[(i_src - l) * width + k]) + LVF(filterHi[j][0]) * LVFU(srcHi[(i_src - l) * width + k]))); + } + + _mm_storeu_ps(&dst[width * i + k], LVFU(dst[width * i + k]) * srcFactorv + dstFactorv * fourv * totv); + } + + for (; k < width; k++) { + float tot = 0.f; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + tot += ((filterLo[j][0] * srcLo[(i_src - l) * width + k] + filterHi[j][0] * srcHi[(i_src - l) * width + k])); + } + + dst[width * i + k] = dst[width * i + k] * srcFactor + blend * 4.f * tot; + } + } else {//boundary + int k; + + for (k = 0; k < width - 3; k += 4) { + __m128 totv = _mm_setzero_ps(); + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + int arg = max(0, min((i_src - l), srcheight - 1)) * width + k; //clamped BC's + totv += ((LVF(filterLo[j][0]) * LVFU(srcLo[arg]) + LVF(filterHi[j][0]) * LVFU(srcHi[arg]))); + } + + _mm_storeu_ps(&dst[width * i + k], LVFU(dst[width * i + k]) * srcFactorv + dstFactorv * fourv * totv); + } + + for (; k < width; k++) { + float tot = 0.f; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + int arg = max(0, min((i_src - l), srcheight - 1)) * width + k; //clamped BC's + tot += ((filterLo[j][0] * srcLo[arg] + filterHi[j][0] * srcHi[arg])); + } + + dst[width * i + k] = dst[width * i + k] * srcFactor + blend * 4.f * tot; + } + } + } +} +#else +template void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend) +{ + + /* Basic convolution code + * Applies an FIR filter 'filter' with filter length 'taps', + * aligning the 'offset' element of the filter with + * the input pixel, and skipping 'skip' pixels between taps + * Output is subsampled by two + */ + + const float srcFactor = 1.f - blend; + // calculate coefficients + int shift = skip * (taps - offset - 1); //align filter with data + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(numThreads) if(numThreads>1) +#endif + + for(int i = 0; i < dstheight; i++) { + int i_src = (i + shift) / 2; + int begin = (i + shift) % 2; + + //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' + if (LIKELY(i > skip * taps && i < (dstheight - skip * taps))) { //bulk + for (int k = 0; k < width; k++) { + float tot = 0.f; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + tot += ((filterLo[j] * srcLo[(i_src - l) * width + k] + filterHi[j] * srcHi[(i_src - l) * width + k])); + } + + dst[width * i + k] = dst[width * i + k] * srcFactor + blend * 4.f * tot; + } + } else {//boundary + for (int k = 0; k < width; k++) { + float tot = 0.f; + + for (int j = begin, l = 0; j < taps; j += 2, l += skip) { + int arg = max(0, min((i_src - l), srcheight - 1)) * width + k; //clamped BC's + tot += ((filterLo[j] * srcLo[arg] + filterHi[j] * srcHi[arg])); + } + + dst[width * i + k] = dst[width * i + k] * srcFactor + blend * 4.f * tot; + } + } + } +} +#endif + +#ifdef __SSE2__ +template template SSEFUNCTION void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) +{ + + /* filter along rows and columns */ + float filterVarray[2 * taps][4] ALIGNED64; + + if(subsamp_out) { + for(int i = 0; i < 2 * taps; i++) { + for(int j = 0; j < 4; j++) { + filterVarray[i][j] = filterV[i]; + } + } + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(numThreads) if(numThreads>1) +#endif + { + T tmpLo[m_w] ALIGNED64; + T tmpHi[m_w] ALIGNED64; + + if(subsamp_out) { +#ifdef _RT_NESTED_OPENMP + #pragma omp for +#endif + + for(int row = 0; row < m_h; row += 2) { + AnalysisFilterSubsampVertical (src, tmpLo, tmpHi, filterVarray, filterVarray + taps, taps, offset, m_w, m_h, row); + AnalysisFilterSubsampHorizontal (tmpLo, dst, wavcoeffs[1], filterH, filterH + taps, taps, offset, m_w, m_w2, row / 2); + AnalysisFilterSubsampHorizontal (tmpHi, wavcoeffs[2], wavcoeffs[3], filterH, filterH + taps, taps, offset, m_w, m_w2, row / 2); + } + } else { +#ifdef _RT_NESTED_OPENMP + #pragma omp for +#endif + + for(int row = 0; row < m_h; row++) { + AnalysisFilterHaarVertical (src, tmpLo, tmpHi, m_w, m_h, row); + AnalysisFilterHaarHorizontal (tmpLo, dst, wavcoeffs[1], m_w, row); + AnalysisFilterHaarHorizontal (tmpHi, wavcoeffs[2], wavcoeffs[3], m_w, row); + } + } + } +} +#else +template template void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) +{ + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(numThreads) if(numThreads>1) +#endif + { + T tmpLo[m_w] ALIGNED64; + T tmpHi[m_w] ALIGNED64; + /* filter along rows and columns */ + if(subsamp_out) + { +#ifdef _RT_NESTED_OPENMP + #pragma omp for +#endif + + for(int row = 0; row < m_h; row += 2) { + AnalysisFilterSubsampVertical (src, tmpLo, tmpHi, filterV, filterV + taps, taps, offset, m_w, m_h, row); + AnalysisFilterSubsampHorizontal (tmpLo, dst, wavcoeffs[1], filterH, filterH + taps, taps, offset, m_w, m_w2, row / 2); + AnalysisFilterSubsampHorizontal (tmpHi, wavcoeffs[2], wavcoeffs[3], filterH, filterH + taps, taps, offset, m_w, m_w2, row / 2); + } + } else { +#ifdef _RT_NESTED_OPENMP + #pragma omp for +#endif + + for(int row = 0; row < m_h; row++) + { + AnalysisFilterHaarVertical (src, tmpLo, tmpHi, m_w, m_h, row); + AnalysisFilterHaarHorizontal (tmpLo, dst, wavcoeffs[1], m_w, row); + AnalysisFilterHaarHorizontal (tmpHi, wavcoeffs[2], wavcoeffs[3], m_w, row); + } + } + } } - } #endif #ifdef __SSE2__ - template template SSEFUNCTION void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend) { - if(memoryAllocationFailed) - return; +template template SSEFUNCTION void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend) +{ + if(memoryAllocationFailed) { + return; + } - /* filter along rows and columns */ - if (subsamp_out) { - float filterVarray[2*taps][4] ALIGNED64; - for(int i=0;i<2*taps;i++) { - for(int j=0;j<4;j++) { - filterVarray[i][j] = filterV[i]; - } - } - SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterVarray, filterVarray+taps, taps, offset, m_w, m_h2, m_h, blend); - } else { - SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); - SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); - SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); - } - } + /* filter along rows and columns */ + if (subsamp_out) { + float filterVarray[2 * taps][4] ALIGNED64; + + for(int i = 0; i < 2 * taps; i++) { + for(int j = 0; j < 4; j++) { + filterVarray[i][j] = filterV[i]; + } + } + + SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH + taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH + taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterVarray, filterVarray + taps, taps, offset, m_w, m_h2, m_h, blend); + } else { + SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); + SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); + SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); + } +} #else - template template void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend) { - if(memoryAllocationFailed) - return; - /* filter along rows and columns */ - if (subsamp_out) { - SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterV, filterV+taps, taps, offset, m_w, m_h2, m_h, blend); - } else { - SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); - SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); - SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); - } - } +template template void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend) +{ + if(memoryAllocationFailed) { + return; + } + + /* filter along rows and columns */ + if (subsamp_out) { + SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH + taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH + taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterV, filterV + taps, taps, offset, m_w, m_h2, m_h, blend); + } else { + SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); + SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); + SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); + } +} #endif }; diff --git a/rtengine/curves.cc b/rtengine/curves.cc index 4bb5425b9..4e94be1b8 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -7,7 +7,7 @@ * 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 @@ -38,1648 +38,1907 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ - Curve::Curve () : N(0), x(NULL), y(NULL), ypp(NULL), hashSize(1000 /* has to be initialized to the maximum value */ ) {} - - void Curve::AddPolygons () - { - if (firstPointIncluded) { - poly_x.push_back(x1); - poly_y.push_back(y1); - } - for (int k=1; k<(nbr_points-1); k++) { - double t = k*increment; - double t2 = t*t; - double tr = 1.-t; - double tr2 = tr*tr; - double tr2t = tr*2*t; - - // adding a point to the polyline - poly_x.push_back( tr2*x1 + tr2t*x2 + t2*x3); - poly_y.push_back( tr2*y1 + tr2t*y2 + t2*y3); - } - // adding the last point of the sub-curve - poly_x.push_back(x3); - poly_y.push_back(y3); - } +Curve::Curve () : N(0), x(NULL), y(NULL), ypp(NULL), hashSize(1000 /* has to be initialized to the maximum value */ ) {} - void Curve::fillHash() { - hash.resize(hashSize+2); +void Curve::AddPolygons () +{ + if (firstPointIncluded) { + poly_x.push_back(x1); + poly_y.push_back(y1); + } - unsigned int polyIter = 0; - double const increment = 1./hashSize; - double milestone = 0.; + for (int k = 1; k < (nbr_points - 1); k++) { + double t = k * increment; + double t2 = t * t; + double tr = 1. - t; + double tr2 = tr * tr; + double tr2t = tr * 2 * t; - for (unsigned short i=0; i<(hashSize+1);) { - while(poly_x[polyIter] <= milestone) ++polyIter; - hash.at(i).smallerValue = polyIter-1; - ++i; - milestone = i*increment; - } - milestone = 0.; - polyIter = 0; - for (unsigned int i=0; i<(hashSize+1);) { - while(poly_x[polyIter] < (milestone+increment)) ++polyIter; - hash.at(i).higherValue = polyIter; - ++i; - milestone = i*increment; - } - hash.at(hashSize+1).smallerValue = poly_x.size()-1; - hash.at(hashSize+1).higherValue = poly_x.size(); + // adding a point to the polyline + poly_x.push_back( tr2 * x1 + tr2t * x2 + t2 * x3); + poly_y.push_back( tr2 * y1 + tr2t * y2 + t2 * y3); + } - /* - * Uncoment the code below to dump the polygon points and the hash table in files - if (poly_x.size() > 500) { - printf("Files generated (%d points)\n", poly_x.size()); - FILE* f = fopen ("hash.txt", "wt"); - for (unsigned int i=0; ix && cpNum < N) { - x = this->x[cpNum]; - y = this->y[cpNum]; - } - else { - x = y = -1.; - } - } + for (unsigned short i = 0; i < (hashSize + 1);) { + while(poly_x[polyIter] <= milestone) { + ++polyIter; + } - // Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. - // The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent - // and a gamma (slope of log output versus log input) changing from 1.0 through about 2.3. - const double CurveFactory::sRGBGamma = 2.2; - const double CurveFactory::sRGBGammaCurve = 2.4; + hash.at(i).smallerValue = polyIter - 1; + ++i; + milestone = i * increment; + } - SSEFUNCTION void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed) { + milestone = 0.; + polyIter = 0; - if (needed) { - LUTf lutCurve (65536); + for (unsigned int i = 0; i < (hashSize + 1);) { + while(poly_x[polyIter] < (milestone + increment)) { + ++polyIter; + } - for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) { - // change to [0,1] range - float val = (float)i / 65535.f; - // apply custom/parametric/NURBS curve, if any - val = diagCurve->getVal (val); - // store result in a temporary array - lutCurve[i] = (val); - } + hash.at(i).higherValue = polyIter; + ++i; + milestone = i * increment; + } - // if skip>1, let apply linear interpolation in the skipped points of the curve - if (skip > 1) { - int prev = 0; - for (int i=1; i<=0xffff-skip; i++) { - if (i%skip==0) { - prev+=skip; - continue; - } - lutCurve[i] = ( lutCurve[prev] * (skip - i%skip) + lutCurve[prev+skip] * (i%skip) ) / skip; - } - } + hash.at(hashSize + 1).smallerValue = poly_x.size() - 1; + hash.at(hashSize + 1).higherValue = poly_x.size(); - for (int i=0; i<=0xffff; i++) { - outCurve[i] = (65535.f * lutCurve[i]); - } - } - else { + /* + * Uncoment the code below to dump the polygon points and the hash table in files + if (poly_x.size() > 500) { + printf("Files generated (%d points)\n", poly_x.size()); + FILE* f = fopen ("hash.txt", "wt"); + for (unsigned int i=0; ix && cpNum < N) { + x = this->x[cpNum]; + y = this->y[cpNum]; + } else { + x = y = -1.; + } +} + +// Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. +// The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent +// and a gamma (slope of log output versus log input) changing from 1.0 through about 2.3. +const double CurveFactory::sRGBGamma = 2.2; +const double CurveFactory::sRGBGammaCurve = 2.4; + +SSEFUNCTION void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed) +{ + + if (needed) { + LUTf lutCurve (65536); + + for (int i = 0; i <= 0xffff; i += i < 0xffff - skip ? skip : 1 ) { + // change to [0,1] range + float val = (float)i / 65535.f; + // apply custom/parametric/NURBS curve, if any + val = diagCurve->getVal (val); + // store result in a temporary array + lutCurve[i] = (val); + } + + // if skip>1, let apply linear interpolation in the skipped points of the curve + if (skip > 1) { + int prev = 0; + + for (int i = 1; i <= 0xffff - skip; i++) { + if (i % skip == 0) { + prev += skip; + continue; + } + + lutCurve[i] = ( lutCurve[prev] * (skip - i % skip) + lutCurve[prev + skip] * (i % skip) ) / skip; + } + } + + for (int i = 0; i <= 0xffff; i++) { + outCurve[i] = (65535.f * lutCurve[i]); + } + } else { #ifdef __SSE2__ - __m128 fourv = _mm_set1_ps(4.f); - __m128 iv = _mm_set_ps(3.f,2.f,1.f,0.f); - for (int i=0; i<=0xfffc; i+=4) { - _mm_storeu_ps(&outCurve[i],iv); - iv += fourv; - } -#else - for (int i=0; i<=0xffff; i++) { - outCurve[i] = (float)i; - } -#endif - } + __m128 fourv = _mm_set1_ps(4.f); + __m128 iv = _mm_set_ps(3.f, 2.f, 1.f, 0.f); - } + for (int i = 0; i <= 0xfffc; i += 4) { + _mm_storeu_ps(&outCurve[i], iv); + iv += fourv; + } + +#else + + for (int i = 0; i <= 0xffff; i++) { + outCurve[i] = (float)i; + } + +#endif + } + +} void CurveFactory::updatechroma ( - const std::vector& cccurvePoints, - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma - int skip) + const std::vector& cccurvePoints, + LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma + int skip) { - LUTf dCcurve(65536,0); - float val; - for (int i=0; i<48000; i++) {//32768*1.414 + ... - val = (double)i / 47999.0; - dCcurve[i] = CLIPD(val); - } + LUTf dCcurve(65536, 0); + float val; - outBeforeCCurveHistogramC.clear(); - bool histNeededC = false; - + for (int i = 0; i < 48000; i++) { //32768*1.414 + ... + val = (double)i / 47999.0; + dCcurve[i] = CLIPD(val); + } - if (!cccurvePoints.empty() && cccurvePoints[0]!=0) { - if (outBeforeCCurveHistogramC /*&& histogramCropped*/) - histNeededC = true; - } - for (int i=0; i<48000; i++) {//32768*1.414 + ... - float val; - if (histNeededC) { - float hval = dCcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); // - outBeforeCCurveHistogramC[hi] += histogramC[i] ; - } - } + outBeforeCCurveHistogramC.clear(); + bool histNeededC = false; + + + if (!cccurvePoints.empty() && cccurvePoints[0] != 0) { + if (outBeforeCCurveHistogramC /*&& histogramCropped*/) { + histNeededC = true; + } + } + + for (int i = 0; i < 48000; i++) { //32768*1.414 + ... + float val; + + if (histNeededC) { + float hval = dCcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); // + outBeforeCCurveHistogramC[hi] += histogramC[i] ; + } + } } - - + + void CurveFactory::curveLightBrightColor ( - procparams::ColorAppearanceParams::eTCModeId curveMode1, const std::vector& curvePoints1, - procparams::ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2, - procparams::ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3, - LUTu & histogram, LUTu & histogramCropped, LUTu & outBeforeCCurveHistogram,//for Luminance - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma - ColorAppearance & customColCurve1, - ColorAppearance & customColCurve2, - ColorAppearance & customColCurve3, - int skip) + procparams::ColorAppearanceParams::eTCModeId curveMode1, const std::vector& curvePoints1, + procparams::ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2, + procparams::ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3, + LUTu & histogram, LUTu & histogramCropped, LUTu & outBeforeCCurveHistogram,//for Luminance + LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma + ColorAppearance & customColCurve1, + ColorAppearance & customColCurve2, + ColorAppearance & customColCurve3, + int skip) { - outBeforeCCurveHistogram.clear(); - outBeforeCCurveHistogramC.clear(); - bool histNeededC = false; - - bool histNeeded = false; - DiagonalCurve* tcurve = NULL; - customColCurve3.Reset(); + outBeforeCCurveHistogram.clear(); + outBeforeCCurveHistogramC.clear(); + bool histNeededC = false; - if (!curvePoints3.empty() && curvePoints3[0]>DCT_Linear && curvePoints3[0]isIdentity()) { - delete tcurve; - tcurve = NULL; - } - else - customColCurve3.Set(tcurve); - delete tcurve; - tcurve = NULL; - } + bool histNeeded = false; + DiagonalCurve* tcurve = NULL; + customColCurve3.Reset(); - customColCurve2.Reset(); + if (!curvePoints3.empty() && curvePoints3[0] > DCT_Linear && curvePoints3[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePoints3, CURVES_MIN_POLY_POINTS / skip); - if (!curvePoints2.empty() && curvePoints2[0]>DCT_Linear && curvePoints2[0]isIdentity()) { - delete tcurve; - tcurve = NULL; - } - else - customColCurve2.Set(tcurve); - delete tcurve; - tcurve = NULL; - } - // create first curve if needed - customColCurve1.Reset(); + if (outBeforeCCurveHistogramC /*&& histogramCropped*/) { + histNeededC = true; + } - if (!curvePoints1.empty() && curvePoints1[0]>DCT_Linear && curvePoints1[0]isIdentity()) { - delete tcurve; - tcurve = NULL; - } - else { - customColCurve1.Set(tcurve); - delete tcurve; - tcurve = NULL; - } - } - if (histNeeded) { - for (int i=0; i<32768; i++) { - double hval = CLIPD((double)i / 32767.0); - int hi = (int)(255.0*hval); - outBeforeCCurveHistogram[hi] += histogram[i] ; - } - } - if (histNeededC) { - for (int i=0; i<48000; i++) {//32768*1.414 + ... - double hval = CLIPD((double)i / 47999.0); - int hi = (int)(255.0*hval); // - outBeforeCCurveHistogramC[hi] += histogramC[i] ; - } - } - - if (tcurve) delete tcurve; + } + + if (tcurve) { + if (tcurve->isIdentity()) { + delete tcurve; + tcurve = NULL; + } else { + customColCurve3.Set(tcurve); + } + + delete tcurve; + tcurve = NULL; + } + + customColCurve2.Reset(); + + if (!curvePoints2.empty() && curvePoints2[0] > DCT_Linear && curvePoints2[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePoints2, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogram /*&& histogramCropped*/) { + histNeeded = true; + } + + } + + if (tcurve) { + if (tcurve->isIdentity()) { + delete tcurve; + tcurve = NULL; + } else { + customColCurve2.Set(tcurve); + } + + delete tcurve; + tcurve = NULL; + } + + // create first curve if needed + customColCurve1.Reset(); + + if (!curvePoints1.empty() && curvePoints1[0] > DCT_Linear && curvePoints1[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePoints1, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogram /*&& histogramCropped*/) { + histNeeded = true; + } + + } + + if (tcurve) { + if (tcurve->isIdentity()) { + delete tcurve; + tcurve = NULL; + } else { + customColCurve1.Set(tcurve); + delete tcurve; + tcurve = NULL; + } + } + + if (histNeeded) { + for (int i = 0; i < 32768; i++) { + double hval = CLIPD((double)i / 32767.0); + int hi = (int)(255.0 * hval); + outBeforeCCurveHistogram[hi] += histogram[i] ; + } + } + + if (histNeededC) { + for (int i = 0; i < 48000; i++) { //32768*1.414 + ... + double hval = CLIPD((double)i / 47999.0); + int hi = (int)(255.0 * hval); // + outBeforeCCurveHistogramC[hi] += histogramC[i] ; + } + } + + if (tcurve) { + delete tcurve; + } } // add curve Denoise : C=f(C) -void CurveFactory::denoiseCC ( bool & ccdenoiseutili,const std::vector& cccurvePoints, LUTf & NoiseCCcurve,int skip){ - bool needed; - DiagonalCurve* dCurve = NULL; - LUTf dCcurve(65536,0); - - float val; - for (int i=0; i<48000; i++) { - dCcurve[i] = (float)i / 47999.0; - } - - needed = false; - if (!cccurvePoints.empty() && cccurvePoints[0]!=0) { - dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS/skip); - - if (dCurve && !dCurve->isIdentity()) - {needed = true;ccdenoiseutili=true;} - } - fillCurveArray(dCurve, NoiseCCcurve, skip, needed); - //NoiseCCcurve.dump("Noise"); - - if (dCurve) { - delete dCurve; - dCurve = NULL; - } +void CurveFactory::denoiseCC ( bool & ccdenoiseutili, const std::vector& cccurvePoints, LUTf & NoiseCCcurve, int skip) +{ + bool needed; + DiagonalCurve* dCurve = NULL; + LUTf dCcurve(65536, 0); + + float val; + + for (int i = 0; i < 48000; i++) { + dCcurve[i] = (float)i / 47999.0; + } + + needed = false; + + if (!cccurvePoints.empty() && cccurvePoints[0] != 0) { + dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + ccdenoiseutili = true; + } + } + + fillCurveArray(dCurve, NoiseCCcurve, skip, needed); + //NoiseCCcurve.dump("Noise"); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } } void CurveFactory::curveBW ( - const std::vector& curvePointsbw, const std::vector& curvePointsbw2, - LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw,//for Luminance - ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip) + const std::vector& curvePointsbw, const std::vector& curvePointsbw2, + LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw,//for Luminance + ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip) { - const float gamma_ = Color::sRGBGammaCurve; - const float start = expf(gamma_*logf( -0.055 / ((1.0/gamma_-1.0)*1.055 ))); - const float slope = 1.055 * powf (start, 1.0/gamma_-1) - 0.055/start; - const float mul = 1.055; - const float add = 0.055; + const float gamma_ = Color::sRGBGammaCurve; + const float start = expf(gamma_ * logf( -0.055 / ((1.0 / gamma_ - 1.0) * 1.055 ))); + const float slope = 1.055 * powf (start, 1.0 / gamma_ - 1) - 0.055 / start; + const float mul = 1.055; + const float add = 0.055; - outBeforeCCurveHistogrambw.clear(); - bool histNeeded = false; - - DiagonalCurve* tcurve = NULL; - customToneCurvebw2.Reset(); + outBeforeCCurveHistogrambw.clear(); + bool histNeeded = false; - if (!curvePointsbw2.empty() && curvePointsbw2[0]>DCT_Linear && curvePointsbw2[0]isIdentity()) - customToneCurvebw2.Set(tcurve, gamma_, start, slope, mul, add); - delete tcurve; - tcurve = NULL; - } + DiagonalCurve* tcurve = NULL; + customToneCurvebw2.Reset(); - customToneCurvebw1.Reset(); + if (!curvePointsbw2.empty() && curvePointsbw2[0] > DCT_Linear && curvePointsbw2[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePointsbw2, CURVES_MIN_POLY_POINTS / skip); - if (!curvePointsbw.empty() && curvePointsbw[0]>DCT_Linear && curvePointsbw[0]isIdentity()) - customToneCurvebw1.Set(tcurve, gamma_, start, slope, mul, add); - delete tcurve; - tcurve = NULL; - } - // create first curve if needed - if (histNeeded) { - LUTf dcurve(65536,0); - - float val; - for (int i=0; i<32768; i++) { - val = (float)i / 32767.f; - dcurve[i] = CLIPD(val); - } + if (outBeforeCCurveHistogrambw /*&& histogramCropped*/) { + histNeeded = true; + } - for (int i=0; i<32768; i++) { - float hval = dcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); - outBeforeCCurveHistogrambw[hi] += histogrambw[i] ; - } - } - - if (tcurve) delete tcurve; + } + + if (tcurve) { + if (!tcurve->isIdentity()) { + customToneCurvebw2.Set(tcurve, gamma_, start, slope, mul, add); + } + + delete tcurve; + tcurve = NULL; + } + + customToneCurvebw1.Reset(); + + if (!curvePointsbw.empty() && curvePointsbw[0] > DCT_Linear && curvePointsbw[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePointsbw, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogrambw /*&& histogramCropped*/) { + histNeeded = true; + } + + } + + if (tcurve) { + if (!tcurve->isIdentity()) { + customToneCurvebw1.Set(tcurve, gamma_, start, slope, mul, add); + } + + delete tcurve; + tcurve = NULL; + } + + // create first curve if needed + if (histNeeded) { + LUTf dcurve(65536, 0); + + float val; + + for (int i = 0; i < 32768; i++) { + val = (float)i / 32767.f; + dcurve[i] = CLIPD(val); + } + + for (int i = 0; i < 32768; i++) { + float hval = dcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); + outBeforeCCurveHistogrambw[hi] += histogrambw[i] ; + } + } + + if (tcurve) { + delete tcurve; + } } // add curve Lab : C=f(L) -void CurveFactory::curveCL ( bool & clcutili,const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram,int skip){ - bool needed; - DiagonalCurve* dCurve = NULL; - - if (outBeforeCLurveHistogram) - outBeforeCLurveHistogram.clear(); - bool histNeededCL = false; +void CurveFactory::curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip) +{ + bool needed; + DiagonalCurve* dCurve = NULL; - needed = false; - if (!clcurvePoints.empty() && clcurvePoints[0]!=0) { - dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS/skip); - if (outBeforeCLurveHistogram) - histNeededCL = true; - - if (dCurve && !dCurve->isIdentity()) - {needed = true;clcutili=true;} - } - if(histNeededCL) - for (int i=0; i<50000; i++) {//32768*1.414 + ... - int hi = (int)(255.0*CLIPD((float)i / 49999.0)); // - outBeforeCLurveHistogram[hi] += histogramcl[i] ; - } + if (outBeforeCLurveHistogram) { + outBeforeCLurveHistogram.clear(); + } - - fillCurveArray(dCurve, clCurve, skip, needed); - if (dCurve) { - delete dCurve; - dCurve = NULL; - } + bool histNeededCL = false; + + needed = false; + + if (!clcurvePoints.empty() && clcurvePoints[0] != 0) { + dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCLurveHistogram) { + histNeededCL = true; + } + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + clcutili = true; + } + } + + if(histNeededCL) + for (int i = 0; i < 50000; i++) { //32768*1.414 + ... + int hi = (int)(255.0 * CLIPD((float)i / 49999.0)); // + outBeforeCLurveHistogram[hi] += histogramcl[i] ; + } + + + fillCurveArray(dCurve, clCurve, skip, needed); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } } // add curve Lab wavelet : Cont=f(L) -void CurveFactory::curveWavContL ( bool & wavcontlutili,const std::vector& wavclcurvePoints, LUTf & wavclCurve, /*LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip){ - bool needed; - DiagonalCurve* dCurve = NULL; - - // if (outBeforeWavCLurveHistogram) - // outBeforeWavCLurveHistogram.clear(); - bool histNeededCL = false; +void CurveFactory::curveWavContL ( bool & wavcontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve, /*LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip) +{ + bool needed; + DiagonalCurve* dCurve = NULL; - needed = false; - if (!wavclcurvePoints.empty() && wavclcurvePoints[0]!=0) { - dCurve = new DiagonalCurve (wavclcurvePoints, CURVES_MIN_POLY_POINTS/skip); - // if (outBeforeWavCLurveHistogram) - // histNeededCL = true; - - if (dCurve && !dCurve->isIdentity()) - {needed = true;wavcontlutili=true;} - } - // if(histNeededCL) - for (int i=0; i<32768; i++) {//32768*1.414 + ... - int hi = (int)(255.0*CLIPD((float)i / 32767.0)); // - // outBeforeWavCLurveHistogram[hi] += histogramwavcl[i] ; - } + // if (outBeforeWavCLurveHistogram) + // outBeforeWavCLurveHistogram.clear(); + bool histNeededCL = false; - - fillCurveArray(dCurve, wavclCurve, skip, needed); - // wavclCurve.dump("WL"); + needed = false; - if (dCurve) { - delete dCurve; - dCurve = NULL; - } + if (!wavclcurvePoints.empty() && wavclcurvePoints[0] != 0) { + dCurve = new DiagonalCurve (wavclcurvePoints, CURVES_MIN_POLY_POINTS / skip); + // if (outBeforeWavCLurveHistogram) + // histNeededCL = true; + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + wavcontlutili = true; + } + } + + // if(histNeededCL) + for (int i = 0; i < 32768; i++) { //32768*1.414 + ... + int hi = (int)(255.0 * CLIPD((float)i / 32767.0)); // + // outBeforeWavCLurveHistogram[hi] += histogramwavcl[i] ; + } + + + fillCurveArray(dCurve, wavclCurve, skip, needed); + // wavclCurve.dump("WL"); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } } // add curve Colortoning : C=f(L) -void CurveFactory::curveToningCL ( bool & clctoningutili,const std::vector& clcurvePoints, LUTf & clToningCurve,int skip){ - bool needed; - DiagonalCurve* dCurve = NULL; - - needed = false; - if (!clcurvePoints.empty() && clcurvePoints[0]!=0) { - dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS/skip); - - if (dCurve && !dCurve->isIdentity()) - {needed = true;clctoningutili=true;} - } - fillCurveArray(dCurve, clToningCurve, skip, needed); - // clToningCurve.dump("CLToning"); - if (dCurve) { - delete dCurve; - dCurve = NULL; - } +void CurveFactory::curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip) +{ + bool needed; + DiagonalCurve* dCurve = NULL; + + needed = false; + + if (!clcurvePoints.empty() && clcurvePoints[0] != 0) { + dCurve = new DiagonalCurve (clcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + clctoningutili = true; + } + } + + fillCurveArray(dCurve, clToningCurve, skip, needed); + + // clToningCurve.dump("CLToning"); + if (dCurve) { + delete dCurve; + dCurve = NULL; + } } // add curve Colortoning : CLf(L) -void CurveFactory::curveToningLL ( bool & llctoningutili,const std::vector& llcurvePoints, LUTf & llToningCurve, int skip){ - bool needed; - DiagonalCurve* dCurve = NULL; +void CurveFactory::curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip) +{ + bool needed; + DiagonalCurve* dCurve = NULL; - needed = false; - if (!llcurvePoints.empty() && llcurvePoints[0]!=0) { - dCurve = new DiagonalCurve (llcurvePoints, CURVES_MIN_POLY_POINTS/skip); - - if (dCurve && !dCurve->isIdentity()) - {needed = true;llctoningutili=true;} - } - fillCurveArray(dCurve, llToningCurve, skip, needed); -// llToningCurve.dump("LLToning"); + needed = false; - if (dCurve) { - delete dCurve; - dCurve = NULL; - } + if (!llcurvePoints.empty() && llcurvePoints[0] != 0) { + dCurve = new DiagonalCurve (llcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + llctoningutili = true; + } + } + + fillCurveArray(dCurve, llToningCurve, skip, needed); +// llToningCurve.dump("LLToning"); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili, bool & ccutili, bool & cclutili, double saturation, double rstprotection, - const std::vector& acurvePoints, const std::vector& bcurvePoints,const std::vector& cccurvePoints, - const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, - LUTu & histogramC, LUTu & histogramLC, LUTu & outBeforeCCurveHistogram,LUTu & outBeforeLCurveHistogram, //for chroma - int skip) { - - - //----------------------------------------------------- - - bool needed; - DiagonalCurve* dCurve = NULL; - LUTf dCcurve(65536,0); - int k=48000;//32768*1.41 - if(outBeforeCCurveHistogram || outBeforeLCurveHistogram) { - for (int i=0; iisIdentity()) { - needed = true; - autili=true; - } - } - fillCurveArray(dCurve, aoutCurve, skip, needed); - //if(autili) aoutCurve.dump("acurve"); - - if (dCurve) { - delete dCurve; - dCurve = NULL; - } - - //----------------------------------------------------- - - needed = false; - if (!bcurvePoints.empty() && bcurvePoints[0]!=0) { - dCurve = new DiagonalCurve (bcurvePoints, CURVES_MIN_POLY_POINTS/skip); - if (dCurve && !dCurve->isIdentity()) { - needed = true; - butili=true; - } - } - fillCurveArray(dCurve, boutCurve, skip, needed); - if (dCurve) { - delete dCurve; - dCurve = NULL; - } - - //----------------------------------------------- - needed = false; - if (!cccurvePoints.empty() && cccurvePoints[0]!=0) { - dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS/skip); - if (outBeforeCCurveHistogram /*&& histogramCropped*/) - histNeededC = true; - - if (dCurve && !dCurve->isIdentity()) - {needed = true;ccutili=true;} - } - if (histNeededC) { - for (int i=0; iisIdentity()) - {needed = true;cclutili=true;} - } - if (histNeededLC) { - for (int i=0; i& curvePoints, - procparams::ToneCurveParams::eTCModeId curveMode2, const std::vector& curvePoints2, - LUTu & histogram, LUTu & histogramCropped, - LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, - LUTu & outBeforeCCurveHistogram, - ToneCurve & customToneCurve1, - ToneCurve & customToneCurve2, - int skip) { - - // the curve shapes are defined in sRGB gamma, but the output curves will operate on linear floating point data, - // hence we do both forward and inverse gamma conversions here. - const float gamma_ = Color::sRGBGammaCurve; - const float start = expf(gamma_*logf( -0.055 / ((1.0/gamma_-1.0)*1.055 ))); - const float slope = 1.055 * powf (start, 1.0/gamma_-1) - 0.055/start; - const float mul = 1.055; - const float add = 0.055; - - // a: slope of the curve, black: starting point at the x axis - const float a = powf (2.0, ecomp); - - // clear array that stores histogram valid before applying the custom curve - outBeforeCCurveHistogram.clear(); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - DiagonalCurve* brightcurve = NULL; - - // check if brightness curve is needed - if (br>0.00001 || br<-0.00001) { - - std::vector brightcurvePoints; - brightcurvePoints.resize(9); - brightcurvePoints.at(0) = double(DCT_NURBS); - - brightcurvePoints.at(1) = 0.; //black point. Value in [0 ; 1] range - brightcurvePoints.at(2) = 0.; //black point. Value in [0 ; 1] range - - if(br>0) { - brightcurvePoints.at(3) = 0.1; //toe point - brightcurvePoints.at(4) = 0.1+br/150.0; //value at toe point - - brightcurvePoints.at(5) = 0.7; //shoulder point - brightcurvePoints.at(6) = min(1.0,0.7+br/300.0); //value at shoulder point - } else { - brightcurvePoints.at(3) = max(0.0,0.1-br/150.0); //toe point - brightcurvePoints.at(4) = 0.1; //value at toe point - - brightcurvePoints.at(5) = 0.7-br/300.0; //shoulder point - brightcurvePoints.at(6) = 0.7; //value at shoulder point - } - brightcurvePoints.at(7) = 1.; // white point - brightcurvePoints.at(8) = 1.; // value at white point - - brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details - float exp_scale = a; - float scale = 65536.0; - float comp = (max(0.0,ecomp) + 1.0)*hlcompr/100.0; - float shoulder = ((scale/max(1.0f,exp_scale))*(hlcomprthresh/200.0))+0.1; - //printf("shoulder = %e\n",shoulder); - //printf ("exp_scale= %f comp= %f def_mul=%f a= %f \n",exp_scale,comp,def_mul,a); - - if (comp<=0.0f) - for (int i=0; i<0x10000; i++) - hlCurve[i]=exp_scale; - else { - for (int i=0; i<=shoulder; i++) - hlCurve[i]=exp_scale; - float scalemshoulder = scale - shoulder; - - for (int i=shoulder+1; i<0x10000; i++) { - // change to [0,1] range - float val = (float)i-shoulder; - float R = val*comp/(scalemshoulder); - hlCurve[i] = xlog(1.0+R*exp_scale)/R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision - } - } - - - // curve without contrast - LUTf dcurve(0x10000); - - //%%%%%%%%%%%%%%%%%%%%%%%%%% - // change to [0,1] range - shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value. - float val = 1.f/65535.f; - float val2 = simplebasecurve (val, black, 0.015*shcompr); - shCurve[0] = CLIPD(val2)/val; - val = 0.0; - // gamma correction - val = gamma (val, gamma_, start, slope, mul, add); - - // apply brightness curve - if (brightcurve) - val = brightcurve->getVal (val); // TODO: getVal(double) is very slow! Optimize with a LUTf - - // store result in a temporary array - dcurve[0] = CLIPD(val); - -#pragma omp parallel for - for (int i=1; i<0x10000; i++) { - float val; - val = (float)i / 65535.0f; - - float val2 = simplebasecurve (val, black, 0.015*shcompr); - shCurve[i] = CLIPD(val2)/val; - - // gamma correction - val = gamma (val, gamma_, start, slope, mul, add); - - // apply brightness curve - if (brightcurve) - val = brightcurve->getVal (val); // TODO: getVal(double) is very slow! Optimize with a LUTf - - // store result in a temporary array - dcurve[i] = CLIPD(val); - } - - if (brightcurve) - delete brightcurve; - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // check if contrast curve is needed - if (contr>0.00001 || contr<-0.00001) { - - // compute mean luminance of the image with the curve applied - unsigned int sum = 0; - float avg = 0; - //double sqavg = 0; - for (int i=0; i<=0xffff; i++) { - float fi=i; - fi *= hlCurve[i]; - avg += dcurve[(int)(shCurve[fi]*fi)] * histogram[i]; - //sqavg += dcurve[i]*dcurve[i] * histogram[i]; - sum += histogram[i]; - } - - avg /= sum; - //sqavg /= sum; - //double stddev = sqrt(sqavg-avg*avg); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - std::vector contrastcurvePoints; - contrastcurvePoints.resize(9); - contrastcurvePoints.at(0) = double(DCT_NURBS); - - contrastcurvePoints.at(1) = 0; //black point. Value in [0 ; 1] range - contrastcurvePoints.at(2) = 0; //black point. Value in [0 ; 1] range - - contrastcurvePoints.at(3) = avg-avg*(0.6-contr/250.0); //toe point - contrastcurvePoints.at(4) = avg-avg*(0.6+contr/250.0); //value at toe point - - contrastcurvePoints.at(5) = avg+(1-avg)*(0.6-contr/250.0); //shoulder point - contrastcurvePoints.at(6) = avg+(1-avg)*(0.6+contr/250.0); //value at shoulder point - - contrastcurvePoints.at(7) = 1.; // white point - contrastcurvePoints.at(8) = 1.; // value at white point - - DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS/skip); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // apply contrast enhancement - for (int i=0; i<=0xffff; i++) { - dcurve[i] = contrastcurve->getVal (dcurve[i]); - } - - delete contrastcurve; - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // create second curve if needed - bool histNeeded = false; - DiagonalCurve* tcurve = NULL; - customToneCurve2.Reset(); - - if (!curvePoints2.empty() && curvePoints2[0]>DCT_Linear && curvePoints2[0]isIdentity()) - customToneCurve2.Set(tcurve, gamma_, start, slope, mul, add); - delete tcurve; - tcurve = NULL; - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // create first curve if needed - customToneCurve1.Reset(); - - if (!curvePoints.empty() && curvePoints[0]>DCT_Linear && curvePoints[0]isIdentity()) - customToneCurve1.Set(tcurve, gamma_, start, slope, mul, add); - delete tcurve; - tcurve = NULL; - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // create curve bw - // curve 2 -/* DiagonalCurve* tbwcurve = NULL; - customToneCurvebw2.Reset(); - - if (!curvePointsbw2.empty() && curvePointsbw2[0]>DCT_Linear && curvePointsbw2[0]isIdentity()) { - delete tbwcurve; - tbwcurve = NULL; - } - else - customToneCurvebw2.Set(tbwcurve); - delete tbwcurve; - tbwcurve = NULL; - } - - customToneCurvebw1.Reset(); - - if (!curvePointsbw.empty() && curvePointsbw[0]>DCT_Linear && curvePointsbw[0]isIdentity()) { - delete tbwcurve; - tbwcurve = NULL; - } - else if (curveModeb != procparams::BlackWhiteParams::TC_MODE_STD_BW) { - customToneCurvebw1.Set(tbwcurve); - delete tbwcurve; - tbwcurve = NULL; - } - } - */ - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - for (int i=0; i<=0xffff; i++) { - float val = dcurve[i]; - - if (histNeeded) { - float fi=i; - float hval = hlCurve[i]*fi; - hval = dcurve[shCurve[hval]*hval]; - //if (needigamma) - // hval = igamma2 (hval); - int hi = (int)(255.0*(hval)); - outBeforeCCurveHistogram[hi] += histogram/*Cropped*/[i] ; - } - val = igamma (val, gamma_, start, slope, mul, add); - outCurve[i] = (65535.f * val); - } - - if (tcurve) delete tcurve; - - /*if (outBeforeCCurveHistogram) { - for (int i=0; i<256; i++) printf("i= %d bchist= %d \n",i,outBeforeCCurveHistogram[i]); - }*/ - } - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void CurveFactory::complexLCurve (double br, double contr, const std::vector& curvePoints, - LUTu & histogram, LUTu & histogramCropped, LUTf & outCurve, - LUTu & outBeforeCCurveHistogram, int skip, bool & utili) { - - // curve without contrast - LUTf dcurve(65536,0); - - // clear array that stores histogram valid before applying the custom curve - if (outBeforeCCurveHistogram) - outBeforeCCurveHistogram.clear(); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // check if brightness curve is needed - if (br>0.00001 || br<-0.00001) { - utili=true; - - std::vector brightcurvePoints; - brightcurvePoints.resize(9); - brightcurvePoints.at(0) = double(DCT_NURBS); - - brightcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range - brightcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range - - if (br>0) { - brightcurvePoints.at(3) = 0.1; // toe point - brightcurvePoints.at(4) = 0.1+br/150.0; //value at toe point - - brightcurvePoints.at(5) = 0.7; // shoulder point - brightcurvePoints.at(6) = min(1.0,0.7+br/300.0); //value at shoulder point - } else { - brightcurvePoints.at(3) = 0.1-br/150.0; // toe point - brightcurvePoints.at(4) = 0.1; // value at toe point - - brightcurvePoints.at(5) = min(1.0,0.7-br/300.0); // shoulder point - brightcurvePoints.at(6) = 0.7; // value at shoulder point - } - brightcurvePoints.at(7) = 1.; // white point - brightcurvePoints.at(8) = 1.; // value at white point - - DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // Applying brightness curve - for (int i=0; i<32768; i++) { // L values range up to 32767, higher values are for highlight overflow - - // change to [0,1] range - float val = (float)i / 32767.0; - - // apply brightness curve - val = brightcurve->getVal (val); - - // store result in a temporary array - dcurve[i] = CLIPD(val); - } - delete brightcurve; - } - else { - for (int i=0; i<32768; i++) { // L values range up to 32767, higher values are for highlight overflow - // set the identity curve in the temporary array - dcurve[i] = (float)i / 32767.0; - } - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // check if contrast curve is needed - if (contr>0.00001 || contr<-0.00001) { - utili=true; - - DiagonalCurve* contrastcurve = NULL; - - // compute mean luminance of the image with the curve applied - int sum = 0; - float avg = 0; - //float sqavg = 0; - for (int i=0; i<32768; i++) { - avg += dcurve[i] * histogram[i]; - //sqavg += dcurve[i]*dcurve[i] * histogram[i]; - sum += histogram[i]; - } - if(sum) { - avg /= sum; - //sqavg /= sum; - //float stddev = sqrt(sqavg-avg*avg); - // printf("avg=%f\n",avg); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - std::vector contrastcurvePoints; - contrastcurvePoints.resize(9); - contrastcurvePoints.at(0) = double(DCT_NURBS); - - contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range - contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range - - contrastcurvePoints.at(3) = avg-avg*(0.6-contr/250.0); // toe point - contrastcurvePoints.at(4) = avg-avg*(0.6+contr/250.0); // value at toe point - - contrastcurvePoints.at(5) = avg+(1-avg)*(0.6-contr/250.0); // shoulder point - contrastcurvePoints.at(6) = avg+(1-avg)*(0.6+contr/250.0); // value at shoulder point - - contrastcurvePoints.at(7) = 1.; // white point - contrastcurvePoints.at(8) = 1.; // value at white point - - contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS/skip); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - } else { - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image - std::vector contrastcurvePoints; - contrastcurvePoints.resize(5); - contrastcurvePoints.at(0) = double(DCT_NURBS); - - contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range - contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range - - contrastcurvePoints.at(3) = 1.; // white point - contrastcurvePoints.at(4) = 1.; // value at white point - - contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS/skip); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - } - // apply contrast enhancement - for (int i=0; i<32768; i++) { - dcurve[i] = contrastcurve->getVal (dcurve[i]); - } - - delete contrastcurve; - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // create a curve if needed - DiagonalCurve* tcurve = NULL; - bool histNeeded = false; - if (!curvePoints.empty() && curvePoints[0]!=0) { - tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS/skip); - if (outBeforeCCurveHistogram /*&& histogramCropped*/) - histNeeded = true; - } - if (tcurve && tcurve->isIdentity()) { - delete tcurve; - tcurve = NULL; - } - - if (tcurve) { - utili=true;//if active - - // L values go up to 32767, last stop is for highlight overflow - for (int i=0; i<32768; i++) { - float val; - - if (histNeeded) { - float hval = dcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); - outBeforeCCurveHistogram[hi]+=histogram/*Cropped*/[i] ; - } - - // apply custom/parametric/NURBS curve, if any - val = tcurve->getVal (dcurve[i]); - - outCurve[i] = (32767.0 * val); - } - } - else { - // Skip the slow getval method if no curve is used (or an identity curve) - // L values go up to 32767, last stop is for highlight overflow - for (int i=0; i<32768; i++) { - if (histNeeded) { - float hval = dcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); - outBeforeCCurveHistogram[hi]+=histogram/*Cropped*/[i] ; - } - - outCurve[i] = 32767.0*dcurve[i]; - } - } - for (int i=32768; i<65536; i++) outCurve[i]=(float)i; - - if (tcurve) - delete tcurve; - - /*if (outBeforeCCurveHistogram) { - for (int i=0; i<256; i++) printf("i= %d bchist= %d \n",i,outBeforeCCurveHistogram[i]); - }*/ - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void CurveFactory::RGBCurve (const std::vector& curvePoints, LUTf & outCurve, int skip) { - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // create a curve if needed - DiagonalCurve* tcurve = NULL; - if (!curvePoints.empty() && curvePoints[0]!=0) { - tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS/skip); - } - if (tcurve && tcurve->isIdentity()) { - delete tcurve; - tcurve = NULL; - } - - if (tcurve) { - if (!outCurve) - outCurve(65536, 0); - for (int i=0; i<65536; i++) { - // apply custom/parametric/NURBS curve, if any - - // RGB curves are defined with sRGB gamma, but operate on linear data - float val = float(i)/65535.f; - val = CurveFactory::gamma2 (val); - val = tcurve->getVal(val); - val = CurveFactory::igamma2 (val); - //float val = tcurve->getVal ((float)i/65536.0f); - outCurve[i] = (65536.0f * val); - } - delete tcurve; - } - // let the LUTf empty for identity curves - else { - outCurve.reset(); - } - - } - - -void ColorAppearance::Reset() { +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +void CurveFactory::complexsgnCurve (float adjustr, bool & autili, bool & butili, bool & ccutili, bool & cclutili, double saturation, double rstprotection, + const std::vector& acurvePoints, const std::vector& bcurvePoints, const std::vector& cccurvePoints, + const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, + LUTu & histogramC, LUTu & histogramLC, LUTu & outBeforeCCurveHistogram, LUTu & outBeforeLCurveHistogram, //for chroma + int skip) +{ + + + //----------------------------------------------------- + + bool needed; + DiagonalCurve* dCurve = NULL; + LUTf dCcurve(65536, 0); + int k = 48000; //32768*1.41 + + if(outBeforeCCurveHistogram || outBeforeLCurveHistogram) { + for (int i = 0; i < k * adjustr; i++) { //# 32768*1.414 approximation maxi for chroma + dCcurve[i] = (float)i / (k * adjustr - 1); + } + } + + if (outBeforeCCurveHistogram) { + outBeforeCCurveHistogram.clear(); + } + + bool histNeededC = false; + + if (outBeforeLCurveHistogram) { + outBeforeLCurveHistogram.clear(); + } + + bool histNeededLC = false; + + //----------------------------------------------------- + + needed = false; + + // create a curve if needed + if (!acurvePoints.empty() && acurvePoints[0] != 0) { + dCurve = new DiagonalCurve (acurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + autili = true; + } + } + + fillCurveArray(dCurve, aoutCurve, skip, needed); + //if(autili) aoutCurve.dump("acurve"); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } + + //----------------------------------------------------- + + needed = false; + + if (!bcurvePoints.empty() && bcurvePoints[0] != 0) { + dCurve = new DiagonalCurve (bcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + butili = true; + } + } + + fillCurveArray(dCurve, boutCurve, skip, needed); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } + + //----------------------------------------------- + needed = false; + + if (!cccurvePoints.empty() && cccurvePoints[0] != 0) { + dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogram /*&& histogramCropped*/) { + histNeededC = true; + } + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + ccutili = true; + } + } + + if (histNeededC) { + for (int i = 0; i < k * adjustr; i++) { //32768*1.414 + ... + float hval = dCcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); // + outBeforeCCurveHistogram[hi] += histogramC[i] ; + } + } + + fillCurveArray(dCurve, satCurve, skip, needed); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } + + //---------------------------- + needed = false; + + if (!lccurvePoints.empty() && lccurvePoints[0] != 0) { + dCurve = new DiagonalCurve (lccurvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeLCurveHistogram /*&& histogramCropped*/) { + histNeededLC = true; + } + + if (dCurve && !dCurve->isIdentity()) { + needed = true; + cclutili = true; + } + } + + if (histNeededLC) { + for (int i = 0; i < k * adjustr; i++) { //32768*1.414 + ... + float hval = dCcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); // + outBeforeLCurveHistogram[hi] += histogramLC[i] ; + } + } + + + fillCurveArray(dCurve, lhskCurve, skip, needed); + + if (dCurve) { + delete dCurve; + dCurve = NULL; + } + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +SSEFUNCTION void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, + double shcompr, double br, double contr, + procparams::ToneCurveParams::eTCModeId curveMode, const std::vector& curvePoints, + procparams::ToneCurveParams::eTCModeId curveMode2, const std::vector& curvePoints2, + LUTu & histogram, LUTu & histogramCropped, + LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, + LUTu & outBeforeCCurveHistogram, + ToneCurve & customToneCurve1, + ToneCurve & customToneCurve2, + int skip) +{ + + // the curve shapes are defined in sRGB gamma, but the output curves will operate on linear floating point data, + // hence we do both forward and inverse gamma conversions here. + const float gamma_ = Color::sRGBGammaCurve; + const float start = expf(gamma_ * logf( -0.055 / ((1.0 / gamma_ - 1.0) * 1.055 ))); + const float slope = 1.055 * powf (start, 1.0 / gamma_ - 1) - 0.055 / start; + const float mul = 1.055; + const float add = 0.055; + + // a: slope of the curve, black: starting point at the x axis + const float a = powf (2.0, ecomp); + + // clear array that stores histogram valid before applying the custom curve + outBeforeCCurveHistogram.clear(); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + DiagonalCurve* brightcurve = NULL; + + // check if brightness curve is needed + if (br > 0.00001 || br < -0.00001) { + + std::vector brightcurvePoints; + brightcurvePoints.resize(9); + brightcurvePoints.at(0) = double(DCT_NURBS); + + brightcurvePoints.at(1) = 0.; //black point. Value in [0 ; 1] range + brightcurvePoints.at(2) = 0.; //black point. Value in [0 ; 1] range + + if(br > 0) { + brightcurvePoints.at(3) = 0.1; //toe point + brightcurvePoints.at(4) = 0.1 + br / 150.0; //value at toe point + + brightcurvePoints.at(5) = 0.7; //shoulder point + brightcurvePoints.at(6) = min(1.0, 0.7 + br / 300.0); //value at shoulder point + } else { + brightcurvePoints.at(3) = max(0.0, 0.1 - br / 150.0); //toe point + brightcurvePoints.at(4) = 0.1; //value at toe point + + brightcurvePoints.at(5) = 0.7 - br / 300.0; //shoulder point + brightcurvePoints.at(6) = 0.7; //value at shoulder point + } + + brightcurvePoints.at(7) = 1.; // white point + brightcurvePoints.at(8) = 1.; // value at white point + + brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip); + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details + float exp_scale = a; + float scale = 65536.0; + float comp = (max(0.0, ecomp) + 1.0) * hlcompr / 100.0; + float shoulder = ((scale / max(1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1; + //printf("shoulder = %e\n",shoulder); + //printf ("exp_scale= %f comp= %f def_mul=%f a= %f \n",exp_scale,comp,def_mul,a); + + if (comp <= 0.0f) + for (int i = 0; i < 0x10000; i++) { + hlCurve[i] = exp_scale; + } + else { + for (int i = 0; i <= shoulder; i++) { + hlCurve[i] = exp_scale; + } + + float scalemshoulder = scale - shoulder; + + for (int i = shoulder + 1; i < 0x10000; i++) { + // change to [0,1] range + float val = (float)i - shoulder; + float R = val * comp / (scalemshoulder); + hlCurve[i] = xlog(1.0 + R * exp_scale) / R; // don't use xlogf or 1.f here. Leads to errors caused by too low precision + } + } + + + // curve without contrast + LUTf dcurve(0x10000); + + //%%%%%%%%%%%%%%%%%%%%%%%%%% + // change to [0,1] range + shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value. + float val = 1.f / 65535.f; + float val2 = simplebasecurve (val, black, 0.015 * shcompr); + shCurve[0] = CLIPD(val2) / val; + val = 0.0; + // gamma correction + val = gamma (val, gamma_, start, slope, mul, add); + + // apply brightness curve + if (brightcurve) { + val = brightcurve->getVal (val); // TODO: getVal(double) is very slow! Optimize with a LUTf + } + + // store result in a temporary array + dcurve[0] = CLIPD(val); + + #pragma omp parallel for + + for (int i = 1; i < 0x10000; i++) { + float val; + val = (float)i / 65535.0f; + + float val2 = simplebasecurve (val, black, 0.015 * shcompr); + shCurve[i] = CLIPD(val2) / val; + + // gamma correction + val = gamma (val, gamma_, start, slope, mul, add); + + // apply brightness curve + if (brightcurve) { + val = brightcurve->getVal (val); // TODO: getVal(double) is very slow! Optimize with a LUTf + } + + // store result in a temporary array + dcurve[i] = CLIPD(val); + } + + if (brightcurve) { + delete brightcurve; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // check if contrast curve is needed + if (contr > 0.00001 || contr < -0.00001) { + + // compute mean luminance of the image with the curve applied + unsigned int sum = 0; + float avg = 0; + + //double sqavg = 0; + for (int i = 0; i <= 0xffff; i++) { + float fi = i; + fi *= hlCurve[i]; + avg += dcurve[(int)(shCurve[fi] * fi)] * histogram[i]; + //sqavg += dcurve[i]*dcurve[i] * histogram[i]; + sum += histogram[i]; + } + + avg /= sum; + //sqavg /= sum; + //double stddev = sqrt(sqavg-avg*avg); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + std::vector contrastcurvePoints; + contrastcurvePoints.resize(9); + contrastcurvePoints.at(0) = double(DCT_NURBS); + + contrastcurvePoints.at(1) = 0; //black point. Value in [0 ; 1] range + contrastcurvePoints.at(2) = 0; //black point. Value in [0 ; 1] range + + contrastcurvePoints.at(3) = avg - avg * (0.6 - contr / 250.0); //toe point + contrastcurvePoints.at(4) = avg - avg * (0.6 + contr / 250.0); //value at toe point + + contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - contr / 250.0); //shoulder point + contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + contr / 250.0); //value at shoulder point + + contrastcurvePoints.at(7) = 1.; // white point + contrastcurvePoints.at(8) = 1.; // value at white point + + DiagonalCurve* contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // apply contrast enhancement + for (int i = 0; i <= 0xffff; i++) { + dcurve[i] = contrastcurve->getVal (dcurve[i]); + } + + delete contrastcurve; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // create second curve if needed + bool histNeeded = false; + DiagonalCurve* tcurve = NULL; + customToneCurve2.Reset(); + + if (!curvePoints2.empty() && curvePoints2[0] > DCT_Linear && curvePoints2[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePoints2, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogram /*&& histogramCropped*/) { + histNeeded = true; + } + } + + if (tcurve) { + if (!tcurve->isIdentity()) { + customToneCurve2.Set(tcurve, gamma_, start, slope, mul, add); + } + + delete tcurve; + tcurve = NULL; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // create first curve if needed + customToneCurve1.Reset(); + + if (!curvePoints.empty() && curvePoints[0] > DCT_Linear && curvePoints[0] < DCT_Unchanged) { + tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogram /*&& histogramCropped*/) { + histNeeded = true; + } + } + + if (tcurve) { + if (!tcurve->isIdentity()) { + customToneCurve1.Set(tcurve, gamma_, start, slope, mul, add); + } + + delete tcurve; + tcurve = NULL; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // create curve bw + // curve 2 + /* DiagonalCurve* tbwcurve = NULL; + customToneCurvebw2.Reset(); + + if (!curvePointsbw2.empty() && curvePointsbw2[0]>DCT_Linear && curvePointsbw2[0]isIdentity()) { + delete tbwcurve; + tbwcurve = NULL; + } + else + customToneCurvebw2.Set(tbwcurve); + delete tbwcurve; + tbwcurve = NULL; + } + + customToneCurvebw1.Reset(); + + if (!curvePointsbw.empty() && curvePointsbw[0]>DCT_Linear && curvePointsbw[0]isIdentity()) { + delete tbwcurve; + tbwcurve = NULL; + } + else if (curveModeb != procparams::BlackWhiteParams::TC_MODE_STD_BW) { + customToneCurvebw1.Set(tbwcurve); + delete tbwcurve; + tbwcurve = NULL; + } + } + */ + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + for (int i = 0; i <= 0xffff; i++) { + float val = dcurve[i]; + + if (histNeeded) { + float fi = i; + float hval = hlCurve[i] * fi; + hval = dcurve[shCurve[hval] * hval]; + //if (needigamma) + // hval = igamma2 (hval); + int hi = (int)(255.0 * (hval)); + outBeforeCCurveHistogram[hi] += histogram/*Cropped*/[i] ; + } + + val = igamma (val, gamma_, start, slope, mul, add); + outCurve[i] = (65535.f * val); + } + + if (tcurve) { + delete tcurve; + } + + /*if (outBeforeCCurveHistogram) { + for (int i=0; i<256; i++) printf("i= %d bchist= %d \n",i,outBeforeCCurveHistogram[i]); + }*/ +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void CurveFactory::complexLCurve (double br, double contr, const std::vector& curvePoints, + LUTu & histogram, LUTu & histogramCropped, LUTf & outCurve, + LUTu & outBeforeCCurveHistogram, int skip, bool & utili) +{ + + // curve without contrast + LUTf dcurve(65536, 0); + + // clear array that stores histogram valid before applying the custom curve + if (outBeforeCCurveHistogram) { + outBeforeCCurveHistogram.clear(); + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // check if brightness curve is needed + if (br > 0.00001 || br < -0.00001) { + utili = true; + + std::vector brightcurvePoints; + brightcurvePoints.resize(9); + brightcurvePoints.at(0) = double(DCT_NURBS); + + brightcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range + brightcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range + + if (br > 0) { + brightcurvePoints.at(3) = 0.1; // toe point + brightcurvePoints.at(4) = 0.1 + br / 150.0; //value at toe point + + brightcurvePoints.at(5) = 0.7; // shoulder point + brightcurvePoints.at(6) = min(1.0, 0.7 + br / 300.0); //value at shoulder point + } else { + brightcurvePoints.at(3) = 0.1 - br / 150.0; // toe point + brightcurvePoints.at(4) = 0.1; // value at toe point + + brightcurvePoints.at(5) = min(1.0, 0.7 - br / 300.0); // shoulder point + brightcurvePoints.at(6) = 0.7; // value at shoulder point + } + + brightcurvePoints.at(7) = 1.; // white point + brightcurvePoints.at(8) = 1.; // value at white point + + DiagonalCurve* brightcurve = new DiagonalCurve (brightcurvePoints, CURVES_MIN_POLY_POINTS / skip); + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // Applying brightness curve + for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow + + // change to [0,1] range + float val = (float)i / 32767.0; + + // apply brightness curve + val = brightcurve->getVal (val); + + // store result in a temporary array + dcurve[i] = CLIPD(val); + } + + delete brightcurve; + } else { + for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow + // set the identity curve in the temporary array + dcurve[i] = (float)i / 32767.0; + } + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // check if contrast curve is needed + if (contr > 0.00001 || contr < -0.00001) { + utili = true; + + DiagonalCurve* contrastcurve = NULL; + + // compute mean luminance of the image with the curve applied + int sum = 0; + float avg = 0; + + //float sqavg = 0; + for (int i = 0; i < 32768; i++) { + avg += dcurve[i] * histogram[i]; + //sqavg += dcurve[i]*dcurve[i] * histogram[i]; + sum += histogram[i]; + } + + if(sum) { + avg /= sum; + //sqavg /= sum; + //float stddev = sqrt(sqavg-avg*avg); + // printf("avg=%f\n",avg); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + std::vector contrastcurvePoints; + contrastcurvePoints.resize(9); + contrastcurvePoints.at(0) = double(DCT_NURBS); + + contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range + contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range + + contrastcurvePoints.at(3) = avg - avg * (0.6 - contr / 250.0); // toe point + contrastcurvePoints.at(4) = avg - avg * (0.6 + contr / 250.0); // value at toe point + + contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point + contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point + + contrastcurvePoints.at(7) = 1.; // white point + contrastcurvePoints.at(8) = 1.; // value at white point + + contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + } else { + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image + std::vector contrastcurvePoints; + contrastcurvePoints.resize(5); + contrastcurvePoints.at(0) = double(DCT_NURBS); + + contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range + contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range + + contrastcurvePoints.at(3) = 1.; // white point + contrastcurvePoints.at(4) = 1.; // value at white point + + contrastcurve = new DiagonalCurve (contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip); + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + } + + // apply contrast enhancement + for (int i = 0; i < 32768; i++) { + dcurve[i] = contrastcurve->getVal (dcurve[i]); + } + + delete contrastcurve; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // create a curve if needed + DiagonalCurve* tcurve = NULL; + bool histNeeded = false; + + if (!curvePoints.empty() && curvePoints[0] != 0) { + tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip); + + if (outBeforeCCurveHistogram /*&& histogramCropped*/) { + histNeeded = true; + } + } + + if (tcurve && tcurve->isIdentity()) { + delete tcurve; + tcurve = NULL; + } + + if (tcurve) { + utili = true; //if active + + // L values go up to 32767, last stop is for highlight overflow + for (int i = 0; i < 32768; i++) { + float val; + + if (histNeeded) { + float hval = dcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); + outBeforeCCurveHistogram[hi] += histogram/*Cropped*/[i] ; + } + + // apply custom/parametric/NURBS curve, if any + val = tcurve->getVal (dcurve[i]); + + outCurve[i] = (32767.0 * val); + } + } else { + // Skip the slow getval method if no curve is used (or an identity curve) + // L values go up to 32767, last stop is for highlight overflow + for (int i = 0; i < 32768; i++) { + if (histNeeded) { + float hval = dcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); + outBeforeCCurveHistogram[hi] += histogram/*Cropped*/[i] ; + } + + outCurve[i] = 32767.0 * dcurve[i]; + } + } + + for (int i = 32768; i < 65536; i++) { + outCurve[i] = (float)i; + } + + if (tcurve) { + delete tcurve; + } + + /*if (outBeforeCCurveHistogram) { + for (int i=0; i<256; i++) printf("i= %d bchist= %d \n",i,outBeforeCCurveHistogram[i]); + }*/ +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void CurveFactory::RGBCurve (const std::vector& curvePoints, LUTf & outCurve, int skip) +{ + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // create a curve if needed + DiagonalCurve* tcurve = NULL; + + if (!curvePoints.empty() && curvePoints[0] != 0) { + tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS / skip); + } + + if (tcurve && tcurve->isIdentity()) { + delete tcurve; + tcurve = NULL; + } + + if (tcurve) { + if (!outCurve) { + outCurve(65536, 0); + } + + for (int i = 0; i < 65536; i++) { + // apply custom/parametric/NURBS curve, if any + + // RGB curves are defined with sRGB gamma, but operate on linear data + float val = float(i) / 65535.f; + val = CurveFactory::gamma2 (val); + val = tcurve->getVal(val); + val = CurveFactory::igamma2 (val); + //float val = tcurve->getVal ((float)i/65536.0f); + outCurve[i] = (65536.0f * val); + } + + delete tcurve; + } + // let the LUTf empty for identity curves + else { + outCurve.reset(); + } + +} + + +void ColorAppearance::Reset() +{ lutColCurve.reset(); } // Fill a LUT with X/Y, ranged 0xffff -void ColorAppearance::Set(Curve *pCurve) { +void ColorAppearance::Set(Curve *pCurve) +{ lutColCurve(65536); - for (int i=0; i<65536; i++) lutColCurve[i] = pCurve->getVal(double(i)/65535.) * 65535.; + + for (int i = 0; i < 65536; i++) { + lutColCurve[i] = pCurve->getVal(double(i) / 65535.) * 65535.; + } } -void ToneCurve::Reset() { +void ToneCurve::Reset() +{ lutToneCurve.reset(); } // Fill a LUT with X/Y, ranged 0xffff -void ToneCurve::Set(Curve *pCurve, float gamma, float start, float slope, float mul, float add) { - lutToneCurve(65536); - if (gamma <= 0.0 || gamma == 1.) { - for (int i=0; i<65536; i++) lutToneCurve[i] = (float)pCurve->getVal(float(i)/65535.f) * 65535.f; - } else { - // apply gamma, that is 'pCurve' is defined with the given gamma and here we convert it to a curve in linear space - for (int i=0; i<65536; i++) { - float val = float(i)/65535.f; - val = CurveFactory::gamma (val, gamma, start, slope, mul, add); - val = pCurve->getVal(val); - val = CurveFactory::igamma (val, gamma, start, slope, mul, add); - lutToneCurve[i] = val * 65535.f; - } - } +void ToneCurve::Set(Curve *pCurve, float gamma, float start, float slope, float mul, float add) +{ + lutToneCurve(65536); + + if (gamma <= 0.0 || gamma == 1.) { + for (int i = 0; i < 65536; i++) { + lutToneCurve[i] = (float)pCurve->getVal(float(i) / 65535.f) * 65535.f; + } + } else { + // apply gamma, that is 'pCurve' is defined with the given gamma and here we convert it to a curve in linear space + for (int i = 0; i < 65536; i++) { + float val = float(i) / 65535.f; + val = CurveFactory::gamma (val, gamma, start, slope, mul, add); + val = pCurve->getVal(val); + val = CurveFactory::igamma (val, gamma, start, slope, mul, add); + lutToneCurve[i] = val * 65535.f; + } + } } -void OpacityCurve::Reset() { - lutOpacityCurve.reset(); +void OpacityCurve::Reset() +{ + lutOpacityCurve.reset(); } -void OpacityCurve::Set(const Curve *pCurve) { - if (pCurve->isIdentity()) { - lutOpacityCurve.reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutOpacityCurve(501); // raise this value if the quality suffers from this number of samples +void OpacityCurve::Set(const Curve *pCurve) +{ + if (pCurve->isIdentity()) { + lutOpacityCurve.reset(); // raise this value if the quality suffers from this number of samples + return; + } - for (int i=0; i<501; i++) lutOpacityCurve[i] = pCurve->getVal(double(i)/500.); - //lutOpacityCurve.dump("opacity"); + lutOpacityCurve(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + lutOpacityCurve[i] = pCurve->getVal(double(i) / 500.); + } + + //lutOpacityCurve.dump("opacity"); } -void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili) { - FlatCurve* tcurve = NULL; +void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili) +{ + FlatCurve* tcurve = NULL; - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0]setIdentityValue(0.); - } - if (tcurve) { - Set(tcurve);opautili=true; - delete tcurve; - tcurve = NULL; - } + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + tcurve = new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve->setIdentityValue(0.); + } + + if (tcurve) { + Set(tcurve); + opautili = true; + delete tcurve; + tcurve = NULL; + } } WavCurve::WavCurve() : sum(0.f) {}; -void WavCurve::Reset() { - lutWavCurve.reset(); - sum = 0.f; +void WavCurve::Reset() +{ + lutWavCurve.reset(); + sum = 0.f; } -void WavCurve::Set(const Curve &pCurve) { - if (pCurve.isIdentity()) { - Reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutWavCurve(501); // raise this value if the quality suffers from this number of samples - sum=0.f; - for (int i=0; i<501; i++) { - lutWavCurve[i] = pCurve.getVal(double(i)/500.); - if(lutWavCurve[i] < 0.02f) - lutWavCurve[i] = 0.02f;//avoid 0.f for wavelet : under 0.01f quasi no action for each value - sum += lutWavCurve[i]; - } - //lutWavCurve.dump("wav"); +void WavCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutWavCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutWavCurve[i] = pCurve.getVal(double(i) / 500.); + + if(lutWavCurve[i] < 0.02f) { + lutWavCurve[i] = 0.02f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutWavCurve[i]; + } + + //lutWavCurve.dump("wav"); } -void WavCurve::Set(const std::vector &curvePoints) { - - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] &curvePoints) +{ + + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } } -WavOpacityCurveRG::WavOpacityCurveRG(){}; +WavOpacityCurveRG::WavOpacityCurveRG() {}; -void WavOpacityCurveRG::Reset() { - lutOpacityCurveRG.reset(); +void WavOpacityCurveRG::Reset() +{ + lutOpacityCurveRG.reset(); } -void WavOpacityCurveRG::Set(const Curve &pCurve) { - if (pCurve.isIdentity()) { - Reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutOpacityCurveRG(501); // raise this value if the quality suffers from this number of samples +void WavOpacityCurveRG::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } - for (int i=0; i<501; i++) lutOpacityCurveRG[i] = pCurve.getVal(double(i)/500.); + lutOpacityCurveRG(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + lutOpacityCurveRG[i] = pCurve.getVal(double(i) / 500.); + } } -void WavOpacityCurveRG::Set(const std::vector &curvePoints) { - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] &curvePoints) +{ + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } } -WavOpacityCurveBY::WavOpacityCurveBY(){}; +WavOpacityCurveBY::WavOpacityCurveBY() {}; -void WavOpacityCurveBY::Reset() { - lutOpacityCurveBY.reset(); +void WavOpacityCurveBY::Reset() +{ + lutOpacityCurveBY.reset(); } -void WavOpacityCurveBY::Set(const Curve &pCurve) { - if (pCurve.isIdentity()) { - lutOpacityCurveBY.reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutOpacityCurveBY(501); // raise this value if the quality suffers from this number of samples +void WavOpacityCurveBY::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + lutOpacityCurveBY.reset(); // raise this value if the quality suffers from this number of samples + return; + } - for (int i=0; i<501; i++) lutOpacityCurveBY[i] = pCurve.getVal(double(i)/500.); + lutOpacityCurveBY(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + lutOpacityCurveBY[i] = pCurve.getVal(double(i) / 500.); + } } -void WavOpacityCurveBY::Set(const std::vector &curvePoints) { - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] &curvePoints) +{ + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } } -WavOpacityCurveW::WavOpacityCurveW(){}; +WavOpacityCurveW::WavOpacityCurveW() {}; -void WavOpacityCurveW::Reset() { - lutOpacityCurveW.reset(); +void WavOpacityCurveW::Reset() +{ + lutOpacityCurveW.reset(); } -void WavOpacityCurveW::Set(const Curve &pCurve) { - if (pCurve.isIdentity()) { - lutOpacityCurveW.reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutOpacityCurveW(501); // raise this value if the quality suffers from this number of samples +void WavOpacityCurveW::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + lutOpacityCurveW.reset(); // raise this value if the quality suffers from this number of samples + return; + } - for (int i=0; i<501; i++) lutOpacityCurveW[i] = pCurve.getVal(double(i)/500.); + lutOpacityCurveW(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + lutOpacityCurveW[i] = pCurve.getVal(double(i) / 500.); + } } -void WavOpacityCurveW::Set(const std::vector &curvePoints) { - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] &curvePoints) +{ + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } } -WavOpacityCurveWL::WavOpacityCurveWL(){}; +WavOpacityCurveWL::WavOpacityCurveWL() {}; -void WavOpacityCurveWL::Reset() { - lutOpacityCurveWL.reset(); +void WavOpacityCurveWL::Reset() +{ + lutOpacityCurveWL.reset(); } -void WavOpacityCurveWL::Set(const Curve &pCurve) { - if (pCurve.isIdentity()) { - lutOpacityCurveWL.reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutOpacityCurveWL(501); // raise this value if the quality suffers from this number of samples +void WavOpacityCurveWL::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + lutOpacityCurveWL.reset(); // raise this value if the quality suffers from this number of samples + return; + } - for (int i=0; i<501; i++) lutOpacityCurveWL[i] = pCurve.getVal(double(i)/500.); + lutOpacityCurveWL(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + lutOpacityCurveWL[i] = pCurve.getVal(double(i) / 500.); + } } -void WavOpacityCurveWL::Set(const std::vector &curvePoints) { - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] &curvePoints) +{ + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } } NoiseCurve::NoiseCurve() : sum(0.f) {}; -void NoiseCurve::Reset() { - lutNoiseCurve.reset(); - sum = 0.f; +void NoiseCurve::Reset() +{ + lutNoiseCurve.reset(); + sum = 0.f; } -void NoiseCurve::Set(const Curve &pCurve) { - if (pCurve.isIdentity()) { - Reset(); // raise this value if the quality suffers from this number of samples - return; - } - lutNoiseCurve(501); // raise this value if the quality suffers from this number of samples - sum=0.f; - for (int i=0; i<501; i++) { - lutNoiseCurve[i] = pCurve.getVal(double(i)/500.); - if(lutNoiseCurve[i] < 0.01f) - lutNoiseCurve[i] = 0.01f;//avoid 0.f for wavelet : under 0.01f quasi no action for each value - sum += lutNoiseCurve[i]; //minima for Wavelet about 6.f or 7.f quasi no action - } - //lutNoisCurve.dump("Nois"); +void NoiseCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + Reset(); // raise this value if the quality suffers from this number of samples + return; + } + + lutNoiseCurve(501); // raise this value if the quality suffers from this number of samples + sum = 0.f; + + for (int i = 0; i < 501; i++) { + lutNoiseCurve[i] = pCurve.getVal(double(i) / 500.); + + if(lutNoiseCurve[i] < 0.01f) { + lutNoiseCurve[i] = 0.01f; //avoid 0.f for wavelet : under 0.01f quasi no action for each value + } + + sum += lutNoiseCurve[i]; //minima for Wavelet about 6.f or 7.f quasi no action + } + + //lutNoisCurve.dump("Nois"); } -void NoiseCurve::Set(const std::vector &curvePoints) { +void NoiseCurve::Set(const std::vector &curvePoints) +{ - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } } -void ColorGradientCurve::Reset() { - lut1.reset(); - lut2.reset(); - lut3.reset(); +void ColorGradientCurve::Reset() +{ + lut1.reset(); + lut2.reset(); + lut3.reset(); } -void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) { - if (pCurve->isIdentity()) { - lut1.reset(); - lut2.reset(); - lut3.reset(); - return; - } - if (!lut1) { - lut1(501); - lut2(501); - lut3(501); - } +void ColorGradientCurve::SetXYZ(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) +{ + if (pCurve->isIdentity()) { + lut1.reset(); + lut2.reset(); + lut3.reset(); + return; + } - float r, g, b, xx, yy, zz; - float lr1,lr2; - int upperBound = lut1.getUpperBound(); - if (pCurve->isIdentity()) { - Color::hsv2rgb(0.5f, satur, lumin, r, g, b); - Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); - - for (int i=0; i<=500; ++i) { - // WARNING: set the identity value according to what is set in the GUI - lut1[i] = xx; - lut2[i] = yy; - lut3[i] = zz; - } - return; - } + if (!lut1) { + lut1(501); + lut2(501); + lut3(501); + } - int nPoints = pCurve->getSize(); - int ptNum = 0; - double nextX, nextY; - pCurve->getControlPoint(ptNum, nextX, nextY); - double prevY = nextY; - double dY = 0.; - low=nextX; - lr1=(0.5f+low)/2.f;//optimize use of gamut in low light..one can optimize more using directly low ? - //lr1=low; - - for (int i=0; i<=upperBound; ++i) { - double x = double(i)/double(upperBound); + float r, g, b, xx, yy, zz; + float lr1, lr2; + int upperBound = lut1.getUpperBound(); - if (x > nextX) { - ++ptNum; - if (ptNum < nPoints) { - prevY = nextY; - pCurve->getControlPoint(ptNum, nextX, nextY); - dY = nextY - prevY; - high=nextX; - lr2=(0.5f + high)/2.f;//optimize use of gamut in high light..one can optimize more using directly high ? - //lr2=high; - } - } + if (pCurve->isIdentity()) { + Color::hsv2rgb(0.5f, satur, lumin, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); - if (!ptNum) { - Color::hsv2rgb(float(prevY), satur, lr1, r, g, b); - Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); - lut1[i] = xx; - lut2[i] = yy; - lut3[i] = zz; - } - else if (ptNum >= nPoints) { - Color::hsv2rgb(float(nextY), satur, lr2, r, g, b); - Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); - lut1[i] = xx; - lut2[i] = yy; - lut3[i] = zz; - } - else { - double currY = pCurve->getVal(x) - prevY; - if (dY > 0.000001 || dY < -0.000001) { - float r1, g1, b1, r2, g2, b2, ro, go, bo; - Color::hsv2rgb(float(prevY), satur, lr1, r1, g1, b1); - Color::hsv2rgb(float(nextY), satur, lr2, r2, g2, b2); - bool chr = false; - bool lum = true; - LUTf dum; - float X1,X2,Y1,Y2,Z1,Z2,L1,a_1,b_1,c1,h1; - Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb); - Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); - //I use XYZ to mix color 1 and 2 rather than rgb (gamut) and rather than Lab artifacts - X1 = X1 + (X2-X1)*currY/dY; if(X1<0.f) X1=0.f;//negative value not good - Y1 = Y1 + (Y2-Y1)*currY/dY; if(Y1<0.f) Y1=0.f; - Z1 = Z1 + (Z2-Z1)*currY/dY; if(Z1<0.f) Z1=0.f; - Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1);//prepare to gamut control - Color::Lab2Lch(a_1, b_1, c1, h1); - float Lr=L1/327.68f; - float RR,GG,BB; - #ifndef NDEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); - #else - Color::gamutLchonly(h1,Lr,c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); - #endif - L1=Lr*327.68f; - float a,b,X,Y,Z; - // converting back to rgb - Color::Lch2Lab(c1, h1, a, b); - Color::Lab2XYZ(L1, a, b, X, Y, Z); - lut1[i] = X; - lut2[i] = Y; - lut3[i] = Z; - } - else { - Color::hsv2rgb(float(nextY), satur, lumin, r, g, b); - Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); - lut1[i] = xx; - lut2[i] = yy; - lut3[i] = zz; - } - } - } - /* - #ifndef NDEBUG - lutRed.dump("red"); - lutGreen.dump("green"); - lutBlue.dump("blue"); - #endif - */ + for (int i = 0; i <= 500; ++i) { + // WARNING: set the identity value according to what is set in the GUI + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } + + return; + } + + int nPoints = pCurve->getSize(); + int ptNum = 0; + double nextX, nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + double prevY = nextY; + double dY = 0.; + low = nextX; + lr1 = (0.5f + low) / 2.f; //optimize use of gamut in low light..one can optimize more using directly low ? + //lr1=low; + + for (int i = 0; i <= upperBound; ++i) { + double x = double(i) / double(upperBound); + + if (x > nextX) { + ++ptNum; + + if (ptNum < nPoints) { + prevY = nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + dY = nextY - prevY; + high = nextX; + lr2 = (0.5f + high) / 2.f; //optimize use of gamut in high light..one can optimize more using directly high ? + //lr2=high; + } + } + + if (!ptNum) { + Color::hsv2rgb(float(prevY), satur, lr1, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } else if (ptNum >= nPoints) { + Color::hsv2rgb(float(nextY), satur, lr2, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } else { + double currY = pCurve->getVal(x) - prevY; + + if (dY > 0.000001 || dY < -0.000001) { + float r1, g1, b1, r2, g2, b2, ro, go, bo; + Color::hsv2rgb(float(prevY), satur, lr1, r1, g1, b1); + Color::hsv2rgb(float(nextY), satur, lr2, r2, g2, b2); + bool chr = false; + bool lum = true; + LUTf dum; + float X1, X2, Y1, Y2, Z1, Z2, L1, a_1, b_1, c1, h1; + Color::rgbxyz(r2, g2, b2, X2, Y2, Z2, xyz_rgb); + Color::rgbxyz(r1, g1, b1, X1, Y1, Z1, xyz_rgb); + //I use XYZ to mix color 1 and 2 rather than rgb (gamut) and rather than Lab artifacts + X1 = X1 + (X2 - X1) * currY / dY; + + if(X1 < 0.f) { + X1 = 0.f; //negative value not good + } + + Y1 = Y1 + (Y2 - Y1) * currY / dY; + + if(Y1 < 0.f) { + Y1 = 0.f; + } + + Z1 = Z1 + (Z2 - Z1) * currY / dY; + + if(Z1 < 0.f) { + Z1 = 0.f; + } + + Color::XYZ2Lab(X1, Y1, Z1, L1, a_1, b_1);//prepare to gamut control + Color::Lab2Lch(a_1, b_1, c1, h1); + float Lr = L1 / 327.68f; + float RR, GG, BB; +#ifndef NDEBUG + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f, neg, more_rgb); +#else + Color::gamutLchonly(h1, Lr, c1, RR, GG, BB, xyz_rgb, false, 0.15f, 0.96f); +#endif + L1 = Lr * 327.68f; + float a, b, X, Y, Z; + // converting back to rgb + Color::Lch2Lab(c1, h1, a, b); + Color::Lab2XYZ(L1, a, b, X, Y, Z); + lut1[i] = X; + lut2[i] = Y; + lut3[i] = Z; + } else { + Color::hsv2rgb(float(nextY), satur, lumin, r, g, b); + Color::rgbxyz(r, g, b, xx, yy, zz, xyz_rgb); + lut1[i] = xx; + lut2[i] = yy; + lut3[i] = zz; + } + } + } + + /* + #ifndef NDEBUG + lutRed.dump("red"); + lutGreen.dump("green"); + lutBlue.dump("blue"); + #endif + */ } -void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) { - FlatCurve* tcurve = NULL; +void ColorGradientCurve::SetXYZ(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3], float satur, float lumin) +{ + FlatCurve* tcurve = NULL; - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] FCT_Linear && curvePoints[0] < FCT_Unchanged) { + tcurve = new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + } + + if (tcurve) { + SetXYZ(tcurve, xyz_rgb, rgb_xyz, satur, lumin); + delete tcurve; + tcurve = NULL; + } } -void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) { - if (pCurve->isIdentity()) { - lut1.reset(); - lut2.reset(); - lut3.reset(); - return; - } - if (!lut1) { - lut1(501); - lut2(501); - lut3(501); - } +void ColorGradientCurve::SetRGB(const Curve *pCurve, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) +{ + if (pCurve->isIdentity()) { + lut1.reset(); + lut2.reset(); + lut3.reset(); + return; + } - float r, g, b; + if (!lut1) { + lut1(501); + lut2(501); + lut3(501); + } - int upperBound = lut1.getUpperBound(); + float r, g, b; - int nPoints = pCurve->getSize(); - int ptNum = 0; - double nextX, nextY; - pCurve->getControlPoint(ptNum, nextX, nextY); - double prevY = nextY; - double dY = 0.; - Color::eInterpolationDirection dir = Color::ID_DOWN; - for (int i=0; i<=upperBound; ++i) { - double x = double(i)/double(upperBound); + int upperBound = lut1.getUpperBound(); - if (x > nextX) { - ++ptNum; - if (ptNum < nPoints) { - prevY = nextY; - pCurve->getControlPoint(ptNum, nextX, nextY); - dY = nextY - prevY; - dir = Color::getHueInterpolationDirection(prevY, nextY, Color::IP_SHORTEST); - } - } + int nPoints = pCurve->getSize(); + int ptNum = 0; + double nextX, nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + double prevY = nextY; + double dY = 0.; + Color::eInterpolationDirection dir = Color::ID_DOWN; - if (!ptNum) { - Color::hsv2rgb(float(prevY), 1.f, 1.f, r, g, b); - lut1[i] = r; - lut2[i] = g; - lut3[i] = b; - } - else if (ptNum >= nPoints) { - Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b); - lut1[i] = r; - lut2[i] = g; - lut3[i] = b; - } - else { - double currY = pCurve->getVal(x) - prevY; - if (dY > 0.0000001 || dY < -0.0000001) { - #if 1 - float ro, go, bo; - double h2 = Color::interpolateHueHSV(prevY, nextY, currY/dY, dir); - Color::hsv2rgb(h2, 1.f, 1.f, ro, go, bo); - #else - float r1, g1, b1, r2, g2, b2, ro, go, bo; - Color::hsv2rgb(float(prevY), 1., 1., r1, g1, b1); - Color::hsv2rgb(float(nextY), 1., 1., r2, g2, b2); - Color::interpolateRGBColor(currY/dY, r1, g1, b1, r2, g2, b2, Color::CHANNEL_LIGHTNESS|Color::CHANNEL_CHROMATICITY|Color::CHANNEL_HUE, xyz_rgb, rgb_xyz, ro, go, bo); - #endif - lut1[i] = ro; - lut2[i] = go; - lut3[i] = bo; - } - else { - Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b); - lut1[i] = r; - lut2[i] = g; - lut3[i] = b; - } - } - } - /* - #ifndef NDEBUG - lut1.dump("red"); - lut2.dump("green"); - lut3.dump("blue"); - #endif - */ + for (int i = 0; i <= upperBound; ++i) { + double x = double(i) / double(upperBound); + + if (x > nextX) { + ++ptNum; + + if (ptNum < nPoints) { + prevY = nextY; + pCurve->getControlPoint(ptNum, nextX, nextY); + dY = nextY - prevY; + dir = Color::getHueInterpolationDirection(prevY, nextY, Color::IP_SHORTEST); + } + } + + if (!ptNum) { + Color::hsv2rgb(float(prevY), 1.f, 1.f, r, g, b); + lut1[i] = r; + lut2[i] = g; + lut3[i] = b; + } else if (ptNum >= nPoints) { + Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b); + lut1[i] = r; + lut2[i] = g; + lut3[i] = b; + } else { + double currY = pCurve->getVal(x) - prevY; + + if (dY > 0.0000001 || dY < -0.0000001) { +#if 1 + float ro, go, bo; + double h2 = Color::interpolateHueHSV(prevY, nextY, currY / dY, dir); + Color::hsv2rgb(h2, 1.f, 1.f, ro, go, bo); +#else + float r1, g1, b1, r2, g2, b2, ro, go, bo; + Color::hsv2rgb(float(prevY), 1., 1., r1, g1, b1); + Color::hsv2rgb(float(nextY), 1., 1., r2, g2, b2); + Color::interpolateRGBColor(currY / dY, r1, g1, b1, r2, g2, b2, Color::CHANNEL_LIGHTNESS | Color::CHANNEL_CHROMATICITY | Color::CHANNEL_HUE, xyz_rgb, rgb_xyz, ro, go, bo); +#endif + lut1[i] = ro; + lut2[i] = go; + lut3[i] = bo; + } else { + Color::hsv2rgb(float(nextY), 1.f, 1.f, r, g, b); + lut1[i] = r; + lut2[i] = g; + lut3[i] = b; + } + } + } + + /* + #ifndef NDEBUG + lut1.dump("red"); + lut2.dump("green"); + lut3.dump("blue"); + #endif + */ } -void ColorGradientCurve::SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) { - FlatCurve* tcurve = NULL; +void ColorGradientCurve::SetRGB(const std::vector &curvePoints, const double xyz_rgb[3][3], const double rgb_xyz[3][3]) +{ + FlatCurve* tcurve = NULL; - if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0] FCT_Linear && curvePoints[0] < FCT_Unchanged) { + tcurve = new FlatCurve (curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + } + + if (tcurve) { + SetRGB(tcurve, xyz_rgb, rgb_xyz); + delete tcurve; + tcurve = NULL; + } } -void ColorGradientCurve::getVal(float index, float &r, float &g, float &b) const { - r = lut1[index*500.f]; - g = lut2[index*500.f]; - b = lut3[index*500.f]; +void ColorGradientCurve::getVal(float index, float &r, float &g, float &b) const +{ + r = lut1[index * 500.f]; + g = lut2[index * 500.f]; + b = lut3[index * 500.f]; } // this is a generic cubic spline implementation, to clean up we could probably use something already existing elsewhere -void PerceptualToneCurve::cubic_spline(const float x[], const float y[], const int len, const float out_x[], float out_y[], const int out_len) { +void PerceptualToneCurve::cubic_spline(const float x[], const float y[], const int len, const float out_x[], float out_y[], const int out_len) +{ int i, j; float **A = (float **)malloc(2 * len * sizeof(*A)); float *As = (float *)calloc(1, 2 * len * 2 * len * sizeof(*As)); - float *b = (float *)calloc(1, 2*len*sizeof(*b)); - float *c = (float *)calloc(1, 2*len*sizeof(*c)); - float *d = (float *)calloc(1, 2*len*sizeof(*d)); + float *b = (float *)calloc(1, 2 * len * sizeof(*b)); + float *c = (float *)calloc(1, 2 * len * sizeof(*c)); + float *d = (float *)calloc(1, 2 * len * sizeof(*d)); - for (i = 0; i < 2*len; i++) { - A[i] = &As[2*len*i]; + for (i = 0; i < 2 * len; i++) { + A[i] = &As[2 * len * i]; } - for (i = len-1; i > 0; i--) { - b[i] = (y[i] - y[i-1]) / (x[i] - x[i-1]); - d[i-1] = x[i] - x[i-1]; + for (i = len - 1; i > 0; i--) { + b[i] = (y[i] - y[i - 1]) / (x[i] - x[i - 1]); + d[i - 1] = x[i] - x[i - 1]; } - for (i = 1; i < len-1; i++) { - A[i][i] = 2 * (d[i-1] + d[i]); + for (i = 1; i < len - 1; i++) { + A[i][i] = 2 * (d[i - 1] + d[i]); + if (i > 1) { - A[i][i-1] = d[i-1]; - A[i-1][i] = d[i-1]; + A[i][i - 1] = d[i - 1]; + A[i - 1][i] = d[i - 1]; } - A[i][len-1] = 6 * (b[i+1] - b[i]); + + A[i][len - 1] = 6 * (b[i + 1] - b[i]); } - for(i = 1; i < len-2; i++) { - float v = A[i+1][i] / A[i][i]; - for(j = 1; j <= len-1; j++) { - A[i+1][j] -= v * A[i][j]; + for(i = 1; i < len - 2; i++) { + float v = A[i + 1][i] / A[i][i]; + + for(j = 1; j <= len - 1; j++) { + A[i + 1][j] -= v * A[i][j]; } } - for(i = len-2; i > 0; i--) { + for(i = len - 2; i > 0; i--) { float acc = 0; - for(j = i; j <= len-2; j++) { - acc += A[i][j]*c[j]; + + for(j = i; j <= len - 2; j++) { + acc += A[i][j] * c[j]; } - c[i] = (A[i][len-1] - acc) / A[i][i]; + + c[i] = (A[i][len - 1] - acc) / A[i][i]; } for (i = 0; i < out_len; i++) { float x_out = out_x[i]; float y_out = 0; - for (j = 0; j < len-1; j++) { - if (x[j] <= x_out && x_out <= x[j+1]) { + + for (j = 0; j < len - 1; j++) { + if (x[j] <= x_out && x_out <= x[j + 1]) { float v = x_out - x[j]; y_out = y[j] + - ((y[j+1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j+1] * d[j]) / 6) * v + - (c[j] * 0.5) * v*v + - ((c[j+1] - c[j]) / (6 * d[j])) * v*v*v; + ((y[j + 1] - y[j]) / d[j] - (2 * d[j] * c[j] + c[j + 1] * d[j]) / 6) * v + + (c[j] * 0.5) * v * v + + ((c[j + 1] - c[j]) / (6 * d[j])) * v * v * v; } } + out_y[i] = y_out; } + free(A); free(As); free(b); @@ -1688,319 +1947,371 @@ void PerceptualToneCurve::cubic_spline(const float x[], const float y[], const i } // generic function for finding minimum of f(x) in the a-b range using the interval halving method -float PerceptualToneCurve::find_minimum_interval_halving(float (*func)(float x, void *arg), void *arg, float a, float b, float tol, int nmax) { - float L = b - a; - float x = (a + b) * 0.5; - for (int i = 0; i < nmax; i++) { - float f_x = func(x, arg); - if ((b - a) * 0.5 < tol) { - return x; - } - float x1 = a + L/4; - float f_x1 = func(x1, arg); - if (f_x1 < f_x) { - b = x; - x = x1; - } else { - float x2 = b - L/4; - float f_x2 = func(x2, arg); - if (f_x2 < f_x) { - a = x; - x = x2; - } else { - a = x1; - b = x2; - } - } - L = b - a; - } - return x; +float PerceptualToneCurve::find_minimum_interval_halving(float (*func)(float x, void *arg), void *arg, float a, float b, float tol, int nmax) +{ + float L = b - a; + float x = (a + b) * 0.5; + + for (int i = 0; i < nmax; i++) { + float f_x = func(x, arg); + + if ((b - a) * 0.5 < tol) { + return x; + } + + float x1 = a + L / 4; + float f_x1 = func(x1, arg); + + if (f_x1 < f_x) { + b = x; + x = x1; + } else { + float x2 = b - L / 4; + float f_x2 = func(x2, arg); + + if (f_x2 < f_x) { + a = x; + x = x2; + } else { + a = x1; + b = x2; + } + } + + L = b - a; + } + + return x; } struct find_tc_slope_fun_arg { - const ToneCurve * tc; + const ToneCurve * tc; }; float PerceptualToneCurve::find_tc_slope_fun(float k, void *arg) { - struct find_tc_slope_fun_arg *a = (struct find_tc_slope_fun_arg *)arg; - float areasum = 0; - const int steps = 10; - for (int i = 0; i < steps; i++) { - float x = 0.1 + ((float)i / (steps-1)) * 0.5; // testing (sRGB) range [0.1 - 0.6], ie ignore highligths and dark shadows - float y = CurveFactory::gamma2(a->tc->lutToneCurve[CurveFactory::igamma2(x) * 65535] / 65535.0); - float y1 = k * x; - if (y1 > 1) y1 = 1; - areasum += (y - y1) * (y - y1); // square is a rough approx of (twice) the area, but it's fine for our purposes - } - return areasum; + struct find_tc_slope_fun_arg *a = (struct find_tc_slope_fun_arg *)arg; + float areasum = 0; + const int steps = 10; + + for (int i = 0; i < steps; i++) { + float x = 0.1 + ((float)i / (steps - 1)) * 0.5; // testing (sRGB) range [0.1 - 0.6], ie ignore highligths and dark shadows + float y = CurveFactory::gamma2(a->tc->lutToneCurve[CurveFactory::igamma2(x) * 65535] / 65535.0); + float y1 = k * x; + + if (y1 > 1) { + y1 = 1; + } + + areasum += (y - y1) * (y - y1); // square is a rough approx of (twice) the area, but it's fine for our purposes + } + + return areasum; } -float PerceptualToneCurve::get_curve_val(float x, float range[2], float lut[], size_t lut_size) { - float xm = (x - range[0]) / (range[1] - range[0]) * (lut_size - 1); - if (xm <= 0) { - return lut[0]; - } - int idx = (int)xm; - if (idx >= lut_size-1) { - return lut[lut_size-1]; - } - float d = xm - (float)idx; // [0 .. 1] - return (1.0 - d) * lut[idx] + d * lut[idx+1]; +float PerceptualToneCurve::get_curve_val(float x, float range[2], float lut[], size_t lut_size) +{ + float xm = (x - range[0]) / (range[1] - range[0]) * (lut_size - 1); + + if (xm <= 0) { + return lut[0]; + } + + int idx = (int)xm; + + if (idx >= lut_size - 1) { + return lut[lut_size - 1]; + } + + float d = xm - (float)idx; // [0 .. 1] + return (1.0 - d) * lut[idx] + d * lut[idx + 1]; } // calculate a single value that represents the contrast of the tone curve -float PerceptualToneCurve::calculateToneCurveContrastValue(void) const { +float PerceptualToneCurve::calculateToneCurveContrastValue(void) const +{ - // find linear y = k*x the best approximates the curve, which is the linear scaling/exposure component that does not contribute any contrast + // find linear y = k*x the best approximates the curve, which is the linear scaling/exposure component that does not contribute any contrast - // Note: the analysis is made on the gamma encoded curve, as the LUT is linear we make backwards gamma to - struct find_tc_slope_fun_arg arg = { this }; - float k = find_minimum_interval_halving(find_tc_slope_fun, &arg, 0.1, 5.0, 0.01, 20); // normally found in 8 iterations - //fprintf(stderr, "average slope: %f\n", k); + // Note: the analysis is made on the gamma encoded curve, as the LUT is linear we make backwards gamma to + struct find_tc_slope_fun_arg arg = { this }; + float k = find_minimum_interval_halving(find_tc_slope_fun, &arg, 0.1, 5.0, 0.01, 20); // normally found in 8 iterations + //fprintf(stderr, "average slope: %f\n", k); - float maxslope = 0; - { - // look at midtone slope - const float xd = 0.07; - const float tx[] = { 0.30, 0.35, 0.40, 0.45 }; // we only look in the midtone range - for (int i = 0; i < sizeof(tx)/sizeof(tx[0]); i++) { - float x0 = tx[i] - xd; - float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0; - float x1 = tx[i] + xd; - float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1; - float slope = 1.0 + (y1 - y0) / (x1 - x0); - if (slope > maxslope) { - maxslope = slope; - } - } + float maxslope = 0; + { + // look at midtone slope + const float xd = 0.07; + const float tx[] = { 0.30, 0.35, 0.40, 0.45 }; // we only look in the midtone range - // look at slope at (light) shadows and (dark) highlights - float e_maxslope = 0; - { - const float tx[] = { 0.20, 0.25, 0.50, 0.55 }; // we only look in the midtone range - for (int i = 0; i < sizeof(tx)/sizeof(tx[0]); i++) { - float x0 = tx[i] - xd; - float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0; - float x1 = tx[i] + xd; - float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1; - float slope = 1.0 + (y1 - y0) / (x1 - x0); - if (slope > e_maxslope) { - e_maxslope = slope; - } - } - } - //fprintf(stderr, "%.3f %.3f\n", maxslope, e_maxslope); - // midtone slope is more important for contrast, but weigh in some slope from brights and darks too. - maxslope = maxslope * 0.7 + e_maxslope * 0.3; + for (int i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) { + float x0 = tx[i] - xd; + float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0; + float x1 = tx[i] + xd; + float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1; + float slope = 1.0 + (y1 - y0) / (x1 - x0); + + if (slope > maxslope) { + maxslope = slope; + } } - return maxslope; + + // look at slope at (light) shadows and (dark) highlights + float e_maxslope = 0; + { + const float tx[] = { 0.20, 0.25, 0.50, 0.55 }; // we only look in the midtone range + + for (int i = 0; i < sizeof(tx) / sizeof(tx[0]); i++) { + float x0 = tx[i] - xd; + float y0 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x0) * 65535.f] / 65535.f) - k * x0; + float x1 = tx[i] + xd; + float y1 = CurveFactory::gamma2(lutToneCurve[CurveFactory::igamma2(x1) * 65535.f] / 65535.f) - k * x1; + float slope = 1.0 + (y1 - y0) / (x1 - x0); + + if (slope > e_maxslope) { + e_maxslope = slope; + } + } + } + //fprintf(stderr, "%.3f %.3f\n", maxslope, e_maxslope); + // midtone slope is more important for contrast, but weigh in some slope from brights and darks too. + maxslope = maxslope * 0.7 + e_maxslope * 0.3; + } + return maxslope; } -void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurveState & state) const { - float x,y,z; - cmsCIEXYZ XYZ; - cmsJCh JCh; +void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurveState & state) const +{ + float x, y, z; + cmsCIEXYZ XYZ; + cmsJCh JCh; - int thread_idx = 0; + int thread_idx = 0; #ifdef _OPENMP - thread_idx = omp_get_thread_num(); + thread_idx = omp_get_thread_num(); #endif - if (!state.isProphoto) { - // convert to prophoto space to make sure the same result is had regardless of working color space - float newr = state.Working2Prophoto[0][0]*r + state.Working2Prophoto[0][1]*g + state.Working2Prophoto[0][2]*b; - float newg = state.Working2Prophoto[1][0]*r + state.Working2Prophoto[1][1]*g + state.Working2Prophoto[1][2]*b; - float newb = state.Working2Prophoto[2][0]*r + state.Working2Prophoto[2][1]*g + state.Working2Prophoto[2][2]*b; - r = newr; - g = newg; - b = newb; - } - const AdobeToneCurve& adobeTC = static_cast((const ToneCurve&)*this); - float ar = r; - float ag = g; - float ab = b; - adobeTC.Apply(ar, ag, ab); + if (!state.isProphoto) { + // convert to prophoto space to make sure the same result is had regardless of working color space + float newr = state.Working2Prophoto[0][0] * r + state.Working2Prophoto[0][1] * g + state.Working2Prophoto[0][2] * b; + float newg = state.Working2Prophoto[1][0] * r + state.Working2Prophoto[1][1] * g + state.Working2Prophoto[1][2] * b; + float newb = state.Working2Prophoto[2][0] * r + state.Working2Prophoto[2][1] * g + state.Working2Prophoto[2][2] * b; + r = newr; + g = newg; + b = newb; + } - if (ar >= 65535.f && ag >= 65535.f && ab >= 65535.f) { - // clip fast path, will also avoid strange colors of clipped highlights - r = g = b = 65535.f; - return; - } - if (ar <= 0.f && ag <= 0.f && ab <= 0.f) { - r = g = b = 0; - return; - } + const AdobeToneCurve& adobeTC = static_cast((const ToneCurve&) * this); + float ar = r; + float ag = g; + float ab = b; + adobeTC.Apply(ar, ag, ab); - // ProPhoto constants for luminance, that is xyz_prophoto[1][] - const float Yr = 0.2880402f; - const float Yg = 0.7118741f; - const float Yb = 0.0000857f; + if (ar >= 65535.f && ag >= 65535.f && ab >= 65535.f) { + // clip fast path, will also avoid strange colors of clipped highlights + r = g = b = 65535.f; + return; + } - // we use the Adobe (RGB-HSV hue-stabilized) curve to decide luminance, which generally leads to a less contrasty result - // compared to a pure luminance curve. We do this to be more compatible with the most popular curves. - float oldLuminance = r*Yr + g*Yg + b*Yb; - float newLuminance = ar*Yr + ag*Yg + ab*Yb; - float Lcoef = newLuminance/oldLuminance; - r = LIM(r*Lcoef, 0.f, 65535.f); - g = LIM(g*Lcoef, 0.f, 65535.f); - b = LIM(b*Lcoef, 0.f, 65535.f); + if (ar <= 0.f && ag <= 0.f && ab <= 0.f) { + r = g = b = 0; + return; + } - // move to JCh so we can modulate chroma based on the global contrast-related chroma scaling factor - Color::Prophotoxyz(r,g,b,x,y,z); - XYZ.X = x * 100.0f/65535; - XYZ.Y = y * 100.0f/65535; - XYZ.Z = z * 100.0f/65535; - cmsCIECAM02Forward(h02[thread_idx], &XYZ, &JCh); - if (!isfinite(JCh.J) || !isfinite(JCh.C) || !isfinite(JCh.h)) { - // this can happen for dark noise colors or colors outside human gamut. Then we just return the curve's result. - if (!state.isProphoto) { - float newr = state.Prophoto2Working[0][0]*r + state.Prophoto2Working[0][1]*g + state.Prophoto2Working[0][2]*b; - float newg = state.Prophoto2Working[1][0]*r + state.Prophoto2Working[1][1]*g + state.Prophoto2Working[1][2]*b; - float newb = state.Prophoto2Working[2][0]*r + state.Prophoto2Working[2][1]*g + state.Prophoto2Working[2][2]*b; - r = newr; - g = newg; - b = newb; - } - return; - } + // ProPhoto constants for luminance, that is xyz_prophoto[1][] + const float Yr = 0.2880402f; + const float Yg = 0.7118741f; + const float Yb = 0.0000857f; - float cmul = state.cmul_contrast; // chroma scaling factor + // we use the Adobe (RGB-HSV hue-stabilized) curve to decide luminance, which generally leads to a less contrasty result + // compared to a pure luminance curve. We do this to be more compatible with the most popular curves. + float oldLuminance = r * Yr + g * Yg + b * Yb; + float newLuminance = ar * Yr + ag * Yg + ab * Yb; + float Lcoef = newLuminance / oldLuminance; + r = LIM(r * Lcoef, 0.f, 65535.f); + g = LIM(g * Lcoef, 0.f, 65535.f); + b = LIM(b * Lcoef, 0.f, 65535.f); - // depending on color, the chroma scaling factor can be fine-tuned below + // move to JCh so we can modulate chroma based on the global contrast-related chroma scaling factor + Color::Prophotoxyz(r, g, b, x, y, z); + XYZ.X = x * 100.0f / 65535; + XYZ.Y = y * 100.0f / 65535; + XYZ.Z = z * 100.0f / 65535; + cmsCIECAM02Forward(h02[thread_idx], &XYZ, &JCh); - { // decrease chroma scaling sligthly of extremely saturated colors - float saturated_scale_factor = 0.95; - const float lolim = 35; // lower limit, below this chroma all colors will keep original chroma scaling factor - const float hilim = 60; // high limit, above this chroma the chroma scaling factor is multiplied with the saturated scale factor value above - if (JCh.C < lolim) { - // chroma is low enough, don't scale - saturated_scale_factor = 1.0; - } else if (JCh.C < hilim) { - // S-curve transition between low and high limit - float x = (JCh.C - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - if (x < 0.5) { - x = 0.5 * powf(2*x, 2); - } else { - x = 0.5 + 0.5 * (1-powf(1-2*(x-0.5), 2)); - } - saturated_scale_factor = 1.0*(1.0-x) + saturated_scale_factor*x; - } else { - // do nothing, high saturation color, keep scale factor - } - cmul *= saturated_scale_factor; - } + if (!isfinite(JCh.J) || !isfinite(JCh.C) || !isfinite(JCh.h)) { + // this can happen for dark noise colors or colors outside human gamut. Then we just return the curve's result. + if (!state.isProphoto) { + float newr = state.Prophoto2Working[0][0] * r + state.Prophoto2Working[0][1] * g + state.Prophoto2Working[0][2] * b; + float newg = state.Prophoto2Working[1][0] * r + state.Prophoto2Working[1][1] * g + state.Prophoto2Working[1][2] * b; + float newb = state.Prophoto2Working[2][0] * r + state.Prophoto2Working[2][1] * g + state.Prophoto2Working[2][2] * b; + r = newr; + g = newg; + b = newb; + } - { // increase chroma scaling slightly of shadows - float nL = CurveFactory::gamma2(newLuminance / 65535); // apply gamma so we make comparison and transition with a more perceptual lightness scale - float dark_scale_factor = 1.20; - //float dark_scale_factor = 1.0 + state.debug.p2 / 100.0f; - const float lolim = 0.15; - const float hilim = 0.50; - if (nL < lolim) { - // do nothing, keep scale factor - } else if (nL < hilim) { - // S-curve transition - float x = (nL - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - if (x < 0.5) { - x = 0.5 * powf(2*x, 2); - } else { - x = 0.5 + 0.5 * (1-powf(1-2*(x-0.5), 2)); - } - dark_scale_factor = dark_scale_factor*(1.0-x) + 1.0*x; - } else { - dark_scale_factor = 1.0; - } - cmul *= dark_scale_factor; - } + return; + } - { // to avoid strange CIECAM02 chroma errors on close-to-shadow-clipping colors we reduce chroma scaling towards 1.0 for black colors - float dark_scale_factor = 1.0 / cmul; - const float lolim = 4; - const float hilim = 7; - if (JCh.J < lolim) { - // do nothing, keep scale factor - } else if (JCh.J < hilim) { - // S-curve transition - float x = (JCh.J - lolim) / (hilim - lolim); - if (x < 0.5) { - x = 0.5 * powf(2*x, 2); - } else { - x = 0.5 + 0.5 * (1-powf(1-2*(x-0.5), 2)); - } - dark_scale_factor = dark_scale_factor*(1.0-x) + 1.0*x; - } else { - dark_scale_factor = 1.0; - } - cmul *= dark_scale_factor; - } + float cmul = state.cmul_contrast; // chroma scaling factor - JCh.C *= cmul; - cmsCIECAM02Reverse(h02[thread_idx], &JCh, &XYZ); - if (!isfinite(XYZ.X) || !isfinite(XYZ.Y) || !isfinite(XYZ.Z)) { - // can happen for colors on the rim of being outside gamut, that worked without chroma scaling but not with. Then we return only the curve's result. - if (!state.isProphoto) { - float newr = state.Prophoto2Working[0][0]*r + state.Prophoto2Working[0][1]*g + state.Prophoto2Working[0][2]*b; - float newg = state.Prophoto2Working[1][0]*r + state.Prophoto2Working[1][1]*g + state.Prophoto2Working[1][2]*b; - float newb = state.Prophoto2Working[2][0]*r + state.Prophoto2Working[2][1]*g + state.Prophoto2Working[2][2]*b; - r = newr; - g = newg; - b = newb; - } - return; - } - Color::xyz2Prophoto(XYZ.X,XYZ.Y,XYZ.Z,r,g,b); - r *= 655.35; - g *= 655.35; - b *= 655.35; - r = LIM(r, 0.f, 65535.f); - g = LIM(g, 0.f, 65535.f); - b = LIM(b, 0.f, 65535.f); + // depending on color, the chroma scaling factor can be fine-tuned below - { // limit saturation increase in rgb space to avoid severe clipping and flattening in extreme highlights + { + // decrease chroma scaling sligthly of extremely saturated colors + float saturated_scale_factor = 0.95; + const float lolim = 35; // lower limit, below this chroma all colors will keep original chroma scaling factor + const float hilim = 60; // high limit, above this chroma the chroma scaling factor is multiplied with the saturated scale factor value above - // we use the RGB-HSV hue-stable "Adobe" curve as reference. For S-curve contrast it increases - // saturation greatly, but desaturates extreme highlights and thus provide a smooth transition to - // the white point. However the desaturation effect is quite strong so we make a weighting - float ah,as,av,h,s,v; - Color::rgb2hsv(ar,ag,ab, ah,as,av); - Color::rgb2hsv(r,g,b, h,s,v); + if (JCh.C < lolim) { + // chroma is low enough, don't scale + saturated_scale_factor = 1.0; + } else if (JCh.C < hilim) { + // S-curve transition between low and high limit + float x = (JCh.C - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - float sat_scale = as <= 0.0 ? 1.0 : s / as; // saturation scale compared to Adobe curve - float keep = 0.2; - const float lolim = 1.00; // only mix in the Adobe curve if we have increased saturation compared to it - const float hilim = 1.20; - if (sat_scale < lolim) { - // saturation is low enough, don't desaturate - keep = 1.0; - } else if (sat_scale < hilim) { - // S-curve transition - float x = (sat_scale - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim - if (x < 0.5) { - x = 0.5 * powf(2*x, 2); - } else { - x = 0.5 + 0.5 * (1-powf(1-2*(x-0.5), 2)); - } - keep = 1.0*(1.0-x) + keep*x; - } else { - // do nothing, very high increase, keep minimum amount - } - if (keep < 1.0) { - // mix in some of the Adobe curve result - r = r * keep + (1.0 - keep) * ar; - g = g * keep + (1.0 - keep) * ag; - b = b * keep + (1.0 - keep) * ab; - } - } + if (x < 0.5) { + x = 0.5 * powf(2 * x, 2); + } else { + x = 0.5 + 0.5 * (1 - powf(1 - 2 * (x - 0.5), 2)); + } - if (!state.isProphoto) { - float newr = state.Prophoto2Working[0][0]*r + state.Prophoto2Working[0][1]*g + state.Prophoto2Working[0][2]*b; - float newg = state.Prophoto2Working[1][0]*r + state.Prophoto2Working[1][1]*g + state.Prophoto2Working[1][2]*b; - float newb = state.Prophoto2Working[2][0]*r + state.Prophoto2Working[2][1]*g + state.Prophoto2Working[2][2]*b; - r = newr; - g = newg; - b = newb; - } + saturated_scale_factor = 1.0 * (1.0 - x) + saturated_scale_factor * x; + } else { + // do nothing, high saturation color, keep scale factor + } + + cmul *= saturated_scale_factor; + } + + { + // increase chroma scaling slightly of shadows + float nL = CurveFactory::gamma2(newLuminance / 65535); // apply gamma so we make comparison and transition with a more perceptual lightness scale + float dark_scale_factor = 1.20; + //float dark_scale_factor = 1.0 + state.debug.p2 / 100.0f; + const float lolim = 0.15; + const float hilim = 0.50; + + if (nL < lolim) { + // do nothing, keep scale factor + } else if (nL < hilim) { + // S-curve transition + float x = (nL - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim + + if (x < 0.5) { + x = 0.5 * powf(2 * x, 2); + } else { + x = 0.5 + 0.5 * (1 - powf(1 - 2 * (x - 0.5), 2)); + } + + dark_scale_factor = dark_scale_factor * (1.0 - x) + 1.0 * x; + } else { + dark_scale_factor = 1.0; + } + + cmul *= dark_scale_factor; + } + + { + // to avoid strange CIECAM02 chroma errors on close-to-shadow-clipping colors we reduce chroma scaling towards 1.0 for black colors + float dark_scale_factor = 1.0 / cmul; + const float lolim = 4; + const float hilim = 7; + + if (JCh.J < lolim) { + // do nothing, keep scale factor + } else if (JCh.J < hilim) { + // S-curve transition + float x = (JCh.J - lolim) / (hilim - lolim); + + if (x < 0.5) { + x = 0.5 * powf(2 * x, 2); + } else { + x = 0.5 + 0.5 * (1 - powf(1 - 2 * (x - 0.5), 2)); + } + + dark_scale_factor = dark_scale_factor * (1.0 - x) + 1.0 * x; + } else { + dark_scale_factor = 1.0; + } + + cmul *= dark_scale_factor; + } + + JCh.C *= cmul; + cmsCIECAM02Reverse(h02[thread_idx], &JCh, &XYZ); + + if (!isfinite(XYZ.X) || !isfinite(XYZ.Y) || !isfinite(XYZ.Z)) { + // can happen for colors on the rim of being outside gamut, that worked without chroma scaling but not with. Then we return only the curve's result. + if (!state.isProphoto) { + float newr = state.Prophoto2Working[0][0] * r + state.Prophoto2Working[0][1] * g + state.Prophoto2Working[0][2] * b; + float newg = state.Prophoto2Working[1][0] * r + state.Prophoto2Working[1][1] * g + state.Prophoto2Working[1][2] * b; + float newb = state.Prophoto2Working[2][0] * r + state.Prophoto2Working[2][1] * g + state.Prophoto2Working[2][2] * b; + r = newr; + g = newg; + b = newb; + } + + return; + } + + Color::xyz2Prophoto(XYZ.X, XYZ.Y, XYZ.Z, r, g, b); + r *= 655.35; + g *= 655.35; + b *= 655.35; + r = LIM(r, 0.f, 65535.f); + g = LIM(g, 0.f, 65535.f); + b = LIM(b, 0.f, 65535.f); + + { + // limit saturation increase in rgb space to avoid severe clipping and flattening in extreme highlights + + // we use the RGB-HSV hue-stable "Adobe" curve as reference. For S-curve contrast it increases + // saturation greatly, but desaturates extreme highlights and thus provide a smooth transition to + // the white point. However the desaturation effect is quite strong so we make a weighting + float ah, as, av, h, s, v; + Color::rgb2hsv(ar, ag, ab, ah, as, av); + Color::rgb2hsv(r, g, b, h, s, v); + + float sat_scale = as <= 0.0 ? 1.0 : s / as; // saturation scale compared to Adobe curve + float keep = 0.2; + const float lolim = 1.00; // only mix in the Adobe curve if we have increased saturation compared to it + const float hilim = 1.20; + + if (sat_scale < lolim) { + // saturation is low enough, don't desaturate + keep = 1.0; + } else if (sat_scale < hilim) { + // S-curve transition + float x = (sat_scale - lolim) / (hilim - lolim); // x = [0..1], 0 at lolim, 1 at hilim + + if (x < 0.5) { + x = 0.5 * powf(2 * x, 2); + } else { + x = 0.5 + 0.5 * (1 - powf(1 - 2 * (x - 0.5), 2)); + } + + keep = 1.0 * (1.0 - x) + keep * x; + } else { + // do nothing, very high increase, keep minimum amount + } + + if (keep < 1.0) { + // mix in some of the Adobe curve result + r = r * keep + (1.0 - keep) * ar; + g = g * keep + (1.0 - keep) * ag; + b = b * keep + (1.0 - keep) * ab; + } + } + + if (!state.isProphoto) { + float newr = state.Prophoto2Working[0][0] * r + state.Prophoto2Working[0][1] * g + state.Prophoto2Working[0][2] * b; + float newg = state.Prophoto2Working[1][0] * r + state.Prophoto2Working[1][1] * g + state.Prophoto2Working[1][2] * b; + float newb = state.Prophoto2Working[2][0] * r + state.Prophoto2Working[2][1] * g + state.Prophoto2Working[2][2] * b; + r = newr; + g = newg; + b = newb; + } } cmsContext * PerceptualToneCurve::c02; @@ -2008,107 +2319,123 @@ cmsHANDLE * PerceptualToneCurve::h02; float PerceptualToneCurve::cf_range[2]; float PerceptualToneCurve::cf[1000]; -void PerceptualToneCurve::init() { +void PerceptualToneCurve::init() +{ - { // init ciecam02 state, used for chroma scalings - cmsViewingConditions vc; - vc.whitePoint = *cmsD50_XYZ(); - vc.whitePoint.X *= 100; - vc.whitePoint.Y *= 100; - vc.whitePoint.Z *= 100; - vc.Yb = 20; - vc.La = 20; - vc.surround = AVG_SURROUND; - vc.D_value = 1.0; + { + // init ciecam02 state, used for chroma scalings + cmsViewingConditions vc; + vc.whitePoint = *cmsD50_XYZ(); + vc.whitePoint.X *= 100; + vc.whitePoint.Y *= 100; + vc.whitePoint.Z *= 100; + vc.Yb = 20; + vc.La = 20; + vc.surround = AVG_SURROUND; + vc.D_value = 1.0; - int thread_count = 1; + int thread_count = 1; #ifdef _OPENMP - thread_count = omp_get_max_threads(); + thread_count = omp_get_max_threads(); #endif - h02 = (cmsHANDLE *)malloc(sizeof(h02[0]) * (thread_count + 1)); - c02 = (cmsContext *)malloc(sizeof(c02[0]) * (thread_count + 1)); - h02[thread_count] = NULL; - c02[thread_count] = NULL; - // little cms requires one state per thread, for thread safety - for (int i = 0; i < thread_count; i++) { - c02[i] = cmsCreateContext(NULL, NULL); - h02[i] = cmsCIECAM02Init(c02[i], &vc); - } - } + h02 = (cmsHANDLE *)malloc(sizeof(h02[0]) * (thread_count + 1)); + c02 = (cmsContext *)malloc(sizeof(c02[0]) * (thread_count + 1)); + h02[thread_count] = NULL; + c02[thread_count] = NULL; - { // init contrast-value-to-chroma-scaling conversion curve + // little cms requires one state per thread, for thread safety + for (int i = 0; i < thread_count; i++) { + c02[i] = cmsCreateContext(NULL, NULL); + h02[i] = cmsCIECAM02Init(c02[i], &vc); + } + } - // contrast value in the left column, chroma scaling in the right. Handles for a spline. - // Put the columns in a file (without commas) and you can plot the spline with gnuplot: "plot 'curve.txt' smooth csplines" - // A spline can easily get overshoot issues so if you fine-tune the values here make sure that the resulting spline is smooth afterwards, by - // plotting it for example. - const float p[] = { - 0.60, 0.70, // lowest contrast - 0.70, 0.80, - 0.90, 0.94, - 0.99, 1.00, - 1.00, 1.00, // 1.0 (linear curve) to 1.0, no scaling - 1.07, 1.00, - 1.08, 1.00, - 1.11, 1.02, - 1.20, 1.08, - 1.30, 1.12, - 1.80, 1.20, - 2.00, 1.22 // highest contrast - }; + { + // init contrast-value-to-chroma-scaling conversion curve - const size_t in_len = sizeof(p)/sizeof(p[0])/2; - float in_x[in_len]; - float in_y[in_len]; - for (size_t i = 0; i < in_len; i++) { - in_x[i]= p[2*i+0]; - in_y[i]= p[2*i+1]; - } - const size_t out_len = sizeof(cf)/sizeof(cf[0]); - float out_x[out_len]; - for (size_t i = 0; i < out_len; i++) { - out_x[i] = in_x[0] + (in_x[in_len-1] - in_x[0]) * (float)i / (out_len-1); - } - cubic_spline(in_x, in_y, in_len, out_x, cf, out_len); - cf_range[0] = in_x[0]; - cf_range[1] = in_x[in_len-1]; - } + // contrast value in the left column, chroma scaling in the right. Handles for a spline. + // Put the columns in a file (without commas) and you can plot the spline with gnuplot: "plot 'curve.txt' smooth csplines" + // A spline can easily get overshoot issues so if you fine-tune the values here make sure that the resulting spline is smooth afterwards, by + // plotting it for example. + const float p[] = { + 0.60, 0.70, // lowest contrast + 0.70, 0.80, + 0.90, 0.94, + 0.99, 1.00, + 1.00, 1.00, // 1.0 (linear curve) to 1.0, no scaling + 1.07, 1.00, + 1.08, 1.00, + 1.11, 1.02, + 1.20, 1.08, + 1.30, 1.12, + 1.80, 1.20, + 2.00, 1.22 // highest contrast + }; + + const size_t in_len = sizeof(p) / sizeof(p[0]) / 2; + float in_x[in_len]; + float in_y[in_len]; + + for (size_t i = 0; i < in_len; i++) { + in_x[i] = p[2 * i + 0]; + in_y[i] = p[2 * i + 1]; + } + + const size_t out_len = sizeof(cf) / sizeof(cf[0]); + float out_x[out_len]; + + for (size_t i = 0; i < out_len; i++) { + out_x[i] = in_x[0] + (in_x[in_len - 1] - in_x[0]) * (float)i / (out_len - 1); + } + + cubic_spline(in_x, in_y, in_len, out_x, cf, out_len); + cf_range[0] = in_x[0]; + cf_range[1] = in_x[in_len - 1]; + } } -void PerceptualToneCurve::cleanup() { - for (int i = 0; h02[i] != NULL; i++) { - cmsCIECAM02Done(h02[i]); - cmsDeleteContext(c02[i]); - } - free(h02); - free(c02); +void PerceptualToneCurve::cleanup() +{ + for (int i = 0; h02[i] != NULL; i++) { + cmsCIECAM02Done(h02[i]); + cmsDeleteContext(c02[i]); + } + + free(h02); + free(c02); } -void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const { +void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const +{ - // Get the curve's contrast value, and convert to a chroma scaling - const float contrast_value = calculateToneCurveContrastValue(); - state.cmul_contrast = get_curve_val(contrast_value, cf_range, cf, sizeof(cf)/sizeof(cf[0])); - //fprintf(stderr, "contrast value: %f => chroma scaling %f\n", contrast_value, state.cmul_contrast); + // Get the curve's contrast value, and convert to a chroma scaling + const float contrast_value = calculateToneCurveContrastValue(); + state.cmul_contrast = get_curve_val(contrast_value, cf_range, cf, sizeof(cf) / sizeof(cf[0])); + //fprintf(stderr, "contrast value: %f => chroma scaling %f\n", contrast_value, state.cmul_contrast); - // Create state for converting to/from prophoto (if necessary) - if (workingSpace == "ProPhoto") { - state.isProphoto = true; - } else { - state.isProphoto = false; - TMatrix Work = iccStore->workingSpaceMatrix(workingSpace); - memset(state.Working2Prophoto, 0, sizeof(state.Working2Prophoto)); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) - state.Working2Prophoto[i][j] += prophoto_xyz[i][k] * Work[k][j]; - Work = iccStore->workingSpaceInverseMatrix (workingSpace); - memset(state.Prophoto2Working, 0, sizeof(state.Prophoto2Working)); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) - state.Prophoto2Working[i][j] += Work[i][k] * xyz_prophoto[k][j]; - } + // Create state for converting to/from prophoto (if necessary) + if (workingSpace == "ProPhoto") { + state.isProphoto = true; + } else { + state.isProphoto = false; + TMatrix Work = iccStore->workingSpaceMatrix(workingSpace); + memset(state.Working2Prophoto, 0, sizeof(state.Working2Prophoto)); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { + state.Working2Prophoto[i][j] += prophoto_xyz[i][k] * Work[k][j]; + } + + Work = iccStore->workingSpaceInverseMatrix (workingSpace); + memset(state.Prophoto2Working, 0, sizeof(state.Prophoto2Working)); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { + state.Prophoto2Working[i][j] += Work[i][k] * xyz_prophoto[k][j]; + } + } } } diff --git a/rtengine/curves.h b/rtengine/curves.h index a0277ccdd..f43542dba 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -7,7 +7,7 @@ * 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 @@ -40,239 +40,291 @@ using namespace std; -namespace rtengine { - class ToneCurve; - class ColorAppearance; +namespace rtengine +{ +class ToneCurve; +class ColorAppearance; -class CurveFactory { +class CurveFactory +{ friend class Curve; - protected: +protected: // functions calculating the parameters of the contrast curve based on the desired slope at the center static double solve_upper (double m, double c, double deriv); static double solve_lower (double m, double c, double deriv); static double dupper (const double b, const double m, const double c); static double dlower (const double b, const double m, const double c); - + // basic convex function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point - static inline double basel (double x, double m1, double m2) { - if (x==0.0) + static inline double basel (double x, double m1, double m2) + { + if (x == 0.0) { return 0.0; - double k = sqrt ((m1-1.0)*(m1-m2)*0.5) / (1.0-m2); - double l = (m1-m2) / (1.0-m2) + k; + } + + double k = sqrt ((m1 - 1.0) * (m1 - m2) * 0.5) / (1.0 - m2); + double l = (m1 - m2) / (1.0 - m2) + k; double lx = xlog(x); - return m2*x + (1.0-m2)*(2.0 - xexp(k*lx))*xexp(l*lx); + return m2 * x + (1.0 - m2) * (2.0 - xexp(k * lx)) * xexp(l * lx); } // basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point - static inline double baseu (double x, double m1, double m2) { - return 1.0 - basel(1.0-x, m1, m2); + static inline double baseu (double x, double m1, double m2) + { + return 1.0 - basel(1.0 - x, m1, m2); } - // convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery - static inline double cupper (double x, double m, double hr) { - if (hr>1.0) - return baseu (x, m, 2.0*(hr-1.0)/m); - double x1 = (1.0-hr)/m; - double x2 = x1 + hr; - if (x>=x2) return 1.0; - if (x=x2) return 1.0; - if (xx1 || sr<0.001) - return 1-(1-x)*m; - else - { - double y1 = 1-(1-x1)*m; - return y1+m*(x-x1)-(1-m)*SQR(SQR(1-x/x1)); - } - } - // tone curve base. a: slope (from exp.comp.), b: black point normalized by 65535, - // D: max. x value (can be>1), hr,sr: highlight,shadow recovery - static inline double basecurve (double x, double a, double b, double D, double hr, double sr) { - if (b<0) { - double m = 0.5;//midpoint - double slope = 1.0+b;//slope of straight line between (0,-b) and (1,1) - double y = -b+m*slope;//value at midpoint - if (x>m) - return y + (x - m)*slope;//value on straight line between (m,y) and (1,1) - else - return y*clower2(x/m, slope*m/y, 2.0-sr); - } else { - double slope = a/(1.0-b); - double m = a*D>1.0 ? b/a+(0.25)/slope : b+(1-b)/4; - double y = a*D>1.0 ? 0.25 : (m-b/a)*slope; - if (x<=m) - return b==0 ? x*slope : clower (x/m, slope*m/y, sr) * y; - else if (a*D>1.0) - return y+(1.0-y)*cupper2((x-m)/(D-m), slope*(D-m)/(1.0-y), hr); - else - return y+(x-m)*slope; - } - } - static inline double simplebasecurve (double x, double b, double sr) { - // a = 1, D = 1, hr = 0 (unused for a = D = 1) - if (b<0) { - double m = 0.5;//midpoint - double slope = 1.0+b;//slope of straight line between (0,-b) and (1,1) - double y = -b+m*slope;//value at midpoint - if (x>m) - return y + (x - m)*slope;//value on straight line between (m,y) and (1,1) - else - return y*clower2(x/m, slope*m/y, 2.0-sr); - } else { - double slope = 1.0/(1.0-b); - double m = b+(1-b)*0.25; - double y = (m-b)*slope; - if (x<=m) - return b==0 ? x*slope : clower (x/m, slope*m/y, sr) * y; - else - return y+(x-m)*slope; - } - } - + // convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery + static inline double cupper (double x, double m, double hr) + { + if (hr > 1.0) { + return baseu (x, m, 2.0 * (hr - 1.0) / m); + } - public: - const static double sRGBGamma; // standard average gamma + double x1 = (1.0 - hr) / m; + double x2 = x1 + hr; + + if (x >= x2) { + return 1.0; + } + + if (x < x1) { + return x * m; + } + + return 1.0 - hr + hr * baseu((x - x1) / hr, m, 0); + } + // concave curve between (0,0) and (1,1) with slope m at (1,1). sr controls the shadow recovery + static inline double clower (double x, double m, double sr) + { + return 1.0 - cupper(1.0 - x, m, sr); + } + // convex curve between (0,0) and (1,1) with slope m at (0,0). hr controls the highlight recovery + static inline double cupper2 (double x, double m, double hr) + { + double x1 = (1.0 - hr) / m; + double x2 = x1 + hr; + + if (x >= x2) { + return 1.0; + } + + if (x < x1) { + return x * m; + } + + return 1.0 - hr + hr * baseu((x - x1) / hr, m, 0.3 * hr); + } + static inline double clower2 (double x, double m, double sr) + { + //curve for b<0; starts with positive slope and then rolls over toward straight line to x=y=1 + double x1 = sr / 1.5 + 0.00001; + + if (x > x1 || sr < 0.001) { + return 1 - (1 - x) * m; + } else { + double y1 = 1 - (1 - x1) * m; + return y1 + m * (x - x1) - (1 - m) * SQR(SQR(1 - x / x1)); + } + } + // tone curve base. a: slope (from exp.comp.), b: black point normalized by 65535, + // D: max. x value (can be>1), hr,sr: highlight,shadow recovery + static inline double basecurve (double x, double a, double b, double D, double hr, double sr) + { + if (b < 0) { + double m = 0.5;//midpoint + double slope = 1.0 + b; //slope of straight line between (0,-b) and (1,1) + double y = -b + m * slope; //value at midpoint + + if (x > m) { + return y + (x - m) * slope; //value on straight line between (m,y) and (1,1) + } else { + return y * clower2(x / m, slope * m / y, 2.0 - sr); + } + } else { + double slope = a / (1.0 - b); + double m = a * D > 1.0 ? b / a + (0.25) / slope : b + (1 - b) / 4; + double y = a * D > 1.0 ? 0.25 : (m - b / a) * slope; + + if (x <= m) { + return b == 0 ? x * slope : clower (x / m, slope * m / y, sr) * y; + } else if (a * D > 1.0) { + return y + (1.0 - y) * cupper2((x - m) / (D - m), slope * (D - m) / (1.0 - y), hr); + } else { + return y + (x - m) * slope; + } + } + } + static inline double simplebasecurve (double x, double b, double sr) + { + // a = 1, D = 1, hr = 0 (unused for a = D = 1) + if (b < 0) { + double m = 0.5;//midpoint + double slope = 1.0 + b; //slope of straight line between (0,-b) and (1,1) + double y = -b + m * slope; //value at midpoint + + if (x > m) { + return y + (x - m) * slope; //value on straight line between (m,y) and (1,1) + } else { + return y * clower2(x / m, slope * m / y, 2.0 - sr); + } + } else { + double slope = 1.0 / (1.0 - b); + double m = b + (1 - b) * 0.25; + double y = (m - b) * slope; + + if (x <= m) { + return b == 0 ? x * slope : clower (x / m, slope * m / y, sr) * y; + } else { + return y + (x - m) * slope; + } + } + } + + +public: + const static double sRGBGamma; // standard average gamma const static double sRGBGammaCurve; // 2.4 in the curve - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // accurately determine value from integer array with float as index - //linearly interpolate from ends of range if arg is out of bounds - static inline float interp(int *array,float f) - { - int index = CLIPI(floor(f)); - float part = (float)((f)-index)*(float)(array[index+1]-array[index]); - return (float)array[index]+part; - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // accurately determine value from float array with float as index - //linearly interpolate from ends of range if arg is out of bounds - static inline float flinterp(float *array,float f) - { - int index = CLIPI(floor(f)); - float part = ((f)-(float)index)*(array[index+1]-array[index]); - return array[index]+part; - } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // accurately determine value from integer array with float as index + //linearly interpolate from ends of range if arg is out of bounds + static inline float interp(int *array, float f) + { + int index = CLIPI(floor(f)); + float part = (float)((f) - index) * (float)(array[index + 1] - array[index]); + return (float)array[index] + part; + } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // accurately determine value from float array with float as index + //linearly interpolate from ends of range if arg is out of bounds + static inline float flinterp(float *array, float f) + { + int index = CLIPI(floor(f)); + float part = ((f) - (float)index) * (array[index + 1] - array[index]); + return array[index] + part; + } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% static inline double centercontrast (double x, double b, double m); - + // standard srgb gamma and its inverse - static inline double gamma2 (double x) { - return x <= 0.00304 ? x*12.92 : 1.055*exp(log(x)/sRGBGammaCurve)-0.055; - } - static inline double igamma2 (double x) { - return x <= 0.03928 ? x/12.92 : exp(log((x+0.055)/1.055)*sRGBGammaCurve); - } - static inline float gamma2 (float x) { - return x <= 0.00304 ? x*12.92 : 1.055*expf(logf(x)/sRGBGammaCurve)-0.055; - } - static inline float igamma2 (float x) { - return x <= 0.03928 ? x/12.92 : expf(logf((x+0.055)/1.055)*sRGBGammaCurve); - } + static inline double gamma2 (double x) + { + return x <= 0.00304 ? x * 12.92 : 1.055 * exp(log(x) / sRGBGammaCurve) - 0.055; + } + static inline double igamma2 (double x) + { + return x <= 0.03928 ? x / 12.92 : exp(log((x + 0.055) / 1.055) * sRGBGammaCurve); + } + static inline float gamma2 (float x) + { + return x <= 0.00304 ? x * 12.92 : 1.055 * expf(logf(x) / sRGBGammaCurve) - 0.055; + } + static inline float igamma2 (float x) + { + return x <= 0.03928 ? x / 12.92 : expf(logf((x + 0.055) / 1.055) * sRGBGammaCurve); + } // gamma function with adjustable parameters - static inline double gamma (double x, double gamma, double start, double slope, double mul, double add){ - return (x <= start ? x*slope : exp(log(x)/gamma)*mul-add); - } - static inline double igamma (double x, double gamma, double start, double slope, double mul, double add){ - return (x <= start*slope ? x/slope : exp(log((x+add)/mul)*gamma) ); - } - static inline float gamma (float x, float gamma, float start, float slope, float mul, float add){ - return (x <= start ? x*slope : expf(logf(x)/gamma)*mul-add); - } - static inline float igamma (float x, float gamma, float start, float slope, float mul, float add){ - return (x <= start*slope ? x/slope : expf(logf((x+add)/mul)*gamma) ); - } - - static inline float hlcurve (const float exp_scale, const float comp, const float hlrange, float level) - { - if (comp>0.0) { - float val = level+(hlrange-65536.0); - if(val == 0.0f) // to avoid division by zero - val = 0.000001f; - float Y = val*exp_scale/hlrange; - Y *= comp; - if(Y <= -1.0) // to avoid log(<=0) - Y = -.999999f; - float R = hlrange/(val*comp); - return log(1.0+Y)*R; - } else { - return exp_scale; - } - } + static inline double gamma (double x, double gamma, double start, double slope, double mul, double add) + { + return (x <= start ? x*slope : exp(log(x) / gamma) * mul - add); + } + static inline double igamma (double x, double gamma, double start, double slope, double mul, double add) + { + return (x <= start * slope ? x / slope : exp(log((x + add) / mul) * gamma) ); + } + static inline float gamma (float x, float gamma, float start, float slope, float mul, float add) + { + return (x <= start ? x*slope : expf(logf(x) / gamma) * mul - add); + } + static inline float igamma (float x, float gamma, float start, float slope, float mul, float add) + { + return (x <= start * slope ? x / slope : expf(logf((x + add) / mul) * gamma) ); + } - public: + static inline float hlcurve (const float exp_scale, const float comp, const float hlrange, float level) + { + if (comp > 0.0) { + float val = level + (hlrange - 65536.0); + + if(val == 0.0f) { // to avoid division by zero + val = 0.000001f; + } + + float Y = val * exp_scale / hlrange; + Y *= comp; + + if(Y <= -1.0) { // to avoid log(<=0) + Y = -.999999f; + } + + float R = hlrange / (val * comp); + return log(1.0 + Y) * R; + } else { + return exp_scale; + } + } + +public: static void complexCurve (double ecomp, double black, double hlcompr, double hlcomprthresh, double shcompr, double br, double contr, - procparams::ToneCurveParams::eTCModeId curveMode, const std::vector& curvePoints, procparams::ToneCurveParams::eTCModeId curveMode2, const std::vector& curvePoints2, - - LUTu & histogram, LUTu & histogramCropped, - LUTf & hlCurve, LUTf & shCurve,LUTf & outCurve, LUTu & outBeforeCCurveHistogram, ToneCurve & outToneCurve, ToneCurve & outToneCurve2, - - int skip=1); - static void curveBW (const std::vector& curvePointsbw, const std::vector& curvePointsbw2, LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw, - ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip); - - static void curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip); + procparams::ToneCurveParams::eTCModeId curveMode, const std::vector& curvePoints, procparams::ToneCurveParams::eTCModeId curveMode2, const std::vector& curvePoints2, - static void curveWavContL ( bool & wavcontlutili,const std::vector& wavclcurvePoints, LUTf & wavclCurve,/* LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip); - - static void curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip); - static void curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip); - static void denoiseCC ( bool & ccdenoiseutili, const std::vector& cccurvePoints, LUTf & NoiseCCcurve,int skip); - - static void complexsgnCurve ( float adjustr, bool & autili, bool & butili, bool & ccutili, bool & clcutili, double saturation, double rstprotection, const std::vector& acurvePoints, - const std::vector& bcurvePoints,const std::vector& cccurvePoints,const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, - LUTu & histogramC, LUTu & histogramLC, LUTu & outBeforeCCurveHistogram,LUTu & outBeforeLCurveHistogram,///for chroma - int skip=1); - static void complexLCurve (double br, double contr, const std::vector& curvePoints, LUTu & histogram, LUTu & histogramCropped, - LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip, bool & utili); + LUTu & histogram, LUTu & histogramCropped, + LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTu & outBeforeCCurveHistogram, ToneCurve & outToneCurve, ToneCurve & outToneCurve2, - static void updatechroma ( - const std::vector& cccurvePoints, - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma - int skip=1); + int skip = 1); + static void curveBW (const std::vector& curvePointsbw, const std::vector& curvePointsbw2, LUTu & histogrambw, LUTu & outBeforeCCurveHistogrambw, + ToneCurve & customToneCurvebw1, ToneCurve & customToneCurvebw2, int skip); - static void curveLightBrightColor ( - procparams::ColorAppearanceParams::eTCModeId curveMode, const std::vector& curvePoints, - procparams::ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2, - procparams::ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3, - LUTu & histogram, LUTu & histogramCropped, LUTu & outBeforeCCurveHistogram, - LUTu & histogramC, LUTu & outBeforeCCurveHistogramC, - ColorAppearance & outColCurve1, - ColorAppearance & outColCurve2, - ColorAppearance & outColCurve3, - int skip=1); - static void RGBCurve (const std::vector& curvePoints, LUTf & outCurve, int skip); + static void curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip); + + static void curveWavContL ( bool & wavcontlutili, const std::vector& wavclcurvePoints, LUTf & wavclCurve,/* LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip); + + static void curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip); + static void curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip); + static void denoiseCC ( bool & ccdenoiseutili, const std::vector& cccurvePoints, LUTf & NoiseCCcurve, int skip); + + static void complexsgnCurve ( float adjustr, bool & autili, bool & butili, bool & ccutili, bool & clcutili, double saturation, double rstprotection, const std::vector& acurvePoints, + const std::vector& bcurvePoints, const std::vector& cccurvePoints, const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve, + LUTu & histogramC, LUTu & histogramLC, LUTu & outBeforeCCurveHistogram, LUTu & outBeforeLCurveHistogram, ///for chroma + int skip = 1); + static void complexLCurve (double br, double contr, const std::vector& curvePoints, LUTu & histogram, LUTu & histogramCropped, + LUTf & outCurve, LUTu & outBeforeCCurveHistogram, int skip, bool & utili); + + static void updatechroma ( + const std::vector& cccurvePoints, + LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma + int skip = 1); + + static void curveLightBrightColor ( + procparams::ColorAppearanceParams::eTCModeId curveMode, const std::vector& curvePoints, + procparams::ColorAppearanceParams::eTCModeId curveMode2, const std::vector& curvePoints2, + procparams::ColorAppearanceParams::eCTCModeId curveMode3, const std::vector& curvePoints3, + LUTu & histogram, LUTu & histogramCropped, LUTu & outBeforeCCurveHistogram, + LUTu & histogramC, LUTu & outBeforeCCurveHistogramC, + ColorAppearance & outColCurve1, + ColorAppearance & outColCurve2, + ColorAppearance & outColCurve3, + int skip = 1); + static void RGBCurve (const std::vector& curvePoints, LUTf & outCurve, int skip); }; -class Curve { +class Curve +{ - class HashEntry { + class HashEntry + { public: unsigned short smallerValue; unsigned short higherValue; }; - protected: +protected: int N; - int ppn; // targeted polyline point number + int ppn; // targeted polyline point number double* x; double* y; // begin of variables used in Parametric curves only @@ -281,10 +333,10 @@ class Curve { double msc; double mhc; // end of variables used in Parametric curves only - std::vector poly_x; // X points of the faceted curve - std::vector poly_y; // Y points of the faceted curve + std::vector poly_x; // X points of the faceted curve + std::vector poly_y; // Y points of the faceted curve std::vector hash; - unsigned short hashSize; // hash table's size, between [10, 100, 1000] + unsigned short hashSize; // hash table's size, between [10, 100, 1000] double* ypp; @@ -294,15 +346,30 @@ class Curve { double increment; int nbr_points; - static inline double p00 (double x, double prot) { return CurveFactory::clower (x, 2.0, prot); } - static inline double p11 (double x, double prot) { return CurveFactory::cupper (x, 2.0, prot); } - static inline double p01 (double x, double prot) { return x<=0.5 ? CurveFactory::clower (x*2, 2.0, prot)/2.0 : 0.5 + CurveFactory::cupper ((x-0.5)*2, 2.0, prot)/2.0; } - static inline double p10 (double x, double prot) { return x<=0.5 ? CurveFactory::cupper (x*2, 2.0, prot)/2.0 : 0.5 + CurveFactory::clower ((x-0.5)*2, 2.0, prot)/2.0; } - static inline double pfull (double x, double prot, double sh, double hl) { return (1-sh)*(1-hl)*p00(x,prot) + sh*hl*p11(x,prot) + (1-sh)*hl*p01(x,prot) + sh*(1-hl)*p10(x,prot); } + static inline double p00 (double x, double prot) + { + return CurveFactory::clower (x, 2.0, prot); + } + static inline double p11 (double x, double prot) + { + return CurveFactory::cupper (x, 2.0, prot); + } + static inline double p01 (double x, double prot) + { + return x <= 0.5 ? CurveFactory::clower (x * 2, 2.0, prot) / 2.0 : 0.5 + CurveFactory::cupper ((x - 0.5) * 2, 2.0, prot) / 2.0; + } + static inline double p10 (double x, double prot) + { + return x <= 0.5 ? CurveFactory::cupper (x * 2, 2.0, prot) / 2.0 : 0.5 + CurveFactory::clower ((x - 0.5) * 2, 2.0, prot) / 2.0; + } + static inline double pfull (double x, double prot, double sh, double hl) + { + return (1 - sh) * (1 - hl) * p00(x, prot) + sh * hl * p11(x, prot) + (1 - sh) * hl * p01(x, prot) + sh * (1 - hl) * p10(x, prot); + } void fillHash(); - public: +public: Curve (); virtual ~Curve () {}; void AddPolygons (); @@ -314,26 +381,31 @@ class Curve { virtual bool isIdentity () const = 0; }; -class DiagonalCurve : public Curve { +class DiagonalCurve : public Curve +{ - protected: +protected: DiagonalCurveType kind; void spline_cubic_set (); void NURBS_set (); - public: - DiagonalCurve (const std::vector& points, int ppn=CURVES_MIN_POLY_POINTS); +public: + DiagonalCurve (const std::vector& points, int ppn = CURVES_MIN_POLY_POINTS); virtual ~DiagonalCurve (); double getVal (double t) const; void getVal (const std::vector& t, std::vector& res) const; - bool isIdentity () const { return kind==DCT_Empty; }; + bool isIdentity () const + { + return kind == DCT_Empty; + }; }; -class FlatCurve : public Curve { +class FlatCurve : public Curve +{ - protected: +protected: FlatCurveType kind; double* leftTangent; double* rightTangent; @@ -342,30 +414,38 @@ class FlatCurve : public Curve { void CtrlPoints_set (); - public: +public: - FlatCurve (const std::vector& points, bool isPeriodic = true, int ppn=CURVES_MIN_POLY_POINTS); + FlatCurve (const std::vector& points, bool isPeriodic = true, int ppn = CURVES_MIN_POLY_POINTS); virtual ~FlatCurve (); double getVal (double t) const; void getVal (const std::vector& t, std::vector& res) const; bool setIdentityValue (double iVal); - bool isIdentity () const { return kind==FCT_Empty; }; + bool isIdentity () const + { + return kind == FCT_Empty; + }; }; -class ToneCurve { - public: +class ToneCurve +{ +public: LUTf lutToneCurve; // 0xffff range virtual ~ToneCurve() {}; void Reset(); - void Set(Curve *pCurve, float gamma=0, float start=0, float slope=0, float mul=0, float add=0); - operator bool (void) const { return lutToneCurve; } + void Set(Curve *pCurve, float gamma = 0, float start = 0, float slope = 0, float mul = 0, float add = 0); + operator bool (void) const + { + return lutToneCurve; + } }; -class OpacityCurve { - public: +class OpacityCurve +{ +public: LUTf lutOpacityCurve; // 0xffff range virtual ~OpacityCurve() {}; @@ -375,121 +455,175 @@ class OpacityCurve { void Set(const std::vector &curvePoints, bool &opautili); // TODO: transfer this method to the Color class... - float blend (float x, float lower, float upper) const { - return (upper-lower)*lutOpacityCurve[x*500.f] + lower; + float blend (float x, float lower, float upper) const + { + return (upper - lower) * lutOpacityCurve[x * 500.f] + lower; } - void blend3f (float x, float lower1, float upper1, float &result1, float lower2, float upper2, float &result2, float lower3, float upper3, float &result3) const { - float opacity = lutOpacityCurve[x*500.f]; - result1 = (upper1-lower1)*opacity + lower1; - result2 = (upper2-lower2)*opacity + lower2; - result3 = (upper3-lower3)*opacity + lower3; + void blend3f (float x, float lower1, float upper1, float &result1, float lower2, float upper2, float &result2, float lower3, float upper3, float &result3) const + { + float opacity = lutOpacityCurve[x * 500.f]; + result1 = (upper1 - lower1) * opacity + lower1; + result2 = (upper2 - lower2) * opacity + lower2; + result3 = (upper3 - lower3) * opacity + lower3; } - operator bool (void) const { return lutOpacityCurve; } + operator bool (void) const + { + return lutOpacityCurve; + } }; -class WavCurve { - private: +class WavCurve +{ +private: LUTf lutWavCurve; // 0xffff range void Set(const Curve &pCurve); - - public: - float sum; - + +public: + float sum; + virtual ~WavCurve() {}; - WavCurve(); + WavCurve(); void Reset(); void Set(const std::vector &curvePoints); - float getSum() const {return sum;} + float getSum() const + { + return sum; + } - float operator[](float index) const { return lutWavCurve[index]; } - operator bool (void) const { return lutWavCurve; } + float operator[](float index) const + { + return lutWavCurve[index]; + } + operator bool (void) const + { + return lutWavCurve; + } }; -class WavOpacityCurveRG { - private: +class WavOpacityCurveRG +{ +private: LUTf lutOpacityCurveRG; // 0xffff range void Set(const Curve &pCurve); - public: +public: virtual ~WavOpacityCurveRG() {}; - WavOpacityCurveRG(); + WavOpacityCurveRG(); void Reset(); - // void Set(const std::vector &curvePoints, bool &opautili); + // void Set(const std::vector &curvePoints, bool &opautili); void Set(const std::vector &curvePoints); - float operator[](float index) const { return lutOpacityCurveRG[index]; } + float operator[](float index) const + { + return lutOpacityCurveRG[index]; + } - operator bool (void) const { return lutOpacityCurveRG; } + operator bool (void) const + { + return lutOpacityCurveRG; + } }; -class WavOpacityCurveBY { - private: +class WavOpacityCurveBY +{ +private: LUTf lutOpacityCurveBY; // 0xffff range void Set(const Curve &pCurve); - public: +public: virtual ~WavOpacityCurveBY() {}; - WavOpacityCurveBY(); + WavOpacityCurveBY(); void Reset(); void Set(const Curve *pCurve); void Set(const std::vector &curvePoints); - float operator[](float index) const { return lutOpacityCurveBY[index]; } + float operator[](float index) const + { + return lutOpacityCurveBY[index]; + } - operator bool (void) const { return lutOpacityCurveBY; } + operator bool (void) const + { + return lutOpacityCurveBY; + } }; -class WavOpacityCurveW { - private: +class WavOpacityCurveW +{ +private: LUTf lutOpacityCurveW; // 0xffff range void Set(const Curve &pCurve); - public: +public: virtual ~WavOpacityCurveW() {}; - WavOpacityCurveW(); + WavOpacityCurveW(); void Reset(); void Set(const Curve *pCurve); void Set(const std::vector &curvePoints); - float operator[](float index) const { return lutOpacityCurveW[index]; } + float operator[](float index) const + { + return lutOpacityCurveW[index]; + } - operator bool (void) const { return lutOpacityCurveW; } + operator bool (void) const + { + return lutOpacityCurveW; + } }; -class WavOpacityCurveWL { - private: +class WavOpacityCurveWL +{ +private: LUTf lutOpacityCurveWL; // 0xffff range void Set(const Curve &pCurve); - public: +public: virtual ~WavOpacityCurveWL() {}; - WavOpacityCurveWL(); + WavOpacityCurveWL(); void Reset(); void Set(const Curve *pCurve); void Set(const std::vector &curvePoints); - float operator[](float index) const { return lutOpacityCurveWL[index]; } + float operator[](float index) const + { + return lutOpacityCurveWL[index]; + } - operator bool (void) const { return lutOpacityCurveWL; } + operator bool (void) const + { + return lutOpacityCurveWL; + } }; -class NoiseCurve { - private: +class NoiseCurve +{ +private: LUTf lutNoiseCurve; // 0xffff range - float sum; + float sum; void Set(const Curve &pCurve); - - public: + +public: virtual ~NoiseCurve() {}; - NoiseCurve(); + NoiseCurve(); void Reset(); void Set(const std::vector &curvePoints); - - float getSum() const {return sum;} - float operator[](float index) const { return lutNoiseCurve[index]; } - operator bool (void) const { return lutNoiseCurve; } + + float getSum() const + { + return sum; + } + float operator[](float index) const + { + return lutNoiseCurve[index]; + } + operator bool (void) const + { + return lutNoiseCurve; + } }; -class ColorGradientCurve { - public: +class ColorGradientCurve +{ +public: LUTf lut1; // [0.;1.] range (float values) LUTf lut2; // [0.;1.] range (float values) LUTf lut3; // [0.;1.] range (float values) @@ -512,78 +646,95 @@ class ColorGradientCurve { * @param b corresponding blue value [0 ; 65535] (return value) */ void getVal(float index, float &r, float &g, float &b) const; - operator bool (void) const { return lut1 && lut2 && lut3; } + operator bool (void) const + { + return lut1 && lut2 && lut3; + } }; -class ColorAppearance { - public: +class ColorAppearance +{ +public: LUTf lutColCurve; // 0xffff range virtual ~ColorAppearance() {}; void Reset(); void Set(Curve *pCurve); - operator bool (void) const { return lutColCurve; } + operator bool (void) const + { + return lutColCurve; + } }; -class Lightcurve : public ColorAppearance { - public: +class Lightcurve : public ColorAppearance +{ +public: void Apply(float& Li) const; }; //lightness curve -inline void Lightcurve::Apply (float& Li) const { +inline void Lightcurve::Apply (float& Li) const +{ assert (lutColCurve); Li = lutColCurve[Li]; } -class Brightcurve : public ColorAppearance { - public: +class Brightcurve : public ColorAppearance +{ +public: void Apply(float& Br) const; }; //brightness curve -inline void Brightcurve::Apply (float& Br) const { +inline void Brightcurve::Apply (float& Br) const +{ assert (lutColCurve); Br = lutColCurve[Br]; } -class Chromacurve : public ColorAppearance { - public: +class Chromacurve : public ColorAppearance +{ +public: void Apply(float& Cr) const; }; //Chroma curve -inline void Chromacurve::Apply (float& Cr) const { +inline void Chromacurve::Apply (float& Cr) const +{ assert (lutColCurve); Cr = lutColCurve[Cr]; } -class Saturcurve : public ColorAppearance { - public: +class Saturcurve : public ColorAppearance +{ +public: void Apply(float& Sa) const; }; //Saturation curve -inline void Saturcurve::Apply (float& Sa) const { +inline void Saturcurve::Apply (float& Sa) const +{ assert (lutColCurve); Sa = lutColCurve[Sa]; } -class Colorfcurve : public ColorAppearance { - public: +class Colorfcurve : public ColorAppearance +{ +public: void Apply(float& Cf) const; }; //Colorfullness curve -inline void Colorfcurve::Apply (float& Cf) const { +inline void Colorfcurve::Apply (float& Cf) const +{ assert (lutColCurve); @@ -591,55 +742,64 @@ inline void Colorfcurve::Apply (float& Cf) const { } -class StandardToneCurve : public ToneCurve { - public: +class StandardToneCurve : public ToneCurve +{ +public: void Apply(float& r, float& g, float& b) const; }; -class StandardToneCurvebw : public ToneCurve { - public: +class StandardToneCurvebw : public ToneCurve +{ +public: void Apply(float& r, float& g, float& b) const; }; -class AdobeToneCurve : public ToneCurve { - private: +class AdobeToneCurve : public ToneCurve +{ +private: void RGBTone(float& r, float& g, float& b) const; // helper for tone curve - public: +public: void Apply(float& r, float& g, float& b) const; }; -class AdobeToneCurvebw : public ToneCurve { - private: +class AdobeToneCurvebw : public ToneCurve +{ +private: void RGBTone(float& r, float& g, float& b) const; // helper for tone curve - public: +public: void Apply(float& r, float& g, float& b) const; }; -class SatAndValueBlendingToneCurve : public ToneCurve { - public: +class SatAndValueBlendingToneCurve : public ToneCurve +{ +public: void Apply(float& r, float& g, float& b) const; }; -class SatAndValueBlendingToneCurvebw : public ToneCurve { - public: +class SatAndValueBlendingToneCurvebw : public ToneCurve +{ +public: void Apply(float& r, float& g, float& b) const; }; -class WeightedStdToneCurve : public ToneCurve { - private: +class WeightedStdToneCurve : public ToneCurve +{ +private: float Triangle(float refX, float refY, float X2) const; - public: +public: void Apply(float& r, float& g, float& b) const; }; -class LuminanceToneCurve : public ToneCurve { - public: +class LuminanceToneCurve : public ToneCurve +{ +public: void Apply(float& r, float& g, float& b) const; }; -class PerceptualToneCurveState { - public: +class PerceptualToneCurveState +{ +public: bool isProphoto; float Working2Prophoto[3][3]; float Prophoto2Working[3][3]; @@ -650,8 +810,9 @@ class PerceptualToneCurveState { // but colors appears to have the same hue and saturation as before. As contrast and saturation is tightly // coupled in human vision saturation is modulated based on the curve's contrast, and that way the appearance // can be kept perceptually constant (within limits). -class PerceptualToneCurve : public ToneCurve { - private: +class PerceptualToneCurve : public ToneCurve +{ +private: static cmsHANDLE *h02; static cmsContext *c02; static float cf_range[2]; @@ -661,22 +822,24 @@ class PerceptualToneCurve : public ToneCurve { static float find_tc_slope_fun(float k, void *arg); static float get_curve_val(float x, float range[2], float lut[], size_t lut_size); float calculateToneCurveContrastValue() const; - public: +public: static void init(); static void cleanup(); void initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const; void Apply(float& r, float& g, float& b, PerceptualToneCurveState & state) const; }; -class WeightedStdToneCurvebw : public ToneCurve { - private: +class WeightedStdToneCurvebw : public ToneCurve +{ +private: float Triangle(float refX, float refY, float X2) const; - public: +public: void Apply(float& r, float& g, float& b) const; }; // Standard tone curve -inline void StandardToneCurve::Apply (float& r, float& g, float& b) const { +inline void StandardToneCurve::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); @@ -685,7 +848,8 @@ inline void StandardToneCurve::Apply (float& r, float& g, float& b) const { b = lutToneCurve[b]; } // Standard tone curve -inline void StandardToneCurvebw::Apply (float& r, float& g, float& b) const { +inline void StandardToneCurvebw::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); @@ -697,56 +861,72 @@ inline void StandardToneCurvebw::Apply (float& r, float& g, float& b) const { // Tone curve according to Adobe's reference implementation // values in 0xffff space // inlined to make sure there will be no cache flush when used -inline void AdobeToneCurve::Apply (float& r, float& g, float& b) const { +inline void AdobeToneCurve::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); if (r >= g) { - if (g > b) RGBTone (r, g, b); // Case 1: r >= g > b - else if (b > r) RGBTone (b, r, g); // Case 2: b > r >= g - else if (b > g) RGBTone (r, b, g); // Case 3: r >= b > g - else { // Case 4: r >= g == b + if (g > b) { + RGBTone (r, g, b); // Case 1: r >= g > b + } else if (b > r) { + RGBTone (b, r, g); // Case 2: b > r >= g + } else if (b > g) { + RGBTone (r, b, g); // Case 3: r >= b > g + } else { // Case 4: r >= g == b r = lutToneCurve[r]; g = lutToneCurve[g]; b = g; } - } - else { - if (r >= b) RGBTone (g, r, b); // Case 5: g > r >= b - else if (b > g) RGBTone (b, g, r); // Case 6: b > g > r - else RGBTone (g, b, r); // Case 7: g >= b > r + } else { + if (r >= b) { + RGBTone (g, r, b); // Case 5: g > r >= b + } else if (b > g) { + RGBTone (b, g, r); // Case 6: b > g > r + } else { + RGBTone (g, b, r); // Case 7: g >= b > r + } } } -inline void AdobeToneCurvebw::Apply (float& r, float& g, float& b) const { +inline void AdobeToneCurvebw::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); if (r >= g) { - if (g > b) RGBTone (r, g, b); // Case 1: r >= g > b - else if (b > r) RGBTone (b, r, g); // Case 2: b > r >= g - else if (b > g) RGBTone (r, b, g); // Case 3: r >= b > g - else { // Case 4: r >= g == b + if (g > b) { + RGBTone (r, g, b); // Case 1: r >= g > b + } else if (b > r) { + RGBTone (b, r, g); // Case 2: b > r >= g + } else if (b > g) { + RGBTone (r, b, g); // Case 3: r >= b > g + } else { // Case 4: r >= g == b r = lutToneCurve[r]; g = lutToneCurve[g]; b = g; } - } - else { - if (r >= b) RGBTone (g, r, b); // Case 5: g > r >= b - else if (b > g) RGBTone (b, g, r); // Case 6: b > g > r - else RGBTone (g, b, r); // Case 7: g >= b > r + } else { + if (r >= b) { + RGBTone (g, r, b); // Case 5: g > r >= b + } else if (b > g) { + RGBTone (b, g, r); // Case 6: b > g > r + } else { + RGBTone (g, b, r); // Case 7: g >= b > r + } } } -inline void AdobeToneCurve::RGBTone (float& r, float& g, float& b) const { - float rold=r,gold=g,bold=b; +inline void AdobeToneCurve::RGBTone (float& r, float& g, float& b) const +{ + float rold = r, gold = g, bold = b; r = lutToneCurve[rold]; b = lutToneCurve[bold]; g = b + ((r - b) * (gold - bold) / (rold - bold)); } -inline void AdobeToneCurvebw::RGBTone (float& r, float& g, float& b) const { - float rold=r,gold=g,bold=b; +inline void AdobeToneCurvebw::RGBTone (float& r, float& g, float& b) const +{ + float rold = r, gold = g, bold = b; r = lutToneCurve[rold]; b = lutToneCurve[bold]; @@ -754,41 +934,57 @@ inline void AdobeToneCurvebw::RGBTone (float& r, float& g, float& b) const { } // Modifying the Luminance channel only -inline void LuminanceToneCurve::Apply(float &r, float &g, float &b) const { - assert (lutToneCurve); +inline void LuminanceToneCurve::Apply(float &r, float &g, float &b) const +{ + assert (lutToneCurve); - float currLuminance = r*0.2126729f + g*0.7151521f + b*0.0721750f; - float newLuminance = lutToneCurve[currLuminance]; - float coef = newLuminance/currLuminance; - r = LIM(r*coef, 0.f, 65535.f); - g = LIM(g*coef, 0.f, 65535.f); - b = LIM(b*coef, 0.f, 65535.f); + float currLuminance = r * 0.2126729f + g * 0.7151521f + b * 0.0721750f; + float newLuminance = lutToneCurve[currLuminance]; + float coef = newLuminance / currLuminance; + r = LIM(r * coef, 0.f, 65535.f); + g = LIM(g * coef, 0.f, 65535.f); + b = LIM(b * coef, 0.f, 65535.f); } -inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const { - if (a != b) { - float b1; - float a2 = a1 - a; - if (b < a) { b1 = b + a2 * b / a ; } - else { b1 = b + a2 * (65535.f-b) / (65535.f-a); } - return b1; - } - return a1; +inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const +{ + if (a != b) { + float b1; + float a2 = a1 - a; + + if (b < a) { + b1 = b + a2 * b / a ; + } else { + b1 = b + a2 * (65535.f - b) / (65535.f - a); + } + + return b1; + } + + return a1; } -inline float WeightedStdToneCurvebw::Triangle(float a, float a1, float b) const { - if (a != b) { - float b1; - float a2 = a1 - a; - if (b < a) { b1 = b + a2 * b / a ; } - else { b1 = b + a2 * (65535.f-b) / (65535.f-a); } - return b1; - } - return a1; +inline float WeightedStdToneCurvebw::Triangle(float a, float a1, float b) const +{ + if (a != b) { + float b1; + float a2 = a1 - a; + + if (b < a) { + b1 = b + a2 * b / a ; + } else { + b1 = b + a2 * (65535.f - b) / (65535.f - a); + } + + return b1; + } + + return a1; } // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space -inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const { +inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); @@ -804,12 +1000,13 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const { float r3 = Triangle(b, b3, r); float g3 = Triangle(b, b3, g); - r = CLIP( r1*0.50f + r2*0.25f + r3*0.25f); - g = CLIP(g1*0.25f + g2*0.50f + g3*0.25f); - b = CLIP(b1*0.25f + b2*0.25f + b3*0.50f); + r = CLIP( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); + g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f); + b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f); } -inline void WeightedStdToneCurvebw::Apply (float& r, float& g, float& b) const { +inline void WeightedStdToneCurvebw::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); @@ -825,68 +1022,74 @@ inline void WeightedStdToneCurvebw::Apply (float& r, float& g, float& b) const { float r3 = Triangle(b, b3, r); float g3 = Triangle(b, b3, g); - r = CLIP( r1*0.50f + r2*0.25f + r3*0.25f); - g = CLIP(g1*0.25f + g2*0.50f + g3*0.25f); - b = CLIP(b1*0.25f + b2*0.25f + b3*0.50f); + r = CLIP( r1 * 0.50f + r2 * 0.25f + r3 * 0.25f); + g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f); + b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f); } // Tone curve modifying the value channel only, preserving hue and saturation // values in 0xffff space -inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) const { +inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); float h, s, v; - float lum = (r+g+b)/3.f; + float lum = (r + g + b) / 3.f; //float lum = Color::rgbLuminance(r, g, b); float newLum = lutToneCurve[lum]; - if (newLum == lum) - return; + + if (newLum == lum) { + return; + } + bool increase = newLum > lum; Color::rgb2hsv(r, g, b, h, s, v); if (increase) { - // Linearly targeting Value = 1 and Saturation = 0 - float coef = (newLum-lum)/(65535.f-lum); - float dV = (1.f-v)*coef; - s *= 1.f-coef; - Color::hsv2rgb(h, s, v+dV, r, g, b); - } - else { - // Linearly targeting Value = 0 - float coef = (lum-newLum)/lum ; - float dV = v*coef; - Color::hsv2rgb(h, s, v-dV, r, g, b); + // Linearly targeting Value = 1 and Saturation = 0 + float coef = (newLum - lum) / (65535.f - lum); + float dV = (1.f - v) * coef; + s *= 1.f - coef; + Color::hsv2rgb(h, s, v + dV, r, g, b); + } else { + // Linearly targeting Value = 0 + float coef = (lum - newLum) / lum ; + float dV = v * coef; + Color::hsv2rgb(h, s, v - dV, r, g, b); } } -inline void SatAndValueBlendingToneCurvebw::Apply (float& r, float& g, float& b) const { +inline void SatAndValueBlendingToneCurvebw::Apply (float& r, float& g, float& b) const +{ assert (lutToneCurve); float h, s, v; - float lum = (r+g+b)/3.f; + float lum = (r + g + b) / 3.f; //float lum = Color::rgbLuminance(r, g, b); float newLum = lutToneCurve[lum]; - if (newLum == lum) - return; + + if (newLum == lum) { + return; + } + bool increase = newLum > lum; Color::rgb2hsv(r, g, b, h, s, v); if (increase) { - // Linearly targeting Value = 1 and Saturation = 0 - float coef = (newLum-lum)/(65535.f-lum); - float dV = (1.f-v)*coef; - s *= 1.f-coef; - Color::hsv2rgb(h, s, v+dV, r, g, b); - } - else { - // Linearly targeting Value = 0 - float coef = (lum-newLum)/lum ; - float dV = v*coef; - Color::hsv2rgb(h, s, v-dV, r, g, b); + // Linearly targeting Value = 1 and Saturation = 0 + float coef = (newLum - lum) / (65535.f - lum); + float dV = (1.f - v) * coef; + s *= 1.f - coef; + Color::hsv2rgb(h, s, v + dV, r, g, b); + } else { + // Linearly targeting Value = 0 + float coef = (lum - newLum) / lum ; + float dV = v * coef; + Color::hsv2rgb(h, s, v - dV, r, g, b); } } diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 907d7d7c8..965ed47b2 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -7,7 +7,7 @@ * 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 @@ -291,24 +291,29 @@ static const float adobe_camera_raw_default_curve[] = { }; // This sRGB gamma is taken from DNG reference code, with the added linear extension past 1.0, as we run clipless here -static float sRGBGammaForward (const float x) { - if (x <= 0.0031308) +static float sRGBGammaForward (const float x) +{ + if (x <= 0.0031308) { return x * 12.92; - else if (x > 1.0) - return 1.0 + (x - 1.0) * (1.055*(1.0/2.4)); // linear extension - else + } else if (x > 1.0) { + return 1.0 + (x - 1.0) * (1.055 * (1.0 / 2.4)); // linear extension + } else { return 1.055 * pow (x, 1.0 / 2.4) - 0.055; + } } -static float sRGBGammaInverse (const float y) { - if (y <= 0.0031308 * 12.92) +static float sRGBGammaInverse (const float y) +{ + if (y <= 0.0031308 * 12.92) { return y * (1.0 / 12.92); - else if (y > 1.0) - return 1.0 + (y - 1.0) / (1.055*(1.0/2.4)); - else + } else if (y > 1.0) { + return 1.0 + (y - 1.0) / (1.055 * (1.0 / 2.4)); + } else { return pow ((y + 0.055) * (1.0 / 1.055), 2.4); + } } -static void Invert3x3(const double (*A)[3], double (*B)[3]) { +static void Invert3x3(const double (*A)[3], double (*B)[3]) +{ double a00 = A[0][0]; double a01 = A[0][1]; @@ -337,52 +342,63 @@ static void Invert3x3(const double (*A)[3], double (*B)[3]) { abort(); // can't be inverted, we shouldn't be dealing with such matrices } - for (int j = 0; j < 3; j++) { + for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { B[j][k] = temp[j][k] / det; } } } -static void Multiply3x3(const double (*A)[3], const double (*B)[3], double (*C)[3]) { +static void Multiply3x3(const double (*A)[3], const double (*B)[3], double (*C)[3]) +{ // use temp to support having output same as input double M[3][3]; + for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { M[i][j] = 0; + for (int k = 0; k < 3; k++) { M[i][j] += A[i][k] * B[k][j]; } } } + memcpy(C, M, 3 * 3 * sizeof(double)); } -static void Multiply3x3_v3(const double (*A)[3], const double B[3], double C[3]) { +static void Multiply3x3_v3(const double (*A)[3], const double B[3], double C[3]) +{ // use temp to support having output same as input double M[3] = { 0, 0, 0 }; + for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { M[i] += A[i][j] * B[j]; } } + memcpy(C, M, 3 * sizeof(double)); } -static void Mix3x3(const double (*A)[3], double mulA, const double (*B)[3], double mulB, double (*C)[3]) { +static void Mix3x3(const double (*A)[3], double mulA, const double (*B)[3], double mulB, double (*C)[3]) +{ double M[3][3]; + for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { M[i][j] = A[i][j] * mulA + B[i][j] * mulB; } } + memcpy(C, M, 3 * 3 * sizeof(double)); } -static void MapWhiteMatrix(const double white1[3], const double white2[3], double (*B)[3]) { +static void MapWhiteMatrix(const double white1[3], const double white2[3], double (*B)[3]) +{ // code adapted from dng_color_spec::MapWhiteMatrix @@ -414,11 +430,13 @@ static void MapWhiteMatrix(const double white1[3], const double white2[3], doubl Multiply3x3(temp, Mb, B); } -static void XYZtoXY(const double XYZ[3], double XY[2]) { +static void XYZtoXY(const double XYZ[3], double XY[2]) +{ double X = XYZ[0]; double Y = XYZ[1]; double Z = XYZ[2]; double total = X + Y + Z; + if (total > 0.0) { XY[0] = X / total; XY[1] = Y / total; @@ -428,18 +446,21 @@ static void XYZtoXY(const double XYZ[3], double XY[2]) { } } -static void XYtoXYZ(const double XY[2], double XYZ[3]) { +static void XYtoXYZ(const double XY[2], double XYZ[3]) +{ double temp[2] = { XY[0], XY[1] }; // Restrict xy coord to someplace inside the range of real xy coordinates. // This prevents math from doing strange things when users specify // extreme temperature/tint coordinates. temp[0] = std::max(0.000001, std::min(temp[0], 0.999999)); temp[1] = std::max(0.000001, std::min(temp[1], 0.999999)); + if (temp[0] + temp[1] > 0.999999) { double scale = 0.999999 / (temp[0] + temp[1]); temp[0] *= scale; temp[1] *= scale; } + XYZ[0] = temp[0] / temp[1]; XYZ[1] = 1.0; XYZ[2] = (1.0 - temp[0] - temp[1]) / temp[1]; @@ -454,8 +475,8 @@ enum dngCalibrationIlluminant { lsFineWeather = 9, lsCloudyWeather = 10, lsShade = 11, - lsDaylightFluorescent = 12, // D 5700 - 7100K - lsDayWhiteFluorescent = 13, // N 4600 - 5500K + lsDaylightFluorescent = 12, // D 5700 - 7100K + lsDayWhiteFluorescent = 13, // N 4600 - 5500K lsCoolWhiteFluorescent = 14, // W 3800 - 4500K lsWhiteFluorescent = 15, // WW 3250 - 3800K lsWarmWhiteFluorescent = 16, // L 2600 - 3250K @@ -471,41 +492,53 @@ enum dngCalibrationIlluminant { }; // should probably be moved to colortemp.cc -static double calibrationIlluminantToTemperature(int light) { +static double calibrationIlluminantToTemperature(int light) +{ // these temperatures are those found in DNG SDK reference code. switch (light) { case lsStandardLightA: case lsTungsten: return 2850.0; + case lsISOStudioTungsten: return 3200.0; + case lsD50: return 5000.0; + case lsD55: case lsDaylight: case lsFineWeather: case lsFlash: case lsStandardLightB: return 5500.0; + case lsD65: case lsStandardLightC: case lsCloudyWeather: return 6500.0; + case lsD75: case lsShade: return 7500.0; + case lsDaylightFluorescent: return (5700.0 + 7100.0) * 0.5; + case lsDayWhiteFluorescent: return (4600.0 + 5500.0) * 0.5; + case lsCoolWhiteFluorescent: case lsFluorescent: return (3800.0 + 4500.0) * 0.5; + case lsWhiteFluorescent: return (3250.0 + 3800.0) * 0.5; + case lsWarmWhiteFluorescent: return (2600.0 + 3250.0) * 0.5; + default: return 0.0; } @@ -528,18 +561,20 @@ void DCPProfile::MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix Invert3x3(camWbMatrix, cam_xyz); double cam_rgb[3][3]; Multiply3x3(cam_xyz, xyz_sRGB, cam_rgb); - double camwb_red = cam_rgb[0][0]*r + cam_rgb[0][1]*g + cam_rgb[0][2]*b; - double camwb_green = cam_rgb[1][0]*r + cam_rgb[1][1]*g + cam_rgb[1][2]*b; - double camwb_blue = cam_rgb[2][0]*r + cam_rgb[2][1]*g + cam_rgb[2][2]*b; + double camwb_red = cam_rgb[0][0] * r + cam_rgb[0][1] * g + cam_rgb[0][2] * b; + double camwb_green = cam_rgb[1][0] * r + cam_rgb[1][1] * g + cam_rgb[1][2] * b; + double camwb_blue = cam_rgb[2][0] * r + cam_rgb[2][1] * g + cam_rgb[2][2] * b; neutral[0] = camwb_red / pre_mul[0]; neutral[1] = camwb_green / pre_mul[1]; neutral[2] = camwb_blue / pre_mul[2]; double maxentry = 0; + for (int i = 0; i < 3; i++) { if (neutral[i] > maxentry) { maxentry = neutral[i]; } } + for (int i = 0; i < 3; i++) { neutral[i] /= maxentry; } @@ -556,22 +591,35 @@ void DCPProfile::MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix bool hasFwd2 = hasForwardMatrix2; bool hasCol1 = hasColorMatrix1; bool hasCol2 = hasColorMatrix2; + if (preferredIlluminant == 1) { - if (hasFwd1) hasFwd2 = false; - if (hasCol1) hasCol2 = false; + if (hasFwd1) { + hasFwd2 = false; + } + + if (hasCol1) { + hasCol2 = false; + } } else if (preferredIlluminant == 2) { - if (hasFwd2) hasFwd1 = false; - if (hasCol2) hasCol1 = false; + if (hasFwd2) { + hasFwd1 = false; + } + + if (hasCol2) { + hasCol1 = false; + } } // mix if we have two matrices double mix = 1.0; + if ((hasCol1 && hasCol2) || (hasFwd1 && hasFwd2)) { double wbtemp; /* DNG ref way to convert XY to temperature, which affect matrix mixing. A different model here typically does not affect the result too much, ie it's probably not strictly necessary to use the DNG reference code here, but we do it for now. */ dngref_XYCoord2Temperature(white_xy, &wbtemp, NULL); + if (wbtemp <= temperature1) { mix = 1.0; } else if (wbtemp >= temperature2) { @@ -584,6 +632,7 @@ void DCPProfile::MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix // Colormatrix double mCol[3][3]; + if (hasCol1 && hasCol2) { // interpolate if (mix >= 1.0) { @@ -611,9 +660,11 @@ void DCPProfile::MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix XYtoXYZ(white_xy, white_xyz); double cam_xyz[3][3]; + if (hasFwd1 || hasFwd2) { // always prefer ForwardMatrix ahead of ColorMatrix double mFwd[3][3]; + if (hasFwd1 && hasFwd2) { // interpolate if (mix >= 1.0) { @@ -628,6 +679,7 @@ void DCPProfile::MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix } else { memcpy(mFwd, mForwardMatrix2, sizeof(mFwd)); } + // adapted from dng_color_spec::SetWhiteXY double CameraWhite[3]; Multiply3x3_v3(mCol, white_xyz, CameraWhite); @@ -651,40 +703,55 @@ void DCPProfile::MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix { // This block can probably be simplified, seems unnecessary to pass through the sRGB matrix // (probably dcraw legacy), it does no harm though as we don't clip anything. - int i,j,k; + int i, j, k; // Multiply out XYZ colorspace double cam_rgb[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; - for (i=0; i < 3; i++) - for (j=0; j < 3; j++) - for (k=0; k < 3; k++) + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + for (k = 0; k < 3; k++) { cam_rgb[i][j] += cam_xyz[i][k] * xyz_sRGB[k][j]; + } // Normalize cam_rgb so that: cam_rgb * (1,1,1) is (1,1,1,1) double num; - for (i=0; i<3; i++) { - for (num=j=0; j<3; j++) num += cam_rgb[i][j]; - for (j=0; j<3; j++) cam_rgb[i][j] /= num; + + for (i = 0; i < 3; i++) { + for (num = j = 0; j < 3; j++) { + num += cam_rgb[i][j]; + } + + for (j = 0; j < 3; j++) { + cam_rgb[i][j] /= num; + } } double rgb_cam[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; RawImageSource::inverse33 (cam_rgb, rgb_cam); - for (i=0; i<3; i++) - for (j=0; j<3; j++) mXYZCAM[i][j]=0; - for (i=0; i<3; i++) - for (j=0; j<3; j++) - for (k=0; k<3; k++) + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) { + mXYZCAM[i][j] = 0; + } + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + for (k = 0; k < 3; k++) { mXYZCAM[i][j] += xyz_sRGB[i][k] * rgb_cam[k][j]; + } } } -const DCPProfile::HSBModify* DCPProfile::MakeHueSatMap(ColorTemp &wb, int preferredIlluminant, HSBModify **deleteHandle) const { +const DCPProfile::HSBModify* DCPProfile::MakeHueSatMap(ColorTemp &wb, int preferredIlluminant, HSBModify **deleteHandle) const +{ *deleteHandle = NULL; + if (!aDeltas1) { return NULL; } + if (!aDeltas2) { return aDeltas1; } @@ -699,8 +766,10 @@ const DCPProfile::HSBModify* DCPProfile::MakeHueSatMap(ColorTemp &wb, int prefer if (temperature1 <= 0.0 || temperature2 <= 0.0 || temperature1 == temperature2) { return aDeltas1; } + bool reverseOrder = temperature1 > temperature2; double t1, t2; + if (reverseOrder) { t1 = temperature2; t2 = temperature1; @@ -710,6 +779,7 @@ const DCPProfile::HSBModify* DCPProfile::MakeHueSatMap(ColorTemp &wb, int prefer } double mix; + if (wb.getTemp() <= t1) { mix = 1.0; } else if (wb.getTemp() >= t2) { @@ -734,37 +804,42 @@ const DCPProfile::HSBModify* DCPProfile::MakeHueSatMap(ColorTemp &wb, int prefer *deleteHandle = aDeltas; float w1 = (float)mix; float w2 = 1.0f - (float)mix; + for (int i = 0; i < DeltaInfo.iArrayCount; i++) { aDeltas[i].fHueShift = w1 * aDeltas1[i].fHueShift + w2 * aDeltas2[i].fHueShift; aDeltas[i].fSatScale = w1 * aDeltas1[i].fSatScale + w2 * aDeltas2[i].fSatScale; aDeltas[i].fValScale = w1 * aDeltas1[i].fValScale + w2 * aDeltas2[i].fValScale; } + return aDeltas; } -DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { - const int TIFFFloatSize=4; - const int TagColorMatrix1=50721, TagColorMatrix2=50722, TagProfileHueSatMapDims=50937; - const int TagForwardMatrix1=50964, TagForwardMatrix2=50965; - const int TagProfileHueSatMapData1=50938, TagProfileHueSatMapData2=50939; - const int TagCalibrationIlluminant1=50778, TagCalibrationIlluminant2=50779; - const int TagProfileLookTableData=50982, TagProfileLookTableDims=50981; // ProfileLookup is the low quality variant - const int TagProfileHueSatMapEncoding=51107, TagProfileLookTableEncoding=51108; - const int TagProfileToneCurve=50940, TagBaselineExposureOffset=51109; - const int TagProfileCopyright=50942; +DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) +{ + const int TIFFFloatSize = 4; + const int TagColorMatrix1 = 50721, TagColorMatrix2 = 50722, TagProfileHueSatMapDims = 50937; + const int TagForwardMatrix1 = 50964, TagForwardMatrix2 = 50965; + const int TagProfileHueSatMapData1 = 50938, TagProfileHueSatMapData2 = 50939; + const int TagCalibrationIlluminant1 = 50778, TagCalibrationIlluminant2 = 50779; + const int TagProfileLookTableData = 50982, TagProfileLookTableDims = 50981; // ProfileLookup is the low quality variant + const int TagProfileHueSatMapEncoding = 51107, TagProfileLookTableEncoding = 51108; + const int TagProfileToneCurve = 50940, TagBaselineExposureOffset = 51109; + const int TagProfileCopyright = 50942; - aDeltas1=aDeltas2=aLookTable=NULL; + aDeltas1 = aDeltas2 = aLookTable = NULL; FILE *pFile = safe_g_fopen(fname, "rb"); - TagDirectory *tagDir=ExifManager::parseTIFF(pFile, false); + TagDirectory *tagDir = ExifManager::parseTIFF(pFile, false); - Tag* tag = tagDir->getTag(TagCalibrationIlluminant1); iLightSource1 = (tag!=NULL ? tag->toInt(0,rtexif::SHORT) : -1); - tag = tagDir->getTag(TagCalibrationIlluminant2); iLightSource2 = (tag!=NULL ? tag->toInt(0,rtexif::SHORT) : -1); + Tag* tag = tagDir->getTag(TagCalibrationIlluminant1); + iLightSource1 = (tag != NULL ? tag->toInt(0, rtexif::SHORT) : -1); + tag = tagDir->getTag(TagCalibrationIlluminant2); + iLightSource2 = (tag != NULL ? tag->toInt(0, rtexif::SHORT) : -1); temperature1 = calibrationIlluminantToTemperature(iLightSource1); temperature2 = calibrationIlluminantToTemperature(iLightSource2); - bool hasSecondHueSat = tagDir->getTag(TagProfileHueSatMapData2)!=NULL; // some profiles have two matrices, but just one huesat + bool hasSecondHueSat = tagDir->getTag(TagProfileHueSatMapData2) != NULL; // some profiles have two matrices, but just one huesat // Fetch Forward Matrices, if any hasForwardMatrix1 = false; @@ -775,55 +850,65 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { hasBaselineExposureOffset = false; baselineExposureOffset = 0; tag = tagDir->getTag(TagForwardMatrix1); + if (tag) { hasForwardMatrix1 = true; - for (int row=0;row<3;row++) { - for (int col=0;col<3;col++) { - mForwardMatrix1[row][col]=(float)tag->toDouble((col+row*3)*8); + + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 3; col++) { + mForwardMatrix1[row][col] = (float)tag->toDouble((col + row * 3) * 8); } } } + tag = tagDir->getTag(TagForwardMatrix2); + if (tag) { hasForwardMatrix2 = true; - for (int row=0;row<3;row++) { - for (int col=0;col<3;col++) { - mForwardMatrix2[row][col]=(float)tag->toDouble((col+row*3)*8); + + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 3; col++) { + mForwardMatrix2[row][col] = (float)tag->toDouble((col + row * 3) * 8); } } } // Color Matrix (1 is always there) tag = tagDir->getTag(TagColorMatrix1); + if (!tag) { // FIXME: better error handling fprintf(stderr, "Bad DCP, no ColorMatrix1\n"); abort(); } + hasColorMatrix1 = true; - for (int row=0;row<3;row++) { - for (int col=0;col<3;col++) { - mColorMatrix1[row][col]=(float)tag->toDouble((col+row*3)*8); + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 3; col++) { + mColorMatrix1[row][col] = (float)tag->toDouble((col + row * 3) * 8); } } - tag=tagDir->getTag(TagProfileLookTableDims); - if (tag!=NULL) { - LookInfo.iHueDivisions=tag->toInt(0); LookInfo.iSatDivisions=tag->toInt(4); LookInfo.iValDivisions=tag->toInt(8); + tag = tagDir->getTag(TagProfileLookTableDims); + + if (tag != NULL) { + LookInfo.iHueDivisions = tag->toInt(0); + LookInfo.iSatDivisions = tag->toInt(4); + LookInfo.iValDivisions = tag->toInt(8); tag = tagDir->getTag(TagProfileLookTableEncoding); LookInfo.sRGBGamma = tag != NULL && tag->toInt(0); tag = tagDir->getTag(TagProfileLookTableData); - LookInfo.iArrayCount = tag->getCount()/3; + LookInfo.iArrayCount = tag->getCount() / 3; - aLookTable =new HSBModify[LookInfo.iArrayCount]; + aLookTable = new HSBModify[LookInfo.iArrayCount]; - for (int i=0;itoDouble((i*3)*TIFFFloatSize); - aLookTable[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize); - aLookTable[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize); + for (int i = 0; i < LookInfo.iArrayCount; i++) { + aLookTable[i].fHueShift = tag->toDouble((i * 3) * TIFFFloatSize); + aLookTable[i].fSatScale = tag->toDouble((i * 3 + 1) * TIFFFloatSize); + aLookTable[i].fValScale = tag->toDouble((i * 3 + 2) * TIFFFloatSize); } // precalculated constants for table application @@ -838,21 +923,24 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { } tag = tagDir->getTag(TagProfileHueSatMapDims); - if (tag!=NULL) { - DeltaInfo.iHueDivisions=tag->toInt(0); DeltaInfo.iSatDivisions=tag->toInt(4); DeltaInfo.iValDivisions=tag->toInt(8); + + if (tag != NULL) { + DeltaInfo.iHueDivisions = tag->toInt(0); + DeltaInfo.iSatDivisions = tag->toInt(4); + DeltaInfo.iValDivisions = tag->toInt(8); tag = tagDir->getTag(TagProfileHueSatMapEncoding); DeltaInfo.sRGBGamma = tag != NULL && tag->toInt(0); tag = tagDir->getTag(TagProfileHueSatMapData1); - DeltaInfo.iArrayCount = tag->getCount()/3; + DeltaInfo.iArrayCount = tag->getCount() / 3; - aDeltas1=new HSBModify[DeltaInfo.iArrayCount]; + aDeltas1 = new HSBModify[DeltaInfo.iArrayCount]; - for (int i=0;itoDouble((i*3)*TIFFFloatSize); - aDeltas1[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize); - aDeltas1[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize); + for (int i = 0; i < DeltaInfo.iArrayCount; i++) { + aDeltas1[i].fHueShift = tag->toDouble((i * 3) * TIFFFloatSize); + aDeltas1[i].fSatScale = tag->toDouble((i * 3 + 1) * TIFFFloatSize); + aDeltas1[i].fValScale = tag->toDouble((i * 3 + 2) * TIFFFloatSize); } DeltaInfo.pc.hScale = (DeltaInfo.iHueDivisions < 2) ? 0.0f : (DeltaInfo.iHueDivisions * (1.0f / 6.0f)); @@ -865,33 +953,34 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { DeltaInfo.pc.valStep = DeltaInfo.iHueDivisions * DeltaInfo.pc.hueStep; } - if (iLightSource2!=-1) { + if (iLightSource2 != -1) { // Second matrix tag = tagDir->getTag(TagColorMatrix2); hasColorMatrix2 = true; - for (int row=0;row<3;row++) { - for (int col=0;col<3;col++) { - mColorMatrix2[row][col]= (tag!=NULL ? (float)tag->toDouble((col+row*3)*8) : mColorMatrix1[row][col]); + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 3; col++) { + mColorMatrix2[row][col] = (tag != NULL ? (float)tag->toDouble((col + row * 3) * 8) : mColorMatrix1[row][col]); } } // Second huesatmap if (hasSecondHueSat) { - aDeltas2=new HSBModify[DeltaInfo.iArrayCount]; + aDeltas2 = new HSBModify[DeltaInfo.iArrayCount]; // Saturation maps. Need to be unwinded. tag = tagDir->getTag(TagProfileHueSatMapData2); - for (int i=0;itoDouble((i*3)*TIFFFloatSize); - aDeltas2[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize); - aDeltas2[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize); + for (int i = 0; i < DeltaInfo.iArrayCount; i++) { + aDeltas2[i].fHueShift = tag->toDouble((i * 3) * TIFFFloatSize); + aDeltas2[i].fSatScale = tag->toDouble((i * 3 + 1) * TIFFFloatSize); + aDeltas2[i].fValScale = tag->toDouble((i * 3 + 2) * TIFFFloatSize); } } } tag = tagDir->getTag(TagBaselineExposureOffset); + if (tag) { hasBaselineExposureOffset = true; baselineExposureOffset = tag->toDouble(); @@ -899,18 +988,22 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { // Read tone curve points, if any, but disable to RTs own profiles tag = tagDir->getTag(TagProfileToneCurve); - if (tag!=NULL && !isRTProfile) { + + if (tag != NULL && !isRTProfile) { std::vector cPoints; cPoints.push_back(double(DCT_Spline)); // The first value is the curve type // push back each X/Y coordinates in a loop bool curve_is_linear = true; - for (int i=0;igetCount(); i+= 2) { - double x = tag->toDouble((i+0)*TIFFFloatSize); - double y = tag->toDouble((i+1)*TIFFFloatSize); + + for (int i = 0; i < tag->getCount(); i += 2) { + double x = tag->toDouble((i + 0) * TIFFFloatSize); + double y = tag->toDouble((i + 1) * TIFFFloatSize); + if (x != y) { curve_is_linear = false; } + cPoints.push_back( x ); cPoints.push_back( y ); } @@ -924,17 +1017,20 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { } } else if (tag == NULL) { tag = tagDir->getTag(TagProfileCopyright); - if (tag!=NULL && tag->valueToString().find("Adobe Systems") != std::string::npos) { + + if (tag != NULL && tag->valueToString().find("Adobe Systems") != std::string::npos) { // an Adobe profile without tone curve is expected to have the Adobe Default Curve, we add that std::vector cPoints; cPoints.push_back(double(DCT_Spline)); - const size_t tc_len = sizeof(adobe_camera_raw_default_curve)/sizeof(adobe_camera_raw_default_curve[0]); + const size_t tc_len = sizeof(adobe_camera_raw_default_curve) / sizeof(adobe_camera_raw_default_curve[0]); + for (size_t i = 0; i < tc_len; i++) { double x = (double)i / (tc_len - 1); double y = (double)adobe_camera_raw_default_curve[i]; cPoints.push_back( x ); cPoints.push_back( y ); } + DiagonalCurve rawCurve(cPoints, CURVES_MIN_POLY_POINTS); toneCurve.Set((Curve*)&rawCurve); hasToneCurve = true; @@ -942,55 +1038,62 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) { } willInterpolate = false; + if (hasForwardMatrix1) { if (hasForwardMatrix2) { if (memcmp(mForwardMatrix1, mForwardMatrix2, sizeof(mForwardMatrix1)) != 0) { // common that forward matrices are the same! willInterpolate = true; } + if (aDeltas1 && aDeltas2) { // we assume tables are different willInterpolate = true; } } } + if (hasColorMatrix1 && hasColorMatrix2) { if (memcmp(mColorMatrix1, mColorMatrix2, sizeof(mColorMatrix1)) != 0) { willInterpolate = true; } + if (aDeltas1 && aDeltas2) { willInterpolate = true; } } - if (pFile!=NULL) fclose(pFile); + if (pFile != NULL) { + fclose(pFile); + } + delete tagDir; } -DCPProfile::~DCPProfile() { +DCPProfile::~DCPProfile() +{ delete[] aDeltas1; delete[] aDeltas2; delete[] aLookTable; } -void DCPProfile::HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, float &h, float &s, float &v) const { +void DCPProfile::HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, float &h, float &s, float &v) const +{ // Apply the HueSatMap. Ported from Adobes reference implementation float hueShift, satScale, valScale; float vEncoded = v; - if (ti.iValDivisions < 2) // Optimize most common case of "2.5D" table. - { + if (ti.iValDivisions < 2) { // Optimize most common case of "2.5D" table. float hScaled = h * ti.pc.hScale; float sScaled = s * ti.pc.sScale; int hIndex0 = max((int)hScaled, 0); - int sIndex0 = max(min((int)sScaled,ti.pc.maxSatIndex0),0); + int sIndex0 = max(min((int)sScaled, ti.pc.maxSatIndex0), 0); int hIndex1 = hIndex0 + 1; - if (hIndex0 >= ti.pc.maxHueIndex0) - { + if (hIndex0 >= ti.pc.maxHueIndex0) { hIndex0 = ti.pc.maxHueIndex0; hIndex1 = 0; } @@ -1012,13 +1115,13 @@ void DCPProfile::HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, fl entry01++; float hueShift1 = hFract0 * entry00->fHueShift + - hFract1 * entry01->fHueShift; + hFract1 * entry01->fHueShift; float satScale1 = hFract0 * entry00->fSatScale + - hFract1 * entry01->fSatScale; + hFract1 * entry01->fSatScale; float valScale1 = hFract0 * entry00->fValScale + - hFract1 * entry01->fValScale; + hFract1 * entry01->fValScale; hueShift = sFract0 * hueShift0 + sFract1 * hueShift1; satScale = sFract0 * satScale0 + sFract1 * satScale1; @@ -1028,17 +1131,20 @@ void DCPProfile::HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, fl float hScaled = h * ti.pc.hScale; float sScaled = s * ti.pc.sScale; - if (ti.sRGBGamma) vEncoded = sRGBGammaForward(v); + + if (ti.sRGBGamma) { + vEncoded = sRGBGammaForward(v); + } + float vScaled = vEncoded * ti.pc.vScale; int hIndex0 = (int) hScaled; - int sIndex0 = max(min((int)sScaled,ti.pc.maxSatIndex0),0); - int vIndex0 = max(min((int)vScaled,ti.pc.maxValIndex0),0); + int sIndex0 = max(min((int)sScaled, ti.pc.maxSatIndex0), 0); + int vIndex0 = max(min((int)vScaled, ti.pc.maxValIndex0), 0); int hIndex1 = hIndex0 + 1; - if (hIndex0 >= ti.pc.maxHueIndex0) - { + if (hIndex0 >= ti.pc.maxHueIndex0) { hIndex0 = ti.pc.maxHueIndex0; hIndex1 = 0; } @@ -1060,18 +1166,18 @@ void DCPProfile::HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, fl float hueShift0 = vFract0 * (hFract0 * entry00->fHueShift + hFract1 * entry01->fHueShift) + - vFract1 * (hFract0 * entry10->fHueShift + - hFract1 * entry11->fHueShift); + vFract1 * (hFract0 * entry10->fHueShift + + hFract1 * entry11->fHueShift); float satScale0 = vFract0 * (hFract0 * entry00->fSatScale + hFract1 * entry01->fSatScale) + - vFract1 * (hFract0 * entry10->fSatScale + - hFract1 * entry11->fSatScale); + vFract1 * (hFract0 * entry10->fSatScale + + hFract1 * entry11->fSatScale); float valScale0 = vFract0 * (hFract0 * entry00->fValScale + hFract1 * entry01->fValScale) + - vFract1 * (hFract0 * entry10->fValScale + - hFract1 * entry11->fValScale); + vFract1 * (hFract0 * entry10->fValScale + + hFract1 * entry11->fValScale); entry00++; entry01++; @@ -1080,28 +1186,29 @@ void DCPProfile::HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, fl float hueShift1 = vFract0 * (hFract0 * entry00->fHueShift + hFract1 * entry01->fHueShift) + - vFract1 * (hFract0 * entry10->fHueShift + - hFract1 * entry11->fHueShift); + vFract1 * (hFract0 * entry10->fHueShift + + hFract1 * entry11->fHueShift); float satScale1 = vFract0 * (hFract0 * entry00->fSatScale + hFract1 * entry01->fSatScale) + - vFract1 * (hFract0 * entry10->fSatScale + - hFract1 * entry11->fSatScale); + vFract1 * (hFract0 * entry10->fSatScale + + hFract1 * entry11->fSatScale); float valScale1 = vFract0 * (hFract0 * entry00->fValScale + hFract1 * entry01->fValScale) + - vFract1 * (hFract0 * entry10->fValScale + - hFract1 * entry11->fValScale); + vFract1 * (hFract0 * entry10->fValScale + + hFract1 * entry11->fValScale); hueShift = sFract0 * hueShift0 + sFract1 * hueShift1; satScale = sFract0 * satScale0 + sFract1 * satScale1; valScale = sFract0 * valScale0 + sFract1 * valScale1; } - hueShift *= (6.0f / 360.0f); // Convert to internal hue range. + hueShift *= (6.0f / 360.0f); // Convert to internal hue range. h += hueShift; s *= satScale; // no clipping here, we are RT float :-) + if (ti.sRGBGamma) { v = sRGBGammaInverse(vEncoded * valScale); } else { @@ -1117,42 +1224,42 @@ struct ruvt { }; static const double kTintScale = -3000.0; -static const ruvt kTempTable [] = - { - { 0, 0.18006, 0.26352, -0.24341 }, - { 10, 0.18066, 0.26589, -0.25479 }, - { 20, 0.18133, 0.26846, -0.26876 }, - { 30, 0.18208, 0.27119, -0.28539 }, - { 40, 0.18293, 0.27407, -0.30470 }, - { 50, 0.18388, 0.27709, -0.32675 }, - { 60, 0.18494, 0.28021, -0.35156 }, - { 70, 0.18611, 0.28342, -0.37915 }, - { 80, 0.18740, 0.28668, -0.40955 }, - { 90, 0.18880, 0.28997, -0.44278 }, - { 100, 0.19032, 0.29326, -0.47888 }, - { 125, 0.19462, 0.30141, -0.58204 }, - { 150, 0.19962, 0.30921, -0.70471 }, - { 175, 0.20525, 0.31647, -0.84901 }, - { 200, 0.21142, 0.32312, -1.0182 }, - { 225, 0.21807, 0.32909, -1.2168 }, - { 250, 0.22511, 0.33439, -1.4512 }, - { 275, 0.23247, 0.33904, -1.7298 }, - { 300, 0.24010, 0.34308, -2.0637 }, - { 325, 0.24702, 0.34655, -2.4681 }, - { 350, 0.25591, 0.34951, -2.9641 }, - { 375, 0.26400, 0.35200, -3.5814 }, - { 400, 0.27218, 0.35407, -4.3633 }, - { 425, 0.28039, 0.35577, -5.3762 }, - { 450, 0.28863, 0.35714, -6.7262 }, - { 475, 0.29685, 0.35823, -8.5955 }, - { 500, 0.30505, 0.35907, -11.324 }, - { 525, 0.31320, 0.35968, -15.628 }, - { 550, 0.32129, 0.36011, -23.325 }, - { 575, 0.32931, 0.36038, -40.770 }, - { 600, 0.33724, 0.36051, -116.45 } - }; +static const ruvt kTempTable [] = { + { 0, 0.18006, 0.26352, -0.24341 }, + { 10, 0.18066, 0.26589, -0.25479 }, + { 20, 0.18133, 0.26846, -0.26876 }, + { 30, 0.18208, 0.27119, -0.28539 }, + { 40, 0.18293, 0.27407, -0.30470 }, + { 50, 0.18388, 0.27709, -0.32675 }, + { 60, 0.18494, 0.28021, -0.35156 }, + { 70, 0.18611, 0.28342, -0.37915 }, + { 80, 0.18740, 0.28668, -0.40955 }, + { 90, 0.18880, 0.28997, -0.44278 }, + { 100, 0.19032, 0.29326, -0.47888 }, + { 125, 0.19462, 0.30141, -0.58204 }, + { 150, 0.19962, 0.30921, -0.70471 }, + { 175, 0.20525, 0.31647, -0.84901 }, + { 200, 0.21142, 0.32312, -1.0182 }, + { 225, 0.21807, 0.32909, -1.2168 }, + { 250, 0.22511, 0.33439, -1.4512 }, + { 275, 0.23247, 0.33904, -1.7298 }, + { 300, 0.24010, 0.34308, -2.0637 }, + { 325, 0.24702, 0.34655, -2.4681 }, + { 350, 0.25591, 0.34951, -2.9641 }, + { 375, 0.26400, 0.35200, -3.5814 }, + { 400, 0.27218, 0.35407, -4.3633 }, + { 425, 0.28039, 0.35577, -5.3762 }, + { 450, 0.28863, 0.35714, -6.7262 }, + { 475, 0.29685, 0.35823, -8.5955 }, + { 500, 0.30505, 0.35907, -11.324 }, + { 525, 0.31320, 0.35968, -15.628 }, + { 550, 0.32129, 0.36011, -23.325 }, + { 575, 0.32931, 0.36038, -40.770 }, + { 600, 0.33724, 0.36051, -116.45 } +}; -void DCPProfile::dngref_XYCoord2Temperature(const double whiteXY[2], double *temp, double *tint) const { +void DCPProfile::dngref_XYCoord2Temperature(const double whiteXY[2], double *temp, double *tint) const +{ double fTemperature = 0; double fTint = 0; @@ -1183,16 +1290,16 @@ void DCPProfile::dngref_XYCoord2Temperature(const double whiteXY[2], double *tem // If below line, we have found line pair. if (dt <= 0.0 || index == 30) { // Find fractional weight of two lines. - if (dt > 0.0) + if (dt > 0.0) { dt = 0.0; + } + dt = -dt; double f; - if (index == 1) - { + + if (index == 1) { f = 0.0; - } - else - { + } else { f = dt / (last_dt + dt); } @@ -1216,29 +1323,41 @@ void DCPProfile::dngref_XYCoord2Temperature(const double whiteXY[2], double *tem fTint = (uu * du + vv * dv) * kTintScale; break; } + // Try next line pair. last_dt = dt; last_du = du; last_dv = dv; } - if (temp != NULL) + + if (temp != NULL) { *temp = fTemperature; - if (tint != NULL) + } + + if (tint != NULL) { *tint = fTint; + } } -void DCPProfile::dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIlluminant, double (*xyzToCamera)[3]) const { +void DCPProfile::dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIlluminant, double (*xyzToCamera)[3]) const +{ bool hasCol1 = hasColorMatrix1; bool hasCol2 = hasColorMatrix2; + if (preferredIlluminant == 1) { - if (hasCol1) hasCol2 = false; + if (hasCol1) { + hasCol2 = false; + } } else if (preferredIlluminant == 2) { - if (hasCol2) hasCol1 = false; + if (hasCol2) { + hasCol1 = false; + } } // mix if we have two matrices double mix; + if (hasCol1 && hasCol2) { double wbtemp; /* @@ -1246,6 +1365,7 @@ void DCPProfile::dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIl the reference code does. */ dngref_XYCoord2Temperature(whiteXY, &wbtemp, NULL); + if (wbtemp <= temperature1) { mix = 1.0; } else if (wbtemp >= temperature2) { @@ -1258,6 +1378,7 @@ void DCPProfile::dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIl // Interpolate the color matrix. double mCol[3][3]; + if (hasCol1 && hasCol2) { // interpolate if (mix >= 1.0) { @@ -1272,12 +1393,15 @@ void DCPProfile::dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIl } else { memcpy(mCol, mColorMatrix2, sizeof(mCol)); } + memcpy(xyzToCamera, mCol, sizeof(mCol)); } -void DCPProfile::dngref_NeutralToXY(double neutral[3], int preferredIlluminant, double XY[2]) const { +void DCPProfile::dngref_NeutralToXY(double neutral[3], int preferredIlluminant, double XY[2]) const +{ const int kMaxPasses = 30; double lastXY[2] = { 0.3457, 0.3585 }; // D50 + for (int pass = 0; pass < kMaxPasses; pass++) { double xyzToCamera[3][3]; dngref_FindXYZtoCamera(lastXY, preferredIlluminant, xyzToCamera); @@ -1288,12 +1412,12 @@ void DCPProfile::dngref_NeutralToXY(double neutral[3], int preferredIlluminant, XYZtoXY(nextXYZ, nextXY); if (fabs(nextXY[0] - lastXY[0]) + - fabs(nextXY[1] - lastXY[1]) < 0.0000001) - { + fabs(nextXY[1] - lastXY[1]) < 0.0000001) { XY[0] = nextXY[0]; XY[1] = nextXY[1]; return; } + // If we reach the limit without converging, we are most likely // in a two value oscillation. So take the average of the last // two estimates and give up. @@ -1301,14 +1425,17 @@ void DCPProfile::dngref_NeutralToXY(double neutral[3], int preferredIlluminant, nextXY[0] = (lastXY[0] + nextXY[0]) * 0.5; nextXY[1] = (lastXY[1] + nextXY[1]) * 0.5; } + lastXY[0] = nextXY[0]; lastXY[1] = nextXY[1]; } + XY[0] = lastXY[0]; XY[1] = lastXY[1]; } -void DCPProfile::Apply(Imagefloat *pImg, int preferredIlluminant, Glib::ustring workingSpace, ColorTemp &wb, double pre_mul[3], double camWbMatrix[3][3], bool useToneCurve, bool applyHueSatMap, bool applyLookTable) const { +void DCPProfile::Apply(Imagefloat *pImg, int preferredIlluminant, Glib::ustring workingSpace, ColorTemp &wb, double pre_mul[3], double camWbMatrix[3][3], bool useToneCurve, bool applyHueSatMap, bool applyLookTable) const +{ TMatrix mWork = iccStore->workingSpaceInverseMatrix (workingSpace); @@ -1316,93 +1443,130 @@ void DCPProfile::Apply(Imagefloat *pImg, int preferredIlluminant, Glib::ustring MakeXYZCAM(wb, pre_mul, camWbMatrix, preferredIlluminant, mXYZCAM); HSBModify *deleteTableHandle; const HSBModify *deltaBase = MakeHueSatMap(wb, preferredIlluminant, &deleteTableHandle); - if (!deltaBase) applyHueSatMap = false; - if (!aLookTable) applyLookTable = false; - useToneCurve&=toneCurve; + if (!deltaBase) { + applyHueSatMap = false; + } + + if (!aLookTable) { + applyLookTable = false; + } + + useToneCurve &= toneCurve; if (!applyHueSatMap && !applyLookTable && !useToneCurve) { //===== The fast path: no LUT and not tone curve- Calculate matrix for direct conversion raw>working space double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { mat[i][j] += mWork[i][k] * mXYZCAM[k][j]; + } // Apply the matrix part -#pragma omp parallel for - for (int y=0; yheight; y++) { - float newr, newg, newb; - for (int x=0; xwidth; x++) { - newr = mat[0][0]*pImg->r(y,x) + mat[0][1]*pImg->g(y,x) + mat[0][2]*pImg->b(y,x); - newg = mat[1][0]*pImg->r(y,x) + mat[1][1]*pImg->g(y,x) + mat[1][2]*pImg->b(y,x); - newb = mat[2][0]*pImg->r(y,x) + mat[2][1]*pImg->g(y,x) + mat[2][2]*pImg->b(y,x); + #pragma omp parallel for - pImg->r(y,x) = newr; pImg->g(y,x) = newg; pImg->b(y,x) = newb; + for (int y = 0; y < pImg->height; y++) { + float newr, newg, newb; + + for (int x = 0; x < pImg->width; x++) { + newr = mat[0][0] * pImg->r(y, x) + mat[0][1] * pImg->g(y, x) + mat[0][2] * pImg->b(y, x); + newg = mat[1][0] * pImg->r(y, x) + mat[1][1] * pImg->g(y, x) + mat[1][2] * pImg->b(y, x); + newb = mat[2][0] * pImg->r(y, x) + mat[2][1] * pImg->g(y, x) + mat[2][2] * pImg->b(y, x); + + pImg->r(y, x) = newr; + pImg->g(y, x) = newg; + pImg->b(y, x) = newb; } } - } - else { + } else { //===== LUT available- Calculate matrix for conversion raw>ProPhoto double m2ProPhoto[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { m2ProPhoto[i][j] += prophoto_xyz[i][k] * mXYZCAM[k][j]; + } double m2Work[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { m2Work[i][j] += mWork[i][k] * xyz_prophoto[k][j]; + } // Convert to prophoto and apply LUT -#pragma omp parallel for - for (int y=0; yheight; y++) { - float newr, newg, newb, h,s,v,hs,ss,vs; - for (int x=0; xwidth; x++) { - newr = m2ProPhoto[0][0]*pImg->r(y,x) + m2ProPhoto[0][1]*pImg->g(y,x) + m2ProPhoto[0][2]*pImg->b(y,x); - newg = m2ProPhoto[1][0]*pImg->r(y,x) + m2ProPhoto[1][1]*pImg->g(y,x) + m2ProPhoto[1][2]*pImg->b(y,x); - newb = m2ProPhoto[2][0]*pImg->r(y,x) + m2ProPhoto[2][1]*pImg->g(y,x) + m2ProPhoto[2][2]*pImg->b(y,x); + #pragma omp parallel for + + for (int y = 0; y < pImg->height; y++) { + float newr, newg, newb, h, s, v, hs, ss, vs; + + for (int x = 0; x < pImg->width; x++) { + newr = m2ProPhoto[0][0] * pImg->r(y, x) + m2ProPhoto[0][1] * pImg->g(y, x) + m2ProPhoto[0][2] * pImg->b(y, x); + newg = m2ProPhoto[1][0] * pImg->r(y, x) + m2ProPhoto[1][1] * pImg->g(y, x) + m2ProPhoto[1][2] * pImg->b(y, x); + newb = m2ProPhoto[2][0] * pImg->r(y, x) + m2ProPhoto[2][1] * pImg->g(y, x) + m2ProPhoto[2][2] * pImg->b(y, x); // if point is in negative area, just the matrix, but not the LUT - if ((applyHueSatMap || applyLookTable) && newr>=0 && newg>=0 && newb>=0) { + if ((applyHueSatMap || applyLookTable) && newr >= 0 && newg >= 0 && newb >= 0) { Color::rgb2hsv(newr, newg, newb, h , s, v); - h*=6.f; // RT calculates in [0,1] + h *= 6.f; // RT calculates in [0,1] if (applyHueSatMap) { HSDApply(DeltaInfo, deltaBase, h, s, v); } + if (applyLookTable) { HSDApply(LookInfo, aLookTable, h, s, v); } // RT range correction - if (h < 0.0f) h += 6.0f; - if (h >= 6.0f) h -= 6.0f; - h/=6.f; + if (h < 0.0f) { + h += 6.0f; + } + + if (h >= 6.0f) { + h -= 6.0f; + } + + h /= 6.f; Color::hsv2rgb( h, s, v, newr, newg, newb); } - // tone curve - if (useToneCurve) toneCurve.Apply(newr, newg, newb); - pImg->r(y,x) = m2Work[0][0]*newr + m2Work[0][1]*newg + m2Work[0][2]*newb; - pImg->g(y,x) = m2Work[1][0]*newr + m2Work[1][1]*newg + m2Work[1][2]*newb; - pImg->b(y,x) = m2Work[2][0]*newr + m2Work[2][1]*newg + m2Work[2][2]*newb; + // tone curve + if (useToneCurve) { + toneCurve.Apply(newr, newg, newb); + } + + pImg->r(y, x) = m2Work[0][0] * newr + m2Work[0][1] * newg + m2Work[0][2] * newb; + pImg->g(y, x) = m2Work[1][0] * newr + m2Work[1][1] * newg + m2Work[1][2] * newb; + pImg->b(y, x) = m2Work[2][0] * newr + m2Work[2][1] * newg + m2Work[2][2] * newb; } } } - if (deleteTableHandle) delete[] deleteTableHandle; + if (deleteTableHandle) { + delete[] deleteTableHandle; + } } -void DCPProfile::setStep2ApplyState(Glib::ustring workingSpace, bool useToneCurve, bool applyLookTable, bool applyBaselineExposure) { +void DCPProfile::setStep2ApplyState(Glib::ustring workingSpace, bool useToneCurve, bool applyLookTable, bool applyBaselineExposure) +{ applyState.useToneCurve = useToneCurve; applyState.applyLookTable = applyLookTable; applyState.blScale = 1.0; - if (!aLookTable) applyState.applyLookTable = false; - if (!hasToneCurve) applyState.useToneCurve = false; + + if (!aLookTable) { + applyState.applyLookTable = false; + } + + if (!hasToneCurve) { + applyState.useToneCurve = false; + } + if (hasBaselineExposureOffset && applyBaselineExposure) { applyState.blScale = powf(2, baselineExposureOffset); } @@ -1415,58 +1579,68 @@ void DCPProfile::setStep2ApplyState(Glib::ustring workingSpace, bool useToneCurv mWork = iccStore->workingSpaceMatrix (workingSpace); memset(applyState.m2ProPhoto, 0, sizeof(applyState.m2ProPhoto)); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { applyState.m2ProPhoto[i][j] += prophoto_xyz[i][k] * mWork[k][j]; + } mWork = iccStore->workingSpaceInverseMatrix (workingSpace); memset(applyState.m2Work, 0, sizeof(applyState.m2Work)); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { applyState.m2Work[i][j] += mWork[i][k] * xyz_prophoto[k][j]; + } } } -void DCPProfile::step2ApplyTile(float *rc, float *gc, float *bc, int width, int height, int tileWidth) const { +void DCPProfile::step2ApplyTile(float *rc, float *gc, float *bc, int width, int height, int tileWidth) const +{ #define FCLIP(a) ((a)>0.0?((a)<65535.5?(a):65535.5):0.0) #define CLIP01(a) ((a)>0?((a)<1?(a):1):0) float exp_scale = 1.0; exp_scale *= applyState.blScale; + if (!applyState.useToneCurve && !applyState.applyLookTable) { if (exp_scale == 1.0) { return; } - for (int y=0; y= 6.0f) h -= 6.0f; - h/=6.f; + if (h < 0.0f) { + h += 6.0f; + } + + if (h >= 6.0f) { + h -= 6.0f; + } + + h /= 6.f; Color::hsv2rgb( h, s, v, newr, newg, newb); } + if (applyState.useToneCurve) { toneCurve.Apply(newr, newg, newb); } if (applyState.alreadyProPhoto) { - rc[y*tileWidth+x] = newr; - gc[y*tileWidth+x] = newg; - bc[y*tileWidth+x] = newb; + rc[y * tileWidth + x] = newr; + gc[y * tileWidth + x] = newg; + bc[y * tileWidth + x] = newb; } else { - rc[y*tileWidth+x] = applyState.m2Work[0][0]*newr + applyState.m2Work[0][1]*newg + applyState.m2Work[0][2]*newb; - gc[y*tileWidth+x] = applyState.m2Work[1][0]*newr + applyState.m2Work[1][1]*newg + applyState.m2Work[1][2]*newb; - bc[y*tileWidth+x] = applyState.m2Work[2][0]*newr + applyState.m2Work[2][1]*newg + applyState.m2Work[2][2]*newb; + rc[y * tileWidth + x] = applyState.m2Work[0][0] * newr + applyState.m2Work[0][1] * newg + applyState.m2Work[0][2] * newb; + gc[y * tileWidth + x] = applyState.m2Work[1][0] * newr + applyState.m2Work[1][1] * newg + applyState.m2Work[1][2] * newb; + bc[y * tileWidth + x] = applyState.m2Work[2][0] * newr + applyState.m2Work[2][1] * newg + applyState.m2Work[2][2] * newb; } } } @@ -1511,27 +1692,29 @@ void DCPProfile::step2ApplyTile(float *rc, float *gc, float *bc, int width, int DCPStore* DCPStore::getInstance() { static DCPStore* instance_ = 0; - if ( instance_ == 0 ) - { + + if ( instance_ == 0 ) { static MyMutex smutex_; MyMutex::MyLock lock(smutex_); - if ( instance_ == 0 ) - { + + if ( instance_ == 0 ) { instance_ = new DCPStore(); } } + return instance_; } // Reads all profiles from the given profiles dir -void DCPStore::init (Glib::ustring rtProfileDir) { +void DCPStore::init (Glib::ustring rtProfileDir) +{ MyMutex::MyLock lock(mtx); fileStdProfiles.clear(); - Glib::ustring rootDirName=rtProfileDir; + Glib::ustring rootDirName = rtProfileDir; - if (rootDirName!="") { + if (rootDirName != "") { std::deque qDirs; qDirs.push_front(rootDirName); @@ -1542,55 +1725,76 @@ void DCPStore::init (Glib::ustring rtProfileDir) { qDirs.pop_back(); Glib::Dir* dir = NULL; + try { - if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) return; + if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) { + return; + } + dir = new Glib::Dir (dirname); - } - catch (Glib::Exception& fe) { + } catch (Glib::Exception& fe) { return; } + dirname = dirname + "/"; - for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) { + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { Glib::ustring fname = dirname + *i; Glib::ustring sname = *i; + // ignore directories if (!safe_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"))) { - Glib::ustring camShortName = sname.substr(0,lastdot).uppercase(); - fileStdProfiles[camShortName]=fname; // they will be loaded and cached on demand + + if (lastdot != Glib::ustring::npos && lastdot <= sname.size() - 4 && (!sname.casefold().compare (lastdot, 4, ".dcp"))) { + Glib::ustring camShortName = sname.substr(0, lastdot).uppercase(); + fileStdProfiles[camShortName] = fname; // they will be loaded and cached on demand } - } else qDirs.push_front(fname); // for later scanning + } else { + qDirs.push_front(fname); // for later scanning + } } + delete dir; } } } -DCPProfile* DCPStore::getProfile (Glib::ustring filename, bool isRTProfile) { +DCPProfile* DCPStore::getProfile (Glib::ustring filename, bool isRTProfile) +{ MyMutex::MyLock lock(mtx); std::map::iterator r = profileCache.find (filename); - if (r!=profileCache.end()) return r->second; + + if (r != profileCache.end()) { + return r->second; + } // Add profile - profileCache[filename]=new DCPProfile(filename, isRTProfile); + profileCache[filename] = new DCPProfile(filename, isRTProfile); return profileCache[filename]; } -DCPProfile* DCPStore::getStdProfile(Glib::ustring camShortName) { - Glib::ustring name2=camShortName.uppercase(); +DCPProfile* DCPStore::getStdProfile(Glib::ustring camShortName) +{ + Glib::ustring name2 = camShortName.uppercase(); // Warning: do NOT use map.find(), since it does not seem to work reliably here - for (std::map::iterator i=fileStdProfiles.begin();i!=fileStdProfiles.end();i++) - if (name2==(*i).first) return getProfile((*i).second, true); + for (std::map::iterator i = fileStdProfiles.begin(); i != fileStdProfiles.end(); i++) + if (name2 == (*i).first) { + return getProfile((*i).second, true); + } return NULL; } -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)) return false; - size_t pos=filename.find_last_of ('.'); - return pos>0 && (!filename.casefold().compare (pos, 4, ".dcp") || !filename.casefold().compare (pos, 4, ".dng")); +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)) { + return false; + } + + size_t pos = filename.find_last_of ('.'); + return pos > 0 && (!filename.casefold().compare (pos, 4, ".dcp") || !filename.casefold().compare (pos, 4, ".dng")); } diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 5e0fe2f0c..0d3bcc029 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -7,7 +7,7 @@ * 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 @@ -28,88 +28,106 @@ #include #include -namespace rtengine { +namespace rtengine +{ - class DCPProfile { - struct HSBModify - { - float fHueShift; - float fSatScale; - float fValScale; - }; - struct HSDTableInfo - { - int iHueDivisions, iSatDivisions, iValDivisions; - int iHueStep, iValStep, iArrayCount; - bool sRGBGamma; - struct - { - float hScale, sScale, vScale; - int maxHueIndex0, maxSatIndex0, maxValIndex0; - int hueStep, valStep; - } pc; - }; - - double mColorMatrix1[3][3],mColorMatrix2[3][3]; - bool hasColorMatrix1, hasColorMatrix2, hasForwardMatrix1, hasForwardMatrix2, hasToneCurve, hasBaselineExposureOffset, willInterpolate; - double mForwardMatrix1[3][3],mForwardMatrix2[3][3]; - double temperature1, temperature2; - double baselineExposureOffset; - HSBModify *aDeltas1,*aDeltas2,*aLookTable; - HSDTableInfo DeltaInfo,LookInfo; - short iLightSource1,iLightSource2; - - AdobeToneCurve toneCurve; +class DCPProfile +{ + struct HSBModify { + float fHueShift; + float fSatScale; + float fValScale; + }; + struct HSDTableInfo { + int iHueDivisions, iSatDivisions, iValDivisions; + int iHueStep, iValStep, iArrayCount; + bool sRGBGamma; struct { - double m2ProPhoto[3][3]; - double m2Work[3][3]; - bool alreadyProPhoto; - bool useToneCurve; - bool applyLookTable; - float blScale; - } applyState; - - void dngref_XYCoord2Temperature(const double whiteXY[2], double *temp, double *tint) const; - void dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIlluminant, double (*xyzToCamera)[3]) const; - void dngref_NeutralToXY(double neutral[3], int preferredIlluminant, double XY[2]) const; - void MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix[3][3], int preferredIlluminant, double (*mXYZCAM)[3]) const; - const HSBModify* MakeHueSatMap(ColorTemp &wb, int preferredIlluminant, HSBModify **deleteHandle) const; - void HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, float &h, float &s, float &v) const; - - public: - DCPProfile(Glib::ustring fname, bool isRTProfile); - ~DCPProfile(); - - bool getHasToneCurve() { return hasToneCurve; } - bool getHasLookTable() { return !!aLookTable; } - bool getHasHueSatMap() { return !!aDeltas1; } - bool getHasBaselineExposureOffset() { return hasBaselineExposureOffset; } - void getIlluminants(int &i1, double &temp1, int &i2, double &temp2, bool &willInterpolate_) { i1 = iLightSource1; i2 = iLightSource2; temp1 = temperature1, temp2 = temperature2; willInterpolate_ = willInterpolate; }; - void Apply(Imagefloat *pImg, int preferredIlluminant, Glib::ustring workingSpace, ColorTemp &wb, double pre_mul[3], double camMatrix[3][3], bool useToneCurve=false, bool applyHueSatMap=true, bool applyLookTable=false) const; - void setStep2ApplyState(Glib::ustring workingSpace, bool useToneCurve, bool applyLookTable, bool applyBaselineExposure); - void step2ApplyTile(float *r, float *g, float *b, int width, int height, int tileWidth) const; + float hScale, sScale, vScale; + int maxHueIndex0, maxSatIndex0, maxValIndex0; + int hueStep, valStep; + } pc; }; - class DCPStore { - MyMutex mtx; + double mColorMatrix1[3][3], mColorMatrix2[3][3]; + bool hasColorMatrix1, hasColorMatrix2, hasForwardMatrix1, hasForwardMatrix2, hasToneCurve, hasBaselineExposureOffset, willInterpolate; + double mForwardMatrix1[3][3], mForwardMatrix2[3][3]; + double temperature1, temperature2; + double baselineExposureOffset; + HSBModify *aDeltas1, *aDeltas2, *aLookTable; + HSDTableInfo DeltaInfo, LookInfo; + short iLightSource1, iLightSource2; - // these contain standard profiles from RT. keys are all in uppercase, file path is value - std::map fileStdProfiles; - - // Maps file name to profile as cache - std::map profileCache; + AdobeToneCurve toneCurve; + struct { + double m2ProPhoto[3][3]; + double m2Work[3][3]; + bool alreadyProPhoto; + bool useToneCurve; + bool applyLookTable; + float blScale; + } applyState; - public: - void init(Glib::ustring rtProfileDir); + void dngref_XYCoord2Temperature(const double whiteXY[2], double *temp, double *tint) const; + void dngref_FindXYZtoCamera(const double whiteXY[2], int preferredIlluminant, double (*xyzToCamera)[3]) const; + void dngref_NeutralToXY(double neutral[3], int preferredIlluminant, double XY[2]) const; + void MakeXYZCAM(ColorTemp &wb, double pre_mul[3], double camWbMatrix[3][3], int preferredIlluminant, double (*mXYZCAM)[3]) const; + const HSBModify* MakeHueSatMap(ColorTemp &wb, int preferredIlluminant, HSBModify **deleteHandle) const; + void HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, float &h, float &s, float &v) const; - bool isValidDCPFileName(Glib::ustring filename) const; +public: + DCPProfile(Glib::ustring fname, bool isRTProfile); + ~DCPProfile(); - DCPProfile* getProfile(Glib::ustring filename, bool isRTProfile=false); - DCPProfile* getStdProfile(Glib::ustring camShortName); - - static DCPStore* getInstance(); + bool getHasToneCurve() + { + return hasToneCurve; + } + bool getHasLookTable() + { + return !!aLookTable; + } + bool getHasHueSatMap() + { + return !!aDeltas1; + } + bool getHasBaselineExposureOffset() + { + return hasBaselineExposureOffset; + } + void getIlluminants(int &i1, double &temp1, int &i2, double &temp2, bool &willInterpolate_) + { + i1 = iLightSource1; + i2 = iLightSource2; + temp1 = temperature1, temp2 = temperature2; + willInterpolate_ = willInterpolate; }; + void Apply(Imagefloat *pImg, int preferredIlluminant, Glib::ustring workingSpace, ColorTemp &wb, double pre_mul[3], double camMatrix[3][3], bool useToneCurve = false, bool applyHueSatMap = true, bool applyLookTable = false) const; + void setStep2ApplyState(Glib::ustring workingSpace, bool useToneCurve, bool applyLookTable, bool applyBaselineExposure); + void step2ApplyTile(float *r, float *g, float *b, int width, int height, int tileWidth) const; +}; - #define dcpStore DCPStore::getInstance() +class DCPStore +{ + MyMutex mtx; + + // these contain standard profiles from RT. keys are all in uppercase, file path is value + std::map fileStdProfiles; + + // Maps file name to profile as cache + std::map profileCache; + +public: + void init(Glib::ustring rtProfileDir); + + bool isValidDCPFileName(Glib::ustring filename) const; + + DCPProfile* getProfile(Glib::ustring filename, bool isRTProfile = false); + DCPProfile* getStdProfile(Glib::ustring camShortName); + + static DCPStore* getInstance(); +}; + +#define dcpStore DCPStore::getInstance() } #endif diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 1d2cb7d45..138a03594 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -8,7 +8,7 @@ * 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 @@ -25,7 +25,8 @@ // "ceil" rounding #define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0)) -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; @@ -43,33 +44,39 @@ Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool parent->crops.push_back (this); } -Crop::~Crop () { +Crop::~Crop () +{ MyMutex::MyLock cropLock(cropMutex); std::vector::iterator i = std::find (parent->crops.begin(), parent->crops.end(), this); - if (i!=parent->crops.end ()) + + if (i != parent->crops.end ()) { parent->crops.erase (i); + } MyMutex::MyLock processingLock(parent->mProcessing); freeAll (); } -void Crop::destroy () { +void Crop::destroy () +{ MyMutex::MyLock lock(cropMutex); MyMutex::MyLock processingLock(parent->mProcessing); freeAll(); } -void Crop::setListener (DetailedCropListener* il) { +void Crop::setListener (DetailedCropListener* il) +{ // We can make reads in the IF, because the mProcessing lock is only needed for change - if (cropImageListener!=il) { + if (cropImageListener != il) { MyMutex::MyLock lock(cropMutex); cropImageListener = il; } } -EditUniqueID Crop::getCurrEditID() { +EditUniqueID Crop::getCurrEditID() +{ EditSubscriber *subscriber = EditBuffer::dataProvider ? EditBuffer::dataProvider->getCurrSubscriber() : NULL; return subscriber ? subscriber->getEditID() : EUID_None; } @@ -78,39 +85,45 @@ EditUniqueID Crop::getCurrEditID() { * Delete the edit image buffer if there's no subscriber anymore. * If allocation has to be done, it is deferred to Crop::update */ -void Crop::setEditSubscriber(EditSubscriber* newSubscriber) { +void Crop::setEditSubscriber(EditSubscriber* newSubscriber) +{ MyMutex::MyLock lock(cropMutex); // At this point, editCrop.dataProvider->currSubscriber is the old subscriber EditSubscriber *oldSubscriber = EditBuffer::dataProvider ? EditBuffer::dataProvider->getCurrSubscriber() : NULL; + if (newSubscriber == NULL || (oldSubscriber != NULL && oldSubscriber->getEditBufferType() != newSubscriber->getEditBufferType())) { - if (EditBuffer::imgFloatBuffer!=NULL) { + if (EditBuffer::imgFloatBuffer != NULL) { delete EditBuffer::imgFloatBuffer; EditBuffer::imgFloatBuffer = NULL; } - if (EditBuffer::LabBuffer!=NULL) { + + if (EditBuffer::LabBuffer != NULL) { delete EditBuffer::LabBuffer; EditBuffer::LabBuffer = NULL; } - if (EditBuffer::singlePlaneBuffer.getW()!=-1) { + + if (EditBuffer::singlePlaneBuffer.getW() != -1) { EditBuffer::singlePlaneBuffer.flushData(); } } + if (newSubscriber == NULL && oldSubscriber != NULL && oldSubscriber->getEditingType() == ET_OBJECTS) { - printf("Free object buffers\n"); + printf("Free object buffers\n"); EditBuffer::resize(0, 0); // This will delete the objects buffer - } - else if (newSubscriber && newSubscriber->getEditingType() == ET_OBJECTS) { + } else if (newSubscriber && newSubscriber->getEditingType() == ET_OBJECTS) { EditBuffer::resize(cropw, croph, newSubscriber); } + // If oldSubscriber == NULL && newSubscriber != NULL -> the image will be allocated when necessary } -void Crop::update (int todo) { +void Crop::update (int todo) +{ MyMutex::MyLock cropLock(cropMutex); ProcParams& params = parent->params; - // CropGUIListener* cropgl; +// CropGUIListener* cropgl; // No need to update todo here, since it has already been changed in ImprocCoordinator::updatePreviewImage, // and Crop::update ask to do ALL anyway @@ -118,454 +131,605 @@ void Crop::update (int todo) { // give possibility to the listener to modify crop window (as the full image dimensions are already known at this point) int wx, wy, ww, wh, ws; bool overrideWindow = false; - if (cropImageListener) + + if (cropImageListener) { overrideWindow = cropImageListener->getWindow (wx, wy, ww, wh, ws); + } + // re-allocate sub-images and arrays if their dimensions changed bool needsinitupdate = false; - if (!overrideWindow) + + if (!overrideWindow) { needsinitupdate = setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true); - else - needsinitupdate = setCropSizes (wx, wy, ww, wh, ws, true); // this set skip=ws + } else { + needsinitupdate = setCropSizes (wx, wy, ww, wh, ws, true); // this set skip=ws + } + // it something has been reallocated, all processing steps have to be performed - if (needsinitupdate || (todo & M_HIGHQUAL)) + if (needsinitupdate || (todo & M_HIGHQUAL)) { todo = ALL; + } // Tells to the ImProcFunctions' tool what is the preview scale, which may lead to some simplifications parent->ipf.setScale (skip); - + Imagefloat* baseCrop = origCrop; - int widIm = parent->fw;//full image - int heiIm = parent->fh; + int widIm = parent->fw;//full image + int heiIm = parent->fh; bool needstransform = parent->ipf.needsTransform(); - if (todo & (M_INIT|M_LINDENOISE)) { + if (todo & (M_INIT | M_LINDENOISE)) { MyMutex::MyLock lock(parent->minit); // Also used in improccoord int tr = getCoarseBitMask(params.coarse); - if (!needsinitupdate) + + if (!needsinitupdate) { setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true); - - // printf("x=%d y=%d crow=%d croh=%d skip=%d\n",rqcropx, rqcropy, rqcropw, rqcroph, skip); - // printf("trafx=%d trafyy=%d trafwsk=%d trafHs=%d \n",trafx, trafy, trafw*skip, trafh*skip); - - Imagefloat *calclum = NULL;//for Luminance denoise curve - NoiseCurve noiseLCurve; - NoiseCurve noiseCCurve; - float autoNR = (float) settings->nrauto;// - float autoNRmax = (float) settings->nrautomax;// - - params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve); + } - int tilesize; - int overlap; - if(settings->leveldnti ==0) { - tilesize = 1024; - overlap = 128; - } - if(settings->leveldnti ==1) { - tilesize = 768; - overlap = 96; - } - - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - int kall=2; - - parent->ipf.Tile_calc (tilesize, overlap, kall, widIm, heiIm, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - kall=0; - - float *ch_M = new float [9];//allocate memory - float *max_r = new float [9]; - float *max_b = new float [9]; - float *min_b = new float [9]; - float *min_r = new float [9]; - float *lumL = new float [9]; - float *chromC = new float [9]; - float *ry = new float [9]; - float *sk = new float [9]; - float *pcsk = new float [9]; - int *centerTile_X = new int [numtiles_W]; - int *centerTile_Y = new int [numtiles_H]; - for(int cX=0;cXleveldnautsimpl==1){ - if(params.dirpyrDenoise.Cmethod=="MAN" || params.dirpyrDenoise.Cmethod=="PON" ) { - PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); - parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); - } - } else { - if(params.dirpyrDenoise.C2method=="MANU") { - PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); - parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); - } - } + // printf("x=%d y=%d crow=%d croh=%d skip=%d\n",rqcropx, rqcropy, rqcropw, rqcroph, skip); + // printf("trafx=%d trafyy=%d trafwsk=%d trafHs=%d \n",trafx, trafy, trafw*skip, trafh*skip); - if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="PRE") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="PREV")) { - PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); - parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); - if((!isDetailWindow) && parent->adnListener && skip==1 && params.dirpyrDenoise.enabled) { - float lowdenoise=1.f; - int levaut=settings->leveldnaut; - if(levaut==1) //Standard - lowdenoise=0.7f; - int CenterPreview_X=trafx+(trafw*skip)/2; - int CenterPreview_Y=trafy+(trafh*skip)/2; - int minimuX=20000; - int minimuY=20000; - int poscenterX=0; - int poscenterY=0; - for(int cc=0;ccleveldnv ==0) {crW=100;} - if(settings->leveldnv ==1) {crW=250;} - // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview - if(settings->leveldnv ==2) {crW=int(tileWskip/2);} - if(settings->leveldnv ==3) {crW=tileWskip-10;} + Imagefloat *calclum = NULL;//for Luminance denoise curve + NoiseCurve noiseLCurve; + NoiseCurve noiseCCurve; + float autoNR = (float) settings->nrauto;// + float autoNRmax = (float) settings->nrautomax;// - float adjustr=1.f; - if (params.icm.working=="ProPhoto") {adjustr =1.f;} - else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} - else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} - if(parent->adnListener) - parent->adnListener->noiseTilePrev (centerTile_X[poscenterX], centerTile_Y[poscenterY],CenterPreview_X,CenterPreview_Y,crW, trafw*skip); - // I have tried "blind" some solutions..to move review ...but GUI is not my truc ! - // int W,H; - // cropgl->cropMoved (centerTile_X[poscenterX],centerTile_Y[poscenterY] , W, H); - // cropImageListener->setPosition (int x, int y, bool update=true); - // bool update; - // cropImageListener->setPosition (centerTile_X[poscenterX],centerTile_Y[poscenterY] , true); - //setCropSizes (centerTile_X[poscenterX], centerTile_Y[poscenterY], trafw*skip,trafh*skip , skip, true); + params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve); - // we only need image reduced to 1/4 here - int W = origCrop->getWidth(); - int H = origCrop->getHeight(); - Imagefloat *provicalc = new Imagefloat ((W+1)/2, (H+1)/2);//for denoise curves - for(int ii=0;iir(ii>>1,jj>>1) = origCrop->r(ii,jj); - provicalc->g(ii>>1,jj>>1) = origCrop->g(ii,jj); - provicalc->b(ii>>1,jj>>1) = origCrop->b(ii,jj); - } - } - parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve + int tilesize; + int overlap; - float maxr=0.f; - float maxb=0.f; - float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; - int Nb; - - chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;minredaut=0.f; minblueaut=0.f; - LUTf gamcurve(65536,0); - float gam, gamthresh, gamslope; - parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); - parent->ipf.RGB_denoise_info(origCrop, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut,nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, true); -// printf("redy=%f skin=%f pcskin=%f\n",redyel, skinc,nsknc); -// printf("DCROP skip=%d cha=%4.0f Nb=%d red=%4.0f bl=%4.0f redM=%4.0f bluM=%4.0f L=%4.0f sigL=%4.0f Ch=%4.0f Si=%4.0f\n",skip, chaut,Nb, redaut,blueaut, maxredaut, maxblueaut, lumema, sigma_L, chromina, sigma); - float multip=1.f; - if(!parent->imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good for gamma=1 - - float maxmax=max(maxredaut,maxblueaut); - float delta; - int mode=0; - // float redyel, skinc, nsknc; - int lissage=settings->leveldnliss; - parent->ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc); - - - if(maxredaut > maxblueaut) { - // maxr=(maxredaut-chaut)/((autoNRmax*multip*adjustr)/2.f); - maxr=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - if(minblueaut <= minredaut && minblueaut < chaut) maxb=(-chaut+minblueaut)/(autoNRmax*multip*adjustr*lowdenoise); - } - else { - // maxb=(maxblueaut-chaut)/((autoNRmax*multip*adjustr)/2.f); - maxb=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - if(minredaut <= minblueaut && minredaut < chaut) maxr=(-chaut+minredaut)/(autoNRmax*multip*adjustr*lowdenoise); - }//maxb mxr - empirical evaluation red / blue - - - params.dirpyrDenoise.chroma=chaut/(autoNR*multip*adjustr*lowdenoise); - params.dirpyrDenoise.redchro=maxr; - params.dirpyrDenoise.bluechro=maxb; - parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); - - delete provicalc; - } - } + if(settings->leveldnti == 0) { + tilesize = 1024; + overlap = 128; + } - if(skip==1 && params.dirpyrDenoise.enabled && ((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO"))) { - MyTime t1aue,t2aue; - t1aue.set(); - - int crW,crH; - if(settings->leveldnv ==0) {crW=100;crH=100;} - if(settings->leveldnv ==1) {crW=250;crH=250;} - // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview - if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} - if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} - float lowdenoise=1.f; - int levaut=settings->leveldnaut; - if(levaut==1) //Standard - lowdenoise=0.7f; + if(settings->leveldnti == 1) { + tilesize = 768; + overlap = 96; + } - LUTf gamcurve(65536,0); - float gam, gamthresh, gamslope; - parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); - int Nb[9]; + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + int kall = 2; + + parent->ipf.Tile_calc (tilesize, overlap, kall, widIm, heiIm, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + kall = 0; + + float *ch_M = new float [9];//allocate memory + float *max_r = new float [9]; + float *max_b = new float [9]; + float *min_b = new float [9]; + float *min_r = new float [9]; + float *lumL = new float [9]; + float *chromC = new float [9]; + float *ry = new float [9]; + float *sk = new float [9]; + float *pcsk = new float [9]; + int *centerTile_X = new int [numtiles_W]; + int *centerTile_Y = new int [numtiles_H]; + + for(int cX = 0; cX < numtiles_W; cX++) { + centerTile_X[cX] = tileWskip / 2 + tileWskip * cX; + } + + for(int cY = 0; cY < numtiles_H; cY++) { + centerTile_Y[cY] = tileHskip / 2 + tileHskip * cY; + } + + if(settings->leveldnautsimpl == 1) { + if(params.dirpyrDenoise.Cmethod == "MAN" || params.dirpyrDenoise.Cmethod == "PON" ) { + PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + } + } else { + if(params.dirpyrDenoise.C2method == "MANU") { + PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + } + } + + if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PRE") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "PREV")) { + PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + + if((!isDetailWindow) && parent->adnListener && skip == 1 && params.dirpyrDenoise.enabled) { + float lowdenoise = 1.f; + int levaut = settings->leveldnaut; + + if(levaut == 1) { //Standard + lowdenoise = 0.7f; + } + + int CenterPreview_X = trafx + (trafw * skip) / 2; + int CenterPreview_Y = trafy + (trafh * skip) / 2; + int minimuX = 20000; + int minimuY = 20000; + int poscenterX = 0; + int poscenterY = 0; + + for(int cc = 0; cc < numtiles_W; cc++) { + if(abs(centerTile_X[cc] - CenterPreview_X) < minimuX) { + minimuX = abs(centerTile_X[cc] - CenterPreview_X); + poscenterX = cc; + } + } + + for(int cc = 0; cc < numtiles_H; cc++) { + if(abs(centerTile_Y[cc] - CenterPreview_Y) < minimuY) { + minimuY = abs(centerTile_Y[cc] - CenterPreview_Y); + poscenterY = cc; + } + } + + // printf("TileCX=%d TileCY=%d prevX=%d prevY=%d \n",centerTile_X[poscenterX],centerTile_Y[poscenterY],CenterPreview_X,CenterPreview_Y); + int crW; + + if(settings->leveldnv == 0) { + crW = 100; + } + + if(settings->leveldnv == 1) { + crW = 250; + } + + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv == 2) { + crW = int(tileWskip / 2); + } + + if(settings->leveldnv == 3) { + crW = tileWskip - 10; + } + + float adjustr = 1.f; + + if (params.icm.working == "ProPhoto") { + adjustr = 1.f; + } else if (params.icm.working == "Adobe RGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "sRGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "WideGamut") { + adjustr = 1.f / 1.1f; + } else if (params.icm.working == "Beta RGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BestRGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BruceRGB") { + adjustr = 1.f / 1.2f; + } + + if(parent->adnListener) { + parent->adnListener->noiseTilePrev (centerTile_X[poscenterX], centerTile_Y[poscenterY], CenterPreview_X, CenterPreview_Y, crW, trafw * skip); + } + + // I have tried "blind" some solutions..to move review ...but GUI is not my truc ! + // int W,H; + // cropgl->cropMoved (centerTile_X[poscenterX],centerTile_Y[poscenterY] , W, H); + // cropImageListener->setPosition (int x, int y, bool update=true); + // bool update; + // cropImageListener->setPosition (centerTile_X[poscenterX],centerTile_Y[poscenterY] , true); + //setCropSizes (centerTile_X[poscenterX], centerTile_Y[poscenterY], trafw*skip,trafh*skip , skip, true); + + // we only need image reduced to 1/4 here + int W = origCrop->getWidth(); + int H = origCrop->getHeight(); + Imagefloat *provicalc = new Imagefloat ((W + 1) / 2, (H + 1) / 2); //for denoise curves + + for(int ii = 0; ii < H; ii += 2) { + for(int jj = 0; jj < W; jj += 2) { + provicalc->r(ii >> 1, jj >> 1) = origCrop->r(ii, jj); + provicalc->g(ii >> 1, jj >> 1) = origCrop->g(ii, jj); + provicalc->b(ii >> 1, jj >> 1) = origCrop->b(ii, jj); + } + } + + parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve + + float maxr = 0.f; + float maxb = 0.f; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + int Nb; + + chaut = 0.f; + redaut = 0.f; + blueaut = 0.f; + maxredaut = 0.f; + maxblueaut = 0.f; + minredaut = 0.f; + minblueaut = 0.f; + LUTf gamcurve(65536, 0); + float gam, gamthresh, gamslope; + parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + parent->ipf.RGB_denoise_info(origCrop, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, true); +// printf("redy=%f skin=%f pcskin=%f\n",redyel, skinc,nsknc); +// printf("DCROP skip=%d cha=%4.0f Nb=%d red=%4.0f bl=%4.0f redM=%4.0f bluM=%4.0f L=%4.0f sigL=%4.0f Ch=%4.0f Si=%4.0f\n",skip, chaut,Nb, redaut,blueaut, maxredaut, maxblueaut, lumema, sigma_L, chromina, sigma); + float multip = 1.f; + + if(!parent->imgsrc->isRAW()) { + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good for gamma=1 + } + + float maxmax = max(maxredaut, maxblueaut); + float delta; + int mode = 0; + // float redyel, skinc, nsknc; + int lissage = settings->leveldnliss; + parent->ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc); + + + if(maxredaut > maxblueaut) { + // maxr=(maxredaut-chaut)/((autoNRmax*multip*adjustr)/2.f); + maxr = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + + if(minblueaut <= minredaut && minblueaut < chaut) { + maxb = (-chaut + minblueaut) / (autoNRmax * multip * adjustr * lowdenoise); + } + } else { + // maxb=(maxblueaut-chaut)/((autoNRmax*multip*adjustr)/2.f); + maxb = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + + if(minredaut <= minblueaut && minredaut < chaut) { + maxr = (-chaut + minredaut) / (autoNRmax * multip * adjustr * lowdenoise); + } + }//maxb mxr - empirical evaluation red / blue + + + params.dirpyrDenoise.chroma = chaut / (autoNR * multip * adjustr * lowdenoise); + params.dirpyrDenoise.redchro = maxr; + params.dirpyrDenoise.bluechro = maxb; + parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); + + delete provicalc; + } + } + + if(skip == 1 && params.dirpyrDenoise.enabled && ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO"))) { + MyTime t1aue, t2aue; + t1aue.set(); + + int crW, crH; + + if(settings->leveldnv == 0) { + crW = 100; + crH = 100; + } + + if(settings->leveldnv == 1) { + crW = 250; + crH = 250; + } + + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv == 2) { + crW = int(tileWskip / 2); + crH = int(tileHskip / 2); + } + + if(settings->leveldnv == 3) { + crW = tileWskip - 10; + crH = tileHskip - 10; + } + + float lowdenoise = 1.f; + int levaut = settings->leveldnaut; + + if(levaut == 1) { //Standard + lowdenoise = 0.7f; + } + + LUTf gamcurve(65536, 0); + float gam, gamthresh, gamslope; + parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + int Nb[9]; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - Imagefloat *origCropPart = new Imagefloat (crW, crH);//allocate memory - Imagefloat *provicalc = new Imagefloat ((crW+1)/2, (crH+1)/2);//for denoise curves + { + Imagefloat *origCropPart = new Imagefloat (crW, crH);//allocate memory + Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves - int coordW[3];//coordonate of part of image to mesure noise - int coordH[3]; - int begW=50; - int begH=50; - coordW[0]=begW;coordW[1]=widIm/2-crW/2;coordW[2]=widIm-crW-begW; - coordH[0]=begH;coordH[1]=heiIm/2-crH/2;coordH[2]=heiIm-crH-begH; + int coordW[3];//coordonate of part of image to mesure noise + int coordH[3]; + int begW = 50; + int begH = 50; + coordW[0] = begW; + coordW[1] = widIm / 2 - crW / 2; + coordW[2] = widIm - crW - begW; + coordH[0] = begH; + coordH[1] = heiIm / 2 - crH / 2; + coordH[2] = heiIm - crH - begH; #ifdef _OPENMP -#pragma omp for schedule(dynamic) collapse(2) nowait + #pragma omp for schedule(dynamic) collapse(2) nowait #endif - for(int wcr=0;wcr<=2;wcr++) { - for(int hcr=0;hcr<=2;hcr++) { - PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1); - parent->imgsrc->getImage (parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); - // we only need image reduced to 1/4 here - for(int ii=0;iir(ii>>1,jj>>1) = origCropPart->r(ii,jj); - provicalc->g(ii>>1,jj>>1) = origCropPart->g(ii,jj); - provicalc->b(ii>>1,jj>>1) = origCropPart->b(ii,jj); - } - } - parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve + for(int wcr = 0; wcr <= 2; wcr++) { + for(int hcr = 0; hcr <= 2; hcr++) { + PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1); + parent->imgsrc->getImage (parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); - float pondcorrec=1.0f; - float chaut=0.f, redaut=0.f, blueaut=0.f, maxredaut=0.f, maxblueaut=0.f, minredaut=0.f, minblueaut=0.f, nresi=0.f, highresi=0.f, chromina=0.f, sigma=0.f, lumema=0.f, sigma_L=0.f, redyel=0.f, skinc=0.f, nsknc=0.f; - int nb=0; - parent->ipf.RGB_denoise_info(origCropPart, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + // we only need image reduced to 1/4 here + for(int ii = 0; ii < crH; ii += 2) { + for(int jj = 0; jj < crW; jj += 2) { + provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj); + provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj); + provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj); + } + } - //printf("DCROP skip=%d cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f\n",skip, chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema); - Nb[hcr*3 + wcr] = nb; - ch_M[hcr*3 + wcr]=pondcorrec*chaut; - max_r[hcr*3 + wcr]=pondcorrec*maxredaut; - max_b[hcr*3 + wcr]=pondcorrec*maxblueaut; - min_r[hcr*3 + wcr]=pondcorrec*minredaut; - min_b[hcr*3 + wcr]=pondcorrec*minblueaut; - lumL[hcr*3 + wcr]=lumema; - chromC[hcr*3 + wcr]=chromina; - ry[hcr*3 + wcr]=redyel; - sk[hcr*3 + wcr]=skinc; - pcsk[hcr*3 + wcr]=nsknc; - - } - } - delete provicalc; - delete origCropPart; -} - float chM=0.f; - float MaxR=0.f; - float MaxB=0.f; - float MinR=100000000000.f; - float MinB=100000000000.f; - float maxr=0.f; - float maxb=0.f; - float Max_R[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; - float Max_B[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; - float Min_R[9]; - float Min_B[9]; - float MaxRMoy=0.f; - float MaxBMoy=0.f; - float MinRMoy=0.f; - float MinBMoy=0.f; + parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve - float multip=1.f; - if(!parent->imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good fot gamma=1 - float adjustr=1.f; - if (params.icm.working=="ProPhoto") {adjustr =1.f;}// - else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} - else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} + float pondcorrec = 1.0f; + float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, nresi = 0.f, highresi = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f; + int nb = 0; + parent->ipf.RGB_denoise_info(origCropPart, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); - float delta[9]; - int mode=1; - int lissage=settings->leveldnliss; - for (int k=0;k<9;k++) { - float maxmax=max(max_r[k],max_b[k]); - parent->ipf.calcautodn_info (ch_M[k], delta[k], Nb[k], levaut, maxmax,lumL[k],chromC[k], mode, lissage, ry[k], sk[k], pcsk[k]); - // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]); - } - for (int k=0;k<9;k++) { - if(max_r[k] > max_b[k]) { - Max_R[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - Min_B[k]= -(ch_M[k]- min_b[k])/(autoNRmax*multip*adjustr*lowdenoise); - Max_B[k]=0.f; - Min_R[k]=0.f; - } - else { - Max_B[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - Min_R[k]=- (ch_M[k]-min_r[k]) / (autoNRmax*multip*adjustr*lowdenoise); - Min_B[k]=0.f; - Max_R[k]=0.f; - } - } + //printf("DCROP skip=%d cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f\n",skip, chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema); + Nb[hcr * 3 + wcr] = nb; + ch_M[hcr * 3 + wcr] = pondcorrec * chaut; + max_r[hcr * 3 + wcr] = pondcorrec * maxredaut; + max_b[hcr * 3 + wcr] = pondcorrec * maxblueaut; + min_r[hcr * 3 + wcr] = pondcorrec * minredaut; + min_b[hcr * 3 + wcr] = pondcorrec * minblueaut; + lumL[hcr * 3 + wcr] = lumema; + chromC[hcr * 3 + wcr] = chromina; + ry[hcr * 3 + wcr] = redyel; + sk[hcr * 3 + wcr] = skinc; + pcsk[hcr * 3 + wcr] = nsknc; - for (int k=0;k<9;k++) { - // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]); - chM+=ch_M[k]; - MaxBMoy+=Max_B[k]; - MaxRMoy+=Max_R[k]; - MinRMoy+=Min_R[k]; - MinBMoy+=Min_B[k]; + } + } - if(Max_R[k]>MaxR) MaxR=Max_R[k]; - if(Max_B[k]>MaxB) MaxB=Max_B[k]; - if(Min_R[k] MaxB) { - maxr=MaxRMoy + (MaxR-MaxRMoy)*0.66f;//#std Dev - //maxb=MinB; - maxb=MinBMoy + (MinB-MinBMoy)*0.66f; - } - else { - maxb=MaxBMoy + (MaxB-MaxBMoy)*0.66f; - maxr=MinRMoy + (MinR-MinRMoy)*0.66f; - } + float multip = 1.f; -// printf("DCROP skip=%d cha=%f red=%f bl=%f \n",skip, chM,maxr,maxb); - params.dirpyrDenoise.chroma=chM/(autoNR*multip*adjustr); - params.dirpyrDenoise.redchro=maxr; - params.dirpyrDenoise.bluechro=maxb; - if(parent->adnListener) { - parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); - } - if (settings->verbose) { - t2aue.set(); - printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue)); - } - - //end evaluate noise - } - // if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto - if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) {//reinit origCrop after Auto - PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); - parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); - } - DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; + if(!parent->imgsrc->isRAW()) { + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + } - if(params.dirpyrDenoise.Lmethod == "CUR") { - if(noiseLCurve) - denoiseParams.luma = 0.5f; //very small value to init process - select curve or slider - else - denoiseParams.luma = 0.0f; - } else if(denoiseParams.Lmethod == "SLI") - noiseLCurve.Reset(); + float adjustr = 1.f; - if((noiseLCurve || noiseCCurve ) && skip==1 && denoiseParams.enabled) {//only allocate memory if enabled and skip - // we only need image reduced to 1/4 here - int W = origCrop->getWidth(); - int H = origCrop->getHeight(); - calclum = new Imagefloat ((W+1)/2, (H+1)/2);//for denoise curves - for(int ii=0;iir(ii>>1,jj>>1) = origCrop->r(ii,jj); - calclum->g(ii>>1,jj>>1) = origCrop->g(ii,jj); - calclum->b(ii>>1,jj>>1) = origCrop->b(ii,jj); - } - } - - parent->imgsrc->convertColorSpace(calclum, params.icm, parent->currWB);//for denoise luminance curve - } + if (params.icm.working == "ProPhoto") { + adjustr = 1.f; // + } else if (params.icm.working == "Adobe RGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "sRGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "WideGamut") { + adjustr = 1.f / 1.1f; + } else if (params.icm.working == "Beta RGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BestRGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BruceRGB") { + adjustr = 1.f / 1.2f; + } - if(skip!=1) if(parent->adnListener) parent->adnListener->noiseChanged(0.f, 0.f); + float delta[9]; + int mode = 1; + int lissage = settings->leveldnliss; + + for (int k = 0; k < 9; k++) { + float maxmax = max(max_r[k], max_b[k]); + parent->ipf.calcautodn_info (ch_M[k], delta[k], Nb[k], levaut, maxmax, lumL[k], chromC[k], mode, lissage, ry[k], sk[k], pcsk[k]); + // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]); + } + + for (int k = 0; k < 9; k++) { + if(max_r[k] > max_b[k]) { + Max_R[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + Min_B[k] = -(ch_M[k] - min_b[k]) / (autoNRmax * multip * adjustr * lowdenoise); + Max_B[k] = 0.f; + Min_R[k] = 0.f; + } else { + Max_B[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + Min_R[k] = - (ch_M[k] - min_r[k]) / (autoNRmax * multip * adjustr * lowdenoise); + Min_B[k] = 0.f; + Max_R[k] = 0.f; + } + } + + for (int k = 0; k < 9; k++) { + // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]); + chM += ch_M[k]; + MaxBMoy += Max_B[k]; + MaxRMoy += Max_R[k]; + MinRMoy += Min_R[k]; + MinBMoy += Min_B[k]; + + if(Max_R[k] > MaxR) { + MaxR = Max_R[k]; + } + + if(Max_B[k] > MaxB) { + MaxB = Max_B[k]; + } + + if(Min_R[k] < MinR) { + MinR = Min_R[k]; + } + + if(Min_B[k] < MinB) { + MinB = Min_B[k]; + } + } + + chM /= 9; + MaxBMoy /= 9; + MaxRMoy /= 9; + MinBMoy /= 9; + MinRMoy /= 9; + + if(MaxR > MaxB) { + maxr = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev + //maxb=MinB; + maxb = MinBMoy + (MinB - MinBMoy) * 0.66f; + } else { + maxb = MaxBMoy + (MaxB - MaxBMoy) * 0.66f; + maxr = MinRMoy + (MinR - MinRMoy) * 0.66f; + } + +// printf("DCROP skip=%d cha=%f red=%f bl=%f \n",skip, chM,maxr,maxb); + params.dirpyrDenoise.chroma = chM / (autoNR * multip * adjustr); + params.dirpyrDenoise.redchro = maxr; + params.dirpyrDenoise.bluechro = maxb; + + if(parent->adnListener) { + parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); + } + + if (settings->verbose) { + t2aue.set(); + printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue)); + } + + //end evaluate noise + } + + // if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto + if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto + PreviewProps pp (trafx, trafy, trafw * skip, trafh * skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + } + + DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; + + if(params.dirpyrDenoise.Lmethod == "CUR") { + if(noiseLCurve) { + denoiseParams.luma = 0.5f; //very small value to init process - select curve or slider + } else { + denoiseParams.luma = 0.0f; + } + } else if(denoiseParams.Lmethod == "SLI") { + noiseLCurve.Reset(); + } + + if((noiseLCurve || noiseCCurve ) && skip == 1 && denoiseParams.enabled) { //only allocate memory if enabled and skip + // we only need image reduced to 1/4 here + int W = origCrop->getWidth(); + int H = origCrop->getHeight(); + calclum = new Imagefloat ((W + 1) / 2, (H + 1) / 2); //for denoise curves + + for(int ii = 0; ii < H; ii += 2) { + for(int jj = 0; jj < W; jj += 2) { + calclum->r(ii >> 1, jj >> 1) = origCrop->r(ii, jj); + calclum->g(ii >> 1, jj >> 1) = origCrop->g(ii, jj); + calclum->b(ii >> 1, jj >> 1) = origCrop->b(ii, jj); + } + } + + parent->imgsrc->convertColorSpace(calclum, params.icm, parent->currWB);//for denoise luminance curve + } + + if(skip != 1) if(parent->adnListener) { + parent->adnListener->noiseChanged(0.f, 0.f); + } if (todo & M_LINDENOISE) { - if (skip==1 && denoiseParams.enabled) { - int kall=0; + if (skip == 1 && denoiseParams.enabled) { + int kall = 0; - float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi; + float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi; parent->ipf.RGB_denoise(kall, origCrop, origCrop, calclum, ch_M, max_r, max_b, parent->imgsrc->isRAW(), /*Roffset,*/ denoiseParams, parent->imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); - if (parent->adnListener) parent->adnListener->noiseChanged(nresi, highresi); - if (settings->leveldnautsimpl == 1) { - if ((denoiseParams.Cmethod == "AUT" || denoiseParams.Cmethod == "PRE") && (parent->adnListener)) // force display value of sliders - parent->adnListener->chromaChanged(denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro); - } else { - if((denoiseParams.C2method == "AUTO" || denoiseParams.C2method == "PREV") && (parent->adnListener)) // force display value of sliders - parent->adnListener->chromaChanged(denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro); - } - - } - } + + if (parent->adnListener) { + parent->adnListener->noiseChanged(nresi, highresi); + } + + if (settings->leveldnautsimpl == 1) { + if ((denoiseParams.Cmethod == "AUT" || denoiseParams.Cmethod == "PRE") && (parent->adnListener)) { // force display value of sliders + parent->adnListener->chromaChanged(denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro); + } + } else { + if((denoiseParams.C2method == "AUTO" || denoiseParams.C2method == "PREV") && (parent->adnListener)) { // force display value of sliders + parent->adnListener->chromaChanged(denoiseParams.chroma, denoiseParams.redchro, denoiseParams.bluechro); + } + } + + } + } + parent->imgsrc->convertColorSpace(origCrop, params.icm, parent->currWB); - delete [] ch_M; - delete [] max_r; - delete [] max_b; - delete [] min_r; - delete [] min_b; - delete [] lumL; - delete [] chromC; - delete [] ry; - delete [] sk; - delete [] pcsk; - delete [] centerTile_X; - delete [] centerTile_Y; - - } + delete [] ch_M; + delete [] max_r; + delete [] max_b; + delete [] min_r; + delete [] min_b; + delete [] lumL; + delete [] chromC; + delete [] ry; + delete [] sk; + delete [] pcsk; + delete [] centerTile_X; + delete [] centerTile_Y; + + } // has to be called after setCropSizes! Tools prior to this point can't handle the Edit mechanism, but that shouldn't be a problem. createBuffer(cropw, croph); // transform if (needstransform) { - if (!transCrop) + if (!transCrop) { transCrop = new Imagefloat (cropw, croph); + } if ((todo & M_TRANSFORM) && needstransform) - parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip), parent->getFullWidth(), parent->getFullHeight(), + parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, SKIPS(parent->fw, skip), SKIPS(parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(), parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false); - if (transCrop) + + if (transCrop) { baseCrop = transCrop; - } - else { - if (transCrop) delete transCrop; + } + } else { + if (transCrop) { + delete transCrop; + } + transCrop = NULL; } // 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; + double radius = sqrt (double(SKIPS(parent->fw, skip) * SKIPS(parent->fw, skip) + SKIPS(parent->fh, skip) * SKIPS(parent->fh, skip))) / 2.0; double shradius = params.sh.radius; - if (!params.sh.hq) shradius *= radius / 1800.0; - if(!cshmap) - cshmap = new SHMap (cropw, croph, true); + + if (!params.sh.hq) { + shradius *= radius / 1800.0; + } + + if(!cshmap) { + cshmap = new SHMap (cropw, croph, true); + } + cshmap->update (baseCrop, shradius, parent->ipf.lumimul, params.sh.hq, skip); - if(parent->shmap->min_f < 65535.f) // don't call forceStat with wrong values + + if(parent->shmap->min_f < 65535.f) { // don't call forceStat with wrong values cshmap->forceStat (parent->shmap->max_f, parent->shmap->min_f, parent->shmap->avg); + } } // shadows & highlights & tone curve & convert to cielab @@ -580,29 +744,37 @@ void Crop::update (int todo) { baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256, parent->imgsrc->getGamma()); }*/ - float satLimit = float(params.colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; - float satLimitOpacity = 1.f-(float(params.colorToning.saturatedOpacity)/100.f); + float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; + float satLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f); - if(params.colorToning.enabled && params.colorToning.autosat){//for colortoning evaluation of saturation settings - float moyS=0.f; - float eqty=0.f; + if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + float moyS = 0.f; + float eqty = 0.f; parent->ipf.moyeqt (baseCrop, moyS, eqty);//return image : mean saturation and standard dev of saturation //printf("moy=%f ET=%f\n", moyS,eqty); - float satp=((moyS+1.5f*eqty)-0.3f)/0.7f;//1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale - if(satp >= 0.92f) satp=0.92f;//avoid values too high (out of gamut) - if(satp <= 0.15f) satp=0.15f;//avoid too low values - satLimit= 100.f*satp; - satLimitOpacity= 100.f*(moyS-0.85f*eqty);//-0.85 sigma==>20% pixels with low saturation + float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale + + if(satp >= 0.92f) { + satp = 0.92f; //avoid values too high (out of gamut) + } + + if(satp <= 0.15f) { + satp = 0.15f; //avoid too low values + } + + satLimit = 100.f * satp; + satLimitOpacity = 100.f * (moyS - 0.85f * eqty); //-0.85 sigma==>20% pixels with low saturation } if (todo & M_RGBCURVE) { - double rrm, ggm, bbm; + double rrm, ggm, bbm; DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, parent->currWB); parent->ipf.rgbProc (baseCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap, - params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, satLimit ,satLimitOpacity, parent->ctColorCurve, parent->ctOpacityCurve, parent->opautili, parent->clToningcurve,parent->cl2Toningcurve, - parent->customToneCurve1, parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW,rrm, ggm, bbm, + params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, satLimit , satLimitOpacity, parent->ctColorCurve, parent->ctOpacityCurve, parent->opautili, parent->clToningcurve, parent->cl2Toningcurve, + parent->customToneCurve1, parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW, rrm, ggm, bbm, parent->bwAutoR, parent->bwAutoG, parent->bwAutoB, dcpProf); } + /*xref=000;yref=000; if (colortest && cropw>115 && croph>115) for(int j=1;j<5;j++){ @@ -620,139 +792,192 @@ void Crop::update (int todo) { }*/ // apply luminance operations - if (todo & (M_LUMINANCE+M_COLOR)) { + if (todo & (M_LUMINANCE + M_COLOR)) { //I made a little change here. Rather than have luminanceCurve (and others) use in/out lab images, we can do more if we copy right here. labnCrop->CopyFrom(laboCrop); //parent->ipf.luminanceCurve (labnCrop, labnCrop, parent->lumacurve); - bool utili=parent->utili; - bool autili=parent->autili; - bool butili=parent->butili; - bool ccutili=parent->ccutili; - bool clcutili=parent->clcutili; - bool cclutili=parent->cclutili; - bool wavcontlutili=parent->wavcontlutili; + bool utili = parent->utili; + bool autili = parent->autili; + bool butili = parent->butili; + bool ccutili = parent->ccutili; + bool clcutili = parent->clcutili; + bool cclutili = parent->cclutili; + bool wavcontlutili = parent->wavcontlutili; LUTu dummy; - parent->ipf.chromiLuminanceCurve (this, 1,labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->clcurve, parent->lumacurve, utili, autili, butili, ccutili,cclutili, clcutili, dummy, dummy, dummy, dummy); + parent->ipf.chromiLuminanceCurve (this, 1, labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->clcurve, parent->lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); parent->ipf.vibrance (labnCrop); - if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) parent->ipf.EPDToneMap(labnCrop,5,1); + + if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) { + parent->ipf.EPDToneMap(labnCrop, 5, 1); + } + //parent->ipf.EPDToneMap(labnCrop, 5, 1); //Go with much fewer than normal iterates for fast redisplay. // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled - if (skip==1) { + if (skip == 1) { if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - parent->ipf.impulsedenoise (labnCrop);} - if((params.colorappearance.enabled && !settings->autocielab) ||(!params.colorappearance.enabled) ) {parent->ipf.defringe (labnCrop);} + parent->ipf.impulsedenoise (labnCrop); + } + + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled) ) { + parent->ipf.defringe (labnCrop); + } + parent->ipf.MLsharpen (labnCrop); + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { parent->ipf.MLmicrocontrast (labnCrop); parent->ipf.sharpening (labnCrop, (float**)cbuffer, params.sharpening); } } - // if (skip==1) { - WaveletParams WaveParams = params.wavelet; - + + // 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); - } + // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + } - - int kall=0; - int minwin=min(labnCrop->W,labnCrop->H); - int maxlevelcrop=10; - // if(cp.mul[9]!=0)maxlevelcrop=10; - // adap maximum level wavelet to size of crop - if(minwin*skip < 1024) maxlevelcrop = 9;//sampling wavelet 512 - if(minwin*skip < 512) maxlevelcrop = 8;//sampling wavelet 256 - if(minwin*skip < 256) maxlevelcrop = 7;//sampling 128 - if(minwin*skip < 128) maxlevelcrop = 6; - if(minwin < 64) maxlevelcrop = 5; - - int realtile; - if(params.wavelet.Tilesmethod=="big") realtile=22; - if(params.wavelet.Tilesmethod=="lit") realtile=12; - - int tilesize; - int overlap; - tilesize = 1024; - overlap = 128; - tilesize=128*realtile; - //overlap=(int) tilesize*params->wavelet.overl; - overlap=(int) tilesize*0.125f; - // printf("overl=%d\n",overlap); - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - - parent->ipf.Tile_calc (tilesize, overlap, kall, labnCrop->W, labnCrop->H, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - //now we have tile dimensions, overlaps - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - int minsizetile=min(tilewidth, tileheight); - int maxlev2=10; - if(minsizetile < 1024 && maxlevelcrop==10) maxlev2 = 9; - if(minsizetile < 512) maxlev2 = 8; - if(minsizetile < 256) maxlev2 = 7; - if(minsizetile < 128) maxlev2 = 6; - int maxL=min(maxlev2,maxlevelcrop); - - if(parent->awavListener) parent->awavListener->wavChanged(float(maxL)); - - if((params.wavelet.enabled)) { - WavCurve wavCLVCurve; - WavOpacityCurveRG waOpacityCurveRG; - WavOpacityCurveBY waOpacityCurveBY; - WavOpacityCurveW waOpacityCurveW; - WavOpacityCurveWL waOpacityCurveWL; - LUTf wavclCurve; - LUTu dummy; - params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); + int kall = 0; + int minwin = min(labnCrop->W, labnCrop->H); + int maxlevelcrop = 10; - parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, wavcontlutili, skip); - } + // if(cp.mul[9]!=0)maxlevelcrop=10; + // adap maximum level wavelet to size of crop + if(minwin * skip < 1024) { + maxlevelcrop = 9; //sampling wavelet 512 + } - // } - - // } - if(params.colorappearance.enabled){ + if(minwin * skip < 512) { + maxlevelcrop = 8; //sampling wavelet 256 + } + + if(minwin * skip < 256) { + maxlevelcrop = 7; //sampling 128 + } + + if(minwin * skip < 128) { + maxlevelcrop = 6; + } + + if(minwin < 64) { + maxlevelcrop = 5; + } + + int realtile; + + if(params.wavelet.Tilesmethod == "big") { + realtile = 22; + } + + if(params.wavelet.Tilesmethod == "lit") { + realtile = 12; + } + + int tilesize; + int overlap; + tilesize = 1024; + overlap = 128; + tilesize = 128 * realtile; + //overlap=(int) tilesize*params->wavelet.overl; + overlap = (int) tilesize * 0.125f; + // printf("overl=%d\n",overlap); + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + + parent->ipf.Tile_calc (tilesize, overlap, kall, labnCrop->W, labnCrop->H, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + //now we have tile dimensions, overlaps + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + int minsizetile = min(tilewidth, tileheight); + int maxlev2 = 10; + + if(minsizetile < 1024 && maxlevelcrop == 10) { + maxlev2 = 9; + } + + if(minsizetile < 512) { + maxlev2 = 8; + } + + if(minsizetile < 256) { + maxlev2 = 7; + } + + if(minsizetile < 128) { + maxlev2 = 6; + } + + int maxL = min(maxlev2, maxlevelcrop); + + if(parent->awavListener) { + parent->awavListener->wavChanged(float(maxL)); + } + + if((params.wavelet.enabled)) { + WavCurve wavCLVCurve; + WavOpacityCurveRG waOpacityCurveRG; + WavOpacityCurveBY waOpacityCurveBY; + WavOpacityCurveW waOpacityCurveW; + WavOpacityCurveWL waOpacityCurveWL; + LUTf wavclCurve; + LUTu dummy; + + params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); + + parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, wavcontlutili, skip); + } + + // } + + // } + if(params.colorappearance.enabled) { float fnum = parent->imgsrc->getMetaData()->getFNumber (); // F number float fiso = parent->imgsrc->getMetaData()->getISOSpeed () ; // ISO float fspeed = parent->imgsrc->getMetaData()->getShutterSpeed () ; // Speed double fcomp = parent->imgsrc->getMetaData()->getExpComp (); // Compensation +/- double adap; // Scene's luminosity adaptation factor + if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong - adap=2000.; - } - else { - double E_V = fcomp + log2 (double((fnum*fnum) / fspeed / (fiso/100.f))); + adap = 2000.; + } else { + double E_V = fcomp + log2 (double((fnum * fnum) / fspeed / (fiso / 100.f))); E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV - adap= pow(2., E_V-3.);// cd / m2 + adap = pow(2., E_V - 3.); // cd / m2 // end calculation adaptation scene luminosity } int begh = 0, endh = labnCrop->H; - bool execsharp=false; - if(skip==1) execsharp=true; + bool execsharp = false; - if (!cieCrop) - { cieCrop = new CieImage (cropw, croph); } + if(skip == 1) { + execsharp = true; + } + + if (!cieCrop) { + cieCrop = new CieImage (cropw, croph); + } if(settings->ciecamfloat) { float d; // not used after this block parent->ipf.ciecam_02float (cieCrop, float(adap), begh, endh, 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, - dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, 1, execsharp, d, skip, 1); - } - else { + dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, 1, execsharp, d, skip, 1); + } else { double dd; // not used after this block - parent->ipf.ciecam_02 (cieCrop,adap, begh, endh, 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, + parent->ipf.ciecam_02 (cieCrop, adap, begh, endh, 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, 1, execsharp, dd, skip, 1); } - } - else { + } else { // CIECAM is disbaled, we free up its image buffer to save some space - if (cieCrop) delete cieCrop; cieCrop=NULL; + if (cieCrop) { + delete cieCrop; + } + + cieCrop = NULL; } } @@ -798,28 +1023,40 @@ void Crop::update (int todo) { */ if (cropImageListener) { // this in output space held in parallel to allow analysis like shadow/highlight - Glib::ustring outProfile=params.icm.output; - Glib::ustring workProfile=params.icm.working; - Image8 *cropImgtrue; - if(settings->HistogramWorking) cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0,0,cropw,croph, workProfile, false); - else { - if (params.icm.output=="" || params.icm.output==ColorManagementParams::NoICMString) outProfile="sRGB"; - cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0,0,cropw,croph, outProfile, false); - } + Glib::ustring outProfile = params.icm.output; + Glib::ustring workProfile = params.icm.working; + Image8 *cropImgtrue; + + if(settings->HistogramWorking) { + cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, workProfile, false); + } else { + if (params.icm.output == "" || params.icm.output == ColorManagementParams::NoICMString) { + outProfile = "sRGB"; + } + + cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, outProfile, false); + } int finalW = rqcropw; - if (cropImg->getWidth()-leftBorder < finalW) - finalW = cropImg->getWidth()-leftBorder; + + if (cropImg->getWidth() - leftBorder < finalW) { + finalW = cropImg->getWidth() - leftBorder; + } + int finalH = rqcroph; - if (cropImg->getHeight()-upperBorder < finalH) - finalH = cropImg->getHeight()-upperBorder; + + if (cropImg->getHeight() - upperBorder < finalH) { + finalH = cropImg->getHeight() - upperBorder; + } Image8* final = new Image8 (finalW, finalH); Image8* finaltrue = new Image8 (finalW, finalH); - for (int i=0; idata + 3*i*finalW, cropImg->data + 3*(i+upperBorder)*cropw + 3*leftBorder, 3*finalW); - memcpy (finaltrue->data + 3*i*finalW, cropImgtrue->data + 3*(i+upperBorder)*cropw + 3*leftBorder, 3*finalW); + + for (int i = 0; i < finalH; i++) { + memcpy (final->data + 3 * i * finalW, cropImg->data + 3 * (i + upperBorder)*cropw + 3 * leftBorder, 3 * finalW); + memcpy (finaltrue->data + 3 * i * finalW, cropImgtrue->data + 3 * (i + upperBorder)*cropw + 3 * leftBorder, 3 * finalW); } + cropImageListener->setDetailedCrop (final, finaltrue, params.icm, params.crop, rqcropx, rqcropy, rqcropw, rqcroph, skip); delete final; delete finaltrue; @@ -827,23 +1064,62 @@ void Crop::update (int todo) { } } -void Crop::freeAll () { +void Crop::freeAll () +{ - if (settings->verbose) printf ("freeallcrop starts %d\n", (int)cropAllocated); + if (settings->verbose) { + printf ("freeallcrop starts %d\n", (int)cropAllocated); + } if (cropAllocated) { - if (origCrop ) { delete origCrop; origCrop=NULL; } - if (transCrop) { delete transCrop; transCrop=NULL; } - if (laboCrop ) { delete laboCrop; laboCrop=NULL; } - if (labnCrop ) { delete labnCrop; labnCrop=NULL; } - if (cropImg ) { delete cropImg; cropImg=NULL; } - if (cieCrop ) { delete cieCrop; cieCrop=NULL; } - if (cbuf_real) { delete [] cbuf_real; cbuf_real=NULL; } - if (cbuffer ) { delete [] cbuffer; cbuffer=NULL; } - if (cshmap ) { delete cshmap; cshmap=NULL; } + if (origCrop ) { + delete origCrop; + origCrop = NULL; + } + + if (transCrop) { + delete transCrop; + transCrop = NULL; + } + + if (laboCrop ) { + delete laboCrop; + laboCrop = NULL; + } + + if (labnCrop ) { + delete labnCrop; + labnCrop = NULL; + } + + if (cropImg ) { + delete cropImg; + cropImg = NULL; + } + + if (cieCrop ) { + delete cieCrop; + cieCrop = NULL; + } + + if (cbuf_real) { + delete [] cbuf_real; + cbuf_real = NULL; + } + + if (cbuffer ) { + delete [] cbuffer; + cbuffer = NULL; + } + + if (cshmap ) { + delete cshmap; + cshmap = NULL; + } EditBuffer::flush(); } + cropAllocated = false; } @@ -851,12 +1127,16 @@ void Crop::freeAll () { * If the scale changes, this method will free all buffers and reallocate ones of the new size. * It will then tell to the SizeListener that size has changed (sizeChanged) */ -bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool internal) { +bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool internal) +{ -if (settings->verbose) printf ("setcropsizes before lock\n"); + if (settings->verbose) { + printf ("setcropsizes before lock\n"); + } - if (!internal) + if (!internal) { cropMutex.lock (); + } bool changed = false; @@ -866,28 +1146,28 @@ if (settings->verbose) printf ("setcropsizes before lock\n"); rqcroph = rch; // store and set requested crop size - int rqx1 = LIM(rqcropx,0,parent->fullw-1); - int rqy1 = LIM(rqcropy,0,parent->fullh-1); + int rqx1 = LIM(rqcropx, 0, parent->fullw - 1); + int rqy1 = LIM(rqcropy, 0, parent->fullh - 1); int rqx2 = rqx1 + rqcropw - 1; int rqy2 = rqy1 + rqcroph - 1; - rqx2 = LIM(rqx2,0,parent->fullw-1); - rqy2 = LIM(rqy2,0,parent->fullh-1); + rqx2 = LIM(rqx2, 0, parent->fullw - 1); + rqy2 = LIM(rqy2, 0, parent->fullh - 1); this->skip = skip; - + // add border, if possible - int bx1 = rqx1 - skip*borderRequested; - int by1 = rqy1 - skip*borderRequested; - int bx2 = rqx2 + skip*borderRequested; - int by2 = rqy2 + skip*borderRequested; + int bx1 = rqx1 - skip * borderRequested; + int by1 = rqy1 - skip * borderRequested; + int bx2 = rqx2 + skip * borderRequested; + int by2 = rqy2 + skip * borderRequested; // clip it to fit into image area - bx1 = LIM(bx1,0,parent->fullw-1); - by1 = LIM(by1,0,parent->fullh-1); - bx2 = LIM(bx2,0,parent->fullw-1); - by2 = LIM(by2,0,parent->fullh-1); + bx1 = LIM(bx1, 0, parent->fullw - 1); + by1 = LIM(by1, 0, parent->fullh - 1); + bx2 = LIM(bx2, 0, parent->fullw - 1); + by2 = LIM(by2, 0, parent->fullh - 1); int bw = bx2 - bx1 + 1; int bh = by2 - by1 + 1; - + // determine which part of the source image is required to compute the crop rectangle int orx, ory, orw, orh; ProcParams& params = parent->params; @@ -899,52 +1179,81 @@ if (settings->verbose) printf ("setcropsizes before lock\n"); int orW, orH; parent->imgsrc->getSize (tr, cp, orW, orH); - int cw = SKIPS(bw,skip); - int ch = SKIPS(bh,skip); + int cw = SKIPS(bw, skip); + int ch = SKIPS(bh, skip); - leftBorder = SKIPS(rqx1-bx1,skip); - upperBorder = SKIPS(rqy1-by1,skip); + leftBorder = SKIPS(rqx1 - bx1, skip); + upperBorder = SKIPS(rqy1 - by1, skip); - if (settings->verbose) - printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh,cw,ch); + if (settings->verbose) { + printf ("setsizes starts (%d, %d, %d, %d, %d, %d)\n", orW, orH, trafw, trafh, cw, ch); + } - if (cw!=cropw || ch!=croph || orW!=trafw || orH!=trafh) { + if (cw != cropw || ch != croph || orW != trafw || orH != trafh) { cropw = cw; croph = ch; trafw = orW; trafh = orH; - if (!origCrop) + if (!origCrop) { origCrop = new Imagefloat; + } + origCrop->allocate(trafw, trafh); // Resizing the buffer (optimization) // if transCrop doesn't exist yet, it'll be created where necessary - if (transCrop) transCrop->allocate(cropw, croph); + if (transCrop) { + transCrop->allocate(cropw, croph); + } + + if (laboCrop) { + delete laboCrop; // laboCrop can't be resized + } - if (laboCrop) delete laboCrop; // laboCrop can't be resized laboCrop = new LabImage (cropw, croph); - if (labnCrop) delete labnCrop; // labnCrop can't be resized + if (labnCrop) { + delete labnCrop; // labnCrop can't be resized + } + labnCrop = new LabImage (cropw, croph); - if (!cropImg) + if (!cropImg) { cropImg = new Image8; + } + cropImg->allocate(cropw, croph); // Resizing the buffer (optimization) //cieCrop is only used in Crop::update, it is destroyed now but will be allocated on first use - if (cieCrop) { delete cieCrop; cieCrop=NULL; } + if (cieCrop) { + delete cieCrop; + cieCrop = NULL; + } + + if (cbuffer ) { + delete [] cbuffer; + } + + if (cbuf_real) { + delete [] cbuf_real; + } + + if (cshmap ) { + delete cshmap; + cshmap = NULL; + } - if (cbuffer ) delete [] cbuffer; - if (cbuf_real) delete [] cbuf_real; - if (cshmap ) { delete cshmap; cshmap = NULL;} cbuffer = new float*[croph]; - cbuf_real= new float[(croph+2)*cropw]; - for (int i=0; iverbose) printf ("setcropsizes before lock\n"); trafx = orx; trafy = ory; - if (settings->verbose) printf ("setsizes ends\n"); + if (settings->verbose) { + printf ("setsizes ends\n"); + } - if (!internal) + if (!internal) { cropMutex.unlock (); + } return changed; } @@ -970,7 +1282,8 @@ if (settings->verbose) printf ("setcropsizes before lock\n"); * * @return If true, a new updating thread has to be created. If false, the current updating thread will be used */ -bool Crop::tryUpdate() { +bool Crop::tryUpdate() +{ bool needsNewThread = true; if (updating) { @@ -978,10 +1291,11 @@ bool Crop::tryUpdate() { newUpdatePending = true; // no need for a new thread, the current one will do the job needsNewThread = false; - } - else + } else // the crop is now being updated ...well, when fullUpdate will be called + { updating = true; + } return needsNewThread; } @@ -993,9 +1307,11 @@ bool Crop::tryUpdate() { * * This method is called when the visible part of the crop has changed (resize, zoom, etc..), so it needs a full update */ -void Crop::fullUpdate () { +void Crop::fullUpdate () +{ parent->updaterThreadStart.lock (); + if (parent->updaterRunning && parent->thread) { // Do NOT reset changes here, since in a long chain of events it will lead to chroma_scale not being updated, // causing Color::lab2rgb to return a black image on some opens @@ -1003,19 +1319,24 @@ void Crop::fullUpdate () { parent->thread->join (); } - if (parent->plistener) + if (parent->plistener) { parent->plistener->setProgressState (true); + } // If there are more update request, the following WHILE will collect it newUpdatePending = true; + while (newUpdatePending) { newUpdatePending = false; - update (ALL); + update (ALL); } + updating = false; // end of crop update - if (parent->plistener) + if (parent->plistener) { parent->plistener->setProgressState (false); + } + parent->updaterThreadStart.unlock (); } diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index 6f858779f..57f388a51 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -7,7 +7,7 @@ * 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 @@ -29,71 +29,94 @@ #include "editbuffer.h" #include "../rtgui/threadutils.h" -namespace rtengine { +namespace rtengine +{ using namespace procparams; class ImProcCoordinator; -class Crop : public DetailedCrop, public EditBuffer { +class Crop : public DetailedCrop, public EditBuffer +{ - protected: - // --- permanently allocated in RAM and only renewed on size changes - Imagefloat* origCrop; // "one chunk" allocation - LabImage* laboCrop; // "one chunk" allocation - LabImage* labnCrop; // "one chunk" allocation - Image8* cropImg; // "one chunk" allocation - float * cbuf_real; // "one chunk" allocation - SHMap* cshmap; // per line allocation +protected: + // --- permanently allocated in RAM and only renewed on size changes + Imagefloat* origCrop; // "one chunk" allocation + LabImage* laboCrop; // "one chunk" allocation + LabImage* labnCrop; // "one chunk" allocation + Image8* cropImg; // "one chunk" allocation + float * cbuf_real; // "one chunk" allocation + SHMap* cshmap; // per line allocation - // --- automatically allocated and deleted when necessary, and only renewed on size changes - Imagefloat* transCrop; // "one chunk" allocation, allocated if necessary - CieImage* cieCrop; // allocating 6 images, each in "one chunk" allocation - // ----------------------------------------------------------------- - float** cbuffer; + // --- automatically allocated and deleted when necessary, and only renewed on size changes + Imagefloat* transCrop; // "one chunk" allocation, allocated if necessary + CieImage* cieCrop; // allocating 6 images, each in "one chunk" allocation + // ----------------------------------------------------------------- + float** cbuffer; - bool updating; /// Flag telling if an updater thread is currently processing - bool newUpdatePending; /// Flag telling the updater thread that a new update is pending - int skip; - int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border - int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area - int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border) - int borderRequested; /// requested extra border size for image processing - int upperBorder, leftBorder; /// extra border size really allocated for image processing + bool updating; /// Flag telling if an updater thread is currently processing + bool newUpdatePending; /// Flag telling the updater thread that a new update is pending + int skip; + int cropx, cropy, cropw, croph; /// size of the detail crop image ('skip' taken into account), with border + int trafx, trafy, trafw, trafh; /// the size and position to get from the imagesource that is transformed to the requested crop area + int rqcropx, rqcropy, rqcropw, rqcroph; /// size of the requested detail crop image (the image might be smaller) (without border) + int borderRequested; /// requested extra border size for image processing + int upperBorder, leftBorder; /// extra border size really allocated for image processing - bool cropAllocated; - DetailedCropListener* cropImageListener; + bool cropAllocated; + DetailedCropListener* cropImageListener; - MyMutex cropMutex; - ImProcCoordinator* parent; - bool isDetailWindow; - EditUniqueID getCurrEditID(); - bool setCropSizes (int cx, int cy, int cw, int ch, int skip, bool internal); - void freeAll (); + MyMutex cropMutex; + ImProcCoordinator* parent; + bool isDetailWindow; + EditUniqueID getCurrEditID(); + bool setCropSizes (int cx, int cy, int cw, int ch, int skip, bool internal); + void freeAll (); - public: - Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow); - virtual ~Crop (); +public: + Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow); + virtual ~Crop (); - void mLock () { cropMutex.lock(); } - void mUnlock () { cropMutex.lock(); } - void setEditSubscriber(EditSubscriber* newSubscriber); - bool hasListener () { return cropImageListener; } - void update (int todo); - void setWindow (int cx, int cy, int cw, int ch, int skip) { setCropSizes (cx, cy, cw, ch, skip, false); } + void mLock () + { + cropMutex.lock(); + } + void mUnlock () + { + cropMutex.lock(); + } + void setEditSubscriber(EditSubscriber* newSubscriber); + bool hasListener () + { + return cropImageListener; + } + void update (int todo); + void setWindow (int cx, int cy, int cw, int ch, int skip) + { + setCropSizes (cx, cy, cw, ch, skip, false); + } - /** @brief Synchronously look out if a full update is necessary - * First try, only make fullUpdate if this returns false - */ - bool tryUpdate (); - /** @brief Asynchronously reprocess the detailed crop */ - void fullUpdate (); // called via thread + /** @brief Synchronously look out if a full update is necessary + * First try, only make fullUpdate if this returns false + */ + bool tryUpdate (); + /** @brief Asynchronously reprocess the detailed crop */ + void fullUpdate (); // called via thread - void setListener (DetailedCropListener* il); - void destroy (); - int get_skip () { return skip;} - int getLeftBorder () { return leftBorder; } - int getUpperBorder () { return upperBorder; } + void setListener (DetailedCropListener* il); + void destroy (); + int get_skip () + { + return skip; + } + int getLeftBorder () + { + return leftBorder; + } + int getUpperBorder () + { + return upperBorder; + } }; } #endif diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index e986270ff..954be456b 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -43,7 +43,8 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ #undef ABS #undef DIST @@ -58,238 +59,257 @@ namespace rtengine { #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } -#define PIX_SORTV(av,bv) tempv = _mm_min_ps(av,bv); bv = _mm_max_ps(av,bv); av = tempv; +#define PIX_SORTV(av,bv) tempv = _mm_min_ps(av,bv); bv = _mm_max_ps(av,bv); av = tempv; extern const Settings* settings; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::eahd_demosaic () { - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::eahd])); - plistener->setProgress (0.0); - } - - // prepare cache and constants for cielab conversion - //TODO: revisit after conversion to D50 illuminant - lc00 = (0.412453 * imatrices.rgb_cam[0][0] + 0.357580 * imatrices.rgb_cam[0][1] + 0.180423 * imatrices.rgb_cam[0][2]) ;// / 0.950456; - lc01 = (0.412453 * imatrices.rgb_cam[1][0] + 0.357580 * imatrices.rgb_cam[1][1] + 0.180423 * imatrices.rgb_cam[1][2]) ;// / 0.950456; - lc02 = (0.412453 * imatrices.rgb_cam[2][0] + 0.357580 * imatrices.rgb_cam[2][1] + 0.180423 * imatrices.rgb_cam[2][2]) ;// / 0.950456; - - lc10 = 0.212671 * imatrices.rgb_cam[0][0] + 0.715160 * imatrices.rgb_cam[0][1] + 0.072169 * imatrices.rgb_cam[0][2]; - lc11 = 0.212671 * imatrices.rgb_cam[1][0] + 0.715160 * imatrices.rgb_cam[1][1] + 0.072169 * imatrices.rgb_cam[1][2]; - lc12 = 0.212671 * imatrices.rgb_cam[2][0] + 0.715160 * imatrices.rgb_cam[2][1] + 0.072169 * imatrices.rgb_cam[2][2]; - - lc20 = (0.019334 * imatrices.rgb_cam[0][0] + 0.119193 * imatrices.rgb_cam[0][1] + 0.950227 * imatrices.rgb_cam[0][2]) ;// / 1.088754; - lc21 = (0.019334 * imatrices.rgb_cam[1][0] + 0.119193 * imatrices.rgb_cam[1][1] + 0.950227 * imatrices.rgb_cam[1][2]) ;// / 1.088754; - lc22 = (0.019334 * imatrices.rgb_cam[2][0] + 0.119193 * imatrices.rgb_cam[2][1] + 0.950227 * imatrices.rgb_cam[2][2]) ;// / 1.088754; - - int maxindex = 3*65536;//2*65536 3 = avoid crash 3/2013 J.Desmis - cache = new double[maxindex]; - threshold = (int)(0.008856*MAXVALD); - for (int i=0; isetProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::eahd])); + plistener->setProgress (0.0); } - convert_to_cielab_row (rh[(i+1)%3], gh[(i+1)%4], bh[(i+1)%3], lLh[(i+1)%3], lah[(i+1)%3], lbh[(i+1)%3]); - convert_to_cielab_row (rv[(i+1)%3], gv[(i+1)%4], bv[(i+1)%3], lLv[(i+1)%3], lav[(i+1)%3], lbv[(i+1)%3]); + // prepare cache and constants for cielab conversion + //TODO: revisit after conversion to D50 illuminant + lc00 = (0.412453 * imatrices.rgb_cam[0][0] + 0.357580 * imatrices.rgb_cam[0][1] + 0.180423 * imatrices.rgb_cam[0][2]) ;// / 0.950456; + lc01 = (0.412453 * imatrices.rgb_cam[1][0] + 0.357580 * imatrices.rgb_cam[1][1] + 0.180423 * imatrices.rgb_cam[1][2]) ;// / 0.950456; + lc02 = (0.412453 * imatrices.rgb_cam[2][0] + 0.357580 * imatrices.rgb_cam[2][1] + 0.180423 * imatrices.rgb_cam[2][2]) ;// / 0.950456; - for (int j=0; jsv) { // fixate horizontal pixel - dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j+y]); - dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j+y]); - dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j+y]); - dLmapv[dmi] = DIST(lLv[ix][j], lLh[idx][j+y]); - dCamapv[dmi] = DIST(lav[ix][j], lah[idx][j+y]); - dCbmapv[dmi] = DIST(lbv[ix][j], lbh[idx][j+y]); - } - else if (sh sv) { // fixate horizontal pixel + dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLh[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lah[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbh[idx][j + y]); + } else if (sh < sv) { + dLmaph[dmi] = DIST(lLh[ix][j], lLv[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lav[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbv[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); + } else { + dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); + } + } else { + dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); + } + + dmi++; + } + } + + // compute eL & eC + int eL = min(max(dLmaph[3], dLmaph[5]), max(dLmapv[1], dLmapv[7])); + int eCa = min(max(dCamaph[3], dCamaph[5]), max(dCamapv[1], dCamapv[7])); + int eCb = min(max(dCbmaph[3], dCbmaph[5]), max(dCbmapv[1], dCbmapv[7])); + + int wh = 0; + + for (int dmi = 0; dmi < 9; dmi++) + if (dLmaph[dmi] <= eL && dCamaph[dmi] <= eCa && dCbmaph[dmi] <= eCb) { + wh++; + } + + int wv = 0; + + for (int dmi = 0; dmi < 9; dmi++) + if (dLmapv[dmi] <= eL && dCamapv[dmi] <= eCa && dCbmapv[dmi] <= eCb) { + wv++; + } + + homh[imx][j - 1] += wh; + homh[imx][j] += wh; + homh[imx][j + 1] += wh; + homh[ix][j - 1] += wh; + homh[ix][j] += wh; + homh[ix][j + 1] += wh; + homh[ipx][j - 1] += wh; + homh[ipx][j] += wh; + homh[ipx][j + 1] += wh; + + homv[imx][j - 1] += wv; + homv[imx][j] += wv; + homv[imx][j + 1] += wv; + homv[ix][j - 1] += wv; + homv[ix][j] += wv; + homv[ix][j + 1] += wv; + homv[ipx][j - 1] += wv; + homv[ipx][j] += wv; + homv[ipx][j + 1] += wv; + } - homv[imx][j-1]+=wv; - homv[imx][j] +=wv; - homv[imx][j+1]+=wv; - homv[ix][j-1] +=wv; - homv[ix][j] +=wv; - homv[ix][j+1] +=wv; - homv[ipx][j-1]+=wv; - homv[ipx][j] +=wv; - homv[ipx][j+1]+=wv; - } //} - // finalize image - int hc, vc; - for (int j=0; jISGREEN(i-1,j)) - green[i-1][j] = rawData[i-1][j]; - else { - hc = homh[imx][j]; - vc = homv[imx][j]; - if (hc > vc) - green[i-1][j] = gh[(i-1)%4][j]; - else if (hc < vc) - green[i-1][j] = gv[(i-1)%4][j]; - else - green[i-1][j] = (gh[(i-1)%4][j] + gv[(i-1)%4][j]) / 2; - } + // finalize image + int hc, vc; + + for (int j = 0; j < W; j++) { + if (ri->ISGREEN(i - 1, j)) { + green[i - 1][j] = rawData[i - 1][j]; + } else { + hc = homh[imx][j]; + vc = homv[imx][j]; + + if (hc > vc) { + green[i - 1][j] = gh[(i - 1) % 4][j]; + } else if (hc < vc) { + green[i - 1][j] = gv[(i - 1) % 4][j]; + } else { + green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; + } + } + } + + if (!(i % 20) && plistener) { + plistener->setProgress ((double)i / (H - 2)); + } } - if (!(i%20) && plistener) - plistener->setProgress ((double)i / (H-2)); - } - // finish H-2th and H-1th row, homogenity value is still valailable - int hc, vc; - for (int i=H-1; i vc) - green[i-1][j] = gh[(i-1)%4][j]; - else if (hc < vc) - green[i-1][j] = gv[(i-1)%4][j]; - else - green[i-1][j] = (gh[(i-1)%4][j] + gv[(i-1)%4][j]) / 2; - } + // finish H-2th and H-1th row, homogenity value is still valailable + int hc, vc; + + for (int i = H - 1; i < H + 1; i++) + for (int j = 0; j < W; j++) { + hc = homh[(i - 1) % 3][j]; + vc = homv[(i - 1) % 3][j]; + + if (hc > vc) { + green[i - 1][j] = gh[(i - 1) % 4][j]; + } else if (hc < vc) { + green[i - 1][j] = gv[(i - 1) % 4][j]; + } else { + green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; + } + } freeArray2(rh, 3); freeArray2(gh, 4); @@ -307,513 +327,602 @@ void RawImageSource::eahd_demosaic () { freeArray2(homv, 3); // Interpolate R and B - for (int i=0; iISGREEN(i,j)) - green[i][j] = rawData[i][j]; - else { - if (hpmap[i][j]==1) { - int g2 = rawData[i][j+1] + ((rawData[i][j] - rawData[i][j+2]) /2); - int g4 = rawData[i][j-1] + ((rawData[i][j] - rawData[i][j-2]) /2); - int dx = rawData[i][j+1] - rawData[i][j-1]; - int d1 = rawData[i][j+3] - rawData[i][j+1]; - int d2 = rawData[i][j+2] - rawData[i][j]; - int d3 = (rawData[i-1][j+2] - rawData[i-1][j]) /2; - int d4 = (rawData[i+1][j+2] - rawData[i+1][j]) /2; + for (int i = 3; i < H - 3; i++) { + for (int j = 3; j < W - 3; j++) { + if (ri->ISGREEN(i, j)) { + green[i][j] = rawData[i][j]; + } else { + if (hpmap[i][j] == 1) { + int g2 = rawData[i][j + 1] + ((rawData[i][j] - rawData[i][j + 2]) / 2); + int g4 = rawData[i][j - 1] + ((rawData[i][j] - rawData[i][j - 2]) / 2); - double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + int dx = rawData[i][j + 1] - rawData[i][j - 1]; + int d1 = rawData[i][j + 3] - rawData[i][j + 1]; + int d2 = rawData[i][j + 2] - rawData[i][j]; + int d3 = (rawData[i - 1][j + 2] - rawData[i - 1][j]) / 2; + int d4 = (rawData[i + 1][j + 2] - rawData[i + 1][j]) / 2; - d1 = rawData[i][j-3] - rawData[i][j-1]; - d2 = rawData[i][j-2] - rawData[i][j]; - d3 = (rawData[i-1][j-2] - rawData[i-1][j]) /2; - d4 = (rawData[i+1][j-2] - rawData[i+1][j]) /2; + double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + d1 = rawData[i][j - 3] - rawData[i][j - 1]; + d2 = rawData[i][j - 2] - rawData[i][j]; + d3 = (rawData[i - 1][j - 2] - rawData[i - 1][j]) / 2; + d4 = (rawData[i + 1][j - 2] - rawData[i + 1][j]) / 2; - green[i][j] = (e2 * g2 + e4 * g4) / (e2 + e4); + double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + green[i][j] = (e2 * g2 + e4 * g4) / (e2 + e4); + } else if (hpmap[i][j] == 2) { + int g1 = rawData[i - 1][j] + ((rawData[i][j] - rawData[i - 2][j]) / 2); + int g3 = rawData[i + 1][j] + ((rawData[i][j] - rawData[i + 2][j]) / 2); + + int dy = rawData[i + 1][j] - rawData[i - 1][j]; + int d1 = rawData[i - 1][j] - rawData[i - 3][j]; + int d2 = rawData[i][j] - rawData[i - 2][j]; + int d3 = (rawData[i][j - 1] - rawData[i - 2][j - 1]) / 2; + int d4 = (rawData[i][j + 1] - rawData[i - 2][j + 1]) / 2; + + double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i + 1][j] - rawData[i + 3][j]; + d2 = rawData[i][j] - rawData[i + 2][j]; + d3 = (rawData[i][j - 1] - rawData[i + 2][j - 1]) / 2; + d4 = (rawData[i][j + 1] - rawData[i + 2][j + 1]) / 2; + + double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + green[i][j] = (e1 * g1 + e3 * g3) / (e1 + e3); + } else { + int g1 = rawData[i - 1][j] + ((rawData[i][j] - rawData[i - 2][j]) / 2); + int g2 = rawData[i][j + 1] + ((rawData[i][j] - rawData[i][j + 2]) / 2); + int g3 = rawData[i + 1][j] + ((rawData[i][j] - rawData[i + 2][j]) / 2); + int g4 = rawData[i][j - 1] + ((rawData[i][j] - rawData[i][j - 2]) / 2); + + int dx = rawData[i][j + 1] - rawData[i][j - 1]; + int dy = rawData[i + 1][j] - rawData[i - 1][j]; + + int d1 = rawData[i - 1][j] - rawData[i - 3][j]; + int d2 = rawData[i][j] - rawData[i - 2][j]; + int d3 = (rawData[i][j - 1] - rawData[i - 2][j - 1]) / 2; + int d4 = (rawData[i][j + 1] - rawData[i - 2][j + 1]) / 2; + + double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i][j + 3] - rawData[i][j + 1]; + d2 = rawData[i][j + 2] - rawData[i][j]; + d3 = (rawData[i - 1][j + 2] - rawData[i - 1][j]) / 2; + d4 = (rawData[i + 1][j + 2] - rawData[i + 1][j]) / 2; + + double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i + 1][j] - rawData[i + 3][j]; + d2 = rawData[i][j] - rawData[i + 2][j]; + d3 = (rawData[i][j - 1] - rawData[i + 2][j - 1]) / 2; + d4 = (rawData[i][j + 1] - rawData[i + 2][j + 1]) / 2; + + double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i][j - 3] - rawData[i][j - 1]; + d2 = rawData[i][j - 2] - rawData[i][j]; + d3 = (rawData[i - 1][j - 2] - rawData[i - 1][j]) / 2; + d4 = (rawData[i + 1][j - 2] - rawData[i + 1][j]) / 2; + + double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + green[i][j] = (e1 * g1 + e2 * g2 + e3 * g3 + e4 * g4) / (e1 + e2 + e3 + e4); + } + } } - else if (hpmap[i][j]==2) { - int g1 = rawData[i-1][j] + ((rawData[i][j] - rawData[i-2][j]) /2); - int g3 = rawData[i+1][j] + ((rawData[i][j] - rawData[i+2][j]) /2); - - int dy = rawData[i+1][j] - rawData[i-1][j]; - int d1 = rawData[i-1][j] - rawData[i-3][j]; - int d2 = rawData[i][j] - rawData[i-2][j]; - int d3 = (rawData[i][j-1] - rawData[i-2][j-1]) /2; - int d4 = (rawData[i][j+1] - rawData[i-2][j+1]) /2; - - double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i+1][j] - rawData[i+3][j]; - d2 = rawData[i][j] - rawData[i+2][j]; - d3 = (rawData[i][j-1] - rawData[i+2][j-1]) /2; - d4 = (rawData[i][j+1] - rawData[i+2][j+1]) /2; - - double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - green[i][j] = (e1 * g1 + e3 * g3) / (e1 + e3); - } - else { - int g1 = rawData[i-1][j] + ((rawData[i][j] - rawData[i-2][j]) /2); - int g2 = rawData[i][j+1] + ((rawData[i][j] - rawData[i][j+2]) /2); - int g3 = rawData[i+1][j] + ((rawData[i][j] - rawData[i+2][j]) /2); - int g4 = rawData[i][j-1] + ((rawData[i][j] - rawData[i][j-2]) /2); - - int dx = rawData[i][j+1] - rawData[i][j-1]; - int dy = rawData[i+1][j] - rawData[i-1][j]; - - int d1 = rawData[i-1][j] - rawData[i-3][j]; - int d2 = rawData[i][j] - rawData[i-2][j]; - int d3 = (rawData[i][j-1] - rawData[i-2][j-1]) /2; - int d4 = (rawData[i][j+1] - rawData[i-2][j+1]) /2; - - double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i][j+3] - rawData[i][j+1]; - d2 = rawData[i][j+2] - rawData[i][j]; - d3 = (rawData[i-1][j+2] - rawData[i-1][j]) /2; - d4 = (rawData[i+1][j+2] - rawData[i+1][j]) /2; - - double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i+1][j] - rawData[i+3][j]; - d2 = rawData[i][j] - rawData[i+2][j]; - d3 = (rawData[i][j-1] - rawData[i+2][j-1]) /2; - d4 = (rawData[i][j+1] - rawData[i+2][j+1]) /2; - - double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i][j-3] - rawData[i][j-1]; - d2 = rawData[i][j-2] - rawData[i][j]; - d3 = (rawData[i-1][j-2] - rawData[i-1][j]) /2; - d4 = (rawData[i+1][j-2] - rawData[i+1][j]) /2; - - double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - green[i][j] = (e1*g1 + e2*g2 + e3*g3 + e4*g4) / (e1 + e2 + e3 + e4); - } - } } - } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::hphd_demosaic () { - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::hphd])); - plistener->setProgress (0.0); - } +void RawImageSource::hphd_demosaic () +{ + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::hphd])); + plistener->setProgress (0.0); + } - float** hpmap = allocArray< float >(W,H, true); + float** hpmap = allocArray< float >(W, H, true); #ifdef _OPENMP - #pragma omp parallel - { - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = W/nthreads; + #pragma omp parallel + { + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = W / nthreads; - if (tidsetProgress (0.33); - for (int i=0; isetProgress (0.33); + } + + for (int i = 0; i < H; i++) { + memset(hpmap[i], 0, W * sizeof(char)); + } #ifdef _OPENMP - #pragma omp parallel - { - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = H/nthreads; + #pragma omp parallel + { + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = H / nthreads; - if (tid(hpmap, H);//TODO: seems to cause sigabrt ??? why??? + hphd_green (hpmap); + freeArray(hpmap, H);//TODO: seems to cause sigabrt ??? why??? - if (plistener) - plistener->setProgress (0.66); + if (plistener) { + plistener->setProgress (0.66); + } - for (int i=0; isetProgress (1.0); + for (int i = 0; i < H; i++) { + if (i == 0) + // rm, gm, bm must be recovered + //interpolate_row_rb_mul_pp (red, blue, NULL, green[i], green[i+1], i, rm, gm, bm, 0, W, 1); + { + interpolate_row_rb_mul_pp (red[i], blue[i], NULL, green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } else if (i == H - 1) { + interpolate_row_rb_mul_pp (red[i], blue[i], green[i - 1], green[i], NULL, i, 1.0, 1.0, 1.0, 0, W, 1); + } else { + interpolate_row_rb_mul_pp (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } + } + + if (plistener) { + plistener->setProgress (1.0); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) typedef unsigned short ushort; -void RawImageSource::vng4_demosaic () { - const signed short int *cp, terms[] = { - -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01, - -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01, - -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03, - -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06, - -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04, - -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01, - -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40, - -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11, - -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11, - -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22, - -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44, - -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10, - -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04, - +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40, - +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20, - +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08, - +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20, - +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44, - +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60, - +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80, - +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40, - +1,+0,+2,+1,0,0x10 - }, - chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 }; +void RawImageSource::vng4_demosaic () +{ + const signed short int *cp, terms[] = { + -2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01, + -2, -1, +0, -1, 0, 0x02, -2, -1, +0, +0, 0, 0x03, -2, -1, +0, +1, 1, 0x01, + -2, +0, +0, -1, 0, 0x06, -2, +0, +0, +0, 1, 0x02, -2, +0, +0, +1, 0, 0x03, + -2, +1, -1, +0, 0, 0x04, -2, +1, +0, -1, 1, 0x04, -2, +1, +0, +0, 0, 0x06, + -2, +1, +0, +1, 0, 0x02, -2, +2, +0, +0, 1, 0x04, -2, +2, +0, +1, 0, 0x04, + -1, -2, -1, +0, 0, 0x80, -1, -2, +0, -1, 0, 0x01, -1, -2, +1, -1, 0, 0x01, + -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, 0x88, -1, -1, +1, -2, 0, 0x40, + -1, -1, +1, -1, 0, 0x22, -1, -1, +1, +0, 0, 0x33, -1, -1, +1, +1, 1, 0x11, + -1, +0, -1, +2, 0, 0x08, -1, +0, +0, -1, 0, 0x44, -1, +0, +0, +1, 0, 0x11, + -1, +0, +1, -2, 1, 0x40, -1, +0, +1, -1, 0, 0x66, -1, +0, +1, +0, 1, 0x22, + -1, +0, +1, +1, 0, 0x33, -1, +0, +1, +2, 1, 0x10, -1, +1, +1, -1, 1, 0x44, + -1, +1, +1, +0, 0, 0x66, -1, +1, +1, +1, 0, 0x22, -1, +1, +1, +2, 0, 0x10, + -1, +2, +0, +1, 0, 0x04, -1, +2, +1, +0, 1, 0x04, -1, +2, +1, +1, 0, 0x04, + +0, -2, +0, +0, 1, 0x80, +0, -1, +0, +1, 1, 0x88, +0, -1, +1, -2, 0, 0x40, + +0, -1, +1, +0, 0, 0x11, +0, -1, +2, -2, 0, 0x40, +0, -1, +2, -1, 0, 0x20, + +0, -1, +2, +0, 0, 0x30, +0, -1, +2, +1, 1, 0x10, +0, +0, +0, +2, 1, 0x08, + +0, +0, +2, -2, 1, 0x40, +0, +0, +2, -1, 0, 0x60, +0, +0, +2, +0, 1, 0x20, + +0, +0, +2, +1, 0, 0x30, +0, +0, +2, +2, 1, 0x10, +0, +1, +1, +0, 0, 0x44, + +0, +1, +1, +2, 0, 0x10, +0, +1, +2, -1, 1, 0x40, +0, +1, +2, +0, 0, 0x60, + +0, +1, +2, +1, 0, 0x20, +0, +1, +2, +2, 0, 0x10, +1, -2, +1, +0, 0, 0x80, + +1, -1, +1, +1, 0, 0x88, +1, +0, +1, +2, 0, 0x08, +1, +0, +2, -1, 0, 0x40, + +1, +0, +2, +1, 0, 0x10 + }, + chood[] = { -1, -1, -1, 0, -1, +1, 0, +1, +1, +1, +1, 0, +1, -1, 0, -1 }; - double progress = 0.0; - const bool plistenerActive = plistener; + double progress = 0.0; + const bool plistenerActive = plistener; - if (plistenerActive) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::vng4])); - plistener->setProgress (progress); - } + if (plistenerActive) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::vng4])); + plistener->setProgress (progress); + } - const unsigned prefilters = ri->prefilters; - const int width=W, height=H; - const int colors=4; - float (*image)[4]; + const unsigned prefilters = ri->prefilters; + const int width = W, height = H; + const int colors = 4; + float (*image)[4]; + + image = (float (*)[4]) calloc (height * width, sizeof * image); - image = (float (*)[4]) calloc (height*width, sizeof *image); - #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int ii=0; iisetProgress (progress); - } + for (int i = 0; i < 8; i++, ip += 2) { + sum[ip[1]] += pix[ip[0]] * mul[row & 15][col & 15][i]; + } + + for (int i = 0; i < colors - 1; i++, ip++) { + pix[ip[0]] = sum[ip[0]] / csum[row & 15][col & 15][i]; + } + } + } + } + + const int prow = 7, pcol = 1; + int *code[8][2]; + int t, g; + int * ip = (int *) calloc ((prow + 1) * (pcol + 1), 1280); + + for (int row = 0; row <= prow; row++) /* Precalculate for VNG */ + for (int col = 0; col <= pcol; col++) { + code[row][col] = ip; + + for (cp = terms, t = 0; t < 64; t++) { + int y1 = *cp++; + int x1 = *cp++; + int y2 = *cp++; + int x2 = *cp++; + int weight = *cp++; + int grads = *cp++; + int color = fc(row + y1, col + x1); + + if (fc(row + y2, col + x2) != color) { + continue; + } + + int diag = (fc(row, col + 1) == color && fc(row + 1, col) == color) ? 2 : 1; + + if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) { + continue; + } + + *ip++ = (y1 * width + x1) * 4 + color; + *ip++ = (y2 * width + x2) * 4 + color; + *ip++ = weight; + + for (g = 0; g < 8; g++) + if (grads & (1 << g)) { + *ip++ = g; + } + + *ip++ = -1; + } + + *ip++ = INT_MAX; + + for (cp = chood, g = 0; g < 8; g++) { + int y = *cp++; + int x = *cp++; + *ip++ = (y * width + x) * 4; + int color = fc(row, col); + + if (fc(row + y, col + x) != color && fc(row + y * 2, col + x * 2) == color) { + *ip++ = (y * width + x) * 8 + color; + } else { + *ip++ = 0; + } + } + } + + if(plistenerActive) { + progress = 0.1; + plistener->setProgress (progress); + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - float gval[8], thold, sum[3]; - int g; - const int progressStep = 64; - const double progressInc = (0.98-progress)/((height-2)/progressStep); + { + float gval[8], thold, sum[3]; + int g; + const int progressStep = 64; + const double progressInc = (0.98 - progress) / ((height - 2) / progressStep); #ifdef _OPENMP -#pragma omp for nowait + #pragma omp for nowait #endif - for (int row=2; row < height-2; row++) { /* Do VNG interpolation */ - for (int col=2; col < width-2; col++) { - float * pix = image[row*width+col]; - int * ip = code[row & prow][col & pcol]; - memset (gval, 0, sizeof gval); - while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ - float diff = fabsf(pix[g] - pix[ip[1]]) * (1<< ip[2]); - gval[ip[3]] += diff; - ip+=4; - while ((g = *ip++) != -1) - gval[g] += diff; - } - ip++; - { - float gmin, gmax; - gmin = gmax = gval[0]; /* Choose a threshold */ - for (g=1; g < 8; g++) { - if (gmin > gval[g]) - gmin = gval[g]; - if (gmax < gval[g]) - gmax = gval[g]; - } - thold = gmin + (gmax /2); - } - memset (sum, 0, sizeof sum); - float t1,t2; - int color = fc(row,col); - t1 = t2 = pix[color]; - if(color&1) { - int num = 0; - for (g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ - if (gval[g] <= thold) { - if(ip[1]) - sum[0] += (t1 + pix[ip[1]])*0.5f; - sum[1] += pix[ip[0] + (color ^ 2)]; - num++; - } - } - t1 += (sum[1] - sum[0]) / num; - } else { - int num = 0; - for (g=0; g < 8; g++,ip+=2) { /* Average the neighbors */ - if (gval[g] <= thold) { - sum[1] += pix[ip[0] + 1]; - sum[2] += pix[ip[0] + 3]; - if(ip[1]) - sum[0] += (t1 + pix[ip[1]])*0.5f; - num++; - } - } - t1 += (sum[1] - sum[0]) / num; - t2 += (sum[2] - sum[0]) / num; - } - green[row][col] = 0.5f * (t1 + t2); - } - if(plistenerActive) { - if((row % progressStep) == 0) -#ifdef _OPENMP -#pragma omp critical (updateprogress) -#endif -{ - progress += progressInc; - plistener->setProgress (progress); -} - } - } -} - free (code[0][0]); - free (image); - if(plistenerActive) - plistener->setProgress (0.98); + for (int row = 2; row < height - 2; row++) { /* Do VNG interpolation */ + for (int col = 2; col < width - 2; col++) { + float * pix = image[row * width + col]; + int * ip = code[row & prow][col & pcol]; + memset (gval, 0, sizeof gval); - // Interpolate R and B + while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ + float diff = fabsf(pix[g] - pix[ip[1]]) * (1 << ip[2]); + gval[ip[3]] += diff; + ip += 4; + + while ((g = *ip++) != -1) { + gval[g] += diff; + } + } + + ip++; + { + float gmin, gmax; + gmin = gmax = gval[0]; /* Choose a threshold */ + + for (g = 1; g < 8; g++) { + if (gmin > gval[g]) { + gmin = gval[g]; + } + + if (gmax < gval[g]) { + gmax = gval[g]; + } + } + + thold = gmin + (gmax / 2); + } + memset (sum, 0, sizeof sum); + float t1, t2; + int color = fc(row, col); + t1 = t2 = pix[color]; + + if(color & 1) { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + sum[1] += pix[ip[0] + (color ^ 2)]; + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + } else { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + sum[1] += pix[ip[0] + 1]; + sum[2] += pix[ip[0] + 3]; + + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + t2 += (sum[2] - sum[0]) / num; + } + + green[row][col] = 0.5f * (t1 + t2); + } + + if(plistenerActive) { + if((row % progressStep) == 0) #ifdef _OPENMP -#pragma omp parallel for + #pragma omp critical (updateprogress) #endif - for (int i=0; isetProgress (1.0); + { + progress += progressInc; + plistener->setProgress (progress); + } + } + } + + } + free (code[0][0]); + free (image); + + if(plistenerActive) { + plistener->setProgress (0.98); + } + + // Interpolate R and B +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H; i++) { + if (i == 0) + // rm, gm, bm must be recovered + //interpolate_row_rb_mul_pp (red, blue, NULL, green[i], green[i+1], i, rm, gm, bm, 0, W, 1); + { + interpolate_row_rb_mul_pp (red[i], blue[i], NULL, green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } else if (i == H - 1) { + interpolate_row_rb_mul_pp (red[i], blue[i], green[i - 1], green[i], NULL, i, 1.0, 1.0, 1.0, 0, W, 1); + } else { + interpolate_row_rb_mul_pp (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } + } + + if(plistenerActive) { + plistener->setProgress (1.0); + } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -821,7 +930,7 @@ void RawImageSource::vng4_demosaic () { #undef fc #define fc(row,col) \ - (ri->get_filters() >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) + (ri->get_filters() >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) #define FORCC for (int c=0; c < colors; c++) @@ -830,243 +939,303 @@ void RawImageSource::vng4_demosaic () { */ void RawImageSource::ppg_demosaic() { - int width=W, height=H; - int dir[5] = { 1, width, -1, -width, 1 }; - int row, col, diff[2], guess[2], c, d, i; - float (*pix)[4]; + int width = W, height = H; + int dir[5] = { 1, width, -1, -width, 1 }; + int row, col, diff[2], guess[2], c, d, i; + float (*pix)[4]; - float (*image)[4]; + float (*image)[4]; - if (plistener) { - // looks like ppg isn't supported anymore - //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::ppg])); - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); - plistener->setProgress (0.0); - } - - image = (float (*)[4]) calloc (H*W, sizeof *image); - for (int ii=0; ii 0; i++) { - guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - - pix[-2*d][c] - pix[2*d][c]; - diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + - ABS(pix[ 2*d][c] - pix[ 0][c]) + - ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + - ( ABS(pix[ 3*d][1] - pix[ d][1]) + - ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; - } - d = dir[i = diff[0] > diff[1]]; - pix[0][1] = ULIM(static_cast(guess[i] >> 2), pix[d][1], pix[-d][1]); + if (plistener) { + // looks like ppg isn't supported anymore + //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::ppg])); + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); + plistener->setProgress (0.0); } - if(plistener) plistener->setProgress(0.33*row/(height-3)); - } -/* Calculate red and blue for each green pixel: */ - for (row=1; row < height-1; row++) { - for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { - pix = image + row*width+col; - for (i=0; (d=dir[i]) > 0; c=2-c, i++) - pix[0][c] = CLIP(0.5*(pix[-d][c] + pix[d][c] + 2*pix[0][1] - - pix[-d][1] - pix[d][1]) ); - } - if(plistener) plistener->setProgress(0.33 + 0.33*row/(height-1)); - } -/* Calculate blue for red pixels and vice versa: */ - for (row=1; row < height-1; row++) { - for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { - pix = image + row*width+col; - for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) { - diff[i] = ABS(pix[-d][c] - pix[d][c]) + - ABS(pix[-d][1] - pix[0][1]) + - ABS(pix[ d][1] - pix[0][1]); - guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1] - - pix[-d][1] - pix[d][1]; - } - if (diff[0] != diff[1]) - pix[0][c] = CLIP(guess[diff[0] > diff[1]] /2); - else - pix[0][c] = CLIP((guess[0]+guess[1]) /4); - } - if(plistener) plistener->setProgress(0.67 + 0.33*row/(height-1)); - } - red(W,H); - for (int i=0; i 0; i++) { + guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 + - pix[-2 * d][c] - pix[2 * d][c]; + diff[i] = ( ABS(pix[-2 * d][c] - pix[ 0][c]) + + ABS(pix[ 2 * d][c] - pix[ 0][c]) + + ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + + ( ABS(pix[ 3 * d][1] - pix[ d][1]) + + ABS(pix[-3 * d][1] - pix[-d][1]) ) * 2; + } + + d = dir[i = diff[0] > diff[1]]; + pix[0][1] = ULIM(static_cast(guess[i] >> 2), pix[d][1], pix[-d][1]); + } + + if(plistener) { + plistener->setProgress(0.33 * row / (height - 3)); + } + } + + /* Calculate red and blue for each green pixel: */ + for (row = 1; row < height - 1; row++) { + for (col = 1 + (FC(row, 2) & 1), c = FC(row, col + 1); col < width - 1; col += 2) { + pix = image + row * width + col; + + for (i = 0; (d = dir[i]) > 0; c = 2 - c, i++) + pix[0][c] = CLIP(0.5 * (pix[-d][c] + pix[d][c] + 2 * pix[0][1] + - pix[-d][1] - pix[d][1]) ); + } + + if(plistener) { + plistener->setProgress(0.33 + 0.33 * row / (height - 1)); + } + } + + /* Calculate blue for red pixels and vice versa: */ + for (row = 1; row < height - 1; row++) { + for (col = 1 + (FC(row, 1) & 1), c = 2 - FC(row, col); col < width - 1; col += 2) { + pix = image + row * width + col; + + for (i = 0; (d = dir[i] + dir[i + 1]) > 0; i++) { + diff[i] = ABS(pix[-d][c] - pix[d][c]) + + ABS(pix[-d][1] - pix[0][1]) + + ABS(pix[ d][1] - pix[0][1]); + guess[i] = pix[-d][c] + pix[d][c] + 2 * pix[0][1] + - pix[-d][1] - pix[d][1]; + } + + if (diff[0] != diff[1]) { + pix[0][c] = CLIP(guess[diff[0] > diff[1]] / 2); + } else { + pix[0][c] = CLIP((guess[0] + guess[1]) / 4); + } + } + + if(plistener) { + plistener->setProgress(0.67 + 0.33 * row / (height - 1)); + } + } + + red(W, H); + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + red[i][j] = image[i * W + j][0]; + } + + green(W, H); + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + green[i][j] = image[i * W + j][1]; + } + + blue(W, H); + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + blue[i][j] = image[i * W + j][2]; + } + + free (image); } void RawImageSource::border_interpolate(unsigned int border, float (*image)[4], unsigned int start, unsigned int end) { - unsigned row, col, y, x, f, c, sum[8]; - unsigned int width=W, height=H; - unsigned int colors = 3; + unsigned row, col, y, x, f, c, sum[8]; + unsigned int width = W, height = H; + unsigned int colors = 3; - if (end == 0 )end = H; - for (row=start; row < end; row++) - for (col=0; col < width; col++) { - if (col==border && row >= border && row < height-border) - col = width-border; - memset (sum, 0, sizeof sum); - for (y=row-1; y != row+2; y++) - for (x=col-1; x != col+2; x++) - if (y < height && x < width) { - f = fc(y,x); - sum[f] += image[y*width+x][f]; - sum[f+4]++; - } - f = fc(row,col); - FORCC if (c != f && sum[c+4]) - image[row*width+col][c] = sum[c] / sum[c+4]; - } + if (end == 0 ) { + end = H; + } + + for (row = start; row < end; row++) + for (col = 0; col < width; col++) { + if (col == border && row >= border && row < height - border) { + col = width - border; + } + + memset (sum, 0, sizeof sum); + + for (y = row - 1; y != row + 2; y++) + for (x = col - 1; x != col + 2; x++) + if (y < height && x < width) { + f = fc(y, x); + sum[f] += image[y * width + x][f]; + sum[f + 4]++; + } + + f = fc(row, col); + + FORCC if (c != f && sum[c + 4]) { + image[row * width + col][c] = sum[c] / sum[c + 4]; + } + } } void RawImageSource::border_interpolate2( int winw, int winh, int lborders) { -int bord=lborders; -int width=winw; -int height=winh; - for (int i=0; i -1) && (i1 < height) && (j1 > -1)) { - int c = FC(i1,j1); - sum[c] += rawData[i1][j1]; - sum[c+3]++; - } - } - int c=FC(i,j); - if (c==1) { - red[i][j]=sum[0]/sum[3]; - green[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - green[i][j]=sum[1]/sum[4]; - if (c==0) { - red[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - red[i][j]=sum[0]/sum[3]; - blue[i][j]=rawData[i][j]; - } - } - }//j + for (int j = 0; j < bord; j++) { //first few columns + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } - for (int j=width-bord; j -1) && (i1 < height ) && (j1 < width)) { - int c = FC(i1,j1); - sum[c] += rawData[i1][j1]; - sum[c+3]++; - } - } - int c=FC(i,j); - if (c==1) { - red[i][j]=sum[0]/sum[3]; - green[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - green[i][j]=sum[1]/sum[4]; - if (c==0) { - red[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - red[i][j]=sum[0]/sum[3]; - blue[i][j]=rawData[i][j]; - } - } - }//j - }//i - for (int i=0; i -1) && (i1 < height) && (j1 > -1)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + + for (int j = width - bord; j < width; j++) { //last few columns + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } + + for (int i1 = i - 1; i1 < i + 2; i1++) + for (int j1 = j - 1; j1 < j + 2; j1++) { + if ((i1 > -1) && (i1 < height ) && (j1 < width)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + }//i + + for (int i = 0; i < bord; i++) { float sum[6]; - for (int j=bord; j -1) && (i1 < height) && (j1 > -1)) { - int c = FC(i1,j1); - sum[c] += rawData[i1][j1]; - sum[c+3]++; - } - } - int c=FC(i,j); - if (c==1) { - red[i][j]=sum[0]/sum[3]; - green[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - green[i][j]=sum[1]/sum[4]; - if (c==0) { - red[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - red[i][j]=sum[0]/sum[3]; - blue[i][j]=rawData[i][j]; - } - } - }//j - } + for (int j = bord; j < width - bord; j++) { //first few rows + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } - for (int i=height-bord; i -1) && (i1 < height) && (j1 > -1)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + } + + for (int i = height - bord; i < height; i++) { float sum[6]; - for (int j=bord; j -1) && (i1 < height) && (j1 < width)) { - int c = FC(i1,j1); - sum[c] += rawData[i1][j1]; - sum[c+3]++; - } - } - int c=FC(i,j); - if (c==1) { - red[i][j]=sum[0]/sum[3]; - green[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - green[i][j]=sum[1]/sum[4]; - if (c==0) { - red[i][j]=rawData[i][j]; - blue[i][j]=sum[2]/sum[5]; - } else { - red[i][j]=sum[0]/sum[3]; - blue[i][j]=rawData[i][j]; - } - } - }//j - } + for (int j = bord; j < width - bord; j++) { //last few rows + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } + + for (int i1 = i - 1; i1 < i + 2; i1++) + for (int j1 = j - 1; j1 < j + 2; j1++) { + if ((i1 > -1) && (i1 < height) && (j1 < width)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + } } @@ -1077,107 +1246,120 @@ int height=winh; void RawImageSource::jdl_interpolate_omp() // from "Lassus" { - int width=W, height=H; - int row,col,c,d,i,u=width,v=2*u,w=3*u,x=4*u,y=5*u,z=6*u,indx,(*dif)[2],(*chr)[2]; - float f[4],g[4]; - float (*image)[4]; - image = (float (*)[4]) calloc (width*height, sizeof *image); - dif = (int (*)[2]) calloc(width*height, sizeof *dif); - chr = (int (*)[2]) calloc(width*height, sizeof *chr); - if (plistener) { - // this function seems to be unused - //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::jdl])); - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); - plistener->setProgress (0.0); - } + int width = W, height = H; + int row, col, c, d, i, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, z = 6 * u, indx, (*dif)[2], (*chr)[2]; + float f[4], g[4]; + float (*image)[4]; + image = (float (*)[4]) calloc (width * height, sizeof * image); + dif = (int (*)[2]) calloc(width * height, sizeof * dif); + chr = (int (*)[2]) calloc(width * height, sizeof * chr); + + if (plistener) { + // this function seems to be unused + //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::jdl])); + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); + plistener->setProgress (0.0); + } #ifdef _OPENMP -#pragma omp parallel default(none) shared(image,width,height,u,w,v,y,x,z,dif,chr) private(row,col,f,g,indx,c,d,i) + #pragma omp parallel default(none) shared(image,width,height,u,w,v,y,x,z,dif,chr) private(row,col,f,g,indx,c,d,i) #endif -{ + { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int ii=0; ii(0.725f*dif[indx][0]+0.1375f*dif[indx-v][0]+0.1375f*dif[indx+v][0],dif[indx-v][0],dif[indx+v][0]); - g[1]=ULIM(0.725f*dif[indx][1]+0.1375f*dif[indx-2][1]+0.1375f*dif[indx+2][1],dif[indx-2][1],dif[indx+2][1]); - chr[indx][c]=(f[1]*g[0]+f[0]*g[1])/(f[0]+f[1]); - } + + for (row = 6; row < height - 6; row++) + for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col) / 2; col < u - 6; col += 2, indx += 2) { + f[0] = 1.f + 78.f * SQR((float)dif[indx][0]) + 69.f * (SQR((float) dif[indx - v][0]) + SQR((float)dif[indx + v][0])) + 51.f * (SQR((float)dif[indx - x][0]) + SQR((float)dif[indx + x][0])) + 21.f * (SQR((float)dif[indx - z][0]) + SQR((float)dif[indx + z][0])) - 6.f * SQR((float)dif[indx - v][0] + dif[indx][0] + dif[indx + v][0]) - 10.f * (SQR((float)dif[indx - x][0] + dif[indx - v][0] + dif[indx][0]) + SQR((float)dif[indx][0] + dif[indx + v][0] + dif[indx + x][0])) - 7.f * (SQR((float)dif[indx - z][0] + dif[indx - x][0] + dif[indx - v][0]) + SQR((float)dif[indx + v][0] + dif[indx + x][0] + dif[indx + z][0])); + f[1] = 1.f + 78.f * SQR((float)dif[indx][1]) + 69.f * (SQR((float)dif[indx - 2][1]) + SQR((float)dif[indx + 2][1])) + 51.f * (SQR((float)dif[indx - 4][1]) + SQR((float)dif[indx + 4][1])) + 21.f * (SQR((float)dif[indx - 6][1]) + SQR((float)dif[indx + 6][1])) - 6.f * SQR((float)dif[indx - 2][1] + dif[indx][1] + dif[indx + 2][1]) - 10.f * (SQR((float)dif[indx - 4][1] + dif[indx - 2][1] + dif[indx][1]) + SQR((float)dif[indx][1] + dif[indx + 2][1] + dif[indx + 4][1])) - 7.f * (SQR((float)dif[indx - 6][1] + dif[indx - 4][1] + dif[indx - 2][1]) + SQR((float)dif[indx + 2][1] + dif[indx + 4][1] + dif[indx + 6][1])); + g[0] = ULIM(0.725f * dif[indx][0] + 0.1375f * dif[indx - v][0] + 0.1375f * dif[indx + v][0], dif[indx - v][0], dif[indx + v][0]); + g[1] = ULIM(0.725f * dif[indx][1] + 0.1375f * dif[indx - 2][1] + 0.1375f * dif[indx + 2][1], dif[indx - 2][1], dif[indx + 2][1]); + chr[indx][c] = (f[1] * g[0] + f[0] * g[1]) / (f[0] + f[1]); + } + #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (row=6; rowsetProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::lmmse])); - plistener->setProgress (0.0); - } + bool applyGamma = true; + + if(iterations == 0) { + applyGamma = false; + iter = 0; + } else { + applyGamma = true; + } + + float *rix[5]; + float *qix[5]; + float *buffer = (float *)calloc(rr1 * cc1 * 5 * sizeof(float), 1); + + if(buffer == NULL) { // allocation of big block of memory failed, try to get 5 smaller ones + printf("lmmse_interpolate_omp: allocation of big memory block failed, try to get 5 smaller ones now...\n"); + bool allocationFailed = false; + + for(int i = 0; i < 5; i++) { + qix[i] = (float *)calloc(rr1 * cc1 * sizeof(float), 1); + + if(!qix[i]) { // allocation of at least one small block failed + allocationFailed = true; + } + } + + if(allocationFailed) { // fall back to igv_interpolate + printf("lmmse_interpolate_omp: allocation of 5 small memory blocks failed, falling back to igv_interpolate...\n"); + + for(int i = 0; i < 5; i++) { // free the already allocated buffers + if(qix[i]) { + free(qix[i]); + } + } + + igv_interpolate(winw, winh); + return; + } + } else { + qix[0] = buffer; + + for(int i = 1; i < 5; i++) { + qix[i] = qix[i - 1] + rr1 * cc1; + } + } + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::lmmse])); + plistener->setProgress (0.0); + } - LUTf *gamtab; - if(applyGamma) - gamtab = &(Color::gammatab_24_17a); - else { - gamtab = new LUTf(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); - for(int i=0;i<65536;i++) - (*gamtab)[i] = (float)i / 65535.f; - } + LUTf *gamtab; + + if(applyGamma) { + gamtab = &(Color::gammatab_24_17a); + } else { + gamtab = new LUTf(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); + + for(int i = 0; i < 65536; i++) { + (*gamtab)[i] = (float)i / 65535.f; + } + } #ifdef _OPENMP -#pragma omp parallel private(rix) + #pragma omp parallel private(rix) #endif -{ + { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int rrr=ba; rrr < rr1-ba; rrr++) { - for (int ccc=ba, row=rrr-ba; ccc < cc1-ba; ccc++) { - int col = ccc - ba; - float *rix = qix[4] + rrr*cc1 + ccc; - rix[0] = (*gamtab)[rawData[row][col]]; - } - } + + for (int rrr = ba; rrr < rr1 - ba; rrr++) { + for (int ccc = ba, row = rrr - ba; ccc < cc1 - ba; ccc++) { + int col = ccc - ba; + float *rix = qix[4] + rrr * cc1 + ccc; + rix[0] = (*gamtab)[rawData[row][col]]; + } + } #ifdef _OPENMP -#pragma omp single + #pragma omp single #endif -{ - if (plistener) plistener->setProgress (0.1); -} + { + if (plistener) { + plistener->setProgress (0.1); + } + } - // G-R(B) + // G-R(B) #ifdef _OPENMP -#pragma omp for schedule(dynamic,16) + #pragma omp for schedule(dynamic,16) #endif - for (int rr=2; rr < rr1-2; rr++) { - // G-R(B) at R(B) location - for (int cc=2+(FC(rr,2)&1); cc < cc1-2; cc+=2) { - rix[4] = qix[4] + rr*cc1 + cc; - float v0 = x00625(rix[4][-w1-1]+rix[4][-w1+1]+rix[4][w1-1]+rix[4][w1+1]) +x0250(rix[4][0]); - // horizontal - rix[0] = qix[0] + rr*cc1 + cc; - rix[0][0] = - x0250(rix[4][ -2] + rix[4][ 2])+ xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); - float Y = v0 + xdiv2f(rix[0][0]); - if (rix[4][0] > 1.75f*Y) - rix[0][0] = ULIM(rix[0][0],rix[4][ -1],rix[4][ 1]); - else - rix[0][0] = LIM(rix[0][0],0.0f,1.0f); - rix[0][0] -= rix[4][0]; - // vertical - rix[1] = qix[1] + rr*cc1 + cc; - rix[1][0] = -x0250(rix[4][-w2] + rix[4][w2])+ xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); - Y = v0 + xdiv2f(rix[1][0]); - if (rix[4][0] > 1.75f*Y) - rix[1][0] = ULIM(rix[1][0],rix[4][-w1],rix[4][w1]); - else - rix[1][0] = LIM(rix[1][0],0.0f,1.0f); - rix[1][0] -= rix[4][0]; - } - // G-R(B) at G location - for (int ccc=2+(FC(rr,3)&1); ccc < cc1-2; ccc+=2) { - rix[0] = qix[0] + rr*cc1 + ccc; - rix[1] = qix[1] + rr*cc1 + ccc; - rix[4] = qix[4] + rr*cc1 + ccc; - rix[0][0] = x0250(rix[4][ -2] + rix[4][ 2])- xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); - rix[1][0] = x0250(rix[4][-w2] + rix[4][w2])- xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); - rix[0][0] = LIM(rix[0][0],-1.0f,0.0f) + rix[4][0]; - rix[1][0] = LIM(rix[1][0],-1.0f,0.0f) + rix[4][0]; - } - } + + for (int rr = 2; rr < rr1 - 2; rr++) { + // G-R(B) at R(B) location + for (int cc = 2 + (FC(rr, 2) & 1); cc < cc1 - 2; cc += 2) { + rix[4] = qix[4] + rr * cc1 + cc; + float v0 = x00625(rix[4][-w1 - 1] + rix[4][-w1 + 1] + rix[4][w1 - 1] + rix[4][w1 + 1]) + x0250(rix[4][0]); + // horizontal + rix[0] = qix[0] + rr * cc1 + cc; + rix[0][0] = - x0250(rix[4][ -2] + rix[4][ 2]) + xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); + float Y = v0 + xdiv2f(rix[0][0]); + + if (rix[4][0] > 1.75f * Y) { + rix[0][0] = ULIM(rix[0][0], rix[4][ -1], rix[4][ 1]); + } else { + rix[0][0] = LIM(rix[0][0], 0.0f, 1.0f); + } + + rix[0][0] -= rix[4][0]; + // vertical + rix[1] = qix[1] + rr * cc1 + cc; + rix[1][0] = -x0250(rix[4][-w2] + rix[4][w2]) + xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); + Y = v0 + xdiv2f(rix[1][0]); + + if (rix[4][0] > 1.75f * Y) { + rix[1][0] = ULIM(rix[1][0], rix[4][-w1], rix[4][w1]); + } else { + rix[1][0] = LIM(rix[1][0], 0.0f, 1.0f); + } + + rix[1][0] -= rix[4][0]; + } + + // G-R(B) at G location + for (int ccc = 2 + (FC(rr, 3) & 1); ccc < cc1 - 2; ccc += 2) { + rix[0] = qix[0] + rr * cc1 + ccc; + rix[1] = qix[1] + rr * cc1 + ccc; + rix[4] = qix[4] + rr * cc1 + ccc; + rix[0][0] = x0250(rix[4][ -2] + rix[4][ 2]) - xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); + rix[1][0] = x0250(rix[4][-w2] + rix[4][w2]) - xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); + rix[0][0] = LIM(rix[0][0], -1.0f, 0.0f) + rix[4][0]; + rix[1][0] = LIM(rix[1][0], -1.0f, 0.0f) + rix[4][0]; + } + } + #ifdef _OPENMP -#pragma omp single + #pragma omp single #endif -{ - if (plistener) plistener->setProgress (0.2); -} + { + if (plistener) { + plistener->setProgress (0.2); + } + } - // apply low pass filter on differential colors + // apply low pass filter on differential colors #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int rr=4; rr < rr1-4; rr++) - for (int cc=4; cc < cc1-4; cc++) { - rix[0] = qix[0] + rr*cc1 + cc; - rix[2] = qix[2] + rr*cc1 + cc; - rix[2][0] = h0*rix[0][0] + h1*(rix[0][ -1] + rix[0][ 1]) + h2*(rix[0][ -2] + rix[0][ 2]) + h3*(rix[0][ -3] + rix[0][ 3]) + h4*(rix[0][ -4] + rix[0][ 4]); - rix[1] = qix[1] + rr*cc1 + cc; - rix[3] = qix[3] + rr*cc1 + cc; - rix[3][0] = h0*rix[1][0] + h1*(rix[1][-w1] + rix[1][w1]) + h2*(rix[1][-w2] + rix[1][w2]) + h3*(rix[1][-w3] + rix[1][w3]) + h4*(rix[1][-w4] + rix[1][w4]); - } -#ifdef _OPENMP -#pragma omp single -#endif -{ - if (plistener) plistener->setProgress (0.3); -} - // interpolate G-R(B) at R(B) + for (int rr = 4; rr < rr1 - 4; rr++) + for (int cc = 4; cc < cc1 - 4; cc++) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[2][0] = h0 * rix[0][0] + h1 * (rix[0][ -1] + rix[0][ 1]) + h2 * (rix[0][ -2] + rix[0][ 2]) + h3 * (rix[0][ -3] + rix[0][ 3]) + h4 * (rix[0][ -4] + rix[0][ 4]); + rix[1] = qix[1] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[3][0] = h0 * rix[1][0] + h1 * (rix[1][-w1] + rix[1][w1]) + h2 * (rix[1][-w2] + rix[1][w2]) + h3 * (rix[1][-w3] + rix[1][w3]) + h4 * (rix[1][-w4] + rix[1][w4]); + } + #ifdef _OPENMP -#pragma omp for + #pragma omp single #endif - for (int rr=4; rr < rr1-4; rr++) { - int cc=4+(FC(rr,4)&1); + { + if (plistener) { + plistener->setProgress (0.3); + } + } + + // interpolate G-R(B) at R(B) +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 4) & 1); #ifdef __SSE2__ - __m128 p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, muv, vxv, vnv, xhv, vhv, xvv, vvv; - __m128 epsv = _mm_set1_ps(1e-7); - __m128 ninev = _mm_set1_ps(9.f); - for (; cc < cc1-10; cc+=8) { - rix[0] = qix[0] + rr*cc1 + cc; - rix[1] = qix[1] + rr*cc1 + cc; - rix[2] = qix[2] + rr*cc1 + cc; - rix[3] = qix[3] + rr*cc1 + cc; - rix[4] = qix[4] + rr*cc1 + cc; - // horizontal - p1v = LC2VFU(rix[2][-4]); - p2v = LC2VFU(rix[2][-3]); - p3v = LC2VFU(rix[2][-2]); - p4v = LC2VFU(rix[2][-1]); - p5v = LC2VFU(rix[2][ 0]); - p6v = LC2VFU(rix[2][ 1]); - p7v = LC2VFU(rix[2][ 2]); - p8v = LC2VFU(rix[2][ 3]); - p9v = LC2VFU(rix[2][ 4]); - muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; - vxv = epsv+SQRV(p1v-muv)+SQRV(p2v-muv)+SQRV(p3v-muv)+SQRV(p4v-muv)+SQRV(p5v-muv)+SQRV(p6v-muv)+SQRV(p7v-muv)+SQRV(p8v-muv)+SQRV(p9v-muv); - p1v -= LC2VFU(rix[0][-4]); - p2v -= LC2VFU(rix[0][-3]); - p3v -= LC2VFU(rix[0][-2]); - p4v -= LC2VFU(rix[0][-1]); - p5v -= LC2VFU(rix[0][ 0]); - p6v -= LC2VFU(rix[0][ 1]); - p7v -= LC2VFU(rix[0][ 2]); - p8v -= LC2VFU(rix[0][ 3]); - p9v -= LC2VFU(rix[0][ 4]); - vnv = epsv+SQRV(p1v)+SQRV(p2v)+SQRV(p3v)+SQRV(p4v)+SQRV(p5v)+SQRV(p6v)+SQRV(p7v)+SQRV(p8v)+SQRV(p9v); - xhv = (LC2VFU(rix[0][0])*vxv + LC2VFU(rix[2][0])*vnv)/(vxv + vnv); - vhv = vxv*vnv/(vxv + vnv); + __m128 p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, muv, vxv, vnv, xhv, vhv, xvv, vvv; + __m128 epsv = _mm_set1_ps(1e-7); + __m128 ninev = _mm_set1_ps(9.f); + + for (; cc < cc1 - 10; cc += 8) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + // horizontal + p1v = LC2VFU(rix[2][-4]); + p2v = LC2VFU(rix[2][-3]); + p3v = LC2VFU(rix[2][-2]); + p4v = LC2VFU(rix[2][-1]); + p5v = LC2VFU(rix[2][ 0]); + p6v = LC2VFU(rix[2][ 1]); + p7v = LC2VFU(rix[2][ 2]); + p8v = LC2VFU(rix[2][ 3]); + p9v = LC2VFU(rix[2][ 4]); + muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; + vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); + p1v -= LC2VFU(rix[0][-4]); + p2v -= LC2VFU(rix[0][-3]); + p3v -= LC2VFU(rix[0][-2]); + p4v -= LC2VFU(rix[0][-1]); + p5v -= LC2VFU(rix[0][ 0]); + p6v -= LC2VFU(rix[0][ 1]); + p7v -= LC2VFU(rix[0][ 2]); + p8v -= LC2VFU(rix[0][ 3]); + p9v -= LC2VFU(rix[0][ 4]); + vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); + xhv = (LC2VFU(rix[0][0]) * vxv + LC2VFU(rix[2][0]) * vnv) / (vxv + vnv); + vhv = vxv * vnv / (vxv + vnv); + + // vertical + p1v = LC2VFU(rix[3][-w4]); + p2v = LC2VFU(rix[3][-w3]); + p3v = LC2VFU(rix[3][-w2]); + p4v = LC2VFU(rix[3][-w1]); + p5v = LC2VFU(rix[3][ 0]); + p6v = LC2VFU(rix[3][ w1]); + p7v = LC2VFU(rix[3][ w2]); + p8v = LC2VFU(rix[3][ w3]); + p9v = LC2VFU(rix[3][ w4]); + muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; + vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); + p1v -= LC2VFU(rix[1][-w4]); + p2v -= LC2VFU(rix[1][-w3]); + p3v -= LC2VFU(rix[1][-w2]); + p4v -= LC2VFU(rix[1][-w1]); + p5v -= LC2VFU(rix[1][ 0]); + p6v -= LC2VFU(rix[1][ w1]); + p7v -= LC2VFU(rix[1][ w2]); + p8v -= LC2VFU(rix[1][ w3]); + p9v -= LC2VFU(rix[1][ w4]); + vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); + xvv = (LC2VFU(rix[1][0]) * vxv + LC2VFU(rix[3][0]) * vnv) / (vxv + vnv); + vvv = vxv * vnv / (vxv + vnv); + // interpolated G-R(B) + muv = (xhv * vvv + xvv * vhv) / (vhv + vvv); + STC2VFU(rix[4][0], muv); + } - // vertical - p1v = LC2VFU(rix[3][-w4]); - p2v = LC2VFU(rix[3][-w3]); - p3v = LC2VFU(rix[3][-w2]); - p4v = LC2VFU(rix[3][-w1]); - p5v = LC2VFU(rix[3][ 0]); - p6v = LC2VFU(rix[3][ w1]); - p7v = LC2VFU(rix[3][ w2]); - p8v = LC2VFU(rix[3][ w3]); - p9v = LC2VFU(rix[3][ w4]); - muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; - vxv = epsv+SQRV(p1v-muv)+SQRV(p2v-muv)+SQRV(p3v-muv)+SQRV(p4v-muv)+SQRV(p5v-muv)+SQRV(p6v-muv)+SQRV(p7v-muv)+SQRV(p8v-muv)+SQRV(p9v-muv); - p1v -= LC2VFU(rix[1][-w4]); - p2v -= LC2VFU(rix[1][-w3]); - p3v -= LC2VFU(rix[1][-w2]); - p4v -= LC2VFU(rix[1][-w1]); - p5v -= LC2VFU(rix[1][ 0]); - p6v -= LC2VFU(rix[1][ w1]); - p7v -= LC2VFU(rix[1][ w2]); - p8v -= LC2VFU(rix[1][ w3]); - p9v -= LC2VFU(rix[1][ w4]); - vnv = epsv+SQRV(p1v)+SQRV(p2v)+SQRV(p3v)+SQRV(p4v)+SQRV(p5v)+SQRV(p6v)+SQRV(p7v)+SQRV(p8v)+SQRV(p9v); - xvv = (LC2VFU(rix[1][0])*vxv + LC2VFU(rix[3][0])*vnv)/(vxv + vnv); - vvv = vxv*vnv/(vxv + vnv); - // interpolated G-R(B) - muv = (xhv*vvv + xvv*vhv)/(vhv + vvv); - STC2VFU(rix[4][0], muv); - } #endif - for (; cc < cc1-4; cc+=2) { - rix[0] = qix[0] + rr*cc1 + cc; - rix[1] = qix[1] + rr*cc1 + cc; - rix[2] = qix[2] + rr*cc1 + cc; - rix[3] = qix[3] + rr*cc1 + cc; - rix[4] = qix[4] + rr*cc1 + cc; - // horizontal - float p1 = rix[2][-4]; - float p2 = rix[2][-3]; - float p3 = rix[2][-2]; - float p4 = rix[2][-1]; - float p5 = rix[2][ 0]; - float p6 = rix[2][ 1]; - float p7 = rix[2][ 2]; - float p8 = rix[2][ 3]; - float p9 = rix[2][ 4]; - float mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; - float vx = 1e-7+SQR(p1-mu)+SQR(p2-mu)+SQR(p3-mu)+SQR(p4-mu)+SQR(p5-mu)+SQR(p6-mu)+SQR(p7-mu)+SQR(p8-mu)+SQR(p9-mu); - p1 -= rix[0][-4]; - p2 -= rix[0][-3]; - p3 -= rix[0][-2]; - p4 -= rix[0][-1]; - p5 -= rix[0][ 0]; - p6 -= rix[0][ 1]; - p7 -= rix[0][ 2]; - p8 -= rix[0][ 3]; - p9 -= rix[0][ 4]; - float vn = 1e-7+SQR(p1)+SQR(p2)+SQR(p3)+SQR(p4)+SQR(p5)+SQR(p6)+SQR(p7)+SQR(p8)+SQR(p9); - float xh = (rix[0][0]*vx + rix[2][0]*vn)/(vx + vn); - float vh = vx*vn/(vx + vn); - // vertical - p1 = rix[3][-w4]; - p2 = rix[3][-w3]; - p3 = rix[3][-w2]; - p4 = rix[3][-w1]; - p5 = rix[3][ 0]; - p6 = rix[3][ w1]; - p7 = rix[3][ w2]; - p8 = rix[3][ w3]; - p9 = rix[3][ w4]; - mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; - vx = 1e-7+SQR(p1-mu)+SQR(p2-mu)+SQR(p3-mu)+SQR(p4-mu)+SQR(p5-mu)+SQR(p6-mu)+SQR(p7-mu)+SQR(p8-mu)+SQR(p9-mu); - p1 -= rix[1][-w4]; - p2 -= rix[1][-w3]; - p3 -= rix[1][-w2]; - p4 -= rix[1][-w1]; - p5 -= rix[1][ 0]; - p6 -= rix[1][ w1]; - p7 -= rix[1][ w2]; - p8 -= rix[1][ w3]; - p9 -= rix[1][ w4]; - vn = 1e-7+SQR(p1)+SQR(p2)+SQR(p3)+SQR(p4)+SQR(p5)+SQR(p6)+SQR(p7)+SQR(p8)+SQR(p9); - float xv = (rix[1][0]*vx + rix[3][0]*vn)/(vx + vn); - float vv = vx*vn/(vx + vn); - // interpolated G-R(B) - rix[4][0] = (xh*vv + xv*vh)/(vh + vv); - } - } + for (; cc < cc1 - 4; cc += 2) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + // horizontal + float p1 = rix[2][-4]; + float p2 = rix[2][-3]; + float p3 = rix[2][-2]; + float p4 = rix[2][-1]; + float p5 = rix[2][ 0]; + float p6 = rix[2][ 1]; + float p7 = rix[2][ 2]; + float p8 = rix[2][ 3]; + float p9 = rix[2][ 4]; + float mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; + float vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); + p1 -= rix[0][-4]; + p2 -= rix[0][-3]; + p3 -= rix[0][-2]; + p4 -= rix[0][-1]; + p5 -= rix[0][ 0]; + p6 -= rix[0][ 1]; + p7 -= rix[0][ 2]; + p8 -= rix[0][ 3]; + p9 -= rix[0][ 4]; + float vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); + float xh = (rix[0][0] * vx + rix[2][0] * vn) / (vx + vn); + float vh = vx * vn / (vx + vn); + + // vertical + p1 = rix[3][-w4]; + p2 = rix[3][-w3]; + p3 = rix[3][-w2]; + p4 = rix[3][-w1]; + p5 = rix[3][ 0]; + p6 = rix[3][ w1]; + p7 = rix[3][ w2]; + p8 = rix[3][ w3]; + p9 = rix[3][ w4]; + mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; + vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); + p1 -= rix[1][-w4]; + p2 -= rix[1][-w3]; + p3 -= rix[1][-w2]; + p4 -= rix[1][-w1]; + p5 -= rix[1][ 0]; + p6 -= rix[1][ w1]; + p7 -= rix[1][ w2]; + p8 -= rix[1][ w3]; + p9 -= rix[1][ w4]; + vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); + float xv = (rix[1][0] * vx + rix[3][0] * vn) / (vx + vn); + float vv = vx * vn / (vx + vn); + // interpolated G-R(B) + rix[4][0] = (xh * vv + xv * vh) / (vh + vv); + } + } #ifdef _OPENMP -#pragma omp single + #pragma omp single #endif -{ - if (plistener) plistener->setProgress (0.4); -} + { + if (plistener) { + plistener->setProgress (0.4); + } + } - // copy CFA values + // copy CFA values #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int rr=0; rr < rr1; rr++) - for (int cc=0, row=rr-ba; cc < cc1; cc++) { - int col=cc-ba; - int c = FC(rr,cc); - rix[c] = qix[c] + rr*cc1 + cc; - if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { - rix[c][0] = (*gamtab)[rawData[row][col]]; - } - else - rix[c][0] = 0.f; - if (c != 1) { - rix[1] = qix[1] + rr*cc1 + cc; - rix[4] = qix[4] + rr*cc1 + cc; - rix[1][0] = rix[c][0] + rix[4][0]; - } - } + + for (int rr = 0; rr < rr1; rr++) + for (int cc = 0, row = rr - ba; cc < cc1; cc++) { + int col = cc - ba; + int c = FC(rr, cc); + rix[c] = qix[c] + rr * cc1 + cc; + + if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { + rix[c][0] = (*gamtab)[rawData[row][col]]; + } else { + rix[c][0] = 0.f; + } + + if (c != 1) { + rix[1] = qix[1] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + rix[1][0] = rix[c][0] + rix[4][0]; + } + } #ifdef _OPENMP -#pragma omp single + #pragma omp single #endif -{ - if (plistener) plistener->setProgress (0.5); -} + { + if (plistener) { + plistener->setProgress (0.5); + } + } - // bilinear interpolation for R/B - // interpolate R/B at G location + // bilinear interpolation for R/B + // interpolate R/B at G location #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int rr=1; rr < rr1-1; rr++) - for (int cc=1+(FC(rr,2)&1), c=FC(rr,cc+1); cc < cc1-1; cc+=2) { - rix[c] = qix[c] + rr*cc1 + cc; - rix[1] = qix[1] + rr*cc1 + cc; - rix[c][0] = rix[1][0] + xdiv2f(rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1]); - c = 2 - c; - rix[c] = qix[c] + rr*cc1 + cc; - rix[c][0] = rix[1][0]+ xdiv2f(rix[c][-w1] - rix[1][-w1] + rix[c][w1] - rix[1][w1]); - c = 2 - c; - } + + for (int rr = 1; rr < rr1 - 1; rr++) + for (int cc = 1 + (FC(rr, 2) & 1), c = FC(rr, cc + 1); cc < cc1 - 1; cc += 2) { + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + xdiv2f(rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1]); + c = 2 - c; + rix[c] = qix[c] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + xdiv2f(rix[c][-w1] - rix[1][-w1] + rix[c][w1] - rix[1][w1]); + c = 2 - c; + } #ifdef _OPENMP -#pragma omp single + #pragma omp single #endif -{ - if (plistener) plistener->setProgress (0.6); -} + { + if (plistener) { + plistener->setProgress (0.6); + } + } - // interpolate R/B at B/R location + // interpolate R/B at B/R location #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int rr=1; rr < rr1-1; rr++) - for (int cc=1+(FC(rr,1)&1), c=2-FC(rr,cc); cc < cc1-1; cc+=2) { - rix[c] = qix[c] + rr*cc1 + cc; - rix[1] = qix[1] + rr*cc1 + cc; - rix[c][0] = rix[1][0]+ x0250(rix[c][-w1] - rix[1][-w1] + rix[c][ -1] - rix[1][ -1]+ rix[c][ 1] - rix[1][ 1] + rix[c][ w1] - rix[1][ w1]); - } + + for (int rr = 1; rr < rr1 - 1; rr++) + for (int cc = 1 + (FC(rr, 1) & 1), c = 2 - FC(rr, cc); cc < cc1 - 1; cc += 2) { + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + x0250(rix[c][-w1] - rix[1][-w1] + rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1] + rix[c][ w1] - rix[1][ w1]); + } #ifdef _OPENMP -#pragma omp single + #pragma omp single #endif -{ - if (plistener) plistener->setProgress (0.7); -} + { + if (plistener) { + plistener->setProgress (0.7); + } + } -}// End of parallelization 1 + }// End of parallelization 1 - // median filter/ - for (int pass=0; pass < iter; pass++) { - // Apply 3x3 median filter - // Compute median(R-G) and median(B-G) + // median filter/ + for (int pass = 0; pass < iter; pass++) { + // Apply 3x3 median filter + // Compute median(R-G) and median(B-G) #ifdef _OPENMP -#pragma omp parallel for private(rix) + #pragma omp parallel for private(rix) #endif - for (int rr=1; rr < rr1-1; rr++) { - for (int c=0; c < 3; c+=2) { - int d = c + 3 - (c == 0 ? 0 : 1); - int cc=1; + + for (int rr = 1; rr < rr1 - 1; rr++) { + for (int c = 0; c < 3; c += 2) { + int d = c + 3 - (c == 0 ? 0 : 1); + int cc = 1; #ifdef __SSE2__ - __m128 p1v,p2v,p3v,p4v,p5v,p6v,p7v,p8v,p9v,tempv; - for (; cc < cc1-4; cc+=4) { - rix[d] = qix[d] + rr*cc1 + cc; - rix[c] = qix[c] + rr*cc1 + cc; - rix[1] = qix[1] + rr*cc1 + cc; - // Assign 3x3 differential color values - p1v = LVFU(rix[c][-w1-1])-LVFU(rix[1][-w1-1]); p2v = LVFU(rix[c][-w1])-LVFU(rix[1][-w1]); p3v = LVFU(rix[c][-w1+1])-LVFU(rix[1][-w1+1]); - p4v = LVFU(rix[c][ -1])-LVFU(rix[1][ -1]); p5v = LVFU(rix[c][ 0])-LVFU(rix[1][ 0]); p6v = LVFU(rix[c][ 1])-LVFU(rix[1][ 1]); - p7v = LVFU(rix[c][ w1-1])-LVFU(rix[1][ w1-1]); p8v = LVFU(rix[c][ w1])-LVFU(rix[1][ w1]); p9v = LVFU(rix[c][ w1+1])-LVFU(rix[1][ w1+1]); - // Sort for median of 9 values - PIX_SORTV(p2v,p3v); PIX_SORTV(p5v,p6v); PIX_SORTV(p8v,p9v); - PIX_SORTV(p1v,p2v); PIX_SORTV(p4v,p5v); PIX_SORTV(p7v,p8v); - PIX_SORTV(p2v,p3v); PIX_SORTV(p5v,p6v); PIX_SORTV(p8v,p9v); - p4v = _mm_max_ps(p1v,p4v); p6v = _mm_min_ps(p6v,p9v); PIX_SORTV(p5v,p8v); - p7v = _mm_max_ps(p4v,p7v); p5v = _mm_max_ps(p5v,p2v); p3v = _mm_min_ps(p3v,p6v); - p5v = _mm_min_ps(p5v,p8v); PIX_SORTV(p5v,p3v); p5v = _mm_max_ps(p7v,p5v); - p5v = _mm_min_ps(p3v,p5v); - _mm_storeu_ps(&rix[d][0], p5v); - } -#endif - for (; cc < cc1-1; cc++) { - float temp; - rix[d] = qix[d] + rr*cc1 + cc; - rix[c] = qix[c] + rr*cc1 + cc; - rix[1] = qix[1] + rr*cc1 + cc; - // Assign 3x3 differential color values - float p1 = rix[c][-w1-1]-rix[1][-w1-1]; float p2 = rix[c][-w1]-rix[1][-w1]; float p3 = rix[c][-w1+1]-rix[1][-w1+1]; - float p4 = rix[c][ -1]-rix[1][ -1]; float p5 = rix[c][ 0]-rix[1][ 0]; float p6 = rix[c][ 1]-rix[1][ 1]; - float p7 = rix[c][ w1-1]-rix[1][ w1-1]; float p8 = rix[c][ w1]-rix[1][ w1]; float p9 = rix[c][ w1+1]-rix[1][ w1+1]; - // Sort for median of 9 values - PIX_SORT(p2,p3); PIX_SORT(p5,p6); PIX_SORT(p8,p9); - PIX_SORT(p1,p2); PIX_SORT(p4,p5); PIX_SORT(p7,p8); - PIX_SORT(p2,p3); PIX_SORT(p5,p6); PIX_SORT(p8,p9); - PIX_SORT(p1,p4); PIX_SORT(p6,p9); PIX_SORT(p5,p8); - PIX_SORT(p4,p7); PIX_SORT(p2,p5); PIX_SORT(p3,p6); - PIX_SORT(p5,p8); PIX_SORT(p5,p3); PIX_SORT(p7,p5); - PIX_SORT(p5,p3); - rix[d][0] = p5; - } - } - } + __m128 p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, tempv; - // red/blue at GREEN pixel locations & red/blue and green at BLUE/RED pixel locations + for (; cc < cc1 - 4; cc += 4) { + rix[d] = qix[d] + rr * cc1 + cc; + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + // Assign 3x3 differential color values + p1v = LVFU(rix[c][-w1 - 1]) - LVFU(rix[1][-w1 - 1]); + p2v = LVFU(rix[c][-w1]) - LVFU(rix[1][-w1]); + p3v = LVFU(rix[c][-w1 + 1]) - LVFU(rix[1][-w1 + 1]); + p4v = LVFU(rix[c][ -1]) - LVFU(rix[1][ -1]); + p5v = LVFU(rix[c][ 0]) - LVFU(rix[1][ 0]); + p6v = LVFU(rix[c][ 1]) - LVFU(rix[1][ 1]); + p7v = LVFU(rix[c][ w1 - 1]) - LVFU(rix[1][ w1 - 1]); + p8v = LVFU(rix[c][ w1]) - LVFU(rix[1][ w1]); + p9v = LVFU(rix[c][ w1 + 1]) - LVFU(rix[1][ w1 + 1]); + // Sort for median of 9 values + PIX_SORTV(p2v, p3v); + PIX_SORTV(p5v, p6v); + PIX_SORTV(p8v, p9v); + PIX_SORTV(p1v, p2v); + PIX_SORTV(p4v, p5v); + PIX_SORTV(p7v, p8v); + PIX_SORTV(p2v, p3v); + PIX_SORTV(p5v, p6v); + PIX_SORTV(p8v, p9v); + p4v = _mm_max_ps(p1v, p4v); + p6v = _mm_min_ps(p6v, p9v); + PIX_SORTV(p5v, p8v); + p7v = _mm_max_ps(p4v, p7v); + p5v = _mm_max_ps(p5v, p2v); + p3v = _mm_min_ps(p3v, p6v); + p5v = _mm_min_ps(p5v, p8v); + PIX_SORTV(p5v, p3v); + p5v = _mm_max_ps(p7v, p5v); + p5v = _mm_min_ps(p3v, p5v); + _mm_storeu_ps(&rix[d][0], p5v); + } + +#endif + + for (; cc < cc1 - 1; cc++) { + float temp; + rix[d] = qix[d] + rr * cc1 + cc; + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + // Assign 3x3 differential color values + float p1 = rix[c][-w1 - 1] - rix[1][-w1 - 1]; + float p2 = rix[c][-w1] - rix[1][-w1]; + float p3 = rix[c][-w1 + 1] - rix[1][-w1 + 1]; + float p4 = rix[c][ -1] - rix[1][ -1]; + float p5 = rix[c][ 0] - rix[1][ 0]; + float p6 = rix[c][ 1] - rix[1][ 1]; + float p7 = rix[c][ w1 - 1] - rix[1][ w1 - 1]; + float p8 = rix[c][ w1] - rix[1][ w1]; + float p9 = rix[c][ w1 + 1] - rix[1][ w1 + 1]; + // Sort for median of 9 values + PIX_SORT(p2, p3); + PIX_SORT(p5, p6); + PIX_SORT(p8, p9); + PIX_SORT(p1, p2); + PIX_SORT(p4, p5); + PIX_SORT(p7, p8); + PIX_SORT(p2, p3); + PIX_SORT(p5, p6); + PIX_SORT(p8, p9); + PIX_SORT(p1, p4); + PIX_SORT(p6, p9); + PIX_SORT(p5, p8); + PIX_SORT(p4, p7); + PIX_SORT(p2, p5); + PIX_SORT(p3, p6); + PIX_SORT(p5, p8); + PIX_SORT(p5, p3); + PIX_SORT(p7, p5); + PIX_SORT(p5, p3); + rix[d][0] = p5; + } + } + } + + // red/blue at GREEN pixel locations & red/blue and green at BLUE/RED pixel locations #ifdef _OPENMP -#pragma omp parallel for private (rix) + #pragma omp parallel for private (rix) #endif - for (int rr=0; rr < rr1; rr++) { - rix[0] = qix[0] + rr*cc1; - rix[1] = qix[1] + rr*cc1; - rix[2] = qix[2] + rr*cc1; - rix[3] = qix[3] + rr*cc1; - rix[4] = qix[4] + rr*cc1; - int c0 = FC(rr,0); - int c1 = FC(rr,1); - if(c0 == 1){ - c1 = 2 - c1; - int d = c1 + 3 - (c1 == 0 ? 0 : 1); - int cc; - for (cc=0; cc < cc1-1; cc+=2) { - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - rix[0]++; rix[1]++; rix[2]++; rix[3]++; rix[4]++; - rix[c1][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - rix[0]++; rix[1]++; rix[2]++; rix[3]++; rix[4]++; - } - if(cc < cc1) { // remaining pixel, only if width is odd - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - } - } else { - c0 = 2 - c0; - int d = c0 + 3 - (c0 == 0 ? 0 : 1); - int cc; - for (cc=0; cc < cc1-1; cc+=2) { - rix[c0][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - rix[0]++; rix[1]++; rix[2]++; rix[3]++; rix[4]++; - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - rix[0]++; rix[1]++; rix[2]++; rix[3]++; rix[4]++; - } - if(cc < cc1) { // remaining pixel, only if width is odd - rix[c0][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - } - } - } - } - if (plistener) plistener->setProgress (0.8); + for (int rr = 0; rr < rr1; rr++) { + rix[0] = qix[0] + rr * cc1; + rix[1] = qix[1] + rr * cc1; + rix[2] = qix[2] + rr * cc1; + rix[3] = qix[3] + rr * cc1; + rix[4] = qix[4] + rr * cc1; + int c0 = FC(rr, 0); + int c1 = FC(rr, 1); - if(applyGamma) - gamtab = &(Color::igammatab_24_17); - else { - for(int i=0;i<65536;i++) - (*gamtab)[i] = (float)i + 0.5f; - } + if(c0 == 1) { + c1 = 2 - c1; + int d = c1 + 3 - (c1 == 0 ? 0 : 1); + int cc; - array2D (*rgb[3]); - rgb[0] = &red; - rgb[1] = &green; - rgb[2] = &blue; + for (cc = 0; cc < cc1 - 1; cc += 2) { + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + rix[c1][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + } - // copy result back to image matrix + if(cc < cc1) { // remaining pixel, only if width is odd + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + } + } else { + c0 = 2 - c0; + int d = c0 + 3 - (c0 == 0 ? 0 : 1); + int cc; + + for (cc = 0; cc < cc1 - 1; cc += 2) { + rix[c0][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + } + + if(cc < cc1) { // remaining pixel, only if width is odd + rix[c0][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + } + } + } + } + + if (plistener) { + plistener->setProgress (0.8); + } + + if(applyGamma) { + gamtab = &(Color::igammatab_24_17); + } else { + for(int i = 0; i < 65536; i++) { + (*gamtab)[i] = (float)i + 0.5f; + } + } + + array2D (*rgb[3]); + rgb[0] = &red; + rgb[1] = &green; + rgb[2] = &blue; + + // copy result back to image matrix #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row=0; row < height; row++) { - for (int col=0, rr=row+ba; col < width; col++) { - int cc = col+ba; - int c = FC(row,col); - for (int ii=0; ii < 3; ii++) - if (ii != c) { - float *rix = qix[ii] + rr*cc1 + cc; - (*(rgb[ii]))[row][col] = (*gamtab)[65535.f*rix[0]]; - } else { - (*(rgb[ii]))[row][col] = CLIP(rawData[row][col]); - } - } - } - if (plistener) plistener->setProgress (1.0); - if(buffer) - free(buffer); - else - for(int i=0;i<5;i++) - free(qix[i]); + for (int row = 0; row < height; row++) { + for (int col = 0, rr = row + ba; col < width; col++) { + int cc = col + ba; + int c = FC(row, col); - if(!applyGamma) - delete gamtab; + for (int ii = 0; ii < 3; ii++) + if (ii != c) { + float *rix = qix[ii] + rr * cc1 + cc; + (*(rgb[ii]))[row][col] = (*gamtab)[65535.f * rix[0]]; + } else { + (*(rgb[ii]))[row][col] = CLIP(rawData[row][col]); + } + } + } - if(iterations > 4 && iterations <=6) refinement(passref); - else if(iterations > 6) refinement_lassus(passref); + if (plistener) { + plistener->setProgress (1.0); + } + + if(buffer) { + free(buffer); + } else + for(int i = 0; i < 5; i++) { + free(qix[i]); + } + + if(!applyGamma) { + delete gamtab; + } + + if(iterations > 4 && iterations <= 6) { + refinement(passref); + } else if(iterations > 6) { + refinement_lassus(passref); + } } @@ -1739,581 +2047,657 @@ SSEFUNCTION void RawImageSource::lmmse_interpolate_omp(int winw, int winh, int i #define CLIPV(a) LIMV(a,zerov,c65535v) SSEFUNCTION void RawImageSource::igv_interpolate(int winw, int winh) { - static const float eps=1e-5f, epssq=1e-5f;//mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) + static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) - static const int h1=1, h2=2, h3=3, h5=5; - const int width=winw, height=winh; - const int v1=1*width, v2=2*width, v3=3*width, v5=5*width; - float* rgb[2]; - float* chr[4]; - float *rgbarray, *vdif, *hdif, *chrarray; - rgbarray = (float (*)) malloc((width*height) * sizeof( float ) ); - rgb[0] = rgbarray; - rgb[1] = rgbarray + (width*height)/2; + static const int h1 = 1, h2 = 2, h3 = 3, h5 = 5; + const int width = winw, height = winh; + const int v1 = 1 * width, v2 = 2 * width, v3 = 3 * width, v5 = 5 * width; + float* rgb[2]; + float* chr[4]; + float *rgbarray, *vdif, *hdif, *chrarray; + rgbarray = (float (*)) malloc((width * height) * sizeof( float ) ); + rgb[0] = rgbarray; + rgb[1] = rgbarray + (width * height) / 2; - vdif = (float (*)) calloc( width*height/2, sizeof *vdif ); - hdif = (float (*)) calloc( width*height/2, sizeof *hdif ); + vdif = (float (*)) calloc( width * height / 2, sizeof * vdif ); + hdif = (float (*)) calloc( width * height / 2, sizeof * hdif ); - chrarray = (float (*)) calloc( width*height, sizeof( float ) ); - chr[0] = chrarray; - chr[1] = chrarray + (width*height)/2; + chrarray = (float (*)) calloc( width * height, sizeof( float ) ); + chr[0] = chrarray; + chr[1] = chrarray + (width * height) / 2; - // mapped chr[2] and chr[3] to hdif and hdif, because these are out of use, when chr[2] and chr[3] are used - chr[2] = hdif; - chr[3] = vdif; + // mapped chr[2] and chr[3] to hdif and hdif, because these are out of use, when chr[2] and chr[3] are used + chr[2] = hdif; + chr[3] = vdif; - border_interpolate2(winw,winh,7); + border_interpolate2(winw, winh, 7); - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv])); - plistener->setProgress (0.0); - } -#ifdef _OPENMP -#pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) -#endif -{ - __m128 ngv, egv, wgv, sgv, nvv, evv, wvv, svv, nwgv, negv, swgv, segv, nwvv, nevv, swvv, sevv,tempv,temp1v,temp2v,temp3v,temp4v,temp5v,temp6v,temp7v,temp8v; - __m128 epsv = _mm_set1_ps( eps ); - __m128 epssqv = _mm_set1_ps( epssq ); - __m128 c65535v = _mm_set1_ps( 65535.f ); - __m128 c23v = _mm_set1_ps( 23.f ); - __m128 c40v = _mm_set1_ps( 40.f ); - __m128 c51v = _mm_set1_ps( 51.f ); - __m128 c32v = _mm_set1_ps( 32.f ); - __m128 c8v = _mm_set1_ps( 8.f ); - __m128 c7v = _mm_set1_ps( 7.f ); - __m128 c6v = _mm_set1_ps( 6.f ); - __m128 c10v = _mm_set1_ps( 10.f ); - __m128 c21v = _mm_set1_ps( 21.f ); - __m128 c78v = _mm_set1_ps( 78.f ); - __m128 c69v = _mm_set1_ps( 69.f ); - __m128 c3145680v = _mm_set1_ps( 3145680.f ); - __m128 onev = _mm_set1_ps ( 1.f ); - __m128 zerov = _mm_set1_ps ( 0.f ); - __m128 d725v = _mm_set1_ps ( 0.725f ); - __m128 d1375v = _mm_set1_ps ( 0.1375f ); - - float *dest1, *dest2; - float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=0; row>1], tempv ); - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3,1,3,1 ) ); - _mm_storeu_ps( &dest2[indx>>1], tempv ); - } - for (; col>1] = CLIP(rawData[row][col]); //rawData = RT datas - col++; - dest2[indx>>1] = CLIP(rawData[row][col]); //rawData = RT datas - } - } -#ifdef _OPENMP -#pragma omp single -#endif -{ - if (plistener) plistener->setProgress (0.13); -} + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv])); + plistener->setProgress (0.0); + } #ifdef _OPENMP -#pragma omp for + #pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) #endif - for (int row=5; row>1; col>1])-LVFU(rgb[1][(indx-v3)>>1]))+vabsf(LVFU(rgb[0][indx1])-LVFU(rgb[0][(indx1-v1)])))/c65535v); - egv=(epsv+(vabsf(LVFU(rgb[1][(indx+h1)>>1])-LVFU(rgb[1][(indx+h3)>>1]))+vabsf(LVFU(rgb[0][indx1])-LVFU(rgb[0][(indx1+h1)])))/c65535v); - wgv=(epsv+(vabsf(LVFU(rgb[1][(indx-h1)>>1])-LVFU(rgb[1][(indx-h3)>>1]))+vabsf(LVFU(rgb[0][indx1])-LVFU(rgb[0][(indx1-h1)])))/c65535v); - sgv=(epsv+(vabsf(LVFU(rgb[1][(indx+v1)>>1])-LVFU(rgb[1][(indx+v3)>>1]))+vabsf(LVFU(rgb[0][indx1])-LVFU(rgb[0][(indx1+v1)])))/c65535v); - //N,E,W,S High Order Interpolation (Li & Randhawa) - //N,E,W,S Hamilton Adams Interpolation - // (48.f * 65535.f) = 3145680.f - tempv = c40v*LVFU(rgb[0][indx1]); - nvv=LIMV(((c23v*LVFU(rgb[1][(indx-v1)>>1])+c23v*LVFU(rgb[1][(indx-v3)>>1])+LVFU(rgb[1][(indx-v5)>>1])+LVFU(rgb[1][(indx+v1)>>1])+tempv-c32v*LVFU(rgb[0][(indx1-v1)])-c8v*LVFU(rgb[0][(indx1-v2)])))/c3145680v, zerov, onev); - evv=LIMV(((c23v*LVFU(rgb[1][(indx+h1)>>1])+c23v*LVFU(rgb[1][(indx+h3)>>1])+LVFU(rgb[1][(indx+h5)>>1])+LVFU(rgb[1][(indx-h1)>>1])+tempv-c32v*LVFU(rgb[0][(indx1+h1)])-c8v*LVFU(rgb[0][(indx1+h2)])))/c3145680v, zerov, onev); - wvv=LIMV(((c23v*LVFU(rgb[1][(indx-h1)>>1])+c23v*LVFU(rgb[1][(indx-h3)>>1])+LVFU(rgb[1][(indx-h5)>>1])+LVFU(rgb[1][(indx+h1)>>1])+tempv-c32v*LVFU(rgb[0][(indx1-h1)])-c8v*LVFU(rgb[0][(indx1-h2)])))/c3145680v, zerov, onev); - svv=LIMV(((c23v*LVFU(rgb[1][(indx+v1)>>1])+c23v*LVFU(rgb[1][(indx+v3)>>1])+LVFU(rgb[1][(indx+v5)>>1])+LVFU(rgb[1][(indx-v1)>>1])+tempv-c32v*LVFU(rgb[0][(indx1+v1)])-c8v*LVFU(rgb[0][(indx1+v2)])))/c3145680v, zerov, onev); - //Horizontal and vertical color differences - tempv = LVFU( rgb[0][indx1] ) / c65535v; - _mm_storeu_ps( &vdif[indx1], (sgv*nvv+ngv*svv)/(ngv+sgv)- tempv ); - _mm_storeu_ps( &hdif[indx1], (wgv*evv+egv*wvv)/(egv+wgv)- tempv ); - } - // borders without SSE - for (; col>1]-rgb[1][(indx-v3)>>1])+fabsf(rgb[0][indx1]-rgb[0][(indx1-v1)]))/65535.f);; - eg=(eps+(fabsf(rgb[1][(indx+h1)>>1]-rgb[1][(indx+h3)>>1])+fabsf(rgb[0][indx1]-rgb[0][(indx1+h1)]))/65535.f); - wg=(eps+(fabsf(rgb[1][(indx-h1)>>1]-rgb[1][(indx-h3)>>1])+fabsf(rgb[0][indx1]-rgb[0][(indx1-h1)]))/65535.f); - sg=(eps+(fabsf(rgb[1][(indx+v1)>>1]-rgb[1][(indx+v3)>>1])+fabsf(rgb[0][indx1]-rgb[0][(indx1+v1)]))/65535.f); - //N,E,W,S High Order Interpolation (Li & Randhawa) - //N,E,W,S Hamilton Adams Interpolation - // (48.f * 65535.f) = 3145680.f - nv=LIM(((23.0f*rgb[1][(indx-v1)>>1]+23.0f*rgb[1][(indx-v3)>>1]+rgb[1][(indx-v5)>>1]+rgb[1][(indx+v1)>>1]+40.0f*rgb[0][indx1]-32.0f*rgb[0][(indx1-v1)]-8.0f*rgb[0][(indx1-v2)]))/3145680.f, 0.0f, 1.0f); - ev=LIM(((23.0f*rgb[1][(indx+h1)>>1]+23.0f*rgb[1][(indx+h3)>>1]+rgb[1][(indx+h5)>>1]+rgb[1][(indx-h1)>>1]+40.0f*rgb[0][indx1]-32.0f*rgb[0][(indx1+h1)]-8.0f*rgb[0][(indx1+h2)]))/3145680.f, 0.0f, 1.0f); - wv=LIM(((23.0f*rgb[1][(indx-h1)>>1]+23.0f*rgb[1][(indx-h3)>>1]+rgb[1][(indx-h5)>>1]+rgb[1][(indx+h1)>>1]+40.0f*rgb[0][indx1]-32.0f*rgb[0][(indx1-h1)]-8.0f*rgb[0][(indx1-h2)]))/3145680.f, 0.0f, 1.0f); - sv=LIM(((23.0f*rgb[1][(indx+v1)>>1]+23.0f*rgb[1][(indx+v3)>>1]+rgb[1][(indx+v5)>>1]+rgb[1][(indx-v1)>>1]+40.0f*rgb[0][indx1]-32.0f*rgb[0][(indx1+v1)]-8.0f*rgb[0][(indx1+v2)]))/3145680.f, 0.0f, 1.0f); - //Horizontal and vertical color differences - vdif[indx1]=(sg*nv+ng*sv)/(ng+sg)-(rgb[0][indx1])/65535.f; - hdif[indx1]=(wg*ev+eg*wv)/(eg+wg)-(rgb[0][indx1])/65535.f; - } - } -#ifdef _OPENMP -#pragma omp single -#endif -{ - if (plistener) plistener->setProgress (0.26); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; row>1, d=FC(row,col)/2; colsetProgress (0.39); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; row>1])-LVFU(chr[c][(indx-v3-h3)>>1]))+vabsf(LVFU(chr[c][(indx+v1+h1)>>1])-LVFU(chr[c][(indx-v3-h3)>>1]))); - negv=onev/(epsv+vabsf(LVFU(chr[c][(indx-v1+h1)>>1])-LVFU(chr[c][(indx-v3+h3)>>1]))+vabsf(LVFU(chr[c][(indx+v1-h1)>>1])-LVFU(chr[c][(indx-v3+h3)>>1]))); - swgv=onev/(epsv+vabsf(LVFU(chr[c][(indx+v1-h1)>>1])-LVFU(chr[c][(indx+v3+h3)>>1]))+vabsf(LVFU(chr[c][(indx-v1+h1)>>1])-LVFU(chr[c][(indx+v3-h3)>>1]))); - segv=onev/(epsv+vabsf(LVFU(chr[c][(indx+v1+h1)>>1])-LVFU(chr[c][(indx+v3-h3)>>1]))+vabsf(LVFU(chr[c][(indx-v1-h1)>>1])-LVFU(chr[c][(indx+v3+h3)>>1]))); - //Limit NW,NE,SW,SE Color differences - nwvv=ULIMV(LVFU(chr[c][(indx-v1-h1)>>1]),LVFU(chr[c][(indx-v3-h1)>>1]),LVFU(chr[c][(indx-v1-h3)>>1])); - nevv=ULIMV(LVFU(chr[c][(indx-v1+h1)>>1]),LVFU(chr[c][(indx-v3+h1)>>1]),LVFU(chr[c][(indx-v1+h3)>>1])); - swvv=ULIMV(LVFU(chr[c][(indx+v1-h1)>>1]),LVFU(chr[c][(indx+v3-h1)>>1]),LVFU(chr[c][(indx+v1-h3)>>1])); - sevv=ULIMV(LVFU(chr[c][(indx+v1+h1)>>1]),LVFU(chr[c][(indx+v3+h1)>>1]),LVFU(chr[c][(indx+v1+h3)>>1])); - //Interpolate chrominance: R@B and B@R - tempv = (nwgv*nwvv+negv*nevv+swgv*swvv+segv*sevv)/(nwgv+negv+swgv+segv); - _mm_storeu_ps( &(chr[c][indx>>1]), tempv); - } - for (; col>1]-chr[c][(indx-v3-h3)>>1])+fabsf(chr[c][(indx+v1+h1)>>1]-chr[c][(indx-v3-h3)>>1])); - neg=1.0f/(eps+fabsf(chr[c][(indx-v1+h1)>>1]-chr[c][(indx-v3+h3)>>1])+fabsf(chr[c][(indx+v1-h1)>>1]-chr[c][(indx-v3+h3)>>1])); - swg=1.0f/(eps+fabsf(chr[c][(indx+v1-h1)>>1]-chr[c][(indx+v3+h3)>>1])+fabsf(chr[c][(indx-v1+h1)>>1]-chr[c][(indx+v3-h3)>>1])); - seg=1.0f/(eps+fabsf(chr[c][(indx+v1+h1)>>1]-chr[c][(indx+v3-h3)>>1])+fabsf(chr[c][(indx-v1-h1)>>1]-chr[c][(indx+v3+h3)>>1])); - //Limit NW,NE,SW,SE Color differences - nwv=ULIM(chr[c][(indx-v1-h1)>>1],chr[c][(indx-v3-h1)>>1],chr[c][(indx-v1-h3)>>1]); - nev=ULIM(chr[c][(indx-v1+h1)>>1],chr[c][(indx-v3+h1)>>1],chr[c][(indx-v1+h3)>>1]); - swv=ULIM(chr[c][(indx+v1-h1)>>1],chr[c][(indx+v3-h1)>>1],chr[c][(indx+v1-h3)>>1]); - sev=ULIM(chr[c][(indx+v1+h1)>>1],chr[c][(indx+v3+h1)>>1],chr[c][(indx+v1+h3)>>1]); - //Interpolate chrominance: R@B and B@R - chr[c][indx>>1]=(nwg*nwv+neg*nev+swg*swv+seg*sev)/(nwg+neg+swg+seg); - } - } -#ifdef _OPENMP -#pragma omp single -#endif -{ - if (plistener) plistener->setProgress (0.65); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; row>1])-LVFU(chr[0][(indx-v3)>>1]))+vabsf(LVFU(chr[0][(indx+v1)>>1])-LVFU(chr[0][(indx-v3)>>1]))); - egv=onev/(epsv+vabsf(LVFU(chr[0][(indx+h1)>>1])-LVFU(chr[0][(indx+h3)>>1]))+vabsf(LVFU(chr[0][(indx-h1)>>1])-LVFU(chr[0][(indx+h3)>>1]))); - wgv=onev/(epsv+vabsf(LVFU(chr[0][(indx-h1)>>1])-LVFU(chr[0][(indx-h3)>>1]))+vabsf(LVFU(chr[0][(indx+h1)>>1])-LVFU(chr[0][(indx-h3)>>1]))); - sgv=onev/(epsv+vabsf(LVFU(chr[0][(indx+v1)>>1])-LVFU(chr[0][(indx+v3)>>1]))+vabsf(LVFU(chr[0][(indx-v1)>>1])-LVFU(chr[0][(indx+v3)>>1]))); - //Interpolate chrominance: R@G and B@G - tempv = ((ngv*LVFU(chr[0][(indx-v1)>>1])+egv*LVFU(chr[0][(indx+h1)>>1])+wgv*LVFU(chr[0][(indx-h1)>>1])+sgv*LVFU(chr[0][(indx+v1)>>1]))/(ngv+egv+wgv+sgv)); - _mm_storeu_ps( &chr[0+2][indx>>1], tempv); - } - for (; col>1]-chr[0][(indx-v3)>>1])+fabsf(chr[0][(indx+v1)>>1]-chr[0][(indx-v3)>>1])); - eg=1.0f/(eps+fabsf(chr[0][(indx+h1)>>1]-chr[0][(indx+h3)>>1])+fabsf(chr[0][(indx-h1)>>1]-chr[0][(indx+h3)>>1])); - wg=1.0f/(eps+fabsf(chr[0][(indx-h1)>>1]-chr[0][(indx-h3)>>1])+fabsf(chr[0][(indx+h1)>>1]-chr[0][(indx-h3)>>1])); - sg=1.0f/(eps+fabsf(chr[0][(indx+v1)>>1]-chr[0][(indx+v3)>>1])+fabsf(chr[0][(indx-v1)>>1]-chr[0][(indx+v3)>>1])); - //Interpolate chrominance: R@G and B@G - chr[0+2][indx>>1]=((ng*chr[0][(indx-v1)>>1]+eg*chr[0][(indx+h1)>>1]+wg*chr[0][(indx-h1)>>1]+sg*chr[0][(indx+v1)>>1])/(ng+eg+wg+sg)); - } - } -#ifdef _OPENMP -#pragma omp single -#endif -{ - if (plistener) plistener->setProgress (0.78); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; row>1])-LVFU(chr[1][(indx-v3)>>1]))+vabsf(LVFU(chr[1][(indx+v1)>>1])-LVFU(chr[1][(indx-v3)>>1]))); - egv=onev/(epsv+vabsf(LVFU(chr[1][(indx+h1)>>1])-LVFU(chr[1][(indx+h3)>>1]))+vabsf(LVFU(chr[1][(indx-h1)>>1])-LVFU(chr[1][(indx+h3)>>1]))); - wgv=onev/(epsv+vabsf(LVFU(chr[1][(indx-h1)>>1])-LVFU(chr[1][(indx-h3)>>1]))+vabsf(LVFU(chr[1][(indx+h1)>>1])-LVFU(chr[1][(indx-h3)>>1]))); - sgv=onev/(epsv+vabsf(LVFU(chr[1][(indx+v1)>>1])-LVFU(chr[1][(indx+v3)>>1]))+vabsf(LVFU(chr[1][(indx-v1)>>1])-LVFU(chr[1][(indx+v3)>>1]))); - //Interpolate chrominance: R@G and B@G - tempv = ((ngv*LVFU(chr[1][(indx-v1)>>1])+egv*LVFU(chr[1][(indx+h1)>>1])+wgv*LVFU(chr[1][(indx-h1)>>1])+sgv*LVFU(chr[1][(indx+v1)>>1]))/(ngv+egv+wgv+sgv)); - _mm_storeu_ps( &chr[1+2][indx>>1], tempv); - } - for (; col>1]-chr[1][(indx-v3)>>1])+fabsf(chr[1][(indx+v1)>>1]-chr[1][(indx-v3)>>1])); - eg=1.0f/(eps+fabsf(chr[1][(indx+h1)>>1]-chr[1][(indx+h3)>>1])+fabsf(chr[1][(indx-h1)>>1]-chr[1][(indx+h3)>>1])); - wg=1.0f/(eps+fabsf(chr[1][(indx-h1)>>1]-chr[1][(indx-h3)>>1])+fabsf(chr[1][(indx+h1)>>1]-chr[1][(indx-h3)>>1])); - sg=1.0f/(eps+fabsf(chr[1][(indx+v1)>>1]-chr[1][(indx+v3)>>1])+fabsf(chr[1][(indx-v1)>>1]-chr[1][(indx+v3)>>1])); - //Interpolate chrominance: R@G and B@G - chr[1+2][indx>>1]=((ng*chr[1][(indx-v1)>>1]+eg*chr[1][(indx+h1)>>1]+wg*chr[1][(indx-h1)>>1]+sg*chr[1][(indx+v1)>>1])/(ng+eg+wg+sg)); - } - } -#ifdef _OPENMP -#pragma omp single -#endif -{ - if (plistener) plistener->setProgress (0.91); -} - float *src1, *src2, *redsrc0, *redsrc1, *bluesrc0, *bluesrc1; -#ifdef _OPENMP -#pragma omp for -#endif - for(int row=7; row>1] ); - temp2v = LVFU( src2[(indx+1)>>1] ); - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 1,0,1,0 ) ); - tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3,1,2,0 ) ); - _mm_storeu_ps( &green[row][col], CLIPV( tempv )); - temp5v = LVFU(redsrc0[indx>>1]); - temp6v = LVFU(redsrc1[(indx+1)>>1]); - temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 1,0,1,0 ) ); - temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3,1,2,0 ) ); - temp3v = CLIPV( tempv - c65535v * temp3v ); - _mm_storeu_ps( &red[row][col], temp3v); - temp7v = LVFU(bluesrc0[indx>>1]); - temp8v = LVFU(bluesrc1[(indx+1)>>1]); - temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 1,0,1,0 ) ); - temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3,1,2,0 ) ); - temp4v = CLIPV( tempv - c65535v * temp4v ); - _mm_storeu_ps( &blue[row][col], temp4v); + { + __m128 ngv, egv, wgv, sgv, nvv, evv, wvv, svv, nwgv, negv, swgv, segv, nwvv, nevv, swvv, sevv, tempv, temp1v, temp2v, temp3v, temp4v, temp5v, temp6v, temp7v, temp8v; + __m128 epsv = _mm_set1_ps( eps ); + __m128 epssqv = _mm_set1_ps( epssq ); + __m128 c65535v = _mm_set1_ps( 65535.f ); + __m128 c23v = _mm_set1_ps( 23.f ); + __m128 c40v = _mm_set1_ps( 40.f ); + __m128 c51v = _mm_set1_ps( 51.f ); + __m128 c32v = _mm_set1_ps( 32.f ); + __m128 c8v = _mm_set1_ps( 8.f ); + __m128 c7v = _mm_set1_ps( 7.f ); + __m128 c6v = _mm_set1_ps( 6.f ); + __m128 c10v = _mm_set1_ps( 10.f ); + __m128 c21v = _mm_set1_ps( 21.f ); + __m128 c78v = _mm_set1_ps( 78.f ); + __m128 c69v = _mm_set1_ps( 69.f ); + __m128 c3145680v = _mm_set1_ps( 3145680.f ); + __m128 onev = _mm_set1_ps ( 1.f ); + __m128 zerov = _mm_set1_ps ( 0.f ); + __m128 d725v = _mm_set1_ps ( 0.725f ); + __m128 d1375v = _mm_set1_ps ( 0.1375f ); - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3,2,3,2 ) ); - tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3,1,2,0 ) ); - _mm_storeu_ps( &green[row][col+4], CLIPV( tempv )); + float *dest1, *dest2; + float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; +#ifdef _OPENMP + #pragma omp for +#endif - temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 3,2,3,2 ) ); - temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3,1,2,0 ) ); - temp3v = CLIPV( tempv - c65535v * temp3v ); - _mm_storeu_ps( &red[row][col+4], temp3v); - temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 3,2,3,2 ) ); - temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3,1,2,0 ) ); - temp4v = CLIPV( tempv - c65535v * temp4v ); - _mm_storeu_ps( &blue[row][col+4], temp4v); - } + for (int row = 0; row < height - 0; row++) { + dest1 = rgb[FC(row, 0) & 1]; + dest2 = rgb[FC(row, 1) & 1]; + int col, indx; - for(; col>1]-65535.f*redsrc0[indx>>1]); - green[row][col] = CLIP(src1[indx>>1]); - blue [row][col] = CLIP(src1[indx>>1]-65535.f*bluesrc0[indx>>1]); - col++; - red [row][col] = CLIP(src2[(indx+1)>>1]-65535.f*redsrc1[(indx+1)>>1]); - green[row][col] = CLIP(src2[(indx+1)>>1]); - blue [row][col] = CLIP(src2[(indx+1)>>1]-65535.f*bluesrc1[(indx+1)>>1]); - } - } -}// End of parallelization - if (plistener) plistener->setProgress (1.0); + for (col = 0, indx = row * width + col; col < width - 7; col += 8, indx += 8) { + temp1v = LVFU( rawData[row][col] ); + temp1v = CLIPV( temp1v ); + temp2v = LVFU( rawData[row][col + 4] ); + temp2v = CLIPV( temp2v ); + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 2, 0, 2, 0 ) ); + _mm_storeu_ps( &dest1[indx >> 1], tempv ); + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 1, 3, 1 ) ); + _mm_storeu_ps( &dest2[indx >> 1], tempv ); + } - free(chrarray); free(rgbarray); - free(vdif); free(hdif); + for (; col < width; col++, indx += 2) { + dest1[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT datas + col++; + dest2[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT datas + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.13); + } + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 5; row < height - 5; row++) { + int col, indx, indx1; + + for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, indx1 = indx >> 1; col < width - 12; col += 8, indx += 8, indx1 += 4) { + //N,E,W,S Gradients + ngv = (epsv + (vabsf(LVFU(rgb[1][(indx - v1) >> 1]) - LVFU(rgb[1][(indx - v3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 - v1)]))) / c65535v); + egv = (epsv + (vabsf(LVFU(rgb[1][(indx + h1) >> 1]) - LVFU(rgb[1][(indx + h3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 + h1)]))) / c65535v); + wgv = (epsv + (vabsf(LVFU(rgb[1][(indx - h1) >> 1]) - LVFU(rgb[1][(indx - h3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 - h1)]))) / c65535v); + sgv = (epsv + (vabsf(LVFU(rgb[1][(indx + v1) >> 1]) - LVFU(rgb[1][(indx + v3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 + v1)]))) / c65535v); + //N,E,W,S High Order Interpolation (Li & Randhawa) + //N,E,W,S Hamilton Adams Interpolation + // (48.f * 65535.f) = 3145680.f + tempv = c40v * LVFU(rgb[0][indx1]); + nvv = LIMV(((c23v * LVFU(rgb[1][(indx - v1) >> 1]) + c23v * LVFU(rgb[1][(indx - v3) >> 1]) + LVFU(rgb[1][(indx - v5) >> 1]) + LVFU(rgb[1][(indx + v1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 - v1)]) - c8v * LVFU(rgb[0][(indx1 - v2)]))) / c3145680v, zerov, onev); + evv = LIMV(((c23v * LVFU(rgb[1][(indx + h1) >> 1]) + c23v * LVFU(rgb[1][(indx + h3) >> 1]) + LVFU(rgb[1][(indx + h5) >> 1]) + LVFU(rgb[1][(indx - h1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 + h1)]) - c8v * LVFU(rgb[0][(indx1 + h2)]))) / c3145680v, zerov, onev); + wvv = LIMV(((c23v * LVFU(rgb[1][(indx - h1) >> 1]) + c23v * LVFU(rgb[1][(indx - h3) >> 1]) + LVFU(rgb[1][(indx - h5) >> 1]) + LVFU(rgb[1][(indx + h1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 - h1)]) - c8v * LVFU(rgb[0][(indx1 - h2)]))) / c3145680v, zerov, onev); + svv = LIMV(((c23v * LVFU(rgb[1][(indx + v1) >> 1]) + c23v * LVFU(rgb[1][(indx + v3) >> 1]) + LVFU(rgb[1][(indx + v5) >> 1]) + LVFU(rgb[1][(indx - v1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 + v1)]) - c8v * LVFU(rgb[0][(indx1 + v2)]))) / c3145680v, zerov, onev); + //Horizontal and vertical color differences + tempv = LVFU( rgb[0][indx1] ) / c65535v; + _mm_storeu_ps( &vdif[indx1], (sgv * nvv + ngv * svv) / (ngv + sgv) - tempv ); + _mm_storeu_ps( &hdif[indx1], (wgv * evv + egv * wvv) / (egv + wgv) - tempv ); + } + + // borders without SSE + for (; col < width - 5; col += 2, indx += 2, indx1++) { + //N,E,W,S Gradients + ng = (eps + (fabsf(rgb[1][(indx - v1) >> 1] - rgb[1][(indx - v3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 - v1)])) / 65535.f);; + eg = (eps + (fabsf(rgb[1][(indx + h1) >> 1] - rgb[1][(indx + h3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 + h1)])) / 65535.f); + wg = (eps + (fabsf(rgb[1][(indx - h1) >> 1] - rgb[1][(indx - h3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 - h1)])) / 65535.f); + sg = (eps + (fabsf(rgb[1][(indx + v1) >> 1] - rgb[1][(indx + v3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 + v1)])) / 65535.f); + //N,E,W,S High Order Interpolation (Li & Randhawa) + //N,E,W,S Hamilton Adams Interpolation + // (48.f * 65535.f) = 3145680.f + nv = LIM(((23.0f * rgb[1][(indx - v1) >> 1] + 23.0f * rgb[1][(indx - v3) >> 1] + rgb[1][(indx - v5) >> 1] + rgb[1][(indx + v1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 - v1)] - 8.0f * rgb[0][(indx1 - v2)])) / 3145680.f, 0.0f, 1.0f); + ev = LIM(((23.0f * rgb[1][(indx + h1) >> 1] + 23.0f * rgb[1][(indx + h3) >> 1] + rgb[1][(indx + h5) >> 1] + rgb[1][(indx - h1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 + h1)] - 8.0f * rgb[0][(indx1 + h2)])) / 3145680.f, 0.0f, 1.0f); + wv = LIM(((23.0f * rgb[1][(indx - h1) >> 1] + 23.0f * rgb[1][(indx - h3) >> 1] + rgb[1][(indx - h5) >> 1] + rgb[1][(indx + h1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 - h1)] - 8.0f * rgb[0][(indx1 - h2)])) / 3145680.f, 0.0f, 1.0f); + sv = LIM(((23.0f * rgb[1][(indx + v1) >> 1] + 23.0f * rgb[1][(indx + v3) >> 1] + rgb[1][(indx + v5) >> 1] + rgb[1][(indx - v1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 + v1)] - 8.0f * rgb[0][(indx1 + v2)])) / 3145680.f, 0.0f, 1.0f); + //Horizontal and vertical color differences + vdif[indx1] = (sg * nv + ng * sv) / (ng + sg) - (rgb[0][indx1]) / 65535.f; + hdif[indx1] = (wg * ev + eg * wv) / (eg + wg) - (rgb[0][indx1]) / 65535.f; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.26); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, d, indx1; + + for (col = 7 + (FC(row, 1) & 1), indx1 = (row * width + col) >> 1, d = FC(row, col) / 2; col < width - 14; col += 8, indx1 += 4) { + //H&V integrated gaussian vector over variance on color differences + //Mod Jacques 3/2013 + ngv = LIMV(epssqv + c78v * SQRV(LVFU(vdif[indx1])) + c69v * (SQRV(LVFU(vdif[indx1 - v1])) + SQRV(LVFU(vdif[indx1 + v1]))) + c51v * (SQRV(LVFU(vdif[indx1 - v2])) + SQRV(LVFU(vdif[indx1 + v2]))) + c21v * (SQRV(LVFU(vdif[indx1 - v3])) + SQRV(LVFU(vdif[indx1 + v3]))) - c6v * SQRV(LVFU(vdif[indx1 - v1]) + LVFU(vdif[indx1]) + LVFU(vdif[indx1 + v1])) + - c10v * (SQRV(LVFU(vdif[indx1 - v2]) + LVFU(vdif[indx1 - v1]) + LVFU(vdif[indx1])) + SQRV(LVFU(vdif[indx1]) + LVFU(vdif[indx1 + v1]) + LVFU(vdif[indx1 + v2]))) - c7v * (SQRV(LVFU(vdif[indx1 - v3]) + LVFU(vdif[indx1 - v2]) + LVFU(vdif[indx1 - v1])) + SQRV(LVFU(vdif[indx1 + v1]) + LVFU(vdif[indx1 + v2]) + LVFU(vdif[indx1 + v3]))), zerov, onev); + egv = LIMV(epssqv + c78v * SQRV(LVFU(hdif[indx1])) + c69v * (SQRV(LVFU(hdif[indx1 - h1])) + SQRV(LVFU(hdif[indx1 + h1]))) + c51v * (SQRV(LVFU(hdif[indx1 - h2])) + SQRV(LVFU(hdif[indx1 + h2]))) + c21v * (SQRV(LVFU(hdif[indx1 - h3])) + SQRV(LVFU(hdif[indx1 + h3]))) - c6v * SQRV(LVFU(hdif[indx1 - h1]) + LVFU(hdif[indx1]) + LVFU(hdif[indx1 + h1])) + - c10v * (SQRV(LVFU(hdif[indx1 - h2]) + LVFU(hdif[indx1 - h1]) + LVFU(hdif[indx1])) + SQRV(LVFU(hdif[indx1]) + LVFU(hdif[indx1 + h1]) + LVFU(hdif[indx1 + h2]))) - c7v * (SQRV(LVFU(hdif[indx1 - h3]) + LVFU(hdif[indx1 - h2]) + LVFU(hdif[indx1 - h1])) + SQRV(LVFU(hdif[indx1 + h1]) + LVFU(hdif[indx1 + h2]) + LVFU(hdif[indx1 + h3]))), zerov, onev); + //Limit chrominance using H/V neighbourhood + nvv = ULIMV(d725v * LVFU(vdif[indx1]) + d1375v * LVFU(vdif[indx1 - v1]) + d1375v * LVFU(vdif[indx1 + v1]), LVFU(vdif[indx1 - v1]), LVFU(vdif[indx1 + v1])); + evv = ULIMV(d725v * LVFU(hdif[indx1]) + d1375v * LVFU(hdif[indx1 - h1]) + d1375v * LVFU(hdif[indx1 + h1]), LVFU(hdif[indx1 - h1]), LVFU(hdif[indx1 + h1])); + //Chrominance estimation + tempv = (egv * nvv + ngv * evv) / (ngv + egv); + _mm_storeu_ps(&(chr[d][indx1]), tempv); + //Green channel population + temp1v = c65535v * tempv + LVFU(rgb[0][indx1]); + _mm_storeu_ps( &(rgb[0][indx1]), temp1v ); + } + + for (; col < width - 7; col += 2, indx1++) { + //H&V integrated gaussian vector over variance on color differences + //Mod Jacques 3/2013 + ng = LIM(epssq + 78.0f * SQR(vdif[indx1]) + 69.0f * (SQR(vdif[indx1 - v1]) + SQR(vdif[indx1 + v1])) + 51.0f * (SQR(vdif[indx1 - v2]) + SQR(vdif[indx1 + v2])) + 21.0f * (SQR(vdif[indx1 - v3]) + SQR(vdif[indx1 + v3])) - 6.0f * SQR(vdif[indx1 - v1] + vdif[indx1] + vdif[indx1 + v1]) + - 10.0f * (SQR(vdif[indx1 - v2] + vdif[indx1 - v1] + vdif[indx1]) + SQR(vdif[indx1] + vdif[indx1 + v1] + vdif[indx1 + v2])) - 7.0f * (SQR(vdif[indx1 - v3] + vdif[indx1 - v2] + vdif[indx1 - v1]) + SQR(vdif[indx1 + v1] + vdif[indx1 + v2] + vdif[indx1 + v3])), 0.f, 1.f); + eg = LIM(epssq + 78.0f * SQR(hdif[indx1]) + 69.0f * (SQR(hdif[indx1 - h1]) + SQR(hdif[indx1 + h1])) + 51.0f * (SQR(hdif[indx1 - h2]) + SQR(hdif[indx1 + h2])) + 21.0f * (SQR(hdif[indx1 - h3]) + SQR(hdif[indx1 + h3])) - 6.0f * SQR(hdif[indx1 - h1] + hdif[indx1] + hdif[indx1 + h1]) + - 10.0f * (SQR(hdif[indx1 - h2] + hdif[indx1 - h1] + hdif[indx1]) + SQR(hdif[indx1] + hdif[indx1 + h1] + hdif[indx1 + h2])) - 7.0f * (SQR(hdif[indx1 - h3] + hdif[indx1 - h2] + hdif[indx1 - h1]) + SQR(hdif[indx1 + h1] + hdif[indx1 + h2] + hdif[indx1 + h3])), 0.f, 1.f); + //Limit chrominance using H/V neighbourhood + nv = ULIM(0.725f * vdif[indx1] + 0.1375f * vdif[indx1 - v1] + 0.1375f * vdif[indx1 + v1], vdif[indx1 - v1], vdif[indx1 + v1]); + ev = ULIM(0.725f * hdif[indx1] + 0.1375f * hdif[indx1 - h1] + 0.1375f * hdif[indx1 + h1], hdif[indx1 - h1], hdif[indx1 + h1]); + //Chrominance estimation + chr[d][indx1] = (eg * nv + ng * ev) / (ng + eg); + //Green channel population + rgb[0][indx1] = rgb[0][indx1] + 65535.f * chr[d][indx1]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.39); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, indx, c; + + for (col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 14; col += 8, indx += 8) { + //NW,NE,SW,SE Gradients + nwgv = onev / (epsv + vabsf(LVFU(chr[c][(indx - v1 - h1) >> 1]) - LVFU(chr[c][(indx - v3 - h3) >> 1])) + vabsf(LVFU(chr[c][(indx + v1 + h1) >> 1]) - LVFU(chr[c][(indx - v3 - h3) >> 1]))); + negv = onev / (epsv + vabsf(LVFU(chr[c][(indx - v1 + h1) >> 1]) - LVFU(chr[c][(indx - v3 + h3) >> 1])) + vabsf(LVFU(chr[c][(indx + v1 - h1) >> 1]) - LVFU(chr[c][(indx - v3 + h3) >> 1]))); + swgv = onev / (epsv + vabsf(LVFU(chr[c][(indx + v1 - h1) >> 1]) - LVFU(chr[c][(indx + v3 + h3) >> 1])) + vabsf(LVFU(chr[c][(indx - v1 + h1) >> 1]) - LVFU(chr[c][(indx + v3 - h3) >> 1]))); + segv = onev / (epsv + vabsf(LVFU(chr[c][(indx + v1 + h1) >> 1]) - LVFU(chr[c][(indx + v3 - h3) >> 1])) + vabsf(LVFU(chr[c][(indx - v1 - h1) >> 1]) - LVFU(chr[c][(indx + v3 + h3) >> 1]))); + //Limit NW,NE,SW,SE Color differences + nwvv = ULIMV(LVFU(chr[c][(indx - v1 - h1) >> 1]), LVFU(chr[c][(indx - v3 - h1) >> 1]), LVFU(chr[c][(indx - v1 - h3) >> 1])); + nevv = ULIMV(LVFU(chr[c][(indx - v1 + h1) >> 1]), LVFU(chr[c][(indx - v3 + h1) >> 1]), LVFU(chr[c][(indx - v1 + h3) >> 1])); + swvv = ULIMV(LVFU(chr[c][(indx + v1 - h1) >> 1]), LVFU(chr[c][(indx + v3 - h1) >> 1]), LVFU(chr[c][(indx + v1 - h3) >> 1])); + sevv = ULIMV(LVFU(chr[c][(indx + v1 + h1) >> 1]), LVFU(chr[c][(indx + v3 + h1) >> 1]), LVFU(chr[c][(indx + v1 + h3) >> 1])); + //Interpolate chrominance: R@B and B@R + tempv = (nwgv * nwvv + negv * nevv + swgv * swvv + segv * sevv) / (nwgv + negv + swgv + segv); + _mm_storeu_ps( &(chr[c][indx >> 1]), tempv); + } + + for (; col < width - 7; col += 2, indx += 2) { + //NW,NE,SW,SE Gradients + nwg = 1.0f / (eps + fabsf(chr[c][(indx - v1 - h1) >> 1] - chr[c][(indx - v3 - h3) >> 1]) + fabsf(chr[c][(indx + v1 + h1) >> 1] - chr[c][(indx - v3 - h3) >> 1])); + neg = 1.0f / (eps + fabsf(chr[c][(indx - v1 + h1) >> 1] - chr[c][(indx - v3 + h3) >> 1]) + fabsf(chr[c][(indx + v1 - h1) >> 1] - chr[c][(indx - v3 + h3) >> 1])); + swg = 1.0f / (eps + fabsf(chr[c][(indx + v1 - h1) >> 1] - chr[c][(indx + v3 + h3) >> 1]) + fabsf(chr[c][(indx - v1 + h1) >> 1] - chr[c][(indx + v3 - h3) >> 1])); + seg = 1.0f / (eps + fabsf(chr[c][(indx + v1 + h1) >> 1] - chr[c][(indx + v3 - h3) >> 1]) + fabsf(chr[c][(indx - v1 - h1) >> 1] - chr[c][(indx + v3 + h3) >> 1])); + //Limit NW,NE,SW,SE Color differences + nwv = ULIM(chr[c][(indx - v1 - h1) >> 1], chr[c][(indx - v3 - h1) >> 1], chr[c][(indx - v1 - h3) >> 1]); + nev = ULIM(chr[c][(indx - v1 + h1) >> 1], chr[c][(indx - v3 + h1) >> 1], chr[c][(indx - v1 + h3) >> 1]); + swv = ULIM(chr[c][(indx + v1 - h1) >> 1], chr[c][(indx + v3 - h1) >> 1], chr[c][(indx + v1 - h3) >> 1]); + sev = ULIM(chr[c][(indx + v1 + h1) >> 1], chr[c][(indx + v3 + h1) >> 1], chr[c][(indx + v1 + h3) >> 1]); + //Interpolate chrominance: R@B and B@R + chr[c][indx >> 1] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.65); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, indx; + + for (col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 14; col += 8, indx += 8) { + //N,E,W,S Gradients + ngv = onev / (epsv + vabsf(LVFU(chr[0][(indx - v1) >> 1]) - LVFU(chr[0][(indx - v3) >> 1])) + vabsf(LVFU(chr[0][(indx + v1) >> 1]) - LVFU(chr[0][(indx - v3) >> 1]))); + egv = onev / (epsv + vabsf(LVFU(chr[0][(indx + h1) >> 1]) - LVFU(chr[0][(indx + h3) >> 1])) + vabsf(LVFU(chr[0][(indx - h1) >> 1]) - LVFU(chr[0][(indx + h3) >> 1]))); + wgv = onev / (epsv + vabsf(LVFU(chr[0][(indx - h1) >> 1]) - LVFU(chr[0][(indx - h3) >> 1])) + vabsf(LVFU(chr[0][(indx + h1) >> 1]) - LVFU(chr[0][(indx - h3) >> 1]))); + sgv = onev / (epsv + vabsf(LVFU(chr[0][(indx + v1) >> 1]) - LVFU(chr[0][(indx + v3) >> 1])) + vabsf(LVFU(chr[0][(indx - v1) >> 1]) - LVFU(chr[0][(indx + v3) >> 1]))); + //Interpolate chrominance: R@G and B@G + tempv = ((ngv * LVFU(chr[0][(indx - v1) >> 1]) + egv * LVFU(chr[0][(indx + h1) >> 1]) + wgv * LVFU(chr[0][(indx - h1) >> 1]) + sgv * LVFU(chr[0][(indx + v1) >> 1])) / (ngv + egv + wgv + sgv)); + _mm_storeu_ps( &chr[0 + 2][indx >> 1], tempv); + } + + for (; col < width - 7; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[0][(indx - v1) >> 1] - chr[0][(indx - v3) >> 1]) + fabsf(chr[0][(indx + v1) >> 1] - chr[0][(indx - v3) >> 1])); + eg = 1.0f / (eps + fabsf(chr[0][(indx + h1) >> 1] - chr[0][(indx + h3) >> 1]) + fabsf(chr[0][(indx - h1) >> 1] - chr[0][(indx + h3) >> 1])); + wg = 1.0f / (eps + fabsf(chr[0][(indx - h1) >> 1] - chr[0][(indx - h3) >> 1]) + fabsf(chr[0][(indx + h1) >> 1] - chr[0][(indx - h3) >> 1])); + sg = 1.0f / (eps + fabsf(chr[0][(indx + v1) >> 1] - chr[0][(indx + v3) >> 1]) + fabsf(chr[0][(indx - v1) >> 1] - chr[0][(indx + v3) >> 1])); + //Interpolate chrominance: R@G and B@G + chr[0 + 2][indx >> 1] = ((ng * chr[0][(indx - v1) >> 1] + eg * chr[0][(indx + h1) >> 1] + wg * chr[0][(indx - h1) >> 1] + sg * chr[0][(indx + v1) >> 1]) / (ng + eg + wg + sg)); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.78); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, indx; + + for (col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 14; col += 8, indx += 8) { + //N,E,W,S Gradients + ngv = onev / (epsv + vabsf(LVFU(chr[1][(indx - v1) >> 1]) - LVFU(chr[1][(indx - v3) >> 1])) + vabsf(LVFU(chr[1][(indx + v1) >> 1]) - LVFU(chr[1][(indx - v3) >> 1]))); + egv = onev / (epsv + vabsf(LVFU(chr[1][(indx + h1) >> 1]) - LVFU(chr[1][(indx + h3) >> 1])) + vabsf(LVFU(chr[1][(indx - h1) >> 1]) - LVFU(chr[1][(indx + h3) >> 1]))); + wgv = onev / (epsv + vabsf(LVFU(chr[1][(indx - h1) >> 1]) - LVFU(chr[1][(indx - h3) >> 1])) + vabsf(LVFU(chr[1][(indx + h1) >> 1]) - LVFU(chr[1][(indx - h3) >> 1]))); + sgv = onev / (epsv + vabsf(LVFU(chr[1][(indx + v1) >> 1]) - LVFU(chr[1][(indx + v3) >> 1])) + vabsf(LVFU(chr[1][(indx - v1) >> 1]) - LVFU(chr[1][(indx + v3) >> 1]))); + //Interpolate chrominance: R@G and B@G + tempv = ((ngv * LVFU(chr[1][(indx - v1) >> 1]) + egv * LVFU(chr[1][(indx + h1) >> 1]) + wgv * LVFU(chr[1][(indx - h1) >> 1]) + sgv * LVFU(chr[1][(indx + v1) >> 1])) / (ngv + egv + wgv + sgv)); + _mm_storeu_ps( &chr[1 + 2][indx >> 1], tempv); + } + + for (; col < width - 7; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[1][(indx - v1) >> 1] - chr[1][(indx - v3) >> 1]) + fabsf(chr[1][(indx + v1) >> 1] - chr[1][(indx - v3) >> 1])); + eg = 1.0f / (eps + fabsf(chr[1][(indx + h1) >> 1] - chr[1][(indx + h3) >> 1]) + fabsf(chr[1][(indx - h1) >> 1] - chr[1][(indx + h3) >> 1])); + wg = 1.0f / (eps + fabsf(chr[1][(indx - h1) >> 1] - chr[1][(indx - h3) >> 1]) + fabsf(chr[1][(indx + h1) >> 1] - chr[1][(indx - h3) >> 1])); + sg = 1.0f / (eps + fabsf(chr[1][(indx + v1) >> 1] - chr[1][(indx + v3) >> 1]) + fabsf(chr[1][(indx - v1) >> 1] - chr[1][(indx + v3) >> 1])); + //Interpolate chrominance: R@G and B@G + chr[1 + 2][indx >> 1] = ((ng * chr[1][(indx - v1) >> 1] + eg * chr[1][(indx + h1) >> 1] + wg * chr[1][(indx - h1) >> 1] + sg * chr[1][(indx + v1) >> 1]) / (ng + eg + wg + sg)); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.91); + } + } + float *src1, *src2, *redsrc0, *redsrc1, *bluesrc0, *bluesrc1; +#ifdef _OPENMP + #pragma omp for +#endif + + for(int row = 7; row < height - 7; row++) { + int col, indx, fc; + fc = FC(row, 7) & 1; + src1 = rgb[fc]; + src2 = rgb[fc ^ 1]; + redsrc0 = chr[fc << 1]; + redsrc1 = chr[(fc ^ 1) << 1]; + bluesrc0 = chr[(fc << 1) + 1]; + bluesrc1 = chr[((fc ^ 1) << 1) + 1]; + + for(col = 7, indx = row * width + col; col < width - 14; col += 8, indx += 8) { + temp1v = LVFU( src1[indx >> 1] ); + temp2v = LVFU( src2[(indx + 1) >> 1] ); + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + _mm_storeu_ps( &green[row][col], CLIPV( tempv )); + temp5v = LVFU(redsrc0[indx >> 1]); + temp6v = LVFU(redsrc1[(indx + 1) >> 1]); + temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp3v = CLIPV( tempv - c65535v * temp3v ); + _mm_storeu_ps( &red[row][col], temp3v); + temp7v = LVFU(bluesrc0[indx >> 1]); + temp8v = LVFU(bluesrc1[(indx + 1) >> 1]); + temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp4v = CLIPV( tempv - c65535v * temp4v ); + _mm_storeu_ps( &blue[row][col], temp4v); + + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + _mm_storeu_ps( &green[row][col + 4], CLIPV( tempv )); + + temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp3v = CLIPV( tempv - c65535v * temp3v ); + _mm_storeu_ps( &red[row][col + 4], temp3v); + temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp4v = CLIPV( tempv - c65535v * temp4v ); + _mm_storeu_ps( &blue[row][col + 4], temp4v); + } + + for(; col < width - 7; col++, indx += 2) { + red [row][col] = CLIP(src1[indx >> 1] - 65535.f * redsrc0[indx >> 1]); + green[row][col] = CLIP(src1[indx >> 1]); + blue [row][col] = CLIP(src1[indx >> 1] - 65535.f * bluesrc0[indx >> 1]); + col++; + red [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * redsrc1[(indx + 1) >> 1]); + green[row][col] = CLIP(src2[(indx + 1) >> 1]); + blue [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * bluesrc1[(indx + 1) >> 1]); + } + } + }// End of parallelization + + if (plistener) { + plistener->setProgress (1.0); + } + + free(chrarray); + free(rgbarray); + free(vdif); + free(hdif); } #undef CLIPV #else void RawImageSource::igv_interpolate(int winw, int winh) { - static const float eps=1e-5f, epssq=1e-5f;//mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) - static const int h1=1, h2=2, h3=3, h4=4, h5=5, h6=6; - const int width=winw, height=winh; - const int v1=1*width, v2=2*width, v3=3*width, v4=4*width, v5=5*width, v6=6*width; - float* rgb[3]; - float* chr[2]; - float (*rgbarray), *vdif, *hdif, (*chrarray); + static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) + static const int h1 = 1, h2 = 2, h3 = 3, h4 = 4, h5 = 5, h6 = 6; + const int width = winw, height = winh; + const int v1 = 1 * width, v2 = 2 * width, v3 = 3 * width, v4 = 4 * width, v5 = 5 * width, v6 = 6 * width; + float* rgb[3]; + float* chr[2]; + float (*rgbarray), *vdif, *hdif, (*chrarray); - rgbarray = (float (*)) calloc(width*height*3, sizeof( float)); - rgb[0] = rgbarray; - rgb[1] = rgbarray + (width*height); - rgb[2] = rgbarray + 2*(width*height); + rgbarray = (float (*)) calloc(width * height * 3, sizeof( float)); + rgb[0] = rgbarray; + rgb[1] = rgbarray + (width * height); + rgb[2] = rgbarray + 2 * (width * height); - chrarray = (float (*)) calloc(width*height*2, sizeof( float)); - chr[0] = chrarray; - chr[1] = chrarray + (width*height); + chrarray = (float (*)) calloc(width * height * 2, sizeof( float)); + chr[0] = chrarray; + chr[1] = chrarray + (width * height); - vdif = (float (*)) calloc(width*height/2, sizeof *vdif); - hdif = (float (*)) calloc(width*height/2, sizeof *hdif); + vdif = (float (*)) calloc(width * height / 2, sizeof * vdif); + hdif = (float (*)) calloc(width * height / 2, sizeof * hdif); - border_interpolate2(winw,winh,7); + border_interpolate2(winw, winh, 7); - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv])); - plistener->setProgress (0.0); - } -#ifdef _OPENMP -#pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) -#endif -{ - - float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv])); + plistener->setProgress (0.0); + } #ifdef _OPENMP -#pragma omp for + #pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) #endif - for (int row=0; rowsetProgress (0.13); -} + + for (int row = 0; row < height - 0; row++) + for (int col = 0, indx = row * width + col; col < width - 0; col++, indx++) { + int c = FC(row, col); + rgb[c][indx] = CLIP(rawData[row][col]); //rawData = RT datas + } + +// border_interpolate2(7, rgb); #ifdef _OPENMP -#pragma omp for + #pragma omp single #endif - for (int row=5; row>1]=(sg*nv+ng*sv)/(ng+sg)-(rgb[c][indx])/65535.f; - hdif[indx>>1]=(wg*ev+eg*wv)/(eg+wg)-(rgb[c][indx])/65535.f; - } + { + if (plistener) { + plistener->setProgress (0.13); + } + } #ifdef _OPENMP -#pragma omp single + #pragma omp for #endif -{ - if (plistener) plistener->setProgress (0.26); -} + + for (int row = 5; row < height - 5; row++) + for (int col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col); col < width - 5; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = (eps + (fabsf(rgb[1][indx - v1] - rgb[1][indx - v3]) + fabsf(rgb[c][indx] - rgb[c][indx - v2])) / 65535.f);; + eg = (eps + (fabsf(rgb[1][indx + h1] - rgb[1][indx + h3]) + fabsf(rgb[c][indx] - rgb[c][indx + h2])) / 65535.f); + wg = (eps + (fabsf(rgb[1][indx - h1] - rgb[1][indx - h3]) + fabsf(rgb[c][indx] - rgb[c][indx - h2])) / 65535.f); + sg = (eps + (fabsf(rgb[1][indx + v1] - rgb[1][indx + v3]) + fabsf(rgb[c][indx] - rgb[c][indx + v2])) / 65535.f); + //N,E,W,S High Order Interpolation (Li & Randhawa) + //N,E,W,S Hamilton Adams Interpolation + // (48.f * 65535.f) = 3145680.f + nv = LIM(((23.0f * rgb[1][indx - v1] + 23.0f * rgb[1][indx - v3] + rgb[1][indx - v5] + rgb[1][indx + v1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx - v2] - 8.0f * rgb[c][indx - v4])) / 3145680.f, 0.0f, 1.0f); + ev = LIM(((23.0f * rgb[1][indx + h1] + 23.0f * rgb[1][indx + h3] + rgb[1][indx + h5] + rgb[1][indx - h1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx + h2] - 8.0f * rgb[c][indx + h4])) / 3145680.f, 0.0f, 1.0f); + wv = LIM(((23.0f * rgb[1][indx - h1] + 23.0f * rgb[1][indx - h3] + rgb[1][indx - h5] + rgb[1][indx + h1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx - h2] - 8.0f * rgb[c][indx - h4])) / 3145680.f, 0.0f, 1.0f); + sv = LIM(((23.0f * rgb[1][indx + v1] + 23.0f * rgb[1][indx + v3] + rgb[1][indx + v5] + rgb[1][indx - v1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx + v2] - 8.0f * rgb[c][indx + v4])) / 3145680.f, 0.0f, 1.0f); + //Horizontal and vertical color differences + vdif[indx >> 1] = (sg * nv + ng * sv) / (ng + sg) - (rgb[c][indx]) / 65535.f; + hdif[indx >> 1] = (wg * ev + eg * wv) / (eg + wg) - (rgb[c][indx]) / 65535.f; + } #ifdef _OPENMP -#pragma omp for + #pragma omp single #endif - for (int row=7; row>1])+69.0f*(SQR(vdif[(indx-v2)>>1])+SQR(vdif[(indx+v2)>>1]))+51.0f*(SQR(vdif[(indx-v4)>>1])+SQR(vdif[(indx+v4)>>1]))+21.0f*(SQR(vdif[(indx-v6)>>1])+SQR(vdif[(indx+v6)>>1]))-6.0f*SQR(vdif[(indx-v2)>>1]+vdif[indx>>1]+vdif[(indx+v2)>>1]) - -10.0f*(SQR(vdif[(indx-v4)>>1]+vdif[(indx-v2)>>1]+vdif[indx>>1])+SQR(vdif[indx>>1]+vdif[(indx+v2)>>1]+vdif[(indx+v4)>>1]))-7.0f*(SQR(vdif[(indx-v6)>>1]+vdif[(indx-v4)>>1]+vdif[(indx-v2)>>1])+SQR(vdif[(indx+v2)>>1]+vdif[(indx+v4)>>1]+vdif[(indx+v6)>>1])),0.f,1.f); - eg=LIM(epssq+78.0f*SQR(hdif[indx>>1])+69.0f*(SQR(hdif[(indx-h2)>>1])+SQR(hdif[(indx+h2)>>1]))+51.0f*(SQR(hdif[(indx-h4)>>1])+SQR(hdif[(indx+h4)>>1]))+21.0f*(SQR(hdif[(indx-h6)>>1])+SQR(hdif[(indx+h6)>>1]))-6.0f*SQR(hdif[(indx-h2)>>1]+hdif[indx>>1]+hdif[(indx+h2)>>1]) - -10.0f*(SQR(hdif[(indx-h4)>>1]+hdif[(indx-h2)>>1]+hdif[indx>>1])+SQR(hdif[indx>>1]+hdif[(indx+h2)>>1]+hdif[(indx+h4)>>1]))-7.0f*(SQR(hdif[(indx-h6)>>1]+hdif[(indx-h4)>>1]+hdif[(indx-h2)>>1])+SQR(hdif[(indx+h2)>>1]+hdif[(indx+h4)>>1]+hdif[(indx+h6)>>1])),0.f,1.f); - //Limit chrominance using H/V neighbourhood - nv=ULIM(0.725f*vdif[indx>>1]+0.1375f*vdif[(indx-v2)>>1]+0.1375f*vdif[(indx+v2)>>1],vdif[(indx-v2)>>1],vdif[(indx+v2)>>1]); - ev=ULIM(0.725f*hdif[indx>>1]+0.1375f*hdif[(indx-h2)>>1]+0.1375f*hdif[(indx+h2)>>1],hdif[(indx-h2)>>1],hdif[(indx+h2)>>1]); - //Chrominance estimation - chr[d][indx]=(eg*nv+ng*ev)/(ng+eg); - //Green channel population - rgb[1][indx]=rgb[c][indx]+65535.f*chr[d][indx]; - } + { + if (plistener) { + plistener->setProgress (0.26); + } + } #ifdef _OPENMP -#pragma omp single + #pragma omp for #endif -{ - if (plistener) plistener->setProgress (0.39); -} -// free(vdif); free(hdif); -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; rowsetProgress (0.52); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=8; rowsetProgress (0.65); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; rowsetProgress (0.78); -} -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=7; rowsetProgress (0.91); - - //Interpolate borders -// border_interpolate2(7, rgb); -} -/* -#ifdef _OPENMP -#pragma omp for -#endif - for (int row=0; row < height; row++) //borders - for (int col=0; col < width; col++) { - if (col==7 && row >= 7 && row < height-7) - col = width-7; - int indxc=row*width+col; - red [row][col] = rgb[indxc][0]; - green[row][col] = rgb[indxc][1]; - blue [row][col] = rgb[indxc][2]; - } -*/ + for (int row = 7; row < height - 7; row++) + for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col), d = c / 2; col < width - 7; col += 2, indx += 2) { + //H&V integrated gaussian vector over variance on color differences + //Mod Jacques 3/2013 + ng = LIM(epssq + 78.0f * SQR(vdif[indx >> 1]) + 69.0f * (SQR(vdif[(indx - v2) >> 1]) + SQR(vdif[(indx + v2) >> 1])) + 51.0f * (SQR(vdif[(indx - v4) >> 1]) + SQR(vdif[(indx + v4) >> 1])) + 21.0f * (SQR(vdif[(indx - v6) >> 1]) + SQR(vdif[(indx + v6) >> 1])) - 6.0f * SQR(vdif[(indx - v2) >> 1] + vdif[indx >> 1] + vdif[(indx + v2) >> 1]) + - 10.0f * (SQR(vdif[(indx - v4) >> 1] + vdif[(indx - v2) >> 1] + vdif[indx >> 1]) + SQR(vdif[indx >> 1] + vdif[(indx + v2) >> 1] + vdif[(indx + v4) >> 1])) - 7.0f * (SQR(vdif[(indx - v6) >> 1] + vdif[(indx - v4) >> 1] + vdif[(indx - v2) >> 1]) + SQR(vdif[(indx + v2) >> 1] + vdif[(indx + v4) >> 1] + vdif[(indx + v6) >> 1])), 0.f, 1.f); + eg = LIM(epssq + 78.0f * SQR(hdif[indx >> 1]) + 69.0f * (SQR(hdif[(indx - h2) >> 1]) + SQR(hdif[(indx + h2) >> 1])) + 51.0f * (SQR(hdif[(indx - h4) >> 1]) + SQR(hdif[(indx + h4) >> 1])) + 21.0f * (SQR(hdif[(indx - h6) >> 1]) + SQR(hdif[(indx + h6) >> 1])) - 6.0f * SQR(hdif[(indx - h2) >> 1] + hdif[indx >> 1] + hdif[(indx + h2) >> 1]) + - 10.0f * (SQR(hdif[(indx - h4) >> 1] + hdif[(indx - h2) >> 1] + hdif[indx >> 1]) + SQR(hdif[indx >> 1] + hdif[(indx + h2) >> 1] + hdif[(indx + h4) >> 1])) - 7.0f * (SQR(hdif[(indx - h6) >> 1] + hdif[(indx - h4) >> 1] + hdif[(indx - h2) >> 1]) + SQR(hdif[(indx + h2) >> 1] + hdif[(indx + h4) >> 1] + hdif[(indx + h6) >> 1])), 0.f, 1.f); + //Limit chrominance using H/V neighbourhood + nv = ULIM(0.725f * vdif[indx >> 1] + 0.1375f * vdif[(indx - v2) >> 1] + 0.1375f * vdif[(indx + v2) >> 1], vdif[(indx - v2) >> 1], vdif[(indx + v2) >> 1]); + ev = ULIM(0.725f * hdif[indx >> 1] + 0.1375f * hdif[(indx - h2) >> 1] + 0.1375f * hdif[(indx + h2) >> 1], hdif[(indx - h2) >> 1], hdif[(indx + h2) >> 1]); + //Chrominance estimation + chr[d][indx] = (eg * nv + ng * ev) / (ng + eg); + //Green channel population + rgb[1][indx] = rgb[c][indx] + 65535.f * chr[d][indx]; + } #ifdef _OPENMP -#pragma omp for + #pragma omp single #endif - for(int row=7; rowsetProgress (0.39); + } + } - if (plistener) plistener->setProgress (1.0); +// free(vdif); free(hdif); +#ifdef _OPENMP + #pragma omp for +#endif - free(chrarray); free(rgbarray); - free(vdif); free(hdif); + for (int row = 7; row < height - 7; row += 2) + for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 7; col += 2, indx += 2) { + //NW,NE,SW,SE Gradients + nwg = 1.0f / (eps + fabsf(chr[c][indx - v1 - h1] - chr[c][indx - v3 - h3]) + fabsf(chr[c][indx + v1 + h1] - chr[c][indx - v3 - h3])); + neg = 1.0f / (eps + fabsf(chr[c][indx - v1 + h1] - chr[c][indx - v3 + h3]) + fabsf(chr[c][indx + v1 - h1] - chr[c][indx - v3 + h3])); + swg = 1.0f / (eps + fabsf(chr[c][indx + v1 - h1] - chr[c][indx + v3 + h3]) + fabsf(chr[c][indx - v1 + h1] - chr[c][indx + v3 - h3])); + seg = 1.0f / (eps + fabsf(chr[c][indx + v1 + h1] - chr[c][indx + v3 - h3]) + fabsf(chr[c][indx - v1 - h1] - chr[c][indx + v3 + h3])); + //Limit NW,NE,SW,SE Color differences + nwv = ULIM(chr[c][indx - v1 - h1], chr[c][indx - v3 - h1], chr[c][indx - v1 - h3]); + nev = ULIM(chr[c][indx - v1 + h1], chr[c][indx - v3 + h1], chr[c][indx - v1 + h3]); + swv = ULIM(chr[c][indx + v1 - h1], chr[c][indx + v3 - h1], chr[c][indx + v1 - h3]); + sev = ULIM(chr[c][indx + v1 + h1], chr[c][indx + v3 + h1], chr[c][indx + v1 + h3]); + //Interpolate chrominance: R@B and B@R + chr[c][indx] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.52); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 8; row < height - 7; row += 2) + for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 7; col += 2, indx += 2) { + //NW,NE,SW,SE Gradients + nwg = 1.0f / (eps + fabsf(chr[c][indx - v1 - h1] - chr[c][indx - v3 - h3]) + fabsf(chr[c][indx + v1 + h1] - chr[c][indx - v3 - h3])); + neg = 1.0f / (eps + fabsf(chr[c][indx - v1 + h1] - chr[c][indx - v3 + h3]) + fabsf(chr[c][indx + v1 - h1] - chr[c][indx - v3 + h3])); + swg = 1.0f / (eps + fabsf(chr[c][indx + v1 - h1] - chr[c][indx + v3 + h3]) + fabsf(chr[c][indx - v1 + h1] - chr[c][indx + v3 - h3])); + seg = 1.0f / (eps + fabsf(chr[c][indx + v1 + h1] - chr[c][indx + v3 - h3]) + fabsf(chr[c][indx - v1 - h1] - chr[c][indx + v3 + h3])); + //Limit NW,NE,SW,SE Color differences + nwv = ULIM(chr[c][indx - v1 - h1], chr[c][indx - v3 - h1], chr[c][indx - v1 - h3]); + nev = ULIM(chr[c][indx - v1 + h1], chr[c][indx - v3 + h1], chr[c][indx - v1 + h3]); + swv = ULIM(chr[c][indx + v1 - h1], chr[c][indx + v3 - h1], chr[c][indx + v1 - h3]); + sev = ULIM(chr[c][indx + v1 + h1], chr[c][indx + v3 + h1], chr[c][indx + v1 + h3]); + //Interpolate chrominance: R@B and B@R + chr[c][indx] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.65); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) + for (int col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 7; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[0][indx - v1] - chr[0][indx - v3]) + fabsf(chr[0][indx + v1] - chr[0][indx - v3])); + eg = 1.0f / (eps + fabsf(chr[0][indx + h1] - chr[0][indx + h3]) + fabsf(chr[0][indx - h1] - chr[0][indx + h3])); + wg = 1.0f / (eps + fabsf(chr[0][indx - h1] - chr[0][indx - h3]) + fabsf(chr[0][indx + h1] - chr[0][indx - h3])); + sg = 1.0f / (eps + fabsf(chr[0][indx + v1] - chr[0][indx + v3]) + fabsf(chr[0][indx - v1] - chr[0][indx + v3])); + //Interpolate chrominance: R@G and B@G + chr[0][indx] = ((ng * chr[0][indx - v1] + eg * chr[0][indx + h1] + wg * chr[0][indx - h1] + sg * chr[0][indx + v1]) / (ng + eg + wg + sg)); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.78); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) + for (int col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 7; col += 2, indx += 2) { + + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[1][indx - v1] - chr[1][indx - v3]) + fabsf(chr[1][indx + v1] - chr[1][indx - v3])); + eg = 1.0f / (eps + fabsf(chr[1][indx + h1] - chr[1][indx + h3]) + fabsf(chr[1][indx - h1] - chr[1][indx + h3])); + wg = 1.0f / (eps + fabsf(chr[1][indx - h1] - chr[1][indx - h3]) + fabsf(chr[1][indx + h1] - chr[1][indx - h3])); + sg = 1.0f / (eps + fabsf(chr[1][indx + v1] - chr[1][indx + v3]) + fabsf(chr[1][indx - v1] - chr[1][indx + v3])); + //Interpolate chrominance: R@G and B@G + chr[1][indx] = ((ng * chr[1][indx - v1] + eg * chr[1][indx + h1] + wg * chr[1][indx - h1] + sg * chr[1][indx + v1]) / (ng + eg + wg + sg)); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.91); + } + + //Interpolate borders +// border_interpolate2(7, rgb); + } + /* +#ifdef _OPENMP + #pragma omp for +#endif + for (int row=0; row < height; row++) //borders + for (int col=0; col < width; col++) { + if (col==7 && row >= 7 && row < height-7) + col = width-7; + int indxc=row*width+col; + red [row][col] = rgb[indxc][0]; + green[row][col] = rgb[indxc][1]; + blue [row][col] = rgb[indxc][2]; + } + */ + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int row = 7; row < height - 7; row++) + for(int col = 7, indx = row * width + col; col < width - 7; col++, indx++) { + red [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[0][indx]); + green[row][col] = CLIP(rgb[1][indx]); + blue [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[1][indx]); + } + }// End of parallelization + + if (plistener) { + plistener->setProgress (1.0); + } + + free(chrarray); + free(rgbarray); + free(vdif); + free(hdif); } #endif @@ -2322,7 +2706,7 @@ void RawImageSource::igv_interpolate(int winw, int winh) Adaptive Homogeneity-Directed interpolation is based on the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. */ -#define TS 256 /* Tile Size */ +#define TS 256 /* Tile Size */ #define FORC(cnt) for (c=0; c < cnt; c++) #define FORC3 FORC(3) @@ -2340,7 +2724,7 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) char (*homo)[TS][TS], *buffer; double r; - int width=W, height=H; + int width = W, height = H; float (*image)[4]; int colors = 3; @@ -2357,70 +2741,77 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) plistener->setProgress (0.0); } - image = (float (*)[4]) calloc (H*W, sizeof *image); - for (int ii=0; ii 0.008856 ? pow(r,0.333333333) : 7.787*r + 16/116.0; + cbrt[i] = r > 0.008856 ? pow(r, 0.333333333) : 7.787 * r + 16 / 116.0; } - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (xyz_cam[i][j] = k=0; k < 3; k++) - xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i]; + for (i = 0; i < 3; i++) + for (j = 0; j < colors; j++) + for (xyz_cam[i][j] = k = 0; k < 3; k++) { + xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i]; + } border_interpolate(5, image); - buffer = (char *) malloc (13*TS*TS*sizeof(float)); /* 1664 kB */ + buffer = (char *) malloc (13 * TS * TS * sizeof(float)); /* 1664 kB */ //merror (buffer, "ahd_interpolate()"); rgb = (float(*)[TS][TS][3]) buffer; - lab = (float(*)[TS][TS][3])(buffer + 6*TS*TS*sizeof(float)); - homo = (char (*)[TS][TS]) (buffer + 12*TS*TS*sizeof(float)); + lab = (float(*)[TS][TS][3])(buffer + 6 * TS * TS * sizeof(float)); + homo = (char (*)[TS][TS]) (buffer + 12 * TS * TS * sizeof(float)); // helper variables for progress indication - int n_tiles = ((height-7 + (TS-7))/(TS-6)) * ((width-7 + (TS-7))/(TS-6)); + int n_tiles = ((height - 7 + (TS - 7)) / (TS - 6)) * ((width - 7 + (TS - 7)) / (TS - 6)); int tile = 0; - for (top=2; top < height-5; top += TS-6) - for (left=2; left < width-5; left += TS-6) { - /* Interpolate green horizontally and vertically: */ - for (row = top; row < top+TS && row < height-2; row++) { - col = left + (FC(row,left) & 1); - for (c = FC(row,col); col < left+TS && col < width-2; col+=2) { - pix = image + (row*width+col); - val = 0.25*((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 - - pix[-2][c] - pix[2][c]) ; - rgb[0][row-top][col-left][1] = ULIM(static_cast(val),pix[-1][1],pix[1][1]); - val = 0.25*((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - - pix[-2*width][c] - pix[2*width][c]) ; - rgb[1][row-top][col-left][1] = ULIM(static_cast(val),pix[-width][1],pix[width][1]); + for (top = 2; top < height - 5; top += TS - 6) + for (left = 2; left < width - 5; left += TS - 6) { + /* Interpolate green horizontally and vertically: */ + for (row = top; row < top + TS && row < height - 2; row++) { + col = left + (FC(row, left) & 1); + + for (c = FC(row, col); col < left + TS && col < width - 2; col += 2) { + pix = image + (row * width + col); + val = 0.25 * ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 + - pix[-2][c] - pix[2][c]) ; + rgb[0][row - top][col - left][1] = ULIM(static_cast(val), pix[-1][1], pix[1][1]); + val = 0.25 * ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 + - pix[-2 * width][c] - pix[2 * width][c]) ; + rgb[1][row - top][col - left][1] = ULIM(static_cast(val), pix[-width][1], pix[width][1]); } } - /* Interpolate red and blue, and convert to CIELab: */ - for (d=0; d < 2; d++) - for (row=top+1; row < top+TS-1 && row < height-3; row++) - for (col=left+1; col < left+TS-1 && col < width-3; col++) { - pix = image + (row*width+col); - rix = &rgb[d][row-top][col-left]; - lix = &lab[d][row-top][col-left]; - if ((c = 2 - FC(row,col)) == 1) { - c = FC(row+1,col); - val = pix[0][1] + (0.5*( pix[-1][2-c] + pix[1][2-c] - - rix[-1][1] - rix[1][1] ) ); - rix[0][2-c] = CLIP(val); - val = pix[0][1] + (0.5*( pix[-width][c] + pix[width][c] - - rix[-TS][1] - rix[TS][1] ) ); + /* Interpolate red and blue, and convert to CIELab: */ + for (d = 0; d < 2; d++) + for (row = top + 1; row < top + TS - 1 && row < height - 3; row++) + for (col = left + 1; col < left + TS - 1 && col < width - 3; col++) { + pix = image + (row * width + col); + rix = &rgb[d][row - top][col - left]; + lix = &lab[d][row - top][col - left]; + + if ((c = 2 - FC(row, col)) == 1) { + c = FC(row + 1, col); + val = pix[0][1] + (0.5 * ( pix[-1][2 - c] + pix[1][2 - c] + - rix[-1][1] - rix[1][1] ) ); + rix[0][2 - c] = CLIP(val); + val = pix[0][1] + (0.5 * ( pix[-width][c] + pix[width][c] + - rix[-TS][1] - rix[TS][1] ) ); } else - val = rix[0][1] + (0.25*( pix[-width-1][c] + pix[-width+1][c] - + pix[+width-1][c] + pix[+width+1][c] - - rix[-TS-1][1] - rix[-TS+1][1] - - rix[+TS-1][1] - rix[+TS+1][1]) ); + val = rix[0][1] + (0.25 * ( pix[-width - 1][c] + pix[-width + 1][c] + + pix[+width - 1][c] + pix[+width + 1][c] + - rix[-TS - 1][1] - rix[-TS + 1][1] + - rix[+TS - 1][1] - rix[+TS + 1][1]) ); + rix[0][c] = CLIP(val); - c = FC(row,col); + c = FC(row, col); rix[0][c] = pix[0][c]; xyz[0] = xyz[1] = xyz[2] = 0.0; FORCC { @@ -2429,9 +2820,9 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) xyz[2] += xyz_cam[2][c] * rix[0][c]; } - xyz[0] = CurveFactory::flinterp(cbrt,xyz[0]); - xyz[1] = CurveFactory::flinterp(cbrt,xyz[1]); - xyz[2] = CurveFactory::flinterp(cbrt,xyz[2]); + xyz[0] = CurveFactory::flinterp(cbrt, xyz[0]); + xyz[1] = CurveFactory::flinterp(cbrt, xyz[1]); + xyz[2] = CurveFactory::flinterp(cbrt, xyz[2]); //xyz[0] = xyz[0] > 0.008856 ? pow(xyz[0]/65535,1/3.0) : 7.787*xyz[0] + 16/116.0; //xyz[1] = xyz[1] > 0.008856 ? pow(xyz[1]/65535,1/3.0) : 7.787*xyz[1] + 16/116.0; @@ -2443,60 +2834,76 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) } /* Build homogeneity maps from the CIELab images: */ - memset (homo, 0, 2*TS*TS); - for (row=top+2; row < top+TS-2 && row < height-4; row++) { - tr = row-top; - for (col=left+2; col < left+TS-2 && col < width-4; col++) { - tc = col-left; - for (d=0; d < 2; d++) { + memset (homo, 0, 2 * TS * TS); + + for (row = top + 2; row < top + TS - 2 && row < height - 4; row++) { + tr = row - top; + + for (col = left + 2; col < left + TS - 2 && col < width - 4; col++) { + tc = col - left; + + for (d = 0; d < 2; d++) { lix = &lab[d][tr][tc]; - for (i=0; i < 4; i++) { - ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]); - abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1]) - + SQR(lix[0][2]-lix[dir[i]][2]); + + for (i = 0; i < 4; i++) { + ldiff[d][i] = ABS(lix[0][0] - lix[dir[i]][0]); + abdiff[d][i] = SQR(lix[0][1] - lix[dir[i]][1]) + + SQR(lix[0][2] - lix[dir[i]][2]); } } - leps = min(max(ldiff[0][0],ldiff[0][1]), - max(ldiff[1][2],ldiff[1][3])); - abeps = min(max(abdiff[0][0],abdiff[0][1]), - max(abdiff[1][2],abdiff[1][3])); - for (d=0; d < 2; d++) - for (i=0; i < 4; i++) - if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) + + leps = min(max(ldiff[0][0], ldiff[0][1]), + max(ldiff[1][2], ldiff[1][3])); + abeps = min(max(abdiff[0][0], abdiff[0][1]), + max(abdiff[1][2], abdiff[1][3])); + + for (d = 0; d < 2; d++) + for (i = 0; i < 4; i++) + if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) { homo[d][tr][tc]++; + } } } - /* Combine the most homogenous pixels for the final result: */ - for (row=top+3; row < top+TS-3 && row < height-5; row++) { - tr = row-top; - for (col=left+3; col < left+TS-3 && col < width-5; col++) { - tc = col-left; - for (d=0; d < 2; d++) - for (hm[d]=0, i=tr-1; i <= tr+1; i++) - for (j=tc-1; j <= tc+1; j++) + /* Combine the most homogenous pixels for the final result: */ + for (row = top + 3; row < top + TS - 3 && row < height - 5; row++) { + tr = row - top; + + for (col = left + 3; col < left + TS - 3 && col < width - 5; col++) { + tc = col - left; + + for (d = 0; d < 2; d++) + for (hm[d] = 0, i = tr - 1; i <= tr + 1; i++) + for (j = tc - 1; j <= tc + 1; j++) { hm[d] += homo[d][i][j]; - if (hm[0] != hm[1]) - FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; - else - FORC3 image[row*width+col][c] = - 0.5*(rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; + } + + if (hm[0] != hm[1]) { + FORC3 image[row * width + col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; + } else + FORC3 image[row * width + col][c] = + 0.5 * (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; } } tile++; + if(plistener) { plistener->setProgress((double)tile / n_tiles); } } - if(plistener) plistener->setProgress (1.0); + if(plistener) { + plistener->setProgress (1.0); + } + free (buffer); - for (int i=0; igetSensorType()!=ST_FUJI_XTRANS){ - switch( FC(i,j)) { - case 0: red[i][j] = rawData[i][j]; green[i][j]=blue[i][j]=0; break; - case 1: green[i][j] = rawData[i][j]; red[i][j]=blue[i][j]=0; break; - case 2: blue[i][j] = rawData[i][j]; red[i][j]=green[i][j]=0; break; + } else if(ri->getSensorType() != ST_FUJI_XTRANS) { + switch( FC(i, j)) { + case 0: + red[i][j] = rawData[i][j]; + green[i][j] = blue[i][j] = 0; + break; + + case 1: + green[i][j] = rawData[i][j]; + red[i][j] = blue[i][j] = 0; + break; + + case 2: + blue[i][j] = rawData[i][j]; + red[i][j] = green[i][j] = 0; + break; } } else { - switch( ri->XTRANSFC(i,j)) { - case 0: red[i][j] = rawData[i][j]; green[i][j]=blue[i][j]=0; break; - case 1: green[i][j] = rawData[i][j]; red[i][j]=blue[i][j]=0; break; - case 2: blue[i][j] = rawData[i][j]; red[i][j]=green[i][j]=0; break; + switch( ri->XTRANSFC(i, j)) { + case 0: + red[i][j] = rawData[i][j]; + green[i][j] = blue[i][j] = 0; + break; + + case 1: + green[i][j] = rawData[i][j]; + red[i][j] = blue[i][j] = 0; + break; + + case 2: + blue[i][j] = rawData[i][j]; + red[i][j] = green[i][j] = 0; + break; } } } @@ -2543,154 +2973,175 @@ void RawImageSource::nodemosaic(bool bw) #endif SSEFUNCTION void RawImageSource::refinement(int PassCount) { - MyTime t1e,t2e; + MyTime t1e, t2e; t1e.set(); - int width=W; - int height=H; - int w1 = width; - int w2 = 2*w1; - if (plistener) { - plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); - } + int width = W; + int height = H; + int w1 = width; + int w2 = 2 * w1; - array2D *rgb[3]; - rgb[0] = &red; - rgb[1] = &green; - rgb[2] = &blue; + if (plistener) { + plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); + } - for (int b=0; bsetProgress ((float)b/PassCount); - } + array2D *rgb[3]; + rgb[0] = &red; + rgb[1] = &green; + rgb[2] = &blue; + + for (int b = 0; b < PassCount; b++) { + if (plistener) { + plistener->setProgress ((float)b / PassCount); + } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - float *pix[3]; + { + float *pix[3]; - /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ + /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int row=2; row < height-2; row++) { - int col = 2+(FC(row,2) & 1); - int c = FC(row,col); + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 2) & 1); + int c = FC(row, col); #ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - for (; col < width-8; col+=8) { - int indx = row*width+col; - pix[c] = (float*)(*rgb[c]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - dLv = onev/(onev+vabsf(LC2VFU(pix[c][ -2])-LC2VFU(pix[c][0]))+vabsf(LC2VFU(pix[1][ 1])-LC2VFU(pix[1][ -1]))); - dRv = onev/(onev+vabsf(LC2VFU(pix[c][ 2])-LC2VFU(pix[c][0]))+vabsf(LC2VFU(pix[1][ 1])-LC2VFU(pix[1][ -1]))); - dUv = onev/(onev+vabsf(LC2VFU(pix[c][-w2])-LC2VFU(pix[c][0]))+vabsf(LC2VFU(pix[1][w1])-LC2VFU(pix[1][-w1]))); - dDv = onev/(onev+vabsf(LC2VFU(pix[c][ w2])-LC2VFU(pix[c][0]))+vabsf(LC2VFU(pix[1][w1])-LC2VFU(pix[1][-w1]))); - v0v = CLIPV(LC2VFU(pix[c][0]) + zd5v +((LC2VFU(pix[1][-1])-LC2VFU(pix[c][-1]))*dLv +(LC2VFU(pix[1][1])-LC2VFU(pix[c][1]))*dRv +(LC2VFU(pix[1][-w1])-LC2VFU(pix[c][-w1]))*dUv + (LC2VFU(pix[1][w1])-LC2VFU(pix[c][w1]))*dDv ) / (dLv+dRv+dUv+dDv)); - STC2VFU(pix[1][0],v0v); - } + __m128 dLv, dRv, dUv, dDv, v0v; + __m128 onev = _mm_set1_ps(1.f); + __m128 zd5v = _mm_set1_ps(0.5f); + __m128 c65535v = _mm_set1_ps(65535.f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[c] = (float*)(*rgb[c]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + dLv = onev / (onev + vabsf(LC2VFU(pix[c][ -2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[c][ 2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[c][-w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[c][ w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + v0v = CLIPV(LC2VFU(pix[c][0]) + zd5v + ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[1][0], v0v); + } + #endif - for (; col < width-2; col+=2) { - int indx = row*width+col; - pix[c] = (float*)(*rgb[c]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - float dL = 1.f/(1.f+fabsf(pix[c][ -2]-pix[c][0])+fabsf(pix[1][ 1]-pix[1][ -1])); - float dR = 1.f/(1.f+fabsf(pix[c][ 2]-pix[c][0])+fabsf(pix[1][ 1]-pix[1][ -1])); - float dU = 1.f/(1.f+fabsf(pix[c][-w2]-pix[c][0])+fabsf(pix[1][w1]-pix[1][-w1])); - float dD = 1.f/(1.f+fabsf(pix[c][ w2]-pix[c][0])+fabsf(pix[1][w1]-pix[1][-w1])); - float v0 = (pix[c][0] + 0.5f +((pix[1][ -1]-pix[c][ -1])*dL +(pix[1][ 1]-pix[c][ 1])*dR +(pix[1][-w1]-pix[c][-w1])*dU + (pix[1][ w1]-pix[c][ w1])*dD ) / (dL+dR+dU+dD)); - pix[1][0] = CLIP(v0); - } - } - /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[c] = (float*)(*rgb[c]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + float dL = 1.f / (1.f + fabsf(pix[c][ -2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dR = 1.f / (1.f + fabsf(pix[c][ 2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dU = 1.f / (1.f + fabsf(pix[c][-w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float dD = 1.f / (1.f + fabsf(pix[c][ w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float v0 = (pix[c][0] + 0.5f + ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[1][0] = CLIP(v0); + } + } + + /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int row=2; row < height-2; row++) { - int col = 2+(FC(row,3) & 1); - int c = FC(row,col+1); + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 3) & 1); + int c = FC(row, col + 1); #ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - for (; col < width-8; col+=8) { - int indx = row*width+col; - pix[1] = (float*)(*rgb[1]) + indx; - for (int i=0; i < 2; c=2-c, i++) { - pix[c] = (float*)(*rgb[c]) + indx; - dLv = onev/(onev+vabsf(LC2VFU(pix[1][ -2])-LC2VFU(pix[1][0]))+vabsf(LC2VFU(pix[c][ 1])-LC2VFU(pix[c][ -1]))); - dRv = onev/(onev+vabsf(LC2VFU(pix[1][ 2])-LC2VFU(pix[1][0]))+vabsf(LC2VFU(pix[c][ 1])-LC2VFU(pix[c][ -1]))); - dUv = onev/(onev+vabsf(LC2VFU(pix[1][-w2])-LC2VFU(pix[1][0]))+vabsf(LC2VFU(pix[c][w1])-LC2VFU(pix[c][-w1]))); - dDv = onev/(onev+vabsf(LC2VFU(pix[1][ w2])-LC2VFU(pix[1][0]))+vabsf(LC2VFU(pix[c][w1])-LC2VFU(pix[c][-w1]))); - v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v -((LC2VFU(pix[1][-1])-LC2VFU(pix[c][-1]))*dLv + (LC2VFU(pix[1][1])-LC2VFU(pix[c][1]))*dRv +(LC2VFU(pix[1][-w1])-LC2VFU(pix[c][-w1]))*dUv + (LC2VFU(pix[1][w1])-LC2VFU(pix[c][w1]))*dDv ) / (dLv+dRv+dUv+dDv)); - STC2VFU(pix[c][0],v0v); - } - } + __m128 dLv, dRv, dUv, dDv, v0v; + __m128 onev = _mm_set1_ps(1.f); + __m128 zd5v = _mm_set1_ps(0.5f); + __m128 c65535v = _mm_set1_ps(65535.f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[1] = (float*)(*rgb[1]) + indx; + + for (int i = 0; i < 2; c = 2 - c, i++) { + pix[c] = (float*)(*rgb[c]) + indx; + dLv = onev / (onev + vabsf(LC2VFU(pix[1][ -2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[1][ 2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[1][-w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[1][ w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); + v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[c][0], v0v); + } + } + #endif - for (; col < width-2; col+=2) { - int indx = row*width+col; - pix[1] = (float*)(*rgb[1]) + indx; - for (int i=0; i < 2; c=2-c, i++) { - pix[c] = (float*)(*rgb[c]) + indx; - float dL = 1.f/(1.f+fabsf(pix[1][ -2]-pix[1][0])+fabsf(pix[c][ 1]-pix[c][ -1])); - float dR = 1.f/(1.f+fabsf(pix[1][ 2]-pix[1][0])+fabsf(pix[c][ 1]-pix[c][ -1])); - float dU = 1.f/(1.f+fabsf(pix[1][-w2]-pix[1][0])+fabsf(pix[c][w1]-pix[c][-w1])); - float dD = 1.f/(1.f+fabsf(pix[1][ w2]-pix[1][0])+fabsf(pix[c][w1]-pix[c][-w1])); - float v0 = (pix[1][0] + 0.5f -((pix[1][ -1]-pix[c][ -1])*dL + (pix[1][ 1]-pix[c][ 1])*dR +(pix[1][-w1]-pix[c][-w1])*dU + (pix[1][ w1]-pix[c][ w1])*dD ) / (dL+dR+dU+dD)); - pix[c][0] = CLIP(v0); - } - } - } - /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[1] = (float*)(*rgb[1]) + indx; + + for (int i = 0; i < 2; c = 2 - c, i++) { + pix[c] = (float*)(*rgb[c]) + indx; + float dL = 1.f / (1.f + fabsf(pix[1][ -2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); + float dR = 1.f / (1.f + fabsf(pix[1][ 2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); + float dU = 1.f / (1.f + fabsf(pix[1][-w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); + float dD = 1.f / (1.f + fabsf(pix[1][ w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); + float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[c][0] = CLIP(v0); + } + } + } + + /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int row=2; row < height-2; row++) { - int col = 2+(FC(row,2) & 1); - int c = 2-FC(row,col); + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 2) & 1); + int c = 2 - FC(row, col); #ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - for (; col < width-8; col+=8) { - int indx = row*width+col; - pix[0] = (float*)(*rgb[0]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - pix[2] = (float*)(*rgb[2]) + indx; - int d = 2 - c; - dLv = onev/(onev+vabsf(LC2VFU(pix[d][ -2])-LC2VFU(pix[d][0]))+vabsf(LC2VFU(pix[1][ 1])-LC2VFU(pix[1][ -1]))); - dRv = onev/(onev+vabsf(LC2VFU(pix[d][ 2])-LC2VFU(pix[d][0]))+vabsf(LC2VFU(pix[1][ 1])-LC2VFU(pix[1][ -1]))); - dUv = onev/(onev+vabsf(LC2VFU(pix[d][-w2])-LC2VFU(pix[d][0]))+vabsf(LC2VFU(pix[1][w1])-LC2VFU(pix[1][-w1]))); - dDv = onev/(onev+vabsf(LC2VFU(pix[d][ w2])-LC2VFU(pix[d][0]))+vabsf(LC2VFU(pix[1][w1])-LC2VFU(pix[1][-w1]))); - v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v -((LC2VFU(pix[1][-1])-LC2VFU(pix[c][-1]))*dLv +(LC2VFU(pix[1][1])-LC2VFU(pix[c][1]))*dRv +(LC2VFU(pix[1][-w1])-LC2VFU(pix[c][-w1]))*dUv + (LC2VFU(pix[1][w1])-LC2VFU(pix[c][w1]))*dDv ) / (dLv+dRv+dUv+dDv)); - STC2VFU(pix[c][0],v0v); - } + __m128 dLv, dRv, dUv, dDv, v0v; + __m128 onev = _mm_set1_ps(1.f); + __m128 zd5v = _mm_set1_ps(0.5f); + __m128 c65535v = _mm_set1_ps(65535.f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[0] = (float*)(*rgb[0]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + pix[2] = (float*)(*rgb[2]) + indx; + int d = 2 - c; + dLv = onev / (onev + vabsf(LC2VFU(pix[d][ -2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[d][ 2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[d][-w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[d][ w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[c][0], v0v); + } + #endif - for (; col < width-2; col+=2) { - int indx = row*width+col; - pix[0] = (float*)(*rgb[0]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - pix[2] = (float*)(*rgb[2]) + indx; - int d = 2 - c; - float dL = 1.f/(1.f+fabsf(pix[d][ -2]-pix[d][0])+fabsf(pix[1][ 1]-pix[1][ -1])); - float dR = 1.f/(1.f+fabsf(pix[d][ 2]-pix[d][0])+fabsf(pix[1][ 1]-pix[1][ -1])); - float dU = 1.f/(1.f+fabsf(pix[d][-w2]-pix[d][0])+fabsf(pix[1][w1]-pix[1][-w1])); - float dD = 1.f/(1.f+fabsf(pix[d][ w2]-pix[d][0])+fabsf(pix[1][w1]-pix[1][-w1])); - float v0 = (pix[1][0] + 0.5f -((pix[1][ -1]-pix[c][ -1])*dL +(pix[1][ 1]-pix[c][ 1])*dR +(pix[1][-w1]-pix[c][-w1])*dU + (pix[1][ w1]-pix[c][ w1])*dD ) / (dL+dR+dU+dD)); - pix[c][0] = CLIP(v0); - } - } -} // end parallel - } + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[0] = (float*)(*rgb[0]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + pix[2] = (float*)(*rgb[2]) + indx; + int d = 2 - c; + float dL = 1.f / (1.f + fabsf(pix[d][ -2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dR = 1.f / (1.f + fabsf(pix[d][ 2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dU = 1.f / (1.f + fabsf(pix[d][-w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float dD = 1.f / (1.f + fabsf(pix[d][ w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[c][0] = CLIP(v0); + } + } + } // end parallel + } + t2e.set(); - if (settings->verbose) printf("Refinement Lee %d usec\n", t2e.etime(t1e)); + + if (settings->verbose) { + printf("Refinement Lee %d usec\n", t2e.etime(t1e)); + } } #ifdef __SSE2__ #undef CLIPV @@ -2706,124 +3157,149 @@ SSEFUNCTION void RawImageSource::refinement(int PassCount) // Should be DISABLED if it decreases image quality by increases some image noise and generates blocky edges void RawImageSource::refinement_lassus(int PassCount) { - // const int PassCount=1; + // const int PassCount=1; - // if (settings->verbose) printf("Refinement\n"); + // if (settings->verbose) printf("Refinement\n"); - MyTime t1e,t2e; + MyTime t1e, t2e; t1e.set(); - int u=W, v=2*u, w=3*u, x=4*u, y=5*u; + int u = W, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u; float (*image)[3]; - image = (float(*)[3]) calloc(W*H, sizeof *image); + image = (float(*)[3]) calloc(W * H, sizeof * image); #ifdef _OPENMP -#pragma omp parallel shared(image) + #pragma omp parallel shared(image) #endif { // convert red, blue, green to image #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0;isetProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); - plistener->setProgress ((float)b/PassCount); + plistener->setProgress ((float)b / PassCount); } // Reinforce interpolated green pixels on RED/BLUE pixel locations #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int row=6; rowverbose) printf("Refinement Lassus %d usec\n", t2e.etime(t1e)); + + if (settings->verbose) { + printf("Refinement Lassus %d usec\n", t2e.etime(t1e)); + } } @@ -2891,176 +3371,198 @@ void RawImageSource::refinement_lassus(int PassCount) inline void RawImageSource::dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border) { - rowMin = border; - colMin = border; - rowMax = CACHESIZE-border; - colMax = CACHESIZE-border; - if(!y0 ) rowMin = TILEBORDER+border; - if(!x0 ) colMin = TILEBORDER+border; - if( y0+TILESIZE+TILEBORDER >= H-border) rowMax = TILEBORDER+H-border-y0; - if( x0+TILESIZE+TILEBORDER >= W-border) colMax = TILEBORDER+W-border-x0; + rowMin = border; + colMin = border; + rowMax = CACHESIZE - border; + colMax = CACHESIZE - border; + + if(!y0 ) { + rowMin = TILEBORDER + border; + } + + if(!x0 ) { + colMin = TILEBORDER + border; + } + + if( y0 + TILESIZE + TILEBORDER >= H - border) { + rowMax = TILEBORDER + H - border - y0; + } + + if( x0 + TILESIZE + TILEBORDER >= W - border) { + colMax = TILEBORDER + W - border - x0; + } } void RawImageSource::fill_raw( float (*cache )[4], int x0, int y0, float** rawData) { - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,0); + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 0); - for (int row=rowMin,y=y0-TILEBORDER+rowMin; row= border && col < W - border && row >= border && row < H - border){ - col = W - border; - if(col >= x0+TILESIZE+TILEBORDER ) - break; - } - memset(sum, 0, sizeof sum); - for (y = row - 1; y != row + 2; y++) - for (x = col - 1; x != col + 2; x++) - if (y < H && y< y0+TILESIZE+TILEBORDER && x < W && x0) - cache[(row-y0+TILEBORDER) * CACHESIZE +TILEBORDER + col-x0][c] = sum[c] / sum[c + 4]; - } - } + for (row = y0; row < y0 + TILESIZE + TILEBORDER && row < H; row++) { + for (col = x0; col < x0 + TILESIZE + TILEBORDER && col < W; col++) { + if (col >= border && col < W - border && row >= border && row < H - border) { + col = W - border; + + if(col >= x0 + TILESIZE + TILEBORDER ) { + break; + } + } + + memset(sum, 0, sizeof sum); + + for (y = row - 1; y != row + 2; y++) + for (x = col - 1; x != col + 2; x++) + if (y < H && y < y0 + TILESIZE + TILEBORDER && x < W && x < x0 + TILESIZE + TILEBORDER) { + f = fc(y, x); + sum[f] += cache[(y - y0 + TILEBORDER) * CACHESIZE + TILEBORDER + x - x0][f]; + sum[f + 4]++; + } + + f = fc(row, col); + FORCC + + if (c != f && sum[c + 4] > 0) { + cache[(row - y0 + TILEBORDER) * CACHESIZE + TILEBORDER + col - x0][c] = sum[c] / sum[c + 4]; + } + } + } } // saves red and blue void RawImageSource::copy_to_buffer( float (*buffer)[3], float (*image)[4]) { - for (int indx=0; indx < CACHESIZE*CACHESIZE; indx++) { - buffer[indx][0]=image[indx][0]; //R - buffer[indx][2]=image[indx][2]; //B - } + for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { + buffer[indx][0] = image[indx][0]; //R + buffer[indx][2] = image[indx][2]; //B + } } // restores red and blue void RawImageSource::restore_from_buffer(float (*image)[4], float (*buffer)[3]) { - for (int indx=0; indx < CACHESIZE*CACHESIZE; indx++) { - image[indx][0]=buffer[indx][0]; //R - image[indx][2]=buffer[indx][2]; //B - } + for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { + image[indx][0] = buffer[indx][0]; //R + image[indx][2] = buffer[indx][2]; //B + } } // First pass green interpolation -void RawImageSource::dcb_hid(float (*image)[4],float (*bufferH)[3], float (*bufferV)[3], int x0, int y0) +void RawImageSource::dcb_hid(float (*image)[4], float (*bufferH)[3], float (*bufferV)[3], int x0, int y0) { - const int u=CACHESIZE, v=2*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,2); + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - // green pixels - for (int row = rowMin; row < rowMax; row++) { - for (int col = colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin)&1),indx=row*CACHESIZE+col; col < colMax; col+=2, indx+=2) { - assert(indx-u>=0 && indx+u=0 && indx+u+1=0 && c<3); + // green pixels + for (int row = rowMin; row < rowMax; row++) { + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { + assert(indx - u >= 0 && indx + u < u * u); + bufferH[indx][1] = (image[indx - 1][1] + image[indx + 1][1]) * 0.5f; + bufferV[indx][1] = (image[indx + u][1] + image[indx - u][1]) * 0.5f; + } + } + + // red in blue pixel, blue in red pixel + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 2 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + assert(indx - u - 1 >= 0 && indx + u + 1 < u * u && c >= 0 && c < 3); bufferH[indx][c] = ( 4.f * bufferH[indx][1] - - bufferH[indx+u+1][1] - bufferH[indx+u-1][1] - bufferH[indx-u+1][1] - bufferH[indx-u-1][1] - + image[indx+u+1][c] + image[indx+u-1][c] + image[indx-u+1][c] + image[indx-u-1][c] ) * 0.25f; - bufferV[indx][c] = ( 4.f * bufferV[indx][1] - - bufferV[indx+u+1][1] - bufferV[indx+u-1][1] - bufferV[indx-u+1][1] - bufferV[indx-u-1][1] - + image[indx+u+1][c] + image[indx+u-1][c] + image[indx-u+1][c] + image[indx-u-1][c] ) * 0.25f; - } + - bufferH[indx + u + 1][1] - bufferH[indx + u - 1][1] - bufferH[indx - u + 1][1] - bufferH[indx - u - 1][1] + + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; + bufferV[indx][c] = ( 4.f * bufferV[indx][1] + - bufferV[indx + u + 1][1] - bufferV[indx + u - 1][1] - bufferV[indx - u + 1][1] - bufferV[indx - u - 1][1] + + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; + } - // red or blue in green pixels - for (int row=rowMin; row=0 && indx+u=0 && c<3 && d>=0 && d<3); - bufferH[indx][c] = (image[indx+1][c] + image[indx-1][c]) * 0.5f; - bufferH[indx][d] = (2.f * bufferH[indx][1] - bufferH[indx+u][1] - bufferH[indx-u][1] + image[indx+u][d] + image[indx-u][d]) * 0.5f; - bufferV[indx][c] = (2.f * bufferV[indx][1] - bufferV[indx+1][1] - bufferV[indx-1][1] + image[indx+1][c] + image[indx-1][c]) * 0.5f; - bufferV[indx][d] = (image[indx+u][d] + image[indx-u][d]) * 0.5f; - } + // red or blue in green pixels + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1), d = 2 - c; col < colMax; col += 2, indx += 2) { + assert(indx - u >= 0 && indx + u < u * u && c >= 0 && c < 3 && d >= 0 && d < 3); + bufferH[indx][c] = (image[indx + 1][c] + image[indx - 1][c]) * 0.5f; + bufferH[indx][d] = (2.f * bufferH[indx][1] - bufferH[indx + u][1] - bufferH[indx - u][1] + image[indx + u][d] + image[indx - u][d]) * 0.5f; + bufferV[indx][c] = (2.f * bufferV[indx][1] - bufferV[indx + 1][1] - bufferV[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) * 0.5f; + bufferV[indx][d] = (image[indx + u][d] + image[indx - u][d]) * 0.5f; + } // Decide green pixels for (int row = rowMin; row < rowMax; row++) - for (int col = colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin)&1),indx=row*CACHESIZE+col,c=FC(y0-TILEBORDER+row,x0-TILEBORDER+col),d=2-c; col < colMax; col+=2, indx+=2) { - float current = max(image[indx+v][c], image[indx-v][c], image[indx-2][c], image[indx+2][c]) - - min(image[indx+v][c], image[indx-v][c], image[indx-2][c], image[indx+2][c]) + - max(image[indx+1+u][d], image[indx+1-u][d], image[indx-1+u][d], image[indx-1-u][d]) - - min(image[indx+1+u][d], image[indx+1-u][d], image[indx-1+u][d], image[indx-1-u][d]); + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col), d = 2 - c; col < colMax; col += 2, indx += 2) { + float current = max(image[indx + v][c], image[indx - v][c], image[indx - 2][c], image[indx + 2][c]) - + min(image[indx + v][c], image[indx - v][c], image[indx - 2][c], image[indx + 2][c]) + + max(image[indx + 1 + u][d], image[indx + 1 - u][d], image[indx - 1 + u][d], image[indx - 1 - u][d]) - + min(image[indx + 1 + u][d], image[indx + 1 - u][d], image[indx - 1 + u][d], image[indx - 1 - u][d]); - float currentH = max(bufferH[indx+v][d], bufferH[indx-v][d], bufferH[indx-2][d], bufferH[indx+2][d]) - - min(bufferH[indx+v][d], bufferH[indx-v][d], bufferH[indx-2][d], bufferH[indx+2][d]) + - max(bufferH[indx+1+u][c], bufferH[indx+1-u][c], bufferH[indx-1+u][c], bufferH[indx-1-u][c]) - - min(bufferH[indx+1+u][c], bufferH[indx+1-u][c], bufferH[indx-1+u][c], bufferH[indx-1-u][c]); + float currentH = max(bufferH[indx + v][d], bufferH[indx - v][d], bufferH[indx - 2][d], bufferH[indx + 2][d]) - + min(bufferH[indx + v][d], bufferH[indx - v][d], bufferH[indx - 2][d], bufferH[indx + 2][d]) + + max(bufferH[indx + 1 + u][c], bufferH[indx + 1 - u][c], bufferH[indx - 1 + u][c], bufferH[indx - 1 - u][c]) - + min(bufferH[indx + 1 + u][c], bufferH[indx + 1 - u][c], bufferH[indx - 1 + u][c], bufferH[indx - 1 - u][c]); - float currentV = max(bufferV[indx+v][d], bufferV[indx-v][d], bufferV[indx-2][d], bufferV[indx+2][d]) - - min(bufferV[indx+v][d], bufferV[indx-v][d], bufferV[indx-2][d], bufferV[indx+2][d]) + - max(bufferV[indx+1+u][c], bufferV[indx+1-u][c], bufferV[indx-1+u][c], bufferV[indx-1-u][c]) - - min(bufferV[indx+1+u][c], bufferV[indx+1-u][c], bufferV[indx-1+u][c], bufferV[indx-1-u][c]); + float currentV = max(bufferV[indx + v][d], bufferV[indx - v][d], bufferV[indx - 2][d], bufferV[indx + 2][d]) - + min(bufferV[indx + v][d], bufferV[indx - v][d], bufferV[indx - 2][d], bufferV[indx + 2][d]) + + max(bufferV[indx + 1 + u][c], bufferV[indx + 1 - u][c], bufferV[indx - 1 + u][c], bufferV[indx - 1 - u][c]) - + min(bufferV[indx + 1 + u][c], bufferV[indx + 1 - u][c], bufferV[indx - 1 + u][c], bufferV[indx - 1 - u][c]); - assert(indx>=0 && indx= 0 && indx < u * u); + + if (ABS(current - currentH) < ABS(current - currentV)) { image[indx][1] = bufferH[indx][1]; - else + } else { image[indx][1] = bufferV[indx][1]; + } } } // missing colors are interpolated void RawImageSource::dcb_color(float (*image)[4], int x0, int y0) { - const int u=CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,1); + const int u = CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 1); - // red in blue pixel, blue in red pixel - for (int row=rowMin; row < rowMax; row++) - for (int col=colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin) & 1), indx=row*CACHESIZE+col, c=2-FC(y0-TILEBORDER+row,x0-TILEBORDER+col); col < colMax; col+=2, indx+=2) { - assert(indx>=0 && indx=0 && c<4); - image[indx][c] = ( 4.f * image[indx][1] - - image[indx+u+1][1] - image[indx+u-1][1] - image[indx-u+1][1] - image[indx-u-1][1] - + image[indx+u+1][c] + image[indx+u-1][c] + image[indx-u+1][c] + image[indx-u-1][c] ) * 0.25f; - } + // red in blue pixel, blue in red pixel + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 2 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + image[indx][c] = ( 4.f * image[indx][1] + - image[indx + u + 1][1] - image[indx + u - 1][1] - image[indx - u + 1][1] - image[indx - u - 1][1] + + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; + } - // red or blue in green pixels - for (int row=rowMin; row=0 && indx=0 && c<4); - image[indx][c] = (2.f * image[indx][1] - image[indx+1][1] - image[indx-1][1] + image[indx+1][c] + image[indx-1][c]) * 0.5f; - image[indx][d] = (2.f * image[indx][1] - image[indx+u][1] - image[indx-u][1] + image[indx+u][d] + image[indx-u][d]) * 0.5f; - } + // red or blue in green pixels + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1), d = 2 - c; col < colMax; col += 2, indx += 2) { + assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + image[indx][c] = (2.f * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) * 0.5f; + image[indx][d] = (2.f * image[indx][1] - image[indx + u][1] - image[indx - u][1] + image[indx + u][d] + image[indx - u][d]) * 0.5f; + } } // green correction void RawImageSource::dcb_hid2(float (*image)[4], int x0, int y0) { - const int u=CACHESIZE, v=2*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,2); + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - for (int row=rowMin; row < rowMax; row++) { - for (int col = colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin)&1),indx=row*CACHESIZE+col,c=FC(y0-TILEBORDER+row,x0-TILEBORDER+col); col < colMax; col+=2, indx+=2) { - assert(indx-v>=0 && indx+v= 0 && indx + v < u * u); + image[indx][1] = (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1]) * 0.25f + + image[indx][c] - ( image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c]) * 0.25f; + } + } } // green is used to create @@ -3070,425 +3572,459 @@ void RawImageSource::dcb_hid2(float (*image)[4], int x0, int y0) // saved in image[][3] void RawImageSource::dcb_map(float (*image)[4], int x0, int y0) { - const int u=4*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,2); + const int u = 4 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - for (int row=rowMin; row < rowMax; row++) { - for (int col=colMin, indx=row*CACHESIZE+col; col < colMax; col++, indx++) { - float *pix = &(image[indx][1]); + for (int row = rowMin; row < rowMax; row++) { + for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { + float *pix = &(image[indx][1]); - assert(indx>=0 && indx ( pix[-4] + pix[+4] + pix[-u] + pix[+u])/4 ) - image[indx][3] = ((min(pix[-4], pix[+4]) + pix[-4] + pix[+4] ) < (min(pix[-u], pix[+u]) + pix[-u] + pix[+u])); - else - image[indx][3] = ((max(pix[-4], pix[+4]) + pix[-4] + pix[+4] ) > (max(pix[-u], pix[+u]) + pix[-u] + pix[+u])); - } - } + assert(indx >= 0 && indx < u * u); + + if ( *pix > ( pix[-4] + pix[+4] + pix[-u] + pix[+u]) / 4 ) { + image[indx][3] = ((min(pix[-4], pix[+4]) + pix[-4] + pix[+4] ) < (min(pix[-u], pix[+u]) + pix[-u] + pix[+u])); + } else { + image[indx][3] = ((max(pix[-4], pix[+4]) + pix[-4] + pix[+4] ) > (max(pix[-u], pix[+u]) + pix[-u] + pix[+u])); + } + } + } } // interpolated green pixels are corrected using the map void RawImageSource::dcb_correction(float (*image)[4], int x0, int y0) { - const int u=CACHESIZE, v=2*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,2); + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - for (int row=rowMin; row < rowMax; row++) { - for (int col = colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin)&1),indx=row*CACHESIZE+col; col < colMax; col+=2, indx+=2) { - float current = 4.f * image[indx][3] + - 2.f * (image[indx+u][3] + image[indx-u][3] + image[indx+1][3] + image[indx-1][3]) + - image[indx+v][3] + image[indx-v][3] + image[indx+2][3] + image[indx-2][3]; + for (int row = rowMin; row < rowMax; row++) { + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { + float current = 4.f * image[indx][3] + + 2.f * (image[indx + u][3] + image[indx - u][3] + image[indx + 1][3] + image[indx - 1][3]) + + image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] + image[indx - 2][3]; - assert(indx>=0 && indx= 0 && indx < u * u); + image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) * 0.5f + current * (image[indx - u][1] + image[indx + u][1]) * 0.5f ) * 0.0625f; + } + } } // R and B smoothing using green contrast, all pixels except 2 pixel wide border void RawImageSource::dcb_pp(float (*image)[4], int x0, int y0) { - const int u=CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,2); + const int u = CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - for (int row=rowMin; row < rowMax; row++) - for (int col=colMin, indx=row*CACHESIZE+col; col < colMax; col++, indx++) { - //int r1 = ( image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0])/8; - //int g1 = ( image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1])/8; - //int b1 = ( image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2])/8; - float (*pix)[4] = image+(indx-u-1); - float r1 = (*pix)[0]; - float g1 = (*pix)[1]; - float b1 = (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix+=CACHESIZE-2; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix+=2; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix+=CACHESIZE-2; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - r1 *=0.125f; - g1 *=0.125f; - b1 *=0.125f; - r1 = r1 + ( image[indx][1] - g1 ); - b1 = b1 + ( image[indx][1] - g1 ); + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { + //int r1 = ( image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0])/8; + //int g1 = ( image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1])/8; + //int b1 = ( image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2])/8; + float (*pix)[4] = image + (indx - u - 1); + float r1 = (*pix)[0]; + float g1 = (*pix)[1]; + float b1 = (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix += CACHESIZE - 2; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix += 2; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix += CACHESIZE - 2; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + r1 *= 0.125f; + g1 *= 0.125f; + b1 *= 0.125f; + r1 = r1 + ( image[indx][1] - g1 ); + b1 = b1 + ( image[indx][1] - g1 ); - assert(indx>=0 && indx= 0 && indx < u * u); + image[indx][0] = r1; + image[indx][2] = b1; + } } // interpolated green pixels are corrected using the map // with correction void RawImageSource::dcb_correction2(float (*image)[4], int x0, int y0) { - const int u=CACHESIZE, v=2*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,4); + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); - for (int row=rowMin; row < rowMax; row++) { - for (int col = colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin)&1),indx=row*CACHESIZE+col,c=FC(y0-TILEBORDER+row,x0-TILEBORDER+col); col < colMax; col+=2, indx+=2) { - float current = 4.f * image[indx][3] + - 2.f * (image[indx+u][3] + image[indx-u][3] + image[indx+1][3] + image[indx-1][3]) + - image[indx+v][3] + image[indx-v][3] + image[indx+2][3] + image[indx-2][3]; + for (int row = rowMin; row < rowMax; row++) { + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + float current = 4.f * image[indx][3] + + 2.f * (image[indx + u][3] + image[indx - u][3] + image[indx + 1][3] + image[indx - 1][3]) + + image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] + image[indx - 2][3]; - assert(indx>=0 && indx= 0 && indx < u * u); + image[indx][1] = ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) * 0.5f + + image[indx][c] - (image[indx + 2][c] + image[indx - 2][c]) * 0.5f) + + current * ((image[indx - u][1] + image[indx + u][1]) * 0.5f + image[indx][c] - (image[indx + v][c] + image[indx - v][c]) * 0.5f)) * 0.0625f; + } + } } // image refinement void RawImageSource::dcb_refinement(float (*image)[4], int x0, int y0) { - const int u=CACHESIZE, v=2*CACHESIZE, w=3*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,4); + const int u = CACHESIZE, v = 2 * CACHESIZE, w = 3 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); - float f[5],g1,g2; + float f[5], g1, g2; - for (int row=rowMin; row < rowMax; row++) - for (int col=colMin+(FC(y0-TILEBORDER+row,x0-TILEBORDER+colMin)&1),indx=row*CACHESIZE+col,c=FC(y0-TILEBORDER+row,x0-TILEBORDER+col); col < colMax; col+=2,indx+=2){ - float current = 4.f * image[indx][3] + - 2.f * (image[indx+u][3] + image[indx-u][3] + image[indx+1][3] + image[indx-1][3]) - +image[indx+v][3] + image[indx-v][3] + image[indx-2][3] + image[indx+2][3]; + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + float current = 4.f * image[indx][3] + + 2.f * (image[indx + u][3] + image[indx - u][3] + image[indx + 1][3] + image[indx - 1][3]) + + image[indx + v][3] + image[indx - v][3] + image[indx - 2][3] + image[indx + 2][3]; - f[0] = (float)(image[indx-u][1] + image[indx+u][1])/(2.f + 2.f * image[indx][c]); - f[1] = 2.f * image[indx-u][1]/(2 + image[indx-v][c] + image[indx][c]); - f[2] = (float)(image[indx-u][1] + image[indx-w][1])/(2.f + 2.f * image[indx-v][c]); - f[3] = 2.f * image[indx+u][1]/(2 + image[indx+v][c] + image[indx][c]); - f[4] = (float)(image[indx+u][1] + image[indx+w][1])/(2.f + 2.f * image[indx+v][c]); + f[0] = (float)(image[indx - u][1] + image[indx + u][1]) / (2.f + 2.f * image[indx][c]); + f[1] = 2.f * image[indx - u][1] / (2 + image[indx - v][c] + image[indx][c]); + f[2] = (float)(image[indx - u][1] + image[indx - w][1]) / (2.f + 2.f * image[indx - v][c]); + f[3] = 2.f * image[indx + u][1] / (2 + image[indx + v][c] + image[indx][c]); + f[4] = (float)(image[indx + u][1] + image[indx + w][1]) / (2.f + 2.f * image[indx + v][c]); - g1 = (f[0] + f[1] + f[2] + f[3] + f[4] - max(f[1], f[2], f[3], f[4]) - min(f[1], f[2], f[3], f[4])) / 3.f; + g1 = (f[0] + f[1] + f[2] + f[3] + f[4] - max(f[1], f[2], f[3], f[4]) - min(f[1], f[2], f[3], f[4])) / 3.f; - f[0] = (float)(image[indx-1][1] + image[indx+1][1])/(2.f + 2.f * image[indx][c]); - f[1] = 2.f * image[indx-1][1]/(2 + image[indx-2][c] + image[indx][c]); - f[2] = (float)(image[indx-1][1] + image[indx-3][1])/(2.f + 2.f * image[indx-2][c]); - f[3] = 2.f * image[indx+1][1]/(2 + image[indx+2][c] + image[indx][c]); - f[4] = (float)(image[indx+1][1] + image[indx+3][1])/(2.f + 2.f * image[indx+2][c]); + f[0] = (float)(image[indx - 1][1] + image[indx + 1][1]) / (2.f + 2.f * image[indx][c]); + f[1] = 2.f * image[indx - 1][1] / (2 + image[indx - 2][c] + image[indx][c]); + f[2] = (float)(image[indx - 1][1] + image[indx - 3][1]) / (2.f + 2.f * image[indx - 2][c]); + f[3] = 2.f * image[indx + 1][1] / (2 + image[indx + 2][c] + image[indx][c]); + f[4] = (float)(image[indx + 1][1] + image[indx + 3][1]) / (2.f + 2.f * image[indx + 2][c]); - g2 = (f[0] + f[1] + f[2] + f[3] + f[4] - max(f[1], f[2], f[3], f[4]) - min(f[1], f[2], f[3], f[4])) / 3.f; + g2 = (f[0] + f[1] + f[2] + f[3] + f[4] - max(f[1], f[2], f[3], f[4]) - min(f[1], f[2], f[3], f[4])) / 3.f; - assert(indx>=0 && indx= 0 && indx < u * u); + image[indx][1] = (2.f + image[indx][c]) * (current * g1 + (16.f - current) * g2) * 0.0625f; // get rid of the overshooted pixels - float min_f = min(image[indx+1+u][1], min(image[indx+1-u][1], min(image[indx-1+u][1], min(image[indx-1-u][1], min(image[indx-1][1], min(image[indx+1][1], min(image[indx-u][1], image[indx+u][1]))))))); - float max_f = max(image[indx+1+u][1], max(image[indx+1-u][1], max(image[indx-1+u][1], max(image[indx-1-u][1], max(image[indx-1][1], max(image[indx+1][1], max(image[indx-u][1], image[indx+u][1]))))))); + float min_f = min(image[indx + 1 + u][1], min(image[indx + 1 - u][1], min(image[indx - 1 + u][1], min(image[indx - 1 - u][1], min(image[indx - 1][1], min(image[indx + 1][1], min(image[indx - u][1], image[indx + u][1]))))))); + float max_f = max(image[indx + 1 + u][1], max(image[indx + 1 - u][1], max(image[indx - 1 + u][1], max(image[indx - 1 - u][1], max(image[indx - 1][1], max(image[indx + 1][1], max(image[indx - u][1], image[indx + u][1]))))))); - image[indx][1] = LIM(image[indx][1], min_f, max_f); - } + image[indx][1] = LIM(image[indx][1], min_f, max_f); + } } // missing colors are interpolated using high quality algorithm by Luis Sanz Rodriguez void RawImageSource::dcb_color_full(float (*image)[4], int x0, int y0, float (*chroma)[2]) { - const int u=CACHESIZE, w=3*CACHESIZE; - int rowMin,colMin,rowMax,colMax; - dcb_initTileLimits(colMin,rowMin,colMax,rowMax,x0,y0,3); + const int u = CACHESIZE, w = 3 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 3); - float f[4],g[4]; + float f[4], g[4]; - for (int row=1; row < CACHESIZE-1; row++) - for (int col=1+(FC(y0-TILEBORDER+row,x0-TILEBORDER+1)&1),indx=row*CACHESIZE+col,c=FC(y0-TILEBORDER+row,x0-TILEBORDER+col),d=c/2; col < CACHESIZE-1; col+=2,indx+=2) { - assert(indx>=0 && indx=0 && c<4); - chroma[indx][d]=image[indx][c]-image[indx][1]; + for (int row = 1; row < CACHESIZE - 1; row++) + for (int col = 1 + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col), d = c / 2; col < CACHESIZE - 1; col += 2, indx += 2) { + assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + chroma[indx][d] = image[indx][c] - image[indx][1]; } - for (int row=rowMin; row=0 && indx=0 && c<2); - chroma[indx][c]=(f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]); - } - for (int row=rowMin; row= 0 && indx < u * u && c >= 0 && c < 2); + chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + } - g[0]= 0.875f * chroma[indx-u][c] + 0.125f * chroma[indx-w][c]; - g[1]= 0.875f * chroma[indx+1][c] + 0.125f * chroma[indx+3][c]; - g[2]= 0.875f * chroma[indx-1][c] + 0.125f * chroma[indx-3][c]; - g[3]= 0.875f * chroma[indx+u][c] + 0.125f * chroma[indx+w][c]; + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1) / 2; col < colMax; col += 2, indx += 2) + for(int d = 0; d <= 1; c = 1 - c, d++) { + f[0] = 1.f / (float)(1.f + fabs(chroma[indx - u][c] - chroma[indx + u][c]) + fabs(chroma[indx - u][c] - chroma[indx - w][c]) + fabs(chroma[indx + u][c] - chroma[indx - w][c])); + f[1] = 1.f / (float)(1.f + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) + fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) + fabs(chroma[indx - 1][c] - chroma[indx + 3][c])); + f[2] = 1.f / (float)(1.f + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) + fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) + fabs(chroma[indx + 1][c] - chroma[indx - 3][c])); + f[3] = 1.f / (float)(1.f + fabs(chroma[indx + u][c] - chroma[indx - u][c]) + fabs(chroma[indx + u][c] - chroma[indx + w][c]) + fabs(chroma[indx - u][c] - chroma[indx + w][c])); - assert(indx>=0 && indx=0 && c<2); - chroma[indx][c]=(f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]); - } + g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c]; + g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c]; + g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c]; + g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c]; - for(int row=rowMin; row=0 && indx= 0 && indx < u * u && c >= 0 && c < 2); + chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + } - image[indx][0] = chroma[indx][0] + image[indx][1]; - image[indx][2] = chroma[indx][1] + image[indx][1]; - } + for(int row = rowMin; row < rowMax; row++) + for(int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { + assert(indx >= 0 && indx < u * u); + + image[indx][0] = chroma[indx][0] + image[indx][1]; + image[indx][2] = chroma[indx][1] + image[indx][1]; + } } // DCB demosaicing main routine (sharp version) void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) { - double currentProgress=0.0; + double currentProgress = 0.0; + if(plistener) { plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::dcb])); plistener->setProgress (currentProgress); } - int wTiles = W/TILESIZE + (W%TILESIZE?1:0); - int hTiles = H/TILESIZE + (H%TILESIZE?1:0); + int wTiles = W / TILESIZE + (W % TILESIZE ? 1 : 0); + int hTiles = H / TILESIZE + (H % TILESIZE ? 1 : 0); int numTiles = wTiles * hTiles; - int tilesDone=0; + int tilesDone = 0; #ifdef _OPENMP - int nthreads = omp_get_max_threads(); - float (**image)[4] = (float(**)[4]) calloc( nthreads,sizeof( void*) ); - float (**image2)[3] = (float(**)[3]) calloc( nthreads,sizeof( void*) ); - float (**image3)[3] = (float(**)[3]) calloc( nthreads,sizeof( void*) ); - float (**chroma)[2] = (float (**)[2]) calloc( nthreads,sizeof( void*) ); - for(int i=0; i0;i--) { - dcb_hid2(tile,x0,y0); - dcb_hid2(tile,x0,y0); - dcb_hid2(tile,x0,y0); - dcb_map(tile,x0,y0); - dcb_correction(tile,x0,y0); + fill_raw( tile, x0, y0, rawData ); + + if( !xTile || !yTile || xTile == wTiles - 1 || yTile == hTiles - 1) { + fill_border(tile, 6, x0, y0); } - dcb_color(tile,x0,y0); - dcb_pp(tile,x0,y0); - dcb_map(tile,x0,y0); - dcb_correction2(tile,x0,y0); - dcb_map(tile,x0,y0); - dcb_correction(tile,x0,y0); - dcb_color(tile,x0,y0); - dcb_map(tile,x0,y0); - dcb_correction(tile,x0,y0); - dcb_map(tile,x0,y0); - dcb_correction(tile,x0,y0); - dcb_map(tile,x0,y0); + + dcb_hid(tile, buffer, buffer2, x0, y0); + copy_to_buffer(buffer, tile); + + for (int i = iterations; i > 0; i--) { + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + } + + dcb_color(tile, x0, y0); + dcb_pp(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction2(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + dcb_color(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + dcb_map(tile, x0, y0); restore_from_buffer(tile, buffer); - dcb_color(tile,x0,y0); + dcb_color(tile, x0, y0); + if (dcb_enhance) { - dcb_refinement(tile,x0,y0); - dcb_color_full(tile,x0,y0,chrm); + dcb_refinement(tile, x0, y0); + dcb_color_full(tile, x0, y0, chrm); } - for(int y=0;y currentProgress){ - currentProgress+=0.1; // Show progress each 10% - plistener->setProgress (currentProgress); - } + if( plistener && double(tilesDone) / numTiles > currentProgress) { + currentProgress += 0.1; // Show progress each 10% + plistener->setProgress (currentProgress); + } } + #ifdef _OPENMP -#pragma omp atomic + #pragma omp atomic #endif tilesDone++; } #ifdef _OPENMP - for(int i=0; isetProgress (1.0); + if(plistener) { + plistener->setProgress (1.0); + } } -const double xyz_rgb[3][3] = { // XYZ from RGB - { 0.412453, 0.357580, 0.180423 }, - { 0.212671, 0.715160, 0.072169 }, - { 0.019334, 0.119193, 0.950227 } }; +const double xyz_rgb[3][3] = { // XYZ from RGB + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } +}; const float d65_white[3] = { 0.950456, 1, 1.088754 }; void RawImageSource::cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]) { - static float cbrt[0x10000]; - static bool cbrtinit = false; - if (!rgb) { - int i, j, k; - float r; - if(!cbrtinit) { - for (i=0; i < 0x10000; i++) { - r = i / 65535.f; - cbrt[i] = r > 0.008856f ? xcbrtf(r) : 7.787f*r + 16.f/116.f; - } - cbrtinit = true; - } - return; - } + static float cbrt[0x10000]; + static bool cbrtinit = false; - int rgbOffset = (width - labWidth); - for(int i=0;i 0.008856f ? xcbrtf(r) : 7.787f * r + 16.f / 116.f; + } + + cbrtinit = true; + } + + return; + } + + int rgbOffset = (width - labWidth); + + for(int i = 0; i < height; i++) { + for(int j = 0; j < labWidth; j++) { + float xyz[3] = {0.5f}; + int c; + FORC3 { + xyz[0] += xyz_cam[0][c] * rgb[i * width + j][c]; + xyz[1] += xyz_cam[1][c] * rgb[i * width + j][c]; + xyz[2] += xyz_cam[2][c] * rgb[i * width + j][c]; + } + xyz[0] = cbrt[CLIP((int) xyz[0])]; + xyz[1] = cbrt[CLIP((int) xyz[1])]; + xyz[2] = cbrt[CLIP((int) xyz[2])]; + + l[i * labWidth + j] = 116 * xyz[1] - 16; + a[i * labWidth + j] = 500 * (xyz[0] - xyz[1]); + b[i * labWidth + j] = 200 * (xyz[1] - xyz[2]); + } + } } #define fcol(row,col) xtrans[(row)%6][(col)%6] void RawImageSource::xtransborder_interpolate (int border) { - const int height = H, width = W; - - char xtrans[6][6]; - ri->getXtransMatrix(xtrans); + const int height = H, width = W; - for (int row=0; row < height; row++) - for (int col=0; col < width; col++) { - if (col==border && row >= border && row < height-border) - col = width-border; - float sum[6] = {0.f}; - for (int y=MAX(0,row-1); y <= MIN(row+1,height-1); y++) - for (int x=MAX(0,col-1); x <= MIN(col+1,width-1); x++) { - int f = fcol(y,x); - sum[f] += rawData[y][x]; - sum[f+3]++; - } + char xtrans[6][6]; + ri->getXtransMatrix(xtrans); - switch(fcol(row,col)) { - case 0: red[row][col] = rawData[row][col]; - green[row][col] = (sum[1]/sum[4]); - blue[row][col] = (sum[2]/sum[5]); - break; - case 1: if(sum[3]==0.f) { // at the 4 corner pixels it can happen, that we have only green pixels in 2x2 area - red[row][col] = green[row][col] = blue[row][col] = rawData[row][col]; - } else { - red[row][col] = (sum[0]/sum[3]); - green[row][col] = rawData[row][col]; - blue[row][col] = (sum[2]/sum[5]); - } - break; - case 2: red[row][col] = (sum[0]/sum[3]); - green[row][col] = (sum[1]/sum[4]); - blue[row][col] = rawData[row][col]; - } - } + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + if (col == border && row >= border && row < height - border) { + col = width - border; + } + + float sum[6] = {0.f}; + + for (int y = MAX(0, row - 1); y <= MIN(row + 1, height - 1); y++) + for (int x = MAX(0, col - 1); x <= MIN(col + 1, width - 1); x++) { + int f = fcol(y, x); + sum[f] += rawData[y][x]; + sum[f + 3]++; + } + + switch(fcol(row, col)) { + case 0: + red[row][col] = rawData[row][col]; + green[row][col] = (sum[1] / sum[4]); + blue[row][col] = (sum[2] / sum[5]); + break; + + case 1: + if(sum[3] == 0.f) { // at the 4 corner pixels it can happen, that we have only green pixels in 2x2 area + red[row][col] = green[row][col] = blue[row][col] = rawData[row][col]; + } else { + red[row][col] = (sum[0] / sum[3]); + green[row][col] = rawData[row][col]; + blue[row][col] = (sum[2] / sum[5]); + } + + break; + + case 2: + red[row][col] = (sum[0] / sum[3]); + green[row][col] = (sum[1] / sum[4]); + blue[row][col] = rawData[row][col]; + } + } } /* @@ -3496,451 +4032,538 @@ void RawImageSource::xtransborder_interpolate (int border) adapted to RT by Ingo Weyrich 2014 */ -#define TS 122 /* Tile Size */ +#define TS 122 /* Tile Size */ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) { - double progress = 0.0; - const bool plistenerActive = plistener; - - if (plistenerActive) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "Xtrans")); - plistener->setProgress (progress); - } + double progress = 0.0; + const bool plistenerActive = plistener; - char xtrans[6][6]; - ri->getXtransMatrix(xtrans); + if (plistenerActive) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "Xtrans")); + plistener->setProgress (progress); + } - static const short orth[12] = { 1,0,0,1,-1,0,0,-1,1,0,0,1 }, - patt[2][16] = { { 0,1,0,-1,2,0,-1,0,1,1,1,-1,0,0,0,0 }, - { 0,1,0,-2,1,0,-2,0,1,1,-2,-2,1,-1,-1,1 } }, - dir[4] = { 1,TS,TS+1,TS-1 }; + char xtrans[6][6]; + ri->getXtransMatrix(xtrans); - short allhex[2][3][3][8]; + static const short orth[12] = { 1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1 }, + patt[2][16] = { { 0, 1, 0, -1, 2, 0, -1, 0, 1, 1, 1, -1, 0, 0, 0, 0 }, + { 0, 1, 0, -2, 1, 0, -2, 0, 1, 1, -2, -2, 1, -1, -1, 1 } + }, + dir[4] = { 1, TS, TS + 1, TS - 1 }; - // sgrow/sgcol is the offset in the sensor matrix of the solitary - // green pixels - ushort sgrow, sgcol; - - const int height = H, width = W; + short allhex[2][3][3][8]; - if (settings->verbose) - printf("%d-pass X-Trans interpolation using %s conversion...\n", passes, useCieLab ? "lab" : "yuv"); + // sgrow/sgcol is the offset in the sensor matrix of the solitary + // green pixels + ushort sgrow, sgcol; - xtransborder_interpolate(6); + const int height = H, width = W; - float xyz_cam[3][3]; - { - float rgb_cam[3][4]; - ri->getRgbCam(rgb_cam); - int k; - for (int i=0; i < 3; i++) - for (int j=0; j < 3; j++) - for (xyz_cam[i][j] = k=0; k < 3; k++) - xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; - } + if (settings->verbose) { + printf("%d-pass X-Trans interpolation using %s conversion...\n", passes, useCieLab ? "lab" : "yuv"); + } -/* Map a green hexagon around each non-green pixel and vice versa: */ -{ - int gint, d, h, v, ng, row, col, c; + xtransborder_interpolate(6); - for (row=0; row < 3; row++) - for (col=0; col < 3; col++) { - gint = fcol(row,col) == 1; - for (ng=d=0; d < 10; d+=2) { - if (fcol(row+orth[d]+6,col+orth[d+2]+6) == 1) - ng=0; - else - ng++; - if (ng == 4) { - // if there are four non-green pixels adjacent in cardinal - // directions, this is the solitary green pixel - sgrow = row; - sgcol = col; - } - if (ng == gint+1) - FORC(8) { - v = orth[d]*patt[gint][c*2] + orth[d+1]*patt[gint][c*2+1]; - h = orth[d+2]*patt[gint][c*2] + orth[d+3]*patt[gint][c*2+1]; - allhex[0][row][col][c^(gint*2 & d)] = h + v*width; - allhex[1][row][col][c^(gint*2 & d)] = h + v*TS; - } - } - } + float xyz_cam[3][3]; + { + float rgb_cam[3][4]; + ri->getRgbCam(rgb_cam); + int k; -} - if(plistenerActive) { - progress += 0.05; - plistener->setProgress(progress); - } + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (xyz_cam[i][j] = k = 0; k < 3; k++) { + xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; + } + } + + /* Map a green hexagon around each non-green pixel and vice versa: */ + { + int gint, d, h, v, ng, row, col, c; + + for (row = 0; row < 3; row++) + for (col = 0; col < 3; col++) { + gint = fcol(row, col) == 1; + + for (ng = d = 0; d < 10; d += 2) { + if (fcol(row + orth[d] + 6, col + orth[d + 2] + 6) == 1) { + ng = 0; + } else { + ng++; + } + + if (ng == 4) { + // if there are four non-green pixels adjacent in cardinal + // directions, this is the solitary green pixel + sgrow = row; + sgcol = col; + } + + if (ng == gint + 1) + FORC(8) { + v = orth[d] * patt[gint][c * 2] + orth[d + 1] * patt[gint][c * 2 + 1]; + h = orth[d + 2] * patt[gint][c * 2] + orth[d + 3] * patt[gint][c * 2 + 1]; + allhex[0][row][col][c ^ (gint * 2 & d)] = h + v * width; + allhex[1][row][col][c ^ (gint * 2 & d)] = h + v * TS; + } + } + } + + } + + if(plistenerActive) { + progress += 0.05; + plistener->setProgress(progress); + } - double progressInc = 36.0*(1.0-progress)/((H*W)/((TS-16)*(TS-16))); - const int ndir = 4 << (passes > 1); - cielab (0,0,0,0,0,0,0,0); - struct s_minmaxgreen { - float min; - float max; - }; + double progressInc = 36.0 * (1.0 - progress) / ((H * W) / ((TS - 16) * (TS - 16))); + const int ndir = 4 << (passes > 1); + cielab (0, 0, 0, 0, 0, 0, 0, 0); + struct s_minmaxgreen { + float min; + float max; + }; - int RightShift[6]; - for(int row=0;row<6;row++) { - // count number of green pixels in three cols - int greencount = 0; - for(int col=0;col<3;col++) - greencount += (fcol(row,col) == 1); - RightShift[row] = (greencount == 2); - } + int RightShift[6]; - -#pragma omp parallel -{ - int progressCounter = 0; - short *hex; - int c, d, f, h, i, v, mrow, mcol; - int pass; - float color[3][8], g, val; - float (*rgb)[TS][TS][3], (*rix)[3]; - float (*lab)[TS-8][TS-8]; - float (*drv)[TS-10][TS-10], diff[6], tr; - s_minmaxgreen (*greenminmaxtile)[TS]; - uint8_t (*homo)[TS][TS]; - uint8_t (*homosum)[TS][TS]; - float *buffer; - buffer = (float *) malloc ((TS*TS*(ndir*3+11)+128)*sizeof(float)); - rgb = (float(*)[TS][TS][3]) buffer; - lab = (float (*) [TS-8][TS-8])(buffer + TS*TS*(ndir*3)); - drv = (float (*)[TS-10][TS-10]) (buffer + TS*TS*(ndir*3+3)); - homo = (uint8_t (*)[TS][TS]) (lab); // we can reuse the lab-buffer because they are not used together - greenminmaxtile = (s_minmaxgreen(*)[TS]) (lab); // we can reuse the lab-buffer because they are not used together - homosum = (uint8_t (*)[TS][TS]) (drv); // we can reuse the drv-buffer because they are not used together + for(int row = 0; row < 6; row++) { + // count number of green pixels in three cols + int greencount = 0; -#pragma omp for collapse(2) schedule(dynamic) nowait - for (int top=3; top < height-19; top += TS-16) - for (int left=3; left < width-19; left += TS-16) { - int mrow = MIN (top+TS, height-3); - int mcol = MIN (left+TS, width-3); - memset(rgb,0,TS*TS*3*sizeof(float)); - for (int row=top; row < mrow; row++) - for (int col=left; col < mcol; col++) { - rgb[0][row-top][col-left][fcol(row,col)] = rawData[row][col]; - } - FORC3 memcpy (rgb[c+1], rgb[0], sizeof *rgb); + for(int col = 0; col < 3; col++) { + greencount += (fcol(row, col) == 1); + } - /* Set green1 and green3 to the minimum and maximum allowed values: */ - for (int row=top; row < mrow; row++) { - float minval=FLT_MAX; - float maxval=0.f; - int shiftindex = RightShift[(row)%6]; - for (int col=left; col < mcol; col++) { - if (fcol(row,col) == 1) { - minval=FLT_MAX; - maxval=0.f; - continue; - } - float *pix = &rawData[row][col]; - hex = allhex[0][row % 3][col % 3]; - if (maxval==0.f) - FORC(6) { - val = pix[hex[c]]; - if (minval > val) - minval = val; - if (maxval < val) - maxval = val; - } - greenminmaxtile[row-top][(col-left)>>shiftindex].min = minval; - greenminmaxtile[row-top][(col-left)>>shiftindex].max = maxval; - switch ((row-sgrow) % 3) { - case 1: if (row < mrow-1) { - row++; - shiftindex = RightShift[(row)%6]; - col--; - } - break; - case 2: minval=FLT_MAX; - maxval=0.f; - if ((col+=2) < mcol-1 && row > top+1) { - row--; - shiftindex = RightShift[(row)%6]; - } - } - } - } + RightShift[row] = (greencount == 2); + } - /* Interpolate green horizontally, vertically, and along both diagonals: */ - for (int row=top; row < mrow; row++) { - // find first non-green pixel - int leftstart = left; - for(;leftstart>shiftindex].min,greenminmaxtile[row-top][(col-left)>>shiftindex].max); - } - } - for (pass=0; pass < passes; pass++) { - if (pass == 1) - memcpy (rgb+=4, buffer, 4*sizeof *rgb); -/* Recalculate green from interpolated values of closer pixels: */ - if (pass) { - for (int row=top+2; row < mrow-2; row++) { - int leftstart = left+2; - for(;leftstart>shiftindex].min,greenminmaxtile[row-top][(col-left)>>shiftindex].max); - } - } - } - } + #pragma omp parallel + { + int progressCounter = 0; + short *hex; + int c, d, f, h, i, v, mrow, mcol; + int pass; + float color[3][8], g, val; + float (*rgb)[TS][TS][3], (*rix)[3]; + float (*lab)[TS - 8][TS - 8]; + float (*drv)[TS - 10][TS - 10], diff[6], tr; + s_minmaxgreen (*greenminmaxtile)[TS]; + uint8_t (*homo)[TS][TS]; + uint8_t (*homosum)[TS][TS]; + float *buffer; + buffer = (float *) malloc ((TS * TS * (ndir * 3 + 11) + 128) * sizeof(float)); + rgb = (float(*)[TS][TS][3]) buffer; + lab = (float (*) [TS - 8][TS - 8])(buffer + TS * TS * (ndir * 3)); + drv = (float (*)[TS - 10][TS - 10]) (buffer + TS * TS * (ndir * 3 + 3)); + homo = (uint8_t (*)[TS][TS]) (lab); // we can reuse the lab-buffer because they are not used together + greenminmaxtile = (s_minmaxgreen(*)[TS]) (lab); // we can reuse the lab-buffer because they are not used together + homosum = (uint8_t (*)[TS][TS]) (drv); // we can reuse the drv-buffer because they are not used together -/* Interpolate red and blue values for solitary green pixels: */ - for (int row=(top-sgrow+4)/3*3+sgrow; row < mrow-2; row+=3) - for (int col=(left-sgcol+4)/3*3+sgcol; col < mcol-2; col+=3) { - rix = &rgb[0][row-top][col-left]; - h = fcol(row,col+1); - memset (diff, 0, sizeof diff); - for (i=1, d=0; d < 6; d++, i^=TS^1, h^=2) { - for (c=0; c < 2; c++, h^=2) { - g = rix[0][1] + rix[0][1] - rix[i< 1) - diff[d] += SQR (rix[i< 2 && (d & 1)) // 3, 5 - if (diff[d-1] < diff[d]) - FORC(2) - color[c*2][d] = color[c*2][d-1]; - if ((d & 1) || d < 2) { // d: 0, 1, 3, 5 - FORC(2) - rix[0][c*2] = CLIP(0.5f*color[c*2][d]); - rix += TS*TS; - } - } - } + #pragma omp for collapse(2) schedule(dynamic) nowait -/* Interpolate red for blue pixels and vice versa: */ - for (int row=top+3; row < mrow-3; row++) { - int leftstart = left+3; - for(;leftstart 1 || ((d ^ c) & 1) || - ((fabsf(rix[0][1]-rix[c][1])+fabsf(rix[0][1]-rix[-c][1])) < 2.f*(fabsf(rix[0][1]-rix[h][1])+fabsf(rix[0][1]-rix[-h][1]))) ? c:h; + for (int top = 3; top < height - 19; top += TS - 16) + for (int left = 3; left < width - 19; left += TS - 16) { + int mrow = MIN (top + TS, height - 3); + int mcol = MIN (left + TS, width - 3); + memset(rgb, 0, TS * TS * 3 * sizeof(float)); - rix[0][f] = CLIP(0.5f*(rix[i][f] + rix[-i][f] + - rix[0][1] + rix[0][1] - rix[i][1] - rix[-i][1])); - } - } - } + for (int row = top; row < mrow; row++) + for (int col = left; col < mcol; col++) { + rgb[0][row - top][col - left][fcol(row, col)] = rawData[row][col]; + } + + FORC3 memcpy (rgb[c + 1], rgb[0], sizeof * rgb); + + /* Set green1 and green3 to the minimum and maximum allowed values: */ + for (int row = top; row < mrow; row++) { + float minval = FLT_MAX; + float maxval = 0.f; + int shiftindex = RightShift[(row) % 6]; + + for (int col = left; col < mcol; col++) { + if (fcol(row, col) == 1) { + minval = FLT_MAX; + maxval = 0.f; + continue; + } + + float *pix = &rawData[row][col]; + hex = allhex[0][row % 3][col % 3]; + + if (maxval == 0.f) + FORC(6) { + val = pix[hex[c]]; + + if (minval > val) { + minval = val; + } + + if (maxval < val) { + maxval = val; + } + } + + greenminmaxtile[row - top][(col - left) >> shiftindex].min = minval; + greenminmaxtile[row - top][(col - left) >> shiftindex].max = maxval; + + switch ((row - sgrow) % 3) { + case 1: + if (row < mrow - 1) { + row++; + shiftindex = RightShift[(row) % 6]; + col--; + } + + break; + + case 2: + minval = FLT_MAX; + maxval = 0.f; + + if ((col += 2) < mcol - 1 && row > top + 1) { + row--; + shiftindex = RightShift[(row) % 6]; + } + } + } + } + + /* Interpolate green horizontally, vertically, and along both diagonals: */ + for (int row = top; row < mrow; row++) { + // find first non-green pixel + int leftstart = left; + + for(; leftstart < mcol; leftstart++) + if(fcol(row, leftstart) != 1) { + break; + } + + const int shiftindex = RightShift[(row) % 6]; + const int coloffset = (shiftindex == 1 ? 3 : 1); + + for (int col = leftstart; col < mcol; col += coloffset) { + if (fcol(row, col) == 1) { + continue; + } + + float *pix = &rawData[row][col]; + hex = allhex[0][row % 3][col % 3]; + color[1][0] = 0.6796875f * (pix[hex[1]] + pix[hex[0]]) - + 0.1796875f * (pix[2 * hex[1]] + pix[2 * hex[0]]); + color[1][1] = 0.87109375f * pix[hex[3]] + pix[hex[2]] * 0.12890625f + + 0.359375f * (pix[0] - pix[-hex[2]]); + FORC(2) + color[1][2 + c] = 0.640625f * pix[hex[4 + c]] + 0.359375f * pix[-2 * hex[4 + c]] + 0.12890625f * + (2.f * pix[0] - pix[3 * hex[4 + c]] - pix[-3 * hex[4 + c]]); + FORC(4) + rgb[c ^ !((row - sgrow) % 3)][row - top][col - left][1] = LIM(color[1][c], greenminmaxtile[row - top][(col - left) >> shiftindex].min, greenminmaxtile[row - top][(col - left) >> shiftindex].max); + } + } + + for (pass = 0; pass < passes; pass++) { + if (pass == 1) { + memcpy (rgb += 4, buffer, 4 * sizeof * rgb); + } + + /* Recalculate green from interpolated values of closer pixels: */ + if (pass) { + for (int row = top + 2; row < mrow - 2; row++) { + int leftstart = left + 2; + + for(; leftstart < mcol - 2; leftstart++) + if(fcol(row, leftstart) != 1) { + break; + } + + const int shiftindex = RightShift[(row) % 6]; + const int coloffset = (shiftindex == 1 ? 3 : 1); + + for (int col = leftstart; col < mcol - 2; col += coloffset) { + if ((f = fcol(row, col)) == 1) { + continue; + } + + hex = allhex[1][row % 3][col % 3]; + + for (d = 3; d < 6; d++) { + rix = &rgb[(d - 2) ^ !((row - sgrow) % 3)][row - top][col - left]; + val = rix[-2 * hex[d]][1] + 2 * (rix[hex[d]][1] - rix[hex[d]][f]) + - rix[-2 * hex[d]][f] + 3 * rix[0][f]; + rix[0][1] = LIM((float)(val * .33333333f), greenminmaxtile[row - top][(col - left) >> shiftindex].min, greenminmaxtile[row - top][(col - left) >> shiftindex].max); + } + } + } + } + + /* Interpolate red and blue values for solitary green pixels: */ + for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3) + for (int col = (left - sgcol + 4) / 3 * 3 + sgcol; col < mcol - 2; col += 3) { + rix = &rgb[0][row - top][col - left]; + h = fcol(row, col + 1); + memset (diff, 0, sizeof diff); + + for (i = 1, d = 0; d < 6; d++, i ^= TS ^ 1, h ^= 2) { + for (c = 0; c < 2; c++, h ^= 2) { + g = rix[0][1] + rix[0][1] - rix[i << c][1] - rix[-i << c][1]; + color[h][d] = g + rix[i << c][h] + rix[-i << c][h]; + + if (d > 1) + diff[d] += SQR (rix[i << c][1] - rix[-i << c][1] + - rix[i << c][h] + rix[-i << c][h]) + SQR(g); + } + + if (d > 2 && (d & 1)) // 3, 5 + if (diff[d - 1] < diff[d]) + FORC(2) + color[c * 2][d] = color[c * 2][d - 1]; + + if ((d & 1) || d < 2) { // d: 0, 1, 3, 5 + FORC(2) + rix[0][c * 2] = CLIP(0.5f * color[c * 2][d]); + rix += TS * TS; + } + } + } + + /* Interpolate red for blue pixels and vice versa: */ + for (int row = top + 3; row < mrow - 3; row++) { + int leftstart = left + 3; + + for(; leftstart < mcol - 1; leftstart++) + if(fcol(row, leftstart) != 1) { + break; + } + + const int coloffset = (RightShift[(row) % 6] == 1 ? 3 : 1); + c = (row - sgrow) % 3 ? TS : 1; + h = 3 * (c ^ TS ^ 1); + + for (int col = leftstart; col < mcol - 3; col += coloffset) { + if ((f = 2 - fcol(row, col)) == 1) { + continue; + } + + rix = &rgb[0][row - top][col - left]; + + for (d = 0; d < 4; d++, rix += TS * TS) { + i = d > 1 || ((d ^ c) & 1) || + ((fabsf(rix[0][1] - rix[c][1]) + fabsf(rix[0][1] - rix[-c][1])) < 2.f * (fabsf(rix[0][1] - rix[h][1]) + fabsf(rix[0][1] - rix[-h][1]))) ? c : h; + + rix[0][f] = CLIP(0.5f * (rix[i][f] + rix[-i][f] + + rix[0][1] + rix[0][1] - rix[i][1] - rix[-i][1])); + } + } + } + + /* Fill in red and blue for 2x2 blocks of green: */ + for (int row = top + 2; row < mrow - 2; row++) + if ((row - sgrow) % 3) { + for (int col = left + 2; col < mcol - 2; col++) + if ((col - sgcol) % 3) { + rix = &rgb[0][row - top][col - left]; + hex = allhex[1][row % 3][col % 3]; + + for (d = 0; d < ndir; d += 2, rix += TS * TS) + if (hex[d] + hex[d + 1]) { + g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1]; + + for (c = 0; c < 4; c += 2) { + rix[0][c] = CLIP((g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.33333333f); + } + } else { + g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1]; + + for (c = 0; c < 4; c += 2) { + rix[0][c] = CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) * 0.5f); + } + } + } + } + } -/* Fill in red and blue for 2x2 blocks of green: */ - for (int row=top+2; row < mrow-2; row++) - if ((row-sgrow) % 3) { - for (int col=left+2; col < mcol-2; col++) - if ((col-sgcol) % 3) { - rix = &rgb[0][row-top][col-left]; - hex = allhex[1][row%3][col % 3]; - for (d=0; d < ndir; d+=2, rix += TS*TS) - if (hex[d] + hex[d+1]) { - g = 3*rix[0][1] - 2*rix[hex[d]][1] - rix[hex[d+1]][1]; - for (c=0; c < 4; c+=2) - rix[0][c] = CLIP((g + 2*rix[hex[d]][c] + rix[hex[d+1]][c])*0.33333333f); - } else { - g = 2*rix[0][1] - rix[hex[d]][1] - rix[hex[d+1]][1]; - for (c=0; c < 4; c+=2) - rix[0][c] = CLIP((g + rix[hex[d]][c] + rix[hex[d+1]][c])*0.5f); - } - } - } - } - // end of multipass part - rgb = (float(*)[TS][TS][3]) buffer; - mrow -= top; - mcol -= left; + rgb = (float(*)[TS][TS][3]) buffer; + mrow -= top; + mcol -= left; - if(useCieLab) { - /* Convert to CIELab and differentiate in all directions: */ - // Original dcraw algorithm uses CIELab as perceptual space - // (presumably coming from original AHD) and converts taking - // camera matrix into account. We use this in RT. - for (d=0; d < ndir; d++) { - float *l = &lab[0][0][0]; - float *a = &lab[1][0][0]; - float *b = &lab[2][0][0]; - cielab(&rgb[d][4][4],l,a,b,TS,mrow-8,TS-8,xyz_cam); - int f = dir[d & 3]; - f = f == 1 ? 1 : f-8; - for (int row=5; row < mrow-5; row++) - for (int col=5; col < mcol-5; col++) { - float *l = &lab[0][row-4][col-4]; - float *a = &lab[1][row-4][col-4]; - float *b = &lab[2][row-4][col-4]; - - g = 2*l[0] - l[f] - l[-f]; - drv[d][row-5][col-5] = SQR(g) - + SQR((2*a[0] - a[f] - a[-f] + g*2.1551724f)) - + SQR((2*b[0] - b[f] - b[-f] - g*0.86206896f)); - } + if(useCieLab) { + /* Convert to CIELab and differentiate in all directions: */ + // Original dcraw algorithm uses CIELab as perceptual space + // (presumably coming from original AHD) and converts taking + // camera matrix into account. We use this in RT. + for (d = 0; d < ndir; d++) { + float *l = &lab[0][0][0]; + float *a = &lab[1][0][0]; + float *b = &lab[2][0][0]; + cielab(&rgb[d][4][4], l, a, b, TS, mrow - 8, TS - 8, xyz_cam); + int f = dir[d & 3]; + f = f == 1 ? 1 : f - 8; - } - } else { - // Now use YPbPr which requires much - // less code and is nearly indistinguishable. It assumes the - // camera RGB is roughly linear. - // - for (d=0; d < ndir; d++) { - float (*yuv)[TS-8][TS-8] = lab; // we use the lab buffer, which has the same dimensions - for (int row=4; row < mrow-4; row++) - for (int col=4; col < mcol-4; col++) { - // use ITU-R BT.2020 YPbPr, which is great, but could use - // a better/simpler choice? note that imageop.h provides - // dt_iop_RGB_to_YCbCr which uses Rec. 601 conversion, - // which appears less good with specular highlights - float y = 0.2627f * rgb[d][row][col][0] + 0.6780f * rgb[d][row][col][1] + 0.0593f * rgb[d][row][col][2]; - yuv[0][row-4][col-4] = y; - yuv[1][row-4][col-4] = (rgb[d][row][col][2]-y)*0.56433f; - yuv[2][row-4][col-4] = (rgb[d][row][col][0]-y)*0.67815f; - } - int f=dir[d & 3]; - f = f == 1 ? 1 : f-8; - for (int row=5; row < mrow-5; row++) - for (int col=5; col < mcol-5; col++) { - float *y = &yuv[0][row-4][col-4]; - float *u = &yuv[1][row-4][col-4]; - float *v = &yuv[2][row-4][col-4]; - drv[d][row-5][col-5] = SQR(2*y[0] - y[f] - y[-f]) - + SQR(2*u[0] - u[f] - u[-f]) - + SQR(2*v[0] - v[f] - v[-f]); - } - } - } + for (int row = 5; row < mrow - 5; row++) + for (int col = 5; col < mcol - 5; col++) { + float *l = &lab[0][row - 4][col - 4]; + float *a = &lab[1][row - 4][col - 4]; + float *b = &lab[2][row - 4][col - 4]; -/* Build homogeneity maps from the derivatives: */ - memset(homo, 0, ndir*TS*TS*sizeof(uint8_t)); - for (int row=6; row < mrow-6; row++) - for (int col=6; col < mcol-6; col++) { - for (tr=FLT_MAX, d=0; d < ndir; d++) - tr = (drv[d][row-5][col-5] < tr ? drv[d][row-5][col-5] : tr); - tr *= 8; - for (d=0; d < ndir; d++) - for (v=-1; v <= 1; v++) - for (h=-1; h <= 1; h++) - homo[d][row][col] += (drv[d][row+v-5][col+h-5] <= tr ? 1:0) ; - } + g = 2 * l[0] - l[f] - l[-f]; + drv[d][row - 5][col - 5] = SQR(g) + + SQR((2 * a[0] - a[f] - a[-f] + g * 2.1551724f)) + + SQR((2 * b[0] - b[f] - b[-f] - g * 0.86206896f)); + } - if (height-top < TS+4) - mrow = height-top+2; - if (width-left < TS+4) - mcol = width-left+2; + } + } else { + // Now use YPbPr which requires much + // less code and is nearly indistinguishable. It assumes the + // camera RGB is roughly linear. + // + for (d = 0; d < ndir; d++) { + float (*yuv)[TS - 8][TS - 8] = lab; // we use the lab buffer, which has the same dimensions + + for (int row = 4; row < mrow - 4; row++) + for (int col = 4; col < mcol - 4; col++) { + // use ITU-R BT.2020 YPbPr, which is great, but could use + // a better/simpler choice? note that imageop.h provides + // dt_iop_RGB_to_YCbCr which uses Rec. 601 conversion, + // which appears less good with specular highlights + float y = 0.2627f * rgb[d][row][col][0] + 0.6780f * rgb[d][row][col][1] + 0.0593f * rgb[d][row][col][2]; + yuv[0][row - 4][col - 4] = y; + yuv[1][row - 4][col - 4] = (rgb[d][row][col][2] - y) * 0.56433f; + yuv[2][row - 4][col - 4] = (rgb[d][row][col][0] - y) * 0.67815f; + } + + int f = dir[d & 3]; + f = f == 1 ? 1 : f - 8; + + for (int row = 5; row < mrow - 5; row++) + for (int col = 5; col < mcol - 5; col++) { + float *y = &yuv[0][row - 4][col - 4]; + float *u = &yuv[1][row - 4][col - 4]; + float *v = &yuv[2][row - 4][col - 4]; + drv[d][row - 5][col - 5] = SQR(2 * y[0] - y[f] - y[-f]) + + SQR(2 * u[0] - u[f] - u[-f]) + + SQR(2 * v[0] - v[f] - v[-f]); + } + } + } + + /* Build homogeneity maps from the derivatives: */ + memset(homo, 0, ndir * TS * TS * sizeof(uint8_t)); + + for (int row = 6; row < mrow - 6; row++) + for (int col = 6; col < mcol - 6; col++) { + for (tr = FLT_MAX, d = 0; d < ndir; d++) { + tr = (drv[d][row - 5][col - 5] < tr ? drv[d][row - 5][col - 5] : tr); + } + + tr *= 8; + + for (d = 0; d < ndir; d++) + for (v = -1; v <= 1; v++) + for (h = -1; h <= 1; h++) { + homo[d][row][col] += (drv[d][row + v - 5][col + h - 5] <= tr ? 1 : 0) ; + } + } + + if (height - top < TS + 4) { + mrow = height - top + 2; + } + + if (width - left < TS + 4) { + mcol = width - left + 2; + } -/* Build 5x5 sum of homogeneity maps */ - for(d=0;d hm[d]) - hm[d] = 0; - } - maxval -= maxval >> 3; - float avg[4] = {0.f}; - for (d=0; d < ndir; d++) - if (hm[d] >= maxval) { - FORC3 avg[c] += rgb[d][row][col][c]; - avg[3]++; - } + for(v = -2; v <= 2; v++) + for(h = -2; h <= 2; h++) { + v5sum[2 + h] += homo[d][row + v][startcol + h]; + } - red[row+top][col+left] = (avg[0]/avg[3]); - green[row+top][col+left] = (avg[1]/avg[3]); - blue[row+top][col+left] = (avg[2]/avg[3]); - } - - if(plistenerActive && ((++progressCounter) % 32 == 0)) { + int blocksum = v5sum[0] + v5sum[1] + v5sum[2] + v5sum[3] + v5sum[4]; + homosum[d][row][startcol] = blocksum; + int voffset = -1; + + // now we can subtract a column of five from blocksum and get new colsum of 5 + for (int col = startcol + 1; col < mcol - 8; col++) { + int colsum = homo[d][row - 2][col + 2]; + + for(v = -1; v <= 2; v++) { + colsum += homo[d][row + v][col + 2]; + } + + voffset ++; + voffset = voffset == 5 ? 0 : voffset; // faster than voffset %= 5; + blocksum -= v5sum[voffset]; + blocksum += colsum; + v5sum[voffset] = colsum; + homosum[d][row][col] = blocksum; + } + } + } + + /* Average the most homogenous pixels for the final result: */ + for (int row = MIN(top, 8); row < mrow - 8; row++) + for (int col = MIN(left, 8); col < mcol - 8; col++) { + uint8_t hm[8]; + uint8_t maxval = 0; + + for (d = 0; d < 4; d++) { + hm[d] = homosum[d][row][col]; + maxval = (maxval < hm[d] ? hm[d] : maxval); + } + + for (; d < ndir; d++) { + hm[d] = homosum[d][row][col]; + maxval = (maxval < hm[d] ? hm[d] : maxval); + + if (hm[d - 4] < hm[d]) { + hm[d - 4] = 0; + } else if (hm[d - 4] > hm[d]) { + hm[d] = 0; + } + } + + maxval -= maxval >> 3; + float avg[4] = {0.f}; + + for (d = 0; d < ndir; d++) + if (hm[d] >= maxval) { + FORC3 avg[c] += rgb[d][row][col][c]; + avg[3]++; + } + + red[row + top][col + left] = (avg[0] / avg[3]); + green[row + top][col + left] = (avg[1] / avg[3]); + blue[row + top][col + left] = (avg[2] / avg[3]); + } + + if(plistenerActive && ((++progressCounter) % 32 == 0)) { #ifdef _OPENMP -#pragma omp critical (xtransdemosaic) + #pragma omp critical (xtransdemosaic) #endif -{ - progress += progressInc; - progress = min(1.0,progress); - plistener->setProgress (progress); -} - } + { + progress += progressInc; + progress = min(1.0, progress); + plistener->setProgress (progress); + } + } - } - free(buffer); -} + } + + free(buffer); + } } @@ -3948,52 +4571,61 @@ void RawImageSource::xtrans_interpolate (int passes, bool useCieLab) void RawImageSource::fast_xtrans_interpolate () { - if (settings->verbose) - printf("fast X-Trans interpolation...\n"); + if (settings->verbose) { + printf("fast X-Trans interpolation...\n"); + } - double progress = 0.0; - const bool plistenerActive = plistener; - - if (plistenerActive) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "fast Xtrans")); - plistener->setProgress (progress); - } + double progress = 0.0; + const bool plistenerActive = plistener; - const int height = H, width = W; + if (plistenerActive) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "fast Xtrans")); + plistener->setProgress (progress); + } - xtransborder_interpolate (1); - char xtrans[6][6]; - ri->getXtransMatrix(xtrans); + const int height = H, width = W; -#pragma omp parallel for - for(int row=1;rowsetProgress (1.0); - } + xtransborder_interpolate (1); + char xtrans[6][6]; + ri->getXtransMatrix(xtrans); + + #pragma omp parallel for + + for(int row = 1; row < height - 1; row++) { + for(int col = 1; col < width - 1; col++) { + float sum[3] = {0.f}; + + for(int v = -1; v <= 1; v++) { + for(int h = -1; h <= 1; h++) { + sum[fcol(row + v, col + h)] += rawData[row + v][(col + h)]; + } + } + + switch(fcol(row, col)) { + case 0: + red[row][col] = rawData[row][col]; + green[row][col] = sum[1] * 0.2f; + blue[row][col] = sum[2] * 0.33333333f; + break; + + case 1: + red[row][col] = sum[0] * 0.5f; + green[row][col] = rawData[row][col]; + blue[row][col] = sum[2] * 0.5f; + break; + + case 2: + red[row][col] = sum[0] * 0.33333333f; + green[row][col] = sum[1] * 0.2f; + blue[row][col] = rawData[row][col]; + break; + } + } + } + + if (plistenerActive) { + plistener->setProgress (1.0); + } } #undef fcol diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index 947542e50..19ab16cfb 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -7,7 +7,7 @@ * 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 @@ -28,81 +28,102 @@ #include "imagedata.h" #include -namespace rtengine{ +namespace rtengine +{ extern const Settings* settings; // *********************** class dfInfo ************************************** -inline dfInfo& dfInfo::operator =(const dfInfo &o){ - pathname = o.pathname; - maker = o.maker; - model = o.model; - iso = o.iso; - shutter = o.shutter; - timestamp = o.timestamp; - if( ri ){ - delete ri; - ri = NULL; - } - return *this; +inline dfInfo& dfInfo::operator =(const dfInfo &o) +{ + pathname = o.pathname; + maker = o.maker; + model = o.model; + iso = o.iso; + shutter = o.shutter; + timestamp = o.timestamp; + + if( ri ) { + delete ri; + ri = NULL; + } + + return *this; } bool dfInfo::operator <(const dfInfo &e2) const { - if( this->maker.compare( e2.maker) >=0 ) - return false; - if( this->model.compare( e2.model) >=0 ) - return false; - if( this->iso >= e2.iso ) - return false; - if( this->shutter >= e2.shutter ) - return false; - if( this->timestamp >= e2.timestamp ) - return false; - return true; + if( this->maker.compare( e2.maker) >= 0 ) { + return false; + } + + if( this->model.compare( e2.model) >= 0 ) { + return false; + } + + if( this->iso >= e2.iso ) { + return false; + } + + if( this->shutter >= e2.shutter ) { + return false; + } + + if( this->timestamp >= e2.timestamp ) { + return false; + } + + return true; } std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso, double shut ) { - std::ostringstream s; - s << mak << " " << mod << " "; - s.width(5); - s << iso << "ISO "; - s.precision( 2 ); - s.width(4); - s << shut << "s"; - return s.str(); + std::ostringstream s; + s << mak << " " << mod << " "; + s.width(5); + s << iso << "ISO "; + s.precision( 2 ); + s.width(4); + s << shut << "s"; + return s.str(); } double dfInfo::distance(const std::string &mak, const std::string &mod, int iso, double shutter) const { - if( this->maker.compare( mak) != 0 ) - return INFINITY; - if( this->model.compare( mod) != 0 ) - return INFINITY; - double dISO= (log(this->iso/100.) - log(iso/100.))/log(2); - double dShutter = (log(this->shutter) - log(shutter))/log(2); - return sqrt( dISO*dISO + dShutter*dShutter); + if( this->maker.compare( mak) != 0 ) { + return INFINITY; + } + + if( this->model.compare( mod) != 0 ) { + return INFINITY; + } + + double dISO = (log(this->iso / 100.) - log(iso / 100.)) / log(2); + double dShutter = (log(this->shutter) - log(shutter)) / log(2); + return sqrt( dISO * dISO + dShutter * dShutter); } RawImage* dfInfo::getRawImage() { - if(ri) - return ri; - updateRawImage(); - updateBadPixelList( ri ); + if(ri) { + return ri; + } - return ri; + updateRawImage(); + updateBadPixelList( ri ); + + return ri; } std::vector& dfInfo::getHotPixels() { - if( !ri ){ - updateRawImage(); - updateBadPixelList( ri ); - } - return badPixels; + if( !ri ) { + updateRawImage(); + updateBadPixelList( ri ); + } + + return badPixels; } /* updateRawImage() load into ri the actual pixel data from pathname if there is a single shot * otherwise load each file from the pathNames list and extract a template from the media; @@ -110,105 +131,130 @@ std::vector& dfInfo::getHotPixels() */ void dfInfo::updateRawImage() { - typedef unsigned int acc_t; - if( !pathNames.empty() ){ - std::list::iterator iName = pathNames.begin(); - ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) - if( ri->loadRaw(true)){ - delete ri; - ri=NULL; - }else{ - int H = ri->get_height(); - int W = ri->get_width(); - ri->compress_image(); - int rSize = W*((ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS)?1:3); - acc_t **acc = new acc_t*[H]; - for( int row=0; rowdata[row][col]; - int nFiles = 1; // First file data already loaded + if( !pathNames.empty() ) { + std::list::iterator iName = pathNames.begin(); + ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) - for( iName++; iName != pathNames.end(); iName++){ - RawImage* temp = new RawImage(*iName); - if( !temp->loadRaw(true)){ - temp->compress_image(); //\ TODO would be better working on original, because is temporary - nFiles++; - if( ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS ){ - for( int row=0; rowdata[row][col]; - } - }else{ - for( int row=0; rowdata[row][3*col+0]; - acc[row][3*col+1] += temp->data[row][3*col+1]; - acc[row][3*col+2] += temp->data[row][3*col+2]; - } - } - } - } - delete temp; - } - for (int row = 0; row < H; row++){ - for (int col = 0; col < rSize; col++) - ri->data[row][col] = acc[row][col] / nFiles; - delete [] acc[row]; - } - delete [] acc; - } - }else{ - ri = new RawImage(pathname); - if( ri->loadRaw(true)){ - delete ri; - ri=NULL; - }else - ri->compress_image(); - } + if( ri->loadRaw(true)) { + delete ri; + ri = NULL; + } else { + int H = ri->get_height(); + int W = ri->get_width(); + ri->compress_image(); + int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) ? 1 : 3); + acc_t **acc = new acc_t*[H]; + + for( int row = 0; row < H; row++) { + acc[row] = new acc_t[rSize ]; + } + + // copy first image into accumulators + for (int row = 0; row < H; row++) + for (int col = 0; col < rSize; col++) { + acc[row][col] = ri->data[row][col]; + } + + int nFiles = 1; // First file data already loaded + + for( iName++; iName != pathNames.end(); iName++) { + RawImage* temp = new RawImage(*iName); + + if( !temp->loadRaw(true)) { + temp->compress_image(); //\ TODO would be better working on original, because is temporary + nFiles++; + + if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) { + for( int row = 0; row < H; row++) { + for( int col = 0; col < W; col++) { + acc[row][col] += temp->data[row][col]; + } + } + } else { + for( int row = 0; row < H; row++) { + for( int col = 0; col < W; col++) { + acc[row][3 * col + 0] += temp->data[row][3 * col + 0]; + acc[row][3 * col + 1] += temp->data[row][3 * col + 1]; + acc[row][3 * col + 2] += temp->data[row][3 * col + 2]; + } + } + } + } + + delete temp; + } + + for (int row = 0; row < H; row++) { + for (int col = 0; col < rSize; col++) { + ri->data[row][col] = acc[row][col] / nFiles; + } + + delete [] acc[row]; + } + + delete [] acc; + } + } else { + ri = new RawImage(pathname); + + if( ri->loadRaw(true)) { + delete ri; + ri = NULL; + } else { + ri->compress_image(); + } + } } void dfInfo::updateBadPixelList( RawImage *df ) { - const float threshold=10.f/8.f; - if( ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS ){ - std::vector badPixelsTemp; + const float threshold = 10.f / 8.f; -#pragma omp parallel -{ - std::vector badPixelsThread; -#pragma omp for nowait - for( int row=2; rowget_height()-2; row++) - for( int col=2; col < df->get_width()-2; col++){ - float m = (df->data[row-2][col-2] + df->data[row-2][col] + df->data[row-2][col+2]+ - df->data[row][col-2] + df->data[row][col+2]+ - df->data[row+2][col-2] + df->data[row+2][col] + df->data[row+2][col+2]); - if( df->data[row][col] > m*threshold ) - badPixelsThread.push_back( badPix(col,row) ); - } -#pragma omp critical - badPixelsTemp.insert(badPixelsTemp.end(),badPixelsThread.begin(),badPixelsThread.end()); -} - badPixels.insert(badPixels.end(),badPixelsTemp.begin(),badPixelsTemp.end()); - }else{ - for( int row=1; rowget_height()-1; row++) - for( int col=1; col < df->get_width()-1; col++){ - float m[3]; - for( int c=0; c<3;c++){ - m[c] = (df->data[row-1][3*(col-1)+c] + df->data[row-1][3*col+c] + df->data[row-1][3*(col+1)+c]+ - df->data[row] [3*(col-1)+c] + df->data[row] [3*col+c]+ - df->data[row+1][3*(col-1)+c] + df->data[row+1][3*col+c] + df->data[row+1][3*(col+1)+c]); - } - if( df->data[row][3*col] > m[0]*threshold || df->data[row][3*col+1] > m[1]*threshold || df->data[row][3*col+2] > m[2]*threshold) - badPixels.push_back( badPix(col,row) ); - } - } - if( settings->verbose ){ - std::cout << "Extracted " << badPixels.size() << " pixels from darkframe:" << df->get_filename().c_str() << std::endl; - } + if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) { + std::vector badPixelsTemp; + + #pragma omp parallel + { + std::vector badPixelsThread; + #pragma omp for nowait + + for( int row = 2; row < df->get_height() - 2; row++) + for( int col = 2; col < df->get_width() - 2; col++) { + float m = (df->data[row - 2][col - 2] + df->data[row - 2][col] + df->data[row - 2][col + 2] + + df->data[row][col - 2] + df->data[row][col + 2] + + df->data[row + 2][col - 2] + df->data[row + 2][col] + df->data[row + 2][col + 2]); + + if( df->data[row][col] > m * threshold ) { + badPixelsThread.push_back( badPix(col, row) ); + } + } + + #pragma omp critical + badPixelsTemp.insert(badPixelsTemp.end(), badPixelsThread.begin(), badPixelsThread.end()); + } + badPixels.insert(badPixels.end(), badPixelsTemp.begin(), badPixelsTemp.end()); + } else { + for( int row = 1; row < df->get_height() - 1; row++) + for( int col = 1; col < df->get_width() - 1; col++) { + float m[3]; + + for( int c = 0; c < 3; c++) { + m[c] = (df->data[row - 1][3 * (col - 1) + c] + df->data[row - 1][3 * col + c] + df->data[row - 1][3 * (col + 1) + c] + + df->data[row] [3 * (col - 1) + c] + df->data[row] [3 * col + c] + + df->data[row + 1][3 * (col - 1) + c] + df->data[row + 1][3 * col + c] + df->data[row + 1][3 * (col + 1) + c]); + } + + if( df->data[row][3 * col] > m[0]*threshold || df->data[row][3 * col + 1] > m[1]*threshold || df->data[row][3 * col + 2] > m[2]*threshold) { + badPixels.push_back( badPix(col, row) ); + } + } + } + + if( settings->verbose ) { + std::cout << "Extracted " << badPixels.size() << " pixels from darkframe:" << df->get_filename().c_str() << std::endl; + } } @@ -218,106 +264,139 @@ void DFManager::init( Glib::ustring pathname ) { std::vector names; Glib::RefPtr dir = Gio::File::create_for_path (pathname); - if( dir && !dir->query_exists()) - return; - safe_build_file_list (dir, names, pathname); - - dfList.clear(); - bpList.clear(); - for (size_t i=0; iquery_exists()) { + return; + } + + safe_build_file_list (dir, names, pathname); + + dfList.clear(); + bpList.clear(); + + for (size_t i = 0; i < names.size(); i++) { size_t lastdot = names[i].find_last_of ('.'); - if (lastdot != Glib::ustring::npos && names[i].substr(lastdot) == ".badpixels" ){ - int n = scanBadPixelsFile( names[i] ); - if( n>0 && settings->verbose) - printf("Loaded %s: %d pixels\n",names[i].c_str(),n); - continue; + + if (lastdot != Glib::ustring::npos && names[i].substr(lastdot) == ".badpixels" ) { + int n = scanBadPixelsFile( names[i] ); + + if( n > 0 && settings->verbose) { + printf("Loaded %s: %d pixels\n", names[i].c_str(), n); + } + + continue; } - try{ + + try { addFileInfo(names[i]); - }catch( std::exception& e ){} + } catch( std::exception& e ) {} } + // Where multiple shots exist for same group, move filename to list - for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){ - dfInfo &i = iter->second; - if( !i.pathNames.empty() && !i.pathname.empty() ){ - i.pathNames.push_back( i.pathname ); - i.pathname.clear(); - } - if( settings->verbose ){ - if( !i.pathname.empty() ) - printf( "%s: %s\n",i.key().c_str(),i.pathname.c_str()); - else{ - printf( "%s: MEAN of \n ",i.key().c_str()); - for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end();iter++ ) - printf( "%s, ", iter->c_str() ); - printf("\n"); - } - } + for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); iter++ ) { + dfInfo &i = iter->second; + + if( !i.pathNames.empty() && !i.pathname.empty() ) { + i.pathNames.push_back( i.pathname ); + i.pathname.clear(); + } + + if( settings->verbose ) { + if( !i.pathname.empty() ) { + printf( "%s: %s\n", i.key().c_str(), i.pathname.c_str()); + } else { + printf( "%s: MEAN of \n ", i.key().c_str()); + + for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end(); iter++ ) { + printf( "%s, ", iter->c_str() ); + } + + printf("\n"); + } + } } + currentPath = 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); - if (!file ) - return 0; - if( !file->query_exists()) - return 0; - Glib::RefPtr info = safe_query_file_info(file); - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); - 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( !res ){ - 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++; + Glib::RefPtr file = Gio::File::create_for_path(filename); - 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); - } - } + if (!file ) { + return 0; } + + if( !file->query_exists()) { + return 0; + } + + Glib::RefPtr info = safe_query_file_info(file); + + if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { + size_t lastdot = info->get_name().find_last_of ('.'); + + 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( !res ) { + 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); + } + } + } + return 0; } void DFManager::getStat( int &totFiles, int &totTemplates) { - totFiles=0; - totTemplates=0; - for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){ - dfInfo &i = iter->second; - if( i.pathname.empty() ){ - totTemplates++; - totFiles += i.pathNames.size(); - }else - totFiles++; + totFiles = 0; + totTemplates = 0; + + for( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); iter++ ) { + dfInfo &i = iter->second; + + if( i.pathname.empty() ) { + totTemplates++; + totFiles += i.pathNames.size(); + } else { + totFiles++; + } } } @@ -327,156 +406,202 @@ void DFManager::getStat( int &totFiles, int &totTemplates) */ dfInfo* DFManager::find( const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t ) { - if( dfList.empty() ) - return 0; - std::string key( dfInfo::key(mak,mod,isospeed,shut) ); - dfList_t::iterator iter = dfList.find( key ); + if( dfList.empty() ) { + return 0; + } + + std::string key( dfInfo::key(mak, mod, isospeed, shut) ); + dfList_t::iterator iter = dfList.find( key ); + + if( iter != dfList.end() ) { + dfList_t::iterator bestMatch = iter; + time_t bestDeltaTime = ABS(iter->second.timestamp - t); + + for(iter++; iter != dfList.end() && !key.compare( iter->second.key() ); iter++ ) { + time_t d = ABS(iter->second.timestamp - t ); + + if( d < bestDeltaTime ) { + bestMatch = iter; + bestDeltaTime = d; + } + } - if( iter != dfList.end() ){ - dfList_t::iterator bestMatch = iter; - time_t bestDeltaTime = ABS(iter->second.timestamp - t); - for(iter++; iter != dfList.end() && !key.compare( iter->second.key() ); iter++ ){ - time_t d = ABS(iter->second.timestamp - t ); - if( d< bestDeltaTime ){ - bestMatch = iter; - bestDeltaTime = d; - } - } return &(bestMatch->second); - }else{ - iter = dfList.begin(); - dfList_t::iterator bestMatch = iter; - double bestD = iter->second.distance( mak, mod, isospeed, shut ); - for( iter++; iter != dfList.end();iter++ ){ - double d = iter->second.distance( mak, mod, isospeed, shut ); - if( d < bestD ){ - bestD = d; - bestMatch = iter; - } - } - return bestD != INFINITY ? &(bestMatch->second) : 0 ; - } + } else { + iter = dfList.begin(); + dfList_t::iterator bestMatch = iter; + double bestD = iter->second.distance( mak, mod, isospeed, shut ); + + for( iter++; iter != dfList.end(); iter++ ) { + double d = iter->second.distance( mak, mod, isospeed, shut ); + + if( d < bestD ) { + bestD = d; + bestMatch = iter; + } + } + + return bestD != INFINITY ? &(bestMatch->second) : 0 ; + } } RawImage* DFManager::searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t ) { - dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t ); - if( df ) - return df->getRawImage(); - else - return 0; + dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t ); + + if( df ) { + return df->getRawImage(); + } else { + return 0; + } } RawImage* DFManager::searchDarkFrame( const Glib::ustring filename ) { - for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){ - if( iter->second.pathname.compare( filename )==0 ) - return iter->second.getRawImage(); - } - dfInfo *df = addFileInfo( filename, false ); - if(df) - return df->getRawImage(); - return 0; + for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); iter++ ) { + if( iter->second.pathname.compare( filename ) == 0 ) { + return iter->second.getRawImage(); + } + } + + dfInfo *df = addFileInfo( filename, false ); + + if(df) { + return df->getRawImage(); + } + + return 0; } std::vector *DFManager::getHotPixels ( const Glib::ustring filename ) { - for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){ - if( iter->second.pathname.compare( filename )==0 ) - return &iter->second.getHotPixels(); - } - return 0; + for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end(); iter++ ) { + if( iter->second.pathname.compare( filename ) == 0 ) { + return &iter->second.getHotPixels(); + } + } + + return 0; } std::vector *DFManager::getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t ) { - dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t ); - if( df ){ - if( settings->verbose ) { - if( !df->pathname.empty() ) { - printf( "Searched hotpixels from %s\n",df->pathname.c_str()); - } else { - if( !df->pathNames.empty() ) { - printf( "Searched hotpixels from template (first %s)\n",df->pathNames.begin()->c_str()); - } - } - } - return &df->getHotPixels(); - }else - return 0; + dfInfo *df = find( ((Glib::ustring)mak).uppercase(), ((Glib::ustring)mod).uppercase(), iso, shut, t ); + + if( df ) { + if( settings->verbose ) { + if( !df->pathname.empty() ) { + printf( "Searched hotpixels from %s\n", df->pathname.c_str()); + } else { + if( !df->pathNames.empty() ) { + printf( "Searched hotpixels from template (first %s)\n", df->pathNames.begin()->c_str()); + } + } + } + + return &df->getHotPixels(); + } else { + return 0; + } } int DFManager::scanBadPixelsFile( Glib::ustring filename ) { - FILE *file = fopen( filename.c_str(),"r" ); - if( !file ) return false; - size_t lastdot = filename.find_last_of ('.'); - size_t dirpos1 = filename.find_last_of ('/'); - size_t dirpos2 = filename.find_last_of ('\\'); - if( dirpos1 == Glib::ustring::npos && dirpos2== Glib::ustring::npos ) - dirpos1 =0; - else if( dirpos1 != Glib::ustring::npos && dirpos2 != Glib::ustring::npos ) - dirpos1= (dirpos1> dirpos2 ? dirpos1: dirpos2); - else if( dirpos1 == Glib::ustring::npos ) - dirpos1= dirpos2; + FILE *file = fopen( filename.c_str(), "r" ); + + if( !file ) { + return false; + } + + size_t lastdot = filename.find_last_of ('.'); + size_t dirpos1 = filename.find_last_of ('/'); + size_t dirpos2 = filename.find_last_of ('\\'); + + if( dirpos1 == Glib::ustring::npos && dirpos2 == Glib::ustring::npos ) { + dirpos1 = 0; + } else if( dirpos1 != Glib::ustring::npos && dirpos2 != Glib::ustring::npos ) { + dirpos1 = (dirpos1 > dirpos2 ? dirpos1 : dirpos2); + } else if( dirpos1 == Glib::ustring::npos ) { + dirpos1 = dirpos2; + } + + std::string makmodel(filename, dirpos1 + 1, lastdot - (dirpos1 + 1) ); + std::vector bp; + char line[256]; + + if(fgets(line, sizeof(line), file )) { + int x, y; + int offset = 0; + int numparms = sscanf(line, "%d %d", &x, &y); + + if( numparms == 1 ) { // only one number in first line means, that this is the offset. + offset = x; + } else if(numparms == 2) { + bp.push_back( badPix(x + offset, y + offset) ); + } + + while( fgets(line, sizeof(line), file ) ) { + if( sscanf(line, "%d %d", &x, &y) == 2 ) { + bp.push_back( badPix(x + offset, y + offset) ); + } + } + } - std::string makmodel(filename,dirpos1+1,lastdot-(dirpos1+1) ); - std::vector bp; - char line[256]; - if(fgets(line,sizeof(line),file )) { - int x,y; - int offset = 0; - int numparms = sscanf(line,"%d %d",&x,&y); - if( numparms == 1 ) // only one number in first line means, that this is the offset. - offset = x; - else if(numparms == 2) - bp.push_back( badPix(x+offset,y+offset) ); - while( fgets(line,sizeof(line),file ) ){ - if( sscanf(line,"%d %d",&x,&y) == 2 ) - bp.push_back( badPix(x+offset,y+offset) ); - } - } int numPixels = bp.size(); - if( numPixels >0 ) - bpList[ makmodel ] = bp; + + if( numPixels > 0 ) { + bpList[ makmodel ] = bp; + } + fclose(file); - return numPixels; + return numPixels; } std::vector *DFManager::getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial) { - bpList_t::iterator iter; - bool found = false; - if( !serial.empty() ) { - // search with sreial number first - std::ostringstream s; - s << mak << " " << mod << " " << serial; - iter = bpList.find( s.str() ); - if( iter != bpList.end() ) - found = true; - if( settings->verbose ) - if(found) - printf("%s.badpixels found\n",s.str().c_str()); - else - printf("%s.badpixels not found\n",s.str().c_str()); + bpList_t::iterator iter; + bool found = false; - } - if(!found) { - // search without serial number - std::ostringstream s; - s << mak << " " <verbose ) - if(found) - printf("%s.badpixels found\n",s.str().c_str()); - else - printf("%s.badpixels not found\n",s.str().c_str()); - } - if(!found) { - return 0; - } else { - return &(iter->second); - } + if( !serial.empty() ) { + // search with sreial number first + std::ostringstream s; + s << mak << " " << mod << " " << serial; + iter = bpList.find( s.str() ); + + if( iter != bpList.end() ) { + found = true; + } + + if( settings->verbose ) + if(found) { + printf("%s.badpixels found\n", s.str().c_str()); + } else { + printf("%s.badpixels not found\n", s.str().c_str()); + } + + } + + if(!found) { + // search without serial number + std::ostringstream s; + s << mak << " " << mod; + iter = bpList.find( s.str() ); + + if( iter != bpList.end() ) { + found = true; + } + + if( settings->verbose ) + if(found) { + printf("%s.badpixels found\n", s.str().c_str()); + } else { + printf("%s.badpixels not found\n", s.str().c_str()); + } + } + + if(!found) { + return 0; + } else { + return &(iter->second); + } } // Global variable diff --git a/rtengine/dfmanager.h b/rtengine/dfmanager.h index 784e70290..befe67f5a 100644 --- a/rtengine/dfmanager.h +++ b/rtengine/dfmanager.h @@ -7,7 +7,7 @@ * 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 @@ -22,71 +22,83 @@ #include #include "rawimage.h" -namespace rtengine{ +namespace rtengine +{ class dfInfo { public: - Glib::ustring pathname; // filename of dark frame - std::list pathNames; // other similar dark frames, used for average - std::string maker; ///< manufacturer - std::string model; ///< model - int iso; ///< ISO (gain) - double shutter; ///< shutter or exposure time in sec - time_t timestamp; ///< seconds since 1 Jan 1970 + Glib::ustring pathname; // filename of dark frame + std::list pathNames; // other similar dark frames, used for average + std::string maker; ///< manufacturer + std::string model; ///< model + int iso; ///< ISO (gain) + double shutter; ///< shutter or exposure time in sec + time_t timestamp; ///< seconds since 1 Jan 1970 - dfInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod,int iso,double shut,time_t t) - :pathname(name),maker(mak),model(mod),iso(iso),shutter(shut),timestamp(t),ri(NULL){} + dfInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, int iso, double shut, time_t t) + : pathname(name), maker(mak), model(mod), iso(iso), shutter(shut), timestamp(t), ri(NULL) {} - dfInfo( const dfInfo &o) - :pathname(o.pathname),maker(o.maker),model(o.model),iso(o.iso),shutter(o.shutter),timestamp(o.timestamp),ri(NULL){} - ~dfInfo() { if( ri ) delete ri; } + dfInfo( const dfInfo &o) + : pathname(o.pathname), maker(o.maker), model(o.model), iso(o.iso), shutter(o.shutter), timestamp(o.timestamp), ri(NULL) {} + ~dfInfo() + { + if( ri ) { + delete ri; + } + } - - dfInfo &operator =(const dfInfo &o); - bool operator <(const dfInfo &e2) const; - // Calculate virtual distance between two shots; different model return infinite - double distance(const std::string &mak, const std::string &mod, int iso, double shutter) const; + dfInfo &operator =(const dfInfo &o); + bool operator <(const dfInfo &e2) const; - static std::string key(const std::string &mak, const std::string &mod, int iso, double shut ); - std::string key(){ return key( maker,model,iso,shutter); } + // Calculate virtual distance between two shots; different model return infinite + double distance(const std::string &mak, const std::string &mod, int iso, double shutter) const; - RawImage *getRawImage(); - std::vector &getHotPixels(); + static std::string key(const std::string &mak, const std::string &mod, int iso, double shut ); + std::string key() + { + return key( maker, model, iso, shutter); + } + + RawImage *getRawImage(); + std::vector &getHotPixels(); protected: - RawImage *ri; ///< Dark Frame raw data - std::vector badPixels; ///< Extracted hot pixels + RawImage *ri; ///< Dark Frame raw data + std::vector badPixels; ///< Extracted hot pixels - void updateBadPixelList( RawImage *df ); - void updateRawImage(); + void updateBadPixelList( RawImage *df ); + void updateRawImage(); }; class DFManager { public: - void init( Glib::ustring pathname ); - Glib::ustring getPathname(){ return currentPath; }; - void getStat( int &totFiles, int &totTemplate); - RawImage *searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t ); - RawImage *searchDarkFrame( const Glib::ustring filename ); - std::vector *getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t ); - std::vector *getHotPixels ( const Glib::ustring filename ); - std::vector *getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial); + void init( Glib::ustring pathname ); + Glib::ustring getPathname() + { + return currentPath; + }; + void getStat( int &totFiles, int &totTemplate); + RawImage *searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t ); + RawImage *searchDarkFrame( const Glib::ustring filename ); + std::vector *getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t ); + std::vector *getHotPixels ( const Glib::ustring filename ); + std::vector *getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial); protected: - typedef std::multimap dfList_t; - typedef std::map > bpList_t; - dfList_t dfList; - bpList_t bpList; - bool initialized; - Glib::ustring currentPath; - dfInfo *addFileInfo(const Glib::ustring &filename, bool pool=true ); - dfInfo *find( const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t ); - int scanBadPixelsFile( Glib::ustring filename ); + typedef std::multimap dfList_t; + typedef std::map > bpList_t; + dfList_t dfList; + bpList_t bpList; + bool initialized; + Glib::ustring currentPath; + dfInfo *addFileInfo(const Glib::ustring &filename, bool pool = true ); + dfInfo *find( const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t ); + int scanBadPixelsFile( Glib::ustring filename ); }; extern DFManager dfm; diff --git a/rtengine/diagonalcurves.cc b/rtengine/diagonalcurves.cc index 20b22a916..5ef4eefca 100644 --- a/rtengine/diagonalcurves.cc +++ b/rtengine/diagonalcurves.cc @@ -7,7 +7,7 @@ * 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 @@ -26,76 +26,97 @@ #define CLIPD(a) ((a)>0.0?((a)<1.0?(a):1.0):0.0) -namespace rtengine { +namespace rtengine +{ -DiagonalCurve::DiagonalCurve (const std::vector& p, int poly_pn) { +DiagonalCurve::DiagonalCurve (const std::vector& p, int poly_pn) +{ ppn = poly_pn > 65500 ? 65500 : poly_pn; bool identity = true; - if (ppn < 500) hashSize = 100; // Arbitrary cut-off value, but mutliple of 10 - if (ppn < 50) hashSize = 10; // Arbitrary cut-off value, but mutliple of 10 - - if (p.size()<3) { - kind = DCT_Empty; + if (ppn < 500) { + hashSize = 100; // Arbitrary cut-off value, but mutliple of 10 } - else { + + if (ppn < 50) { + hashSize = 10; // Arbitrary cut-off value, but mutliple of 10 + } + + if (p.size() < 3) { + kind = DCT_Empty; + } else { kind = (DiagonalCurveType)p[0]; - if (kind==DCT_Linear || kind==DCT_Spline || kind==DCT_NURBS) { - N = (p.size()-1)/2; + + if (kind == DCT_Linear || kind == DCT_Spline || kind == DCT_NURBS) { + N = (p.size() - 1) / 2; x = new double[N]; y = new double[N]; int ix = 1; - for (int i=0; i 2) + if (kind == DCT_Spline && N > 2) { spline_cubic_set (); - else if (kind==DCT_NURBS && N > 2) { + } else if (kind == DCT_NURBS && N > 2) { NURBS_set (); fillHash(); + } else { + kind = DCT_Linear; } - else kind=DCT_Linear; } - } - else if (kind==DCT_Parametric) { - if ((p.size()==8 || p.size()==9) && (p.at(4)!=0.0f || p.at(5)!=0.0f || p.at(6)!=0.0f || p.at(7)!=0.0f)) { + } else if (kind == DCT_Parametric) { + if ((p.size() == 8 || p.size() == 9) && (p.at(4) != 0.0f || p.at(5) != 0.0f || p.at(6) != 0.0f || p.at(7) != 0.0f)) { identity = false; x = new double[9]; x[0] = p[0]; - for (int i=1; i<4; i++) { - x[i] = min(max(p[i],0.001),0.99); + + for (int i = 1; i < 4; i++) { + x[i] = min(max(p[i], 0.001), 0.99); } - for (int i=4; i<8; i++) - x[i] = (p[i]+100.0)/200.0; - if (p.size()<9) + + for (int i = 4; i < 8; i++) { + x[i] = (p[i] + 100.0) / 200.0; + } + + if (p.size() < 9) { x[8] = 1.0; - else - x[8] = p[8]/100.0; - mc = -xlog(2.0)/xlog(x[2]); - double mbase = pfull (0.5, x[8], x[6], x[5]); - mfc = mbase<=1e-14 ? 0.0 : xexp(xlog(mbase)/mc); // value of the curve at the center point - msc = -xlog(2.0)/xlog(x[1]/x[2]); - mhc = -xlog(2.0)/xlog((x[3]-x[2])/(1-x[2])); + } else { + x[8] = p[8] / 100.0; + } + + mc = -xlog(2.0) / xlog(x[2]); + double mbase = pfull (0.5, x[8], x[6], x[5]); + mfc = mbase <= 1e-14 ? 0.0 : xexp(xlog(mbase) / mc); // value of the curve at the center point + msc = -xlog(2.0) / xlog(x[1] / x[2]); + mhc = -xlog(2.0) / xlog((x[3] - x[2]) / (1 - x[2])); } } + if (identity) { - kind = DCT_Empty; + kind = DCT_Empty; } } } -DiagonalCurve::~DiagonalCurve () { +DiagonalCurve::~DiagonalCurve () +{ delete [] x; delete [] y; @@ -104,45 +125,50 @@ DiagonalCurve::~DiagonalCurve () { poly_y.clear(); } -void DiagonalCurve::spline_cubic_set () { +void DiagonalCurve::spline_cubic_set () +{ - double* u = new double[N-1]; - delete [] ypp; // TODO: why do we delete ypp here since it should not be allocated yet? + double* u = new double[N - 1]; + delete [] ypp; // TODO: why do we delete ypp here since it should not be allocated yet? ypp = new double [N]; - ypp[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */ + ypp[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */ for (int i = 1; i < N - 1; ++i) { double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]); double p = sig * ypp[i - 1] + 2.0; ypp[i] = (sig - 1.0) / p; u[i] = ((y[i + 1] - y[i]) - / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1])); + / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1])); u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p; } ypp[N - 1] = 0.0; - for (int k = N - 2; k >= 0; --k) + + for (int k = N - 2; k >= 0; --k) { ypp[k] = ypp[k] * ypp[k + 1] + u[k]; + } delete [] u; } -void DiagonalCurve::NURBS_set () { +void DiagonalCurve::NURBS_set () +{ - int nbSubCurvesPoints = N + (N-3)*2; + int nbSubCurvesPoints = N + (N - 3) * 2; std::vector sc_x(nbSubCurvesPoints); // X sub-curve points ( XP0,XP1,XP2, XP2,XP3,XP4, ...) std::vector sc_y(nbSubCurvesPoints); // Y sub-curve points ( YP0,YP1,YP2, YP2,YP3,YP4, ...) - std::vector sc_length(N+2); // Length of the subcurves - double total_length=0.; + std::vector sc_length(N + 2); // Length of the subcurves + double total_length = 0.; // Create the list of Bezier sub-curves // NURBS_set is called if N > 2 and non identity only int j = 0; int k = 0; - for (int i = 0; i < N-1;) { + + for (int i = 0; i < N - 1;) { double length; double dx; double dy; @@ -151,33 +177,32 @@ void DiagonalCurve::NURBS_set () { if (!i) { sc_x[j] = x[i]; sc_y[j++] = y[i++]; - } - else { - sc_x[j] = (x[i-1] + x[i]) / 2.; - sc_y[j++] = (y[i-1] + y[i]) / 2.; + } else { + sc_x[j] = (x[i - 1] + x[i]) / 2.; + sc_y[j++] = (y[i - 1] + y[i]) / 2.; } // second point (control point) sc_x[j] = x[i]; sc_y[j] = y[i++]; - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length = sqrt(dx*dx + dy*dy); + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length = sqrt(dx * dx + dy * dy); j++; // third point (on the curve) - if (i==N-1) { + if (i == N - 1) { sc_x[j] = x[i]; sc_y[j] = y[i]; + } else { + sc_x[j] = (x[i - 1] + x[i]) / 2.; + sc_y[j] = (y[i - 1] + y[i]) / 2.; } - else { - sc_x[j] = (x[i-1] + x[i]) / 2.; - sc_y[j] = (y[i-1] + y[i]) / 2.; - } - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length += sqrt(dx*dx + dy*dy); + + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length += sqrt(dx * dx + dy * dy); j++; // Storing the length of all sub-curves and the total length (to have a better distribution @@ -188,127 +213,152 @@ void DiagonalCurve::NURBS_set () { poly_x.clear(); poly_y.clear(); - unsigned int sc_xsize=j-1; + unsigned int sc_xsize = j - 1; j = 0; // adding the initial horizontal segment, if any if (x[0] > 0.) { - poly_x.push_back(0.); - poly_y.push_back(y[0]); + poly_x.push_back(0.); + poly_y.push_back(y[0]); } // adding the initial horizontal segment, if any // create the polyline with the number of points adapted to the X range of the sub-curve - for (unsigned int i=0; i < sc_xsize /*sc_x.size()*/; i+=3) { + for (unsigned int i = 0; i < sc_xsize /*sc_x.size()*/; i += 3) { // TODO: Speeding-up the interface by caching the polyline, instead of rebuilding it at each action on sliders !!! - nbr_points = (int)(((double)(ppn+N-2) * sc_length[i/3] )/ total_length); - if (nbr_points<0){ - for(size_t it=0;it < sc_x.size(); it+=3) printf("sc_length[%zu/3]=%f \n",it,sc_length[it/3]); - printf("NURBS diagonal curve: error detected!\n i=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f",i,nbr_points,ppn,N,sc_length[i/3],total_length); + nbr_points = (int)(((double)(ppn + N - 2) * sc_length[i / 3] ) / total_length); + + if (nbr_points < 0) { + for(size_t it = 0; it < sc_x.size(); it += 3) { + printf("sc_length[%zu/3]=%f \n", it, sc_length[it / 3]); + } + + printf("NURBS diagonal curve: error detected!\n i=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f", i, nbr_points, ppn, N, sc_length[i / 3], total_length); exit(0); } + // increment along the curve, not along the X axis - increment = 1.0 / (double)(nbr_points-1); - x1 = sc_x[i]; y1 = sc_y[i]; - x2 = sc_x[i+1]; y2 = sc_y[i+1]; - x3 = sc_x[i+2]; y3 = sc_y[i+2]; + increment = 1.0 / (double)(nbr_points - 1); + x1 = sc_x[i]; + y1 = sc_y[i]; + x2 = sc_x[i + 1]; + y2 = sc_y[i + 1]; + x3 = sc_x[i + 2]; + y3 = sc_y[i + 2]; firstPointIncluded = !i; AddPolygons (); } // adding the final horizontal segment, always (see under) - poly_x.push_back(3.0); // 3.0 is a hack for optimization purpose of the getVal method (the last value has to be beyond the normal range) - poly_y.push_back(y[N-1]); + poly_x.push_back(3.0); // 3.0 is a hack for optimization purpose of the getVal method (the last value has to be beyond the normal range) + poly_y.push_back(y[N - 1]); } -double DiagonalCurve::getVal (double t) const { +double DiagonalCurve::getVal (double t) const +{ switch (kind) { case DCT_Parametric : { - if (t<=1e-14) + if (t <= 1e-14) { return 0.0; - double tv = xexp(mc*xlog(t)); - double base = pfull (tv, x[8], x[6], x[5]); - double stretched = base<=1e-14 ? 0.0 : xexp(xlog(base)/mc); + } - if (tx[N-1]) - return y[N-1]; - else if (t x[N - 1]) { + return y[N - 1]; + } else if (t < x[0]) { return y[0]; + } // do a binary search for the right interval: int k_lo = 0, k_hi = N - 1; - while (k_hi - k_lo > 1){ + + while (k_hi - k_lo > 1) { int k = (k_hi + k_lo) / 2; - if (x[k] > t) + + if (x[k] > t) { k_hi = k; - else + } else { k_lo = k; + } } double h = x[k_hi] - x[k_lo]; + // linear - if (kind==DCT_Linear) + if (kind == DCT_Linear) { return y[k_lo] + (t - x[k_lo]) * ( y[k_hi] - y[k_lo] ) / h; + } // spline curve else { // if (kind==Spline) { double a = (x[k_hi] - t) / h; double b = (t - x[k_lo]) / h; - double r = a*y[k_lo] + b*y[k_hi] + ((a*a*a - a)*ypp[k_lo] + (b*b*b - b)*ypp[k_hi]) * (h*h)/6.0; + double r = a * y[k_lo] + b * y[k_hi] + ((a * a * a - a) * ypp[k_lo] + (b * b * b - b) * ypp[k_hi]) * (h * h) / 6.0; return CLIPD(r); } + break; } + case DCT_NURBS : { - // get the hash table entry by rounding the value (previously multiplied by "hashSize") - unsigned short int i = (unsigned short int)(t*hashSize); + // get the hash table entry by rounding the value (previously multiplied by "hashSize") + unsigned short int i = (unsigned short int)(t * hashSize); - if (i > (hashSize+1)) { - //printf("\nOVERFLOW: hash #%d is used while seeking for value %.8f, corresponding polygon's point #%d (out of %d point) x value: %.8f\n\n", i, t, hash.at(i), poly_x.size(), poly_x[hash.at(i)]); - printf("\nOVERFLOW: hash #%d is used while seeking for value %.8f\n\n", i, t); - return t; - } + if (i > (hashSize + 1)) { + //printf("\nOVERFLOW: hash #%d is used while seeking for value %.8f, corresponding polygon's point #%d (out of %d point) x value: %.8f\n\n", i, t, hash.at(i), poly_x.size(), poly_x[hash.at(i)]); + printf("\nOVERFLOW: hash #%d is used while seeking for value %.8f\n\n", i, t); + return t; + } - unsigned int k_lo; - unsigned int k_hi; + unsigned int k_lo; + unsigned int k_hi; - k_lo = hash.at(i).smallerValue; - k_hi = hash.at(i).higherValue; + k_lo = hash.at(i).smallerValue; + k_hi = hash.at(i).higherValue; - // do a binary search for the right interval : - while (k_hi - k_lo > 1){ - unsigned int k = (k_hi + k_lo) / 2; - if (poly_x[k] > t) - k_hi = k; - else - k_lo = k; - } - if (k_lo == k_hi) - k_hi = k_lo+1; + // do a binary search for the right interval : + while (k_hi - k_lo > 1) { + unsigned int k = (k_hi + k_lo) / 2; + + if (poly_x[k] > t) { + k_hi = k; + } else { + k_lo = k; + } + } + + if (k_lo == k_hi) { + k_hi = k_lo + 1; + } double dx = poly_x[k_hi] - poly_x[k_lo]; double dy = poly_y[k_hi] - poly_y[k_lo]; return poly_y[k_lo] + (t - poly_x[k_lo]) * ( dy ) / dx; break; } + case DCT_Empty : default: // all other (unknown) kind @@ -316,11 +366,14 @@ double DiagonalCurve::getVal (double t) const { } } -void DiagonalCurve::getVal (const std::vector& t, std::vector& res) const { +void DiagonalCurve::getVal (const std::vector& t, std::vector& res) const +{ res.resize (t.size()); - for (unsigned int i=0; i. * * � 2010 Emil Martinec - * + * */ #include @@ -47,7 +47,7 @@ rangefn_ab[(data_fine->b[i1][j1]-data_fine->b[i][j]+32768)] ) #define hmf(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ (med3(a22,med3(a22,med3(a12,a22,a32),med3(a21,a22,a23)), \ - med3(a22,med3(a11,a22,a33),med3(a13,a22,a31))) ) + med3(a22,med3(a11,a22,a33),med3(a13,a22,a31))) ) #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } @@ -62,643 +62,690 @@ PIX_SORT(p[4],p[7]); PIX_SORT(p[4],p[2]); PIX_SORT(p[6],p[4]); \ PIX_SORT(p[4],p[2]); median=p[4];} //a4 is the median -namespace rtengine { - - static const int maxlevel = 4; - - //sequence of scales - //static const int scales[8] = {1,2,4,8,16,32,64,128}; - //sequence of pitches - //static const int pitches[8] = {1,1,1,1,1,1,1,1}; - - //sequence of scales - //static const int scales[8] = {1,1,1,1,1,1,1,1}; - //sequence of pitches - //static const int pitches[8] = {2,2,2,2,2,2,2,2}; - - //sequence of scales - //static const int scales[8] = {1,1,2,2,4,4,8,8}; - //sequence of pitches - //static const int pitches[8] = {2,1,2,1,2,1,2,1}; - - //sequence of scales - static const int scales[8] = {1,1,2,4,8,16,32,64}; - //sequence of pitches - static const int pitches[8] = {2,1,1,1,1,1,1,1}; - - //pitch is spacing of subsampling - //scale is spacing of directional averaging weights - //example 1: no subsampling at any level -- pitch=1, scale=2^n - //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level - //example 3: no subsampling at first level, subsampling by 2 thereafter -- - // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter - - - - - void ImProcFunctions :: dirpyrLab_denoise(LabImage * src, LabImage * dst, const procparams::DirPyrDenoiseParams & dnparams ) - { - float gam = dnparams.gamma/3.0; - //float gam = 2.0;//min(3.0, 0.1*fabs(c[4])/3.0+0.001); - float gamthresh = 0.03; - float gamslope = exp(log((double)gamthresh)/gam)/gamthresh; - - LUTf gamcurve(65536,0); - - //DiagonalCurve* lumacurve = new DiagonalCurve (dnparams.lumcurve, CURVES_MIN_POLY_POINTS); - //DiagonalCurve* chromacurve = new DiagonalCurve (dnparams.chromcurve, CURVES_MIN_POLY_POINTS); - //LUTf Lcurve(65536); - //LUTf abcurve(65536); - for (int i=0; i<65536; i++) { - int g = (int)(CurveFactory::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 65535.0); - gamcurve[i] = CLIP(g); - /*float val = (float)i/65535.0; - float Lval = (2*(lumacurve->getVal(val))); - float abval = (2*(chromacurve->getVal(val))); - - Lcurve[i] = SQR(Lval); - abcurve[i] = SQR(abval); - if (i % 1000 ==0) printf("%d Lmult=%f abmult=%f \n",i,Lcurve[i],abcurve[i]);*/ - } - //delete lumacurve; - //delete chromacurve; - - - - //#pragma omp parallel for if (multiThread) - for (int i=0; iH; i++) { - for (int j=0; jW; j++) { - //src->L[i][j] = CurveFactory::flinterp(gamcurve,src->L[i][j]); - src->L[i][j] = gamcurve[src->L[i][j]]; - } - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - LUTf rangefn_L(65536); - LUTf nrwt_l(65536); - - LUTf rangefn_ab(65536); - LUTf nrwt_ab(65536); - - //set up NR weight functions - - //gamma correction for chroma in shadows - float nrwtl_norm = ((CurveFactory::gamma((double)65535.0/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) - - (CurveFactory::gamma((double)75535.0/65535.0, gam, gamthresh, gamslope, 1.0, 0.0))); - for (int i=0; i<65536; i++) { - nrwt_l[i] = ((CurveFactory::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0) - - CurveFactory::gamma((double)(i+10000)/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) )/nrwtl_norm; - //if (i % 100 ==0) printf("%d %f \n",i,nrwt_l[i]); - } - - float tonefactor = nrwt_l[32768]; - - float noise_L = 10.0*dnparams.luma; - float noisevar_L = SQR(noise_L); - - float noise_ab = 100.0*dnparams.chroma; - float noisevar_ab = SQR(noise_ab); - - - //set up range functions - for (int i=0; i<65536; i++) - rangefn_L[i] = (( exp(-(double)fabs(i-32768) * tonefactor / (1.0+noise_L)) * (1.0+noisevar_L)/((double)(i-32768)*(double)(i-32768) + noisevar_L+1.0))); - for (int i=0; i<65536; i++) - rangefn_ab[i] = (( exp(-(double)fabs(i-32768) * tonefactor / (1.0+3*noise_ab)) * (1.0+noisevar_ab)/((double)(i-32768)*(double)(i-32768) + noisevar_ab+1.0))); - - - for (int i=0; i<65536; i++) - nrwt_ab[i] = ((1.0+abs(i-32768)/(1.0+8*noise_ab)) * exp(-(double)fabs(i-32768)/ (1.0+8*noise_ab) ) ); - - - //for (int i=0; i<65536; i+=100) printf("%d %d \n",i,gamcurve[i]); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - int level; - - LabImage * dirpyrLablo[maxlevel]; - int w = (int)((src->W-1)/pitches[0])+1; - int h = (int)((src->H-1)/pitches[0])+1; - dirpyrLablo[0] = new LabImage(w, h); - for (level=1; level 0; level--) - { - - int scale = scales[level]; - int pitch = pitches[level]; - idirpyr(dirpyrLablo[level], dirpyrLablo[level-1], level, rangefn_L, nrwt_l, nrwt_ab, pitch, scale, dnparams.luma, dnparams.chroma/*, Lcurve, abcurve*/ ); - } - - - scale = scales[0]; - pitch = pitches[0]; - // freeing as much memory as possible since the next call to idirpyr will need lots - for(int i = 1; i < maxlevel; i++) { - delete dirpyrLablo[i]; - } - - idirpyr(dirpyrLablo[0], dst, 0, rangefn_L, nrwt_l, nrwt_ab, pitch, scale, dnparams.luma, dnparams.chroma/*, Lcurve, abcurve*/ ); - - // freeing the last bunch of memory - delete dirpyrLablo[0]; - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - float igam = 1/gam; - float igamthresh = gamthresh*gamslope; - float igamslope = 1/gamslope; - for (int i=0; i<65536; i++) { - gamcurve[i] = (CurveFactory::gamma((float)i/65535.0, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0); - } - - - if (dnparams.luma>0) { - for (int i=0; iH; i++) - for (int j=0; jW; j++) { - dst->L[i][j] = gamcurve[dst->L[i][j]]; - } - } else { - for (int i=0; iH; i++) - for (int j=0; jW; j++) { - dst->L[i][j] = gamcurve[src->L[i][j]]; - } - } - - } - - void ImProcFunctions::dirpyr(LabImage* data_fine, LabImage* data_coarse, int level, - LUTf & rangefn_L, LUTf & rangefn_ab, int pitch, int scale, - const int luma, const int chroma ) - { - - //pitch is spacing of subsampling - //scale is spacing of directional averaging weights - //example 1: no subsampling at any level -- pitch=1, scale=2^n - //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level - //example 3: no subsampling at first level, subsampling by 2 thereafter -- - // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // calculate weights, compute directionally weighted average - - int width = data_fine->W; - int height = data_fine->H; - - //generate domain kernel - int halfwin = 3;//min(ceil(2*sig),3); - int scalewin = halfwin*scale; - -#ifdef _OPENMP -#pragma omp parallel for -#endif - - for(int i = 0; i < height; i+=pitch ) { int i1=i/pitch; - for(int j = 0, j1=0; j < width; j+=pitch, j1++) - { - float dirwt_l, dirwt_ab, norm_l, norm_ab; - //float lops,aops,bops; - float Lout, aout, bout; - norm_l = norm_ab = 0;//if we do want to include the input pixel in the sum - Lout = 0; - aout = 0; - bout = 0; - - for(int inbr=(i-scalewin); inbr<=(i+scalewin); inbr+=scale) { - if (inbr<0 || inbr>height-1) continue; - for (int jnbr=(j-scalewin); jnbr<=(j+scalewin); jnbr+=scale) { - if (jnbr<0 || jnbr>width-1) continue; - dirwt_l = DIRWT_L(inbr, jnbr, i, j); - dirwt_ab = DIRWT_AB(inbr, jnbr, i, j); - Lout += dirwt_l*data_fine->L[inbr][jnbr]; - aout += dirwt_ab*data_fine->a[inbr][jnbr]; - bout += dirwt_ab*data_fine->b[inbr][jnbr]; - norm_l += dirwt_l; - norm_ab += dirwt_ab; - } - } - //lops = Lout/norm;//diagnostic - //aops = aout/normab;//diagnostic - //bops = bout/normab;//diagnostic - - data_coarse->L[i1][j1]=Lout/norm_l;//low pass filter - data_coarse->a[i1][j1]=aout/norm_ab; - data_coarse->b[i1][j1]=bout/norm_ab; - - - /*if (level<2 && i>0 && i0 && jL[i-1][j-1], data_fine->L[i-1][j], data_fine->L[i-1][j+1], \ - data_fine->L[i][j-1], data_fine->L[i][j], data_fine->L[i][j+1], \ - data_fine->L[i+1][j-1], data_fine->L[i+1][j], data_fine->L[i+1][j+1]); - //med3x3(data_fine->L[i-1][j-1], data_fine->L[i-1][j], data_fine->L[i-1][j+1], \ - data_fine->L[i][j-1], data_fine->L[i][j], data_fine->L[i][j+1], \ - data_fine->L[i+1][j-1], data_fine->L[i+1][j], data_fine->L[i+1][j+1],Lmed); - - data_coarse->L[i1][j1] = Lhmf; - }*/ - } - } - - - - - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void ImProcFunctions::idirpyr(LabImage* data_coarse, LabImage* data_fine, int level, LUTf &rangefn_L, LUTf & nrwt_l, LUTf & nrwt_ab, - int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/ ) - { - - int width = data_fine->W; - int height = data_fine->H; - - array2D nrfactorL (width,height); - - //float eps = 0.0; - - // c[0] noise_L - // c[1] noise_ab (relative to noise_L) - // c[2] decrease of noise var with scale - // c[3] radius of domain blur at each level - // c[4] shadow smoothing - - float noisevar_L = 4*SQR(25.0 * luma); - float noisevar_ab = 2*SQR(100.0 * chroma); - float scalefactor = 1.0/pow(2.0,(level+1)*2);//change the last 2 to 1 for longer tail of higher scale NR - - noisevar_L *= scalefactor; - - // for coarsest level, take non-subsampled lopass image and subtract from lopass_fine to generate hipass image - - // denoise hipass image, add back into lopass_fine to generate denoised image at fine scale - - // now iterate: - // (1) take denoised image at level n, expand and smooth using gradient weights from lopass image at level n-1 - // the result is the smoothed image at level n-1 - // (2) subtract smoothed image at level n-1 from lopass image at level n-1 to make hipass image at level n-1 - // (3) denoise the hipass image at level n-1 - // (4) add the denoised image at level n-1 to the smoothed image at level n-1 to make the denoised image at level n-1 - - // note that the coarsest level amounts to skipping step (1) and doing (2,3,4). - // in other words, skip step one if pitch=1 - - // step (1) - - if (pitch==1) { - - // step (1-2-3-4) - -#ifdef _OPENMP -#pragma omp parallel -#endif +namespace rtengine { - -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - float hipass[3], hpffluct[3], tonefactor, nrfactor; - - tonefactor = (nrwt_l[data_coarse->L[i][j]]); - - hipass[1] = data_fine->a[i][j]-data_coarse->a[i][j]; - hipass[2] = data_fine->b[i][j]-data_coarse->b[i][j]; - - //Wiener filter - //luma - if (level<2) { - hipass[0] = data_fine->L[i][j]-data_coarse->L[i][j]; - hpffluct[0]=SQR(hipass[0])+SQR(hipass[1])+SQR(hipass[2])+0.001; - nrfactorL[i][j] = (1.0+hpffluct[0])/(1.0+hpffluct[0]+noisevar_L /* * Lcurve[data_coarse->L[i][j]]*/); - //hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L); - //data_fine->L[i][j] = CLIP(hipass[0]+data_coarse->L[i][j]); - } - - //chroma - //hipass[1] = data_fine->a[i][j]-data_coarse->a[i][j]; - //hipass[2] = data_fine->b[i][j]-data_coarse->b[i][j]; - hpffluct[1]=SQR(hipass[1]*tonefactor)+0.001; - hpffluct[2]=SQR(hipass[2]*tonefactor)+0.001; - nrfactor = (hpffluct[1]+hpffluct[2]) /((hpffluct[1]+hpffluct[2]) + noisevar_ab * NRWT_AB); - - hipass[1] *= nrfactor; - hipass[2] *= nrfactor; - - data_fine->a[i][j] = hipass[1]+data_coarse->a[i][j]; - data_fine->b[i][j] = hipass[2]+data_coarse->b[i][j]; - } - - if (level<2) { -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - float dirwt_l, norm_l; - float nrfctrave=0; - norm_l = 0;//if we do want to include the input pixel in the sum - - for(int inbr=max(0,i-1); inbr<=min(height-1,i+1); inbr++) { - for (int jnbr=max(0,j-1); jnbr<=min(width-1,j+1); jnbr++) { - dirwt_l = DIRWT_L(inbr, jnbr, i, j); - nrfctrave += dirwt_l*nrfactorL[inbr][jnbr]; - norm_l += dirwt_l; - } - } - - nrfctrave /= norm_l; - //nrfctrave = nrfactorL[i][j]; - //nrfctrave=1; - - float hipass[3]; - //luma - - /*if (i>0 && i0 && jL[i][j]-data_coarse->L[i][j]); - //hipass[0] = median*(data_fine->L[i][j]-data_coarse->L[i][j]); - //hipass[0] = nrfactorL[i][j]*(data_fine->L[i][j]-data_coarse->L[i][j]); - data_fine->L[i][j] = CLIP(hipass[0]+data_coarse->L[i][j]); - - //chroma - //hipass[1] = nrfactorab[i][j]*(data_fine->a[i][j]-data_coarse->a[i][j]); - //hipass[2] = nrfactorab[i][j]*(data_fine->b[i][j]-data_coarse->b[i][j]); - - //data_fine->a[i][j] = hipass[1]+data_coarse->a[i][j]; - //data_fine->b[i][j] = hipass[2]+data_coarse->b[i][j]; - } - }//end of luminance correction - +static const int maxlevel = 4; - -}//end of pitch=1 - - } else {//pitch>1 - - LabImage* smooth; - - smooth = new LabImage(width, height); -#ifdef _OPENMP -#pragma omp parallel -#endif +//sequence of scales +//static const int scales[8] = {1,2,4,8,16,32,64,128}; +//sequence of pitches +//static const int pitches[8] = {1,1,1,1,1,1,1,1}; +//sequence of scales +//static const int scales[8] = {1,1,1,1,1,1,1,1}; +//sequence of pitches +//static const int pitches[8] = {2,2,2,2,2,2,2,2}; + +//sequence of scales +//static const int scales[8] = {1,1,2,2,4,4,8,8}; +//sequence of pitches +//static const int pitches[8] = {2,1,2,1,2,1,2,1}; + +//sequence of scales +static const int scales[8] = {1, 1, 2, 4, 8, 16, 32, 64}; +//sequence of pitches +static const int pitches[8] = {2, 1, 1, 1, 1, 1, 1, 1}; + +//pitch is spacing of subsampling +//scale is spacing of directional averaging weights +//example 1: no subsampling at any level -- pitch=1, scale=2^n +//example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level +//example 3: no subsampling at first level, subsampling by 2 thereafter -- +// pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter + + + + +void ImProcFunctions :: dirpyrLab_denoise(LabImage * src, LabImage * dst, const procparams::DirPyrDenoiseParams & dnparams ) { - -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height; i+=pitch) - { - int ix=i/pitch; - for(int j = 0, jx=0; j < width; j+=pitch, jx++) { - - //copy common pixels - smooth->L[i][j] = data_coarse->L[ix][jx]; - smooth->a[i][j] = data_coarse->a[ix][jx]; - smooth->b[i][j] = data_coarse->b[ix][jx]; - } - } - //if (pitch>1) {//pitch=2; step (1) expand coarse image, fill in missing data -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height-1; i+=2) - for(int j = 0; j < width-1; j+=2) { - //do midpoint first - double norm=0.0,wtdsum[3]={0.0,0.0,0.0}; - //wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0; - for(int ix=i; ixL[ix][jx]; - wtdsum[1] += smooth->a[ix][jx]; - wtdsum[2] += smooth->b[ix][jx]; - norm++; - } - norm = 1/norm; - smooth->L[i+1][j+1]=wtdsum[0]*norm; - smooth->a[i+1][j+1]=wtdsum[1]*norm; - smooth->b[i+1][j+1]=wtdsum[2]*norm; - } -#ifdef _OPENMP -#pragma omp for -#endif - - for(int i = 0; i < height-1; i+=2) - for(int j = 0; j < width-1; j+=2) { - //now right neighbor - if (j+1==width) continue; - double norm=0.0,wtdsum[3]={0.0,0.0,0.0}; + float gam = dnparams.gamma / 3.0; + //float gam = 2.0;//min(3.0, 0.1*fabs(c[4])/3.0+0.001); + float gamthresh = 0.03; + float gamslope = exp(log((double)gamthresh) / gam) / gamthresh; - for (int jx=j; jxL[i][jx]; - wtdsum[1] += smooth->a[i][jx]; - wtdsum[2] += smooth->b[i][jx]; - norm++; - } - for (int ix=max(0,i-1); ixL[ix][j+1]; - wtdsum[1] += smooth->a[ix][j+1]; - wtdsum[2] += smooth->b[ix][j+1]; - norm++; - } - norm = 1/norm; - smooth->L[i][j+1]=wtdsum[0]*norm; - smooth->a[i][j+1]=wtdsum[1]*norm; - smooth->b[i][j+1]=wtdsum[2]*norm; - - //now down neighbor - if (i+1==height) continue; - norm=0.0;wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0; - for (int ix=i; ixL[ix][j]; - wtdsum[1] += smooth->a[ix][j]; - wtdsum[2] += smooth->b[ix][j]; - norm++; - } - for (int jx=max(0,j-1); jxL[i+1][jx]; - wtdsum[1] += smooth->a[i+1][jx]; - wtdsum[2] += smooth->b[i+1][jx]; - norm++; - } - norm=1/norm; - smooth->L[i+1][j]=wtdsum[0]*norm; - smooth->a[i+1][j]=wtdsum[1]*norm; - smooth->b[i+1][j]=wtdsum[2]*norm; - - } - -#ifdef _OPENMP -#pragma omp for -#endif - - // step (2-3-4) - for( int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - float tonefactor = (nrwt_l[smooth->L[i][j]]); - //double wtdsum[3], norm; - float hipass[3], hpffluct[3], nrfactor; - - hipass[1] = data_fine->a[i][j]-smooth->a[i][j]; - hipass[2] = data_fine->b[i][j]-smooth->b[i][j]; - - //Wiener filter - //luma - if (level<2) { - hipass[0] = data_fine->L[i][j]-smooth->L[i][j]; - hpffluct[0]=SQR(hipass[0])+SQR(hipass[1])+SQR(hipass[2])+0.001; - nrfactorL[i][j] = (1.0+hpffluct[0])/(1.0+hpffluct[0]+noisevar_L /* * Lcurve[smooth->L[i][j]]*/); - //hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L); - //data_fine->L[i][j] = CLIP(hipass[0]+smooth->L[i][j]); - } - - //chroma - //hipass[1] = data_fine->a[i][j]-smooth->a[i][j]; - //hipass[2] = data_fine->b[i][j]-smooth->b[i][j]; - hpffluct[1]=SQR(hipass[1]*tonefactor)+0.001; - hpffluct[2]=SQR(hipass[2]*tonefactor)+0.001; - nrfactor = (hpffluct[1]+hpffluct[2]) /((hpffluct[1]+hpffluct[2]) + noisevar_ab * NRWT_AB /* * abcurve[smooth->L[i][j]]*/); + LUTf gamcurve(65536, 0); - hipass[1] *= nrfactor; - hipass[2] *= nrfactor; - - data_fine->a[i][j] = hipass[1]+smooth->a[i][j]; - data_fine->b[i][j] = hipass[2]+smooth->b[i][j]; - } - - - if (level<2) { -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - float dirwt_l, norm_l; - float nrfctrave=0; - norm_l = 0;//if we do want to include the input pixel in the sum - - for(int inbr=(i-pitch); inbr<=(i+pitch); inbr+=pitch) { - if (inbr<0 || inbr>height-1) continue; - for (int jnbr=(j-pitch); jnbr<=(j+pitch); jnbr+=pitch) { - if (jnbr<0 || jnbr>width-1) continue; - dirwt_l = DIRWT_L(inbr, jnbr, i, j); - nrfctrave += dirwt_l*nrfactorL[inbr][jnbr]; - norm_l += dirwt_l; - } - } - - nrfctrave /= norm_l; - //nrfctrave = nrfactorL[i][j]; - //nrfctrave=1; + //DiagonalCurve* lumacurve = new DiagonalCurve (dnparams.lumcurve, CURVES_MIN_POLY_POINTS); + //DiagonalCurve* chromacurve = new DiagonalCurve (dnparams.chromcurve, CURVES_MIN_POLY_POINTS); + //LUTf Lcurve(65536); + //LUTf abcurve(65536); + for (int i = 0; i < 65536; i++) { + int g = (int)(CurveFactory::gamma((double)i / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 65535.0); + gamcurve[i] = CLIP(g); + /*float val = (float)i/65535.0; + float Lval = (2*(lumacurve->getVal(val))); + float abval = (2*(chromacurve->getVal(val))); + + Lcurve[i] = SQR(Lval); + abcurve[i] = SQR(abval); + if (i % 1000 ==0) printf("%d Lmult=%f abmult=%f \n",i,Lcurve[i],abcurve[i]);*/ + } + + //delete lumacurve; + //delete chromacurve; + + + + //#pragma omp parallel for if (multiThread) + for (int i = 0; i < src->H; i++) { + for (int j = 0; j < src->W; j++) { + //src->L[i][j] = CurveFactory::flinterp(gamcurve,src->L[i][j]); + src->L[i][j] = gamcurve[src->L[i][j]]; + } + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + LUTf rangefn_L(65536); + LUTf nrwt_l(65536); + + LUTf rangefn_ab(65536); + LUTf nrwt_ab(65536); + + //set up NR weight functions + + //gamma correction for chroma in shadows + float nrwtl_norm = ((CurveFactory::gamma((double)65535.0 / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) - + (CurveFactory::gamma((double)75535.0 / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0))); + + for (int i = 0; i < 65536; i++) { + nrwt_l[i] = ((CurveFactory::gamma((double)i / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0) - + CurveFactory::gamma((double)(i + 10000) / 65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) ) / nrwtl_norm; + //if (i % 100 ==0) printf("%d %f \n",i,nrwt_l[i]); + } + + float tonefactor = nrwt_l[32768]; + + float noise_L = 10.0 * dnparams.luma; + float noisevar_L = SQR(noise_L); + + float noise_ab = 100.0 * dnparams.chroma; + float noisevar_ab = SQR(noise_ab); + + + //set up range functions + for (int i = 0; i < 65536; i++) { + rangefn_L[i] = (( exp(-(double)fabs(i - 32768) * tonefactor / (1.0 + noise_L)) * (1.0 + noisevar_L) / ((double)(i - 32768) * (double)(i - 32768) + noisevar_L + 1.0))); + } + + for (int i = 0; i < 65536; i++) { + rangefn_ab[i] = (( exp(-(double)fabs(i - 32768) * tonefactor / (1.0 + 3 * noise_ab)) * (1.0 + noisevar_ab) / ((double)(i - 32768) * (double)(i - 32768) + noisevar_ab + 1.0))); + } + + + for (int i = 0; i < 65536; i++) { + nrwt_ab[i] = ((1.0 + abs(i - 32768) / (1.0 + 8 * noise_ab)) * exp(-(double)fabs(i - 32768) / (1.0 + 8 * noise_ab) ) ); + } + + + //for (int i=0; i<65536; i+=100) printf("%d %d \n",i,gamcurve[i]); + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + int level; + + LabImage * dirpyrLablo[maxlevel]; + int w = (int)((src->W - 1) / pitches[0]) + 1; + int h = (int)((src->H - 1) / pitches[0]) + 1; + dirpyrLablo[0] = new LabImage(w, h); + + for (level = 1; level < maxlevel; level++) { + w = (int)((w - 1) / pitches[level]) + 1; + h = (int)((h - 1) / pitches[level]) + 1; + dirpyrLablo[level] = new LabImage(w, h); + }; + + + ////////////////////////////////////////////////////////////////////////////// + + + // c[0] = luma = noise_L + // c[1] = chroma = noise_ab + // c[2] decrease of noise var with scale + // c[3] radius of domain blur at each level + // c[4] shadow smoothing + // c[5] edge preservation + + level = 0; + + int scale = scales[level]; + + int pitch = pitches[level]; + + //int thresh = 10 * c[8]; + //impulse_nr (src, src, m_w1, m_h1, thresh, noisevar); + + dirpyr(src, dirpyrLablo[0], 0, rangefn_L, rangefn_ab, pitch, scale, dnparams.luma, dnparams.chroma ); + + level = 1; + + while(level < maxlevel) { + scale = scales[level]; + pitch = pitches[level]; + + dirpyr(dirpyrLablo[level - 1], dirpyrLablo[level], level, rangefn_L, rangefn_ab, pitch, scale, dnparams.luma, dnparams.chroma ); + + level ++; + } + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + for(int level = maxlevel - 1; level > 0; level--) { + + int scale = scales[level]; + int pitch = pitches[level]; + idirpyr(dirpyrLablo[level], dirpyrLablo[level - 1], level, rangefn_L, nrwt_l, nrwt_ab, pitch, scale, dnparams.luma, dnparams.chroma/*, Lcurve, abcurve*/ ); + } + + + scale = scales[0]; + pitch = pitches[0]; + + // freeing as much memory as possible since the next call to idirpyr will need lots + for(int i = 1; i < maxlevel; i++) { + delete dirpyrLablo[i]; + } + + idirpyr(dirpyrLablo[0], dst, 0, rangefn_L, nrwt_l, nrwt_ab, pitch, scale, dnparams.luma, dnparams.chroma/*, Lcurve, abcurve*/ ); + + // freeing the last bunch of memory + delete dirpyrLablo[0]; + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + float igam = 1 / gam; + float igamthresh = gamthresh * gamslope; + float igamslope = 1 / gamslope; + + for (int i = 0; i < 65536; i++) { + gamcurve[i] = (CurveFactory::gamma((float)i / 65535.0, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0); + } + + + if (dnparams.luma > 0) { + for (int i = 0; i < dst->H; i++) + for (int j = 0; j < dst->W; j++) { + dst->L[i][j] = gamcurve[dst->L[i][j]]; + } + } else { + for (int i = 0; i < dst->H; i++) + for (int j = 0; j < dst->W; j++) { + dst->L[i][j] = gamcurve[src->L[i][j]]; + } + } + +} + +void ImProcFunctions::dirpyr(LabImage* data_fine, LabImage* data_coarse, int level, + LUTf & rangefn_L, LUTf & rangefn_ab, int pitch, int scale, + const int luma, const int chroma ) +{ + + //pitch is spacing of subsampling + //scale is spacing of directional averaging weights + //example 1: no subsampling at any level -- pitch=1, scale=2^n + //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level + //example 3: no subsampling at first level, subsampling by 2 thereafter -- + // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // calculate weights, compute directionally weighted average + + int width = data_fine->W; + int height = data_fine->H; + + //generate domain kernel + int halfwin = 3;//min(ceil(2*sig),3); + int scalewin = halfwin * scale; + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < height; i += pitch ) { + int i1 = i / pitch; + + for(int j = 0, j1 = 0; j < width; j += pitch, j1++) { + float dirwt_l, dirwt_ab, norm_l, norm_ab; + //float lops,aops,bops; + float Lout, aout, bout; + norm_l = norm_ab = 0;//if we do want to include the input pixel in the sum + Lout = 0; + aout = 0; + bout = 0; + + for(int inbr = (i - scalewin); inbr <= (i + scalewin); inbr += scale) { + if (inbr < 0 || inbr > height - 1) { + continue; + } + + for (int jnbr = (j - scalewin); jnbr <= (j + scalewin); jnbr += scale) { + if (jnbr < 0 || jnbr > width - 1) { + continue; + } + + dirwt_l = DIRWT_L(inbr, jnbr, i, j); + dirwt_ab = DIRWT_AB(inbr, jnbr, i, j); + Lout += dirwt_l * data_fine->L[inbr][jnbr]; + aout += dirwt_ab * data_fine->a[inbr][jnbr]; + bout += dirwt_ab * data_fine->b[inbr][jnbr]; + norm_l += dirwt_l; + norm_ab += dirwt_ab; + } + } + + //lops = Lout/norm;//diagnostic + //aops = aout/normab;//diagnostic + //bops = bout/normab;//diagnostic + + data_coarse->L[i1][j1] = Lout / norm_l; //low pass filter + data_coarse->a[i1][j1] = aout / norm_ab; + data_coarse->b[i1][j1] = bout / norm_ab; + + + /*if (level<2 && i>0 && i0 && jL[i-1][j-1], data_fine->L[i-1][j], data_fine->L[i-1][j+1], \ + data_fine->L[i][j-1], data_fine->L[i][j], data_fine->L[i][j+1], \ + data_fine->L[i+1][j-1], data_fine->L[i+1][j], data_fine->L[i+1][j+1]); + //med3x3(data_fine->L[i-1][j-1], data_fine->L[i-1][j], data_fine->L[i-1][j+1], \ + data_fine->L[i][j-1], data_fine->L[i][j], data_fine->L[i][j+1], \ + data_fine->L[i+1][j-1], data_fine->L[i+1][j], data_fine->L[i+1][j+1],Lmed); + + data_coarse->L[i1][j1] = Lhmf; + }*/ + } + } + + + + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void ImProcFunctions::idirpyr(LabImage* data_coarse, LabImage* data_fine, int level, LUTf &rangefn_L, LUTf & nrwt_l, LUTf & nrwt_ab, + int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/ ) +{ + + int width = data_fine->W; + int height = data_fine->H; + + array2D nrfactorL (width, height); + + //float eps = 0.0; + + // c[0] noise_L + // c[1] noise_ab (relative to noise_L) + // c[2] decrease of noise var with scale + // c[3] radius of domain blur at each level + // c[4] shadow smoothing + + float noisevar_L = 4 * SQR(25.0 * luma); + float noisevar_ab = 2 * SQR(100.0 * chroma); + float scalefactor = 1.0 / pow(2.0, (level + 1) * 2); //change the last 2 to 1 for longer tail of higher scale NR + + noisevar_L *= scalefactor; + + // for coarsest level, take non-subsampled lopass image and subtract from lopass_fine to generate hipass image + + // denoise hipass image, add back into lopass_fine to generate denoised image at fine scale + + // now iterate: + // (1) take denoised image at level n, expand and smooth using gradient weights from lopass image at level n-1 + // the result is the smoothed image at level n-1 + // (2) subtract smoothed image at level n-1 from lopass image at level n-1 to make hipass image at level n-1 + // (3) denoise the hipass image at level n-1 + // (4) add the denoised image at level n-1 to the smoothed image at level n-1 to make the denoised image at level n-1 + + // note that the coarsest level amounts to skipping step (1) and doing (2,3,4). + // in other words, skip step one if pitch=1 + + // step (1) + + if (pitch == 1) { + + // step (1-2-3-4) + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height; i++) + for(int j = 0; j < width; j++) + { + float hipass[3], hpffluct[3], tonefactor, nrfactor; + + tonefactor = (nrwt_l[data_coarse->L[i][j]]); + + hipass[1] = data_fine->a[i][j] - data_coarse->a[i][j]; + hipass[2] = data_fine->b[i][j] - data_coarse->b[i][j]; + + //Wiener filter + //luma + if (level < 2) { + hipass[0] = data_fine->L[i][j] - data_coarse->L[i][j]; + hpffluct[0] = SQR(hipass[0]) + SQR(hipass[1]) + SQR(hipass[2]) + 0.001; + nrfactorL[i][j] = (1.0 + hpffluct[0]) / (1.0 + hpffluct[0] + noisevar_L /* * Lcurve[data_coarse->L[i][j]]*/); + //hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L); + //data_fine->L[i][j] = CLIP(hipass[0]+data_coarse->L[i][j]); + } + + //chroma + //hipass[1] = data_fine->a[i][j]-data_coarse->a[i][j]; + //hipass[2] = data_fine->b[i][j]-data_coarse->b[i][j]; + hpffluct[1] = SQR(hipass[1] * tonefactor) + 0.001; + hpffluct[2] = SQR(hipass[2] * tonefactor) + 0.001; + nrfactor = (hpffluct[1] + hpffluct[2]) / ((hpffluct[1] + hpffluct[2]) + noisevar_ab * NRWT_AB); + + hipass[1] *= nrfactor; + hipass[2] *= nrfactor; + + data_fine->a[i][j] = hipass[1] + data_coarse->a[i][j]; + data_fine->b[i][j] = hipass[2] + data_coarse->b[i][j]; + } + + if (level < 2) + { +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height; i++) + for(int j = 0; j < width; j++) { + + float dirwt_l, norm_l; + float nrfctrave = 0; + norm_l = 0;//if we do want to include the input pixel in the sum + + for(int inbr = max(0, i - 1); inbr <= min(height - 1, i + 1); inbr++) { + for (int jnbr = max(0, j - 1); jnbr <= min(width - 1, j + 1); jnbr++) { + dirwt_l = DIRWT_L(inbr, jnbr, i, j); + nrfctrave += dirwt_l * nrfactorL[inbr][jnbr]; + norm_l += dirwt_l; + } + } + + nrfctrave /= norm_l; + //nrfctrave = nrfactorL[i][j]; + //nrfctrave=1; + + float hipass[3]; + + //luma + + /*if (i>0 && i0 && jL[i][j] - data_coarse->L[i][j]); + //hipass[0] = median*(data_fine->L[i][j]-data_coarse->L[i][j]); + //hipass[0] = nrfactorL[i][j]*(data_fine->L[i][j]-data_coarse->L[i][j]); + data_fine->L[i][j] = CLIP(hipass[0] + data_coarse->L[i][j]); + + //chroma + //hipass[1] = nrfactorab[i][j]*(data_fine->a[i][j]-data_coarse->a[i][j]); + //hipass[2] = nrfactorab[i][j]*(data_fine->b[i][j]-data_coarse->b[i][j]); + + //data_fine->a[i][j] = hipass[1]+data_coarse->a[i][j]; + //data_fine->b[i][j] = hipass[2]+data_coarse->b[i][j]; + } + }//end of luminance correction + + + + }//end of pitch=1 + + } else {//pitch>1 + + LabImage* smooth; + + smooth = new LabImage(width, height); +#ifdef _OPENMP + #pragma omp parallel +#endif + + { + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height; i += pitch) { + int ix = i / pitch; + + for(int j = 0, jx = 0; j < width; j += pitch, jx++) { + + //copy common pixels + smooth->L[i][j] = data_coarse->L[ix][jx]; + smooth->a[i][j] = data_coarse->a[ix][jx]; + smooth->b[i][j] = data_coarse->b[ix][jx]; + } + } + + //if (pitch>1) {//pitch=2; step (1) expand coarse image, fill in missing data +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height - 1; i += 2) + for(int j = 0; j < width - 1; j += 2) { + //do midpoint first + double norm = 0.0, wtdsum[3] = {0.0, 0.0, 0.0}; + + //wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0; + for(int ix = i; ix < min(height, i + 3); ix += 2) + for (int jx = j; jx < min(width, j + 3); jx += 2) { + wtdsum[0] += smooth->L[ix][jx]; + wtdsum[1] += smooth->a[ix][jx]; + wtdsum[2] += smooth->b[ix][jx]; + norm++; + } + + norm = 1 / norm; + smooth->L[i + 1][j + 1] = wtdsum[0] * norm; + smooth->a[i + 1][j + 1] = wtdsum[1] * norm; + smooth->b[i + 1][j + 1] = wtdsum[2] * norm; + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height - 1; i += 2) + for(int j = 0; j < width - 1; j += 2) { + //now right neighbor + if (j + 1 == width) { + continue; + } + + double norm = 0.0, wtdsum[3] = {0.0, 0.0, 0.0}; + + for (int jx = j; jx < min(width, j + 3); jx += 2) { + wtdsum[0] += smooth->L[i][jx]; + wtdsum[1] += smooth->a[i][jx]; + wtdsum[2] += smooth->b[i][jx]; + norm++; + } + + for (int ix = max(0, i - 1); ix < min(height, i + 2); ix += 2) { + wtdsum[0] += smooth->L[ix][j + 1]; + wtdsum[1] += smooth->a[ix][j + 1]; + wtdsum[2] += smooth->b[ix][j + 1]; + norm++; + } + + norm = 1 / norm; + smooth->L[i][j + 1] = wtdsum[0] * norm; + smooth->a[i][j + 1] = wtdsum[1] * norm; + smooth->b[i][j + 1] = wtdsum[2] * norm; + + //now down neighbor + if (i + 1 == height) { + continue; + } + + norm = 0.0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0; + + for (int ix = i; ix < min(height, i + 3); ix += 2) { + wtdsum[0] += smooth->L[ix][j]; + wtdsum[1] += smooth->a[ix][j]; + wtdsum[2] += smooth->b[ix][j]; + norm++; + } + + for (int jx = max(0, j - 1); jx < min(width, j + 2); jx += 2) { + wtdsum[0] += smooth->L[i + 1][jx]; + wtdsum[1] += smooth->a[i + 1][jx]; + wtdsum[2] += smooth->b[i + 1][jx]; + norm++; + } + + norm = 1 / norm; + smooth->L[i + 1][j] = wtdsum[0] * norm; + smooth->a[i + 1][j] = wtdsum[1] * norm; + smooth->b[i + 1][j] = wtdsum[2] * norm; + + } + +#ifdef _OPENMP + #pragma omp for +#endif + + // step (2-3-4) + for( int i = 0; i < height; i++) + for(int j = 0; j < width; j++) { + + float tonefactor = (nrwt_l[smooth->L[i][j]]); + //double wtdsum[3], norm; + float hipass[3], hpffluct[3], nrfactor; + + hipass[1] = data_fine->a[i][j] - smooth->a[i][j]; + hipass[2] = data_fine->b[i][j] - smooth->b[i][j]; + + //Wiener filter + //luma + if (level < 2) { + hipass[0] = data_fine->L[i][j] - smooth->L[i][j]; + hpffluct[0] = SQR(hipass[0]) + SQR(hipass[1]) + SQR(hipass[2]) + 0.001; + nrfactorL[i][j] = (1.0 + hpffluct[0]) / (1.0 + hpffluct[0] + noisevar_L /* * Lcurve[smooth->L[i][j]]*/); + //hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L); + //data_fine->L[i][j] = CLIP(hipass[0]+smooth->L[i][j]); + } + + //chroma + //hipass[1] = data_fine->a[i][j]-smooth->a[i][j]; + //hipass[2] = data_fine->b[i][j]-smooth->b[i][j]; + hpffluct[1] = SQR(hipass[1] * tonefactor) + 0.001; + hpffluct[2] = SQR(hipass[2] * tonefactor) + 0.001; + nrfactor = (hpffluct[1] + hpffluct[2]) / ((hpffluct[1] + hpffluct[2]) + noisevar_ab * NRWT_AB /* * abcurve[smooth->L[i][j]]*/); + + hipass[1] *= nrfactor; + hipass[2] *= nrfactor; + + data_fine->a[i][j] = hipass[1] + smooth->a[i][j]; + data_fine->b[i][j] = hipass[2] + smooth->b[i][j]; + } + + + if (level < 2) { +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height; i++) + for(int j = 0; j < width; j++) { + + float dirwt_l, norm_l; + float nrfctrave = 0; + norm_l = 0;//if we do want to include the input pixel in the sum + + for(int inbr = (i - pitch); inbr <= (i + pitch); inbr += pitch) { + if (inbr < 0 || inbr > height - 1) { + continue; + } + + for (int jnbr = (j - pitch); jnbr <= (j + pitch); jnbr += pitch) { + if (jnbr < 0 || jnbr > width - 1) { + continue; + } + + dirwt_l = DIRWT_L(inbr, jnbr, i, j); + nrfctrave += dirwt_l * nrfactorL[inbr][jnbr]; + norm_l += dirwt_l; + } + } + + nrfctrave /= norm_l; + //nrfctrave = nrfactorL[i][j]; + //nrfctrave=1; + + + float hipass[3]; + + //luma + + /*if (i>0 && i0 && jL[i][j] - smooth->L[i][j]); + //hipass[0] = median*(data_fine->L[i][j]-smooth->L[i][j]); + //hipass[0] = nrfactorL[i][j]*(data_fine->L[i][j]-data_coarse->L[i][j]); + data_fine->L[i][j] = CLIP(hipass[0] + smooth->L[i][j]); + + + //chroma + //hipass[1] = nrfactorab[i][j]*(data_fine->a[i][j]-data_coarse->a[i][j]); + //hipass[2] = nrfactorab[i][j]*(data_fine->b[i][j]-data_coarse->b[i][j]); + + //data_fine->a[i][j] = hipass[1]+data_coarse->a[i][j]; + //data_fine->b[i][j] = hipass[2]+data_coarse->b[i][j]; + } + }//end of luminance correction + + + } // end parallel + delete smooth; + }//end of pitch>1 + +} + + +#undef DIRWT_L +#undef DIRWT_AB + +//#undef NRWT_L +#undef NRWT_AB - - float hipass[3]; - - //luma - - /*if (i>0 && i0 && jL[i][j]-smooth->L[i][j]); - //hipass[0] = median*(data_fine->L[i][j]-smooth->L[i][j]); - //hipass[0] = nrfactorL[i][j]*(data_fine->L[i][j]-data_coarse->L[i][j]); - data_fine->L[i][j] = CLIP(hipass[0]+smooth->L[i][j]); - - - //chroma - //hipass[1] = nrfactorab[i][j]*(data_fine->a[i][j]-data_coarse->a[i][j]); - //hipass[2] = nrfactorab[i][j]*(data_fine->b[i][j]-data_coarse->b[i][j]); - - //data_fine->a[i][j] = hipass[1]+data_coarse->a[i][j]; - //data_fine->b[i][j] = hipass[2]+data_coarse->b[i][j]; - } - }//end of luminance correction - - -} // end parallel - delete smooth; - }//end of pitch>1 - - } - - -#undef DIRWT_L -#undef DIRWT_AB - -//#undef NRWT_L -#undef NRWT_AB - } diff --git a/rtengine/dirpyrLab_equalizer.cc b/rtengine/dirpyrLab_equalizer.cc index de7dd402d..93a1b1ff1 100644 --- a/rtengine/dirpyrLab_equalizer.cc +++ b/rtengine/dirpyrLab_equalizer.cc @@ -5,7 +5,7 @@ * 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 @@ -15,7 +15,7 @@ * along with RawTherapee. If not, see . * * © 2010 Emil Martinec - * + * */ #include @@ -34,458 +34,488 @@ #define DIRWT(i1,j1,i,j) (rangefn[abs((int)data_fine->L[i1][j1]-data_fine->L[i][j])+abs((int)data_fine->a[i1][j1]-data_fine->a[i][j])+abs((int)data_fine->b[i1][j1]-data_fine->b[i][j])] ) -namespace rtengine { - - static const int maxlevel = 4; - - //sequence of scales - static const int scales[8] = {1,2,4,8,16,32,64,128}; - //sequence of pitches - static const int pitches[8] = {1,1,1,1,1,1,1,1}; - - //sequence of scales - //static const int scales[8] = {1,1,1,1,1,1,1,1}; - //sequence of pitches - //static const int pitches[8] = {2,2,2,2,2,2,2,2}; - - //sequence of scales - //static const int scales[8] = {1,3,6,10,15,21,28,36}; - //sequence of pitches - //static const int pitches[8] = {1,1,1,1,1,1,1,1}; - - //sequence of scales - //static const int scales[8] = {1,1,2,4,8,16,32,64}; - //sequence of pitches - //static const int pitches[8] = {2,1,1,1,1,1,1,1}; - - //pitch is spacing of subsampling - //scale is spacing of directional averaging weights - //example 1: no subsampling at any level -- pitch=1, scale=2^n - //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level - //example 3: no subsampling at first level, subsampling by 2 thereafter -- - // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter - - - - - void ImProcFunctions :: dirpyrLab_equalizer(LabImage * src, LabImage * dst, /*float luma, float chroma, float gamma*/ const double * mult ) - { - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - LUTf rangefn(0x20000); - - - //set up weights - float noise = 1500; - - - //set up range functions - - for (int i=0; i<0x20000; i++) - rangefn[i] = (int)((noise/((double)i + noise))); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - int level; - int ** buffer[3]; - - - LabImage * dirpyrLablo[maxlevel]; - - int w = src->W; - int h = src->H; - - buffer[0] = allocArray (w+128, h+128); - buffer[1] = allocArray (w+128, h+128); - buffer[2] = allocArray (w+128, h+128); - - for (int i=0; iH; i+=totalpitch, i1++) - for(int j = 0, j1=0; j < src->W; j+=totalpitch, j1++) { - - //copy pixels - buffer[0][i][j] = dirpyrLablo[maxlevel-1]->L[i1][j1]; - buffer[1][i][j] = dirpyrLablo[maxlevel-1]->a[i1][j1]; - buffer[2][i][j] = dirpyrLablo[maxlevel-1]->b[i1][j1]; - - } - - //if we are not subsampling, this is lots faster but does the typecasting work??? - //memcpy(buffer[0],dirpyrLablo[maxlevel-1]->L,sizeof(buffer[0])); - //memcpy(buffer[1],dirpyrLablo[maxlevel-1]->a,sizeof(buffer[1])); - //memcpy(buffer[2],dirpyrLablo[maxlevel-1]->b,sizeof(buffer[2])); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - for(int level = maxlevel - 1; level > 0; level--) - { - - //int scale = scales[level]; - int pitch = pitches[level]; - - totalpitch /= pitch; - - idirpyr_eq(dirpyrLablo[level], dirpyrLablo[level-1], buffer, level, pitch, totalpitch, mult ); - - } - - - scale = scales[0]; - pitch = pitches[0]; - totalpitch /= pitch; - - idirpyr_eq(dirpyrLablo[0], dst, buffer, 0, pitch, totalpitch, mult ); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - for (int i=0; iH; i++) - for (int j=0; jW; j++) { - - // TODO: Is integer cast necessary here? - dst->L[i][j] = CLIP((int)( buffer[0][i][j] )); - dst->a[i][j] = CLIPC((int)( buffer[1][i][j] )); - dst->b[i][j] = CLIPC((int)( buffer[2][i][j] )); - - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - for(int i = 0; i < maxlevel; i++) - { - delete dirpyrLablo[i]; - } - - for (int c=0;c<3;c++) - freeArray(buffer[c], h+128); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - } - - void ImProcFunctions::dirpyr_eq(LabImage* data_fine, LabImage* data_coarse, LUTf & rangefn, int level, int pitch, int scale, const double * mult ) - { - - //pitch is spacing of subsampling - //scale is spacing of directional averaging weights - //example 1: no subsampling at any level -- pitch=1, scale=2^n - //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level - //example 3: no subsampling at first level, subsampling by 2 thereafter -- - // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // calculate weights, compute directionally weighted average - - int width = data_fine->W; - int height = data_fine->H; - - - - //generate domain kernel - int halfwin = 1;//min(ceil(2*sig),3); - int scalewin = halfwin*scale; - - -#ifdef _OPENMP -#pragma omp parallel for -#endif - for(int i = 0; i < height; i+=pitch) { int i1=i/pitch; - for(int j = 0, j1=0; j < width; j+=pitch, j1++) - { - float Lout, aout, bout; - float norm; - norm = 0;//if we do want to include the input pixel in the sum - Lout = 0; - aout = 0; - bout = 0; - - for(int inbr=max(0,i-scalewin); inbr<=min(height-1,i+scalewin); inbr+=scale) { - for (int jnbr=max(0,j-scalewin); jnbr<=min(width-1,j+scalewin); jnbr+=scale) { - float dirwt = DIRWT(inbr, jnbr, i, j); - Lout += dirwt*data_fine->L[inbr][jnbr]; - aout += dirwt*data_fine->a[inbr][jnbr]; - bout += dirwt*data_fine->b[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse->L[i1][j1]=Lout/norm;//low pass filter - data_coarse->a[i1][j1]=aout/norm; - data_coarse->b[i1][j1]=bout/norm; - } - } - - - - - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void ImProcFunctions::idirpyr_eq(LabImage* data_coarse, LabImage* data_fine, int *** buffer, int level, int pitch, int scale, const double * mult ) - { - - int width = data_fine->W; - int height = data_fine->H; - - float lumamult[4], chromamult[4]; - for (int i=0; i<4; i++) { - lumamult[i] = mult[i]; - chromamult[i] = mult[i+4]; - } - - float wtdsum[6], norm, dirwt; - float hipass[3]; - int i1, j1; - - - // for coarsest level, take non-subsampled lopass image and subtract from lopass_fine to generate hipass image - - // denoise hipass image, add back into lopass_fine to generate denoised image at fine scale - - // now iterate: - // (1) take denoised image at level n, expand and smooth using gradient weights from lopass image at level n-1 - // the result is the smoothed image at level n-1 - // (2) subtract smoothed image at level n-1 from lopass image at level n-1 to make hipass image at level n-1 - // (3) denoise the hipass image at level n-1 - // (4) add the denoised image at level n-1 to the smoothed image at level n-1 to make the denoised image at level n-1 - - // note that the coarsest level amounts to skipping step (1) and doing (2,3,4). - // in other words, skip step one if pitch=1 - - - - if (pitch==1) { - // step (1-2-3-4) -#ifdef _OPENMP -#pragma omp parallel for -#endif - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - //luma - float hipass0 = (float)data_fine->L[i][j]-data_coarse->L[i][j]; - buffer[0][i*scale][j*scale] += hipass0 * lumamult[level];//*luma; - - //chroma - float hipass1 = data_fine->a[i][j]-data_coarse->a[i][j]; - float hipass2 = data_fine->b[i][j]-data_coarse->b[i][j]; - buffer[1][i*scale][j*scale] += hipass1 * chromamult[level]; //*chroma; - buffer[2][i*scale][j*scale] += hipass2 * chromamult[level]; //*chroma; - } - - } else { - - // step (1) - //if (pitch>1), pitch=2; expand coarse image, fill in missing data - - LabImage* smooth; - smooth = new LabImage(width, height); -#ifdef _OPENMP -#pragma omp parallel -#endif - +namespace rtengine { -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height; i+=pitch){ int i2=i/pitch; - for(int j = 0, j2=0; j < width; j+=pitch, j2++) { - - //copy common pixels - smooth->L[i][j] = data_coarse->L[i2][j2]; - smooth->a[i][j] = data_coarse->a[i2][j2]; - smooth->b[i][j] = data_coarse->b[i2][j2]; - } - } - -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height-1; i+=2) - for(int j = 0; j < width-1; j+=2) { - //do midpoint first - norm=dirwt=0; - wtdsum[0]=wtdsum[1]=wtdsum[2]=wtdsum[3]=wtdsum[4]=wtdsum[5]=0.0; - for(i1=i; i1L[i1][j1]; - wtdsum[1] += dirwt*smooth->a[i1][j1]; - wtdsum[2] += dirwt*smooth->b[i1][j1]; - wtdsum[3] += dirwt*buffer[0][i1*scale][j1*scale];// not completely right if j1*scale or i1*scale is out of bounds of original image ??? - wtdsum[4] += dirwt*buffer[1][i1*scale][j1*scale];// also should we use directional average? - wtdsum[5] += dirwt*buffer[2][i1*scale][j1*scale]; - norm+=dirwt; - } - norm = 1/norm; - smooth->L[i+1][j+1]=wtdsum[0]*norm; - smooth->a[i+1][j+1]=wtdsum[1]*norm; - smooth->b[i+1][j+1]=wtdsum[2]*norm; - buffer[0][(i+1)*scale][(j+1)*scale]=wtdsum[3]*norm; - buffer[1][(i+1)*scale][(j+1)*scale]=wtdsum[4]*norm; - buffer[2][(i+1)*scale][(j+1)*scale]=wtdsum[5]*norm; - } -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height-1; i+=2) - for(int j = 0; j < width-1; j+=2) { - //now right neighbor - if (j+1==width) continue; - norm=dirwt=0; - wtdsum[0]=wtdsum[1]=wtdsum[2]=wtdsum[3]=wtdsum[4]=wtdsum[5]=0.0; - for (j1=j; j1L[i][j1]; - wtdsum[1] += dirwt*smooth->a[i][j1]; - wtdsum[2] += dirwt*smooth->b[i][j1]; - wtdsum[3] += dirwt*buffer[0][i*scale][j1*scale]; - wtdsum[4] += dirwt*buffer[1][i*scale][j1*scale]; - wtdsum[5] += dirwt*buffer[2][i*scale][j1*scale]; - norm+=dirwt; - } - for (i1=max(0,i-1); i1L[i1][j+1]; - wtdsum[1] += dirwt*smooth->a[i1][j+1]; - wtdsum[2] += dirwt*smooth->b[i1][j+1]; - wtdsum[3] += dirwt*buffer[0][i1*scale][(j+1)*scale]; - wtdsum[4] += dirwt*buffer[1][i1*scale][(j+1)*scale]; - wtdsum[5] += dirwt*buffer[2][i1*scale][(j+1)*scale]; - norm+=dirwt; - } - norm = 1/norm; - smooth->L[i][j+1]=wtdsum[0]*norm; - smooth->a[i][j+1]=wtdsum[1]*norm; - smooth->b[i][j+1]=wtdsum[2]*norm; - buffer[0][i][(j+1)*scale]=wtdsum[3]*norm; - buffer[1][i][(j+1)*scale]=wtdsum[4]*norm; - buffer[2][i][(j+1)*scale]=wtdsum[5]*norm; - - //now down neighbor - if (i+1==height) continue; - norm=0; - wtdsum[0]=wtdsum[1]=wtdsum[2]=wtdsum[3]=wtdsum[4]=wtdsum[5]=0.0; - for (i1=i; i1L[i1][j]; - wtdsum[1] += dirwt*smooth->a[i1][j]; - wtdsum[2] += dirwt*smooth->b[i1][j]; - wtdsum[3] += dirwt*buffer[0][i1*scale][j*scale]; - wtdsum[4] += dirwt*buffer[1][i1*scale][j*scale]; - wtdsum[5] += dirwt*buffer[2][i1*scale][j*scale]; - norm+=dirwt; - } - for (j1=max(0,j-1); j1L[i+1][j1]; - wtdsum[1] += dirwt*smooth->a[i+1][j1]; - wtdsum[2] += dirwt*smooth->b[i+1][j1]; - wtdsum[3] += dirwt*buffer[0][(i+1)*scale][j1*scale]; - wtdsum[4] += dirwt*buffer[1][(i+1)*scale][j1*scale]; - wtdsum[5] += dirwt*buffer[2][(i+1)*scale][j1*scale]; - norm+=dirwt; - } - norm=1/norm; - smooth->L[i+1][j]=wtdsum[0]*norm; - smooth->a[i+1][j]=wtdsum[1]*norm; - smooth->b[i+1][j]=wtdsum[2]*norm; - buffer[0][(i+1)*scale][j*scale]=wtdsum[3]*norm; - buffer[1][(i+1)*scale][j*scale]=wtdsum[4]*norm; - buffer[2][(i+1)*scale][j*scale]=wtdsum[5]*norm; - - } - - - // step (2-3-4) -#ifdef _OPENMP -#pragma omp for -#endif - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - //luma - hipass[0] = (float)data_fine->L[i][j]-smooth->L[i][j]; - buffer[0][i*scale][j*scale] += hipass[0] * lumamult[level]; //*luma; - - //chroma - hipass[1] = data_fine->a[i][j]-smooth->a[i][j]; - hipass[2] = data_fine->b[i][j]-smooth->b[i][j]; - buffer[1][i*scale][j*scale] += hipass[1] * chromamult[level]; //*chroma; - buffer[2][i*scale][j*scale] += hipass[2] * chromamult[level]; //*chroma; - } -} // end parallel - delete smooth; - - } - } - - -#undef DIRWT_L -#undef DIRWT_AB - -#undef NRWT_L -#undef NRWT_AB - + +static const int maxlevel = 4; + +//sequence of scales +static const int scales[8] = {1, 2, 4, 8, 16, 32, 64, 128}; +//sequence of pitches +static const int pitches[8] = {1, 1, 1, 1, 1, 1, 1, 1}; + +//sequence of scales +//static const int scales[8] = {1,1,1,1,1,1,1,1}; +//sequence of pitches +//static const int pitches[8] = {2,2,2,2,2,2,2,2}; + +//sequence of scales +//static const int scales[8] = {1,3,6,10,15,21,28,36}; +//sequence of pitches +//static const int pitches[8] = {1,1,1,1,1,1,1,1}; + +//sequence of scales +//static const int scales[8] = {1,1,2,4,8,16,32,64}; +//sequence of pitches +//static const int pitches[8] = {2,1,1,1,1,1,1,1}; + +//pitch is spacing of subsampling +//scale is spacing of directional averaging weights +//example 1: no subsampling at any level -- pitch=1, scale=2^n +//example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level +//example 3: no subsampling at first level, subsampling by 2 thereafter -- +// pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter + + + + +void ImProcFunctions :: dirpyrLab_equalizer(LabImage * src, LabImage * dst, /*float luma, float chroma, float gamma*/ const double * mult ) +{ + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + LUTf rangefn(0x20000); + + + //set up weights + float noise = 1500; + + + //set up range functions + + for (int i = 0; i < 0x20000; i++) { + rangefn[i] = (int)((noise / ((double)i + noise))); + } + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + int level; + int ** buffer[3]; + + + LabImage * dirpyrLablo[maxlevel]; + + int w = src->W; + int h = src->H; + + buffer[0] = allocArray (w + 128, h + 128); + buffer[1] = allocArray (w + 128, h + 128); + buffer[2] = allocArray (w + 128, h + 128); + + for (int i = 0; i < h + 128; i++) + for (int j = 0; j < w + 128; j++) { + for (int c = 0; c < 3; c++) { + buffer[c][i][j] = 0; + } + } + + w = (int)((w - 1) / pitches[0]) + 1; + h = (int)((h - 1) / pitches[0]) + 1; + + dirpyrLablo[0] = new LabImage(w, h); + + for (level = 1; level < maxlevel; level++) { + w = (int)((w - 1) / pitches[level]) + 1; + h = (int)((h - 1) / pitches[level]) + 1; + dirpyrLablo[level] = new LabImage(w, h); + }; + + ////////////////////////////////////////////////////////////////////////////// + + + // c[0] = luma = noise_L + // c[1] = chroma = noise_ab + // c[2] decrease of noise var with scale + // c[3] radius of domain blur at each level + // c[4] shadow smoothing + // c[5] edge preservation + + level = 0; + + int scale = scales[level]; + + int pitch = pitches[level]; + + //int thresh = 10 * c[8]; + //impulse_nr (src, src, m_w1, m_h1, thresh, noisevar); + + dirpyr_eq(src, dirpyrLablo[0], rangefn, 0, pitch, scale, mult ); + + level = 1; + + int totalpitch = pitches[0]; + + while(level < maxlevel) { + scale = scales[level]; + pitch = pitches[level]; + + dirpyr_eq(dirpyrLablo[level - 1], dirpyrLablo[level], rangefn, level, pitch, scale, mult ); + + level ++; + totalpitch *= pitch; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //initiate buffer for final image + for(int i = 0, i1 = 0; i < src->H; i += totalpitch, i1++) + for(int j = 0, j1 = 0; j < src->W; j += totalpitch, j1++) { + + //copy pixels + buffer[0][i][j] = dirpyrLablo[maxlevel - 1]->L[i1][j1]; + buffer[1][i][j] = dirpyrLablo[maxlevel - 1]->a[i1][j1]; + buffer[2][i][j] = dirpyrLablo[maxlevel - 1]->b[i1][j1]; + + } + + //if we are not subsampling, this is lots faster but does the typecasting work??? + //memcpy(buffer[0],dirpyrLablo[maxlevel-1]->L,sizeof(buffer[0])); + //memcpy(buffer[1],dirpyrLablo[maxlevel-1]->a,sizeof(buffer[1])); + //memcpy(buffer[2],dirpyrLablo[maxlevel-1]->b,sizeof(buffer[2])); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + for(int level = maxlevel - 1; level > 0; level--) { + + //int scale = scales[level]; + int pitch = pitches[level]; + + totalpitch /= pitch; + + idirpyr_eq(dirpyrLablo[level], dirpyrLablo[level - 1], buffer, level, pitch, totalpitch, mult ); + + } + + + scale = scales[0]; + pitch = pitches[0]; + totalpitch /= pitch; + + idirpyr_eq(dirpyrLablo[0], dst, buffer, 0, pitch, totalpitch, mult ); + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + for (int i = 0; i < dst->H; i++) + for (int j = 0; j < dst->W; j++) { + + // TODO: Is integer cast necessary here? + dst->L[i][j] = CLIP((int)( buffer[0][i][j] )); + dst->a[i][j] = CLIPC((int)( buffer[1][i][j] )); + dst->b[i][j] = CLIPC((int)( buffer[2][i][j] )); + + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + for(int i = 0; i < maxlevel; i++) { + delete dirpyrLablo[i]; + } + + for (int c = 0; c < 3; c++) { + freeArray(buffer[c], h + 128); + } + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +} + +void ImProcFunctions::dirpyr_eq(LabImage* data_fine, LabImage* data_coarse, LUTf & rangefn, int level, int pitch, int scale, const double * mult ) +{ + + //pitch is spacing of subsampling + //scale is spacing of directional averaging weights + //example 1: no subsampling at any level -- pitch=1, scale=2^n + //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level + //example 3: no subsampling at first level, subsampling by 2 thereafter -- + // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // calculate weights, compute directionally weighted average + + int width = data_fine->W; + int height = data_fine->H; + + + + //generate domain kernel + int halfwin = 1;//min(ceil(2*sig),3); + int scalewin = halfwin * scale; + + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < height; i += pitch) { + int i1 = i / pitch; + + for(int j = 0, j1 = 0; j < width; j += pitch, j1++) { + float Lout, aout, bout; + float norm; + norm = 0;//if we do want to include the input pixel in the sum + Lout = 0; + aout = 0; + bout = 0; + + for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = max(0, j - scalewin); jnbr <= min(width - 1, j + scalewin); jnbr += scale) { + float dirwt = DIRWT(inbr, jnbr, i, j); + Lout += dirwt * data_fine->L[inbr][jnbr]; + aout += dirwt * data_fine->a[inbr][jnbr]; + bout += dirwt * data_fine->b[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse->L[i1][j1] = Lout / norm; //low pass filter + data_coarse->a[i1][j1] = aout / norm; + data_coarse->b[i1][j1] = bout / norm; + } + } + + + + +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void ImProcFunctions::idirpyr_eq(LabImage* data_coarse, LabImage* data_fine, int *** buffer, int level, int pitch, int scale, const double * mult ) +{ + + int width = data_fine->W; + int height = data_fine->H; + + float lumamult[4], chromamult[4]; + + for (int i = 0; i < 4; i++) { + lumamult[i] = mult[i]; + chromamult[i] = mult[i + 4]; + } + + float wtdsum[6], norm, dirwt; + float hipass[3]; + int i1, j1; + + + // for coarsest level, take non-subsampled lopass image and subtract from lopass_fine to generate hipass image + + // denoise hipass image, add back into lopass_fine to generate denoised image at fine scale + + // now iterate: + // (1) take denoised image at level n, expand and smooth using gradient weights from lopass image at level n-1 + // the result is the smoothed image at level n-1 + // (2) subtract smoothed image at level n-1 from lopass image at level n-1 to make hipass image at level n-1 + // (3) denoise the hipass image at level n-1 + // (4) add the denoised image at level n-1 to the smoothed image at level n-1 to make the denoised image at level n-1 + + // note that the coarsest level amounts to skipping step (1) and doing (2,3,4). + // in other words, skip step one if pitch=1 + + + + if (pitch == 1) { + // step (1-2-3-4) +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < height; i++) + for(int j = 0; j < width; j++) { + + //luma + float hipass0 = (float)data_fine->L[i][j] - data_coarse->L[i][j]; + buffer[0][i * scale][j * scale] += hipass0 * lumamult[level]; //*luma; + + //chroma + float hipass1 = data_fine->a[i][j] - data_coarse->a[i][j]; + float hipass2 = data_fine->b[i][j] - data_coarse->b[i][j]; + buffer[1][i * scale][j * scale] += hipass1 * chromamult[level]; //*chroma; + buffer[2][i * scale][j * scale] += hipass2 * chromamult[level]; //*chroma; + } + + } else { + + // step (1) + //if (pitch>1), pitch=2; expand coarse image, fill in missing data + + LabImage* smooth; + smooth = new LabImage(width, height); +#ifdef _OPENMP + #pragma omp parallel +#endif + + { +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height; i += pitch) { + int i2 = i / pitch; + + for(int j = 0, j2 = 0; j < width; j += pitch, j2++) { + + //copy common pixels + smooth->L[i][j] = data_coarse->L[i2][j2]; + smooth->a[i][j] = data_coarse->a[i2][j2]; + smooth->b[i][j] = data_coarse->b[i2][j2]; + } + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height - 1; i += 2) + for(int j = 0; j < width - 1; j += 2) { + //do midpoint first + norm = dirwt = 0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = wtdsum[3] = wtdsum[4] = wtdsum[5] = 0.0; + + for(i1 = i; i1 < min(height, i + 3); i1 += 2) + for (j1 = j; j1 < min(width, j + 3); j1 += 2) { + dirwt = 1;//IDIRWT(i1, j1, i, j); + wtdsum[0] += dirwt * smooth->L[i1][j1]; + wtdsum[1] += dirwt * smooth->a[i1][j1]; + wtdsum[2] += dirwt * smooth->b[i1][j1]; + wtdsum[3] += dirwt * buffer[0][i1 * scale][j1 * scale]; // not completely right if j1*scale or i1*scale is out of bounds of original image ??? + wtdsum[4] += dirwt * buffer[1][i1 * scale][j1 * scale]; // also should we use directional average? + wtdsum[5] += dirwt * buffer[2][i1 * scale][j1 * scale]; + norm += dirwt; + } + + norm = 1 / norm; + smooth->L[i + 1][j + 1] = wtdsum[0] * norm; + smooth->a[i + 1][j + 1] = wtdsum[1] * norm; + smooth->b[i + 1][j + 1] = wtdsum[2] * norm; + buffer[0][(i + 1)*scale][(j + 1)*scale] = wtdsum[3] * norm; + buffer[1][(i + 1)*scale][(j + 1)*scale] = wtdsum[4] * norm; + buffer[2][(i + 1)*scale][(j + 1)*scale] = wtdsum[5] * norm; + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height - 1; i += 2) + for(int j = 0; j < width - 1; j += 2) { + //now right neighbor + if (j + 1 == width) { + continue; + } + + norm = dirwt = 0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = wtdsum[3] = wtdsum[4] = wtdsum[5] = 0.0; + + for (j1 = j; j1 < min(width, j + 3); j1 += 2) { + dirwt = 1;//IDIRWT(i, j1, i, j); + wtdsum[0] += dirwt * smooth->L[i][j1]; + wtdsum[1] += dirwt * smooth->a[i][j1]; + wtdsum[2] += dirwt * smooth->b[i][j1]; + wtdsum[3] += dirwt * buffer[0][i * scale][j1 * scale]; + wtdsum[4] += dirwt * buffer[1][i * scale][j1 * scale]; + wtdsum[5] += dirwt * buffer[2][i * scale][j1 * scale]; + norm += dirwt; + } + + for (i1 = max(0, i - 1); i1 < min(height, i + 2); i1 += 2) { + dirwt = 1;//IDIRWT(i1, j+1, i, j); + wtdsum[0] += dirwt * smooth->L[i1][j + 1]; + wtdsum[1] += dirwt * smooth->a[i1][j + 1]; + wtdsum[2] += dirwt * smooth->b[i1][j + 1]; + wtdsum[3] += dirwt * buffer[0][i1 * scale][(j + 1) * scale]; + wtdsum[4] += dirwt * buffer[1][i1 * scale][(j + 1) * scale]; + wtdsum[5] += dirwt * buffer[2][i1 * scale][(j + 1) * scale]; + norm += dirwt; + } + + norm = 1 / norm; + smooth->L[i][j + 1] = wtdsum[0] * norm; + smooth->a[i][j + 1] = wtdsum[1] * norm; + smooth->b[i][j + 1] = wtdsum[2] * norm; + buffer[0][i][(j + 1)*scale] = wtdsum[3] * norm; + buffer[1][i][(j + 1)*scale] = wtdsum[4] * norm; + buffer[2][i][(j + 1)*scale] = wtdsum[5] * norm; + + //now down neighbor + if (i + 1 == height) { + continue; + } + + norm = 0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = wtdsum[3] = wtdsum[4] = wtdsum[5] = 0.0; + + for (i1 = i; i1 < min(height, i + 3); i1 += 2) { + dirwt = 1;//IDIRWT(i1, j, i, j); + wtdsum[0] += dirwt * smooth->L[i1][j]; + wtdsum[1] += dirwt * smooth->a[i1][j]; + wtdsum[2] += dirwt * smooth->b[i1][j]; + wtdsum[3] += dirwt * buffer[0][i1 * scale][j * scale]; + wtdsum[4] += dirwt * buffer[1][i1 * scale][j * scale]; + wtdsum[5] += dirwt * buffer[2][i1 * scale][j * scale]; + norm += dirwt; + } + + for (j1 = max(0, j - 1); j1 < min(width, j + 2); j1 += 2) { + dirwt = 1;//IDIRWT(i+1, j1, i, j); + wtdsum[0] += dirwt * smooth->L[i + 1][j1]; + wtdsum[1] += dirwt * smooth->a[i + 1][j1]; + wtdsum[2] += dirwt * smooth->b[i + 1][j1]; + wtdsum[3] += dirwt * buffer[0][(i + 1) * scale][j1 * scale]; + wtdsum[4] += dirwt * buffer[1][(i + 1) * scale][j1 * scale]; + wtdsum[5] += dirwt * buffer[2][(i + 1) * scale][j1 * scale]; + norm += dirwt; + } + + norm = 1 / norm; + smooth->L[i + 1][j] = wtdsum[0] * norm; + smooth->a[i + 1][j] = wtdsum[1] * norm; + smooth->b[i + 1][j] = wtdsum[2] * norm; + buffer[0][(i + 1)*scale][j * scale] = wtdsum[3] * norm; + buffer[1][(i + 1)*scale][j * scale] = wtdsum[4] * norm; + buffer[2][(i + 1)*scale][j * scale] = wtdsum[5] * norm; + + } + + + // step (2-3-4) +#ifdef _OPENMP + #pragma omp for +#endif + + for(int i = 0; i < height; i++) + for(int j = 0; j < width; j++) { + + //luma + hipass[0] = (float)data_fine->L[i][j] - smooth->L[i][j]; + buffer[0][i * scale][j * scale] += hipass[0] * lumamult[level]; //*luma; + + //chroma + hipass[1] = data_fine->a[i][j] - smooth->a[i][j]; + hipass[2] = data_fine->b[i][j] - smooth->b[i][j]; + buffer[1][i * scale][j * scale] += hipass[1] * chromamult[level]; //*chroma; + buffer[2][i * scale][j * scale] += hipass[2] * chromamult[level]; //*chroma; + } + } // end parallel + delete smooth; + + } +} + + +#undef DIRWT_L +#undef DIRWT_AB + +#undef NRWT_L +#undef NRWT_AB + } diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc index ccd92b1ce..ea9a4a46d 100644 --- a/rtengine/dirpyr_equalizer.cc +++ b/rtengine/dirpyr_equalizer.cc @@ -5,7 +5,7 @@ * 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 @@ -15,7 +15,7 @@ * along with RawTherapee. If not, see . * * © 2010 Emil Martinec - * + * */ #include @@ -38,660 +38,805 @@ #define CLIPC(a) ((a)>-32000?((a)<32000?(a):32000):-32000) #define DIRWT(i1,j1,i,j) ( domker[(i1-i)/scale+halfwin][(j1-j)/scale+halfwin] * RANGEFN(fabsf((data_fine[i1][j1]-data_fine[i][j]))) ) -namespace rtengine { - - static const int maxlevel = 6; - static const float noise = 2000; - - //sequence of scales - static const int scales[6] = {1,2,4,8,16,32}; - extern const Settings* settings; - - //sequence of scales - - -SSEFUNCTION void ImProcFunctions :: dirpyr_equalizer(float ** src, float ** dst, int srcwidth, int srcheight, float ** l_a, float ** l_b, float ** dest_a, float ** dest_b,const double * mult, const double dirpyrThreshold, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev) - { - int lastlevel=maxlevel; - if(settings->verbose) printf("Dirpyr scaleprev=%i\n",scaleprev); - float atten123=(float) settings->level123_cbdl; - if(atten123 > 50.f) atten123=50.f; - if(atten123 < 0.f) atten123=0.f; - float atten0=(float) settings->level0_cbdl; - if(atten0 > 40.f) atten123=40.f; - if(atten0 < 0.f) atten0=0.f; - - if((t_r-t_l)<0.55f) - t_l = t_r + 0.55f;//avoid too small range - - - while (lastlevel>0 && fabs(mult[lastlevel-1]-1)<0.001) { - lastlevel--; - //printf("last level to process %d \n",lastlevel); - } - if (lastlevel==0) return; - - int level; - float multi[6]={1.f,1.f,1.f,1.f,1.f,1.f}; - float scalefl[6]; - - for(int lv=0;lv<6;lv++) { - scalefl[lv]= ((float) scales[lv])/(float) scaleprev; - if(lv>=1) {if(scalefl[lv] < 1.f) multi[lv] = (atten123*((float) mult[lv] -1.f)/100.f)+1.f; else multi[lv]=(float) mult[lv];}//modulate action if zoom < 100% - else {if(scalefl[lv] < 1.f) multi[lv] = (atten0*((float) mult[lv] -1.f)/100.f)+1.f; else multi[lv]=(float) mult[lv];}//modulate action if zoom < 100% - - } - if(settings->verbose) printf("CbDL mult0=%f 1=%f 2=%f 3=%f 4=%f 5=%f\n",multi[0],multi[1],multi[2],multi[3],multi[4],multi[5]); - - multi_array2D dirpyrlo (srcwidth, srcheight); - - level = 0; - - //int thresh = 100 * mult[5]; - int scale = (int)(scales[level])/scaleprev; - if(scale < 1) scale=1; - - - dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); - - level = 1; - - while(level < lastlevel) - { - - scale = (int)(scales[level])/scaleprev; - if(scale < 1) scale=1; - - dirpyr_channel(dirpyrlo[level-1], dirpyrlo[level], srcwidth, srcheight, level, scale); - - level ++; - } - - float **tmpHue,**tmpChr; - if(skinprot != 0.f) { - // precalculate hue and chroma, use SSE, if available - // by precalculating these values we can greatly reduce the number of calculations in idirpyr_eq_channel() - // but we need two additional buffers for this preprocessing - tmpHue = new float*[srcheight]; - for (int i=0; iverbose) { + printf("Dirpyr scaleprev=%i\n", scaleprev); + } + + float atten123 = (float) settings->level123_cbdl; + + if(atten123 > 50.f) { + atten123 = 50.f; + } + + if(atten123 < 0.f) { + atten123 = 0.f; + } + + float atten0 = (float) settings->level0_cbdl; + + if(atten0 > 40.f) { + atten123 = 40.f; + } + + if(atten0 < 0.f) { + atten0 = 0.f; + } + + if((t_r - t_l) < 0.55f) { + t_l = t_r + 0.55f; //avoid too small range + } + + + while (lastlevel > 0 && fabs(mult[lastlevel - 1] - 1) < 0.001) { + lastlevel--; + //printf("last level to process %d \n",lastlevel); + } + + if (lastlevel == 0) { + return; + } + + int level; + float multi[6] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; + float scalefl[6]; + + for(int lv = 0; lv < 6; lv++) { + scalefl[lv] = ((float) scales[lv]) / (float) scaleprev; + + if(lv >= 1) { + if(scalefl[lv] < 1.f) { + multi[lv] = (atten123 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100% + } else { + multi[lv] = (float) mult[lv]; + } + } else { + if(scalefl[lv] < 1.f) { + multi[lv] = (atten0 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; //modulate action if zoom < 100% + } else { + multi[lv] = (float) mult[lv]; + } + } + + } + + if(settings->verbose) { + printf("CbDL mult0=%f 1=%f 2=%f 3=%f 4=%f 5=%f\n", multi[0], multi[1], multi[2], multi[3], multi[4], multi[5]); + } + + multi_array2D dirpyrlo (srcwidth, srcheight); + + level = 0; + + //int thresh = 100 * mult[5]; + int scale = (int)(scales[level]) / scaleprev; + + if(scale < 1) { + scale = 1; + } + + + dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); + + level = 1; + + while(level < lastlevel) { + + scale = (int)(scales[level]) / scaleprev; + + if(scale < 1) { + scale = 1; + } + + dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, scale); + + level ++; + } + + float **tmpHue, **tmpChr; + + if(skinprot != 0.f) { + // precalculate hue and chroma, use SSE, if available + // by precalculating these values we can greatly reduce the number of calculations in idirpyr_eq_channel() + // but we need two additional buffers for this preprocessing + tmpHue = new float*[srcheight]; + + for (int i = 0; i < srcheight; i++) { + tmpHue[i] = new float[srcwidth]; + } + +#ifdef __SSE2__ + #pragma omp parallel for + + for(int i = 0; i < srcheight; i++) { + int j; + + for(j = 0; j < srcwidth - 3; j += 4) { + _mm_storeu_ps(&tmpHue[i][j], xatan2f(LVFU(l_b[i][j]), LVFU(l_a[i][j]))); + } + + for(; j < srcwidth; j++) { + tmpHue[i][j] = xatan2f(l_b[i][j], l_a[i][j]); + } + } + #else -#pragma omp parallel for - for(int i=0;i 0; level--) - { - idirpyr_eq_channel(dirpyrlo[level], dirpyrlo[level-1], buffer, srcwidth, srcheight, level, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, gamutlab, b_l,t_l,t_r,b_r, choice ); - } + for (int i = 0; i < srcheight; i++) { + tmpChr[i] = new float[srcwidth]; + } - scale = scales[0]; - - idirpyr_eq_channel(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, gamutlab, b_l,t_l,t_r,b_r, choice ); +#ifdef __SSE2__ + #pragma omp parallel + { + __m128 div = _mm_set1_ps(327.68f); + #pragma omp for - if(skinprot != 0.f) { - for (int i=0; i 0; level--) { + idirpyr_eq_channel(dirpyrlo[level], dirpyrlo[level - 1], buffer, srcwidth, srcheight, level, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice ); + } + + scale = scales[0]; + + idirpyr_eq_channel(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, tmpHue, tmpChr, skinprot, gamutlab, b_l, t_l, t_r, b_r, choice ); + + if(skinprot != 0.f) { + for (int i = 0; i < srcheight; i++) { + delete [] tmpChr[i]; + } + + delete [] tmpChr; + + for (int i = 0; i < srcheight; i++) { + delete [] tmpHue[i]; + } + + delete [] tmpHue; + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + #pragma omp parallel for + + for (int i = 0; i < srcheight; i++) + for (int j = 0; j < srcwidth; j++) { + dst[i][j] = CLIP(buffer[i][j]); // TODO: Really a clip necessary? + } + +} - - void ImProcFunctions :: dirpyr_equalizercam (CieImage *ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev) - { - int lastlevel=maxlevel; - if(settings->verbose) printf("CAM dirpyr scaleprev=%i\n",scaleprev); - float atten123=(float) settings->level123_cbdl; - if(atten123 > 50.f) atten123=50.f; - if(atten123 < 0.f) atten123=0.f; -// printf("atten=%f\n",atten); - float atten0=(float) settings->level0_cbdl; - if(atten0 > 40.f) atten123=40.f; - if(atten0 < 0.f) atten0=0.f; - if((t_r-t_l)<0.55f) - t_l = t_r + 0.55f;//avoid too small range +void ImProcFunctions :: dirpyr_equalizercam (CieImage *ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scaleprev) +{ + int lastlevel = maxlevel; - while (fabs(mult[lastlevel-1]-1)<0.001 && lastlevel>0) { - lastlevel--; - //printf("last level to process %d \n",lastlevel); - } - if (lastlevel==0) return; - - int level; - - float multi[6]={1.f,1.f,1.f,1.f,1.f,1.f}; - float scalefl[6]; - - for(int lv=0;lv<6;lv++) { - scalefl[lv]= ((float) scales[lv])/(float) scaleprev; - // if(scalefl[lv] < 1.f) multi[lv] = 1.f; else multi[lv]=(float) mult[lv]; - if (lv>=1) {if(scalefl[lv] < 1.f) multi[lv] = (atten123*((float) mult[lv] -1.f)/100.f)+1.f; else multi[lv]=(float) mult[lv];} - else {if(scalefl[lv] < 1.f) multi[lv] = (atten0*((float) mult[lv] -1.f)/100.f)+1.f; else multi[lv]=(float) mult[lv];} + if(settings->verbose) { + printf("CAM dirpyr scaleprev=%i\n", scaleprev); + } - - } - if(settings->verbose) printf("CAM CbDL mult0=%f 1=%f 2=%f 3=%f 4=%f 5=%f\n",multi[0],multi[1],multi[2],multi[3],multi[4],multi[5]); - - - - - multi_array2D dirpyrlo (srcwidth, srcheight); + float atten123 = (float) settings->level123_cbdl; - level = 0; - - int scale = (int)(scales[level])/scaleprev; - if(scale < 1) scale=1; + if(atten123 > 50.f) { + atten123 = 50.f; + } - dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); - - level = 1; - - while(level < lastlevel) - { - scale = (int)(scales[level])/scaleprev; - if(scale < 1) scale=1; + if(atten123 < 0.f) { + atten123 = 0.f; + } - dirpyr_channel(dirpyrlo[level-1], dirpyrlo[level], srcwidth, srcheight, level, scale); - - level ++; - } - - - // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory - float ** buffer = dirpyrlo[lastlevel-1]; - - for(int level = lastlevel - 1; level > 0; level--) - { - idirpyr_eq_channelcam(dirpyrlo[level], dirpyrlo[level-1], buffer, srcwidth, srcheight, level, multi, dirpyrThreshold , h_p, C_p, skinprot, b_l,t_l,t_r); - } - - - scale = scales[0]; - - idirpyr_eq_channelcam(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, h_p, C_p, skinprot, b_l,t_l,t_r); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if(execdir){ +// printf("atten=%f\n",atten); + float atten0 = (float) settings->level0_cbdl; + + if(atten0 > 40.f) { + atten123 = 40.f; + } + + if(atten0 < 0.f) { + atten0 = 0.f; + } + + if((t_r - t_l) < 0.55f) { + t_l = t_r + 0.55f; //avoid too small range + } + + while (fabs(mult[lastlevel - 1] - 1) < 0.001 && lastlevel > 0) { + lastlevel--; + //printf("last level to process %d \n",lastlevel); + } + + if (lastlevel == 0) { + return; + } + + int level; + + float multi[6] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; + float scalefl[6]; + + for(int lv = 0; lv < 6; lv++) { + scalefl[lv] = ((float) scales[lv]) / (float) scaleprev; + + // if(scalefl[lv] < 1.f) multi[lv] = 1.f; else multi[lv]=(float) mult[lv]; + if (lv >= 1) { + if(scalefl[lv] < 1.f) { + multi[lv] = (atten123 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; + } else { + multi[lv] = (float) mult[lv]; + } + } else { + if(scalefl[lv] < 1.f) { + multi[lv] = (atten0 * ((float) mult[lv] - 1.f) / 100.f) + 1.f; + } else { + multi[lv] = (float) mult[lv]; + } + } + + + } + + if(settings->verbose) { + printf("CAM CbDL mult0=%f 1=%f 2=%f 3=%f 4=%f 5=%f\n", multi[0], multi[1], multi[2], multi[3], multi[4], multi[5]); + } + + + + + multi_array2D dirpyrlo (srcwidth, srcheight); + + level = 0; + + int scale = (int)(scales[level]) / scaleprev; + + if(scale < 1) { + scale = 1; + } + + dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, 0, scale); + + level = 1; + + while(level < lastlevel) { + scale = (int)(scales[level]) / scaleprev; + + if(scale < 1) { + scale = 1; + } + + dirpyr_channel(dirpyrlo[level - 1], dirpyrlo[level], srcwidth, srcheight, level, scale); + + level ++; + } + + + // with the current implementation of idirpyr_eq_channel we can safely use the buffer from last level as buffer, saves some memory + float ** buffer = dirpyrlo[lastlevel - 1]; + + for(int level = lastlevel - 1; level > 0; level--) { + idirpyr_eq_channelcam(dirpyrlo[level], dirpyrlo[level - 1], buffer, srcwidth, srcheight, level, multi, dirpyrThreshold , h_p, C_p, skinprot, b_l, t_l, t_r); + } + + + scale = scales[0]; + + idirpyr_eq_channelcam(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, multi, dirpyrThreshold, h_p, C_p, skinprot, b_l, t_l, t_r); + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if(execdir) { #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int i=0; iJ_p[i][j] > 8.f && ncie->J_p[i][j] < 92.f) - dst[i][j] = CLIP( buffer[i][j] ); // TODO: Really a clip necessary? - else - dst[i][j]=src[i][j]; - } - } - else - for (int i=0; iJ_p[i][j] > 8.f && ncie->J_p[i][j] < 92.f) { + dst[i][j] = CLIP( buffer[i][j] ); // TODO: Really a clip necessary? + } else { + dst[i][j] = src[i][j]; + } + } + } else + for (int i = 0; i < srcheight; i++) + for (int j = 0; j < srcwidth; j++) { + dst[i][j] = CLIP( buffer[i][j] ); // TODO: Really a clip necessary? + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +} SSEFUNCTION void ImProcFunctions::dirpyr_channel(float ** data_fine, float ** data_coarse, int width, int height, int level, int scale) { - //scale is spacing of directional averaging weights - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // calculate weights, compute directionally weighted average - - if(level > 1) { - //generate domain kernel - int domker[5][5] = {{1,1,1,1,1},{1,2,2,2,1},{1,2,2,2,1},{1,2,2,2,1},{1,1,1,1,1}}; - // int domker[5][5] = {{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}}; - static const int halfwin=2; - const int scalewin = halfwin*scale; + //scale is spacing of directional averaging weights + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // calculate weights, compute directionally weighted average + + if(level > 1) { + //generate domain kernel + int domker[5][5] = {{1, 1, 1, 1, 1}, {1, 2, 2, 2, 1}, {1, 2, 2, 2, 1}, {1, 2, 2, 2, 1}, {1, 1, 1, 1, 1}}; + // int domker[5][5] = {{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}}; + static const int halfwin = 2; + const int scalewin = halfwin * scale; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef __SSE2__ - __m128 thousandv = _mm_set1_ps( 1000.0f ); - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; -// multiplied each value of domkerv by 1000 to avoid multiplication by 1000 inside the loop - float domkerv[5][5][4] __attribute__ ((aligned (16))) = {{{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000}},{{1000,1000,1000,1000},{2000,2000,2000,2000},{2000,2000,2000,2000},{2000,2000,2000,2000},{1000,1000,1000,1000}},{{1000,1000,1000,1000},{2000,2000,2000,2000},{2000,2000,2000,2000},{2000,2000,2000,2000},{1000,1000,1000,1000}},{{1000,1000,1000,1000},{2000,2000,2000,2000},{2000,2000,2000,2000},{2000,2000,2000,2000},{1000,1000,1000,1000}},{{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000}}}; + __m128 thousandv = _mm_set1_ps( 1000.0f ); + __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; +// multiplied each value of domkerv by 1000 to avoid multiplication by 1000 inside the loop + float domkerv[5][5][4] __attribute__ ((aligned (16))) = {{{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {2000, 2000, 2000, 2000}, {1000, 1000, 1000, 1000}}, {{1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}, {1000, 1000, 1000, 1000}}}; #endif // __SSE2__ - int j; + int j; #ifdef _OPENMP -#pragma omp for //schedule (dynamic,8) + #pragma omp for //schedule (dynamic,8) #endif - for(int i = 0; i < height; i++) { - float dirwt; - for(j = 0; j < scalewin; j++) { - float val=0.f; - float norm=0.f; - - - for(int inbr=max(0,i-scalewin); inbr<=min(height-1,i+scalewin); inbr+=scale) { - for (int jnbr=max(0,j-scalewin); jnbr<=j+scalewin; jnbr+=scale) { - //printf("i=%d ",(inbr-i)/scale+halfwin); - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } + + for(int i = 0; i < height; i++) { + float dirwt; + + for(j = 0; j < scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + + for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = max(0, j - scalewin); jnbr <= j + scalewin; jnbr += scale) { + //printf("i=%d ",(inbr-i)/scale+halfwin); + dirwt = DIRWT(inbr, jnbr, i, j); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + #ifdef __SSE2__ - for(; j < width-scalewin-3; j+=4) - { - valv = _mm_setzero_ps(); - normv = _mm_setzero_ps(); - dftemp1v = LVFU(data_fine[i][j]); - for(int inbr=MAX(0,i-scalewin); inbr<=MIN(height-1,i+scalewin); inbr+=scale) { - int indexihlp = (inbr-i)/scale+halfwin; - for (int jnbr=j-scalewin, indexjhlp = 0; jnbr<=j+scalewin; jnbr+=scale,indexjhlp++) { - dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = _mm_load_ps((float*)&domkerv[indexihlp][indexjhlp]) / (vabsf(dftemp1v-dftemp2v) + thousandv); - valv += dirwtv*dftemp2v; - normv += dirwtv; - } - } - _mm_storeu_ps( &data_coarse[i][j],valv/normv);//low pass filter - } - for(; j < width-scalewin; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scalewin); inbr<=min(height-1,i+scalewin); inbr+=scale) { - for (int jnbr=j-scalewin; jnbr<=j+scalewin; jnbr+=scale) { - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } + + for(; j < width - scalewin - 3; j += 4) { + valv = _mm_setzero_ps(); + normv = _mm_setzero_ps(); + dftemp1v = LVFU(data_fine[i][j]); + + for(int inbr = MAX(0, i - scalewin); inbr <= MIN(height - 1, i + scalewin); inbr += scale) { + int indexihlp = (inbr - i) / scale + halfwin; + + for (int jnbr = j - scalewin, indexjhlp = 0; jnbr <= j + scalewin; jnbr += scale, indexjhlp++) { + dftemp2v = LVFU(data_fine[inbr][jnbr]); + dirwtv = _mm_load_ps((float*)&domkerv[indexihlp][indexjhlp]) / (vabsf(dftemp1v - dftemp2v) + thousandv); + valv += dirwtv * dftemp2v; + normv += dirwtv; + } + } + + _mm_storeu_ps( &data_coarse[i][j], valv / normv); //low pass filter + } + + for(; j < width - scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { + dirwt = DIRWT(inbr, jnbr, i, j); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + #else - for(; j < width-scalewin; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scalewin); inbr<=min(height-1,i+scalewin); inbr+=scale) { - for (int jnbr=j-scalewin; jnbr<=j+scalewin; jnbr+=scale) { - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } + for(; j < width - scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { + dirwt = DIRWT(inbr, jnbr, i, j); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + #endif - for(; j < width; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scalewin); inbr<=min(height-1,i+scalewin); inbr+=scale) { - for (int jnbr=j-scalewin; jnbr<=min(width-1,j+scalewin); jnbr+=scale) { - dirwt = DIRWT(inbr, jnbr, i, j); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } - } -} - } else { // level <=1 means that all values of domker would be 1.0f, so no need for multiplication -// const int scalewin = scale; + + for(; j < width; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= min(width - 1, j + scalewin); jnbr += scale) { + dirwt = DIRWT(inbr, jnbr, i, j); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + } + } + } else { // level <=1 means that all values of domker would be 1.0f, so no need for multiplication +// const int scalewin = scale; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef __SSE2__ - __m128 thousandv = _mm_set1_ps( 1000.0f ); - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; + __m128 thousandv = _mm_set1_ps( 1000.0f ); + __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; #endif // __SSE2__ - int j; + int j; #ifdef _OPENMP -#pragma omp for schedule(dynamic,16) + #pragma omp for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - float dirwt; - for(j = 0; j < scale; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scale); inbr<=min(height-1,i+scale); inbr+=scale) { - for (int jnbr=max(0,j-scale); jnbr<=j+scale; jnbr+=scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr]-data_fine[i][j])); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } + + for(int i = 0; i < height; i++) + { + float dirwt; + + for(j = 0; j < scale; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int jnbr = max(0, j - scale); jnbr <= j + scale; jnbr += scale) { + dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + #ifdef __SSE2__ - for(; j < width-scale-3; j+=4) - { - valv = _mm_setzero_ps(); - normv = _mm_setzero_ps(); - dftemp1v = LVFU(data_fine[i][j]); - for(int inbr=MAX(0,i-scale); inbr<=MIN(height-1,i+scale); inbr+=scale) { - for (int jnbr=j-scale; jnbr<=j+scale; jnbr+=scale) { - dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = thousandv / (vabsf(dftemp2v-dftemp1v) + thousandv); - valv += dirwtv*dftemp2v; - normv += dirwtv; - } - } - _mm_storeu_ps( &data_coarse[i][j], valv/normv);//low pass filter - } - for(; j < width-scale; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scale); inbr<=min(height-1,i+scale); inbr+=scale) { - for (int jnbr=j-scale; jnbr<=j+scale; jnbr+=scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr]-data_fine[i][j])); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } + for(; j < width - scale - 3; j += 4) { + valv = _mm_setzero_ps(); + normv = _mm_setzero_ps(); + dftemp1v = LVFU(data_fine[i][j]); + + for(int inbr = MAX(0, i - scale); inbr <= MIN(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { + dftemp2v = LVFU(data_fine[inbr][jnbr]); + dirwtv = thousandv / (vabsf(dftemp2v - dftemp1v) + thousandv); + valv += dirwtv * dftemp2v; + normv += dirwtv; + } + } + + _mm_storeu_ps( &data_coarse[i][j], valv / normv); //low pass filter + } + + for(; j < width - scale; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { + dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + #else - for(; j < width-scale; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scale); inbr<=min(height-1,i+scale); inbr+=scale) { - for (int jnbr=j-scale; jnbr<=j+scale; jnbr+=scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr]-data_fine[i][j])); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } + for(; j < width - scale; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= j + scale; jnbr += scale) { + dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + #endif - for(; j < width; j++) - { - float val=0.f; - float norm=0.f; - - for(int inbr=max(0,i-scale); inbr<=min(height-1,i+scale); inbr+=scale) { - for (int jnbr=j-scale; jnbr<=min(width-1,j+scale); jnbr+=scale) { - dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr]-data_fine[i][j])); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j]=val/norm;//low pass filter - } - } + + for(; j < width; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(0, i - scale); inbr <= min(height - 1, i + scale); inbr += scale) { + for (int jnbr = j - scale; jnbr <= min(width - 1, j + scale); jnbr += scale) { + dirwt = RANGEFN(fabsf(data_fine[inbr][jnbr] - data_fine[i][j])); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; //low pass filter + } + } + } + } } - } + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void ImProcFunctions::idirpyr_eq_channel(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[5], const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r , int choice) +{ + const float skinprotneg = -skinprot; + const float factorHard = (1.f - skinprotneg / 100.f); + + float offs; + + if(skinprot == 0.f) { + offs = 0.f; + } else { + offs = -1.f; + } + + float multbis[6]; + + multbis[level] = mult[level]; //multbis to reduce artifacts for high values mult + + if(level == 4 && mult[level] > 1.f) { + multbis[level] = 1.f + 0.65f * (mult[level] - 1.f); + } + + if(level == 5 && mult[level] > 1.f) { + multbis[level] = 1.f + 0.45f * (mult[level] - 1.f); + } + + LUTf irangefn (0x20000); + { + const float noisehi = 1.33f * noise * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * dirpyrThreshold / expf(level * log(3.0)); + //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); + + for (int i = 0; i < 0x20000; i++) { + if (abs(i - 0x10000) > noisehi || multbis[level] < 1.0) { + irangefn[i] = multbis[level] + offs; + } else { + if (abs(i - 0x10000) < noiselo) { + irangefn[i] = 1.f + offs ; + } else { + irangefn[i] = 1.f + offs + (multbis[level] - 1.f) * (noisehi - abs(i - 0x10000)) / (noisehi - noiselo + 0.01f) ; + } + } + } + } + + if(skinprot == 0.f) +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) { + float hipass = (data_fine[i][j] - data_coarse[i][j]); + buffer[i][j] += irangefn[hipass + 0x10000] * hipass; + } + } + else if(skinprot > 0.f) +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) { + float scale = 1.f; + float hipass = (data_fine[i][j] - data_coarse[i][j]); + // These values are precalculated now + float modhue = hue[i][j]; + float modchro = chrom[i][j]; + Color::SkinSatCbdl ((data_fine[i][j]) / 327.68f, modhue, modchro, skinprot, scale, true, b_l, t_l, t_r); + buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass ; + } + } + else +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) { + float scale = 1.f; + float hipass = (data_fine[i][j] - data_coarse[i][j]); + // These values are precalculated now + float modhue = hue[i][j]; + float modchro = chrom[i][j]; + Color::SkinSatCbdl ((data_fine[i][j]) / 327.68f, modhue, modchro, skinprotneg, scale, false, b_l, t_l, t_r); + float correct = irangefn[hipass + 0x10000]; + + if (scale == 1.f) {//image hard + buffer[i][j] += (1.f + (correct) * (factorHard)) * hipass ; + } else { //image soft with scale < 1 ==> skin + buffer[i][j] += (1.f + (correct)) * hipass ; + } + } + } } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void ImProcFunctions::idirpyr_eq_channel(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[5], const double dirpyrThreshold, float ** hue, float ** chrom, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r , int choice) - { - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg/100.f); - float offs; - if(skinprot==0.f) - offs = 0.f; - else - offs = -1.f; - float multbis[6]; - - multbis[level]=mult[level];//multbis to reduce artifacts for high values mult - if(level==4 && mult[level]> 1.f) multbis[level]=1.f+0.65f*(mult[level]-1.f); - if(level==5 && mult[level]> 1.f) multbis[level]=1.f+0.45f*(mult[level]-1.f); - - LUTf irangefn (0x20000); - { - const float noisehi = 1.33f*noise*dirpyrThreshold/expf(level*log(3.0)), noiselo = 0.66f*noise*dirpyrThreshold/expf(level*log(3.0)); - //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); - - for (int i=0; i<0x20000; i++) { - if (abs(i-0x10000)>noisehi || multbis[level]<1.0) { - irangefn[i] = multbis[level] + offs; - } else { - if (abs(i-0x10000) 0.f) -#ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) -#endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float scale=1.f; - float hipass = (data_fine[i][j]-data_coarse[i][j]); - // These values are precalculated now - float modhue = hue[i][j]; - float modchro = chrom[i][j]; - Color::SkinSatCbdl ((data_fine[i][j])/327.68f, modhue, modchro, skinprot, scale, true, b_l, t_l, t_r); - buffer[i][j] += (1.f +(irangefn[hipass+0x10000])*scale) * hipass ; - } - } - else -#ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) -#endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float scale=1.f; - float hipass = (data_fine[i][j]-data_coarse[i][j]); - // These values are precalculated now - float modhue = hue[i][j]; - float modchro = chrom[i][j]; - Color::SkinSatCbdl ((data_fine[i][j])/327.68f, modhue, modchro, skinprotneg, scale, false, b_l, t_l, t_r); - float correct = irangefn[hipass+0x10000]; - if (scale == 1.f) {//image hard - buffer[i][j] += (1.f +(correct)* (factorHard)) * hipass ; - } - else {//image soft with scale < 1 ==> skin - buffer[i][j] += (1.f +(correct)) * hipass ; - } - } - } - } - - - void ImProcFunctions::idirpyr_eq_channelcam(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r) - { +void ImProcFunctions::idirpyr_eq_channelcam(float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float mult[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r) +{ - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg/100.f); + const float skinprotneg = -skinprot; + const float factorHard = (1.f - skinprotneg / 100.f); - float offs; - if(skinprot==0.f) - offs = 0.f; - else - offs = -1.f; - float multbis[6]; - - multbis[level]=mult[level];//multbis to reduce artifacts for high values mult - if(level==4 && mult[level]> 1.f) multbis[level]=1.f+0.65f*(mult[level]-1.f); - if(level==5 && mult[level]> 1.f) multbis[level]=1.f+0.45f*(mult[level]-1.f); - - LUTf irangefn (0x20000); - { - const float noisehi = 1.33f*noise*dirpyrThreshold/expf(level*log(3.0)), noiselo = 0.66f*noise*dirpyrThreshold/expf(level*log(3.0)); - //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); - for (int i=0; i<0x20000; i++) { - if (abs(i-0x10000)>noisehi || multbis[level]<1.0) { - irangefn[i] = multbis[level] + offs; - } else { - if (abs(i-0x10000) 1.f) { + multbis[level] = 1.f + 0.65f * (mult[level] - 1.f); + } + + if(level == 5 && mult[level] > 1.f) { + multbis[level] = 1.f + 0.45f * (mult[level] - 1.f); + } + + LUTf irangefn (0x20000); + { + const float noisehi = 1.33f * noise * dirpyrThreshold / expf(level * log(3.0)), noiselo = 0.66f * noise * dirpyrThreshold / expf(level * log(3.0)); + + //printf("level=%i multlev=%f noisehi=%f noiselo=%f skinprot=%f\n",level,mult[level], noisehi, noiselo, skinprot); + for (int i = 0; i < 0x20000; i++) { + if (abs(i - 0x10000) > noisehi || multbis[level] < 1.0) { + irangefn[i] = multbis[level] + offs; + } else { + if (abs(i - 0x10000) < noiselo) { + irangefn[i] = 1.f + offs ; + } else { + irangefn[i] = 1.f + offs + (multbis[level] - 1.f) * (noisehi - abs(i - 0x10000)) / (noisehi - noiselo + 0.01f) ; + } + } + } + } + + if(skinprot == 0.f) #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j]-data_coarse[i][j]); - buffer[i][j] += irangefn[hipass+0x10000] * hipass ; - } - } - else if(skinprot > 0.f) + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) { + float hipass = (data_fine[i][j] - data_coarse[i][j]); + buffer[i][j] += irangefn[hipass + 0x10000] * hipass ; + } + } + else if(skinprot > 0.f) #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j]-data_coarse[i][j]); - float scale=1.f; - Color::SkinSatCbdlCam ((data_fine[i][j])/327.68f, l_a_h[i][j] ,l_b_c[i][j], skinprot, scale, true, b_l, t_l, t_r); - buffer[i][j] += (1.f +(irangefn[hipass+0x10000])*scale) * hipass ; - } - } - else + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) { + float hipass = (data_fine[i][j] - data_coarse[i][j]); + float scale = 1.f; + Color::SkinSatCbdlCam ((data_fine[i][j]) / 327.68f, l_a_h[i][j] , l_b_c[i][j], skinprot, scale, true, b_l, t_l, t_r); + buffer[i][j] += (1.f + (irangefn[hipass + 0x10000]) * scale) * hipass ; + } + } + else #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) { - float hipass = (data_fine[i][j]-data_coarse[i][j]); - float scale=1.f; - float correct; - correct=irangefn[hipass+0x10000]; - Color::SkinSatCbdlCam ((data_fine[i][j])/327.68f, l_a_h[i][j],l_b_c[i][j] , skinprotneg, scale, false, b_l, t_l, t_r); - if (scale == 1.f) {//image hard - buffer[i][j] += (1.f +(correct)* factorHard) * hipass ; - - } - else {//image soft - buffer[i][j] += (1.f +(correct)) * hipass ; - } - } - } - // if(gamutlab) { - // ImProcFunctions::badpixcam (buffer[i][j], 6.0, 10, 2);//for bad pixels - // } - - /* if(gamutlab) {//disabled - float Lprov1=(buffer[i][j])/327.68f; - float R,G,B; -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f); -#endif - // Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f);//gamut control in Lab mode ..not in CIECAM - buffer[i][j]=Lprov1*327.68f; - float2 sincosval = xsincosf(modhue); - l_a_h[i][j]=327.68f*modchro*sincosval.y; - l_b_c[i][j]=327.68f*modchro*sincosval.x; - } - */ - } - - // float hipass = (data_fine[i][j]-data_coarse[i][j]); - // buffer[i][j] += irangefn[hipass+0x10000] * hipass ; - + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) { + float hipass = (data_fine[i][j] - data_coarse[i][j]); + float scale = 1.f; + float correct; + correct = irangefn[hipass + 0x10000]; + Color::SkinSatCbdlCam ((data_fine[i][j]) / 327.68f, l_a_h[i][j], l_b_c[i][j] , skinprotneg, scale, false, b_l, t_l, t_r); + + if (scale == 1.f) {//image hard + buffer[i][j] += (1.f + (correct) * factorHard) * hipass ; + + } else { //image soft + buffer[i][j] += (1.f + (correct)) * hipass ; + } + } + } + + // if(gamutlab) { + // ImProcFunctions::badpixcam (buffer[i][j], 6.0, 10, 2);//for bad pixels + // } + + /* if(gamutlab) {//disabled + float Lprov1=(buffer[i][j])/327.68f; + float R,G,B; + #ifdef _DEBUG + bool neg=false; + bool more_rgb=false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); + #else + //gamut control : Lab values are in gamut + Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f); + #endif + // Color::gamutLchonly(modhue,Lprov1,modchro, R, G, B, wip, highlight, 0.15f, 0.96f);//gamut control in Lab mode ..not in CIECAM + buffer[i][j]=Lprov1*327.68f; + float2 sincosval = xsincosf(modhue); + l_a_h[i][j]=327.68f*modchro*sincosval.y; + l_b_c[i][j]=327.68f*modchro*sincosval.x; + } + */ +} + +// float hipass = (data_fine[i][j]-data_coarse[i][j]); +// buffer[i][j] += irangefn[hipass+0x10000] * hipass ; + #undef DIRWT_L #undef DIRWT_AB - -#undef NRWT_L -#undef NRWT_AB - + +#undef NRWT_L +#undef NRWT_AB + } diff --git a/rtengine/editbuffer.cc b/rtengine/editbuffer.cc index a72d05651..caf657070 100644 --- a/rtengine/editbuffer.cc +++ b/rtengine/editbuffer.cc @@ -19,202 +19,246 @@ #include "editbuffer.h" -namespace rtengine { +namespace rtengine +{ EditBuffer::EditBuffer(::EditDataProvider *dataProvider) : - objectMap(NULL), objectMap2(NULL), objectMode(OM_255), dataProvider(dataProvider), - imgFloatBuffer(NULL), LabBuffer(NULL), singlePlaneBuffer(), ready(false) {} + objectMap(NULL), objectMap2(NULL), objectMode(OM_255), dataProvider(dataProvider), + imgFloatBuffer(NULL), LabBuffer(NULL), singlePlaneBuffer(), ready(false) {} -EditBuffer::~EditBuffer() { - flush(); - #ifndef NDEBUG - imgFloatBuffer = (Imagefloat*)(0xbaadf00d); - #endif - #ifndef NDEBUG - LabBuffer = (LabImage*)(0xbaadf00d); - #endif +EditBuffer::~EditBuffer() +{ + flush(); +#ifndef NDEBUG + imgFloatBuffer = (Imagefloat*)(0xbaadf00d); +#endif +#ifndef NDEBUG + LabBuffer = (LabImage*)(0xbaadf00d); +#endif } -void EditBuffer::createBuffer(int width, int height) { - //printf("Appel de createBuffer %d x %d\n", width, height); - resize (width, height); +void EditBuffer::createBuffer(int width, int height) +{ + //printf("Appel de createBuffer %d x %d\n", width, height); + resize (width, height); } -void EditBuffer::flush() { - if (imgFloatBuffer) { - delete imgFloatBuffer; - imgFloatBuffer = NULL; - } - if (LabBuffer) { - delete LabBuffer; - LabBuffer = NULL; - } - singlePlaneBuffer.flushData(); - ready = false; +void EditBuffer::flush() +{ + if (imgFloatBuffer) { + delete imgFloatBuffer; + imgFloatBuffer = NULL; + } + + if (LabBuffer) { + delete LabBuffer; + LabBuffer = NULL; + } + + singlePlaneBuffer.flushData(); + ready = false; } /* Upgrade or downgrade the objectModeType; we're assuming that objectMap has been allocated */ -void EditBuffer::setObjectMode(ObjectMode newType) { - switch (newType) { - case (OM_255): - if (objectMap2) { - objectMap2->unreference(); - } - objectMode = OM_255; - break; - case (OM_65535): - if (!objectMap2) { - objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, objectMap->get_width(), objectMap->get_height()); - } - objectMode = OM_65535; - break; - } +void EditBuffer::setObjectMode(ObjectMode newType) +{ + switch (newType) { + case (OM_255): + if (objectMap2) { + objectMap2->unreference(); + } + + objectMode = OM_255; + break; + + case (OM_65535): + if (!objectMap2) { + objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, objectMap->get_width(), objectMap->get_height()); + } + + objectMode = OM_65535; + break; + } } -EditUniqueID EditBuffer::getEditID() { - if (dataProvider && dataProvider->getCurrSubscriber()) { - return dataProvider->getCurrSubscriber()->getEditID(); - } - else return EUID_None; +EditUniqueID EditBuffer::getEditID() +{ + if (dataProvider && dataProvider->getCurrSubscriber()) { + return dataProvider->getCurrSubscriber()->getEditID(); + } else { + return EUID_None; + } } -void EditBuffer::resize(int newWidth, int newHeight) { - resize(newWidth, newHeight, dataProvider ? dataProvider->getCurrSubscriber() : NULL); +void EditBuffer::resize(int newWidth, int newHeight) +{ + resize(newWidth, newHeight, dataProvider ? dataProvider->getCurrSubscriber() : NULL); } // Resize buffers if they already exist -void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) { - if (newSubscriber) { - if (newSubscriber->getEditingType() == ET_OBJECTS) { - if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight)) - objectMap.clear(); +void EditBuffer::resize(int newWidth, int newHeight, EditSubscriber* newSubscriber) +{ + if (newSubscriber) { + if (newSubscriber->getEditingType() == ET_OBJECTS) { + if (objectMap && (objectMap->get_width() != newWidth || objectMap->get_height() != newHeight)) { + objectMap.clear(); + } - if (!objectMap && newWidth && newHeight) { - objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); - } - if (objectMode==OM_65535) { - if (objectMap2) { - if (objectMap2->get_width() != newWidth || objectMap2->get_height() != newHeight) { - objectMap2.clear(); - } - } - if (!objectMap2 && newWidth && newHeight) { - objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); - } - } - // OM_255 -> deleting objectMap2, if any - else if (objectMap2) - objectMap2.clear(); + if (!objectMap && newWidth && newHeight) { + objectMap = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); + } - // Should never happen! - if (imgFloatBuffer) { - delete imgFloatBuffer; - imgFloatBuffer = NULL; - } - if (LabBuffer) { - delete LabBuffer; - LabBuffer = NULL; - } - if (singlePlaneBuffer.data) { - singlePlaneBuffer.allocate(0,0); - } - } + if (objectMode == OM_65535) { + if (objectMap2) { + if (objectMap2->get_width() != newWidth || objectMap2->get_height() != newHeight) { + objectMap2.clear(); + } + } - if (newSubscriber->getEditingType() == ET_PIPETTE) { - if (newSubscriber->getEditBufferType() == BT_IMAGEFLOAT) { - if (!imgFloatBuffer) - imgFloatBuffer = new Imagefloat(newWidth, newHeight); - else - imgFloatBuffer->allocate(newWidth, newHeight); - } - else if (imgFloatBuffer) { - delete imgFloatBuffer; - imgFloatBuffer = NULL; - } + if (!objectMap2 && newWidth && newHeight) { + objectMap2 = Cairo::ImageSurface::create(Cairo::FORMAT_A8, newWidth, newHeight); + } + } + // OM_255 -> deleting objectMap2, if any + else if (objectMap2) { + objectMap2.clear(); + } - if (newSubscriber->getEditBufferType() == BT_LABIMAGE) { - if (LabBuffer && (LabBuffer->W != newWidth && LabBuffer->H != newHeight)) { - delete LabBuffer; - LabBuffer = NULL; - } - if (!LabBuffer) - LabBuffer = new LabImage(newWidth, newHeight); - } - else if (LabBuffer) { - delete LabBuffer; - LabBuffer = NULL; - } + // Should never happen! + if (imgFloatBuffer) { + delete imgFloatBuffer; + imgFloatBuffer = NULL; + } - if (newSubscriber->getEditBufferType() == BT_SINGLEPLANE_FLOAT) { - singlePlaneBuffer.allocate(newWidth, newHeight); - } - else if (singlePlaneBuffer.data) - singlePlaneBuffer.allocate(0,0); + if (LabBuffer) { + delete LabBuffer; + LabBuffer = NULL; + } - // Should never happen! - if (objectMap ) objectMap.clear(); - if (objectMap2) objectMap2.clear(); - } - } - ready = false; + if (singlePlaneBuffer.data) { + singlePlaneBuffer.allocate(0, 0); + } + } + + if (newSubscriber->getEditingType() == ET_PIPETTE) { + if (newSubscriber->getEditBufferType() == BT_IMAGEFLOAT) { + if (!imgFloatBuffer) { + imgFloatBuffer = new Imagefloat(newWidth, newHeight); + } else { + imgFloatBuffer->allocate(newWidth, newHeight); + } + } else if (imgFloatBuffer) { + delete imgFloatBuffer; + imgFloatBuffer = NULL; + } + + if (newSubscriber->getEditBufferType() == BT_LABIMAGE) { + if (LabBuffer && (LabBuffer->W != newWidth && LabBuffer->H != newHeight)) { + delete LabBuffer; + LabBuffer = NULL; + } + + if (!LabBuffer) { + LabBuffer = new LabImage(newWidth, newHeight); + } + } else if (LabBuffer) { + delete LabBuffer; + LabBuffer = NULL; + } + + if (newSubscriber->getEditBufferType() == BT_SINGLEPLANE_FLOAT) { + singlePlaneBuffer.allocate(newWidth, newHeight); + } else if (singlePlaneBuffer.data) { + singlePlaneBuffer.allocate(0, 0); + } + + // Should never happen! + if (objectMap ) { + objectMap.clear(); + } + + if (objectMap2) { + objectMap2.clear(); + } + } + } + + ready = false; } -bool EditBuffer::bufferCreated() { - EditSubscriber* subscriber; - if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) { - switch (subscriber->getEditingType()) { - case ET_PIPETTE: - switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { - case (BT_IMAGEFLOAT): - return imgFloatBuffer != NULL; - case (BT_LABIMAGE): - return LabBuffer != NULL; - case (BT_SINGLEPLANE_FLOAT): - return singlePlaneBuffer.data != NULL; - } - break; - case (ET_OBJECTS): - return bool(objectMap); - } - } - return false; +bool EditBuffer::bufferCreated() +{ + EditSubscriber* subscriber; + + if (dataProvider && (subscriber = dataProvider->getCurrSubscriber())) { + switch (subscriber->getEditingType()) { + case ET_PIPETTE: + switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { + case (BT_IMAGEFLOAT): + return imgFloatBuffer != NULL; + + case (BT_LABIMAGE): + return LabBuffer != NULL; + + case (BT_SINGLEPLANE_FLOAT): + return singlePlaneBuffer.data != NULL; + } + + break; + + case (ET_OBJECTS): + return bool(objectMap); + } + } + + return false; } -int EditBuffer::getObjectID(const Coord& location) { - int id = 0; +int EditBuffer::getObjectID(const Coord& location) +{ + int id = 0; - if (objectMap && location.x>0 && location.y>0 && location.xget_width() && location.yget_height()) { - id = (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); - if (objectMap2) - id |= (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )) << 8; - } - return id-1; + if (objectMap && location.x > 0 && location.y > 0 && location.x < objectMap->get_width() && location.y < objectMap->get_height()) { + id = (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )); + + if (objectMap2) { + id |= (unsigned short)(*( objectMap->get_data() + location.y * objectMap->get_stride() + location.x )) << 8; + } + } + + return id - 1; } -void EditBuffer::getPipetteData(float* v, int x, int y, int squareSize) { - if (ready && dataProvider && dataProvider->getCurrSubscriber()) { - switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { - case (BT_IMAGEFLOAT): - if (imgFloatBuffer) { - imgFloatBuffer->getPipetteData(v[0], v[1], v[2], x, y, squareSize, 0); - return; - } - break; - case (BT_LABIMAGE): - if (LabBuffer) { - LabBuffer->getPipetteData(v[0], v[1], v[2], x, y, squareSize); - return; - } - break; - case (BT_SINGLEPLANE_FLOAT): - if (singlePlaneBuffer.data != NULL) { - singlePlaneBuffer.getPipetteData(v[0], x, y, squareSize, 0); - v[1] = v[2] = -1.f; - return; - } - } - } - v[0] = v[1] = v[2] = -1.f; +void EditBuffer::getPipetteData(float* v, int x, int y, int squareSize) +{ + if (ready && dataProvider && dataProvider->getCurrSubscriber()) { + switch (dataProvider->getCurrSubscriber()->getEditBufferType()) { + case (BT_IMAGEFLOAT): + if (imgFloatBuffer) { + imgFloatBuffer->getPipetteData(v[0], v[1], v[2], x, y, squareSize, 0); + return; + } + + break; + + case (BT_LABIMAGE): + if (LabBuffer) { + LabBuffer->getPipetteData(v[0], v[1], v[2], x, y, squareSize); + return; + } + + break; + + case (BT_SINGLEPLANE_FLOAT): + if (singlePlaneBuffer.data != NULL) { + singlePlaneBuffer.getPipetteData(v[0], x, y, squareSize, 0); + v[1] = v[2] = -1.f; + return; + } + } + } + + v[0] = v[1] = v[2] = -1.f; } } diff --git a/rtengine/editbuffer.h b/rtengine/editbuffer.h index f52373349..ba1cc7e0c 100644 --- a/rtengine/editbuffer.h +++ b/rtengine/editbuffer.h @@ -23,65 +23,94 @@ #include "array2D.h" #include "iimage.h" -namespace rtengine { +namespace rtengine +{ /// @brief Structure that contains information about and pointers to the Edit buffer -class EditBuffer { +class EditBuffer +{ private: - // Used to draw the objects where the color correspond to the object's ID, in order to find the correct object when hovering - Cairo::RefPtr objectMap; - // If more than 254 objects has to be handled, objectMap2 contains the "upper part" of the 16 bit int value. objectMap2 will be NULL otherwise. - Cairo::RefPtr objectMap2; - ObjectMode objectMode; + // Used to draw the objects where the color correspond to the object's ID, in order to find the correct object when hovering + Cairo::RefPtr objectMap; + // If more than 254 objects has to be handled, objectMap2 contains the "upper part" of the 16 bit int value. objectMap2 will be NULL otherwise. + Cairo::RefPtr objectMap2; + ObjectMode objectMode; protected: - // To avoid duplicated information, we points to a EditDataProvider that contains the current EditSubscriber - // instead of pointing to the EditSubscriber directly - ::EditDataProvider* dataProvider; + // To avoid duplicated information, we points to a EditDataProvider that contains the current EditSubscriber + // instead of pointing to the EditSubscriber directly + ::EditDataProvider* dataProvider; - // TODO: Unfortunately, buffer can be of several type, each one representing a floating point image. Maybe we could unify everything one day!? - // Only one of the following pointers will be allocated at a time, if any; "one chunk" allocation - Imagefloat* imgFloatBuffer; - LabImage* LabBuffer; - PlanarWhateverData singlePlaneBuffer; + // TODO: Unfortunately, buffer can be of several type, each one representing a floating point image. Maybe we could unify everything one day!? + // Only one of the following pointers will be allocated at a time, if any; "one chunk" allocation + Imagefloat* imgFloatBuffer; + LabImage* LabBuffer; + PlanarWhateverData singlePlaneBuffer; - bool ready; // flag that indicates if the _pipette_ buffer is ready + bool ready; // flag that indicates if the _pipette_ buffer is ready - void createBuffer(int width, int height); - void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); - void resize(int newWidth, int newHeight); - void flush(); + void createBuffer(int width, int height); + void resize(int newWidth, int newHeight, EditSubscriber* newSubscriber); + void resize(int newWidth, int newHeight); + void flush(); public: - EditBuffer(::EditDataProvider *dataProvider); - ~EditBuffer(); + EditBuffer(::EditDataProvider *dataProvider); + ~EditBuffer(); - /** @brief Getter to know if the pipette buffer is correctly filled */ - bool isReady() { return ready; } + /** @brief Getter to know if the pipette buffer is correctly filled */ + bool isReady() + { + return ready; + } - /** @brief Setter to tell that the pipette buffer is correctly filled - * You have to use this method once the pipette is filled, so it can be read. */ - void setReady() { ready = true; } + /** @brief Setter to tell that the pipette buffer is correctly filled + * You have to use this method once the pipette is filled, so it can be read. */ + void setReady() + { + ready = true; + } - void setObjectMode(ObjectMode newType); - ::EditDataProvider* getDataProvider() { return dataProvider; } - EditUniqueID getEditID(); - Imagefloat* getImgFloatBuffer() { return imgFloatBuffer; } - LabImage* getLabBuffer() { return LabBuffer; } - PlanarWhateverData* getSinglePlaneBuffer() { return &singlePlaneBuffer; } - ObjectMode getObjectMode() { return objectMode; } + void setObjectMode(ObjectMode newType); + ::EditDataProvider* getDataProvider() + { + return dataProvider; + } + EditUniqueID getEditID(); + Imagefloat* getImgFloatBuffer() + { + return imgFloatBuffer; + } + LabImage* getLabBuffer() + { + return LabBuffer; + } + PlanarWhateverData* getSinglePlaneBuffer() + { + return &singlePlaneBuffer; + } + ObjectMode getObjectMode() + { + return objectMode; + } - Cairo::RefPtr &getObjectMap () { return objectMap; } - Cairo::RefPtr &getObjectMap2() { return objectMap2; } + Cairo::RefPtr &getObjectMap () + { + return objectMap; + } + Cairo::RefPtr &getObjectMap2() + { + return objectMap2; + } - // return true if the buffer has been allocated - bool bufferCreated(); + // return true if the buffer has been allocated + bool bufferCreated(); - int getObjectID(const Coord& location); - // get the pipette values - void getPipetteData(float* v, int x, int y, int squareSize); + int getObjectID(const Coord& location); + // get the pipette values + void getPipetteData(float* v, int x, int y, int squareSize); }; } diff --git a/rtengine/ex1simple.cc b/rtengine/ex1simple.cc index 97aecb2cd..0768a97e7 100644 --- a/rtengine/ex1simple.cc +++ b/rtengine/ex1simple.cc @@ -7,7 +7,7 @@ * 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 @@ -17,24 +17,28 @@ * along with RawTherapee. If not, see . */ #include "rtengine.h" -#include +#include //#include #include -class PListener : public rtengine::ProgressListener { - - public: - void setProgressStr (Glib::ustring str) { - std::cout << str << std::endl; - } - void setProgress (double p) { - std::cout << p << std::endl; - } +class PListener : public rtengine::ProgressListener +{ + +public: + void setProgressStr (Glib::ustring str) + { + std::cout << str << std::endl; + } + void setProgress (double p) + { + std::cout << p << std::endl; + } }; -int main (int argc, char* argv[]) { +int main (int argc, char* argv[]) +{ - if (argc<4) { + if (argc < 4) { std::cout << "Usage: rtcmd " << std::endl; exit(1); } @@ -51,7 +55,7 @@ int main (int argc, char* argv[]) { // init rtengine rtengine::init (s); // the settings can be modified later through the "s" pointer without calling any api function - + // Create a listener object. Any class is appropriate that inherits from rtengine::ProgressListener PListener pl; @@ -59,8 +63,11 @@ int main (int argc, char* argv[]) { rtengine::InitialImage* ii; int errorCode; ii = rtengine::InitialImage::load (argv[1], true, errorCode, &pl); - if (!ii) + + if (!ii) { ii = rtengine::InitialImage::load (argv[1], false, errorCode, &pl); + } + if (!ii) { std::cout << "Input file not supported." << std::endl; exit(2); @@ -70,7 +77,7 @@ int main (int argc, char* argv[]) { rtengine::procparams::ProcParams params; params.load (argv[2]); -/* First, simplest scenario. Develope image and save it in a file */ + /* First, simplest scenario. Develope image and save it in a file */ // create a processing job with the loaded image and the current processing parameters rtengine::ProcessingJob* job = ProcessingJob::create (i, params); // process image. The error is given back in errorcode. diff --git a/rtengine/ex2simple.cc b/rtengine/ex2simple.cc index f78c4a967..1a83526e7 100644 --- a/rtengine/ex2simple.cc +++ b/rtengine/ex2simple.cc @@ -7,7 +7,7 @@ * 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 @@ -17,63 +17,71 @@ * along with RawTherapee. If not, see . */ #include "rtengine.h" -#include +#include //#include #include -class PListener : public rtengine::ProgressListener { - - public: - void setProgressStr (Glib::ustring str) { - std::cout << str << std::endl; - } - void setProgress (double p) { - std::cout << p << std::endl; - } +class PListener : public rtengine::ProgressListener +{ + +public: + void setProgressStr (Glib::ustring str) + { + std::cout << str << std::endl; + } + void setProgress (double p) + { + std::cout << p << std::endl; + } }; -class MyPrevImgListener : public rtengine::PreviewImageListener { - +class MyPrevImgListener : public rtengine::PreviewImageListener +{ + IImage8* i; - public: - // this method is called when the staged image processor creates a new image to store the resulting preview image (this does not happen too often) - // usually you just have to store it - void setImage (IImage8* img, double scale, procparams::CropParams cp) { - i = img; +public: + // this method is called when the staged image processor creates a new image to store the resulting preview image (this does not happen too often) + // usually you just have to store it + void setImage (IImage8* img, double scale, procparams::CropParams cp) + { + i = img; + } + // if the staged image processor wants to delete the image that stores the preview image, it calls this method. You have to destroy the image. + void delImage (IImage8* img) + { + if (img) { + // make sure we dont use this image in an other thread + IImage8* temp = i; + i->getMutex().lock (); + i = NULL; + temp->getMutex().unlock (); + // free it + img->free (); } - // if the staged image processor wants to delete the image that stores the preview image, it calls this method. You have to destroy the image. - void delImage (IImage8* img) { - if (img) { - // make sure we dont use this image in an other thread - IImage8* temp = i; - i->getMutex().lock (); - i = NULL; - temp->getMutex().unlock (); - // free it - img->free (); - } - } - // if the preview image changes, this method is called - void imageReady (procparams::CropParams cp) { - // initiate a redraw in the background and return as fast as possible - } - // a possible redraw function: - //void redraw () { - // if (i) { - // i->lock (); - // int w = i->getWidth (); - // int h = i->getHeigt (); - // const char* data = i->getData (); - // ... draw it ... - // i->unlock (); - // } - // } + } + // if the preview image changes, this method is called + void imageReady (procparams::CropParams cp) + { + // initiate a redraw in the background and return as fast as possible + } + // a possible redraw function: + //void redraw () { + // if (i) { + // i->lock (); + // int w = i->getWidth (); + // int h = i->getHeigt (); + // const char* data = i->getData (); + // ... draw it ... + // i->unlock (); + // } + // } }; -int main (int argc, char* argv[]) { +int main (int argc, char* argv[]) +{ - if (argc<4) { + if (argc < 4) { std::cout << "Usage: rtcmd " << std::endl; exit(1); } @@ -90,7 +98,7 @@ int main (int argc, char* argv[]) { // init rtengine rtengine::init (s); // the settings can be modified later through the "s" pointer without calling any api function - + // Create a listener object. Any class is appropriate that inherits from rtengine::ProgressListener PListener pl; @@ -98,14 +106,17 @@ int main (int argc, char* argv[]) { rtengine::InitialImage* ii; int errorCode; ii = rtengine::InitialImage::load (argv[1], true, errorCode, &pl); - if (!ii) + + if (!ii) { ii = rtengine::InitialImage::load (argv[1], false, errorCode, &pl); + } + if (!ii) { std::cout << "Input file not supported." << std::endl; exit(2); } -/* Second scenario. Create a stagedimageprocessor with a preview scale of 1:5 and change few things */ + /* Second scenario. Create a stagedimageprocessor with a preview scale of 1:5 and change few things */ MyPrevImgListener myPrevImgListener; StagedImageProcessor* ipc = StagedImageProcessor::create (ii); @@ -123,16 +134,16 @@ int main (int argc, char* argv[]) { // you have to tell it what has changed. At the first time tell it EvPhotoLoaded so a full processing will be performed rtengine::procparams::ProcParams* params = ipc->beginUpdateParams (); // change this and that... - params->toneCurve.brightness = 1.0; + params->toneCurve.brightness = 1.0; // you can load it, too, from a file: params->load (argv[2]); // finally you have to call this non-blocking method, and the image processing starts in the background. When finished, the preview image listener will be notified ipc->endUpdateParams (rtengine::EvPhotoLoaded); // you can go on with changing of the settings, following the gui actions // now we know that only the brightness has changed compared to the previous settings, to only a part of the processing has to be repeated params = ipc->beginUpdateParams (); - params->toneCurve.brightness = 1.2; + params->toneCurve.brightness = 1.2; ipc->endUpdateParams (rtengine::EvBrightness); - + // ... and so on. If you dont need it any more, you can destroy it (make sure that no processing is happening when you destroy it!) StagedImageProcessor::destroy (ipc); } diff --git a/rtengine/expo_before_b.cc b/rtengine/expo_before_b.cc index 5c86fd786..0854647c5 100644 --- a/rtengine/expo_before_b.cc +++ b/rtengine/expo_before_b.cc @@ -1,34 +1,34 @@ //////////////////////////////////////////////////////////////// // -// //exposure correction before interpolation +// //exposure correction before interpolation // // code dated: December 27, 2010 // -// Expo_before.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// Expo_before.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// -// Jacques Desmis -// use fast-demo(provisional) from Emil Martinec -// inspired from work Guillermo Luijk and Manuel LLorens(Perfectraw) -// Ingo Weyrich (2014-07-07) -// optimized the highlight protection case -// needs 2*width*height*sizeof(float) byte less memory than before -// needs about 60% less processing time than before +// Jacques Desmis +// use fast-demo(provisional) from Emil Martinec +// inspired from work Guillermo Luijk and Manuel LLorens(Perfectraw) +// Ingo Weyrich (2014-07-07) +// optimized the highlight protection case +// needs 2*width*height*sizeof(float) byte less memory than before +// needs about 60% less processing time than before // // This function uses parameters: // exposure (linear): 2^(-8..0..8): currently 0.5 +3 @@ -39,115 +39,133 @@ #include "mytime.h" #include "rt_math.h" -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; -void RawImageSource::processRawWhitepoint(float expos, float preser) { - MyTime t1e,t2e; - if (settings->verbose) - t1e.set(); - - int width=W, height=H; +void RawImageSource::processRawWhitepoint(float expos, float preser) +{ + MyTime t1e, t2e; + + if (settings->verbose) { + t1e.set(); + } + + int width = W, height = H; // exposure correction inspired from G.Luijk - for (int c=0; c<4; c++) - chmax[c] *= expos; + for (int c = 0; c < 4; c++) { + chmax[c] *= expos; + } - if (fabs(preser)<0.001f) { + if (fabs(preser) < 0.001f) { // No highlight protection - simple mutiplication - if (ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS) - #pragma omp parallel for - for (int row=0;rowgetSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) + #pragma omp parallel for + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + rawData[row][col] *= expos; + } + else + #pragma omp parallel for + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + rawData[row][col * 3] *= expos; + rawData[row][col * 3 + 1] *= expos; + rawData[row][col * 3 + 2] *= expos; + } } else { - if (ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS) { - // Demosaic to allow calculation of luminosity. - if(ri->getSensorType()==ST_BAYER) - fast_demosaic (0,0,W,H); - else - fast_xtrans_interpolate(); + if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) { + // Demosaic to allow calculation of luminosity. + if(ri->getSensorType() == ST_BAYER) { + fast_demosaic (0, 0, W, H); + } else { + fast_xtrans_interpolate(); + } } - + // Find maximum to adjust LUTs. New float engines clips only at the very end float maxValFloat = 0.f; -#pragma omp parallel -{ - float maxValFloatThr = 0.f; - if (ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS) -#pragma omp for schedule(dynamic,16) nowait - for(int row=0;rowmaxValFloatThr) - maxValFloatThr = rawData[row][col]; - } - else -#pragma omp for schedule(dynamic,16) nowait - for(int row=0;rowmaxValFloatThr) - maxValFloatThr = rawData[row][col*3+c]; + #pragma omp parallel + { + float maxValFloatThr = 0.f; + + if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) + #pragma omp for schedule(dynamic,16) nowait + for(int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + if (rawData[row][col] > maxValFloatThr) { + maxValFloatThr = rawData[row][col]; + } + } + else + #pragma omp for schedule(dynamic,16) nowait + for(int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + for (int c = 0; c < 3; c++) + if (rawData[row][col * 3 + c] > maxValFloatThr) { + maxValFloatThr = rawData[row][col * 3 + c]; + } + } + + #pragma omp critical + { + if(maxValFloatThr > maxValFloat) { + maxValFloat = maxValFloatThr; } + } + } -#pragma omp critical -{ - if(maxValFloatThr > maxValFloat) - maxValFloat = maxValFloatThr; -} -} - - // Exposure correction with highlight preservation - int maxVal = maxValFloat; - LUTf lut(maxVal+1); + // Exposure correction with highlight preservation + int maxVal = maxValFloat; + LUTf lut(maxVal + 1); float K; - if(expos>1){ + + if(expos > 1) { // Positive exposure - K = (float) maxVal / expos*exp(-preser*log(2.0)); - for (int j=max(1,(int)K);j<=maxVal;j++) - lut[(int)j]=(((float)maxVal-K*expos)/((float)maxVal-K)*(j-maxVal)+(float) maxVal) / j; + K = (float) maxVal / expos * exp(-preser * log(2.0)); + + for (int j = max(1, (int)K); j <= maxVal; j++) { + lut[(int)j] = (((float)maxVal - K * expos) / ((float)maxVal - K) * (j - maxVal) + (float) maxVal) / j; + } } else { // Negative exposure - float EV=log(expos)/log(2.0); // Convert exp. linear to EV + float EV = log(expos) / log(2.0); // Convert exp. linear to EV K = (float)maxVal * exp(-preser * log(2.0)); - - for (int j=0;j<=maxVal;j++) - lut[(int)j] = exp(EV*((float)maxVal-j) / ((float)maxVal-K) * log(2.0)); - } - if (ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS) - #pragma omp parallel for schedule(dynamic,16) - for(int row=0;rowgetSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) + #pragma omp parallel for schedule(dynamic,16) + for(int row = 0; row < height; row++) + for(int col = 0; col < width; col++) { + float lumi = 0.299f * red[row][col] + 0.587f * green[row][col] + 0.114f * blue[row][col]; + rawData[row][col] *= lumi < K ? expos : lut[lumi]; + } + else + #pragma omp parallel for + for(int row = 0; row < height; row++) + for(int col = 0; col < width; col++) { + float lumi = 0.299f * rawData[row][col * 3] + 0.587f * rawData[row][col * 3 + 1] + 0.114f * rawData[row][col * 3 + 2]; + float fac = lumi < K ? expos : lut[lumi]; + + for (int c = 0; c < 3; c++) { + rawData[row][col * 3 + c] *= fac; + } + } + } - if (settings->verbose) { - t2e.set(); - printf("Exposure before %d usec\n", t2e.etime(t1e)); - } - + + if (settings->verbose) { + t2e.set(); + printf("Exposure before %d usec\n", t2e.etime(t1e)); + } + } } //namespace diff --git a/rtengine/fast_demo.cc b/rtengine/fast_demo.cc index 7654d3586..d5bca20b9 100644 --- a/rtengine/fast_demo.cc +++ b/rtengine/fast_demo.cc @@ -1,24 +1,24 @@ //////////////////////////////////////////////////////////////// // -// Fast demosaicing algorythm +// Fast demosaicing algorythm // -// copyright (c) 2008-2010 Emil Martinec +// copyright (c) 2008-2010 Emil Martinec // // // code dated: August 26, 2010 // -// fast_demo.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// fast_demo.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -31,7 +31,7 @@ using namespace std; using namespace rtengine; -#define TS 224 +#define TS 224 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* @@ -39,9 +39,9 @@ LUTf RawImageSource::initInvGrad() { LUTf invGrad (0x10000); - //set up directional weight function - for (int i=0; i<0x10000; i++) - invGrad[i] = 1.0/SQR(1.0+i); + //set up directional weight function + for (int i=0; i<0x10000; i++) + invGrad[i] = 1.0/SQR(1.0+i); return invGrad; } @@ -52,383 +52,444 @@ LUTf RawImageSource::initInvGrad() #endif //LUTf RawImageSource::invGrad = RawImageSource::initInvGrad(); -SSEFUNCTION void RawImageSource::fast_demosaic(int winx, int winy, int winw, int winh) { +SSEFUNCTION void RawImageSource::fast_demosaic(int winx, int winy, int winw, int winh) +{ - double progress = 0.0; - const bool plistenerActive = plistener; + double progress = 0.0; + const bool plistenerActive = plistener; - //int winx=0, winy=0; - //int winw=W, winh=H; - - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast])); - plistener->setProgress (progress); - } - + //int winx=0, winy=0; + //int winw=W, winh=H; - const int bord=5; - - float clip_pt = 4*65535*initialGain; - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast])); + plistener->setProgress (progress); + } + + + const int bord = 5; + + float clip_pt = 4 * 65535 * initialGain; + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - - char (*buffer); - float (*greentile); - float (*redtile); - float (*bluetile); + { + + char (*buffer); + float (*greentile); + float (*redtile); + float (*bluetile); #define CLF 1 - // assign working space - buffer = (char *) calloc(3*sizeof(float)*TS*TS + 3*CLF*64 + 63,1); - char *data; - data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); + // assign working space + buffer = (char *) calloc(3 * sizeof(float) * TS * TS + 3 * CLF * 64 + 63, 1); + char *data; + data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); - greentile = (float (*)) data; //pointers to array - redtile = (float (*)) ((char*)greentile + sizeof(float)*TS*TS + CLF*64); - bluetile = (float (*)) ((char*)redtile + sizeof(float)*TS*TS + CLF*64); + greentile = (float (*)) data; //pointers to array + redtile = (float (*)) ((char*)greentile + sizeof(float) * TS * TS + CLF * 64); + bluetile = (float (*)) ((char*)redtile + sizeof(float) * TS * TS + CLF * 64); #ifdef _OPENMP -#pragma omp sections + #pragma omp sections #endif -{ + { #ifdef _OPENMP -#pragma omp section + #pragma omp section #endif -{ + { - //first, interpolate borders using bilinear - for (int i=0; isetProgress(progress); - } -} - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - int progressCounter = 0; - const double progressInc = 16.0*(1.0-progress)/((H*W)/((TS-4)*(TS-4))); + { + if(plistenerActive) { + progress += 0.1; + plistener->setProgress(progress); + } + } + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + int progressCounter = 0; + const double progressInc = 16.0 * (1.0 - progress) / ((H * W) / ((TS - 4) * (TS - 4))); #ifdef _OPENMP -#pragma omp for nowait + #pragma omp for nowait #endif - for (int top=bord-2; top < H-bord+2; top += TS-(4)) - for (int left=bord-2; left < W-bord+2; left += TS-(4)) { - int bottom = min(top+TS, H-bord+2); - int right = min(left+TS, W-bord+2); + + for (int top = bord - 2; top < H - bord + 2; top += TS - (4)) + for (int left = bord - 2; left < W - bord + 2; left += TS - (4)) { + int bottom = min(top + TS, H - bord + 2); + int right = min(left + TS, W - bord + 2); #ifdef __SSE2__ - int j,cc; - __m128 wtuv, wtdv, wtlv, wtrv; - __m128 greenv,tempv,absv,abs2v; - __m128 onev = _mm_set1_ps( 1.0f ); - __m128 c16v = _mm_set1_ps( 16.0f ); - __m128 fourv = _mm_set1_ps( 4.0f ); - vmask selmask; - vmask andmask = _mm_set_epi32( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff ); - if(FC(top,left) == 1) - selmask = _mm_set_epi32( 0, 0xffffffff, 0, 0xffffffff ); - else - selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 ); + int j, cc; + __m128 wtuv, wtdv, wtlv, wtrv; + __m128 greenv, tempv, absv, abs2v; + __m128 onev = _mm_set1_ps( 1.0f ); + __m128 c16v = _mm_set1_ps( 16.0f ); + __m128 fourv = _mm_set1_ps( 4.0f ); + vmask selmask; + vmask andmask = _mm_set_epi32( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff ); + + if(FC(top, left) == 1) { + selmask = _mm_set_epi32( 0, 0xffffffff, 0, 0xffffffff ); + } else { + selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 ); + } + #endif - // interpolate G using gradient weights - for (int i=top,rr=0; i< bottom; i++,rr++) { - float wtu, wtd, wtl, wtr; + + // interpolate G using gradient weights + for (int i = top, rr = 0; i < bottom; i++, rr++) { + float wtu, wtd, wtl, wtr; #ifdef __SSE2__ - selmask = (vmask)_mm_andnot_ps( (__m128)selmask, (__m128)andmask); + selmask = (vmask)_mm_andnot_ps( (__m128)selmask, (__m128)andmask); - for (j=left,cc=0; j < right-3; j+=4,cc+=4) { - tempv = LVFU(rawData[i][j]); - absv = vabsf(LVFU(rawData[i-1][j])-LVFU(rawData[i+1][j])); - wtuv = INVGRADV(absv+vabsf(tempv-LVFU(rawData[i-2][j]))+vabsf(LVFU(rawData[i-1][j])-LVFU(rawData[i-3][j]))); - wtdv = INVGRADV(absv+vabsf(tempv-LVFU(rawData[i+2][j]))+vabsf(LVFU(rawData[i+1][j])-LVFU(rawData[i+3][j]))); - abs2v = vabsf(LVFU(rawData[i][j-1])-LVFU(rawData[i][j+1])); - wtlv = INVGRADV(abs2v+vabsf(tempv-LVFU(rawData[i][j-2]))+vabsf(LVFU(rawData[i][j-1])-LVFU(rawData[i][j-3]))); - wtrv = INVGRADV(abs2v+vabsf(tempv-LVFU(rawData[i][j+2]))+vabsf(LVFU(rawData[i][j+1])-LVFU(rawData[i][j+3]))); - greenv = (wtuv*LVFU(rawData[i-1][j])+wtdv*LVFU(rawData[i+1][j])+wtlv*LVFU(rawData[i][j-1])+wtrv*LVFU(rawData[i][j+1])) / (wtuv+wtdv+wtlv+wtrv); - _mm_store_ps(&greentile[rr*TS+cc],vself(selmask, greenv, tempv)); - _mm_store_ps(&redtile[rr*TS+cc],tempv); - _mm_store_ps(&bluetile[rr*TS+cc],tempv); - } - for (; j < right; j++,cc++) { - - if (FC(i,j)==1) { - greentile[rr*TS+cc] = rawData[i][j]; - - } else { - //compute directional weights using image gradients - wtu=INVGRAD((abs(rawData[i+1][j]-rawData[i-1][j])+abs(rawData[i][j]-rawData[i-2][j])+abs(rawData[i-1][j]-rawData[i-3][j]))); - wtd=INVGRAD((abs(rawData[i-1][j]-rawData[i+1][j])+abs(rawData[i][j]-rawData[i+2][j])+abs(rawData[i+1][j]-rawData[i+3][j]))); - wtl=INVGRAD((abs(rawData[i][j+1]-rawData[i][j-1])+abs(rawData[i][j]-rawData[i][j-2])+abs(rawData[i][j-1]-rawData[i][j-3]))); - wtr=INVGRAD((abs(rawData[i][j-1]-rawData[i][j+1])+abs(rawData[i][j]-rawData[i][j+2])+abs(rawData[i][j+1]-rawData[i][j+3]))); + for (j = left, cc = 0; j < right - 3; j += 4, cc += 4) { + tempv = LVFU(rawData[i][j]); + absv = vabsf(LVFU(rawData[i - 1][j]) - LVFU(rawData[i + 1][j])); + wtuv = INVGRADV(absv + vabsf(tempv - LVFU(rawData[i - 2][j])) + vabsf(LVFU(rawData[i - 1][j]) - LVFU(rawData[i - 3][j]))); + wtdv = INVGRADV(absv + vabsf(tempv - LVFU(rawData[i + 2][j])) + vabsf(LVFU(rawData[i + 1][j]) - LVFU(rawData[i + 3][j]))); + abs2v = vabsf(LVFU(rawData[i][j - 1]) - LVFU(rawData[i][j + 1])); + wtlv = INVGRADV(abs2v + vabsf(tempv - LVFU(rawData[i][j - 2])) + vabsf(LVFU(rawData[i][j - 1]) - LVFU(rawData[i][j - 3]))); + wtrv = INVGRADV(abs2v + vabsf(tempv - LVFU(rawData[i][j + 2])) + vabsf(LVFU(rawData[i][j + 1]) - LVFU(rawData[i][j + 3]))); + greenv = (wtuv * LVFU(rawData[i - 1][j]) + wtdv * LVFU(rawData[i + 1][j]) + wtlv * LVFU(rawData[i][j - 1]) + wtrv * LVFU(rawData[i][j + 1])) / (wtuv + wtdv + wtlv + wtrv); + _mm_store_ps(&greentile[rr * TS + cc], vself(selmask, greenv, tempv)); + _mm_store_ps(&redtile[rr * TS + cc], tempv); + _mm_store_ps(&bluetile[rr * TS + cc], tempv); + } + + for (; j < right; j++, cc++) { + + if (FC(i, j) == 1) { + greentile[rr * TS + cc] = rawData[i][j]; + + } else { + //compute directional weights using image gradients + wtu = INVGRAD((abs(rawData[i + 1][j] - rawData[i - 1][j]) + abs(rawData[i][j] - rawData[i - 2][j]) + abs(rawData[i - 1][j] - rawData[i - 3][j]))); + wtd = INVGRAD((abs(rawData[i - 1][j] - rawData[i + 1][j]) + abs(rawData[i][j] - rawData[i + 2][j]) + abs(rawData[i + 1][j] - rawData[i + 3][j]))); + wtl = INVGRAD((abs(rawData[i][j + 1] - rawData[i][j - 1]) + abs(rawData[i][j] - rawData[i][j - 2]) + abs(rawData[i][j - 1] - rawData[i][j - 3]))); + wtr = INVGRAD((abs(rawData[i][j - 1] - rawData[i][j + 1]) + abs(rawData[i][j] - rawData[i][j + 2]) + abs(rawData[i][j + 1] - rawData[i][j + 3]))); + + //store in rgb array the interpolated G value at R/B grid points using directional weighted average + greentile[rr * TS + cc] = (wtu * rawData[i - 1][j] + wtd * rawData[i + 1][j] + wtl * rawData[i][j - 1] + wtr * rawData[i][j + 1]) / (wtu + wtd + wtl + wtr); + } + + redtile[rr * TS + cc] = rawData[i][j]; + bluetile[rr * TS + cc] = rawData[i][j]; + } - //store in rgb array the interpolated G value at R/B grid points using directional weighted average - greentile[rr*TS+cc]=(wtu*rawData[i-1][j]+wtd*rawData[i+1][j]+wtl*rawData[i][j-1]+wtr*rawData[i][j+1]) / (wtu+wtd+wtl+wtr); - } - redtile[rr*TS+cc] = rawData[i][j]; - bluetile[rr*TS+cc] = rawData[i][j]; - } - #else - for (int j=left,cc=0; j < right; j++,cc++) { - if (FC(i,j)==1) { - greentile[rr*TS+cc] = rawData[i][j]; - } else { - //compute directional weights using image gradients - wtu=INVGRAD((abs(rawData[i+1][j]-rawData[i-1][j])+abs(rawData[i][j]-rawData[i-2][j])+abs(rawData[i-1][j]-rawData[i-3][j]))); - wtd=INVGRAD((abs(rawData[i-1][j]-rawData[i+1][j])+abs(rawData[i][j]-rawData[i+2][j])+abs(rawData[i+1][j]-rawData[i+3][j]))); - wtl=INVGRAD((abs(rawData[i][j+1]-rawData[i][j-1])+abs(rawData[i][j]-rawData[i][j-2])+abs(rawData[i][j-1]-rawData[i][j-3]))); - wtr=INVGRAD((abs(rawData[i][j-1]-rawData[i][j+1])+abs(rawData[i][j]-rawData[i][j+2])+abs(rawData[i][j+1]-rawData[i][j+3]))); - //store in rgb array the interpolated G value at R/B grid points using directional weighted average - greentile[rr*TS+cc]=(wtu*rawData[i-1][j]+wtd*rawData[i+1][j]+wtl*rawData[i][j-1]+wtr*rawData[i][j+1]) / (wtu+wtd+wtl+wtr); - } - redtile[rr*TS+cc] = rawData[i][j]; - bluetile[rr*TS+cc] = rawData[i][j]; - } + for (int j = left, cc = 0; j < right; j++, cc++) { + if (FC(i, j) == 1) { + greentile[rr * TS + cc] = rawData[i][j]; + } else { + //compute directional weights using image gradients + wtu = INVGRAD((abs(rawData[i + 1][j] - rawData[i - 1][j]) + abs(rawData[i][j] - rawData[i - 2][j]) + abs(rawData[i - 1][j] - rawData[i - 3][j]))); + wtd = INVGRAD((abs(rawData[i - 1][j] - rawData[i + 1][j]) + abs(rawData[i][j] - rawData[i + 2][j]) + abs(rawData[i + 1][j] - rawData[i + 3][j]))); + wtl = INVGRAD((abs(rawData[i][j + 1] - rawData[i][j - 1]) + abs(rawData[i][j] - rawData[i][j - 2]) + abs(rawData[i][j - 1] - rawData[i][j - 3]))); + wtr = INVGRAD((abs(rawData[i][j - 1] - rawData[i][j + 1]) + abs(rawData[i][j] - rawData[i][j + 2]) + abs(rawData[i][j + 1] - rawData[i][j + 3]))); + + //store in rgb array the interpolated G value at R/B grid points using directional weighted average + greentile[rr * TS + cc] = (wtu * rawData[i - 1][j] + wtd * rawData[i + 1][j] + wtl * rawData[i][j - 1] + wtr * rawData[i][j + 1]) / (wtu + wtd + wtl + wtr); + } + + redtile[rr * TS + cc] = rawData[i][j]; + bluetile[rr * TS + cc] = rawData[i][j]; + } + #endif - } + } #ifdef __SSE2__ - __m128 zd25v = _mm_set1_ps(0.25f); - __m128 clip_ptv = _mm_set1_ps( clip_pt ); -#endif - for (int i=top+1,rr=1; i< bottom-1; i++,rr++) { - if (FC(i,left+(FC(i,2)&1)+1)==0) + __m128 zd25v = _mm_set1_ps(0.25f); + __m128 clip_ptv = _mm_set1_ps( clip_pt ); +#endif + + for (int i = top + 1, rr = 1; i < bottom - 1; i++, rr++) { + if (FC(i, left + (FC(i, 2) & 1) + 1) == 0) #ifdef __SSE2__ - for (int j=left+1,cc=1; j < right-1; j+=4,cc+=4) { - //interpolate B/R colors at R/B sites - _mm_storeu_ps(&bluetile[rr*TS+cc], LVFU(greentile[rr*TS+cc]) - zd25v*((LVFU(greentile[(rr-1)*TS+(cc-1)])+LVFU(greentile[(rr-1)*TS+(cc+1)])+LVFU(greentile[(rr+1)*TS+cc+1])+LVFU(greentile[(rr+1)*TS+cc-1])) - - _mm_min_ps(clip_ptv,LVFU(rawData[i-1][j-1])+LVFU(rawData[i-1][j+1])+LVFU(rawData[i+1][j+1])+LVFU(rawData[i+1][j-1])))); - } + for (int j = left + 1, cc = 1; j < right - 1; j += 4, cc += 4) { + //interpolate B/R colors at R/B sites + _mm_storeu_ps(&bluetile[rr * TS + cc], LVFU(greentile[rr * TS + cc]) - zd25v * ((LVFU(greentile[(rr - 1)*TS + (cc - 1)]) + LVFU(greentile[(rr - 1)*TS + (cc + 1)]) + LVFU(greentile[(rr + 1)*TS + cc + 1]) + LVFU(greentile[(rr + 1)*TS + cc - 1])) - + _mm_min_ps(clip_ptv, LVFU(rawData[i - 1][j - 1]) + LVFU(rawData[i - 1][j + 1]) + LVFU(rawData[i + 1][j + 1]) + LVFU(rawData[i + 1][j - 1])))); + } + #else - for (int cc=(FC(i,2)&1)+1, j=left+cc; j < right-1; j+=2, cc+=2) { - //interpolate B/R colors at R/B sites - bluetile[rr*TS+cc] = greentile[rr*TS+cc] - 0.25f*((greentile[(rr-1)*TS+(cc-1)]+greentile[(rr-1)*TS+(cc+1)]+greentile[(rr+1)*TS+cc+1]+greentile[(rr+1)*TS+cc-1]) - - min(clip_pt,rawData[i-1][j-1]+rawData[i-1][j+1]+rawData[i+1][j+1]+rawData[i+1][j-1])); - } + + for (int cc = (FC(i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) { + //interpolate B/R colors at R/B sites + bluetile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + (cc - 1)] + greentile[(rr - 1) * TS + (cc + 1)] + greentile[(rr + 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc - 1]) - + min(clip_pt, rawData[i - 1][j - 1] + rawData[i - 1][j + 1] + rawData[i + 1][j + 1] + rawData[i + 1][j - 1])); + } + #endif - else + else #ifdef __SSE2__ - for (int j=left+1,cc=1; j < right-1; j+=4,cc+=4) { - //interpolate B/R colors at R/B sites - _mm_storeu_ps(&redtile[rr*TS+cc], LVFU(greentile[rr*TS+cc]) - zd25v*((LVFU(greentile[(rr-1)*TS+cc-1])+LVFU(greentile[(rr-1)*TS+cc+1])+LVFU(greentile[(rr+1)*TS+cc+1])+LVFU(greentile[(rr+1)*TS+cc-1])) - - _mm_min_ps(clip_ptv,LVFU(rawData[i-1][j-1])+LVFU(rawData[i-1][j+1])+LVFU(rawData[i+1][j+1])+LVFU(rawData[i+1][j-1])))); - } + for (int j = left + 1, cc = 1; j < right - 1; j += 4, cc += 4) { + //interpolate B/R colors at R/B sites + _mm_storeu_ps(&redtile[rr * TS + cc], LVFU(greentile[rr * TS + cc]) - zd25v * ((LVFU(greentile[(rr - 1)*TS + cc - 1]) + LVFU(greentile[(rr - 1)*TS + cc + 1]) + LVFU(greentile[(rr + 1)*TS + cc + 1]) + LVFU(greentile[(rr + 1)*TS + cc - 1])) - + _mm_min_ps(clip_ptv, LVFU(rawData[i - 1][j - 1]) + LVFU(rawData[i - 1][j + 1]) + LVFU(rawData[i + 1][j + 1]) + LVFU(rawData[i + 1][j - 1])))); + } + #else - for (int cc=(FC(i,2)&1)+1, j=left+cc; j < right-1; j+=2,cc+=2) { - //interpolate B/R colors at R/B sites - redtile[rr*TS+cc] = greentile[rr*TS+cc] - 0.25f*((greentile[(rr-1)*TS+cc-1]+greentile[(rr-1)*TS+cc+1]+greentile[(rr+1)*TS+cc+1]+greentile[(rr+1)*TS+cc-1]) - - min(clip_pt,rawData[i-1][j-1]+rawData[i-1][j+1]+rawData[i+1][j+1]+rawData[i+1][j-1])); - } + + for (int cc = (FC(i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) { + //interpolate B/R colors at R/B sites + redtile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc - 1] + greentile[(rr - 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc - 1]) - + min(clip_pt, rawData[i - 1][j - 1] + rawData[i - 1][j + 1] + rawData[i + 1][j + 1] + rawData[i + 1][j - 1])); + } + #endif - } + } #ifdef __SSE2__ - __m128 temp1v,temp2v,greensumv; - selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 ); + __m128 temp1v, temp2v, greensumv; + selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 ); #endif - // interpolate R/B using color differences - for (int i=top+2, rr=2; i< bottom-2; i++,rr++) { + // interpolate R/B using color differences + for (int i = top + 2, rr = 2; i < bottom - 2; i++, rr++) { #ifdef __SSE2__ - for (int cc=2+(FC(i,2)&1), j=left+cc; j < right-2; j+=4,cc+=4) { - // no need to take care about the borders of the tile. There's enough free space. - //interpolate R and B colors at G sites - greenv = LVFU(greentile[rr*TS+cc]); - greensumv = LVFU(greentile[(rr-1)*TS+cc]) + LVFU(greentile[(rr+1)*TS+cc]) + LVFU(greentile[rr*TS+cc-1]) + LVFU(greentile[rr*TS+cc+1]); - - temp1v = LVFU(redtile[rr*TS+cc]); - temp2v = greenv - zd25v*(greensumv - LVFU(redtile[(rr-1)*TS+cc]) - LVFU(redtile[(rr+1)*TS+cc]) - LVFU(redtile[rr*TS+cc-1]) - LVFU(redtile[rr*TS+cc+1])); -// temp2v = greenv - zd25v*((LVFU(greentile[(rr-1)*TS+cc])-LVFU(redtile[(rr-1)*TS+cc]))+(LVFU(greentile[(rr+1)*TS+cc])-LVFU(redtile[(rr+1)*TS+cc]))+ -// (LVFU(greentile[rr*TS+cc-1])-LVFU(redtile[rr*TS+cc-1]))+(LVFU(greentile[rr*TS+cc+1])-LVFU(redtile[rr*TS+cc+1]))); - _mm_storeu_ps( &redtile[rr*TS+cc], vself(selmask, temp1v, temp2v)); - - temp1v = LVFU(bluetile[rr*TS+cc]); + for (int cc = 2 + (FC(i, 2) & 1), j = left + cc; j < right - 2; j += 4, cc += 4) { + // no need to take care about the borders of the tile. There's enough free space. + //interpolate R and B colors at G sites + greenv = LVFU(greentile[rr * TS + cc]); + greensumv = LVFU(greentile[(rr - 1) * TS + cc]) + LVFU(greentile[(rr + 1) * TS + cc]) + LVFU(greentile[rr * TS + cc - 1]) + LVFU(greentile[rr * TS + cc + 1]); - temp2v = greenv - zd25v*(greensumv - LVFU(bluetile[(rr-1)*TS+cc]) - LVFU(bluetile[(rr+1)*TS+cc]) - LVFU(bluetile[rr*TS+cc-1]) - LVFU(bluetile[rr*TS+cc+1])); + temp1v = LVFU(redtile[rr * TS + cc]); + temp2v = greenv - zd25v * (greensumv - LVFU(redtile[(rr - 1) * TS + cc]) - LVFU(redtile[(rr + 1) * TS + cc]) - LVFU(redtile[rr * TS + cc - 1]) - LVFU(redtile[rr * TS + cc + 1])); + +// temp2v = greenv - zd25v*((LVFU(greentile[(rr-1)*TS+cc])-LVFU(redtile[(rr-1)*TS+cc]))+(LVFU(greentile[(rr+1)*TS+cc])-LVFU(redtile[(rr+1)*TS+cc]))+ +// (LVFU(greentile[rr*TS+cc-1])-LVFU(redtile[rr*TS+cc-1]))+(LVFU(greentile[rr*TS+cc+1])-LVFU(redtile[rr*TS+cc+1]))); + _mm_storeu_ps( &redtile[rr * TS + cc], vself(selmask, temp1v, temp2v)); + + temp1v = LVFU(bluetile[rr * TS + cc]); + + temp2v = greenv - zd25v * (greensumv - LVFU(bluetile[(rr - 1) * TS + cc]) - LVFU(bluetile[(rr + 1) * TS + cc]) - LVFU(bluetile[rr * TS + cc - 1]) - LVFU(bluetile[rr * TS + cc + 1])); + +// temp2v = greenv - zd25v*((LVFU(greentile[(rr-1)*TS+cc])-LVFU(bluetile[(rr-1)*TS+cc]))+(LVFU(greentile[(rr+1)*TS+cc])-LVFU(bluetile[(rr+1)*TS+cc]))+ +// (LVFU(greentile[rr*TS+cc-1])-LVFU(bluetile[rr*TS+cc-1]))+(LVFU(greentile[rr*TS+cc+1])-LVFU(bluetile[rr*TS+cc+1]))); + _mm_storeu_ps( &bluetile[rr * TS + cc], vself(selmask, temp1v, temp2v)); + } -// temp2v = greenv - zd25v*((LVFU(greentile[(rr-1)*TS+cc])-LVFU(bluetile[(rr-1)*TS+cc]))+(LVFU(greentile[(rr+1)*TS+cc])-LVFU(bluetile[(rr+1)*TS+cc]))+ -// (LVFU(greentile[rr*TS+cc-1])-LVFU(bluetile[rr*TS+cc-1]))+(LVFU(greentile[rr*TS+cc+1])-LVFU(bluetile[rr*TS+cc+1]))); - _mm_storeu_ps( &bluetile[rr*TS+cc], vself(selmask, temp1v, temp2v)); - } #else - for (int cc=2+(FC(i,2)&1), j=left+cc; j < right-2; j+=2,cc+=2) { - //interpolate R and B colors at G sites - redtile[rr*TS+cc] = greentile[rr*TS+cc] - 0.25f*((greentile[(rr-1)*TS+cc]-redtile[(rr-1)*TS+cc])+(greentile[(rr+1)*TS+cc]-redtile[(rr+1)*TS+cc])+ - (greentile[rr*TS+cc-1]-redtile[rr*TS+cc-1])+(greentile[rr*TS+cc+1]-redtile[rr*TS+cc+1])); - bluetile[rr*TS+cc] = greentile[rr*TS+cc] - 0.25f*((greentile[(rr-1)*TS+cc]-bluetile[(rr-1)*TS+cc])+(greentile[(rr+1)*TS+cc]-bluetile[(rr+1)*TS+cc])+ - (greentile[rr*TS+cc-1]-bluetile[rr*TS+cc-1])+(greentile[rr*TS+cc+1]-bluetile[rr*TS+cc+1])); - } + + for (int cc = 2 + (FC(i, 2) & 1), j = left + cc; j < right - 2; j += 2, cc += 2) { + //interpolate R and B colors at G sites + redtile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc] - redtile[(rr - 1) * TS + cc]) + (greentile[(rr + 1) * TS + cc] - redtile[(rr + 1) * TS + cc]) + + (greentile[rr * TS + cc - 1] - redtile[rr * TS + cc - 1]) + (greentile[rr * TS + cc + 1] - redtile[rr * TS + cc + 1])); + bluetile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc] - bluetile[(rr - 1) * TS + cc]) + (greentile[(rr + 1) * TS + cc] - bluetile[(rr + 1) * TS + cc]) + + (greentile[rr * TS + cc - 1] - bluetile[rr * TS + cc - 1]) + (greentile[rr * TS + cc + 1] - bluetile[rr * TS + cc + 1])); + } + #endif - } + } - for (int i=top+2, rr=2; i< bottom-2; i++,rr++) { + for (int i = top + 2, rr = 2; i < bottom - 2; i++, rr++) { #ifdef __SSE2__ - for (j=left+2, cc=2; j< right-5; j+=4,cc+=4) { - _mm_storeu_ps(&red[i][j], LVFU(redtile[rr*TS+cc])); - _mm_storeu_ps(&green[i][j], LVFU(greentile[rr*TS+cc])); - _mm_storeu_ps(&blue[i][j], LVFU(bluetile[rr*TS+cc])); - } - for (; j< right-2; j++,cc++) { - red[i][j] = redtile[rr*TS+cc]; - green[i][j] = greentile[rr*TS+cc]; - blue[i][j] = bluetile[rr*TS+cc]; - } -#else - for (int j=left+2, cc=2; j< right-2; j++,cc++) { - red[i][j] = redtile[rr*TS+cc]; - green[i][j] = greentile[rr*TS+cc]; - blue[i][j] = bluetile[rr*TS+cc]; - } -#endif - - } - if(plistenerActive && ((++progressCounter) % 16 == 0)) { + for (j = left + 2, cc = 2; j < right - 5; j += 4, cc += 4) { + _mm_storeu_ps(&red[i][j], LVFU(redtile[rr * TS + cc])); + _mm_storeu_ps(&green[i][j], LVFU(greentile[rr * TS + cc])); + _mm_storeu_ps(&blue[i][j], LVFU(bluetile[rr * TS + cc])); + } + + for (; j < right - 2; j++, cc++) { + red[i][j] = redtile[rr * TS + cc]; + green[i][j] = greentile[rr * TS + cc]; + blue[i][j] = bluetile[rr * TS + cc]; + } + +#else + + for (int j = left + 2, cc = 2; j < right - 2; j++, cc++) { + red[i][j] = redtile[rr * TS + cc]; + green[i][j] = greentile[rr * TS + cc]; + blue[i][j] = bluetile[rr * TS + cc]; + } + +#endif + + + } + + if(plistenerActive && ((++progressCounter) % 16 == 0)) { #ifdef _OPENMP -#pragma omp critical (updateprogress) + #pragma omp critical (updateprogress) #endif -{ - progress += progressInc; - progress = min(1.0,progress); - plistener->setProgress (progress); -} - } - - } - free(buffer); -} // End of parallelization - if(plistenerActive) plistener->setProgress(1.00); - + { + progress += progressInc; + progress = min(1.0, progress); + plistener->setProgress (progress); + } + } + + } + + free(buffer); + } // End of parallelization + + if(plistenerActive) { + plistener->setProgress(1.00); + } + } diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index abc7d64fe..c311361e6 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -7,7 +7,7 @@ * 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 @@ -25,75 +25,97 @@ #include #include "imagedata.h" -namespace rtengine{ +namespace rtengine +{ extern const Settings* settings; // *********************** class ffInfo ************************************** -inline ffInfo& ffInfo::operator =(const ffInfo &o){ - pathname = o.pathname; - maker = o.maker; - model = o.model; - lens = o.lens; - shutter = o.shutter; - focallength = o.focallength; - timestamp = o.timestamp; - if( ri ){ - delete ri; - ri = NULL; - } - return *this; +inline ffInfo& ffInfo::operator =(const ffInfo &o) +{ + pathname = o.pathname; + maker = o.maker; + model = o.model; + lens = o.lens; + shutter = o.shutter; + focallength = o.focallength; + timestamp = o.timestamp; + + if( ri ) { + delete ri; + ri = NULL; + } + + return *this; } bool ffInfo::operator <(const ffInfo &e2) const { - if( this->maker.compare( e2.maker) >=0 ) - return false; - if( this->model.compare( e2.model) >=0 ) - return false; - if( this->lens.compare( e2.lens) >=0 ) - return false; - if( this->focallength >= e2.focallength ) - return false; - if( this->timestamp >= e2.timestamp ) - return false; - return true; + if( this->maker.compare( e2.maker) >= 0 ) { + return false; + } + + if( this->model.compare( e2.model) >= 0 ) { + return false; + } + + if( this->lens.compare( e2.lens) >= 0 ) { + return false; + } + + if( this->focallength >= e2.focallength ) { + return false; + } + + if( this->timestamp >= e2.timestamp ) { + return false; + } + + return true; } std::string ffInfo::key(const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert ) { - std::ostringstream s; - s << mak << " " << mod << " "; - s.width(5); - s << len << " "; - s.precision( 2 ); - s.width(4); - s << focal << "mm F" << apert; - return s.str(); + std::ostringstream s; + s << mak << " " << mod << " "; + s.width(5); + s << len << " "; + s.precision( 2 ); + s.width(4); + s << focal << "mm F" << apert; + return s.str(); } double ffInfo::distance(const std::string &mak, const std::string &mod, const std::string &len, double focallength, double aperture) const { - if( this->maker.compare( mak) != 0 ) - return INFINITY; - if( this->model.compare( mod) != 0 ) - return INFINITY; - if( this->lens.compare( len) != 0 ) - return INFINITY; - double dAperture = 2*(log(this->aperture) - log(aperture))/log(2);//more important for vignette - double dfocallength = (log(this->focallength/100.) - log(focallength/100.))/log(2);//more important for PRNU + if( this->maker.compare( mak) != 0 ) { + return INFINITY; + } - return sqrt( dfocallength*dfocallength + dAperture*dAperture); + if( this->model.compare( mod) != 0 ) { + return INFINITY; + } + + if( this->lens.compare( len) != 0 ) { + return INFINITY; + } + + double dAperture = 2 * (log(this->aperture) - log(aperture)) / log(2); //more important for vignette + double dfocallength = (log(this->focallength / 100.) - log(focallength / 100.)) / log(2); //more important for PRNU + + return sqrt( dfocallength * dfocallength + dAperture * dAperture); } RawImage* ffInfo::getRawImage() { - if(ri) - return ri; - updateRawImage(); + if(ri) { + return ri; + } - return ri; + updateRawImage(); + + return ri; } /* updateRawImage() load into ri the actual pixel data from pathname if there is a single shot @@ -102,68 +124,83 @@ RawImage* ffInfo::getRawImage() */ void ffInfo::updateRawImage() { - typedef unsigned int acc_t; - // averaging of flatfields if more than one is found matching the same key. - // this may not be necessary, as flatfield is further blurred before being applied to the processed image. - if( !pathNames.empty() ){ - std::list::iterator iName = pathNames.begin(); - ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) - if( ri->loadRaw(true)){ - delete ri; - ri=NULL; - }else{ - int H = ri->get_height(); - int W = ri->get_width(); - ri->compress_image(); - int rSize = W*((ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS)?1:3); - acc_t **acc = new acc_t*[H]; - for( int row=0; rowdata[row][col]; - int nFiles = 1; // First file data already loaded + // averaging of flatfields if more than one is found matching the same key. + // this may not be necessary, as flatfield is further blurred before being applied to the processed image. + if( !pathNames.empty() ) { + std::list::iterator iName = pathNames.begin(); + ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. ) - for( iName++; iName != pathNames.end(); iName++){ - RawImage* temp = new RawImage(*iName); - if( !temp->loadRaw(true)){ - temp->compress_image(); //\ TODO would be better working on original, because is temporary - nFiles++; - if( ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS ){ - for( int row=0; rowdata[row][col]; - } - }else{ - for( int row=0; rowdata[row][3*col+0]; - acc[row][3*col+1] += temp->data[row][3*col+1]; - acc[row][3*col+2] += temp->data[row][3*col+2]; - } - } - } - } - delete temp; - } - for (int row = 0; row < H; row++){ - for (int col = 0; col < rSize; col++) - ri->data[row][col] = acc[row][col] / nFiles; - delete [] acc[row]; - } - delete [] acc; - } - }else{ - ri = new RawImage(pathname); - if( ri->loadRaw(true)){ - delete ri; - ri=NULL; - }else { - ri->compress_image(); - } - } + if( ri->loadRaw(true)) { + delete ri; + ri = NULL; + } else { + int H = ri->get_height(); + int W = ri->get_width(); + ri->compress_image(); + int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) ? 1 : 3); + acc_t **acc = new acc_t*[H]; + + for( int row = 0; row < H; row++) { + acc[row] = new acc_t[rSize ]; + } + + // copy first image into accumulators + for (int row = 0; row < H; row++) + for (int col = 0; col < rSize; col++) { + acc[row][col] = ri->data[row][col]; + } + + int nFiles = 1; // First file data already loaded + + for( iName++; iName != pathNames.end(); iName++) { + RawImage* temp = new RawImage(*iName); + + if( !temp->loadRaw(true)) { + temp->compress_image(); //\ TODO would be better working on original, because is temporary + nFiles++; + + if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) { + for( int row = 0; row < H; row++) { + for( int col = 0; col < W; col++) { + acc[row][col] += temp->data[row][col]; + } + } + } else { + for( int row = 0; row < H; row++) { + for( int col = 0; col < W; col++) { + acc[row][3 * col + 0] += temp->data[row][3 * col + 0]; + acc[row][3 * col + 1] += temp->data[row][3 * col + 1]; + acc[row][3 * col + 2] += temp->data[row][3 * col + 2]; + } + } + } + } + + delete temp; + } + + for (int row = 0; row < H; row++) { + for (int col = 0; col < rSize; col++) { + ri->data[row][col] = acc[row][col] / nFiles; + } + + delete [] acc[row]; + } + + delete [] acc; + } + } else { + ri = new RawImage(pathname); + + if( ri->loadRaw(true)) { + delete ri; + ri = NULL; + } else { + ri->compress_image(); + } + } } @@ -173,98 +210,126 @@ void FFManager::init( Glib::ustring pathname ) { std::vector names; Glib::RefPtr dir = Gio::File::create_for_path (pathname); - if( dir && !dir->query_exists()) - return; - safe_build_file_list (dir, names, pathname); - - ffList.clear(); - for (size_t i=0; iquery_exists()) { + return; + } + + safe_build_file_list (dir, names, pathname); + + ffList.clear(); + + for (size_t i = 0; i < names.size(); i++) { + try { addFileInfo(names[i]); - }catch( std::exception& e ){} + } catch( std::exception& e ) {} } + // Where multiple shots exist for same group, move filename to list - for( ffList_t::iterator iter = ffList.begin(); iter != ffList.end();iter++ ){ - ffInfo &i = iter->second; - if( !i.pathNames.empty() && !i.pathname.empty() ){ - i.pathNames.push_back( i.pathname ); - i.pathname.clear(); - } - if( settings->verbose ){ - if( !i.pathname.empty() ) - printf( "%s: %s\n",i.key().c_str(),i.pathname.c_str()); - else{ - printf( "%s: MEAN of \n ",i.key().c_str()); - for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end();iter++ ) - printf( "%s, ", iter->c_str() ); - printf("\n"); - } - } + for( ffList_t::iterator iter = ffList.begin(); iter != ffList.end(); iter++ ) { + ffInfo &i = iter->second; + + if( !i.pathNames.empty() && !i.pathname.empty() ) { + i.pathNames.push_back( i.pathname ); + i.pathname.clear(); + } + + if( settings->verbose ) { + if( !i.pathname.empty() ) { + printf( "%s: %s\n", i.key().c_str(), i.pathname.c_str()); + } else { + printf( "%s: MEAN of \n ", i.key().c_str()); + + for( std::list::iterator iter = i.pathNames.begin(); iter != i.pathNames.end(); iter++ ) { + printf( "%s, ", iter->c_str() ); + } + + printf("\n"); + } + } } + currentPath = pathname; return; } ffInfo *FFManager::addFileInfo(const Glib::ustring &filename, bool pool ) { - Glib::RefPtr file = Gio::File::create_for_path(filename); - if (!file ) - return 0; - if( !file->query_exists()) - return 0; - Glib::RefPtr info = safe_query_file_info(file); - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); - 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( !res ){ - 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++; + Glib::RefPtr file = Gio::File::create_for_path(filename); - 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); - } - } + if (!file ) { + return 0; } + + if( !file->query_exists()) { + return 0; + } + + Glib::RefPtr info = safe_query_file_info(file); + + if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { + size_t lastdot = info->get_name().find_last_of ('.'); + + 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( !res ) { + 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); + } + } + } + return 0; } void FFManager::getStat( int &totFiles, int &totTemplates) { - totFiles=0; - totTemplates=0; - for( ffList_t::iterator iter = ffList.begin(); iter != ffList.end();iter++ ){ - ffInfo &i = iter->second; - if( i.pathname.empty() ){ - totTemplates++; - totFiles += i.pathNames.size(); - }else - totFiles++; + totFiles = 0; + totTemplates = 0; + + for( ffList_t::iterator iter = ffList.begin(); iter != ffList.end(); iter++ ) { + ffInfo &i = iter->second; + + if( i.pathname.empty() ) { + totTemplates++; + totFiles += i.pathNames.size(); + } else { + totFiles++; + } } } @@ -274,56 +339,71 @@ void FFManager::getStat( int &totFiles, int &totTemplates) */ ffInfo* FFManager::find( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t ) { - if( ffList.empty() ) - return 0; - std::string key( ffInfo::key(mak,mod,len,focal,apert) ); - ffList_t::iterator iter = ffList.find( key ); + if( ffList.empty() ) { + return 0; + } + + std::string key( ffInfo::key(mak, mod, len, focal, apert) ); + ffList_t::iterator iter = ffList.find( key ); + + if( iter != ffList.end() ) { + ffList_t::iterator bestMatch = iter; + time_t bestDeltaTime = ABS(iter->second.timestamp - t); + + for(iter++; iter != ffList.end() && !key.compare( iter->second.key() ); iter++ ) { + time_t d = ABS(iter->second.timestamp - t ); + + if( d < bestDeltaTime ) { + bestMatch = iter; + bestDeltaTime = d; + } + } - if( iter != ffList.end() ){ - ffList_t::iterator bestMatch = iter; - time_t bestDeltaTime = ABS(iter->second.timestamp - t); - for(iter++; iter != ffList.end() && !key.compare( iter->second.key() ); iter++ ){ - time_t d = ABS(iter->second.timestamp - t ); - if( d< bestDeltaTime ){ - bestMatch = iter; - bestDeltaTime = d; - } - } return &(bestMatch->second); - }else{ - iter = ffList.begin(); - ffList_t::iterator bestMatch = iter; - double bestD = iter->second.distance( mak, mod, len, focal, apert ); - for( iter++; iter != ffList.end();iter++ ){ - double d = iter->second.distance( mak, mod, len, focal, apert ); - if( d < bestD ){ - bestD = d; - bestMatch = iter; - } - } - return bestD != INFINITY ? &(bestMatch->second) : 0 ; - } + } else { + iter = ffList.begin(); + ffList_t::iterator bestMatch = iter; + double bestD = iter->second.distance( mak, mod, len, focal, apert ); + + for( iter++; iter != ffList.end(); iter++ ) { + double d = iter->second.distance( mak, mod, len, focal, apert ); + + if( d < bestD ) { + bestD = d; + bestMatch = iter; + } + } + + return bestD != INFINITY ? &(bestMatch->second) : 0 ; + } } RawImage* FFManager::searchFlatField( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t ) { - ffInfo *ff = find( mak, mod, len, focal, apert, t ); - if( ff ) - return ff->getRawImage(); - else - return 0; + ffInfo *ff = find( mak, mod, len, focal, apert, t ); + + if( ff ) { + return ff->getRawImage(); + } else { + return 0; + } } RawImage* FFManager::searchFlatField( const Glib::ustring filename ) { - for ( ffList_t::iterator iter = ffList.begin(); iter != ffList.end();iter++ ){ - if( iter->second.pathname.compare( filename )==0 ) - return iter->second.getRawImage(); - } - ffInfo *ff = addFileInfo( filename , false); - if(ff) - return ff->getRawImage(); - return 0; + for ( ffList_t::iterator iter = ffList.begin(); iter != ffList.end(); iter++ ) { + if( iter->second.pathname.compare( filename ) == 0 ) { + return iter->second.getRawImage(); + } + } + + ffInfo *ff = addFileInfo( filename , false); + + if(ff) { + return ff->getRawImage(); + } + + return 0; } diff --git a/rtengine/ffmanager.h b/rtengine/ffmanager.h index 415eaff9b..5f6b2d267 100644 --- a/rtengine/ffmanager.h +++ b/rtengine/ffmanager.h @@ -7,7 +7,7 @@ * 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 @@ -22,66 +22,78 @@ #include #include "rawimage.h" -namespace rtengine{ +namespace rtengine +{ class ffInfo { public: - Glib::ustring pathname; // filename of flat field - std::list pathNames; // other similar dark frames, used for average - std::string maker; ///< manufacturer - std::string model; ///< model - std::string lens; ///< lens - int iso; ///< ISO (gain) - double shutter; ///< shutter or exposure time in sec - double aperture; ///< aperture in stops - double focallength; ///< focal length in mm - time_t timestamp; ///< seconds since 1 Jan 1970 + Glib::ustring pathname; // filename of flat field + std::list pathNames; // other similar dark frames, used for average + std::string maker; ///< manufacturer + std::string model; ///< model + std::string lens; ///< lens + int iso; ///< ISO (gain) + double shutter; ///< shutter or exposure time in sec + double aperture; ///< aperture in stops + double focallength; ///< focal length in mm + time_t timestamp; ///< seconds since 1 Jan 1970 - ffInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod,const std::string & len,double focal,double apert,time_t t) - :pathname(name),maker(mak),model(mod),lens(len),aperture(apert),focallength(focal),timestamp(t),ri(NULL){} + ffInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, const std::string & len, double focal, double apert, time_t t) + : pathname(name), maker(mak), model(mod), lens(len), aperture(apert), focallength(focal), timestamp(t), ri(NULL) {} - ffInfo( const ffInfo &o) - :pathname(o.pathname),maker(o.maker),model(o.model),lens(o.lens),aperture(o.aperture),focallength(o.focallength),timestamp(o.timestamp),ri(NULL){} - ~ffInfo() { if( ri ) delete ri; } + ffInfo( const ffInfo &o) + : pathname(o.pathname), maker(o.maker), model(o.model), lens(o.lens), aperture(o.aperture), focallength(o.focallength), timestamp(o.timestamp), ri(NULL) {} + ~ffInfo() + { + if( ri ) { + delete ri; + } + } - - ffInfo &operator =(const ffInfo &o); - bool operator <(const ffInfo &e2) const; - // Calculate virtual distance between two shots; different model return infinite - double distance(const std::string &mak, const std::string &mod, const std::string &lens, double focallength, double aperture) const; + ffInfo &operator =(const ffInfo &o); + bool operator <(const ffInfo &e2) const; - static std::string key(const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert ); - std::string key(){ return key( maker,model,lens,focallength,aperture); } + // Calculate virtual distance between two shots; different model return infinite + double distance(const std::string &mak, const std::string &mod, const std::string &lens, double focallength, double aperture) const; - RawImage *getRawImage(); + static std::string key(const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert ); + std::string key() + { + return key( maker, model, lens, focallength, aperture); + } + + RawImage *getRawImage(); protected: - RawImage *ri; ///< Flat Field raw data + RawImage *ri; ///< Flat Field raw data - void updateRawImage(); + void updateRawImage(); }; class FFManager { public: - void init( Glib::ustring pathname ); - Glib::ustring getPathname(){ return currentPath; }; - void getStat( int &totFiles, int &totTemplate); - RawImage *searchFlatField( const std::string &mak, const std::string &mod, const std::string &len, double focallength, double apert, time_t t ); - RawImage *searchFlatField( const Glib::ustring filename ); + void init( Glib::ustring pathname ); + Glib::ustring getPathname() + { + return currentPath; + }; + void getStat( int &totFiles, int &totTemplate); + RawImage *searchFlatField( const std::string &mak, const std::string &mod, const std::string &len, double focallength, double apert, time_t t ); + RawImage *searchFlatField( const Glib::ustring filename ); protected: - typedef std::multimap ffList_t; - typedef std::map > bpList_t; - ffList_t ffList; - bool initialized; - Glib::ustring currentPath; - ffInfo *addFileInfo(const Glib::ustring &filename, bool pool=true ); - ffInfo *find( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t ); + typedef std::multimap ffList_t; + typedef std::map > bpList_t; + ffList_t ffList; + bool initialized; + Glib::ustring currentPath; + ffInfo *addFileInfo(const Glib::ustring &filename, bool pool = true ); + ffInfo *find( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t ); }; extern FFManager ffm; diff --git a/rtengine/flatcurves.cc b/rtengine/flatcurves.cc index 179bbe9b0..ee4d6d29c 100644 --- a/rtengine/flatcurves.cc +++ b/rtengine/flatcurves.cc @@ -7,7 +7,7 @@ * 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 @@ -27,9 +27,11 @@ #include #include -namespace rtengine { +namespace rtengine +{ -FlatCurve::FlatCurve (const std::vector& p, bool isPeriodic, int poly_pn) : kind(FCT_Empty), leftTangent(NULL), rightTangent(NULL), identityValue(0.5), periodic(isPeriodic) { +FlatCurve::FlatCurve (const std::vector& p, bool isPeriodic, int poly_pn) : kind(FCT_Empty), leftTangent(NULL), rightTangent(NULL), identityValue(0.5), periodic(isPeriodic) +{ ppn = poly_pn > 65500 ? 65500 : poly_pn; poly_x.clear(); @@ -37,44 +39,53 @@ FlatCurve::FlatCurve (const std::vector& p, bool isPeriodic, int poly_pn bool identity = true; - if (p.size()>4) { + if (p.size() > 4) { kind = (FlatCurveType)p[0]; - if (kind==FCT_MinMaxCPoints) { - int oneMorePoint = periodic ? 1:0; - N = (p.size()-1)/4; - x = new double[N+oneMorePoint]; - y = new double[N+oneMorePoint]; - leftTangent = new double[N+oneMorePoint]; - rightTangent = new double[N+oneMorePoint]; + + if (kind == FCT_MinMaxCPoints) { + int oneMorePoint = periodic ? 1 : 0; + N = (p.size() - 1) / 4; + x = new double[N + oneMorePoint]; + y = new double[N + oneMorePoint]; + leftTangent = new double[N + oneMorePoint]; + rightTangent = new double[N + oneMorePoint]; int ix = 1; - for (int i=0; i= identityValue+1.e-7 || y[i] <= identityValue-1.e-7) + + if (y[i] >= identityValue + 1.e-7 || y[i] <= identityValue - 1.e-7) { identity = false; + } } + // The first point is copied to the end of the point list, to handle the curve periodicity if (periodic) { - x[N] = p[1]+1.0; + x[N] = p[1] + 1.0; y[N] = p[2]; leftTangent[N] = p[3]; rightTangent[N] = p[4]; } - if (!identity && N > (periodic?1:0) ) { + + if (!identity && N > (periodic ? 1 : 0) ) { CtrlPoints_set (); fillHash(); } } + /*else if (kind==FCT_Parametric) { }*/ - if (identity) + if (identity) { kind = FCT_Empty; + } } } -FlatCurve::~FlatCurve () { +FlatCurve::~FlatCurve () +{ delete [] x; delete [] y; @@ -89,47 +100,50 @@ FlatCurve::~FlatCurve () { * The nominal (identity) curve may not be 0.5, use this method to set it to whatever value in the 0.-1. range you want * Return true if the curve is nominal */ -bool FlatCurve::setIdentityValue (double iVal) { +bool FlatCurve::setIdentityValue (double iVal) +{ - if (identityValue == iVal) - return kind==FCT_Empty; + if (identityValue == iVal) { + return kind == FCT_Empty; + } identityValue = iVal; bool identity = true; - for (int i=0; i= identityValue+1.e-7 || y[i] <= identityValue-1.e-7) { + + for (int i = 0; i < N + (periodic ? 1 : 0); i++) { + if (y[i] >= identityValue + 1.e-7 || y[i] <= identityValue - 1.e-7) { identity = false; break; } } - if (!identity && N > (periodic?1:0) ) { + if (!identity && N > (periodic ? 1 : 0) ) { CtrlPoints_set (); fillHash(); kind = FCT_MinMaxCPoints; - } - else { + } else { poly_x.clear(); poly_y.clear(); hash.clear(); kind = FCT_Empty; } - return kind==FCT_Empty; + return kind == FCT_Empty; } -void FlatCurve::CtrlPoints_set () { +void FlatCurve::CtrlPoints_set () +{ - int N_ = periodic ? N : N-1; - int nbSubCurvesPoints = N_*6; + int N_ = periodic ? N : N - 1; + int nbSubCurvesPoints = N_ * 6; std::vector sc_x(nbSubCurvesPoints); // X sub-curve points ( XP0,XP1,XP2, XP2,XP3,XP4, ...) std::vector sc_y(nbSubCurvesPoints); // Y sub-curve points ( YP0,YP1,YP2, YP2,YP3,YP4, ...) - std::vector sc_length(N_*2); // Length of the subcurves - std::vector sc_isLinear(N_*2); // true if the subcurve is linear - double total_length=0.; + std::vector sc_length(N_ * 2); // Length of the subcurves + std::vector sc_isLinear(N_ * 2); // true if the subcurve is linear + double total_length = 0.; - // Create the list of Bezier sub-curves + // Create the list of Bezier sub-curves // CtrlPoints_set is called if N > 1 unsigned int j = 0; @@ -142,238 +156,253 @@ void FlatCurve::CtrlPoints_set () { double xp1, xp2, yp2, xp3; bool startLinear, endLinear; - startLinear = (rightTangent[i] == 0.) || (y[i] == y[i+1]); - endLinear = (leftTangent [i+1] == 0.) || (y[i] == y[i+1]); + startLinear = (rightTangent[i] == 0.) || (y[i] == y[i + 1]); + endLinear = (leftTangent [i + 1] == 0.) || (y[i] == y[i + 1]); if (startLinear && endLinear) { - // line shape - sc_x[j] = x[i]; - sc_y[j++] = y[i]; - sc_x[j] = x[i+1]; - sc_y[j] = y[i+1]; - sc_isLinear[k] = true; - i++; + // line shape + sc_x[j] = x[i]; + sc_y[j++] = y[i]; + sc_x[j] = x[i + 1]; + sc_y[j] = y[i + 1]; + sc_isLinear[k] = true; + i++; - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length = sqrt(dx*dx + dy*dy); - j++; + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length = sqrt(dx * dx + dy * dy); + j++; - // Storing the length of all sub-curves and the total length (to have a better distribution - // of the points along the curve) - sc_length[k++] = length; - total_length += length; - } - else { - if (startLinear) { - xp1 = x[i]; - } - else { - //xp1 = (xp4 - xp0) * rightTangent0 + xp0; - xp1 = (x[i+1] - x[i]) * rightTangent[i] + x[i]; - } - if (endLinear) { - xp3 = x[i+1]; - } - else { - //xp3 = (xp0 - xp4]) * leftTangent4 + xp4; - xp3 = (x[i] - x[i+1]) * leftTangent[i+1] + x[i+1]; - } - - xp2 = (xp1 + xp3) / 2.0; - yp2 = (y[i] + y[i+1]) / 2.0; - - if (rightTangent[i]+leftTangent[i+1] > 1.0) { // also means that start and end are not linear - xp1 = xp3 = xp2; + // Storing the length of all sub-curves and the total length (to have a better distribution + // of the points along the curve) + sc_length[k++] = length; + total_length += length; + } else { + if (startLinear) { + xp1 = x[i]; + } else { + //xp1 = (xp4 - xp0) * rightTangent0 + xp0; + xp1 = (x[i + 1] - x[i]) * rightTangent[i] + x[i]; } - if (startLinear) { - // Point 0, 2 - sc_x[j] = x[i]; - sc_y[j++] = y[i]; - sc_x[j] = xp2; - sc_y[j] = yp2; - sc_isLinear[k] = true; + if (endLinear) { + xp3 = x[i + 1]; + } else { + //xp3 = (xp0 - xp4]) * leftTangent4 + xp4; + xp3 = (x[i] - x[i + 1]) * leftTangent[i + 1] + x[i + 1]; + } - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length = sqrt(dx*dx + dy*dy); - j++; + xp2 = (xp1 + xp3) / 2.0; + yp2 = (y[i] + y[i + 1]) / 2.0; - // Storing the length of all sub-curves and the total length (to have a better distribution - // of the points along the curve) - sc_length[k++] = length; - total_length += length; - } - else { - // Point 0, 1, 2 - sc_x[j] = x[i]; - sc_y[j++] = y[i]; - sc_x[j] = xp1; - sc_y[j] = y[i]; + if (rightTangent[i] + leftTangent[i + 1] > 1.0) { // also means that start and end are not linear + xp1 = xp3 = xp2; + } - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length = sqrt(dx*dx + dy*dy); - j++; + if (startLinear) { + // Point 0, 2 + sc_x[j] = x[i]; + sc_y[j++] = y[i]; + sc_x[j] = xp2; + sc_y[j] = yp2; + sc_isLinear[k] = true; - sc_x[j] = xp2; - sc_y[j] = yp2; - sc_isLinear[k] = false; + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length = sqrt(dx * dx + dy * dy); + j++; - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length += sqrt(dx*dx + dy*dy); - j++; + // Storing the length of all sub-curves and the total length (to have a better distribution + // of the points along the curve) + sc_length[k++] = length; + total_length += length; + } else { + // Point 0, 1, 2 + sc_x[j] = x[i]; + sc_y[j++] = y[i]; + sc_x[j] = xp1; + sc_y[j] = y[i]; - // Storing the length of all sub-curves and the total length (to have a better distribution - // of the points along the curve) - sc_length[k++] = length; - total_length += length; - } - if (endLinear) { - // Point 2, 4 - sc_x[j] = xp2; - sc_y[j++] = yp2; - sc_x[j] = x[i+1]; - sc_y[j] = y[i+1]; - sc_isLinear[k] = true; + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length = sqrt(dx * dx + dy * dy); + j++; - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length = sqrt(dx*dx + dy*dy); - j++; + sc_x[j] = xp2; + sc_y[j] = yp2; + sc_isLinear[k] = false; - // Storing the length of all sub-curves and the total length (to have a better distribution - // of the points along the curve) - sc_length[k++] = length; - total_length += length; - } - else { - // Point 2, 3, 4 - sc_x[j] = xp2; - sc_y[j++] = yp2; - sc_x[j] = xp3; - sc_y[j] = y[i+1]; + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length += sqrt(dx * dx + dy * dy); + j++; - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length = sqrt(dx*dx + dy*dy); - j++; + // Storing the length of all sub-curves and the total length (to have a better distribution + // of the points along the curve) + sc_length[k++] = length; + total_length += length; + } - sc_x[j] = x[i+1]; - sc_y[j] = y[i+1]; - sc_isLinear[k] = false; + if (endLinear) { + // Point 2, 4 + sc_x[j] = xp2; + sc_y[j++] = yp2; + sc_x[j] = x[i + 1]; + sc_y[j] = y[i + 1]; + sc_isLinear[k] = true; - dx = sc_x[j] - sc_x[j-1]; - dy = sc_y[j] - sc_y[j-1]; - length += sqrt(dx*dx + dy*dy); - j++; + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length = sqrt(dx * dx + dy * dy); + j++; - // Storing the length of all sub-curves and the total length (to have a better distribution - // of the points along the curve) - sc_length[k++] = length; - total_length += length; - } - i++; + // Storing the length of all sub-curves and the total length (to have a better distribution + // of the points along the curve) + sc_length[k++] = length; + total_length += length; + } else { + // Point 2, 3, 4 + sc_x[j] = xp2; + sc_y[j++] = yp2; + sc_x[j] = xp3; + sc_y[j] = y[i + 1]; + + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length = sqrt(dx * dx + dy * dy); + j++; + + sc_x[j] = x[i + 1]; + sc_y[j] = y[i + 1]; + sc_isLinear[k] = false; + + dx = sc_x[j] - sc_x[j - 1]; + dy = sc_y[j] - sc_y[j - 1]; + length += sqrt(dx * dx + dy * dy); + j++; + + // Storing the length of all sub-curves and the total length (to have a better distribution + // of the points along the curve) + sc_length[k++] = length; + total_length += length; + } + + i++; } } poly_x.clear(); - poly_y.clear(); + poly_y.clear(); j = 0; // adding an initial horizontal line if necessary if (!periodic && sc_x[j] != 0.) { - poly_x.push_back(0.); - poly_y.push_back(sc_y[j]); - } + poly_x.push_back(0.); + poly_y.push_back(sc_y[j]); + } - // the first point of the curves - poly_x.push_back(sc_x[j]); - poly_y.push_back(sc_y[j]); + // the first point of the curves + poly_x.push_back(sc_x[j]); + poly_y.push_back(sc_y[j]); - firstPointIncluded = false; + firstPointIncluded = false; - // create the polyline with the number of points adapted to the X range of the sub-curve - for (unsigned int i=0; i < k; i++) { - if (sc_isLinear[i]) { - j++; // skip the first point - poly_x.push_back(sc_x[j]); - poly_y.push_back(sc_y[j++]); - } - else { - nbr_points = (int)(((double)(ppn) * sc_length[i] )/ total_length); - if (nbr_points<0){ - for(size_t it=0;it < sc_x.size(); it+=3) printf("sc_length[%zd/3]=%f \n",it,sc_length[it/3]); - printf("Flat curve: error detected!\n i=%d k=%d periodic=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f\n",i,k,periodic,nbr_points,ppn,N,sc_length[i/3],total_length); - exit(0); - } - // increment along the curve, not along the X axis - increment = 1.0 / (double)(nbr_points-1); - x1 = sc_x[j]; y1 = sc_y[j++]; - x2 = sc_x[j]; y2 = sc_y[j++]; - x3 = sc_x[j]; y3 = sc_y[j++]; - AddPolygons (); - } + // create the polyline with the number of points adapted to the X range of the sub-curve + for (unsigned int i = 0; i < k; i++) { + if (sc_isLinear[i]) { + j++; // skip the first point + poly_x.push_back(sc_x[j]); + poly_y.push_back(sc_y[j++]); + } else { + nbr_points = (int)(((double)(ppn) * sc_length[i] ) / total_length); + + if (nbr_points < 0) { + for(size_t it = 0; it < sc_x.size(); it += 3) { + printf("sc_length[%zd/3]=%f \n", it, sc_length[it / 3]); + } + + printf("Flat curve: error detected!\n i=%d k=%d periodic=%d nbr_points=%d ppn=%d N=%d sc_length[i/3]=%f total_length=%f\n", i, k, periodic, nbr_points, ppn, N, sc_length[i / 3], total_length); + exit(0); + } + + // increment along the curve, not along the X axis + increment = 1.0 / (double)(nbr_points - 1); + x1 = sc_x[j]; + y1 = sc_y[j++]; + x2 = sc_x[j]; + y2 = sc_y[j++]; + x3 = sc_x[j]; + y3 = sc_y[j++]; + AddPolygons (); + } } // adding the final horizontal segment, always (see under) - poly_x.push_back(3.0); // 3.0 is a hack for optimization purpose of the getVal method (the last value has to be beyond the normal range) - poly_y.push_back(sc_y[j-1]); + poly_x.push_back(3.0); // 3.0 is a hack for optimization purpose of the getVal method (the last value has to be beyond the normal range) + poly_y.push_back(sc_y[j - 1]); /* // Checking the values Glib::ustring fname = "Curve.xyz"; // TopSolid'Design "plot" file format - std::ofstream f (fname.c_str()); - f << "$" << std::endl;; - for (unsigned int iter = 0; iter < poly_x.size(); iter++) { - f << poly_x[iter] << ", " << poly_y[iter] << ", 0." << std::endl;; - } - f << "$" << std::endl;; - f.close (); - */ + std::ofstream f (fname.c_str()); + f << "$" << std::endl;; + for (unsigned int iter = 0; iter < poly_x.size(); iter++) { + f << poly_x[iter] << ", " << poly_y[iter] << ", 0." << std::endl;; + } + f << "$" << std::endl;; + f.close (); + */ } -double FlatCurve::getVal (double t) const { +double FlatCurve::getVal (double t) const +{ switch (kind) { case FCT_MinMaxCPoints : { // magic to handle curve periodicity : we look above the 1.0 bound for the value - if (t < poly_x[0]) t += 1.0; + if (t < poly_x[0]) { + t += 1.0; + } // do a binary search for the right interval: int k_lo = 0, k_hi = poly_x.size() - 1; - while (k_hi - k_lo > 1){ + + while (k_hi - k_lo > 1) { int k = (k_hi + k_lo) / 2; - if (poly_x[k] > t) + + if (poly_x[k] > t) { k_hi = k; - else + } else { k_lo = k; + } } double dx = poly_x[k_hi] - poly_x[k_lo]; double dy = poly_y[k_hi] - poly_y[k_lo]; return poly_y[k_lo] + (t - poly_x[k_lo]) * dy / dx; - break; + break; } + /*case Parametric : { break; }*/ case FCT_Empty : case FCT_Linear : // Linear doesn't exist yet and is then considered as identity default: - return identityValue; + return identityValue; } } -void FlatCurve::getVal (const std::vector& t, std::vector& res) const { +void FlatCurve::getVal (const std::vector& t, std::vector& res) const +{ res.resize (t.size()); - for (unsigned int i=0; i +#include #else - #include +#include #endif #endif // classical filtering if the support window is small: -template void gaussHorizontal3 (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, const float c0, const float c1) { +template void gaussHorizontal3 (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, const float c0, const float c1) +{ #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i* pBuf = buffer.acquire(); - T* temp=(T*)pBuf->data; - for (int j=1; j* pBuf = buffer.acquire(); + T* temp = (T*)pBuf->data; + + for (int j = 1; j < W - 1; j++) { + temp[j] = (T)(c1 * (src[i][j - 1] + src[i][j + 1]) + c0 * src[i][j]); + } + dst[i][0] = src[i][0]; - memcpy (dst[i]+1, temp+1, (W-2)*sizeof(T)); + memcpy (dst[i] + 1, temp + 1, (W - 2)*sizeof(T)); buffer.release(pBuf); - dst[i][W-1] = src[i][W-1]; + dst[i][W - 1] = src[i][W - 1]; } } -template void gaussVertical3 (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, const float c0, const float c1) { +template void gaussVertical3 (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, const float c0, const float c1) +{ #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i* pBuf = buffer.acquire(); - T* temp = (T*)pBuf->data; - for (int j = 1; j* pBuf = buffer.acquire(); + T* temp = (T*)pBuf->data; + + for (int j = 1; j < H - 1; j++) { + temp[j] = (T)(c1 * (src[j - 1][i] + src[j + 1][i]) + c0 * src[j][i]); + } + dst[0][i] = src[0][i]; - for (int j=1; j __attribute__((force_align_arg_pointer)) void gaussVertical3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) { +template __attribute__((force_align_arg_pointer)) void gaussVertical3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) +{ #else -template void gaussVertical3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) { +template void gaussVertical3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) +{ #endif - __m128 Tv,Tm1v,Tp1v; - __m128 c0v,c1v; + __m128 Tv, Tm1v, Tp1v; + __m128 c0v, c1v; c0v = _mm_set1_ps(c0); c1v = _mm_set1_ps(c1); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i1) + + if(H > 1) { Tv = _mm_loadu_ps( &src[1][i]); - for (int j=1; j __attribute__((force_align_arg_pointer)) void gaussHorizontal3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) { +template __attribute__((force_align_arg_pointer)) void gaussHorizontal3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) +{ #else -template void gaussHorizontal3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) { +template void gaussHorizontal3Sse (T** src, T** dst, int W, int H, const float c0, const float c1) +{ #endif float tmp[W][4] __attribute__ ((aligned (16))); - __m128 Tv,Tm1v,Tp1v; - __m128 c0v,c1v; + __m128 Tv, Tm1v, Tp1v; + __m128 c0v, c1v; c0v = _mm_set1_ps(c0); c1v = _mm_set1_ps(c1); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i1) - Tv = _mm_set_ps( src[i][1], src[i+1][1], src[i+2][1], src[i+3][1] ); - for (int j=1; j 1) { + Tv = _mm_set_ps( src[i][1], src[i + 1][1], src[i + 2][1], src[i + 3][1] ); + } + + for (int j = 1; j < W - 1; j++) { + Tp1v = _mm_set_ps( src[i][j + 1], src[i + 1][j + 1], src[i + 2][j + 1], src[i + 3][j + 1] ); _mm_store_ps( &tmp[j][0], c1v * (Tp1v + Tm1v) + Tv * c0v); Tm1v = Tv; Tv = Tp1v; } - for (int j=1; j __attribute__((force_align_arg_pointer)) void gaussHorizontalSse (T** src, T** dst, int W, int H, float sigma) { +template __attribute__((force_align_arg_pointer)) void gaussHorizontalSse (T** src, T** dst, int W, int H, float sigma) +{ #else -template void gaussHorizontalSse (T** src, T** dst, int W, int H, float sigma) { +template void gaussHorizontalSse (T** src, T** dst, int W, int H, float sigma) +{ #endif - if (sigma<0.25) { + + if (sigma < 0.25) { // dont perform filtering - if (src!=dst) -#pragma omp for - for (int i = 0; i void gaussHorizontalSse (T** src, T** dst, int W, int H, float // coefficient calculation float q = 0.98711 * sigma - 0.96330; - if (sigma<2.5) + + if (sigma < 2.5) { q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); - float b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; - float b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; - float b2 = -1.4281*q*q - 1.26661*q*q*q; - float b3 = 0.422205*q*q*q; - float B = 1.0 - (b1+b2+b3) / b0; + } + + float b0 = 1.57825 + 2.44413 * q + 1.4281 * q * q + 0.422205 * q * q * q; + float b1 = 2.44413 * q + 2.85619 * q * q + 1.26661 * q * q * q; + float b2 = -1.4281 * q * q - 1.26661 * q * q * q; + float b3 = 0.422205 * q * q * q; + float B = 1.0 - (b1 + b2 + b3) / b0; b1 /= b0; b2 /= b0; @@ -215,74 +253,86 @@ template void gaussHorizontalSse (T** src, T** dst, int W, int H, float // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering float M[3][3]; - M[0][0] = -b3*b1+1.0-b3*b3-b2; - M[0][1] = (b3+b1)*(b2+b3*b1); - M[0][2] = b3*(b1+b3*b2); - M[1][0] = b1+b3*b2; - M[1][1] = -(b2-1.0)*(b2+b3*b1); - M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; - M[2][0] = b3*b1+b2+b1*b1-b2*b2; - M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; - M[2][2] = b3*(b1+b3*b2); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) { - M[i][j] *= (1.0+b2+(b1-b3)*b3); - M[i][j] /= (1.0+b1-b2+b3)*(1.0-b1-b2-b3); + M[0][0] = -b3 * b1 + 1.0 - b3 * b3 - b2; + M[0][1] = (b3 + b1) * (b2 + b3 * b1); + M[0][2] = b3 * (b1 + b3 * b2); + M[1][0] = b1 + b3 * b2; + M[1][1] = -(b2 - 1.0) * (b2 + b3 * b1); + M[1][2] = -(b3 * b1 + b3 * b3 + b2 - 1.0) * b3; + M[2][0] = b3 * b1 + b2 + b1 * b1 - b2 * b2; + M[2][1] = b1 * b2 + b3 * b2 * b2 - b1 * b3 * b3 - b3 * b3 * b3 - b3 * b2 + b3; + M[2][2] = b3 * (b1 + b3 * b2); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + M[i][j] *= (1.0 + b2 + (b1 - b3) * b3); + M[i][j] /= (1.0 + b1 - b2 + b3) * (1.0 - b1 - b2 - b3); } + float tmp[W][4] __attribute__ ((aligned (16))); float tmpV[4] __attribute__ ((aligned (16))); __m128 Rv; - __m128 Tv,Tm2v,Tm3v; - __m128 Bv,b1v,b2v,b3v; - __m128 temp2W,temp2Wp1; + __m128 Tv, Tm2v, Tm3v; + __m128 Bv, b1v, b2v, b3v; + __m128 temp2W, temp2Wp1; Bv = _mm_set1_ps(B); b1v = _mm_set1_ps(b1); b2v = _mm_set1_ps(b2); b3v = _mm_set1_ps(b3); -#pragma omp for - for (int i=0; i=0; j--) { + for (int j = W - 4; j >= 0; j--) { Tv = Rv; Rv = _mm_load_ps(&tmp[j][0]) * Bv + Tv * b1v + Tm2v * b2v + Tm3v * b3v; _mm_store_ps( &tmp[j][0], Rv ); @@ -290,64 +340,74 @@ template void gaussHorizontalSse (T** src, T** dst, int W, int H, float Tm2v = Tv; } - for (int j=0; j=0; j--) - tmp[j][0] = B * tmp[j][0] + b1*tmp[j+1][0] + b2*tmp[j+2][0] + b3*tmp[j+3][0]; - - for (int j=0; j= 0; j--) { + tmp[j][0] = B * tmp[j][0] + b1 * tmp[j + 1][0] + b2 * tmp[j + 2][0] + b3 * tmp[j + 3][0]; + } + + for (int j = 0; j < W; j++) { + dst[i][j] = tmp[j][0]; + } + + } } #endif // fast gaussian approximation if the support window is large -template void gaussHorizontal (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) { +template void gaussHorizontal (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) +{ #ifdef __SSE__ - if(sigma < 70) { // bigger sigma only with double precision - gaussHorizontalSse (src, dst, W, H, sigma); - return; - } -#endif - if (sigma<0.25) { - // dont perform filtering - if (src!=dst) -#pragma omp for - for (int i = 0; i (src, dst, W, H, sigma); return; } - if (sigma<0.6) { +#endif + + if (sigma < 0.25) { + // dont perform filtering + if (src != dst) + #pragma omp for + for (int i = 0; i < H; i++) { + memcpy (dst[i], src[i], W * sizeof(T)); + } + + return; + } + + if (sigma < 0.6) { // compute 3x3 kernel double c1 = exp (-1.0 / (2.0 * sigma * sigma)); double csum = 2.0 * c1 + 1.0; @@ -359,13 +419,16 @@ template void gaussHorizontal (T** src, T** dst, AlignedBufferMP void gaussHorizontal (T** src, T** dst, AlignedBufferMP* pBuf = buffer.acquire(); double* temp2 = pBuf->data; - temp2[0] = B * src[i][0] + b1*src[i][0] + b2*src[i][0] + b3*src[i][0]; - temp2[1] = B * src[i][1] + b1*temp2[0] + b2*src[i][0] + b3*src[i][0]; - temp2[2] = B * src[i][2] + b1*temp2[1] + b2*temp2[0] + b3*src[i][0]; + temp2[0] = B * src[i][0] + b1 * src[i][0] + b2 * src[i][0] + b3 * src[i][0]; + temp2[1] = B * src[i][1] + b1 * temp2[0] + b2 * src[i][0] + b3 * src[i][0]; + temp2[2] = B * src[i][2] + b1 * temp2[1] + b2 * temp2[0] + b3 * src[i][0]; - for (int j=3; j=0; j--) - temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; - for (int j=0; j= 0; j--) { + temp2[j] = B * temp2[j] + b1 * temp2[j + 1] + b2 * temp2[j + 2] + b3 * temp2[j + 3]; + } + + for (int j = 0; j < W; j++) { dst[i][j] = (T)temp2[j]; + } buffer.release(pBuf); } @@ -417,20 +487,25 @@ template void gaussHorizontal (T** src, T** dst, AlignedBufferMP __attribute__((force_align_arg_pointer)) void gaussVerticalSse (T** src, T** dst, int W, int H, float sigma) { +template __attribute__((force_align_arg_pointer)) void gaussVerticalSse (T** src, T** dst, int W, int H, float sigma) +{ #else -template void gaussVerticalSse (T** src, T** dst, int W, int H, float sigma) { +template void gaussVerticalSse (T** src, T** dst, int W, int H, float sigma) +{ #endif - if (sigma<0.25) { + + if (sigma < 0.25) { // dont perform filtering - if (src!=dst) -#pragma omp for - for (int i = 0; i void gaussVerticalSse (T** src, T** dst, int W, int H, float s // coefficient calculation double q = 0.98711 * sigma - 0.96330; - if (sigma<2.5) + + if (sigma < 2.5) { q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); - double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; - double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; - double b2 = -1.4281*q*q - 1.26661*q*q*q; - double b3 = 0.422205*q*q*q; - double B = 1.0 - (b1+b2+b3) / b0; + } + + double b0 = 1.57825 + 2.44413 * q + 1.4281 * q * q + 0.422205 * q * q * q; + double b1 = 2.44413 * q + 2.85619 * q * q + 1.26661 * q * q * q; + double b2 = -1.4281 * q * q - 1.26661 * q * q * q; + double b3 = 0.422205 * q * q * q; + double B = 1.0 - (b1 + b2 + b3) / b0; b1 /= b0; b2 /= b0; @@ -456,25 +534,27 @@ template void gaussVerticalSse (T** src, T** dst, int W, int H, float s // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering double M[3][3]; - M[0][0] = -b3*b1+1.0-b3*b3-b2; - M[0][1] = (b3+b1)*(b2+b3*b1); - M[0][2] = b3*(b1+b3*b2); - M[1][0] = b1+b3*b2; - M[1][1] = -(b2-1.0)*(b2+b3*b1); - M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; - M[2][0] = b3*b1+b2+b1*b1-b2*b2; - M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; - M[2][2] = b3*(b1+b3*b2); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) { - M[i][j] *= (1.0+b2+(b1-b3)*b3); - M[i][j] /= (1.0+b1-b2+b3)*(1.0-b1-b2-b3); + M[0][0] = -b3 * b1 + 1.0 - b3 * b3 - b2; + M[0][1] = (b3 + b1) * (b2 + b3 * b1); + M[0][2] = b3 * (b1 + b3 * b2); + M[1][0] = b1 + b3 * b2; + M[1][1] = -(b2 - 1.0) * (b2 + b3 * b1); + M[1][2] = -(b3 * b1 + b3 * b3 + b2 - 1.0) * b3; + M[2][0] = b3 * b1 + b2 + b1 * b1 - b2 * b2; + M[2][1] = b1 * b2 + b3 * b2 * b2 - b1 * b3 * b3 - b3 * b3 * b3 - b3 * b2 + b3; + M[2][2] = b3 * (b1 + b3 * b2); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + M[i][j] *= (1.0 + b2 + (b1 - b3) * b3); + M[i][j] /= (1.0 + b1 - b2 + b3) * (1.0 - b1 - b2 - b3); } + float tmp[H][4] __attribute__ ((aligned (16))); __m128 Rv; - __m128 Tv,Tm2v,Tm3v; - __m128 Bv,b1v,b2v,b3v; - __m128 temp2W,temp2Wp1; + __m128 Tv, Tm2v, Tm3v; + __m128 Bv, b1v, b2v, b3v; + __m128 temp2W, temp2Wp1; Bv = _mm_set1_ps(B); b1v = _mm_set1_ps(b1); b2v = _mm_set1_ps(b2); @@ -482,9 +562,10 @@ template void gaussVerticalSse (T** src, T** dst, int W, int H, float s #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i void gaussVerticalSse (T** src, T** dst, int W, int H, float s Rv = _mm_loadu_ps(&src[2][i]) * Bv + Rv * b1v + Tm3v * b2v + Tv * b3v; _mm_store_ps( &tmp[2][0], Rv ); - for (int j=3; j=0; j--) { + for (int j = H - 4; j >= 0; j--) { Tv = Rv; Rv = _mm_load_ps(&tmp[j][0]) * Bv + Tv * b1v + Tm2v * b2v + Tm3v * b3v; _mm_storeu_ps( &dst[j][i], Rv ); @@ -530,55 +612,64 @@ template void gaussVerticalSse (T** src, T** dst, int W, int H, float s Tm2v = Tv; } } + // Borders are done without SSE -#pragma omp for - for(int i=W-(W%4);i=0; j--) - tmp[j][0] = B * tmp[j][0] + b1*tmp[j+1][0] + b2*tmp[j+2][0] + b3*tmp[j+3][0]; - - for (int j=0; j= 0; j--) { + tmp[j][0] = B * tmp[j][0] + b1 * tmp[j + 1][0] + b2 * tmp[j + 2][0] + b3 * tmp[j + 3][0]; + } + + for (int j = 0; j < H; j++) { + dst[j][i] = tmp[j][0]; + } + + } } #endif -template void gaussVertical (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) { +template void gaussVertical (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) +{ #ifdef __SSE__ - if(sigma < 70) { // bigger sigma only with double precision - gaussVerticalSse (src, dst, W, H, sigma); - return; - } -#endif - if (sigma<0.25) { - // dont perform filtering - if (src!=dst) -#pragma omp for - for (int i = 0; i (src, dst, W, H, sigma); return; } - if (sigma<0.6) { +#endif + + if (sigma < 0.25) { + // dont perform filtering + if (src != dst) + #pragma omp for + for (int i = 0; i < H; i++) { + memcpy (dst[i], src[i], W * sizeof(T)); + } + + return; + } + + if (sigma < 0.6) { // compute 3x3 kernel double c1 = exp (-1.0 / (2.0 * sigma * sigma)); double csum = 2.0 * c1 + 1.0; @@ -590,13 +681,16 @@ template void gaussVertical (T** src, T** dst, AlignedBufferMP // coefficient calculation double q = 0.98711 * sigma - 0.96330; - if (sigma<2.5) + + if (sigma < 2.5) { q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); - double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; - double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; - double b2 = -1.4281*q*q - 1.26661*q*q*q; - double b3 = 0.422205*q*q*q; - double B = 1.0 - (b1+b2+b3) / b0; + } + + double b0 = 1.57825 + 2.44413 * q + 1.4281 * q * q + 0.422205 * q * q * q; + double b1 = 2.44413 * q + 2.85619 * q * q + 1.26661 * q * q * q; + double b2 = -1.4281 * q * q - 1.26661 * q * q * q; + double b3 = 0.422205 * q * q * q; + double B = 1.0 - (b1 + b2 + b3) / b0; b1 /= b0; b2 /= b0; @@ -604,44 +698,51 @@ template void gaussVertical (T** src, T** dst, AlignedBufferMP // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering double M[3][3]; - M[0][0] = -b3*b1+1.0-b3*b3-b2; - M[0][1] = (b3+b1)*(b2+b3*b1); - M[0][2] = b3*(b1+b3*b2); - M[1][0] = b1+b3*b2; - M[1][1] = -(b2-1.0)*(b2+b3*b1); - M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; - M[2][0] = b3*b1+b2+b1*b1-b2*b2; - M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; - M[2][2] = b3*(b1+b3*b2); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - M[i][j] /= (1.0+b1-b2+b3)*(1.0+b2+(b1-b3)*b3); + M[0][0] = -b3 * b1 + 1.0 - b3 * b3 - b2; + M[0][1] = (b3 + b1) * (b2 + b3 * b1); + M[0][2] = b3 * (b1 + b3 * b2); + M[1][0] = b1 + b3 * b2; + M[1][1] = -(b2 - 1.0) * (b2 + b3 * b1); + M[1][2] = -(b3 * b1 + b3 * b3 + b2 - 1.0) * b3; + M[2][0] = b3 * b1 + b2 + b1 * b1 - b2 * b2; + M[2][1] = b1 * b2 + b3 * b2 * b2 - b1 * b3 * b3 - b3 * b3 * b3 - b3 * b2 + b3; + M[2][2] = b3 * (b1 + b3 * b2); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + M[i][j] /= (1.0 + b1 - b2 + b3) * (1.0 + b2 + (b1 - b3) * b3); + } + #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i* pBuf = buffer.acquire(); double* temp2 = pBuf->data; - temp2[0] = B * src[0][i] + b1*src[0][i] + b2*src[0][i] + b3*src[0][i]; - temp2[1] = B * src[1][i] + b1*temp2[0] + b2*src[0][i] + b3*src[0][i]; - temp2[2] = B * src[2][i] + b1*temp2[1] + b2*temp2[0] + b3*src[0][i]; + temp2[0] = B * src[0][i] + b1 * src[0][i] + b2 * src[0][i] + b3 * src[0][i]; + temp2[1] = B * src[1][i] + b1 * temp2[0] + b2 * src[0][i] + b3 * src[0][i]; + temp2[2] = B * src[2][i] + b1 * temp2[1] + b2 * temp2[0] + b3 * src[0][i]; - for (int j=3; j=0; j--) - temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; + for (int j = H - 4; j >= 0; j--) { + temp2[j] = B * temp2[j] + b1 * temp2[j + 1] + b2 * temp2[j + 2] + b3 * temp2[j + 3]; + } - for (int j=0; j void gaussVertical (T** src, T** dst, AlignedBufferMP //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -template void gaussDerivH (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) { +template void gaussDerivH (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) +{ - if (sigma<0.6) { + if (sigma < 0.6) { // apply symmetric derivative #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i* pBuf = buffer.acquire(); - T* temp = (T*)pBuf->data; - // double* temp = buffer->data;// replaced by 2 lines above - for (int j=1; j* pBuf = buffer.acquire(); + T* temp = (T*)pBuf->data; + + // double* temp = buffer->data;// replaced by 2 lines above + for (int j = 1; j < W - 1; j++) { + temp[j] = (0.5 * (src[i][j + 1] - src[i][j - 1]) ); + } + + dst[i][0] = (src[i][1] - src[i][0]); + + //memcpy (dst[i]+1, temp+1, (W-2)*sizeof(T)); + for (int j = 1; j < W - 1; j++) { + dst[i][j] = temp[j]; + } + + buffer.release(pBuf); + dst[i][W - 1] = (src[i][W - 1] - src[i][W - 2]); + } + return; } // coefficient calculation double q = 0.98711 * sigma - 0.96330; - if (sigma<2.5) + + if (sigma < 2.5) { q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); - double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; - double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; - double b2 = -1.4281*q*q - 1.26661*q*q*q; - double b3 = 0.422205*q*q*q; - double B = 1.0 - (b1+b2+b3) / b0; + } + + double b0 = 1.57825 + 2.44413 * q + 1.4281 * q * q + 0.422205 * q * q * q; + double b1 = 2.44413 * q + 2.85619 * q * q + 1.26661 * q * q * q; + double b2 = -1.4281 * q * q - 1.26661 * q * q * q; + double b3 = 0.422205 * q * q * q; + double B = 1.0 - (b1 + b2 + b3) / b0; b1 /= b0; b2 /= b0; @@ -693,50 +805,57 @@ template void gaussDerivH (T** src, T** dst, AlignedBufferMP &b // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering double M[3][3]; - M[0][0] = -b3*b1+1.0-b3*b3-b2; - M[0][1] = (b3+b1)*(b2+b3*b1); - M[0][2] = b3*(b1+b3*b2); - M[1][0] = b1+b3*b2; - M[1][1] = -(b2-1.0)*(b2+b3*b1); - M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; - M[2][0] = b3*b1+b2+b1*b1-b2*b2; - M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; - M[2][2] = b3*(b1+b3*b2); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - M[i][j] /= (1.0+b1-b2+b3)*(1.0+b2+(b1-b3)*b3); + M[0][0] = -b3 * b1 + 1.0 - b3 * b3 - b2; + M[0][1] = (b3 + b1) * (b2 + b3 * b1); + M[0][2] = b3 * (b1 + b3 * b2); + M[1][0] = b1 + b3 * b2; + M[1][1] = -(b2 - 1.0) * (b2 + b3 * b1); + M[1][2] = -(b3 * b1 + b3 * b3 + b2 - 1.0) * b3; + M[2][0] = b3 * b1 + b2 + b1 * b1 - b2 * b2; + M[2][1] = b1 * b2 + b3 * b2 * b2 - b1 * b3 * b3 - b3 * b3 * b3 - b3 * b2 + b3; + M[2][2] = b3 * (b1 + b3 * b2); -#pragma omp for - for (int i=0; i* pBuf = buffer.acquire(); - T* temp2 = (T*)pBuf->data; - // double* temp2 = buffer->data;// replaced by 2 lines above + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + M[i][j] /= (1.0 + b1 - b2 + b3) * (1.0 + b2 + (b1 - b3) * b3); + } - double src0 = (src[i][1]-src[i][0]); + #pragma omp for - temp2[0] = B * src0 + b1*src0 + b2*src0 + b3*src0; - temp2[1] = B * 0.5*(src[i][2]-src[i][0]) + b1*temp2[0] + b2*src0 + b3*src0; - temp2[2] = B * 0.5*(src[i][3]-src[i][1]) + b1*temp2[1] + b2*temp2[0] + b3*src0; + for (int i = 0; i < H; i++) { + AlignedBuffer* pBuf = buffer.acquire(); + T* temp2 = (T*)pBuf->data; + // double* temp2 = buffer->data;// replaced by 2 lines above - for (int j=3; j=0; j--) - temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; - for (int j=0; j= 0; j--) { + temp2[j] = B * temp2[j] + b1 * temp2[j + 1] + b2 * temp2[j + 2] + b3 * temp2[j + 3]; + } + + for (int j = 0; j < W; j++) { dst[i][j] = (T)temp2[j]; + } buffer.release(pBuf); } @@ -744,39 +863,50 @@ template void gaussDerivH (T** src, T** dst, AlignedBufferMP &b //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -template void gaussDerivV (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) { +template void gaussDerivV (T** src, T** dst, AlignedBufferMP &buffer, int W, int H, double sigma) +{ - if (sigma<0.6) { + if (sigma < 0.6) { // apply symmetric derivative #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int j=0; j* pBuf = buffer.acquire(); - T* temp = (T*)pBuf->data; - // double* temp = buffer->data;// replaced by 2 lines above - for (int i = 1; i* pBuf = buffer.acquire(); + T* temp = (T*)pBuf->data; + + // double* temp = buffer->data;// replaced by 2 lines above + for (int i = 1; i < H - 1; i++) { + temp[i] = (0.5 * (src[i + 1][j] - src[i - 1][j]) ); + } + + dst[0][j] = (src[1][j] - src[0][j]); + + for (int i = 1; i < H - 1; i++) { + dst[i][j] = temp[i]; + } + + buffer.release(pBuf); + + dst[H - 1][j] = (src[H - 1][j] - src[H - 2][j]); + } - dst[H-1][j] = (src[H-1][j]-src[H-2][j]); - } return; } // coefficient calculation double q = 0.98711 * sigma - 0.96330; - if (sigma<2.5) + + if (sigma < 2.5) { q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); - double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; - double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; - double b2 = -1.4281*q*q - 1.26661*q*q*q; - double b3 = 0.422205*q*q*q; - double B = 1.0 - (b1+b2+b3) / b0; + } + + double b0 = 1.57825 + 2.44413 * q + 1.4281 * q * q + 0.422205 * q * q * q; + double b1 = 2.44413 * q + 2.85619 * q * q + 1.26661 * q * q * q; + double b2 = -1.4281 * q * q - 1.26661 * q * q * q; + double b3 = 0.422205 * q * q * q; + double B = 1.0 - (b1 + b2 + b3) / b0; b1 /= b0; b2 /= b0; @@ -784,52 +914,59 @@ template void gaussDerivV (T** src, T** dst, AlignedBufferMP &b // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering double M[3][3]; - M[0][0] = -b3*b1+1.0-b3*b3-b2; - M[0][1] = (b3+b1)*(b2+b3*b1); - M[0][2] = b3*(b1+b3*b2); - M[1][0] = b1+b3*b2; - M[1][1] = -(b2-1.0)*(b2+b3*b1); - M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; - M[2][0] = b3*b1+b2+b1*b1-b2*b2; - M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; - M[2][2] = b3*(b1+b3*b2); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - M[i][j] /= (1.0+b1-b2+b3)*(1.0+b2+(b1-b3)*b3); + M[0][0] = -b3 * b1 + 1.0 - b3 * b3 - b2; + M[0][1] = (b3 + b1) * (b2 + b3 * b1); + M[0][2] = b3 * (b1 + b3 * b2); + M[1][0] = b1 + b3 * b2; + M[1][1] = -(b2 - 1.0) * (b2 + b3 * b1); + M[1][2] = -(b3 * b1 + b3 * b3 + b2 - 1.0) * b3; + M[2][0] = b3 * b1 + b2 + b1 * b1 - b2 * b2; + M[2][1] = b1 * b2 + b3 * b2 * b2 - b1 * b3 * b3 - b3 * b3 * b3 - b3 * b2 + b3; + M[2][2] = b3 * (b1 + b3 * b2); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + M[i][j] /= (1.0 + b1 - b2 + b3) * (1.0 + b2 + (b1 - b3) * b3); + } + #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i* pBuf = buffer.acquire(); - T* temp2 = (T*)pBuf->data; - // double* temp2 = buffer->data;// replaced by 2 lines above - double src0 = 0.5*(src[1][i]-src[0][i]); + for (int i = 0; i < W; i++) { + AlignedBuffer* pBuf = buffer.acquire(); + T* temp2 = (T*)pBuf->data; + // double* temp2 = buffer->data;// replaced by 2 lines above - temp2[0] = B * src0 + b1*src0 + b2*src0 + b3*src0; - temp2[1] = B * 0.5*(src[2][i]-src[0][i]) + b1*temp2[0] + b2*src0 + b3*src0; - temp2[2] = B * 0.5*(src[3][i]-src[1][i]) + b1*temp2[1] + b2*temp2[0] + b3*src0; + double src0 = 0.5 * (src[1][i] - src[0][i]); - for (int j=3; j=0; j--) - temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; + temp2[H - 1] = temp2Hm1; + temp2[H - 2] = B * temp2[H - 2] + b1 * temp2[H - 1] + b2 * temp2H + b3 * temp2Hp1; + temp2[H - 3] = B * temp2[H - 3] + b1 * temp2[H - 2] + b2 * temp2[H - 1] + b3 * temp2H; - for (int j=0; j= 0; j--) { + temp2[j] = B * temp2[j] + b1 * temp2[j + 1] + b2 * temp2[j + 2] + b3 * temp2[j + 3]; + } + + for (int j = 0; j < H; j++) { dst[j][i] = (T)temp2[j]; + } buffer.release(pBuf); } diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index 55e88f73c..a9183509d 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -1,27 +1,27 @@ //////////////////////////////////////////////////////////////// // -// Green Equilibration via directional average +// Green Equilibration via directional average // -// copyright (c) 2008-2010 Emil Martinec +// copyright (c) 2008-2010 Emil Martinec // // // code dated: February 12, 2011 // -// green_equil_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// green_equil_RT.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// -#define TS 256 // Tile size +#define TS 256 // Tile size #include #include @@ -31,118 +31,122 @@ #include "rt_math.h" #include "rawimagesource.h" -namespace rtengine { +namespace rtengine +{ //void green_equilibrate()//for dcraw implementation void RawImageSource::green_equilibrate(float thresh) -{ - // thresh = threshold for performing green equilibration; max percentage difference of G1 vs G2 - // G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched - - int height=H, width=W; +{ + // thresh = threshold for performing green equilibration; max percentage difference of G1 vs G2 + // G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched - // local variables - float** rawptr = rawData; - array2D cfa (width,height,rawptr); - //array2D checker (width,height,ARRAY2D_CLEAR_DATA); - - - //int verbose=1; - - static const float eps=1.0; //tolerance to avoid dividing by zero - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // Fill G interpolated values with border interpolation and input values + int height = H, width = W; - //int vote1, vote2; - //int counter, vtest; - - //The green equilibration algorithm starts here + // local variables + float** rawptr = rawData; + array2D cfa (width, height, rawptr); + //array2D checker (width,height,ARRAY2D_CLEAR_DATA); + + + //int verbose=1; + + static const float eps = 1.0; //tolerance to avoid dividing by zero + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // Fill G interpolated values with border interpolation and input values + + //int vote1, vote2; + //int counter, vtest; + + //The green equilibration algorithm starts here /* + #ifdef _OPENMP + #pragma omp parallel for + #endif + for (int rr=1; rr < height-1; rr++) + for (int cc=3-(FC(rr,2)&1); cc < width-2; cc+=2) { + + float pcorr = (cfa[rr+1][cc+1]-cfa[rr][cc])*(cfa[rr-1][cc-1]-cfa[rr][cc]); + float mcorr = (cfa[rr-1][cc+1]-cfa[rr][cc])*(cfa[rr+1][cc-1]-cfa[rr][cc]); + + if (pcorr>0 && mcorr>0) {checker[rr][cc]=1;} else {checker[rr][cc]=0;} + + checker[rr][cc]=1;//test what happens if we always interpolate + } + + counter=vtest=0; + */ + //now smooth the cfa data #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int rr=1; rr < height-1; rr++) - for (int cc=3-(FC(rr,2)&1); cc < width-2; cc+=2) { - - float pcorr = (cfa[rr+1][cc+1]-cfa[rr][cc])*(cfa[rr-1][cc-1]-cfa[rr][cc]); - float mcorr = (cfa[rr-1][cc+1]-cfa[rr][cc])*(cfa[rr+1][cc-1]-cfa[rr][cc]); - - if (pcorr>0 && mcorr>0) {checker[rr][cc]=1;} else {checker[rr][cc]=0;} - - checker[rr][cc]=1;//test what happens if we always interpolate - } - - counter=vtest=0; - */ - //now smooth the cfa data -#ifdef _OPENMP -#pragma omp parallel for -#endif - for (int rr=4; rr < height-4; rr++) - for (int cc=5-(FC(rr,2)&1); cc < width-6; cc+=2) { - //if (checker[rr][cc]) { - //%%%%%%%%%%%%%%%%%%%%%% - //neighbor checking code from Manuel Llorens Garcia - float o1_1=cfa[(rr-1)][cc-1]; - float o1_2=cfa[(rr-1)][cc+1]; - float o1_3=cfa[(rr+1)][cc-1]; - float o1_4=cfa[(rr+1)][cc+1]; - float o2_1=cfa[(rr-2)][cc]; - float o2_2=cfa[(rr+2)][cc]; - float o2_3=cfa[(rr)][cc-2]; - float o2_4=cfa[(rr)][cc+2]; - - float d1=(o1_1+o1_2+o1_3+o1_4)*0.25f; - float d2=(o2_1+o2_2+o2_3+o2_4)*0.25f; - - float c1=(fabs(o1_1-o1_2)+fabs(o1_1-o1_3)+fabs(o1_1-o1_4)+fabs(o1_2-o1_3)+fabs(o1_3-o1_4)+fabs(o1_2-o1_4))/6.0; - float c2=(fabs(o2_1-o2_2)+fabs(o2_1-o2_3)+fabs(o2_1-o2_4)+fabs(o2_2-o2_3)+fabs(o2_3-o2_4)+fabs(o2_2-o2_4))/6.0; - //%%%%%%%%%%%%%%%%%%%%%% - - //vote1=(checker[rr-2][cc]+checker[rr][cc-2]+checker[rr][cc+2]+checker[rr+2][cc]); - //vote2=(checker[rr+1][cc-1]+checker[rr+1][cc+1]+checker[rr-1][cc-1]+checker[rr-1][cc+1]); - //if ((vote1==0 || vote2==0) && (c1+c2)<2*thresh*fabs(d1-d2)) vtest++; - //if (vote1>0 && vote2>0 && (c1+c2)<4*thresh*fabs(d1-d2)) { - if ((c1+c2)<4*thresh*fabs(d1-d2)) { - //pixel interpolation - float gin=cfa[rr][cc]; - - float gse=(cfa[rr+1][cc+1])+0.5*(cfa[rr][cc]-cfa[rr+2][cc+2]); - float gnw=(cfa[rr-1][cc-1])+0.5*(cfa[rr][cc]-cfa[rr-2][cc-2]); - float gne=(cfa[rr-1][cc+1])+0.5*(cfa[rr][cc]-cfa[rr-2][cc+2]); - float gsw=(cfa[rr+1][cc-1])+0.5*(cfa[rr][cc]-cfa[rr+2][cc-2]); - - - - float wtse=1.0f/(eps+SQR(cfa[rr+2][cc+2]-cfa[rr][cc])+SQR(cfa[rr+3][cc+3]-cfa[rr+1][cc+1])); - float wtnw=1.0f/(eps+SQR(cfa[rr-2][cc-2]-cfa[rr][cc])+SQR(cfa[rr-3][cc-3]-cfa[rr-1][cc-1])); - float wtne=1.0f/(eps+SQR(cfa[rr-2][cc+2]-cfa[rr][cc])+SQR(cfa[rr-3][cc+3]-cfa[rr-1][cc+1])); - float wtsw=1.0f/(eps+SQR(cfa[rr+2][cc-2]-cfa[rr][cc])+SQR(cfa[rr+3][cc-3]-cfa[rr+1][cc-1])); - - float ginterp=(gse*wtse+gnw*wtnw+gne*wtne+gsw*wtsw)/(wtse+wtnw+wtne+wtsw); - - if ( ((ginterp-gin) < thresh*(ginterp+gin)) ) { - rawData[rr][cc]=0.5f*(ginterp+gin); - //counter++; - } - - } - // } - } - //printf("pixfix count= %d; vtest= %d \n",counter,vtest); - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - // done - /*t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; - if (verbose) { - fprintf(stderr,_("elapsed time = %5.3fs\n"),dt); - }*/ - - + + for (int rr = 4; rr < height - 4; rr++) + for (int cc = 5 - (FC(rr, 2) & 1); cc < width - 6; cc += 2) { + //if (checker[rr][cc]) { + //%%%%%%%%%%%%%%%%%%%%%% + //neighbor checking code from Manuel Llorens Garcia + float o1_1 = cfa[(rr - 1)][cc - 1]; + float o1_2 = cfa[(rr - 1)][cc + 1]; + float o1_3 = cfa[(rr + 1)][cc - 1]; + float o1_4 = cfa[(rr + 1)][cc + 1]; + float o2_1 = cfa[(rr - 2)][cc]; + float o2_2 = cfa[(rr + 2)][cc]; + float o2_3 = cfa[(rr)][cc - 2]; + float o2_4 = cfa[(rr)][cc + 2]; + + float d1 = (o1_1 + o1_2 + o1_3 + o1_4) * 0.25f; + float d2 = (o2_1 + o2_2 + o2_3 + o2_4) * 0.25f; + + float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)) / 6.0; + float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)) / 6.0; + //%%%%%%%%%%%%%%%%%%%%%% + + //vote1=(checker[rr-2][cc]+checker[rr][cc-2]+checker[rr][cc+2]+checker[rr+2][cc]); + //vote2=(checker[rr+1][cc-1]+checker[rr+1][cc+1]+checker[rr-1][cc-1]+checker[rr-1][cc+1]); + //if ((vote1==0 || vote2==0) && (c1+c2)<2*thresh*fabs(d1-d2)) vtest++; + //if (vote1>0 && vote2>0 && (c1+c2)<4*thresh*fabs(d1-d2)) { + if ((c1 + c2) < 4 * thresh * fabs(d1 - d2)) { + //pixel interpolation + float gin = cfa[rr][cc]; + + float gse = (cfa[rr + 1][cc + 1]) + 0.5 * (cfa[rr][cc] - cfa[rr + 2][cc + 2]); + float gnw = (cfa[rr - 1][cc - 1]) + 0.5 * (cfa[rr][cc] - cfa[rr - 2][cc - 2]); + float gne = (cfa[rr - 1][cc + 1]) + 0.5 * (cfa[rr][cc] - cfa[rr - 2][cc + 2]); + float gsw = (cfa[rr + 1][cc - 1]) + 0.5 * (cfa[rr][cc] - cfa[rr + 2][cc - 2]); + + + + float wtse = 1.0f / (eps + SQR(cfa[rr + 2][cc + 2] - cfa[rr][cc]) + SQR(cfa[rr + 3][cc + 3] - cfa[rr + 1][cc + 1])); + float wtnw = 1.0f / (eps + SQR(cfa[rr - 2][cc - 2] - cfa[rr][cc]) + SQR(cfa[rr - 3][cc - 3] - cfa[rr - 1][cc - 1])); + float wtne = 1.0f / (eps + SQR(cfa[rr - 2][cc + 2] - cfa[rr][cc]) + SQR(cfa[rr - 3][cc + 3] - cfa[rr - 1][cc + 1])); + float wtsw = 1.0f / (eps + SQR(cfa[rr + 2][cc - 2] - cfa[rr][cc]) + SQR(cfa[rr + 3][cc - 3] - cfa[rr + 1][cc - 1])); + + float ginterp = (gse * wtse + gnw * wtnw + gne * wtne + gsw * wtsw) / (wtse + wtnw + wtne + wtsw); + + if ( ((ginterp - gin) < thresh * (ginterp + gin)) ) { + rawData[rr][cc] = 0.5f * (ginterp + gin); + //counter++; + } + + } + + // } + } + + //printf("pixfix count= %d; vtest= %d \n",counter,vtest); + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + // done + /*t2 = clock(); + dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; + if (verbose) { + fprintf(stderr,_("elapsed time = %5.3fs\n"),dt); + }*/ + + } } diff --git a/rtengine/helperavx.h b/rtengine/helperavx.h index e1b3dadee..eb32277c3 100644 --- a/rtengine/helperavx.h +++ b/rtengine/helperavx.h @@ -17,255 +17,510 @@ typedef __m256i vmask; typedef __m256 vfloat; typedef struct { - vint x, y; + vint x, y; } vint2; // -static INLINE vint vrint_vi_vd(vdouble vd) { return _mm256_cvtpd_epi32(vd); } -static INLINE vint vtruncate_vi_vd(vdouble vd) { return _mm256_cvttpd_epi32(vd); } -static INLINE vdouble vcast_vd_vi(vint vi) { return _mm256_cvtepi32_pd(vi); } -static INLINE vdouble vcast_vd_d(double d) { return _mm256_set_pd(d, d, d, d); } -static INLINE vint vcast_vi_i(int i) { return _mm_set_epi32(i, i, i, i); } - -static INLINE vmask vreinterpret_vm_vd(vdouble vd) { return (__m256i)vd; } -static INLINE vdouble vreinterpret_vd_vm(vmask vm) { return (__m256d)vm; } - -static INLINE vmask vreinterpret_vm_vf(vfloat vf) { return (__m256i)vf; } -static INLINE vfloat vreinterpret_vf_vm(vmask vm) { return (__m256)vm; } - -// - -static INLINE vfloat vcast_vf_f(float f) { return _mm256_set_ps(f, f, f, f, f, f, f, f); } - -static INLINE vfloat vaddf(vfloat x, vfloat y) { return _mm256_add_ps(x, y); } -static INLINE vfloat vsubf(vfloat x, vfloat y) { return _mm256_sub_ps(x, y); } -static INLINE vfloat vmulf(vfloat x, vfloat y) { return _mm256_mul_ps(x, y); } -static INLINE vfloat vdivf(vfloat x, vfloat y) { return _mm256_div_ps(x, y); } -static INLINE vfloat vrecf(vfloat x) { return vdivf(vcast_vf_f(1.0f), x); } -static INLINE vfloat vsqrtf(vfloat x) { return _mm256_sqrt_ps(x); } -static INLINE vfloat vmaxf(vfloat x, vfloat y) { return _mm256_max_ps(x, y); } -static INLINE vfloat vminf(vfloat x, vfloat y) { return _mm256_min_ps(x, y); } - -// - -static INLINE vdouble vadd(vdouble x, vdouble y) { return _mm256_add_pd(x, y); } -static INLINE vdouble vsub(vdouble x, vdouble y) { return _mm256_sub_pd(x, y); } -static INLINE vdouble vmul(vdouble x, vdouble y) { return _mm256_mul_pd(x, y); } -static INLINE vdouble vdiv(vdouble x, vdouble y) { return _mm256_div_pd(x, y); } -static INLINE vdouble vrec(vdouble x) { return _mm256_div_pd(_mm256_set_pd(1, 1, 1, 1), x); } -static INLINE vdouble vsqrt(vdouble x) { return _mm256_sqrt_pd(x); } -static INLINE vdouble vmla(vdouble x, vdouble y, vdouble z) { return vadd(vmul(x, y), z); } - -static INLINE vdouble vmax(vdouble x, vdouble y) { return _mm256_max_pd(x, y); } -static INLINE vdouble vmin(vdouble x, vdouble y) { return _mm256_min_pd(x, y); } - -static INLINE vdouble vabs(vdouble d) { return (__m256d)_mm256_andnot_pd(_mm256_set_pd(-0.0,-0.0,-0.0,-0.0), d); } -static INLINE vdouble vneg(vdouble d) { return (__m256d)_mm256_xor_pd(_mm256_set_pd(-0.0,-0.0,-0.0,-0.0), d); } - -// - -static INLINE vint vaddi(vint x, vint y) { return _mm_add_epi32(x, y); } -static INLINE vint vsubi(vint x, vint y) { return _mm_sub_epi32(x, y); } - -static INLINE vint vandi(vint x, vint y) { return _mm_and_si128(x, y); } -static INLINE vint vandnoti(vint x, vint y) { return _mm_andnot_si128(x, y); } -static INLINE vint vori(vint x, vint y) { return _mm_or_si128(x, y); } -static INLINE vint vxori(vint x, vint y) { return _mm_xor_si128(x, y); } - -static INLINE vint vslli(vint x, int c) { return _mm_slli_epi32 (x, c); } -static INLINE vint vsrli(vint x, int c) { return _mm_srli_epi32 (x, c); } -static INLINE vint vsrai(vint x, int c) { return _mm_srai_epi32 (x, c); } - -// - -static INLINE vmask vandm(vmask x, vmask y) { return (vmask)_mm256_and_pd((__m256d)x, (__m256d)y); } -static INLINE vmask vandnotm(vmask x, vmask y) { return (vmask)_mm256_andnot_pd((__m256d)x, (__m256d)y); } -static INLINE vmask vorm(vmask x, vmask y) { return (vmask)_mm256_or_pd((__m256d)x, (__m256d)y); } -static INLINE vmask vxorm(vmask x, vmask y) { return (vmask)_mm256_xor_pd((__m256d)x, (__m256d)y); } - -static INLINE vmask vmask_eq(vdouble x, vdouble y) { return (__m256i)_mm256_cmp_pd(x, y, _CMP_EQ_OQ); } -static INLINE vmask vmask_neq(vdouble x, vdouble y) { return (__m256i)_mm256_cmp_pd(x, y, _CMP_NEQ_OQ); } -static INLINE vmask vmask_lt(vdouble x, vdouble y) { return (__m256i)_mm256_cmp_pd(x, y, _CMP_LT_OQ); } -static INLINE vmask vmask_le(vdouble x, vdouble y) { return (__m256i)_mm256_cmp_pd(x, y, _CMP_LE_OQ); } -static INLINE vmask vmask_gt(vdouble x, vdouble y) { return (__m256i)_mm256_cmp_pd(x, y, _CMP_GT_OQ); } -static INLINE vmask vmask_ge(vdouble x, vdouble y) { return (__m256i)_mm256_cmp_pd(x, y, _CMP_GE_OQ); } - -static INLINE vmask vmaskf_eq(vfloat x, vfloat y) { return (__m256i)_mm256_cmp_ps(x, y, _CMP_EQ_OQ); } -static INLINE vmask vmaskf_neq(vfloat x, vfloat y) { return (__m256i)_mm256_cmp_ps(x, y, _CMP_NEQ_OQ); } -static INLINE vmask vmaskf_lt(vfloat x, vfloat y) { return (__m256i)_mm256_cmp_ps(x, y, _CMP_LT_OQ); } -static INLINE vmask vmaskf_le(vfloat x, vfloat y) { return (__m256i)_mm256_cmp_ps(x, y, _CMP_LE_OQ); } -static INLINE vmask vmaskf_gt(vfloat x, vfloat y) { return (__m256i)_mm256_cmp_ps(x, y, _CMP_GT_OQ); } -static INLINE vmask vmaskf_ge(vfloat x, vfloat y) { return (__m256i)_mm256_cmp_ps(x, y, _CMP_GE_OQ); } - -static INLINE vmask vmaski_eq(vint x, vint y) { - __m256d r = _mm256_cvtepi32_pd(_mm_and_si128(_mm_cmpeq_epi32(x, y), _mm_set_epi32(1, 1, 1, 1))); - return vmask_eq(r, _mm256_set_pd(1, 1, 1, 1)); +static INLINE vint vrint_vi_vd(vdouble vd) +{ + return _mm256_cvtpd_epi32(vd); +} +static INLINE vint vtruncate_vi_vd(vdouble vd) +{ + return _mm256_cvttpd_epi32(vd); +} +static INLINE vdouble vcast_vd_vi(vint vi) +{ + return _mm256_cvtepi32_pd(vi); +} +static INLINE vdouble vcast_vd_d(double d) +{ + return _mm256_set_pd(d, d, d, d); +} +static INLINE vint vcast_vi_i(int i) +{ + return _mm_set_epi32(i, i, i, i); } -static INLINE vdouble vsel(vmask mask, vdouble x, vdouble y) { - return (__m256d)vorm(vandm(mask, (__m256i)x), vandnotm(mask, (__m256i)y)); +static INLINE vmask vreinterpret_vm_vd(vdouble vd) +{ + return (__m256i)vd; +} +static INLINE vdouble vreinterpret_vd_vm(vmask vm) +{ + return (__m256d)vm; } -static INLINE vint vseli_lt(vdouble d0, vdouble d1, vint x, vint y) { - __m128i mask = _mm256_cvtpd_epi32(_mm256_and_pd(_mm256_cmp_pd(d0, d1, _CMP_LT_OQ), _mm256_set_pd(1.0, 1.0, 1.0, 1.0))); - mask = _mm_cmpeq_epi32(mask, _mm_set_epi32(1, 1, 1, 1)); - return vori(vandi(mask, x), vandnoti(mask, y)); +static INLINE vmask vreinterpret_vm_vf(vfloat vf) +{ + return (__m256i)vf; +} +static INLINE vfloat vreinterpret_vf_vm(vmask vm) +{ + return (__m256)vm; } // -static INLINE vint2 vcast_vi2_vm(vmask vm) { - vint2 r; - r.x = _mm256_castsi256_si128(vm); - r.y = _mm256_extractf128_si256(vm, 1); - return r; +static INLINE vfloat vcast_vf_f(float f) +{ + return _mm256_set_ps(f, f, f, f, f, f, f, f); } -static INLINE vmask vcast_vm_vi2(vint2 vi) { - vmask m = _mm256_castsi128_si256(vi.x); - m = _mm256_insertf128_si256(m, vi.y, 1); - return m; +static INLINE vfloat vaddf(vfloat x, vfloat y) +{ + return _mm256_add_ps(x, y); } - -static INLINE vint2 vrint_vi2_vf(vfloat vf) { return vcast_vi2_vm((vmask)_mm256_cvtps_epi32(vf)); } -static INLINE vint2 vtruncate_vi2_vf(vfloat vf) { return vcast_vi2_vm((vmask)_mm256_cvttps_epi32(vf)); } -static INLINE vfloat vcast_vf_vi2(vint2 vi) { return _mm256_cvtepi32_ps((vmask)vcast_vm_vi2(vi)); } -static INLINE vint2 vcast_vi2_i(int i) { vint2 r; r.x = r.y = vcast_vi_i(i); return r; } - -static INLINE vint2 vaddi2(vint2 x, vint2 y) { vint2 r; r.x = vaddi(x.x, y.x); r.y = vaddi(x.y, y.y); return r; } -static INLINE vint2 vsubi2(vint2 x, vint2 y) { vint2 r; r.x = vsubi(x.x, y.x); r.y = vsubi(x.y, y.y); return r; } - -static INLINE vint2 vandi2(vint2 x, vint2 y) { vint2 r; r.x = vandi(x.x, y.x); r.y = vandi(x.y, y.y); return r; } -static INLINE vint2 vandnoti2(vint2 x, vint2 y) { vint2 r; r.x = vandnoti(x.x, y.x); r.y = vandnoti(x.y, y.y); return r; } -static INLINE vint2 vori2(vint2 x, vint2 y) { vint2 r; r.x = vori(x.x, y.x); r.y = vori(x.y, y.y); return r; } -static INLINE vint2 vxori2(vint2 x, vint2 y) { vint2 r; r.x = vxori(x.x, y.x); r.y = vxori(x.y, y.y); return r; } - -static INLINE vint2 vslli2(vint2 x, int c) { vint2 r; r.x = vslli(x.x, c); r.y = vslli(x.y, c); return r; } -static INLINE vint2 vsrli2(vint2 x, int c) { vint2 r; r.x = vsrli(x.x, c); r.y = vsrli(x.y, c); return r; } -static INLINE vint2 vsrai2(vint2 x, int c) { vint2 r; r.x = vsrai(x.x, c); r.y = vsrai(x.y, c); return r; } - -static INLINE vmask vmaski2_eq(vint2 x, vint2 y) { - vint2 r; - r.x = _mm_cmpeq_epi32(x.x, y.x); - r.y = _mm_cmpeq_epi32(x.y, y.y); - return vcast_vm_vi2(r); +static INLINE vfloat vsubf(vfloat x, vfloat y) +{ + return _mm256_sub_ps(x, y); } - -static INLINE vint2 vseli2(vmask m, vint2 x, vint2 y) { - vint2 r, m2 = vcast_vi2_vm(m); - r.x = vori(vandi(m2.x, x.x), vandnoti(m2.x, y.x)); - r.y = vori(vandi(m2.y, x.y), vandnoti(m2.y, y.y)); - return r; +static INLINE vfloat vmulf(vfloat x, vfloat y) +{ + return _mm256_mul_ps(x, y); +} +static INLINE vfloat vdivf(vfloat x, vfloat y) +{ + return _mm256_div_ps(x, y); +} +static INLINE vfloat vrecf(vfloat x) +{ + return vdivf(vcast_vf_f(1.0f), x); +} +static INLINE vfloat vsqrtf(vfloat x) +{ + return _mm256_sqrt_ps(x); +} +static INLINE vfloat vmaxf(vfloat x, vfloat y) +{ + return _mm256_max_ps(x, y); +} +static INLINE vfloat vminf(vfloat x, vfloat y) +{ + return _mm256_min_ps(x, y); } // -static INLINE double vcast_d_vd(vdouble v) { - double s[4]; - _mm256_storeu_pd(s, v); - return s[0]; +static INLINE vdouble vadd(vdouble x, vdouble y) +{ + return _mm256_add_pd(x, y); +} +static INLINE vdouble vsub(vdouble x, vdouble y) +{ + return _mm256_sub_pd(x, y); +} +static INLINE vdouble vmul(vdouble x, vdouble y) +{ + return _mm256_mul_pd(x, y); +} +static INLINE vdouble vdiv(vdouble x, vdouble y) +{ + return _mm256_div_pd(x, y); +} +static INLINE vdouble vrec(vdouble x) +{ + return _mm256_div_pd(_mm256_set_pd(1, 1, 1, 1), x); +} +static INLINE vdouble vsqrt(vdouble x) +{ + return _mm256_sqrt_pd(x); +} +static INLINE vdouble vmla(vdouble x, vdouble y, vdouble z) +{ + return vadd(vmul(x, y), z); } -static INLINE float vcast_f_vf(vfloat v) { - float s[8]; - _mm256_storeu_ps(s, v); - return s[0]; +static INLINE vdouble vmax(vdouble x, vdouble y) +{ + return _mm256_max_pd(x, y); +} +static INLINE vdouble vmin(vdouble x, vdouble y) +{ + return _mm256_min_pd(x, y); } -static INLINE vmask vsignbit(vdouble d) { - return (vmask)_mm256_and_pd(d, _mm256_set_pd(-0.0,-0.0,-0.0,-0.0)); +static INLINE vdouble vabs(vdouble d) +{ + return (__m256d)_mm256_andnot_pd(_mm256_set_pd(-0.0, -0.0, -0.0, -0.0), d); +} +static INLINE vdouble vneg(vdouble d) +{ + return (__m256d)_mm256_xor_pd(_mm256_set_pd(-0.0, -0.0, -0.0, -0.0), d); } -static INLINE vdouble vsign(vdouble d) { - return _mm256_or_pd(_mm256_set_pd(1.0, 1.0, 1.0, 1.0), (vdouble)vsignbit(d)); +// + +static INLINE vint vaddi(vint x, vint y) +{ + return _mm_add_epi32(x, y); +} +static INLINE vint vsubi(vint x, vint y) +{ + return _mm_sub_epi32(x, y); } -static INLINE vdouble vmulsign(vdouble x, vdouble y) { - return (__m256d)vxorm((__m256i)x, vsignbit(y)); +static INLINE vint vandi(vint x, vint y) +{ + return _mm_and_si128(x, y); +} +static INLINE vint vandnoti(vint x, vint y) +{ + return _mm_andnot_si128(x, y); +} +static INLINE vint vori(vint x, vint y) +{ + return _mm_or_si128(x, y); +} +static INLINE vint vxori(vint x, vint y) +{ + return _mm_xor_si128(x, y); } -static INLINE vmask vmask_isinf(vdouble d) { - return (vmask)_mm256_cmp_pd(vabs(d), _mm256_set_pd(INFINITY, INFINITY, INFINITY, INFINITY), _CMP_EQ_OQ); +static INLINE vint vslli(vint x, int c) +{ + return _mm_slli_epi32 (x, c); +} +static INLINE vint vsrli(vint x, int c) +{ + return _mm_srli_epi32 (x, c); +} +static INLINE vint vsrai(vint x, int c) +{ + return _mm_srai_epi32 (x, c); } -static INLINE vmask vmask_ispinf(vdouble d) { - return (vmask)_mm256_cmp_pd(d, _mm256_set_pd(INFINITY, INFINITY, INFINITY, INFINITY), _CMP_EQ_OQ); +// + +static INLINE vmask vandm(vmask x, vmask y) +{ + return (vmask)_mm256_and_pd((__m256d)x, (__m256d)y); +} +static INLINE vmask vandnotm(vmask x, vmask y) +{ + return (vmask)_mm256_andnot_pd((__m256d)x, (__m256d)y); +} +static INLINE vmask vorm(vmask x, vmask y) +{ + return (vmask)_mm256_or_pd((__m256d)x, (__m256d)y); +} +static INLINE vmask vxorm(vmask x, vmask y) +{ + return (vmask)_mm256_xor_pd((__m256d)x, (__m256d)y); } -static INLINE vmask vmask_isminf(vdouble d) { - return (vmask)_mm256_cmp_pd(d, _mm256_set_pd(-INFINITY, -INFINITY, -INFINITY, -INFINITY), _CMP_EQ_OQ); +static INLINE vmask vmask_eq(vdouble x, vdouble y) +{ + return (__m256i)_mm256_cmp_pd(x, y, _CMP_EQ_OQ); +} +static INLINE vmask vmask_neq(vdouble x, vdouble y) +{ + return (__m256i)_mm256_cmp_pd(x, y, _CMP_NEQ_OQ); +} +static INLINE vmask vmask_lt(vdouble x, vdouble y) +{ + return (__m256i)_mm256_cmp_pd(x, y, _CMP_LT_OQ); +} +static INLINE vmask vmask_le(vdouble x, vdouble y) +{ + return (__m256i)_mm256_cmp_pd(x, y, _CMP_LE_OQ); +} +static INLINE vmask vmask_gt(vdouble x, vdouble y) +{ + return (__m256i)_mm256_cmp_pd(x, y, _CMP_GT_OQ); +} +static INLINE vmask vmask_ge(vdouble x, vdouble y) +{ + return (__m256i)_mm256_cmp_pd(x, y, _CMP_GE_OQ); } -static INLINE vmask vmask_isnan(vdouble d) { - return (vmask)_mm256_cmp_pd(d, d, _CMP_NEQ_UQ); +static INLINE vmask vmaskf_eq(vfloat x, vfloat y) +{ + return (__m256i)_mm256_cmp_ps(x, y, _CMP_EQ_OQ); +} +static INLINE vmask vmaskf_neq(vfloat x, vfloat y) +{ + return (__m256i)_mm256_cmp_ps(x, y, _CMP_NEQ_OQ); +} +static INLINE vmask vmaskf_lt(vfloat x, vfloat y) +{ + return (__m256i)_mm256_cmp_ps(x, y, _CMP_LT_OQ); +} +static INLINE vmask vmaskf_le(vfloat x, vfloat y) +{ + return (__m256i)_mm256_cmp_ps(x, y, _CMP_LE_OQ); +} +static INLINE vmask vmaskf_gt(vfloat x, vfloat y) +{ + return (__m256i)_mm256_cmp_ps(x, y, _CMP_GT_OQ); +} +static INLINE vmask vmaskf_ge(vfloat x, vfloat y) +{ + return (__m256i)_mm256_cmp_ps(x, y, _CMP_GE_OQ); } -static INLINE vdouble visinf(vdouble d) { - return _mm256_and_pd((vdouble)vmask_isinf(d), vsign(d)); +static INLINE vmask vmaski_eq(vint x, vint y) +{ + __m256d r = _mm256_cvtepi32_pd(_mm_and_si128(_mm_cmpeq_epi32(x, y), _mm_set_epi32(1, 1, 1, 1))); + return vmask_eq(r, _mm256_set_pd(1, 1, 1, 1)); } -static INLINE vdouble visinf2(vdouble d, vdouble m) { - return _mm256_and_pd((vdouble)vmask_isinf(d), _mm256_or_pd((vdouble)vsignbit(d), m)); +static INLINE vdouble vsel(vmask mask, vdouble x, vdouble y) +{ + return (__m256d)vorm(vandm(mask, (__m256i)x), vandnotm(mask, (__m256i)y)); } -static INLINE vdouble vpow2i(vint q) { - vint r; - vdouble y; - q = _mm_add_epi32(_mm_set_epi32(0x3ff, 0x3ff, 0x3ff, 0x3ff), q); - q = _mm_slli_epi32(q, 20); - r = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(1,0,0,0)); - y = _mm256_castpd128_pd256((__m128d)r); - r = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(3,2,2,2)); - y = _mm256_insertf128_pd(y, (__m128d)r, 1); - y = _mm256_and_pd(y, (__m256d)_mm256_set_epi32(0xfff00000, 0, 0xfff00000, 0, 0xfff00000, 0, 0xfff00000, 0)); - return y; +static INLINE vint vseli_lt(vdouble d0, vdouble d1, vint x, vint y) +{ + __m128i mask = _mm256_cvtpd_epi32(_mm256_and_pd(_mm256_cmp_pd(d0, d1, _CMP_LT_OQ), _mm256_set_pd(1.0, 1.0, 1.0, 1.0))); + mask = _mm_cmpeq_epi32(mask, _mm_set_epi32(1, 1, 1, 1)); + return vori(vandi(mask, x), vandnoti(mask, y)); } -static INLINE vdouble vldexp(vdouble x, vint q) { - vint m = _mm_srai_epi32(q, 31); - m = _mm_slli_epi32(_mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(m, q), 9), m), 7); - q = _mm_sub_epi32(q, _mm_slli_epi32(m, 2)); - vdouble y = vpow2i(m); - return vmul(vmul(vmul(vmul(vmul(x, y), y), y), y), vpow2i(q)); +// + +static INLINE vint2 vcast_vi2_vm(vmask vm) +{ + vint2 r; + r.x = _mm256_castsi256_si128(vm); + r.y = _mm256_extractf128_si256(vm, 1); + return r; } -static INLINE vint vilogbp1(vdouble d) { - vint q, r, c; - vmask m = vmask_lt(d, vcast_vd_d(4.9090934652977266E-91)); - d = vsel(m, vmul(vcast_vd_d(2.037035976334486E90), d), d); - c = _mm256_cvtpd_epi32(vsel(m, vcast_vd_d(300+0x3fe), vcast_vd_d(0x3fe))); - q = (__m128i)_mm256_castpd256_pd128(d); - q = (__m128i)_mm_shuffle_ps((__m128)q, _mm_set_ps(0, 0, 0, 0), _MM_SHUFFLE(0,0,3,1)); - r = (__m128i)_mm256_extractf128_pd(d, 1); - r = (__m128i)_mm_shuffle_ps(_mm_set_ps(0, 0, 0, 0), (__m128)r, _MM_SHUFFLE(3,1,0,0)); - q = _mm_or_si128(q, r); - q = _mm_srli_epi32(q, 20); - q = _mm_sub_epi32(q, c); - return q; +static INLINE vmask vcast_vm_vi2(vint2 vi) +{ + vmask m = _mm256_castsi128_si256(vi.x); + m = _mm256_insertf128_si256(m, vi.y, 1); + return m; } -static INLINE vdouble vupper(vdouble d) { - return (__m256d)_mm256_and_pd(d, (vdouble)_mm256_set_epi32(0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000)); +static INLINE vint2 vrint_vi2_vf(vfloat vf) +{ + return vcast_vi2_vm((vmask)_mm256_cvtps_epi32(vf)); +} +static INLINE vint2 vtruncate_vi2_vf(vfloat vf) +{ + return vcast_vi2_vm((vmask)_mm256_cvttps_epi32(vf)); +} +static INLINE vfloat vcast_vf_vi2(vint2 vi) +{ + return _mm256_cvtepi32_ps((vmask)vcast_vm_vi2(vi)); +} +static INLINE vint2 vcast_vi2_i(int i) +{ + vint2 r; + r.x = r.y = vcast_vi_i(i); + return r; +} + +static INLINE vint2 vaddi2(vint2 x, vint2 y) +{ + vint2 r; + r.x = vaddi(x.x, y.x); + r.y = vaddi(x.y, y.y); + return r; +} +static INLINE vint2 vsubi2(vint2 x, vint2 y) +{ + vint2 r; + r.x = vsubi(x.x, y.x); + r.y = vsubi(x.y, y.y); + return r; +} + +static INLINE vint2 vandi2(vint2 x, vint2 y) +{ + vint2 r; + r.x = vandi(x.x, y.x); + r.y = vandi(x.y, y.y); + return r; +} +static INLINE vint2 vandnoti2(vint2 x, vint2 y) +{ + vint2 r; + r.x = vandnoti(x.x, y.x); + r.y = vandnoti(x.y, y.y); + return r; +} +static INLINE vint2 vori2(vint2 x, vint2 y) +{ + vint2 r; + r.x = vori(x.x, y.x); + r.y = vori(x.y, y.y); + return r; +} +static INLINE vint2 vxori2(vint2 x, vint2 y) +{ + vint2 r; + r.x = vxori(x.x, y.x); + r.y = vxori(x.y, y.y); + return r; +} + +static INLINE vint2 vslli2(vint2 x, int c) +{ + vint2 r; + r.x = vslli(x.x, c); + r.y = vslli(x.y, c); + return r; +} +static INLINE vint2 vsrli2(vint2 x, int c) +{ + vint2 r; + r.x = vsrli(x.x, c); + r.y = vsrli(x.y, c); + return r; +} +static INLINE vint2 vsrai2(vint2 x, int c) +{ + vint2 r; + r.x = vsrai(x.x, c); + r.y = vsrai(x.y, c); + return r; +} + +static INLINE vmask vmaski2_eq(vint2 x, vint2 y) +{ + vint2 r; + r.x = _mm_cmpeq_epi32(x.x, y.x); + r.y = _mm_cmpeq_epi32(x.y, y.y); + return vcast_vm_vi2(r); +} + +static INLINE vint2 vseli2(vmask m, vint2 x, vint2 y) +{ + vint2 r, m2 = vcast_vi2_vm(m); + r.x = vori(vandi(m2.x, x.x), vandnoti(m2.x, y.x)); + r.y = vori(vandi(m2.y, x.y), vandnoti(m2.y, y.y)); + return r; +} + +// + +static INLINE double vcast_d_vd(vdouble v) +{ + double s[4]; + _mm256_storeu_pd(s, v); + return s[0]; +} + +static INLINE float vcast_f_vf(vfloat v) +{ + float s[8]; + _mm256_storeu_ps(s, v); + return s[0]; +} + +static INLINE vmask vsignbit(vdouble d) +{ + return (vmask)_mm256_and_pd(d, _mm256_set_pd(-0.0, -0.0, -0.0, -0.0)); +} + +static INLINE vdouble vsign(vdouble d) +{ + return _mm256_or_pd(_mm256_set_pd(1.0, 1.0, 1.0, 1.0), (vdouble)vsignbit(d)); +} + +static INLINE vdouble vmulsign(vdouble x, vdouble y) +{ + return (__m256d)vxorm((__m256i)x, vsignbit(y)); +} + +static INLINE vmask vmask_isinf(vdouble d) +{ + return (vmask)_mm256_cmp_pd(vabs(d), _mm256_set_pd(INFINITY, INFINITY, INFINITY, INFINITY), _CMP_EQ_OQ); +} + +static INLINE vmask vmask_ispinf(vdouble d) +{ + return (vmask)_mm256_cmp_pd(d, _mm256_set_pd(INFINITY, INFINITY, INFINITY, INFINITY), _CMP_EQ_OQ); +} + +static INLINE vmask vmask_isminf(vdouble d) +{ + return (vmask)_mm256_cmp_pd(d, _mm256_set_pd(-INFINITY, -INFINITY, -INFINITY, -INFINITY), _CMP_EQ_OQ); +} + +static INLINE vmask vmask_isnan(vdouble d) +{ + return (vmask)_mm256_cmp_pd(d, d, _CMP_NEQ_UQ); +} + +static INLINE vdouble visinf(vdouble d) +{ + return _mm256_and_pd((vdouble)vmask_isinf(d), vsign(d)); +} + +static INLINE vdouble visinf2(vdouble d, vdouble m) +{ + return _mm256_and_pd((vdouble)vmask_isinf(d), _mm256_or_pd((vdouble)vsignbit(d), m)); +} + +static INLINE vdouble vpow2i(vint q) +{ + vint r; + vdouble y; + q = _mm_add_epi32(_mm_set_epi32(0x3ff, 0x3ff, 0x3ff, 0x3ff), q); + q = _mm_slli_epi32(q, 20); + r = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(1, 0, 0, 0)); + y = _mm256_castpd128_pd256((__m128d)r); + r = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(3, 2, 2, 2)); + y = _mm256_insertf128_pd(y, (__m128d)r, 1); + y = _mm256_and_pd(y, (__m256d)_mm256_set_epi32(0xfff00000, 0, 0xfff00000, 0, 0xfff00000, 0, 0xfff00000, 0)); + return y; +} + +static INLINE vdouble vldexp(vdouble x, vint q) +{ + vint m = _mm_srai_epi32(q, 31); + m = _mm_slli_epi32(_mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(m, q), 9), m), 7); + q = _mm_sub_epi32(q, _mm_slli_epi32(m, 2)); + vdouble y = vpow2i(m); + return vmul(vmul(vmul(vmul(vmul(x, y), y), y), y), vpow2i(q)); +} + +static INLINE vint vilogbp1(vdouble d) +{ + vint q, r, c; + vmask m = vmask_lt(d, vcast_vd_d(4.9090934652977266E-91)); + d = vsel(m, vmul(vcast_vd_d(2.037035976334486E90), d), d); + c = _mm256_cvtpd_epi32(vsel(m, vcast_vd_d(300 + 0x3fe), vcast_vd_d(0x3fe))); + q = (__m128i)_mm256_castpd256_pd128(d); + q = (__m128i)_mm_shuffle_ps((__m128)q, _mm_set_ps(0, 0, 0, 0), _MM_SHUFFLE(0, 0, 3, 1)); + r = (__m128i)_mm256_extractf128_pd(d, 1); + r = (__m128i)_mm_shuffle_ps(_mm_set_ps(0, 0, 0, 0), (__m128)r, _MM_SHUFFLE(3, 1, 0, 0)); + q = _mm_or_si128(q, r); + q = _mm_srli_epi32(q, 20); + q = _mm_sub_epi32(q, c); + return q; +} + +static INLINE vdouble vupper(vdouble d) +{ + return (__m256d)_mm256_and_pd(d, (vdouble)_mm256_set_epi32(0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000)); } // typedef struct { - vdouble x, y; + vdouble x, y; } vdouble2; -static INLINE vdouble2 dd(vdouble h, vdouble l) { - vdouble2 ret = {h, l}; - return ret; +static INLINE vdouble2 dd(vdouble h, vdouble l) +{ + vdouble2 ret = {h, l}; + return ret; } -static INLINE vdouble2 vsel2(vmask mask, vdouble2 x, vdouble2 y) { - return dd((__m256d)vorm(vandm(mask, (__m256i)x.x), vandnotm(mask, (__m256i)y.x)), - (__m256d)vorm(vandm(mask, (__m256i)x.y), vandnotm(mask, (__m256i)y.y))); +static INLINE vdouble2 vsel2(vmask mask, vdouble2 x, vdouble2 y) +{ + return dd((__m256d)vorm(vandm(mask, (__m256i)x.x), vandnotm(mask, (__m256i)y.x)), + (__m256d)vorm(vandm(mask, (__m256i)x.y), vandnotm(mask, (__m256i)y.y))); } -static INLINE vdouble2 abs_d(vdouble2 x) { - return dd((__m256d)_mm256_xor_pd(_mm256_and_pd(_mm256_set_pd(-0.0,-0.0,-0.0,-0.0), x.x), x.x), - (__m256d)_mm256_xor_pd(_mm256_and_pd(_mm256_set_pd(-0.0,-0.0,-0.0,-0.0), x.x), x.y)); +static INLINE vdouble2 abs_d(vdouble2 x) +{ + return dd((__m256d)_mm256_xor_pd(_mm256_and_pd(_mm256_set_pd(-0.0, -0.0, -0.0, -0.0), x.x), x.x), + (__m256d)_mm256_xor_pd(_mm256_and_pd(_mm256_set_pd(-0.0, -0.0, -0.0, -0.0), x.x), x.y)); } diff --git a/rtengine/helpersse2.h b/rtengine/helpersse2.h index 8d35a40d5..5969784a4 100644 --- a/rtengine/helpersse2.h +++ b/rtengine/helpersse2.h @@ -22,19 +22,19 @@ typedef __m128i vint2; // #ifdef __GNUC__ - #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 - #define LVF(x) _mm_load_ps(&x) - #define LVFU(x) _mm_loadu_ps(&x) - #define STVF(x,y) _mm_store_ps(&x,y) - #else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3 - #define LVF(x) _mm_loadu_ps(&x) - #define LVFU(x) _mm_loadu_ps(&x) - #define STVF(x,y) _mm_storeu_ps(&x,y) - #endif -#else - #define LVF(x) _mm_load_ps(&x) - #define LVFU(x) _mm_loadu_ps(&x) - #define STVF(x,y) _mm_store_ps(&x,y) +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 +#define LVF(x) _mm_load_ps(&x) +#define LVFU(x) _mm_loadu_ps(&x) +#define STVF(x,y) _mm_store_ps(&x,y) +#else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3 +#define LVF(x) _mm_loadu_ps(&x) +#define LVFU(x) _mm_loadu_ps(&x) +#define STVF(x,y) _mm_storeu_ps(&x,y) +#endif +#else +#define LVF(x) _mm_load_ps(&x) +#define LVFU(x) _mm_loadu_ps(&x) +#define STVF(x,y) _mm_store_ps(&x,y) #endif // Load 8 floats from a and combine a[0],a[2],a[4] and a[6] into a vector of 4 floats @@ -43,244 +43,481 @@ typedef __m128i vint2; // Store a vector of 4 floats in a[0],a[2],a[4] and a[6] #if defined(__x86_64__) && defined(__SSE4_1__) // SSE4.1 => use _mm_blend_ps instead of _mm_set_epi32 and vself - #define STC2VFU(a,v) {\ - __m128 TST1V = _mm_loadu_ps(&a);\ - __m128 TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 1,1,0,0 ));\ - _mm_storeu_ps(&a, _mm_blend_ps(TST1V,TST2V,5));\ - TST1V = _mm_loadu_ps((&a)+4);\ - TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 3,3,2,2 ));\ - _mm_storeu_ps((&a)+4, _mm_blend_ps(TST1V,TST2V,5));\ - } +#define STC2VFU(a,v) {\ + __m128 TST1V = _mm_loadu_ps(&a);\ + __m128 TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 1,1,0,0 ));\ + _mm_storeu_ps(&a, _mm_blend_ps(TST1V,TST2V,5));\ + TST1V = _mm_loadu_ps((&a)+4);\ + TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 3,3,2,2 ));\ + _mm_storeu_ps((&a)+4, _mm_blend_ps(TST1V,TST2V,5));\ + } #else - #define STC2VFU(a,v) {\ - __m128 TST1V = _mm_loadu_ps(&a);\ - __m128 TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 1,1,0,0 ));\ - vmask cmask = _mm_set_epi32(0xffffffff,0,0xffffffff,0);\ - _mm_storeu_ps(&a, vself(cmask,TST1V,TST2V));\ - TST1V = _mm_loadu_ps((&a)+4);\ - TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 3,3,2,2 ));\ - _mm_storeu_ps((&a)+4, vself(cmask,TST1V,TST2V));\ - } +#define STC2VFU(a,v) {\ + __m128 TST1V = _mm_loadu_ps(&a);\ + __m128 TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 1,1,0,0 ));\ + vmask cmask = _mm_set_epi32(0xffffffff,0,0xffffffff,0);\ + _mm_storeu_ps(&a, vself(cmask,TST1V,TST2V));\ + TST1V = _mm_loadu_ps((&a)+4);\ + TST2V = _mm_shuffle_ps(v,v,_MM_SHUFFLE( 3,3,2,2 ));\ + _mm_storeu_ps((&a)+4, vself(cmask,TST1V,TST2V));\ + } #endif #define ZEROV _mm_setzero_ps() #define F2V(a) _mm_set1_ps((a)) -static INLINE vint vrint_vi_vd(vdouble vd) { return _mm_cvtpd_epi32(vd); } -static INLINE vint vtruncate_vi_vd(vdouble vd) { return _mm_cvttpd_epi32(vd); } -static INLINE vdouble vcast_vd_vi(vint vi) { return _mm_cvtepi32_pd(vi); } -static INLINE vdouble vcast_vd_d(double d) { return _mm_set_pd(d, d); } -static INLINE vint vcast_vi_i(int i) { return _mm_set_epi32(0, 0, i, i); } - -static INLINE vmask vreinterpret_vm_vd(vdouble vd) { return (__m128i)vd; } -static INLINE vdouble vreinterpret_vd_vm(vint vm) { return (__m128d)vm; } - -static INLINE vmask vreinterpret_vm_vf(vfloat vf) { return (__m128i)vf; } -static INLINE vfloat vreinterpret_vf_vm(vmask vm) { return (__m128)vm; } - -// - -static INLINE vfloat vcast_vf_f(float f) { return _mm_set_ps(f, f, f, f); } - -static INLINE vfloat vaddf(vfloat x, vfloat y) { return _mm_add_ps(x, y); } -static INLINE vfloat vsubf(vfloat x, vfloat y) { return _mm_sub_ps(x, y); } -static INLINE vfloat vmulf(vfloat x, vfloat y) { return _mm_mul_ps(x, y); } -static INLINE vfloat vdivf(vfloat x, vfloat y) { return _mm_div_ps(x, y); } -static INLINE vfloat vrecf(vfloat x) { return vdivf(vcast_vf_f(1.0f), x); } -static INLINE vfloat vsqrtf(vfloat x) { return _mm_sqrt_ps(x); } -static INLINE vfloat vmaxf(vfloat x, vfloat y) { return _mm_max_ps(x, y); } -static INLINE vfloat vminf(vfloat x, vfloat y) { return _mm_min_ps(x, y); } - -// - -static INLINE vdouble vadd(vdouble x, vdouble y) { return _mm_add_pd(x, y); } -static INLINE vdouble vsub(vdouble x, vdouble y) { return _mm_sub_pd(x, y); } -static INLINE vdouble vmul(vdouble x, vdouble y) { return _mm_mul_pd(x, y); } -static INLINE vdouble vdiv(vdouble x, vdouble y) { return _mm_div_pd(x, y); } -static INLINE vdouble vrec(vdouble x) { return _mm_div_pd(_mm_set_pd(1, 1), x); } -static INLINE vdouble vsqrt(vdouble x) { return _mm_sqrt_pd(x); } -static INLINE vdouble vmla(vdouble x, vdouble y, vdouble z) { return vadd(vmul(x, y), z); } - -static INLINE vdouble vmax(vdouble x, vdouble y) { return _mm_max_pd(x, y); } -static INLINE vdouble vmin(vdouble x, vdouble y) { return _mm_min_pd(x, y); } - -static INLINE vdouble vabs(vdouble d) { return (__m128d)_mm_andnot_pd(_mm_set_pd(-0.0,-0.0), d); } -static INLINE vdouble vneg(vdouble d) { return (__m128d)_mm_xor_pd(_mm_set_pd(-0.0,-0.0), d); } - -// - -static INLINE vint vaddi(vint x, vint y) { return _mm_add_epi32(x, y); } -static INLINE vint vsubi(vint x, vint y) { return _mm_sub_epi32(x, y); } - -static INLINE vint vandi(vint x, vint y) { return _mm_and_si128(x, y); } -static INLINE vint vandnoti(vint x, vint y) { return _mm_andnot_si128(x, y); } -static INLINE vint vori(vint x, vint y) { return _mm_or_si128(x, y); } -static INLINE vint vxori(vint x, vint y) { return _mm_xor_si128(x, y); } - -static INLINE vint vslli(vint x, int c) { return _mm_slli_epi32(x, c); } -static INLINE vint vsrli(vint x, int c) { return _mm_srli_epi32(x, c); } -static INLINE vint vsrai(vint x, int c) { return _mm_srai_epi32(x, c); } - -// - -static INLINE vmask vandm(vmask x, vmask y) { return _mm_and_si128(x, y); } -static INLINE vmask vandnotm(vmask x, vmask y) { return _mm_andnot_si128(x, y); } -static INLINE vmask vorm(vmask x, vmask y) { return _mm_or_si128(x, y); } -static INLINE vmask vxorm(vmask x, vmask y) { return _mm_xor_si128(x, y); } -static INLINE vmask vnotm(vmask x) { return _mm_xor_si128(x, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())); } - -static INLINE vmask vmask_eq(vdouble x, vdouble y) { return (__m128i)_mm_cmpeq_pd(x, y); } -static INLINE vmask vmask_neq(vdouble x, vdouble y) { return (__m128i)_mm_cmpneq_pd(x, y); } -static INLINE vmask vmask_lt(vdouble x, vdouble y) { return (__m128i)_mm_cmplt_pd(x, y); } -static INLINE vmask vmask_le(vdouble x, vdouble y) { return (__m128i)_mm_cmple_pd(x, y); } -static INLINE vmask vmask_gt(vdouble x, vdouble y) { return (__m128i)_mm_cmpgt_pd(x, y); } -static INLINE vmask vmask_ge(vdouble x, vdouble y) { return (__m128i)_mm_cmpge_pd(x, y); } - -static INLINE vmask vmaskf_eq(vfloat x, vfloat y) { return (__m128i)_mm_cmpeq_ps(x, y); } -static INLINE vmask vmaskf_neq(vfloat x, vfloat y) { return (__m128i)_mm_cmpneq_ps(x, y); } -static INLINE vmask vmaskf_lt(vfloat x, vfloat y) { return (__m128i)_mm_cmplt_ps(x, y); } -static INLINE vmask vmaskf_le(vfloat x, vfloat y) { return (__m128i)_mm_cmple_ps(x, y); } -static INLINE vmask vmaskf_gt(vfloat x, vfloat y) { return (__m128i)_mm_cmpgt_ps(x, y); } -static INLINE vmask vmaskf_ge(vfloat x, vfloat y) { return (__m128i)_mm_cmpge_ps(x, y); } - - -static INLINE vmask vmaski_eq(vint x, vint y) { - __m128 s = (__m128)_mm_cmpeq_epi32(x, y); - return (__m128i)_mm_shuffle_ps(s, s, _MM_SHUFFLE(1, 1, 0, 0)); +static INLINE vint vrint_vi_vd(vdouble vd) +{ + return _mm_cvtpd_epi32(vd); +} +static INLINE vint vtruncate_vi_vd(vdouble vd) +{ + return _mm_cvttpd_epi32(vd); +} +static INLINE vdouble vcast_vd_vi(vint vi) +{ + return _mm_cvtepi32_pd(vi); +} +static INLINE vdouble vcast_vd_d(double d) +{ + return _mm_set_pd(d, d); +} +static INLINE vint vcast_vi_i(int i) +{ + return _mm_set_epi32(0, 0, i, i); } -static INLINE vdouble vsel(vmask mask, vdouble x, vdouble y) { - return (__m128d)vorm(vandm(mask, (__m128i)x), vandnotm(mask, (__m128i)y)); +static INLINE vmask vreinterpret_vm_vd(vdouble vd) +{ + return (__m128i)vd; +} +static INLINE vdouble vreinterpret_vd_vm(vint vm) +{ + return (__m128d)vm; } -static INLINE vint vseli_lt(vdouble d0, vdouble d1, vint x, vint y) { - vmask mask = (vmask)_mm_cmpeq_ps(_mm_cvtpd_ps((vdouble)vmask_lt(d0, d1)), _mm_set_ps(0, 0, 0, 0)); - return vori(vandnoti(mask, x), vandi(mask, y)); +static INLINE vmask vreinterpret_vm_vf(vfloat vf) +{ + return (__m128i)vf; +} +static INLINE vfloat vreinterpret_vf_vm(vmask vm) +{ + return (__m128)vm; } // -static INLINE vint2 vcast_vi2_vm(vmask vm) { return (vint2)vm; } -static INLINE vmask vcast_vm_vi2(vint2 vi) { return (vmask)vi; } - -static INLINE vint2 vrint_vi2_vf(vfloat vf) { return _mm_cvtps_epi32(vf); } -static INLINE vint2 vtruncate_vi2_vf(vfloat vf) { return _mm_cvttps_epi32(vf); } -static INLINE vfloat vcast_vf_vi2(vint2 vi) { return _mm_cvtepi32_ps(vcast_vm_vi2(vi)); } -static INLINE vint2 vcast_vi2_i(int i) { return _mm_set_epi32(i, i, i, i); } - -static INLINE vint2 vaddi2(vint2 x, vint2 y) { return vaddi(x, y); } -static INLINE vint2 vsubi2(vint2 x, vint2 y) { return vsubi(x, y); } - -static INLINE vint2 vandi2(vint2 x, vint2 y) { return vandi(x, y); } -static INLINE vint2 vandnoti2(vint2 x, vint2 y) { return vandnoti(x, y); } -static INLINE vint2 vori2(vint2 x, vint2 y) { return vori(x, y); } -static INLINE vint2 vxori2(vint2 x, vint2 y) { return vxori(x, y); } - -static INLINE vint2 vslli2(vint2 x, int c) { return vslli(x, c); } -static INLINE vint2 vsrli2(vint2 x, int c) { return vsrli(x, c); } -static INLINE vint2 vsrai2(vint2 x, int c) { return vsrai(x, c); } - -static INLINE vmask vmaski2_eq(vint2 x, vint2 y) { return _mm_cmpeq_epi32(x, y); } -static INLINE vint2 vseli2(vmask m, vint2 x, vint2 y) { return vorm(vandm(m, x), vandnotm(m, y)); } - -// - -static INLINE double vcast_d_vd(vdouble v) { - double s[2]; - _mm_storeu_pd(s, v); - return s[0]; +static INLINE vfloat vcast_vf_f(float f) +{ + return _mm_set_ps(f, f, f, f); } -static INLINE float vcast_f_vf(vfloat v) { - float s[4]; - _mm_storeu_ps(s, v); - return s[0]; +static INLINE vfloat vaddf(vfloat x, vfloat y) +{ + return _mm_add_ps(x, y); } - -static INLINE vmask vsignbit(vdouble d) { - return _mm_and_si128((__m128i)d, _mm_set_epi32(0x80000000, 0x0, 0x80000000, 0x0)); +static INLINE vfloat vsubf(vfloat x, vfloat y) +{ + return _mm_sub_ps(x, y); } - -static INLINE vdouble vsign(vdouble d) { - return (__m128d)_mm_or_si128((__m128i)_mm_set_pd(1, 1), _mm_and_si128((__m128i)d, _mm_set_epi32(0x80000000, 0x0, 0x80000000, 0x0))); +static INLINE vfloat vmulf(vfloat x, vfloat y) +{ + return _mm_mul_ps(x, y); } - -static INLINE vdouble vmulsign(vdouble x, vdouble y) { - return (__m128d)vxori((__m128i)x, vsignbit(y)); +static INLINE vfloat vdivf(vfloat x, vfloat y) +{ + return _mm_div_ps(x, y); } - -static INLINE vmask vmask_isinf(vdouble d) { - return (vmask)_mm_cmpeq_pd(vabs(d), _mm_set_pd(INFINITY, INFINITY)); +static INLINE vfloat vrecf(vfloat x) +{ + return vdivf(vcast_vf_f(1.0f), x); } - -static INLINE vmask vmask_ispinf(vdouble d) { - return (vmask)_mm_cmpeq_pd(d, _mm_set_pd(INFINITY, INFINITY)); +static INLINE vfloat vsqrtf(vfloat x) +{ + return _mm_sqrt_ps(x); } - -static INLINE vmask vmask_isminf(vdouble d) { - return (vmask)_mm_cmpeq_pd(d, _mm_set_pd(-INFINITY, -INFINITY)); +static INLINE vfloat vmaxf(vfloat x, vfloat y) +{ + return _mm_max_ps(x, y); } - -static INLINE vmask vmask_isnan(vdouble d) { - return (vmask)_mm_cmpneq_pd(d, d); -} - -static INLINE vdouble visinf(vdouble d) { - return (__m128d)_mm_and_si128(vmask_isinf(d), _mm_or_si128(vsignbit(d), (__m128i)_mm_set_pd(1, 1))); -} - -static INLINE vdouble visinf2(vdouble d, vdouble m) { - return (__m128d)_mm_and_si128(vmask_isinf(d), _mm_or_si128(vsignbit(d), (__m128i)m)); +static INLINE vfloat vminf(vfloat x, vfloat y) +{ + return _mm_min_ps(x, y); } // -static INLINE vdouble vpow2i(vint q) { - q = _mm_add_epi32(_mm_set_epi32(0x0, 0x0, 0x3ff, 0x3ff), q); - q = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(1,3,0,3)); - return (__m128d)_mm_slli_epi32(q, 20); +static INLINE vdouble vadd(vdouble x, vdouble y) +{ + return _mm_add_pd(x, y); +} +static INLINE vdouble vsub(vdouble x, vdouble y) +{ + return _mm_sub_pd(x, y); +} +static INLINE vdouble vmul(vdouble x, vdouble y) +{ + return _mm_mul_pd(x, y); +} +static INLINE vdouble vdiv(vdouble x, vdouble y) +{ + return _mm_div_pd(x, y); +} +static INLINE vdouble vrec(vdouble x) +{ + return _mm_div_pd(_mm_set_pd(1, 1), x); +} +static INLINE vdouble vsqrt(vdouble x) +{ + return _mm_sqrt_pd(x); +} +static INLINE vdouble vmla(vdouble x, vdouble y, vdouble z) +{ + return vadd(vmul(x, y), z); } -static INLINE vdouble vldexp(vdouble x, vint q) { - vint m = _mm_srai_epi32(q, 31); - m = _mm_slli_epi32(_mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(m, q), 9), m), 7); - q = _mm_sub_epi32(q, _mm_slli_epi32(m, 2)); - vdouble y = vpow2i(m); - return vmul(vmul(vmul(vmul(vmul(x, y), y), y), y), vpow2i(q)); +static INLINE vdouble vmax(vdouble x, vdouble y) +{ + return _mm_max_pd(x, y); +} +static INLINE vdouble vmin(vdouble x, vdouble y) +{ + return _mm_min_pd(x, y); } -static INLINE vint vilogbp1(vdouble d) { - vint m = vmask_lt(d, vcast_vd_d(4.9090934652977266E-91)); - d = vsel(m, vmul(vcast_vd_d(2.037035976334486E90), d), d); - __m128i q = _mm_and_si128((__m128i)d, _mm_set_epi32(((1 << 12)-1) << 20, 0, ((1 << 12)-1) << 20, 0)); - q = _mm_srli_epi32(q, 20); - q = vorm(vandm (m, _mm_sub_epi32(q, _mm_set_epi32(300 + 0x3fe, 0, 300 + 0x3fe, 0))), - vandnotm(m, _mm_sub_epi32(q, _mm_set_epi32( 0x3fe, 0, 0x3fe, 0)))); - q = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(0,0,3,1)); - return q; +static INLINE vdouble vabs(vdouble d) +{ + return (__m128d)_mm_andnot_pd(_mm_set_pd(-0.0, -0.0), d); +} +static INLINE vdouble vneg(vdouble d) +{ + return (__m128d)_mm_xor_pd(_mm_set_pd(-0.0, -0.0), d); } -static INLINE vdouble vupper(vdouble d) { - return (__m128d)_mm_and_si128((__m128i)d, _mm_set_epi32(0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000)); +// + +static INLINE vint vaddi(vint x, vint y) +{ + return _mm_add_epi32(x, y); +} +static INLINE vint vsubi(vint x, vint y) +{ + return _mm_sub_epi32(x, y); +} + +static INLINE vint vandi(vint x, vint y) +{ + return _mm_and_si128(x, y); +} +static INLINE vint vandnoti(vint x, vint y) +{ + return _mm_andnot_si128(x, y); +} +static INLINE vint vori(vint x, vint y) +{ + return _mm_or_si128(x, y); +} +static INLINE vint vxori(vint x, vint y) +{ + return _mm_xor_si128(x, y); +} + +static INLINE vint vslli(vint x, int c) +{ + return _mm_slli_epi32(x, c); +} +static INLINE vint vsrli(vint x, int c) +{ + return _mm_srli_epi32(x, c); +} +static INLINE vint vsrai(vint x, int c) +{ + return _mm_srai_epi32(x, c); +} + +// + +static INLINE vmask vandm(vmask x, vmask y) +{ + return _mm_and_si128(x, y); +} +static INLINE vmask vandnotm(vmask x, vmask y) +{ + return _mm_andnot_si128(x, y); +} +static INLINE vmask vorm(vmask x, vmask y) +{ + return _mm_or_si128(x, y); +} +static INLINE vmask vxorm(vmask x, vmask y) +{ + return _mm_xor_si128(x, y); +} +static INLINE vmask vnotm(vmask x) +{ + return _mm_xor_si128(x, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())); +} + +static INLINE vmask vmask_eq(vdouble x, vdouble y) +{ + return (__m128i)_mm_cmpeq_pd(x, y); +} +static INLINE vmask vmask_neq(vdouble x, vdouble y) +{ + return (__m128i)_mm_cmpneq_pd(x, y); +} +static INLINE vmask vmask_lt(vdouble x, vdouble y) +{ + return (__m128i)_mm_cmplt_pd(x, y); +} +static INLINE vmask vmask_le(vdouble x, vdouble y) +{ + return (__m128i)_mm_cmple_pd(x, y); +} +static INLINE vmask vmask_gt(vdouble x, vdouble y) +{ + return (__m128i)_mm_cmpgt_pd(x, y); +} +static INLINE vmask vmask_ge(vdouble x, vdouble y) +{ + return (__m128i)_mm_cmpge_pd(x, y); +} + +static INLINE vmask vmaskf_eq(vfloat x, vfloat y) +{ + return (__m128i)_mm_cmpeq_ps(x, y); +} +static INLINE vmask vmaskf_neq(vfloat x, vfloat y) +{ + return (__m128i)_mm_cmpneq_ps(x, y); +} +static INLINE vmask vmaskf_lt(vfloat x, vfloat y) +{ + return (__m128i)_mm_cmplt_ps(x, y); +} +static INLINE vmask vmaskf_le(vfloat x, vfloat y) +{ + return (__m128i)_mm_cmple_ps(x, y); +} +static INLINE vmask vmaskf_gt(vfloat x, vfloat y) +{ + return (__m128i)_mm_cmpgt_ps(x, y); +} +static INLINE vmask vmaskf_ge(vfloat x, vfloat y) +{ + return (__m128i)_mm_cmpge_ps(x, y); +} + + +static INLINE vmask vmaski_eq(vint x, vint y) +{ + __m128 s = (__m128)_mm_cmpeq_epi32(x, y); + return (__m128i)_mm_shuffle_ps(s, s, _MM_SHUFFLE(1, 1, 0, 0)); +} + +static INLINE vdouble vsel(vmask mask, vdouble x, vdouble y) +{ + return (__m128d)vorm(vandm(mask, (__m128i)x), vandnotm(mask, (__m128i)y)); +} + +static INLINE vint vseli_lt(vdouble d0, vdouble d1, vint x, vint y) +{ + vmask mask = (vmask)_mm_cmpeq_ps(_mm_cvtpd_ps((vdouble)vmask_lt(d0, d1)), _mm_set_ps(0, 0, 0, 0)); + return vori(vandnoti(mask, x), vandi(mask, y)); +} + +// + +static INLINE vint2 vcast_vi2_vm(vmask vm) +{ + return (vint2)vm; +} +static INLINE vmask vcast_vm_vi2(vint2 vi) +{ + return (vmask)vi; +} + +static INLINE vint2 vrint_vi2_vf(vfloat vf) +{ + return _mm_cvtps_epi32(vf); +} +static INLINE vint2 vtruncate_vi2_vf(vfloat vf) +{ + return _mm_cvttps_epi32(vf); +} +static INLINE vfloat vcast_vf_vi2(vint2 vi) +{ + return _mm_cvtepi32_ps(vcast_vm_vi2(vi)); +} +static INLINE vint2 vcast_vi2_i(int i) +{ + return _mm_set_epi32(i, i, i, i); +} + +static INLINE vint2 vaddi2(vint2 x, vint2 y) +{ + return vaddi(x, y); +} +static INLINE vint2 vsubi2(vint2 x, vint2 y) +{ + return vsubi(x, y); +} + +static INLINE vint2 vandi2(vint2 x, vint2 y) +{ + return vandi(x, y); +} +static INLINE vint2 vandnoti2(vint2 x, vint2 y) +{ + return vandnoti(x, y); +} +static INLINE vint2 vori2(vint2 x, vint2 y) +{ + return vori(x, y); +} +static INLINE vint2 vxori2(vint2 x, vint2 y) +{ + return vxori(x, y); +} + +static INLINE vint2 vslli2(vint2 x, int c) +{ + return vslli(x, c); +} +static INLINE vint2 vsrli2(vint2 x, int c) +{ + return vsrli(x, c); +} +static INLINE vint2 vsrai2(vint2 x, int c) +{ + return vsrai(x, c); +} + +static INLINE vmask vmaski2_eq(vint2 x, vint2 y) +{ + return _mm_cmpeq_epi32(x, y); +} +static INLINE vint2 vseli2(vmask m, vint2 x, vint2 y) +{ + return vorm(vandm(m, x), vandnotm(m, y)); +} + +// + +static INLINE double vcast_d_vd(vdouble v) +{ + double s[2]; + _mm_storeu_pd(s, v); + return s[0]; +} + +static INLINE float vcast_f_vf(vfloat v) +{ + float s[4]; + _mm_storeu_ps(s, v); + return s[0]; +} + +static INLINE vmask vsignbit(vdouble d) +{ + return _mm_and_si128((__m128i)d, _mm_set_epi32(0x80000000, 0x0, 0x80000000, 0x0)); +} + +static INLINE vdouble vsign(vdouble d) +{ + return (__m128d)_mm_or_si128((__m128i)_mm_set_pd(1, 1), _mm_and_si128((__m128i)d, _mm_set_epi32(0x80000000, 0x0, 0x80000000, 0x0))); +} + +static INLINE vdouble vmulsign(vdouble x, vdouble y) +{ + return (__m128d)vxori((__m128i)x, vsignbit(y)); +} + +static INLINE vmask vmask_isinf(vdouble d) +{ + return (vmask)_mm_cmpeq_pd(vabs(d), _mm_set_pd(INFINITY, INFINITY)); +} + +static INLINE vmask vmask_ispinf(vdouble d) +{ + return (vmask)_mm_cmpeq_pd(d, _mm_set_pd(INFINITY, INFINITY)); +} + +static INLINE vmask vmask_isminf(vdouble d) +{ + return (vmask)_mm_cmpeq_pd(d, _mm_set_pd(-INFINITY, -INFINITY)); +} + +static INLINE vmask vmask_isnan(vdouble d) +{ + return (vmask)_mm_cmpneq_pd(d, d); +} + +static INLINE vdouble visinf(vdouble d) +{ + return (__m128d)_mm_and_si128(vmask_isinf(d), _mm_or_si128(vsignbit(d), (__m128i)_mm_set_pd(1, 1))); +} + +static INLINE vdouble visinf2(vdouble d, vdouble m) +{ + return (__m128d)_mm_and_si128(vmask_isinf(d), _mm_or_si128(vsignbit(d), (__m128i)m)); +} + +// + +static INLINE vdouble vpow2i(vint q) +{ + q = _mm_add_epi32(_mm_set_epi32(0x0, 0x0, 0x3ff, 0x3ff), q); + q = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(1, 3, 0, 3)); + return (__m128d)_mm_slli_epi32(q, 20); +} + +static INLINE vdouble vldexp(vdouble x, vint q) +{ + vint m = _mm_srai_epi32(q, 31); + m = _mm_slli_epi32(_mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(m, q), 9), m), 7); + q = _mm_sub_epi32(q, _mm_slli_epi32(m, 2)); + vdouble y = vpow2i(m); + return vmul(vmul(vmul(vmul(vmul(x, y), y), y), y), vpow2i(q)); +} + +static INLINE vint vilogbp1(vdouble d) +{ + vint m = vmask_lt(d, vcast_vd_d(4.9090934652977266E-91)); + d = vsel(m, vmul(vcast_vd_d(2.037035976334486E90), d), d); + __m128i q = _mm_and_si128((__m128i)d, _mm_set_epi32(((1 << 12) - 1) << 20, 0, ((1 << 12) - 1) << 20, 0)); + q = _mm_srli_epi32(q, 20); + q = vorm(vandm (m, _mm_sub_epi32(q, _mm_set_epi32(300 + 0x3fe, 0, 300 + 0x3fe, 0))), + vandnotm(m, _mm_sub_epi32(q, _mm_set_epi32( 0x3fe, 0, 0x3fe, 0)))); + q = (__m128i)_mm_shuffle_ps((__m128)q, (__m128)q, _MM_SHUFFLE(0, 0, 3, 1)); + return q; +} + +static INLINE vdouble vupper(vdouble d) +{ + return (__m128d)_mm_and_si128((__m128i)d, _mm_set_epi32(0xffffffff, 0xf8000000, 0xffffffff, 0xf8000000)); } // typedef struct { - vdouble x, y; + vdouble x, y; } vdouble2; -static INLINE vdouble2 dd(vdouble h, vdouble l) { - vdouble2 ret = {h, l}; - return ret; +static INLINE vdouble2 dd(vdouble h, vdouble l) +{ + vdouble2 ret = {h, l}; + return ret; } -static INLINE vdouble2 vsel2(vmask mask, vdouble2 x, vdouble2 y) { - return dd((__m128d)vorm(vandm(mask, (__m128i)x.x), vandnotm(mask, (__m128i)y.x)), - (__m128d)vorm(vandm(mask, (__m128i)x.y), vandnotm(mask, (__m128i)y.y))); +static INLINE vdouble2 vsel2(vmask mask, vdouble2 x, vdouble2 y) +{ + return dd((__m128d)vorm(vandm(mask, (__m128i)x.x), vandnotm(mask, (__m128i)y.x)), + (__m128d)vorm(vandm(mask, (__m128i)x.y), vandnotm(mask, (__m128i)y.y))); } -static INLINE vdouble2 abs_d(vdouble2 x) { - return dd((__m128d)_mm_xor_pd(_mm_and_pd(_mm_set_pd(-0.0,-0.0), x.x), x.x), - (__m128d)_mm_xor_pd(_mm_and_pd(_mm_set_pd(-0.0,-0.0), x.x), x.y)); +static INLINE vdouble2 abs_d(vdouble2 x) +{ + return dd((__m128d)_mm_xor_pd(_mm_and_pd(_mm_set_pd(-0.0, -0.0), x.x), x.x), + (__m128d)_mm_xor_pd(_mm_and_pd(_mm_set_pd(-0.0, -0.0), x.x), x.y)); } diff --git a/rtengine/hilite_recon.cc b/rtengine/hilite_recon.cc index 3ce6c83cb..411bb0823 100644 --- a/rtengine/hilite_recon.cc +++ b/rtengine/hilite_recon.cc @@ -1,24 +1,24 @@ //////////////////////////////////////////////////////////////// // -// Highlight reconstruction +// Highlight reconstruction // -// copyright (c) 2008-2011 Emil Martinec +// copyright (c) 2008-2011 Emil Martinec // // // code dated: June 16, 2011 // -// hilite_recon.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// hilite_recon.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// @@ -34,822 +34,940 @@ #endif -#define FOREACHCOLOR for (int c=0; c < ColorCount; c++) +#define FOREACHCOLOR for (int c=0; c < ColorCount; c++) //#include "RGBdefringe.cc" -namespace rtengine { - - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -SSEFUNCTION void RawImageSource::boxblur2(float** src, float** dst, int H, int W, int box ) +namespace rtengine { - array2D temp(W,H); - - //box blur image channel; box size = 2*box+1 - //horizontal blur + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +SSEFUNCTION void RawImageSource::boxblur2(float** src, float** dst, int H, int W, int box ) +{ + array2D temp(W, H); + + //box blur image channel; box size = 2*box+1 + //horizontal blur #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int row = 0; row < H; row++) { - int len = box + 1; - temp[row][0] = src[row][0]/len; - for (int j=1; j<=box; j++) { - temp[row][0] += src[row][j]/len; - } - for (int col=1; col<=box; col++) { - temp[row][col] = (temp[row][col-1]*len + src[row][col+box])/(len+1); - len ++; - } - for (int col = box+1; col < W-box; col++) { - temp[row][col] = temp[row][col-1] + (src[row][col+box] - src[row][col-box-1])/len; - } - for (int col=W-box; col temp((W/samp)+ ((W%samp)==0 ? 0 : 1),H); - -#ifdef _OPENMP -#pragma omp parallel -#endif -{ - float tempval; -#ifdef _OPENMP -#pragma omp for -#endif - //box blur image channel; box size = 2*box+1 - //horizontal blur - for (int row = 0; row < H; row++) { - int len = box + 1; - tempval = src[row][0]/len; - for (int j=1; j<=box; j++) { - tempval += src[row][j]/len; - } - temp[row][0] = tempval; - for (int col=1; col<=box; col++) { - tempval = (tempval*len + src[row][col+box])/(len+1); - if(col%samp == 0) - temp[row][col/samp] = tempval; - len ++; - } - for (int col = box+1; col < W-box; col++) { - tempval = tempval + (src[row][col+box] - src[row][col-box-1])/len; - if(col%samp == 0) - temp[row][col/samp] = tempval; - } - for (int col=W-box; col temp((W / samp) + ((W % samp) == 0 ? 0 : 1), H); #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - float tempval; + { + float tempval; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - //vertical blur - for (int col = 0; col < W/samp; col++) { - int len = box + 1; - tempval = temp[0][col]/len; - for (int i=1; i<=box; i++) { - tempval += temp[i][col]/len; - } - dst[0][col] = tempval; - for (int row=1; row<=box; row++) { - tempval = (tempval*len + temp[(row+box)][col])/(len+1); - if(row%samp == 0) - dst[row/samp][col] = tempval; - len ++; - } - for (int row = box+1; row < H-box; row++) { - tempval = tempval + (temp[(row+box)][col] - temp[(row-box-1)][col])/len; - if(row%samp == 0) - dst[row/samp][col] = tempval; - } - for (int row=H-box; rowsetProgressStr ("HL reconstruction..."); - plistener->setProgress (progress); - } - - int height = H; - int width = W; - - const int range = 2; - const int pitch = 4; + if (plistener) { + plistener->setProgressStr ("HL reconstruction..."); + plistener->setProgress (progress); + } - - int hfh = (height-(height%pitch))/pitch; - int hfw = (width-(width%pitch))/pitch; - - static const int numdirs = 4; - - static const float threshpct = 0.25; - static const float fixthreshpct = 0.7; - static const float maxpct = 0.95; + int height = H; + int width = W; - //%%%%%%%%%%%%%%%%%%%% - //for blend algorithm: - static const float blendthresh=1.0; - const int ColorCount=3; - // Transform matrixes rgb>lab and back - static const float trans[2][ColorCount][ColorCount] = - { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, - { { 1,1,1 }, { 1,-1,1 }, { 1,1,-1 } } }; - static const float itrans[2][ColorCount][ColorCount] = - { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, - { { 1,1,1 }, { 1,-1,1 }, { 1,1,-1 } } }; - //%%%%%%%%%%%%%%%%%%%% + const int range = 2; + const int pitch = 4; - - float max_f[3], thresh[3], fixthresh[3], norm[3]; - - //float red1, green1, blue1;//diagnostic -// float chmaxalt[4]={0,0,0,0};//diagnostic - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //halfsize demosaic - -/* - multi_array2D hfsize (hfw+1,hfh+1,ARRAY2D_CLEAR_DATA); - - boxblur_resamp(red,hfsize[0],chmaxalt[0],height,width,range,pitch); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - boxblur_resamp(green,hfsize[1],chmaxalt[1],height,width,range,pitch); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - boxblur_resamp(blue,hfsize[2],chmaxalt[2],height,width,range,pitch); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - - //blur image - //for (int m=0; m<3; m++) - // boxblur2(hfsize[m],hfsizeblur[m],hfh,hfw,3); - -*/ - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - for (int c=0; c<3; c++) { - thresh[c] = chmax[c]*threshpct; - fixthresh[c] = chmax[c]*fixthreshpct; - max_f[c] = chmax[c]*maxpct;//min(chmax[0],chmax[1],chmax[2])*maxpct; - norm[c] = 1.0/(max_f[c]-fixthresh[c]); - } - float whitept = max(max_f[0],max_f[1],max_f[2]); - float clippt = min(max_f[0],max_f[1],max_f[2]); - float medpt = max_f[0]+max_f[1]+max_f[2]-whitept-clippt; - float blendpt = blendthresh*clippt; - - float camwb[4]; - for (int c=0; c<4; c++) camwb[c]=ri->get_cam_mul(c); - multi_array2D channelblur(width,height,ARRAY2D_CLEAR_DATA); - multi_array2D hilite_full(width,height,ARRAY2D_CLEAR_DATA); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - - // blur RGB channels - boxblur2(red ,channelblur[0],height,width,4); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - boxblur2(green,channelblur[1],height,width,4); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - boxblur2(blue ,channelblur[2],height,width,4); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - - float hipass_sum=0, hipass_norm=0.00; - - // set up which pixels are clipped or near clipping + int hfh = (height - (height % pitch)) / pitch; + int hfw = (width - (width % pitch)) / pitch; + + static const int numdirs = 4; + + static const float threshpct = 0.25; + static const float fixthreshpct = 0.7; + static const float maxpct = 0.95; + + //%%%%%%%%%%%%%%%%%%%% + //for blend algorithm: + static const float blendthresh = 1.0; + const int ColorCount = 3; + // Transform matrixes rgb>lab and back + static const float trans[2][ColorCount][ColorCount] = { + { { 1, 1, 1 }, { 1.7320508, -1.7320508, 0 }, { -1, -1, 2 } }, + { { 1, 1, 1 }, { 1, -1, 1 }, { 1, 1, -1 } } + }; + static const float itrans[2][ColorCount][ColorCount] = { + { { 1, 0.8660254, -0.5 }, { 1, -0.8660254, -0.5 }, { 1, 0, 1 } }, + { { 1, 1, 1 }, { 1, -1, 1 }, { 1, 1, -1 } } + }; + //%%%%%%%%%%%%%%%%%%%% + + + float max_f[3], thresh[3], fixthresh[3], norm[3]; + + //float red1, green1, blue1;//diagnostic +// float chmaxalt[4]={0,0,0,0};//diagnostic + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //halfsize demosaic + + /* + multi_array2D hfsize (hfw+1,hfh+1,ARRAY2D_CLEAR_DATA); + + boxblur_resamp(red,hfsize[0],chmaxalt[0],height,width,range,pitch); + if(plistener){ + progress += 0.05; + plistener->setProgress(progress); + } + boxblur_resamp(green,hfsize[1],chmaxalt[1],height,width,range,pitch); + if(plistener){ + progress += 0.05; + plistener->setProgress(progress); + } + boxblur_resamp(blue,hfsize[2],chmaxalt[2],height,width,range,pitch); + if(plistener){ + progress += 0.05; + plistener->setProgress(progress); + } + + //blur image + //for (int m=0; m<3; m++) + // boxblur2(hfsize[m],hfsizeblur[m],hfh,hfw,3); + + */ + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + for (int c = 0; c < 3; c++) { + thresh[c] = chmax[c] * threshpct; + fixthresh[c] = chmax[c] * fixthreshpct; + max_f[c] = chmax[c] * maxpct; //min(chmax[0],chmax[1],chmax[2])*maxpct; + norm[c] = 1.0 / (max_f[c] - fixthresh[c]); + } + + float whitept = max(max_f[0], max_f[1], max_f[2]); + float clippt = min(max_f[0], max_f[1], max_f[2]); + float medpt = max_f[0] + max_f[1] + max_f[2] - whitept - clippt; + float blendpt = blendthresh * clippt; + + float camwb[4]; + + for (int c = 0; c < 4; c++) { + camwb[c] = ri->get_cam_mul(c); + } + + multi_array2D channelblur(width, height, ARRAY2D_CLEAR_DATA); + multi_array2D hilite_full(width, height, ARRAY2D_CLEAR_DATA); + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + // blur RGB channels + boxblur2(red , channelblur[0], height, width, 4); + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + boxblur2(green, channelblur[1], height, width, 4); + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + boxblur2(blue , channelblur[2], height, width, 4); + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + float hipass_sum = 0, hipass_norm = 0.00; + + // set up which pixels are clipped or near clipping #ifdef _OPENMP -#pragma omp parallel for reduction(+:hipass_sum,hipass_norm) schedule(dynamic,16) + #pragma omp parallel for reduction(+:hipass_sum,hipass_norm) schedule(dynamic,16) #endif - for (int i=0; ithresh[0] || green[i][j]>thresh[1] || blue[i][j]>thresh[2]) && - (red[i][j]setProgress(progress); - } + //if one or more channels is highlight but none are blown, add to highlight accumulator - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //blur highlight data - boxblur2(hilite_full[4],hilite_full[4],height,width,1); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } + if ((red[i][j] > thresh[0] || green[i][j] > thresh[1] || blue[i][j] > thresh[2]) && + (red[i][j] < max_f[0] && green[i][j] < max_f[1] && blue[i][j] < max_f[2])) { + + hipass_sum += fabs(channelblur[0][i][j] - red[i][j]) + fabs(channelblur[1][i][j] - green[i][j]) + fabs(channelblur[2][i][j] - blue[i][j]); + hipass_norm++; + + hilite_full[0][i][j] = red[i][j]; + hilite_full[1][i][j] = green[i][j]; + hilite_full[2][i][j] = blue[i][j]; + hilite_full[3][i][j] = 1; + hilite_full[4][i][j] = 1; + + } + + //if (i%100==0 && j%100==0) + // printf("row=%d col=%d r=%f g=%f b=%f hilite=%f \n",i,j,hilite_full[0][i][j],hilite_full[1][i][j],hilite_full[2][i][j],hilite_full[3][i][j]); + } + }//end of filling highlight array + + hipass_norm += 0.01; + + float hipass_ave = (hipass_sum / hipass_norm); + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //blur highlight data + boxblur2(hilite_full[4], hilite_full[4], height, width, 1); + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int i=0; i 2*hipass_ave) { - //too much variation - hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0; - continue; - } - - if (hilite_full[4][i][j]>0.00001 && hilite_full[4][i][j]<0.95) { - //too near an edge, could risk using CA affected pixels, therefore omit - hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0; - } - } - } - - for (int c=0; c<3; c++) channelblur[c](1,1);//free up some memory - - multi_array2D hilite(hfw+1,hfh+1,ARRAY2D_CLEAR_DATA); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // blur and resample highlight data; range=size of blur, pitch=sample spacing - for (int m=0; m<4; m++) { - boxblur_resamp(hilite_full[m],hilite[m],height,width,range,pitch); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - } - for (int c=0; c<5; c++) hilite_full[c](1,1);//free up some memory - - multi_array2D hilite_dir(hfw,hfh,ARRAY2D_CLEAR_DATA); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //blur highlights - //for (int m=0; m<4; m++) - // boxblur2(hilite[m],hilite[m],hfh,hfw,4); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - - LUTf invfn(0x10000); - - for (int i=0; i<0x10000; i++) - invfn[i] = 1.0/(1.0+i); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - //fill gaps in highlight map by directional extension - //raster scan from four corners - for (int j=1; j0.01) { - for (int c=0; c<4; c++) { - hilite_dir[c][i][j] = hilite[c][i][j]/hilite[3][i][j]; - } - } else { - for (int c=0; c<4; c++) { - hilite_dir[c][i][j] = 0.1*((hilite_dir[0+c][i-2][j-1]+hilite_dir[0+c][i-1][j-1]+hilite_dir[0+c][i][j-1]+hilite_dir[0+c][i+1][j-1]+hilite_dir[0+c][i+2][j-1])/ - (hilite_dir[0+3][i-2][j-1]+hilite_dir[0+3][i-1][j-1]+hilite_dir[0+3][i][j-1]+hilite_dir[0+3][i+1][j-1]+hilite_dir[0+3][i+2][j-1]+0.00001)); - hilite_dir[4+c][i][j+1] += hilite_dir[c][i][j]; - hilite_dir[8+c][i-2][j] += hilite_dir[c][i][j]; - hilite_dir[12+c][i+2][j] += hilite_dir[c][i][j]; - } - } - } - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } + float hipass = fabs(channelblur[0][i][j] - red[i][j]) + fabs(channelblur[1][i][j] - green[i][j]) + fabs(channelblur[2][i][j] - blue[i][j]); - for (int j=hfw-2; j>0; j--) - for (int i=2; i0.01) { - for (int c=0; c<4; c++) { - hilite_dir[4+c][i][j] = hilite[c][i][j]/hilite[3][i][j]; - } - } else { - for (int c=0; c<4; c++) { - hilite_dir[4+c][i][j] = 0.1*((hilite_dir[4+c][(i-2)][(j+1)]+hilite_dir[4+c][(i-1)][(j+1)]+hilite_dir[4+c][(i)][(j+1)]+hilite_dir[4+c][(i+1)][(j+1)]+hilite_dir[4+c][(i+2)][(j+1)])/ - (hilite_dir[4+3][(i-2)][(j+1)]+hilite_dir[4+3][(i-1)][(j+1)]+hilite_dir[4+3][(i)][(j+1)]+hilite_dir[4+3][(i+1)][(j+1)]+hilite_dir[4+3][(i+2)][(j+1)]+0.00001)); - hilite_dir[8+c][i-2][j] += hilite_dir[4+c][i][j]; - hilite_dir[12+c][i+2][j] += hilite_dir[4+c][i][j]; - } - } - } - - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } + if (hipass > 2 * hipass_ave) { + //too much variation + hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0; + continue; + } - for (int i=1; i0.01) { - for (int c=0; c<4; c++) { - hilite_dir[8+c][i][j] = hilite[c][i][j]/hilite[3][i][j]; - } - } else { - for (int c=0; c<4; c++) { - hilite_dir[8+c][i][j] = 0.1*((hilite_dir[8+c][i-1][j-2]+hilite_dir[8+c][i-1][j-1]+hilite_dir[8+c][i-1][j]+hilite_dir[8+c][i-1][j+1]+hilite_dir[8+c][i-1][j+2])/ - (hilite_dir[8+3][i-1][j-2]+hilite_dir[8+3][i-1][j-1]+hilite_dir[8+3][i-1][j]+hilite_dir[8+3][i-1][j+1]+hilite_dir[8+3][i-1][j+2]+0.00001)); - hilite_dir[12+c][i+1][j] += hilite_dir[8+c][i][j]; - } - } - } + if (hilite_full[4][i][j] > 0.00001 && hilite_full[4][i][j] < 0.95) { + //too near an edge, could risk using CA affected pixels, therefore omit + hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0; + } + } + } - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } + for (int c = 0; c < 3; c++) { + channelblur[c](1, 1); //free up some memory + } - for (int i=hfh-2; i>0; i--) - for (int j=2; j0.01) { - for (int c=0; c<4; c++) { - hilite_dir[12+c][i][j] = hilite[c][i][j]/hilite[3][i][j]; - } - } else { - for (int c=0; c<4; c++) { - hilite_dir[12+c][i][j] = 0.1*((hilite_dir[12+c][(i+1)][(j-2)]+hilite_dir[12+c][(i+1)][(j-1)]+hilite_dir[12+c][(i+1)][(j)]+hilite_dir[12+c][(i+1)][(j+1)]+hilite_dir[12+c][(i+1)][(j+2)])/ - (hilite_dir[12+3][(i+1)][(j-2)]+hilite_dir[12+3][(i+1)][(j-1)]+hilite_dir[12+3][(i+1)][(j)]+hilite_dir[12+3][(i+1)][(j+1)]+hilite_dir[12+3][(i+1)][(j+2)]+0.00001)); - } - } - - } + multi_array2D hilite(hfw + 1, hfh + 1, ARRAY2D_CLEAR_DATA); - if(plistener){ - progress += 0.05; - plistener->setProgress(progress); - } - - //fill in edges - for (int dir=0; dirsetProgress(progress); - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - /*for (int m=0; m<4*numdirs; m++) { - boxblur2(hilite_dir[m],hilite_dir[m],hfh,hfw,4); - }*/ - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //now we have highlight data extended in various directions - //next step is to build back local data by averaging - + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + } + + for (int c = 0; c < 5; c++) { + hilite_full[c](1, 1); //free up some memory + } + + multi_array2D hilite_dir(hfw, hfh, ARRAY2D_CLEAR_DATA); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //blur highlights + //for (int m=0; m<4; m++) + // boxblur2(hilite[m],hilite[m],hfh,hfw,4); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + LUTf invfn(0x10000); + + for (int i = 0; i < 0x10000; i++) { + invfn[i] = 1.0 / (1.0 + i); + } + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + //fill gaps in highlight map by directional extension + //raster scan from four corners + for (int j = 1; j < hfw - 1; j++) + for (int i = 2; i < hfh - 2; i++) { + //from left + if (hilite[3][i][j] > 0.01) { + for (int c = 0; c < 4; c++) { + hilite_dir[c][i][j] = hilite[c][i][j] / hilite[3][i][j]; + } + } else { + for (int c = 0; c < 4; c++) { + hilite_dir[c][i][j] = 0.1 * ((hilite_dir[0 + c][i - 2][j - 1] + hilite_dir[0 + c][i - 1][j - 1] + hilite_dir[0 + c][i][j - 1] + hilite_dir[0 + c][i + 1][j - 1] + hilite_dir[0 + c][i + 2][j - 1]) / + (hilite_dir[0 + 3][i - 2][j - 1] + hilite_dir[0 + 3][i - 1][j - 1] + hilite_dir[0 + 3][i][j - 1] + hilite_dir[0 + 3][i + 1][j - 1] + hilite_dir[0 + 3][i + 2][j - 1] + 0.00001)); + hilite_dir[4 + c][i][j + 1] += hilite_dir[c][i][j]; + hilite_dir[8 + c][i - 2][j] += hilite_dir[c][i][j]; + hilite_dir[12 + c][i + 2][j] += hilite_dir[c][i][j]; + } + } + } + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + for (int j = hfw - 2; j > 0; j--) + for (int i = 2; i < hfh - 2; i++) { + //from right + if (hilite[3][i][j] > 0.01) { + for (int c = 0; c < 4; c++) { + hilite_dir[4 + c][i][j] = hilite[c][i][j] / hilite[3][i][j]; + } + } else { + for (int c = 0; c < 4; c++) { + hilite_dir[4 + c][i][j] = 0.1 * ((hilite_dir[4 + c][(i - 2)][(j + 1)] + hilite_dir[4 + c][(i - 1)][(j + 1)] + hilite_dir[4 + c][(i)][(j + 1)] + hilite_dir[4 + c][(i + 1)][(j + 1)] + hilite_dir[4 + c][(i + 2)][(j + 1)]) / + (hilite_dir[4 + 3][(i - 2)][(j + 1)] + hilite_dir[4 + 3][(i - 1)][(j + 1)] + hilite_dir[4 + 3][(i)][(j + 1)] + hilite_dir[4 + 3][(i + 1)][(j + 1)] + hilite_dir[4 + 3][(i + 2)][(j + 1)] + 0.00001)); + hilite_dir[8 + c][i - 2][j] += hilite_dir[4 + c][i][j]; + hilite_dir[12 + c][i + 2][j] += hilite_dir[4 + c][i][j]; + } + } + } + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + for (int i = 1; i < hfh - 1; i++) + for (int j = 2; j < hfw - 2; j++) { + //if (i%100==0 && j%100==0) + // printf("row=%d col=%d r=%f g=%f b=%f hilite=%f \n",i,j,hilite[0][i][j],hilite[1][i][j],hilite[2][i][j],hilite[3][i][j]); + + //from top + if (hilite[3][i][j] > 0.01) { + for (int c = 0; c < 4; c++) { + hilite_dir[8 + c][i][j] = hilite[c][i][j] / hilite[3][i][j]; + } + } else { + for (int c = 0; c < 4; c++) { + hilite_dir[8 + c][i][j] = 0.1 * ((hilite_dir[8 + c][i - 1][j - 2] + hilite_dir[8 + c][i - 1][j - 1] + hilite_dir[8 + c][i - 1][j] + hilite_dir[8 + c][i - 1][j + 1] + hilite_dir[8 + c][i - 1][j + 2]) / + (hilite_dir[8 + 3][i - 1][j - 2] + hilite_dir[8 + 3][i - 1][j - 1] + hilite_dir[8 + 3][i - 1][j] + hilite_dir[8 + 3][i - 1][j + 1] + hilite_dir[8 + 3][i - 1][j + 2] + 0.00001)); + hilite_dir[12 + c][i + 1][j] += hilite_dir[8 + c][i][j]; + } + } + } + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + for (int i = hfh - 2; i > 0; i--) + for (int j = 2; j < hfw - 2; j++) { + //from bottom + if (hilite[3][i][j] > 0.01) { + for (int c = 0; c < 4; c++) { + hilite_dir[12 + c][i][j] = hilite[c][i][j] / hilite[3][i][j]; + } + } else { + for (int c = 0; c < 4; c++) { + hilite_dir[12 + c][i][j] = 0.1 * ((hilite_dir[12 + c][(i + 1)][(j - 2)] + hilite_dir[12 + c][(i + 1)][(j - 1)] + hilite_dir[12 + c][(i + 1)][(j)] + hilite_dir[12 + c][(i + 1)][(j + 1)] + hilite_dir[12 + c][(i + 1)][(j + 2)]) / + (hilite_dir[12 + 3][(i + 1)][(j - 2)] + hilite_dir[12 + 3][(i + 1)][(j - 1)] + hilite_dir[12 + 3][(i + 1)][(j)] + hilite_dir[12 + 3][(i + 1)][(j + 1)] + hilite_dir[12 + 3][(i + 1)][(j + 2)] + 0.00001)); + } + } + + } + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + //fill in edges + for (int dir = 0; dir < numdirs; dir++) { + for (int i = 1; i < hfh - 1; i++) + for (int c = 0; c < 4; c++) { + hilite_dir[dir * 4 + c][i][0] = hilite_dir[dir * 4 + c][i][1]; + hilite_dir[dir * 4 + c][i][hfw - 1] = hilite_dir[dir * 4 + c][i][hfw - 2]; + } + + for (int j = 1; j < hfw - 1; j++) + for (int c = 0; c < 4; c++) { + hilite_dir[dir * 4 + c][0][j] = hilite_dir[dir * 4 + c][1][j]; + hilite_dir[dir * 4 + c][hfh - 1][j] = hilite_dir[dir * 4 + c][hfh - 2][j]; + } + + for (int c = 0; c < 4; c++) { + hilite_dir[dir * 4 + c][0][0] = hilite_dir[dir * 4 + c][1][0] = hilite_dir[dir * 4 + c][0][1] = hilite_dir[dir * 4 + c][1][1] = hilite_dir[dir * 4 + c][2][2]; + hilite_dir[dir * 4 + c][0][hfw - 1] = hilite_dir[dir * 4 + c][1][hfw - 1] = hilite_dir[dir * 4 + c][0][hfw - 2] = hilite_dir[dir * 4 + c][1][hfw - 2] = hilite_dir[dir * 4 + c][2][hfw - 3]; + hilite_dir[dir * 4 + c][hfh - 1][0] = hilite_dir[dir * 4 + c][hfh - 2][0] = hilite_dir[dir * 4 + c][hfh - 1][1] = hilite_dir[dir * 4 + c][hfh - 2][1] = hilite_dir[dir * 4 + c][hfh - 3][2]; + hilite_dir[dir * 4 + c][hfh - 1][hfw - 1] = hilite_dir[dir * 4 + c][hfh - 2][hfw - 1] = hilite_dir[dir * 4 + c][hfh - 1][hfw - 2] = hilite_dir[dir * 4 + c][hfh - 2][hfw - 2] = hilite_dir[dir * 4 + c][hfh - 3][hfw - 3]; + } + } + + if(plistener) { + progress += 0.05; + plistener->setProgress(progress); + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + /*for (int m=0; m<4*numdirs; m++) { + boxblur2(hilite_dir[m],hilite_dir[m],hfh,hfw,4); + }*/ + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //now we have highlight data extended in various directions + //next step is to build back local data by averaging + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // now reconstruct clipped channels using color ratios + + //const float Yclip = 0.3333*(max[0] + max[1] + max[2]); + //float sumwt=0, counts=0; - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // now reconstruct clipped channels using color ratios - - //const float Yclip = 0.3333*(max[0] + max[1] + max[2]); - //float sumwt=0, counts=0; - #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int i=0; i blendpt) rgb_blend[0]= rfrac*rgb[0]+(1-rfrac)*pixel[0]; - if (pixel[1] > blendpt) rgb_blend[1]= gfrac*rgb[1]+(1-gfrac)*pixel[1]; - if (pixel[2] > blendpt) rgb_blend[2]= bfrac*rgb[2]+(1-bfrac)*pixel[2]; - - //end of HLRecovery_blend estimation - //%%%%%%%%%%%%%%%%%%%%%%% - - //float pixref[3]={min(Yclip,hfsize[0][i1][j1]),min(Yclip,hfsize[1][i1][j1]),min(Yclip,hfsize[2][i1][j1])}; - - //there are clipped highlights - //first, determine weighted average of unclipped extensions (weighting is by 'hue' proximity) - float dirwt, factor, Y; - float totwt=0;//0.0003; - float clipfix[3]={0,0,0};//={totwt*rgb_blend[0],totwt*rgb_blend[1],totwt*rgb_blend[2]}; - for (int dir=0; dir0.5) { - dirwt = invfn[65535*(SQR(rgb_blend[0]/Y-hilite_dir[dir*4+0][i1][j1]/Yhi) + - SQR(rgb_blend[1]/Y-hilite_dir[dir*4+1][i1][j1]/Yhi) + - SQR(rgb_blend[2]/Y-hilite_dir[dir*4+2][i1][j1]/Yhi))]; - totwt += dirwt; - clipfix[0] += dirwt*hilite_dir[dir*4+0][i1][j1]/(hilite_dir[dir*4+3][i1][j1]+0.00001); - clipfix[1] += dirwt*hilite_dir[dir*4+1][i1][j1]/(hilite_dir[dir*4+3][i1][j1]+0.00001); - clipfix[2] += dirwt*hilite_dir[dir*4+2][i1][j1]/(hilite_dir[dir*4+3][i1][j1]+0.00001); - } - } - if(totwt == 0.f) - continue; - - clipfix[0] /= totwt; - clipfix[1] /= totwt; - clipfix[2] /= totwt; - //sumwt += totwt; - //counts ++; - - //now correct clipped channels - if (pixel[0]>max_f[0] && pixel[1]>max_f[1] && pixel[2]>max_f[2]) { - //all channels clipped - float Y = (0.299*clipfix[0] + 0.587*clipfix[1] + 0.114*clipfix[2]); - //float Y = (clipfix[0] + clipfix[1] + clipfix[2]); - factor = whitept/Y; - red[i][j] = clipfix[0]*factor; - green[i][j] = clipfix[1]*factor; - blue[i][j] = clipfix[2]*factor; - } else {//some channels clipped - int notclipped[3] = {pixel[0]0.01) { - red[i][j] = (red[i][j] + hilite[0][i1][j1])/(1+hilite[3][i1][j1]); - green[i][j] = (green[i][j]+ hilite[1][i1][j1])/(1+hilite[3][i1][j1]); - blue[i][j] = (blue[i][j] + hilite[2][i1][j1])/(1+hilite[3][i1][j1]); - }*/ - - Y = (0.299 * red[i][j] + 0.587 * green[i][j] + 0.114 * blue[i][j]); - - if (Y>whitept) { - factor = whitept/Y; - - /*I = (0.596 * red[i][j] - 0.275 * green[i][j] - 0.321 * blue[i][j]); - Q = (0.212 * red[i][j] - 0.523 * green[i][j] + 0.311 * blue[i][j]); - - Y *= factor; - I *= factor;//max(0,min(1,(whitept-Y)/(whitept-clippt))); - Q *= factor;//max(0,min(1,(whitept-Y)/(whitept-clippt))); - - red[i][j] = Y + 0.956*I + 0.621*Q; - green[i][j] = Y - 0.272*I - 0.647*Q; - blue[i][j] = Y - 1.105*I + 1.702*Q;*/ - - red[i][j] *= factor; - green[i][j] *= factor; - blue[i][j] *= factor; - } - } - } - - if(plistener) plistener->setProgress(1.00); - //printf("ave wt=%f\n",sumwt/counts); + for (int i = 0; i < height; i++) { + int i1 = min((i - (i % pitch)) / pitch, hfh - 1); + + for (int j = 0; j < width; j++) { + int j1 = min((j - (j % pitch)) / pitch, hfw - 1); + + float pixel[3] = {red[i][j], green[i][j], blue[i][j]}; + + if (pixel[0] < max_f[0] && pixel[1] < max_f[1] && pixel[2] < max_f[2]) { + continue; //pixel not clipped + } + + //if (pixel[0] blendpt) { + rgb_blend[0] = rfrac * rgb[0] + (1 - rfrac) * pixel[0]; + } + + if (pixel[1] > blendpt) { + rgb_blend[1] = gfrac * rgb[1] + (1 - gfrac) * pixel[1]; + } + + if (pixel[2] > blendpt) { + rgb_blend[2] = bfrac * rgb[2] + (1 - bfrac) * pixel[2]; + } + + //end of HLRecovery_blend estimation + //%%%%%%%%%%%%%%%%%%%%%%% + + //float pixref[3]={min(Yclip,hfsize[0][i1][j1]),min(Yclip,hfsize[1][i1][j1]),min(Yclip,hfsize[2][i1][j1])}; + + //there are clipped highlights + //first, determine weighted average of unclipped extensions (weighting is by 'hue' proximity) + float dirwt, factor, Y; + float totwt = 0; //0.0003; + float clipfix[3] = {0, 0, 0}; //={totwt*rgb_blend[0],totwt*rgb_blend[1],totwt*rgb_blend[2]}; + + for (int dir = 0; dir < numdirs; dir++) { + float Yhi = 0.001 + (hilite_dir[dir * 4 + 0][i1][j1] + hilite_dir[dir * 4 + 1][i1][j1] + hilite_dir[dir * 4 + 2][i1][j1]); + float Y = 0.001 + (rgb_blend[0] + rgb_blend[1] + rgb_blend[2]); + + if (hilite_dir[dir * 4 + 0][i1][j1] + hilite_dir[dir * 4 + 1][i1][j1] + hilite_dir[dir * 4 + 2][i1][j1] > 0.5) { + dirwt = invfn[65535 * (SQR(rgb_blend[0] / Y - hilite_dir[dir * 4 + 0][i1][j1] / Yhi) + + SQR(rgb_blend[1] / Y - hilite_dir[dir * 4 + 1][i1][j1] / Yhi) + + SQR(rgb_blend[2] / Y - hilite_dir[dir * 4 + 2][i1][j1] / Yhi))]; + totwt += dirwt; + clipfix[0] += dirwt * hilite_dir[dir * 4 + 0][i1][j1] / (hilite_dir[dir * 4 + 3][i1][j1] + 0.00001); + clipfix[1] += dirwt * hilite_dir[dir * 4 + 1][i1][j1] / (hilite_dir[dir * 4 + 3][i1][j1] + 0.00001); + clipfix[2] += dirwt * hilite_dir[dir * 4 + 2][i1][j1] / (hilite_dir[dir * 4 + 3][i1][j1] + 0.00001); + } + } + + if(totwt == 0.f) { + continue; + } + + clipfix[0] /= totwt; + clipfix[1] /= totwt; + clipfix[2] /= totwt; + //sumwt += totwt; + //counts ++; + + //now correct clipped channels + if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) { + //all channels clipped + float Y = (0.299 * clipfix[0] + 0.587 * clipfix[1] + 0.114 * clipfix[2]); + //float Y = (clipfix[0] + clipfix[1] + clipfix[2]); + factor = whitept / Y; + red[i][j] = clipfix[0] * factor; + green[i][j] = clipfix[1] * factor; + blue[i][j] = clipfix[2] * factor; + } else {//some channels clipped + int notclipped[3] = {pixel[0] < max_f[0] ? 1 : 0, pixel[1] < max_f[1] ? 1 : 0, pixel[2] < max_f[2] ? 1 : 0}; + + if (notclipped[0] == 0) { //red clipped + red[i][j] = max(red[i][j], (clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) / + (notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2])))); + } + + if (notclipped[1] == 0) { //green clipped + green[i][j] = max(green[i][j], (clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) / + (notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0])))); + } + + if (notclipped[2] == 0) { //blue clipped + blue[i][j] = max(blue[i][j], (clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) / + (notclipped[0] * clipfix[0] + notclipped[1] * clipfix[1])))); + } + } + + /*if (hilite[3][i1][j1]>0.01) { + red[i][j] = (red[i][j] + hilite[0][i1][j1])/(1+hilite[3][i1][j1]); + green[i][j] = (green[i][j]+ hilite[1][i1][j1])/(1+hilite[3][i1][j1]); + blue[i][j] = (blue[i][j] + hilite[2][i1][j1])/(1+hilite[3][i1][j1]); + }*/ + + Y = (0.299 * red[i][j] + 0.587 * green[i][j] + 0.114 * blue[i][j]); + + if (Y > whitept) { + factor = whitept / Y; + + /*I = (0.596 * red[i][j] - 0.275 * green[i][j] - 0.321 * blue[i][j]); + Q = (0.212 * red[i][j] - 0.523 * green[i][j] + 0.311 * blue[i][j]); + + Y *= factor; + I *= factor;//max(0,min(1,(whitept-Y)/(whitept-clippt))); + Q *= factor;//max(0,min(1,(whitept-Y)/(whitept-clippt))); + + red[i][j] = Y + 0.956*I + 0.621*Q; + green[i][j] = Y - 0.272*I - 0.647*Q; + blue[i][j] = Y - 1.105*I + 1.702*Q;*/ + + red[i][j] *= factor; + green[i][j] *= factor; + blue[i][j] *= factor; + } + } + } + + if(plistener) { + plistener->setProgress(1.00); + } + + //printf("ave wt=%f\n",sumwt/counts); + + + // diagnostic output + /*for (int i=0; i0)// && phase!=4) // continue; - if (phase==-1 || phase==0 || phase==2) { - if (rec[0][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >=0 && rec[2][i][j] != INT_MAX && rec[2][i][j] >=0) { + if (phase == -1 || phase == 0 || phase == 2) { + if (rec[0][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >= 0 && rec[2][i][j] != INT_MAX && rec[2][i][j] >= 0) { co = 0; c1 = 1; - c2 = 2; - } - else if (rec[1][i][j] == INT_MAX && rec[0][i][j] != INT_MAX && rec[0][i][j] >=0 && rec[2][i][j] != INT_MAX && rec[2][i][j] >=0) { + c2 = 2; + } else if (rec[1][i][j] == INT_MAX && rec[0][i][j] != INT_MAX && rec[0][i][j] >= 0 && rec[2][i][j] != INT_MAX && rec[2][i][j] >= 0) { co = 1; c1 = 0; - c2 = 2; - } - else if (rec[2][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >=0 && rec[0][i][j] != INT_MAX && rec[0][i][j] >=0) { + c2 = 2; + } else if (rec[2][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >= 0 && rec[0][i][j] != INT_MAX && rec[0][i][j] >= 0) { co = 2; c1 = 1; - c2 = 0; - } - else + c2 = 0; + } else { continue; - + } + double ratio[2] = {0.0, 0.0}; int count = 0; double rato = (double)rec[c1][i][j] / rec[c2][i][j]; double arato = 0.0; - if (phase==2) { - for (int x=-1; x<=1; x++) - for (int y=-1; y<=1; y++) { + + if (phase == 2) { + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) { // average m/c color ratios in the surrounding pixels - if (rec[co][i+x][j+y]>=0 && rec[co][i+x][j+y]!=INT_MAX && rec[c1][i+x][j+y]>=0 && rec[c1][i+x][j+y]!=INT_MAX && rec[c2][i+x][j+y]>0 && rec[c2][i+x][j+y]!=INT_MAX) { - double ratt = (double)rec[c1][i+x][j+y] / rec[c2][i+x][j+y]; - if (ratt > rato*1.2 || ratt < rato / 1.2 || rec[co][i+x][j+y]= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] >= 0 && rec[c1][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { + double ratt = (double)rec[c1][i + x][j + y] / rec[c2][i + x][j + y]; + + if (ratt > rato * 1.2 || ratt < rato / 1.2 || rec[co][i + x][j + y] < max_3[co] * 1 / 2) { continue; - ratio[0] += (double)rec[c1][i+x][j+y] / rec[co][i+x][j+y]; - ratio[1] += (double)rec[c2][i+x][j+y] / rec[co][i+x][j+y]; + } + + ratio[0] += (double)rec[c1][i + x][j + y] / rec[co][i + x][j + y]; + ratio[1] += (double)rec[c2][i + x][j + y] / rec[co][i + x][j + y]; count++; } } - } - else if (phase==-1) { - for (int x=-1; x<=1; x++) - for (int y=-1; y<=1; y++) { + } else if (phase == -1) { + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) { // average m/c color ratios in the surrounding pixels - if (rec[co][i+x][j+y]>=0 && rec[co][i+x][j+y]!=INT_MAX && rec[c1][i+x][j+y]>=0 && rec[c1][i+x][j+y]!=INT_MAX && rec[c2][i+x][j+y]>0 && rec[c2][i+x][j+y]!=INT_MAX) { - double ratt = (double)rec[c1][i+x][j+y] / rec[c2][i+x][j+y]; - if (ratt > rato*1.05 || ratt < rato / 1.05 || rec[co][i+x][j+y]= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] >= 0 && rec[c1][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { + double ratt = (double)rec[c1][i + x][j + y] / rec[c2][i + x][j + y]; + + if (ratt > rato * 1.05 || ratt < rato / 1.05 || rec[co][i + x][j + y] < max_3[co] * 4 / 5) { continue; + } + arato += ratt; - ratio[0] += (double)rec[c1][i+x][j+y] / rec[co][i+x][j+y]; - ratio[1] += (double)rec[c2][i+x][j+y] / rec[co][i+x][j+y]; - + ratio[0] += (double)rec[c1][i + x][j + y] / rec[co][i + x][j + y]; + ratio[1] += (double)rec[c2][i + x][j + y] / rec[co][i + x][j + y]; + count++; } } - } - else { - for (int x=-1; x<=1; x++) - for (int y=-1; y<=1; y++) { + } else { + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) { // average m/c color ratios in the surrounding pixels - if (rec[co][i+x][j+y]>=0 && rec[co][i+x][j+y]!=INT_MAX && rec[c1][i+x][j+y]>=0 && rec[c1][i+x][j+y]!=INT_MAX && rec[c2][i+x][j+y]>0 && rec[c2][i+x][j+y]!=INT_MAX) { - double ratt = (double)rec[c1][i+x][j+y] / rec[c2][i+x][j+y]; - if (ratt > rato*1.1 || ratt < rato / 1.1 || rec[co][i+x][j+y]= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] >= 0 && rec[c1][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { + double ratt = (double)rec[c1][i + x][j + y] / rec[c2][i + x][j + y]; + + if (ratt > rato * 1.1 || ratt < rato / 1.1 || rec[co][i + x][j + y] < max_3[co] * 3 / 4) { continue; + } + arato += ratt; - ratio[0] += (double)rec[c1][i+x][j+y] / rec[co][i+x][j+y]; - ratio[1] += (double)rec[c2][i+x][j+y] / rec[co][i+x][j+y]; - + ratio[0] += (double)rec[c1][i + x][j + y] / rec[co][i + x][j + y]; + ratio[1] += (double)rec[c2][i + x][j + y] / rec[co][i + x][j + y]; + count++; } } } + // compute new pixel values from the surrounding color ratios - if (count>1) { //(phase==0 && count>1) || (phase==2 && count>1)) { + if (count > 1) { //(phase==0 && count>1) || (phase==2 && count>1)) { rec[co][i][j] = -(int)((rec[c1][i][j] / ratio[0] * count + rec[c2][i][j] / ratio[1] * count) / 2); changed++; } - } - else if (phase==1 || phase==3) { - if (rec[0][i][j] == INT_MAX && rec[1][i][j] == INT_MAX && rec[2][i][j] != INT_MAX && rec[2][i][j] >=0) { + } else if (phase == 1 || phase == 3) { + if (rec[0][i][j] == INT_MAX && rec[1][i][j] == INT_MAX && rec[2][i][j] != INT_MAX && rec[2][i][j] >= 0) { co = 2; c1 = 0; - c2 = 1; - } - else if (rec[0][i][j] == INT_MAX && rec[2][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >=0) { + c2 = 1; + } else if (rec[0][i][j] == INT_MAX && rec[2][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >= 0) { co = 1; c1 = 0; - c2 = 2; - } - else if (rec[1][i][j] == INT_MAX && rec[2][i][j] == INT_MAX && rec[0][i][j] != INT_MAX && rec[0][i][j] >=0) { + c2 = 2; + } else if (rec[1][i][j] == INT_MAX && rec[2][i][j] == INT_MAX && rec[0][i][j] != INT_MAX && rec[0][i][j] >= 0) { co = 0; c1 = 1; - c2 = 2; - } - else + c2 = 2; + } else { continue; + } double ratio[2] = {0.0, 0.0}; int count[2] = {0, 0}; - for (int x=-1; x<=1; x++) - for (int y=-1; y<=1; y++) { + + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) { // average m/c color ratios in the surrounding pixels - if (rec[co][i+x][j+y]>=0 && rec[co][i+x][j+y]!=INT_MAX && rec[c1][i+x][j+y]>0 && rec[c1][i+x][j+y]!=INT_MAX) { - if ((phase==1 && rec[c1][i+x][j+y]= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] > 0 && rec[c1][i + x][j + y] != INT_MAX) { + if ((phase == 1 && rec[c1][i + x][j + y] < max_3[c1] * 3 / 4) || (phase == 3 && rec[c1][i + x][j + y] < max_3[c1] * 1 / 2)) { continue; - ratio[0] += (double)rec[co][i+x][j+y] / rec[c1][i+x][j+y]; + } + + ratio[0] += (double)rec[co][i + x][j + y] / rec[c1][i + x][j + y]; count[0] ++; } - if (rec[co][i+x][j+y]>=0 && rec[co][i+x][j+y]!=INT_MAX && rec[c2][i+x][j+y]>0 && rec[c2][i+x][j+y]!=INT_MAX) { - if ((phase==1 && rec[c2][i+x][j+y]= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { + if ((phase == 1 && rec[c2][i + x][j + y] < max_3[c2] * 3 / 4) || (phase == 3 && rec[c2][i + x][j + y] < max_3[c2] * 1 / 2)) // if (/*phase!=3 && */rec[c2][i+x][j+y]2) || (phase==3 && count[0]>1)) { + if ((phase == 1 && count[0] > 2) || (phase == 3 && count[0] > 1)) { rec[c1][i][j] = - (int) ((double)rec[co][i][j] / ratio[0] * count[0]); changed++; } - if ((phase==1 && count[1]>2) || (phase==3 && count[1]>1)) { + + if ((phase == 1 && count[1] > 2) || (phase == 3 && count[1] > 1)) { rec[c2][i][j] = - (int) ((double)rec[co][i][j] / ratio[1] * count[1]); changed++; } - } - else { + } else { int val = 0; int num = 0; - for (int c=0; c<3; c++) - if (rec[c][i][j]!=INT_MAX) { + + for (int c = 0; c < 3; c++) + if (rec[c][i][j] != INT_MAX) { val += rec[c][i][j]; num++; } - if (num<3 && num>0) { - for (int c=0; c<3; c++) + + if (num < 3 && num > 0) { + for (int c = 0; c < 3; c++) { rec[c][i][j] = val / num; + } } } } bool change = false; - for (int i=1; i=H/HR_SCALE-2) + int blr = (i + HR_SCALE / 2) / HR_SCALE - 1; + + if (blr < 0 || blr >= H / HR_SCALE - 2) { return; - double mr1 = 1.0 - ((double)((i+HR_SCALE/2) % HR_SCALE) / HR_SCALE + 0.5 / HR_SCALE); - int maxcol = W/HR_SCALE-2; - for (int j=sx1, jx=0; jx=maxcol) + } + + double mr1 = 1.0 - ((double)((i + HR_SCALE / 2) % HR_SCALE) / HR_SCALE + 0.5 / HR_SCALE); + int maxcol = W / HR_SCALE - 2; + + for (int j = sx1, jx = 0; jx < width; j += skip, jx++) { + if (needhr[i][j]) { + int blc = (j + HR_SCALE / 2) / HR_SCALE - 1; + + if (blc < 0 || blc >= maxcol) { continue; - double mc1 = 1.0 - ((double)((j+HR_SCALE/2) % HR_SCALE) / HR_SCALE + 0.5 / HR_SCALE); - double mulr = mr1*mc1 * hrmap[0][blr][blc] + mr1*(1.0-mc1) * hrmap[0][blr][blc+1] + (1.0-mr1)*mc1 * hrmap[0][blr+1][blc] + (1.0-mr1)*(1.0-mc1) * hrmap[0][blr+1][blc+1]; - double mulg = mr1*mc1 * hrmap[1][blr][blc] + mr1*(1.0-mc1) * hrmap[1][blr][blc+1] + (1.0-mr1)*mc1 * hrmap[1][blr+1][blc] + (1.0-mr1)*(1.0-mc1) * hrmap[1][blr+1][blc+1]; - double mulb = mr1*mc1 * hrmap[2][blr][blc] + mr1*(1.0-mc1) * hrmap[2][blr][blc+1] + (1.0-mr1)*mc1 * hrmap[2][blr+1][blc] + (1.0-mr1)*(1.0-mc1) * hrmap[2][blr+1][blc+1]; + } + + double mc1 = 1.0 - ((double)((j + HR_SCALE / 2) % HR_SCALE) / HR_SCALE + 0.5 / HR_SCALE); + double mulr = mr1 * mc1 * hrmap[0][blr][blc] + mr1 * (1.0 - mc1) * hrmap[0][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[0][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[0][blr + 1][blc + 1]; + double mulg = mr1 * mc1 * hrmap[1][blr][blc] + mr1 * (1.0 - mc1) * hrmap[1][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[1][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[1][blr + 1][blc + 1]; + double mulb = mr1 * mc1 * hrmap[2][blr][blc] + mr1 * (1.0 - mc1) * hrmap[2][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[2][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[2][blr + 1][blc + 1]; red[jx] = (red[jx] * mulr); green[jx] = (green[jx] * mulg); blue[jx] = (blue[jx] * mulb); @@ -236,24 +272,36 @@ void RawImageSource::HLRecovery_ColorPropagation (float* red, float* green, floa red[jx] = (red[jx]); green[jx] = (green[jx]); blue[jx] = (blue[jx]); - } + } } } -void RawImageSource::updateHLRecoveryMap_ColorPropagation () { +void RawImageSource::updateHLRecoveryMap_ColorPropagation () +{ // detect maximal pixel values float* red = new float[W]; float* blue = new float[W]; int maxr = 0, maxg = 0, maxb = 0; - for (int i=32; iISRED(i,j) || ri->getSensorType()!=ST_BAYER) && red[j] > maxr) maxr = red[j]; - if ((ri->ISGREEN(i,j) || ri->getSensorType()!=ST_BAYER) && green[i][j] > maxg) maxg = green[i][j]; - if ((ri->ISBLUE(i,j) || ri->getSensorType()!=ST_BAYER) && blue[j] > maxb) maxb = blue[j]; + + for (int i = 32; i < H - 32; i++) { + interpolate_row_rb (red, blue, green[i - 1], green[i], green[i + 1], i); + + for (int j = 32; j < W - 32; j++) { + if ((ri->ISRED(i, j) || ri->getSensorType() != ST_BAYER) && red[j] > maxr) { + maxr = red[j]; + } + + if ((ri->ISGREEN(i, j) || ri->getSensorType() != ST_BAYER) && green[i][j] > maxg) { + maxg = green[i][j]; + } + + if ((ri->ISBLUE(i, j) || ri->getSensorType() != ST_BAYER) && blue[j] > maxb) { + maxb = blue[j]; + } } } + delete [] red; delete [] blue; @@ -265,66 +313,106 @@ void RawImageSource::updateHLRecoveryMap_ColorPropagation () { max_3[2] = maxb; // downscale image - int dw = W/HR_SCALE; - int dh = H/HR_SCALE; + int dw = W / HR_SCALE; + int dh = H / HR_SCALE; Image16* ds = new Image16 (dw, dh); // overburnt areas int** rec[3]; - for (int i=0; i<3; i++) - rec[i] = allocArray (dw, dh); - float* reds[HR_SCALE]; + for (int i = 0; i < 3; i++) { + rec[i] = allocArray (dw, dh); + } + + float* reds[HR_SCALE]; float* blues[HR_SCALE]; - for (int i=0; i(needhr, H); - needhr = allocArray (W, H); + if (needhr) { + freeArray(needhr, H); + } - for (int i=0; i=max_3[0] || green[HR_SCALE*i+j][k]>=max_3[1] || blues[j][k]>=max_3[2]) - needhr[HR_SCALE*i+j][k] = 1; - else - needhr[HR_SCALE*i+j][k] = 0; - } - for (int j=0; j (W, H); + + for (int i = 0; i < dh; i++) { + for (int j = 0; j < HR_SCALE; j++) { + interpolate_row_rb (reds[j], blues[j], green[HR_SCALE * i + j - 1], green[HR_SCALE * i + j], green[HR_SCALE * i + j + 1], HR_SCALE * i + j); + + for (int k = 0; k < W; k++) + if (reds[j][k] >= max_3[0] || green[HR_SCALE * i + j][k] >= max_3[1] || blues[j][k] >= max_3[2]) { + needhr[HR_SCALE * i + j][k] = 1; + } else { + needhr[HR_SCALE * i + j][k] = 0; } - if (crr(i,j) = sumr / HR_SCALE/HR_SCALE; - ds->g(i,j) = sumg / HR_SCALE/HR_SCALE; - ds->b(i,j) = sumb / HR_SCALE/HR_SCALE; + } + + for (int j = 0; j < dw; j++) { + int sumr = 0; + int cr = 0; + int sumg = 0; + int cg = 0; + int sumb = 0; + int cb = 0; + + for (int x = 0; x < HR_SCALE; x++) + for (int y = 0; y < HR_SCALE; y++) { + int ix = HR_SCALE * i + x; + int jy = HR_SCALE * j + y; + sumr += reds[x][jy]; + + if (reds[x][jy] < maxr) { + cr++; + } + + sumg += green[ix][jy]; + + if (green[ix][jy] < maxg) { + cg++; + } + + sumb += blues[x][jy]; + + if (blues[x][jy] < maxb) { + cb++; + } + } + + if (cr < HR_SCALE * HR_SCALE) { + rec[0][i][j] = INT_MAX; + } else { + rec[0][i][j] = sumr / HR_SCALE / HR_SCALE; + } + + if (cg < HR_SCALE * HR_SCALE) { + rec[1][i][j] = INT_MAX; + } else { + rec[1][i][j] = sumg / HR_SCALE / HR_SCALE; + } + + if (cb < HR_SCALE * HR_SCALE) { + rec[2][i][j] = INT_MAX; + } else { + rec[2][i][j] = sumb / HR_SCALE / HR_SCALE; + } + + ds->r(i, j) = sumr / HR_SCALE / HR_SCALE; + ds->g(i, j) = sumg / HR_SCALE / HR_SCALE; + ds->b(i, j) = sumb / HR_SCALE / HR_SCALE; } } - for (int i=0; i (hrmap[0], dh); freeArray (hrmap[1], dh); freeArray (hrmap[2], dh); @@ -334,15 +422,15 @@ void RawImageSource::updateHLRecoveryMap_ColorPropagation () { hrmap[1] = allocArray (dw, dh); hrmap[2] = allocArray (dw, dh); - for (int i=0; ir(i,j)>0 ? (double)rec[0][i][j] / ds->r(i,j) : 1.0; - hrmap[1][i][j] = ds->g(i,j)>0 ? (double)rec[1][i][j] / ds->g(i,j) : 1.0; - hrmap[2][i][j] = ds->b(i,j)>0 ? (double)rec[2][i][j] / ds->b(i,j) : 1.0; + for (int i = 0; i < dh; i++) + for (int j = 0; j < dw; j++) { + hrmap[0][i][j] = ds->r(i, j) > 0 ? (double)rec[0][i][j] / ds->r(i, j) : 1.0; + hrmap[1][i][j] = ds->g(i, j) > 0 ? (double)rec[1][i][j] / ds->g(i, j) : 1.0; + hrmap[2][i][j] = ds->b(i, j) > 0 ? (double)rec[2][i][j] / ds->b(i, j) : 1.0; } delete ds; - + freeArray (rec[0], dh); freeArray (rec[1], dh); freeArray (rec[2], dh); diff --git a/rtengine/hlrecovery.cc b/rtengine/hlrecovery.cc index 430466e53..4f527b660 100644 --- a/rtengine/hlrecovery.cc +++ b/rtengine/hlrecovery.cc @@ -7,7 +7,7 @@ * 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 @@ -17,30 +17,47 @@ * along with RawTherapee. If not, see . */ -namespace rtengine { +namespace rtengine +{ -template T** allocArray (int W, int H) { +template T** allocArray (int W, int H) +{ T** t = new T*[H]; - for (int i=0; i maxr) maxr = red[j]; - if (green[i][j] > maxg) maxg = green[i][j]; - if (blue[j] > maxb) maxb = blue[j]; + + for (int i = 32; i < H - 32; i++) { + interpolate_row_rb (red, blue, green[i - 1], green[i], green[i + 1], i); + + for (int j = 32; j < W - 32; j++) { + if (red[j] > maxr) { + maxr = red[j]; + } + + if (green[i][j] > maxg) { + maxg = green[i][j]; + } + + if (blue[j] > maxb) { + maxb = blue[j]; + } } } + delete [] red; delete [] blue; @@ -51,53 +68,92 @@ void RawImageSource::updateHLRecoveryMap (bool needred, bool needgreen, bool nee max[0] = maxr; max[1] = maxg; max[2] = maxb; - if( options.rtSettings.verbose ) - printf ("HLRecoveryMap Maximum: R: %d, G: %d, B: %d\n", maxr, maxg, maxb); + + if( options.rtSettings.verbose ) { + printf ("HLRecoveryMap Maximum: R: %d, G: %d, B: %d\n", maxr, maxg, maxb); + } // downscale image - int dw = W/SCALE; - int dh = H/SCALE; + int dw = W / SCALE; + int dh = H / SCALE; Image16* ds = new Image16 (dw, dh); // overburnt areas int** rec[3]; - for (int i=0; i<3; i++) - rec[i] = allocArray (dw, dh); - unsigned short* reds[SCALE]; + for (int i = 0; i < 3; i++) { + rec[i] = allocArray (dw, dh); + } + + unsigned short* reds[SCALE]; unsigned short* blues[SCALE]; - for (int i=0; ir(i,j) = sumr / SCALE/SCALE; - ds->g(i,j) = sumg / SCALE/SCALE; - ds->b(i,j) = sumb / SCALE/SCALE; + + if (cr < SCALE * SCALE && needred) { + rec[0][i][j] = INT_MAX; + } else { + rec[0][i][j] = sumr / SCALE / SCALE; + } + + if (cg < SCALE * SCALE && needgreen) { + rec[1][i][j] = INT_MAX; + } else { + rec[1][i][j] = sumg / SCALE / SCALE; + } + + if (cb < SCALE * SCALE && needblue) { + rec[2][i][j] = INT_MAX; + } else { + rec[2][i][j] = sumb / SCALE / SCALE; + } + + ds->r(i, j) = sumr / SCALE / SCALE; + ds->g(i, j) = sumg / SCALE / SCALE; + ds->b(i, j) = sumb / SCALE / SCALE; } } - for (int i=0; i200) + + for (int k = 0; k < 400; k++) { + if (k > 200) { phase2 = true; - for (int i=1; i=0) { - for (int x=-1; x<=1; x++) - for (int y=-1; y<=1; y++) + if (rec[m][i][j] != INT_MAX && rec[m][i][j] >= 0) { + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) + // average m/c color ratios in the surrounding pixels - if (rec[m][i+x][j+y]>=0 && rec[m][i+x][j+y]!=INT_MAX && rec[c][i+x][j+y]>0 && rec[c][i+x][j+y]!=INT_MAX) { + if (rec[m][i + x][j + y] >= 0 && rec[m][i + x][j + y] != INT_MAX && rec[c][i + x][j + y] > 0 && rec[c][i + x][j + y] != INT_MAX) { double ww = 1.0; - if (!phase2 && (/*(double)(rec[m][i+x][j+y] - rec[m][i][j])/max[m]*(rec[m][i+x][j+y] - rec[m][i][j])/max[m] > 1.0/2 || */rec[c][i+x][j+y] 1.0/2 || */rec[c][i + x][j + y] < max[c] * 3 / 4)) { continue; + } + w[ix] += ww; - ratio[ix] += ww * rec[m][i+x][j+y] / rec[c][i+x][j+y]; + ratio[ix] += ww * rec[m][i + x][j + y] / rec[c][i + x][j + y]; count[ix] ++; } } + ix++; } + // compute new pixel values from the surrounding color ratios - double newc=0.0; + double newc = 0.0; int nc = 0; ix = 0; - for (int m=0; m<3; m++) { - if (c==m) + + for (int m = 0; m < 3; m++) { + if (c == m) { continue; + } + if (count[ix]) { newc += (double)rec[m][i][j] / ratio[ix] * w[ix]; nc++; } + ix++; } - if (nc) + + if (nc) { rec[c][i][j] = - (int) (newc / nc); + } } } } + bool change = false; - for (int i=0; i200) - phase2 = true; - for (int i=1; i0 && rec[0][i+x][j+y]!=INT_MAX && rec[1][i+x][j+y]>0 && rec[1][i+x][j+y]!=INT_MAX && rec[2][i+x][j+y]>0 && rec[2][i+x][j+y]!=INT_MAX) { - // convert to yiq - double Y = 0.299 * rec[0][i+x][j+y] + 0.587 * rec[1][i+x][j+y] + 0.114 * rec[2][i+x][j+y]; - double I = 0.596 * rec[0][i+x][j+y] - 0.275 * rec[1][i+x][j+y] - 0.321 * rec[2][i+x][j+y]; - double Q = 0.212 * rec[0][i+x][j+y] - 0.523 * rec[1][i+x][j+y] + 0.311 * rec[2][i+x][j+y]; - if (Y > maxY*7/10) { - double w = 1.0;// / (I*I+Q*Q); - yavg += Y*w; - iavg += I*w; - qavg += Q*w; - weight += w; - count++; - } - } - if ((!phase2 && count>5) || (phase2 && count>3)) { - double Y = yavg / weight; - double I = iavg / weight; - double Q = qavg / weight; - rec[0][i][j] = - (Y + 0.956*I + 0.621*Q); - rec[1][i][j] = - (Y - 0.272*I - 0.647*Q); - rec[2][i][j] = - (Y - 1.105*I + 1.702*Q); - } - } + if (full) { + int maxY = (299 * max[0] + 587 * max[1] + 114 * max[2]) / 1000; + phase2 = false; + for (int k = 0; k < 600; k++) { + if (k > 200) { + phase2 = true; } - bool change = false; - for (int i=0; imaxval) + for (int i = 1; i < dh - 1; i++) + for (int j = 1; j < dw - 1; j++) { + if (rec[0][i][j] == INT_MAX || rec[1][i][j] == INT_MAX || rec[2][i][j] == INT_MAX) { + int count = 0; + double yavg = 0, iavg = 0, qavg = 0, weight = 0.0; + + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) + if (rec[0][i + x][j + y] > 0 && rec[0][i + x][j + y] != INT_MAX && rec[1][i + x][j + y] > 0 && rec[1][i + x][j + y] != INT_MAX && rec[2][i + x][j + y] > 0 && rec[2][i + x][j + y] != INT_MAX) { + // convert to yiq + double Y = 0.299 * rec[0][i + x][j + y] + 0.587 * rec[1][i + x][j + y] + 0.114 * rec[2][i + x][j + y]; + double I = 0.596 * rec[0][i + x][j + y] - 0.275 * rec[1][i + x][j + y] - 0.321 * rec[2][i + x][j + y]; + double Q = 0.212 * rec[0][i + x][j + y] - 0.523 * rec[1][i + x][j + y] + 0.311 * rec[2][i + x][j + y]; + + if (Y > maxY * 7 / 10) { + double w = 1.0;// / (I*I+Q*Q); + yavg += Y * w; + iavg += I * w; + qavg += Q * w; + weight += w; + count++; + } + } + + if ((!phase2 && count > 5) || (phase2 && count > 3)) { + double Y = yavg / weight; + double I = iavg / weight; + double Q = qavg / weight; + rec[0][i][j] = - (Y + 0.956 * I + 0.621 * Q); + rec[1][i][j] = - (Y - 0.272 * I - 0.647 * Q); + rec[2][i][j] = - (Y - 1.105 * I + 1.702 * Q); + } + } + + } + + bool change = false; + + for (int i = 0; i < dh; i++) + for (int j = 0; j < dw; j++) + for (int c = 0; c < 3; c++) { + if (rec[c][i][j] < 0) { + rec[c][i][j] = -rec[c][i][j]; + } + + change = true; + } + + if (!change) { + break; + } + } + } + + int maxval = 0; + + for (int i = 0; i < dh; i++) + for (int j = 0; j < dw; j++) + for (int c = 0; c < 3; c++) + if (rec[c][i][j] != INT_MAX && rec[c][i][j] > maxval) { maxval = rec[c][i][j]; - - for (int i=0; i (hrmap[0], dh); freeArray (hrmap[1], dh); freeArray (hrmap[2], dh); } + hrmap[0] = allocArray (dw, dh); hrmap[1] = allocArray (dw, dh); hrmap[2] = allocArray (dw, dh); this->full = full; - - for (int i=0; ir(i,j); - hrmap[1][i][j] = (double)rec[1][i][j] / ds->g(i,j); - hrmap[2][i][j] = (double)rec[2][i][j] / ds->b(i,j); + + for (int i = 0; i < dh; i++) + for (int j = 0; j < dw; j++) { + hrmap[0][i][j] = (double)rec[0][i][j] / ds->r(i, j); + hrmap[1][i][j] = (double)rec[1][i][j] / ds->g(i, j); + hrmap[2][i][j] = (double)rec[2][i][j] / ds->b(i, j); } - -/* for (int i=0; ir(i,j) = CLIP (rec[0][i][j]); - ds->g(i,j) = CLIP (rec[1][i][j]); - ds->b(i,j) = CLIP (rec[2][i][j]); - } - ds->save ("test.png"); -*/ + + /* for (int i=0; ir(i,j) = CLIP (rec[0][i][j]); + ds->g(i,j) = CLIP (rec[1][i][j]); + ds->b(i,j) = CLIP (rec[2][i][j]); + } + ds->save ("test.png"); + */ delete ds; freeArray (rec[0], dh); freeArray (rec[1], dh); freeArray (rec[2], dh); - + printf ("HLMap vege\n"); } -void RawImageSource::hlRecovery (unsigned short* red, unsigned short* green, unsigned short* blue, int i, int sx1, int sx2, int skip) { +void RawImageSource::hlRecovery (unsigned short* red, unsigned short* green, unsigned short* blue, int i, int sx1, int sx2, int skip) +{ - int blr = (i+SCALE/2) / SCALE - 1; - if (blr<0 || blr>=H/SCALE-1) + int blr = (i + SCALE / 2) / SCALE - 1; + + if (blr < 0 || blr >= H / SCALE - 1) { return; - double mr1 = 1.0 - ((double)((i+SCALE/2) % SCALE) / SCALE + 0.5 / SCALE); + } + + double mr1 = 1.0 - ((double)((i + SCALE / 2) % SCALE) / SCALE + 0.5 / SCALE); int jx = 0; - int maxcol = W/SCALE; - for (int j=sx1, jx=0; j=maxcol-1) + int maxcol = W / SCALE; + + for (int j = sx1, jx = 0; j < sx2; j += skip, jx++) { + int blc = (j + SCALE / 2) / SCALE - 1; + + if (blc < 0 || blc >= maxcol - 1) { continue; - double mc1 = 1.0 - ((double)((j+SCALE/2) % SCALE) / SCALE + 0.5 / SCALE); - double mulr = mr1*mc1 * hrmap[0][blr][blc] + mr1*(1.0-mc1) * hrmap[0][blr][blc+1] + (1.0-mr1)*mc1 * hrmap[0][blr+1][blc] + (1.0-mr1)*(1.0-mc1) * hrmap[0][blr+1][blc+1]; - double mulg = mr1*mc1 * hrmap[1][blr][blc] + mr1*(1.0-mc1) * hrmap[1][blr][blc+1] + (1.0-mr1)*mc1 * hrmap[1][blr+1][blc] + (1.0-mr1)*(1.0-mc1) * hrmap[1][blr+1][blc+1]; - double mulb = mr1*mc1 * hrmap[2][blr][blc] + mr1*(1.0-mc1) * hrmap[2][blr][blc+1] + (1.0-mr1)*mc1 * hrmap[2][blr+1][blc] + (1.0-mr1)*(1.0-mc1) * hrmap[2][blr+1][blc+1]; + } + + double mc1 = 1.0 - ((double)((j + SCALE / 2) % SCALE) / SCALE + 0.5 / SCALE); + double mulr = mr1 * mc1 * hrmap[0][blr][blc] + mr1 * (1.0 - mc1) * hrmap[0][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[0][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[0][blr + 1][blc + 1]; + double mulg = mr1 * mc1 * hrmap[1][blr][blc] + mr1 * (1.0 - mc1) * hrmap[1][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[1][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[1][blr + 1][blc + 1]; + double mulb = mr1 * mc1 * hrmap[2][blr][blc] + mr1 * (1.0 - mc1) * hrmap[2][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[2][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[2][blr + 1][blc + 1]; red[jx] = CLIP(red[jx] * mulr); green[jx] = CLIP(green[jx] * mulg); blue[jx] = CLIP(blue[jx] * mulb); diff --git a/rtengine/iccjpeg.cc b/rtengine/iccjpeg.cc index 7500d27ec..fef281c49 100644 --- a/rtengine/iccjpeg.cc +++ b/rtengine/iccjpeg.cc @@ -18,7 +18,7 @@ */ #include "iccjpeg.h" -#include /* define malloc() */ +#include /* define malloc() */ /* @@ -26,17 +26,17 @@ * (64K), we need provisions to split it into multiple markers. The format * defined by the ICC specifies one or more APP2 markers containing the * following data: - * Identifying string ASCII "ICC_PROFILE\0" (12 bytes) - * Marker sequence number 1 for first APP2, 2 for next, etc (1 byte) - * Number of markers Total number of APP2's used (1 byte) - * Profile data (remainder of APP2 data) + * Identifying string ASCII "ICC_PROFILE\0" (12 bytes) + * Marker sequence number 1 for first APP2, 2 for next, etc (1 byte) + * Number of markers Total number of APP2's used (1 byte) + * Profile data (remainder of APP2 data) * Decoders should use the marker sequence numbers to reassemble the profile, * rather than assuming that the APP2 markers appear in the correct sequence. */ -#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ -#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */ -#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */ +#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ +#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */ +#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */ #define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN) @@ -50,56 +50,62 @@ void write_icc_profile (j_compress_ptr cinfo, - const JOCTET *icc_data_ptr, - unsigned int icc_data_len) + const JOCTET *icc_data_ptr, + unsigned int icc_data_len) { - unsigned int num_markers; /* total number of markers we'll write */ - int cur_marker = 1; /* per spec, counting starts at 1 */ - unsigned int length; /* number of bytes to write in this marker */ + unsigned int num_markers; /* total number of markers we'll write */ + int cur_marker = 1; /* per spec, counting starts at 1 */ + unsigned int length; /* number of bytes to write in this marker */ - /* Calculate the number of markers we'll need, rounding up of course */ - num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER; - if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len) - num_markers++; + /* Calculate the number of markers we'll need, rounding up of course */ + num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER; - while (icc_data_len > 0) { - /* length of profile to put in this marker */ - length = icc_data_len; - if (length > MAX_DATA_BYTES_IN_MARKER) - length = MAX_DATA_BYTES_IN_MARKER; - icc_data_len -= length; - - /* Write the JPEG marker header (APP2 code and marker length) */ - jpeg_write_m_header(cinfo, ICC_MARKER, (unsigned int) (length + ICC_OVERHEAD_LEN)); - - /* Write the marker identifying string "ICC_PROFILE" (null-terminated). - * We code it in this less-than-transparent way so that the code works - * even if the local character set is not ASCII. - */ - jpeg_write_m_byte(cinfo, 0x49); - jpeg_write_m_byte(cinfo, 0x43); - jpeg_write_m_byte(cinfo, 0x43); - jpeg_write_m_byte(cinfo, 0x5F); - jpeg_write_m_byte(cinfo, 0x50); - jpeg_write_m_byte(cinfo, 0x52); - jpeg_write_m_byte(cinfo, 0x4F); - jpeg_write_m_byte(cinfo, 0x46); - jpeg_write_m_byte(cinfo, 0x49); - jpeg_write_m_byte(cinfo, 0x4C); - jpeg_write_m_byte(cinfo, 0x45); - jpeg_write_m_byte(cinfo, 0x0); - - /* Add the sequencing info */ - jpeg_write_m_byte(cinfo, cur_marker); - jpeg_write_m_byte(cinfo, (int) num_markers); - - /* Add the profile data */ - while (length--) { - jpeg_write_m_byte(cinfo, *icc_data_ptr); - icc_data_ptr++; + if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len) { + num_markers++; + } + + while (icc_data_len > 0) { + /* length of profile to put in this marker */ + length = icc_data_len; + + if (length > MAX_DATA_BYTES_IN_MARKER) { + length = MAX_DATA_BYTES_IN_MARKER; + } + + icc_data_len -= length; + + /* Write the JPEG marker header (APP2 code and marker length) */ + jpeg_write_m_header(cinfo, ICC_MARKER, (unsigned int) (length + ICC_OVERHEAD_LEN)); + + /* Write the marker identifying string "ICC_PROFILE" (null-terminated). + * We code it in this less-than-transparent way so that the code works + * even if the local character set is not ASCII. + */ + jpeg_write_m_byte(cinfo, 0x49); + jpeg_write_m_byte(cinfo, 0x43); + jpeg_write_m_byte(cinfo, 0x43); + jpeg_write_m_byte(cinfo, 0x5F); + jpeg_write_m_byte(cinfo, 0x50); + jpeg_write_m_byte(cinfo, 0x52); + jpeg_write_m_byte(cinfo, 0x4F); + jpeg_write_m_byte(cinfo, 0x46); + jpeg_write_m_byte(cinfo, 0x49); + jpeg_write_m_byte(cinfo, 0x4C); + jpeg_write_m_byte(cinfo, 0x45); + jpeg_write_m_byte(cinfo, 0x0); + + /* Add the sequencing info */ + jpeg_write_m_byte(cinfo, cur_marker); + jpeg_write_m_byte(cinfo, (int) num_markers); + + /* Add the profile data */ + while (length--) { + jpeg_write_m_byte(cinfo, *icc_data_ptr); + icc_data_ptr++; + } + + cur_marker++; } - cur_marker++; - } } @@ -110,8 +116,8 @@ write_icc_profile (j_compress_ptr cinfo, void setup_read_icc_profile (j_decompress_ptr cinfo) { - /* Tell the library to keep any APP2 data it may find */ - jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF); + /* Tell the library to keep any APP2 data it may find */ + jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF); } @@ -121,22 +127,22 @@ setup_read_icc_profile (j_decompress_ptr cinfo) static boolean marker_is_icc (jpeg_saved_marker_ptr marker) { - return - marker->marker == ICC_MARKER && - marker->data_length >= ICC_OVERHEAD_LEN && - /* verify the identifying string */ - GETJOCTET(marker->data[0]) == 0x49 && - GETJOCTET(marker->data[1]) == 0x43 && - GETJOCTET(marker->data[2]) == 0x43 && - GETJOCTET(marker->data[3]) == 0x5F && - GETJOCTET(marker->data[4]) == 0x50 && - GETJOCTET(marker->data[5]) == 0x52 && - GETJOCTET(marker->data[6]) == 0x4F && - GETJOCTET(marker->data[7]) == 0x46 && - GETJOCTET(marker->data[8]) == 0x49 && - GETJOCTET(marker->data[9]) == 0x4C && - GETJOCTET(marker->data[10]) == 0x45 && - GETJOCTET(marker->data[11]) == 0x0; + return + marker->marker == ICC_MARKER && + marker->data_length >= ICC_OVERHEAD_LEN && + /* verify the identifying string */ + GETJOCTET(marker->data[0]) == 0x49 && + GETJOCTET(marker->data[1]) == 0x43 && + GETJOCTET(marker->data[2]) == 0x43 && + GETJOCTET(marker->data[3]) == 0x5F && + GETJOCTET(marker->data[4]) == 0x50 && + GETJOCTET(marker->data[5]) == 0x52 && + GETJOCTET(marker->data[6]) == 0x4F && + GETJOCTET(marker->data[7]) == 0x46 && + GETJOCTET(marker->data[8]) == 0x49 && + GETJOCTET(marker->data[9]) == 0x4C && + GETJOCTET(marker->data[10]) == 0x45 && + GETJOCTET(marker->data[11]) == 0x0; } @@ -161,84 +167,99 @@ marker_is_icc (jpeg_saved_marker_ptr marker) boolean read_icc_profile (j_decompress_ptr cinfo, - JOCTET **icc_data_ptr, - unsigned int *icc_data_len) + JOCTET **icc_data_ptr, + unsigned int *icc_data_len) { - jpeg_saved_marker_ptr marker; - int num_markers = 0; - int seq_no; - JOCTET *icc_data; - unsigned int total_length; -#define MAX_SEQ_NO 255 /* sufficient since marker numbers are bytes */ - char marker_present[MAX_SEQ_NO+1]; /* 1 if marker found */ - unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */ - unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */ + jpeg_saved_marker_ptr marker; + int num_markers = 0; + int seq_no; + JOCTET *icc_data; + unsigned int total_length; +#define MAX_SEQ_NO 255 /* sufficient since marker numbers are bytes */ + char marker_present[MAX_SEQ_NO + 1]; /* 1 if marker found */ + unsigned int data_length[MAX_SEQ_NO + 1]; /* size of profile data in marker */ + unsigned int data_offset[MAX_SEQ_NO + 1]; /* offset for data in marker */ - *icc_data_ptr = NULL; /* avoid confusion if FALSE return */ - *icc_data_len = 0; + *icc_data_ptr = NULL; /* avoid confusion if FALSE return */ + *icc_data_len = 0; - /* This first pass over the saved markers discovers whether there are - * any ICC markers and verifies the consistency of the marker numbering. - */ + /* This first pass over the saved markers discovers whether there are + * any ICC markers and verifies the consistency of the marker numbering. + */ - for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++) - marker_present[seq_no] = 0; - - for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { - if (marker_is_icc(marker)) { - if (num_markers == 0) - num_markers = GETJOCTET(marker->data[13]); - else if (num_markers != GETJOCTET(marker->data[13])) - return FALSE; /* inconsistent num_markers fields */ - seq_no = GETJOCTET(marker->data[12]); - if (seq_no <= 0 || seq_no > num_markers) - return FALSE; /* bogus sequence number */ - if (marker_present[seq_no]) - return FALSE; /* duplicate sequence numbers */ - marker_present[seq_no] = 1; - data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN; + for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++) { + marker_present[seq_no] = 0; } - } - if (num_markers == 0) - return FALSE; + for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker_is_icc(marker)) { + if (num_markers == 0) { + num_markers = GETJOCTET(marker->data[13]); + } else if (num_markers != GETJOCTET(marker->data[13])) { + return FALSE; /* inconsistent num_markers fields */ + } - /* Check for missing markers, count total space needed, - * compute offset of each marker's part of the data. - */ + seq_no = GETJOCTET(marker->data[12]); - total_length = 0; - for (seq_no = 1; seq_no <= num_markers; seq_no++) { - if (marker_present[seq_no] == 0) - return FALSE; /* missing sequence number */ - data_offset[seq_no] = total_length; - total_length += data_length[seq_no]; - } + if (seq_no <= 0 || seq_no > num_markers) { + return FALSE; /* bogus sequence number */ + } - /* Allocate space for assembled data */ - icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET)); - if (icc_data == NULL) - return FALSE; /* oops, out of memory */ + if (marker_present[seq_no]) { + return FALSE; /* duplicate sequence numbers */ + } - /* and fill it in */ - for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { - if (marker_is_icc(marker)) { - JOCTET FAR *src_ptr; - JOCTET *dst_ptr; - unsigned int length; - seq_no = GETJOCTET(marker->data[12]); - dst_ptr = icc_data + data_offset[seq_no]; - src_ptr = marker->data + ICC_OVERHEAD_LEN; - length = data_length[seq_no]; - while (length--) { - *dst_ptr++ = *src_ptr++; - } + marker_present[seq_no] = 1; + data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN; + } } - } - *icc_data_ptr = icc_data; - *icc_data_len = total_length; + if (num_markers == 0) { + return FALSE; + } - return TRUE; + /* Check for missing markers, count total space needed, + * compute offset of each marker's part of the data. + */ + + total_length = 0; + + for (seq_no = 1; seq_no <= num_markers; seq_no++) { + if (marker_present[seq_no] == 0) { + return FALSE; /* missing sequence number */ + } + + data_offset[seq_no] = total_length; + total_length += data_length[seq_no]; + } + + /* Allocate space for assembled data */ + icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET)); + + if (icc_data == NULL) { + return FALSE; /* oops, out of memory */ + } + + /* and fill it in */ + for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker_is_icc(marker)) { + JOCTET FAR *src_ptr; + JOCTET *dst_ptr; + unsigned int length; + seq_no = GETJOCTET(marker->data[12]); + dst_ptr = icc_data + data_offset[seq_no]; + src_ptr = marker->data + ICC_OVERHEAD_LEN; + length = data_length[seq_no]; + + while (length--) { + *dst_ptr++ = *src_ptr++; + } + } + } + + *icc_data_ptr = icc_data; + *icc_data_len = total_length; + + return TRUE; } diff --git a/rtengine/iccjpeg.h b/rtengine/iccjpeg.h index d7cae7b5d..ce715948d 100644 --- a/rtengine/iccjpeg.h +++ b/rtengine/iccjpeg.h @@ -16,7 +16,7 @@ * for details. */ -#include /* needed to define "FILE", "NULL" */ +#include /* needed to define "FILE", "NULL" */ #include "jpeglib.h" @@ -29,8 +29,8 @@ */ extern void write_icc_profile JPP((j_compress_ptr cinfo, - const JOCTET *icc_data_ptr, - unsigned int icc_data_len)); + const JOCTET *icc_data_ptr, + unsigned int icc_data_len)); /* @@ -69,6 +69,6 @@ extern void setup_read_icc_profile JPP((j_decompress_ptr cinfo)); */ extern boolean read_icc_profile JPP((j_decompress_ptr cinfo, - JOCTET **icc_data_ptr, - unsigned int *icc_data_len)); + JOCTET **icc_data_ptr, + unsigned int *icc_data_len)); diff --git a/rtengine/iccmatrices.h b/rtengine/iccmatrices.h index e5a91c4e0..9e9682a73 100644 --- a/rtengine/iccmatrices.h +++ b/rtengine/iccmatrices.h @@ -7,7 +7,7 @@ * 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 @@ -21,90 +21,108 @@ // Bradford transform between illuminants const double d65_d50[3][3] = {{0.9555766, -0.0230393, 0.0631636}, - {-0.0282895, 1.0099416, 0.0210077}, - {0.0122982, -0.0204830, 1.3299098}}; + { -0.0282895, 1.0099416, 0.0210077}, + {0.0122982, -0.0204830, 1.3299098} +}; const double d50_d65[3][3] = {{ 1.0478112, 0.0228866, -0.0501270}, - {0.0295424, 0.9904844, -0.0170491}, - {-0.0092345, 0.0150436, 0.7521316}}; + {0.0295424, 0.9904844, -0.0170491}, + { -0.0092345, 0.0150436, 0.7521316} +}; // Color space conversion to/from XYZ; color spaces adapted to D65 const double xyz_sRGBd65[3][3] = {{0.4124564, 0.3575761, 0.1804375}, - {0.2126729, 0.7151522, 0.0721750}, // WARNING: the summ of this line is > 1.0 - {0.0193339, 0.1191920, 0.9503041}}; + {0.2126729, 0.7151522, 0.0721750}, // WARNING: the summ of this line is > 1.0 + {0.0193339, 0.1191920, 0.9503041} +}; const double sRGBd65_xyz[3][3] = {{ 3.2404542, -1.5371385, -0.4985314}, - {-0.9692660, 1.8760108, 0.0415560}, - {0.0556434, -0.2040259, 1.0572252}}; + { -0.9692660, 1.8760108, 0.0415560}, + {0.0556434, -0.2040259, 1.0572252} +}; //%%%%%%%%%%%%%%%%%%%%%%%% // TEST using Gabor's matrices -/*const double xyz_sRGB[3][3] = {{0.435859, 0.385336, 0.143023}, - {0.222385, 0.717021, 0.0605936 }, - {0.0139162, 0.0971389, 0.713817}}; +/*const double xyz_sRGB[3][3] = {{0.435859, 0.385336, 0.143023}, + {0.222385, 0.717021, 0.0605936 }, + {0.0139162, 0.0971389, 0.713817}}; const double sRGB_xyz[3][3] = {{3.13593293538656, -1.61878246026431, -0.490913888760734}, - {-0.978702373022194, 1.91609508555177, 0.0334453372795315}, - {0.0720490013929888, -0.22919049060526, 1.40593851447263}};*/ + {-0.978702373022194, 1.91609508555177, 0.0334453372795315}, + {0.0720490013929888, -0.22919049060526, 1.40593851447263}};*/ //%%%%%%%%%%%%%%%%%%%%%%%% // Color space conversion to/from XYZ; color spaces adapted to D50 using Bradford transform const double xyz_sRGB[3][3] = {{0.4360747, 0.3850649, 0.1430804}, - {0.2225045, 0.7168786, 0.0606169}, - {0.0139322, 0.0971045, 0.7141733}}; + {0.2225045, 0.7168786, 0.0606169}, + {0.0139322, 0.0971045, 0.7141733} +}; const double sRGB_xyz[3][3] = {{3.1338561, -1.6168667, -0.4906146}, - {-0.9787684, 1.9161415, 0.0334540}, - {0.0719453, -0.2289914, 1.4052427}}; + { -0.9787684, 1.9161415, 0.0334540}, + {0.0719453, -0.2289914, 1.4052427} +}; const double xyz_adobe[3][3] = {{0.6097559, 0.2052401, 0.1492240}, - {0.3111242, 0.6256560, 0.0632197}, - {0.0194811, 0.0608902, 0.7448387}}; + {0.3111242, 0.6256560, 0.0632197}, + {0.0194811, 0.0608902, 0.7448387} +}; const double adobe_xyz[3][3] = {{1.9624274, -0.6105343, -0.3413404}, - {-0.9787684, 1.9161415, 0.0334540}, - {0.0286869, -0.1406752, 1.3487655}}; + { -0.9787684, 1.9161415, 0.0334540}, + {0.0286869, -0.1406752, 1.3487655} +}; const double xyz_prophoto[3][3] = {{0.7976749, 0.1351917, 0.0313534}, - {0.2880402, 0.7118741, 0.0000857}, - {0.0000000, 0.0000000, 0.8252100}}; + {0.2880402, 0.7118741, 0.0000857}, + {0.0000000, 0.0000000, 0.8252100} +}; const double prophoto_xyz[3][3] = {{1.3459433, -0.2556075, -0.0511118}, - {-0.5445989, 1.5081673, 0.0205351}, - {0.0000000, 0.0000000, 1.2118128}}; + { -0.5445989, 1.5081673, 0.0205351}, + {0.0000000, 0.0000000, 1.2118128} +}; const double xyz_widegamut[3][3] = {{0.7161046, 0.1009296, 0.1471858}, - {0.2581874, 0.7249378, 0.0168748}, - {0.0000000, 0.0517813, 0.7734287}}; + {0.2581874, 0.7249378, 0.0168748}, + {0.0000000, 0.0517813, 0.7734287} +}; const double widegamut_xyz[3][3] = {{ 1.4628067, -0.1840623, -0.2743606}, - {-0.5217933, 1.4472381, 0.0677227}, - {0.0349342, -0.0968930, 1.2884099}}; + { -0.5217933, 1.4472381, 0.0677227}, + {0.0349342, -0.0968930, 1.2884099} +}; const double xyz_bruce[3][3] = {{0.4941816, 0.3204834, 0.1495550}, - {0.2521531, 0.6844869, 0.0633600}, - {0.0157886, 0.0629304, 0.7464909}}; + {0.2521531, 0.6844869, 0.0633600}, + {0.0157886, 0.0629304, 0.7464909} +}; const double bruce_xyz[3][3] = {{2.6502856, -1.2014485, -0.4289936}, - {-0.9787684, 1.9161415, 0.0334540}, - {0.0264570, -0.1361227, 1.3458542}}; + { -0.9787684, 1.9161415, 0.0334540}, + {0.0264570, -0.1361227, 1.3458542} +}; const double xyz_beta[3][3] = {{0.6712537, 0.1745834, 0.1183829}, - {0.3032726, 0.6637861, 0.0329413}, - {0.0000000, 0.0407010, 0.7845090}}; + {0.3032726, 0.6637861, 0.0329413}, + {0.0000000, 0.0407010, 0.7845090} +}; const double beta_xyz[3][3] = {{1.6832270, -0.4282363, -0.2360185}, - {-0.7710229, 1.7065571, 0.0446900}, - {0.0400013, -0.0885376, 1.2723640}}; + { -0.7710229, 1.7065571, 0.0446900}, + {0.0400013, -0.0885376, 1.2723640} +}; const double xyz_best[3][3] = {{0.6326696, 0.2045558, 0.1269946}, - {0.2284569, 0.7373523, 0.0341908}, - {0.0000000, 0.0095142, 0.8156958}}; + {0.2284569, 0.7373523, 0.0341908}, + {0.0000000, 0.0095142, 0.8156958} +}; const double best_xyz[3][3] = {{1.7552599, -0.4836786, -0.2530000}, - {-0.5441336, 1.5068789, 0.0215528}, - {0.0063467, -0.0175761, 1.2256959}}; + { -0.5441336, 1.5068789, 0.0215528}, + {0.0063467, -0.0175761, 1.2256959} +}; /*const double sRGB_d50[3][3] = {{0.4360520246092, 0.2224915978656, 0.0139291219896}, @@ -114,17 +132,17 @@ const double best_xyz[3][3] = {{1.7552599, -0.4836786, -0.2530000}, const double d50_sRGB[3][3] = {{3.13405134405167,-0.978762729953942, 0.0719425766617001}, {-1.61702771153574,1.91614222810656, -0.228971178679309}, {-0.49065220876631,0.0334496273068589, 1.40521830559074}};*/ - + /* // Gabor's matrices const double sRGB_d50[3][3] = {{0.435859, 0.222385, 0.0139162}, - {0.385336, 0.717021, 0.0971389}, - {0.143023, 0.0605936, 0.713817}}; - + {0.385336, 0.717021, 0.0971389}, + {0.143023, 0.0605936, 0.713817}}; + const double d50_sRGB[3][3] = {{3.13593293538656, -0.978702373022194, 0.0720490013929888}, - {-1.61878246026431, 1.91609508555177, -0.22919049060526}, - {-0.490913888760734, 0.0334453372795315, 1.40593851447263}}; - + {-1.61878246026431, 1.91609508555177, -0.22919049060526}, + {-0.490913888760734, 0.0334453372795315, 1.40593851447263}}; + const double adobe_d50[3][3] = {{0.6097395054954, 0.3111142944042, 0.0194773131652}, {0.2052518325737, 0.6256618480686, 0.0608872306106}, {0.1492308013399, 0.0632241329247, 0.744846530711}}; @@ -142,13 +160,13 @@ const double widegamut_d50[3][3] = {{0.716105, 0.258187, 0.000000}, {0.147186, 0.0168748, 0.773429}}; const double d50_widegamut[3][3] = {{1.46280597103052, -0.521792197260068, 0.0349341417298585}, {-0.184062984909417, 1.44723786022891, -0.0968930022172314}, - {-0.27436071519732, 0.0677226440980744,1.28840945122198}}; + {-0.27436071519732, 0.0677226440980744,1.28840945122198}}; const double bruce_d50[3][3] = {{0.4941607255908, 0.2521412970174, 0.0157852934504}, {0.3204990468435, 0.684494580042, 0.062927176507}, {0.1495612990809, 0.0633643619597, 0.746498914581}}; const double d50_bruce[3][3] = {{2.65042308164152, -0.978762745761462, 0.0264609493245811}, {-1.20155941925411, 1.9161402914007, -0.136115844662896}, - {-0.42902228923717, 0.0334495071197919, 1.34583900936772}}; + {-0.42902228923717, 0.0334495071197919, 1.34583900936772}}; const double beta_d50[3][3] = {{0.671254, 0.303273, 0.000000}, {0.174583, 0.663786, 0.040701}, {0.118383, 0.0329413, 0.784509}}; @@ -157,7 +175,7 @@ const double d50_beta[3][3] = {{1.68322591962771, -0.771023599950842, 0.040001 {-0.236018598193503, 0.0446902191738489,1.27236406897742}}; const double best_d50[3][3] = {{0.632670, 0.228457, 0.000000}, {0.204556, 0.737352, 0.00951424}, - {0.126995, 0.0341908, 0.815696}}; + {0.126995, 0.0341908, 0.815696}}; const double d50_best[3][3] = {{1.75525923340349, -0.544133953997468, 0.00634675299435191}, {-0.483679025800866, 1.50687975713407, -0.017576175021718}, {-0.253000840399762, 0.0215532098817316,1.22569552576991}}; diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index a2f2b533f..195da3fe3 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -7,7 +7,7 @@ * 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 @@ -29,50 +29,66 @@ #include -namespace rtengine { +namespace rtengine +{ const double (*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best}; const double (*iwprofiles[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz}; const char* wpnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB", "Beta RGB", "BestRGB"}; -const char* wpgamma[] = {"default","BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "linear_g1.0", "standard_g2.2", "standard_g1.8", "High_g1.3_s3.35","Low_g2.6_s6.9"}; //gamma free +const char* wpgamma[] = {"default", "BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "linear_g1.0", "standard_g2.2", "standard_g1.8", "High_g1.3_s3.35", "Low_g2.6_s6.9"}; //gamma free //default = gamma inside profile -//BT709 g=2.22 s=4.5 sRGB g=2.4 s=12.92 +//BT709 g=2.22 s=4.5 sRGB g=2.4 s=12.92 //linear g=1.0 //std22 g=2.2 std18 g=1.8 // high g=1.3 s=3.35 for high dynamic images //low g=2.6 s=6.9 for low contrast images -std::vector getGamma () {//return gamma +std::vector getGamma () //return gamma +{ std::vector res; - for (unsigned int i=0; i getWorkingProfiles () { +std::vector getWorkingProfiles () +{ std::vector res; - for (unsigned int i=0; i ICCStore::getOutputProfiles () { +std::vector ICCStore::getOutputProfiles () +{ - MyMutex::MyLock lock(mutex_); + MyMutex::MyLock lock(mutex_); std::vector res; - for (std::map::iterator i=fileProfiles.begin(); i!=fileProfiles.end(); i++){ + + for (std::map::iterator i = fileProfiles.begin(); i != fileProfiles.end(); i++) { Glib::ustring name(i->first); std::string::size_type i2 = name.find_last_of('/'); - if( i2 == std::string::npos ) + + if( i2 == std::string::npos ) { i2 = name.find_last_of('\\'); - if( i2 == std::string::npos ) - res.push_back ( name ); // list only profiles inside selected profiles directory + } + + if( i2 == std::string::npos ) { + res.push_back ( name ); // list only profiles inside selected profiles directory + } } + return res; } @@ -84,12 +100,15 @@ ICCStore::makeStdGammaProfile(cmsHPROFILE iprof) if (!iprof) { return NULL; } + cmsUInt32Number bytesNeeded = 0; cmsSaveProfileToMem(iprof, 0, &bytesNeeded); + if (bytesNeeded == 0) { return NULL; } - uint8_t *data = new uint8_t[bytesNeeded+1]; + + uint8_t *data = new uint8_t[bytesNeeded + 1]; cmsSaveProfileToMem(iprof, data, &bytesNeeded); const uint8_t *p = &data[128]; // skip 128 byte header uint32_t tag_count; @@ -106,20 +125,22 @@ ICCStore::makeStdGammaProfile(cmsHPROFILE iprof) const uint32_t gamma = 0x239; int gamma_size = (gamma == 0 || gamma == 256) ? 12 : 14; int data_size = (gamma_size + 3) & ~3; + for (uint32_t i = 0; i < tag_count; i++) { memcpy(&tags[i], p, 12); tags[i].sig = ntohl(tags[i].sig); tags[i].offset = ntohl(tags[i].offset); tags[i].size = ntohl(tags[i].size); p += 12; + if (tags[i].sig != 0x62545243 && // bTRC - tags[i].sig != 0x67545243 && // gTRC - tags[i].sig != 0x72545243 && // rTRC - tags[i].sig != 0x6B545243) // kTRC - { + tags[i].sig != 0x67545243 && // gTRC + tags[i].sig != 0x72545243 && // rTRC + tags[i].sig != 0x6B545243) { // kTRC data_size += (tags[i].size + 3) & ~3; } } + uint32_t sz = 128 + 4 + tag_count * 12 + data_size; uint8_t *nd = new uint8_t[sz]; memset(nd, 0, sz); @@ -128,24 +149,28 @@ ICCStore::makeStdGammaProfile(cmsHPROFILE iprof) memcpy(nd, &sz, 4); uint32_t offset = 128 + 4 + tag_count * 12; uint32_t gamma_offset = 0; + for (uint32_t i = 0; i < tag_count; i++) { struct icctag tag; tag.sig = htonl(tags[i].sig); + if (tags[i].sig == 0x62545243 || // bTRC - tags[i].sig == 0x67545243 || // gTRC - tags[i].sig == 0x72545243 || // rTRC - tags[i].sig == 0x6B545243) // kTRC - { + tags[i].sig == 0x67545243 || // gTRC + tags[i].sig == 0x72545243 || // rTRC + tags[i].sig == 0x6B545243) { // kTRC if (gamma_offset == 0) { gamma_offset = offset; uint32_t pcurve[] = { htonl(0x63757276), htonl(0), htonl(gamma_size == 12 ? 0 : 1) }; memcpy(&nd[offset], pcurve, 12); + if (gamma_size == 14) { uint16_t gm = htons(gamma); - memcpy(&nd[offset+12], &gm, 2); + memcpy(&nd[offset + 12], &gm, 2); } + offset += (gamma_size + 3) & ~3; } + tag.offset = htonl(gamma_offset); tag.size = htonl(gamma_size); } else { @@ -154,6 +179,7 @@ ICCStore::makeStdGammaProfile(cmsHPROFILE iprof) memcpy(&nd[offset], &data[tags[i].offset], tags[i].size); offset += (tags[i].size + 3) & ~3; } + memcpy(&nd[128 + 4 + i * 12], &tag, 12); } @@ -166,89 +192,108 @@ ICCStore::makeStdGammaProfile(cmsHPROFILE iprof) ICCStore* ICCStore::getInstance(void) { - static ICCStore* instance_ = 0; - if ( instance_ == 0 ) - { - static MyMutex smutex_; - MyMutex::MyLock lock(smutex_); - if ( instance_ == 0 ) - { - instance_ = new ICCStore(); - } - } - return instance_; + static ICCStore* instance_ = 0; + + if ( instance_ == 0 ) { + static MyMutex smutex_; + MyMutex::MyLock lock(smutex_); + + if ( instance_ == 0 ) { + instance_ = new ICCStore(); + } + } + + return instance_; } ICCStore::ICCStore () { //cmsErrorAction (LCMS_ERROR_SHOW); - int N = sizeof(wpnames)/sizeof(wpnames[0]); - for (int i=0; i::iterator r = wMatrices.find (name); - if (r!=wMatrices.end()) + + if (r != wMatrices.end()) { return r->second; - else + } else { return wMatrices["sRGB"]; + } } -TMatrix ICCStore::workingSpaceInverseMatrix (Glib::ustring name) { +TMatrix ICCStore::workingSpaceInverseMatrix (Glib::ustring name) +{ std::map::iterator r = iwMatrices.find (name); - if (r!=iwMatrices.end()) + + if (r != iwMatrices.end()) { return r->second; - else + } else { return iwMatrices["sRGB"]; + } } -cmsHPROFILE ICCStore::workingSpace (Glib::ustring name) { +cmsHPROFILE ICCStore::workingSpace (Glib::ustring name) +{ std::map::iterator r = wProfiles.find (name); - if (r!=wProfiles.end()) + + if (r != wProfiles.end()) { return r->second; - else + } else { return wProfiles["sRGB"]; + } } -cmsHPROFILE ICCStore::workingSpaceGamma (Glib::ustring name) { +cmsHPROFILE ICCStore::workingSpaceGamma (Glib::ustring name) +{ std::map::iterator r = wProfilesGamma.find (name); - if (r!=wProfilesGamma.end()) + + if (r != wProfilesGamma.end()) { return r->second; - else + } else { return wProfilesGamma["sRGB"]; + } } -cmsHPROFILE ICCStore::getProfile (Glib::ustring name) { +cmsHPROFILE ICCStore::getProfile (Glib::ustring name) +{ - MyMutex::MyLock lock(mutex_); + MyMutex::MyLock lock(mutex_); std::map::iterator r = fileProfiles.find (name); - if (r!=fileProfiles.end()) + + if (r != fileProfiles.end()) { return r->second; - else { + } else { if (!name.compare (0, 5, "file:") && safe_file_test (name.substr(5), Glib::FILE_TEST_EXISTS) && !safe_file_test (name.substr(5), Glib::FILE_TEST_IS_DIR)) { ProfileContent pc (name.substr(5)); + if (pc.data) { cmsHPROFILE profile = pc.toProfile (); + if (profile) { fileProfiles[name] = profile; fileProfileContents[name] = pc; @@ -257,25 +302,32 @@ cmsHPROFILE ICCStore::getProfile (Glib::ustring name) { } } } + return NULL; } -cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name) { +cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name) +{ - MyMutex::MyLock lock(mutex_); + MyMutex::MyLock lock(mutex_); std::map::iterator r = fileStdProfiles.find (name.uppercase()); - if (r==fileStdProfiles.end()) { + + if (r == fileStdProfiles.end()) { // profile is not yet in store std::map::iterator f = fileStdProfilesFileNames.find (name.uppercase()); - if(f!=fileStdProfilesFileNames.end()) { + + if(f != fileStdProfilesFileNames.end()) { // but there exists one => load it ProfileContent pc (f->second); + if (pc.data) { cmsHPROFILE profile = pc.toProfile (); + if (profile) { fileStdProfiles[name.uppercase()] = profile; } + // profile is not valid or it is now stored => remove entry from fileStdProfilesFileNames fileStdProfilesFileNames.erase(f); return profile; @@ -294,19 +346,21 @@ cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name) { } } -ProfileContent ICCStore::getContent (Glib::ustring name) { +ProfileContent ICCStore::getContent (Glib::ustring name) +{ - MyMutex::MyLock lock(mutex_); + MyMutex::MyLock lock(mutex_); return fileProfileContents[name]; } // Reads all profiles from the given profiles dir -void ICCStore::init (Glib::ustring usrICCDir, Glib::ustring rtICCDir) { +void ICCStore::init (Glib::ustring usrICCDir, Glib::ustring rtICCDir) +{ - MyMutex::MyLock lock(mutex_); + MyMutex::MyLock lock(mutex_); - // + // fileProfiles.clear(); fileProfileContents.clear(); // RawTherapee's profiles take precedence if a user's profile of the same name exists @@ -320,8 +374,9 @@ void ICCStore::init (Glib::ustring usrICCDir, Glib::ustring rtICCDir) { loadICCs(Glib::build_filename(rtICCDir, "input"), true, fileStdProfiles, NULL); } -void ICCStore::loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map *resultProfileContents, bool prefetch, bool onlyRgb) { - if (rootDirName!="") { +void ICCStore::loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map *resultProfileContents, bool prefetch, bool onlyRgb) +{ + if (rootDirName != "") { std::deque qDirs; qDirs.push_front(rootDirName); @@ -332,226 +387,271 @@ void ICCStore::loadICCs(Glib::ustring rootDirName, bool nameUpper, std::mapbegin(); i!=dir->end(); ++i) { + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { Glib::ustring fname = dirname + *i; Glib::ustring sname = *i; + // ignore directories if (!safe_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, ".icm") || !sname.casefold().compare (lastdot, 4, ".icc"))) { - Glib::ustring name = nameUpper ? sname.substr(0,lastdot).uppercase() : sname.substr(0,lastdot); + + if (lastdot != Glib::ustring::npos && lastdot <= sname.size() - 4 && (!sname.casefold().compare (lastdot, 4, ".icm") || !sname.casefold().compare (lastdot, 4, ".icc"))) { + Glib::ustring name = nameUpper ? sname.substr(0, lastdot).uppercase() : sname.substr(0, lastdot); + if(!prefetch) { fileStdProfilesFileNames[name] = fname; } else { ProfileContent pc (fname); + if (pc.data) { cmsHPROFILE profile = pc.toProfile (); + if (profile && (!onlyRgb || cmsGetColorSpace(profile) == cmsSigRgbData)) { resultProfiles[name] = profile; - if(resultProfileContents) + + if(resultProfileContents) { (*resultProfileContents)[name] = pc; + } } } } } } + // Removed recursive scanning, see issue #1730. // To revert to the recursive method, just uncomment the next line. //else qDirs.push_front(fname); // for later scanning } + delete dir; } } } // Determine the first monitor default profile of operating system, if selected -void ICCStore::findDefaultMonitorProfile() { - defaultMonitorProfile=""; +void ICCStore::findDefaultMonitorProfile() +{ + defaultMonitorProfile = ""; #ifdef WIN32 - // Get current main monitor. Could be fine tuned to get the current windows monitor (multi monitor setup), - // but problem is that we live in RTEngine with no GUI window to query around - HDC hDC=GetDC(NULL); + // Get current main monitor. Could be fine tuned to get the current windows monitor (multi monitor setup), + // but problem is that we live in RTEngine with no GUI window to query around + HDC hDC = GetDC(NULL); - if (hDC!=NULL) { - if (SetICMMode(hDC, ICM_ON)) { - char profileName[MAX_PATH+1]; DWORD profileLength=MAX_PATH; - if (GetICMProfileA(hDC,&profileLength,profileName)) defaultMonitorProfile=Glib::ustring(profileName); - // might fail if e.g. the monitor has no profile - } + if (hDC != NULL) { + if (SetICMMode(hDC, ICM_ON)) { + char profileName[MAX_PATH + 1]; + DWORD profileLength = MAX_PATH; - ReleaseDC(NULL,hDC); + if (GetICMProfileA(hDC, &profileLength, profileName)) { + defaultMonitorProfile = Glib::ustring(profileName); + } + + // might fail if e.g. the monitor has no profile + } + + ReleaseDC(NULL, hDC); } + #else // TODO: Add other OS specific code here #endif - if (options.rtSettings.verbose) printf("Default monitor profile is: %s\n", defaultMonitorProfile.c_str()); + if (options.rtSettings.verbose) { + printf("Default monitor profile is: %s\n", defaultMonitorProfile.c_str()); + } } -ProfileContent::ProfileContent (Glib::ustring fileName) : data(NULL), length(0) { +ProfileContent::ProfileContent (Glib::ustring fileName) : data(NULL), length(0) +{ FILE* f = safe_g_fopen (fileName, "rb"); - if (!f) + + if (!f) { return; + } + fseek (f, 0, SEEK_END); length = ftell (f); fseek (f, 0, SEEK_SET); - data = new char[length+1]; + data = new char[length + 1]; fread (data, length, 1, f); - data[length] = 0; + data[length] = 0; fclose (f); } -ProfileContent::ProfileContent (const ProfileContent& other) { +ProfileContent::ProfileContent (const ProfileContent& other) +{ length = other.length; + if (other.data) { - data = new char[length+1]; - memcpy (data, other.data, length+1); - } - else + data = new char[length + 1]; + memcpy (data, other.data, length + 1); + } else { data = NULL; + } } -ProfileContent::ProfileContent (cmsHPROFILE hProfile) : data(NULL), length(0) { +ProfileContent::ProfileContent (cmsHPROFILE hProfile) : data(NULL), length(0) +{ if (hProfile != NULL) { cmsUInt32Number bytesNeeded = 0; cmsSaveProfileToMem(hProfile, 0, &bytesNeeded); - if (bytesNeeded > 0) - { - data = new char[bytesNeeded+1]; - cmsSaveProfileToMem(hProfile, data, &bytesNeeded); - length = (int)bytesNeeded; + + if (bytesNeeded > 0) { + data = new char[bytesNeeded + 1]; + cmsSaveProfileToMem(hProfile, data, &bytesNeeded); + length = (int)bytesNeeded; } } } -ProfileContent& ProfileContent::operator= (const ProfileContent& other) { +ProfileContent& ProfileContent::operator= (const ProfileContent& other) +{ length = other.length; - if (data) + + if (data) { delete [] data; - if (other.data) { - data = new char[length+1]; - memcpy (data, other.data, length+1); } - else + + if (other.data) { + data = new char[length + 1]; + memcpy (data, other.data, length + 1); + } else { data = NULL; + } + return *this; } -ProfileContent::~ProfileContent () { +ProfileContent::~ProfileContent () +{ - if (data) + if (data) { delete [] data; + } } - -cmsHPROFILE ProfileContent::toProfile () { - if (data) +cmsHPROFILE ProfileContent::toProfile () +{ + + if (data) { return cmsOpenProfileFromMem (data, length); - else + } else { return NULL; + } } -cmsHPROFILE ICCStore::createFromMatrix (const double matrix[3][3], bool gamma, Glib::ustring name) { +cmsHPROFILE ICCStore::createFromMatrix (const double matrix[3][3], bool gamma, Glib::ustring name) +{ - static const unsigned phead[] = - { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, - 0x61637370, 0, 0, 0, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d }; - unsigned pbody[] = - { 10, 0x63707274, 0, 36, /* cprt */ - 0x64657363, 0, 40, /* desc */ - 0x77747074, 0, 20, /* wtpt */ - 0x626b7074, 0, 20, /* bkpt */ - 0x72545243, 0, 14, /* rTRC */ - 0x67545243, 0, 14, /* gTRC */ - 0x62545243, 0, 14, /* bTRC */ - 0x7258595a, 0, 20, /* rXYZ */ - 0x6758595a, 0, 20, /* gXYZ */ - 0x6258595a, 0, 20 }; /* bXYZ */ + static const unsigned phead[] = { + 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, + 0x61637370, 0, 0, 0, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d + }; + unsigned pbody[] = { + 10, 0x63707274, 0, 36, /* cprt */ + 0x64657363, 0, 40, /* desc */ + 0x77747074, 0, 20, /* wtpt */ + 0x626b7074, 0, 20, /* bkpt */ + 0x72545243, 0, 14, /* rTRC */ + 0x67545243, 0, 14, /* gTRC */ + 0x62545243, 0, 14, /* bTRC */ + 0x7258595a, 0, 20, /* rXYZ */ + 0x6758595a, 0, 20, /* gXYZ */ + 0x6258595a, 0, 20 + }; /* bXYZ */ static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };//D65 - //static const unsigned pwhite[] = { 0xf6d6, 0x10000, 0xd340 };//D50 + //static const unsigned pwhite[] = { 0xf6d6, 0x10000, 0xd340 };//D50 - // 0x63757276 : curveType, 0 : reserved, 1 : entries (1=gamma, 0=identity), 0x1000000=1.0 + // 0x63757276 : curveType, 0 : reserved, 1 : entries (1=gamma, 0=identity), 0x1000000=1.0 unsigned pcurve[] = { 0x63757276, 0, 0, 0x1000000 }; // unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; - if (gamma) { + if (gamma) { pcurve[2] = 1; - // pcurve[3] = 0x1f00000;// pcurve for gamma BT709 : g=2.22 s=4.5 - // normalize gamma in RT, default (Emil's choice = sRGB) + // pcurve[3] = 0x1f00000;// pcurve for gamma BT709 : g=2.22 s=4.5 + // normalize gamma in RT, default (Emil's choice = sRGB) pcurve[3] = 0x2390000;//pcurve for gamma sRGB : g:2.4 s=12.92 - + } else { - // lcms2 up to 2.4 has a bug with linear gamma causing precision loss (banding) - // of floating point data when a normal icc encoding of linear gamma is used - // (i e 0 table entries), but by encoding a gamma curve which is 1.0 the - // floating point path is taken within lcms2 so no precision loss occurs and - // gamma is still 1.0. - pcurve[2] = 1; - pcurve[3] = 0x1000000; //pcurve for gamma 1 + // lcms2 up to 2.4 has a bug with linear gamma causing precision loss (banding) + // of floating point data when a normal icc encoding of linear gamma is used + // (i e 0 table entries), but by encoding a gamma curve which is 1.0 the + // floating point path is taken within lcms2 so no precision loss occurs and + // gamma is still 1.0. + pcurve[2] = 1; + pcurve[3] = 0x1000000; //pcurve for gamma 1 } // constructing profile header - unsigned* oprof = new unsigned [phead[0]/sizeof(unsigned)]; + unsigned* oprof = new unsigned [phead[0] / sizeof(unsigned)]; memset (oprof, 0, phead[0]); memcpy (oprof, phead, sizeof(phead)); - oprof[0] = 132 + 12*pbody[0]; - + oprof[0] = 132 + 12 * pbody[0]; + // constructing tag directory (pointers inside the file), and types // 0x74657874 : text // 0x64657363 : description tag - for (unsigned int i=0; i < pbody[0]; i++) { - oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; - pbody[i*3+2] = oprof[0]; - oprof[0] += (pbody[i*3+3] + 3) & -4; - } - memcpy (oprof+32, pbody, sizeof(pbody)); + for (unsigned int i = 0; i < pbody[0]; i++) { + oprof[oprof[0] / 4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; + pbody[i * 3 + 2] = oprof[0]; + oprof[0] += (pbody[i * 3 + 3] + 3) & -4; + } + + memcpy (oprof + 32, pbody, sizeof(pbody)); // wtpt - memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof(pwhite)); + memcpy ((char *)oprof + pbody[8] + 8, pwhite, sizeof(pwhite)); // r/g/b TRC - for (int i=4; i < 7; i++) - memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof(pcurve)); - + for (int i = 4; i < 7; i++) { + memcpy ((char *)oprof + pbody[i * 3 + 2], pcurve, sizeof(pcurve)); + } + // r/g/b XYZ // pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); - for (int i=0; i < 3; i++) - for (int j=0; j < 3; j++) { - oprof[pbody[j*3+23]/4+i+2] = matrix[i][j] * 0x10000 + 0.5; -// for (num = k=0; k < 3; k++) -// num += xyzd50_srgb[i][k] * inverse[j][k]; - } + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + oprof[pbody[j * 3 + 23] / 4 + i + 2] = matrix[i][j] * 0x10000 + 0.5; +// for (num = k=0; k < 3; k++) +// num += xyzd50_srgb[i][k] * inverse[j][k]; + } // convert to network byte order - for (unsigned int i=0; i < phead[0]/4; i++) - oprof[i] = htonl(oprof[i]); - + for (unsigned int i = 0; i < phead[0] / 4; i++) { + oprof[i] = htonl(oprof[i]); + } + // cprt - strcpy ((char *)oprof+pbody[2]+8, "--rawtherapee profile--"); + strcpy ((char *)oprof + pbody[2] + 8, "--rawtherapee profile--"); // desc - oprof[pbody[5]/4+2] = name.size() + 1; - strcpy ((char *)oprof+pbody[5]+12, name.c_str()); + oprof[pbody[5] / 4 + 2] = name.size() + 1; + strcpy ((char *)oprof + pbody[5] + 12, name.c_str()); cmsHPROFILE p = cmsOpenProfileFromMem (oprof, ntohl(oprof[0])); - delete [] oprof; - return p; + delete [] oprof; + return p; } } diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 3662d099b..acb31e4cf 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -7,7 +7,7 @@ * 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 @@ -25,72 +25,81 @@ #include #include "../rtgui/threadutils.h" -namespace rtengine { +namespace rtengine +{ typedef const double (*TMatrix)[3]; -class ProfileContent { +class ProfileContent +{ - public: - char* data; - int length; +public: + char* data; + int length; - ProfileContent (): data(NULL), length(0) {} - ProfileContent (Glib::ustring fileName); - ProfileContent (const ProfileContent& other); - ProfileContent (cmsHPROFILE hProfile); - ~ProfileContent (); - ProfileContent& operator= (const rtengine::ProfileContent& other); - cmsHPROFILE toProfile (); + ProfileContent (): data(NULL), length(0) {} + ProfileContent (Glib::ustring fileName); + ProfileContent (const ProfileContent& other); + ProfileContent (cmsHPROFILE hProfile); + ~ProfileContent (); + ProfileContent& operator= (const rtengine::ProfileContent& other); + cmsHPROFILE toProfile (); }; -class ICCStore { +class ICCStore +{ - std::map wProfiles; - std::map wProfilesGamma; - std::map wMatrices; - std::map iwMatrices; - - // these contain profiles from user/system directory (supplied on init) - std::map fileProfiles; - std::map fileProfileContents; + std::map wProfiles; + std::map wProfilesGamma; + std::map wMatrices; + std::map iwMatrices; - // these contain standard profiles from RT. keys are all in uppercase - std::map fileStdProfilesFileNames; - std::map fileStdProfiles; + // these contain profiles from user/system directory (supplied on init) + std::map fileProfiles; + std::map fileProfileContents; - cmsHPROFILE xyz; - cmsHPROFILE srgb; + // these contain standard profiles from RT. keys are all in uppercase + std::map fileStdProfilesFileNames; + std::map fileStdProfiles; - MyMutex mutex_; + cmsHPROFILE xyz; + cmsHPROFILE srgb; - ICCStore (); - void loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map *resultProfileContents, bool prefetch = false, bool onlyRgb = false); - - public: + MyMutex mutex_; - static ICCStore* getInstance(void); - static cmsHPROFILE makeStdGammaProfile(cmsHPROFILE iprof); + ICCStore (); + void loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map *resultProfileContents, bool prefetch = false, bool onlyRgb = false); - Glib::ustring defaultMonitorProfile; // Main monitors standard profile name, from OS - void findDefaultMonitorProfile(); +public: - int numOfWProfiles (); - cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma=false, Glib::ustring name=""); - cmsHPROFILE workingSpace (Glib::ustring name); - cmsHPROFILE workingSpaceGamma (Glib::ustring name); - TMatrix workingSpaceMatrix (Glib::ustring name); - TMatrix workingSpaceInverseMatrix (Glib::ustring name); - - cmsHPROFILE getProfile (Glib::ustring name); - cmsHPROFILE getStdProfile(Glib::ustring name); + static ICCStore* getInstance(void); + static cmsHPROFILE makeStdGammaProfile(cmsHPROFILE iprof); - void init (Glib::ustring usrICCDir, Glib::ustring stdICCDir); - ProfileContent getContent (Glib::ustring name); + Glib::ustring defaultMonitorProfile; // Main monitors standard profile name, from OS + void findDefaultMonitorProfile(); - cmsHPROFILE getXYZProfile () { return xyz; } - cmsHPROFILE getsRGBProfile () { return srgb; } - std::vector getOutputProfiles (); + int numOfWProfiles (); + cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma = false, Glib::ustring name = ""); + cmsHPROFILE workingSpace (Glib::ustring name); + cmsHPROFILE workingSpaceGamma (Glib::ustring name); + TMatrix workingSpaceMatrix (Glib::ustring name); + TMatrix workingSpaceInverseMatrix (Glib::ustring name); + + cmsHPROFILE getProfile (Glib::ustring name); + cmsHPROFILE getStdProfile(Glib::ustring name); + + void init (Glib::ustring usrICCDir, Glib::ustring stdICCDir); + ProfileContent getContent (Glib::ustring name); + + cmsHPROFILE getXYZProfile () + { + return xyz; + } + cmsHPROFILE getsRGBProfile () + { + return srgb; + } + std::vector getOutputProfiles (); }; #define iccStore ICCStore::getInstance() @@ -98,4 +107,4 @@ class ICCStore { //extern const char* wpnames[]; } #endif - + diff --git a/rtengine/iimage.cc b/rtengine/iimage.cc index 9296fd837..adda06162 100644 --- a/rtengine/iimage.cc +++ b/rtengine/iimage.cc @@ -25,19 +25,22 @@ const char rtengine::sImagefloat[] = "Imagefloat"; int rtengine::getCoarseBitMask( const procparams::CoarseTransformParams &coarse) { int tr = TR_NONE; + if (coarse.rotate == 90) { - tr |= TR_R90; - } else if (coarse.rotate == 180) { - tr |= TR_R180; - } else if (coarse.rotate == 270) { - tr |= TR_R270; + tr |= TR_R90; + } else if (coarse.rotate == 180) { + tr |= TR_R180; + } else if (coarse.rotate == 270) { + tr |= TR_R270; } if (coarse.hflip) { - tr |= TR_HFLIP; + tr |= TR_HFLIP; } + if (coarse.vflip) { - tr |= TR_VFLIP; + tr |= TR_VFLIP; } + return tr; } diff --git a/rtengine/iimage.h b/rtengine/iimage.h index 64a30f771..4b0450e54 100644 --- a/rtengine/iimage.h +++ b/rtengine/iimage.h @@ -7,7 +7,7 @@ * 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 @@ -39,1530 +39,1757 @@ #define CHECK_BOUNDS 0 -namespace rtengine { +namespace rtengine +{ - extern const char sImage8[]; - extern const char sImage16[]; - extern const char sImagefloat[]; - int getCoarseBitMask( const procparams::CoarseTransformParams &coarse); - class ProgressListener; - class Color; +extern const char sImage8[]; +extern const char sImage16[]; +extern const char sImagefloat[]; +int getCoarseBitMask( const procparams::CoarseTransformParams &coarse); +class ProgressListener; +class Color; - enum TypeInterpolation { TI_Nearest, TI_Bilinear }; +enum TypeInterpolation { TI_Nearest, TI_Bilinear }; - // -------------------------------------------------------------------- - // Generic classes - // -------------------------------------------------------------------- +// -------------------------------------------------------------------- +// Generic classes +// -------------------------------------------------------------------- - class ImageDatas : virtual public ImageDimensions { - public: - template - void convertTo (S srcValue, D &dstValue) { - dstValue = static_cast(srcValue); - } - - // parameters that will never be used, replaced by the subclasses r, g and b parameters! - // they are still necessary to implement operator() in this parent class - virtual ~ImageDatas() {} - virtual void allocate (int W, int H) {} - virtual void rotate (int deg) {} - // free the memory allocated for the image data without deleting the object. - virtual void flushData () { allocate(0,0); } - - virtual void hflip () {} - virtual void vflip () {} - - // Read the raw dump of the data - void readData (FILE *fh) {} - // Write a raw dump of the data - void writeData (FILE *fh) {} - - virtual void normalizeInt (int srcMinVal, int srcMaxVal) {}; - virtual void normalizeFloat (float srcMinVal, float srcMaxVal) {}; - virtual void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, int compression) {} - virtual void getSpotWBData (double &reds, double &greens, double &blues, int &rn, int &gn, int &bn, - std::vector &red, std::vector &green, std::vector &blue, - int tran) {} - virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) { rm=gm=bm=1.0; } - virtual const char* getType () const { return "unknown"; } - - }; - - template <> - inline void ImageDatas::convertTo (const unsigned short srcValue, unsigned char &dstValue) { - dstValue = (unsigned char)(srcValue >> 8); - } - template <> - inline void ImageDatas::convertTo (const unsigned char srcValue, int &dstValue) { - dstValue = (int)(srcValue) << 8; - } - template <> - inline void ImageDatas::convertTo (const unsigned char srcValue, unsigned short &dstValue) { - dstValue = (unsigned short)(srcValue) << 8; - } - template <> - inline void ImageDatas::convertTo (const float srcValue, unsigned char &dstValue) { - dstValue = (unsigned char)( (unsigned short)(srcValue) >> 8 ); - } - template <> - inline void ImageDatas::convertTo (const unsigned char srcValue, float &dstValue) { - dstValue = float( (unsigned short)(srcValue) << 8 ); +class ImageDatas : virtual public ImageDimensions +{ +public: + template + void convertTo (S srcValue, D &dstValue) + { + dstValue = static_cast(srcValue); } - // -------------------------------------------------------------------- - // Planar order classes - // -------------------------------------------------------------------- - - template - class PlanarPtr { - protected: - AlignedBuffer ab; - public: - #if CHECK_BOUNDS - int width_, height_; - #endif - T** ptrs; - - #if CHECK_BOUNDS - PlanarPtr() : width_(0), height_(0), ptrs (NULL) {} - #else - PlanarPtr() : ptrs (NULL){} - #endif - - bool resize(int newSize) { - if (ab.resize(newSize)) { - ptrs=ab.data; - return true; - } - else { - ptrs=NULL; - return false; - } - } - void swap (PlanarPtr &other) { - ab.swap(other.ab); - T** tmpsPtrs = other.ptrs; - other.ptrs = ptrs; - ptrs = tmpsPtrs; - - #if CHECK_BOUNDS - int tmp = other.width_; - other.width_ = width_; - width_ = tmp; - tmp = other.height_; - other.height_ = height_; - height_ = tmp; - #endif - } - - T*& operator() (unsigned row) { - #if CHECK_BOUNDS - assert (row < height_); - #endif - return ptrs[row]; - } - // Will send back the start of a row, starting with a red, green or blue value - T* operator() (unsigned row) const { - #if CHECK_BOUNDS - assert (row < height_); - #endif - return ptrs[row]; - } - // Will send back a value at a given row, col position - T& operator() (unsigned row, unsigned col) { - #if CHECK_BOUNDS - assert (row < height_ && col < width_); - #endif - return ptrs[row][col]; - } - const T operator() (unsigned row, unsigned col) const { - #if CHECK_BOUNDS - assert (row < height_ && col < width_); - #endif - return ptrs[row][col]; - } - }; - - template - class PlanarWhateverData : virtual public ImageDatas { - - private: - AlignedBuffer abData; - - int rowstride; // Plan size, in bytes (all padding bytes included) - - public: - T* data; - PlanarPtr v; // v stands for "value", whatever it represent - - PlanarWhateverData() : rowstride(0), data (NULL) {} - PlanarWhateverData(int w, int h) : rowstride(0), data (NULL) { - allocate(w, h); - } - - // Send back the row stride. WARNING: unit = byte, not element! - int getRowStride () { return rowstride; } - - void swap(PlanarWhateverData &other) { - abData.swap(other.abData); - v.swap(other.v); - T* tmpData = other.data; - other.data = data; - data = tmpData; - int tmpWidth = other.width; - other.width = width; - width = tmpWidth; - int tmpHeight = other.height; - other.height = height; - height = tmpHeight; - #if CHECK_BOUNDS - v.width_ = width; - v.height_ = height; - #endif - } - - // use as pointer to data - //operator void*() { return data; }; - - /* If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed - * Can be safely used to reallocate an existing image */ - void allocate (int W, int H) { - - if (W==width && H==height) - return; - - width=W; - height=H; - #if CHECK_BOUNDS - v.width_ = width; - v.height_ = height; - #endif - - if (sizeof(T) > 1) { - // 128 bits memory alignment for >8bits data - rowstride = ( width*sizeof(T)+15 )/16*16; - } - else { - // No memory alignment for 8bits data - rowstride = width*sizeof(T); - } - - // find the padding length to ensure a 128 bits alignment for each row - size_t size = rowstride * height; - if (!width) { - size = 0; - rowstride = 0; - } - - if (size && abData.resize(size, 1) - && v.resize(height) ) - { - data = abData.data; - } - else { - // asking for a new size of 0 is safe and will free memory, if any! - abData.resize(0); - data = NULL; - v.resize(0); - width = height = -1; - #if CHECK_BOUNDS - v.width_ = v.height_ = -1; - #endif - - return; - } - - char *start = (char*)(data); - - for (int i=0; i *dest) { - assert (dest!=NULL); - // Make sure that the size is the same, reallocate if necessary - dest->allocate(width, height); - if (dest->width == -1) { - return; - } - for (int i=0; iv(i), v(i), width*sizeof(T)); - } - } - - void rotate (int deg) { - - if (deg==90) { - PlanarWhateverData rotatedImg(height, width); // New image, rotated - - for (int ny=0; ny rotatedImg(height, width); // New image, rotated - - for (int nx=0; nx32 && height>50; - #pragma omp parallel for schedule(static) if(bigImage) - #endif - for (int i=0; i - void resizeImgTo (int nw, int nh, TypeInterpolation interp, PlanarWhateverData *imgPtr) { - //printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height); - if (width==nw && height==nh) { - // special case where no resizing is necessary, just type conversion.... - for (int i=0; iv(i,j)); - } - } - } - else if (interp == TI_Nearest) { - for (int i=0; iv(i,j)); - } - } - } - else if (interp == TI_Bilinear) { - for (int i=0; i=height) sy = height-1; - float dy = float(i)*float(height)/float(nh) - float(sy); - int ny = sy+1; - if (ny>=height) ny = sy; - for (int j=0; j=width) sx = width; - float dx = float(j)*float(width)/float(nw) - float(sx); - int nx = sx+1; - if (nx>=width) nx = sx; - convertTo(v(sy,sx)*(1.f-dx)*(1.f-dy) + v(sy,nx)*dx*(1.f-dy) + v(ny,sx)*(1.f-dx)*dy + v(ny,nx)*dx*dy, imgPtr->v(i,j)); - } - } - } - else { - // This case should never occur! - for (int i=0; i32 && height>50; - #pragma omp parallel for schedule(static) if(bigImage) - #endif - for (int i=0; i32 && height>50; - #pragma omp parallel for schedule(static) if(bigImage) - #endif - for (int i=0; i please creates specialization if necessary - unsigned long int n = 0; - int halfSquare = squareSize/2; - transformPixel (posX, posY, tran, x, y); - for (int iy=y-halfSquare; iy=0 && iy>=0 && ixv(iy, ix)); - ++n; - } - } - } - value = n ? T(accumulator/float(n)) : T(0); - } - - void readData (FILE *f) { - for (int i=0; i - class PlanarRGBData : virtual public ImageDatas { - - private: - AlignedBuffer abData; - - int rowstride; // Plan size, in bytes (all padding bytes included) - int planestride; // Row length, in bytes (padding bytes included) - protected: - T* data; - - public: - PlanarPtr r; - PlanarPtr g; - PlanarPtr b; - - PlanarRGBData() : rowstride(0), planestride(0), data (NULL) {} - PlanarRGBData(int w, int h) : rowstride(0), planestride(0), data (NULL) { - allocate(w, h); - } - - // Send back the row stride. WARNING: unit = byte, not element! - int getRowStride () { return rowstride; } - // Send back the plane stride. WARNING: unit = byte, not element! - int getPlaneStride () { return planestride; } - - void swap(PlanarRGBData &other) { - abData.swap(other.abData); - r.swap(other.r); - g.swap(other.g); - b.swap(other.b); - T* tmpData = other.data; - other.data = data; - data = tmpData; - int tmpWidth = other.width; - other.width = width; - width = tmpWidth; - int tmpHeight = other.height; - other.height = height; - height = tmpHeight; - #if CHECK_BOUNDS - r.width_ = width; r.height_ = height; - g.width_ = width; g.height_ = height; - b.width_ = width; b.height_ = height; - #endif - } - - // use as pointer to data - //operator void*() { return data; }; - - /* If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed - * Can be safely used to reallocate an existing image */ - void allocate (int W, int H) { - - if (W==width && H==height) - return; - - width=W; - height=H; - #if CHECK_BOUNDS - r.width_ = width; r.height_ = height; - g.width_ = width; g.height_ = height; - b.width_ = width; b.height_ = height; - #endif - - if (sizeof(T) > 1) { - // 128 bits memory alignment for >8bits data - rowstride = ( width*sizeof(T)+15 )/16*16; - planestride = rowstride * height; - } - else { - // No memory alignment for 8bits data - rowstride = width*sizeof(T); - planestride = rowstride * height; - } - - // find the padding length to ensure a 128 bits alignment for each row - size_t size = (size_t)rowstride*3*(size_t)height; - if (!width) { - size = 0; - rowstride = 0; - } - - if (size && abData.resize(size, 1) - && r.resize(height) - && g.resize(height) - && b.resize(height) ) - { - data = abData.data; - } - else { - // asking for a new size of 0 is safe and will free memory, if any! - abData.resize(0); - data = NULL; - r.resize(0); - g.resize(0); - b.resize(0); - width = height = -1; - #if CHECK_BOUNDS - r.width_ = r.height_ = -1; - g.width_ = g.height_ = -1; - b.width_ = b.height_ = -1; - #endif - return; - } - - char *redstart = (char*)(data); - char *greenstart = (char*)(data) + planestride; - char *bluestart = (char*)(data) + 2*planestride; - - for (int i=0; i *dest) { - assert (dest!=NULL); - // Make sure that the size is the same, reallocate if necessary - dest->allocate(width, height); - if (dest->width == -1) { - printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n"); - return; - } - for (int i=0; ir(i), r(i), width*sizeof(T)); - memcpy (dest->g(i), g(i), width*sizeof(T)); - memcpy (dest->b(i), b(i), width*sizeof(T)); - } - } - - void rotate (int deg) { - - if (deg==90) { - PlanarRGBData rotatedImg(height, width); // New image, rotated - - for (int ny=0; ny rotatedImg(height, width); // New image, rotated - - for (int nx=0; nx32 && height>50; - #pragma omp parallel for schedule(static) if(bigImage) - #endif - for (int i=0; i - void resizeImgTo (int nw, int nh, TypeInterpolation interp, IC *imgPtr) { - //printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height); - if (width==nw && height==nh) { - // special case where no resizing is necessary, just type conversion.... - for (int i=0; ir(i,j)); - convertTo(g(i,j), imgPtr->g(i,j)); - convertTo(b(i,j), imgPtr->b(i,j)); - } - } - } - else if (interp == TI_Nearest) { - for (int i=0; ir(i,j)); - convertTo(g(ri,ci), imgPtr->g(i,j)); - convertTo(b(ri,ci), imgPtr->b(i,j)); - } - } - } - else if (interp == TI_Bilinear) { - for (int i=0; i=height) sy = height-1; - float dy = float(i)*float(height)/float(nh) - float(sy); - int ny = sy+1; - if (ny>=height) ny = sy; - for (int j=0; j=width) sx = width; - float dx = float(j)*float(width)/float(nw) - float(sx); - int nx = sx+1; - if (nx>=width) nx = sx; - convertTo(r(sy,sx)*(1.f-dx)*(1.f-dy) + r(sy,nx)*dx*(1.f-dy) + r(ny,sx)*(1.f-dx)*dy + r(ny,nx)*dx*dy, imgPtr->r(i,j)); - convertTo(g(sy,sx)*(1.f-dx)*(1.f-dy) + g(sy,nx)*dx*(1.f-dy) + g(ny,sx)*(1.f-dx)*dy + g(ny,nx)*dx*dy, imgPtr->g(i,j)); - convertTo(b(sy,sx)*(1.f-dx)*(1.f-dy) + b(sy,nx)*dx*(1.f-dy) + b(ny,sx)*(1.f-dx)*dy + b(ny,nx)*dx*dy, imgPtr->b(i,j)); - } - } - } - else { - // This case should never occur! - for (int i=0; i32 && height>50; - #pragma omp parallel for schedule(static) if(bigImage) - #endif - for (int i=0; i32 && height>50; - #pragma omp parallel for schedule(static) if(bigImage) - #endif - for (int i=0; i>histcompr); - histogram.clear(); - - for (int i=0; i(r(i,j), r_); - convertTo(g(i,j), g_); - convertTo(b(i,j), b_); - histogram[(int)Color::igamma_srgb (r_)>>histcompr]++; - histogram[(int)Color::igamma_srgb (g_)>>histcompr]++; - histogram[(int)Color::igamma_srgb (b_)>>histcompr]++; - } - } - - void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) { - histogram.clear(); - avg_r = avg_g = avg_b = 0.; - n=0; - for (unsigned int i=0; i<(unsigned int)(height); i++) - for (unsigned int j=0; j<(unsigned int)(width); j++) { - float r_, g_, b_; - convertTo(r(i,j), r_); - convertTo(g(i,j), g_); - convertTo(b(i,j), b_); - int rtemp = Color::igamma_srgb (r_); - int gtemp = Color::igamma_srgb (g_); - int btemp = Color::igamma_srgb (b_); - - histogram[rtemp>>compression]++; - histogram[gtemp>>compression]+=2; - histogram[btemp>>compression]++; - - // autowb computation - if (r_>64000.f || g_>64000.f || b_>64000.f) continue; - avg_r += double(r_); - avg_g += double(g_); - avg_b += double(b_); - n++; - } - } - - void getAutoWBMultipliers (double &rm, double &gm, double &bm) { - - double avg_r = 0.; - double avg_g = 0.; - double avg_b = 0.; - int n = 0; - //int p = 6; - - for (unsigned int i=0; i<(unsigned int)(height); i++) - for (unsigned int j=0; j<(unsigned int)(width); j++) { - float r_, g_, b_; - convertTo(r(i,j), r_); - convertTo(g(i,j), g_); - convertTo(b(i,j), b_); - - if (r_>64000.f || g_>64000.f || b_>64000.f) continue; - avg_r += double(r_); - avg_g += double(g_); - avg_b += double(b_); - /*avg_r += intpow( (double)r(i, j), p); - avg_g += intpow( (double)g(i, j), p); - avg_b += intpow( (double)b(i, j), p);*/ - n++; - } - rm = avg_r/double(n); - gm = avg_g/double(n); - bm = avg_b/double(n); - } - - void transformPixel (int x, int y, int tran, int& tx, int& ty) { - - if (!tran) { - tx = x; - ty = y; - return; - } - int W = width; - int H = height; - int sw = W, sh = H; - if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { - sw = H; - sh = W; - } - - int ppx = x, ppy = y; - if (tran & TR_HFLIP) - ppx = sw - 1 - x; - if (tran & TR_VFLIP) - ppy = sh - 1 - y; - - tx = ppx; - ty = ppy; - - if ((tran & TR_ROT) == TR_R180) { - tx = W - 1 - ppx; - ty = H - 1 - ppy; - } - else if ((tran & TR_ROT) == TR_R90) { - tx = ppy; - ty = H - 1 - ppx; - } - else if ((tran & TR_ROT) == TR_R270) { - tx = W - 1 - ppy; - ty = ppx; - } - } - - virtual void getSpotWBData (double &reds, double &greens, double &blues, int &rn, int &gn, int &bn, - std::vector &red, std::vector &green, std::vector &blue, - int tran) - { - int x; int y; - reds = 0, greens = 0, blues = 0; - rn = 0, gn = 0, bn = 0; - for (size_t i=0; i=0 && y>=0 && x(this->r(y, x), v); - reds += double(v); - rn++; - } - transformPixel (green[i].x, green[i].y, tran, x, y); - if (x>=0 && y>=0 && x(this->g(y, x), v); - greens += double(v); - gn++; - } - transformPixel (blue[i].x, blue[i].y, tran, x, y); - if (x>=0 && y>=0 && x(this->b(y, x), v); - blues += double(v); - bn++; - } - } - } - - void getPipetteData (T &valueR, T &valueG, T &valueB, int posX, int posY, int squareSize, int tran) - { - int x; int y; - float accumulatorR = 0.f; // using float to avoid range overflow; -> please creates specialization if necessary - float accumulatorG = 0.f; // " - float accumulatorB = 0.f; // " - unsigned long int n = 0; - int halfSquare = squareSize/2; - transformPixel (posX, posY, tran, x, y); - for (int iy=y-halfSquare; iy=0 && iy>=0 && ixr(iy, ix)); - accumulatorG += float(this->g(iy, ix)); - accumulatorB += float(this->b(iy, ix)); - ++n; - } - } - } - valueR = n ? T(accumulatorR/float(n)) : T(0); - valueG = n ? T(accumulatorG/float(n)) : T(0); - valueB = n ? T(accumulatorB/float(n)) : T(0); - } - - void readData (FILE *f) { - for (int i=0; i - class ChunkyPtr { - private: - T* ptr; - int width; - public: - #if CHECK_BOUNDS - int width_, height_; - #endif + // parameters that will never be used, replaced by the subclasses r, g and b parameters! + // they are still necessary to implement operator() in this parent class + virtual ~ImageDatas() {} + virtual void allocate (int W, int H) {} + virtual void rotate (int deg) {} + // free the memory allocated for the image data without deleting the object. + virtual void flushData () + { + allocate(0, 0); + } + + virtual void hflip () {} + virtual void vflip () {} + + // Read the raw dump of the data + void readData (FILE *fh) {} + // Write a raw dump of the data + void writeData (FILE *fh) {} + + virtual void normalizeInt (int srcMinVal, int srcMaxVal) {}; + virtual void normalizeFloat (float srcMinVal, float srcMaxVal) {}; + virtual void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, int compression) {} + virtual void getSpotWBData (double &reds, double &greens, double &blues, int &rn, int &gn, int &bn, + std::vector &red, std::vector &green, std::vector &blue, + int tran) {} + virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) + { + rm = gm = bm = 1.0; + } + virtual const char* getType () const + { + return "unknown"; + } + +}; + +template <> +inline void ImageDatas::convertTo (const unsigned short srcValue, unsigned char &dstValue) +{ + dstValue = (unsigned char)(srcValue >> 8); +} +template <> +inline void ImageDatas::convertTo (const unsigned char srcValue, int &dstValue) +{ + dstValue = (int)(srcValue) << 8; +} +template <> +inline void ImageDatas::convertTo (const unsigned char srcValue, unsigned short &dstValue) +{ + dstValue = (unsigned short)(srcValue) << 8; +} +template <> +inline void ImageDatas::convertTo (const float srcValue, unsigned char &dstValue) +{ + dstValue = (unsigned char)( (unsigned short)(srcValue) >> 8 ); +} +template <> +inline void ImageDatas::convertTo (const unsigned char srcValue, float &dstValue) +{ + dstValue = float( (unsigned short)(srcValue) << 8 ); +} + +// -------------------------------------------------------------------- +// Planar order classes +// -------------------------------------------------------------------- + +template +class PlanarPtr +{ +protected: + AlignedBuffer ab; +public: +#if CHECK_BOUNDS + int width_, height_; +#endif + T** ptrs; #if CHECK_BOUNDS - ChunkyPtr() : ptr (NULL), width(-1), width_(0), height_(0) {} + PlanarPtr() : width_(0), height_(0), ptrs (NULL) {} #else - ChunkyPtr() : ptr (NULL), width(-1) {} + PlanarPtr() : ptrs (NULL) {} #endif - void init(T* base, int w=-1) { ptr = base; width=w; } - void swap (ChunkyPtr &other) { - T* tmpsPtr = other.ptr; - other.ptr = ptr; - ptr = tmpsPtr; - int tmpWidth = other.width; - other.width = width; - width = tmpWidth; + bool resize(int newSize) + { + if (ab.resize(newSize)) { + ptrs = ab.data; + return true; + } else { + ptrs = NULL; + return false; + } + } + void swap (PlanarPtr &other) + { + ab.swap(other.ab); + T** tmpsPtrs = other.ptrs; + other.ptrs = ptrs; + ptrs = tmpsPtrs; - #if CHECK_BOUNDS - int tmp = other.width_; - other.width_ = width_; - width_ = tmp; - tmp = other.height_; - other.height_ = height_; - height_ = tmp; - #endif +#if CHECK_BOUNDS + int tmp = other.width_; + other.width_ = width_; + width_ = tmp; + tmp = other.height_; + other.height_ = height_; + height_ = tmp; +#endif + } + T*& operator() (unsigned row) + { +#if CHECK_BOUNDS + assert (row < height_); +#endif + return ptrs[row]; + } + // Will send back the start of a row, starting with a red, green or blue value + T* operator() (unsigned row) const + { +#if CHECK_BOUNDS + assert (row < height_); +#endif + return ptrs[row]; + } + // Will send back a value at a given row, col position + T& operator() (unsigned row, unsigned col) + { +#if CHECK_BOUNDS + assert (row < height_ && col < width_); +#endif + return ptrs[row][col]; + } + const T operator() (unsigned row, unsigned col) const + { +#if CHECK_BOUNDS + assert (row < height_ && col < width_); +#endif + return ptrs[row][col]; + } +}; + +template +class PlanarWhateverData : virtual public ImageDatas +{ + +private: + AlignedBuffer abData; + + int rowstride; // Plan size, in bytes (all padding bytes included) + +public: + T* data; + PlanarPtr v; // v stands for "value", whatever it represent + + PlanarWhateverData() : rowstride(0), data (NULL) {} + PlanarWhateverData(int w, int h) : rowstride(0), data (NULL) + { + allocate(w, h); + } + + // Send back the row stride. WARNING: unit = byte, not element! + int getRowStride () + { + return rowstride; + } + + void swap(PlanarWhateverData &other) + { + abData.swap(other.abData); + v.swap(other.v); + T* tmpData = other.data; + other.data = data; + data = tmpData; + int tmpWidth = other.width; + other.width = width; + width = tmpWidth; + int tmpHeight = other.height; + other.height = height; + height = tmpHeight; +#if CHECK_BOUNDS + v.width_ = width; + v.height_ = height; +#endif + } + + // use as pointer to data + //operator void*() { return data; }; + + /* If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed + * Can be safely used to reallocate an existing image */ + void allocate (int W, int H) + { + + if (W == width && H == height) { + return; } - // Will send back the start of a row, starting with a red, green or blue value - T* operator() (unsigned row) const { - #if CHECK_BOUNDS - assert (row < height_); - #endif - return &ptr[3*(row*width)]; - } - // Will send back a value at a given row, col position - T& operator() (unsigned row, unsigned col) { - #if CHECK_BOUNDS - assert (row < height_ && col < width_); - #endif - return ptr[3*(row*width+col)]; - } - const T operator() (unsigned row, unsigned col) const { - #if CHECK_BOUNDS - assert (row < height_ && col < width_); - #endif - return ptr[3*(row*width+col)]; - } - }; + width = W; + height = H; +#if CHECK_BOUNDS + v.width_ = width; + v.height_ = height; +#endif - template - class ChunkyRGBData : virtual public ImageDatas { - - private: - AlignedBuffer abData; - - public: - T* data; - ChunkyPtr r; - ChunkyPtr g; - ChunkyPtr b; - - ChunkyRGBData() : data (NULL) {} - ChunkyRGBData(int w, int h) : data (NULL) { - allocate(w, h); + if (sizeof(T) > 1) { + // 128 bits memory alignment for >8bits data + rowstride = ( width * sizeof(T) + 15 ) / 16 * 16; + } else { + // No memory alignment for 8bits data + rowstride = width * sizeof(T); } - /** Returns the pixel data, in r/g/b order from top left to bottom right continuously. - * @return a pointer to the pixel data */ - const T* getData () { return data; } + // find the padding length to ensure a 128 bits alignment for each row + size_t size = rowstride * height; - void swap(ChunkyRGBData &other) { - abData.swap(other.abData); - r.swap(other.r); - g.swap(other.g); - b.swap(other.b); - T* tmpData = other.data; - other.data = data; - data = tmpData; - int tmpWidth = other.width; - other.width = width; - width = tmpWidth; - int tmpHeight = other.height; - other.height = height; - height = tmpHeight; - #if CHECK_BOUNDS - r.width_ = width; r.height_ = height; - g.width_ = width; g.height_ = height; - b.width_ = width; b.height_ = height; - #endif - } + if (!width) { + size = 0; + rowstride = 0; + } - /* - * If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed - * Can be safely used to reallocate an existing image or to free up it's memory with "allocate (0,0);" - */ - void allocate (int W, int H) { + if (size && abData.resize(size, 1) + && v.resize(height) ) { + data = abData.data; + } else { + // asking for a new size of 0 is safe and will free memory, if any! + abData.resize(0); + data = NULL; + v.resize(0); + width = height = -1; +#if CHECK_BOUNDS + v.width_ = v.height_ = -1; +#endif - if (W==width && H==height) - return; + return; + } - width=W; - height=H; - #if CHECK_BOUNDS - r.width_ = width; r.height_ = height; - g.width_ = width; g.height_ = height; - b.width_ = width; b.height_ = height; - #endif + char *start = (char*)(data); - abData.resize(width*height*3); - if (!abData.isEmpty()) { - data = abData.data; - r.init(data, width); - g.init(data+1, width); - b.init(data+2, width); + for (int i = 0; i < height; ++i) { + int k = i * rowstride; + v(i) = (T*)(start + k); + } + } + + /** Copy the data to another PlanarWhateverData */ + void copyData(PlanarWhateverData *dest) + { + assert (dest != NULL); + // Make sure that the size is the same, reallocate if necessary + dest->allocate(width, height); + + if (dest->width == -1) { + return; + } + + for (int i = 0; i < height; i++) { + memcpy (dest->v(i), v(i), width * sizeof(T)); + } + } + + void rotate (int deg) + { + + if (deg == 90) { + PlanarWhateverData rotatedImg(height, width); // New image, rotated + + for (int ny = 0; ny < rotatedImg.height; ny++) { + int ox = ny; + int oy = height - 1; + + for (int nx = 0; nx < rotatedImg.width; nx++) { + rotatedImg.v(ny, nx) = v(oy, ox); + --oy; + } } - else { - data = NULL; - r.init(NULL); - g.init(NULL); - b.init(NULL); - width = height = -1; - #if CHECK_BOUNDS - r.width_ = r.height_ = -1; - g.width_ = g.height_ = -1; - b.width_ = b.height_ = -1; - #endif - } - } - /** Copy the data to another ChunkyRGBData */ - void copyData(ChunkyRGBData *dest) { - assert (dest!=NULL); - // Make sure that the size is the same, reallocate if necessary - dest->allocate(width, height); - if (dest->width == -1) { - printf("ERROR: ChunkyRGBData::copyData >>> allocation failed!\n"); - return; - } - memcpy (dest->data, data, 3*width*height*sizeof(T)); - } - - void rotate (int deg) { - - if (deg==90) { - ChunkyRGBData rotatedImg(height, width); // New image, rotated - - for (int ny=0; ny rotatedImg(height, width); // New image, rotated + } else if (deg == 270) { + PlanarWhateverData rotatedImg(height, width); // New image, rotated - for (int nx=0; nx 32 && height > 50; + #pragma omp parallel for schedule(static) if(bigImage) +#endif - tmp = r(i,j); - r(i,j) = r(y,x); - r(y,x) = tmp; + for (int i = 0; i < height2; i++) { + for (int j = 0; j < width; j++) { + T tmp; + int x = width - 1 - j; + int y = height - 1 - i; - tmp = g(i,j); - g(i,j) = g(y,x); - g(y,x) = tmp; - - tmp = b(i,j); - b(i,j) = b(y,x); - b(y,x) = tmp; - } + tmp = v(i, j); + v(i, j) = v(y, x); + v(y, x) = tmp; + } } - } + } + } + + template + void resizeImgTo (int nw, int nh, TypeInterpolation interp, PlanarWhateverData *imgPtr) + { + //printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height); + if (width == nw && height == nh) { + // special case where no resizing is necessary, just type conversion.... + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + convertTo(v(i, j), imgPtr->v(i, j)); + } + } + } else if (interp == TI_Nearest) { + for (int i = 0; i < nh; i++) { + int ri = i * height / nh; + + for (int j = 0; j < nw; j++) { + int ci = j * width / nw; + convertTo(v(ri, ci), imgPtr->v(i, j)); + } + } + } else if (interp == TI_Bilinear) { + for (int i = 0; i < nh; i++) { + int sy = i * height / nh; + + if (sy >= height) { + sy = height - 1; + } + + float dy = float(i) * float(height) / float(nh) - float(sy); + int ny = sy + 1; + + if (ny >= height) { + ny = sy; + } + + for (int j = 0; j < nw; j++) { + int sx = j * width / nw; + + if (sx >= width) { + sx = width; + } + + float dx = float(j) * float(width) / float(nw) - float(sx); + int nx = sx + 1; + + if (nx >= width) { + nx = sx; + } + + convertTo(v(sy, sx) * (1.f - dx) * (1.f - dy) + v(sy, nx)*dx * (1.f - dy) + v(ny, sx) * (1.f - dx)*dy + v(ny, nx)*dx * dy, imgPtr->v(i, j)); + } + } + } else { + // This case should never occur! + for (int i = 0; i < nh; i++) { + for (int j = 0; j < nw; j++) { + v(i, j) = 0; + } + } + } + } + + void hflip () + { + int width2 = width / 2; + +#ifdef _OPENMP + // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... + bool bigImage = width > 32 && height > 50; + #pragma omp parallel for schedule(static) if(bigImage) +#endif + + for (int i = 0; i < height; i++) + for (int j = 0; j < width2; j++) { + float temp; + int x = width - 1 - j; + + temp = v(i, j); + v(i, j) = v(i, x); + v(i, x) = temp; + } + } + + void vflip () + { + + int height2 = height / 2; + +#ifdef _OPENMP + // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... + bool bigImage = width > 32 && height > 50; + #pragma omp parallel for schedule(static) if(bigImage) +#endif + + for (int i = 0; i < height2; i++) + for (int j = 0; j < width; j++) { + T temp; + int y = height - 1 - i; + + temp = v(i, j); + v(i, j) = v(y, j); + v(y, j) = temp; + } + } + + void calcHist(unsigned int *hist16) + { + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + unsigned short idx; + convertTo(v(row, col), idx); + hist16[idx]++; + } + } + + void transformPixel (int x, int y, int tran, int& tx, int& ty) + { + + if (!tran) { + tx = x; + ty = y; + return; } - template - void resizeImgTo (int nw, int nh, TypeInterpolation interp, IC *imgPtr) { - //printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height); - if (width==nw && height==nh) { - // special case where no resizing is necessary, just type conversion.... - for (int i=0; ir(i,j)); - convertTo(g(i,j), imgPtr->g(i,j)); - convertTo(b(i,j), imgPtr->b(i,j)); - } - } - } - else if (interp == TI_Nearest) { - for (int i=0; ir(i,j)); - convertTo(g(ri,ci), imgPtr->g(i,j)); - convertTo(b(ri,ci), imgPtr->b(i,j)); - } - } - } - else if (interp == TI_Bilinear) { - for (int i=0; i=height) sy = height-1; - float dy = float(i)*float(height)/float(nh) - float(sy); - int ny = sy+1; - if (ny>=height) ny = sy; - for (int j=0; j=width) sx = width; - float dx = float(j)*float(width)/float(nw) - float(sx); - int nx = sx+1; - if (nx>=width) nx = sx; - T valR = r(sy,sx)*(1.f-dx)*(1.f-dy) + r(sy,nx)*dx*(1.f-dy) + r(ny,sx)*(1.f-dx)*dy + r(ny,nx)*dx*dy; - T valG = g(sy,sx)*(1.f-dx)*(1.f-dy) + g(sy,nx)*dx*(1.f-dy) + g(ny,sx)*(1.f-dx)*dy + g(ny,nx)*dx*dy; - T valB = b(sy,sx)*(1.f-dx)*(1.f-dy) + b(sy,nx)*dx*(1.f-dy) + b(ny,sx)*(1.f-dx)*dy + b(ny,nx)*dx*dy; - convertTo(valR, imgPtr->r(i,j)); - convertTo(valG, imgPtr->g(i,j)); - convertTo(valB, imgPtr->b(i,j)); - } - } - } - else { - // This case should never occur! - for (int i=0; i please creates specialization if necessary + unsigned long int n = 0; + int halfSquare = squareSize / 2; + transformPixel (posX, posY, tran, x, y); + + for (int iy = y - halfSquare; iy < y - halfSquare + squareSize; ++iy) { + for (int ix = x - halfSquare; ix < x - halfSquare + squareSize; ++ix) { + if (ix >= 0 && iy >= 0 && ix < width && iy < height) { + accumulator += float(this->v(iy, ix)); + ++n; } } } - void hflip () { - int width2 = width/2; + value = n ? T(accumulator / float(n)) : T(0); + } - for (int i=0; i +class PlanarRGBData : virtual public ImageDatas +{ - ++offsetBegin; - ++offsetEnd; +private: + AlignedBuffer abData; - temp = data[offsetBegin]; - data[offsetBegin] = data[offsetEnd]; - data[offsetEnd] = temp; + int rowstride; // Plan size, in bytes (all padding bytes included) + int planestride; // Row length, in bytes (padding bytes included) +protected: + T* data; - ++offsetBegin; - offsetEnd -= 5; +public: + PlanarPtr r; + PlanarPtr g; + PlanarPtr b; - } - } + PlanarRGBData() : rowstride(0), planestride(0), data (NULL) {} + PlanarRGBData(int w, int h) : rowstride(0), planestride(0), data (NULL) + { + allocate(w, h); + } + + // Send back the row stride. WARNING: unit = byte, not element! + int getRowStride () + { + return rowstride; + } + // Send back the plane stride. WARNING: unit = byte, not element! + int getPlaneStride () + { + return planestride; + } + + void swap(PlanarRGBData &other) + { + abData.swap(other.abData); + r.swap(other.r); + g.swap(other.g); + b.swap(other.b); + T* tmpData = other.data; + other.data = data; + data = tmpData; + int tmpWidth = other.width; + other.width = width; + width = tmpWidth; + int tmpHeight = other.height; + other.height = height; + height = tmpHeight; +#if CHECK_BOUNDS + r.width_ = width; + r.height_ = height; + g.width_ = width; + g.height_ = height; + b.width_ = width; + b.height_ = height; +#endif + } + + // use as pointer to data + //operator void*() { return data; }; + + /* If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed + * Can be safely used to reallocate an existing image */ + void allocate (int W, int H) + { + + if (W == width && H == height) { + return; } - void vflip () { + width = W; + height = H; +#if CHECK_BOUNDS + r.width_ = width; + r.height_ = height; + g.width_ = width; + g.height_ = height; + b.width_ = width; + b.height_ = height; +#endif - AlignedBuffer lBuffer(3*width); - T* lineBuffer = lBuffer.data; - size_t size = 3*width*sizeof(T); - for (int i=0; i 1) { + // 128 bits memory alignment for >8bits data + rowstride = ( width * sizeof(T) + 15 ) / 16 * 16; + planestride = rowstride * height; + } else { + // No memory alignment for 8bits data + rowstride = width * sizeof(T); + planestride = rowstride * height; } - void calcGrayscaleHist(unsigned int *hist16) { - for (int row=0; row *dest) + { + assert (dest != NULL); + // Make sure that the size is the same, reallocate if necessary + dest->allocate(width, height); + + if (dest->width == -1) { + printf("ERROR: PlanarRGBData::copyData >>> allocation failed!\n"); + return; + } + + for (int i = 0; i < height; i++) { + memcpy (dest->r(i), r(i), width * sizeof(T)); + memcpy (dest->g(i), g(i), width * sizeof(T)); + memcpy (dest->b(i), b(i), width * sizeof(T)); + } + } + + void rotate (int deg) + { + + if (deg == 90) { + PlanarRGBData rotatedImg(height, width); // New image, rotated + + for (int ny = 0; ny < rotatedImg.height; ny++) { + int ox = ny; + int oy = height - 1; + + for (int nx = 0; nx < rotatedImg.width; nx++) { + rotatedImg.r(ny, nx) = r(oy, ox); + rotatedImg.g(ny, nx) = g(oy, ox); + rotatedImg.b(ny, nx) = b(oy, ox); + --oy; + } + } + + swap(rotatedImg); + } else if (deg == 270) { + PlanarRGBData rotatedImg(height, width); // New image, rotated + + for (int nx = 0; nx < rotatedImg.width; nx++) { + int oy = nx; + int ox = width - 1; + + for (int ny = 0; ny < rotatedImg.height; ny++) { + rotatedImg.r(ny, nx) = r(oy, ox); + rotatedImg.g(ny, nx) = g(oy, ox); + rotatedImg.b(ny, nx) = b(oy, ox); + --ox; + } + } + + swap(rotatedImg); + } else if (deg == 180) { + int height2 = height / 2 + (height & 1); + +#ifdef _OPENMP + // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... + bool bigImage = width > 32 && height > 50; + #pragma omp parallel for schedule(static) if(bigImage) +#endif + + for (int i = 0; i < height2; i++) { + for (int j = 0; j < width; j++) { + T tmp; + int x = width - 1 - j; + int y = height - 1 - i; + + tmp = r(i, j); + r(i, j) = r(y, x); + r(y, x) = tmp; + + tmp = g(i, j); + g(i, j) = g(y, x); + g(y, x) = tmp; + + tmp = b(i, j); + b(i, j) = b(y, x); + b(y, x) = tmp; + } + } + } + } + + template + void resizeImgTo (int nw, int nh, TypeInterpolation interp, IC *imgPtr) + { + //printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height); + if (width == nw && height == nh) { + // special case where no resizing is necessary, just type conversion.... + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + convertTo(r(i, j), imgPtr->r(i, j)); + convertTo(g(i, j), imgPtr->g(i, j)); + convertTo(b(i, j), imgPtr->b(i, j)); + } + } + } else if (interp == TI_Nearest) { + for (int i = 0; i < nh; i++) { + int ri = i * height / nh; + + for (int j = 0; j < nw; j++) { + int ci = j * width / nw; + convertTo(r(ri, ci), imgPtr->r(i, j)); + convertTo(g(ri, ci), imgPtr->g(i, j)); + convertTo(b(ri, ci), imgPtr->b(i, j)); + } + } + } else if (interp == TI_Bilinear) { + for (int i = 0; i < nh; i++) { + int sy = i * height / nh; + + if (sy >= height) { + sy = height - 1; + } + + float dy = float(i) * float(height) / float(nh) - float(sy); + int ny = sy + 1; + + if (ny >= height) { + ny = sy; + } + + for (int j = 0; j < nw; j++) { + int sx = j * width / nw; + + if (sx >= width) { + sx = width; + } + + float dx = float(j) * float(width) / float(nw) - float(sx); + int nx = sx + 1; + + if (nx >= width) { + nx = sx; + } + + convertTo(r(sy, sx) * (1.f - dx) * (1.f - dy) + r(sy, nx)*dx * (1.f - dy) + r(ny, sx) * (1.f - dx)*dy + r(ny, nx)*dx * dy, imgPtr->r(i, j)); + convertTo(g(sy, sx) * (1.f - dx) * (1.f - dy) + g(sy, nx)*dx * (1.f - dy) + g(ny, sx) * (1.f - dx)*dy + g(ny, nx)*dx * dy, imgPtr->g(i, j)); + convertTo(b(sy, sx) * (1.f - dx) * (1.f - dy) + b(sy, nx)*dx * (1.f - dy) + b(ny, sx) * (1.f - dx)*dy + b(ny, nx)*dx * dy, imgPtr->b(i, j)); + } + } + } else { + // This case should never occur! + for (int i = 0; i < nh; i++) { + for (int j = 0; j < nw; j++) { + r(i, j) = 0; + g(i, j) = 0; + b(i, j) = 0; + } + } + } + } + + void hflip () + { + int width2 = width / 2; + +#ifdef _OPENMP + // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... + bool bigImage = width > 32 && height > 50; + #pragma omp parallel for schedule(static) if(bigImage) +#endif + + for (int i = 0; i < height; i++) + for (int j = 0; j < width2; j++) { + float temp; + int x = width - 1 - j; + + temp = r(i, j); + r(i, j) = r(i, x); + r(i, x) = temp; + + temp = g(i, j); + g(i, j) = g(i, x); + g(i, x) = temp; + + temp = b(i, j); + b(i, j) = b(i, x); + b(i, x) = temp; + } + } + + void vflip () + { + + int height2 = height / 2; + +#ifdef _OPENMP + // difficult to find a cutoff value where parallelization is counter productive because of processor's data cache collision... + bool bigImage = width > 32 && height > 50; + #pragma omp parallel for schedule(static) if(bigImage) +#endif + + for (int i = 0; i < height2; i++) + for (int j = 0; j < width; j++) { + T tempR, tempG, tempB; + int y = height - 1 - i; + + tempR = r(i, j); + r(i, j) = r(y, j); + r(y, j) = tempR; + + tempG = g(i, j); + g(i, j) = g(y, j); + g(y, j) = tempG; + + tempB = b(i, j); + b(i, j) = b(y, j); + b(y, j) = tempB; + } + } + + void calcGrayscaleHist(unsigned int *hist16) + { + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { unsigned short rIdx, gIdx, bIdx; - convertTo(r(row,col), rIdx); - convertTo(g(row,col), gIdx); - convertTo(b(row,col), bIdx); + convertTo(r(row, col), rIdx); + convertTo(g(row, col), gIdx); + convertTo(b(row, col), bIdx); hist16[rIdx]++; - hist16[gIdx]+=2; // Bayer 2x green correction + hist16[gIdx] += 2; // Bayer 2x green correction hist16[bIdx]++; } - } + } - void computeAutoHistogram (LUTu & histogram, int& histcompr) { - histcompr = 3; + void computeAutoHistogram (LUTu & histogram, int& histcompr) + { + histcompr = 3; - histogram(65536>>histcompr); - histogram.clear(); + histogram(65536 >> histcompr); + histogram.clear(); - for (int i=0; i(r(i,j), r_); - convertTo(g(i,j), g_); - convertTo(b(i,j), b_); - histogram[(int)Color::igamma_srgb (r_)>>histcompr]++; - histogram[(int)Color::igamma_srgb (g_)>>histcompr]++; - histogram[(int)Color::igamma_srgb (b_)>>histcompr]++; - } - } - - void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) { - histogram.clear(); - avg_r = avg_g = avg_b = 0.; - n=0; - for (unsigned int i=0; i<(unsigned int)(height); i++) - for (unsigned int j=0; j<(unsigned int)(width); j++) { - float r_, g_, b_; - convertTo(r(i,j), r_); - convertTo(g(i,j), g_); - convertTo(b(i,j), b_); - int rtemp = Color::igamma_srgb (r_); - int gtemp = Color::igamma_srgb (g_); - int btemp = Color::igamma_srgb (b_); - - histogram[rtemp>>compression]++; - histogram[gtemp>>compression]+=2; - histogram[btemp>>compression]++; - - // autowb computation - if (r_>64000.f || g_>64000.f || b_>64000.f) continue; - avg_r += double(r_); - avg_g += double(g_); - avg_b += double(b_); - n++; - } - } - - void getAutoWBMultipliers (double &rm, double &gm, double &bm) { - - double avg_r = 0.; - double avg_g = 0.; - double avg_b = 0.; - int n = 0; - //int p = 6; - - for (unsigned int i=0; i<(unsigned int)(height); i++) - for (unsigned int j=0; j<(unsigned int)(width); j++) { - float r_, g_, b_; - convertTo(r(i,j), r_); - convertTo(g(i,j), g_); - convertTo(b(i,j), b_); - - if (r_>64000.f || g_>64000.f || b_>64000.f) continue; - avg_r += double(r_); - avg_g += double(g_); - avg_b += double(b_); - /*avg_r += intpow( (double)r(i, j), p); - avg_g += intpow( (double)g(i, j), p); - avg_b += intpow( (double)b(i, j), p);*/ - n++; - } - rm = avg_r/double(n); - gm = avg_g/double(n); - bm = avg_b/double(n); - } - - void transformPixel (int x, int y, int tran, int& tx, int& ty) { - - if (!tran) { - tx = x; - ty = y; - return; + for (int i = 0; i < height; i++) + for (int j = 0; j < width; j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + histogram[(int)Color::igamma_srgb (r_) >> histcompr]++; + histogram[(int)Color::igamma_srgb (g_) >> histcompr]++; + histogram[(int)Color::igamma_srgb (b_) >> histcompr]++; } - int W = width; - int H = height; - int sw = W, sh = H; - if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { - sw = H; - sh = W; + } + + void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) + { + histogram.clear(); + avg_r = avg_g = avg_b = 0.; + n = 0; + + for (unsigned int i = 0; i < (unsigned int)(height); i++) + for (unsigned int j = 0; j < (unsigned int)(width); j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + int rtemp = Color::igamma_srgb (r_); + int gtemp = Color::igamma_srgb (g_); + int btemp = Color::igamma_srgb (b_); + + histogram[rtemp >> compression]++; + histogram[gtemp >> compression] += 2; + histogram[btemp >> compression]++; + + // autowb computation + if (r_ > 64000.f || g_ > 64000.f || b_ > 64000.f) { + continue; + } + + avg_r += double(r_); + avg_g += double(g_); + avg_b += double(b_); + n++; + } + } + + void getAutoWBMultipliers (double &rm, double &gm, double &bm) + { + + double avg_r = 0.; + double avg_g = 0.; + double avg_b = 0.; + int n = 0; + //int p = 6; + + for (unsigned int i = 0; i < (unsigned int)(height); i++) + for (unsigned int j = 0; j < (unsigned int)(width); j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + + if (r_ > 64000.f || g_ > 64000.f || b_ > 64000.f) { + continue; + } + + avg_r += double(r_); + avg_g += double(g_); + avg_b += double(b_); + /*avg_r += intpow( (double)r(i, j), p); + avg_g += intpow( (double)g(i, j), p); + avg_b += intpow( (double)b(i, j), p);*/ + n++; } - int ppx = x, ppy = y; - if (tran & TR_HFLIP) - ppx = sw - 1 - x; - if (tran & TR_VFLIP) - ppy = sh - 1 - y; + rm = avg_r / double(n); + gm = avg_g / double(n); + bm = avg_b / double(n); + } - tx = ppx; - ty = ppy; + void transformPixel (int x, int y, int tran, int& tx, int& ty) + { - if ((tran & TR_ROT) == TR_R180) { - tx = W - 1 - ppx; - ty = H - 1 - ppy; - } - else if ((tran & TR_ROT) == TR_R90) { - tx = ppy; - ty = H - 1 - ppx; - } - else if ((tran & TR_ROT) == TR_R270) { - tx = W - 1 - ppy; - ty = ppx; - } + if (!tran) { + tx = x; + ty = y; + return; } - virtual void getSpotWBData (double &reds, double &greens, double &blues, int &rn, int &gn, int &bn, - std::vector &red, std::vector &green, std::vector &blue, - int tran) - { - int x; int y; - reds = 0, greens = 0, blues = 0; - rn = 0, gn = 0, bn = 0; - for (size_t i=0; i=0 && y>=0 && x(this->r(y, x), v); - reds += double(v); - rn++; - } - transformPixel (green[i].x, green[i].y, tran, x, y); - if (x>=0 && y>=0 && x(this->g(y, x), v); - greens += double(v); - gn++; - } - transformPixel (blue[i].x, blue[i].y, tran, x, y); - if (x>=0 && y>=0 && x(this->b(y, x), v); - blues += double(v); - bn++; + int W = width; + int H = height; + int sw = W, sh = H; + + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { + sw = H; + sh = W; + } + + int ppx = x, ppy = y; + + if (tran & TR_HFLIP) { + ppx = sw - 1 - x; + } + + if (tran & TR_VFLIP) { + ppy = sh - 1 - y; + } + + tx = ppx; + ty = ppy; + + if ((tran & TR_ROT) == TR_R180) { + tx = W - 1 - ppx; + ty = H - 1 - ppy; + } else if ((tran & TR_ROT) == TR_R90) { + tx = ppy; + ty = H - 1 - ppx; + } else if ((tran & TR_ROT) == TR_R270) { + tx = W - 1 - ppy; + ty = ppx; + } + } + + virtual void getSpotWBData (double &reds, double &greens, double &blues, int &rn, int &gn, int &bn, + std::vector &red, std::vector &green, std::vector &blue, + int tran) + { + int x; + int y; + reds = 0, greens = 0, blues = 0; + rn = 0, gn = 0, bn = 0; + + for (size_t i = 0; i < red.size(); i++) { + transformPixel (red[i].x, red[i].y, tran, x, y); + + if (x >= 0 && y >= 0 && x < width && y < height) { + float v; + convertTo(this->r(y, x), v); + reds += double(v); + rn++; + } + + transformPixel (green[i].x, green[i].y, tran, x, y); + + if (x >= 0 && y >= 0 && x < width && y < height) { + float v; + convertTo(this->g(y, x), v); + greens += double(v); + gn++; + } + + transformPixel (blue[i].x, blue[i].y, tran, x, y); + + if (x >= 0 && y >= 0 && x < width && y < height) { + float v; + convertTo(this->b(y, x), v); + blues += double(v); + bn++; + } + } + } + + void getPipetteData (T &valueR, T &valueG, T &valueB, int posX, int posY, int squareSize, int tran) + { + int x; + int y; + float accumulatorR = 0.f; // using float to avoid range overflow; -> please creates specialization if necessary + float accumulatorG = 0.f; // " + float accumulatorB = 0.f; // " + unsigned long int n = 0; + int halfSquare = squareSize / 2; + transformPixel (posX, posY, tran, x, y); + + for (int iy = y - halfSquare; iy < y - halfSquare + squareSize; ++iy) { + for (int ix = x - halfSquare; ix < x - halfSquare + squareSize; ++ix) { + if (ix >= 0 && iy >= 0 && ix < width && iy < height) { + accumulatorR += float(this->r(iy, ix)); + accumulatorG += float(this->g(iy, ix)); + accumulatorB += float(this->b(iy, ix)); + ++n; } } } - void readData (FILE *f) { - for (int i=0; i +class ChunkyPtr +{ +private: + T* ptr; + int width; +public: +#if CHECK_BOUNDS + int width_, height_; +#endif + +#if CHECK_BOUNDS + ChunkyPtr() : ptr (NULL), width(-1), width_(0), height_(0) {} +#else + ChunkyPtr() : ptr (NULL), width(-1) {} +#endif + void init(T* base, int w = -1) + { + ptr = base; + width = w; + } + void swap (ChunkyPtr &other) + { + T* tmpsPtr = other.ptr; + other.ptr = ptr; + ptr = tmpsPtr; + + int tmpWidth = other.width; + other.width = width; + width = tmpWidth; + +#if CHECK_BOUNDS + int tmp = other.width_; + other.width_ = width_; + width_ = tmp; + tmp = other.height_; + other.height_ = height_; + height_ = tmp; +#endif + + } + + // Will send back the start of a row, starting with a red, green or blue value + T* operator() (unsigned row) const + { +#if CHECK_BOUNDS + assert (row < height_); +#endif + return &ptr[3 * (row * width)]; + } + // Will send back a value at a given row, col position + T& operator() (unsigned row, unsigned col) + { +#if CHECK_BOUNDS + assert (row < height_ && col < width_); +#endif + return ptr[3 * (row * width + col)]; + } + const T operator() (unsigned row, unsigned col) const + { +#if CHECK_BOUNDS + assert (row < height_ && col < width_); +#endif + return ptr[3 * (row * width + col)]; + } +}; + +template +class ChunkyRGBData : virtual public ImageDatas +{ + +private: + AlignedBuffer abData; + +public: + T* data; + ChunkyPtr r; + ChunkyPtr g; + ChunkyPtr b; + + ChunkyRGBData() : data (NULL) {} + ChunkyRGBData(int w, int h) : data (NULL) + { + allocate(w, h); + } + + /** Returns the pixel data, in r/g/b order from top left to bottom right continuously. + * @return a pointer to the pixel data */ + const T* getData () + { + return data; + } + + void swap(ChunkyRGBData &other) + { + abData.swap(other.abData); + r.swap(other.r); + g.swap(other.g); + b.swap(other.b); + T* tmpData = other.data; + other.data = data; + data = tmpData; + int tmpWidth = other.width; + other.width = width; + width = tmpWidth; + int tmpHeight = other.height; + other.height = height; + height = tmpHeight; +#if CHECK_BOUNDS + r.width_ = width; + r.height_ = height; + g.width_ = width; + g.height_ = height; + b.width_ = width; + b.height_ = height; +#endif + } + + /* + * If any of the required allocation fails, "width" and "height" are set to -1, and all remaining buffer are freed + * Can be safely used to reallocate an existing image or to free up it's memory with "allocate (0,0);" + */ + void allocate (int W, int H) + { + + if (W == width && H == height) { + return; + } + + width = W; + height = H; +#if CHECK_BOUNDS + r.width_ = width; + r.height_ = height; + g.width_ = width; + g.height_ = height; + b.width_ = width; + b.height_ = height; +#endif + + abData.resize(width * height * 3); + + if (!abData.isEmpty()) { + data = abData.data; + r.init(data, width); + g.init(data + 1, width); + b.init(data + 2, width); + } else { + data = NULL; + r.init(NULL); + g.init(NULL); + b.init(NULL); + width = height = -1; +#if CHECK_BOUNDS + r.width_ = r.height_ = -1; + g.width_ = g.height_ = -1; + b.width_ = b.height_ = -1; +#endif + } + } + + /** Copy the data to another ChunkyRGBData */ + void copyData(ChunkyRGBData *dest) + { + assert (dest != NULL); + // Make sure that the size is the same, reallocate if necessary + dest->allocate(width, height); + + if (dest->width == -1) { + printf("ERROR: ChunkyRGBData::copyData >>> allocation failed!\n"); + return; + } + + memcpy (dest->data, data, 3 * width * height * sizeof(T)); + } + + void rotate (int deg) + { + + if (deg == 90) { + ChunkyRGBData rotatedImg(height, width); // New image, rotated + + for (int ny = 0; ny < rotatedImg.height; ny++) { + int ox = ny; + int oy = height - 1; + + for (int nx = 0; nx < rotatedImg.width; nx++) { + rotatedImg.r(ny, nx) = r(oy, ox); + rotatedImg.g(ny, nx) = g(oy, ox); + rotatedImg.b(ny, nx) = b(oy, ox); + --oy; + } + } + + swap(rotatedImg); + } else if (deg == 270) { + ChunkyRGBData rotatedImg(height, width); // New image, rotated + + for (int nx = 0; nx < rotatedImg.width; nx++) { + int oy = nx; + int ox = width - 1; + + for (int ny = 0; ny < rotatedImg.height; ny++) { + rotatedImg.r(ny, nx) = r(oy, ox); + rotatedImg.g(ny, nx) = g(oy, ox); + rotatedImg.b(ny, nx) = b(oy, ox); + --ox; + } + } + + swap(rotatedImg); + } else if (deg == 180) { + int height2 = height / 2 + (height & 1); + + // Maybe not sufficiently optimized, but will do what it has to do + for (int i = 0; i < height2; i++) { + for (int j = 0; j < width; j++) { + T tmp; + int x = width - 1 - j; + int y = height - 1 - i; + + tmp = r(i, j); + r(i, j) = r(y, x); + r(y, x) = tmp; + + tmp = g(i, j); + g(i, j) = g(y, x); + g(y, x) = tmp; + + tmp = b(i, j); + b(i, j) = b(y, x); + b(y, x) = tmp; + } + } + } + } + + template + void resizeImgTo (int nw, int nh, TypeInterpolation interp, IC *imgPtr) + { + //printf("resizeImgTo: resizing %s image data (%d x %d) to %s (%d x %d)\n", getType(), width, height, imgPtr->getType(), imgPtr->width, imgPtr->height); + if (width == nw && height == nh) { + // special case where no resizing is necessary, just type conversion.... + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + convertTo(r(i, j), imgPtr->r(i, j)); + convertTo(g(i, j), imgPtr->g(i, j)); + convertTo(b(i, j), imgPtr->b(i, j)); + } + } + } else if (interp == TI_Nearest) { + for (int i = 0; i < nh; i++) { + int ri = i * height / nh; + + for (int j = 0; j < nw; j++) { + int ci = j * width / nw; + convertTo(r(ri, ci), imgPtr->r(i, j)); + convertTo(g(ri, ci), imgPtr->g(i, j)); + convertTo(b(ri, ci), imgPtr->b(i, j)); + } + } + } else if (interp == TI_Bilinear) { + for (int i = 0; i < nh; i++) { + int sy = i * height / nh; + + if (sy >= height) { + sy = height - 1; + } + + float dy = float(i) * float(height) / float(nh) - float(sy); + int ny = sy + 1; + + if (ny >= height) { + ny = sy; + } + + for (int j = 0; j < nw; j++) { + int sx = j * width / nw; + + if (sx >= width) { + sx = width; + } + + float dx = float(j) * float(width) / float(nw) - float(sx); + int nx = sx + 1; + + if (nx >= width) { + nx = sx; + } + + T valR = r(sy, sx) * (1.f - dx) * (1.f - dy) + r(sy, nx) * dx * (1.f - dy) + r(ny, sx) * (1.f - dx) * dy + r(ny, nx) * dx * dy; + T valG = g(sy, sx) * (1.f - dx) * (1.f - dy) + g(sy, nx) * dx * (1.f - dy) + g(ny, sx) * (1.f - dx) * dy + g(ny, nx) * dx * dy; + T valB = b(sy, sx) * (1.f - dx) * (1.f - dy) + b(sy, nx) * dx * (1.f - dy) + b(ny, sx) * (1.f - dx) * dy + b(ny, nx) * dx * dy; + convertTo(valR, imgPtr->r(i, j)); + convertTo(valG, imgPtr->g(i, j)); + convertTo(valB, imgPtr->b(i, j)); + } + } + } else { + // This case should never occur! + for (int i = 0; i < nh; i++) { + for (int j = 0; j < nw; j++) { + r(i, j) = 0; + g(i, j) = 0; + b(i, j) = 0; + } + } + } + } + + void hflip () + { + int width2 = width / 2; + + for (int i = 0; i < height; i++) { + int offsetBegin = 0; + int offsetEnd = 3 * (width - 1); + + for (int j = 0; j < width2; j++) { + T temp; + + temp = data[offsetBegin]; + data[offsetBegin] = data[offsetEnd]; + data[offsetEnd] = temp; + + ++offsetBegin; + ++offsetEnd; + + temp = data[offsetBegin]; + data[offsetBegin] = data[offsetEnd]; + data[offsetEnd] = temp; + + ++offsetBegin; + ++offsetEnd; + + temp = data[offsetBegin]; + data[offsetBegin] = data[offsetEnd]; + data[offsetEnd] = temp; + + ++offsetBegin; + offsetEnd -= 5; + + } + } + } + + void vflip () + { + + AlignedBuffer lBuffer(3 * width); + T* lineBuffer = lBuffer.data; + size_t size = 3 * width * sizeof(T); + + for (int i = 0; i < height / 2; i++) { + T *lineBegin1 = r(i); + T *lineBegin2 = r(height - 1 - i); + memcpy (lineBuffer, lineBegin1, size); + memcpy (lineBegin1, lineBegin2, size); + memcpy (lineBegin2, lineBuffer, size); + } + } + + void calcGrayscaleHist(unsigned int *hist16) + { + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + unsigned short rIdx, gIdx, bIdx; + convertTo(r(row, col), rIdx); + convertTo(g(row, col), gIdx); + convertTo(b(row, col), bIdx); + hist16[rIdx]++; + hist16[gIdx] += 2; // Bayer 2x green correction + hist16[bIdx]++; + } + } + + void computeAutoHistogram (LUTu & histogram, int& histcompr) + { + histcompr = 3; + + histogram(65536 >> histcompr); + histogram.clear(); + + for (int i = 0; i < height; i++) + for (int j = 0; j < width; j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + histogram[(int)Color::igamma_srgb (r_) >> histcompr]++; + histogram[(int)Color::igamma_srgb (g_) >> histcompr]++; + histogram[(int)Color::igamma_srgb (b_) >> histcompr]++; + } + } + + void computeHistogramAutoWB (double &avg_r, double &avg_g, double &avg_b, int &n, LUTu &histogram, const int compression) + { + histogram.clear(); + avg_r = avg_g = avg_b = 0.; + n = 0; + + for (unsigned int i = 0; i < (unsigned int)(height); i++) + for (unsigned int j = 0; j < (unsigned int)(width); j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + int rtemp = Color::igamma_srgb (r_); + int gtemp = Color::igamma_srgb (g_); + int btemp = Color::igamma_srgb (b_); + + histogram[rtemp >> compression]++; + histogram[gtemp >> compression] += 2; + histogram[btemp >> compression]++; + + // autowb computation + if (r_ > 64000.f || g_ > 64000.f || b_ > 64000.f) { + continue; + } + + avg_r += double(r_); + avg_g += double(g_); + avg_b += double(b_); + n++; + } + } + + void getAutoWBMultipliers (double &rm, double &gm, double &bm) + { + + double avg_r = 0.; + double avg_g = 0.; + double avg_b = 0.; + int n = 0; + //int p = 6; + + for (unsigned int i = 0; i < (unsigned int)(height); i++) + for (unsigned int j = 0; j < (unsigned int)(width); j++) { + float r_, g_, b_; + convertTo(r(i, j), r_); + convertTo(g(i, j), g_); + convertTo(b(i, j), b_); + + if (r_ > 64000.f || g_ > 64000.f || b_ > 64000.f) { + continue; + } + + avg_r += double(r_); + avg_g += double(g_); + avg_b += double(b_); + /*avg_r += intpow( (double)r(i, j), p); + avg_g += intpow( (double)g(i, j), p); + avg_b += intpow( (double)b(i, j), p);*/ + n++; + } + + rm = avg_r / double(n); + gm = avg_g / double(n); + bm = avg_b / double(n); + } + + void transformPixel (int x, int y, int tran, int& tx, int& ty) + { + + if (!tran) { + tx = x; + ty = y; + return; + } + + int W = width; + int H = height; + int sw = W, sh = H; + + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { + sw = H; + sh = W; + } + + int ppx = x, ppy = y; + + if (tran & TR_HFLIP) { + ppx = sw - 1 - x; + } + + if (tran & TR_VFLIP) { + ppy = sh - 1 - y; + } + + tx = ppx; + ty = ppy; + + if ((tran & TR_ROT) == TR_R180) { + tx = W - 1 - ppx; + ty = H - 1 - ppy; + } else if ((tran & TR_ROT) == TR_R90) { + tx = ppy; + ty = H - 1 - ppx; + } else if ((tran & TR_ROT) == TR_R270) { + tx = W - 1 - ppy; + ty = ppx; + } + } + + virtual void getSpotWBData (double &reds, double &greens, double &blues, int &rn, int &gn, int &bn, + std::vector &red, std::vector &green, std::vector &blue, + int tran) + { + int x; + int y; + reds = 0, greens = 0, blues = 0; + rn = 0, gn = 0, bn = 0; + + for (size_t i = 0; i < red.size(); i++) { + transformPixel (red[i].x, red[i].y, tran, x, y); + + if (x >= 0 && y >= 0 && x < width && y < height) { + float v; + convertTo(this->r(y, x), v); + reds += double(v); + rn++; + } + + transformPixel (green[i].x, green[i].y, tran, x, y); + + if (x >= 0 && y >= 0 && x < width && y < height) { + float v; + convertTo(this->g(y, x), v); + greens += double(v); + gn++; + } + + transformPixel (blue[i].x, blue[i].y, tran, x, y); + + if (x >= 0 && y >= 0 && x < width && y < height) { + float v; + convertTo(this->b(y, x), v); + blues += double(v); + bn++; + } + } + } + + void readData (FILE *f) + { + for (int i = 0; i < height; i++) { + fread (r(i), sizeof(T), 3 * width, f); + } + } + + void writeData (FILE *f) + { + for (int i = 0; i < height; i++) { + fwrite (r(i), sizeof(T), 3 * width, f); + } + } + +}; + +// -------------------------------------------------------------------- - /** @brief This class represents an image (the result of the image processing) */ - class IImage : virtual public ImageDimensions { - public: +/** @brief This class represents an image (the result of the image processing) */ +class IImage : virtual public ImageDimensions +{ +public: - virtual ~IImage() {} - /** @brief Returns a mutex that can is useful in many situations. No image operations shuold be performed without locking this mutex. - * @return The mutex */ - virtual MyMutex& getMutex ()=0; - virtual cmsHPROFILE getProfile ()=0; - /** @brief Returns the bits per pixel of the image. - * @return The bits per pixel of the image */ - virtual int getBitsPerPixel ()=0; - /** @brief Saves the image to file. It autodetects the format (jpg, tif, png are supported). - * @param fname is the name of the file - @return the error code, 0 if none */ - virtual int saveToFile (Glib::ustring fname)=0; - /** @brief Saves the image to file in a png format. - * @param fname is the name of the file - * @param compression is the amount of compression (0-6), -1 corresponds to the default - * @param bps can be 8 or 16 depending on the bits per pixels the output file will have - @return the error code, 0 if none */ - virtual int saveAsPNG (Glib::ustring fname, int compression = -1, int bps = -1)=0; - /** @brief Saves the image to file in a jpg format. - * @param fname is the name of the file - * @param quality is the quality of the jpeg (0...100), set it to -1 to use default - @return the error code, 0 if none */ - virtual int saveAsJPEG (Glib::ustring fname, int quality = 100, int subSamp = 3 )=0; - /** @brief Saves the image to file in a tif format. - * @param fname is the name of the file - * @param bps can be 8 or 16 depending on the bits per pixels the output file will have - @return the error code, 0 if none */ - virtual int saveAsTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false)=0; - /** @brief Sets the progress listener if you want to follow the progress of the image saving operations (optional). - * @param pl is the pointer to the class implementing the ProgressListener interface */ - virtual void setSaveProgressListener (ProgressListener* pl)=0; - /** @brief Free the image */ - virtual void free ()=0; - }; + virtual ~IImage() {} + /** @brief Returns a mutex that can is useful in many situations. No image operations shuold be performed without locking this mutex. + * @return The mutex */ + virtual MyMutex& getMutex () = 0; + virtual cmsHPROFILE getProfile () = 0; + /** @brief Returns the bits per pixel of the image. + * @return The bits per pixel of the image */ + virtual int getBitsPerPixel () = 0; + /** @brief Saves the image to file. It autodetects the format (jpg, tif, png are supported). + * @param fname is the name of the file + @return the error code, 0 if none */ + virtual int saveToFile (Glib::ustring fname) = 0; + /** @brief Saves the image to file in a png format. + * @param fname is the name of the file + * @param compression is the amount of compression (0-6), -1 corresponds to the default + * @param bps can be 8 or 16 depending on the bits per pixels the output file will have + @return the error code, 0 if none */ + virtual int saveAsPNG (Glib::ustring fname, int compression = -1, int bps = -1) = 0; + /** @brief Saves the image to file in a jpg format. + * @param fname is the name of the file + * @param quality is the quality of the jpeg (0...100), set it to -1 to use default + @return the error code, 0 if none */ + virtual int saveAsJPEG (Glib::ustring fname, int quality = 100, int subSamp = 3 ) = 0; + /** @brief Saves the image to file in a tif format. + * @param fname is the name of the file + * @param bps can be 8 or 16 depending on the bits per pixels the output file will have + @return the error code, 0 if none */ + virtual int saveAsTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false) = 0; + /** @brief Sets the progress listener if you want to follow the progress of the image saving operations (optional). + * @param pl is the pointer to the class implementing the ProgressListener interface */ + virtual void setSaveProgressListener (ProgressListener* pl) = 0; + /** @brief Free the image */ + virtual void free () = 0; +}; - /** @brief This class represents an image having a float pixel planar representation. - The planes are stored as two dimensional arrays. All the rows have a 128 bits alignment. */ - class IImagefloat : public IImage, public PlanarRGBData { - public: - virtual ~IImagefloat() {} - }; +/** @brief This class represents an image having a float pixel planar representation. + The planes are stored as two dimensional arrays. All the rows have a 128 bits alignment. */ +class IImagefloat : public IImage, public PlanarRGBData +{ +public: + virtual ~IImagefloat() {} +}; - /** @brief This class represents an image having a classical 8 bits/pixel representation */ - class IImage8 : public IImage, public ChunkyRGBData { - public: - virtual ~IImage8() {} - }; +/** @brief This class represents an image having a classical 8 bits/pixel representation */ +class IImage8 : public IImage, public ChunkyRGBData +{ +public: + virtual ~IImage8() {} +}; - /** @brief This class represents an image having a 16 bits/pixel planar representation. - The planes are stored as two dimensional arrays. All the rows have a 128 bits alignment. */ - class IImage16 : public IImage, public PlanarRGBData { - public: - virtual ~IImage16() {} - }; +/** @brief This class represents an image having a 16 bits/pixel planar representation. + The planes are stored as two dimensional arrays. All the rows have a 128 bits alignment. */ +class IImage16 : public IImage, public PlanarRGBData +{ +public: + virtual ~IImage16() {} +}; } diff --git a/rtengine/image16.cc b/rtengine/image16.cc index b62ad1d91..8ba88bd4c 100644 --- a/rtengine/image16.cc +++ b/rtengine/image16.cc @@ -7,7 +7,7 @@ * 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 @@ -25,36 +25,42 @@ using namespace rtengine; -Image16::Image16 () { +Image16::Image16 () +{ } -Image16::Image16 (int w, int h) { +Image16::Image16 (int w, int h) +{ allocate (w, h); } -Image16::~Image16 () { +Image16::~Image16 () +{ } -void Image16::getScanline (int row, unsigned char* buffer, int bps) { +void Image16::getScanline (int row, unsigned char* buffer, int bps) +{ - if (data==NULL) + if (data == NULL) { return; + } - if (bps==16) { + if (bps == 16) { int ix = 0; unsigned short* sbuffer = (unsigned short*) buffer; - for (int i=0; i> 8; - buffer[ix++] = g(row,i) >> 8; - buffer[ix++] = b(row,i) >> 8; + + for (int i = 0; i < width; i++) { + buffer[ix++] = r(row, i) >> 8; + buffer[ix++] = g(row, i) >> 8; + buffer[ix++] = b(row, i) >> 8; } } } @@ -63,51 +69,59 @@ void Image16::getScanline (int row, unsigned char* buffer, int bps) { * void Image16::setScanline (int row, unsigned char* buffer, int bps, int minValue[3], int maxValue[3]); * has not been implemented yet, because as of now, this method is called for IIOSF_FLOAT sample format only */ -void Image16::setScanline (int row, unsigned char* buffer, int bps, float *minValue, float *maxValue) { +void Image16::setScanline (int row, unsigned char* buffer, int bps, float *minValue, float *maxValue) +{ - if (data==NULL) + if (data == NULL) { return; + } - // For optimization purpose, we're assuming that this class never have to provide min/max bound + // For optimization purpose, we're assuming that this class never have to provide min/max bound assert(!minValue); switch (sampleFormat) { - case (IIOSF_UNSIGNED_CHAR): - { + case (IIOSF_UNSIGNED_CHAR): { int ix = 0; - for (int i=0; iwidth; // Destination image - int imheight=image->height; // Destination image - if (((tran & TR_ROT) == TR_R90)||((tran & TR_ROT) == TR_R270)) { + int imwidth = image->width; // Destination image + int imheight = image->height; // Destination image + + if (((tran & TR_ROT) == TR_R90) || ((tran & TR_ROT) == TR_R270)) { int swap = imwidth; - imwidth=imheight; - imheight=swap; + imwidth = imheight; + imheight = swap; } - int maxx=width; // Source image - int maxy=height; // Source image + + int maxx = width; // Source image + int maxy = height; // Source image int mtran = tran & TR_ROT; int skip = pp.skip; @@ -147,181 +163,198 @@ void Image16::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Preview // improve speed by integrating the area division into the multipliers // switched to using ints for the red/green/blue channel buffer. // Incidentally this improves accuracy too. - float area=skip*skip; - float rm2=rm; - float gm2=gm; - float bm2=bm; - rm/=area; - gm/=area; - bm/=area; + float area = skip * skip; + float rm2 = rm; + float gm2 = gm; + float bm2 = bm; + rm /= area; + gm /= area; + bm /= area; - #define GCLIP( x ) Color::gamma_srgb(CLIP(x)) +#define GCLIP( x ) Color::gamma_srgb(CLIP(x)) #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel { #endif - AlignedBuffer abR(imwidth); - AlignedBuffer abG(imwidth); - AlignedBuffer abB(imwidth); - float *lineR = abR.data; - float *lineG = abG.data; - float *lineB = abB.data; + AlignedBuffer abR(imwidth); + AlignedBuffer abG(imwidth); + AlignedBuffer abB(imwidth); + float *lineR = abR.data; + float *lineG = abG.data; + float *lineB = abB.data; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - // Iterating all the rows of the destination image - for (int iy=0; iy=maxy) - continue; + // Iterating all the rows of the destination image + for (int iy = 0; iy < imheight; iy++) { + if (skip == 1) { + // special case (speedup for 1:1 scale) + // i: source image, first line of the current destination row + int src_y = sy1 + iy; - for (int dst_x=0,src_x=sx1; dst_x=maxx) + if (src_y >= maxy) { continue; + } - lineR[dst_x] = CLIP(rm2*r(src_y, src_x)); - lineG[dst_x] = CLIP(gm2*g(src_y, src_x)); - lineB[dst_x] = CLIP(bm2*b(src_y, src_x)); - } - } - else { - // source image, first line of the current destination row - int src_y=sy1+skip*iy; - if (src_y>=maxy) - continue; - - for (int dst_x=0,src_x=sx1; dst_x=maxx) - continue; - - int src_sub_width = MIN(maxx-src_x, skip); - int src_sub_height = MIN(maxy-src_y, skip); - - float rtot,gtot,btot; // RGB accumulators - rtot=gtot=btot=0.; - - for (int src_sub_y=0; src_sub_y= maxx) { + continue; } - // convert back to gamma and clip - if (src_sub_width == skip && src_sub_height == skip) { - // Common case where the sub-region is complete - lineR[dst_x] = CLIP(rm*rtot); - lineG[dst_x] = CLIP(gm*gtot); - lineB[dst_x] = CLIP(bm*btot); + + lineR[dst_x] = CLIP(rm2 * r(src_y, src_x)); + lineG[dst_x] = CLIP(gm2 * g(src_y, src_x)); + lineB[dst_x] = CLIP(bm2 * b(src_y, src_x)); } - else { - // computing a special factor for this incomplete sub-region - float area = src_sub_width*src_sub_height; - lineR[dst_x] = CLIP(rm2*rtot/area); - lineG[dst_x] = CLIP(gm2*gtot/area); - lineB[dst_x] = CLIP(bm2*btot/area); + } else { + // source image, first line of the current destination row + int src_y = sy1 + skip * iy; + + if (src_y >= maxy) { + continue; + } + + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + if (src_x >= maxx) { + continue; + } + + int src_sub_width = MIN(maxx - src_x, skip); + int src_sub_height = MIN(maxy - src_y, skip); + + float rtot, gtot, btot; // RGB accumulators + rtot = gtot = btot = 0.; + + for (int src_sub_y = 0; src_sub_y < src_sub_height; src_sub_y++) + for (int src_sub_x = 0; src_sub_x < src_sub_width; src_sub_x++) { + rtot += r(src_y + src_sub_y, src_x + src_sub_x); + gtot += g(src_y + src_sub_y, src_x + src_sub_x); + btot += b(src_y + src_sub_y, src_x + src_sub_x); + } + + // convert back to gamma and clip + if (src_sub_width == skip && src_sub_height == skip) { + // Common case where the sub-region is complete + lineR[dst_x] = CLIP(rm * rtot); + lineG[dst_x] = CLIP(gm * gtot); + lineB[dst_x] = CLIP(bm * btot); + } else { + // computing a special factor for this incomplete sub-region + float area = src_sub_width * src_sub_height; + lineR[dst_x] = CLIP(rm2 * rtot / area); + lineG[dst_x] = CLIP(gm2 * gtot / area); + lineB[dst_x] = CLIP(bm2 * btot / area); + } } } + + if (mtran == TR_NONE) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(iy, dst_x) = lineR[dst_x]; + image->g(iy, dst_x) = lineG[dst_x]; + image->b(iy, dst_x) = lineB[dst_x]; + } + else if (mtran == TR_R180) + for (int dst_x = 0; dst_x < imwidth; dst_x++) { + image->r(imheight - 1 - iy, imwidth - 1 - dst_x) = lineR[dst_x]; + image->g(imheight - 1 - iy, imwidth - 1 - dst_x) = lineG[dst_x]; + image->b(imheight - 1 - iy, imwidth - 1 - dst_x) = lineB[dst_x]; + } + else if (mtran == TR_R90) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(dst_x, imheight - 1 - iy) = lineR[dst_x]; + image->g(dst_x, imheight - 1 - iy) = lineG[dst_x]; + image->b(dst_x, imheight - 1 - iy) = lineB[dst_x]; + } + else if (mtran == TR_R270) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(imwidth - 1 - dst_x, iy) = lineR[dst_x]; + image->g(imwidth - 1 - dst_x, iy) = lineG[dst_x]; + image->b(imwidth - 1 - dst_x, iy) = lineB[dst_x]; + } } - if (mtran == TR_NONE) - for (int dst_x=0,src_x=sx1; dst_xr(iy, dst_x) = lineR[dst_x]; - image->g(iy, dst_x) = lineG[dst_x]; - image->b(iy, dst_x) = lineB[dst_x]; - } - else if (mtran == TR_R180) - for (int dst_x=0; dst_xr(imheight-1-iy, imwidth-1-dst_x) = lineR[dst_x]; - image->g(imheight-1-iy, imwidth-1-dst_x) = lineG[dst_x]; - image->b(imheight-1-iy, imwidth-1-dst_x) = lineB[dst_x]; - } - else if (mtran == TR_R90) - for (int dst_x=0,src_x=sx1; dst_xr(dst_x, imheight-1-iy) = lineR[dst_x]; - image->g(dst_x, imheight-1-iy) = lineG[dst_x]; - image->b(dst_x, imheight-1-iy) = lineB[dst_x]; - } - else if (mtran == TR_R270) - for (int dst_x=0,src_x=sx1; dst_xr(imwidth-1-dst_x, iy) = lineR[dst_x]; - image->g(imwidth-1-dst_x, iy) = lineG[dst_x]; - image->b(imwidth-1-dst_x, iy) = lineB[dst_x]; - } - } #ifdef _OPENMP -} + } #endif - #undef GCLIP +#undef GCLIP } -Image8* +Image8* Image16::to8() { - Image8* img8 = new Image8(width,height); - for ( int h = 0; h < height; ++h ) - { - for ( int w = 0; w < width; ++w ) - { - img8->r(h, w) = (unsigned char)( r(h,w) >> 8); - img8->g(h, w) = (unsigned char)( g(h,w) >> 8); - img8->b(h, w) = (unsigned char)( b(h,w) >> 8); + Image8* img8 = new Image8(width, height); + + for ( int h = 0; h < height; ++h ) { + for ( int w = 0; w < width; ++w ) { + img8->r(h, w) = (unsigned char)( r(h, w) >> 8); + img8->g(h, w) = (unsigned char)( g(h, w) >> 8); + img8->b(h, w) = (unsigned char)( b(h, w) >> 8); } } + return img8; } -Imagefloat* +Imagefloat* Image16::tofloat() { - Imagefloat* imgfloat = new Imagefloat(width,height); - for ( int h = 0; h < height; ++h ) - { - for ( int w = 0; w < width; ++w ) - { - imgfloat->r(h,w) = (float)r(h,w); - imgfloat->g(h,w) = (float)g(h,w); - imgfloat->b(h,w) = (float)b(h,w); + Imagefloat* imgfloat = new Imagefloat(width, height); + + for ( int h = 0; h < height; ++h ) { + for ( int w = 0; w < width; ++w ) { + imgfloat->r(h, w) = (float)r(h, w); + imgfloat->g(h, w) = (float)g(h, w); + imgfloat->b(h, w) = (float)b(h, w); } } + return imgfloat; } // Parallized transformation; create transform with cmsFLAGS_NOCACHE! -void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform) { +void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform) +{ //cmsDoTransform(hTransform, data, data, planestride); // LittleCMS cannot parallelize planar setups -- Hombre: LCMS2.4 can! But it we use this new feature, memory allocation have to be modified too // so build temporary buffers to allow multi processor execution #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - AlignedBuffer buffer(width*3); + { + AlignedBuffer buffer(width * 3); #ifdef _OPENMP -#pragma omp for schedule(static) + #pragma omp for schedule(static) #endif - for (int y=0; y> 8; + switch (sampleFormat) { + case (IIOSF_UNSIGNED_CHAR): + memcpy (data + row * width * 3, buffer, width * 3); break; - } - default: - // Other type are ignored, but could be implemented if necessary - break; - } + + case (IIOSF_UNSIGNED_SHORT): { + unsigned short* sbuffer = (unsigned short*) buffer; + + for (int i = 0, ix = row * width * 3; i < width * 3; i++, ix++) { + data[ix] = sbuffer[i] >> 8; + } + + break; + } + + default: + // Other type are ignored, but could be implemented if necessary + break; + } } -Image8* Image8::copy () { +Image8* Image8::copy () +{ - Image8* cp = new Image8 (width, height); - copyData(cp); - return cp; + Image8* cp = new Image8 (width, height); + copyData(cp); + return cp; } void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp) @@ -85,12 +99,12 @@ void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewP // compute channel multipliers double drm, dgm, dbm; ctemp.getMultipliers (drm, dgm, dbm); - float rm=drm,gm=dgm,bm=dbm; + float rm = drm, gm = dgm, bm = dbm; rm = 1.0 / rm; gm = 1.0 / gm; bm = 1.0 / bm; - float mul_lum = 0.299*rm + 0.587*gm + 0.114*bm; + float mul_lum = 0.299 * rm + 0.587 * gm + 0.114 * bm; rm /= mul_lum; gm /= mul_lum; bm /= mul_lum; @@ -99,15 +113,17 @@ void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewP transform (pp, tran, sx1, sy1, sx2, sy2); - int imwidth=image->width; // Destination image - int imheight=image->height; // Destination image - if (((tran & TR_ROT) == TR_R90)||((tran & TR_ROT) == TR_R270)) { + int imwidth = image->width; // Destination image + int imheight = image->height; // Destination image + + if (((tran & TR_ROT) == TR_R90) || ((tran & TR_ROT) == TR_R270)) { int swap = imwidth; - imwidth=imheight; - imheight=swap; + imwidth = imheight; + imheight = swap; } - int maxx=width; // Source image - int maxy=height; // Source image + + int maxx = width; // Source image + int maxy = height; // Source image int mtran = tran & TR_ROT; int skip = pp.skip; @@ -116,126 +132,132 @@ void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewP // improve speed by integrating the area division into the multipliers // switched to using ints for the red/green/blue channel buffer. // Incidentally this improves accuracy too. - float area=skip*skip; - float rm2=rm; - float gm2=gm; - float bm2=bm; - rm/=area; - gm/=area; - bm/=area; + float area = skip * skip; + float rm2 = rm; + float gm2 = gm; + float bm2 = bm; + rm /= area; + gm /= area; + bm /= area; - #define GCLIP( x ) Color::gamma_srgb(CLIP(x)) +#define GCLIP( x ) Color::gamma_srgb(CLIP(x)) #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel { #endif - AlignedBuffer abR(imwidth); - AlignedBuffer abG(imwidth); - AlignedBuffer abB(imwidth); - float *lineR = abR.data; - float *lineG = abG.data; - float *lineB = abB.data; + AlignedBuffer abR(imwidth); + AlignedBuffer abG(imwidth); + AlignedBuffer abB(imwidth); + float *lineR = abR.data; + float *lineG = abG.data; + float *lineB = abB.data; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - // Iterating all the rows of the destination image - for (int iy=0; iy=maxy) - continue; - - for (int dst_x=0,src_x=sx1; dst_x=maxx) + if (src_y >= maxy) { continue; + } - convertTo(r(src_y, src_x), r_); - convertTo(g(src_y, src_x), g_); - convertTo(b(src_y, src_x), b_); - lineR[dst_x] = CLIP(rm2*r_); - lineG[dst_x] = CLIP(gm2*g_); - lineB[dst_x] = CLIP(bm2*b_); - } - } - else { - // source image, first line of the current destination row - int src_y=sy1+skip*iy; - if (src_y>=maxy) - continue; + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x++) { + float r_, g_, b_; - for (int dst_x=0,src_x=sx1; dst_x=maxx) - continue; - - int src_sub_width = MIN(maxx-src_x, skip); - int src_sub_height = MIN(maxy-src_y, skip); - - float rtot,gtot,btot; // RGB accumulators - rtot=gtot=btot=0.; - - for (int src_sub_y=0; src_sub_y= maxx) { + continue; } - // convert back to gamma and clip - if (src_sub_width == skip && src_sub_height == skip) { - // Common case where the sub-region is complete - lineR[dst_x] = CLIP(rm*rtot); - lineG[dst_x] = CLIP(gm*gtot); - lineB[dst_x] = CLIP(bm*btot); + + convertTo(r(src_y, src_x), r_); + convertTo(g(src_y, src_x), g_); + convertTo(b(src_y, src_x), b_); + lineR[dst_x] = CLIP(rm2 * r_); + lineG[dst_x] = CLIP(gm2 * g_); + lineB[dst_x] = CLIP(bm2 * b_); } - else { - // computing a special factor for this incomplete sub-region - float area = src_sub_width*src_sub_height; - lineR[dst_x] = CLIP(rm2*rtot/area); - lineG[dst_x] = CLIP(gm2*gtot/area); - lineB[dst_x] = CLIP(bm2*btot/area); + } else { + // source image, first line of the current destination row + int src_y = sy1 + skip * iy; + + if (src_y >= maxy) { + continue; + } + + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + if (src_x >= maxx) { + continue; + } + + int src_sub_width = MIN(maxx - src_x, skip); + int src_sub_height = MIN(maxy - src_y, skip); + + float rtot, gtot, btot; // RGB accumulators + rtot = gtot = btot = 0.; + + for (int src_sub_y = 0; src_sub_y < src_sub_height; src_sub_y++) + for (int src_sub_x = 0; src_sub_x < src_sub_width; src_sub_x++) { + float r_, g_, b_; + convertTo(r(src_y + src_sub_y, src_x + src_sub_x), r_); + convertTo(g(src_y + src_sub_y, src_x + src_sub_x), g_); + convertTo(b(src_y + src_sub_y, src_x + src_sub_x), b_); + rtot += r_; + gtot += g_; + btot += b_; + } + + // convert back to gamma and clip + if (src_sub_width == skip && src_sub_height == skip) { + // Common case where the sub-region is complete + lineR[dst_x] = CLIP(rm * rtot); + lineG[dst_x] = CLIP(gm * gtot); + lineB[dst_x] = CLIP(bm * btot); + } else { + // computing a special factor for this incomplete sub-region + float area = src_sub_width * src_sub_height; + lineR[dst_x] = CLIP(rm2 * rtot / area); + lineG[dst_x] = CLIP(gm2 * gtot / area); + lineB[dst_x] = CLIP(bm2 * btot / area); + } } } + + if (mtran == TR_NONE) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(iy, dst_x) = lineR[dst_x]; + image->g(iy, dst_x) = lineG[dst_x]; + image->b(iy, dst_x) = lineB[dst_x]; + } + else if (mtran == TR_R180) + for (int dst_x = 0; dst_x < imwidth; dst_x++) { + image->r(imheight - 1 - iy, imwidth - 1 - dst_x) = lineR[dst_x]; + image->g(imheight - 1 - iy, imwidth - 1 - dst_x) = lineG[dst_x]; + image->b(imheight - 1 - iy, imwidth - 1 - dst_x) = lineB[dst_x]; + } + else if (mtran == TR_R90) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(dst_x, imheight - 1 - iy) = lineR[dst_x]; + image->g(dst_x, imheight - 1 - iy) = lineG[dst_x]; + image->b(dst_x, imheight - 1 - iy) = lineB[dst_x]; + } + else if (mtran == TR_R270) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(imwidth - 1 - dst_x, iy) = lineR[dst_x]; + image->g(imwidth - 1 - dst_x, iy) = lineG[dst_x]; + image->b(imwidth - 1 - dst_x, iy) = lineB[dst_x]; + } } - if (mtran == TR_NONE) - for (int dst_x=0,src_x=sx1; dst_xr(iy, dst_x) = lineR[dst_x]; - image->g(iy, dst_x) = lineG[dst_x]; - image->b(iy, dst_x) = lineB[dst_x]; - } - else if (mtran == TR_R180) - for (int dst_x=0; dst_xr(imheight-1-iy, imwidth-1-dst_x) = lineR[dst_x]; - image->g(imheight-1-iy, imwidth-1-dst_x) = lineG[dst_x]; - image->b(imheight-1-iy, imwidth-1-dst_x) = lineB[dst_x]; - } - else if (mtran == TR_R90) - for (int dst_x=0,src_x=sx1; dst_xr(dst_x, imheight-1-iy) = lineR[dst_x]; - image->g(dst_x, imheight-1-iy) = lineG[dst_x]; - image->b(dst_x, imheight-1-iy) = lineB[dst_x]; - } - else if (mtran == TR_R270) - for (int dst_x=0,src_x=sx1; dst_xr(imwidth-1-dst_x, iy) = lineR[dst_x]; - image->g(imwidth-1-dst_x, iy) = lineG[dst_x]; - image->b(imwidth-1-dst_x, iy) = lineB[dst_x]; - } - } #ifdef _OPENMP -} + } #endif - #undef GCLIP +#undef GCLIP } diff --git a/rtengine/image8.h b/rtengine/image8.h index 9394d2f3f..188e20146 100644 --- a/rtengine/image8.h +++ b/rtengine/image8.h @@ -7,7 +7,7 @@ * 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 @@ -26,35 +26,70 @@ #include "rtengine.h" #include "imagefloat.h" -namespace rtengine { +namespace rtengine +{ -class Image8 : public IImage8, public ImageIO { +class Image8 : public IImage8, public ImageIO +{ - public: +public: - Image8 (); - Image8 (int width, int height); - ~Image8 (); + Image8 (); + Image8 (int width, int height); + ~Image8 (); - Image8* copy (); + Image8* copy (); - virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp); + virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp); - virtual const char* getType () const { return sImage8; } - virtual int getBPS () { return 8*sizeof(unsigned char); } - virtual void getScanline (int row, unsigned char* buffer, int bps); - virtual void setScanline (int row, unsigned char* buffer, int bps, float *minValue=NULL, float *maxValue=NULL); + virtual const char* getType () const + { + return sImage8; + } + virtual int getBPS () + { + return 8 * sizeof(unsigned char); + } + virtual void getScanline (int row, unsigned char* buffer, int bps); + virtual void setScanline (int row, unsigned char* buffer, int bps, float *minValue = NULL, float *maxValue = NULL); - // functions inherited from IImage*: - virtual MyMutex& getMutex () { return mutex (); } - virtual cmsHPROFILE getProfile () { return getEmbeddedProfile (); } - virtual int getBitsPerPixel () { return 8*sizeof(unsigned char); } - virtual int saveToFile (Glib::ustring fname) { return save (fname); } - virtual int saveAsPNG (Glib::ustring fname, int compression = -1, int bps = -1) { return savePNG (fname, compression, bps); } - virtual int saveAsJPEG (Glib::ustring fname, int quality = 100, int subSamp = 3) { return saveJPEG (fname, quality, subSamp); } - virtual int saveAsTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false) { return saveTIFF (fname, bps, uncompressed); } - virtual void setSaveProgressListener (ProgressListener* pl) { setProgressListener (pl); } - virtual void free () { delete this; } + // functions inherited from IImage*: + virtual MyMutex& getMutex () + { + return mutex (); + } + virtual cmsHPROFILE getProfile () + { + return getEmbeddedProfile (); + } + virtual int getBitsPerPixel () + { + return 8 * sizeof(unsigned char); + } + virtual int saveToFile (Glib::ustring fname) + { + return save (fname); + } + virtual int saveAsPNG (Glib::ustring fname, int compression = -1, int bps = -1) + { + return savePNG (fname, compression, bps); + } + virtual int saveAsJPEG (Glib::ustring fname, int quality = 100, int subSamp = 3) + { + return saveJPEG (fname, quality, subSamp); + } + virtual int saveAsTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false) + { + return saveTIFF (fname, bps, uncompressed); + } + virtual void setSaveProgressListener (ProgressListener* pl) + { + setProgressListener (pl); + } + virtual void free () + { + delete this; + } }; diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 1b6a770a0..9d3f8d5ea 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -29,36 +29,43 @@ using namespace rtengine; extern "C" IptcData *iptc_data_new_from_jpeg_file (FILE* infile); -ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml) { +ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml) +{ return new ImageData (fname, rml); } -ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) { +ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) +{ size_t dotpos = fname.find_last_of ('.'); root = NULL; iptc = NULL; - if (ri && (ri->exifBase>=0 || ri->ciffBase>=0)) { + if (ri && (ri->exifBase >= 0 || ri->ciffBase >= 0)) { FILE* f = safe_g_fopen (fname, "rb"); + if (f) { - if (ri->exifBase>=0) { + if (ri->exifBase >= 0) { root = rtexif::ExifManager::parse (f, ri->exifBase); + if (root) { rtexif::Tag* t = root->getTag (0x83BB); - if (t) + + if (t) { iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + } } - } - else if (ri->ciffBase>=0) + } else if (ri->ciffBase >= 0) { root = rtexif::ExifManager::parseCIFF (f, ri->ciffBase, ri->ciffLength); + } + fclose (f); extractInfo (); } - } - else if ((dotposgetTag (0x83BB); - if (t) + + if (t) { iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + } } } - } - else { + } else { root = new rtexif::TagDirectory (); shutter = 0; aperture = 0; @@ -96,276 +105,363 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) { } } -void ImageData::extractInfo () { +void ImageData::extractInfo () +{ - if (!root) - return; + if (!root) { + return; + } - make = ""; - model = ""; - serial = ""; - orientation = ""; - expcomp = 0; - shutter = 0; - aperture = 0; - focal_len = focal_len35mm = 0; - focus_dist = 0; - iso_speed = 0; - memset (&time, 0, sizeof(time)); - timeStamp = 0; + make = ""; + model = ""; + serial = ""; + orientation = ""; + expcomp = 0; + shutter = 0; + aperture = 0; + focal_len = focal_len35mm = 0; + focus_dist = 0; + iso_speed = 0; + memset (&time, 0, sizeof(time)); + timeStamp = 0; - if (root->getTag ("Make")){ - make = root->getTag ("Make")->valueToString (); - // same dcraw treatment - static const char *corp[] = - { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", "RICOH", - "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", - "SAMSUNG", "Mamiya", "MOTOROLA", "Leaf" }; - for (size_t i=0; i < (sizeof(corp)/sizeof(*corp)); i++) - if ( make.find( corp[i] ) != std::string::npos ){ /* Simplify company names */ - make = corp[i]; - break; - } - make.erase( make.find_last_not_of(' ')+1 ); - } + if (root->getTag ("Make")) { + make = root->getTag ("Make")->valueToString (); + // same dcraw treatment + static const char *corp[] = { + "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX", "RICOH", + "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One", + "SAMSUNG", "Mamiya", "MOTOROLA", "Leaf" + }; - if (root->getTag ("Model")) - model = root->getTag ("Model")->valueToString (); - if (!(model.size()==0)) { - std::size_t i=0; - if ( make.find("KODAK") != std::string::npos ){ - if( (i = model.find(" DIGITAL CAMERA")) != std::string::npos || - (i = model.find(" Digital Camera")) != std::string::npos || - (i = model.find("FILE VERSION")) ) - model.resize( i ); - } + for (size_t i = 0; i < (sizeof(corp) / sizeof(*corp)); i++) + if ( make.find( corp[i] ) != std::string::npos ) { /* Simplify company names */ + make = corp[i]; + break; + } - model.erase( model.find_last_not_of(' ')+1 ); + make.erase( make.find_last_not_of(' ') + 1 ); + } - //if( (i=model.find( make )) != std::string::npos ) - if( !strncasecmp (model.c_str(), make.c_str(), make.size()) ) - if( model.at( make.size() )==' ') - model.erase(0,make.size()+1); - if( model.find( "Digital Camera ") != std::string::npos ) - model.erase(0,15); - } - else { - model = "Unknown"; - } - if (root->getTag ("Orientation")){ - orientation = root->getTag ("Orientation")->valueToString (); - } + if (root->getTag ("Model")) { + model = root->getTag ("Model")->valueToString (); + } - rtexif::TagDirectory* exif = NULL; - if (root->getTag ("Exif")) - exif = root->getTag ("Exif")->getDirectory (); + if (!(model.size() == 0)) { + std::size_t i = 0; - if (exif) { + if ( make.find("KODAK") != std::string::npos ) { + if( (i = model.find(" DIGITAL CAMERA")) != std::string::npos || + (i = model.find(" Digital Camera")) != std::string::npos || + (i = model.find("FILE VERSION")) ) { + model.resize( i ); + } + } - // standard exif tags - if (exif->getTag ("ShutterSpeedValue")) - shutter = exif->getTag ("ShutterSpeedValue")->toDouble (); - if (exif->getTag ("ExposureTime")) - shutter = exif->getTag ("ExposureTime")->toDouble (); - if (exif->getTag ("ApertureValue")) - aperture = exif->getTag ("ApertureValue")->toDouble (); - if (exif->getTag ("FNumber")) - aperture = exif->getTag ("FNumber")->toDouble (); - if (exif->getTag ("ExposureBiasValue")) - expcomp = exif->getTag ("ExposureBiasValue")->toDouble (); - if (exif->getTag ("FocalLength")) - focal_len = exif->getTag ("FocalLength")->toDouble (); - if (exif->getTag ("FocalLengthIn35mmFilm")) - focal_len35mm = exif->getTag ("FocalLengthIn35mmFilm")->toDouble (); + model.erase( model.find_last_not_of(' ') + 1 ); - // Focus distance from EXIF or XMP. MakerNote ones are scattered and partly encrypted - int num=-3, denom=-3; + //if( (i=model.find( make )) != std::string::npos ) + if( !strncasecmp (model.c_str(), make.c_str(), make.size()) ) + if( model.at( make.size() ) == ' ') { + model.erase(0, make.size() + 1); + } - // First try, offical EXIF. Set by Adobe on some DNGs - rtexif::Tag* pDst=exif->getTag("SubjectDistance"); - if (pDst) { - int num, denom; - pDst->toRational(num,denom); + if( model.find( "Digital Camera ") != std::string::npos ) { + model.erase(0, 15); + } } else { - // Second try, XMP data - char sXMPVal[64]; - if (root->getXMPTagValue("aux:ApproximateFocusDistance",sXMPVal)) { sscanf(sXMPVal,"%d/%d",&num,&denom); } + model = "Unknown"; } - if (num!=-3) { - if ((denom==1 && num>=10000) || num<0 || denom<0) - focus_dist=10000; // infinity - else if (denom>0) { - focus_dist=(float)num/denom; - } + if (root->getTag ("Orientation")) { + orientation = root->getTag ("Orientation")->valueToString (); } - if (exif->getTag ("ISOSpeedRatings")) - iso_speed = exif->getTag ("ISOSpeedRatings")->toDouble (); - if (exif->getTag ("DateTimeOriginal")) { - if (sscanf ((const char*)exif->getTag("DateTimeOriginal")->getValue(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { - time.tm_year -= 1900; - time.tm_mon -= 1; - time.tm_isdst = -1; - timeStamp = mktime(&time); - } + rtexif::TagDirectory* exif = NULL; + + if (root->getTag ("Exif")) { + exif = root->getTag ("Exif")->getDirectory (); } - rtexif::Tag *snTag = exif->findTag ("SerialNumber"); - if(!snTag) - snTag = exif->findTag ("InternalSerialNumber"); - if ( snTag ) - serial = snTag->valueToString(); - // guess lens... - lens = "Unknown"; - // Sometimes (e.g. DNG) EXIF already contains lens data + if (exif) { - if(!make.compare (0, 8, "FUJIFILM")) { - if(exif->getTag ("LensModel")) { - lens = exif->getTag ("LensModel")->valueToString (); - } - } 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 (isoTag) - iso_speed = isoTag->toInt(); - } - bool lensOk = false; - 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 (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(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"); - lensOk = true; - } - } - } - } - } - 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 (igetTag ("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' - } + // standard exif tags + if (exif->getTag ("ShutterSpeedValue")) { + shutter = exif->getTag ("ShutterSpeedValue")->toDouble (); + } + + if (exif->getTag ("ExposureTime")) { + shutter = exif->getTag ("ExposureTime")->toDouble (); + } + + if (exif->getTag ("ApertureValue")) { + aperture = exif->getTag ("ApertureValue")->toDouble (); + } + + if (exif->getTag ("FNumber")) { + aperture = exif->getTag ("FNumber")->toDouble (); + } + + if (exif->getTag ("ExposureBiasValue")) { + expcomp = exif->getTag ("ExposureBiasValue")->toDouble (); + } + + if (exif->getTag ("FocalLength")) { + focal_len = exif->getTag ("FocalLength")->toDouble (); + } + + if (exif->getTag ("FocalLengthIn35mmFilm")) { + focal_len35mm = exif->getTag ("FocalLengthIn35mmFilm")->toDouble (); + } + + // Focus distance from EXIF or XMP. MakerNote ones are scattered and partly encrypted + int num = -3, denom = -3; + + // First try, offical EXIF. Set by Adobe on some DNGs + rtexif::Tag* pDst = exif->getTag("SubjectDistance"); + + if (pDst) { + int num, denom; + pDst->toRational(num, denom); + } else { + // Second try, XMP data + char sXMPVal[64]; + + if (root->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { + sscanf(sXMPVal, "%d/%d", &num, &denom); } } - 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 (num != -3) { + if ((denom == 1 && num >= 10000) || num < 0 || denom < 0) { + focus_dist = 10000; // infinity + } else if (denom > 0) { + focus_dist = (float)num / denom; } - 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 (exif->getTag ("ISOSpeedRatings")) { + iso_speed = exif->getTag ("ISOSpeedRatings")->toDouble (); + } + + if (exif->getTag ("DateTimeOriginal")) { + if (sscanf ((const char*)exif->getTag("DateTimeOriginal")->getValue(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { + time.tm_year -= 1900; + time.tm_mon -= 1; + time.tm_isdst = -1; + timeStamp = mktime(&time); + } + } + + rtexif::Tag *snTag = exif->findTag ("SerialNumber"); + + if(!snTag) { + snTag = exif->findTag ("InternalSerialNumber"); + } + + if ( snTag ) { + serial = snTag->valueToString(); + } + + // guess lens... + lens = "Unknown"; + + // Sometimes (e.g. DNG) EXIF already contains lens data + + if(!make.compare (0, 8, "FUJIFILM")) { + if(exif->getTag ("LensModel")) { + lens = exif->getTag ("LensModel")->valueToString (); + } + } 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 (isoTag) { + iso_speed = isoTag->toInt(); + } } - } - if( !found || lens.substr(lens.find(' ')).length() < 7 ){ - lt = mnote->findTag("LensID"); + + bool lensOk = false; + + 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 (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(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"); + } + + lensOk = true; + } + } + } + } + } + + 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] != '/') { + 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; + } + + 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' + } 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"); + + 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) { - lens = ldata; + + if (ldata.size() > 1) { + 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) { + 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 (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) - 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 (); } - } } -ImageData::~ImageData () { +ImageData::~ImageData () +{ delete root; - if (iptc) + + if (iptc) { iptc_data_free (iptc); + } } -const procparams::IPTCPairs ImageData::getIPTCData () const { +const procparams::IPTCPairs ImageData::getIPTCData () const +{ procparams::IPTCPairs iptcc; - if (!iptc) + + if (!iptc) { return iptcc; + } unsigned char buffer[2100]; - for (int i=0; i<16; i++) { + + for (int i = 0; i < 16; i++) { IptcDataSet* ds = iptc_data_get_next_dataset (iptc, NULL, IPTC_RECORD_APP_2, strTags[i].tag); + if (ds) { iptc_dataset_get_data (ds, buffer, 2100); std::vector icValues; @@ -375,20 +471,25 @@ const procparams::IPTCPairs ImageData::getIPTCData () const { iptc_dataset_unref (ds); } } + IptcDataSet* ds = NULL; std::vector keywords; - while ((ds=iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS))) { + + 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)); } + iptcc["Keywords"] = keywords; ds = NULL; std::vector suppCategories; - while ((ds=iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY))) { + + 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)); iptc_dataset_unref (ds); } + iptcc["SupplementalCategories"] = suppCategories; return iptcc; } @@ -396,50 +497,60 @@ const procparams::IPTCPairs ImageData::getIPTCData () const { //------inherited functions--------------// -std::string ImageMetaData::apertureToString (double aperture) { +std::string ImageMetaData::apertureToString (double aperture) +{ char buffer[256]; sprintf (buffer, "%0.1f", aperture); return buffer; } -std::string ImageMetaData::shutterToString (double shutter) { +std::string ImageMetaData::shutterToString (double shutter) +{ char buffer[256]; - if (shutter > 0.0 && shutter < 0.9) + + if (shutter > 0.0 && shutter < 0.9) { sprintf (buffer, "1/%0.0f", 1.0 / shutter); - else + } else { sprintf (buffer, "%0.1f", shutter); + } + return buffer; } -std::string ImageMetaData::expcompToString (double expcomp, bool maskZeroexpcomp) { +std::string ImageMetaData::expcompToString (double expcomp, bool maskZeroexpcomp) +{ char buffer[256]; - if (maskZeroexpcomp==true){ - if (expcomp!=0.0){ - sprintf (buffer, "%0.2f", expcomp); - return buffer; + + if (maskZeroexpcomp == true) { + if (expcomp != 0.0) { + sprintf (buffer, "%0.2f", expcomp); + return buffer; + } else { + return ""; } - else - return ""; - } - else{ - sprintf (buffer, "%0.2f", expcomp); - return buffer; + } else { + sprintf (buffer, "%0.2f", expcomp); + return buffer; } } -double ImageMetaData::shutterFromString (std::string s) { +double ImageMetaData::shutterFromString (std::string s) +{ size_t i = s.find_first_of ('/'); - if (i==std::string::npos) + + if (i == std::string::npos) { return atof (s.c_str()); - else - return atof (s.substr(0,i).c_str()) / atof (s.substr(i+1).c_str()); + } else { + return atof (s.substr(0, i).c_str()) / atof (s.substr(i + 1).c_str()); + } } -double ImageMetaData::apertureFromString (std::string s) { +double ImageMetaData::apertureFromString (std::string s) +{ return atof (s.c_str()); } @@ -449,56 +560,60 @@ extern "C" { #include #include -struct _IptcDataPrivate -{ - unsigned int ref_count; + struct _IptcDataPrivate { + unsigned int ref_count; - IptcLog *log; - IptcMem *mem; -}; + IptcLog *log; + IptcMem *mem; + }; -IptcData * -iptc_data_new_from_jpeg_file (FILE *infile) -{ - IptcData *d; - unsigned char * buf; - int buf_len = 256*256; - int len, offset; + IptcData * + iptc_data_new_from_jpeg_file (FILE *infile) + { + IptcData *d; + unsigned char * buf; + int buf_len = 256 * 256; + int len, offset; unsigned int iptc_len; - if (!infile) - return NULL; + if (!infile) { + return NULL; + } - d = iptc_data_new (); - if (!d) - return NULL; + d = iptc_data_new (); - buf = (unsigned char*)iptc_mem_alloc (d->priv->mem, buf_len); - if (!buf) { - iptc_data_unref (d); - return NULL; - } + if (!d) { + return NULL; + } - len = iptc_jpeg_read_ps3 (infile, buf, buf_len); + buf = (unsigned char*)iptc_mem_alloc (d->priv->mem, buf_len); - if (len <= 0) { - goto failure; - } + if (!buf) { + iptc_data_unref (d); + return NULL; + } - offset = iptc_jpeg_ps3_find_iptc (buf, len, &iptc_len); - if (offset <= 0) { - goto failure; - } + len = iptc_jpeg_read_ps3 (infile, buf, buf_len); - iptc_data_load (d, buf + offset, iptc_len); + if (len <= 0) { + goto failure; + } - iptc_mem_free (d->priv->mem, buf); - return d; + offset = iptc_jpeg_ps3_find_iptc (buf, len, &iptc_len); + + if (offset <= 0) { + goto failure; + } + + iptc_data_load (d, buf + offset, iptc_len); + + iptc_mem_free (d->priv->mem, buf); + return d; failure: - iptc_mem_free (d->priv->mem, buf); - iptc_data_unref (d); - return NULL; -} + iptc_mem_free (d->priv->mem, buf); + iptc_data_unref (d); + return NULL; + } } diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 3074c91b2..9ec3558c1 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -7,7 +7,7 @@ * 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 @@ -28,11 +28,13 @@ #include #include "rtengine.h" -namespace rtengine { +namespace rtengine +{ -class ImageData : public ImageMetaData { +class ImageData : public ImageMetaData +{ - protected: +protected: rtexif::TagDirectory* root; IptcData* iptc; @@ -49,32 +51,82 @@ class ImageData : public ImageMetaData { std::string lens; void extractInfo (); - - public: - ImageData (Glib::ustring fname, RawMetaDataLocation* rml=NULL); +public: + + ImageData (Glib::ustring fname, RawMetaDataLocation* rml = NULL); virtual ~ImageData (); - const rtexif::TagDirectory* getExifData () const { return root; } + const rtexif::TagDirectory* getExifData () const + { + return root; + } const procparams::IPTCPairs getIPTCData () const; - bool hasExif () const { return root && root->getCount(); } - bool hasIPTC () const { return iptc; } + bool hasExif () const + { + return root && root->getCount(); + } + bool hasIPTC () const + { + return iptc; + } - struct tm getDateTime () const { return time; } - time_t getDateTimeAsTS() const { return timeStamp; } - int getISOSpeed () const { return iso_speed; } - double getFNumber () const { return aperture; } - double getFocalLen () const { return focal_len; } - double getFocalLen35mm () const { return focal_len35mm; } - float getFocusDist () const { return focus_dist; } - double getShutterSpeed () const { return shutter; } - double getExpComp () const { return expcomp; } - std::string getMake () const { return make; } - std::string getModel () const { return model; } - std::string getLens () const { return lens; } - std::string getSerialNumber () const { return serial;} - std::string getOrientation () const { return orientation; } + struct tm getDateTime () const { + return time; + } + time_t getDateTimeAsTS() const + { + return timeStamp; + } + int getISOSpeed () const + { + return iso_speed; + } + double getFNumber () const + { + return aperture; + } + double getFocalLen () const + { + return focal_len; + } + double getFocalLen35mm () const + { + return focal_len35mm; + } + float getFocusDist () const + { + return focus_dist; + } + double getShutterSpeed () const + { + return shutter; + } + double getExpComp () const + { + return expcomp; + } + std::string getMake () const + { + return make; + } + std::string getModel () const + { + return model; + } + std::string getLens () const + { + return lens; + } + std::string getSerialNumber () const + { + return serial; + } + std::string getOrientation () const + { + return orientation; + } }; } #endif diff --git a/rtengine/imagedimensions.cc b/rtengine/imagedimensions.cc index 949533245..f7d291483 100644 --- a/rtengine/imagedimensions.cc +++ b/rtengine/imagedimensions.cc @@ -20,44 +20,55 @@ #include "imagedimensions.h" #include "rtengine.h" -void ImageDimensions::transform (PreviewProps pp, int tran, int &sx1, int &sy1, int &sx2, int &sy2) { +void ImageDimensions::transform (PreviewProps pp, int tran, int &sx1, int &sy1, int &sx2, int &sy2) +{ - int sw = width, sh = height; - if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { - sw = height; - sh = width; - } - int ppx = pp.x, ppy = pp.y; - if (tran & TR_HFLIP) - ppx = sw - pp.x - pp.w; - if (tran & TR_VFLIP) - ppy = sh - pp.y - pp.h; + int sw = width, sh = height; - sx1 = ppx; - sy1 = ppy; - sx2 = ppx + pp.w; - sy2 = ppy + pp.h; + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { + sw = height; + sh = width; + } - if ((tran & TR_ROT) == TR_R180) { - sx1 = width - ppx - pp.w; - sy1 = height - ppy - pp.h; - sx2 = sx1 + pp.w; - sy2 = sy1 + pp.h; - } - else if ((tran & TR_ROT) == TR_R90) { - sx1 = ppy; - sy1 = height - ppx - pp.w; - sx2 = sx1 + pp.h; - sy2 = sy1 + pp.w; - } - else if ((tran & TR_ROT) == TR_R270) { - sx1 = width - ppy - pp.h; - sy1 = ppx; - sx2 = sx1 + pp.h; - sy2 = sy1 + pp.w; - } - //printf ("ppx %d ppy %d ppw %d pph %d s: %d %d %d %d\n",pp.x, pp.y,pp.w,pp.h,sx1,sy1,sx2,sy2); - if (sx1<0)sx1=0; - if (sy1<0)sy1=0; + int ppx = pp.x, ppy = pp.y; + + if (tran & TR_HFLIP) { + ppx = sw - pp.x - pp.w; + } + + if (tran & TR_VFLIP) { + ppy = sh - pp.y - pp.h; + } + + sx1 = ppx; + sy1 = ppy; + sx2 = ppx + pp.w; + sy2 = ppy + pp.h; + + if ((tran & TR_ROT) == TR_R180) { + sx1 = width - ppx - pp.w; + sy1 = height - ppy - pp.h; + sx2 = sx1 + pp.w; + sy2 = sy1 + pp.h; + } else if ((tran & TR_ROT) == TR_R90) { + sx1 = ppy; + sy1 = height - ppx - pp.w; + sx2 = sx1 + pp.h; + sy2 = sy1 + pp.w; + } else if ((tran & TR_ROT) == TR_R270) { + sx1 = width - ppy - pp.h; + sy1 = ppx; + sx2 = sx1 + pp.h; + sy2 = sy1 + pp.w; + } + + //printf ("ppx %d ppy %d ppw %d pph %d s: %d %d %d %d\n",pp.x, pp.y,pp.w,pp.h,sx1,sy1,sx2,sy2); + if (sx1 < 0) { + sx1 = 0; + } + + if (sy1 < 0) { + sy1 = 0; + } } diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h index 547c3aaf7..0b50d71c1 100644 --- a/rtengine/imagedimensions.h +++ b/rtengine/imagedimensions.h @@ -20,29 +20,43 @@ #ifndef _IMAGEDIMENSIONS_ #define _IMAGEDIMENSIONS_ -class PreviewProps { - public: - int x, y, w, h, skip; - PreviewProps (int _x, int _y, int _w, int _h, int _skip) - : x(_x), y(_y), w(_w), h(_h), skip(_skip) {} +class PreviewProps +{ +public: + int x, y, w, h, skip; + PreviewProps (int _x, int _y, int _w, int _h, int _skip) + : x(_x), y(_y), w(_w), h(_h), skip(_skip) {} }; /* * Description of an image dimension, with getter and setter */ -class ImageDimensions { +class ImageDimensions +{ - public: - int width; - int height; +public: + int width; + int height; - public: - ImageDimensions() : width(-1), height(-1) {} - int getW () { return width; } - int getH () { return height; } - int getWidth () { return width; } - int getHeight () { return height; } - void transform (PreviewProps pp, int tran, int &sx1, int &sy1, int &sx2, int &sy2); +public: + ImageDimensions() : width(-1), height(-1) {} + int getW () + { + return width; + } + int getH () + { + return height; + } + int getWidth () + { + return width; + } + int getHeight () + { + return height; + } + void transform (PreviewProps pp, int tran, int &sx1, int &sy1, int &sx2, int &sy2); }; diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index fd71a7108..26ea8ae6e 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -7,7 +7,7 @@ * 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 @@ -30,79 +30,144 @@ using namespace rtengine; -Imagefloat::Imagefloat () { +Imagefloat::Imagefloat () +{ } -Imagefloat::Imagefloat (int w, int h) { +Imagefloat::Imagefloat (int w, int h) +{ allocate (w, h); } -Imagefloat::~Imagefloat () { +Imagefloat::~Imagefloat () +{ } // Call this method to handle floating points input values of different size -void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, float *minValue, float *maxValue) { +void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, float *minValue, float *maxValue) +{ - if (data==NULL) + if (data == NULL) { return; + } switch (sampleFormat) { - case (IIOSF_FLOAT): - { + case (IIOSF_FLOAT): { int ix = 0; float* sbuffer = (float*) buffer; - for (int i=0; imaxValue[0]) maxValue[0] = sbuffer[ix]; ++ix; } - g(row,i) = sbuffer[ix]; if (minValue) { if (sbuffer[ix]maxValue[1]) maxValue[1] = sbuffer[ix]; ++ix; } - b(row,i) = sbuffer[ix]; if (minValue) { if (sbuffer[ix]maxValue[2]) maxValue[2] = sbuffer[ix]; ++ix; } + + for (int i = 0; i < width; i++) { + r(row, i) = sbuffer[ix]; + + if (minValue) { + if (sbuffer[ix] < minValue[0]) { + minValue[0] = sbuffer[ix]; + } else if (sbuffer[ix] > maxValue[0]) { + maxValue[0] = sbuffer[ix]; + } ++ix; + } + + g(row, i) = sbuffer[ix]; + + if (minValue) { + if (sbuffer[ix] < minValue[1]) { + minValue[1] = sbuffer[ix]; + } else if (sbuffer[ix] > maxValue[1]) { + maxValue[1] = sbuffer[ix]; + } ++ix; + } + + b(row, i) = sbuffer[ix]; + + if (minValue) { + if (sbuffer[ix] < minValue[2]) { + minValue[2] = sbuffer[ix]; + } else if (sbuffer[ix] > maxValue[2]) { + maxValue[2] = sbuffer[ix]; + } ++ix; + } } + break; } + case (IIOSF_LOGLUV24): - case (IIOSF_LOGLUV32): - { + case (IIOSF_LOGLUV32): { int ix = 0; float* sbuffer = (float*) buffer; float xyzvalues[3], rgbvalues[3]; - for (int i=0; imaxValue[0]) maxValue[0] = rgbvalues[0]; } - g(row,i) = rgbvalues[1]; if (minValue) { if (rgbvalues[1]maxValue[1]) maxValue[1] = rgbvalues[1]; } - b(row,i) = rgbvalues[2]; if (minValue) { if (rgbvalues[2]maxValue[2]) maxValue[2] = rgbvalues[2]; } + r(row, i) = rgbvalues[0]; + + if (minValue) { + if (rgbvalues[0] < minValue[0]) { + minValue[0] = rgbvalues[0]; + } else if (rgbvalues[0] > maxValue[0]) { + maxValue[0] = rgbvalues[0]; + } + } + + g(row, i) = rgbvalues[1]; + + if (minValue) { + if (rgbvalues[1] < minValue[1]) { + minValue[1] = rgbvalues[1]; + } else if (rgbvalues[1] > maxValue[1]) { + maxValue[1] = rgbvalues[1]; + } + } + + b(row, i) = rgbvalues[2]; + + if (minValue) { + if (rgbvalues[2] < minValue[2]) { + minValue[2] = rgbvalues[2]; + } else if (rgbvalues[2] > maxValue[2]) { + maxValue[2] = rgbvalues[2]; + } + } } + break; } + default: // Other type are ignored, but could be implemented if necessary break; } } -void Imagefloat::getScanline (int row, unsigned char* buffer, int bps) { +void Imagefloat::getScanline (int row, unsigned char* buffer, int bps) +{ - if (data==NULL) + if (data == NULL) { return; + } - if (bps==32) { + if (bps == 32) { int ix = 0; float* sbuffer = (float*) buffer; - for (int i=0; iwidth; // Destination image - int imheight=image->height; // Destination image - if (((tran & TR_ROT) == TR_R90)||((tran & TR_ROT) == TR_R270)) { + int imwidth = image->width; // Destination image + int imheight = image->height; // Destination image + + if (((tran & TR_ROT) == TR_R90) || ((tran & TR_ROT) == TR_R270)) { int swap = imwidth; - imwidth=imheight; - imheight=swap; + imwidth = imheight; + imheight = swap; } - int maxx=width; // Source image - int maxy=height; // Source image + + int maxx = width; // Source image + int maxy = height; // Source image int mtran = tran & TR_ROT; int skip = pp.skip; // improve speed by integrating the area division into the multipliers // switched to using ints for the red/green/blue channel buffer. // Incidentally this improves accuracy too. - float area=skip*skip; - float rm2=rm; - float gm2=gm; - float bm2=bm; - rm/=area; - gm/=area; - bm/=area; + float area = skip * skip; + float rm2 = rm; + float gm2 = gm; + float bm2 = bm; + rm /= area; + gm /= area; + bm /= area; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel { #endif - AlignedBuffer abR(imwidth); - AlignedBuffer abG(imwidth); - AlignedBuffer abB(imwidth); - float *lineR = abR.data; - float *lineG = abG.data; - float *lineB = abB.data; + AlignedBuffer abR(imwidth); + AlignedBuffer abG(imwidth); + AlignedBuffer abB(imwidth); + float *lineR = abR.data; + float *lineG = abG.data; + float *lineB = abB.data; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int iy=0; iy=maxy) - continue; + for (int iy = 0; iy < imheight; iy++) { + if (skip == 1) { + // special case (speedup for 1:1 scale) + // i: source image, first line of the current destination row + int src_y = sy1 + iy; - for (int dst_x=0,src_x=sx1; dst_x=maxx) + if (src_y >= maxy) { continue; + } - lineR[dst_x] = CLIP(rm2*r(src_y, src_x)); - lineG[dst_x] = CLIP(gm2*g(src_y, src_x)); - lineB[dst_x] = CLIP(bm2*b(src_y, src_x)); - } - } - else { - // source image, first line of the current destination row - int src_y=sy1+skip*iy; - if (src_y>=maxy) - continue; - - for (int dst_x=0,src_x=sx1; dst_x=maxx) - continue; - - int src_sub_width = MIN(maxx-src_x, skip); - int src_sub_height = MIN(maxy-src_y, skip); - - float rtot,gtot,btot; // RGB accumulators - rtot=gtot=btot=0.; - - for (int src_sub_y=0; src_sub_y= maxx) { + continue; } - // convert back to gamma and clip - if (src_sub_width == skip && src_sub_height == skip) { - // Common case where the sub-region is complete - lineR[dst_x] = CLIP(rm*rtot); - lineG[dst_x] = CLIP(gm*gtot); - lineB[dst_x] = CLIP(bm*btot); + + lineR[dst_x] = CLIP(rm2 * r(src_y, src_x)); + lineG[dst_x] = CLIP(gm2 * g(src_y, src_x)); + lineB[dst_x] = CLIP(bm2 * b(src_y, src_x)); } - else { - // computing a special factor for this incomplete sub-region - float area = src_sub_width*src_sub_height; - lineR[dst_x] = CLIP(rm2*rtot/area); - lineG[dst_x] = CLIP(gm2*gtot/area); - lineB[dst_x] = CLIP(bm2*btot/area); + } else { + // source image, first line of the current destination row + int src_y = sy1 + skip * iy; + + if (src_y >= maxy) { + continue; + } + + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + if (src_x >= maxx) { + continue; + } + + int src_sub_width = MIN(maxx - src_x, skip); + int src_sub_height = MIN(maxy - src_y, skip); + + float rtot, gtot, btot; // RGB accumulators + rtot = gtot = btot = 0.; + + for (int src_sub_y = 0; src_sub_y < src_sub_height; src_sub_y++) + for (int src_sub_x = 0; src_sub_x < src_sub_width; src_sub_x++) { + rtot += r(src_y + src_sub_y, src_x + src_sub_x); + gtot += g(src_y + src_sub_y, src_x + src_sub_x); + btot += b(src_y + src_sub_y, src_x + src_sub_x); + } + + // convert back to gamma and clip + if (src_sub_width == skip && src_sub_height == skip) { + // Common case where the sub-region is complete + lineR[dst_x] = CLIP(rm * rtot); + lineG[dst_x] = CLIP(gm * gtot); + lineB[dst_x] = CLIP(bm * btot); + } else { + // computing a special factor for this incomplete sub-region + float area = src_sub_width * src_sub_height; + lineR[dst_x] = CLIP(rm2 * rtot / area); + lineG[dst_x] = CLIP(gm2 * gtot / area); + lineB[dst_x] = CLIP(bm2 * btot / area); + } } } + + if (mtran == TR_NONE) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(iy, dst_x) = lineR[dst_x]; + image->g(iy, dst_x) = lineG[dst_x]; + image->b(iy, dst_x) = lineB[dst_x]; + } + else if (mtran == TR_R180) + for (int dst_x = 0; dst_x < imwidth; dst_x++) { + image->r(imheight - 1 - iy, imwidth - 1 - dst_x) = lineR[dst_x]; + image->g(imheight - 1 - iy, imwidth - 1 - dst_x) = lineG[dst_x]; + image->b(imheight - 1 - iy, imwidth - 1 - dst_x) = lineB[dst_x]; + } + else if (mtran == TR_R90) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(dst_x, imheight - 1 - iy) = lineR[dst_x]; + image->g(dst_x, imheight - 1 - iy) = lineG[dst_x]; + image->b(dst_x, imheight - 1 - iy) = lineB[dst_x]; + } + else if (mtran == TR_R270) + for (int dst_x = 0, src_x = sx1; dst_x < imwidth; dst_x++, src_x += skip) { + image->r(imwidth - 1 - dst_x, iy) = lineR[dst_x]; + image->g(imwidth - 1 - dst_x, iy) = lineG[dst_x]; + image->b(imwidth - 1 - dst_x, iy) = lineB[dst_x]; + } } - if (mtran == TR_NONE) - for (int dst_x=0,src_x=sx1; dst_xr(iy, dst_x) = lineR[dst_x]; - image->g(iy, dst_x) = lineG[dst_x]; - image->b(iy, dst_x) = lineB[dst_x]; - } - else if (mtran == TR_R180) - for (int dst_x=0; dst_xr(imheight-1-iy, imwidth-1-dst_x) = lineR[dst_x]; - image->g(imheight-1-iy, imwidth-1-dst_x) = lineG[dst_x]; - image->b(imheight-1-iy, imwidth-1-dst_x) = lineB[dst_x]; - } - else if (mtran == TR_R90) - for (int dst_x=0,src_x=sx1; dst_xr(dst_x, imheight-1-iy) = lineR[dst_x]; - image->g(dst_x, imheight-1-iy) = lineG[dst_x]; - image->b(dst_x, imheight-1-iy) = lineB[dst_x]; - } - else if (mtran == TR_R270) - for (int dst_x=0,src_x=sx1; dst_xr(imwidth-1-dst_x, iy) = lineR[dst_x]; - image->g(imwidth-1-dst_x, iy) = lineG[dst_x]; - image->b(imwidth-1-dst_x, iy) = lineB[dst_x]; - } - } #ifdef _OPENMP -} + } #endif } -Image8* +Image8* Imagefloat::to8() { - Image8* img8 = new Image8(width,height); + Image8* img8 = new Image8(width, height); #ifdef _OPENMP -#pragma omp parallel for schedule(static) + #pragma omp parallel for schedule(static) #endif - for ( int h=0; h < height; ++h ) - { - for ( int w=0; w < width; ++w ) - { - img8->r(h, w) = (unsigned char)( (unsigned short)(r(h,w)) >> 8); - img8->g(h, w) = (unsigned char)( (unsigned short)(g(h,w)) >> 8); - img8->b(h, w) = (unsigned char)( (unsigned short)(b(h,w)) >> 8); + + for ( int h = 0; h < height; ++h ) { + for ( int w = 0; w < width; ++w ) { + img8->r(h, w) = (unsigned char)( (unsigned short)(r(h, w)) >> 8); + img8->g(h, w) = (unsigned char)( (unsigned short)(g(h, w)) >> 8); + img8->b(h, w) = (unsigned char)( (unsigned short)(b(h, w)) >> 8); } } + return img8; } -Image16* +Image16* Imagefloat::to16() { - Image16* img16 = new Image16(width,height); + Image16* img16 = new Image16(width, height); #ifdef _OPENMP -#pragma omp parallel for schedule(static) + #pragma omp parallel for schedule(static) #endif - for ( int h=0; h < height; ++h ) - { - for ( int w=0; w < width; ++w ) - { - img16->r( h,w) = (unsigned short)(r(h,w)); - img16->g( h,w) = (unsigned short)(g(h,w)); - img16->b( h,w) = (unsigned short)(b(h,w)); + + for ( int h = 0; h < height; ++h ) { + for ( int w = 0; w < width; ++w ) { + img16->r( h, w) = (unsigned short)(r(h, w)); + img16->g( h, w) = (unsigned short)(g(h, w)); + img16->b( h, w) = (unsigned short)(b(h, w)); } } + return img16; } -void Imagefloat::normalizeFloat(float srcMinVal, float srcMaxVal) { +void Imagefloat::normalizeFloat(float srcMinVal, float srcMaxVal) +{ - float scale = MAXVALD / (srcMaxVal-srcMinVal); + float scale = MAXVALD / (srcMaxVal - srcMinVal); int w = width; int h = height; #ifdef _OPENMP -#pragma omp parallel for firstprivate(w, h, srcMinVal, scale) schedule(dynamic, 5) + #pragma omp parallel for firstprivate(w, h, srcMinVal, scale) schedule(dynamic, 5) #endif - for (int y=0; y65535) - i=65535; - histThr[i]++; + #pragma omp parallel + { + LUTu histThr(65536); + histThr.clear(); + #pragma omp for nowait + + for (int y = y1; y < y2; y++) { + int i; + + for (int x = x1; x < x2; x++) { + i = (int)(facRed * r(y, x) + facGreen * g(y, x) + facBlue * b(y, x)); + + if (i < 0) { + i = 0; + } else if (i > 65535) { + i = 65535; + } + + histThr[i]++; + } + } + + #pragma omp critical + { + for(int i = 0; i <= 0xffff; i++) { + hist[i] += histThr[i]; + } } } -#pragma omp critical -{ - for(int i=0;i<=0xffff;i++) - hist[i] += histThr[i]; -} -} } // Parallelized transformation; create transform with cmsFLAGS_NOCACHE! -void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform) { +void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform) +{ // LittleCMS cannot parallelize planar setups -- Hombre: LCMS2.4 can! But it we use this new feature, memory allocation - // have to be modified too to build temporary buffers that allow multi processor execution + // have to be modified too to build temporary buffers that allow multi processor execution #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - AlignedBuffer pBuf(width*3); + { + AlignedBuffer pBuf(width * 3); #ifdef _OPENMP -#pragma omp for schedule(static) + #pragma omp for schedule(static) #endif - for (int y=0; yclone (NULL); @@ -62,12 +66,13 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot) { td->keepTag(0x83bb); // IPTC td->keepTag(0x02bc); // XMP - exifRoot=td; + exifRoot = td; } } // For merging with RT specific data -void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc) { +void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc) +{ // store exif info exifChange.clear(); @@ -79,21 +84,30 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr j++; }*/ - if (exifRoot!=NULL) { delete exifRoot; exifRoot = NULL; } - - if (eroot) - exifRoot = ((rtexif::TagDirectory*)eroot)->clone (NULL); + if (exifRoot != NULL) { + delete exifRoot; + exifRoot = NULL; + } + + if (eroot) { + exifRoot = ((rtexif::TagDirectory*)eroot)->clone (NULL); + } + + if (iptc != NULL) { + iptc_data_free (iptc); + iptc = NULL; + } - if (iptc!=NULL) { iptc_data_free (iptc); iptc = NULL; } - // build iptc structures for libiptcdata - if (iptcc.empty()) + if (iptcc.empty()) { return; + } iptc = iptc_data_new (); - for (rtengine::procparams::IPTCPairs::const_iterator i=iptcc.begin(); i!=iptcc.end(); i++) { + + for (rtengine::procparams::IPTCPairs::const_iterator i = iptcc.begin(); i != iptcc.end(); i++) { if (i->first == "Keywords" && !(i->second.empty())) { - for (unsigned int j=0; jsecond.size(); j++) { + 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)); @@ -101,10 +115,10 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } + continue; - } - else if (i->first == "SupplementalCategories" && !(i->second.empty())) { - for (unsigned int j=0; jsecond.size(); j++) { + } else if (i->first == "SupplementalCategories" && !(i->second.empty())) { + 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)); @@ -112,9 +126,11 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } + continue; } - for (int j=0; j<16; j++) + + for (int j = 0; j < 16; j++) 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); @@ -124,26 +140,33 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr iptc_dataset_unref (ds); } } + iptc_data_sort (iptc); } -void ImageIO::setOutputProfile (char* pdata, int plen) { +void ImageIO::setOutputProfile (char* pdata, int plen) +{ delete [] profileData; + if (pdata) { profileData = new char [plen]; memcpy (profileData, pdata, plen); - } - else + } else { profileData = NULL; + } + profileLength = plen; } -ImageIO::~ImageIO () { +ImageIO::~ImageIO () +{ - if (embProfile) + if (embProfile) { cmsCloseProfile(embProfile); - deleteLoadedProfileData(); + } + + deleteLoadedProfileData(); delete exifRoot; delete [] profileData; } @@ -152,26 +175,34 @@ void png_read_data(png_struct_def *png_ptr, unsigned char *data, size_t length) void png_write_data(png_struct_def *png_ptr, unsigned char *data, size_t length); 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"); - if (!file) - return IMIO_CANNOTREADFILE; +int ImageIO::getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) +{ + FILE *file = safe_g_fopen (fname, "rb"); + + if (!file) { + return IMIO_CANNOTREADFILE; + } //reading PNG header unsigned char header[8]; fread (header, 1, 8, file); + if (png_sig_cmp (header, 0, 8)) { fclose(file); return IMIO_HEADERERROR; } + //initializing main structures png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png) { fclose (file); return IMIO_HEADERERROR; } + png_infop info = png_create_info_struct (png); png_infop end_info = png_create_info_struct (png); + if (!end_info || !info) { png_destroy_read_struct (&png, &info, &end_info); fclose (file); @@ -186,64 +217,71 @@ int ImageIO::getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, //set up png read png_set_read_fn (png, file, png_read_data); - png_set_sig_bytes (png,8); + png_set_sig_bytes (png, 8); - png_read_info(png,info); + png_read_info(png, info); //retrieving image information - png_uint_32 width,height; - int bit_depth,color_type,interlace_type,compression_type,filter_method; - png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type,&compression_type, &filter_method); + png_uint_32 width, height; + int bit_depth, color_type, interlace_type, compression_type, filter_method; + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); png_destroy_read_struct (&png, &info, &end_info); fclose (file); - if (interlace_type!=PNG_INTERLACE_NONE) + if (interlace_type != PNG_INTERLACE_NONE) { return IMIO_VARIANTNOTSUPPORTED; + } if (bit_depth == 8) { sArrangement = IIOSA_CHUNKY; sFormat = IIOSF_UNSIGNED_CHAR; return IMIO_SUCCESS; - } - else if (bit_depth == 16) { + } else if (bit_depth == 16) { sArrangement = IIOSA_CHUNKY; sFormat = IIOSF_UNSIGNED_SHORT; return IMIO_SUCCESS; - } - else { + } else { sArrangement = IIOSA_UNKNOWN; sFormat = IIOSF_UNKNOWN; return IMIO_VARIANTNOTSUPPORTED; } } -int ImageIO::loadPNG (Glib::ustring fname) { +int ImageIO::loadPNG (Glib::ustring fname) +{ - FILE *file = safe_g_fopen (fname,"rb"); - if (!file) - return IMIO_CANNOTREADFILE; + FILE *file = safe_g_fopen (fname, "rb"); + + if (!file) { + return IMIO_CANNOTREADFILE; + } if (pl) { - pl->setProgressStr ("PROGRESSBAR_LOADPNG"); - pl->setProgress (0.0); + pl->setProgressStr ("PROGRESSBAR_LOADPNG"); + pl->setProgress (0.0); } //reading PNG header unsigned char header[8]; fread (header, 1, 8, file); + if (png_sig_cmp (header, 0, 8)) { fclose(file); return IMIO_HEADERERROR; } + //initializing main structures png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png) { fclose (file); return IMIO_HEADERERROR; } + png_infop info = png_create_info_struct (png); png_infop end_info = png_create_info_struct (png); + if (!end_info || !info) { png_destroy_read_struct (&png, &info, &end_info); fclose (file); @@ -258,53 +296,58 @@ int ImageIO::loadPNG (Glib::ustring fname) { //set up png read png_set_read_fn (png, file, png_read_data); - png_set_sig_bytes (png,8); + png_set_sig_bytes (png, 8); - png_read_info(png,info); + png_read_info(png, info); embProfile = NULL; //retrieving image information - png_uint_32 width,height; - int bit_depth,color_type,interlace_type,compression_type,filter_method; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); - if (color_type==PNG_COLOR_TYPE_PALETTE || interlace_type!=PNG_INTERLACE_NONE ) { - // we don't support interlaced png or png with palette + if (color_type == PNG_COLOR_TYPE_PALETTE || interlace_type != PNG_INTERLACE_NONE ) { + // we don't support interlaced png or png with palette png_destroy_read_struct (&png, &info, &end_info); fclose (file); - printf("%s uses an unsupported feature: . Skipping.\n",fname.data()); + printf("%s uses an unsupported feature: . Skipping.\n", fname.data()); return IMIO_VARIANTNOTSUPPORTED; } - if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png); + } - if (png_get_valid(png,info,PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png); + if (png_get_valid(png, info, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png); + } - if (color_type & PNG_COLOR_MASK_ALPHA) + if (color_type & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(png); + } - //setting gamma - double gamma; - if (png_get_gAMA(png,info,&gamma)) - png_set_gamma(png, 1.0/gamma, gamma); // use gamma from metadata - else - png_set_gamma(png, 2.2, 1.0/2.2); // no gamma in metadata, suppose gamma 2.2 + //setting gamma + double gamma; -// if (bps==8 && bit_depth==16) png_set_strip_16(png); + if (png_get_gAMA(png, info, &gamma)) { + png_set_gamma(png, 1.0 / gamma, gamma); // use gamma from metadata + } else { + png_set_gamma(png, 2.2, 1.0 / 2.2); // no gamma in metadata, suppose gamma 2.2 + } + +// if (bps==8 && bit_depth==16) png_set_strip_16(png); //updating png info struct - png_read_update_info(png,info); - png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type,&compression_type, &filter_method); + png_read_update_info(png, info); + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); allocate (width, height); - int rowlen = width*3*bit_depth/8; + int rowlen = width * 3 * bit_depth / 8; unsigned char *row = new unsigned char [rowlen]; - // set a new jump point to avoid memory leak + // set a new jump point to avoid memory leak if (setjmp (png_jmpbuf(png))) { png_destroy_read_struct (&png, &info, &end_info); fclose (file); @@ -312,18 +355,23 @@ int ImageIO::loadPNG (Glib::ustring fname) { return IMIO_READERROR; } - for (unsigned int i=0;isetProgress ((double)(i+1)/height); + if (pl && !(i % 100)) { + pl->setProgress ((double)(i + 1) / height); + } } png_read_end (png, 0); @@ -331,30 +379,33 @@ int ImageIO::loadPNG (Glib::ustring fname) { delete [] row; fclose(file); + if (pl) { pl->setProgressStr ("PROGRESSBAR_READY"); pl->setProgress (1.0); } + return IMIO_SUCCESS; } typedef struct { - struct jpeg_error_mgr pub; /* "public" fields */ - jmp_buf setjmp_buffer; /* for return to caller */ + struct jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ } my_error_mgr; -void my_error_exit (j_common_ptr cinfo) { - /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ - my_error_mgr *myerr = (my_error_mgr*) cinfo->err; - /* Always display the message. */ - /* We could postpone this until after returning, if we chose. */ - (*cinfo->err->output_message) (cinfo); +void my_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + my_error_mgr *myerr = (my_error_mgr*) cinfo->err; + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); - /* Return control to the setjmp point */ + /* Return control to the setjmp point */ #if defined( WIN32 ) && defined( __x86_64__ ) - __builtin_longjmp(myerr->setjmp_buffer, 1); + __builtin_longjmp(myerr->setjmp_buffer, 1); #else - longjmp(myerr->setjmp_buffer, 1); + longjmp(myerr->setjmp_buffer, 1); #endif } @@ -363,29 +414,31 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) { jpeg_decompress_struct cinfo; jpeg_create_decompress(&cinfo); - jpeg_memory_src (&cinfo,(const JOCTET*)buffer,bufsize); + jpeg_memory_src (&cinfo, (const JOCTET*)buffer, bufsize); - /* We use our private extension JPEG error handler. - Note that this struct must live as long as the main JPEG parameter - struct, to avoid dangling-pointer problems. - */ - my_error_mgr jerr; - /* We set up the normal JPEG error routines, then override error_exit. */ - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = my_error_exit; + /* We use our private extension JPEG error handler. + Note that this struct must live as long as the main JPEG parameter + struct, to avoid dangling-pointer problems. + */ + my_error_mgr jerr; + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; - /* Establish the setjmp return context for my_error_exit to use. */ + /* Establish the setjmp return context for my_error_exit to use. */ #if defined( WIN32 ) && defined( __x86_64__ ) - if (__builtin_setjmp(jerr.setjmp_buffer)) { + + if (__builtin_setjmp(jerr.setjmp_buffer)) { #else - if (setjmp(jerr.setjmp_buffer)) { + + if (setjmp(jerr.setjmp_buffer)) { #endif - /* If we get here, the JPEG code has signaled an error. - We need to clean up the JPEG object and return. - */ - jpeg_destroy_decompress(&cinfo); - return IMIO_READERROR; - } + /* If we get here, the JPEG code has signaled an error. + We need to clean up the JPEG object and return. + */ + jpeg_destroy_decompress(&cinfo); + return IMIO_READERROR; + } if (pl) { @@ -401,10 +454,12 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) deleteLoadedProfileData(); loadedProfileDataJpg = true; bool hasprofile = read_icc_profile (&cinfo, (JOCTET**)&loadedProfileData, (unsigned int*)&loadedProfileLength); - if (hasprofile) + + if (hasprofile) { embProfile = cmsOpenProfileFromMem (loadedProfileData, loadedProfileLength); - else + } else { embProfile = NULL; + } jpeg_start_decompress(&cinfo); @@ -413,43 +468,52 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) allocate (width, height); - unsigned char *row=new unsigned char[width*3]; + unsigned char *row = new unsigned char[width * 3]; + while (cinfo.output_scanline < height) { - if (jpeg_read_scanlines(&cinfo,&row,1) < 1) { + if (jpeg_read_scanlines(&cinfo, &row, 1) < 1) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); delete [] row; return IMIO_READERROR; } - setScanline (cinfo.output_scanline-1, row, 8); - if (pl && !(cinfo.output_scanline%100)) - pl->setProgress ((double)(cinfo.output_scanline)/cinfo.output_height); + setScanline (cinfo.output_scanline - 1, row, 8); + + if (pl && !(cinfo.output_scanline % 100)) { + pl->setProgress ((double)(cinfo.output_scanline) / cinfo.output_height); + } } + delete [] row; jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); + if (pl) { pl->setProgressStr ("PROGRESSBAR_READY"); pl->setProgress (1.0); } + return IMIO_SUCCESS; } -int ImageIO::loadJPEG (Glib::ustring fname) { - FILE *file=safe_g_fopen(fname,"rb"); - if (!file) +int ImageIO::loadJPEG (Glib::ustring fname) +{ + FILE *file = safe_g_fopen(fname, "rb"); + + if (!file) { return IMIO_CANNOTREADFILE; + } jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; cinfo.err = my_jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); - my_jpeg_stdio_src (&cinfo,file); - if ( setjmp((reinterpret_cast(cinfo.src))->error_jmp_buf) == 0 ) - { + my_jpeg_stdio_src (&cinfo, file); + + if ( setjmp((reinterpret_cast(cinfo.src))->error_jmp_buf) == 0 ) { if (pl) { pl->setProgressStr ("PROGRESSBAR_LOADJPEG"); pl->setProgress (0.0); @@ -466,13 +530,15 @@ int ImageIO::loadJPEG (Glib::ustring fname) { return IMIO_READERROR; } - deleteLoadedProfileData(); - loadedProfileDataJpg = true; + deleteLoadedProfileData(); + loadedProfileDataJpg = true; bool hasprofile = read_icc_profile (&cinfo, (JOCTET**)&loadedProfileData, (unsigned int*)&loadedProfileLength); - if (hasprofile) + + if (hasprofile) { embProfile = cmsOpenProfileFromMem (loadedProfileData, loadedProfileLength); - else + } else { embProfile = NULL; + } jpeg_start_decompress(&cinfo); @@ -481,37 +547,43 @@ int ImageIO::loadJPEG (Glib::ustring fname) { allocate (width, height); - unsigned char *row=new unsigned char[width*3]; + unsigned char *row = new unsigned char[width * 3]; + while (cinfo.output_scanline < height) { - if (jpeg_read_scanlines(&cinfo,&row,1) < 1) { + if (jpeg_read_scanlines(&cinfo, &row, 1) < 1) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); delete [] row; return IMIO_READERROR; } - setScanline (cinfo.output_scanline-1, row, 8); - if (pl && !(cinfo.output_scanline%100)) - pl->setProgress ((double)(cinfo.output_scanline)/cinfo.output_height); + setScanline (cinfo.output_scanline - 1, row, 8); + + if (pl && !(cinfo.output_scanline % 100)) { + pl->setProgress ((double)(cinfo.output_scanline) / cinfo.output_height); + } } + delete [] row; jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(file); + if (pl) { pl->setProgressStr ("PROGRESSBAR_READY"); pl->setProgress (1.0); } + return IMIO_SUCCESS; - } - else { + } else { jpeg_destroy_decompress(&cinfo); return IMIO_READERROR; } } -int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) { +int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) +{ #ifdef WIN32 wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL); TIFF* in = TIFFOpenW (wfilename, "r"); @@ -519,18 +591,22 @@ int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, #else TIFF* in = TIFFOpen(fname.c_str(), "r"); #endif - if (in == NULL) - return IMIO_CANNOTREADFILE; - uint16 bitspersample=0, samplesperpixel=0, sampleformat=0; + if (in == NULL) { + return IMIO_CANNOTREADFILE; + } + + uint16 bitspersample = 0, samplesperpixel = 0, sampleformat = 0; int hasTag = TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample); hasTag &= TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); + if (!hasTag) { // These are needed TIFFClose(in); sFormat = IIOSF_UNKNOWN; return IMIO_VARIANTNOTSUPPORTED; } + if (!TIFFGetField(in, TIFFTAG_SAMPLEFORMAT, &sampleformat)) /* * WARNING: This is a dirty hack! @@ -538,14 +614,16 @@ int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, * (which is the case with uncompressed TIFFs produced by RT!) are RGB files, * but that may be not true. --- Hombre */ + { sampleformat = SAMPLEFORMAT_UINT; + } uint16 config; TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config); + if (config == PLANARCONFIG_CONTIG) { sArrangement = IIOSA_CHUNKY; - } - else { + } else { sFormat = IIOSF_UNKNOWN; sArrangement = IIOSA_UNKNOWN; TIFFClose(in); @@ -553,30 +631,33 @@ int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, } uint16 photometric; + if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric)) { TIFFClose(in); return IMIO_VARIANTNOTSUPPORTED; } uint16 compression; + if (photometric == PHOTOMETRIC_LOGLUV) - if (!TIFFGetField(in, TIFFTAG_COMPRESSION, &compression)) + if (!TIFFGetField(in, TIFFTAG_COMPRESSION, &compression)) { compression = COMPRESSION_NONE; + } TIFFClose(in); if (photometric == PHOTOMETRIC_RGB) { - if ((samplesperpixel==3 || samplesperpixel==4) && sampleformat==SAMPLEFORMAT_UINT) { - if (bitspersample==8) { + if ((samplesperpixel == 3 || samplesperpixel == 4) && sampleformat == SAMPLEFORMAT_UINT) { + if (bitspersample == 8) { sFormat = IIOSF_UNSIGNED_CHAR; return IMIO_SUCCESS; } - if (bitspersample==16) { + + if (bitspersample == 16) { sFormat = IIOSF_UNSIGNED_SHORT; return IMIO_SUCCESS; } - } - else if (samplesperpixel==3 && sampleformat==SAMPLEFORMAT_IEEEFP) { + } else if (samplesperpixel == 3 && sampleformat == SAMPLEFORMAT_IEEEFP) { /* * Not yet supported * @@ -584,32 +665,34 @@ int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, sFormat = IIOSF_HALF; return IMIO_SUCCESS; }*/ - if ((samplesperpixel==3 || samplesperpixel==4) && bitspersample==32) { + if ((samplesperpixel == 3 || samplesperpixel == 4) && bitspersample == 32) { sFormat = IIOSF_FLOAT; return IMIO_SUCCESS; } } - } - else if (samplesperpixel==3 && photometric == PHOTOMETRIC_LOGLUV) { - if (compression==COMPRESSION_SGILOG24) { + } else if (samplesperpixel == 3 && photometric == PHOTOMETRIC_LOGLUV) { + if (compression == COMPRESSION_SGILOG24) { sFormat = IIOSF_LOGLUV24; return IMIO_SUCCESS; - } - else if (compression==COMPRESSION_SGILOG) { + } else if (compression == COMPRESSION_SGILOG) { sFormat = IIOSF_LOGLUV32; return IMIO_SUCCESS; } } + return IMIO_VARIANTNOTSUPPORTED; } -int ImageIO::loadTIFF (Glib::ustring fname) { +int ImageIO::loadTIFF (Glib::ustring fname) +{ + + static MyMutex thumbMutex; + MyMutex::MyLock lock(thumbMutex); + + if(!options.serializeTiffRead) { + lock.release(); + } - static MyMutex thumbMutex; - MyMutex::MyLock lock(thumbMutex); - if(!options.serializeTiffRead) - lock.release(); - #ifdef WIN32 wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL); TIFF* in = TIFFOpenW (wfilename, "r"); @@ -617,14 +700,16 @@ int ImageIO::loadTIFF (Glib::ustring fname) { #else TIFF* in = TIFFOpen(fname.c_str(), "r"); #endif - if (in == NULL) - return IMIO_CANNOTREADFILE; + + if (in == NULL) { + return IMIO_CANNOTREADFILE; + } if (pl) { pl->setProgressStr ("PROGRESSBAR_LOADTIFF"); pl->setProgress (0.0); } - + int width, height; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); @@ -632,6 +717,7 @@ int ImageIO::loadTIFF (Glib::ustring fname) { uint16 bitspersample, samplesperpixel; int hasTag = TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample); hasTag &= TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); + if (!hasTag) { // These are needed TIFFClose(in); @@ -640,13 +726,15 @@ int ImageIO::loadTIFF (Glib::ustring fname) { uint16 config; TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config); + if (config != PLANARCONFIG_CONTIG) { TIFFClose(in); return IMIO_VARIANTNOTSUPPORTED; } - if (sampleFormat & (IIOSF_LOGLUV24|IIOSF_LOGLUV32)) + if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32)) { TIFFSetField(in, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT); + } /* * We could use the min/max values set in TIFFTAG_SMINSAMPLEVALUE and @@ -687,13 +775,14 @@ int ImageIO::loadTIFF (Glib::ustring fname) { char* profdata; - deleteLoadedProfileData(); - loadedProfileDataJpg = false; + deleteLoadedProfileData(); + loadedProfileDataJpg = false; + if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &loadedProfileLength, &profdata)) { embProfile = cmsOpenProfileFromMem (profdata, loadedProfileLength); // For 32 bits floating point images, gamma is forced to linear in embedded ICC profiles - if ( sampleFormat&(IIOSF_LOGLUV24|IIOSF_LOGLUV32|IIOSF_FLOAT) ) { + if ( sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT) ) { // Modifying the gammaTRG tags cmsWriteTag(embProfile, cmsSigGreenTRCTag, (void*)Color::linearGammaTRC ); cmsWriteTag(embProfile, cmsSigRedTRCTag, (void*)Color::linearGammaTRC ); @@ -702,63 +791,73 @@ int ImageIO::loadTIFF (Glib::ustring fname) { // Saving the profile in the memory cmsUInt32Number bytesNeeded = 0; cmsSaveProfileToMem(embProfile, 0, &bytesNeeded); + if (bytesNeeded > 0) { - loadedProfileData = new char[bytesNeeded+1]; - cmsSaveProfileToMem(embProfile, loadedProfileData, &bytesNeeded); + loadedProfileData = new char[bytesNeeded + 1]; + cmsSaveProfileToMem(embProfile, loadedProfileData, &bytesNeeded); } + loadedProfileLength = (int)bytesNeeded; - } - else { + } else { // Saving the profile in the memory as is loadedProfileData = new char [loadedProfileLength]; memcpy (loadedProfileData, profdata, loadedProfileLength); } - } - else + } else { embProfile = NULL; + } allocate (width, height); - float minValue[3]={0.f, 0.f, 0.f}, maxValue[3]={0.f, 0.f, 0.f}; + float minValue[3] = {0.f, 0.f, 0.f}, maxValue[3] = {0.f, 0.f, 0.f}; unsigned char* linebuffer = new unsigned char[TIFFScanlineSize(in)]; + for (int row = 0; row < height; row++) { - if (TIFFReadScanline(in, linebuffer, row, 0) <0) { - TIFFClose(in); - delete [] linebuffer; - return IMIO_READERROR; + if (TIFFReadScanline(in, linebuffer, row, 0) < 0) { + TIFFClose(in); + delete [] linebuffer; + return IMIO_READERROR; } - if (samplesperpixel>3) - for (int i=0; i 3) + for (int i = 0; i < width; i++) { + memcpy (linebuffer + i * 3 * bitspersample / 8, linebuffer + i * samplesperpixel * bitspersample / 8, 3 * bitspersample / 8); + } + + if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT)) { setScanline (row, linebuffer, bitspersample, minValue, maxValue); - else + } else { setScanline (row, linebuffer, bitspersample, NULL, NULL); + } - if (pl && !(row%100)) - pl->setProgress ((double)(row+1)/height); + if (pl && !(row % 100)) { + pl->setProgress ((double)(row + 1) / height); + } } - if (sampleFormat & (IIOSF_FLOAT|IIOSF_LOGLUV24|IIOSF_LOGLUV32)) { + + if (sampleFormat & (IIOSF_FLOAT | IIOSF_LOGLUV24 | IIOSF_LOGLUV32)) { #ifdef _DEBUG + if (options.rtSettings.verbose) printf("Normalizing \"%s\" image \"%s\" whose mini/maxi values are:\n Red: minimum value=%0.5f / maximum value=%0.5f\n Green: minimum value=%0.5f / maximum value=%0.5f\n Blue: minimum value=%0.5f / maximum value=%0.5f\n", getType(), fname.c_str(), minValue[0], maxValue[0], minValue[1], maxValue[1], minValue[2], maxValue[2] ); + #endif - float minVal = min( min( minValue[0],minValue[1] ),minValue[2] ); - float maxVal = max( max( maxValue[0],maxValue[1] ),maxValue[2] ); + float minVal = min( min( minValue[0], minValue[1] ), minValue[2] ); + float maxVal = max( max( maxValue[0], maxValue[1] ), maxValue[2] ); normalizeFloat(minVal, maxVal); } + TIFFClose(in); delete [] linebuffer; if (pl) { - pl->setProgressStr ("PROGRESSBAR_READY"); - pl->setProgress (1.0); + pl->setProgressStr ("PROGRESSBAR_READY"); + pl->setProgress (1.0); } return IMIO_SUCCESS; @@ -768,95 +867,103 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s { allocate (width, height); - int line_length(width * 3 * (bps/8)); + int line_length(width * 3 * (bps / 8)); - if ( swap && bps > 8 ) - { + if ( swap && bps > 8 ) { char swapped[line_length]; - for ( int row = 0; row < height; ++row ) - { - ::swab(((char*)buffer) + (row * line_length),swapped,line_length); - setScanline(row,(unsigned char*)&swapped[0],bps); + + for ( int row = 0; row < height; ++row ) { + ::swab(((char*)buffer) + (row * line_length), swapped, line_length); + setScanline(row, (unsigned char*)&swapped[0], bps); } - } - else - { - for ( int row = 0; row < height; ++row ) - { - setScanline(row,((unsigned char*)buffer) + (row * line_length),bps); + } else { + for ( int row = 0; row < height; ++row ) { + setScanline(row, ((unsigned char*)buffer) + (row * line_length), bps); } } return IMIO_SUCCESS; } -int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) { +int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) +{ FILE *file = safe_g_fopen_WriteBinLock (fname); - if (!file) - return IMIO_CANNOTWRITEFILE; - - if (pl) { - pl->setProgressStr ("PROGRESSBAR_SAVEPNG"); - pl->setProgress (0.0); + if (!file) { + return IMIO_CANNOTWRITEFILE; } - png_structp png = png_create_write_struct (PNG_LIBPNG_VER_STRING,0,0,0); + if (pl) { + pl->setProgressStr ("PROGRESSBAR_SAVEPNG"); + pl->setProgress (0.0); + } + + png_structp png = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png) { fclose (file); return IMIO_HEADERERROR; } + png_infop info = png_create_info_struct(png); + if (!info) { - png_destroy_write_struct (&png,0); + png_destroy_write_struct (&png, 0); fclose (file); return IMIO_HEADERERROR; } if (setjmp(png_jmpbuf(png))) { - png_destroy_write_struct (&png,&info); + png_destroy_write_struct (&png, &info); fclose(file); return IMIO_CANNOTWRITEFILE; } png_set_write_fn (png, file, png_write_data, png_flush); - png_set_compression_level(png,compression); + png_set_compression_level(png, compression); int width = getW (); int height = getH (); - if (bps<0) + + if (bps < 0) { bps = getBPS (); - - png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_BASE); - - - int rowlen = width*3*bps/8; - unsigned char *row = new unsigned char [rowlen]; - - png_write_info(png,info); - for (int i=0;isetProgress ((double)(i+1)/height); } - png_write_end(png,info); - png_destroy_write_struct(&png,&info); + png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE); + + + int rowlen = width * 3 * bps / 8; + unsigned char *row = new unsigned char [rowlen]; + + png_write_info(png, info); + + for (int i = 0; i < height; i++) { + getScanline (i, row, bps); + + if (bps == 16) { + // convert to network byte order +#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ + for (int j = 0; j < width * 6; j += 2) { + unsigned char tmp = row[j]; + row[j] = row[j + 1]; + row[j + 1] = tmp; + } + +#endif + } + + png_write_row (png, (png_byte*)row); + + if (pl && !(i % 100)) { + pl->setProgress ((double)(i + 1) / height); + } + } + + png_write_end(png, info); + png_destroy_write_struct(&png, &info); delete [] row; fclose (file); @@ -872,36 +979,41 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) { // Quality 0..100, subsampling: 1=low quality, 2=medium, 3=high -int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { +int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) +{ FILE *file = safe_g_fopen_WriteBinLock (fname); - if (!file) - return IMIO_CANNOTWRITEFILE; + + if (!file) { + return IMIO_CANNOTWRITEFILE; + } jpeg_compress_struct cinfo; - /* We use our private extension JPEG error handler. - Note that this struct must live as long as the main JPEG parameter - struct, to avoid dangling-pointer problems. - */ - my_error_mgr jerr; - /* We set up the normal JPEG error routines, then override error_exit. */ - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = my_error_exit; + /* We use our private extension JPEG error handler. + Note that this struct must live as long as the main JPEG parameter + struct, to avoid dangling-pointer problems. + */ + my_error_mgr jerr; + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; - /* Establish the setjmp return context for my_error_exit to use. */ + /* Establish the setjmp return context for my_error_exit to use. */ #if defined( WIN32 ) && defined( __x86_64__ ) - if (__builtin_setjmp(jerr.setjmp_buffer)) { + + if (__builtin_setjmp(jerr.setjmp_buffer)) { #else - if (setjmp(jerr.setjmp_buffer)) { + + if (setjmp(jerr.setjmp_buffer)) { #endif - /* If we get here, the JPEG code has signaled an error. - We need to clean up the JPEG object, close the file, remove the already saved part of the file and return. - */ - jpeg_destroy_compress(&cinfo); - fclose(file); - safe_g_remove(fname); - return IMIO_CANNOTWRITEFILE; - } + /* If we get here, the JPEG code has signaled an error. + We need to clean up the JPEG object, close the file, remove the already saved part of the file and return. + */ + jpeg_destroy_compress(&cinfo); + fclose(file); + safe_g_remove(fname); + return IMIO_CANNOTWRITEFILE; + } jpeg_create_compress (&cinfo); @@ -931,21 +1043,23 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { // (machine dependency is not really an issue, since we all run on x86 and having exactly the same file is not a requirement) cinfo.dct_method = JDCT_FLOAT; - if (quality>=0 && quality<=100) + if (quality >= 0 && quality <= 100) { jpeg_set_quality (&cinfo, quality, true); + } - cinfo.comp_info[1].h_samp_factor=cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor=cinfo.comp_info[2].v_samp_factor = 1; + cinfo.comp_info[1].h_samp_factor = cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = cinfo.comp_info[2].v_samp_factor = 1; - if (subSamp==1) { + if (subSamp == 1) { // Best compression, default of the JPEG library: 2x2, 1x1, 1x1 (4:1:1) - cinfo.comp_info[0].h_samp_factor=cinfo.comp_info[0].v_samp_factor = 2; - } else if (subSamp==2) { + cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 2; + } else if (subSamp == 2) { // Widely used normal ratio 2x1, 1x1, 1x1 (4:2:2) - cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; - } else if (subSamp==3) { + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 1; + } else if (subSamp == 3) { // Best quality 1x1 1x1 1x1 (4:4:4) - cinfo.comp_info[0].h_samp_factor=cinfo.comp_info[0].v_samp_factor = 1; + cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 1; } jpeg_start_compress(&cinfo, TRUE); @@ -953,69 +1067,88 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { // buffer for exif and iptc markers unsigned char* buffer = new unsigned char[165535]; //FIXME: no buffer size check so it can be overflowed in createJPEGMarker() for large tags, and then software will crash unsigned int size; + // assemble and write exif marker - if (exifRoot) { + if (exifRoot) { int size = rtexif::ExifManager::createJPEGMarker (exifRoot, exifChange, cinfo.image_width, cinfo.image_height, buffer); - if (size>0 && size<65530) - jpeg_write_marker(&cinfo, JPEG_APP0+1, buffer, size); + + if (size > 0 && size < 65530) { + jpeg_write_marker(&cinfo, JPEG_APP0 + 1, buffer, size); + } } + // assemble and write iptc marker if (iptc) { unsigned char* iptcdata; bool error = false; + if (iptc_data_save (iptc, &iptcdata, &size)) { - if (iptcdata) + if (iptcdata) { iptc_data_free_buf (iptc, iptcdata); + } + error = true; } + int bytes = 0; + if (!error && (bytes = iptc_jpeg_ps3_save_iptc (NULL, 0, iptcdata, size, buffer, 65532)) < 0) { - if (iptcdata) + if (iptcdata) { iptc_data_free_buf (iptc, iptcdata); + } + error = true; } - if (!error) - jpeg_write_marker(&cinfo, JPEG_APP0+13, buffer, bytes); + + if (!error) { + jpeg_write_marker(&cinfo, JPEG_APP0 + 13, buffer, bytes); + } } - delete [] buffer; + + delete [] buffer; // write icc profile to the output - if (profileData) + if (profileData) { write_icc_profile (&cinfo, (JOCTET*)profileData, profileLength); + } // write image data - int rowlen = width*3; + int rowlen = width * 3; unsigned char *row = new unsigned char [rowlen]; - /* To avoid memory leaks we establish a new setjmp return context for my_error_exit to use. */ + /* To avoid memory leaks we establish a new setjmp return context for my_error_exit to use. */ #if defined( WIN32 ) && defined( __x86_64__ ) - if (__builtin_setjmp(jerr.setjmp_buffer)) { + + if (__builtin_setjmp(jerr.setjmp_buffer)) { #else - if (setjmp(jerr.setjmp_buffer)) { + + if (setjmp(jerr.setjmp_buffer)) { #endif - /* If we get here, the JPEG code has signaled an error. - We need to clean up the JPEG object, close the file, remove the already saved part of the file and return. - */ - delete [] row; - jpeg_destroy_compress(&cinfo); - fclose(file); - safe_g_remove(fname); - return IMIO_CANNOTWRITEFILE; - } + /* If we get here, the JPEG code has signaled an error. + We need to clean up the JPEG object, close the file, remove the already saved part of the file and return. + */ + delete [] row; + jpeg_destroy_compress(&cinfo); + fclose(file); + safe_g_remove(fname); + return IMIO_CANNOTWRITEFILE; + } while (cinfo.next_scanline < cinfo.image_height) { getScanline (cinfo.next_scanline, row, 8); + if (jpeg_write_scanlines (&cinfo, &row, 1) < 1) { jpeg_destroy_compress (&cinfo); delete [] row; fclose (file); - safe_g_remove(fname); + safe_g_remove(fname); return IMIO_CANNOTWRITEFILE; } - if (pl && !(cinfo.next_scanline%100)) - pl->setProgress ((double)(cinfo.next_scanline)/cinfo.image_height); + if (pl && !(cinfo.next_scanline % 100)) { + pl->setProgress ((double)(cinfo.next_scanline) / cinfo.image_height); + } } jpeg_finish_compress (&cinfo); @@ -1024,6 +1157,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { delete [] row; fclose (file); + if (pl) { pl->setProgressStr ("PROGRESSBAR_READY"); pl->setProgress (1.0); @@ -1032,18 +1166,21 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { return IMIO_SUCCESS; } -int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) { +int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) +{ - //TODO: Handling 32 bits floating point output images! - bool writeOk = true; + //TODO: Handling 32 bits floating point output images! + bool writeOk = true; int width = getW (); int height = getH (); - if (bps<0) + if (bps < 0) { bps = getBPS (); + } - int lineWidth = width*3*bps/8; + int lineWidth = width * 3 * bps / 8; unsigned char* linebuffer = new unsigned char[lineWidth]; + // 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); @@ -1052,65 +1189,77 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) { delete [] linebuffer; return IMIO_CANNOTWRITEFILE; } - + if (pl) { pl->setProgressStr ("PROGRESSBAR_SAVETIFF"); pl->setProgress (0.0); } // buffer for the exif and iptc - unsigned char* buffer = new unsigned char[165535]; //TODO: Is it really 165535... or 65535 ? + unsigned char* buffer = new unsigned char[165535]; //TODO: Is it really 165535... or 65535 ? unsigned char* iptcdata = NULL; unsigned int iptclen = 0; + if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) { iptc_data_free_buf (iptc, iptcdata); iptcdata = NULL; } + int size = rtexif::ExifManager::createTIFFHeader (exifRoot, exifChange, width, height, bps, profileData, profileLength, (char*)iptcdata, iptclen, buffer); - if (iptcdata) + + if (iptcdata) { iptc_data_free_buf (iptc, iptcdata); + } // The maximum lenght is strangely not the same than for the JPEG file... // Which maximum length is the good one ? - if (size>0 && size<165530) + if (size > 0 && size < 165530) { fwrite (buffer, size, 1, file); + } #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ - bool needsReverse = bps==16 && exifRoot->getOrder()==rtexif::MOTOROLA; + bool needsReverse = bps == 16 && exifRoot->getOrder() == rtexif::MOTOROLA; #else - bool needsReverse = bps==16 && exifRoot->getOrder()==rtexif::INTEL; + bool needsReverse = bps == 16 && exifRoot->getOrder() == rtexif::INTEL; #endif - for (int i=0; isetProgress ((double)(i+1)/height); + + if (pl && !(i % 100)) { + pl->setProgress ((double)(i + 1) / height); + } } + delete [] buffer; - if (ferror(file)) - writeOk = false; + + if (ferror(file)) { + writeOk = false; + } fclose (file); - } - else { + } else { // little hack to get libTiff to use proper byte order (see TIFFClienOpen()): - const char *mode = !exifRoot ? "w" : (exifRoot->getOrder()==rtexif::INTEL ? "wl":"wb"); - #ifdef WIN32 + const char *mode = !exifRoot ? "w" : (exifRoot->getOrder() == rtexif::INTEL ? "wl" : "wb"); +#ifdef WIN32 wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL); TIFF* out = TIFFOpenW (wfilename, mode); g_free (wfilename); - #else +#else TIFF* out = TIFFOpen(fname.c_str(), mode); - #endif - if (!out) { - delete [] linebuffer; +#endif + + if (!out) { + delete [] linebuffer; return IMIO_CANNOTWRITEFILE; } @@ -1118,38 +1267,49 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) { pl->setProgressStr ("PROGRESSBAR_SAVETIFF"); pl->setProgress (0.0); } - - if (exifRoot){ + + if (exifRoot) { rtexif::Tag *tag = exifRoot->getTag (TIFFTAG_EXIFIFD); - if (tag && tag->isDirectory()){ + + if (tag && tag->isDirectory()) { rtexif::TagDirectory *exif = tag->getDirectory(); - if (exif) { + + if (exif) { int exif_size = exif->calculateSize(); - unsigned char *buffer = new unsigned char[exif_size+8]; + unsigned char *buffer = new unsigned char[exif_size + 8]; // TIFFOpen writes out the header and sets file pointer at position 8 exif->write (8, buffer); - write (TIFFFileno (out), buffer+8, exif_size); + write (TIFFFileno (out), buffer + 8, exif_size); delete [] buffer; // let libtiff know that scanlines or any other following stuff should go // at a different offset: - TIFFSetWriteOffset (out, exif_size+8); + TIFFSetWriteOffset (out, exif_size + 8); TIFFSetField (out, TIFFTAG_EXIFIFD, 8); } } //TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed. - if ((tag = exifRoot->getTag (TIFFTAG_MODEL)) != NULL) + if ((tag = exifRoot->getTag (TIFFTAG_MODEL)) != NULL) { TIFFSetField (out, TIFFTAG_MODEL, tag->getValue()); - if ((tag = exifRoot->getTag (TIFFTAG_MAKE)) != NULL) + } + + if ((tag = exifRoot->getTag (TIFFTAG_MAKE)) != NULL) { TIFFSetField (out, TIFFTAG_MAKE, tag->getValue()); - if ((tag = exifRoot->getTag (TIFFTAG_DATETIME)) != NULL) + } + + if ((tag = exifRoot->getTag (TIFFTAG_DATETIME)) != NULL) { TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue()); - if ((tag = exifRoot->getTag (TIFFTAG_ARTIST)) != NULL) + } + + if ((tag = exifRoot->getTag (TIFFTAG_ARTIST)) != NULL) { TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue()); - if ((tag = exifRoot->getTag (TIFFTAG_COPYRIGHT)) != NULL) + } + + if ((tag = exifRoot->getTag (TIFFTAG_COPYRIGHT)) != NULL) { TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue()); + } } @@ -1166,11 +1326,14 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) { TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_DEFLATE); - if (!uncompressed) - TIFFSetField (out, TIFFTAG_PREDICTOR, PREDICTOR_NONE); - if (profileData) + if (!uncompressed) { + TIFFSetField (out, TIFFTAG_PREDICTOR, PREDICTOR_NONE); + } + + if (profileData) { TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData); + } for (int row = 0; row < height; row++) { getScanline (row, linebuffer, bps); @@ -1180,90 +1343,111 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) { delete [] linebuffer; return IMIO_CANNOTWRITEFILE; } - if (pl && !(row%100)) - pl->setProgress ((double)(row+1)/height); + + if (pl && !(row % 100)) { + pl->setProgress ((double)(row + 1) / height); + } + } + + if (TIFFFlush(out) != 1) { + writeOk = false; } - if (TIFFFlush(out)!=1) - writeOk = false; TIFFClose (out); } delete [] linebuffer; + if (pl) { pl->setProgressStr ("PROGRESSBAR_READY"); pl->setProgress (1.0); } - if(writeOk) - return IMIO_SUCCESS; - else { - safe_g_remove(fname); - return IMIO_CANNOTWRITEFILE; - } + if(writeOk) { + return IMIO_SUCCESS; + } else { + safe_g_remove(fname); + return IMIO_CANNOTWRITEFILE; + } } // PNG read and write routines: -void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { - png_size_t check; +void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - check = (png_size_t)fread(data, (png_size_t)1, length, (FILE *)png_get_io_ptr(png_ptr)); + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = (png_size_t)fread(data, (png_size_t)1, length, (FILE *)png_get_io_ptr(png_ptr)); - if (check != length) - { - png_error(png_ptr, "Read Error"); - } + if (check != length) { + png_error(png_ptr, "Read Error"); + } } -void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { - png_uint_32 check; +void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; - check = fwrite(data, 1, length, (FILE *)png_get_io_ptr(png_ptr)); - if (check != length) - { - png_error(png_ptr, "Write Error"); - } + check = fwrite(data, 1, length, (FILE *)png_get_io_ptr(png_ptr)); + + if (check != length) { + png_error(png_ptr, "Write Error"); + } } -void png_flush(png_structp png_ptr) { - FILE *io_ptr; - io_ptr = (FILE *)(png_get_io_ptr(png_ptr)); - if (io_ptr != NULL) - fflush(io_ptr); +void png_flush(png_structp png_ptr) +{ + FILE *io_ptr; + io_ptr = (FILE *)(png_get_io_ptr(png_ptr)); + + if (io_ptr != NULL) { + fflush(io_ptr); + } } -int ImageIO::load (Glib::ustring fname) { +int ImageIO::load (Glib::ustring fname) +{ - size_t lastdot = fname.find_last_of ('.'); - if( Glib::ustring::npos == lastdot ) - return IMIO_FILETYPENOTSUPPORTED; - if (!fname.casefold().compare (lastdot, 4, ".png")) - return loadPNG (fname); - else if (!fname.casefold().compare (lastdot, 4, ".jpg") || - !fname.casefold().compare (lastdot, 5, ".jpeg")) - return loadJPEG (fname); - else if (!fname.casefold().compare (lastdot, 4, ".tif") || - !fname.casefold().compare (lastdot, 5, ".tiff")) - return loadTIFF (fname); - else return IMIO_FILETYPENOTSUPPORTED; + size_t lastdot = fname.find_last_of ('.'); + + if( Glib::ustring::npos == lastdot ) { + return IMIO_FILETYPENOTSUPPORTED; + } + + if (!fname.casefold().compare (lastdot, 4, ".png")) { + return loadPNG (fname); + } else if (!fname.casefold().compare (lastdot, 4, ".jpg") || + !fname.casefold().compare (lastdot, 5, ".jpeg")) { + return loadJPEG (fname); + } else if (!fname.casefold().compare (lastdot, 4, ".tif") || + !fname.casefold().compare (lastdot, 5, ".tiff")) { + return loadTIFF (fname); + } else { + return IMIO_FILETYPENOTSUPPORTED; + } } -int ImageIO::save (Glib::ustring fname) { +int ImageIO::save (Glib::ustring fname) +{ - size_t lastdot = fname.find_last_of ('.'); - if( Glib::ustring::npos == lastdot ) - return IMIO_FILETYPENOTSUPPORTED; - if (!fname.casefold().compare (lastdot, 4, ".png")) - return savePNG (fname); - else if (!fname.casefold().compare (lastdot, 4, ".jpg") || - !fname.casefold().compare (lastdot, 5, ".jpeg")) - return saveJPEG (fname); - else if (!fname.casefold().compare (lastdot, 4, ".tif") || - !fname.casefold().compare (lastdot, 5, ".tiff")) - return saveTIFF (fname); - else return IMIO_FILETYPENOTSUPPORTED; + size_t lastdot = fname.find_last_of ('.'); + + if( Glib::ustring::npos == lastdot ) { + return IMIO_FILETYPENOTSUPPORTED; + } + + if (!fname.casefold().compare (lastdot, 4, ".png")) { + return savePNG (fname); + } else if (!fname.casefold().compare (lastdot, 4, ".jpg") || + !fname.casefold().compare (lastdot, 5, ".jpeg")) { + return saveJPEG (fname); + } else if (!fname.casefold().compare (lastdot, 4, ".tif") || + !fname.casefold().compare (lastdot, 5, ".tiff")) { + return saveTIFF (fname); + } else { + return IMIO_FILETYPENOTSUPPORTED; + } } diff --git a/rtengine/imageio.h b/rtengine/imageio.h index 980d86f92..1a13458c1 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -7,7 +7,7 @@ * 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 @@ -37,105 +37,150 @@ #include "iimage.h" #include "colortemp.h" -namespace rtengine { +namespace rtengine +{ - class ProgressListener; - class Imagefloat; +class ProgressListener; +class Imagefloat; - typedef enum IIO_Sample_Format { - IIOSF_UNKNOWN = 0, // Unknown or Unsupported file type; Has to remain 0 - //IIOSF_SIGNED_INT , // Not yet supported - IIOSF_UNSIGNED_CHAR = 1<<0, - IIOSF_UNSIGNED_SHORT = 1<<1, - //IIOSF_HALF , // OpenEXR & NVidia's Half Float, not yet supported - IIOSF_LOGLUV24 = 1<<2, - IIOSF_LOGLUV32 = 1<<3, - IIOSF_FLOAT = 1<<4 - } IIOSampleFormat; +typedef enum IIO_Sample_Format { + IIOSF_UNKNOWN = 0, // Unknown or Unsupported file type; Has to remain 0 + //IIOSF_SIGNED_INT , // Not yet supported + IIOSF_UNSIGNED_CHAR = 1 << 0, + IIOSF_UNSIGNED_SHORT = 1 << 1, + //IIOSF_HALF , // OpenEXR & NVidia's Half Float, not yet supported + IIOSF_LOGLUV24 = 1 << 2, + IIOSF_LOGLUV32 = 1 << 3, + IIOSF_FLOAT = 1 << 4 +} IIOSampleFormat; - typedef enum IIO_Sample_Arrangement { - IIOSA_UNKNOWN, // Unknown or Unsupported file type - IIOSA_CHUNKY, - IIOSA_PLANAR - } IIOSampleArrangement; +typedef enum IIO_Sample_Arrangement { + IIOSA_UNKNOWN, // Unknown or Unsupported file type + IIOSA_CHUNKY, + IIOSA_PLANAR +} IIOSampleArrangement; - typedef enum SensorType { - ST_NONE, // use this value if the image is already demosaiced (i.e. not a raw file) - ST_BAYER, - ST_FUJI_XTRANS, - ST_FOVEON, - //ST_FUJI_EXR - } eSensorType; +typedef enum SensorType { + ST_NONE, // use this value if the image is already demosaiced (i.e. not a raw file) + ST_BAYER, + ST_FUJI_XTRANS, + ST_FOVEON, + //ST_FUJI_EXR +} eSensorType; -class ImageIO : virtual public ImageDatas { +class ImageIO : virtual public ImageDatas +{ - protected: - ProgressListener* pl; - cmsHPROFILE embProfile; - char* profileData; - int profileLength; - char* loadedProfileData; - bool loadedProfileDataJpg; - int loadedProfileLength; - procparams::ExifPairs exifChange; - IptcData* iptc; - const rtexif::TagDirectory* exifRoot; - MyMutex imutex; - IIOSampleFormat sampleFormat; - IIOSampleArrangement sampleArrangement; +protected: + ProgressListener* pl; + cmsHPROFILE embProfile; + char* profileData; + int profileLength; + char* loadedProfileData; + bool loadedProfileDataJpg; + int loadedProfileLength; + procparams::ExifPairs exifChange; + IptcData* iptc; + const rtexif::TagDirectory* exifRoot; + MyMutex imutex; + IIOSampleFormat sampleFormat; + IIOSampleArrangement sampleArrangement; - private: - void deleteLoadedProfileData( ) { if(loadedProfileData) {if(loadedProfileDataJpg) free(loadedProfileData); else delete[] loadedProfileData;} loadedProfileData = NULL; } - public: - static Glib::ustring errorMsg[6]; - - ImageIO () : pl (NULL), embProfile(NULL), profileData(NULL), profileLength(0), loadedProfileData(NULL),loadedProfileDataJpg(false), - loadedProfileLength(0), iptc(NULL), exifRoot (NULL), sampleFormat(IIOSF_UNKNOWN), - sampleArrangement(IIOSA_UNKNOWN) {} - - virtual ~ImageIO (); - - void setProgressListener (ProgressListener* l) { pl = l; } - - void setSampleFormat(IIOSampleFormat sFormat) { sampleFormat = sFormat; } - IIOSampleFormat getSampleFormat() { return sampleFormat; } - void setSampleArrangement(IIOSampleArrangement sArrangement) { sampleArrangement = sArrangement; } - IIOSampleArrangement getSampleArrangement() { return sampleArrangement; } - - virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp) { - printf("getStdImage NULL!\n"); +private: + void deleteLoadedProfileData( ) + { + if(loadedProfileData) { + if(loadedProfileDataJpg) { + free(loadedProfileData); + } else { + delete[] loadedProfileData; + } } - virtual int getBPS () =0; - virtual void getScanline (int row, unsigned char* buffer, int bps) {} - virtual void setScanline (int row, unsigned char* buffer, int bps, float minValue[3]=NULL, float maxValue[3]=NULL) {} + loadedProfileData = NULL; + } +public: + static Glib::ustring errorMsg[6]; - virtual bool readImage (Glib::ustring &fname, FILE *fh) { return false; }; - virtual bool writeImage (Glib::ustring &fname, FILE *fh) { return false; }; + ImageIO () : pl (NULL), embProfile(NULL), profileData(NULL), profileLength(0), loadedProfileData(NULL), loadedProfileDataJpg(false), + loadedProfileLength(0), iptc(NULL), exifRoot (NULL), sampleFormat(IIOSF_UNKNOWN), + sampleArrangement(IIOSA_UNKNOWN) {} - int load (Glib::ustring fname); - int save (Glib::ustring fname); + virtual ~ImageIO (); - int loadPNG (Glib::ustring fname); - int loadJPEG (Glib::ustring fname); - int loadTIFF (Glib::ustring fname); - static int getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement); - static int getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement); + void setProgressListener (ProgressListener* l) + { + pl = l; + } - int loadJPEGFromMemory (const char* buffer, int bufsize); - int loadPPMFromMemory(const char* buffer,int width,int height, bool swap, int bps); + void setSampleFormat(IIOSampleFormat sFormat) + { + sampleFormat = sFormat; + } + IIOSampleFormat getSampleFormat() + { + return sampleFormat; + } + void setSampleArrangement(IIOSampleArrangement sArrangement) + { + sampleArrangement = sArrangement; + } + IIOSampleArrangement getSampleArrangement() + { + return sampleArrangement; + } - int savePNG (Glib::ustring fname, int compression = -1, volatile int bps = -1); - int saveJPEG (Glib::ustring fname, int quality = 100, int subSamp=3); - int saveTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false); + virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp) + { + printf("getStdImage NULL!\n"); + } - cmsHPROFILE getEmbeddedProfile () { return embProfile; } - void getEmbeddedProfileData (int& length, unsigned char*& pdata) { length = loadedProfileLength; pdata = (unsigned char*)loadedProfileData; } + virtual int getBPS () = 0; + virtual void getScanline (int row, unsigned char* buffer, int bps) {} + virtual void setScanline (int row, unsigned char* buffer, int bps, float minValue[3] = NULL, float maxValue[3] = NULL) {} - void setMetadata (const rtexif::TagDirectory* eroot); - void setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc); - void setOutputProfile (char* pdata, int plen); - MyMutex& mutex () { return imutex; } + virtual bool readImage (Glib::ustring &fname, FILE *fh) + { + return false; + }; + virtual bool writeImage (Glib::ustring &fname, FILE *fh) + { + return false; + }; + + int load (Glib::ustring fname); + int save (Glib::ustring fname); + + int loadPNG (Glib::ustring fname); + int loadJPEG (Glib::ustring fname); + int loadTIFF (Glib::ustring fname); + static int getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement); + static int getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement); + + int loadJPEGFromMemory (const char* buffer, int bufsize); + int loadPPMFromMemory(const char* buffer, int width, int height, bool swap, int bps); + + int savePNG (Glib::ustring fname, int compression = -1, volatile int bps = -1); + int saveJPEG (Glib::ustring fname, int quality = 100, int subSamp = 3); + int saveTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false); + + cmsHPROFILE getEmbeddedProfile () + { + return embProfile; + } + void getEmbeddedProfileData (int& length, unsigned char*& pdata) + { + length = loadedProfileLength; + pdata = (unsigned char*)loadedProfileData; + } + + void setMetadata (const rtexif::TagDirectory* eroot); + void setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc); + void setOutputProfile (char* pdata, int plen); + MyMutex& mutex () + { + return imutex; + } }; } diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 8ec92c64e..557f9a0b8 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -7,7 +7,7 @@ * 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 @@ -32,11 +32,13 @@ #include "image16.h" #include "imagefloat.h" -namespace rtengine { +namespace rtengine +{ using namespace procparams; -class ImageMatrices { +class ImageMatrices +{ public: double rgb_cam[3][3]; @@ -45,71 +47,112 @@ public: double cam_xyz[3][3]; }; -class ImageSource : public InitialImage { +class ImageSource : public InitialImage +{ - private: - int references; +private: + int references; - protected: - double redAWBMul, greenAWBMul, blueAWBMul; // local copy of the multipliers, to avoid recomputing the values - cmsHPROFILE embProfile; - Glib::ustring fileName; - ImageData* idata; - ImageMatrices imatrices; - double dirpyrdenoiseExpComp; +protected: + double redAWBMul, greenAWBMul, blueAWBMul; // local copy of the multipliers, to avoid recomputing the values + cmsHPROFILE embProfile; + Glib::ustring fileName; + ImageData* idata; + ImageMatrices imatrices; + double dirpyrdenoiseExpComp; - public: - ImageSource () : references (1), redAWBMul(-1.), greenAWBMul(-1.), blueAWBMul(-1.), - embProfile(NULL), idata(NULL), dirpyrdenoiseExpComp(INFINITY) {} +public: + ImageSource () : references (1), redAWBMul(-1.), greenAWBMul(-1.), blueAWBMul(-1.), + embProfile(NULL), idata(NULL), dirpyrdenoiseExpComp(INFINITY) {} - virtual ~ImageSource () {} - virtual int load (Glib::ustring fname, bool batch = false) =0; - virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse){}; - virtual void demosaic (const RAWParams &raw){}; - virtual void flushRawData (){}; - virtual void flushRGB (){}; - virtual void HLRecovery_Global (ToneCurveParams hrp){}; - virtual void HLRecovery_inpaint (float** red, float** green, float** blue){}; + virtual ~ImageSource () {} + virtual int load (Glib::ustring fname, bool batch = false) = 0; + virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse) {}; + virtual void demosaic (const RAWParams &raw) {}; + virtual void flushRawData () {}; + virtual void flushRGB () {}; + virtual void HLRecovery_Global (ToneCurveParams hrp) {}; + virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; - virtual bool IsrgbSourceModified() =0; // tracks whether cached rgb output of demosaic has been modified + virtual bool IsrgbSourceModified() = 0; // tracks whether cached rgb output of demosaic has been modified - // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* - virtual void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hlp, ColorManagementParams cmp, RAWParams raw) {} - virtual eSensorType getSensorType () { return ST_NONE; } - // true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource - virtual bool isWBProviderReady () =0; + // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* + virtual void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hlp, ColorManagementParams cmp, RAWParams raw) {} + virtual eSensorType getSensorType () + { + return ST_NONE; + } + // true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource + virtual bool isWBProviderReady () = 0; - virtual void convertColorSpace (Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb) =0;// DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images - virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) =0; - virtual ColorTemp getWB () =0; - virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) =0; + virtual void convertColorSpace (Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb) = 0; // DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images + virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) = 0; + virtual ColorTemp getWB () = 0; + virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) = 0; - virtual double getDefGain () { return 1.0; } + virtual double getDefGain () + { + return 1.0; + } - virtual void getFullSize (int& w, int& h, int tr = TR_NONE) {} - virtual void getSize (int tran, PreviewProps pp, int& w, int& h) {} - virtual int getRotateDegree() const { return 0; } + virtual void getFullSize (int& w, int& h, int tr = TR_NONE) {} + virtual void getSize (int tran, PreviewProps pp, int& w, int& h) {} + virtual int getRotateDegree() const + { + return 0; + } - virtual ImageData* getImageData () =0; - virtual ImageMatrices* getImageMatrices () =0; - virtual bool isRAW() const =0; - virtual DCPProfile* getDCP(ColorManagementParams cmp, ColorTemp &wb) { return NULL; }; + virtual ImageData* getImageData () = 0; + virtual ImageMatrices* getImageMatrices () = 0; + virtual bool isRAW() const = 0; + virtual DCPProfile* getDCP(ColorManagementParams cmp, ColorTemp &wb) + { + return NULL; + }; - virtual void setProgressListener (ProgressListener* pl) {} + virtual void setProgressListener (ProgressListener* pl) {} - void increaseRef () { references++; } - void decreaseRef () { references--; if (!references) delete this; } + void increaseRef () + { + references++; + } + void decreaseRef () + { + references--; - virtual void getAutoExpHistogram (LUTu & histogram, int& histcompr)=0; - virtual void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) { - histRedRaw.clear(); histGreenRaw.clear(); histBlueRaw.clear(); // only some sources will supply this + if (!references) { + delete this; } - double getDirPyrDenoiseExpComp ( ) { return dirpyrdenoiseExpComp; } - // functions inherited from the InitialImage interface - virtual Glib::ustring getFileName () { return fileName; } - virtual cmsHPROFILE getEmbeddedProfile () { return embProfile; } - virtual const ImageMetaData* getMetaData () { return idata; } - virtual ImageSource* getImageSource () { return this; } + } + + virtual void getAutoExpHistogram (LUTu & histogram, int& histcompr) = 0; + virtual void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) + { + histRedRaw.clear(); + histGreenRaw.clear(); + histBlueRaw.clear(); // only some sources will supply this + } + double getDirPyrDenoiseExpComp ( ) + { + return dirpyrdenoiseExpComp; + } + // functions inherited from the InitialImage interface + virtual Glib::ustring getFileName () + { + return fileName; + } + virtual cmsHPROFILE getEmbeddedProfile () + { + return embProfile; + } + virtual const ImageMetaData* getMetaData () + { + return idata; + } + virtual ImageSource* getImageSource () + { + return this; + } }; } #endif diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 6c928e3c1..fa1fae502 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -7,7 +7,7 @@ * 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 @@ -24,7 +24,8 @@ #include "colortemp.h" #include "improcfun.h" -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; @@ -36,26 +37,26 @@ ImProcCoordinator::ImProcCoordinator () hltonecurve(65536), shtonecurve(65536), - tonecurve(65536,0),//,1); - chaut(0.f), redaut(0.f), blueaut(0.f), maxredaut(0.f), maxblueaut(0.f),minredaut(0.f), minblueaut(0.f),nresi(0.f), - chromina(0.f), sigma(0.f), lumema(0.f), - lumacurve(65536,0), - chroma_acurve(65536,0), - chroma_bcurve(65536,0), - satcurve(65536,0), - lhskcurve(65536,0), - clcurve(65536,0), - wavclCurve(65536,0), - clToningcurve(65536,0), - cl2Toningcurve(65536,0), - Noisecurve(65536,0), - NoiseCCcurve(65536,0), - vhist16(65536),vhist16bw(65536), + tonecurve(65536, 0), //,1); + chaut(0.f), redaut(0.f), blueaut(0.f), maxredaut(0.f), maxblueaut(0.f), minredaut(0.f), minblueaut(0.f), nresi(0.f), + chromina(0.f), sigma(0.f), lumema(0.f), + lumacurve(65536, 0), + chroma_acurve(65536, 0), + chroma_bcurve(65536, 0), + satcurve(65536, 0), + lhskcurve(65536, 0), + clcurve(65536, 0), + wavclCurve(65536, 0), + clToningcurve(65536, 0), + cl2Toningcurve(65536, 0), + Noisecurve(65536, 0), + NoiseCCcurve(65536, 0), + vhist16(65536), vhist16bw(65536), lhist16(65536), lhist16Cropped(65536), lhist16CAM(65536), lhist16CroppedCAM(65536), lhist16CCAM(65536), histCropped(65536), - lhist16Clad(65536),lhist16CLlad(65536), + lhist16Clad(65536), lhist16CLlad(65536), lhist16LClad(65536), lhist16LLClad(65536), histRed(256), histRedRaw(256), histGreen(256), histGreenRaw(256), @@ -82,37 +83,45 @@ ImProcCoordinator::ImProcCoordinator () rcurvehist(256), rcurvehistCropped(256), rbeforehist(256), gcurvehist(256), gcurvehistCropped(256), gbeforehist(256), bcurvehist(256), bcurvehistCropped(256), bbeforehist(256), - fullw(1),fullh(1), + fullw(1), fullh(1), pW(-1), pH(-1), - plistener(NULL), imageListener(NULL), aeListener(NULL), acListener(NULL),abwListener(NULL),actListener(NULL),adnListener(NULL), awavListener(NULL), hListener(NULL), - resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false),utili(false),autili(false),wavcontlutili(false), - butili(false),ccutili(false),cclutili(false),clcutili(false),opautili(false) + plistener(NULL), imageListener(NULL), aeListener(NULL), acListener(NULL), abwListener(NULL), actListener(NULL), adnListener(NULL), awavListener(NULL), hListener(NULL), + resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false), utili(false), autili(false), wavcontlutili(false), + butili(false), ccutili(false), cclutili(false), clcutili(false), opautili(false) - {} +{} -void ImProcCoordinator::assign (ImageSource* imgsrc) { +void ImProcCoordinator::assign (ImageSource* imgsrc) +{ this->imgsrc = imgsrc; } -ImProcCoordinator::~ImProcCoordinator () { +ImProcCoordinator::~ImProcCoordinator () +{ destroying = true; updaterThreadStart.lock (); - if (updaterRunning && thread) + + if (updaterRunning && thread) { thread->join (); - mProcessing.lock(); - mProcessing.unlock(); + } + + mProcessing.lock(); + mProcessing.unlock(); freeAll (); std::vector toDel = crops; - for (size_t i=0; idecreaseRef (); updaterThreadStart.unlock (); } -DetailedCrop* ImProcCoordinator::createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) { +DetailedCrop* ImProcCoordinator::createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) +{ return new Crop (this, editDataProvider, isDetailWindow); } @@ -120,93 +129,107 @@ DetailedCrop* ImProcCoordinator::createCrop (::EditDataProvider *editDataProvid // todo: bitmask containing desired actions, taken from changesSinceLast // cropCall: calling crop, used to prevent self-updates ...doesn't seem to be used -void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { +void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) +{ MyMutex::MyLock processingLock(mProcessing); int numofphases = 14; int readyphase = 0; bwAutoR = bwAutoG = bwAutoB = -9000.f; - chaut=redaut=blueaut=maxredaut=maxblueaut=nresi=highresi=0.f; - chromina=sigma=lumema=0.f; - minredaut=minblueaut=10000.f; - if (todo==CROP && ipf.needsPCVignetting()) - todo |= TRANSFORM; // Change about Crop does affect TRANSFORM + chaut = redaut = blueaut = maxredaut = maxblueaut = nresi = highresi = 0.f; + chromina = sigma = lumema = 0.f; + minredaut = minblueaut = 10000.f; + + if (todo == CROP && ipf.needsPCVignetting()) { + todo |= TRANSFORM; // Change about Crop does affect TRANSFORM + } bool highDetailNeeded = false; - if (options.prevdemo==PD_Sidecar) highDetailNeeded = true; //i#2664 - else highDetailNeeded = (todo & M_HIGHQUAL); + if (options.prevdemo == PD_Sidecar) { + highDetailNeeded = true; //i#2664 + } else { + highDetailNeeded = (todo & M_HIGHQUAL); + } // Check if any detail crops need high detail. If not, take a fast path short cut if (!highDetailNeeded) { - for (size_t i=0; iget_skip() == 1 ) { // skip=1 -> full resolution - highDetailNeeded=true; + highDetailNeeded = true; break; } } RAWParams rp = params.raw; - if( !highDetailNeeded ){ + + if( !highDetailNeeded ) { // if below 100% magnification, take a fast path - if(rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] && rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]) + if(rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] && rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]) { rp.bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast]; + } + //bayerrp.all_enhance = false; - if(rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::none] && rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono]) + if(rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::none] && rp.xtranssensor.method != RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono]) { rp.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast]; + } rp.bayersensor.ccSteps = 0; rp.xtranssensor.ccSteps = 0; //rp.deadPixelFilter = rp.hotPixelFilter = false; } - progress ("Applying white balance, color correction & sRGB conversion...",100*readyphase/numofphases); + progress ("Applying white balance, color correction & sRGB conversion...", 100 * readyphase / numofphases); + // raw auto CA is bypassed if no high detail is needed, so we have to compute it when high detail is needed if ( (todo & M_PREPROC) || (!highDetailPreprocessComputed && highDetailNeeded)) { imgsrc->preprocess( rp, params.lensProf, params.coarse ); imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw ); - if (highDetailNeeded) + + if (highDetailNeeded) { highDetailPreprocessComputed = true; - else + } else { highDetailPreprocessComputed = false; + } } /* - Demosaic is kicked off only when - Detail considerations: + Demosaic is kicked off only when + Detail considerations: accurate detail is not displayed yet needed based on preview specifics (driven via highDetailNeeded flag) OR - HLR considerations: + HLR considerations: Color HLR alters rgb output of demosaic, so re-demosaic is needed when Color HLR is being turned off; if HLR is enabled and changing method *from* Color to any other method OR HLR gets disabled when Color method was selected */ // If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST if ( (todo & M_RAW) - || (!highDetailRawComputed && highDetailNeeded) - || ( params.toneCurve.hrenabled && params.toneCurve.method!="Color" && imgsrc->IsrgbSourceModified()) - || (!params.toneCurve.hrenabled && params.toneCurve.method=="Color" && imgsrc->IsrgbSourceModified())) - { + || (!highDetailRawComputed && highDetailNeeded) + || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->IsrgbSourceModified()) + || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->IsrgbSourceModified())) { if (settings->verbose) { - if (imgsrc->getSensorType() == ST_BAYER) - printf("Demosaic Bayer image using method: %s\n",rp.bayersensor.method.c_str()); - else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) - printf("Demosaic X-Trans image with using method: %s\n",rp.xtranssensor.method.c_str()); + if (imgsrc->getSensorType() == ST_BAYER) { + printf("Demosaic Bayer image using method: %s\n", rp.bayersensor.method.c_str()); + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { + printf("Demosaic X-Trans image with using method: %s\n", rp.xtranssensor.method.c_str()); + } } imgsrc->demosaic( rp ); if (highDetailNeeded) { highDetailRawComputed = true; - if (params.toneCurve.hrenabled && params.toneCurve.method=="Color") { + + if (params.toneCurve.hrenabled && params.toneCurve.method == "Color") { todo |= M_INIT; } - } - else + } else { highDetailRawComputed = false; + } } // Updating toneCurve.hrenabled if necessary @@ -215,7 +238,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { if (params.toneCurve.autoexp) {// this enabled HLRecovery if (ToneCurveParams::HLReconstructionNecessary(histRedRaw, histGreenRaw, histBlueRaw) && !params.toneCurve.hrenabled) { // switching params.toneCurve.hrenabled to true -> shouting in listener's ears! - params.toneCurve.hrenabled=true; + params.toneCurve.hrenabled = true; // forcing INIT to be done, to reconstruct HL again todo |= M_INIT; @@ -223,31 +246,39 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { } } - if (todo & (M_INIT|M_LINDENOISE)) { + if (todo & (M_INIT | M_LINDENOISE)) { MyMutex::MyLock initLock(minit); // Also used in crop window imgsrc->HLRecovery_Global( params.toneCurve ); // this handles Color HLRecovery - if (settings->verbose) printf ("Applying white balance, color correction & sRBG conversion...\n"); + + if (settings->verbose) { + printf ("Applying white balance, color correction & sRBG conversion...\n"); + } + currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); - if (params.wb.method=="Camera") + + if (params.wb.method == "Camera") { currWB = imgsrc->getWB (); - else if (params.wb.method=="Auto") { + } else if (params.wb.method == "Auto") { if (lastAwbEqual != params.wb.equal) { double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); + if (rm != -1.) { autoWB.update(rm, gm, bm, params.wb.equal); lastAwbEqual = params.wb.equal; - } - else { + } else { lastAwbEqual = -1.; autoWB.useDefaults(params.wb.equal); } + //double rr,gg,bb; //autoWB.getMultipliers(rr,gg,bb); } + currWB = autoWB; } + params.wb.temperature = currWB.getTemp (); params.wb.green = currWB.getGreen (); @@ -258,465 +289,573 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { // Will (re)allocate the preview's buffers setScale (scale); PreviewProps pp (0, 0, fw, fh, scale); - // Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications + // Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications ipf.setScale (scale); imgsrc->getImage (currWB, tr, orig_prev, pp, params.toneCurve, params.icm, params.raw); - //ColorTemp::CAT02 (orig_prev, ¶ms) ; + //ColorTemp::CAT02 (orig_prev, ¶ms) ; -/* Issue 2785, disabled some 1:1 tools - if (todo & M_LINDENOISE) { - DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; - if (denoiseParams.enabled && (scale==1)) { - Imagefloat *calclum = NULL ; + /* Issue 2785, disabled some 1:1 tools + if (todo & M_LINDENOISE) { + DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; + if (denoiseParams.enabled && (scale==1)) { + Imagefloat *calclum = NULL ; - denoiseParams.getCurves(noiseLCurve,noiseCCurve); - int nbw=6;//nb tile W - int nbh=4;// - - float ch_M[nbw*nbh]; - float max_r[nbw*nbh]; - float max_b[nbw*nbh]; - - if(denoiseParams.Lmethod == "CUR") { - if(noiseLCurve) - denoiseParams.luma = 0.5f; - else - denoiseParams.luma = 0.0f; - } else if(denoiseParams.Lmethod == "SLI") - noiseLCurve.Reset(); - + denoiseParams.getCurves(noiseLCurve,noiseCCurve); + int nbw=6;//nb tile W + int nbh=4;// - if(noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1 - // we only need image reduced to 1/4 here - calclum = new Imagefloat ((pW+1)/2, (pH+1)/2);//for luminance denoise curve - for(int ii=0;iir(ii>>1,jj>>1) = orig_prev->r(ii,jj); - calclum->g(ii>>1,jj>>1) = orig_prev->g(ii,jj); - calclum->b(ii>>1,jj>>1) = orig_prev->b(ii,jj); + float ch_M[nbw*nbh]; + float max_r[nbw*nbh]; + float max_b[nbw*nbh]; + + if(denoiseParams.Lmethod == "CUR") { + if(noiseLCurve) + denoiseParams.luma = 0.5f; + else + denoiseParams.luma = 0.0f; + } else if(denoiseParams.Lmethod == "SLI") + noiseLCurve.Reset(); + + + if(noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1 + // we only need image reduced to 1/4 here + calclum = new Imagefloat ((pW+1)/2, (pH+1)/2);//for luminance denoise curve + for(int ii=0;iir(ii>>1,jj>>1) = orig_prev->r(ii,jj); + calclum->g(ii>>1,jj>>1) = orig_prev->g(ii,jj); + calclum->b(ii>>1,jj>>1) = orig_prev->b(ii,jj); + } + } + imgsrc->convertColorSpace(calclum, params.icm, currWB);//claculate values after colorspace conversion } - } - imgsrc->convertColorSpace(calclum, params.icm, currWB);//claculate values after colorspace conversion - } - int kall=1; - ipf.RGB_denoise(kall, orig_prev, orig_prev, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); - } - } -*/ + int kall=1; + ipf.RGB_denoise(kall, orig_prev, orig_prev, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); + } + } + */ imgsrc->convertColorSpace(orig_prev, params.icm, currWB); ipf.firstAnalysis (orig_prev, ¶ms, vhist16); } + readyphase++; - progress ("Rotate / Distortion...",100*readyphase/numofphases); + progress ("Rotate / Distortion...", 100 * readyphase / numofphases); // Remove transformation if unneeded bool needstransform = ipf.needsTransform(); - if (!needstransform && orig_prev!=oprevi) { + + if (!needstransform && orig_prev != oprevi) { delete oprevi; oprevi = orig_prev; } - if (needstransform && orig_prev==oprevi) + + if (needstransform && orig_prev == oprevi) { oprevi = new Imagefloat (pW, pH); + } + if ((todo & M_TRANSFORM) && needstransform) 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++; - progress ("Preparing shadow/highlight map...",100*readyphase/numofphases); + progress ("Preparing shadow/highlight map...", 100 * readyphase / numofphases); + if ((todo & M_BLURMAP) && params.sh.enabled) { - double radius = sqrt (double(pW*pW+pH*pH)) / 2.0; + double radius = sqrt (double(pW * pW + pH * pH)) / 2.0; double shradius = params.sh.radius; - if (!params.sh.hq) shradius *= radius / 1800.0; - if(!shmap) - shmap = new SHMap (pW, pH, true); + + if (!params.sh.hq) { + shradius *= radius / 1800.0; + } + + if(!shmap) { + shmap = new SHMap (pW, pH, true); + } + shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale); } + readyphase++; if (todo & M_AUTOEXP) { if (params.toneCurve.autoexp) { - LUTu aehist; int aehistcompr; + LUTu aehist; + int aehistcompr; imgsrc->getAutoExpHistogram (aehist, aehistcompr); ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp, - params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); + params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); + if (aeListener) aeListener->autoExpChanged (params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, - params.toneCurve.black, params.toneCurve.hlcompr,params.toneCurve.hlcomprthresh, params.toneCurve.hrenabled); + params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.hrenabled); } } - progress ("Exposure curve & CIELAB conversion...",100*readyphase/numofphases); + progress ("Exposure curve & CIELAB conversion...", 100 * readyphase / numofphases); + if ((todo & M_RGBCURVE) || (todo & M_CROP)) { // if (hListener) oprevi->calcCroppedHistogram(params, scale, histCropped); //complexCurve also calculated pre-curves histogram depending on crop - CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black/65535.0, + CurveFactory::complexCurve (params.toneCurve.expcomp, params.toneCurve.black / 65535.0, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2, - vhist16, histCropped, hltonecurve, shtonecurve, tonecurve, histToneCurve, customToneCurve1, customToneCurve2, scale==1 ? 1 : 1); + vhist16, histCropped, hltonecurve, shtonecurve, tonecurve, histToneCurve, customToneCurve1, customToneCurve2, scale == 1 ? 1 : 1); - CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, scale==1 ? 1 : 1); - CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, scale==1 ? 1 : 1); - CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, scale==1 ? 1 : 1); + CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, scale == 1 ? 1 : 1); + 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]}, - {wprof[1][0],wprof[1][1],wprof[1][2]}, - {wprof[2][0],wprof[2][1],wprof[2][2]}}; + {wprof[0][0], wprof[0][1], wprof[0][2]}, + {wprof[1][0], wprof[1][1], wprof[1][2]}, + {wprof[2][0], wprof[2][1], wprof[2][2]} + }; TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} }; - opautili=false; + opautili = false; params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); - - bool clctoningutili=false; - bool llctoningutili=false; - CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve,scale==1 ? 1 : 16); - // clToningcurve.dump("CLToning3"); - CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve,scale==1 ? 1 : 16); - CurveFactory::curveBW (params.blackwhite.beforeCurve,params.blackwhite.afterCurve, vhist16bw, histToneCurveBW, beforeToneCurveBW, afterToneCurveBW,scale==1 ? 1 : 1); + bool clctoningutili = false; + bool llctoningutili = false; + CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16); + // clToningcurve.dump("CLToning3"); + CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16); + + CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, vhist16bw, histToneCurveBW, beforeToneCurveBW, afterToneCurveBW, scale == 1 ? 1 : 1); - float satLimit = float(params.colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; - float satLimitOpacity = 1.f-(float(params.colorToning.saturatedOpacity)/100.f); + float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; + float satLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f); - int satTH=80; - int satPR=30; - int indi=0; - if(params.colorToning.enabled && params.colorToning.autosat){//for colortoning evaluation of saturation settings - float moyS=0.f; - float eqty=0.f; + int satTH = 80; + int satPR = 30; + int indi = 0; + + if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + float moyS = 0.f; + float eqty = 0.f; ipf.moyeqt (oprevi, moyS, eqty);//return image : mean saturation and standard dev of saturation //printf("moy=%f ET=%f\n", moyS,eqty); - float satp=((moyS+1.5f*eqty)-0.3f)/0.7f;//1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale - if(satp >= 0.92f) satp=0.92f;//avoid values too high (out of gamut) - if(satp <= 0.15f) satp=0.15f;//avoid too low values + float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale + + if(satp >= 0.92f) { + satp = 0.92f; //avoid values too high (out of gamut) + } + + if(satp <= 0.15f) { + satp = 0.15f; //avoid too low values + } //satTH=(int) 100.f*satp; //satPR=(int) 100.f*(moyS-0.85f*eqty);//-0.85 sigma==>20% pixels with low saturation - satLimit= 100.f*satp; - satTH = (int) 100.f*satp; + satLimit = 100.f * satp; + satTH = (int) 100.f * satp; - satLimitOpacity= 100.f*(moyS-0.85f*eqty);//-0.85 sigma==>20% pixels with low saturation - satPR= (int) 100.f*(moyS-0.85f*eqty); + satLimitOpacity = 100.f * (moyS - 0.85f * eqty); //-0.85 sigma==>20% pixels with low saturation + satPR = (int) 100.f * (moyS - 0.85f * eqty); } + if(actListener) { //if(params.blackwhite.enabled) {actListener->autoColorTonChanged(0, satTH, satPR);} - if(params.blackwhite.enabled && params.colorToning.autosat) {actListener->autoColorTonChanged(0, satTH, satPR);indi=0;}//hide sliders only if autosat - else { - if(params.colorToning.autosat){ - if (params.colorToning.method=="Lab") indi=1; - else if(params.colorToning.method=="RGBCurves") indi=1; - else if(params.colorToning.method=="RGBSliders") indi=1; - else if(params.colorToning.method=="Splico") indi=2; - else if(params.colorToning.method=="Splitlr") indi=2; + if(params.blackwhite.enabled && params.colorToning.autosat) { + actListener->autoColorTonChanged(0, satTH, satPR); //hide sliders only if autosat + indi = 0; + } else { + if(params.colorToning.autosat) { + if (params.colorToning.method == "Lab") { + indi = 1; + } else if(params.colorToning.method == "RGBCurves") { + indi = 1; + } else if(params.colorToning.method == "RGBSliders") { + indi = 1; + } else if(params.colorToning.method == "Splico") { + indi = 2; + } else if(params.colorToning.method == "Splitlr") { + indi = 2; + } //actListener->autoColorTonChanged(indi, satTH, satPR); } } } + // if it's just crop we just need the histogram, no image updates if ( todo & M_RGBCURVE ) { - //initialize rrm bbm ggm different from zero to avoid black screen in some cases - double rrm=33.; - double ggm=33.; - double bbm=33.; + //initialize rrm bbm ggm different from zero to avoid black screen in some cases + double rrm = 33.; + double ggm = 33.; + double bbm = 33.; - DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB); + DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB); ipf.rgbProc (oprevi, oprevl, NULL, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation, - rCurve, gCurve, bCurve, satLimit ,satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2,beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, dcpProf); + rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, dcpProf); + if(params.blackwhite.enabled && params.blackwhite.autoc && abwListener) { - if (settings->verbose) + if (settings->verbose) { printf("ImProcCoordinator / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", bwAutoR, bwAutoG, bwAutoB); + } + abwListener->BWChanged((float) rrm, (float) ggm, (float) bbm); } + if(params.colorToning.autosat && actListener) { - if (settings->verbose) - printf("ImProcCoordinator / Auto CT: indi=%d satH=%d satPR=%d\n", indi,(int)satLimit , (int) satLimitOpacity); + if (settings->verbose) { + printf("ImProcCoordinator / Auto CT: indi=%d satH=%d satPR=%d\n", indi, (int)satLimit , (int) satLimitOpacity); + } + actListener->autoColorTonChanged(indi, (int) satLimit, (int)satLimitOpacity);//change sliders autosat } + // correct GUI black and white with value } + // compute L channel histogram int x1, y1, x2, y2, pos; - params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); - lhist16.clear(); lhist16Cropped.clear(); - lhist16Clad.clear(); lhist16CLlad.clear();lhist16LLClad.clear(); - for (int x=0; xL[x][y])); + params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); + lhist16.clear(); + lhist16Cropped.clear(); + lhist16Clad.clear(); + lhist16CLlad.clear(); + lhist16LLClad.clear(); + + for (int x = 0; x < pH; x++) + for (int y = 0; y < pW; y++) { + pos = CLIP((int)(oprevl->L[x][y])); lhist16[pos]++; - if (y>=y1 && y=x1 && x= y1 && y < y2 && x >= x1 && x < x2) { + lhist16Cropped[pos]++; + } } } + readyphase++; if ((todo & M_LUMACURVE) || (todo & M_CROP)) { utili = false; CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, lhist16, lhist16Cropped, - lumacurve, histLCurve, scale==1 ? 1 : 16, utili); + lumacurve, histLCurve, scale == 1 ? 1 : 16, utili); } + if (todo & M_LUMACURVE) { - autili=false; - butili=false; - ccutili=false; - cclutili=false; - clcutili=false; + autili = false; + butili = false; + ccutili = false; + cclutili = false; + clcutili = false; - CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, lhist16CLlad, histCLurve, scale==1 ? 1 : 16); - float adjustr=1.0f; + CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, lhist16CLlad, histCLurve, scale == 1 ? 1 : 16); + float adjustr = 1.0f; -/* if (params.icm.working=="ProPhoto") {adjustr = adjustbg = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170.. - else if (params.icm.working=="Adobe RGB") {adjustr = 1.8f; adjustbg = 1.4f;} - else if (params.icm.working=="sRGB") {adjustr = 2.0f; adjustbg = 1.7f;} - else if (params.icm.working=="WideGamut") {adjustr = adjustbg = 1.2f;} - else if (params.icm.working=="Beta RGB") {adjustr = adjustbg = 1.4f;} - else if (params.icm.working=="BestRGB") {adjustr = adjustbg = 1.4f;} - else if (params.icm.working=="BruceRGB") {adjustr = 1.8f; adjustbg = 1.5f;} -*/ - CurveFactory::complexsgnCurve (adjustr, autili, butili,ccutili,cclutili, params.labCurve.chromaticity, params.labCurve.rstprotection, - params.labCurve.acurve, params.labCurve.bcurve,params.labCurve.cccurve,params.labCurve.lccurve,chroma_acurve, chroma_bcurve, satcurve,lhskcurve, - lhist16Clad, lhist16LLClad, histCCurve, histLLCurve, scale==1 ? 1 : 16); + /* if (params.icm.working=="ProPhoto") {adjustr = adjustbg = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170.. + else if (params.icm.working=="Adobe RGB") {adjustr = 1.8f; adjustbg = 1.4f;} + else if (params.icm.working=="sRGB") {adjustr = 2.0f; adjustbg = 1.7f;} + else if (params.icm.working=="WideGamut") {adjustr = adjustbg = 1.2f;} + else if (params.icm.working=="Beta RGB") {adjustr = adjustbg = 1.4f;} + else if (params.icm.working=="BestRGB") {adjustr = adjustbg = 1.4f;} + else if (params.icm.working=="BruceRGB") {adjustr = 1.8f; adjustbg = 1.5f;} + */ + CurveFactory::complexsgnCurve (adjustr, autili, butili, ccutili, cclutili, params.labCurve.chromaticity, params.labCurve.rstprotection, + params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve, params.labCurve.lccurve, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, + lhist16Clad, lhist16LLClad, histCCurve, histLLCurve, scale == 1 ? 1 : 16); } - if (todo & (M_LUMINANCE+M_COLOR) ) { + + if (todo & (M_LUMINANCE + M_COLOR) ) { nprevl->CopyFrom(oprevl); - progress ("Applying Color Boost...",100*readyphase/numofphases); + progress ("Applying Color Boost...", 100 * readyphase / numofphases); - ipf.chromiLuminanceCurve (NULL, pW,nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili,cclutili,clcutili, histCCurve, histCLurve, histLLCurve, histLCurve); + ipf.chromiLuminanceCurve (NULL, pW, nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, histCCurve, histCLurve, histLLCurve, histLCurve); ipf.vibrance(nprevl); - if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) ipf.EPDToneMap(nprevl,5,1); + + if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) { + ipf.EPDToneMap(nprevl, 5, 1); + } + // for all treatments Defringe, Sharpening, Contrast detail , Microcontrast they are activated if "CIECAM" function are disabled readyphase++; -/* Issue 2785, disabled some 1:1 tools - if (scale==1) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ - progress ("Denoising luminance impulse...",100*readyphase/numofphases); - ipf.impulsedenoise (nprevl); - readyphase++; - } - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ - progress ("Defringing...",100*readyphase/numofphases); - ipf.defringe (nprevl); - readyphase++; - } - if (params.sharpenEdge.enabled) { - progress ("Edge sharpening...",100*readyphase/numofphases); - ipf.MLsharpen (nprevl); - readyphase++; - } - if (params.sharpenMicro.enabled) { - if(( params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ - progress ("Microcontrast...",100*readyphase/numofphases); - ipf.MLmicrocontrast (nprevl); - readyphase++; + /* Issue 2785, disabled some 1:1 tools + if (scale==1) { + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + progress ("Denoising luminance impulse...",100*readyphase/numofphases); + ipf.impulsedenoise (nprevl); + readyphase++; + } + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + progress ("Defringing...",100*readyphase/numofphases); + ipf.defringe (nprevl); + readyphase++; + } + if (params.sharpenEdge.enabled) { + progress ("Edge sharpening...",100*readyphase/numofphases); + ipf.MLsharpen (nprevl); + readyphase++; + } + if (params.sharpenMicro.enabled) { + if(( params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)){ + progress ("Microcontrast...",100*readyphase/numofphases); + ipf.MLmicrocontrast (nprevl); + readyphase++; + } + } + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { + progress ("Sharpening...",100*readyphase/numofphases); + + float **buffer = new float*[pH]; + for (int i=0; iautocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { - progress ("Sharpening...",100*readyphase/numofphases); - - float **buffer = new float*[pH]; - for (int i=0; iautocielab) || (!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.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); - CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve , /*lhist16CLlad, histCLurve,*/ scale==1 ? 1 : 16); - - - if((params.wavelet.enabled)) { - WaveletParams WaveParams = params.wavelet; - // WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY); - WaveParams.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL); - - int kall=0; - progress ("Wavelet...",100*readyphase/numofphases); - // ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, scale); - ipf.ip_wavelet(nprevl, nprevl, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, scale); + //CurveFactory::curveWavContL ( wavcontlutili,params.wavelet.lcurve, wavclCurve, LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,int skip); + CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve , /*lhist16CLlad, histCLurve,*/ scale == 1 ? 1 : 16); - } - - if(params.colorappearance.enabled){ - //L histo and Chroma histo for ciecam - // histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C - int x1, y1, x2, y2, pos, posc; - params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); - lhist16CAM.clear(); lhist16CroppedCAM.clear(); - lhist16CCAM.clear(); - for (int x=0; xL[x][y])); - if(!params.colorappearance.datacie) { - posc=CLIP((int)sqrt(nprevl->a[x][y]*nprevl->a[x][y] + nprevl->b[x][y]*nprevl->b[x][y])); - lhist16CAM[pos]++; - lhist16CCAM[posc]++; - } - if (y>=y1 && y=x1 && xL[x][y])); + + if(!params.colorappearance.datacie) { + posc = CLIP((int)sqrt(nprevl->a[x][y] * nprevl->a[x][y] + nprevl->b[x][y] * nprevl->b[x][y])); + lhist16CAM[pos]++; + lhist16CCAM[posc]++; + } + + if (y >= y1 && y < y2 && x >= x1 && x < x2) { + lhist16CroppedCAM[pos]++; + } + } + + LUTu dummy; + CurveFactory::curveLightBrightColor ( + params.colorappearance.curveMode, params.colorappearance.curve, + params.colorappearance.curveMode2, params.colorappearance.curve2, + params.colorappearance.curveMode3, params.colorappearance.curve3, + lhist16CAM, lhist16CroppedCAM, histLCAM, + lhist16CCAM, histCCAM, + customColCurve1, + customColCurve2, + customColCurve3, + scale == 1 ? 1 : 1 + ); float fnum = imgsrc->getMetaData()->getFNumber (); // F number float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO float fspeed = imgsrc->getMetaData()->getShutterSpeed () ; // Speed double fcomp = imgsrc->getMetaData()->getExpComp (); // Compensation +/- double adap; + if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong - adap=2000.; - } - else { - double E_V = fcomp + log2 (double((fnum*fnum) / fspeed / (fiso/100.f))); + adap = 2000.; + } else { + double E_V = fcomp + log2 (double((fnum * fnum) / fspeed / (fiso / 100.f))); E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV - adap= powf(2.f, E_V-3.f);// cd / m2 + adap = powf(2.f, E_V - 3.f); // cd / m2 // end calculation adaptation scene luminosity } - int begh=0; - int endh=pH; + + int begh = 0; + int endh = pH; float d; - bool execsharp=false; + bool execsharp = false; - if(!ncie) + if(!ncie) { ncie = new CieImage (pW, pH); + } + + if (!CAMBrightCurveJ && (params.colorappearance.algo == "JC" || params.colorappearance.algo == "JS" || params.colorappearance.algo == "ALL")) { + CAMBrightCurveJ(32768, 0); + } + + if (!CAMBrightCurveQ && (params.colorappearance.algo == "QM" || params.colorappearance.algo == "ALL")) { + CAMBrightCurveQ(32768, 0); + } - if (!CAMBrightCurveJ && (params.colorappearance.algo=="JC" || params.colorappearance.algo=="JS" || params.colorappearance.algo=="ALL")) - CAMBrightCurveJ(32768,0); - if (!CAMBrightCurveQ && (params.colorappearance.algo=="QM" || params.colorappearance.algo=="ALL")) - CAMBrightCurveQ(32768,0); // Issue 2785, only float version of ciecam02 for navigator and pan background - ipf.ciecam_02float (ncie, float(adap), begh, endh, pW, 2, nprevl, ¶ms, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, execsharp, d, scale, 1); - if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*(double)d); - if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) acListener->adapCamChanged(adap);//real value of adapt scene luminosity + ipf.ciecam_02float (ncie, float(adap), begh, endh, pW, 2, nprevl, ¶ms, customColCurve1, customColCurve2, customColCurve3, histLCAM, histCCAM, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, execsharp, d, scale, 1); + + if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) { + acListener->autoCamChanged(100.*(double)d); + } + + if(params.colorappearance.autoadapscen && acListener && params.colorappearance.enabled) { + acListener->adapCamChanged(adap); //real value of adapt scene luminosity + } readyphase++; } else { // CIECAM is disabled, we free up its image buffer to save some space - if (ncie) - delete ncie; ncie=NULL; + if (ncie) { + delete ncie; + } - if (CAMBrightCurveJ) CAMBrightCurveJ.reset(); - if (CAMBrightCurveQ) CAMBrightCurveQ.reset(); + ncie = NULL; + + if (CAMBrightCurveJ) { + CAMBrightCurveJ.reset(); + } + + if (CAMBrightCurveQ) { + CAMBrightCurveQ.reset(); + } } } + // process crop, if needed - for (size_t i=0; ihasListener () && cropCall != crops[i] ) - crops[i]->update (todo); // may call ourselves + for (size_t i = 0; i < crops.size(); i++) + if (crops[i]->hasListener () && cropCall != crops[i] ) { + crops[i]->update (todo); // may call ourselves + } // Flagging some LUT as dirty now, whether they have been freed up or not CAMBrightCurveJ.dirty = true; CAMBrightCurveQ.dirty = true; - progress ("Conversion to RGB...",100*readyphase/numofphases); - if (todo!=CROP && todo!=MINUPDATE) { + progress ("Conversion to RGB...", 100 * readyphase / numofphases); + + if (todo != CROP && todo != MINUPDATE) { MyMutex::MyLock prevImgLock(previmg->getMutex()); - try - { + + try { ipf.lab2monitorRgb (nprevl, previmg); delete workimg; Glib::ustring outProfile = params.icm.output; if(settings->HistogramWorking) { Glib::ustring workProfile = params.icm.working; - workimg = ipf.lab2rgb (nprevl, 0,0,pW,pH, workProfile, true); + workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, workProfile, true); } else { - if (params.icm.output=="" || params.icm.output==ColorManagementParams::NoICMString) - outProfile="sRGB"; - workimg = ipf.lab2rgb (nprevl, 0,0,pW,pH, outProfile, false); + if (params.icm.output == "" || params.icm.output == ColorManagementParams::NoICMString) { + outProfile = "sRGB"; + } + + workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, outProfile, false); } - } - catch(char * str) - { - progress ("Error converting file...",0); + } catch(char * str) { + progress ("Error converting file...", 0); return; } } + if (!resultValid) { resultValid = true; - if (imageListener) + + if (imageListener) { imageListener->setImage (previmg, scale, params.crop); + } } + if (imageListener) // TODO: The WB tool should be advertised too in order to get the AutoWB's temp and green values + { imageListener->imageReady (params.crop); + } readyphase++; if (hListener) { updateLRGBHistograms (); - hListener->histogramChanged (histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve,histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRedRaw, histGreenRaw, histBlueRaw, histChroma); + hListener->histogramChanged (histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRedRaw, histGreenRaw, histBlueRaw, histChroma); } } -void ImProcCoordinator::freeAll () { +void ImProcCoordinator::freeAll () +{ - if (settings->verbose) printf ("freeall starts %d\n", (int)allocated); + if (settings->verbose) { + printf ("freeall starts %d\n", (int)allocated); + } if (allocated) { - if (orig_prev!=oprevi) - delete oprevi; oprevi = NULL; - delete orig_prev; orig_prev = NULL; - delete oprevl; oprevl = NULL; - delete nprevl; nprevl = NULL; - if (ncie) - delete ncie; ncie = NULL; + if (orig_prev != oprevi) { + delete oprevi; + } + + oprevi = NULL; + delete orig_prev; + orig_prev = NULL; + delete oprevl; + oprevl = NULL; + delete nprevl; + nprevl = NULL; + + if (ncie) { + delete ncie; + } + + ncie = NULL; if (imageListener) { imageListener->delImage (previmg); - } - else + } else { delete previmg; + } delete workimg; - if(shmap) - delete shmap; shmap = NULL; + + if(shmap) { + delete shmap; + } + + shmap = NULL; } + allocated = false; } @@ -726,10 +865,12 @@ void ImProcCoordinator::freeAll () { * * @param prevscale New Preview's scale. */ -void ImProcCoordinator::setScale (int prevscale) { +void ImProcCoordinator::setScale (int prevscale) +{ - if (settings->verbose) + if (settings->verbose) { printf ("setscale before lock\n"); + } tr = getCoarseBitMask(params.coarse); @@ -737,15 +878,18 @@ void ImProcCoordinator::setScale (int prevscale) { imgsrc->getFullSize (fw, fh, tr); prevscale++; + do { prevscale--; PreviewProps pp (0, 0, fw, fh, prevscale); imgsrc->getSize (tr, pp, nW, nH); - } while(nH<400 && prevscale>1 && (nW*nH < 1000000) ); // sctually hardcoded values, perhaps a better choice is possible + } while(nH < 400 && prevscale > 1 && (nW * nH < 1000000) ); // sctually hardcoded values, perhaps a better choice is possible - if (settings->verbose) printf ("setscale starts (%d, %d)\n", nW, nH); + if (settings->verbose) { + printf ("setscale starts (%d, %d)\n", nW, nH); + } - if (nW!=pW || nH!=pH) { + if (nW != pW || nH != pH) { freeAll (); @@ -759,9 +903,10 @@ void ImProcCoordinator::setScale (int prevscale) { //ncie is only used in ImProcCoordinator::updatePreviewImage, it will be allocated on first use and deleted if not used anymore previmg = new Image8 (pW, pH); workimg = new Image8 (pW, pH); - if(params.sh.enabled) { - shmap = new SHMap (pW, pH, true); - } + + if(params.sh.enabled) { + shmap = new SHMap (pW, pH, true); + } allocated = true; } @@ -770,90 +915,107 @@ void ImProcCoordinator::setScale (int prevscale) { resultValid = false; fullw = fw; fullh = fh; - if (settings->verbose) printf ("setscale ends\n"); + + if (settings->verbose) { + printf ("setscale ends\n"); + } + if (!sizeListeners.empty()) - for (size_t i=0; isizeChanged (fullw, fullh, fw, fh); - if (settings->verbose) printf ("setscale ends2\n"); + } + + if (settings->verbose) { + printf ("setscale ends2\n"); + } } -void ImProcCoordinator::updateLRGBHistograms () { +void ImProcCoordinator::updateLRGBHistograms () +{ int x1, y1, x2, y2; - params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); + params.crop.mapToResized(pW, pH, scale, x1, x2, y1, y2); -#pragma omp parallel sections -{ -#pragma omp section -{ - histChroma.clear(); - for (int i=y1; ia[i][j]) + SQR(nprevl->b[i][j]))/188.f)]++;//188 = 48000/256 + #pragma omp parallel sections + { + #pragma omp section + { + histChroma.clear(); + + for (int i = y1; i < y2; i++) + for (int j = x1; j < x2; j++) + { + histChroma[(int)(sqrtf(SQR(nprevl->a[i][j]) + SQR(nprevl->b[i][j])) / 188.f)]++; //188 = 48000/256 + } } -} -#pragma omp section -{ - histLuma.clear(); - for (int i=y1; iL[i][j]/128.f)]++; + #pragma omp section + { + histLuma.clear(); + + for (int i = y1; i < y2; i++) + for (int j = x1; j < x2; j++) + { + histLuma[(int)(nprevl->L[i][j] / 128.f)]++; + } } -} -#pragma omp section -{ - histRed.clear(); - histGreen.clear(); - histBlue.clear(); + #pragma omp section + { + histRed.clear(); + histGreen.clear(); + histBlue.clear(); - for (int i=y1; idata[ofs++]; - int g=workimg->data[ofs++]; - int b=workimg->data[ofs++]; + for (int i = y1; i < y2; i++) + { + int ofs = (i * pW + x1) * 3; - histRed[r]++; - histGreen[g]++; - histBlue[b]++; + for (int j = x1; j < x2; j++) { + int r = workimg->data[ofs++]; + int g = workimg->data[ofs++]; + int b = workimg->data[ofs++]; + + histRed[r]++; + histGreen[g]++; + histBlue[b]++; + } + } } } -} -} } -void ImProcCoordinator::progress (Glib::ustring str, int pr) { +void ImProcCoordinator::progress (Glib::ustring str, int pr) +{ -/* if (plistener) { - plistener->setProgressStr (str); - plistener->setProgress ((double)pr / 100.0); - }*/ + /* if (plistener) { + plistener->setProgressStr (str); + plistener->setProgress ((double)pr / 100.0); + }*/ } -bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal) { +bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal) +{ if (imgsrc) { if (lastAwbEqual != equal) { // Issue 2500 MyMutex::MyLock lock(minit); // Also used in crop window double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); + if (rm != -1) { autoWB.update(rm, gm, bm, equal); lastAwbEqual = equal; - } - else { + } else { lastAwbEqual = -1.; autoWB.useDefaults(equal); } } + temp = autoWB.getTemp (); green = autoWB.getGreen (); return true; - } - else { + } else { //temp = autoWB.getTemp(); temp = -1.0; green = -1.0; @@ -861,7 +1023,8 @@ bool ImProcCoordinator::getAutoWB (double& temp, double& green, double equal) { } } -void ImProcCoordinator::getCamWB (double& temp, double& green) { +void ImProcCoordinator::getCamWB (double& temp, double& green) +{ if (imgsrc) { temp = imgsrc->getWB().getTemp (); @@ -869,26 +1032,29 @@ void ImProcCoordinator::getCamWB (double& temp, double& green) { } } -void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& tgreen) { +void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& tgreen) +{ ColorTemp ret; { - MyMutex::MyLock lock(mProcessing); - std::vector points, red, green, blue; - for (int i=y-rect; i<=y+rect; i++) - for (int j=x-rect; j<=x+rect; j++) - points.push_back (Coord2D (j, i)); + MyMutex::MyLock lock(mProcessing); + std::vector points, red, green, blue; - ipf.transCoord (fw, fh, points, red, green, blue); + for (int i = y - rect; i <= y + rect; i++) + for (int j = x - rect; j <= x + rect; j++) { + points.push_back (Coord2D (j, i)); + } - int tr = getCoarseBitMask(params.coarse); + ipf.transCoord (fw, fh, points, red, green, blue); + + int tr = getCoarseBitMask(params.coarse); + + ret = imgsrc->getSpotWB (red, green, blue, tr, params.wb.equal); + currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); + //double rr,gg,bb; + //currWB.getMultipliers(rr,gg,bb); - ret = imgsrc->getSpotWB (red, green, blue, tr, params.wb.equal); - currWB = ColorTemp (params.wb.temperature, params.wb.green,params.wb.equal, params.wb.method); - //double rr,gg,bb; - //currWB.getMultipliers(rr,gg,bb); - } // end of mutex lockong if (ret.getTemp() > 0) { @@ -900,158 +1066,182 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& } } -void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &h) { +void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &h) +{ MyMutex::MyLock lock(mProcessing); - LCPMapper *pLCPMap=NULL; - if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen()>0) { - LCPProfile *pLCPProf=lcpStore->getProfile(params.lensProf.lcpFile); - if (pLCPProf) pLCPMap=new LCPMapper(pLCPProf, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), - 0, false, params.lensProf.useDist, fullw, fullh, params.coarse, imgsrc->getRotateDegree()); + LCPMapper *pLCPMap = NULL; + + if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen() > 0) { + LCPProfile *pLCPProf = lcpStore->getProfile(params.lensProf.lcpFile); + + if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), + 0, false, params.lensProf.useDist, fullw, fullh, params.coarse, imgsrc->getRotateDegree()); } double fillscale = ipf.getTransformAutoFill (fullw, fullh, pLCPMap); - if (ratio>0) { + + if (ratio > 0) { w = fullw * fillscale; h = w / ratio; + if (h > fullh * fillscale) { h = fullh * fillscale; w = h * ratio; } - } - else { + } else { w = fullw * fillscale; h = fullh * fillscale; } + x = (fullw - w) / 2; y = (fullh - h) / 2; } -void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb) { - - MyMutex::MyLock lock(mProcessing); - - int fW, fH; +void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb) +{ + + MyMutex::MyLock lock(mProcessing); + + int fW, fH; int tr = getCoarseBitMask(params.coarse); - imgsrc->getFullSize (fW, fH, tr); - PreviewProps pp (0, 0, fW, fH, 1); - ProcParams ppar = params; - ppar.toneCurve.hrenabled = false; - ppar.icm.input = "(none)"; - Imagefloat* im = new Imagefloat (fW, fH); - imgsrc->preprocess( ppar.raw, ppar.lensProf, ppar.coarse ); - imgsrc->demosaic(ppar.raw ); - ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); - if (params.wb.method=="Camera") - currWB = imgsrc->getWB (); - else if (params.wb.method=="Auto") { - if (lastAwbEqual != params.wb.equal) { - double rm, gm, bm; - imgsrc->getAutoWBMultipliers(rm, gm, bm); - if (rm != -1.) { - autoWB.update(rm, gm, bm, params.wb.equal); - lastAwbEqual = params.wb.equal; - } - else { - lastAwbEqual = -1.; - autoWB.useDefaults(params.wb.equal); - } - } - currWB = autoWB; - } - if (!apply_wb) { - currWB = ColorTemp(); // = no white balance - } - imgsrc->getImage (currWB, tr, im, pp, ppar.toneCurve, ppar.icm, ppar.raw); - ImProcFunctions ipf (&ppar, true); - if (ipf.needsTransform()) { - Imagefloat* trImg = new Imagefloat (fW, fH); - ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), - imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); - delete im; - im = trImg; - } - if (params.crop.enabled) { - Imagefloat *tmpim = new Imagefloat (params.crop.w, params.crop.h); - int cx = params.crop.x; - int cy = params.crop.y; - int cw = params.crop.w; - int ch = params.crop.h; -#pragma omp parallel for - for (int i=cy; ir(i-cy, j-cx) = im->r(i, j); - tmpim->g(i-cy, j-cx) = im->g(i, j); - tmpim->b(i-cy, j-cx) = im->b(i, j); - } - } - delete im; - im = tmpim; - } + imgsrc->getFullSize (fW, fH, tr); + PreviewProps pp (0, 0, fW, fH, 1); + ProcParams ppar = params; + ppar.toneCurve.hrenabled = false; + ppar.icm.input = "(none)"; + Imagefloat* im = new Imagefloat (fW, fH); + imgsrc->preprocess( ppar.raw, ppar.lensProf, ppar.coarse ); + imgsrc->demosaic(ppar.raw ); + ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); - // image may contain out of range samples, clip them to avoid wrap-arounds -#pragma omp parallel for - for(int i=0;iheight;i++) { - for(int j=0;jwidth;j++) { - im->r(i,j) = CLIP(im->r(i,j)); - im->g(i,j) = CLIP(im->g(i,j)); - im->b(i,j) = CLIP(im->b(i,j)); + if (params.wb.method == "Camera") { + currWB = imgsrc->getWB (); + } else if (params.wb.method == "Auto") { + if (lastAwbEqual != params.wb.equal) { + double rm, gm, bm; + imgsrc->getAutoWBMultipliers(rm, gm, bm); + + if (rm != -1.) { + autoWB.update(rm, gm, bm, params.wb.equal); + lastAwbEqual = params.wb.equal; + } else { + lastAwbEqual = -1.; + autoWB.useDefaults(params.wb.equal); } } - Image16* im16 = im->to16(); - delete im; + currWB = autoWB; + } - int imw, imh; - double tmpScale = ipf.resizeScale(¶ms, fW, fH, imw, imh); - if (tmpScale != 1.0) { - Image16* tempImage = new Image16 (imw, imh); - ipf.resize (im16, tempImage, tmpScale); - delete im16; - im16 = tempImage; - } - im16->saveTIFF (fname,16,true); - delete im16; - - if (plistener) + if (!apply_wb) { + currWB = ColorTemp(); // = no white balance + } + + imgsrc->getImage (currWB, tr, im, pp, ppar.toneCurve, ppar.icm, ppar.raw); + ImProcFunctions ipf (&ppar, true); + + if (ipf.needsTransform()) { + Imagefloat* trImg = new Imagefloat (fW, fH); + ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), + imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); + delete im; + im = trImg; + } + + if (params.crop.enabled) { + Imagefloat *tmpim = new Imagefloat (params.crop.w, params.crop.h); + int cx = params.crop.x; + int cy = params.crop.y; + int cw = params.crop.w; + int ch = params.crop.h; + #pragma omp parallel for + + for (int i = cy; i < cy + ch; i++) { + for (int j = cx; j < cx + cw; j++) { + tmpim->r(i - cy, j - cx) = im->r(i, j); + tmpim->g(i - cy, j - cx) = im->g(i, j); + tmpim->b(i - cy, j - cx) = im->b(i, j); + } + } + + delete im; + im = tmpim; + } + + // image may contain out of range samples, clip them to avoid wrap-arounds + #pragma omp parallel for + + for(int i = 0; i < im->height; i++) { + for(int j = 0; j < im->width; j++) { + im->r(i, j) = CLIP(im->r(i, j)); + im->g(i, j) = CLIP(im->g(i, j)); + im->b(i, j) = CLIP(im->b(i, j)); + } + } + + Image16* im16 = im->to16(); + delete im; + + int imw, imh; + double tmpScale = ipf.resizeScale(¶ms, fW, fH, imw, imh); + + if (tmpScale != 1.0) { + Image16* tempImage = new Image16 (imw, imh); + ipf.resize (im16, tempImage, tmpScale); + delete im16; + im16 = tempImage; + } + + im16->saveTIFF (fname, 16, true); + delete im16; + + if (plistener) { plistener->setProgressState (false); - //im->saveJPEG (fname, 85); + } + + //im->saveJPEG (fname, 85); } -void ImProcCoordinator::stopProcessing () { +void ImProcCoordinator::stopProcessing () +{ updaterThreadStart.lock (); + if (updaterRunning && thread) { changeSinceLast = 0; thread->join (); } + updaterThreadStart.unlock (); } -void ImProcCoordinator::startProcessing () { +void ImProcCoordinator::startProcessing () +{ - #undef THREAD_PRIORITY_NORMAL +#undef THREAD_PRIORITY_NORMAL if (!destroying) { if (!updaterRunning) { - updaterThreadStart.lock (); + updaterThreadStart.lock (); thread = NULL; updaterRunning = true; updaterThreadStart.unlock (); //batchThread->yield(); //the running batch should wait other threads to avoid conflict - + thread = Glib::Thread::create(sigc::mem_fun(*this, &ImProcCoordinator::process), 0, true, true, Glib::THREAD_PRIORITY_NORMAL); } } } -void ImProcCoordinator::startProcessing(int changeCode) { +void ImProcCoordinator::startProcessing(int changeCode) +{ paramsUpdateMutex.lock(); changeSinceLast |= changeCode; paramsUpdateMutex.unlock(); @@ -1059,12 +1249,15 @@ void ImProcCoordinator::startProcessing(int changeCode) { startProcessing (); } -void ImProcCoordinator::process () { +void ImProcCoordinator::process () +{ - if (plistener) + if (plistener) { plistener->setProgressState (true); + } paramsUpdateMutex.lock (); + while (changeSinceLast) { params = nextParams; int change = changeSinceLast; @@ -1072,27 +1265,35 @@ void ImProcCoordinator::process () { paramsUpdateMutex.unlock (); // M_VOID means no update, and is a bit higher that the rest - if (change & (M_VOID-1)) updatePreviewImage (change); + if (change & (M_VOID - 1)) { + updatePreviewImage (change); + } + paramsUpdateMutex.lock (); - } + } + paramsUpdateMutex.unlock (); updaterRunning = false; - if (plistener) + if (plistener) { plistener->setProgressState (false); + } } -ProcParams* ImProcCoordinator::beginUpdateParams () { +ProcParams* ImProcCoordinator::beginUpdateParams () +{ paramsUpdateMutex.lock (); return &nextParams; } -void ImProcCoordinator::endUpdateParams (ProcEvent change) { +void ImProcCoordinator::endUpdateParams (ProcEvent change) +{ endUpdateParams( refreshmap[(int)change] ); } -void ImProcCoordinator::endUpdateParams (int changeFlags) { +void ImProcCoordinator::endUpdateParams (int changeFlags) +{ changeSinceLast |= changeFlags; paramsUpdateMutex.unlock (); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 6040b9977..e0588d5df 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -7,7 +7,7 @@ * 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 @@ -29,7 +29,8 @@ #include "LUT.h" #include "../rtgui/threadutils.h" -namespace rtengine { +namespace rtengine +{ using namespace procparams; @@ -46,199 +47,267 @@ class Crop; * but using this class' LUT and other precomputed parameters. The main preview area is displaying a non framed Crop object, * while detail windows are framed Crop objects. */ -class ImProcCoordinator : public StagedImageProcessor { +class ImProcCoordinator : public StagedImageProcessor +{ friend class Crop; - protected: - Imagefloat *orig_prev; - Imagefloat *oprevi; - LabImage *oprevl; - LabImage *nprevl; - Image8 *previmg; - Image8 *workimg; - CieImage *ncie; +protected: + Imagefloat *orig_prev; + Imagefloat *oprevi; + LabImage *oprevl; + LabImage *nprevl; + Image8 *previmg; + Image8 *workimg; + CieImage *ncie; - ImageSource* imgsrc; + ImageSource* imgsrc; - SHMap* shmap; + SHMap* shmap; - ColorTemp currWB; - ColorTemp autoWB; + ColorTemp currWB; + ColorTemp autoWB; - double lastAwbEqual; + double lastAwbEqual; - ImProcFunctions ipf; + ImProcFunctions ipf; - int scale; - bool highDetailPreprocessComputed; - bool highDetailRawComputed; - bool allocated; + int scale; + bool highDetailPreprocessComputed; + bool highDetailRawComputed; + bool allocated; - void freeAll (); + void freeAll (); - // Precomputed values used by DetailedCrop ---------------------------------------------- + // Precomputed values used by DetailedCrop ---------------------------------------------- - float bwAutoR, bwAutoG, bwAutoB; - float CAMMean; - LUTf hltonecurve; - LUTf shtonecurve; - LUTf tonecurve; - float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema; + float bwAutoR, bwAutoG, bwAutoB; + float CAMMean; + LUTf hltonecurve; + LUTf shtonecurve; + LUTf tonecurve; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema; - LUTf lumacurve; - LUTf chroma_acurve; - LUTf chroma_bcurve; - LUTf satcurve; - LUTf lhskcurve; - LUTf clcurve; - LUTf wavclCurve; - LUTf clToningcurve; - LUTf cl2Toningcurve; - LUTf Noisecurve; - LUTf NoiseCCcurve; + LUTf lumacurve; + LUTf chroma_acurve; + LUTf chroma_bcurve; + LUTf satcurve; + LUTf lhskcurve; + LUTf clcurve; + LUTf wavclCurve; + LUTf clToningcurve; + LUTf cl2Toningcurve; + LUTf Noisecurve; + LUTf NoiseCCcurve; - LUTu vhist16,vhist16bw; - LUTu lhist16,lhist16Cropped; - LUTu lhist16CAM,lhist16CroppedCAM; - LUTu lhist16CCAM; - LUTu histCropped; - LUTu lhist16Clad,lhist16CLlad,lhist16LClad,lhist16LLClad; - LUTu histRed, histRedRaw; - LUTu histGreen, histGreenRaw; - LUTu histBlue, histBlueRaw; - LUTu histLuma, histToneCurve, histToneCurveBW, histLCurve, histCCurve, histCLurve; - LUTu histLLCurve, histLCAM, histCCAM, histClad, bcabhist, histChroma; + LUTu vhist16, vhist16bw; + LUTu lhist16, lhist16Cropped; + LUTu lhist16CAM, lhist16CroppedCAM; + LUTu lhist16CCAM; + LUTu histCropped; + LUTu lhist16Clad, lhist16CLlad, lhist16LClad, lhist16LLClad; + LUTu histRed, histRedRaw; + LUTu histGreen, histGreenRaw; + LUTu histBlue, histBlueRaw; + LUTu histLuma, histToneCurve, histToneCurveBW, histLCurve, histCCurve, histCLurve; + LUTu histLLCurve, histLCAM, histCCAM, histClad, bcabhist, histChroma; - LUTf CAMBrightCurveJ, CAMBrightCurveQ; + LUTf CAMBrightCurveJ, CAMBrightCurveQ; - LUTf rCurve; - LUTf gCurve; - LUTf bCurve; - ToneCurve customToneCurve1; - ToneCurve customToneCurve2; - ColorGradientCurve ctColorCurve; - OpacityCurve ctOpacityCurve; - NoiseCurve noiseLCurve; - NoiseCurve noiseCCurve; - WavCurve wavCLVCurve; - WavOpacityCurveRG waOpacityCurveRG; - WavOpacityCurveBY waOpacityCurveBY; - WavOpacityCurveW waOpacityCurveW; - WavOpacityCurveWL waOpacityCurveWL; - - ColorAppearance customColCurve1; - ColorAppearance customColCurve2; - ColorAppearance customColCurve3; - ToneCurve beforeToneCurveBW; - ToneCurve afterToneCurveBW; + LUTf rCurve; + LUTf gCurve; + LUTf bCurve; + ToneCurve customToneCurve1; + ToneCurve customToneCurve2; + ColorGradientCurve ctColorCurve; + OpacityCurve ctOpacityCurve; + NoiseCurve noiseLCurve; + NoiseCurve noiseCCurve; + WavCurve wavCLVCurve; + WavOpacityCurveRG waOpacityCurveRG; + WavOpacityCurveBY waOpacityCurveBY; + WavOpacityCurveW waOpacityCurveW; + WavOpacityCurveWL waOpacityCurveWL; - LUTu rcurvehist, rcurvehistCropped, rbeforehist; - LUTu gcurvehist, gcurvehistCropped, gbeforehist; - LUTu bcurvehist, bcurvehistCropped, bbeforehist; + ColorAppearance customColCurve1; + ColorAppearance customColCurve2; + ColorAppearance customColCurve3; + ToneCurve beforeToneCurveBW; + ToneCurve afterToneCurveBW; - // ------------------------------------------------------------------------------------ + LUTu rcurvehist, rcurvehistCropped, rbeforehist; + LUTu gcurvehist, gcurvehistCropped, gbeforehist; + LUTu bcurvehist, bcurvehistCropped, bbeforehist; - int fw, fh, tr, fullw, fullh; - int pW, pH; + // ------------------------------------------------------------------------------------ - ProgressListener* plistener; - PreviewImageListener* imageListener; - AutoExpListener* aeListener; - AutoCamListener* acListener; - AutoBWListener* abwListener; - AutoColorTonListener* actListener; - AutoChromaListener* adnListener; - WaveletListener* awavListener; + int fw, fh, tr, fullw, fullh; + int pW, pH; - HistogramListener* hListener; - std::vector sizeListeners; + ProgressListener* plistener; + PreviewImageListener* imageListener; + AutoExpListener* aeListener; + AutoCamListener* acListener; + AutoBWListener* abwListener; + AutoColorTonListener* actListener; + AutoChromaListener* adnListener; + WaveletListener* awavListener; - std::vector crops; + HistogramListener* hListener; + std::vector sizeListeners; - bool resultValid; + std::vector crops; - MyMutex minit; // to gain mutually exclusive access to ... to what exactly? + bool resultValid; - void progress (Glib::ustring str, int pr); - void reallocAll (); - void updateLRGBHistograms (); - void setScale (int prevscale); - void updatePreviewImage (int todo, Crop* cropCall= NULL); + MyMutex minit; // to gain mutually exclusive access to ... to what exactly? - MyMutex mProcessing; - ProcParams params; + void progress (Glib::ustring str, int pr); + void reallocAll (); + void updateLRGBHistograms (); + void setScale (int prevscale); + void updatePreviewImage (int todo, Crop* cropCall = NULL); - // members of the updater: - Glib::Thread* thread; - MyMutex updaterThreadStart; - MyMutex paramsUpdateMutex; - int changeSinceLast; - bool updaterRunning; - ProcParams nextParams; - bool destroying; - bool utili; - bool autili; - bool butili; - bool ccutili; - bool cclutili; - bool clcutili; - bool opautili; - bool wavcontlutili; - void startProcessing (); - void process (); + MyMutex mProcessing; + ProcParams params; - public: + // members of the updater: + Glib::Thread* thread; + MyMutex updaterThreadStart; + MyMutex paramsUpdateMutex; + int changeSinceLast; + bool updaterRunning; + ProcParams nextParams; + bool destroying; + bool utili; + bool autili; + bool butili; + bool ccutili; + bool cclutili; + bool clcutili; + bool opautili; + bool wavcontlutili; + void startProcessing (); + void process (); - ImProcCoordinator (); - ~ImProcCoordinator (); - void assign (ImageSource* imgsrc); +public: - void getParams (procparams::ProcParams* dst) { *dst = params; } + ImProcCoordinator (); + ~ImProcCoordinator (); + void assign (ImageSource* imgsrc); - void startProcessing(int changeCode); - ProcParams* beginUpdateParams (); - void endUpdateParams (ProcEvent change); // must be called after beginUpdateParams, triggers update - void endUpdateParams (int changeFlags); - void stopProcessing (); + void getParams (procparams::ProcParams* dst) + { + *dst = params; + } + + void startProcessing(int changeCode); + ProcParams* beginUpdateParams (); + void endUpdateParams (ProcEvent change); // must be called after beginUpdateParams, triggers update + void endUpdateParams (int changeFlags); + void stopProcessing (); - void setPreviewScale (int scale) { setScale (scale); } - int getPreviewScale () { return scale; } + void setPreviewScale (int scale) + { + setScale (scale); + } + int getPreviewScale () + { + return scale; + } - //void fullUpdatePreviewImage (); + //void fullUpdatePreviewImage (); - int getFullWidth () { return fullw; } - int getFullHeight () { return fullh; } + int getFullWidth () + { + return fullw; + } + int getFullHeight () + { + return fullh; + } - int getPreviewWidth () { return pW; } - int getPreviewHeight () { return pH; } + int getPreviewWidth () + { + return pW; + } + int getPreviewHeight () + { + return pH; + } - DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow); + DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow); - bool getAutoWB (double& temp, double& green, double equal); - void getCamWB (double& temp, double& green); - void getSpotWB (int x, int y, int rectSize, double& temp, double& green); - void getAutoCrop (double ratio, int &x, int &y, int &w, int &h); + bool getAutoWB (double& temp, double& green, double equal); + void getCamWB (double& temp, double& green); + void getSpotWB (int x, int y, int rectSize, double& temp, double& green); + void getAutoCrop (double ratio, int &x, int &y, int &w, int &h); - bool updateTryLock () {return updaterThreadStart.trylock();} - void updateUnLock () {updaterThreadStart.unlock();} + bool updateTryLock () + { + return updaterThreadStart.trylock(); + } + void updateUnLock () + { + updaterThreadStart.unlock(); + } - void setProgressListener (ProgressListener* pl) { plistener = pl; } - void setPreviewImageListener (PreviewImageListener* il) {imageListener = il; } - void setSizeListener (SizeListener* il) {sizeListeners.push_back (il); } - void delSizeListener (SizeListener* il) {std::vector::iterator it = std::find (sizeListeners.begin(), sizeListeners.end(), il); if (it!=sizeListeners.end()) sizeListeners.erase (it); } - void setAutoExpListener (AutoExpListener* ael) {aeListener = ael; } - void setHistogramListener(HistogramListener *h) {hListener = h; } - void setAutoCamListener (AutoCamListener* acl) {acListener = acl; } - void setAutoBWListener (AutoBWListener* abw) {abwListener = abw; } - void setAutoColorTonListener (AutoColorTonListener* bwct) {actListener = bwct; } - void setAutoChromaListener (AutoChromaListener* adn) {adnListener = adn; } - void setWaveletListener (WaveletListener* awa) {awavListener = awa; } + void setProgressListener (ProgressListener* pl) + { + plistener = pl; + } + void setPreviewImageListener (PreviewImageListener* il) + { + imageListener = il; + } + void setSizeListener (SizeListener* il) + { + sizeListeners.push_back (il); + } + void delSizeListener (SizeListener* il) + { + std::vector::iterator it = std::find (sizeListeners.begin(), sizeListeners.end(), il); - void saveInputICCReference (const Glib::ustring& fname, bool apply_wb); + if (it != sizeListeners.end()) { + sizeListeners.erase (it); + } + } + void setAutoExpListener (AutoExpListener* ael) + { + aeListener = ael; + } + void setHistogramListener(HistogramListener *h) + { + hListener = h; + } + void setAutoCamListener (AutoCamListener* acl) + { + acListener = acl; + } + void setAutoBWListener (AutoBWListener* abw) + { + abwListener = abw; + } + void setAutoColorTonListener (AutoColorTonListener* bwct) + { + actListener = bwct; + } + void setAutoChromaListener (AutoChromaListener* adn) + { + adnListener = adn; + } + void setWaveletListener (WaveletListener* awa) + { + awavListener = awa; + } - InitialImage* getInitialImage () { return imgsrc; } + void saveInputICCReference (const Glib::ustring& fname, bool apply_wb); + + InitialImage* getInitialImage () + { + return imgsrc; + } }; } #endif diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index d8932d0e6..e6b05095f 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -47,9 +47,10 @@ #undef CLIPD #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) -namespace rtengine { +namespace rtengine +{ - using namespace procparams; +using namespace procparams; #undef ABS #undef CLIPS @@ -65,61 +66,67 @@ namespace rtengine { extern const Settings* settings; LUTf ImProcFunctions::cachef; LUTf ImProcFunctions::gamma2curve; -void ImProcFunctions::initCache () { +void ImProcFunctions::initCache () +{ const int maxindex = 65536; - cachef(maxindex,0/*LUT_CLIP_BELOW*/); + cachef(maxindex, 0/*LUT_CLIP_BELOW*/); - gamma2curve(maxindex,0); + gamma2curve(maxindex, 0); - for (int i=0; iColor::eps_max) { - cachef[i] = 327.68*( exp(1.0/3.0 * log((double)i / MAXVALD) )); + 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); } - else { - cachef[i] = 327.68*((Color::kappa*i/MAXVALD+16.0)/116.0); - } - } + } - for (int i=0; iworkingSpaceMatrix (wprofile); + TMatrix wprof = iccStore->workingSpaceMatrix (wprofile); + + lumimul[0] = wprof[1][0]; + lumimul[1] = wprof[1][1]; + lumimul[2] = wprof[1][2]; - lumimul[0] = wprof[1][0]; - lumimul[1] = wprof[1][1]; - lumimul[2] = wprof[1][2]; - int W = original->width; - for (int i=row_from; ir(i,j); - int g = original->g(i,j); - int b = original->b(i,j); + + for (int i = row_from; i < row_to; i++) { + for (int j = 0; j < W; j++) { + + int r = original->r(i, j); + int g = original->g(i, j); + int b = original->b(i, j); int y = CLIP((int)(lumimul[0] * r + lumimul[1] * g + lumimul[2] * b)) ; - if (histogram) { + if (histogram) { histogram[y]++; } } @@ -128,13 +135,13 @@ void ImProcFunctions::firstAnalysisThread (Imagefloat* original, Glib::ustring w /* void ImProcFunctions::CAT02 (Imagefloat* baseImg, const ProcParams* params) { - const double toxyz[3][3] = {{0.7976749, 0.1351917, 0.0313534}, - {0.2880402, 0.7118741, 0.0000857}, - {0.0000000, 0.0000000, 0.8252100}}; + const double toxyz[3][3] = {{0.7976749, 0.1351917, 0.0313534}, + {0.2880402, 0.7118741, 0.0000857}, + {0.0000000, 0.0000000, 0.8252100}}; - const double xyzto[3][3] = {{1.3459433, -0.2556075, -0.0511118}, - {-0.5445989, 1.5081673, 0.0205351}, - {0.0000000, 0.0000000, 1.2118128}}; + const double xyzto[3][3] = {{1.3459433, -0.2556075, -0.0511118}, + {-0.5445989, 1.5081673, 0.0205351}, + {0.0000000, 0.0000000, 1.2118128}}; int fw = baseImg->width; int fh = baseImg->height; @@ -151,2303 +158,3013 @@ void ImProcFunctions::CAT02 (Imagefloat* baseImg, const ProcParams* params) ColorTemp::cieCAT02(Xxx, Yyy, Zzz, CAM02BB00,CAM02BB01,CAM02BB02,CAM02BB10,CAM02BB11,CAM02BB12,CAM02BB20,CAM02BB21,CAM02BB22); printf("00=%f 01=%f 11=%f 20=%f 22=%f\n", CAM02BB00,CAM02BB01,CAM02BB11,CAM02BB20,CAM02BB22); - - for (int i=0; ir(i,j); - float g = baseImg->g(i,j); - float b = baseImg->b(i,j); - - float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; - float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; - float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; - float Xcam=CAM02BB00* x +CAM02BB01* y + CAM02BB02* z ; - float Ycam=CAM02BB10* x +CAM02BB11* y + CAM02BB12* z ; - float Zcam=CAM02BB20* x +CAM02BB21* y + CAM02BB22* z ; - baseImg->r(i,j) = xyzto[0][0] * Xcam + xyzto[0][1] * Ycam + xyzto[0][2] * Zcam; - baseImg->g(i,j) = xyzto[1][0] * Xcam + xyzto[1][1] * Ycam + xyzto[1][2] * Zcam; - baseImg->b(i,j) = xyzto[2][0] * Xcam + xyzto[2][1] * Ycam + xyzto[2][2] * Zcam; - } - } + + for (int i=0; ir(i,j); + float g = baseImg->g(i,j); + float b = baseImg->b(i,j); + + float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; + float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; + float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; + float Xcam=CAM02BB00* x +CAM02BB01* y + CAM02BB02* z ; + float Ycam=CAM02BB10* x +CAM02BB11* y + CAM02BB12* z ; + float Zcam=CAM02BB20* x +CAM02BB21* y + CAM02BB22* z ; + baseImg->r(i,j) = xyzto[0][0] * Xcam + xyzto[0][1] * Ycam + xyzto[0][2] * Zcam; + baseImg->g(i,j) = xyzto[1][0] * Xcam + xyzto[1][1] * Ycam + xyzto[1][2] * Zcam; + baseImg->b(i,j) = xyzto[2][0] * Xcam + xyzto[2][1] * Ycam + xyzto[2][2] * Zcam; + } + } } */ -void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* params, LUTu & histogram) { +void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* params, LUTu & histogram) +{ - // set up monitor transform - Glib::ustring wprofile = params->icm.working; - if (monitorTransform) - cmsDeleteTransform (monitorTransform); - monitorTransform = NULL; + // set up monitor transform + Glib::ustring wprofile = params->icm.working; + + if (monitorTransform) { + cmsDeleteTransform (monitorTransform); + } + + monitorTransform = NULL; #if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB - Glib::ustring monitorProfile=settings->monitorProfile; + Glib::ustring monitorProfile = settings->monitorProfile; #if defined(WIN32) - if (settings->autoMonitorProfile) monitorProfile=iccStore->defaultMonitorProfile; + + if (settings->autoMonitorProfile) { + monitorProfile = iccStore->defaultMonitorProfile; + } + #endif - cmsHPROFILE monitor = iccStore->getProfile ("file:"+monitorProfile); - if (monitor) { + cmsHPROFILE monitor = iccStore->getProfile ("file:" + monitorProfile); + + if (monitor) { lcmsMutex->lock (); cmsHPROFILE iprof = cmsCreateLab4Profile(NULL); - monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_DBL, monitor, TYPE_RGB_8, settings->colorimetricIntent, - cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is for thread safety, NOOPTIMIZE for precision + monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_DBL, monitor, TYPE_RGB_8, settings->colorimetricIntent, + cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is for thread safety, NOOPTIMIZE for precision cmsCloseProfile(iprof); lcmsMutex->unlock (); - } -#endif - // calculate histogram of the y channel needed for contrast curve calculation in exposure adjustments + } - int T = 1; +#endif + // calculate histogram of the y channel needed for contrast curve calculation in exposure adjustments + + int T = 1; #ifdef _OPENMP - if(multiThread) - T = omp_get_max_threads(); + + if(multiThread) { + T = omp_get_max_threads(); + } + #endif unsigned int** hist = new unsigned int* [T]; - for (int i=0; iheight; - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = H/nthreads; + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = H / nthreads; - if (tidheight); #endif - histogram.clear(); - for (int j=0; j void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh, int pW, int pwb, LabImage* lab, const ProcParams* params , - const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2,const ColorAppearance & customColCurve3, - LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, double &d, int scalecd, int rtt) + const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2, const ColorAppearance & customColCurve3, + LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, double &d, int scalecd, int rtt) { -if(params->colorappearance.enabled) { + if(params->colorappearance.enabled) { //int lastskip; //if(rtt==1) {lastskip=scalecd;} //not for Rtthumbnail #ifdef _DEBUG - MyTime t1e,t2e; - t1e.set(); + MyTime t1e, t2e; + t1e.set(); #endif - LUTf dLcurve; - LUTu hist16JCAM; - bool jp=false; - float val; - //preparate for histograms CIECAM - if(pW!=1){//only with improccoordinator - dLcurve(65536,0); - dLcurve.clear(); - hist16JCAM(65536,0); - hist16JCAM.clear(); - for (int i=0; i<32768; i++) { //# 32768*1.414 approximation maxi for chroma - val = (double)i / 32767.0; - dLcurve[i] = CLIPD(val); - } - } - LUTf dCcurve; - LUTu hist16_CCAM; - bool chropC=false; - float valc; + LUTf dLcurve; + LUTu hist16JCAM; + bool jp = false; + float val; - if(pW!=1){//only with improccoordinator - dCcurve(65536,0); - hist16_CCAM(65536); - hist16_CCAM.clear(); - for (int i=0; i<48000; i++) { //# 32768*1.414 approximation maxi for chroma - valc = (double)i / 47999.0; - dCcurve[i] = CLIPD(valc); - } - } - //end preparate histogram - int width = lab->W, height = lab->H; - float minQ=10000.f; - float minM=10000.f; - float maxQ= -1000.f; - float maxM= -1000.f; - float w_h; - float a_w; - float c_; - float f_l; - double Yw; - Yw=1.0; - double Xw, Zw; - double f,c,nc,yb,la,xw,yw,zw,f2,c2,nc2,yb2,la2; - double fl,n,nbb,ncb,aw; - double xwd,ywd,zwd; - int alg=0; - bool algepd=false; - float sum=0.f; + //preparate for histograms CIECAM + if(pW != 1) { //only with improccoordinator + dLcurve(65536, 0); + dLcurve.clear(); + hist16JCAM(65536, 0); + hist16JCAM.clear(); - bool ciedata=params->colorappearance.datacie; + for (int i = 0; i < 32768; i++) { //# 32768*1.414 approximation maxi for chroma + val = (double)i / 32767.0; + dLcurve[i] = CLIPD(val); + } + } - ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB - //viewing condition for surround - if(params->colorappearance.surround=="Average") { f = 1.00; c = 0.69; nc = 1.00;f2=1.0,c2=0.69,nc2=1.0;} - else if(params->colorappearance.surround=="Dim"){ f2 = 0.9; c2 = 0.59; nc2 = 0.9;f=1.0,c=0.69,nc=1.0;} - else if(params->colorappearance.surround=="Dark"){f2 = 0.8; c2 = 0.525;nc2 = 0.8;f=1.0,c=0.69,nc=1.0;} - else if(params->colorappearance.surround=="ExtremelyDark"){f2 = 0.8; c2 = 0.41;nc2 = 0.8;f=1.0,c=0.69,nc=1.0;} + LUTf dCcurve; + LUTu hist16_CCAM; + bool chropC = false; + float valc; - //scene condition for surround - if(params->colorappearance.surrsource==true) {f = 0.85; c = 0.55; nc = 0.85;}// if user => source image has surround very dark - //with which algorithme - if (params->colorappearance.algo=="JC") alg=0; - else if(params->colorappearance.algo=="JS") alg=1; - else if(params->colorappearance.algo=="QM") {alg=2;algepd=true;} - else if(params->colorappearance.algo=="ALL") {alg=3;algepd=true;} + if(pW != 1) { //only with improccoordinator + dCcurve(65536, 0); + hist16_CCAM(65536); + hist16_CCAM.clear(); - bool needJ = (alg==0 || alg==1 || alg==3); - bool needQ = (alg==2 || alg==3); - //settings white point of output device - or illuminant viewing - if(settings->viewingdevice==0) {xwd=96.42;ywd=100.0;zwd=82.52;}//5000K - else if(settings->viewingdevice==1) {xwd=95.68;ywd=100.0;zwd=92.15;}//5500 - else if(settings->viewingdevice==2) {xwd=95.24;ywd=100.0;zwd=100.81;}//6000 - else if(settings->viewingdevice==3) {xwd=95.04;ywd=100.0;zwd=108.88;}//6500 - else if(settings->viewingdevice==4) {xwd=109.85;ywd=100.0;zwd=35.58;}//tungsten - else if(settings->viewingdevice==5) {xwd=99.18;ywd=100.0;zwd=67.39;}//fluo F2 - else if(settings->viewingdevice==6) {xwd=95.04;ywd=100.0;zwd=108.75;}//fluo F7 - else if(settings->viewingdevice==7) {xwd=100.96;ywd=100.0;zwd=64.35;}//fluo F11 + for (int i = 0; i < 48000; i++) { //# 32768*1.414 approximation maxi for chroma + valc = (double)i / 47999.0; + dCcurve[i] = CLIPD(valc); + } + } + + //end preparate histogram + int width = lab->W, height = lab->H; + float minQ = 10000.f; + float minM = 10000.f; + float maxQ = -1000.f; + float maxM = -1000.f; + float w_h; + float a_w; + float c_; + float f_l; + double Yw; + Yw = 1.0; + double Xw, Zw; + double f, c, nc, yb, la, xw, yw, zw, f2, c2, nc2, yb2, la2; + double fl, n, nbb, ncb, aw; + double xwd, ywd, zwd; + int alg = 0; + bool algepd = false; + float sum = 0.f; + + bool ciedata = params->colorappearance.datacie; + + ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB + + //viewing condition for surround + if(params->colorappearance.surround == "Average") { + f = 1.00; + c = 0.69; + nc = 1.00; + f2 = 1.0, c2 = 0.69, nc2 = 1.0; + } else if(params->colorappearance.surround == "Dim") { + f2 = 0.9; + c2 = 0.59; + nc2 = 0.9; + f = 1.0, c = 0.69, nc = 1.0; + } else if(params->colorappearance.surround == "Dark") { + f2 = 0.8; + c2 = 0.525; + nc2 = 0.8; + f = 1.0, c = 0.69, nc = 1.0; + } else if(params->colorappearance.surround == "ExtremelyDark") { + f2 = 0.8; + c2 = 0.41; + nc2 = 0.8; + f = 1.0, c = 0.69, nc = 1.0; + } + + //scene condition for surround + if(params->colorappearance.surrsource == true) { + f = 0.85; // if user => source image has surround very dark + c = 0.55; + nc = 0.85; + } + + //with which algorithme + if (params->colorappearance.algo == "JC") { + alg = 0; + } else if(params->colorappearance.algo == "JS") { + alg = 1; + } else if(params->colorappearance.algo == "QM") { + alg = 2; + algepd = true; + } else if(params->colorappearance.algo == "ALL") { + alg = 3; + algepd = true; + } + + bool needJ = (alg == 0 || alg == 1 || alg == 3); + bool needQ = (alg == 2 || alg == 3); + + //settings white point of output device - or illuminant viewing + if(settings->viewingdevice == 0) { + xwd = 96.42; //5000K + ywd = 100.0; + zwd = 82.52; + } else if(settings->viewingdevice == 1) { + xwd = 95.68; //5500 + ywd = 100.0; + zwd = 92.15; + } else if(settings->viewingdevice == 2) { + xwd = 95.24; //6000 + ywd = 100.0; + zwd = 100.81; + } else if(settings->viewingdevice == 3) { + xwd = 95.04; //6500 + ywd = 100.0; + zwd = 108.88; + } else if(settings->viewingdevice == 4) { + xwd = 109.85; //tungsten + ywd = 100.0; + zwd = 35.58; + } else if(settings->viewingdevice == 5) { + xwd = 99.18; //fluo F2 + ywd = 100.0; + zwd = 67.39; + } else if(settings->viewingdevice == 6) { + xwd = 95.04; //fluo F7 + ywd = 100.0; + zwd = 108.75; + } else if(settings->viewingdevice == 7) { + xwd = 100.96; //fluo F11 + ywd = 100.0; + zwd = 64.35; + } - //settings mean Luminance Y of output device or viewing - if(settings->viewingdevicegrey==0) {yb2=5.0;} - else if(settings->viewingdevicegrey==1) {yb2=10.0;} - else if(settings->viewingdevicegrey==2) {yb2=15.0;} - else if(settings->viewingdevicegrey==3) {yb2=18.0;} - else if(settings->viewingdevicegrey==4) {yb2=23.0;} - else if(settings->viewingdevicegrey==5) {yb2=30.0;} - else if(settings->viewingdevicegrey==6) {yb2=40.0;} + //settings mean Luminance Y of output device or viewing + if(settings->viewingdevicegrey == 0) { + yb2 = 5.0; + } else if(settings->viewingdevicegrey == 1) { + yb2 = 10.0; + } else if(settings->viewingdevicegrey == 2) { + yb2 = 15.0; + } else if(settings->viewingdevicegrey == 3) { + yb2 = 18.0; + } else if(settings->viewingdevicegrey == 4) { + yb2 = 23.0; + } else if(settings->viewingdevicegrey == 5) { + yb2 = 30.0; + } else if(settings->viewingdevicegrey == 6) { + yb2 = 40.0; + } - //La and la2 = ambiant luminosity scene and viewing - la=double(params->colorappearance.adapscen); - if(pwb==2){ - if(params->colorappearance.autoadapscen) la=adap; - } - - la2=double(params->colorappearance.adaplum); + //La and la2 = ambiant luminosity scene and viewing + la = double(params->colorappearance.adapscen); - // level of adaptation - double deg=(params->colorappearance.degree)/100.0; - double pilot=params->colorappearance.autodegree ? 2.0 : deg; + if(pwb == 2) { + if(params->colorappearance.autoadapscen) { + la = adap; + } + } - //algoritm's params - float jli=params->colorappearance.jlight; - float chr=params->colorappearance.chroma; - float contra=params->colorappearance.contrast; - float qbri=params->colorappearance.qbright; - float schr=params->colorappearance.schroma; - float mchr=params->colorappearance.mchroma; - float qcontra=params->colorappearance.qcontrast; - float hue=params->colorappearance.colorh; - double rstprotection = 100.-params->colorappearance.rstprotection; - if(schr>0.0) schr=schr/2.0f;//divide sensibility for saturation + la2 = double(params->colorappearance.adaplum); - // extracting datas from 'params' to avoid cache flush (to be confirmed) - ColorAppearanceParams::eTCModeId curveMode = params->colorappearance.curveMode; - ColorAppearanceParams::eTCModeId curveMode2 = params->colorappearance.curveMode2; - bool hasColCurve1 = bool(customColCurve1); - bool hasColCurve2 = bool(customColCurve2); - ColorAppearanceParams::eCTCModeId curveMode3 = params->colorappearance.curveMode3; - bool hasColCurve3 = bool(customColCurve3); + // level of adaptation + double deg = (params->colorappearance.degree) / 100.0; + double pilot = params->colorappearance.autodegree ? 2.0 : deg; + + //algoritm's params + float jli = params->colorappearance.jlight; + float chr = params->colorappearance.chroma; + float contra = params->colorappearance.contrast; + float qbri = params->colorappearance.qbright; + float schr = params->colorappearance.schroma; + float mchr = params->colorappearance.mchroma; + float qcontra = params->colorappearance.qcontrast; + float hue = params->colorappearance.colorh; + double rstprotection = 100. - params->colorappearance.rstprotection; + + if(schr > 0.0) { + schr = schr / 2.0f; //divide sensibility for saturation + } + + // extracting datas from 'params' to avoid cache flush (to be confirmed) + ColorAppearanceParams::eTCModeId curveMode = params->colorappearance.curveMode; + ColorAppearanceParams::eTCModeId curveMode2 = params->colorappearance.curveMode2; + bool hasColCurve1 = bool(customColCurve1); + bool hasColCurve2 = bool(customColCurve2); + ColorAppearanceParams::eCTCModeId curveMode3 = params->colorappearance.curveMode3; + bool hasColCurve3 = bool(customColCurve3); - if(CAMBrightCurveJ.dirty || CAMBrightCurveQ.dirty){ - LUTu hist16J; - LUTu hist16Q; - if (needJ) { - hist16J (65536); - hist16J.clear(); - } - if (needQ) { - hist16Q (65536); - hist16Q.clear(); - } - float koef=1.0f;//rough correspondence between L and J - for (int i=0; iL[i][j]/327.68f; - if (currL>95.) koef=1.f; - else if(currL>85.) koef=0.97f; - else if(currL>80.) koef=0.93f; - else if(currL>70.) koef=0.87f; - else if(currL>60.) koef=0.85f; - else if(currL>50.) koef=0.8f; - else if(currL>40.) koef=0.75f; - else if(currL>30.) koef=0.7f; - else if(currL>20.) koef=0.7f; - else if(currL>10.) koef=0.9f; - else if(currL>0.) koef=1.0f; + if(CAMBrightCurveJ.dirty || CAMBrightCurveQ.dirty) { + LUTu hist16J; + LUTu hist16Q; - if (needJ) - hist16J[CLIP((int)((koef*lab->L[i][j])))]++;//evaluate histogram luminance L # J - if (needQ) - hist16Q[CLIP((int) (32768.f*sqrt((koef*(lab->L[i][j]))/32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L - sum+=koef*lab->L[i][j];//evaluate mean J to calcualte Yb - } - //mean=(sum/((endh-begh)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone - mean=(sum/((height)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone + if (needJ) { + hist16J (65536); + hist16J.clear(); + } - //evaluate lightness, contrast - if (needJ) { - if (!CAMBrightCurveJ) { - CAMBrightCurveJ(65536,0); - CAMBrightCurveJ.dirty = false; - } - Ciecam02::curveJ (jli, contra, 1, CAMBrightCurveJ, hist16J);//lightness and contrast J - } - if (needQ) { - if (!CAMBrightCurveQ) { - CAMBrightCurveQ(65536,0); - CAMBrightCurveQ.dirty = false; - } - Ciecam02::curveJ (qbri, qcontra, 1, CAMBrightCurveQ, hist16Q);//brightness and contrast Q - } - } -if(settings->viewinggreySc==0){//auto - if (mean<15.f) yb=3.0; - else if(mean<30.f) yb=5.0; - else if(mean<40.f) yb=10.0; - else if(mean<45.f) yb=15.0; - else if(mean<50.f) yb=18.0; - else if(mean<55.f) yb=23.0; - else if(mean<60.f) yb=30.0; - else if(mean<70.f) yb=40.0; - else if(mean<80.f) yb=60.0; - else if(mean<90.f) yb=80.0; - else yb=90.0; -} -if(settings->viewinggreySc==1) yb=18.0; + if (needQ) { + hist16Q (65536); + hist16Q.clear(); + } - int gamu=0; - bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated + float koef = 1.0f; //rough correspondence between L and J - if(params->colorappearance.gamut==true) gamu=1;//enabled gamut control - xw=100.0*Xw; - yw=100.0*Yw; - zw=100.0*Zw; - double xw1,yw1,zw1,xw2,yw2,zw2; - // settings of WB: scene and viewing - if(params->colorappearance.wbmodel=="RawT") {xw1=96.46;yw1=100.0;zw1=82.445;xw2=xwd;yw2=ywd;zw2=zwd;} //use RT WB; CAT 02 is used for output device (see prefreneces) - else if(params->colorappearance.wbmodel=="RawTCAT02") {xw1=xw;yw1=yw;zw1=zw;xw2=xwd;yw2=ywd;zw2=zwd;} // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences - double cz,wh, pfl; - Ciecam02::initcam1(gamu, yb, pilot, f, la,xw, yw, zw, n, d, nbb, ncb,cz, aw, wh, pfl, fl, c); - double nj,dj,nbbj,ncbj,czj,awj,flj; - Ciecam02::initcam2(gamu,yb2, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj,czj, awj, flj); + for (int i = 0; i < height; i++) + + // for (int i=begh; iL[i][j] / 327.68f; + + if (currL > 95.) { + koef = 1.f; + } else if(currL > 85.) { + koef = 0.97f; + } else if(currL > 80.) { + koef = 0.93f; + } else if(currL > 70.) { + koef = 0.87f; + } else if(currL > 60.) { + koef = 0.85f; + } else if(currL > 50.) { + koef = 0.8f; + } else if(currL > 40.) { + koef = 0.75f; + } else if(currL > 30.) { + koef = 0.7f; + } else if(currL > 20.) { + koef = 0.7f; + } else if(currL > 10.) { + koef = 0.9f; + } else if(currL > 0.) { + koef = 1.0f; + } + + if (needJ) { + hist16J[CLIP((int)((koef * lab->L[i][j])))]++; //evaluate histogram luminance L # J + } + + if (needQ) { + hist16Q[CLIP((int) (32768.f * sqrt((koef * (lab->L[i][j])) / 32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L + } + + sum += koef * lab->L[i][j]; //evaluate mean J to calcualte Yb + } + + //mean=(sum/((endh-begh)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone + mean = (sum / ((height) * width)) / 327.68f; //for Yb for all image...if one day "pipette" we can adapt Yb for each zone + + //evaluate lightness, contrast + if (needJ) { + if (!CAMBrightCurveJ) { + CAMBrightCurveJ(65536, 0); + CAMBrightCurveJ.dirty = false; + } + + Ciecam02::curveJ (jli, contra, 1, CAMBrightCurveJ, hist16J);//lightness and contrast J + } + + if (needQ) { + if (!CAMBrightCurveQ) { + CAMBrightCurveQ(65536, 0); + CAMBrightCurveQ.dirty = false; + } + + Ciecam02::curveJ (qbri, qcontra, 1, CAMBrightCurveQ, hist16Q);//brightness and contrast Q + } + } + + if(settings->viewinggreySc == 0) { //auto + if (mean < 15.f) { + yb = 3.0; + } else if(mean < 30.f) { + yb = 5.0; + } else if(mean < 40.f) { + yb = 10.0; + } else if(mean < 45.f) { + yb = 15.0; + } else if(mean < 50.f) { + yb = 18.0; + } else if(mean < 55.f) { + yb = 23.0; + } else if(mean < 60.f) { + yb = 30.0; + } else if(mean < 70.f) { + yb = 40.0; + } else if(mean < 80.f) { + yb = 60.0; + } else if(mean < 90.f) { + yb = 80.0; + } else { + yb = 90.0; + } + } + + if(settings->viewinggreySc == 1) { + yb = 18.0; + } + + int gamu = 0; + bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated + + if(params->colorappearance.gamut == true) { + gamu = 1; //enabled gamut control + } + + xw = 100.0 * Xw; + yw = 100.0 * Yw; + zw = 100.0 * Zw; + double xw1, yw1, zw1, xw2, yw2, zw2; + + // settings of WB: scene and viewing + if(params->colorappearance.wbmodel == "RawT") { + xw1 = 96.46; //use RT WB; CAT 02 is used for output device (see prefreneces) + yw1 = 100.0; + zw1 = 82.445; + xw2 = xwd; + yw2 = ywd; + zw2 = zwd; + } else if(params->colorappearance.wbmodel == "RawTCAT02") { + xw1 = xw; // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences + yw1 = yw; + zw1 = zw; + xw2 = xwd; + yw2 = ywd; + zw2 = zwd; + } + + double cz, wh, pfl; + Ciecam02::initcam1(gamu, yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c); + double nj, dj, nbbj, ncbj, czj, awj, flj; + Ciecam02::initcam2(gamu, yb2, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj); #ifndef _DEBUG -#pragma omp parallel default(shared) firstprivate(lab,xw1,xw2,yw1,yw2,zw1,zw2,pilot,jli,chr,yb,la,yb2,la2,fl,nc,f,c, height,width,begh, endh,nc2,f2,c2, alg,algepd, gamu, highlight, rstprotection, pW, scalecd) + #pragma omp parallel default(shared) firstprivate(lab,xw1,xw2,yw1,yw2,zw1,zw2,pilot,jli,chr,yb,la,yb2,la2,fl,nc,f,c, height,width,begh, endh,nc2,f2,c2, alg,algepd, gamu, highlight, rstprotection, pW, scalecd) #endif -{ //matrix for current working space - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; + { + //matrix for current working space + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; #ifndef _DEBUG -#pragma omp for schedule(dynamic, 10) + #pragma omp for schedule(dynamic, 10) #endif - for (int i=0; iL[i][j]; - float a=lab->a[i][j]; - float b=lab->b[i][j]; - float x1,y1,z1; - double x,y,z; - double epsil=0.0001; - //convert Lab => XYZ - Color::Lab2XYZ(L, a, b, x1, y1, z1); - // double J, C, h, Q, M, s, aw, fl, wh; - double J, C, h, Q, M, s; + for (int i = 0; i < height; i++) - double Jpro,Cpro, hpro, Qpro, Mpro, spro; - bool t1L=false; - bool t1B=false; - bool t2B=false; - int c1s=0; - int c1co=0; - //double n,nbb,ncb,pfl,cz,d; - x=(double)x1/655.35; - y=(double)y1/655.35; - z=(double)z1/655.35; - //process source==> normal - Ciecam02::xyz2jchqms_ciecam02( J, C, h, - Q, M, s, aw, fl, wh, - x, y, z, - xw1, yw1, zw1, - yb, la, - f, c, nc, pilot, gamu , n, nbb, ncb, pfl, cz, d ); - Jpro=J; - Cpro=C; - hpro=h; - Qpro=Q; - Mpro=M; - spro=s; - w_h=wh+epsil; - a_w=aw; - c_=c; - f_l=fl; - // we cannot have all algoritms with all chroma curves - if(alg==1) { - // Lightness saturation - if(Jpro > 99.9f) - Jpro = 99.9f; - Jpro=(CAMBrightCurveJ[(float)(Jpro*327.68)])/327.68;//ligthness CIECAM02 + contrast - double sres; - double Sp=spro/100.0; - double parsat=1.5; - parsat=1.5;//parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation) - if(schr==-100.0) schr=-99.8; - Ciecam02::curvecolor(schr, Sp , sres, parsat); - double coe=pow(fl,0.25); - float dred=100.f;// in C mode - float protect_red=80.0f; // in C mode - dred = 100.0 * sqrt((dred*coe)/Qpro); - protect_red=100.0 * sqrt((protect_red*coe)/Qpro); - int sk=0; - float ko=100.f; - Color::skinred(Jpro, hpro, sres, Sp, dred, protect_red,sk,rstprotection,ko, spro); - Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; - Cpro=(spro*spro*Qpro)/(10000.0); - } - else if(alg==3 || alg==0 || alg==2) { - double coef=32760./wh; - if(alg==3 || alg==2) { - if(Qpro*coef > 32767.0f) - Qpro=(CAMBrightCurveQ[(float)32767.0f])/coef;//brightness and contrast - else - Qpro=(CAMBrightCurveQ[(float)(Qpro*coef)])/coef;//brightness and contrast - } - double Mp, sres; - double coe=pow(fl,0.25); - Mp=Mpro/100.0; - double parsat=2.5; - if(mchr==-100.0) mchr=-99.8 ; - if(mchr==100.0) mchr=99.9; - if(alg==3 || alg==2) Ciecam02::curvecolor(mchr, Mp , sres, parsat); else Ciecam02::curvecolor(0.0, Mp , sres, parsat);//colorfullness - float dred=100.f;//in C mode - float protect_red=80.0f;// in C mode - dred *=coe;//in M mode - protect_red *=coe;//M mode - int sk=0; - float ko=100.f; - Color::skinred(Jpro, hpro, sres, Mp, dred, protect_red,sk,rstprotection,ko, Mpro); - Jpro=(100.0* Qpro*Qpro) /(wh*wh); - Cpro= Mpro/coe; - spro = 100.0 * sqrt( Mpro / Qpro ); - if(alg!=2) { - if(Jpro > 99.9f) - Jpro = 99.9f; - Jpro=(CAMBrightCurveJ[(float)(Jpro*327.68f)])/327.68f;//ligthness CIECAM02 + contrast - } - double Cp; - double Sp=spro/100.0; - parsat=1.5; - if(schr==-100.0) schr=-99.; - if(schr==100.0) schr=98.; - if(alg==3) Ciecam02::curvecolor(schr, Sp , sres, parsat); else Ciecam02::curvecolor(0.0, Sp , sres, parsat); //saturation - dred=100.f;// in C mode - protect_red=80.0f; // in C mode - dred = 100.0 * sqrt((dred*coe)/Q); - protect_red=100.0 * sqrt((protect_red*coe)/Q); - sk=0; - Color::skinred(Jpro, hpro, sres, Sp, dred, protect_red,sk,rstprotection,ko, spro); - //double Q1; - Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; - Cpro=(spro*spro*Qpro)/(10000.0); - Cp=Cpro/100.0; - parsat=1.8;//parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation : for not) - if(chr==-100.0) chr=-99.8; - if(alg!=2) Ciecam02::curvecolor(chr, Cp , sres, parsat);else Ciecam02::curvecolor(0.0, Cp , sres, parsat); //chroma - dred=55.f; - protect_red=30.0f; - sk=1; - Color::skinred(Jpro, hpro, sres, Cp, dred, protect_red,sk,rstprotection, ko, Cpro); - if(Jpro < 1. && Cpro > 12.) Cpro=12.;//reduce artifacts by "pseudo gamut control CIECAM" - else if(Jpro < 2. && Cpro > 15.) Cpro=15.; - else if(Jpro < 4. && Cpro > 30.) Cpro=30.; - else if(Jpro < 7. && Cpro > 50.) Cpro=50.; +// for (int i=begh; iL[i][j]; + float a = lab->a[i][j]; + float b = lab->b[i][j]; + float x1, y1, z1; + double x, y, z; + double epsil = 0.0001; + //convert Lab => XYZ + Color::Lab2XYZ(L, a, b, x1, y1, z1); + // double J, C, h, Q, M, s, aw, fl, wh; + double J, C, h, Q, M, s; - if (hasColCurve1) {//curve 1 with Lightness and Brightness - if (curveMode==ColorAppearanceParams::TC_MODE_LIGHT){ - /* float Jj=(float) Jpro*327.68; - float Jold=Jj; - const Lightcurve& userColCurve = static_cast(customColCurve1); - userColCurve.Apply(Jj); - Jj=0.7f*(Jj-Jold)+Jold;//divide sensibility - */ - float Jj=(float) Jpro*327.68f; - float Jold=Jj; - float Jold100=(float) Jpro; - float redu=25.f; - float reduc=1.f; - const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); - userColCurveJ1.Apply(Jj); - if(Jj>Jold) { - if(Jj<65535.f) { - if(Jold < 327.68f*redu) Jj=0.3f*(Jj-Jold)+Jold;//divide sensibility - else { - reduc=LIM((100.f-Jold100)/(100.f-redu),0.f,1.f); - Jj=0.3f*reduc*(Jj-Jold)+Jold;//reduct sensibility in highlights - } - } - } - else if(Jj>10.f) Jj=0.8f*(Jj-Jold)+Jold; - else if (Jj>=0.f) Jj=0.90f*(Jj-Jold)+Jold;// not zero ==>artifacts - - - Jpro=(double)(Jj/327.68f); - if(Jpro < 1.) Jpro=1.; - t1L=true; - } - else if (curveMode==ColorAppearanceParams::TC_MODE_BRIGHT){ - //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different - float coef=((aw+4.f)*(4.f/c))/100.f; - float Qq=(float) Qpro*327.68f*(1.f/coef); - float Qold100=(float) Qpro/coef; - - float Qold=Qq; - float redu=20.f; - float reduc=1.f; - - const Brightcurve& userColCurveB1 = static_cast(customColCurve1); - userColCurveB1.Apply(Qq); - if(Qq>Qold) { - if(Qq<65535.f) { - if(Qold < 327.68f*redu) Qq=0.25f*(Qq-Qold)+Qold;//divide sensibility - else { - reduc=LIM((100.f-Qold100)/(100.f-redu),0.f,1.f); - Qq=0.25f*reduc*(Qq-Qold)+Qold;//reduct sensibility in highlights - } - } - } - else if(Qq>10.f) Qq=0.5f*(Qq-Qold)+Qold; - else if (Qq>=0.f) Qq=0.7f*(Qq-Qold)+Qold;// not zero ==>artifacts - Qpro=(double)(Qq*(coef)/327.68f); - Jpro=100.*(Qpro*Qpro)/((4.0/c)*(4.0/c)*(aw+4.0)*(aw+4.0)); - t1B=true; - if(Jpro < 1.) Jpro=1.; - - } - } + double Jpro, Cpro, hpro, Qpro, Mpro, spro; + bool t1L = false; + bool t1B = false; + bool t2B = false; + int c1s = 0; + int c1co = 0; + //double n,nbb,ncb,pfl,cz,d; + x = (double)x1 / 655.35; + y = (double)y1 / 655.35; + z = (double)z1 / 655.35; + //process source==> normal + Ciecam02::xyz2jchqms_ciecam02( J, C, h, + Q, M, s, aw, fl, wh, + x, y, z, + xw1, yw1, zw1, + yb, la, + f, c, nc, pilot, gamu , n, nbb, ncb, pfl, cz, d ); + Jpro = J; + Cpro = C; + hpro = h; + Qpro = Q; + Mpro = M; + spro = s; + w_h = wh + epsil; + a_w = aw; + c_ = c; + f_l = fl; - if (hasColCurve2) {//curve 2 with Lightness and Brightness - if (curveMode2==ColorAppearanceParams::TC_MODE_LIGHT){ - float Jj=(float) Jpro*327.68; - float Jold=Jj; - /* - const Lightcurve& userColCurve = static_cast(customColCurve2); - userColCurve.Apply(Jj); - Jj=0.7f*(Jj-Jold)+Jold;//divide sensibility - */ - float Jold100=(float) Jpro; - float redu=25.f; - float reduc=1.f; - const Lightcurve& userColCurveJ2 = static_cast(customColCurve2); - userColCurveJ2.Apply(Jj); - if(Jj>Jold) { - if(Jj<65535.f) { - if(Jold < 327.68f*redu) Jj=0.3f*(Jj-Jold)+Jold;//divide sensibility - else { - reduc=LIM((100.f-Jold100)/(100.f-redu),0.f,1.f); - Jj=0.3f*reduc*(Jj-Jold)+Jold;//reduct sensibility in highlights - } - } - } - else if(Jj>10.f) {if(!t1L)Jj=0.8f*(Jj-Jold)+Jold;else Jj=0.4f*(Jj-Jold)+Jold;} - else if (Jj>=0.f){if(!t1L)Jj=0.90f*(Jj-Jold)+Jold;else Jj=0.5f*(Jj-Jold)+Jold;}// not zero ==>artifacts - - Jpro=(double)(Jj/327.68f); - if(Jpro < 1.) Jpro=1.; - - } - else if (curveMode2==ColorAppearanceParams::TC_MODE_BRIGHT){ // - float coef=((aw+4.f)*(4.f/c))/100.f; - float Qq=(float) Qpro*327.68f*(1.f/coef); - float Qold100=(float) Qpro/coef; - - float Qold=Qq; - float redu=20.f; - float reduc=1.f; - - const Brightcurve& userColCurveB2 = static_cast(customColCurve2); - userColCurveB2.Apply(Qq); - if(Qq>Qold) { - if(Qq<65535.f) { - if(Qold < 327.68f*redu) Qq=0.25f*(Qq-Qold)+Qold;//divide sensibility - else { - reduc=LIM((100.f-Qold100)/(100.f-redu),0.f,1.f); - Qq=0.25f*reduc*(Qq-Qold)+Qold;//reduct sensibility in highlights - } - } - } - else if(Qq>10.f) Qq=0.5f*(Qq-Qold)+Qold; - else if (Qq>=0.f) Qq=0.7f*(Qq-Qold)+Qold;// not zero ==>artifacts - Qpro=(double)(Qq*(coef)/327.68f); - Jpro=100.*(Qpro*Qpro)/((4.0/c)*(4.0/c)*(aw+4.0)*(aw+4.0)); - t2B=true; - - if(t1L){//to workaround the problem if we modify curve1-lightnees after curve2 brightness(the cat that bites its own tail!) in fact it's another type of curve only for this case - coef=2.f;//adapt Q to J approximation - Qq=(float) Qpro*coef; - Qold=Qq; - const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); - userColCurveJ1.Apply(Qq); - Qq=0.1f*(Qq-Qold)+Qold;//approximative adaptation - Qpro=(double)(Qq/coef); - Jpro=100.*(Qpro*Qpro)/((4.0/c)*(4.0/c)*(aw+4.0)*(aw+4.0)); - } - if(Jpro < 1.) Jpro=1.; - } - } + // we cannot have all algoritms with all chroma curves + if(alg == 1) { + // Lightness saturation + if(Jpro > 99.9f) { + Jpro = 99.9f; + } - if (hasColCurve3) {//curve 3 with chroma saturation colorfullness - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA){ - double parsat=0.8;//0.68; - double coef=327.68/parsat; - float Cc=(float) Cpro*coef; - float Ccold=Cc; - const Chromacurve& userColCurve = static_cast(customColCurve3); - userColCurve.Apply(Cc); - float dred=55.f; - float protect_red=30.0f; - float sk=1; - float ko=1.f/coef; - Color::skinred(Jpro, hpro, Cc, Ccold, dred, protect_red,sk,rstprotection,ko, Cpro); - if(Jpro < 1. && Cpro > 12.) Cpro=12.;//reduce artifacts by "pseudo gamut control CIECAM" - else if(Jpro < 2. && Cpro > 15.) Cpro=15.; - else if(Jpro < 4. && Cpro > 30.) Cpro=30.; - else if(Jpro < 7. && Cpro > 50.) Cpro=50.; - - // Cpro=Cc/coef; - } - else if (curveMode3==ColorAppearanceParams::TC_MODE_SATUR){ // - double parsat=0.8;//0.6 - double coef=327.68/parsat; - float Ss=(float) spro*coef; - float Sold=Ss; - const Saturcurve& userColCurve = static_cast(customColCurve3); - userColCurve.Apply(Ss); - Ss=0.6f*(Ss-Sold)+Sold;//divide sensibility saturation - double coe=pow(fl,0.25); - float dred=100.f;// in C mode - float protect_red=80.0f; // in C mode - dred = 100.0 * sqrt((dred*coe)/Qpro); - protect_red=100.0 * sqrt((protect_red*coe)/Qpro); - int sk=0; - float ko=1.f/coef; - Color::skinred(Jpro, hpro, Ss, Sold, dred, protect_red,sk,rstprotection,ko, spro); - Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; - Cpro=(spro*spro*Qpro)/(10000.0); - c1s=1; + Jpro = (CAMBrightCurveJ[(float)(Jpro * 327.68)]) / 327.68; //ligthness CIECAM02 + contrast + double sres; + double Sp = spro / 100.0; + double parsat = 1.5; + parsat = 1.5; //parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation) - } - else if (curveMode3==ColorAppearanceParams::TC_MODE_COLORF){ // - double parsat=0.8;//0.68; - double coef=327.68/parsat; - float Mm=(float) Mpro*coef; - float Mold=Mm; - const Colorfcurve& userColCurve = static_cast(customColCurve3); - userColCurve.Apply(Mm); - double coe=pow(fl,0.25); - float dred=100.f;//in C mode - float protect_red=80.0f;// in C mode - dred *=coe;//in M mode - protect_red *=coe; - int sk=0; - float ko=1.f/coef; - Color::skinred(Jpro, hpro, Mm, Mold, dred, protect_red,sk,rstprotection,ko, Mpro); - Cpro= Mpro/coe; - if(Jpro < 1. && Mpro > 12.*coe) Mpro=12.*coe;//reduce artifacts by "pseudo gamut control CIECAM" - else if(Jpro < 2. && Mpro > 15.*coe) Mpro=15.*coe; - else if(Jpro < 4. && Mpro > 30.*coe) Mpro=30.*coe; - else if(Jpro < 7. && Mpro > 50.*coe) Mpro=50.*coe; - - - c1co=1; - } - } - //to retrieve the correct values of variables - if(t2B && t1B) Jpro=(100.0* Qpro*Qpro) /(wh*wh);// for brightness curve - if(c1s==1) { - Qpro= ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ;//for saturation curve - Cpro=(spro*spro*Qpro)/(10000.0); - } - if(c1co==1) { double coe=pow(fl,0.25);Cpro= Mpro/coe;} // for colorfullness curve - //retrieve values C,J...s - C=Cpro; - J=Jpro; - Q=Qpro; - M=Mpro; - h=hpro; - s=spro; + if(schr == -100.0) { + schr = -99.8; + } - if(params->colorappearance.tonecie || settings->autocielab){//use pointer for tonemapping with CIECAM and also sharpening , defringe, contrast detail - // if(params->colorappearance.tonecie || params->colorappearance.sharpcie){//use pointer for tonemapping with CIECAM and also sharpening , defringe, contrast detail - float Qred= ( 4.0 / c) * ( aw + 4.0 );//estimate Q max if J=100.0 - ncie->Q_p[i][j]=(float)Q+epsil;//epsil to avoid Q=0 - ncie->M_p[i][j]=(float)M+epsil; - ncie->J_p[i][j]=(float)J+epsil; - ncie->h_p[i][j]=(float)h; - ncie->C_p[i][j]=(float)C+epsil; - // ncie->s_p[i][j]=(float)s; - ncie->sh_p[i][j]=(float) 32768.*(( 4.0 / c )*sqrt( J / 100.0 ) * ( aw + 4.0 ))/Qred ; - // ncie->ch_p[i][j]=(float) 327.68*C; - if(ncie->Q_p[i][j]Q_p[i][j];//minima - if(ncie->Q_p[i][j]>maxQ) maxQ=ncie->Q_p[i][j];//maxima - } - if(!params->colorappearance.tonecie || !settings->autocielab || !params->epd.enabled ){ - -// if(!params->epd.enabled || !params->colorappearance.tonecie || !settings->autocielab){ - // if(!params->epd.enabled || !params->colorappearance.tonecie || !params->colorappearance.sharpcie){ - int posl, posc; - double brli=327.; - double chsacol=327.; - int libr=0; - int colch=0; - if(curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) {brli=70.0; libr=1;} - else if(curveMode==ColorAppearanceParams::TC_MODE_LIGHT) {brli=327.;libr=0;} - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA) {chsacol=327.;colch=0;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_SATUR) {chsacol=450.0;colch=1;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_COLORF) {chsacol=327.0;colch=2;} - if(ciedata) { - // Data for J Q M s and C histograms - //update histogram - jp=true; - if(pW!=1){//only with improccoordinator - if(libr==1) posl=CLIP((int)(Q*brli));//40.0 to 100.0 approximative factor for Q - 327 for J - else if(libr==0) posl=CLIP((int)(J*brli));//327 for J - hist16JCAM[posl]++; - } - chropC=true; - if(pW!=1){//only with improccoordinator - if(colch==0) posc=CLIP((int)(C*chsacol));//450.0 approximative factor for s 320 for M - else if(colch==1) posc=CLIP((int)(s*chsacol)); - else if(colch==2) posc=CLIP((int)(M*chsacol)); - hist16_CCAM[posc]++; - } - } - double xx,yy,zz; - //double nj, nbbj, ncbj, flj, czj, dj, awj; - //process normal==> viewing - Ciecam02::jch2xyz_ciecam02( xx, yy, zz, - J, C, h, - xw2, yw2, zw2, - yb2, la2, - f2, c2, nc2, gamu, nj, nbbj, ncbj, flj, czj, dj, awj); - x=(float)xx*655.35; - y=(float)yy*655.35; - z=(float)zz*655.35; - float Ll,aa,bb; - //convert xyz=>lab - Color::XYZ2Lab(x, y, z, Ll, aa, bb); - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; - // gamut control in Lab mode; I must study how to do with cIECAM only - if(gamu==1) { - float R,G,B; - float HH, Lprov1, Chprov1; - Lprov1=lab->L[i][j]/327.68f; - Chprov1=sqrt(SQR(lab->a[i][j]/327.68f) + SQR(lab->b[i][j]/327.68f)); - HH=atan2(lab->b[i][j],lab->a[i][j]); + Ciecam02::curvecolor(schr, Sp , sres, parsat); + double coe = pow(fl, 0.25); + float dred = 100.f; // in C mode + float protect_red = 80.0f; // in C mode + dred = 100.0 * sqrt((dred * coe) / Qpro); + protect_red = 100.0 * sqrt((protect_red * coe) / Qpro); + int sk = 0; + float ko = 100.f; + Color::skinred(Jpro, hpro, sres, Sp, dred, protect_red, sk, rstprotection, ko, spro); + Qpro = ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; + Cpro = (spro * spro * Qpro) / (10000.0); + } else if(alg == 3 || alg == 0 || alg == 2) { + double coef = 32760. / wh; + + if(alg == 3 || alg == 2) { + if(Qpro * coef > 32767.0f) { + Qpro = (CAMBrightCurveQ[(float)32767.0f]) / coef; //brightness and contrast + } else { + Qpro = (CAMBrightCurveQ[(float)(Qpro * coef)]) / coef; //brightness and contrast + } + } + + double Mp, sres; + double coe = pow(fl, 0.25); + Mp = Mpro / 100.0; + double parsat = 2.5; + + if(mchr == -100.0) { + mchr = -99.8 ; + } + + if(mchr == 100.0) { + mchr = 99.9; + } + + if(alg == 3 || alg == 2) { + Ciecam02::curvecolor(mchr, Mp , sres, parsat); + } else { + Ciecam02::curvecolor(0.0, Mp , sres, parsat); //colorfullness + } + + float dred = 100.f; //in C mode + float protect_red = 80.0f; // in C mode + dred *= coe; //in M mode + protect_red *= coe; //M mode + int sk = 0; + float ko = 100.f; + Color::skinred(Jpro, hpro, sres, Mp, dred, protect_red, sk, rstprotection, ko, Mpro); + Jpro = (100.0 * Qpro * Qpro) / (wh * wh); + Cpro = Mpro / coe; + spro = 100.0 * sqrt( Mpro / Qpro ); + + if(alg != 2) { + if(Jpro > 99.9f) { + Jpro = 99.9f; + } + + Jpro = (CAMBrightCurveJ[(float)(Jpro * 327.68f)]) / 327.68f; //ligthness CIECAM02 + contrast + } + + double Cp; + double Sp = spro / 100.0; + parsat = 1.5; + + if(schr == -100.0) { + schr = -99.; + } + + if(schr == 100.0) { + schr = 98.; + } + + if(alg == 3) { + Ciecam02::curvecolor(schr, Sp , sres, parsat); + } else { + Ciecam02::curvecolor(0.0, Sp , sres, parsat); //saturation + } + + dred = 100.f; // in C mode + protect_red = 80.0f; // in C mode + dred = 100.0 * sqrt((dred * coe) / Q); + protect_red = 100.0 * sqrt((protect_red * coe) / Q); + sk = 0; + Color::skinred(Jpro, hpro, sres, Sp, dred, protect_red, sk, rstprotection, ko, spro); + //double Q1; + Qpro = ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; + Cpro = (spro * spro * Qpro) / (10000.0); + Cp = Cpro / 100.0; + parsat = 1.8; //parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation : for not) + + if(chr == -100.0) { + chr = -99.8; + } + + if(alg != 2) { + Ciecam02::curvecolor(chr, Cp , sres, parsat); + } else { + Ciecam02::curvecolor(0.0, Cp , sres, parsat); //chroma + } + + dred = 55.f; + protect_red = 30.0f; + sk = 1; + Color::skinred(Jpro, hpro, sres, Cp, dred, protect_red, sk, rstprotection, ko, Cpro); + + if(Jpro < 1. && Cpro > 12.) { + Cpro = 12.; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2. && Cpro > 15.) { + Cpro = 15.; + } else if(Jpro < 4. && Cpro > 30.) { + Cpro = 30.; + } else if(Jpro < 7. && Cpro > 50.) { + Cpro = 50.; + } + + hpro = hpro + hue; + + if( hpro < 0.0 ) { + hpro += 360.0; //hue + } + } + + if (hasColCurve1) {//curve 1 with Lightness and Brightness + if (curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + /* float Jj=(float) Jpro*327.68; + float Jold=Jj; + const Lightcurve& userColCurve = static_cast(customColCurve1); + userColCurve.Apply(Jj); + Jj=0.7f*(Jj-Jold)+Jold;//divide sensibility + */ + float Jj = (float) Jpro * 327.68f; + float Jold = Jj; + float Jold100 = (float) Jpro; + float redu = 25.f; + float reduc = 1.f; + const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); + userColCurveJ1.Apply(Jj); + + if(Jj > Jold) { + if(Jj < 65535.f) { + if(Jold < 327.68f * redu) { + Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility + } else { + reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f); + Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights + } + } + } else if(Jj > 10.f) { + Jj = 0.8f * (Jj - Jold) + Jold; + } else if (Jj >= 0.f) { + Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts + } + + + Jpro = (double)(Jj / 327.68f); + + if(Jpro < 1.) { + Jpro = 1.; + } + + t1L = true; + } else if (curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different + float coef = ((aw + 4.f) * (4.f / c)) / 100.f; + float Qq = (float) Qpro * 327.68f * (1.f / coef); + float Qold100 = (float) Qpro / coef; + + float Qold = Qq; + float redu = 20.f; + float reduc = 1.f; + + const Brightcurve& userColCurveB1 = static_cast(customColCurve1); + userColCurveB1.Apply(Qq); + + if(Qq > Qold) { + if(Qq < 65535.f) { + if(Qold < 327.68f * redu) { + Qq = 0.25f * (Qq - Qold) + Qold; //divide sensibility + } else { + reduc = LIM((100.f - Qold100) / (100.f - redu), 0.f, 1.f); + Qq = 0.25f * reduc * (Qq - Qold) + Qold; //reduct sensibility in highlights + } + } + } else if(Qq > 10.f) { + Qq = 0.5f * (Qq - Qold) + Qold; + } else if (Qq >= 0.f) { + Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts + } + + Qpro = (double)(Qq * (coef) / 327.68f); + Jpro = 100.*(Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0)); + t1B = true; + + if(Jpro < 1.) { + Jpro = 1.; + } + + } + } + + if (hasColCurve2) {//curve 2 with Lightness and Brightness + if (curveMode2 == ColorAppearanceParams::TC_MODE_LIGHT) { + float Jj = (float) Jpro * 327.68; + float Jold = Jj; + /* + const Lightcurve& userColCurve = static_cast(customColCurve2); + userColCurve.Apply(Jj); + Jj=0.7f*(Jj-Jold)+Jold;//divide sensibility + */ + float Jold100 = (float) Jpro; + float redu = 25.f; + float reduc = 1.f; + const Lightcurve& userColCurveJ2 = static_cast(customColCurve2); + userColCurveJ2.Apply(Jj); + + if(Jj > Jold) { + if(Jj < 65535.f) { + if(Jold < 327.68f * redu) { + Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility + } else { + reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f); + Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights + } + } + } else if(Jj > 10.f) { + if(!t1L) { + Jj = 0.8f * (Jj - Jold) + Jold; + } else { + Jj = 0.4f * (Jj - Jold) + Jold; + } + } else if (Jj >= 0.f) { + if(!t1L) { + Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts + } else { + Jj = 0.5f * (Jj - Jold) + Jold; + } + } + + Jpro = (double)(Jj / 327.68f); + + if(Jpro < 1.) { + Jpro = 1.; + } + + } else if (curveMode2 == ColorAppearanceParams::TC_MODE_BRIGHT) { // + float coef = ((aw + 4.f) * (4.f / c)) / 100.f; + float Qq = (float) Qpro * 327.68f * (1.f / coef); + float Qold100 = (float) Qpro / coef; + + float Qold = Qq; + float redu = 20.f; + float reduc = 1.f; + + const Brightcurve& userColCurveB2 = static_cast(customColCurve2); + userColCurveB2.Apply(Qq); + + if(Qq > Qold) { + if(Qq < 65535.f) { + if(Qold < 327.68f * redu) { + Qq = 0.25f * (Qq - Qold) + Qold; //divide sensibility + } else { + reduc = LIM((100.f - Qold100) / (100.f - redu), 0.f, 1.f); + Qq = 0.25f * reduc * (Qq - Qold) + Qold; //reduct sensibility in highlights + } + } + } else if(Qq > 10.f) { + Qq = 0.5f * (Qq - Qold) + Qold; + } else if (Qq >= 0.f) { + Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts + } + + Qpro = (double)(Qq * (coef) / 327.68f); + Jpro = 100.*(Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0)); + t2B = true; + + if(t1L) { //to workaround the problem if we modify curve1-lightnees after curve2 brightness(the cat that bites its own tail!) in fact it's another type of curve only for this case + coef = 2.f; //adapt Q to J approximation + Qq = (float) Qpro * coef; + Qold = Qq; + const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); + userColCurveJ1.Apply(Qq); + Qq = 0.1f * (Qq - Qold) + Qold; //approximative adaptation + Qpro = (double)(Qq / coef); + Jpro = 100.*(Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0)); + } + + if(Jpro < 1.) { + Jpro = 1.; + } + } + } + + if (hasColCurve3) {//curve 3 with chroma saturation colorfullness + if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { + double parsat = 0.8; //0.68; + double coef = 327.68 / parsat; + float Cc = (float) Cpro * coef; + float Ccold = Cc; + const Chromacurve& userColCurve = static_cast(customColCurve3); + userColCurve.Apply(Cc); + float dred = 55.f; + float protect_red = 30.0f; + float sk = 1; + float ko = 1.f / coef; + Color::skinred(Jpro, hpro, Cc, Ccold, dred, protect_red, sk, rstprotection, ko, Cpro); + + if(Jpro < 1. && Cpro > 12.) { + Cpro = 12.; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2. && Cpro > 15.) { + Cpro = 15.; + } else if(Jpro < 4. && Cpro > 30.) { + Cpro = 30.; + } else if(Jpro < 7. && Cpro > 50.) { + Cpro = 50.; + } + + // Cpro=Cc/coef; + } else if (curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { // + double parsat = 0.8; //0.6 + double coef = 327.68 / parsat; + float Ss = (float) spro * coef; + float Sold = Ss; + const Saturcurve& userColCurve = static_cast(customColCurve3); + userColCurve.Apply(Ss); + Ss = 0.6f * (Ss - Sold) + Sold; //divide sensibility saturation + double coe = pow(fl, 0.25); + float dred = 100.f; // in C mode + float protect_red = 80.0f; // in C mode + dred = 100.0 * sqrt((dred * coe) / Qpro); + protect_red = 100.0 * sqrt((protect_red * coe) / Qpro); + int sk = 0; + float ko = 1.f / coef; + Color::skinred(Jpro, hpro, Ss, Sold, dred, protect_red, sk, rstprotection, ko, spro); + Qpro = ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; + Cpro = (spro * spro * Qpro) / (10000.0); + c1s = 1; + + } else if (curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { // + double parsat = 0.8; //0.68; + double coef = 327.68 / parsat; + float Mm = (float) Mpro * coef; + float Mold = Mm; + const Colorfcurve& userColCurve = static_cast(customColCurve3); + userColCurve.Apply(Mm); + double coe = pow(fl, 0.25); + float dred = 100.f; //in C mode + float protect_red = 80.0f; // in C mode + dred *= coe; //in M mode + protect_red *= coe; + int sk = 0; + float ko = 1.f / coef; + Color::skinred(Jpro, hpro, Mm, Mold, dred, protect_red, sk, rstprotection, ko, Mpro); + Cpro = Mpro / coe; + + if(Jpro < 1. && Mpro > 12.*coe) { + Mpro = 12.*coe; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2. && Mpro > 15.*coe) { + Mpro = 15.*coe; + } else if(Jpro < 4. && Mpro > 30.*coe) { + Mpro = 30.*coe; + } else if(Jpro < 7. && Mpro > 50.*coe) { + Mpro = 50.*coe; + } + + + c1co = 1; + } + } + + //to retrieve the correct values of variables + if(t2B && t1B) { + Jpro = (100.0 * Qpro * Qpro) / (wh * wh); // for brightness curve + } + + if(c1s == 1) { + Qpro = ( 4.0 / c ) * sqrt( Jpro / 100.0 ) * ( aw + 4.0 ) ; //for saturation curve + Cpro = (spro * spro * Qpro) / (10000.0); + } + + if(c1co == 1) { + double coe = pow(fl, 0.25); // for colorfullness curve + Cpro = Mpro / coe; + } + + //retrieve values C,J...s + C = Cpro; + J = Jpro; + Q = Qpro; + M = Mpro; + h = hpro; + s = spro; + + if(params->colorappearance.tonecie || settings->autocielab) { //use pointer for tonemapping with CIECAM and also sharpening , defringe, contrast detail + // if(params->colorappearance.tonecie || params->colorappearance.sharpcie){//use pointer for tonemapping with CIECAM and also sharpening , defringe, contrast detail + float Qred = ( 4.0 / c) * ( aw + 4.0 ); //estimate Q max if J=100.0 + ncie->Q_p[i][j] = (float)Q + epsil; //epsil to avoid Q=0 + ncie->M_p[i][j] = (float)M + epsil; + ncie->J_p[i][j] = (float)J + epsil; + ncie->h_p[i][j] = (float)h; + ncie->C_p[i][j] = (float)C + epsil; + // ncie->s_p[i][j]=(float)s; + ncie->sh_p[i][j] = (float) 32768.*(( 4.0 / c ) * sqrt( J / 100.0 ) * ( aw + 4.0 )) / Qred ; + + // ncie->ch_p[i][j]=(float) 327.68*C; + if(ncie->Q_p[i][j] < minQ) { + minQ = ncie->Q_p[i][j]; //minima + } + + if(ncie->Q_p[i][j] > maxQ) { + maxQ = ncie->Q_p[i][j]; //maxima + } + } + + if(!params->colorappearance.tonecie || !settings->autocielab || !params->epd.enabled ) { + +// if(!params->epd.enabled || !params->colorappearance.tonecie || !settings->autocielab){ + // if(!params->epd.enabled || !params->colorappearance.tonecie || !params->colorappearance.sharpcie){ + int posl, posc; + double brli = 327.; + double chsacol = 327.; + int libr = 0; + int colch = 0; + + if(curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + brli = 70.0; + libr = 1; + } else if(curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + brli = 327.; + libr = 0; + } + + if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { + chsacol = 327.; + colch = 0; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { + chsacol = 450.0; + colch = 1; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { + chsacol = 327.0; + colch = 2; + } + + if(ciedata) { + // Data for J Q M s and C histograms + //update histogram + jp = true; + + if(pW != 1) { //only with improccoordinator + if(libr == 1) { + posl = CLIP((int)(Q * brli)); //40.0 to 100.0 approximative factor for Q - 327 for J + } else if(libr == 0) { + posl = CLIP((int)(J * brli)); //327 for J + } + + hist16JCAM[posl]++; + } + + chropC = true; + + if(pW != 1) { //only with improccoordinator + if(colch == 0) { + posc = CLIP((int)(C * chsacol)); //450.0 approximative factor for s 320 for M + } else if(colch == 1) { + posc = CLIP((int)(s * chsacol)); + } else if(colch == 2) { + posc = CLIP((int)(M * chsacol)); + } + + hist16_CCAM[posc]++; + } + } + + double xx, yy, zz; + //double nj, nbbj, ncbj, flj, czj, dj, awj; + //process normal==> viewing + Ciecam02::jch2xyz_ciecam02( xx, yy, zz, + J, C, h, + xw2, yw2, zw2, + yb2, la2, + f2, c2, nc2, gamu, nj, nbbj, ncbj, flj, czj, dj, awj); + x = (float)xx * 655.35; + y = (float)yy * 655.35; + z = (float)zz * 655.35; + float Ll, aa, bb; + //convert xyz=>lab + Color::XYZ2Lab(x, y, z, Ll, aa, bb); + lab->L[i][j] = Ll; + lab->a[i][j] = aa; + lab->b[i][j] = bb; + + // gamut control in Lab mode; I must study how to do with cIECAM only + if(gamu == 1) { + float R, G, B; + float HH, Lprov1, Chprov1; + Lprov1 = lab->L[i][j] / 327.68f; + Chprov1 = sqrt(SQR(lab->a[i][j] / 327.68f) + SQR(lab->b[i][j] / 327.68f)); + HH = atan2(lab->b[i][j], lab->a[i][j]); #ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); #else - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); #endif - lab->L[i][j]=Lprov1*327.68f; - lab->a[i][j]=327.68f*Chprov1*cos(HH); - lab->b[i][j]=327.68f*Chprov1*sin(HH); + lab->L[i][j] = Lprov1 * 327.68f; + lab->a[i][j] = 327.68f * Chprov1 * cos(HH); + lab->b[i][j] = 327.68f * Chprov1 * sin(HH); - } - } - } - } - // End of parallelization -if(!params->epd.enabled || !params->colorappearance.tonecie || !settings->autocielab){//normal + } + } + } + } + + // End of parallelization + if(!params->epd.enabled || !params->colorappearance.tonecie || !settings->autocielab) { //normal //if(!params->epd.enabled || !params->colorappearance.tonecie || !params->colorappearance.sharpcie){//normal - if(ciedata) { - //update histogram J - if(pW!=1){//only with improccoordinator - for (int i=0; i<32768; i++) {// - if (jp) { - float hval = dLcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); // - histLCAM[hi] += hist16JCAM[i] ; - } - } - } - if(pW!=1){//only with improccoordinator - for (int i=0; i<48000; i++) {// - if (chropC) { - float hvalc = dCcurve[i]; - int hic = (int)(255.0*CLIPD(hvalc)); // - histCCAM[hic] += hist16_CCAM[i] ; - } - } - } - } -} + if(ciedata) { + //update histogram J + if(pW != 1) { //only with improccoordinator + for (int i = 0; i < 32768; i++) { // + if (jp) { + float hval = dLcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); // + histLCAM[hi] += hist16JCAM[i] ; + } + } + } + + if(pW != 1) { //only with improccoordinator + for (int i = 0; i < 48000; i++) { // + if (chropC) { + float hvalc = dCcurve[i]; + int hic = (int)(255.0 * CLIPD(hvalc)); // + histCCAM[hic] += hist16_CCAM[i] ; + } + } + } + } + } + #ifdef _DEBUG - if (settings->verbose) { - t2e.set(); - printf("CIECAM02 performed in %d usec:\n", t2e.etime(t1e)); - // printf("minc=%f maxc=%f minj=%f maxj=%f\n",minc,maxc,minj,maxj); - } + + if (settings->verbose) { + t2e.set(); + printf("CIECAM02 performed in %d usec:\n", t2e.etime(t1e)); + // printf("minc=%f maxc=%f minj=%f maxj=%f\n",minc,maxc,minj,maxj); + } + #endif -if(settings->autocielab) { + if(settings->autocielab) { //if(params->colorappearance.sharpcie) { //all this treatments reduce artifacts, but can lead to slightly different results -if(params->defringe.enabled) if(execsharp) ImProcFunctions::defringecam (ncie);// + if(params->defringe.enabled) if(execsharp) { + ImProcFunctions::defringecam (ncie); // + } //if(params->dirpyrequalizer.enabled) if(execsharp) { -if(params->dirpyrequalizer.enabled) { - if(params->dirpyrequalizer.gamutlab /*&& execsharp*/) { - float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; - float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; - float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; - float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; - int choice=0; + if(params->dirpyrequalizer.enabled) { + if(params->dirpyrequalizer.gamutlab /*&& execsharp*/) { + float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; + float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; + float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; + float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; + int choice = 0; - bool alread=false; - float artifact=(float) settings->artifact_cbdl; - if(artifact>6.f) artifact=6.f; - if(artifact <0.f) artifact=1.f; - int hotbad=0; - float chrom=50.f; - {ImProcFunctions::badpixcam (ncie, artifact, 5, 2 , b_l, t_l, t_r, b_r,params->dirpyrequalizer.skinprotect , chrom, hotbad); alread=true; }//enabled remove artifacts for cbDL -} -} -if(params->colorappearance.badpixsl > 0) if(execsharp) { - int mode=params->colorappearance.badpixsl; - ImProcFunctions::badpixcam (ncie, 3.4, 5, mode, 0, 0, 0, 0, 0, 0, 1);//for bad pixels CIECAM -} + bool alread = false; + float artifact = (float) settings->artifact_cbdl; -if (params->sharpenMicro.enabled)if(execsharp) ImProcFunctions::MLmicrocontrastcam(ncie); + if(artifact > 6.f) { + artifact = 6.f; + } -if(params->sharpening.enabled) - if(execsharp) { - float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory - ImProcFunctions::sharpeningcam (ncie, buffer); // sharpening adapted to CIECAM - } + if(artifact < 0.f) { + artifact = 1.f; + } + + int hotbad = 0; + float chrom = 50.f; + { + ImProcFunctions::badpixcam (ncie, artifact, 5, 2 , b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect , chrom, hotbad); //enabled remove artifacts for cbDL + alread = true; + } + } + } + + if(params->colorappearance.badpixsl > 0) if(execsharp) { + int mode = params->colorappearance.badpixsl; + ImProcFunctions::badpixcam (ncie, 3.4, 5, mode, 0, 0, 0, 0, 0, 0, 1);//for bad pixels CIECAM + } + + if (params->sharpenMicro.enabled)if(execsharp) { + ImProcFunctions::MLmicrocontrastcam(ncie); + } + + if(params->sharpening.enabled) + if(execsharp) { + float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory + ImProcFunctions::sharpeningcam (ncie, buffer); // sharpening adapted to CIECAM + } //if(params->dirpyrequalizer.enabled) if(execsharp) { -if(params->dirpyrequalizer.enabled /*&& (execsharp)*/) { - float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; - float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; - float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; - float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; - int choice=0;//not disabled in case of ! always 0 -// if (params->dirpyrequalizer.algo=="FI") choice=0; -// else if(params->dirpyrequalizer.algo=="LA") choice=1; - if(rtt==1) dirpyr_equalizercam(ncie, ncie->sh_p, ncie->sh_p, ncie->W, ncie->H, ncie->h_p, ncie->C_p, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, true, params->dirpyrequalizer.gamutlab, b_l,t_l,t_r,b_r, choice, scalecd);//contrast by detail adapted to CIECAM -} - float Qredi= ( 4.0 / c_) * ( a_w + 4.0 ); - float co_e=(pow(f_l,0.25f)); + if(params->dirpyrequalizer.enabled /*&& (execsharp)*/) { + float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; + float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; + float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; + float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; + int choice = 0; //not disabled in case of ! always 0 + +// if (params->dirpyrequalizer.algo=="FI") choice=0; +// else if(params->dirpyrequalizer.algo=="LA") choice=1; + if(rtt == 1) { + dirpyr_equalizercam(ncie, ncie->sh_p, ncie->sh_p, ncie->W, ncie->H, ncie->h_p, ncie->C_p, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, true, params->dirpyrequalizer.gamutlab, b_l, t_l, t_r, b_r, choice, scalecd); //contrast by detail adapted to CIECAM + } + } + + float Qredi = ( 4.0 / c_) * ( a_w + 4.0 ); + float co_e = (pow(f_l, 0.25f)); -#ifndef _DEBUG -#pragma omp parallel default(shared) firstprivate(height,width, Qredi,a_w,c_) -#endif -{ #ifndef _DEBUG - #pragma omp for schedule(dynamic, 10) + #pragma omp parallel default(shared) firstprivate(height,width, Qredi,a_w,c_) #endif - for (int i=0; ish_p[i][j]/(32768.f); - ncie->J_p[i][j]=100.0* interm*interm/((a_w+4.)*(a_w+4.)*(4./c_)*(4./c_)); - ncie->Q_p[i][j]=( 4.0 / c_) * ( a_w + 4.0 ) * sqrt(ncie->J_p[i][j]/100.f); - ncie->M_p[i][j]=ncie->C_p[i][j]*co_e; - } - } -} - -if((params->colorappearance.tonecie || (params->colorappearance.tonecie && params->epd.enabled)) || (params->sharpening.enabled && settings->autocielab) - || (params->dirpyrequalizer.enabled && settings->autocielab) ||(params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) - || (params->colorappearance.badpixsl > 0 && settings->autocielab)) { - - if(params->epd.enabled && params->colorappearance.tonecie && algepd) ImProcFunctions::EPDToneMapCIE(ncie, a_w, c_, w_h, width, height, begh, endh, minQ, maxQ, Iterates, scale ); - //EPDToneMapCIE adapted to CIECAM - - -#ifndef _DEBUG -#pragma omp parallel default(shared) firstprivate(lab,xw2,yw2,zw2,chr,yb,la2,yb2, height,width,begh, endh, nc2,f2,c2, gamu, highlight,pW) -#endif -{ - TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); - double wipa[3][3] = { - {wiprofa[0][0],wiprofa[0][1],wiprofa[0][2]}, - {wiprofa[1][0],wiprofa[1][1],wiprofa[1][2]}, - {wiprofa[2][0],wiprofa[2][1],wiprofa[2][2]} - }; - - + { #ifndef _DEBUG - #pragma omp for schedule(dynamic, 10) + #pragma omp for schedule(dynamic, 10) #endif - for (int i=0; iepd.enabled) ncie->J_p[i][j]=(100.0* ncie->Q_p[i][j]*ncie->Q_p[i][j])/(w_h*w_h); - if(params->epd.enabled) ncie->J_p[i][j]=(100.0* ncie->Q_p[i][j]*ncie->Q_p[i][j])/SQR((4./c)*(aw+4.)); - - ncie->C_p[i][j] =(ncie->M_p[i][j])/co_e; - //show histogram in CIECAM mode (Q,J, M,s,C) - int posl, posc; - double brli=327.; - double chsacol=327.; - int libr=0; - int colch=0; - float sa_t; - if(curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) {brli=70.0; libr=1;} - else if(curveMode==ColorAppearanceParams::TC_MODE_LIGHT) {brli=327.;libr=0;} - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA) {chsacol=327.;colch=0;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_SATUR) {chsacol=450.0;colch=1;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_COLORF) {chsacol=327.0;colch=2;} - if(ciedata) { - // Data for J Q M s and C histograms - //update histogram - jp=true; - if(pW!=1){//only with improccoordinator - if(libr==1) posl=CLIP((int)(ncie->Q_p[i][j]*brli));//40.0 to 100.0 approximative factor for Q - 327 for J - else if(libr==0) posl=CLIP((int)(ncie->J_p[i][j]*brli));//327 for J - hist16JCAM[posl]++; - } - chropC=true; - if(pW!=1){//only with improccoordinator - if(colch==0) posc=CLIP((int)(ncie->C_p[i][j]*chsacol));//450.0 approximative factor for s 320 for M - else if(colch==1) {sa_t=100.f*sqrt(ncie->C_p[i][j]/ncie->Q_p[i][j]); posc=CLIP((int)(sa_t*chsacol));}//Q_p always > 0 - else if(colch==2) posc=CLIP((int)(ncie->M_p[i][j]*chsacol)); - hist16_CCAM[posc]++; - } - } - //end histograms - // double nd, nbbd, ncbd, fld, czd, dd, awd; - Ciecam02::jch2xyz_ciecam02( xx, yy, zz, - ncie->J_p[i][j], ncie->C_p[i][j], ncie->h_p[i][j], - xw2, yw2, zw2, - yb2, la2, - f2, c2, nc2, gamu, nj, nbbj, ncbj, flj, czj, dj, awj); - x=(float)xx*655.35; - y=(float)yy*655.35; - z=(float)zz*655.35; - float Ll,aa,bb; - //convert xyz=>lab - Color::XYZ2Lab(x, y, z, Ll, aa, bb); - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; - if(gamu==1) { - float R,G,B; - float HH, Lprov1, Chprov1; - Lprov1=lab->L[i][j]/327.68f; - Chprov1=sqrt(SQR(lab->a[i][j]/327.68f) + SQR(lab->b[i][j]/327.68f)); - HH=atan2(lab->b[i][j],lab->a[i][j]); + + for (int i = 0; i < height; i++) // update CieImages with new values after sharpening, defringe, contrast by detail level + for (int j = 0; j < width; j++) { + float interm = Qredi * ncie->sh_p[i][j] / (32768.f); + ncie->J_p[i][j] = 100.0 * interm * interm / ((a_w + 4.) * (a_w + 4.) * (4. / c_) * (4. / c_)); + ncie->Q_p[i][j] = ( 4.0 / c_) * ( a_w + 4.0 ) * sqrt(ncie->J_p[i][j] / 100.f); + ncie->M_p[i][j] = ncie->C_p[i][j] * co_e; + } + } + } + + if((params->colorappearance.tonecie || (params->colorappearance.tonecie && params->epd.enabled)) || (params->sharpening.enabled && settings->autocielab) + || (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) + || (params->colorappearance.badpixsl > 0 && settings->autocielab)) { + + if(params->epd.enabled && params->colorappearance.tonecie && algepd) { + ImProcFunctions::EPDToneMapCIE(ncie, a_w, c_, w_h, width, height, begh, endh, minQ, maxQ, Iterates, scale ); + } + + //EPDToneMapCIE adapted to CIECAM + + +#ifndef _DEBUG + #pragma omp parallel default(shared) firstprivate(lab,xw2,yw2,zw2,chr,yb,la2,yb2, height,width,begh, endh, nc2,f2,c2, gamu, highlight,pW) +#endif + { + TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); + double wipa[3][3] = { + {wiprofa[0][0], wiprofa[0][1], wiprofa[0][2]}, + {wiprofa[1][0], wiprofa[1][1], wiprofa[1][2]}, + {wiprofa[2][0], wiprofa[2][1], wiprofa[2][2]} + }; + + +#ifndef _DEBUG + #pragma omp for schedule(dynamic, 10) +#endif + + for (int i = 0; i < height; i++) // update CIECAM with new values after tone-mapping + + // for (int i=begh; iepd.enabled) ncie->J_p[i][j]=(100.0* ncie->Q_p[i][j]*ncie->Q_p[i][j])/(w_h*w_h); + if(params->epd.enabled) { + ncie->J_p[i][j] = (100.0 * ncie->Q_p[i][j] * ncie->Q_p[i][j]) / SQR((4. / c) * (aw + 4.)); + } + + ncie->C_p[i][j] = (ncie->M_p[i][j]) / co_e; + //show histogram in CIECAM mode (Q,J, M,s,C) + int posl, posc; + double brli = 327.; + double chsacol = 327.; + int libr = 0; + int colch = 0; + float sa_t; + + if(curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + brli = 70.0; + libr = 1; + } else if(curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + brli = 327.; + libr = 0; + } + + if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { + chsacol = 327.; + colch = 0; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { + chsacol = 450.0; + colch = 1; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { + chsacol = 327.0; + colch = 2; + } + + if(ciedata) { + // Data for J Q M s and C histograms + //update histogram + jp = true; + + if(pW != 1) { //only with improccoordinator + if(libr == 1) { + posl = CLIP((int)(ncie->Q_p[i][j] * brli)); //40.0 to 100.0 approximative factor for Q - 327 for J + } else if(libr == 0) { + posl = CLIP((int)(ncie->J_p[i][j] * brli)); //327 for J + } + + hist16JCAM[posl]++; + } + + chropC = true; + + if(pW != 1) { //only with improccoordinator + if(colch == 0) { + posc = CLIP((int)(ncie->C_p[i][j] * chsacol)); //450.0 approximative factor for s 320 for M + } else if(colch == 1) { + sa_t = 100.f * sqrt(ncie->C_p[i][j] / ncie->Q_p[i][j]); //Q_p always > 0 + posc = CLIP((int)(sa_t * chsacol)); + } else if(colch == 2) { + posc = CLIP((int)(ncie->M_p[i][j] * chsacol)); + } + + hist16_CCAM[posc]++; + } + } + + //end histograms + // double nd, nbbd, ncbd, fld, czd, dd, awd; + Ciecam02::jch2xyz_ciecam02( xx, yy, zz, + ncie->J_p[i][j], ncie->C_p[i][j], ncie->h_p[i][j], + xw2, yw2, zw2, + yb2, la2, + f2, c2, nc2, gamu, nj, nbbj, ncbj, flj, czj, dj, awj); + x = (float)xx * 655.35; + y = (float)yy * 655.35; + z = (float)zz * 655.35; + float Ll, aa, bb; + //convert xyz=>lab + Color::XYZ2Lab(x, y, z, Ll, aa, bb); + lab->L[i][j] = Ll; + lab->a[i][j] = aa; + lab->b[i][j] = bb; + + if(gamu == 1) { + float R, G, B; + float HH, Lprov1, Chprov1; + Lprov1 = lab->L[i][j] / 327.68f; + Chprov1 = sqrt(SQR(lab->a[i][j] / 327.68f) + SQR(lab->b[i][j] / 327.68f)); + HH = atan2(lab->b[i][j], lab->a[i][j]); #ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wipa, highlight, 0.15f, 0.96f, neg, more_rgb); + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wipa, highlight, 0.15f, 0.96f, neg, more_rgb); #else - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wipa, highlight, 0.15f, 0.96f); + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lprov1, Chprov1, R, G, B, wipa, highlight, 0.15f, 0.96f); #endif - lab->L[i][j]=Lprov1*327.68f; - lab->a[i][j]=327.68f*Chprov1*cos(HH); - lab->b[i][j]=327.68f*Chprov1*sin(HH); - } - } + lab->L[i][j] = Lprov1 * 327.68f; + lab->a[i][j] = 327.68f * Chprov1 * cos(HH); + lab->b[i][j] = 327.68f * Chprov1 * sin(HH); + } + } - } - //end parallelization - //show CIECAM histograms - if(ciedata) { - //update histogram J and Q - if(pW!=1){//only with improccoordinator - for (int i=0; i<32768; i++) {// - if (jp) { - float hval = dLcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); // - histLCAM[hi] += hist16JCAM[i] ; - } - } - } - //update color histogram M,s,C - if(pW!=1){//only with improccoordinator - for (int i=0; i<48000; i++) {// - if (chropC) { - float hvalc = dCcurve[i]; - int hic = (int)(255.0*CLIPD(hvalc)); // - histCCAM[hic] += hist16_CCAM[i] ; - } - } - } - } + } - } + //end parallelization + //show CIECAM histograms + if(ciedata) { + //update histogram J and Q + if(pW != 1) { //only with improccoordinator + for (int i = 0; i < 32768; i++) { // + if (jp) { + float hval = dLcurve[i]; + int hi = (int)(255.0 * CLIPD(hval)); // + histLCAM[hi] += hist16JCAM[i] ; + } + } + } -} + //update color histogram M,s,C + if(pW != 1) { //only with improccoordinator + for (int i = 0; i < 48000; i++) { // + if (chropC) { + float hvalc = dCcurve[i]; + int hic = (int)(255.0 * CLIPD(hvalc)); // + histCCAM[hic] += hist16_CCAM[i] ; + } + } + } + } + + } + + } } //end CIECAM // Copyright (c) 2012 Jacques Desmis void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int endh, int pW, int pwb, LabImage* lab, const ProcParams* params, - const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2,const ColorAppearance & customColCurve3, - LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, int scalecd, int rtt) + const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2, const ColorAppearance & customColCurve3, + LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, int scalecd, int rtt) { -if(params->colorappearance.enabled) { + if(params->colorappearance.enabled) { //int lastskip; //if(rtt==1) {lastskip=scalecd;} //not for Rtthumbnail #ifdef _DEBUG - MyTime t1e,t2e; - t1e.set(); + MyTime t1e, t2e; + t1e.set(); #endif - LUTf dLcurve; - LUTu hist16JCAM; - float val; - //preparate for histograms CIECAM - if(pW!=1){//only with improccoordinator - dLcurve(65536, 0); - dLcurve.clear(); - hist16JCAM(65536); - hist16JCAM.clear(); - for (int i=0; i<32768; i++) { //# 32768*1.414 approximation maxi for chroma - val = (double)i / 32767.0; - dLcurve[i] = CLIPD(val); - } - } - LUTf dCcurve(65536,0); - LUTu hist16_CCAM(65536); - bool chropC=false; - float valc; - - if(pW!=1){//only with improccoordinator - for (int i=0; i<48000; i++) { //# 32768*1.414 approximation maxi for chroma - valc = (double)i / 47999.0; - dCcurve[i] = CLIPD(valc); - } - hist16_CCAM.clear(); - } - //end preparate histogram - int width = lab->W, height = lab->H; - float minQ = 10000.f; - float maxQ = -1000.f; - float Yw; - Yw=1.0; - double Xw, Zw; - float f,nc,yb,la,c,xw,yw,zw,f2,c2,nc2,yb2,la2; - float fl,n,nbb,ncb,aw;//d - float xwd,ywd,zwd; - int alg=0; - bool algepd=false; - float sum=0.f; + LUTf dLcurve; + LUTu hist16JCAM; + float val; - const bool ciedata = (params->colorappearance.datacie && pW!=1); - bool jp=ciedata; + //preparate for histograms CIECAM + if(pW != 1) { //only with improccoordinator + dLcurve(65536, 0); + dLcurve.clear(); + hist16JCAM(65536); + hist16JCAM.clear(); - ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB - //viewing condition for surround - if(params->colorappearance.surround=="Average") { f = 1.00f; c = 0.69f; nc = 1.00f;f2=1.0f,c2=0.69f,nc2=1.0f;} - else if(params->colorappearance.surround=="Dim"){ f2 = 0.9f; c2 = 0.59f; nc2 = 0.9f;f=1.0f,c=0.69f,nc=1.0f;} - else if(params->colorappearance.surround=="Dark"){f2 = 0.8f; c2 = 0.525f;nc2 = 0.8f;f=1.0f,c=0.69f,nc=1.0f;} - else if(params->colorappearance.surround=="ExtremelyDark"){f2 = 0.8f; c2 = 0.41f;nc2 = 0.8f;f=1.0f,c=0.69f,nc=1.0f;} - - //scene condition for surround - if(params->colorappearance.surrsource==true) {f = 0.85f; c = 0.55f; nc = 0.85f;}// if user => source image has surround very dark - //with which algorithm - if (params->colorappearance.algo=="JC") alg=0; - else if(params->colorappearance.algo=="JS") alg=1; - else if(params->colorappearance.algo=="QM") {alg=2;algepd=true;} - else if(params->colorappearance.algo=="ALL") {alg=3;algepd=true;} - - //settings white point of output device - or illuminant viewing - if(settings->viewingdevice==0) {xwd=96.42f;ywd=100.0f;zwd=82.52f;}//5000K - else if(settings->viewingdevice==1) {xwd=95.68f;ywd=100.0f;zwd=92.15f;}//5500 - else if(settings->viewingdevice==2) {xwd=95.24f;ywd=100.0f;zwd=100.81f;}//6000 - else if(settings->viewingdevice==3) {xwd=95.04f;ywd=100.0f;zwd=108.88f;}//6500 - else if(settings->viewingdevice==4) {xwd=109.85f;ywd=100.0f;zwd=35.58f;}//tungsten - else if(settings->viewingdevice==5) {xwd=99.18f;ywd=100.0f;zwd=67.39f;}//fluo F2 - else if(settings->viewingdevice==6) {xwd=95.04f;ywd=100.0f;zwd=108.75f;}//fluo F7 - else if(settings->viewingdevice==7) {xwd=100.96f;ywd=100.0f;zwd=64.35f;}//fluo F11 - - - //settings mean Luminance Y of output device or viewing - if(settings->viewingdevicegrey==0) {yb2=5.0f;} - else if(settings->viewingdevicegrey==1) {yb2=10.0f;} - else if(settings->viewingdevicegrey==2) {yb2=15.0f;} - else if(settings->viewingdevicegrey==3) {yb2=18.0f;} - else if(settings->viewingdevicegrey==4) {yb2=23.0f;} - else if(settings->viewingdevicegrey==5) {yb2=30.0f;} - else if(settings->viewingdevicegrey==6) {yb2=40.0f;} - - //La and la2 = ambiant luminosity scene and viewing - la=float(params->colorappearance.adapscen); - if(pwb==2){ - if(params->colorappearance.autoadapscen) la=adap; - } - - la2=float(params->colorappearance.adaplum); - - // level of adaptation - const float deg=(params->colorappearance.degree)/100.0f; - const float pilot=params->colorappearance.autodegree ? 2.0f : deg; - - //algoritm's params - float chr=0.f; - if(alg==0 || alg==3) { - chr=params->colorappearance.chroma; - if(chr==-100.0f) - chr=-99.8f; - } - - float schr=0.f; - if(alg==3 || alg==1) { - schr=params->colorappearance.schroma; - if(schr>0.0) schr=schr/2.0f;//divide sensibility for saturation - if(alg==3) { - if(schr==-100.0f) - schr=-99.f; - if(schr==100.0f) - schr=98.f; - } else { - if(schr==-100.0f) - schr=-99.8f; - } - } - float mchr=0.f; - if(alg==3 || alg == 2) { - mchr = params->colorappearance.mchroma; - if(mchr==-100.0f) - mchr=-99.8f ; - if(mchr==100.0f) - mchr=99.9f; - } - - const float hue=params->colorappearance.colorh; - const float rstprotection = 100.-params->colorappearance.rstprotection; - - // extracting datas from 'params' to avoid cache flush (to be confirmed) - const ColorAppearanceParams::eTCModeId curveMode = params->colorappearance.curveMode; - const bool hasColCurve1 = bool(customColCurve1); - bool t1L=false; - bool t1B=false; - if (hasColCurve1 && curveMode==ColorAppearanceParams::TC_MODE_LIGHT) - t1L = true; - if(hasColCurve1 && curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) - t1B = true; - - const ColorAppearanceParams::eTCModeId curveMode2 = params->colorappearance.curveMode2; - const bool hasColCurve2 = bool(customColCurve2); - bool t2B=false; - if(hasColCurve2 && curveMode2==ColorAppearanceParams::TC_MODE_BRIGHT) - t2B = true; - - const ColorAppearanceParams::eCTCModeId curveMode3 = params->colorappearance.curveMode3; - const bool hasColCurve3 = bool(customColCurve3); - bool c1s = false; - bool c1co = false; - if( hasColCurve3 && curveMode3==ColorAppearanceParams::TC_MODE_SATUR) - c1s = true; - if(hasColCurve3 && curveMode3==ColorAppearanceParams::TC_MODE_COLORF) - c1co = true; - - if(CAMBrightCurveJ.dirty || CAMBrightCurveQ.dirty){ - bool needJ = (alg==0 || alg==1 || alg==3); - bool needQ = (alg==2 || alg==3); - LUTu hist16J; - LUTu hist16Q; - if (needJ) { - hist16J (65536); - hist16J.clear(); - } - if (needQ) { - hist16Q (65536); - hist16Q.clear(); - } -#pragma omp parallel -{ - LUTu hist16Jthr; - LUTu hist16Qthr; - if (needJ) { - hist16Jthr (65536); - hist16Jthr.clear(); - } - if (needQ) { - hist16Qthr(65536); - hist16Qthr.clear(); - } - -#pragma omp for reduction(+:sum) - for (int i=0; iL[i][j]/327.68f; - float koef=1.0f;//rough correspondence between L and J -// if (currL>95.f) koef=1.f; - if(currL>85.f) koef=0.97f; - else if(currL>80.f) koef=0.93f; - else if(currL>70.f) koef=0.87f; - else if(currL>60.f) koef=0.85f; - else if(currL>50.f) koef=0.8f; - else if(currL>40.f) koef=0.75f; -// else if(currL>30.f) koef=0.7f; - else if(currL>20.f) koef=0.7f; - else if(currL>10.f) koef=0.9f; -// else if(currL>0.f) koef=1.0f; - - if (needJ) - hist16Jthr[CLIP((int)((koef*lab->L[i][j])))]++;//evaluate histogram luminance L # J - if (needQ) - hist16Qthr[CLIP((int) (sqrtf((koef*(lab->L[i][j]))*32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L - sum+=koef*lab->L[i][j];//evaluate mean J to calculate Yb - } -#pragma omp critical -{ - if(needJ) - for(int i=0;i<65536;i++) - hist16J[i] += hist16Jthr[i]; - if(needQ) - for(int i=0;i<65536;i++) - hist16Q[i] += hist16Qthr[i]; - -} -} - - - //mean=(sum/((endh-begh)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone - mean=(sum/((height)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone - - //evaluate lightness, contrast - if (needJ) { - if (!CAMBrightCurveJ) { - CAMBrightCurveJ(32768,LUT_CLIP_ABOVE); - CAMBrightCurveJ.dirty = false; - } - float jli=params->colorappearance.jlight; - float contra=params->colorappearance.contrast; - Ciecam02::curveJfloat (jli, contra, 1, CAMBrightCurveJ, hist16J);//lightness and contrast J - } - if (needQ) { - if (!CAMBrightCurveQ) { - CAMBrightCurveQ(32768,LUT_CLIP_ABOVE); - CAMBrightCurveQ.clear(); - CAMBrightCurveQ.dirty = false; - } - float qbri=params->colorappearance.qbright; - float qcontra=params->colorappearance.qcontrast; - Ciecam02::curveJfloat (qbri, qcontra, 1, CAMBrightCurveQ, hist16Q);//brightness and contrast Q - } - } - -if(settings->viewinggreySc==0){//auto - if (mean<15.f) yb=3.0f; - else if(mean<30.f) yb=5.0f; - else if(mean<40.f) yb=10.0f; - else if(mean<45.f) yb=15.0f; - else if(mean<50.f) yb=18.0f; - else if(mean<55.f) yb=23.0f; - else if(mean<60.f) yb=30.0f; - else if(mean<70.f) yb=40.0f; - else if(mean<80.f) yb=60.0f; - else if(mean<90.f) yb=80.0f; - else yb=90.0f; -} -if(settings->viewinggreySc==1) yb=18.0f;//fixed - - - const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated - - const int gamu = (params->colorappearance.gamut==true) ? 1 : 0; - xw=100.0f*Xw; - yw=100.0f*Yw; - zw=100.0f*Zw; - float xw1,yw1,zw1,xw2,yw2,zw2; - // settings of WB: scene and viewing - if(params->colorappearance.wbmodel=="RawT") {xw1=96.46f;yw1=100.0f;zw1=82.445f;xw2=xwd;yw2=ywd;zw2=zwd;} //use RT WB; CAT 02 is used for output device (see prefreneces) - else if(params->colorappearance.wbmodel=="RawTCAT02") {xw1=xw;yw1=yw;zw1=zw;xw2=xwd;yw2=ywd;zw2=zwd;} // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences - float cz,wh, pfl; - Ciecam02::initcam1float(gamu, yb, pilot, f, la,xw, yw, zw, n, d, nbb, ncb,cz, aw, wh, pfl, fl, c); - const float pow1 = pow_F( 1.64f - pow_F( 0.29f, n ), 0.73f ); - float nj,dj,nbbj,ncbj,czj,awj,flj; - Ciecam02::initcam2float(gamu,yb2, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj,czj, awj, flj); - const float reccmcz = 1.f / (c2*czj); - const float pow1n = pow_F( 1.64f - pow_F( 0.29f, nj ), 0.73f ); - - const float epsil=0.0001f; - const float w_h=wh+epsil; - const float a_w=aw; - const float c_=c; - const float f_l=fl; - const float coe=pow_F(fl,0.25f); - const float QproFactor = ( 0.4f / c ) * ( aw + 4.0f ) ; - const bool epdEnabled = params->epd.enabled; - const bool LabPassOne = !((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) - || (params->dirpyrequalizer.enabled && settings->autocielab) ||(params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) - || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl >0 && settings->autocielab)); - - //matrix for current working space - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); - const float wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; - -#ifdef __SSE2__ - int bufferLength = ((width+3)/4) * 4; // bufferLength has to be a multiple of 4 -#endif -#ifndef _DEBUG -#pragma omp parallel -#endif -{ - float minQThr = 10000.f; - float maxQThr = -1000.f; -#ifdef __SSE2__ - // one line buffer per channel and thread - float Jbuffer[bufferLength] ALIGNED16; - float Cbuffer[bufferLength] ALIGNED16; - float hbuffer[bufferLength] ALIGNED16; - float Qbuffer[bufferLength] ALIGNED16; - float Mbuffer[bufferLength] ALIGNED16; - float sbuffer[bufferLength] ALIGNED16; -#endif -#ifndef _DEBUG -#pragma omp for schedule(dynamic, 16) -#endif - for (int i=0; iL[i][k]),LVFU(lab->a[i][k]),LVFU(lab->b[i][k]),x,y,z); - x = x/c655d35; - y = y/c655d35; - z = z/c655d35; - Ciecam02::xyz2jchqms_ciecam02float( J, C, h, - Q, M, s, F2V(aw), F2V(fl), F2V(wh), - x, y, z, - F2V(xw1), F2V(yw1), F2V(zw1), - F2V(yb), F2V(la), - F2V(f), F2V(c), F2V(nc), F2V(pow1), F2V(nbb), F2V(ncb), F2V(pfl), F2V(cz), F2V(d)); - STVF(Jbuffer[k],J); - STVF(Cbuffer[k],C); - STVF(hbuffer[k],h); - STVF(Qbuffer[k],Q); - STVF(Mbuffer[k],M); - STVF(sbuffer[k],s); - } - for(;kL[i][k]; - float a=lab->a[i][k]; - float b=lab->b[i][k]; - float x,y,z; - //convert Lab => XYZ - Color::Lab2XYZ(L, a, b, x, y, z); - x = x/655.35f; - y = y/655.35f; - z = z/655.35f; - float J, C, h, Q, M, s; - Ciecam02::xyz2jchqms_ciecam02float( J, C, h, - Q, M, s, aw, fl, wh, - x, y, z, - xw1, yw1, zw1, - yb, la, - f, c, nc, pilot, gamu, pow1, nbb, ncb, pfl, cz, d); - Jbuffer[k] = J; - Cbuffer[k] = C; - hbuffer[k] = h; - Qbuffer[k] = Q; - Mbuffer[k] = M; - sbuffer[k] = s; - } -#endif // __SSE2__ - for (int j=0; jL[i][j]; - float a=lab->a[i][j]; - float b=lab->b[i][j]; - float x1,y1,z1; - //convert Lab => XYZ - Color::Lab2XYZ(L, a, b, x1, y1, z1); - x=(float)x1/655.35f; - y=(float)y1/655.35f; - z=(float)z1/655.35f; - //process source==> normal - Ciecam02::xyz2jchqms_ciecam02float( J, C, h, - Q, M, s, aw, fl, wh, - x, y, z, - xw1, yw1, zw1, - yb, la, - f, c, nc, pilot, gamu, pow1, nbb, ncb, pfl, cz, d); -#endif - float Jpro,Cpro, hpro, Qpro, Mpro, spro; - Jpro=J; - Cpro=C; - hpro=h; - Qpro=Q; - Mpro=M; - spro=s; - // we cannot have all algorithms with all chroma curves - if(alg==0) { - Jpro = CAMBrightCurveJ[Jpro*327.68f]/327.68f; //lightness CIECAM02 + contrast - Qpro = QproFactor * sqrtf(Jpro); - float Cp = (spro*spro*Qpro)/(1000000.f); - Cpro = Cp * 100.f; - float sres; - Ciecam02::curvecolorfloat(chr, Cp , sres, 1.8f); - Color::skinredfloat(Jpro, hpro, sres, Cp, 55.f, 30.f,1,rstprotection, 100.f, Cpro); - } - if(alg==1) { - // Lightness saturation - Jpro = CAMBrightCurveJ[Jpro*327.68f]/327.68f;//lightness CIECAM02 + contrast - float sres; - float Sp=spro/100.0f; - float parsat=1.5f; //parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation) - Ciecam02::curvecolorfloat(schr, Sp , sres, parsat); - float dred=100.f;// in C mode - float protect_red=80.0f; // in C mode - dred = 100.0f * sqrtf((dred*coe)/Qpro); - protect_red=100.0f * sqrtf((protect_red*coe)/Qpro); - Color::skinredfloat(Jpro, hpro, sres, Sp, dred, protect_red,0,rstprotection,100.f, spro); - Qpro = QproFactor * sqrtf(Jpro); - Cpro=(spro*spro*Qpro)/(10000.0f); - } - else if(alg==2) { - float coef=32767.f/wh; - Qpro=(CAMBrightCurveQ[(float)(Qpro*coef)])/coef;//brightness and contrast - float Mp, sres; - Mp=Mpro/100.0f; - Ciecam02::curvecolorfloat(mchr, Mp , sres, 2.5f); - float dred=100.f;//in C mode - float protect_red=80.0f;// in C mode - dred *=coe;//in M mode - protect_red *=coe;//M mode - Color::skinredfloat(Jpro, hpro, sres, Mp, dred, protect_red,0,rstprotection,100.f, Mpro); - Jpro = SQR((10.f*Qpro)/wh); - Cpro= Mpro/coe; - Qpro = (Qpro == 0.f ? epsil : Qpro); // avoid division by zero - spro = 100.0f * sqrtf( Mpro / Qpro ); - } - else if(alg==3) { - float coef=32760.f/wh; - if(Qpro*coef >= 32767.0f) - Qpro=(CAMBrightCurveQ[32767])/coef;//brightness and contrast - else - Qpro=(CAMBrightCurveQ[(float)(Qpro*coef)])/coef;//brightness and contrast - float Mp, sres; - Mp=Mpro/100.0f; - Ciecam02::curvecolorfloat(mchr, Mp , sres, 2.5f); - float dred=100.f;//in C mode - float protect_red=80.0f;// in C mode - dred *=coe;//in M mode - protect_red *=coe;//M mode - Color::skinredfloat(Jpro, hpro, sres, Mp, dred, protect_red,0,rstprotection,100.f, Mpro); - Jpro = SQR((10.f*Qpro)/wh); - Cpro= Mpro/coe; - Qpro = (Qpro == 0.f ? epsil : Qpro); // avoid division by zero - spro = 100.0f * sqrtf( Mpro / Qpro ); - if(Jpro > 99.9f) - Jpro = 99.9f; - Jpro=(CAMBrightCurveJ[(float)(Jpro*327.68f)])/327.68f;//lightness CIECAM02 + contrast - float Sp=spro/100.0f; - Ciecam02::curvecolorfloat(schr, Sp , sres, 1.5f); - dred=100.f;// in C mode - protect_red=80.0f; // in C mode - dred = 100.0f * sqrtf((dred*coe)/Q); - protect_red=100.0f * sqrtf((protect_red*coe)/Q); - Color::skinredfloat(Jpro, hpro, sres, Sp, dred, protect_red,0,rstprotection,100.f, spro); - Qpro = QproFactor * sqrtf(Jpro); - float Cp=(spro*spro*Qpro)/(1000000.f); - Cpro = Cp*100.f; - Ciecam02::curvecolorfloat(chr, Cp , sres, 1.8f); - Color::skinredfloat(Jpro, hpro, sres, Cp, 55.f, 30.f,1,rstprotection, 100.f, Cpro); -// disabled this code, Issue 2690 -// if(Jpro < 1.f && Cpro > 12.f) Cpro=12.f;//reduce artifacts by "pseudo gamut control CIECAM" -// else if(Jpro < 2.f && Cpro > 15.f) Cpro=15.f; -// else if(Jpro < 4.f && Cpro > 30.f) Cpro=30.f; -// else if(Jpro < 7.f && Cpro > 50.f) Cpro=50.f; - hpro=hpro+hue; - if( hpro < 0.0f ) - hpro += 360.0f;//hue - } - - if (hasColCurve1) {//curve 1 with Lightness and Brightness - if (curveMode==ColorAppearanceParams::TC_MODE_LIGHT){ - float Jj=(float) Jpro*327.68f; - float Jold=Jj; - float Jold100=(float) Jpro; - float redu=25.f; - float reduc=1.f; - const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); - userColCurveJ1.Apply(Jj); - if(Jj>Jold) { - if(Jj<65535.f) { - if(Jold < 327.68f*redu) Jj=0.3f*(Jj-Jold)+Jold;//divide sensibility - else { - reduc=LIM((100.f-Jold100)/(100.f-redu),0.f,1.f); - Jj=0.3f*reduc*(Jj-Jold)+Jold;//reduct sensibility in highlights - } - } - } - else if(Jj>10.f) Jj=0.8f*(Jj-Jold)+Jold; - else if (Jj>=0.f) Jj=0.90f*(Jj-Jold)+Jold;// not zero ==>artifacts - Jpro=(float)(Jj/327.68f); - if(Jpro<1.f) Jpro=1.f; - } - else if (curveMode==ColorAppearanceParams::TC_MODE_BRIGHT){ - //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different - float coef=((aw+4.f)*(4.f/c))/100.f; - float Qq=(float) Qpro*327.68f*(1.f/coef); - float Qold100=(float) Qpro/coef; - - float Qold=Qq; - float redu=20.f; - float reduc=1.f; - - const Brightcurve& userColCurveB1 = static_cast(customColCurve1); - userColCurveB1.Apply(Qq); - if(Qq>Qold) { - if(Qq<65535.f) { - if(Qold < 327.68f*redu) Qq=0.25f*(Qq-Qold)+Qold;//divide sensibility - else { - reduc=LIM((100.f-Qold100)/(100.f-redu),0.f,1.f); - Qq=0.25f*reduc*(Qq-Qold)+Qold;//reduct sensibility in highlights - } - } - } - else if(Qq>10.f) Qq=0.5f*(Qq-Qold)+Qold; - else if (Qq>=0.f) Qq=0.7f*(Qq-Qold)+Qold;// not zero ==>artifacts - Qpro=(float)(Qq*(coef)/327.68f); - Jpro=100.f*(Qpro*Qpro)/((4.0f/c)*(4.0f/c)*(aw+4.0f)*(aw+4.0f)); - if(Jpro< 1.f) Jpro=1.f; - } - } - - if (hasColCurve2) {//curve 2 with Lightness and Brightness - if (curveMode2==ColorAppearanceParams::TC_MODE_LIGHT){ - float Jj=(float) Jpro*327.68f; - float Jold=Jj; - float Jold100=(float) Jpro; - float redu=25.f; - float reduc=1.f; - const Lightcurve& userColCurveJ2 = static_cast(customColCurve2); - userColCurveJ2.Apply(Jj); - if(Jj>Jold) { - if(Jj<65535.f) { - if(Jold < 327.68f*redu) Jj=0.3f*(Jj-Jold)+Jold;//divide sensibility - else { - reduc=LIM((100.f-Jold100)/(100.f-redu),0.f,1.f); - Jj=0.3f*reduc*(Jj-Jold)+Jold;//reduct sensibility in highlights - } - } - } - else if(Jj>10.f) {if(!t1L)Jj=0.8f*(Jj-Jold)+Jold;else Jj=0.4f*(Jj-Jold)+Jold;} - else if (Jj>=0.f){if(!t1L)Jj=0.90f*(Jj-Jold)+Jold;else Jj=0.5f*(Jj-Jold)+Jold;}// not zero ==>artifacts - Jpro=(float)(Jj/327.68f); - if(Jpro< 1.f) Jpro=1.f; - - } - else if (curveMode2==ColorAppearanceParams::TC_MODE_BRIGHT){ // - float coef=((aw+4.f)*(4.f/c))/100.f; - float Qq=(float) Qpro*327.68f*(1.f/coef); - float Qold100=(float) Qpro/coef; - - float Qold=Qq; - float redu=20.f; - float reduc=1.f; - - const Brightcurve& userColCurveB2 = static_cast(customColCurve2); - userColCurveB2.Apply(Qq); - if(Qq>Qold) { - if(Qq<65535.f) { - if(Qold < 327.68f*redu) Qq=0.25f*(Qq-Qold)+Qold;//divide sensibility - else { - reduc=LIM((100.f-Qold100)/(100.f-redu),0.f,1.f); - Qq=0.25f*reduc*(Qq-Qold)+Qold;//reduct sensibility in highlights - } - } - } - else if(Qq>10.f) Qq=0.5f*(Qq-Qold)+Qold; - else if (Qq>=0.f) Qq=0.7f*(Qq-Qold)+Qold;// not zero ==>artifacts - - Qpro=(float)(Qq*(coef)/327.68f); - Jpro=100.f*(Qpro*Qpro)/((4.0f/c)*(4.0f/c)*(aw+4.0f)*(aw+4.0f)); - - if(t1L){//to workaround the problem if we modify curve1-lightnees after curve2 brightness(the cat that bites its own tail!) in fact it's another type of curve only for this case - coef=2.f;//adapt Q to J approximation - Qq=(float) Qpro*coef; - Qold=Qq; - const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); - userColCurveJ1.Apply(Qq); - Qq=0.05f*(Qq-Qold)+Qold;//approximative adaptation - Qpro=(float)(Qq/coef); - Jpro=100.f*(Qpro*Qpro)/((4.0f/c)*(4.0f/c)*(aw+4.0f)*(aw+4.0f)); - } - if(Jpro < 1.f) Jpro=1.f; - } - } - - if (hasColCurve3) {//curve 3 with chroma saturation colorfullness - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA){ - float parsat=0.8f;//0.68; - float coef=327.68f/parsat; - float Cc=(float) Cpro*coef; - float Ccold=Cc; - const Chromacurve& userColCurve = static_cast(customColCurve3); - userColCurve.Apply(Cc); - float dred=55.f; - float protect_red=30.0f; - int sk=1; - float ko=1.f/coef; - Color::skinredfloat(Jpro, hpro, Cc, Ccold, dred, protect_red,sk,rstprotection,ko, Cpro); - if(Jpro < 1.f && Cpro > 12.f) Cpro=12.f;//reduce artifacts by "pseudo gamut control CIECAM" - else if(Jpro < 2.f && Cpro > 15.f) Cpro=15.f; - else if(Jpro < 4.f && Cpro > 30.f) Cpro=30.f; - else if(Jpro < 7.f && Cpro > 50.f) Cpro=50.f; - - } - else if (curveMode3==ColorAppearanceParams::TC_MODE_SATUR){ // - float parsat=0.8f;//0.6 - float coef=327.68f/parsat; - float Ss=(float) spro*coef; - float Sold=Ss; - const Saturcurve& userColCurve = static_cast(customColCurve3); - userColCurve.Apply(Ss); - Ss=0.6f*(Ss-Sold)+Sold;//divide sensibility saturation - float dred=100.f;// in C mode - float protect_red=80.0f; // in C mode - dred = 100.0f * sqrtf((dred*coe)/Qpro); - protect_red=100.0f * sqrtf((protect_red*coe)/Qpro); - int sk=0; - float ko=1.f/coef; - Color::skinredfloat(Jpro, hpro, Ss, Sold, dred, protect_red,sk,rstprotection,ko, spro); - Qpro= ( 4.0f / c ) * sqrtf( Jpro / 100.0f ) * ( aw + 4.0f ) ; - Cpro=(spro*spro*Qpro)/(10000.0f); - - } - else if (curveMode3==ColorAppearanceParams::TC_MODE_COLORF){ // - float parsat=0.8f;//0.68; - float coef=327.68f/parsat; - float Mm=(float) Mpro*coef; - float Mold=Mm; - const Colorfcurve& userColCurve = static_cast(customColCurve3); - userColCurve.Apply(Mm); - float dred=100.f;//in C mode - float protect_red=80.0f;// in C mode - dred *=coe;//in M mode - protect_red *=coe; - int sk=0; - float ko=1.f/coef; - Color::skinredfloat(Jpro, hpro, Mm, Mold, dred, protect_red,sk,rstprotection,ko, Mpro); - Cpro= Mpro/coe; - if(Jpro < 1.f && Mpro > 12.f*coe) Mpro=12.f*coe;//reduce artifacts by "pseudo gamut control CIECAM" - else if(Jpro < 2.f && Mpro > 15.f*coe) Mpro=15.f*coe; - else if(Jpro < 4.f && Mpro > 30.f*coe) Mpro=30.f*coe; - else if(Jpro < 7.f && Mpro > 50.f*coe) Mpro=50.f*coe; - } - } - //to retrieve the correct values of variables - - if(c1s) { - Qpro= ( 4.0f / c ) * sqrtf( Jpro / 100.0f ) * ( aw + 4.0f ) ;//for saturation curve - Cpro=(spro*spro*Qpro)/(10000.0f); - } - if(c1co) { - float coe=pow_F(fl,0.25f);Cpro= Mpro/coe;} // for colorfullness curve - //retrieve values C,J...s - C=Cpro; - J=Jpro; - Q=Qpro; - M=Mpro; - h=hpro; - s=spro; - - if(params->colorappearance.tonecie || settings->autocielab){//use pointer for tonemapping with CIECAM and also sharpening , defringe, contrast detail - ncie->Q_p[i][j]=(float)Q+epsil;//epsil to avoid Q=0 - ncie->M_p[i][j]=(float)M+epsil; - ncie->J_p[i][j]=(float)J+epsil; - ncie->h_p[i][j]=(float)h; - ncie->C_p[i][j]=(float)C+epsil; - ncie->sh_p[i][j]=(float) 3276.8f*(sqrtf( J ) ) ; - if(epdEnabled) { - if(ncie->Q_p[i][j]Q_p[i][j];//minima - if(ncie->Q_p[i][j]>maxQThr) - maxQThr = ncie->Q_p[i][j];//maxima - } - } - if(!params->colorappearance.tonecie || !settings->autocielab || !epdEnabled){ - - if(ciedata) { - // Data for J Q M s and C histograms - int posl, posc; - float brli=327.f; - float chsacol=327.f; - int libr=0; - int colch=0; - if(curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) {brli=70.0f; libr=1;} - else if(curveMode==ColorAppearanceParams::TC_MODE_LIGHT) {brli=327.f;libr=0;} - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA) {chsacol=327.f;colch=0;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_SATUR) {chsacol=450.0f;colch=1;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_COLORF) {chsacol=327.0f;colch=2;} - //update histogram - if(pW!=1){//only with improccoordinator - if(libr==1) posl=CLIP((int)(Q*brli));//40.0 to 100.0 approximative factor for Q - 327 for J - else if(libr==0) posl=CLIP((int)(J*brli));//327 for J - hist16JCAM[posl]++; - } - chropC=true; - if(pW!=1){//only with improccoordinator - if(colch==0) posc=CLIP((int)(C*chsacol));//450.0 approximative factor for s 320 for M - else if(colch==1) posc=CLIP((int)(s*chsacol)); - else if(colch==2) posc=CLIP((int)(M*chsacol)); - hist16_CCAM[posc]++; - } - } -if(LabPassOne){ -#ifdef __SSE2__ - // write to line buffers - Jbuffer[j] = J; - Cbuffer[j] = C; - hbuffer[j] = h; -#else - float xx,yy,zz; - //process normal==> viewing - - Ciecam02::jch2xyz_ciecam02float( xx, yy, zz, - J, C, h, - xw2, yw2, zw2, - yb2, la2, - f2, c2, nc2, gamu, pow1n, nbbj, ncbj, flj, czj, dj, awj); - float x,y,z; - x=(float)xx*655.35f; - y=(float)yy*655.35f; - z=(float)zz*655.35f; - float Ll,aa,bb; - //convert xyz=>lab - Color::XYZ2Lab(x, y, z, Ll, aa, bb); - - // gamut control in Lab mode; I must study how to do with cIECAM only - if(gamu==1) { - float HH, Lprov1, Chprov1; - Lprov1=Ll/327.68f; - Chprov1=sqrtf(SQR(aa) + SQR(bb))/327.68f; - HH=xatan2f(bb,aa); - float2 sincosval; - if(Chprov1==0.0f) { - sincosval.y = 1.f; - sincosval.x = 0.0f; - } else { - sincosval.y = aa/(Chprov1*327.68f); - sincosval.x = bb/(Chprov1*327.68f); - } - - -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wip, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wip, highlight, 0.15f, 0.96f); -#endif - - lab->L[i][j]=Lprov1*327.68f; - lab->a[i][j]=327.68f*Chprov1*sincosval.y; - lab->b[i][j]=327.68f*Chprov1*sincosval.x; - - } else { - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; - } -#endif - } - } - } -#ifdef __SSE2__ - // process line buffers - float *xbuffer = Qbuffer; - float *ybuffer = Mbuffer; - float *zbuffer = sbuffer; - for(k=0;klab - Color::XYZ2Lab(xbuffer[j], ybuffer[j], zbuffer[j], Ll, aa, bb); - - // gamut control in Lab mode; I must study how to do with cIECAM only - if(gamu==1) { - float HH, Lprov1, Chprov1; - Lprov1=Ll/327.68f; - Chprov1=sqrtf(SQR(aa) + SQR(bb))/327.68f; - HH=xatan2f(bb,aa); - float2 sincosval; - if(Chprov1==0.0f) { - sincosval.y = 1.f; - sincosval.x = 0.0f; - } else { - sincosval.y = aa/(Chprov1*327.68f); - sincosval.x = bb/(Chprov1*327.68f); - } -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wip, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wip, highlight, 0.15f, 0.96f); -#endif - lab->L[i][j]=Lprov1*327.68f; - lab->a[i][j]=327.68f*Chprov1*sincosval.y; - lab->b[i][j]=327.68f*Chprov1*sincosval.x; - } else { - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; + for (int i = 0; i < 32768; i++) { //# 32768*1.414 approximation maxi for chroma + val = (double)i / 32767.0; + dLcurve[i] = CLIPD(val); } } -#endif - } -#pragma omp critical -{ - if(minQThr < minQ) - minQ = minQThr; - if(maxQThr > maxQ) - maxQ = maxQThr; -} - } - // End of parallelization -if(!params->colorappearance.tonecie || !settings->autocielab){//normal - if(ciedata) { - //update histogram J - for (int i=0; i<32768; i++) {// - if (jp) { - float hval = dLcurve[i]; - int hi = (int)(255.0f*CLIPD(hval)); // - histLCAM[hi] += hist16JCAM[i] ; - } - } - for (int i=0; i<48000; i++) {// - if (chropC) { - float hvalc = dCcurve[i]; - int hic = (int)(255.0f*CLIPD(hvalc)); // - histCCAM[hic] += hist16_CCAM[i] ; - } - } - } -} + LUTf dCcurve(65536, 0); + LUTu hist16_CCAM(65536); + bool chropC = false; + float valc; + + if(pW != 1) { //only with improccoordinator + for (int i = 0; i < 48000; i++) { //# 32768*1.414 approximation maxi for chroma + valc = (double)i / 47999.0; + dCcurve[i] = CLIPD(valc); + } + + hist16_CCAM.clear(); + } + + //end preparate histogram + int width = lab->W, height = lab->H; + float minQ = 10000.f; + float maxQ = -1000.f; + float Yw; + Yw = 1.0; + double Xw, Zw; + float f, nc, yb, la, c, xw, yw, zw, f2, c2, nc2, yb2, la2; + float fl, n, nbb, ncb, aw; //d + float xwd, ywd, zwd; + int alg = 0; + bool algepd = false; + float sum = 0.f; + + const bool ciedata = (params->colorappearance.datacie && pW != 1); + bool jp = ciedata; + + ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB + + //viewing condition for surround + if(params->colorappearance.surround == "Average") { + f = 1.00f; + c = 0.69f; + nc = 1.00f; + f2 = 1.0f, c2 = 0.69f, nc2 = 1.0f; + } else if(params->colorappearance.surround == "Dim") { + f2 = 0.9f; + c2 = 0.59f; + nc2 = 0.9f; + f = 1.0f, c = 0.69f, nc = 1.0f; + } else if(params->colorappearance.surround == "Dark") { + f2 = 0.8f; + c2 = 0.525f; + nc2 = 0.8f; + f = 1.0f, c = 0.69f, nc = 1.0f; + } else if(params->colorappearance.surround == "ExtremelyDark") { + f2 = 0.8f; + c2 = 0.41f; + nc2 = 0.8f; + f = 1.0f, c = 0.69f, nc = 1.0f; + } + + //scene condition for surround + if(params->colorappearance.surrsource == true) { + f = 0.85f; // if user => source image has surround very dark + c = 0.55f; + nc = 0.85f; + } + + //with which algorithm + if (params->colorappearance.algo == "JC") { + alg = 0; + } else if(params->colorappearance.algo == "JS") { + alg = 1; + } else if(params->colorappearance.algo == "QM") { + alg = 2; + algepd = true; + } else if(params->colorappearance.algo == "ALL") { + alg = 3; + algepd = true; + } + + //settings white point of output device - or illuminant viewing + if(settings->viewingdevice == 0) { + xwd = 96.42f; //5000K + ywd = 100.0f; + zwd = 82.52f; + } else if(settings->viewingdevice == 1) { + xwd = 95.68f; //5500 + ywd = 100.0f; + zwd = 92.15f; + } else if(settings->viewingdevice == 2) { + xwd = 95.24f; //6000 + ywd = 100.0f; + zwd = 100.81f; + } else if(settings->viewingdevice == 3) { + xwd = 95.04f; //6500 + ywd = 100.0f; + zwd = 108.88f; + } else if(settings->viewingdevice == 4) { + xwd = 109.85f; //tungsten + ywd = 100.0f; + zwd = 35.58f; + } else if(settings->viewingdevice == 5) { + xwd = 99.18f; //fluo F2 + ywd = 100.0f; + zwd = 67.39f; + } else if(settings->viewingdevice == 6) { + xwd = 95.04f; //fluo F7 + ywd = 100.0f; + zwd = 108.75f; + } else if(settings->viewingdevice == 7) { + xwd = 100.96f; //fluo F11 + ywd = 100.0f; + zwd = 64.35f; + } + + + //settings mean Luminance Y of output device or viewing + if(settings->viewingdevicegrey == 0) { + yb2 = 5.0f; + } else if(settings->viewingdevicegrey == 1) { + yb2 = 10.0f; + } else if(settings->viewingdevicegrey == 2) { + yb2 = 15.0f; + } else if(settings->viewingdevicegrey == 3) { + yb2 = 18.0f; + } else if(settings->viewingdevicegrey == 4) { + yb2 = 23.0f; + } else if(settings->viewingdevicegrey == 5) { + yb2 = 30.0f; + } else if(settings->viewingdevicegrey == 6) { + yb2 = 40.0f; + } + + //La and la2 = ambiant luminosity scene and viewing + la = float(params->colorappearance.adapscen); + + if(pwb == 2) { + if(params->colorappearance.autoadapscen) { + la = adap; + } + } + + la2 = float(params->colorappearance.adaplum); + + // level of adaptation + const float deg = (params->colorappearance.degree) / 100.0f; + const float pilot = params->colorappearance.autodegree ? 2.0f : deg; + + //algoritm's params + float chr = 0.f; + + if(alg == 0 || alg == 3) { + chr = params->colorappearance.chroma; + + if(chr == -100.0f) { + chr = -99.8f; + } + } + + float schr = 0.f; + + if(alg == 3 || alg == 1) { + schr = params->colorappearance.schroma; + + if(schr > 0.0) { + schr = schr / 2.0f; //divide sensibility for saturation + } + + if(alg == 3) { + if(schr == -100.0f) { + schr = -99.f; + } + + if(schr == 100.0f) { + schr = 98.f; + } + } else { + if(schr == -100.0f) { + schr = -99.8f; + } + } + } + + float mchr = 0.f; + + if(alg == 3 || alg == 2) { + mchr = params->colorappearance.mchroma; + + if(mchr == -100.0f) { + mchr = -99.8f ; + } + + if(mchr == 100.0f) { + mchr = 99.9f; + } + } + + const float hue = params->colorappearance.colorh; + const float rstprotection = 100. - params->colorappearance.rstprotection; + + // extracting datas from 'params' to avoid cache flush (to be confirmed) + const ColorAppearanceParams::eTCModeId curveMode = params->colorappearance.curveMode; + const bool hasColCurve1 = bool(customColCurve1); + bool t1L = false; + bool t1B = false; + + if (hasColCurve1 && curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + t1L = true; + } + + if(hasColCurve1 && curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + t1B = true; + } + + const ColorAppearanceParams::eTCModeId curveMode2 = params->colorappearance.curveMode2; + const bool hasColCurve2 = bool(customColCurve2); + bool t2B = false; + + if(hasColCurve2 && curveMode2 == ColorAppearanceParams::TC_MODE_BRIGHT) { + t2B = true; + } + + const ColorAppearanceParams::eCTCModeId curveMode3 = params->colorappearance.curveMode3; + const bool hasColCurve3 = bool(customColCurve3); + bool c1s = false; + bool c1co = false; + + if( hasColCurve3 && curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { + c1s = true; + } + + if(hasColCurve3 && curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { + c1co = true; + } + + if(CAMBrightCurveJ.dirty || CAMBrightCurveQ.dirty) { + bool needJ = (alg == 0 || alg == 1 || alg == 3); + bool needQ = (alg == 2 || alg == 3); + LUTu hist16J; + LUTu hist16Q; + + if (needJ) { + hist16J (65536); + hist16J.clear(); + } + + if (needQ) { + hist16Q (65536); + hist16Q.clear(); + } + + #pragma omp parallel + { + LUTu hist16Jthr; + LUTu hist16Qthr; + + if (needJ) { + hist16Jthr (65536); + hist16Jthr.clear(); + } + + if (needQ) { + hist16Qthr(65536); + hist16Qthr.clear(); + } + + #pragma omp for reduction(+:sum) + + for (int i = 0; i < height; i++) + for (int j = 0; j < width; j++) { //rough correspondence between L and J + float currL = lab->L[i][j] / 327.68f; + float koef = 1.0f; //rough correspondence between L and J + +// if (currL>95.f) koef=1.f; + if(currL > 85.f) { + koef = 0.97f; + } else if(currL > 80.f) { + koef = 0.93f; + } else if(currL > 70.f) { + koef = 0.87f; + } else if(currL > 60.f) { + koef = 0.85f; + } else if(currL > 50.f) { + koef = 0.8f; + } else if(currL > 40.f) { + koef = 0.75f; + } +// else if(currL>30.f) koef=0.7f; + else if(currL > 20.f) { + koef = 0.7f; + } else if(currL > 10.f) { + koef = 0.9f; + } + +// else if(currL>0.f) koef=1.0f; + + if (needJ) { + hist16Jthr[CLIP((int)((koef * lab->L[i][j])))]++; //evaluate histogram luminance L # J + } + + if (needQ) { + hist16Qthr[CLIP((int) (sqrtf((koef * (lab->L[i][j])) * 32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L + } + + sum += koef * lab->L[i][j]; //evaluate mean J to calculate Yb + } + + #pragma omp critical + { + if(needJ) + for(int i = 0; i < 65536; i++) { + hist16J[i] += hist16Jthr[i]; + } + + if(needQ) + for(int i = 0; i < 65536; i++) { + hist16Q[i] += hist16Qthr[i]; + } + + } + } + + + //mean=(sum/((endh-begh)*width))/327.68f;//for Yb for all image...if one day "pipette" we can adapt Yb for each zone + mean = (sum / ((height) * width)) / 327.68f; //for Yb for all image...if one day "pipette" we can adapt Yb for each zone + + //evaluate lightness, contrast + if (needJ) { + if (!CAMBrightCurveJ) { + CAMBrightCurveJ(32768, LUT_CLIP_ABOVE); + CAMBrightCurveJ.dirty = false; + } + + float jli = params->colorappearance.jlight; + float contra = params->colorappearance.contrast; + Ciecam02::curveJfloat (jli, contra, 1, CAMBrightCurveJ, hist16J);//lightness and contrast J + } + + if (needQ) { + if (!CAMBrightCurveQ) { + CAMBrightCurveQ(32768, LUT_CLIP_ABOVE); + CAMBrightCurveQ.clear(); + CAMBrightCurveQ.dirty = false; + } + + float qbri = params->colorappearance.qbright; + float qcontra = params->colorappearance.qcontrast; + Ciecam02::curveJfloat (qbri, qcontra, 1, CAMBrightCurveQ, hist16Q);//brightness and contrast Q + } + } + + if(settings->viewinggreySc == 0) { //auto + if (mean < 15.f) { + yb = 3.0f; + } else if(mean < 30.f) { + yb = 5.0f; + } else if(mean < 40.f) { + yb = 10.0f; + } else if(mean < 45.f) { + yb = 15.0f; + } else if(mean < 50.f) { + yb = 18.0f; + } else if(mean < 55.f) { + yb = 23.0f; + } else if(mean < 60.f) { + yb = 30.0f; + } else if(mean < 70.f) { + yb = 40.0f; + } else if(mean < 80.f) { + yb = 60.0f; + } else if(mean < 90.f) { + yb = 80.0f; + } else { + yb = 90.0f; + } + } + + if(settings->viewinggreySc == 1) { + yb = 18.0f; //fixed + } + + + const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated + + const int gamu = (params->colorappearance.gamut == true) ? 1 : 0; + xw = 100.0f * Xw; + yw = 100.0f * Yw; + zw = 100.0f * Zw; + float xw1, yw1, zw1, xw2, yw2, zw2; + + // settings of WB: scene and viewing + if(params->colorappearance.wbmodel == "RawT") { + xw1 = 96.46f; //use RT WB; CAT 02 is used for output device (see prefreneces) + yw1 = 100.0f; + zw1 = 82.445f; + xw2 = xwd; + yw2 = ywd; + zw2 = zwd; + } else if(params->colorappearance.wbmodel == "RawTCAT02") { + xw1 = xw; // Settings RT WB are used for CAT02 => mix , CAT02 is use for output device (screen: D50 D65, projector: lamp, LED) see preferences + yw1 = yw; + zw1 = zw; + xw2 = xwd; + yw2 = ywd; + zw2 = zwd; + } + + float cz, wh, pfl; + Ciecam02::initcam1float(gamu, yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c); + const float pow1 = pow_F( 1.64f - pow_F( 0.29f, n ), 0.73f ); + float nj, dj, nbbj, ncbj, czj, awj, flj; + Ciecam02::initcam2float(gamu, yb2, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj); + const float reccmcz = 1.f / (c2 * czj); + const float pow1n = pow_F( 1.64f - pow_F( 0.29f, nj ), 0.73f ); + + const float epsil = 0.0001f; + const float w_h = wh + epsil; + const float a_w = aw; + const float c_ = c; + const float f_l = fl; + const float coe = pow_F(fl, 0.25f); + const float QproFactor = ( 0.4f / c ) * ( aw + 4.0f ) ; + const bool epdEnabled = params->epd.enabled; + const bool LabPassOne = !((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) + || (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) + || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab)); + + //matrix for current working space + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + const float wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; + +#ifdef __SSE2__ + int bufferLength = ((width + 3) / 4) * 4; // bufferLength has to be a multiple of 4 +#endif +#ifndef _DEBUG + #pragma omp parallel +#endif + { + float minQThr = 10000.f; + float maxQThr = -1000.f; +#ifdef __SSE2__ + // one line buffer per channel and thread + float Jbuffer[bufferLength] ALIGNED16; + float Cbuffer[bufferLength] ALIGNED16; + float hbuffer[bufferLength] ALIGNED16; + float Qbuffer[bufferLength] ALIGNED16; + float Mbuffer[bufferLength] ALIGNED16; + float sbuffer[bufferLength] ALIGNED16; +#endif +#ifndef _DEBUG + #pragma omp for schedule(dynamic, 16) +#endif + + for (int i = 0; i < height; i++) { +#ifdef __SSE2__ + // vectorized conversion from Lab to jchqms + int k; + vfloat x, y, z; + vfloat J, C, h, Q, M, s; + + vfloat c655d35 = F2V(655.35f); + + for(k = 0; k < width - 3; k += 4) { + Color::Lab2XYZ(LVFU(lab->L[i][k]), LVFU(lab->a[i][k]), LVFU(lab->b[i][k]), x, y, z); + x = x / c655d35; + y = y / c655d35; + z = z / c655d35; + Ciecam02::xyz2jchqms_ciecam02float( J, C, h, + Q, M, s, F2V(aw), F2V(fl), F2V(wh), + x, y, z, + F2V(xw1), F2V(yw1), F2V(zw1), + F2V(yb), F2V(la), + F2V(f), F2V(c), F2V(nc), F2V(pow1), F2V(nbb), F2V(ncb), F2V(pfl), F2V(cz), F2V(d)); + STVF(Jbuffer[k], J); + STVF(Cbuffer[k], C); + STVF(hbuffer[k], h); + STVF(Qbuffer[k], Q); + STVF(Mbuffer[k], M); + STVF(sbuffer[k], s); + } + + for(; k < width; k++) { + float L = lab->L[i][k]; + float a = lab->a[i][k]; + float b = lab->b[i][k]; + float x, y, z; + //convert Lab => XYZ + Color::Lab2XYZ(L, a, b, x, y, z); + x = x / 655.35f; + y = y / 655.35f; + z = z / 655.35f; + float J, C, h, Q, M, s; + Ciecam02::xyz2jchqms_ciecam02float( J, C, h, + Q, M, s, aw, fl, wh, + x, y, z, + xw1, yw1, zw1, + yb, la, + f, c, nc, pilot, gamu, pow1, nbb, ncb, pfl, cz, d); + Jbuffer[k] = J; + Cbuffer[k] = C; + hbuffer[k] = h; + Qbuffer[k] = Q; + Mbuffer[k] = M; + sbuffer[k] = s; + } + +#endif // __SSE2__ + + for (int j = 0; j < width; j++) { + float J, C, h, Q, M, s; + +#ifdef __SSE2__ + // use precomputed values from above + J = Jbuffer[j]; + C = Cbuffer[j]; + h = hbuffer[j]; + Q = Qbuffer[j]; + M = Mbuffer[j]; + s = sbuffer[j]; +#else + float x, y, z; + float L = lab->L[i][j]; + float a = lab->a[i][j]; + float b = lab->b[i][j]; + float x1, y1, z1; + //convert Lab => XYZ + Color::Lab2XYZ(L, a, b, x1, y1, z1); + x = (float)x1 / 655.35f; + y = (float)y1 / 655.35f; + z = (float)z1 / 655.35f; + //process source==> normal + Ciecam02::xyz2jchqms_ciecam02float( J, C, h, + Q, M, s, aw, fl, wh, + x, y, z, + xw1, yw1, zw1, + yb, la, + f, c, nc, pilot, gamu, pow1, nbb, ncb, pfl, cz, d); +#endif + float Jpro, Cpro, hpro, Qpro, Mpro, spro; + Jpro = J; + Cpro = C; + hpro = h; + Qpro = Q; + Mpro = M; + spro = s; + + // we cannot have all algorithms with all chroma curves + if(alg == 0) { + Jpro = CAMBrightCurveJ[Jpro * 327.68f] / 327.68f; //lightness CIECAM02 + contrast + Qpro = QproFactor * sqrtf(Jpro); + float Cp = (spro * spro * Qpro) / (1000000.f); + Cpro = Cp * 100.f; + float sres; + Ciecam02::curvecolorfloat(chr, Cp , sres, 1.8f); + Color::skinredfloat(Jpro, hpro, sres, Cp, 55.f, 30.f, 1, rstprotection, 100.f, Cpro); + } + + if(alg == 1) { + // Lightness saturation + Jpro = CAMBrightCurveJ[Jpro * 327.68f] / 327.68f; //lightness CIECAM02 + contrast + float sres; + float Sp = spro / 100.0f; + float parsat = 1.5f; //parsat=1.5 =>saturation ; 1.8 => chroma ; 2.5 => colorfullness (personal evaluation) + Ciecam02::curvecolorfloat(schr, Sp , sres, parsat); + float dred = 100.f; // in C mode + float protect_red = 80.0f; // in C mode + dred = 100.0f * sqrtf((dred * coe) / Qpro); + protect_red = 100.0f * sqrtf((protect_red * coe) / Qpro); + Color::skinredfloat(Jpro, hpro, sres, Sp, dred, protect_red, 0, rstprotection, 100.f, spro); + Qpro = QproFactor * sqrtf(Jpro); + Cpro = (spro * spro * Qpro) / (10000.0f); + } else if(alg == 2) { + float coef = 32767.f / wh; + Qpro = (CAMBrightCurveQ[(float)(Qpro * coef)]) / coef; //brightness and contrast + float Mp, sres; + Mp = Mpro / 100.0f; + Ciecam02::curvecolorfloat(mchr, Mp , sres, 2.5f); + float dred = 100.f; //in C mode + float protect_red = 80.0f; // in C mode + dred *= coe; //in M mode + protect_red *= coe; //M mode + Color::skinredfloat(Jpro, hpro, sres, Mp, dred, protect_red, 0, rstprotection, 100.f, Mpro); + Jpro = SQR((10.f * Qpro) / wh); + Cpro = Mpro / coe; + Qpro = (Qpro == 0.f ? epsil : Qpro); // avoid division by zero + spro = 100.0f * sqrtf( Mpro / Qpro ); + } else if(alg == 3) { + float coef = 32760.f / wh; + + if(Qpro * coef >= 32767.0f) { + Qpro = (CAMBrightCurveQ[32767]) / coef; //brightness and contrast + } else { + Qpro = (CAMBrightCurveQ[(float)(Qpro * coef)]) / coef; //brightness and contrast + } + + float Mp, sres; + Mp = Mpro / 100.0f; + Ciecam02::curvecolorfloat(mchr, Mp , sres, 2.5f); + float dred = 100.f; //in C mode + float protect_red = 80.0f; // in C mode + dred *= coe; //in M mode + protect_red *= coe; //M mode + Color::skinredfloat(Jpro, hpro, sres, Mp, dred, protect_red, 0, rstprotection, 100.f, Mpro); + Jpro = SQR((10.f * Qpro) / wh); + Cpro = Mpro / coe; + Qpro = (Qpro == 0.f ? epsil : Qpro); // avoid division by zero + spro = 100.0f * sqrtf( Mpro / Qpro ); + + if(Jpro > 99.9f) { + Jpro = 99.9f; + } + + Jpro = (CAMBrightCurveJ[(float)(Jpro * 327.68f)]) / 327.68f; //lightness CIECAM02 + contrast + float Sp = spro / 100.0f; + Ciecam02::curvecolorfloat(schr, Sp , sres, 1.5f); + dred = 100.f; // in C mode + protect_red = 80.0f; // in C mode + dred = 100.0f * sqrtf((dred * coe) / Q); + protect_red = 100.0f * sqrtf((protect_red * coe) / Q); + Color::skinredfloat(Jpro, hpro, sres, Sp, dred, protect_red, 0, rstprotection, 100.f, spro); + Qpro = QproFactor * sqrtf(Jpro); + float Cp = (spro * spro * Qpro) / (1000000.f); + Cpro = Cp * 100.f; + Ciecam02::curvecolorfloat(chr, Cp , sres, 1.8f); + Color::skinredfloat(Jpro, hpro, sres, Cp, 55.f, 30.f, 1, rstprotection, 100.f, Cpro); +// disabled this code, Issue 2690 +// if(Jpro < 1.f && Cpro > 12.f) Cpro=12.f;//reduce artifacts by "pseudo gamut control CIECAM" +// else if(Jpro < 2.f && Cpro > 15.f) Cpro=15.f; +// else if(Jpro < 4.f && Cpro > 30.f) Cpro=30.f; +// else if(Jpro < 7.f && Cpro > 50.f) Cpro=50.f; + hpro = hpro + hue; + + if( hpro < 0.0f ) { + hpro += 360.0f; //hue + } + } + + if (hasColCurve1) {//curve 1 with Lightness and Brightness + if (curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + float Jj = (float) Jpro * 327.68f; + float Jold = Jj; + float Jold100 = (float) Jpro; + float redu = 25.f; + float reduc = 1.f; + const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); + userColCurveJ1.Apply(Jj); + + if(Jj > Jold) { + if(Jj < 65535.f) { + if(Jold < 327.68f * redu) { + Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility + } else { + reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f); + Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights + } + } + } else if(Jj > 10.f) { + Jj = 0.8f * (Jj - Jold) + Jold; + } else if (Jj >= 0.f) { + Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts + } + + Jpro = (float)(Jj / 327.68f); + + if(Jpro < 1.f) { + Jpro = 1.f; + } + } else if (curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + //attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different + float coef = ((aw + 4.f) * (4.f / c)) / 100.f; + float Qq = (float) Qpro * 327.68f * (1.f / coef); + float Qold100 = (float) Qpro / coef; + + float Qold = Qq; + float redu = 20.f; + float reduc = 1.f; + + const Brightcurve& userColCurveB1 = static_cast(customColCurve1); + userColCurveB1.Apply(Qq); + + if(Qq > Qold) { + if(Qq < 65535.f) { + if(Qold < 327.68f * redu) { + Qq = 0.25f * (Qq - Qold) + Qold; //divide sensibility + } else { + reduc = LIM((100.f - Qold100) / (100.f - redu), 0.f, 1.f); + Qq = 0.25f * reduc * (Qq - Qold) + Qold; //reduct sensibility in highlights + } + } + } else if(Qq > 10.f) { + Qq = 0.5f * (Qq - Qold) + Qold; + } else if (Qq >= 0.f) { + Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts + } + + Qpro = (float)(Qq * (coef) / 327.68f); + Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f)); + + if(Jpro < 1.f) { + Jpro = 1.f; + } + } + } + + if (hasColCurve2) {//curve 2 with Lightness and Brightness + if (curveMode2 == ColorAppearanceParams::TC_MODE_LIGHT) { + float Jj = (float) Jpro * 327.68f; + float Jold = Jj; + float Jold100 = (float) Jpro; + float redu = 25.f; + float reduc = 1.f; + const Lightcurve& userColCurveJ2 = static_cast(customColCurve2); + userColCurveJ2.Apply(Jj); + + if(Jj > Jold) { + if(Jj < 65535.f) { + if(Jold < 327.68f * redu) { + Jj = 0.3f * (Jj - Jold) + Jold; //divide sensibility + } else { + reduc = LIM((100.f - Jold100) / (100.f - redu), 0.f, 1.f); + Jj = 0.3f * reduc * (Jj - Jold) + Jold; //reduct sensibility in highlights + } + } + } else if(Jj > 10.f) { + if(!t1L) { + Jj = 0.8f * (Jj - Jold) + Jold; + } else { + Jj = 0.4f * (Jj - Jold) + Jold; + } + } else if (Jj >= 0.f) { + if(!t1L) { + Jj = 0.90f * (Jj - Jold) + Jold; // not zero ==>artifacts + } else { + Jj = 0.5f * (Jj - Jold) + Jold; + } + } + + Jpro = (float)(Jj / 327.68f); + + if(Jpro < 1.f) { + Jpro = 1.f; + } + + } else if (curveMode2 == ColorAppearanceParams::TC_MODE_BRIGHT) { // + float coef = ((aw + 4.f) * (4.f / c)) / 100.f; + float Qq = (float) Qpro * 327.68f * (1.f / coef); + float Qold100 = (float) Qpro / coef; + + float Qold = Qq; + float redu = 20.f; + float reduc = 1.f; + + const Brightcurve& userColCurveB2 = static_cast(customColCurve2); + userColCurveB2.Apply(Qq); + + if(Qq > Qold) { + if(Qq < 65535.f) { + if(Qold < 327.68f * redu) { + Qq = 0.25f * (Qq - Qold) + Qold; //divide sensibility + } else { + reduc = LIM((100.f - Qold100) / (100.f - redu), 0.f, 1.f); + Qq = 0.25f * reduc * (Qq - Qold) + Qold; //reduct sensibility in highlights + } + } + } else if(Qq > 10.f) { + Qq = 0.5f * (Qq - Qold) + Qold; + } else if (Qq >= 0.f) { + Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts + } + + Qpro = (float)(Qq * (coef) / 327.68f); + Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f)); + + if(t1L) { //to workaround the problem if we modify curve1-lightnees after curve2 brightness(the cat that bites its own tail!) in fact it's another type of curve only for this case + coef = 2.f; //adapt Q to J approximation + Qq = (float) Qpro * coef; + Qold = Qq; + const Lightcurve& userColCurveJ1 = static_cast(customColCurve1); + userColCurveJ1.Apply(Qq); + Qq = 0.05f * (Qq - Qold) + Qold; //approximative adaptation + Qpro = (float)(Qq / coef); + Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f)); + } + + if(Jpro < 1.f) { + Jpro = 1.f; + } + } + } + + if (hasColCurve3) {//curve 3 with chroma saturation colorfullness + if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { + float parsat = 0.8f; //0.68; + float coef = 327.68f / parsat; + float Cc = (float) Cpro * coef; + float Ccold = Cc; + const Chromacurve& userColCurve = static_cast(customColCurve3); + userColCurve.Apply(Cc); + float dred = 55.f; + float protect_red = 30.0f; + int sk = 1; + float ko = 1.f / coef; + Color::skinredfloat(Jpro, hpro, Cc, Ccold, dred, protect_red, sk, rstprotection, ko, Cpro); + + if(Jpro < 1.f && Cpro > 12.f) { + Cpro = 12.f; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2.f && Cpro > 15.f) { + Cpro = 15.f; + } else if(Jpro < 4.f && Cpro > 30.f) { + Cpro = 30.f; + } else if(Jpro < 7.f && Cpro > 50.f) { + Cpro = 50.f; + } + + } else if (curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { // + float parsat = 0.8f; //0.6 + float coef = 327.68f / parsat; + float Ss = (float) spro * coef; + float Sold = Ss; + const Saturcurve& userColCurve = static_cast(customColCurve3); + userColCurve.Apply(Ss); + Ss = 0.6f * (Ss - Sold) + Sold; //divide sensibility saturation + float dred = 100.f; // in C mode + float protect_red = 80.0f; // in C mode + dred = 100.0f * sqrtf((dred * coe) / Qpro); + protect_red = 100.0f * sqrtf((protect_red * coe) / Qpro); + int sk = 0; + float ko = 1.f / coef; + Color::skinredfloat(Jpro, hpro, Ss, Sold, dred, protect_red, sk, rstprotection, ko, spro); + Qpro = ( 4.0f / c ) * sqrtf( Jpro / 100.0f ) * ( aw + 4.0f ) ; + Cpro = (spro * spro * Qpro) / (10000.0f); + + } else if (curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { // + float parsat = 0.8f; //0.68; + float coef = 327.68f / parsat; + float Mm = (float) Mpro * coef; + float Mold = Mm; + const Colorfcurve& userColCurve = static_cast(customColCurve3); + userColCurve.Apply(Mm); + float dred = 100.f; //in C mode + float protect_red = 80.0f; // in C mode + dred *= coe; //in M mode + protect_red *= coe; + int sk = 0; + float ko = 1.f / coef; + Color::skinredfloat(Jpro, hpro, Mm, Mold, dred, protect_red, sk, rstprotection, ko, Mpro); + Cpro = Mpro / coe; + + if(Jpro < 1.f && Mpro > 12.f * coe) { + Mpro = 12.f * coe; //reduce artifacts by "pseudo gamut control CIECAM" + } else if(Jpro < 2.f && Mpro > 15.f * coe) { + Mpro = 15.f * coe; + } else if(Jpro < 4.f && Mpro > 30.f * coe) { + Mpro = 30.f * coe; + } else if(Jpro < 7.f && Mpro > 50.f * coe) { + Mpro = 50.f * coe; + } + } + } + + //to retrieve the correct values of variables + + if(c1s) { + Qpro = ( 4.0f / c ) * sqrtf( Jpro / 100.0f ) * ( aw + 4.0f ) ; //for saturation curve + Cpro = (spro * spro * Qpro) / (10000.0f); + } + + if(c1co) { + float coe = pow_F(fl, 0.25f); + Cpro = Mpro / coe; + } // for colorfullness curve + + //retrieve values C,J...s + C = Cpro; + J = Jpro; + Q = Qpro; + M = Mpro; + h = hpro; + s = spro; + + if(params->colorappearance.tonecie || settings->autocielab) { //use pointer for tonemapping with CIECAM and also sharpening , defringe, contrast detail + ncie->Q_p[i][j] = (float)Q + epsil; //epsil to avoid Q=0 + ncie->M_p[i][j] = (float)M + epsil; + ncie->J_p[i][j] = (float)J + epsil; + ncie->h_p[i][j] = (float)h; + ncie->C_p[i][j] = (float)C + epsil; + ncie->sh_p[i][j] = (float) 3276.8f * (sqrtf( J ) ) ; + + if(epdEnabled) { + if(ncie->Q_p[i][j] < minQThr) { + minQThr = ncie->Q_p[i][j]; //minima + } + + if(ncie->Q_p[i][j] > maxQThr) { + maxQThr = ncie->Q_p[i][j]; //maxima + } + } + } + + if(!params->colorappearance.tonecie || !settings->autocielab || !epdEnabled) { + + if(ciedata) { + // Data for J Q M s and C histograms + int posl, posc; + float brli = 327.f; + float chsacol = 327.f; + int libr = 0; + int colch = 0; + + if(curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + brli = 70.0f; + libr = 1; + } else if(curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + brli = 327.f; + libr = 0; + } + + if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { + chsacol = 327.f; + colch = 0; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { + chsacol = 450.0f; + colch = 1; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { + chsacol = 327.0f; + colch = 2; + } + + //update histogram + if(pW != 1) { //only with improccoordinator + if(libr == 1) { + posl = CLIP((int)(Q * brli)); //40.0 to 100.0 approximative factor for Q - 327 for J + } else if(libr == 0) { + posl = CLIP((int)(J * brli)); //327 for J + } + + hist16JCAM[posl]++; + } + + chropC = true; + + if(pW != 1) { //only with improccoordinator + if(colch == 0) { + posc = CLIP((int)(C * chsacol)); //450.0 approximative factor for s 320 for M + } else if(colch == 1) { + posc = CLIP((int)(s * chsacol)); + } else if(colch == 2) { + posc = CLIP((int)(M * chsacol)); + } + + hist16_CCAM[posc]++; + } + } + + if(LabPassOne) { +#ifdef __SSE2__ + // write to line buffers + Jbuffer[j] = J; + Cbuffer[j] = C; + hbuffer[j] = h; +#else + float xx, yy, zz; + //process normal==> viewing + + Ciecam02::jch2xyz_ciecam02float( xx, yy, zz, + J, C, h, + xw2, yw2, zw2, + yb2, la2, + f2, c2, nc2, gamu, pow1n, nbbj, ncbj, flj, czj, dj, awj); + float x, y, z; + x = (float)xx * 655.35f; + y = (float)yy * 655.35f; + z = (float)zz * 655.35f; + float Ll, aa, bb; + //convert xyz=>lab + Color::XYZ2Lab(x, y, z, Ll, aa, bb); + + // gamut control in Lab mode; I must study how to do with cIECAM only + if(gamu == 1) { + float HH, Lprov1, Chprov1; + Lprov1 = Ll / 327.68f; + Chprov1 = sqrtf(SQR(aa) + SQR(bb)) / 327.68f; + HH = xatan2f(bb, aa); + float2 sincosval; + + if(Chprov1 == 0.0f) { + sincosval.y = 1.f; + sincosval.x = 0.0f; + } else { + sincosval.y = aa / (Chprov1 * 327.68f); + sincosval.x = bb / (Chprov1 * 327.68f); + } + + #ifdef _DEBUG - if (settings->verbose) { - t2e.set(); - printf("CIECAM02 performed in %d usec:\n", t2e.etime(t1e)); - // printf("minc=%f maxc=%f minj=%f maxj=%f\n",minc,maxc,minj,maxj); - } + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.96f); #endif -if(settings->autocielab) { -if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) - || (params->dirpyrequalizer.enabled && settings->autocielab) ||(params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) - || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl >0 && settings->autocielab)){ + lab->L[i][j] = Lprov1 * 327.68f; + lab->a[i][j] = 327.68f * Chprov1 * sincosval.y; + lab->b[i][j] = 327.68f * Chprov1 * sincosval.x; + + } else { + lab->L[i][j] = Ll; + lab->a[i][j] = aa; + lab->b[i][j] = bb; + } + +#endif + } + } + } + +#ifdef __SSE2__ + // process line buffers + float *xbuffer = Qbuffer; + float *ybuffer = Mbuffer; + float *zbuffer = sbuffer; + + for(k = 0; k < bufferLength; k += 4) { + Ciecam02::jch2xyz_ciecam02float( x, y, z, + LVF(Jbuffer[k]), LVF(Cbuffer[k]), LVF(hbuffer[k]), + F2V(xw2), F2V(yw2), F2V(zw2), + F2V(yb2), F2V(la2), + F2V(f2), F2V(nc2), F2V(pow1n), F2V(nbbj), F2V(ncbj), F2V(flj), F2V(dj), F2V(awj), F2V(reccmcz)); + STVF(xbuffer[k], x * c655d35); + STVF(ybuffer[k], y * c655d35); + STVF(zbuffer[k], z * c655d35); + } + + // XYZ2Lab uses a lookup table. The function behind that lut is a cube root. + // SSE can't beat the speed of that lut, so it doesn't make sense to use SSE + for(int j = 0; j < width; j++) { + float Ll, aa, bb; + //convert xyz=>lab + Color::XYZ2Lab(xbuffer[j], ybuffer[j], zbuffer[j], Ll, aa, bb); + + // gamut control in Lab mode; I must study how to do with cIECAM only + if(gamu == 1) { + float HH, Lprov1, Chprov1; + Lprov1 = Ll / 327.68f; + Chprov1 = sqrtf(SQR(aa) + SQR(bb)) / 327.68f; + HH = xatan2f(bb, aa); + float2 sincosval; + + if(Chprov1 == 0.0f) { + sincosval.y = 1.f; + sincosval.x = 0.0f; + } else { + sincosval.y = aa / (Chprov1 * 327.68f); + sincosval.x = bb / (Chprov1 * 327.68f); + } + +#ifdef _DEBUG + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wip, highlight, 0.15f, 0.96f); +#endif + lab->L[i][j] = Lprov1 * 327.68f; + lab->a[i][j] = 327.68f * Chprov1 * sincosval.y; + lab->b[i][j] = 327.68f * Chprov1 * sincosval.x; + } else { + lab->L[i][j] = Ll; + lab->a[i][j] = aa; + lab->b[i][j] = bb; + } + } + +#endif + } + + #pragma omp critical + { + if(minQThr < minQ) { + minQ = minQThr; + } + + if(maxQThr > maxQ) { + maxQ = maxQThr; + } + } + } + + // End of parallelization + if(!params->colorappearance.tonecie || !settings->autocielab) { //normal + + if(ciedata) { + //update histogram J + for (int i = 0; i < 32768; i++) { // + if (jp) { + float hval = dLcurve[i]; + int hi = (int)(255.0f * CLIPD(hval)); // + histLCAM[hi] += hist16JCAM[i] ; + } + } + + for (int i = 0; i < 48000; i++) { // + if (chropC) { + float hvalc = dCcurve[i]; + int hic = (int)(255.0f * CLIPD(hvalc)); // + histCCAM[hic] += hist16_CCAM[i] ; + } + } + } + } + +#ifdef _DEBUG + + if (settings->verbose) { + t2e.set(); + printf("CIECAM02 performed in %d usec:\n", t2e.etime(t1e)); + // printf("minc=%f maxc=%f minj=%f maxj=%f\n",minc,maxc,minj,maxj); + } + +#endif + + if(settings->autocielab) { + if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) + || (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) + || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab)) { //all this treatments reduce artefacts, but can leed to slighty different results -if(params->defringe.enabled) - if(execsharp) { - lab->deleteLab(); - ImProcFunctions::defringecam (ncie);//defringe adapted to CIECAM - lab->reallocLab(); - } -//if(params->dirpyrequalizer.enabled) if(execsharp) { -if(params->dirpyrequalizer.enabled) { - if(params->dirpyrequalizer.gamutlab /*&& execsharp*/) {//remove artifacts by gaussian blur - skin control - float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; - float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; - float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; - float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; - float artifact=(float) settings->artifact_cbdl; - if(artifact > 6.f) artifact=6.f; - if(artifact <0.f) artifact=1.f; + if(params->defringe.enabled) + if(execsharp) { + lab->deleteLab(); + ImProcFunctions::defringecam (ncie);//defringe adapted to CIECAM + lab->reallocLab(); + } - int hotbad=0; - float chrom=50.f; - lab->deleteLab(); - ImProcFunctions::badpixcam (ncie, artifact, 5, 2 , b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect, chrom, hotbad); //enabled remove artifacts for cbDL - lab->reallocLab(); - } -} +//if(params->dirpyrequalizer.enabled) if(execsharp) { + if(params->dirpyrequalizer.enabled) { + if(params->dirpyrequalizer.gamutlab /*&& execsharp*/) {//remove artifacts by gaussian blur - skin control + float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; + float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; + float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; + float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; + float artifact = (float) settings->artifact_cbdl; + + if(artifact > 6.f) { + artifact = 6.f; + } + + if(artifact < 0.f) { + artifact = 1.f; + } + + int hotbad = 0; + float chrom = 50.f; + lab->deleteLab(); + ImProcFunctions::badpixcam (ncie, artifact, 5, 2 , b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect, chrom, hotbad); //enabled remove artifacts for cbDL + lab->reallocLab(); + } + } //if(params->colorappearance.badpixsl > 0) { int mode=params->colorappearance.badpixsl; -if(params->colorappearance.badpixsl > 0) if(execsharp){ - int mode=params->colorappearance.badpixsl; - lab->deleteLab(); - ImProcFunctions::badpixcam (ncie, 3.0, 10, mode, 0, 0, 0, 0, 0, 0, 1);//for bad pixels CIECAM - lab->reallocLab(); -} + if(params->colorappearance.badpixsl > 0) if(execsharp) { + int mode = params->colorappearance.badpixsl; + lab->deleteLab(); + ImProcFunctions::badpixcam (ncie, 3.0, 10, mode, 0, 0, 0, 0, 0, 0, 1);//for bad pixels CIECAM + lab->reallocLab(); + } -if(params->impulseDenoise.enabled) if(execsharp) { - float **buffers[3]; - buffers[0] = lab->L; - buffers[1] = lab->a; - buffers[2] = lab->b; - ImProcFunctions::impulsedenoisecam (ncie,buffers);//impulse adapted to CIECAM -} + if(params->impulseDenoise.enabled) if(execsharp) { + float **buffers[3]; + buffers[0] = lab->L; + buffers[1] = lab->a; + buffers[2] = lab->b; + ImProcFunctions::impulsedenoisecam (ncie, buffers); //impulse adapted to CIECAM + } -if (params->sharpenMicro.enabled)if(execsharp) ImProcFunctions::MLmicrocontrastcam(ncie); + if (params->sharpenMicro.enabled)if(execsharp) { + ImProcFunctions::MLmicrocontrastcam(ncie); + } -if(params->sharpening.enabled) - if(execsharp) { - float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory - ImProcFunctions::sharpeningcam (ncie, buffer); // sharpening adapted to CIECAM - } + if(params->sharpening.enabled) + if(execsharp) { + float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory + ImProcFunctions::sharpeningcam (ncie, buffer); // sharpening adapted to CIECAM + } //if(params->dirpyrequalizer.enabled) if(execsharp) { -if(params->dirpyrequalizer.enabled /*&& execsharp*/) { - float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; - float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; - float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; - float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; - int choice=0;// I have not suppress this statement in case of !! always to 0 -// if(params->dirpyrequalizer.algo=="FI") choice=0; -// else if(params->dirpyrequalizer.algo=="LA") choice=1; + if(params->dirpyrequalizer.enabled /*&& execsharp*/) { + float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; + float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; + float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; + float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; + int choice = 0; // I have not suppress this statement in case of !! always to 0 +// if(params->dirpyrequalizer.algo=="FI") choice=0; +// else if(params->dirpyrequalizer.algo=="LA") choice=1; - if(rtt==1) { - lab->deleteLab(); - dirpyr_equalizercam(ncie, ncie->sh_p, ncie->sh_p, ncie->W, ncie->H, ncie->h_p, ncie->C_p, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, true, params->dirpyrequalizer.gamutlab, b_l,t_l,t_r,b_r, choice, scalecd);//contrast by detail adapted to CIECAM - lab->reallocLab(); - } -/* -if(params->colorappearance.badpixsl > 0) if(execsharp){ int mode=params->colorappearance.badpixsl; -printf("BADPIX"); - ImProcFunctions::badpixcam (ncie, 8.0, 10, mode);//for bad pixels - } - */ -} - const float Qredi= ( 4.0f / c_) * ( a_w + 4.0f ); - const float co_e=(pow_F(f_l,0.25f)); + if(rtt == 1) { + lab->deleteLab(); + dirpyr_equalizercam(ncie, ncie->sh_p, ncie->sh_p, ncie->W, ncie->H, ncie->h_p, ncie->C_p, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, true, params->dirpyrequalizer.gamutlab, b_l, t_l, t_r, b_r, choice, scalecd); //contrast by detail adapted to CIECAM + lab->reallocLab(); + } + + /* + if(params->colorappearance.badpixsl > 0) if(execsharp){ int mode=params->colorappearance.badpixsl; + printf("BADPIX"); + ImProcFunctions::badpixcam (ncie, 8.0, 10, mode);//for bad pixels + } + */ + } + + const float Qredi = ( 4.0f / c_) * ( a_w + 4.0f ); + const float co_e = (pow_F(f_l, 0.25f)); #ifndef _DEBUG -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifndef _DEBUG - #pragma omp for schedule(dynamic, 10) -#endif - for (int i=0; ish_p[i][j]/(32768.f)); - ncie->J_p[i][j]=100.0f* SQR(interm); - ncie->Q_p[i][j]=interm*Qredi; - ncie->M_p[i][j]=ncie->C_p[i][j]*co_e; - } - } -} -} -if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) - || (params->dirpyrequalizer.enabled && settings->autocielab) ||(params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) - || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl >0 && settings->autocielab)){ - - if(epdEnabled && params->colorappearance.tonecie && algepd) { - lab->deleteLab(); - ImProcFunctions::EPDToneMapCIE(ncie, a_w, c_, w_h, width, height, begh, endh, minQ, maxQ, Iterates, scale ); - lab->reallocLab(); - } - //EPDToneMapCIE adated to CIECAM - - - const float eps=0.0001f; - const float co_e=(pow_F(f_l,0.25f))+eps; - TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); - const float wipa[3][3] = { - {float(wiprofa[0][0]),float(wiprofa[0][1]),float(wiprofa[0][2])}, - {float(wiprofa[1][0]),float(wiprofa[1][1]),float(wiprofa[1][2])}, - {float(wiprofa[2][0]),float(wiprofa[2][1]),float(wiprofa[2][2])} - }; - -#ifndef _DEBUG -#pragma omp parallel -#endif -{ -#ifdef __SSE2__ - // one line buffer per channel - float Jbuffer[bufferLength] ALIGNED16; - float Cbuffer[bufferLength] ALIGNED16; - float hbuffer[bufferLength] ALIGNED16; - float *xbuffer = Jbuffer; // we can use one of the above buffers - float *ybuffer = Cbuffer; // " - float *zbuffer = hbuffer; // " + #pragma omp for schedule(dynamic, 10) #endif -#ifndef _DEBUG - #pragma omp for schedule(dynamic, 10) -#endif - for (int i=0; iJ_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/(w_h*w_h); - if(epdEnabled) ncie->J_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/SQR((4.f/c)*(aw+4.f)); - - const float ncie_C_p = (ncie->M_p[i][j])/co_e; - //show histogram in CIECAM mode (Q,J, M,s,C) - if(ciedata) { - // Data for J Q M s and C histograms - int posl, posc; - float brli=327.f; - float chsacol=327.f; - int libr=0; - int colch=0; - float sa_t; - if(curveMode==ColorAppearanceParams::TC_MODE_BRIGHT) {brli=70.0f; libr=1;} - else if(curveMode==ColorAppearanceParams::TC_MODE_LIGHT) {brli=327.f;libr=0;} - if (curveMode3==ColorAppearanceParams::TC_MODE_CHROMA) {chsacol=327.f;colch=0;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_SATUR) {chsacol=450.0f;colch=1;} - else if(curveMode3==ColorAppearanceParams::TC_MODE_COLORF) {chsacol=327.0f;colch=2;} - //update histogram - if(pW!=1){//only with improccoordinator - if(libr==1) posl=CLIP((int)(ncie->Q_p[i][j]*brli));//40.0 to 100.0 approximative factor for Q - 327 for J - else if(libr==0) posl=CLIP((int)(ncie->J_p[i][j]*brli));//327 for J - hist16JCAM[posl]++; - } - chropC=true; - if(pW!=1){//only with improccoordinator - if(colch==0) posc=CLIP((int)(ncie_C_p*chsacol));//450.0 approximative factor for s 320 for M - else if(colch==1) {sa_t=100.f*sqrtf(ncie_C_p/ncie->Q_p[i][j]); posc=CLIP((int)(sa_t*chsacol));}//Q_p always > 0 - else if(colch==2) posc=CLIP((int)(ncie->M_p[i][j]*chsacol)); - hist16_CCAM[posc]++; - } - } - //end histograms - -#ifdef __SSE2__ - Jbuffer[j] = ncie->J_p[i][j]; - Cbuffer[j] = ncie_C_p; - hbuffer[j] = ncie->h_p[i][j]; -#else - Ciecam02::jch2xyz_ciecam02float( xx, yy, zz, - ncie->J_p[i][j], ncie_C_p, ncie->h_p[i][j], - xw2, yw2, zw2, - yb2, la2, - f2, c2, nc2, gamu, pow1n, nbbj, ncbj, flj, czj, dj, awj); - x=(float)xx*655.35f; - y=(float)yy*655.35f; - z=(float)zz*655.35f; - float Ll,aa,bb; - //convert xyz=>lab - Color::XYZ2Lab(x, y, z, Ll, aa, bb); - if(gamu==1) { - float Lprov1, Chprov1; - Lprov1=Ll/327.68f; - Chprov1=sqrtf(SQR(aa) + SQR(bb))/327.68f; - float2 sincosval; - if(Chprov1==0.0f) { - sincosval.y = 1.f; - sincosval.x = 0.0f; - } else { - sincosval.y = aa/(Chprov1*327.68f); - sincosval.x = bb/(Chprov1*327.68f); - } - - -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wipa, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wipa, highlight, 0.15f, 0.96f); -#endif - - lab->L[i][j]=Lprov1*327.68f; - lab->a[i][j]=327.68f*Chprov1*sincosval.y; - lab->b[i][j]=327.68f*Chprov1*sincosval.x; - } else { - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; - } -#endif - } -#ifdef __SSE2__ - // process line buffers - int k; - vfloat x,y,z; - vfloat c655d35 = F2V(655.35f); - for(k=0;ksh_p[i][j] / (32768.f)); + ncie->J_p[i][j] = 100.0f * SQR(interm); + ncie->Q_p[i][j] = interm * Qredi; + ncie->M_p[i][j] = ncie->C_p[i][j] * co_e; + } + } } - // XYZ2Lab uses a lookup table. The function behind that lut is a cube root. - // SSE can't beat the speed of that lut, so it doesn't make sense to use SSE - for(int j=0;jlab - Color::XYZ2Lab(xbuffer[j], ybuffer[j], zbuffer[j], Ll, aa, bb); - if(gamu==1) { - float Lprov1, Chprov1; - Lprov1=Ll/327.68f; - Chprov1=sqrtf(SQR(aa) + SQR(bb))/327.68f; - float2 sincosval; - if(Chprov1==0.0f) { - sincosval.y = 1.f; - sincosval.x = 0.0f; - } else { - sincosval.y = aa/(Chprov1*327.68f); - sincosval.x = bb/(Chprov1*327.68f); - } -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wipa, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(sincosval,Lprov1,Chprov1, wipa, highlight, 0.15f, 0.96f); -#endif - lab->L[i][j]=Lprov1*327.68f; - lab->a[i][j]=327.68f*Chprov1*sincosval.y; - lab->b[i][j]=327.68f*Chprov1*sincosval.x; - } else { - lab->L[i][j]=Ll; - lab->a[i][j]=aa; - lab->b[i][j]=bb; - } - - } -#endif // __SSE2__ } -} //end parallelization + if((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp) + || (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab) + || (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab)) { - //show CIECAM histograms - if(ciedata) { - //update histogram J and Q - for (int i=0; i<32768; i++) {// - if (jp) { - float hval = dLcurve[i]; - int hi = (int)(255.0f*CLIPD(hval)); // - histLCAM[hi] += hist16JCAM[i] ; - } - } - //update color histogram M,s,C - for (int i=0; i<48000; i++) {// - if (chropC) { - float hvalc = dCcurve[i]; - int hic = (int)(255.0f*CLIPD(hvalc)); // - histCCAM[hic] += hist16_CCAM[i] ; - } - } - } + if(epdEnabled && params->colorappearance.tonecie && algepd) { + lab->deleteLab(); + ImProcFunctions::EPDToneMapCIE(ncie, a_w, c_, w_h, width, height, begh, endh, minQ, maxQ, Iterates, scale ); + lab->reallocLab(); + } - } -} + //EPDToneMapCIE adated to CIECAM + + + const float eps = 0.0001f; + const float co_e = (pow_F(f_l, 0.25f)) + eps; + TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); + const float wipa[3][3] = { + {float(wiprofa[0][0]), float(wiprofa[0][1]), float(wiprofa[0][2])}, + {float(wiprofa[1][0]), float(wiprofa[1][1]), float(wiprofa[1][2])}, + {float(wiprofa[2][0]), float(wiprofa[2][1]), float(wiprofa[2][2])} + }; + +#ifndef _DEBUG + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + // one line buffer per channel + float Jbuffer[bufferLength] ALIGNED16; + float Cbuffer[bufferLength] ALIGNED16; + float hbuffer[bufferLength] ALIGNED16; + float *xbuffer = Jbuffer; // we can use one of the above buffers + float *ybuffer = Cbuffer; // " + float *zbuffer = hbuffer; // " +#endif + +#ifndef _DEBUG + #pragma omp for schedule(dynamic, 10) +#endif + + for (int i = 0; i < height; i++) { // update CIECAM with new values after tone-mapping + for (int j = 0; j < width; j++) { + float xx, yy, zz; + float x, y, z; + + // if(epdEnabled) ncie->J_p[i][j]=(100.0f* ncie->Q_p[i][j]*ncie->Q_p[i][j])/(w_h*w_h); + if(epdEnabled) { + ncie->J_p[i][j] = (100.0f * ncie->Q_p[i][j] * ncie->Q_p[i][j]) / SQR((4.f / c) * (aw + 4.f)); + } + + const float ncie_C_p = (ncie->M_p[i][j]) / co_e; + + //show histogram in CIECAM mode (Q,J, M,s,C) + if(ciedata) { + // Data for J Q M s and C histograms + int posl, posc; + float brli = 327.f; + float chsacol = 327.f; + int libr = 0; + int colch = 0; + float sa_t; + + if(curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) { + brli = 70.0f; + libr = 1; + } else if(curveMode == ColorAppearanceParams::TC_MODE_LIGHT) { + brli = 327.f; + libr = 0; + } + + if (curveMode3 == ColorAppearanceParams::TC_MODE_CHROMA) { + chsacol = 327.f; + colch = 0; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_SATUR) { + chsacol = 450.0f; + colch = 1; + } else if(curveMode3 == ColorAppearanceParams::TC_MODE_COLORF) { + chsacol = 327.0f; + colch = 2; + } + + //update histogram + if(pW != 1) { //only with improccoordinator + if(libr == 1) { + posl = CLIP((int)(ncie->Q_p[i][j] * brli)); //40.0 to 100.0 approximative factor for Q - 327 for J + } else if(libr == 0) { + posl = CLIP((int)(ncie->J_p[i][j] * brli)); //327 for J + } + + hist16JCAM[posl]++; + } + + chropC = true; + + if(pW != 1) { //only with improccoordinator + if(colch == 0) { + posc = CLIP((int)(ncie_C_p * chsacol)); //450.0 approximative factor for s 320 for M + } else if(colch == 1) { + sa_t = 100.f * sqrtf(ncie_C_p / ncie->Q_p[i][j]); //Q_p always > 0 + posc = CLIP((int)(sa_t * chsacol)); + } else if(colch == 2) { + posc = CLIP((int)(ncie->M_p[i][j] * chsacol)); + } + + hist16_CCAM[posc]++; + } + } + + //end histograms + +#ifdef __SSE2__ + Jbuffer[j] = ncie->J_p[i][j]; + Cbuffer[j] = ncie_C_p; + hbuffer[j] = ncie->h_p[i][j]; +#else + Ciecam02::jch2xyz_ciecam02float( xx, yy, zz, + ncie->J_p[i][j], ncie_C_p, ncie->h_p[i][j], + xw2, yw2, zw2, + yb2, la2, + f2, c2, nc2, gamu, pow1n, nbbj, ncbj, flj, czj, dj, awj); + x = (float)xx * 655.35f; + y = (float)yy * 655.35f; + z = (float)zz * 655.35f; + float Ll, aa, bb; + //convert xyz=>lab + Color::XYZ2Lab(x, y, z, Ll, aa, bb); + + if(gamu == 1) { + float Lprov1, Chprov1; + Lprov1 = Ll / 327.68f; + Chprov1 = sqrtf(SQR(aa) + SQR(bb)) / 327.68f; + float2 sincosval; + + if(Chprov1 == 0.0f) { + sincosval.y = 1.f; + sincosval.x = 0.0f; + } else { + sincosval.y = aa / (Chprov1 * 327.68f); + sincosval.x = bb / (Chprov1 * 327.68f); + } + + +#ifdef _DEBUG + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wipa, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wipa, highlight, 0.15f, 0.96f); +#endif + + lab->L[i][j] = Lprov1 * 327.68f; + lab->a[i][j] = 327.68f * Chprov1 * sincosval.y; + lab->b[i][j] = 327.68f * Chprov1 * sincosval.x; + } else { + lab->L[i][j] = Ll; + lab->a[i][j] = aa; + lab->b[i][j] = bb; + } + +#endif + } + +#ifdef __SSE2__ + // process line buffers + int k; + vfloat x, y, z; + vfloat c655d35 = F2V(655.35f); + + for(k = 0; k < bufferLength; k += 4) { + Ciecam02::jch2xyz_ciecam02float( x, y, z, + LVF(Jbuffer[k]), LVF(Cbuffer[k]), LVF(hbuffer[k]), + F2V(xw2), F2V(yw2), F2V(zw2), + F2V(yb2), F2V(la2), + F2V(f2), F2V(nc2), F2V(pow1n), F2V(nbbj), F2V(ncbj), F2V(flj), F2V(dj), F2V(awj), F2V(reccmcz)); + x *= c655d35; + y *= c655d35; + z *= c655d35; + STVF(xbuffer[k], x); + STVF(ybuffer[k], y); + STVF(zbuffer[k], z); + } + + // XYZ2Lab uses a lookup table. The function behind that lut is a cube root. + // SSE can't beat the speed of that lut, so it doesn't make sense to use SSE + for(int j = 0; j < width; j++) { + float Ll, aa, bb; + //convert xyz=>lab + Color::XYZ2Lab(xbuffer[j], ybuffer[j], zbuffer[j], Ll, aa, bb); + + if(gamu == 1) { + float Lprov1, Chprov1; + Lprov1 = Ll / 327.68f; + Chprov1 = sqrtf(SQR(aa) + SQR(bb)) / 327.68f; + float2 sincosval; + + if(Chprov1 == 0.0f) { + sincosval.y = 1.f; + sincosval.x = 0.0f; + } else { + sincosval.y = aa / (Chprov1 * 327.68f); + sincosval.x = bb / (Chprov1 * 327.68f); + } + +#ifdef _DEBUG + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wipa, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(sincosval, Lprov1, Chprov1, wipa, highlight, 0.15f, 0.96f); +#endif + lab->L[i][j] = Lprov1 * 327.68f; + lab->a[i][j] = 327.68f * Chprov1 * sincosval.y; + lab->b[i][j] = 327.68f * Chprov1 * sincosval.x; + } else { + lab->L[i][j] = Ll; + lab->a[i][j] = aa; + lab->b[i][j] = bb; + } + + } + +#endif // __SSE2__ + } + + } //end parallelization + + //show CIECAM histograms + if(ciedata) { + //update histogram J and Q + for (int i = 0; i < 32768; i++) { // + if (jp) { + float hval = dLcurve[i]; + int hi = (int)(255.0f * CLIPD(hval)); // + histLCAM[hi] += hist16JCAM[i] ; + } + } + + //update color histogram M,s,C + for (int i = 0; i < 48000; i++) { // + if (chropC) { + float hvalc = dCcurve[i]; + int hic = (int)(255.0f * CLIPD(hvalc)); // + histCCAM[hic] += hist16_CCAM[i] ; + } + } + } + + } + } } //end CIECAM -void ImProcFunctions::moyeqt (Imagefloat* working, float &moyS, float &eqty) { -// MyTime t1e,t2e; -// t1e.set(); - - int tHh=working->height; - int tWw=working->width; - float moy=0.f; - float eqt=0.f; -#pragma omp parallel +void ImProcFunctions::moyeqt (Imagefloat* working, float &moyS, float &eqty) { -float mo=0.f; +// MyTime t1e,t2e; +// t1e.set(); + + int tHh = working->height; + int tWw = working->width; + float moy = 0.f; + float eqt = 0.f; + #pragma omp parallel + { + float mo = 0.f; #ifndef _DEBUG - #pragma omp for reduction(+:moy) -#endif - for (int i=0; ir(i,j)); - float g = CLIP(working->g(i,j)); - float b = CLIP(working->b(i,j)); - float h, s, v; - Color::rgb2hsv(r, g, b, h, s, v); - moy+=s; - } - } - mo=moy/(tHh*tWw); - moyS=mo; + #pragma omp for reduction(+:moy) +#endif + + for (int i = 0; i < tHh; i++) { + for (int j = 0; j < tWw; j++) { + float r = CLIP(working->r(i, j)); + float g = CLIP(working->g(i, j)); + float b = CLIP(working->b(i, j)); + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); + moy += s; + } + } + + mo = moy / (tHh * tWw); + moyS = mo; #ifndef _DEBUG - #pragma omp for reduction(+:eqt) -#endif - for (int i=0; ir(i,j)); - float g = CLIP(working->g(i,j)); - float b = CLIP(working->b(i,j)); - float h, s, v; - Color::rgb2hsv(r, g, b, h, s, v); - eqt+=SQR(s-mo); - } - } -} - eqt=eqt/(tHh*tWw); - eqty=(sqrt(eqt)); - - // t2e.set(); - // printf("Moyeqt:%d\n", t2e.etime(t1e)); - + #pragma omp for reduction(+:eqt) +#endif + + for (int i = 0; i < tHh; i++) { + for (int j = 0; j < tWw; j++) { + float r = CLIP(working->r(i, j)); + float g = CLIP(working->g(i, j)); + float b = CLIP(working->b(i, j)); + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); + eqt += SQR(s - mo); + } + } + } + eqt = eqt / (tHh * tWw); + eqty = (sqrt(eqt)); + + // t2e.set(); + // printf("Moyeqt:%d\n", t2e.etime(t1e)); + } static inline void filmlike_clip_rgb_tone(float *r, float *g, float *b, const float L) { - float r_ = *r > L ? L : *r; - float b_ = *b > L ? L : *b; - float g_ = b_ + ((r_ - b_) * (*g - *b) / (*r - *b)); - *r = r_; - *g = g_; - *b = b_; + float r_ = *r > L ? L : *r; + float b_ = *b > L ? L : *b; + float g_ = b_ + ((r_ - b_) * (*g - *b) / (*r - *b)); + *r = r_; + *g = g_; + *b = b_; } static void filmlike_clip(float *r, float *g, float *b) { - // This is Adobe's hue-stable film-like curve with a diagonal, ie only used for clipping. Can probably be further optimized. - const float L = 65535.0; - if (*r >= *g) { - if (*g > *b) { // Case 1: r >= g > b - filmlike_clip_rgb_tone(r, g, b, L); - } else if (*b > *r) { // Case 2: b > r >= g - filmlike_clip_rgb_tone(b, r, g, L); - } else if (*b > *g) { // Case 3: r >= b > g - filmlike_clip_rgb_tone(r, b, g, L); - } else { // Case 4: r >= g == b - *r = *r > L ? L : *r; - *g = *g > L ? L : *g; - *b = *g; - } - } else { - if (*r >= *b) { // Case 5: g > r >= b - filmlike_clip_rgb_tone(g, r, b, L); - } else if (*b > *g) { // Case 6: b > g > r - filmlike_clip_rgb_tone(b, g, r, L); - } else { // Case 7: g >= b > r - filmlike_clip_rgb_tone(g, b, r, L); - } - } + // This is Adobe's hue-stable film-like curve with a diagonal, ie only used for clipping. Can probably be further optimized. + const float L = 65535.0; + + if (*r >= *g) { + if (*g > *b) { // Case 1: r >= g > b + filmlike_clip_rgb_tone(r, g, b, L); + } else if (*b > *r) { // Case 2: b > r >= g + filmlike_clip_rgb_tone(b, r, g, L); + } else if (*b > *g) { // Case 3: r >= b > g + filmlike_clip_rgb_tone(r, b, g, L); + } else { // Case 4: r >= g == b + *r = *r > L ? L : *r; + *g = *g > L ? L : *g; + *b = *g; + } + } else { + if (*r >= *b) { // Case 5: g > r >= b + filmlike_clip_rgb_tone(g, r, b, L); + } else if (*b > *g) { // Case 6: b > g > r + filmlike_clip_rgb_tone(b, g, r, L); + } else { // Case 7: g >= b > r + filmlike_clip_rgb_tone(g, b, r, L); + } + } } void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit ,float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve,LUTf & cl2Toningcurve, - const ToneCurve & customToneCurve1,const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf ) { - rgbProc (working, lab, editBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit ,satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve,customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2,rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf); + SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, + const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf ) +{ + rgbProc (working, lab, editBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf); } // Process RGB image and convert to LAB space void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, - SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit ,float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve,LUTf & cl2Toningcurve, - const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1,const ToneCurve & customToneCurvebw2,double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf) { + SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve, + const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf) +{ LUTf fGammaLUTf; - Imagefloat *tmpImage=NULL; + Imagefloat *tmpImage = NULL; // NOTE: We're getting all 3 pointers here, but this function may not need them all, so one could optimize this Imagefloat* editImgFloat = NULL; LabImage* editLab = NULL; PlanarWhateverData* editWhatever = NULL; EditUniqueID editID = editBuffer ? editBuffer->getEditID() : EUID_None; + if (editID != EUID_None) { switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { case (BT_IMAGEFLOAT): editImgFloat = editBuffer->getImgFloatBuffer(); break; + case (BT_LABIMAGE): editLab = editBuffer->getLabBuffer(); break; + case (BT_SINGLEPLANE_FLOAT): editWhatever = editBuffer->getSinglePlaneBuffer(); break; @@ -2455,13 +3172,14 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } int h_th, s_th; + if (shmap) { h_th = shmap->max_f - params->sh.htonalwidth * (shmap->max_f - shmap->avg) / 100; s_th = params->sh.stonalwidth * (shmap->avg - shmap->min_f) / 100; } - bool processSH = params->sh.enabled && shmap!=NULL && (params->sh.highlights>0 || params->sh.shadows>0); - bool processLCE = params->sh.enabled && shmap!=NULL && params->sh.localcontrast>0; + bool processSH = params->sh.enabled && shmap != NULL && (params->sh.highlights > 0 || params->sh.shadows > 0); + bool processLCE = params->sh.enabled && shmap != NULL && params->sh.localcontrast > 0; double lceamount = params->sh.localcontrast / 200.0; TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); @@ -2472,113 +3190,121 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e ( wprof[0][0] / Color::D50x), ( wprof[0][1] / Color::D50x), ( wprof[0][2] / Color::D50x) - },{ + }, { ( wprof[1][0]), ( wprof[1][1]), ( wprof[1][2]) - },{ + }, { ( wprof[2][0] / Color::D50z), ( wprof[2][1] / Color::D50z), ( wprof[2][2] / Color::D50z) } }; - //inverse matrix user select - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; + //inverse matrix user select + double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; - double wp[3][3] = { - {wprof[0][0],wprof[0][1],wprof[0][2]}, - {wprof[1][0],wprof[1][1],wprof[1][2]}, - {wprof[2][0],wprof[2][1],wprof[2][2]}}; + double wp[3][3] = { + {wprof[0][0], wprof[0][1], wprof[0][2]}, + {wprof[1][0], wprof[1][1], wprof[1][2]}, + {wprof[2][0], wprof[2][1], wprof[2][2]} + }; - bool mixchannels = (params->chmixer.red[0]!=100 || params->chmixer.red[1]!=0 || params->chmixer.red[2]!=0 || - params->chmixer.green[0]!=0 || params->chmixer.green[1]!=100 || params->chmixer.green[2]!=0 || - params->chmixer.blue[0]!=0 || params->chmixer.blue[1]!=0 || params->chmixer.blue[2]!=100); + bool mixchannels = (params->chmixer.red[0] != 100 || params->chmixer.red[1] != 0 || params->chmixer.red[2] != 0 || + params->chmixer.green[0] != 0 || params->chmixer.green[1] != 100 || params->chmixer.green[2] != 0 || + params->chmixer.blue[0] != 0 || params->chmixer.blue[1] != 0 || params->chmixer.blue[2] != 100); - FlatCurve* hCurve; - FlatCurve* sCurve; - FlatCurve* vCurve; - FlatCurve* bwlCurve; + FlatCurve* hCurve; + FlatCurve* sCurve; + FlatCurve* vCurve; + FlatCurve* bwlCurve; - FlatCurveType hCurveType = (FlatCurveType)params->hsvequalizer.hcurve.at(0); - FlatCurveType sCurveType = (FlatCurveType)params->hsvequalizer.scurve.at(0); - FlatCurveType vCurveType = (FlatCurveType)params->hsvequalizer.vcurve.at(0); - FlatCurveType bwlCurveType = (FlatCurveType)params->blackwhite.luminanceCurve.at(0); - bool hCurveEnabled = hCurveType > FCT_Linear; - bool sCurveEnabled = sCurveType > FCT_Linear; - bool vCurveEnabled = vCurveType > FCT_Linear; - bool bwlCurveEnabled = bwlCurveType > FCT_Linear; + FlatCurveType hCurveType = (FlatCurveType)params->hsvequalizer.hcurve.at(0); + FlatCurveType sCurveType = (FlatCurveType)params->hsvequalizer.scurve.at(0); + FlatCurveType vCurveType = (FlatCurveType)params->hsvequalizer.vcurve.at(0); + FlatCurveType bwlCurveType = (FlatCurveType)params->blackwhite.luminanceCurve.at(0); + bool hCurveEnabled = hCurveType > FCT_Linear; + bool sCurveEnabled = sCurveType > FCT_Linear; + bool vCurveEnabled = vCurveType > FCT_Linear; + bool bwlCurveEnabled = bwlCurveType > FCT_Linear; - // TODO: We should create a 'skip' value like for CurveFactory::complexsgnCurve (rtengine/curves.cc) - if (hCurveEnabled) { - hCurve = new FlatCurve(params->hsvequalizer.hcurve); - if (hCurve->isIdentity()) { - delete hCurve; - hCurve = NULL; - hCurveEnabled = false; - } - } - if (sCurveEnabled) { - sCurve = new FlatCurve(params->hsvequalizer.scurve); - if (sCurve->isIdentity()) { - delete sCurve; - sCurve = NULL; - sCurveEnabled = false; - } - } - if (vCurveEnabled) { - vCurve = new FlatCurve(params->hsvequalizer.vcurve); - if (vCurve->isIdentity()) { - delete vCurve; - vCurve = NULL; - vCurveEnabled = false; - } - } - if (bwlCurveEnabled) { - bwlCurve = new FlatCurve(params->blackwhite.luminanceCurve); - if (bwlCurve->isIdentity()) { - delete bwlCurve; - bwlCurve = NULL; - bwlCurveEnabled = false; - } - } + // TODO: We should create a 'skip' value like for CurveFactory::complexsgnCurve (rtengine/curves.cc) + if (hCurveEnabled) { + hCurve = new FlatCurve(params->hsvequalizer.hcurve); + + if (hCurve->isIdentity()) { + delete hCurve; + hCurve = NULL; + hCurveEnabled = false; + } + } + + if (sCurveEnabled) { + sCurve = new FlatCurve(params->hsvequalizer.scurve); + + if (sCurve->isIdentity()) { + delete sCurve; + sCurve = NULL; + sCurveEnabled = false; + } + } + + if (vCurveEnabled) { + vCurve = new FlatCurve(params->hsvequalizer.vcurve); + + if (vCurve->isIdentity()) { + delete vCurve; + vCurve = NULL; + vCurveEnabled = false; + } + } + + if (bwlCurveEnabled) { + bwlCurve = new FlatCurve(params->blackwhite.luminanceCurve); + + if (bwlCurve->isIdentity()) { + delete bwlCurve; + bwlCurve = NULL; + bwlCurveEnabled = false; + } + } ClutPtr colorLUT; bool clutAndWorkingProfilesAreSame = false; TMatrix work2xyz, xyz2clut, clut2xyz, xyz2work; - if ( params->filmSimulation.enabled && !params->filmSimulation.clutFilename.empty() ) - { + + if ( params->filmSimulation.enabled && !params->filmSimulation.clutFilename.empty() ) { colorLUT.set( clutStore.getClut( params->filmSimulation.clutFilename ) ); - if ( colorLUT ) - { + + if ( colorLUT ) { clutAndWorkingProfilesAreSame = colorLUT->profile() == params->icm.working; - if ( !clutAndWorkingProfilesAreSame ) - { + + if ( !clutAndWorkingProfilesAreSame ) { work2xyz = iccStore->workingSpaceMatrix( params->icm.working ); xyz2clut = iccStore->workingSpaceInverseMatrix( colorLUT->profile() ); xyz2work = iccStore->workingSpaceInverseMatrix( params->icm.working ); - clut2xyz = iccStore->workingSpaceMatrix( colorLUT->profile() ); + clut2xyz = iccStore->workingSpaceMatrix( colorLUT->profile() ); } } } - double filmSimCorrectedStrength = double(params->filmSimulation.strength)/100.; - double filmSimSourceStrength = double(100-params->filmSimulation.strength)/100.; + double filmSimCorrectedStrength = double(params->filmSimulation.strength) / 100.; + double filmSimSourceStrength = double(100 - params->filmSimulation.strength) / 100.; - const float exp_scale = pow (2.0, expcomp); - const float comp = (max(0.0, expcomp) + 1.0)*hlcompr/100.0; - const float shoulder = ((65536.0/max(1.0f,exp_scale))*(hlcomprthresh/200.0))+0.1; - const float hlrange = 65536.0-shoulder; - const bool isProPhoto = (params->icm.working == "ProPhoto"); + const float exp_scale = pow (2.0, expcomp); + const float comp = (max(0.0, expcomp) + 1.0) * hlcompr / 100.0; + const float shoulder = ((65536.0 / max(1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1; + const float hlrange = 65536.0 - shoulder; + const bool isProPhoto = (params->icm.working == "ProPhoto"); // extracting datas from 'params' to avoid cache flush (to be confirmed) ToneCurveParams::eTCModeId curveMode = params->toneCurve.curveMode; ToneCurveParams::eTCModeId curveMode2 = params->toneCurve.curveMode2; - bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated + bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated bool hasToneCurve1 = bool(customToneCurve1); bool hasToneCurve2 = bool(customToneCurve2); BlackWhiteParams::eTCModeId beforeCurveMode = params->blackwhite.beforeCurveMode; @@ -2587,20 +3313,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e bool hasToneCurvebw1 = bool(customToneCurvebw1); bool hasToneCurvebw2 = bool(customToneCurvebw2); - PerceptualToneCurveState ptc1ApplyState, ptc2ApplyState; - if (hasToneCurve1 && curveMode==ToneCurveParams::TC_MODE_PERCEPTUAL) { - const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve1); - userToneCurve.initApplyState(ptc1ApplyState, params->icm.working); - } - if (hasToneCurve2 && curveMode2==ToneCurveParams::TC_MODE_PERCEPTUAL) { - const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve2); - userToneCurve.initApplyState(ptc2ApplyState, params->icm.working); - } + PerceptualToneCurveState ptc1ApplyState, ptc2ApplyState; + + if (hasToneCurve1 && curveMode == ToneCurveParams::TC_MODE_PERCEPTUAL) { + const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve1); + userToneCurve.initApplyState(ptc1ApplyState, params->icm.working); + } + + if (hasToneCurve2 && curveMode2 == ToneCurveParams::TC_MODE_PERCEPTUAL) { + const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve2); + userToneCurve.initApplyState(ptc2ApplyState, params->icm.working); + } bool hasColorToning = params->colorToning.enabled && bool(ctOpacityCurve) && bool(ctColorCurve); - // float satLimit = float(params->colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; - // float satLimitOpacity = 1.f-(float(params->colorToning.saturatedOpacity)/100.f); - float strProtect = (float(params->colorToning.strength)/100.f); + // float satLimit = float(params->colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; + // float satLimitOpacity = 1.f-(float(params->colorToning.saturatedOpacity)/100.f); + float strProtect = (float(params->colorToning.strength) / 100.f); /* // Debug output - Color LUTf points @@ -2632,17 +3360,17 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e } */ - float RedLow = (100.f + float(params->colorToning.redlow))/100.f;//printf("Rel=%f\n",RedLow); - float GreenLow = (100.f + float(params->colorToning.greenlow))/100.f;//printf("Gre=%f\n",GreenLow); - float BlueLow = (100.f + float(params->colorToning.bluelow))/100.f;//printf("Blu=%f\n",BlueLow); - float RedMed = (100.f + float(params->colorToning.redmed))/100.f; - float GreenMed = (100.f + float(params->colorToning.greenmed))/100.f; - float BlueMed = (100.f + float(params->colorToning.bluemed))/100.f; - float RedHigh = (100.f + float(params->colorToning.redhigh))/100.f;//printf("RedH=%f\n",RedHigh); - float GreenHigh = (100.f + float(params->colorToning.greenhigh))/100.f; - float BlueHigh = (100.f + float(params->colorToning.bluehigh))/100.f; - float SatLow = float(params->colorToning.shadowsColSat.value[0])/100.f; - float SatHigh = float(params->colorToning.hlColSat.value[0])/100.f; + float RedLow = (100.f + float(params->colorToning.redlow)) / 100.f; //printf("Rel=%f\n",RedLow); + float GreenLow = (100.f + float(params->colorToning.greenlow)) / 100.f; //printf("Gre=%f\n",GreenLow); + float BlueLow = (100.f + float(params->colorToning.bluelow)) / 100.f; //printf("Blu=%f\n",BlueLow); + float RedMed = (100.f + float(params->colorToning.redmed)) / 100.f; + float GreenMed = (100.f + float(params->colorToning.greenmed)) / 100.f; + float BlueMed = (100.f + float(params->colorToning.bluemed)) / 100.f; + float RedHigh = (100.f + float(params->colorToning.redhigh)) / 100.f; //printf("RedH=%f\n",RedHigh); + float GreenHigh = (100.f + float(params->colorToning.greenhigh)) / 100.f; + float BlueHigh = (100.f + float(params->colorToning.bluehigh)) / 100.f; + float SatLow = float(params->colorToning.shadowsColSat.value[0]) / 100.f; + float SatHigh = float(params->colorToning.hlColSat.value[0]) / 100.f; float Balan = float(params->colorToning.balance); @@ -2671,1434 +3399,1634 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *e float mixerCyan = float(params->blackwhite.mixerCyan); float mixerMagenta = float(params->blackwhite.mixerMagenta); float mixerPurple = float(params->blackwhite.mixerPurple); - int algm=0; - if (params->blackwhite.method=="Desaturation") algm=0; - else if(params->blackwhite.method=="LumEqualizer") algm=1; - else if(params->blackwhite.method=="ChannelMixer") algm=2; - float kcorec=1.f; - //gamma correction of each channel - float gamvalr=125.f; - float gamvalg=125.f; - float gamvalb=125.f; - double nr=0; - double ng=0; - double nb=0; - bool computeMixerAuto = params->blackwhite.autoc && (autor < -5000.f); - if(bwrgam < 0) gamvalr=100.f; - if(bwggam < 0) gamvalg=100.f; - if(bwbgam < 0) gamvalb=100.f; - float gammabwr=1.f; - float gammabwg=1.f; - float gammabwb=1.f; - //if (params->blackwhite.setting=="Ma" || params->blackwhite.setting=="Mr" || params->blackwhite.setting=="Fr" || params->blackwhite.setting=="Fa") { - { - gammabwr=1.f -bwrgam/gamvalr; - gammabwg=1.f -bwggam/gamvalg; - gammabwb=1.f -bwbgam/gamvalb; - } - bool hasgammabw = gammabwr!=1.f || gammabwg!=1.f || gammabwb!=1.f; + int algm = 0; - fGammaLUTf(65535); -#pragma omp parallel for - for (int i=0; i<65536; i++) { - fGammaLUTf[i] = CurveFactory::gamma2 (float(i)/65535.f) * 65535.f; - } - if (hasColorToning || blackwhite) - tmpImage = new Imagefloat(working->width,working->height); + if (params->blackwhite.method == "Desaturation") { + algm = 0; + } else if(params->blackwhite.method == "LumEqualizer") { + algm = 1; + } else if(params->blackwhite.method == "ChannelMixer") { + algm = 2; + } + + float kcorec = 1.f; + //gamma correction of each channel + float gamvalr = 125.f; + float gamvalg = 125.f; + float gamvalb = 125.f; + double nr = 0; + double ng = 0; + double nb = 0; + bool computeMixerAuto = params->blackwhite.autoc && (autor < -5000.f); + + if(bwrgam < 0) { + gamvalr = 100.f; + } + + if(bwggam < 0) { + gamvalg = 100.f; + } + + if(bwbgam < 0) { + gamvalb = 100.f; + } + + float gammabwr = 1.f; + float gammabwg = 1.f; + float gammabwb = 1.f; + //if (params->blackwhite.setting=="Ma" || params->blackwhite.setting=="Mr" || params->blackwhite.setting=="Fr" || params->blackwhite.setting=="Fa") { + { + gammabwr = 1.f - bwrgam / gamvalr; + gammabwg = 1.f - bwggam / gamvalg; + gammabwb = 1.f - bwbgam / gamvalb; + } + bool hasgammabw = gammabwr != 1.f || gammabwg != 1.f || gammabwb != 1.f; + + fGammaLUTf(65535); + #pragma omp parallel for + + for (int i = 0; i < 65536; i++) { + fGammaLUTf[i] = CurveFactory::gamma2 (float(i) / 65535.f) * 65535.f; + } + + if (hasColorToning || blackwhite) { + tmpImage = new Imagefloat(working->width, working->height); + } #define TS 112 #ifdef _OPENMP -#pragma omp parallel if (multiThread) + #pragma omp parallel if (multiThread) #endif -{ - char *buffer; - char *editIFloatBuffer = NULL; - char *editWhateverBuffer = NULL; + { + char *buffer; + char *editIFloatBuffer = NULL; + char *editWhateverBuffer = NULL; - buffer = (char *) malloc(3*sizeof(float)*TS*TS + 20*64 + 63); - char *data; - data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); + buffer = (char *) malloc(3 * sizeof(float) * TS * TS + 20 * 64 + 63); + char *data; + data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); - float *rtemp = (float(*))data; - float *gtemp = (float (*)) ((char*)rtemp + sizeof(float)*TS*TS + 4*64); - float *btemp = (float (*)) ((char*)gtemp + sizeof(float)*TS*TS + 8*64); - int istart; - int jstart; - int tW; - int tH; + float *rtemp = (float(*))data; + float *gtemp = (float (*)) ((char*)rtemp + sizeof(float) * TS * TS + 4 * 64); + float *btemp = (float (*)) ((char*)gtemp + sizeof(float) * TS * TS + 8 * 64); + int istart; + int jstart; + int tW; + int tH; - // Allocating buffer for the EditBuffer - float *editIFloatTmpR, *editIFloatTmpG, *editIFloatTmpB, *editWhateverTmp; - if (editImgFloat) { - editIFloatBuffer = (char *) malloc(3*sizeof(float)*TS*TS + 20*64 + 63); - data = (char*)( ( uintptr_t(editIFloatBuffer) + uintptr_t(63)) / 64 * 64); + // Allocating buffer for the EditBuffer + float *editIFloatTmpR, *editIFloatTmpG, *editIFloatTmpB, *editWhateverTmp; + + if (editImgFloat) { + editIFloatBuffer = (char *) malloc(3 * sizeof(float) * TS * TS + 20 * 64 + 63); + data = (char*)( ( uintptr_t(editIFloatBuffer) + uintptr_t(63)) / 64 * 64); + + editIFloatTmpR = (float(*))data; + editIFloatTmpG = (float (*)) ((char*)editIFloatTmpR + sizeof(float) * TS * TS + 4 * 64); + editIFloatTmpB = (float (*)) ((char*)editIFloatTmpG + sizeof(float) * TS * TS + 8 * 64); + } + + if (editWhatever) { + editWhateverBuffer = (char *) malloc(sizeof(float) * TS * TS + 20 * 64 + 63); + data = (char*)( ( uintptr_t(editWhateverBuffer) + uintptr_t(63)) / 64 * 64); + + editWhateverTmp = (float(*))data; + } - editIFloatTmpR = (float(*))data; - editIFloatTmpG = (float (*)) ((char*)editIFloatTmpR + sizeof(float)*TS*TS + 4*64); - editIFloatTmpB = (float (*)) ((char*)editIFloatTmpG + sizeof(float)*TS*TS + 8*64); - } - if (editWhatever) { - editWhateverBuffer = (char *) malloc(sizeof(float)*TS*TS + 20*64 + 63); - data = (char*)( ( uintptr_t(editWhateverBuffer) + uintptr_t(63)) / 64 * 64); - editWhateverTmp = (float(*))data; - } - - #ifdef _OPENMP -#pragma omp for schedule(dynamic) collapse(2) + #pragma omp for schedule(dynamic) collapse(2) #endif - for(int ii=0;iiheight;ii+=TS) - for(int jj=0;jjwidth;jj+=TS) { - istart = ii; - jstart = jj; - tH = min(ii+TS,working->height); - tW = min(jj+TS,working->width); + + for(int ii = 0; ii < working->height; ii += TS) + for(int jj = 0; jj < working->width; jj += TS) { + istart = ii; + jstart = jj; + tH = min(ii + TS, working->height); + tW = min(jj + TS, working->width); - for (int i=istart,ti=0; ir(i,j); - gtemp[ti*TS+tj] = working->g(i,j); - btemp[ti*TS+tj] = working->b(i,j); - } - } + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + rtemp[ti * TS + tj] = working->r(i, j); + gtemp[ti * TS + tj] = working->g(i, j); + btemp[ti * TS + tj] = working->b(i, j); + } + } - if (mixchannels) { - for (int i=istart,ti=0; imap[i][j]; - double factor = 1.0; + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; - if (processSH) { - if (mapval > h_th) - factor = (h_th + (100.0 - shHighlights) * (mapval - h_th) / 100.0) / mapval; - else if (mapval < s_th) - factor = (s_th - (100.0 - shShadows) * (s_th - mapval) / 100.0) / mapval; - } - if (processLCE) { - double sub = lceamount*(mapval-factor*(r*lumimul[0] + g*lumimul[1] + b*lumimul[2])); - rtemp[ti*TS+tj] = factor*r-sub; - gtemp[ti*TS+tj] = factor*g-sub; - btemp[ti*TS+tj] = factor*b-sub; - } - else { - rtemp[ti*TS+tj] = factor*r; - gtemp[ti*TS+tj] = factor*g; - btemp[ti*TS+tj] = factor*b; - } - } - } - } + double mapval = 1.0 + shmap->map[i][j]; + double factor = 1.0; - for (int i=istart,ti=0; i h_th) { + factor = (h_th + (100.0 - shHighlights) * (mapval - h_th) / 100.0) / mapval; + } else if (mapval < s_th) { + factor = (s_th - (100.0 - shShadows) * (s_th - mapval) / 100.0) / mapval; + } + } - float r = rtemp[ti*TS+tj]; - float g = gtemp[ti*TS+tj]; - float b = btemp[ti*TS+tj]; + if (processLCE) { + double sub = lceamount * (mapval - factor * (r * lumimul[0] + g * lumimul[1] + b * lumimul[2])); + rtemp[ti * TS + tj] = factor * r - sub; + gtemp[ti * TS + tj] = factor * g - sub; + btemp[ti * TS + tj] = factor * b - sub; + } else { + rtemp[ti * TS + tj] = factor * r; + gtemp[ti * TS + tj] = factor * g; + btemp[ti * TS + tj] = factor * b; + } + } + } + } - //TODO: proper treatment of out-of-gamut colors - //float tonefactor = hltonecurve[(0.299f*r+0.587f*g+0.114f*b)]; - float tonefactor=((rstep2ApplyTile(rtemp, gtemp, btemp, tW-jstart, tH-istart, TS); - } - for (int i=istart,ti=0; i 65535 || g > 65535 || b > 65535) { - filmlike_clip(&r, &g, &b); - } + //shadow tone curve + float Y = (0.299f * r + 0.587f * g + 0.114f * b); + float tonefactor = shtonecurve[Y]; + rtemp[ti * TS + tj] = rtemp[ti * TS + tj] * tonefactor; + gtemp[ti * TS + tj] = gtemp[ti * TS + tj] * tonefactor; + btemp[ti * TS + tj] = btemp[ti * TS + tj] * tonefactor; + } + } - rtemp[ti*TS+tj] = r; - gtemp[ti*TS+tj] = g; - btemp[ti*TS+tj] = b; - } + if (dcpProf != NULL) { + dcpProf->step2ApplyTile(rtemp, gtemp, btemp, tW - jstart, tH - istart, TS); + } + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + + // clip out of gamut colors, without distorting color too bad + if (r < 0) { + r = 0; } - for (int i=istart,ti=0; i 65535 || g > 65535 || b > 65535) { + filmlike_clip(&r, &g, &b); + } - if (hasToneCurve1) { - if (curveMode==ToneCurveParams::TC_MODE_STD){ // Standard - for (int i=istart,ti=0; i(customToneCurve1); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode==ToneCurveParams::TC_MODE_FILMLIKE){ // Adobe like - for (int i=istart,ti=0; i(customToneCurve1); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode==ToneCurveParams::TC_MODE_SATANDVALBLENDING){ // apply the curve on the saturation and value channels - for (int i=istart,ti=0; i(customToneCurve1); - rtemp[ti*TS+tj] = CLIP(rtemp[ti*TS+tj]); - gtemp[ti*TS+tj] = CLIP(gtemp[ti*TS+tj]); - btemp[ti*TS+tj] = CLIP(btemp[ti*TS+tj]); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode==ToneCurveParams::TC_MODE_WEIGHTEDSTD){ // apply the curve to the rgb channels, weighted - const WeightedStdToneCurve& userToneCurve = static_cast(customToneCurve1); - for (int i=istart,ti=0; i(rtemp[ti*TS+tj]); - gtemp[ti*TS+tj] = CLIP(gtemp[ti*TS+tj]); - btemp[ti*TS+tj] = CLIP(btemp[ti*TS+tj]); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode==ToneCurveParams::TC_MODE_LUMINANCE){ // apply the curve to the luminance channel - const LuminanceToneCurve& userToneCurve = static_cast(customToneCurve1); - for (int i=istart,ti=0; i(rtemp[ti*TS+tj]); - gtemp[ti*TS+tj] = CLIP(gtemp[ti*TS+tj]); - btemp[ti*TS+tj] = CLIP(btemp[ti*TS+tj]); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode==ToneCurveParams::TC_MODE_PERCEPTUAL){ // apply curve while keeping color appearance constant - const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve1); - for (int i=istart,ti=0; i(rtemp[ti*TS+tj]); - gtemp[ti*TS+tj] = CLIP(gtemp[ti*TS+tj]); - btemp[ti*TS+tj] = CLIP(btemp[ti*TS+tj]); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj], ptc1ApplyState); - } - } - } - } + rtemp[ti * TS + tj] = r; + gtemp[ti * TS + tj] = g; + btemp[ti * TS + tj] = b; + } + } - if (editID == EUID_ToneCurve2) { // filling the pipette buffer - for (int i=istart,ti=0; i(customToneCurve2); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode2==ToneCurveParams::TC_MODE_FILMLIKE){ // Adobe like - for (int i=istart,ti=0; i(customToneCurve2); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode2==ToneCurveParams::TC_MODE_SATANDVALBLENDING){ // apply the curve on the saturation and value channels - for (int i=istart,ti=0; i(customToneCurve2); - userToneCurve.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (curveMode2==ToneCurveParams::TC_MODE_WEIGHTEDSTD){ // apply the curve to the rgb channels, weighted - const WeightedStdToneCurve& userToneCurve = static_cast(customToneCurve2); - for (int i=istart,ti=0; i(customToneCurve2); - for (int i=istart,ti=0; i(customToneCurve2); - for (int i=istart,ti=0; irgbCurves.lumamode){ // normal RGB mode - - for (int i=istart,ti=0; irgbCurves.lumamode==true (Luminosity mode) - // rCurve.dump("r_curve");//debug + if (hasToneCurve1) { + if (curveMode == ToneCurveParams::TC_MODE_STD) { // Standard + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const StandardToneCurve& userToneCurve = static_cast(customToneCurve1); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode == ToneCurveParams::TC_MODE_FILMLIKE) { // Adobe like + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const AdobeToneCurve& userToneCurve = static_cast(customToneCurve1); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode == ToneCurveParams::TC_MODE_SATANDVALBLENDING) { // apply the curve on the saturation and value channels + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const SatAndValueBlendingToneCurve& userToneCurve = static_cast(customToneCurve1); + rtemp[ti * TS + tj] = CLIP(rtemp[ti * TS + tj]); + gtemp[ti * TS + tj] = CLIP(gtemp[ti * TS + tj]); + btemp[ti * TS + tj] = CLIP(btemp[ti * TS + tj]); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode == ToneCurveParams::TC_MODE_WEIGHTEDSTD) { // apply the curve to the rgb channels, weighted + const WeightedStdToneCurve& userToneCurve = static_cast(customToneCurve1); - for (int i=istart,ti=0; i(rtemp[ti * TS + tj]); + gtemp[ti * TS + tj] = CLIP(gtemp[ti * TS + tj]); + btemp[ti * TS + tj] = CLIP(btemp[ti * TS + tj]); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode == ToneCurveParams::TC_MODE_LUMINANCE) { // apply the curve to the luminance channel + const LuminanceToneCurve& userToneCurve = static_cast(customToneCurve1); - L_1 = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; - a_1 = (500.0f * (fx - fy) ); - b_1 = (200.0f * (fy - fz) ); - - // rgb values after RGB curves - if (rCurve) r2 = rCurve[ rtemp[ti*TS+tj]]; else r2=r1; - if (gCurve) g2 = gCurve[ gtemp[ti*TS+tj]]; else g2=g1; - if (bCurve) b2 = bCurve[ btemp[ti*TS+tj]]; else b2=b1; - - // 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 )))); - L_2 = (116.0f * fyy - 5242.88f); + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + rtemp[ti * TS + tj] = CLIP(rtemp[ti * TS + tj]); + gtemp[ti * TS + tj] = CLIP(gtemp[ti * TS + tj]); + btemp[ti * TS + tj] = CLIP(btemp[ti * TS + tj]); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode == ToneCurveParams::TC_MODE_PERCEPTUAL) { // apply curve while keeping color appearance constant + const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve1); - //gamut control - if(settings->rgbcurveslumamode_gamut) { - float RR,GG,BB; - float HH, Lpro, Chpro; - Lpro=L_2/327.68f; - Chpro=sqrt(SQR(a_1) + SQR(b_1))/327.68f; - HH=xatan2f(b_1,a_1); - // According to mathematical laws we can get the sin and cos of HH by simple operations - float2 sincosval; - if(Chpro==0.0f) { - sincosval.y = 1.0f; - sincosval.x = 0.0f; - } else { - sincosval.y = a_1/(Chpro*327.68f); - sincosval.x = b_1/(Chpro*327.68f); - } + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + rtemp[ti * TS + tj] = CLIP(rtemp[ti * TS + tj]); + gtemp[ti * TS + tj] = CLIP(gtemp[ti * TS + tj]); + btemp[ti * TS + tj] = CLIP(btemp[ti * TS + tj]); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], ptc1ApplyState); + } + } + } + } + + if (editID == EUID_ToneCurve2) { // filling the pipette buffer + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + editIFloatTmpR[ti * TS + tj] = CLIP(fGammaLUTf[rtemp[ti * TS + tj]] / 65535.f); + editIFloatTmpG[ti * TS + tj] = CLIP(fGammaLUTf[gtemp[ti * TS + tj]] / 65535.f); + editIFloatTmpB[ti * TS + tj] = CLIP(fGammaLUTf[btemp[ti * TS + tj]] / 65535.f); + } + } + } + + if (hasToneCurve2) { + if (curveMode2 == ToneCurveParams::TC_MODE_STD) { // Standard + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const StandardToneCurve& userToneCurve = static_cast(customToneCurve2); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode2 == ToneCurveParams::TC_MODE_FILMLIKE) { // Adobe like + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const AdobeToneCurve& userToneCurve = static_cast(customToneCurve2); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode2 == ToneCurveParams::TC_MODE_SATANDVALBLENDING) { // apply the curve on the saturation and value channels + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const SatAndValueBlendingToneCurve& userToneCurve = static_cast(customToneCurve2); + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode2 == ToneCurveParams::TC_MODE_WEIGHTEDSTD) { // apply the curve to the rgb channels, weighted + const WeightedStdToneCurve& userToneCurve = static_cast(customToneCurve2); + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode2 == ToneCurveParams::TC_MODE_LUMINANCE) { // apply the curve to the luminance channel + const LuminanceToneCurve& userToneCurve = static_cast(customToneCurve2); + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (curveMode2 == ToneCurveParams::TC_MODE_PERCEPTUAL) { // apply curve while keeping color appearance constant + const PerceptualToneCurve& userToneCurve = static_cast(customToneCurve2); + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + userToneCurve.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], ptc2ApplyState); + } + } + } + } + + if (editID == EUID_RGB_R) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + editWhateverTmp[ti * TS + tj] = fGammaLUTf[rtemp[ti * TS + tj]] / 65536.f; + } + } + } else if (editID == EUID_RGB_G) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + editWhateverTmp[ti * TS + tj] = fGammaLUTf[gtemp[ti * TS + tj]] / 65536.f; + } + } + } else if (editID == EUID_RGB_B) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + editWhateverTmp[ti * TS + tj] = fGammaLUTf[btemp[ti * TS + tj]] / 65536.f; + } + } + } + + if (rCurve || gCurve || bCurve) { // if any of the RGB curves is engaged + if (!params->rgbCurves.lumamode) { // normal RGB mode + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + // individual R tone curve + if (rCurve) { + rtemp[ti * TS + tj] = rCurve[ rtemp[ti * TS + tj] ]; + } + + // individual G tone curve + if (gCurve) { + gtemp[ti * TS + tj] = gCurve[ gtemp[ti * TS + tj] ]; + } + + // individual B tone curve + if (bCurve) { + btemp[ti * TS + tj] = bCurve[ btemp[ti * TS + tj] ]; + } + } + } + } else { //params->rgbCurves.lumamode==true (Luminosity mode) + // rCurve.dump("r_curve");//debug + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r1, g1, b1, r2, g2, b2, L_1, L_2, Lfactor, a_1, b_1, x_, y_, z_, R, G, B ; + float y, fy, yy, fyy, x, z, fx, fz; + + // rgb values before RGB curves + r1 = rtemp[ti * TS + tj] ; + g1 = gtemp[ti * TS + tj] ; + b1 = btemp[ti * TS + tj] ; + //convert to Lab to get a&b before RGB curves + x = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1; + 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 )))); + + L_1 = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; + a_1 = (500.0f * (fx - fy) ); + b_1 = (200.0f * (fy - fz) ); + + // rgb values after RGB curves + if (rCurve) { + r2 = rCurve[ rtemp[ti * TS + tj]]; + } else { + r2 = r1; + } + + if (gCurve) { + g2 = gCurve[ gtemp[ti * TS + tj]]; + } else { + g2 = g1; + } + + if (bCurve) { + b2 = bCurve[ btemp[ti * TS + tj]]; + } else { + b2 = b1; + } + + // 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 )))); + L_2 = (116.0f * fyy - 5242.88f); + + //gamut control + if(settings->rgbcurveslumamode_gamut) { + float RR, GG, BB; + float HH, Lpro, Chpro; + Lpro = L_2 / 327.68f; + Chpro = sqrt(SQR(a_1) + SQR(b_1)) / 327.68f; + HH = xatan2f(b_1, a_1); + // According to mathematical laws we can get the sin and cos of HH by simple operations + float2 sincosval; + + if(Chpro == 0.0f) { + sincosval.y = 1.0f; + sincosval.x = 0.0f; + } else { + sincosval.y = a_1 / (Chpro * 327.68f); + sincosval.x = b_1 / (Chpro * 327.68f); + } #ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lpro,Chpro, RR, GG, BB, wip, highlight, 0.15f, 0.96f, neg, more_rgb); + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lpro, Chpro, RR, GG, BB, wip, highlight, 0.15f, 0.96f, neg, more_rgb); #else - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lpro,Chpro, RR, GG, BB, wip, highlight, 0.15f, 0.96f); + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lpro, Chpro, RR, GG, BB, wip, highlight, 0.15f, 0.96f); #endif - - //Color::gamutLchonly(HH,Lpro,Chpro, RR, GG, BB, wip, highlight, 0.15f, 0.96f); + + //Color::gamutLchonly(HH,Lpro,Chpro, RR, GG, BB, wip, highlight, 0.15f, 0.96f); -// float2 sincosval = xsincosf(HH); +// float2 sincosval = xsincosf(HH); - L_2=Lpro*327.68f; - a_1=327.68f*Chpro*sincosval.y; - b_1=327.68f*Chpro*sincosval.x; - } //end of gamut control - - //calculate RGB with L_2 and old value of a and b - Color::Lab2XYZ(L_2, a_1, b_1, x_, y_, z_) ; - Color::xyz2rgb(x_,y_,z_,R,G,B,wip); - - rtemp[ti*TS+tj] =R; - gtemp[ti*TS+tj] =G; - btemp[ti*TS+tj] =B; - } - } - } - } + L_2 = Lpro * 327.68f; + a_1 = 327.68f * Chpro * sincosval.y; + b_1 = 327.68f * Chpro * sincosval.x; + } //end of gamut control - if (editID == EUID_HSV_H || editID == EUID_HSV_S || editID == EUID_HSV_V) { - for (int i=istart,ti=0; i 0) { - s = (1.f-satby100)*s+satby100*(1.f-SQR(SQR(1.f-min(s,1.0f)))); - if (s<0.f) s=0.f; - } else /*if (sat < 0)*/ - s *= 1.f+satby100; + if (editID == EUID_HSV_H || editID == EUID_HSV_S || editID == EUID_HSV_V) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float h, s, v; + Color::rgb2hsv(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], h, s, v); + editWhateverTmp[ti * TS + tj] = h; + } + } + } - //HSV equalizer - if (hCurveEnabled) { - h = (hCurve->getVal(double(h)) - 0.5) * 2.f + h; - if (h > 1.0f) - h -= 1.0f; - else if (h < 0.0f) - h += 1.0f; - } - if (sCurveEnabled) { - //shift saturation - float satparam = (sCurve->getVal(double(h))-0.5) * 2; - if (satparam > 0.00001f) { - s = (1.f-satparam)*s+satparam*(1.f-SQR(1.f-min(s,1.0f))); - if (s<0.f) s=0.f; - } else if (satparam < -0.00001f) - s *= 1.f+satparam; + if (sat != 0 || hCurveEnabled || sCurveEnabled || vCurveEnabled) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { - } - if (vCurveEnabled) { - if (v<0) v=0; // important + const float satby100 = sat / 100.f; + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); - //shift value - float valparam = vCurve->getVal((double)h)-0.5f; - valparam *= (1.f-SQR(SQR(1.f-min(s,1.0f)))); - if (valparam > 0.00001f) { - v = (1.f-valparam)*v+ valparam*(1.f-SQR(1.f-min(v,1.0f)));// SQR (SQR to increase action and avoid artefacts - if (v<0) v=0; - } else { - if (valparam < -0.00001f) - v *= (1.f+ valparam);//1.99 to increase action - } + if (sat > 0) { + s = (1.f - satby100) * s + satby100 * (1.f - SQR(SQR(1.f - min(s, 1.0f)))); - } - Color::hsv2rgb(h, s, v, rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } + if (s < 0.f) { + s = 0.f; + } + } else { /*if (sat < 0)*/ + s *= 1.f + satby100; + } - if (isProPhoto) { // this is a hack to avoid the blue=>black bug (Issue 2141) - for (int i=istart,ti=0; igetVal(double(h)) - 0.5) * 2.f + h; - if (hasColorToning && !blackwhite) { - if (params->colorToning.method=="Splitlr") { - float balanS, balanH; - float reducac= 0.4f; - int preser=0; - if(params->colorToning.lumamode == true) preser=1; + if (h > 1.0f) { + h -= 1.0f; + } else if (h < 0.0f) { + h += 1.0f; + } + } - balanS = 1.f + Balan/100.f;//balan between 0 and 2 - balanH = 1.f - Balan/100.f; - float rh, gh, bh; - float rl, gl, bl; - float xh, yh, zh; - float xl, yl, zl; - float iplow,iphigh; - iplow=(float)ctColorCurve.low; - iphigh=(float)ctColorCurve.high; - //2 colours - ctColorCurve.getVal(iphigh, xh, yh, zh); - ctColorCurve.getVal(iplow, xl, yl, zl); + if (sCurveEnabled) { + //shift saturation + float satparam = (sCurve->getVal(double(h)) - 0.5) * 2; - Color::xyz2rgb(xh, yh, zh, rh, gh, bh, wip); - Color::xyz2rgb(xl, yl, zl, rl, gl, bl, wip); - //reteave rgb value with s and l =1 - retreavergb(rl,gl,bl); - retreavergb(rh,gh,bh); - //printf("rl=%f gl=%f bl=%f\n",rl,gl,bl); + if (satparam > 0.00001f) { + s = (1.f - satparam) * s + satparam * (1.f - SQR(1.f - min(s, 1.0f))); - for (int i=istart,ti=0; icolorToning.method=="Splitco") { -/* -#if 1 - for (int i=istart,ti=0; i crash - gtemp[ti*TS+tj] = CLIP(go); - btemp[ti*TS+tj] = CLIP(bo); - } - } -#else -*/ - float reducac = 0.3f; - int preser = 0; - //bool execbal = params->colorToning.method=="Splitbal"; - if(params->colorToning.lumamode == true) preser = 1; + } + + if (vCurveEnabled) { + if (v < 0) { + v = 0; // important + } + + //shift value + float valparam = vCurve->getVal((double)h) - 0.5f; + valparam *= (1.f - SQR(SQR(1.f - min(s, 1.0f)))); + + if (valparam > 0.00001f) { + v = (1.f - valparam) * v + valparam * (1.f - SQR(1.f - min(v, 1.0f))); // SQR (SQR to increase action and avoid artefacts + + if (v < 0) { + v = 0; + } + } else { + if (valparam < -0.00001f) { + v *= (1.f + valparam); //1.99 to increase action + } + } + + } + + Color::hsv2rgb(h, s, v, rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } + + if (isProPhoto) { // this is a hack to avoid the blue=>black bug (Issue 2141) + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + + if(r == 0.0f || g == 0.0f) { + float b = btemp[ti * TS + tj]; + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); + s *= 0.99f; + Color::hsv2rgb(h, s, v, rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } + } + + if (hasColorToning && !blackwhite) { + if (params->colorToning.method == "Splitlr") { + float balanS, balanH; + float reducac = 0.4f; + int preser = 0; + + if(params->colorToning.lumamode == true) { + preser = 1; + } + + balanS = 1.f + Balan / 100.f; //balan between 0 and 2 + balanH = 1.f - Balan / 100.f; + float rh, gh, bh; + float rl, gl, bl; + float xh, yh, zh; + float xl, yl, zl; + float iplow, iphigh; + iplow = (float)ctColorCurve.low; + iphigh = (float)ctColorCurve.high; + //2 colours + ctColorCurve.getVal(iphigh, xh, yh, zh); + ctColorCurve.getVal(iplow, xl, yl, zl); + + Color::xyz2rgb(xh, yh, zh, rh, gh, bh, wip); + Color::xyz2rgb(xl, yl, zl, rl, gl, bl, wip); + //reteave rgb value with s and l =1 + retreavergb(rl, gl, bl); + retreavergb(rh, gh, bh); + //printf("rl=%f gl=%f bl=%f\n",rl,gl,bl); + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + float ro, go, bo; + int mode = 0; + toning2col (r, g, b, ro, go, bo, iplow, iphigh, rl, gl, bl, rh, gh, bh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); + rtemp[ti * TS + tj] = ro; + gtemp[ti * TS + tj] = go; + btemp[ti * TS + tj] = bo; + } + } + } + + // color toning with colour + else if (params->colorToning.method == "Splitco") { + /* + #if 1 + for (int i=istart,ti=0; i crash + gtemp[ti*TS+tj] = CLIP(go); + btemp[ti*TS+tj] = CLIP(bo); + } + } + #else + */ + float reducac = 0.3f; + int preser = 0; + + //bool execbal = params->colorToning.method=="Splitbal"; + if(params->colorToning.lumamode == true) { + preser = 1; + } + + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; + float ro, go, bo; + int mode = 0; + toningsmh (r, g, b, ro, go, bo, RedLow, GreenLow, BlueLow, RedMed, GreenMed, BlueMed, RedHigh, GreenHigh, BlueHigh, reducac, mode, preser, strProtect); + float lumafter = 0.299f * ro + 0.587f * go + 0.114f * bo; + float preserv = 1.f; + + if(preser == 1) { + preserv = lumbefore / lumafter; + } + + ro *= preserv; + go *= preserv; + bo *= preserv; + ro = CLIP(ro); + go = CLIP(go); + bo = CLIP(bo); + rtemp[ti * TS + tj] = ro; + gtemp[ti * TS + tj] = go; + btemp[ti * TS + tj] = bo; + } + } - for (int i=istart,ti=0; icolorToning.method=="Lab" && opautili) { - int algm=0; - bool twocol = true;//true=500 color false=2 color - int metchrom; - if (params->colorToning.twocolor=="Std" ) metchrom=0; - else if (params->colorToning.twocolor=="All" ) metchrom=1; - else if (params->colorToning.twocolor=="Separ") metchrom=2; - else if (params->colorToning.twocolor=="Two" ) metchrom=3; + //colortoning with shift color XYZ or Lch + else if (params->colorToning.method == "Lab" && opautili) { + int algm = 0; + bool twocol = true;//true=500 color false=2 color + int metchrom; - if(metchrom==3) twocol=false; + if (params->colorToning.twocolor == "Std" ) { + metchrom = 0; + } else if (params->colorToning.twocolor == "All" ) { + metchrom = 1; + } else if (params->colorToning.twocolor == "Separ") { + metchrom = 2; + } else if (params->colorToning.twocolor == "Two" ) { + metchrom = 3; + } - float iplow,iphigh; - if(twocol==false){ - iplow=(float)ctColorCurve.low; - iphigh=(float)ctColorCurve.high; - } - - int twoc=0;//integer instead of bool to let more possible choice...other than 2 and 500. - if (twocol==false) twoc=0; // 2 colours - else twoc=1; // 500 colours - if (params->colorToning.method=="Lab") algm=1; - else if (params->colorToning.method=="Lch") algm=2;//in case of - if (algm <=2) { - for (int i=istart,ti=0; i crash - gtemp[ti*TS+tj] = CLIP(go); - btemp[ti*TS+tj] = CLIP(bo); - } - } - } - } - else if (params->colorToning.method.substr(0,3)=="RGB" && opautili) { - // color toning - for (int i=istart,ti=0; i(s/satLimit, 1.f)*(1.f-satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l_*500.f]; - if(!ctOpacityCurve) opacity=0.f; - float r2, g2, b2; - ctColorCurve.getVal(l_, r2, g2, b2); // get the color from the color curve + if (twocol == false) { + twoc = 0; // 2 colours + } else { + twoc = 1; // 500 colours + } - float h2, s2, l2; - Color::rgb2hsl(r2,g2,b2,h2,s2,l2); // transform this new color to hsl + if (params->colorToning.method == "Lab") { + algm = 1; + } else if (params->colorToning.method == "Lch") { + algm = 2; //in case of + } - Color::hsl2rgb(h2, s+((1.f-s)*(1.f-l)*0.7f), l, r2, g2, b2); + if (algm <= 2) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + float ro, go, bo; + labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip); + rtemp[ti * TS + tj] = CLIP(ro); //I used CLIP because there is a little bug in gamutLchonly that return 65536.ii intead of 65535 ==> crash + gtemp[ti * TS + tj] = CLIP(go); + btemp[ti * TS + tj] = CLIP(bo); + } + } + } + } else if (params->colorToning.method.substr(0, 3) == "RGB" && opautili) { + // color toning + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; - rtemp[ti*TS+tj] = r+(r2-r)*opacity; // merge the color to the old color, depending on the opacity - gtemp[ti*TS+tj] = g+(g2-g)*opacity; - btemp[ti*TS+tj] = b+(b2-b)*opacity; - } - } - } - } + // Luminance = (0.299f*r + 0.587f*g + 0.114f*b) - // filling the pipette buffer - if (editID == EUID_BlackWhiteBeforeCurve) { - for (int i=istart,ti=0; ilab - Color::rgbxyz(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj], X, Y, Z, wp); - //convert Lab - Color::XYZ2Lab(X, Y, Z, L, aa, bb); - //end rgb=>lab - float HH=xatan2f(bb,aa);// HH hue in -3.141 +3.141 + float h, s, l; + Color::rgb2hsl(r, g, b, h, s, l); - editWhateverTmp[ti*TS+tj] = float(Color::huelab_to_huehsv2(HH)); - } - } - } + float l_ = Color::gamma_srgb(l * 65535.f) / 65535.f; - //Film Simulations - if ( colorLUT ) - { - for (int i=istart,ti=0; i( Color::gamma_srgb( sourceR ) ); - sourceG = CLIP( Color::gamma_srgb( sourceG ) ); - sourceB = CLIP( Color::gamma_srgb( sourceB ) ); + if(ctOpacityCurve) { + opacity = (1.f - min(s / satLimit, 1.f) * (1.f - satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l_ * 500.f]; + } - 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(!ctOpacityCurve) { + opacity = 0.f; + } + + float r2, g2, b2; + ctColorCurve.getVal(l_, r2, g2, b2); // get the color from the color curve + + float h2, s2, l2; + Color::rgb2hsl(r2, g2, b2, h2, s2, l2); // transform this new color to hsl + + Color::hsl2rgb(h2, s + ((1.f - s) * (1.f - l) * 0.7f), l, r2, g2, b2); + + rtemp[ti * TS + tj] = r + (r2 - r) * opacity; // merge the color to the old color, depending on the opacity + gtemp[ti * TS + tj] = g + (g2 - g) * opacity; + btemp[ti * TS + tj] = b + (b2 - b) * opacity; + } + } + } + } + + // filling the pipette buffer + if (editID == EUID_BlackWhiteBeforeCurve) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + editIFloatTmpR[ti * TS + tj] = CLIP(fGammaLUTf[rtemp[ti * TS + tj]] / 65535.f); + editIFloatTmpG[ti * TS + tj] = CLIP(fGammaLUTf[gtemp[ti * TS + tj]] / 65535.f); + editIFloatTmpB[ti * TS + tj] = CLIP(fGammaLUTf[btemp[ti * TS + tj]] / 65535.f); + } + } + } else if (editID == EUID_BlackWhiteLuminance) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float X, Y, Z, L, aa, bb; + //rgb=>lab + Color::rgbxyz(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, aa, bb); + //end rgb=>lab + float HH = xatan2f(bb, aa); // HH hue in -3.141 +3.141 + + editWhateverTmp[ti * TS + tj] = float(Color::huelab_to_huehsv2(HH)); + } + } + } + + //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) { + if (beforeCurveMode == BlackWhiteParams::TC_MODE_STD_BW) { // Standard + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const StandardToneCurvebw& userToneCurvebw = static_cast(customToneCurvebw1); + userToneCurvebw.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (beforeCurveMode == BlackWhiteParams::TC_MODE_FILMLIKE_BW) { // Adobe like + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const AdobeToneCurvebw& userToneCurvebw = static_cast(customToneCurvebw1); + userToneCurvebw.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (beforeCurveMode == BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW) { // apply the curve on the saturation and value channels + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const SatAndValueBlendingToneCurvebw& userToneCurvebw = static_cast(customToneCurvebw1); + rtemp[ti * TS + tj] = CLIP(rtemp[ti * TS + tj]); + gtemp[ti * TS + tj] = CLIP(gtemp[ti * TS + tj]); + btemp[ti * TS + tj] = CLIP(btemp[ti * TS + tj]); + userToneCurvebw.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } else if (beforeCurveMode == BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW) { // apply the curve to the rgb channels, weighted + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + const WeightedStdToneCurvebw& userToneCurvebw = static_cast(customToneCurvebw1); + rtemp[ti * TS + tj] = CLIP(rtemp[ti * TS + tj]); + gtemp[ti * TS + tj] = CLIP(gtemp[ti * TS + tj]); + btemp[ti * TS + tj] = CLIP(btemp[ti * TS + tj]); + + userToneCurvebw.Apply(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj]); + } + } + } + } + + if (algm == 0) { //lightness + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + + // -------------------------------------------------- + + // Method 1: Luminosity (code taken from Gimp) + /* + float maxi = max(r, g, b); + float mini = min(r, g, b); + r = g = b = (maxi+mini)/2; + */ + + // Method 2: Luminance (former RT code) + r = g = b = (0.299f * r + 0.587f * g + 0.114f * b); + + // -------------------------------------------------- + + //gamma correction: pseudo TRC curve + if (hasgammabw) { + Color::trcGammaBW (r, g, b, gammabwr, gammabwg, gammabwb); + } + + rtemp[ti * TS + tj] = r; + gtemp[ti * TS + tj] = g; + btemp[ti * TS + tj] = b; + } + } + } else if (algm == 1) { //Luminance mixer in Lab mode to avoid artifacts + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + //rgb=>lab + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + float X, Y, Z; + float L, aa, bb; + Color::rgbxyz(r, g, b, X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, aa, bb); + //end rgb=>lab + //lab ==> Ch + float CC = sqrt(SQR(aa / 327.68f) + SQR(bb / 327.68f)); //CC chromaticity in 0..180 or more + float HH = xatan2f(bb, aa); // HH hue in -3.141 +3.141 + float l_r;//Luminance Lab in 0..1 + l_r = L / 32768.f; + + if (bwlCurveEnabled) { + double hr = Color::huelab_to_huehsv2(HH); + float valparam = float((bwlCurve->getVal(hr) - 0.5f) * 2.0f); //get l_r=f(H) + float kcc = (CC / 70.f); //take Chroma into account...70 "middle" of chromaticity (arbitrary and simple), one can imagine other algorithme + //reduct action for low chroma and increase action for high chroma + valparam *= kcc; + + if(valparam > 0.f) { + l_r = (1.f - valparam) * l_r + valparam * (1.f - SQR(SQR(SQR(SQR(1.f - min(l_r, 1.0f)))))); // SQR (SQR((SQR) to increase action in low light + } else { + l_r *= (1.f + valparam); //for negative + } + } + + L = l_r * 32768.f; + float RR, GG, BB; + float Lr; + Lr = L / 327.68f; //for gamutlch +#ifdef _DEBUG + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lr, CC, RR, GG, BB, wip, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, Lr, CC, RR, GG, BB, wip, highlight, 0.15f, 0.96f); +#endif + //convert CH ==> ab + L = Lr * 327.68f; + // float a_,b_; + // a_=0.f;//grey + // b_=0.f;//grey + //convert lab=>rgb + Color::Lab2XYZ(L, 0.f, 0.f, X, Y, Z); + float rr_, gg_, bb_; + Color::xyz2rgb(X, Y, Z, rr_, gg_, bb_, wip); + rtemp[ti * TS + tj] = gtemp[ti * TS + tj] = btemp[ti * TS + tj] = rr_; + // tmpImage->r(i,j) = tmpImage->g(i,j) = tmpImage->b(i,j) = CLIP(val[0]*kcorec); + + if (hasgammabw) { + Color::trcGammaBW (rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], gammabwr, gammabwg, gammabwb); + } + + //gamma correction: pseudo TRC curve + // if (hasgammabw) + // Color::trcGammaBW (rr_, gg_, bb_, gammabwr, gammabwg, gammabwb); + // rtemp[ti*TS+tj] = rr_; + // gtemp[ti*TS+tj] = gg_; + // btemp[ti*TS+tj] = bb_; + } + } + } + } + + if(!blackwhite) { + // ready, fill lab + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + + // filling the pipette buffer by the content of the temp pipette buffers + if (editImgFloat) { + editImgFloat->r(i, j) = editIFloatTmpR[ti * TS + tj]; + editImgFloat->g(i, j) = editIFloatTmpG[ti * TS + tj]; + editImgFloat->b(i, j) = editIFloatTmpB[ti * TS + tj]; + } else if (editWhatever) { + editWhatever->v(i, j) = editWhateverTmp[ti * TS + tj]; + } + + float r = rtemp[ti * TS + tj]; + float g = gtemp[ti * TS + tj]; + float b = btemp[ti * TS + tj]; + + float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; + float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; + float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; + + 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 )))); + + lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; + lab->a[i][j] = (500.0f * (fx - fy) ); + lab->b[i][j] = (200.0f * (fy - fz) ); + + //test for color accuracy + /* + float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 + float fx = (0.002 * lab->a[i][j])/327.68 + fy; + float fz = fy - (0.005 * lab->b[i][j])/327.68; + + float x_ = 65535*Lab2xyz(fx)*Color::D50x; + float y_ = 65535*Lab2xyz(fy); + float z_ = 65535*Lab2xyz(fz)*Color::D50z; + + int R,G,B; + xyz2srgb(x_,y_,z_,R,G,B); + r=(float)R; g=(float)G; b=(float)B; + float xxx=1; + */ + } + } + } else { // black & white + // Auto channel mixer needs whole image, so we now copy to tmpImage and close the tiled processing + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + // filling the pipette buffer by the content of the temp pipette buffers + if (editImgFloat) { + editImgFloat->r(i, j) = editIFloatTmpR[ti * TS + tj]; + editImgFloat->g(i, j) = editIFloatTmpG[ti * TS + tj]; + editImgFloat->b(i, j) = editIFloatTmpB[ti * TS + tj]; + } else if (editWhatever) { + editWhatever->v(i, j) = editWhateverTmp[ti * TS + tj]; + } + + tmpImage->r(i, j) = rtemp[ti * TS + tj]; + tmpImage->g(i, j) = gtemp[ti * TS + tj]; + tmpImage->b(i, j) = btemp[ti * TS + tj]; + } } } } - //black and white - if(blackwhite){ - if (hasToneCurvebw1) { - if (beforeCurveMode==BlackWhiteParams::TC_MODE_STD_BW){ // Standard - for (int i=istart,ti=0; i(customToneCurvebw1); - userToneCurvebw.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (beforeCurveMode==BlackWhiteParams::TC_MODE_FILMLIKE_BW){ // Adobe like - for (int i=istart,ti=0; i(customToneCurvebw1); - userToneCurvebw.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (beforeCurveMode==BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW){ // apply the curve on the saturation and value channels - for (int i=istart,ti=0; i(customToneCurvebw1); - rtemp[ti*TS+tj] = CLIP(rtemp[ti*TS+tj]); - gtemp[ti*TS+tj] = CLIP(gtemp[ti*TS+tj]); - btemp[ti*TS+tj] = CLIP(btemp[ti*TS+tj]); - userToneCurvebw.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - else if (beforeCurveMode==BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW){ // apply the curve to the rgb channels, weighted - for (int i=istart,ti=0; i(customToneCurvebw1); - rtemp[ti*TS+tj] = CLIP(rtemp[ti*TS+tj]); - gtemp[ti*TS+tj] = CLIP(gtemp[ti*TS+tj]); - btemp[ti*TS+tj] = CLIP(btemp[ti*TS+tj]); + free(buffer); - userToneCurvebw.Apply(rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj]); - } - } - } - } + if (editIFloatBuffer) { + free (editIFloatBuffer); + } - if (algm==0){//lightness - for (int i=istart,ti=0; iwidth; + int tH = working->height; - // Method 1: Luminosity (code taken from Gimp) - /* - float maxi = max(r, g, b); - float mini = min(r, g, b); - r = g = b = (maxi+mini)/2; - */ + if (algm == 2) { //channel-mixer + //end auto chmix + float mix[3][3]; - // Method 2: Luminance (former RT code) - r = g = b = (0.299f*r + 0.587f*g + 0.114f*b); - - // -------------------------------------------------- - - //gamma correction: pseudo TRC curve - if (hasgammabw) Color::trcGammaBW (r, g, b, gammabwr, gammabwg, gammabwb); - - rtemp[ti*TS+tj] = r; - gtemp[ti*TS+tj] = g; - btemp[ti*TS+tj] = b; - } - } - } - else if (algm==1) {//Luminance mixer in Lab mode to avoid artifacts - for (int i=istart,ti=0; ilab - float r = rtemp[ti*TS+tj]; - float g = gtemp[ti*TS+tj]; - float b = btemp[ti*TS+tj]; - float X,Y,Z; - float L,aa,bb; - Color::rgbxyz(r,g,b,X,Y,Z,wp); - //convert Lab - Color::XYZ2Lab(X, Y, Z, L, aa, bb); - //end rgb=>lab - //lab ==> Ch - float CC=sqrt(SQR(aa/327.68f) + SQR(bb/327.68f));//CC chromaticity in 0..180 or more - float HH=xatan2f(bb,aa);// HH hue in -3.141 +3.141 - float l_r;//Luminance Lab in 0..1 - l_r = L/32768.f; - - if (bwlCurveEnabled) { - double hr = Color::huelab_to_huehsv2(HH); - float valparam = float((bwlCurve->getVal(hr)-0.5f) * 2.0f);//get l_r=f(H) - float kcc=(CC/70.f);//take Chroma into account...70 "middle" of chromaticity (arbitrary and simple), one can imagine other algorithme - //reduct action for low chroma and increase action for high chroma - valparam *= kcc; - if(valparam > 0.f) { l_r = (1.f-valparam)*l_r+ valparam*(1.f-SQR(SQR(SQR(SQR(1.f-min(l_r,1.0f))))));}// SQR (SQR((SQR) to increase action in low light - else l_r *= (1.f + valparam);//for negative - } - L=l_r*32768.f; - float RR,GG,BB; - float Lr; - Lr=L/327.68f;//for gamutlch -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lr,CC, RR, GG, BB, wip, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH,Lr,CC, RR, GG, BB, wip, highlight, 0.15f, 0.96f); -#endif - //convert CH ==> ab - L=Lr*327.68f; - // float a_,b_; - // a_=0.f;//grey - // b_=0.f;//grey - //convert lab=>rgb - Color::Lab2XYZ(L, 0.f, 0.f, X, Y, Z); - float rr_,gg_,bb_; - Color::xyz2rgb(X,Y,Z,rr_,gg_,bb_,wip); - rtemp[ti*TS+tj] = gtemp[ti*TS+tj]= btemp[ti*TS+tj] = rr_; - // tmpImage->r(i,j) = tmpImage->g(i,j) = tmpImage->b(i,j) = CLIP(val[0]*kcorec); - - if (hasgammabw) - Color::trcGammaBW (rtemp[ti*TS+tj], gtemp[ti*TS+tj], btemp[ti*TS+tj], gammabwr, gammabwg, gammabwb); - - //gamma correction: pseudo TRC curve - // if (hasgammabw) - // Color::trcGammaBW (rr_, gg_, bb_, gammabwr, gammabwg, gammabwb); - // rtemp[ti*TS+tj] = rr_; - // gtemp[ti*TS+tj] = gg_; - // btemp[ti*TS+tj] = bb_; - } - } - } - } - if(!blackwhite) { - // ready, fill lab - for (int i=istart,ti=0; ir(i,j) = editIFloatTmpR[ti*TS+tj]; - editImgFloat->g(i,j) = editIFloatTmpG[ti*TS+tj]; - editImgFloat->b(i,j) = editIFloatTmpB[ti*TS+tj]; - } - else if (editWhatever) { - editWhatever->v(i,j) = editWhateverTmp[ti*TS+tj]; - } - - float r = rtemp[ti*TS+tj]; - float g = gtemp[ti*TS+tj]; - float b = btemp[ti*TS+tj]; - - float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; - float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; - float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; - - 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 )))); - - lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; - lab->a[i][j] = (500.0f * (fx - fy) ); - lab->b[i][j] = (200.0f * (fy - fz) ); - - //test for color accuracy - /* - float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 - float fx = (0.002 * lab->a[i][j])/327.68 + fy; - float fz = fy - (0.005 * lab->b[i][j])/327.68; - - float x_ = 65535*Lab2xyz(fx)*Color::D50x; - float y_ = 65535*Lab2xyz(fy); - float z_ = 65535*Lab2xyz(fz)*Color::D50z; - - int R,G,B; - xyz2srgb(x_,y_,z_,R,G,B); - r=(float)R; g=(float)G; b=(float)B; - float xxx=1; - */ - } - } - } else { // black & white - // Auto channel mixer needs whole image, so we now copy to tmpImage and close the tiled processing - for (int i=istart,ti=0; ir(i,j) = editIFloatTmpR[ti*TS+tj]; - editImgFloat->g(i,j) = editIFloatTmpG[ti*TS+tj]; - editImgFloat->b(i,j) = editIFloatTmpB[ti*TS+tj]; - } - else if (editWhatever) { - editWhatever->v(i,j) = editWhateverTmp[ti*TS+tj]; - } - - tmpImage->r(i,j) = rtemp[ti*TS+tj]; - tmpImage->g(i,j) = gtemp[ti*TS+tj]; - tmpImage->b(i,j) = btemp[ti*TS+tj]; - } - } - } - } - free(buffer); - if (editIFloatBuffer) free (editIFloatBuffer); - if (editWhateverBuffer) free (editWhateverBuffer); - -} - // starting a new tile processing with a 'reduction' clause for the auto mixer computing - if (blackwhite) {//channel-mixer - int tW = working->width; - int tH = working->height; - if (algm==2) {//channel-mixer - //end auto chmix - float mix[3][3]; - - if (computeMixerAuto) { - // auto channel-mixer + if (computeMixerAuto) { + // auto channel-mixer #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) reduction(+:nr,ng,nb) + #pragma omp parallel for schedule(dynamic, 5) reduction(+:nr,ng,nb) #endif - for (int i=0; ir(i,j); - ng += tmpImage->g(i,j); - nb += tmpImage->b(i,j); - } - } - double srgb = nr+ng+nb; - double knr = srgb/nr; - double kng = srgb/ng; - double knb = srgb/nb; - double sk = knr+kng+knb; - autor=(float)(100.0*knr/sk); - autog=(float)(100.0*kng/sk); - autob=(float)(100.0*knb/sk); + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + nr += tmpImage->r(i, j); + ng += tmpImage->g(i, j); + nb += tmpImage->b(i, j); + } + } - } + double srgb = nr + ng + nb; + double knr = srgb / nr; + double kng = srgb / ng; + double knb = srgb / nb; + double sk = knr + kng + knb; + autor = (float)(100.0 * knr / sk); + autog = (float)(100.0 * kng / sk); + autob = (float)(100.0 * knb / sk); - if (params->blackwhite.autoc) { - // auto channel-mixer - bwr = autor; - bwg = autog; - bwb = autob; - mixerOrange = 33.f; - mixerYellow = 33.f; - mixerMagenta = 33.f; - mixerPurple = 33.f; - mixerCyan = 33.f; - } - float filcor; - Color::computeBWMixerConstants(params->blackwhite.setting, params->blackwhite.filter,params->blackwhite.algo,filcor, - bwr, bwg, bwb, mixerOrange, mixerYellow, mixerCyan, mixerPurple, mixerMagenta, - params->blackwhite.autoc, complem, kcorec, rrm, ggm, bbm); + } - mix[0][0] = bwr; - mix[1][0] = bwr; - mix[2][0] = bwr; - mix[0][1] = bwg; - mix[1][1] = bwg; - mix[2][1] = bwg; - mix[0][2] = bwb; - mix[1][2] = bwb; - mix[2][2] = bwb; + if (params->blackwhite.autoc) { + // auto channel-mixer + bwr = autor; + bwg = autog; + bwb = autob; + mixerOrange = 33.f; + mixerYellow = 33.f; + mixerMagenta = 33.f; + mixerPurple = 33.f; + mixerCyan = 33.f; + } + + float filcor; + Color::computeBWMixerConstants(params->blackwhite.setting, params->blackwhite.filter, params->blackwhite.algo, filcor, + bwr, bwg, bwb, mixerOrange, mixerYellow, mixerCyan, mixerPurple, mixerMagenta, + params->blackwhite.autoc, complem, kcorec, rrm, ggm, bbm); + + mix[0][0] = bwr; + mix[1][0] = bwr; + mix[2][0] = bwr; + mix[0][1] = bwg; + mix[1][1] = bwg; + mix[2][1] = bwg; + mix[0][2] = bwb; + mix[1][2] = bwb; + mix[2][2] = bwb; #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) + #pragma omp parallel for schedule(dynamic, 5) #endif - for (int i=0; ir(i,j); - in[1] = tmpImage->g(i,j); - in[2] = tmpImage->b(i,j); - //mix channel - for (int end=0; end < 3 ; end++){ - val[end]=0.f; - for (int beg=0; beg < 3 ; beg++) { - val[end] += mix[end][beg] *in[beg]; - } - } - tmpImage->r(i,j) = tmpImage->g(i,j) = tmpImage->b(i,j) = CLIP(val[0]*kcorec); - //gamma correction: pseudo TRC curve - if (hasgammabw) Color::trcGammaBW (tmpImage->r(i,j), tmpImage->g(i,j), tmpImage->b(i,j), gammabwr, gammabwg, gammabwb); - } - } - } - if (editID == EUID_BlackWhiteAfterCurve) { + for (int i = 0; i < tH; i++) { + float in[3], val[3]; + + for (int j = 0; j < tW; j++) { + in[0] = tmpImage->r(i, j); + in[1] = tmpImage->g(i, j); + in[2] = tmpImage->b(i, j); + + //mix channel + for (int end = 0; end < 3 ; end++) { + val[end] = 0.f; + + for (int beg = 0; beg < 3 ; beg++) { + val[end] += mix[end][beg] * in[beg]; + } + } + + tmpImage->r(i, j) = tmpImage->g(i, j) = tmpImage->b(i, j) = CLIP(val[0] * kcorec); + + //gamma correction: pseudo TRC curve + if (hasgammabw) { + Color::trcGammaBW (tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j), gammabwr, gammabwg, gammabwb); + } + } + } + } + + if (editID == EUID_BlackWhiteAfterCurve) { #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) + #pragma omp parallel for schedule(dynamic, 5) #endif - for (int i=0; iv(i,j) = CLIP(fGammaLUTf[tmpImage->r(i,j)]/65535.f); // assuming that r=g=b - } - } - } - if (hasToneCurvebw2) { + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + editWhatever->v(i, j) = CLIP(fGammaLUTf[tmpImage->r(i, j)] / 65535.f); // assuming that r=g=b + } + } + } - if (afterCurveMode==BlackWhiteParams::TC_MODE_STD_BW){ // Standard + if (hasToneCurvebw2) { + + if (afterCurveMode == BlackWhiteParams::TC_MODE_STD_BW) { // Standard #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) + #pragma omp parallel for schedule(dynamic, 5) #endif - for (int i=0; i(customToneCurvebw2); - userToneCurve.Apply(tmpImage->r(i,j), tmpImage->g(i,j), tmpImage->b(i,j)); - } - } - } - else if (afterCurveMode==BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW){ // apply the curve to the rgb channels, weighted + + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + const StandardToneCurvebw& userToneCurve = static_cast(customToneCurvebw2); + userToneCurve.Apply(tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j)); + } + } + } else if (afterCurveMode == BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW) { // apply the curve to the rgb channels, weighted #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) + #pragma omp parallel for schedule(dynamic, 5) #endif - for (int i=0; i(customToneCurvebw2); - - tmpImage->r(i,j) = CLIP(tmpImage->r(i,j)); - tmpImage->g(i,j) = CLIP(tmpImage->g(i,j)); - tmpImage->b(i,j) = CLIP(tmpImage->b(i,j)); - userToneCurve.Apply(tmpImage->r(i,j), tmpImage->g(i,j), tmpImage->b(i,j)); - } - } - } - } + for (int i = 0; i < tH; i++) { //for ulterior usage if bw data modified + for (int j = 0; j < tW; j++) { + const WeightedStdToneCurvebw& userToneCurve = static_cast(customToneCurvebw2); - //colortoning with black and white - if (hasColorToning) { - if(params->colorToning.method=="Splitco") { -/* - #if 1 - for (int i=istart,ti=0; i crash - gtemp[ti*TS+tj] = CLIP(go); - btemp[ti*TS+tj] = CLIP(bo); - } - } -#else -*/ - int preser=0; - if(params->colorToning.lumamode == true) preser=1; + tmpImage->r(i, j) = CLIP(tmpImage->r(i, j)); + tmpImage->g(i, j) = CLIP(tmpImage->g(i, j)); + tmpImage->b(i, j) = CLIP(tmpImage->b(i, j)); - float reducac= 0.3f; + userToneCurve.Apply(tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j)); + } + } + } + } + + //colortoning with black and white + if (hasColorToning) { + if(params->colorToning.method == "Splitco") { + /* + #if 1 + for (int i=istart,ti=0; i crash + gtemp[ti*TS+tj] = CLIP(go); + btemp[ti*TS+tj] = CLIP(bo); + } + } + #else + */ + int preser = 0; + + if(params->colorToning.lumamode == true) { + preser = 1; + } + + float reducac = 0.3f; #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) + #pragma omp parallel for schedule(dynamic, 5) #endif - - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); - - float lumbefore=0.299f*r + 0.587f*g + 0.114f*b; - if(lumbefore < 65000.f && lumbefore > 500.f) { //reduct artifacts for highlights an extrem shadows - float ro,go,bo; - int mode=1; - toningsmh (r, g, b, ro, go, bo, RedLow, GreenLow, BlueLow, RedMed, GreenMed, BlueMed, RedHigh, GreenHigh, BlueHigh, reducac, mode, preser, strProtect); - float lumafter=0.299f*ro + 0.587f*go + 0.114f*bo; - float preserv=1.f; - if(preser==1) preserv=lumbefore/lumafter; - ro*=preserv; - go*=preserv; - bo*=preserv; - ro=CLIP(ro); - go=CLIP(go); - bo=CLIP(bo); - tmpImage->r(i,j)=ro; - tmpImage->g(i,j)=go; - tmpImage->b(i,j)=bo; - } - } - } + + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + float r = tmpImage->r(i, j); + float g = tmpImage->g(i, j); + float b = tmpImage->b(i, j); + + float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; + + if(lumbefore < 65000.f && lumbefore > 500.f) { //reduct artifacts for highlights an extrem shadows + float ro, go, bo; + int mode = 1; + toningsmh (r, g, b, ro, go, bo, RedLow, GreenLow, BlueLow, RedMed, GreenMed, BlueMed, RedHigh, GreenHigh, BlueHigh, reducac, mode, preser, strProtect); + float lumafter = 0.299f * ro + 0.587f * go + 0.114f * bo; + float preserv = 1.f; + + if(preser == 1) { + preserv = lumbefore / lumafter; + } + + ro *= preserv; + go *= preserv; + bo *= preserv; + ro = CLIP(ro); + go = CLIP(go); + bo = CLIP(bo); + tmpImage->r(i, j) = ro; + tmpImage->g(i, j) = go; + tmpImage->b(i, j) = bo; + } + } + } + //#endif - } + } - else if (params->colorToning.method=="Splitlr") { - float balanS, balanH; - float reducac= 0.4f; - int preser=0; - if(params->colorToning.lumamode == true) preser=1; + else if (params->colorToning.method == "Splitlr") { + float balanS, balanH; + float reducac = 0.4f; + int preser = 0; - balanS = 1.f + Balan/100.f;//balan between 0 and 2 - balanH = 1.f - Balan/100.f; - float rh, gh, bh; - float rl, gl, bl; - float xh, yh, zh; - float xl, yl, zl; - float iplow,iphigh; - iplow=(float)ctColorCurve.low; - iphigh=(float)ctColorCurve.high; + if(params->colorToning.lumamode == true) { + preser = 1; + } - //2 colours - ctColorCurve.getVal(iphigh, xh, yh, zh); - ctColorCurve.getVal(iplow, xl, yl, zl); + balanS = 1.f + Balan / 100.f; //balan between 0 and 2 + balanH = 1.f - Balan / 100.f; + float rh, gh, bh; + float rl, gl, bl; + float xh, yh, zh; + float xl, yl, zl; + float iplow, iphigh; + iplow = (float)ctColorCurve.low; + iphigh = (float)ctColorCurve.high; - Color::xyz2rgb(xh, yh, zh, rh, gh, bh, wip); - Color::xyz2rgb(xl, yl, zl, rl, gl, bl, wip); + //2 colours + ctColorCurve.getVal(iphigh, xh, yh, zh); + ctColorCurve.getVal(iplow, xl, yl, zl); - //retrieve rgb value with s and l =1 - retreavergb(rl,gl,bl); - retreavergb(rh,gh,bh); + Color::xyz2rgb(xh, yh, zh, rh, gh, bh, wip); + Color::xyz2rgb(xl, yl, zl, rl, gl, bl, wip); + + //retrieve rgb value with s and l =1 + retreavergb(rl, gl, bl); + retreavergb(rh, gh, bh); #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) -#endif - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); - - float ro,go,bo; - int mode=1; - toning2col (r, g, b, ro, go, bo, iplow, iphigh, rl, gl, bl, rh, gh, bh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); - tmpImage->r(i,j)=ro; - tmpImage->g(i,j)=go; - tmpImage->b(i,j)=bo; - } - } - } - - //colortoning with shift color Lab - else if (params->colorToning.method=="Lab" && opautili) { - int algm=0; - bool twocol = true; - int metchrom; - if (params->colorToning.twocolor=="Std" ) metchrom=0; - else if (params->colorToning.twocolor=="All" ) metchrom=1; - else if (params->colorToning.twocolor=="Separ") metchrom=2; - else if (params->colorToning.twocolor=="Two" ) metchrom=3; - - if(metchrom==3) twocol=false; - - float iplow,iphigh; - if(twocol==false) { - iplow=(float)ctColorCurve.low; - iphigh=(float)ctColorCurve.high; - - } - int twoc=0;//integer instead of bool to let more possible choice...other than 2 and 500. - if(twocol==false) twoc=0; // 2 colours - else twoc=1; // 500 colours - if (params->colorToning.method=="Lab") algm=1; - else if(params->colorToning.method=="Lch") algm=2; //in case of - if(algm <=2) { -#ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) -#endif - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); - float ro,bo,go; - labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve,cl2Toningcurve, iplow, iphigh, wp, wip); - tmpImage->r(i,j)=CLIP(ro); - tmpImage->g(i,j)=CLIP(go); - tmpImage->b(i,j)=CLIP(bo); - - } - } - } - } - - else if (params->colorToning.method.substr(0,3)=="RGB" && opautili) { - // color toning -#ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) -#endif - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); - - // Luminance = (0.299f*r + 0.587f*g + 0.114f*b) - - float h,s,l; - Color::rgb2hsl(r,g,b,h,s,l); - - float l_ = Color::gamma_srgb(l*65535.f)/65535.f; - - // get the opacity and tweak it to preserve saturated colors - float opacity = ctOpacityCurve.lutOpacityCurve[l_*500.f]/4.f; - - float r2, g2, b2; - ctColorCurve.getVal(l_, r2, g2, b2); // get the color from the color curve - - float h2, s2, l2; - Color::rgb2hsl(r2,g2,b2,h2,s2,l2); // transform this new color to hsl - - Color::hsl2rgb(h2, s2, l, r2, g2, b2); - - tmpImage->r(i,j)= r+(r2-r)*opacity; - tmpImage->g(i,j) = g+(g2-g)*opacity; - tmpImage->b(i,j)= b+(b2-b)*opacity; - } - } - } - } - // filling the pipette buffer by the content of the temp pipette buffers - // due to optimization, we have to test now if the pipette has been filled in the second tile loop, by - // testing editID - /*if (editImgFloat) { - for (int i=istart,ti=0; ir(i,j) = editIFloatTmpR[ti*TS+tj]; - editImgFloat->g(i,j) = editIFloatTmpG[ti*TS+tj]; - editImgFloat->b(i,j) = editIFloatTmpB[ti*TS+tj]; - } - } - else*/ - /* - if (editWhatever && (editID==EUID_BlackWhiteAfterCurve)) { - for (int i=istart,ti=0; iv(i,j) = editWhateverTmp[ti*TS+tj]; - } - } -*/ - - // ready, fill lab (has to be the same code than the "fill lab" above!) - -#ifdef _OPENMP -#pragma omp parallel for schedule(dynamic, 5) + #pragma omp parallel for schedule(dynamic, 5) #endif - for (int i=0; ir(i,j); - float g = tmpImage->g(i,j); - float b = tmpImage->b(i,j); - float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; - float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; - float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + float r = tmpImage->r(i, j); + float g = tmpImage->g(i, j); + float b = tmpImage->b(i, j); - float fx,fy,fz; + float ro, go, bo; + int mode = 1; + toning2col (r, g, b, ro, go, bo, iplow, iphigh, rl, gl, bl, rh, gh, bh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); + tmpImage->r(i, j) = ro; + tmpImage->g(i, j) = go; + tmpImage->b(i, j) = bo; + } + } + } - 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 )))); + //colortoning with shift color Lab + else if (params->colorToning.method == "Lab" && opautili) { + int algm = 0; + bool twocol = true; + int metchrom; - lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; - lab->a[i][j] = (500.0f * (fx - fy) ); - lab->b[i][j] = (200.0f * (fy - fz) ); + if (params->colorToning.twocolor == "Std" ) { + metchrom = 0; + } else if (params->colorToning.twocolor == "All" ) { + metchrom = 1; + } else if (params->colorToning.twocolor == "Separ") { + metchrom = 2; + } else if (params->colorToning.twocolor == "Two" ) { + metchrom = 3; + } + + if(metchrom == 3) { + twocol = false; + } + + float iplow, iphigh; + + if(twocol == false) { + iplow = (float)ctColorCurve.low; + iphigh = (float)ctColorCurve.high; + + } + + int twoc = 0; //integer instead of bool to let more possible choice...other than 2 and 500. + + if(twocol == false) { + twoc = 0; // 2 colours + } else { + twoc = 1; // 500 colours + } + + if (params->colorToning.method == "Lab") { + algm = 1; + } else if(params->colorToning.method == "Lch") { + algm = 2; //in case of + } + + if(algm <= 2) { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 5) +#endif + + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + float h, s, l; + float r = tmpImage->r(i, j); + float g = tmpImage->g(i, j); + float b = tmpImage->b(i, j); + float ro, bo, go; + labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip); + tmpImage->r(i, j) = CLIP(ro); + tmpImage->g(i, j) = CLIP(go); + tmpImage->b(i, j) = CLIP(bo); + + } + } + } + } + + else if (params->colorToning.method.substr(0, 3) == "RGB" && opautili) { + // color toning +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 5) +#endif + + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + float r = tmpImage->r(i, j); + float g = tmpImage->g(i, j); + float b = tmpImage->b(i, j); + + // Luminance = (0.299f*r + 0.587f*g + 0.114f*b) + + float h, s, l; + Color::rgb2hsl(r, g, b, h, s, l); + + float l_ = Color::gamma_srgb(l * 65535.f) / 65535.f; + + // get the opacity and tweak it to preserve saturated colors + float opacity = ctOpacityCurve.lutOpacityCurve[l_ * 500.f] / 4.f; + + float r2, g2, b2; + ctColorCurve.getVal(l_, r2, g2, b2); // get the color from the color curve + + float h2, s2, l2; + Color::rgb2hsl(r2, g2, b2, h2, s2, l2); // transform this new color to hsl + + Color::hsl2rgb(h2, s2, l, r2, g2, b2); + + tmpImage->r(i, j) = r + (r2 - r) * opacity; + tmpImage->g(i, j) = g + (g2 - g) * opacity; + tmpImage->b(i, j) = b + (b2 - b) * opacity; + } + } + } + } + + // filling the pipette buffer by the content of the temp pipette buffers + // due to optimization, we have to test now if the pipette has been filled in the second tile loop, by + // testing editID + /*if (editImgFloat) { + for (int i=istart,ti=0; ir(i,j) = editIFloatTmpR[ti*TS+tj]; + editImgFloat->g(i,j) = editIFloatTmpG[ti*TS+tj]; + editImgFloat->b(i,j) = editIFloatTmpB[ti*TS+tj]; + } + } + else*/ + /* + if (editWhatever && (editID==EUID_BlackWhiteAfterCurve)) { + for (int i=istart,ti=0; iv(i,j) = editWhateverTmp[ti*TS+tj]; + } + } + */ + + // ready, fill lab (has to be the same code than the "fill lab" above!) + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 5) +#endif + + for (int i = 0; i < tH; i++) { + for (int j = 0; j < tW; j++) { + float r = tmpImage->r(i, j); + float g = tmpImage->g(i, j); + float b = tmpImage->b(i, j); + + float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; + float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; + float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; + + 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 )))); + + lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; + lab->a[i][j] = (500.0f * (fx - fy) ); + lab->b[i][j] = (200.0f * (fy - fz) ); - //test for color accuracy - /*float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 - float fx = (0.002 * lab->a[i][j])/327.68 + fy; - float fz = fy - (0.005 * lab->b[i][j])/327.68; + //test for color accuracy + /*float fy = (0.00862069 * lab->L[i][j])/327.68 + 0.137932; // (L+16)/116 + float fx = (0.002 * lab->a[i][j])/327.68 + fy; + float fz = fy - (0.005 * lab->b[i][j])/327.68; - float x_ = 65535*Lab2xyz(fx)*Color::D50x; - float y_ = 65535*Lab2xyz(fy); - float z_ = 65535*Lab2xyz(fz)*Color::D50z; + float x_ = 65535*Lab2xyz(fx)*Color::D50x; + float y_ = 65535*Lab2xyz(fy); + float z_ = 65535*Lab2xyz(fz)*Color::D50z; - int R,G,B; - xyz2srgb(x_,y_,z_,R,G,B); - r=(float)R; g=(float)G; b=(float)B; - float xxx=1;*/ + int R,G,B; + xyz2srgb(x_,y_,z_,R,G,B); + r=(float)R; g=(float)G; b=(float)B; + float xxx=1;*/ - } - } + } + } - if(tmpImage) - delete tmpImage; - } - if (hCurveEnabled) delete hCurve; - if (sCurveEnabled) delete sCurve; - if (vCurveEnabled) delete vCurve; + if(tmpImage) { + delete tmpImage; + } + } + + if (hCurveEnabled) { + delete hCurve; + } + + if (sCurveEnabled) { + delete sCurve; + } + + if (vCurveEnabled) { + delete vCurve; + } } /** -* @brief retreave RGB value with maximum saturation -* @param r red input and in exit new r -* @param g green input and in exit new g -* @param b blue input and in exit new b +* @brief retreave RGB value with maximum saturation +* @param r red input and in exit new r +* @param g green input and in exit new g +* @param b blue input and in exit new b **/ -void ImProcFunctions::retreavergb (float &r, float &g, float &b) { - float mini = min(r,g,b); - float maxi = max(r,g,b); - float kkm=65535.f/maxi; - if(b==mini && r==maxi) {r=65535.f;g=kkm*(g-b);b=0.f;} - else if(b==mini && g==maxi) {g=65535.f;r=kkm*(r-b);b=0.f;} - else if(g==mini && r==maxi) {r=65535.f;b=kkm*(b-g);g=0.f;} - else if(g==mini && b==maxi) {b=65535.f;r=kkm*(r-g);g=0.f;} - else if(r==mini && b==maxi) {b=65535.f;g=kkm*(g-r);r=0.f;} - else if(r==mini && g==maxi) {g=65535.f;b=kkm*(b-r);r=0.f;} +void ImProcFunctions::retreavergb (float &r, float &g, float &b) +{ + float mini = min(r, g, b); + float maxi = max(r, g, b); + float kkm = 65535.f / maxi; + + if(b == mini && r == maxi) { + r = 65535.f; + g = kkm * (g - b); + b = 0.f; + } else if(b == mini && g == maxi) { + g = 65535.f; + r = kkm * (r - b); + b = 0.f; + } else if(g == mini && r == maxi) { + r = 65535.f; + b = kkm * (b - g); + g = 0.f; + } else if(g == mini && b == maxi) { + b = 65535.f; + r = kkm * (r - g); + g = 0.f; + } else if(r == mini && b == maxi) { + b = 65535.f; + g = kkm * (g - r); + r = 0.f; + } else if(r == mini && g == maxi) { + g = 65535.f; + b = kkm * (b - r); + r = 0.f; + } } /** * @brief Interpolate by decreasing with a parabol k = aa*v*v + bb*v +c v[0..1] -* @param reducac val ue of the reduction in the middle of the range +* @param reducac val ue of the reduction in the middle of the range * @param vinf value [0..1] for beginning decrease * @param aa second degree parameter * @param bb first degree parameter * @param cc third parameter **/ -void ImProcFunctions::secondeg_end (float reducac, float vinf, float &aa, float &bb, float &cc) { - float zrd=reducac;//value at me linear =0.5 - float v0=vinf;//max shadows - float me=(1.f + v0)/2.f;//"median" value = (v0 + 1.=/2) - //float a1=1.f-v0; - float a2=me-v0; - float a3=1.f-v0*v0; - float a4=me*me-v0*v0; - aa = (1.f + (zrd-1.f)*(1-v0)/a2)/(a4*(1.f-v0)/a2 - a3); - bb = -(1.f + a3*aa)/(1.f-v0); - cc = - (aa +bb); +void ImProcFunctions::secondeg_end (float reducac, float vinf, float &aa, float &bb, float &cc) +{ + float zrd = reducac; //value at me linear =0.5 + float v0 = vinf; //max shadows + float me = (1.f + v0) / 2.f; //"median" value = (v0 + 1.=/2) + //float a1=1.f-v0; + float a2 = me - v0; + float a3 = 1.f - v0 * v0; + float a4 = me * me - v0 * v0; + aa = (1.f + (zrd - 1.f) * (1 - v0) / a2) / (a4 * (1.f - v0) / a2 - a3); + bb = -(1.f + a3 * aa) / (1.f - v0); + cc = - (aa + bb); } /** * @brief Interpolate by increasing with a parabol k = aa*v*v + bb*v v[0..1] -* @param reducac val ue of the reduction in the middle of the range +* @param reducac val ue of the reduction in the middle of the range * @param vend value [0..1] for beginning increase * @param aa second degree parameter * @param bb first degree parameter **/ -void ImProcFunctions::secondeg_begin (float reducac, float vend, float &aam, float &bbm) { - float zrmd=reducac;//linear = 0.5 - float v0m=vend; - float mem=vend/2.f;//(0. + 0.8)/2.f - aam=(1.f-zrmd*v0m/mem)/(v0m*v0m-mem*v0m);// - bbm=(1.f-aam*v0m*v0m)/v0m; +void ImProcFunctions::secondeg_begin (float reducac, float vend, float &aam, float &bbm) +{ + float zrmd = reducac; //linear = 0.5 + float v0m = vend; + float mem = vend / 2.f; //(0. + 0.8)/2.f + aam = (1.f - zrmd * v0m / mem) / (v0m * v0m - mem * v0m); // + bbm = (1.f - aam * v0m * v0m) / v0m; } @@ -4123,249 +5051,270 @@ void ImProcFunctions::secondeg_begin (float reducac, float vend, float &aam, flo * @param mode ? * @param preser whether to preserve luminance (if 1) or not **/ -void ImProcFunctions::toningsmh (float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, int preser, float strProtect) { - float bmu = mode==1 ? 0.5f : 0.4f; - float RedL = 1.f + (RedLow -1.f)*0.4f; - float GreenL = 1.f + (GreenLow-1.f)*0.4f; - float BlueL = 1.f + (BlueLow -1.f)*bmu; - float h,s,v; - Color::rgb2hsv(r, g, b, h, s, v); - float ksat=1.f; - float ksatlow=1.f; -// float s_0=0.55f; -// float s_1=0.85f; - /* - if(mode==0) {//color - if(s < s_0) ksat=SQR((1.f/s_0)*s); - if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); - } - */ - ksat=1.f; - float kl=1.f; - float rlo=1.f;//0.4 0.5 - float rlm=1.5f;//1.1 - float rlh=2.2f;//1.1 - float rlob=bmu;//for BW old mode - - if(mode==0){//color - rlo*=pow_F(strProtect,0.4f);//0.5 ==> 0.75 - rlh*=pow_F(strProtect,0.4f); - rlm*=pow_F(strProtect,0.4f); - } - else {//bw coefficient to preserve same results as before for satlimtopacity = 0.5 (default) - rlo=strProtect*0.8f;//0.4 - rlob=strProtect;//0.5 - rlm=strProtect*2.2f;//1.1 - rlh=strProtect*2.4f;//1.2 - } - if(mode==0) rlob=rlo; +void ImProcFunctions::toningsmh (float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, int preser, float strProtect) +{ + float bmu = mode == 1 ? 0.5f : 0.4f; + float RedL = 1.f + (RedLow - 1.f) * 0.4f; + float GreenL = 1.f + (GreenLow - 1.f) * 0.4f; + float BlueL = 1.f + (BlueLow - 1.f) * bmu; + float h, s, v; + Color::rgb2hsv(r, g, b, h, s, v); + float ksat = 1.f; + float ksatlow = 1.f; +// float s_0=0.55f; +// float s_1=0.85f; + /* + if(mode==0) {//color + if(s < s_0) ksat=SQR((1.f/s_0)*s); + if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); + } + */ + ksat = 1.f; + float kl = 1.f; + float rlo = 1.f; //0.4 0.5 + float rlm = 1.5f; //1.1 + float rlh = 2.2f; //1.1 + float rlob = bmu; //for BW old mode - //second degree - float aa,bb,cc; - float v0=0.15f; - //fixed value of reducac=0.3 - //secondeg_end (reducac, v0, aa, bb, cc); - if(mode==1) { - reducac=0.5f;//black and white mode - if(v > 0.15f) - kl =(-1.f/0.85f)*v + (1.f)/0.85f;//Low light ==> decrease action after v=0.15 - } - else { //color - secondeg_end (reducac, v0, aa, bb, cc); - float aab,bbb; - secondeg_begin (0.7f, v0, aab, bbb); + if(mode == 0) { //color + rlo *= pow_F(strProtect, 0.4f); //0.5 ==> 0.75 + rlh *= pow_F(strProtect, 0.4f); + rlm *= pow_F(strProtect, 0.4f); + } else { //bw coefficient to preserve same results as before for satlimtopacity = 0.5 (default) + rlo = strProtect * 0.8f; //0.4 + rlob = strProtect; //0.5 + rlm = strProtect * 2.2f; //1.1 + rlh = strProtect * 2.4f; //1.2 + } - if(v > v0) kl=aa*v*v+bb*v+cc;//verified ==> exact - else if (mode==0) kl=aab*v*v+bbb*v;//ksatlow=ksat; - } + if(mode == 0) { + rlob = rlo; + } - if(RedLow !=1.f) { - RedL = 1.f + (RedLow-1.f) * kl * ksat * rlo; //0.4 - if(RedLow >= 1.f) { - g -= 20000.f*(RedL-1.f) * ksatlow; - b -= 20000.f*(RedL-1.f) * ksatlow; - } - else { - r += 20000.f*(RedL-1.f) * ksatlow; - } - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } + //second degree + float aa, bb, cc; + float v0 = 0.15f; - if(GreenLow !=1.f) { - GreenL = 1.f + (GreenLow-1.f) * kl * ksat * rlo; //0.4 - if(GreenLow >= 1.f) { - r -= 20000.f*(GreenL-1.f) * ksatlow; - b -= 20000.f*(GreenL-1.f) * ksatlow; - } - else { - g += 20000.f*(GreenL-1.f) * ksatlow; - } + //fixed value of reducac=0.3 + //secondeg_end (reducac, v0, aa, bb, cc); + if(mode == 1) { + reducac = 0.5f; //black and white mode - r=CLIP(r); - b=CLIP(b); - g=CLIP(g); - } + if(v > 0.15f) { + kl = (-1.f / 0.85f) * v + (1.f) / 0.85f; //Low light ==> decrease action after v=0.15 + } + } else { //color + secondeg_end (reducac, v0, aa, bb, cc); + float aab, bbb; + secondeg_begin (0.7f, v0, aab, bbb); - if(BlueLow !=1.f) { - BlueL = 1.f + (BlueLow-1.f) * kl * ksat * rlob; - if(BlueLow >= 1.f) { - r -= 20000.f*(BlueL-1.f) * ksatlow; - g -= 20000.f*(BlueL-1.f) * ksatlow; - } - else { - b += 20000.f*(BlueL-1.f)* ksatlow; - } + if(v > v0) { + kl = aa * v * v + bb * v + cc; //verified ==> exact + } else if (mode == 0) { + kl = aab * v * v + bbb * v; //ksatlow=ksat; + } + } - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - // mid tones - float km; - float v0m=0.5f;//max action - float v0mm=0.5f;//max + if(RedLow != 1.f) { + RedL = 1.f + (RedLow - 1.f) * kl * ksat * rlo; //0.4 - if(v= 1.f) { + g -= 20000.f * (RedL - 1.f) * ksatlow; + b -= 20000.f * (RedL - 1.f) * ksatlow; + } else { + r += 20000.f * (RedL - 1.f) * ksatlow; + } - float RedM = 1.f + (RedMed-1.f)*rlm; - if(RedMed !=1.f) { - RedM = 1.f + (RedMed-1.f) * km * rlm; - if(RedMed >= 1.f) { - r += 20000.f*(RedM-1.f); - g -= 10000.f*(RedM-1.f); - b -= 10000.f*(RedM-1.f); - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - else { - r += 10000.f*(RedM-1.f); - g -= 20000.f*(RedM-1.f); - b -= 20000.f*(RedM-1.f); - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - } + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } - float GreenM = 1.f + (GreenMed-1.f)*rlm; - if(GreenMed !=1.f) { - GreenM = 1.f + (GreenMed-1.f) * km * rlm; - if(GreenMed >= 1.f) { - r -= 10000.f*(GreenM-1.f); - g += 20000.f*(GreenM-1.f); - b -= 10000.f*(GreenM-1.f); - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - else { - r -= 20000.f*(GreenM-1.f); - g += 10000.f*(GreenM-1.f); - b -= 20000.f*(GreenM-1.f); - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - } + if(GreenLow != 1.f) { + GreenL = 1.f + (GreenLow - 1.f) * kl * ksat * rlo; //0.4 - float BlueM = 1.f + (BlueMed-1.f)*rlm; - if(BlueMed !=1.f) { - BlueM = 1.f + (BlueMed-1.f) * km * rlm; - if(BlueMed >= 1.f) { - r -= 10000.f*(BlueM-1.f); - g -= 10000.f*(BlueM-1.f); - b += 20000.f*(BlueM-1.f); - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - else { - r -= 20000.f*(BlueM-1.f); - g -= 20000.f*(BlueM-1.f); - b += 10000.f*(BlueM-1.f); - r=CLIP(r); - g=CLIP(g); - b=CLIP(b); - } - } + if(GreenLow >= 1.f) { + r -= 20000.f * (GreenL - 1.f) * ksatlow; + b -= 20000.f * (GreenL - 1.f) * ksatlow; + } else { + g += 20000.f * (GreenL - 1.f) * ksatlow; + } - //high tones - float kh; - kh=1.f; - float v00=0.8f;//max action - float aa0, bb0; - secondeg_begin (reducac, v00, aa0, bb0); -// float hmu=1.5f; -// if(mode==1) hmu=1.2f;//for BW old mode + r = CLIP(r); + b = CLIP(b); + g = CLIP(g); + } - if(v > v00) { kh =(-1.f/(1.f-v00))*v + (1.f)/(1.f-v00); }//High tones - else kh=aa0*v*v+bb0*v;//verification = good + if(BlueLow != 1.f) { + BlueL = 1.f + (BlueLow - 1.f) * kl * ksat * rlob; - float RedH=1.f + (RedHigh-1.f)*rlh; - float GreenH=1.f + (GreenHigh-1.f)*rlh; - float BlueH=1.f + (BlueHigh-1.f)*rlh;//1.2 - if(RedHigh !=1.f) { - RedH = 1.f + (RedHigh-1.f) * kh * rlh; //1.2 - if(RedHigh >= 1.f) { - r += 20000.f*(RedH-1.f); - r=CLIP(r); - } - else { - g -= 20000.f*(RedH-1.f); - b -= 20000.f*(RedH-1.f); - } - g=CLIP(g); - b=CLIP(b); - } - if(GreenHigh !=1.f) { - GreenH = 1.f + (GreenHigh-1.f) * kh * rlh; //1.2 - if(GreenHigh >= 1.f) { - g += 20000.f*(GreenH-1.f); - g=CLIP(g); - } - else { - r -= 20000.f*(GreenH-1.f); - b -= 20000.f*(GreenH-1.f); - } - r=CLIP(r); - b=CLIP(b); - } - if(BlueHigh !=1.f) { - BlueH = 1.f + (BlueHigh-1.f) * kh * rlh; //1.2 - if(BlueHigh >= 1.f) { - b += 20000.f*(BlueH-1.f); - b=CLIP(b); - } - else { - r -= 20000.f*(BlueH-1.f); - g -= 20000.f*(BlueH-1.f); - } - r=CLIP(r); - g=CLIP(g); - } + if(BlueLow >= 1.f) { + r -= 20000.f * (BlueL - 1.f) * ksatlow; + g -= 20000.f * (BlueL - 1.f) * ksatlow; + } else { + b += 20000.f * (BlueL - 1.f) * ksatlow; + } - ro=r; - go=g; - bo=b; + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } + + // mid tones + float km; + float v0m = 0.5f; //max action + float v0mm = 0.5f; //max + + if(v < v0m) { + float aam, bbm; + float vend = v0m; + secondeg_begin (reducac, vend, aam, bbm); + km = aam * v * v + bbm * v; //verification = good + } else { + float aamm, bbmm, ccmm; + secondeg_end (reducac, v0mm, aamm, bbmm, ccmm); + km = aamm * v * v + bbmm * v + ccmm; //verification good + } + + float RedM = 1.f + (RedMed - 1.f) * rlm; + + if(RedMed != 1.f) { + RedM = 1.f + (RedMed - 1.f) * km * rlm; + + if(RedMed >= 1.f) { + r += 20000.f * (RedM - 1.f); + g -= 10000.f * (RedM - 1.f); + b -= 10000.f * (RedM - 1.f); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } else { + r += 10000.f * (RedM - 1.f); + g -= 20000.f * (RedM - 1.f); + b -= 20000.f * (RedM - 1.f); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } + } + + float GreenM = 1.f + (GreenMed - 1.f) * rlm; + + if(GreenMed != 1.f) { + GreenM = 1.f + (GreenMed - 1.f) * km * rlm; + + if(GreenMed >= 1.f) { + r -= 10000.f * (GreenM - 1.f); + g += 20000.f * (GreenM - 1.f); + b -= 10000.f * (GreenM - 1.f); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } else { + r -= 20000.f * (GreenM - 1.f); + g += 10000.f * (GreenM - 1.f); + b -= 20000.f * (GreenM - 1.f); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } + } + + float BlueM = 1.f + (BlueMed - 1.f) * rlm; + + if(BlueMed != 1.f) { + BlueM = 1.f + (BlueMed - 1.f) * km * rlm; + + if(BlueMed >= 1.f) { + r -= 10000.f * (BlueM - 1.f); + g -= 10000.f * (BlueM - 1.f); + b += 20000.f * (BlueM - 1.f); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } else { + r -= 20000.f * (BlueM - 1.f); + g -= 20000.f * (BlueM - 1.f); + b += 10000.f * (BlueM - 1.f); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); + } + } + + //high tones + float kh; + kh = 1.f; + float v00 = 0.8f; //max action + float aa0, bb0; + secondeg_begin (reducac, v00, aa0, bb0); +// float hmu=1.5f; +// if(mode==1) hmu=1.2f;//for BW old mode + + if(v > v00) { + kh = (-1.f / (1.f - v00)) * v + (1.f) / (1.f - v00); //High tones + } else { + kh = aa0 * v * v + bb0 * v; //verification = good + } + + float RedH = 1.f + (RedHigh - 1.f) * rlh; + float GreenH = 1.f + (GreenHigh - 1.f) * rlh; + float BlueH = 1.f + (BlueHigh - 1.f) * rlh; //1.2 + + if(RedHigh != 1.f) { + RedH = 1.f + (RedHigh - 1.f) * kh * rlh; //1.2 + + if(RedHigh >= 1.f) { + r += 20000.f * (RedH - 1.f); + r = CLIP(r); + } else { + g -= 20000.f * (RedH - 1.f); + b -= 20000.f * (RedH - 1.f); + } + + g = CLIP(g); + b = CLIP(b); + } + + if(GreenHigh != 1.f) { + GreenH = 1.f + (GreenHigh - 1.f) * kh * rlh; //1.2 + + if(GreenHigh >= 1.f) { + g += 20000.f * (GreenH - 1.f); + g = CLIP(g); + } else { + r -= 20000.f * (GreenH - 1.f); + b -= 20000.f * (GreenH - 1.f); + } + + r = CLIP(r); + b = CLIP(b); + } + + if(BlueHigh != 1.f) { + BlueH = 1.f + (BlueHigh - 1.f) * kh * rlh; //1.2 + + if(BlueHigh >= 1.f) { + b += 20000.f * (BlueH - 1.f); + b = CLIP(b); + } else { + r -= 20000.f * (BlueH - 1.f); + g -= 20000.f * (BlueH - 1.f); + } + + r = CLIP(r); + g = CLIP(g); + } + + ro = r; + go = g; + bo = b; } /** * @brief color toning with 2 colors - 2 sliders saturation shadows and highlight and one balance -* @param r g b input values [0..65535] -* @param ro go bo output values [0..65535] +* @param r g b input values [0..65535] +* @param ro go bo output values [0..65535] * @param iplow iphigh [0..1] from curve color - value of luminance shadows and highlights * @param rl gl bl [0..65535] - color of reference shadow * @param rh gh bh [0..65535] - color of reference highlight @@ -4374,1495 +5323,1803 @@ void ImProcFunctions::toningsmh (float r, float g, float b, float &ro, float &go * @param balanH [0..1] balance for highlights (same slider than for balanS) * @param reducac value of the reduction in the middle of the range for second degree, increase or decrease action **/ -void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl,float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect) { - float lumbefore=0.299f*r + 0.587f*g + 0.114f*b; - float h,s,l; - Color::rgb2hsl(r,g,b,h,s,l); - float v; - Color::rgb2hsv(r, g, b, h, s, v); - float ksat=1.f; - float ksatlow=1.f; - float s_0=0.55f; - float s_1=0.85f; -/* - if(mode==0) {//color - if(s < s_0) ksat=SQR((1.f/s_0)*s); - if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); - } - */ - ksat=1.f; - float kl=1.f; - float rlo=1.f; - float rlh=2.2f; - rlo*=pow_F(strProtect,0.4f);//0.5 ==> 0.75 transfered value for more action - rlh*=pow_F(strProtect,0.4f); - //low tones - //second degree - float aa, bb, cc; - //fixed value of reducac =0.4; - secondeg_end (reducac, iplow, aa, bb, cc); - float aab, bbb, ccb; - - secondeg_begin (0.7f, iplow, aab, bbb); +void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl, float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect) +{ + float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; + float h, s, l; + Color::rgb2hsl(r, g, b, h, s, l); + float v; + Color::rgb2hsv(r, g, b, h, s, v); + float ksat = 1.f; + float ksatlow = 1.f; + float s_0 = 0.55f; + float s_1 = 0.85f; + /* + if(mode==0) {//color + if(s < s_0) ksat=SQR((1.f/s_0)*s); + if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); + } + */ + ksat = 1.f; + float kl = 1.f; + float rlo = 1.f; + float rlh = 2.2f; + rlo *= pow_F(strProtect, 0.4f); //0.5 ==> 0.75 transfered value for more action + rlh *= pow_F(strProtect, 0.4f); + //low tones + //second degree + float aa, bb, cc; + //fixed value of reducac =0.4; + secondeg_end (reducac, iplow, aa, bb, cc); + float aab, bbb, ccb; - if(v > iplow) kl=aa*v*v+bb*v+cc; - else if (mode==0) kl=aab*v*v+bbb*v; + secondeg_begin (0.7f, iplow, aab, bbb); - //rl gl bl - float RedL, GreenL, BlueL; - float krl=rl/(rl+gl+bl); - float kgl=gl/(rl+gl+bl); - float kbl=bl/(rl+gl+bl); + if(v > iplow) { + kl = aa * v * v + bb * v + cc; + } else if (mode == 0) { + kl = aab * v * v + bbb * v; + } - if(SatLow > 0.f) { - float kmgb; - if(g<20000.f || b < 20000.f || r < 20000.f) { kmgb=min(r,g,b);kl *= pow((kmgb/20000.f),0.85f); } //I have tested ...0.85 compromise... - RedL = 1.f + (SatLow*krl) * kl * ksat * rlo * balanS; //0.4 - if(krl > 0.f) { - g -= 20000.f*(RedL-1.f) * ksatlow; - b -= 20000.f*(RedL-1.f) * ksatlow; - } - g=CLIP(g); - b=CLIP(b); + //rl gl bl + float RedL, GreenL, BlueL; + float krl = rl / (rl + gl + bl); + float kgl = gl / (rl + gl + bl); + float kbl = bl / (rl + gl + bl); - GreenL = 1.f + (SatLow*kgl) * kl * ksat * rlo * balanS; //0.4 - if(kgl > 0.f) { - r -= 20000.f*(GreenL-1.f) * ksatlow; - b -= 20000.f*(GreenL-1.f) * ksatlow; - } - r=CLIP(r); - b=CLIP(b); + if(SatLow > 0.f) { + float kmgb; - BlueL = 1.f + (SatLow*kbl) * kl * ksat * rlo * balanS; //0.4 - if(kbl > 0.f) { - r -= 20000.f*(BlueL-1.f) * ksatlow; - g -= 20000.f*(BlueL-1.f) * ksatlow; - } - r=CLIP(r); - g=CLIP(g); - } + if(g < 20000.f || b < 20000.f || r < 20000.f) { + kmgb = min(r, g, b); //I have tested ...0.85 compromise... + kl *= pow((kmgb / 20000.f), 0.85f); + } - //high tones - float kh=1.f; - kh=1.f; - float aa0, bb0; - //fixed value of reducac ==0.4; - secondeg_begin (reducac, iphigh, aa0, bb0); + RedL = 1.f + (SatLow * krl) * kl * ksat * rlo * balanS; //0.4 - if(v > iphigh) { kh =(-1.f/(1.f-iphigh))*v + (1.f)/(1.f-iphigh); } //Low light ==> decrease action after iplow - else kh=aa0*v*v+bb0*v; - float kmgb; - if(g>45535.f || b > 45535.f || r > 45535.f) { - kmgb=max(r,g,b); - float cora=1.f/(45535.f-65535.f); - float corb=1.f-cora*45535.f; - float cor=kmgb*cora+corb; - kh *= cor; - /* best algo if necessary with non linear response...little differences and more time! - float aa=1.f /(pow(45535.f,0.65f) - pow(65535.f,0.65f)); - float bb=1.f-aa*pow(45535.f,0.65f); - float cor=aa*pow(kmbg,0.65f)+bb; - kh*=cor;*/ - } + if(krl > 0.f) { + g -= 20000.f * (RedL - 1.f) * ksatlow; + b -= 20000.f * (RedL - 1.f) * ksatlow; + } - float RedH, GreenH, BlueH; - float krh=rh/(rh+gh+bh); - float kgh=gh/(rh+gh+bh); - float kbh=bh/(rh+gh+bh); - if(SatHigh > 0.f) { - RedH = 1.f + (SatHigh*krh) * kh * rlh * balanH; //1.2 - if(krh > 0.f) { - r += 20000.f*(RedH-1.f); - r=CLIP(r); - } - g=CLIP(g); - b=CLIP(b); + g = CLIP(g); + b = CLIP(b); - GreenH = 1.f + (SatHigh*kgh) * kh * rlh * balanH; //1.2 - if(kgh> 0.f) { - g += 20000.f*(GreenH-1.f); - g=CLIP(g); - } - r=CLIP(r); - b=CLIP(b); - BlueH = 1.f + (SatHigh*kbh) * kh * rlh * balanH; //1.2 - if(kbh > 0.f) { - b += 20000.f*(BlueH-1.f); - b=CLIP(b); - } - r=CLIP(r); - g=CLIP(g); - } - float lumafter=0.299f*r + 0.587f*g + 0.114f*b; - float preserv=1.f; - if(preser==1) preserv=lumbefore/lumafter; + GreenL = 1.f + (SatLow * kgl) * kl * ksat * rlo * balanS; //0.4 - //float preserv=lumbefore/lumafter; - ro=r; - go=g; - bo=b; - ro*=preserv; - go*=preserv; - bo*=preserv; - ro=CLIP(ro); - go=CLIP(go); - bo=CLIP(bo); + if(kgl > 0.f) { + r -= 20000.f * (GreenL - 1.f) * ksatlow; + b -= 20000.f * (GreenL - 1.f) * ksatlow; + } + + r = CLIP(r); + b = CLIP(b); + + BlueL = 1.f + (SatLow * kbl) * kl * ksat * rlo * balanS; //0.4 + + if(kbl > 0.f) { + r -= 20000.f * (BlueL - 1.f) * ksatlow; + g -= 20000.f * (BlueL - 1.f) * ksatlow; + } + + r = CLIP(r); + g = CLIP(g); + } + + //high tones + float kh = 1.f; + kh = 1.f; + float aa0, bb0; + //fixed value of reducac ==0.4; + secondeg_begin (reducac, iphigh, aa0, bb0); + + if(v > iphigh) { + kh = (-1.f / (1.f - iphigh)) * v + (1.f) / (1.f - iphigh); //Low light ==> decrease action after iplow + } else { + kh = aa0 * v * v + bb0 * v; + } + + float kmgb; + + if(g > 45535.f || b > 45535.f || r > 45535.f) { + kmgb = max(r, g, b); + float cora = 1.f / (45535.f - 65535.f); + float corb = 1.f - cora * 45535.f; + float cor = kmgb * cora + corb; + kh *= cor; + /* best algo if necessary with non linear response...little differences and more time! + float aa=1.f /(pow(45535.f,0.65f) - pow(65535.f,0.65f)); + float bb=1.f-aa*pow(45535.f,0.65f); + float cor=aa*pow(kmbg,0.65f)+bb; + kh*=cor;*/ + } + + float RedH, GreenH, BlueH; + float krh = rh / (rh + gh + bh); + float kgh = gh / (rh + gh + bh); + float kbh = bh / (rh + gh + bh); + + if(SatHigh > 0.f) { + RedH = 1.f + (SatHigh * krh) * kh * rlh * balanH; //1.2 + + if(krh > 0.f) { + r += 20000.f * (RedH - 1.f); + r = CLIP(r); + } + + g = CLIP(g); + b = CLIP(b); + + GreenH = 1.f + (SatHigh * kgh) * kh * rlh * balanH; //1.2 + + if(kgh > 0.f) { + g += 20000.f * (GreenH - 1.f); + g = CLIP(g); + } + + r = CLIP(r); + b = CLIP(b); + BlueH = 1.f + (SatHigh * kbh) * kh * rlh * balanH; //1.2 + + if(kbh > 0.f) { + b += 20000.f * (BlueH - 1.f); + b = CLIP(b); + } + + r = CLIP(r); + g = CLIP(g); + } + + float lumafter = 0.299f * r + 0.587f * g + 0.114f * b; + float preserv = 1.f; + + if(preser == 1) { + preserv = lumbefore / lumafter; + } + + //float preserv=lumbefore/lumafter; + ro = r; + go = g; + bo = b; + ro *= preserv; + go *= preserv; + bo *= preserv; + ro = CLIP(ro); + go = CLIP(go); + bo = CLIP(bo); } /** * @brief color toning with interpolation in mode Lab -* @param r g b input values [0..65535] -* @param ro go bo output values [0..65535] +* @param r g b input values [0..65535] +* @param ro go bo output values [0..65535] * @param algm metchrom twoc - methods * @param ctColorCurve curve 500 colors * @param ctOpacityCurve curve standard 'ab' -* @param clToningcurve curve special 'ab' and 'a' -* @param cl2Toningcurve curve special 'b' +* @param clToningcurve curve special 'ab' and 'a' +* @param cl2Toningcurve curve special 'b' * @param iplow iphigh [0..1] luminance * @param wp wip 3x3 matrix and inverse conversion rgb XYZ **/ -void ImProcFunctions::labtoning (float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve,LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3] ) { - float realL; - float h,s,l; - Color::rgb2hsl(r,g,b,h,s,l); - float x2, y2, z2; - float xl, yl, zl; +void ImProcFunctions::labtoning (float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve, LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3] ) +{ + float realL; + float h, s, l; + Color::rgb2hsl(r, g, b, h, s, l); + float x2, y2, z2; + float xl, yl, zl; - if(twoc!=1) { - l = (Color::gammatab_13_2[ l*65535.f])/65535.f;//to compensate L from Lab - iphigh = (Color::gammatab_13_2[iphigh*65535.f])/65535.f; - iplow = (Color::gammatab_13_2[ iplow*65535.f])/65535.f; - } + if(twoc != 1) { + l = (Color::gammatab_13_2[ l * 65535.f]) / 65535.f; //to compensate L from Lab + iphigh = (Color::gammatab_13_2[iphigh * 65535.f]) / 65535.f; + iplow = (Color::gammatab_13_2[ iplow * 65535.f]) / 65535.f; + } - if(twoc==1) { - ctColorCurve.getVal(l, x2, y2, z2); - } - else { - ctColorCurve.getVal(iphigh, x2, y2, z2); - ctColorCurve.getVal(iplow, xl, yl, zl); - } - realL=l; + if(twoc == 1) { + ctColorCurve.getVal(l, x2, y2, z2); + } else { + ctColorCurve.getVal(iphigh, x2, y2, z2); + ctColorCurve.getVal(iplow, xl, yl, zl); + } + + realL = l; - //float opacity = ctOpacityCurve.lutOpacityCurve[l*500.f]; - //if(params->blackwhite.enabled){satLimit=80.f;satLimitOpacity=30.f;}//force BW + //float opacity = ctOpacityCurve.lutOpacityCurve[l*500.f]; + //if(params->blackwhite.enabled){satLimit=80.f;satLimitOpacity=30.f;}//force BW - // get the opacity and tweak it to preserve saturated colors - //float l_ = Color::gamma_srgb(l*65535.f)/65535.f; - float opacity; - opacity = (1.f-min(s/satLimit, 1.f)*(1.f-satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l*500.f]; - float opacity2 = (1.f-min(s/satLimit, 1.f)*(1.f-satLimitOpacity)); + // get the opacity and tweak it to preserve saturated colors + //float l_ = Color::gamma_srgb(l*65535.f)/65535.f; + float opacity; + opacity = (1.f - min(s / satLimit, 1.f) * (1.f - satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l * 500.f]; + float opacity2 = (1.f - min(s / satLimit, 1.f) * (1.f - satLimitOpacity)); - //float ro, go, bo; - bool chr = true; - bool lum = false; - float lm=l; - float chromat, luma; - if (clToningcurve[lm*65535.f]/(lm*65535.f) < 1.f) - {chromat = (clToningcurve[(lm)*65535.f]/(lm*65535.f))-1.f;} //special effect - else - {chromat = 1.f-SQR(SQR((lm*65535.f)/clToningcurve[(lm)*65535.f]));} //apply C=f(L) acts on 'a' and 'b' + //float ro, go, bo; + bool chr = true; + bool lum = false; + float lm = l; + float chromat, luma; - if (cl2Toningcurve[lm*65535.f]/(lm*65535.f) < 1.f) - {luma = (cl2Toningcurve[(lm)*65535.f]/(lm*65535.f))-1.f;} //special effect - else - {luma = 1.f-SQR(SQR((lm*65535.f)/(cl2Toningcurve[(lm)*65535.f])));} //apply C2=f(L) acts only on 'b' - int todo=1; - if (algm==1) Color::interpolateRGBColor(realL, iplow, iphigh, algm, opacity, twoc, metchrom, chr, lum, chromat, luma, r, g, b, xl, yl, zl, x2, y2, z2, todo, wp, wip, ro, go, bo); - else Color::interpolateRGBColor(realL, iplow, iphigh, algm, opacity2, twoc, metchrom, chr, lum, chromat, luma, r, g, b, xl, yl, zl, x2, y2, z2, todo, wp, wip, ro, go, bo); + if (clToningcurve[lm * 65535.f] / (lm * 65535.f) < 1.f) { + chromat = (clToningcurve[(lm) * 65535.f] / (lm * 65535.f)) - 1.f; //special effect + } else { + chromat = 1.f - SQR(SQR((lm * 65535.f) / clToningcurve[(lm) * 65535.f])); //apply C=f(L) acts on 'a' and 'b' + } + + if (cl2Toningcurve[lm * 65535.f] / (lm * 65535.f) < 1.f) { + luma = (cl2Toningcurve[(lm) * 65535.f] / (lm * 65535.f)) - 1.f; //special effect + } else { + luma = 1.f - SQR(SQR((lm * 65535.f) / (cl2Toningcurve[(lm) * 65535.f]))); //apply C2=f(L) acts only on 'b' + } + + int todo = 1; + + if (algm == 1) { + Color::interpolateRGBColor(realL, iplow, iphigh, algm, opacity, twoc, metchrom, chr, lum, chromat, luma, r, g, b, xl, yl, zl, x2, y2, z2, todo, wp, wip, ro, go, bo); + } else { + Color::interpolateRGBColor(realL, iplow, iphigh, algm, opacity2, twoc, metchrom, chr, lum, chromat, luma, r, g, b, xl, yl, zl, x2, y2, z2, todo, wp, wip, ro, go, bo); + } } -void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & curve) { +void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & curve) +{ int W = lold->W; int H = lold->H; -#pragma omp parallel for if (multiThread) - for (int i=0; iL[i][j]; - //if (Lin>0 && Lin<65535) - lnew->L[i][j] = curve[Lin]; - } + #pragma omp parallel for if (multiThread) + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + float Lin = lold->L[i][j]; + //if (Lin>0 && Lin<65535) + lnew->L[i][j] = curve[Lin]; + } } -SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve,LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) { - int W = lold->W; - int H = lold->H; - // lhskcurve.dump("lh_curve"); - //init Flatcurve for C=f(H) +SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve, LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) +{ + int W = lold->W; + int H = lold->H; + // lhskcurve.dump("lh_curve"); + //init Flatcurve for C=f(H) - // NOTE: We're getting all 3 pointers here, but this function may not need them all, so one could optimize this - Imagefloat* editImgFloat = NULL; - LabImage* editLab = NULL; - PlanarWhateverData* editWhatever = NULL; - EditUniqueID editID = EUID_None; - bool editPipette = false; - if (editBuffer) { - editID = editBuffer->getEditID(); - if (editID != EUID_None) { + // NOTE: We're getting all 3 pointers here, but this function may not need them all, so one could optimize this + Imagefloat* editImgFloat = NULL; + LabImage* editLab = NULL; + PlanarWhateverData* editWhatever = NULL; + EditUniqueID editID = EUID_None; + bool editPipette = false; + + if (editBuffer) { + editID = editBuffer->getEditID(); + + if (editID != EUID_None) { editPipette = true; - switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { - case (BT_IMAGEFLOAT): - editImgFloat = editBuffer->getImgFloatBuffer(); - break; - case (BT_LABIMAGE): - editLab = editBuffer->getLabBuffer(); - break; - case (BT_SINGLEPLANE_FLOAT): - editWhatever = editBuffer->getSinglePlaneBuffer(); - break; - } - } - } - FlatCurve* chCurve = NULL;// curve C=f(H) - bool chutili = false; - if (params->labCurve.chromaticity > -100) { - chCurve = new FlatCurve(params->labCurve.chcurve); - if (!chCurve || chCurve->isIdentity()) { - if (chCurve) { - delete chCurve; - chCurve = NULL; - } - }//do not use "Munsell" if Chcurve not used - else - chutili=true; - } - FlatCurve* lhCurve = NULL;//curve L=f(H) - bool lhutili = false; - if (params->labCurve.chromaticity > -100) { - lhCurve = new FlatCurve(params->labCurve.lhcurve); - if (!lhCurve || lhCurve->isIdentity()) { - if (lhCurve) { - delete lhCurve; - lhCurve = NULL; - } - }//do not use "Munsell" if Chcurve not used - else - lhutili=true; - } + switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) { + case (BT_IMAGEFLOAT): + editImgFloat = editBuffer->getImgFloatBuffer(); + break; - FlatCurve* hhCurve = NULL;//curve H=f(H) - bool hhutili = false; - if (params->labCurve.chromaticity > -100) { - hhCurve = new FlatCurve(params->labCurve.hhcurve); - if (!hhCurve || hhCurve->isIdentity()) { - if (hhCurve) { - delete hhCurve; - hhCurve = NULL; - } - }//do not use "Munsell" if Chcurve not used - else - hhutili = true; - } + case (BT_LABIMAGE): + editLab = editBuffer->getLabBuffer(); + break; - LUTf dCcurve; - LUTf dLcurve; + case (BT_SINGLEPLANE_FLOAT): + editWhatever = editBuffer->getSinglePlaneBuffer(); + break; + } + } + } - LUTu hist16Clad; - LUTu hist16Llad; + FlatCurve* chCurve = NULL;// curve C=f(H) + bool chutili = false; - //preparate for histograms CIECAM - if(pW!=1){//only with improccoordinator - dCcurve(48000,0); - dLcurve(65536,0); - hist16Clad(65536); - hist16Llad(65536); - float val; - for (int i=0; i<48000; i++) { //# 32768*1.414 approximation maxi for chroma - val = (double)i / 47999.0; - dCcurve[i] = CLIPD(val); - } - for (int i=0; i<65535; i++) { // a - val = (double)i / 65534.0; - dLcurve[i] = CLIPD(val); - } + if (params->labCurve.chromaticity > -100) { + chCurve = new FlatCurve(params->labCurve.chcurve); - hist16Clad.clear(); - hist16Llad.clear(); + if (!chCurve || chCurve->isIdentity()) { + if (chCurve) { + delete chCurve; + chCurve = NULL; + } + }//do not use "Munsell" if Chcurve not used + else { + chutili = true; + } + } + + FlatCurve* lhCurve = NULL;//curve L=f(H) + bool lhutili = false; + + if (params->labCurve.chromaticity > -100) { + lhCurve = new FlatCurve(params->labCurve.lhcurve); + + if (!lhCurve || lhCurve->isIdentity()) { + if (lhCurve) { + delete lhCurve; + lhCurve = NULL; + } + }//do not use "Munsell" if Chcurve not used + else { + lhutili = true; + } + } + + FlatCurve* hhCurve = NULL;//curve H=f(H) + bool hhutili = false; + + if (params->labCurve.chromaticity > -100) { + hhCurve = new FlatCurve(params->labCurve.hhcurve); + + if (!hhCurve || hhCurve->isIdentity()) { + if (hhCurve) { + delete hhCurve; + hhCurve = NULL; + } + }//do not use "Munsell" if Chcurve not used + else { + hhutili = true; + } + } + + LUTf dCcurve; + LUTf dLcurve; + + LUTu hist16Clad; + LUTu hist16Llad; + + //preparate for histograms CIECAM + if(pW != 1) { //only with improccoordinator + dCcurve(48000, 0); + dLcurve(65536, 0); + hist16Clad(65536); + hist16Llad(65536); + float val; + + for (int i = 0; i < 48000; i++) { //# 32768*1.414 approximation maxi for chroma + val = (double)i / 47999.0; + dCcurve[i] = CLIPD(val); + } + + for (int i = 0; i < 65535; i++) { // a + val = (double)i / 65534.0; + dLcurve[i] = CLIPD(val); + } + + hist16Clad.clear(); + hist16Llad.clear(); + + } - } #ifdef _DEBUG - MyTime t1e,t2e; - t1e.set(); - // init variables to display Munsell corrections - MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); + MyTime t1e, t2e; + t1e.set(); + // init variables to display Munsell corrections + MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); #endif - float adjustr=1.0f; + float adjustr = 1.0f; -// if(params->labCurve.avoidclip ){ - // parameter to adapt curve C=f(C) to gamut +// if(params->labCurve.avoidclip ){ + // parameter to adapt curve C=f(C) to gamut - if (params->icm.working=="ProPhoto") {adjustr = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170.. - else if (params->icm.working=="Adobe RGB") {adjustr = 1.8f;} - else if (params->icm.working=="sRGB") {adjustr = 2.0f;} - else if (params->icm.working=="WideGamut") {adjustr = 1.2f;} - else if (params->icm.working=="Beta RGB") {adjustr = 1.4f;} - else if (params->icm.working=="BestRGB") {adjustr = 1.4f;} - else if (params->icm.working=="BruceRGB") {adjustr = 1.8f;} + if (params->icm.working == "ProPhoto") { + adjustr = 1.2f; // 1.2 instead 1.0 because it's very rare to have C>170.. + } else if (params->icm.working == "Adobe RGB") { + adjustr = 1.8f; + } else if (params->icm.working == "sRGB") { + adjustr = 2.0f; + } else if (params->icm.working == "WideGamut") { + adjustr = 1.2f; + } else if (params->icm.working == "Beta RGB") { + adjustr = 1.4f; + } else if (params->icm.working == "BestRGB") { + adjustr = 1.4f; + } else if (params->icm.working == "BruceRGB") { + adjustr = 1.8f; + } - // reference to the params structure has to be done outside of the parallelization to avoid CPU cache problem - const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated - const int chromaticity = params->labCurve.chromaticity; - const float chromapro = (chromaticity + 100.0f)/100.0f; - const bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled; - const bool bwToning = params->labCurve.chromaticity ==- 100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly; - //if(chromaticity==-100) chromaticity==-99; - const bool LCredsk = params->labCurve.lcredsk; - const bool ccut = ccutili; - const bool clut = clcutili; - const double rstprotection = 100.-params->labCurve.rstprotection; // Red and Skin Tones Protection - // avoid color shift is disabled when bwToning is activated and enabled if gamut is true in colorappearanace - const bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ; - const float protectRed = (float)settings->protectred; - const double protectRedH = settings->protectredh; - float protect_red,protect_redh; + // reference to the params structure has to be done outside of the parallelization to avoid CPU cache problem + const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated + const int chromaticity = params->labCurve.chromaticity; + const float chromapro = (chromaticity + 100.0f) / 100.0f; + const bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled; + const bool bwToning = params->labCurve.chromaticity == - 100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly; + //if(chromaticity==-100) chromaticity==-99; + const bool LCredsk = params->labCurve.lcredsk; + const bool ccut = ccutili; + const bool clut = clcutili; + const double rstprotection = 100. - params->labCurve.rstprotection; // Red and Skin Tones Protection + // avoid color shift is disabled when bwToning is activated and enabled if gamut is true in colorappearanace + const bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ; + const float protectRed = (float)settings->protectred; + const double protectRedH = settings->protectredh; + float protect_red, protect_redh; protect_red = protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160 - if(protect_red < 20.0f) protect_red=20.0; // avoid too low value - if(protect_red > 180.0f) protect_red=180.0; // avoid too high value - protect_redh=float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 - if(protect_redh<0.1f) protect_redh=0.1f;//avoid divide by 0 and negatives values - if(protect_redh>1.0f) protect_redh=1.0f;//avoid too big values + + if(protect_red < 20.0f) { + protect_red = 20.0; // avoid too low value + } + + if(protect_red > 180.0f) { + protect_red = 180.0; // avoid too high value + } + + protect_redh = float(protectRedH); //default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 + + if(protect_redh < 0.1f) { + protect_redh = 0.1f; //avoid divide by 0 and negatives values + } + + if(protect_redh > 1.0f) { + protect_redh = 1.0f; //avoid too big values + } + float protect_redhcur = protectRedH;//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1 - if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values:minimal protection for transition - if(protect_redhcur>3.5f) protect_redhcur=3.5f;//avoid too big values + + if(protect_redhcur < 0.1f) { + protect_redhcur = 0.1f; //avoid divide by 0 and negatives values:minimal protection for transition + } + + if(protect_redhcur > 3.5f) { + protect_redhcur = 3.5f; //avoid too big values + } //increase saturation after denoise : ...approximation - float factnoise=1.f; + float factnoise = 1.f; + if(params->dirpyrDenoise.enabled) { - factnoise=(1.f+params->dirpyrDenoise.chroma/500.f);//levels=5 -// if(yyyy) factnoise=(1.f+params->dirpyrDenoise.chroma/100.f);//levels=7 + factnoise = (1.f + params->dirpyrDenoise.chroma / 500.f); //levels=5 +// if(yyyy) factnoise=(1.f+params->dirpyrDenoise.chroma/100.f);//levels=7 } - const float scaleConst = 100.0f/100.1f; - - const bool gamutLch = settings->gamutLch; - const float amountchroma = (float) settings->amchroma; + const float scaleConst = 100.0f / 100.1f; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; - - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); - double wp[3][3] = { - {wprof[0][0],wprof[0][1],wprof[0][2]}, - {wprof[1][0],wprof[1][1],wprof[1][2]}, - {wprof[2][0],wprof[2][1],wprof[2][2]}}; + + const bool gamutLch = settings->gamutLch; + const float amountchroma = (float) settings->amchroma; + + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; + + TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + double wp[3][3] = { + {wprof[0][0], wprof[0][1], wprof[0][2]}, + {wprof[1][0], wprof[1][1], wprof[1][2]}, + {wprof[2][0], wprof[2][1], wprof[2][2]} + }; #ifdef _DEBUG -#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, MunsDebugInfo, pW) if (multiThread) + #pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, MunsDebugInfo, pW) if (multiThread) #else -#pragma omp parallel if (multiThread) + #pragma omp parallel if (multiThread) #endif -{ + { #ifdef __SSE2__ float HHBuffer[W] ALIGNED16; float CCBuffer[W] ALIGNED16; #endif -#pragma omp for schedule(dynamic, 16) - for (int i=0; iL[i],lold->a[i], lold->b[i], W, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, wip, multiThread); - } + #pragma omp for schedule(dynamic, 16) + + for (int i = 0; i < H; i++) { + if (avoidColorShift) + + // only if user activate Lab adjustments + if(autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity) { + Color::LabGamutMunsell(lold->L[i], lold->a[i], lold->b[i], W, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, wip, multiThread); + } + #ifdef __SSE2__ - // precalculate some values using SSE - if(bwToning || (!autili && !butili)) { - __m128 c327d68v = _mm_set1_ps(327.68f); - __m128 av,bv; - int k; - for (k=0; ka[i][k]); - bv = LVFU(lold->b[i][k]); - STVF(HHBuffer[k],xatan2f(bv,av)); - STVF(CCBuffer[k],_mm_sqrt_ps(SQRV(av)+SQRV(bv))/c327d68v); + + // precalculate some values using SSE + if(bwToning || (!autili && !butili)) { + __m128 c327d68v = _mm_set1_ps(327.68f); + __m128 av, bv; + int k; + + for (k = 0; k < W - 3; k += 4) { + av = LVFU(lold->a[i][k]); + bv = LVFU(lold->b[i][k]); + STVF(HHBuffer[k], xatan2f(bv, av)); + STVF(CCBuffer[k], _mm_sqrt_ps(SQRV(av) + SQRV(bv)) / c327d68v); + } + + for(; k < W; k++) { + HHBuffer[k] = xatan2f(lold->b[i][k], lold->a[i][k]); + CCBuffer[k] = sqrt(SQR(lold->a[i][k]) + SQR(lold->b[i][k])) / 327.68f; + } } - for(;kb[i][k],lold->a[i][k]); - CCBuffer[k] = sqrt(SQR(lold->a[i][k]) + SQR(lold->b[i][k]))/327.68f; - } - } + #endif // __SSE2__ - for (int j=0; jL[i][j]; - float LL=Lin/327.68f; - float CC; - float HH; - float Chprov; - float Chprov1; - float memChprov; - float2 sincosval; - if(bwToning) { // this values will be also set when bwToning is false some lines down + + for (int j = 0; j < W; j++) { + const float Lin = lold->L[i][j]; + float LL = Lin / 327.68f; + float CC; + float HH; + float Chprov; + float Chprov1; + float memChprov; + float2 sincosval; + + if(bwToning) { // this values will be also set when bwToning is false some lines down #ifdef __SSE2__ - // use precalculated values from above - HH = HHBuffer[j]; - CC = CCBuffer[j]; -#else - HH=xatan2f(lold->b[i][j],lold->a[i][j]); - CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f; -#endif - // According to mathematical laws we can get the sin and cos of HH by simple operations - if(CC==0.0f) { - sincosval.y = 1.0f; - sincosval.x = 0.0f; - } else { - sincosval.y = lold->a[i][j]/(CC*327.68f); - sincosval.x = lold->b[i][j]/(CC*327.68f); - } - - Chprov=CC; - Chprov1=CC; - memChprov=Chprov; - } - - if (editPipette && editID == EUID_Lab_LCurve) - editWhatever->v(i,j) = LIM01(Lin/32768.0f);// Lab L pipette - - lnew->L[i][j] = curve[Lin]; - - float Lprov1=(lnew->L[i][j])/327.68f; - - if(editPipette) { - if (editID == EUID_Lab_aCurve) { // Lab a pipette - float chromapipa =lold->a[i][j]+(32768.f*1.28f); - editWhatever->v(i,j) = LIM01((chromapipa)/(65536.f*1.28f)); - } else if (editID == EUID_Lab_bCurve) { //Lab b pipette - float chromapipb =lold->b[i][j]+(32768.f*1.28f); - editWhatever->v(i,j) = LIM01((chromapipb)/(65536.f*1.28f)); - } - } - - float atmp, btmp; - - atmp = lold->a[i][j]; - if(autili) - atmp = acurve[atmp+32768.0f]-32768.0f;// curves Lab a - - btmp = lold->b[i][j]; - if(butili) - btmp = bcurve[btmp+32768.0f]-32768.0f;// curves Lab b - - if(!bwToning) { //take into account modification of 'a' and 'b' -#ifdef __SSE2__ - if(!autili && !butili) { // use precalculated values from above HH = HHBuffer[j]; CC = CCBuffer[j]; - } else { - CC = sqrt(SQR(atmp) + SQR(btmp))/327.68f; - HH = xatan2f(btmp,atmp); - } #else - CC=sqrt(SQR(atmp) + SQR(btmp))/327.68f; - HH=xatan2f(btmp,atmp); + HH = xatan2f(lold->b[i][j], lold->a[i][j]); + CC = sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j])) / 327.68f; #endif - // According to mathematical laws we can get the sin and cos of HH by simple operations - //float2 sincosval; - if(CC == 0.f) { - sincosval.y = 1.f; - sincosval.x = 0.f; - } else { - sincosval.y = atmp/(CC*327.68f); - sincosval.x = btmp/(CC*327.68f); - } - Chprov=CC; - Chprov1=CC; - memChprov=Chprov; - } // now new values of lold with 'a' and 'b' - if(editPipette) - if (editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve) {//H pipette - float valpar =Color::huelab_to_huehsv2(HH); - editWhatever->v(i,j) = valpar; - } - - if (lhutili) { // L=f(H) - const float ClipLevel = 65535.f; - float l_r;//Luminance Lab in 0..1 - l_r = Lprov1/100.f; - { - float khue=1.9f;//in reserve in case of! - float valparam = float((lhCurve->getVal(Color::huelab_to_huehsv2(HH))-0.5f));//get l_r=f(H) - float valparamneg; - valparamneg=valparam; - float kcc=(CC/amountchroma);//take Chroma into account...40 "middle low" of chromaticity (arbitrary and simple), one can imagine other algorithme - //reduce action for low chroma and increase action for high chroma - valparam *= 2.f*kcc; - valparamneg*= kcc;//slightly different for negative - if(valparam > 0.f) - l_r = (1.f-valparam)*l_r+ valparam*(1.f-SQR(((SQR(1.f-min(l_r,1.0f)))))); - else - //for negative - l_r *= (1.f+khue*valparamneg); - } - - Lprov1=l_r*100.f; - - float Chprov2 = sqrt(SQR(atmp)+SQR(btmp))/327.68f; - //Gamut control especialy fot negative values slightly different of gamutlchonly - bool inRGB; - do { - inRGB=true; - float aprov1=Chprov2*sincosval.y; - float bprov1=Chprov2*sincosval.x; - - float fy = (0.00862069f *Lprov1 )+ 0.137932f; - float fx = (0.002f * aprov1) + fy; - float fz = fy - (0.005f * bprov1); - - float x_ = 65535.0f * Color::f2xyz(fx)*Color::D50x; - float z_ = 65535.0f * Color::f2xyz(fz)*Color::D50z; - float y_=(Lprov1>Color::epskap) ? 65535.0*fy*fy*fy : 65535.0*Lprov1/Color::kappa; - float R,G,B; - Color::xyz2rgb(x_,y_,z_,R,G,B,wip); - if (R<0.0f || G<0.0f || B<0.0f) { - if(Lprov1 < 0.1f) Lprov1=0.1f; - Chprov2*=0.95f; - inRGB=false; - } - else if (!highlight && (R>ClipLevel || G>ClipLevel || B>ClipLevel)) { - if (Lprov1 > 99.98f) Lprov1 = 99.98f; - Chprov2 *= 0.95f; - inRGB = false; - } - } - while (!inRGB); - - atmp=327.68f*Chprov2*sincosval.y; - btmp=327.68f*Chprov2*sincosval.x; - } - -// calculate C=f(H) - if (chutili) { - double hr = Color::huelab_to_huehsv2(HH); - float chparam = float((chCurve->getVal(hr)-0.5f) * 2.0f);//get C=f(H) - float chromaChfactor=1.0f+chparam; - atmp *= chromaChfactor;//apply C=f(H) - btmp *= chromaChfactor; - } - - if (hhutili) { // H=f(H) - //hue Lab in -PI +PI - float valparam = float((hhCurve->getVal(Color::huelab_to_huehsv2(HH))-0.5f) * 1.7f) +HH;//get H=f(H) 1.7 optimisation ! - HH = valparam; - sincosval = xsincosf(HH); - } - - if(!bwToning){ - float factorskin, factorsat, factorskinext; - if(chromapro > 1.f) { - float scale = scaleConst;//reduction in normal zone - float scaleext = 1.f;//reduction in transition zone - Color::scalered ( rstprotection, chromapro, 0.0, HH, protect_redh, scale, scaleext);//1.0 - float interm = (chromapro - 1.f); - factorskin = 1.f + (interm*scale); - factorskinext = 1.f+ (interm*scaleext); - } else { - factorskin = chromapro ; // +(chromapro)*scale; - factorskinext = chromapro ;// +(chromapro)*scaleext; - } - factorsat = chromapro * factnoise; - - //simulate very approximative gamut f(L) : with pyramid transition - float dred /*=55.f*/;//C red value limit - if (Lprov1<25.f) dred = 40.f; - else if(Lprov1<30.f) dred = 3.f * Lprov1 -35.f; - else if(Lprov1<70.f) dred = 55.f; - else if(Lprov1<75.f) dred = -3.f * Lprov1 + 265.f; - else dred = 40.f; - // end pyramid - - // Test if chroma is in the normal range first - Color::transitred ( HH, Chprov1, dred, factorskin, protect_red, factorskinext, protect_redh, factorsat, factorsat); - atmp *= factorsat; - btmp *= factorsat; - - if (editPipette && editID == EUID_Lab_CLCurve) - editWhatever->v(i,j) = LIM01(LL/100.f);// Lab C=f(L) pipette - - if (clut) { // begin C=f(L) - float factorskin,factorsat,factor,factorskinext,interm; - float chromaCfactor=(clcurve[LL*655.35f])/(LL*655.35f);//apply C=f(L) - float curf=0.7f;//empirical coeff because curve is more progressive - float scale = 100.0f/100.1f;//reduction in normal zone for curve C - float scaleext=1.0f;//reduction in transition zone for curve C - float protect_redcur,protect_redhcur;//perhaps the same value than protect_red and protect_redh - float deltaHH;//HH value transition for C curve - protect_redcur=curf*protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive - if(protect_redcur < 20.0f) protect_redcur=20.0; // avoid too low value - if(protect_redcur > 180.0f) protect_redcur=180.0; // avoid too high value - protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive - if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values - if(protect_redhcur>1.0f) protect_redhcur=1.0f;//avoid too big values - - deltaHH=protect_redhcur;//transition hue - if(chromaCfactor>0.0) Color::scalered ( rstprotection, chromaCfactor, 0.0, HH, deltaHH, scale, scaleext);//1.0 - if(chromaCfactor>1.0) { - interm=(chromaCfactor-1.0f)*100.0f; - factorskin= 1.0f+(interm*scale)/100.0f; - factorskinext=1.0f+(interm*scaleext)/100.0f; - } - else { - factorskin= chromaCfactor; // +(1.0f-chromaCfactor)*scale; - factorskinext= chromaCfactor ; //+(1.0f-chromaCfactor)*scaleext; - } - - factorsat=chromaCfactor; - factor=factorsat; - Color::transitred ( HH, Chprov1, dred, factorskin, protect_redcur, factorskinext, deltaHH, factorsat, factor); - atmp *= factor; - btmp *= factor; - } - // end C=f(L) - // if (editID == EUID_Lab_CLCurve) - // editWhatever->v(i,j) = LIM01(Lprov2/100.f);// Lab C=f(L) pipette - - // I have placed C=f(C) after all C treatments to assure maximum amplitude of "C" - if (editPipette && editID == EUID_Lab_CCurve){ - float chromapip = sqrt(SQR(atmp)+SQR(btmp)+0.001f); - editWhatever->v(i,j) = LIM01((chromapip)/(48000.f));}//Lab C=f(C) pipette - - if (ccut) { - float factorskin,factorsat,factor,factorskinext,interm; - float chroma = sqrt(SQR(atmp)+SQR(btmp)+0.001f); - float chromaCfactor=(satcurve[chroma*adjustr])/(chroma*adjustr);//apply C=f(C) - float curf=0.7f;//empirical coeff because curve is more progressive - float scale = 100.0f/100.1f;//reduction in normal zone for curve CC - float scaleext=1.0f;//reduction in transition zone for curve CC - float protect_redcur,protect_redhcur;//perhaps the same value than protect_red and protect_redh - float deltaHH;//HH value transition for CC curve - protect_redcur=curf*protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive - if(protect_redcur < 20.0f) protect_redcur=20.0; // avoid too low value - if(protect_redcur > 180.0f) protect_redcur=180.0; // avoid too high value - protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive - if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values - if(protect_redhcur>1.0f) protect_redhcur=1.0f;//avoid too big values - - deltaHH=protect_redhcur;//transition hue - if(chromaCfactor>0.0) Color::scalered ( rstprotection, chromaCfactor, 0.0, HH, deltaHH, scale, scaleext);//1.0 - if(chromaCfactor>1.0) { - interm=(chromaCfactor-1.0f)*100.0f; - factorskin= 1.0f+(interm*scale)/100.0f; - factorskinext=1.0f+(interm*scaleext)/100.0f; - } - else { - //factorskin= chromaCfactor*scale; - //factorskinext=chromaCfactor*scaleext; - factorskin= chromaCfactor; // +(1.0f-chromaCfactor)*scale; - factorskinext= chromaCfactor ; //+(1.0f-chromaCfactor)*scaleext; - - } - - factorsat=chromaCfactor; - factor=factorsat; - Color::transitred ( HH, Chprov1, dred, factorskin, protect_redcur, factorskinext, deltaHH, factorsat, factor); - atmp *= factor; - btmp *= factor; - } - } - // end chroma C=f(C) - - //update histogram C - if(pW!=1){//only with improccoordinator - int posp=CLIP((int)sqrt((atmp*atmp + btmp*btmp))); - hist16Clad[posp]++; - } - - if (editPipette && editID == EUID_Lab_LCCurve){ - float chromapiplc = sqrt(SQR(atmp)+SQR(btmp)+0.001f); - editWhatever->v(i,j) = LIM01((chromapiplc)/(48000.f)); - }//Lab L=f(C) pipette - - - if (cclutili && !bwToning) { //apply curve L=f(C) for skin and rd...but also for extended color ==> near green and blue (see 'curf') - - const float xx=0.25f;//soft : between 0.2 and 0.4 - float skdeltaHH; - - skdeltaHH=protect_redhcur;//transition hue - - float skbeg=-0.05f;//begin hue skin - float skend=1.60f;//end hue skin - const float chrmin=50.0f;//to avoid artifact, because L curve is not a real curve for luminance - float aa,bb; - float zz=0.0f; - float yy=0.0f; - if(Chprov1 < chrmin) - yy=SQR(Chprov1/chrmin)*xx; - else - yy=xx;//avoid artifact for low C - if(!LCredsk) { - skbeg=-3.1415; - skend=3.14159; - skdeltaHH=0.001f; - } - if(HH>skbeg && HH < skend ) { - zz=yy; - } else if(HH>skbeg-skdeltaHH && HH<=skbeg) { //transition - aa=yy/skdeltaHH; - bb=-aa*(skbeg-skdeltaHH); - zz=aa*HH+bb; - } else if(HH>=skend && HH < skend+skdeltaHH) { //transition - aa=-yy/skdeltaHH; - bb=-aa*(skend+skdeltaHH); - zz=aa*HH+bb; - } - - float chroma=sqrt(SQR(atmp)+SQR(btmp)+0.001f); - float Lc = (lhskcurve[chroma*adjustr])/(chroma*adjustr);//apply L=f(C) - Lc=(Lc-1.0f)*zz+1.0f;//reduct action - Lprov1*=Lc;//adjust luminance - } - //update histo LC - if(pW!=1){//only with improccoordinator - int posl=CLIP((int(Lprov1*327.68f))); - hist16Llad[posl]++; - } - - Chprov1 = sqrt(SQR(atmp)+SQR(btmp))/327.68f; - - // labCurve.bwtoning option allows to decouple modulation of a & b curves by saturation - // with bwtoning enabled the net effect of a & b curves is visible - if (bwToning) { - atmp -= lold->a[i][j]; - btmp -= lold->b[i][j]; - } - - if (avoidColorShift) { - //gamutmap Lch ==> preserve Hue,but a little slower than gamutbdy for high values...and little faster for low values - if(gamutLch) { - float R,G,B; - -#ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH, sincosval, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); -#else - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH, sincosval,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); -#endif - lnew->L[i][j]=Lprov1*327.68f; -// float2 sincosval = xsincosf(HH); - lnew->a[i][j]=327.68f*Chprov1*sincosval.y; - lnew->b[i][j]=327.68f*Chprov1*sincosval.x; - } else { - //use gamutbdy - //Luv limiter - float Y,u,v; - Color::Lab2Yuv(lnew->L[i][j],atmp,btmp,Y,u,v); - //Yuv2Lab includes gamut restriction map - Color::Yuv2Lab(Y,u,v,lnew->L[i][j],lnew->a[i][j],lnew->b[i][j], wp); - } - - if (utili || autili || butili || ccut || clut || cclutili || chutili || lhutili || hhutili || clcutili || chromaticity) { - float correctionHue=0.f; // Munsell's correction - float correctlum=0.f; - - Lprov1=lnew->L[i][j]/327.68f; - Chprov=sqrt(SQR(lnew->a[i][j])+ SQR(lnew->b[i][j]))/327.68f; - -#ifdef _DEBUG - Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,LL,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo); -#else - Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,LL,HH,Chprov,memChprov,correctionHue,correctlum); -#endif - if(correctionHue != 0.f || correctlum != 0.f) { - if(fabs(correctionHue) < 0.015f) - HH+=correctlum; // correct only if correct Munsell chroma very little. - /* if((HH>0.0f && HH < 1.6f) && memChprov < 70.0f) HH+=correctlum;//skin correct - else if(fabs(correctionHue) < 0.3f) HH+=0.08f*correctlum; - else if(fabs(correctionHue) < 0.2f) HH+=0.25f*correctlum; - else if(fabs(correctionHue) < 0.1f) HH+=0.35f*correctlum; - else if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little. - */ - sincosval = xsincosf(HH+correctionHue); + // According to mathematical laws we can get the sin and cos of HH by simple operations + if(CC == 0.0f) { + sincosval.y = 1.0f; + sincosval.x = 0.0f; + } else { + sincosval.y = lold->a[i][j] / (CC * 327.68f); + sincosval.x = lold->b[i][j] / (CC * 327.68f); } - lnew->a[i][j]=327.68f*Chprov*sincosval.y;// apply Munsell - lnew->b[i][j]=327.68f*Chprov*sincosval.x; - } - } else { -// if(Lprov1 > maxlp) maxlp=Lprov1; -// if(Lprov1 < minlp) minlp=Lprov1; - if(!bwToning){ - lnew->L[i][j]=Lprov1*327.68f; -// float2 sincosval = xsincosf(HH); - lnew->a[i][j]=327.68f*Chprov1*sincosval.y; - lnew->b[i][j]=327.68f*Chprov1*sincosval.x; - } - else { - //Luv limiter only - lnew->a[i][j] = atmp; - lnew->b[i][j] = btmp; - } - } - } - } -} // end of parallelization + + Chprov = CC; + Chprov1 = CC; + memChprov = Chprov; + } + + if (editPipette && editID == EUID_Lab_LCurve) { + editWhatever->v(i, j) = LIM01(Lin / 32768.0f); // Lab L pipette + } + + lnew->L[i][j] = curve[Lin]; + + float Lprov1 = (lnew->L[i][j]) / 327.68f; + + if(editPipette) { + if (editID == EUID_Lab_aCurve) { // Lab a pipette + float chromapipa = lold->a[i][j] + (32768.f * 1.28f); + editWhatever->v(i, j) = LIM01((chromapipa) / (65536.f * 1.28f)); + } else if (editID == EUID_Lab_bCurve) { //Lab b pipette + float chromapipb = lold->b[i][j] + (32768.f * 1.28f); + editWhatever->v(i, j) = LIM01((chromapipb) / (65536.f * 1.28f)); + } + } + + float atmp, btmp; + + atmp = lold->a[i][j]; + + if(autili) { + atmp = acurve[atmp + 32768.0f] - 32768.0f; // curves Lab a + } + + btmp = lold->b[i][j]; + + if(butili) { + btmp = bcurve[btmp + 32768.0f] - 32768.0f; // curves Lab b + } + + if(!bwToning) { //take into account modification of 'a' and 'b' +#ifdef __SSE2__ + if(!autili && !butili) { + // use precalculated values from above + HH = HHBuffer[j]; + CC = CCBuffer[j]; + } else { + CC = sqrt(SQR(atmp) + SQR(btmp)) / 327.68f; + HH = xatan2f(btmp, atmp); + } + +#else + CC = sqrt(SQR(atmp) + SQR(btmp)) / 327.68f; + HH = xatan2f(btmp, atmp); +#endif + + // According to mathematical laws we can get the sin and cos of HH by simple operations + //float2 sincosval; + if(CC == 0.f) { + sincosval.y = 1.f; + sincosval.x = 0.f; + } else { + sincosval.y = atmp / (CC * 327.68f); + sincosval.x = btmp / (CC * 327.68f); + } + + Chprov = CC; + Chprov1 = CC; + memChprov = Chprov; + } // now new values of lold with 'a' and 'b' + + if(editPipette) + if (editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve) {//H pipette + float valpar = Color::huelab_to_huehsv2(HH); + editWhatever->v(i, j) = valpar; + } + + if (lhutili) { // L=f(H) + const float ClipLevel = 65535.f; + float l_r;//Luminance Lab in 0..1 + l_r = Lprov1 / 100.f; + { + float khue = 1.9f; //in reserve in case of! + float valparam = float((lhCurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f)); //get l_r=f(H) + float valparamneg; + valparamneg = valparam; + float kcc = (CC / amountchroma); //take Chroma into account...40 "middle low" of chromaticity (arbitrary and simple), one can imagine other algorithme + //reduce action for low chroma and increase action for high chroma + valparam *= 2.f * kcc; + valparamneg *= kcc; //slightly different for negative + + if(valparam > 0.f) { + l_r = (1.f - valparam) * l_r + valparam * (1.f - SQR(((SQR(1.f - min(l_r, 1.0f)))))); + } else + //for negative + { + l_r *= (1.f + khue * valparamneg); + } + } + + Lprov1 = l_r * 100.f; + + float Chprov2 = sqrt(SQR(atmp) + SQR(btmp)) / 327.68f; + //Gamut control especialy fot negative values slightly different of gamutlchonly + bool inRGB; + + do { + inRGB = true; + float aprov1 = Chprov2 * sincosval.y; + float bprov1 = Chprov2 * sincosval.x; + + float fy = (0.00862069f * Lprov1 ) + 0.137932f; + float fx = (0.002f * aprov1) + fy; + float fz = fy - (0.005f * bprov1); + + float x_ = 65535.0f * Color::f2xyz(fx) * Color::D50x; + float z_ = 65535.0f * Color::f2xyz(fz) * Color::D50z; + float y_ = (Lprov1 > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * Lprov1 / Color::kappa; + float R, G, B; + Color::xyz2rgb(x_, y_, z_, R, G, B, wip); + + if (R < 0.0f || G < 0.0f || B < 0.0f) { + if(Lprov1 < 0.1f) { + Lprov1 = 0.1f; + } + + Chprov2 *= 0.95f; + inRGB = false; + } else if (!highlight && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) { + if (Lprov1 > 99.98f) { + Lprov1 = 99.98f; + } + + Chprov2 *= 0.95f; + inRGB = false; + } + } while (!inRGB); + + atmp = 327.68f * Chprov2 * sincosval.y; + btmp = 327.68f * Chprov2 * sincosval.x; + } + +// calculate C=f(H) + if (chutili) { + double hr = Color::huelab_to_huehsv2(HH); + float chparam = float((chCurve->getVal(hr) - 0.5f) * 2.0f); //get C=f(H) + float chromaChfactor = 1.0f + chparam; + atmp *= chromaChfactor;//apply C=f(H) + btmp *= chromaChfactor; + } + + if (hhutili) { // H=f(H) + //hue Lab in -PI +PI + float valparam = float((hhCurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f) * 1.7f) + HH; //get H=f(H) 1.7 optimisation ! + HH = valparam; + sincosval = xsincosf(HH); + } + + if(!bwToning) { + float factorskin, factorsat, factorskinext; + + if(chromapro > 1.f) { + float scale = scaleConst;//reduction in normal zone + float scaleext = 1.f;//reduction in transition zone + Color::scalered ( rstprotection, chromapro, 0.0, HH, protect_redh, scale, scaleext);//1.0 + float interm = (chromapro - 1.f); + factorskin = 1.f + (interm * scale); + factorskinext = 1.f + (interm * scaleext); + } else { + factorskin = chromapro ; // +(chromapro)*scale; + factorskinext = chromapro ;// +(chromapro)*scaleext; + } + + factorsat = chromapro * factnoise; + + //simulate very approximative gamut f(L) : with pyramid transition + float dred /*=55.f*/;//C red value limit + + if (Lprov1 < 25.f) { + dred = 40.f; + } else if(Lprov1 < 30.f) { + dred = 3.f * Lprov1 - 35.f; + } else if(Lprov1 < 70.f) { + dred = 55.f; + } else if(Lprov1 < 75.f) { + dred = -3.f * Lprov1 + 265.f; + } else { + dred = 40.f; + } + + // end pyramid + + // Test if chroma is in the normal range first + Color::transitred ( HH, Chprov1, dred, factorskin, protect_red, factorskinext, protect_redh, factorsat, factorsat); + atmp *= factorsat; + btmp *= factorsat; + + if (editPipette && editID == EUID_Lab_CLCurve) { + editWhatever->v(i, j) = LIM01(LL / 100.f); // Lab C=f(L) pipette + } + + if (clut) { // begin C=f(L) + float factorskin, factorsat, factor, factorskinext, interm; + float chromaCfactor = (clcurve[LL * 655.35f]) / (LL * 655.35f); //apply C=f(L) + float curf = 0.7f; //empirical coeff because curve is more progressive + float scale = 100.0f / 100.1f; //reduction in normal zone for curve C + float scaleext = 1.0f; //reduction in transition zone for curve C + float protect_redcur, protect_redhcur; //perhaps the same value than protect_red and protect_redh + float deltaHH;//HH value transition for C curve + protect_redcur = curf * protectRed; //default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive + + if(protect_redcur < 20.0f) { + protect_redcur = 20.0; // avoid too low value + } + + if(protect_redcur > 180.0f) { + protect_redcur = 180.0; // avoid too high value + } + + protect_redhcur = curf * float(protectRedH); //default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive + + if(protect_redhcur < 0.1f) { + protect_redhcur = 0.1f; //avoid divide by 0 and negatives values + } + + if(protect_redhcur > 1.0f) { + protect_redhcur = 1.0f; //avoid too big values + } + + deltaHH = protect_redhcur; //transition hue + + if(chromaCfactor > 0.0) { + Color::scalered ( rstprotection, chromaCfactor, 0.0, HH, deltaHH, scale, scaleext); //1.0 + } + + if(chromaCfactor > 1.0) { + interm = (chromaCfactor - 1.0f) * 100.0f; + factorskin = 1.0f + (interm * scale) / 100.0f; + factorskinext = 1.0f + (interm * scaleext) / 100.0f; + } else { + factorskin = chromaCfactor; // +(1.0f-chromaCfactor)*scale; + factorskinext = chromaCfactor ; //+(1.0f-chromaCfactor)*scaleext; + } + + factorsat = chromaCfactor; + factor = factorsat; + Color::transitred ( HH, Chprov1, dred, factorskin, protect_redcur, factorskinext, deltaHH, factorsat, factor); + atmp *= factor; + btmp *= factor; + } + + // end C=f(L) + // if (editID == EUID_Lab_CLCurve) + // editWhatever->v(i,j) = LIM01(Lprov2/100.f);// Lab C=f(L) pipette + + // I have placed C=f(C) after all C treatments to assure maximum amplitude of "C" + if (editPipette && editID == EUID_Lab_CCurve) { + float chromapip = sqrt(SQR(atmp) + SQR(btmp) + 0.001f); + editWhatever->v(i, j) = LIM01((chromapip) / (48000.f)); + }//Lab C=f(C) pipette + + if (ccut) { + float factorskin, factorsat, factor, factorskinext, interm; + float chroma = sqrt(SQR(atmp) + SQR(btmp) + 0.001f); + float chromaCfactor = (satcurve[chroma * adjustr]) / (chroma * adjustr); //apply C=f(C) + float curf = 0.7f; //empirical coeff because curve is more progressive + float scale = 100.0f / 100.1f; //reduction in normal zone for curve CC + float scaleext = 1.0f; //reduction in transition zone for curve CC + float protect_redcur, protect_redhcur; //perhaps the same value than protect_red and protect_redh + float deltaHH;//HH value transition for CC curve + protect_redcur = curf * protectRed; //default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive + + if(protect_redcur < 20.0f) { + protect_redcur = 20.0; // avoid too low value + } + + if(protect_redcur > 180.0f) { + protect_redcur = 180.0; // avoid too high value + } + + protect_redhcur = curf * float(protectRedH); //default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive + + if(protect_redhcur < 0.1f) { + protect_redhcur = 0.1f; //avoid divide by 0 and negatives values + } + + if(protect_redhcur > 1.0f) { + protect_redhcur = 1.0f; //avoid too big values + } + + deltaHH = protect_redhcur; //transition hue + + if(chromaCfactor > 0.0) { + Color::scalered ( rstprotection, chromaCfactor, 0.0, HH, deltaHH, scale, scaleext); //1.0 + } + + if(chromaCfactor > 1.0) { + interm = (chromaCfactor - 1.0f) * 100.0f; + factorskin = 1.0f + (interm * scale) / 100.0f; + factorskinext = 1.0f + (interm * scaleext) / 100.0f; + } else { + //factorskin= chromaCfactor*scale; + //factorskinext=chromaCfactor*scaleext; + factorskin = chromaCfactor; // +(1.0f-chromaCfactor)*scale; + factorskinext = chromaCfactor ; //+(1.0f-chromaCfactor)*scaleext; + + } + + factorsat = chromaCfactor; + factor = factorsat; + Color::transitred ( HH, Chprov1, dred, factorskin, protect_redcur, factorskinext, deltaHH, factorsat, factor); + atmp *= factor; + btmp *= factor; + } + } + + // end chroma C=f(C) + + //update histogram C + if(pW != 1) { //only with improccoordinator + int posp = CLIP((int)sqrt((atmp * atmp + btmp * btmp))); + hist16Clad[posp]++; + } + + if (editPipette && editID == EUID_Lab_LCCurve) { + float chromapiplc = sqrt(SQR(atmp) + SQR(btmp) + 0.001f); + editWhatever->v(i, j) = LIM01((chromapiplc) / (48000.f)); + }//Lab L=f(C) pipette + + + if (cclutili && !bwToning) { //apply curve L=f(C) for skin and rd...but also for extended color ==> near green and blue (see 'curf') + + const float xx = 0.25f; //soft : between 0.2 and 0.4 + float skdeltaHH; + + skdeltaHH = protect_redhcur; //transition hue + + float skbeg = -0.05f; //begin hue skin + float skend = 1.60f; //end hue skin + const float chrmin = 50.0f; //to avoid artifact, because L curve is not a real curve for luminance + float aa, bb; + float zz = 0.0f; + float yy = 0.0f; + + if(Chprov1 < chrmin) { + yy = SQR(Chprov1 / chrmin) * xx; + } else { + yy = xx; //avoid artifact for low C + } + + if(!LCredsk) { + skbeg = -3.1415; + skend = 3.14159; + skdeltaHH = 0.001f; + } + + if(HH > skbeg && HH < skend ) { + zz = yy; + } else if(HH > skbeg - skdeltaHH && HH <= skbeg) { //transition + aa = yy / skdeltaHH; + bb = -aa * (skbeg - skdeltaHH); + zz = aa * HH + bb; + } else if(HH >= skend && HH < skend + skdeltaHH) { //transition + aa = -yy / skdeltaHH; + bb = -aa * (skend + skdeltaHH); + zz = aa * HH + bb; + } + + float chroma = sqrt(SQR(atmp) + SQR(btmp) + 0.001f); + float Lc = (lhskcurve[chroma * adjustr]) / (chroma * adjustr); //apply L=f(C) + Lc = (Lc - 1.0f) * zz + 1.0f; //reduct action + Lprov1 *= Lc; //adjust luminance + } + + //update histo LC + if(pW != 1) { //only with improccoordinator + int posl = CLIP((int(Lprov1 * 327.68f))); + hist16Llad[posl]++; + } + + Chprov1 = sqrt(SQR(atmp) + SQR(btmp)) / 327.68f; + + // labCurve.bwtoning option allows to decouple modulation of a & b curves by saturation + // with bwtoning enabled the net effect of a & b curves is visible + if (bwToning) { + atmp -= lold->a[i][j]; + btmp -= lold->b[i][j]; + } + + if (avoidColorShift) { + //gamutmap Lch ==> preserve Hue,but a little slower than gamutbdy for high values...and little faster for low values + if(gamutLch) { + float R, G, B; + +#ifdef _DEBUG + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, sincosval, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); +#endif + lnew->L[i][j] = Lprov1 * 327.68f; +// float2 sincosval = xsincosf(HH); + lnew->a[i][j] = 327.68f * Chprov1 * sincosval.y; + lnew->b[i][j] = 327.68f * Chprov1 * sincosval.x; + } else { + //use gamutbdy + //Luv limiter + float Y, u, v; + Color::Lab2Yuv(lnew->L[i][j], atmp, btmp, Y, u, v); + //Yuv2Lab includes gamut restriction map + Color::Yuv2Lab(Y, u, v, lnew->L[i][j], lnew->a[i][j], lnew->b[i][j], wp); + } + + if (utili || autili || butili || ccut || clut || cclutili || chutili || lhutili || hhutili || clcutili || chromaticity) { + float correctionHue = 0.f; // Munsell's correction + float correctlum = 0.f; + + Lprov1 = lnew->L[i][j] / 327.68f; + Chprov = sqrt(SQR(lnew->a[i][j]) + SQR(lnew->b[i][j])) / 327.68f; + +#ifdef _DEBUG + Color::AllMunsellLch(/*lumaMuns*/true, Lprov1, LL, HH, Chprov, memChprov, correctionHue, correctlum, MunsDebugInfo); +#else + Color::AllMunsellLch(/*lumaMuns*/true, Lprov1, LL, HH, Chprov, memChprov, correctionHue, correctlum); +#endif + + if(correctionHue != 0.f || correctlum != 0.f) { + if(fabs(correctionHue) < 0.015f) { + HH += correctlum; // correct only if correct Munsell chroma very little. + } + + /* if((HH>0.0f && HH < 1.6f) && memChprov < 70.0f) HH+=correctlum;//skin correct + else if(fabs(correctionHue) < 0.3f) HH+=0.08f*correctlum; + else if(fabs(correctionHue) < 0.2f) HH+=0.25f*correctlum; + else if(fabs(correctionHue) < 0.1f) HH+=0.35f*correctlum; + else if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little. + */ + sincosval = xsincosf(HH + correctionHue); + } + + lnew->a[i][j] = 327.68f * Chprov * sincosval.y; // apply Munsell + lnew->b[i][j] = 327.68f * Chprov * sincosval.x; + } + } else { +// if(Lprov1 > maxlp) maxlp=Lprov1; +// if(Lprov1 < minlp) minlp=Lprov1; + if(!bwToning) { + lnew->L[i][j] = Lprov1 * 327.68f; +// float2 sincosval = xsincosf(HH); + lnew->a[i][j] = 327.68f * Chprov1 * sincosval.y; + lnew->b[i][j] = 327.68f * Chprov1 * sincosval.x; + } else { + //Luv limiter only + lnew->a[i][j] = atmp; + lnew->b[i][j] = btmp; + } + } + } + } + } // end of parallelization //update histogram C with data chromaticity and not with CC curve - if(pW!=1){//only with improccoordinator - for (int i=0; i<48000; i++) {//32768*1.414 + ... + if(pW != 1) { //only with improccoordinator + for (int i = 0; i < 48000; i++) { //32768*1.414 + ... float hval = dCcurve[i]; - int hi = (int)(255.0*CLIPD(hval)); // + int hi = (int)(255.0 * CLIPD(hval)); // histCCurve[hi] += hist16Clad[i] ; - } - //update histogram L with data luminance - for (int i=0; i<65535; i++) { + } + + //update histogram L with data luminance + for (int i = 0; i < 65535; i++) { float hlval = dLcurve[i]; - int hli = (int)(255.0*CLIPD(hlval)); + int hli = (int)(255.0 * CLIPD(hlval)); histLCurve[hli] += hist16Llad[i] ; } - } + } #ifdef _DEBUG - if (settings->verbose) { - t2e.set(); - printf("Color::AllMunsellLch (correction performed in %d usec):\n", t2e.etime(t1e)); - printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad dep=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass); - printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad dep=%i\n", MunsDebugInfo->maxdhuelum[0], MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum); - } - delete MunsDebugInfo; + + if (settings->verbose) { + t2e.set(); + printf("Color::AllMunsellLch (correction performed in %d usec):\n", t2e.etime(t1e)); + printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad dep=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass); + printf(" Munsell luminance : MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad dep=%i\n", MunsDebugInfo->maxdhuelum[0], MunsDebugInfo->maxdhuelum[1], MunsDebugInfo->maxdhuelum[2], MunsDebugInfo->maxdhuelum[3], MunsDebugInfo->depassLum); + } + + delete MunsDebugInfo; #endif - if (chCurve) delete chCurve; - if (lhCurve) delete lhCurve; - if (hhCurve) delete hhCurve; - - // t2e.set(); - // printf("Chromil took %d �sec\n",t2e.etime(t1e)); + if (chCurve) { + delete chCurve; + } + + if (lhCurve) { + delete lhCurve; + } + + if (hhCurve) { + delete hhCurve; + } + + // t2e.set(); + // printf("Chromil took %d �sec\n",t2e.etime(t1e)); } //#include "cubic.cc" -void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) { +void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) +{ -/* LUT cmultiplier(181021); + /* LUT cmultiplier(181021); - double boost_a = ((float)params->colorBoost.amount + 100.0) / 100.0; - double boost_b = ((float)params->colorBoost.amount + 100.0) / 100.0; + double boost_a = ((float)params->colorBoost.amount + 100.0) / 100.0; + double boost_b = ((float)params->colorBoost.amount + 100.0) / 100.0; - double c, amul = 1.0, bmul = 1.0; - if (boost_a > boost_b) { - c = boost_a; - if (boost_a > 0) - bmul = boost_b / boost_a; - } - else { - c = boost_b; - if (boost_b > 0) - amul = boost_a / boost_b; - } - - if (params->colorBoost.enable_saturationlimiter && c>1.0) { - // re-generate color multiplier lookup table - double d = params->colorBoost.saturationlimit / 3.0; - double alpha = 0.5; - double threshold1 = alpha * d; - double threshold2 = c*d*(alpha+1.0) - d; - for (int i=0; i<=181020; i++) { // lookup table stores multipliers with a 0.25 chrominance resolution - double chrominance = (double)i/4.0; - if (chrominance < threshold1) - cmultiplier[i] = c; - else if (chrominance < d) - cmultiplier[i] = (c / (2.0*d*(alpha-1.0)) * (chrominance-d)*(chrominance-d) + c*d/2.0 * (alpha+1.0) ) / chrominance; - else if (chrominance < threshold2) - cmultiplier[i] = (1.0 / (2.0*d*(c*(alpha+1.0)-2.0)) * (chrominance-d)*(chrominance-d) + c*d/2.0 * (alpha+1.0) ) / chrominance; - else - cmultiplier[i] = 1.0; + double c, amul = 1.0, bmul = 1.0; + if (boost_a > boost_b) { + c = boost_a; + if (boost_a > 0) + bmul = boost_b / boost_a; + } + else { + c = boost_b; + if (boost_b > 0) + amul = boost_a / boost_b; } - } - float eps = 0.001; - double shift_a = params->colorShift.a + eps, shift_b = params->colorShift.b + eps; - - float** oa = lold->a; - float** ob = lold->b; - - #pragma omp parallel for if (multiThread) - for (int i=0; iH; i++) - for (int j=0; jW; j++) { - - double wanted_c = c; - if (params->colorBoost.enable_saturationlimiter && c>1) { - float chroma = (float)(4.0 * sqrt((oa[i][j]+shift_a)*(oa[i][j]+shift_a) + (ob[i][j]+shift_b)*(ob[i][j]+shift_b))); - wanted_c = cmultiplier [chroma]; + if (params->colorBoost.enable_saturationlimiter && c>1.0) { + // re-generate color multiplier lookup table + double d = params->colorBoost.saturationlimit / 3.0; + double alpha = 0.5; + double threshold1 = alpha * d; + double threshold2 = c*d*(alpha+1.0) - d; + for (int i=0; i<=181020; i++) { // lookup table stores multipliers with a 0.25 chrominance resolution + double chrominance = (double)i/4.0; + if (chrominance < threshold1) + cmultiplier[i] = c; + else if (chrominance < d) + cmultiplier[i] = (c / (2.0*d*(alpha-1.0)) * (chrominance-d)*(chrominance-d) + c*d/2.0 * (alpha+1.0) ) / chrominance; + else if (chrominance < threshold2) + cmultiplier[i] = (1.0 / (2.0*d*(c*(alpha+1.0)-2.0)) * (chrominance-d)*(chrominance-d) + c*d/2.0 * (alpha+1.0) ) / chrominance; + else + cmultiplier[i] = 1.0; } + } - double real_c = wanted_c; - if (wanted_c >= 1.0 && params->colorBoost.avoidclip) { - double cclip = 100000.0; - double cr = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa[i][j]+shift_a)*amul, (double)(ob[i][j]+shift_b)*bmul, 3.079935, -1.5371515, -0.54278342); - double cg = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa[i][j]+shift_a)*amul, (double)(ob[i][j]+shift_b)*bmul, -0.92123418, 1.87599, 0.04524418); - double cb = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa[i][j]+shift_a)*amul, (double)(ob[i][j]+shift_b)*bmul, 0.052889682, -0.20404134, 1.15115166); - if (cr>1.0 && cr1.0 && cg1.0 && cbcolorShift.a + eps, shift_b = params->colorShift.b + eps; + + float** oa = lold->a; + float** ob = lold->b; + + #pragma omp parallel for if (multiThread) + for (int i=0; iH; i++) + for (int j=0; jW; j++) { + + double wanted_c = c; + if (params->colorBoost.enable_saturationlimiter && c>1) { + float chroma = (float)(4.0 * sqrt((oa[i][j]+shift_a)*(oa[i][j]+shift_a) + (ob[i][j]+shift_b)*(ob[i][j]+shift_b))); + wanted_c = cmultiplier [chroma]; } - } - float nna = ((oa[i][j]+shift_a) * real_c * amul); - float nnb = ((ob[i][j]+shift_b) * real_c * bmul); - lnew->a[i][j] = LIM(nna,-32000.0f,32000.0f); - lnew->b[i][j] = LIM(nnb,-32000.0f,32000.0f); - } -*/ + double real_c = wanted_c; + if (wanted_c >= 1.0 && params->colorBoost.avoidclip) { + double cclip = 100000.0; + double cr = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa[i][j]+shift_a)*amul, (double)(ob[i][j]+shift_b)*bmul, 3.079935, -1.5371515, -0.54278342); + double cg = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa[i][j]+shift_a)*amul, (double)(ob[i][j]+shift_b)*bmul, -0.92123418, 1.87599, 0.04524418); + double cb = tightestroot ((double)lnew->L[i][j]/655.35, (double)(oa[i][j]+shift_a)*amul, (double)(ob[i][j]+shift_b)*bmul, 0.052889682, -0.20404134, 1.15115166); + if (cr>1.0 && cr1.0 && cg1.0 && cba[i][j] = LIM(nna,-32000.0f,32000.0f); + lnew->b[i][j] = LIM(nnb,-32000.0f,32000.0f); + } + */ //delete [] cmultiplier; } - void ImProcFunctions::impulsedenoise (LabImage* lab) { +void ImProcFunctions::impulsedenoise (LabImage* lab) +{ - if (params->impulseDenoise.enabled && lab->W>=8 && lab->H>=8) + if (params->impulseDenoise.enabled && lab->W >= 8 && lab->H >= 8) - impulse_nr (lab, (float)params->impulseDenoise.thresh/20.0 ); - } + { + impulse_nr (lab, (float)params->impulseDenoise.thresh / 20.0 ); + } +} - void ImProcFunctions::impulsedenoisecam (CieImage* ncie, float **buffers[3]) { +void ImProcFunctions::impulsedenoisecam (CieImage* ncie, float **buffers[3]) +{ - if (params->impulseDenoise.enabled && ncie->W>=8 && ncie->H>=8) + if (params->impulseDenoise.enabled && ncie->W >= 8 && ncie->H >= 8) - impulse_nrcam (ncie, (float)params->impulseDenoise.thresh/20.0, buffers ); - } - - void ImProcFunctions::defringe (LabImage* lab) { + { + impulse_nrcam (ncie, (float)params->impulseDenoise.thresh / 20.0, buffers ); + } +} - if (params->defringe.enabled && lab->W>=8 && lab->H>=8) +void ImProcFunctions::defringe (LabImage* lab) +{ - PF_correct_RT(lab, lab, params->defringe.radius, params->defringe.threshold); - } + if (params->defringe.enabled && lab->W >= 8 && lab->H >= 8) - void ImProcFunctions::defringecam (CieImage* ncie) { - if (params->defringe.enabled && ncie->W>=8 && ncie->H>=8) - PF_correct_RTcam(ncie, ncie, params->defringe.radius, params->defringe.threshold); - } - - void ImProcFunctions::badpixcam(CieImage* ncie, double rad, int thr, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad){ - if(ncie->W>=8 && ncie->H>=8) Badpixelscam(ncie, ncie, rad, thr, mode, b_l, t_l, t_r,b_r, skinprot, chrom, hotbad); - } + { + PF_correct_RT(lab, lab, params->defringe.radius, params->defringe.threshold); + } +} - void ImProcFunctions::badpixlab(LabImage* lab, double rad, int thr, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom){ - if(lab->W>=8 && lab->H>=8) BadpixelsLab(lab, lab, rad, thr, mode, b_l, t_l, t_r,b_r, skinprot, chrom); - } +void ImProcFunctions::defringecam (CieImage* ncie) +{ + if (params->defringe.enabled && ncie->W >= 8 && ncie->H >= 8) { + PF_correct_RTcam(ncie, ncie, params->defringe.radius, params->defringe.threshold); + } +} - void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale) { +void ImProcFunctions::badpixcam(CieImage* ncie, double rad, int thr, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad) +{ + if(ncie->W >= 8 && ncie->H >= 8) { + Badpixelscam(ncie, ncie, rad, thr, mode, b_l, t_l, t_r, b_r, skinprot, chrom, hotbad); + } +} - 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; - float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; - float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; - int choice=0;//I have not disabled this statement in case of ! always 0 - // if (params->dirpyrequalizer.algo=="FI") choice=0; - // else if(params->dirpyrequalizer.algo=="LA") choice=1; - float artifact=(float) settings->artifact_cbdl; - if(artifact > 6.f) artifact =6.f; - if(artifact <0.f) artifact=1.f; - - float chrom = 50.f; - if(params->dirpyrequalizer.gamutlab) - ImProcFunctions::badpixlab (lab, artifact, 5, 3, b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect, chrom);//for artifacts +void ImProcFunctions::badpixlab(LabImage* lab, double rad, int thr, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom) +{ + if(lab->W >= 8 && lab->H >= 8) { + BadpixelsLab(lab, lab, rad, thr, mode, b_l, t_l, t_r, b_r, skinprot, chrom); + } +} - //dirpyrLab_equalizer(lab, lab, params->dirpyrequalizer.mult); - dirpyr_equalizer(lab->L, lab->L, lab->W, lab->H, lab->a, lab->b, lab->a, lab->b, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, params->dirpyrequalizer.gamutlab, b_l,t_l,t_r,b_r, choice, scale); - } - } -void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, float w_h, int Wid, int Hei, int begh, int endh, float minQ, float maxQ, unsigned int Iterates, int skip){ +void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale) +{ -if(!params->epd.enabled) return; -if(params->wavelet.enabled && params->wavelet.tmrs!=0) return; + 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; + float b_r = static_cast(params->dirpyrequalizer.hueskin.value[2]) / 100.0f; + float t_r = static_cast(params->dirpyrequalizer.hueskin.value[3]) / 100.0f; + int choice = 0; //I have not disabled this statement in case of ! always 0 + // if (params->dirpyrequalizer.algo=="FI") choice=0; + // else if(params->dirpyrequalizer.algo=="LA") choice=1; + float artifact = (float) settings->artifact_cbdl; - float stren=params->epd.strength; - float edgest=params->epd.edgeStopping; - float sca=params->epd.scale; - float gamm=params->epd.gamma; - float rew=params->epd.reweightingIterates; - unsigned int i, N = Wid*Hei; - float Qpro= ( 4.0 / c_) * ( a_w + 4.0 ) ;//estimate Q max if J=100.0 - float *Qpr=ncie->Q_p[0]; - if (settings->verbose) - printf("minQ=%f maxQ=%f Qpro=%f\n",minQ,maxQ, Qpro); - if(maxQ>Qpro) - Qpro=maxQ; + if(artifact > 6.f) { + artifact = 6.f; + } - EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei); + if(artifact < 0.f) { + artifact = 1.f; + } - #pragma omp parallel for - for (int i=0; iQ_p[i][j] = gamm*ncie->Q_p[i][j]/(Qpro); + float chrom = 50.f; - float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. - float DetailBoost = stren; - if(stren < 0.0f) DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + if(params->dirpyrequalizer.gamutlab) { + ImProcFunctions::badpixlab (lab, artifact, 5, 3, b_l, t_l, t_r, b_r, params->dirpyrequalizer.skinprotect, chrom); //for artifacts + } - //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. - if(Iterates == 0) Iterates = (unsigned int)(edgest*15.0); - //Jacques Desmis : always Iterates=5 for compatibility images between preview and output + //dirpyrLab_equalizer(lab, lab, params->dirpyrequalizer.mult); + dirpyr_equalizer(lab->L, lab->L, lab->W, lab->H, lab->a, lab->b, lab->a, lab->b, params->dirpyrequalizer.mult, params->dirpyrequalizer.threshold, params->dirpyrequalizer.skinprotect, params->dirpyrequalizer.gamutlab, b_l, t_l, t_r, b_r, choice, scale); + } +} +void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, float w_h, int Wid, int Hei, int begh, int endh, float minQ, float maxQ, unsigned int Iterates, int skip) +{ - epd.CompressDynamicRange(Qpr, (float)sca/skip, (float)edgest, Compression, DetailBoost, Iterates, rew, Qpr); + if(!params->epd.enabled) { + return; + } - //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. - float s = (1.0f + 38.7889f)*powf(Compression, 1.5856f)/(1.0f + 38.7889f*powf(Compression, 1.5856f)); - #ifndef _DEBUG - #pragma omp parallel for schedule(dynamic,10) - #endif - for (int i=0; iQ_p[i][j]=(ncie->Q_p[i][j]*Qpro)/gamm; - ncie->M_p[i][j]*=s; - } -/* - float *Qpr2 = new float[Wid*((heir)+1)]; + if(params->wavelet.enabled && params->wavelet.tmrs != 0) { + return; + } - for (int i=heir; iQ_p[i][j];} - if(minQ>0.0) minQ=0.0;//normaly minQ always > 0... -// EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei); -//EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei/2); - for(i = N2; i != N; i++) -// for(i = begh*Wid; i != N; i++) - //Qpr[i] = (Qpr[i]-minQ)/(maxQ+1.0); - Qpr2[i-N2] = (Qpr2[i-N2]-minQ)/(Qpro+1.0); + float stren = params->epd.strength; + float edgest = params->epd.edgeStopping; + float sca = params->epd.scale; + float gamm = params->epd.gamma; + float rew = params->epd.reweightingIterates; + unsigned int i, N = Wid * Hei; + float Qpro = ( 4.0 / c_) * ( a_w + 4.0 ) ; //estimate Q max if J=100.0 + float *Qpr = ncie->Q_p[0]; - float Compression2 = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. - float DetailBoost2 = stren; - if(stren < 0.0f) DetailBoost2 = 0.0f; //Go with effect of exponent only if uncompressing. + if (settings->verbose) { + printf("minQ=%f maxQ=%f Qpro=%f\n", minQ, maxQ, Qpro); + } - //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. - if(Iterates == 0) Iterates = (unsigned int)(edgest*15.0); + if(maxQ > Qpro) { + Qpro = maxQ; + } + + EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei); + + #pragma omp parallel for + + for (int i = 0; i < Hei; i++) + for (int j = 0; j < Wid; j++) { + ncie->Q_p[i][j] = gamm * ncie->Q_p[i][j] / (Qpro); + } + + float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. + float DetailBoost = stren; + + if(stren < 0.0f) { + DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + } + + //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. + if(Iterates == 0) { + Iterates = (unsigned int)(edgest * 15.0); + } + + //Jacques Desmis : always Iterates=5 for compatibility images between preview and output + + epd.CompressDynamicRange(Qpr, (float)sca / skip, (float)edgest, Compression, DetailBoost, Iterates, rew, Qpr); + + //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. + float s = (1.0f + 38.7889f) * powf(Compression, 1.5856f) / (1.0f + 38.7889f * powf(Compression, 1.5856f)); +#ifndef _DEBUG + #pragma omp parallel for schedule(dynamic,10) +#endif + + for (int i = 0; i < Hei; i++) + for (int j = 0; j < Wid; j++) { + ncie->Q_p[i][j] = (ncie->Q_p[i][j] * Qpro) / gamm; + ncie->M_p[i][j] *= s; + } + + /* + float *Qpr2 = new float[Wid*((heir)+1)]; + + for (int i=heir; iQ_p[i][j];} + if(minQ>0.0) minQ=0.0;//normaly minQ always > 0... + // EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei); + //EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei/2); + for(i = N2; i != N; i++) + // for(i = begh*Wid; i != N; i++) + //Qpr[i] = (Qpr[i]-minQ)/(maxQ+1.0); + Qpr2[i-N2] = (Qpr2[i-N2]-minQ)/(Qpro+1.0); + + float Compression2 = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. + float DetailBoost2 = stren; + if(stren < 0.0f) DetailBoost2 = 0.0f; //Go with effect of exponent only if uncompressing. + + //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. + if(Iterates == 0) Iterates = (unsigned int)(edgest*15.0); - epd.CompressDynamicRange(Qpr2, (float)sca/skip, (float)edgest, Compression2, DetailBoost2, Iterates, rew, Qpr2); + epd.CompressDynamicRange(Qpr2, (float)sca/skip, (float)edgest, Compression2, DetailBoost2, Iterates, rew, Qpr2); - //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. - float s2 = (1.0f + 38.7889f)*powf(Compression, 1.5856f)/(1.0f + 38.7889f*powf(Compression, 1.5856f)); - for (int i=heir; iQ_p[i][j]=Qpr2[(i-heir)*Wid+j]*Qpro + minQ; - // Qpr[i*Wid+j]=Qpr[i*Wid+j]*maxQ + minQ; - // ncie->J_p[i][j]=(100.0* Qpr[i*Wid+j]*Qpr[i*Wid+j]) /(w_h*w_h); + //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. + float s2 = (1.0f + 38.7889f)*powf(Compression, 1.5856f)/(1.0f + 38.7889f*powf(Compression, 1.5856f)); + for (int i=heir; iQ_p[i][j]=Qpr2[(i-heir)*Wid+j]*Qpro + minQ; + // Qpr[i*Wid+j]=Qpr[i*Wid+j]*maxQ + minQ; + // ncie->J_p[i][j]=(100.0* Qpr[i*Wid+j]*Qpr[i*Wid+j]) /(w_h*w_h); - ncie->M_p[i][j]*=s2; - } - delete [] Qpr2; + ncie->M_p[i][j]*=s2; + } + delete [] Qpr2; -*/ + */ } //Map tones by way of edge preserving decomposition. Is this the right way to include source? //#include "EdgePreservingDecomposition.cc" -void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip){ - //Hasten access to the parameters. -// EPDParams *p = (EPDParams *)(¶ms->epd); - - //Enabled? Leave now if not. -// if(!p->enabled) return; -if(!params->epd.enabled) return; -if(params->wavelet.enabled && params->wavelet.tmrs!=0) return; - -float stren=params->epd.strength; -float edgest=params->epd.edgeStopping; -float sca=params->epd.scale; -float gamm=params->epd.gamma; -float rew=params->epd.reweightingIterates; - //Pointers to whole data and size of it. - float *L = lab->L[0]; - float *a = lab->a[0]; - float *b = lab->b[0]; - unsigned int i, N = lab->W*lab->H; - EdgePreservingDecomposition epd = EdgePreservingDecomposition(lab->W, lab->H); - - //Due to the taking of logarithms, L must be nonnegative. Further, scale to 0 to 1 using nominal range of L, 0 to 15 bit. - float minL = FLT_MAX; - float maxL = 0.f; -#pragma omp parallel +void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip) { - float lminL = FLT_MAX; - float lmaxL = 0.f; -#pragma omp for - for(i = 0; i < N; i++) { - if(L[i] < lminL) lminL = L[i]; - if(L[i] > lmaxL) lmaxL = L[i]; - } -#pragma omp critical - if(lminL < minL) minL = lminL; - if(lmaxL > maxL) maxL = lmaxL; - -} - if(minL > 0.0f) minL = 0.0f; //Disable the shift if there are no negative numbers. I wish there were just no negative numbers to begin with. -#pragma omp parallel for - for(i = 0; i < N; i++) - //{L[i] = (L[i] - minL)/32767.0f; - {L[i] = (L[i] - minL)/maxL; - L[i]*=gamm; - } - //Some interpretations. - float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. - float DetailBoost = stren; - if(stren < 0.0f) DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + //Hasten access to the parameters. +// EPDParams *p = (EPDParams *)(¶ms->epd); - //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. - if(Iterates == 0) Iterates = (unsigned int)(edgest*15.0f); + //Enabled? Leave now if not. +// if(!p->enabled) return; + if(!params->epd.enabled) { + return; + } -/* Debuggery. Saves L for toying with outside of RT. -char nm[64]; -sprintf(nm, "%ux%ufloat.bin", lab->W, lab->H); -FILE *f = fopen(nm, "wb"); -fwrite(L, N, sizeof(float), f); -fclose(f);*/ + if(params->wavelet.enabled && params->wavelet.tmrs != 0) { + return; + } - epd.CompressDynamicRange(L, sca/float(skip), edgest, Compression, DetailBoost, Iterates, rew, L); + float stren = params->epd.strength; + float edgest = params->epd.edgeStopping; + float sca = params->epd.scale; + float gamm = params->epd.gamma; + float rew = params->epd.reweightingIterates; + //Pointers to whole data and size of it. + float *L = lab->L[0]; + float *a = lab->a[0]; + float *b = lab->b[0]; + unsigned int i, N = lab->W * lab->H; + EdgePreservingDecomposition epd = EdgePreservingDecomposition(lab->W, lab->H); - //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. - float s = (1.0f + 38.7889f)*powf(Compression, 1.5856f)/(1.0f + 38.7889f*powf(Compression, 1.5856f)); - #ifdef _OPENMP - #pragma omp parallel for // removed schedule(dynamic,10) - #endif - for(int ii = 0; ii < N; ii++) - a[ii] *= s, - b[ii] *= s, - //L[ii] = L[ii]*32767.0f*(1.f/gamm) + minL; - L[ii] = L[ii]*maxL*(1.f/gamm) + minL; + //Due to the taking of logarithms, L must be nonnegative. Further, scale to 0 to 1 using nominal range of L, 0 to 15 bit. + float minL = FLT_MAX; + float maxL = 0.f; + #pragma omp parallel + { + float lminL = FLT_MAX; + float lmaxL = 0.f; + #pragma omp for + + for(i = 0; i < N; i++) { + if(L[i] < lminL) { + lminL = L[i]; + } + + if(L[i] > lmaxL) { + lmaxL = L[i]; + } + } + + #pragma omp critical + + if(lminL < minL) { + minL = lminL; + } + + if(lmaxL > maxL) { + maxL = lmaxL; + } + + } + + if(minL > 0.0f) { + minL = 0.0f; //Disable the shift if there are no negative numbers. I wish there were just no negative numbers to begin with. + } + + #pragma omp parallel for + + for(i = 0; i < N; i++) + //{L[i] = (L[i] - minL)/32767.0f; + { + L[i] = (L[i] - minL) / maxL; + L[i] *= gamm; + } + + //Some interpretations. + float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. + float DetailBoost = stren; + + if(stren < 0.0f) { + DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + } + + //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. + if(Iterates == 0) { + Iterates = (unsigned int)(edgest * 15.0f); + } + + /* Debuggery. Saves L for toying with outside of RT. + char nm[64]; + sprintf(nm, "%ux%ufloat.bin", lab->W, lab->H); + FILE *f = fopen(nm, "wb"); + fwrite(L, N, sizeof(float), f); + fclose(f);*/ + + epd.CompressDynamicRange(L, sca / float(skip), edgest, Compression, DetailBoost, Iterates, rew, L); + + //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. + float s = (1.0f + 38.7889f) * powf(Compression, 1.5856f) / (1.0f + 38.7889f * powf(Compression, 1.5856f)); +#ifdef _OPENMP + #pragma omp parallel for // removed schedule(dynamic,10) +#endif + + for(int ii = 0; ii < N; ii++) + a[ii] *= s, + b[ii] *= s, + //L[ii] = L[ii]*32767.0f*(1.f/gamm) + minL; + L[ii] = L[ii] * maxL * (1.f / gamm) + minL; } - void ImProcFunctions::getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip, - double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh) { +void ImProcFunctions::getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip, + double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh) +{ - float scale = 65536.0f; - float midgray=0.1842f;//middle gray in linear gamma =1 50% luminance + float scale = 65536.0f; + float midgray = 0.1842f; //middle gray in linear gamma =1 50% luminance - int imax=65536>>histcompr; - int overex=0; - float sum = 0.f, hisum=0.f, losum=0.f; - float ave = 0.f, hidev=0.f, lodev=0.f; - //find average luminance - for (int i=0; i> histcompr; + int overex = 0; + float sum = 0.f, hisum = 0.f, losum = 0.f; + float ave = 0.f, hidev = 0.f, lodev = 0.f; - //find median of luminance - int median=0, count=histogram[0]; - while (countsum/8.f || (count==7 && octile[count]>sum/16.f)) { - octile[count]=log(1.+(float)i)/log(2.f); - count++;// = min(count+1,7); - } - } - if (ilog((float)imax+1.f)/log2(2.f)) {//if very overxposed image - octile[6]=1.5f*octile[5]-0.5f*octile[4]; - overex=2; - } - - if (octile[7]>log((float)imax+1.f)/log2(2.f)) {//if overexposed - octile[7]=1.5f*octile[6]-0.5f*octile[5]; - overex=1; - } + //find median of luminance + int median = 0, count = histogram[0]; - // store values of octile[6] and octile[7] for calculation of exposure compensation - // if we don't do this and the pixture is underexposed, calculation of exposure compensation assumes - // that it's overexposed and calculates the wrong direction - float oct6,oct7; - oct6 = octile[6]; - oct7 = octile[7]; - + while (count < sum / 2) { + median++; + count += histogram[median]; + } - for(int i=1; i<8; i++) { - if (octile[i] == 0.0f) - octile[i] = octile[i-1]; - } - // compute weighted average separation of octiles - // for future use in contrast setting - for (int i=1; i<6; i++) { - ospread += (octile[i+1]-octile[i])/max(0.5f,(i>2 ? (octile[i+1]-octile[3]) : (octile[3]-octile[i]))); - } - ospread /= 5.f; - if (ospread<=0.f) {//probably the image is a blackframe - expcomp=0.; - black=0; - bright=0; - contr=0; - hlcompr=0; - hlcomprthresh=0; - return; - } + if (median == 0 || ave < 1.f) { //probably the image is a blackframe + expcomp = 0.; + black = 0; + bright = 0; + contr = 0; + hlcompr = 0; + hlcomprthresh = 0; + return; + } + + // compute std dev on the high and low side of median + // and octiles of histogram + float octile[8] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}, ospread = 0.f; + count = 0; + + for (int i = 0; i < imax; i++) { + if (count < 8) { + octile[count] += histogram[i]; + + if (octile[count] > sum / 8.f || (count == 7 && octile[count] > sum / 16.f)) { + octile[count] = log(1. + (float)i) / log(2.f); + count++;// = min(count+1,7); + } + } + + if (i < ave) { + //lodev += SQR(ave-i)*histogram[i]; + lodev += (log(ave + 1.f) - log((float)i + 1.)) * histogram[i]; + losum += histogram[i]; + } else { + //hidev += SQR(i-ave)*histogram[i]; + hidev += (log((float)i + 1.) - log(ave + 1.f)) * histogram[i]; + hisum += histogram[i]; + } + } + + if (losum == 0 || hisum == 0) { //probably the image is a blackframe + expcomp = 0.; + black = 0; + bright = 0; + contr = 0; + hlcompr = 0; + hlcomprthresh = 0; + return; + } + + lodev = (lodev / (log(2.f) * losum)); + hidev = (hidev / (log(2.f) * hisum)); + + if (octile[6] > log((float)imax + 1.f) / log2(2.f)) { //if very overxposed image + octile[6] = 1.5f * octile[5] - 0.5f * octile[4]; + overex = 2; + } + + if (octile[7] > log((float)imax + 1.f) / log2(2.f)) { //if overexposed + octile[7] = 1.5f * octile[6] - 0.5f * octile[5]; + overex = 1; + } + + // store values of octile[6] and octile[7] for calculation of exposure compensation + // if we don't do this and the pixture is underexposed, calculation of exposure compensation assumes + // that it's overexposed and calculates the wrong direction + float oct6, oct7; + oct6 = octile[6]; + oct7 = octile[7]; - // compute clipping points based on the original histograms (linear, without exp comp.) - int clipped = 0; - int rawmax = (imax) - 1; - while (rawmax>1 && histogram[rawmax]+clipped <= 0) { - clipped += histogram[rawmax]; - rawmax--; - } + for(int i = 1; i < 8; i++) { + if (octile[i] == 0.0f) { + octile[i] = octile[i - 1]; + } + } - //compute clipped white point - int clippable = (int)(sum * clip/100.f ); - int somm=sum; - clipped = 0; - int whiteclip = (imax) - 1; - while (whiteclip>1 && histogram[whiteclip]+clipped <= clippable) { - clipped += histogram[whiteclip]; - whiteclip--; - } - int clipwh=clipped; - //compute clipped black point - clipped = 0; - int shc = 0; - - while (shc 2 ? (octile[i + 1] - octile[3]) : (octile[3] - octile[i]))); + } - //prevent division by 0 - if (lodev==0.f) - lodev=1.f; + ospread /= 5.f; - //compute exposure compensation as geometric mean of the amount that - //sets the mean or median at middle gray, and the amount that sets the estimated top - //of the histogram at or near clipping. - float expo=log(midgray*scale/(ave-shc+midgray*shc)); - //float expcomp1 = (log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc))+log((hidev/lodev)))/log(2.f); - float expcomp1 = (log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc)))/log(2.f); - float expcomp2; - - if(overex == 0) { // image is not overexposed - expcomp2 = 0.5f*( (15.5f-histcompr-(2.f*oct7-oct6)) + log(scale/rawmax)/log(2.f) ); - } - else { - expcomp2 = 0.5f*( (15.5f-histcompr-(2.f*octile[7]-octile[6])) + log(scale/rawmax)/log(2.f) ); - } - - if(fabs(expcomp1)-fabs(expcomp2)> 1.f) {//for great expcomp - expcomp = (expcomp1*fabs(expcomp2)+expcomp2*fabs(expcomp1))/(fabs(expcomp1)+fabs(expcomp2)); - } - else { - expcomp = 0.5 * (double)expcomp1 + 0.5 *(double) expcomp2;//for small expcomp - } - float gain = exp((float)expcomp*log(2.f)); - - float corr = sqrt(gain*scale/rawmax); - black = (int) shc*corr; + if (ospread <= 0.f) { //probably the image is a blackframe + expcomp = 0.; + black = 0; + bright = 0; + contr = 0; + hlcompr = 0; + hlcomprthresh = 0; + return; + } - //now tune hlcompr to bring back rawmax to 65535 - hlcomprthresh = 33; - //this is a series approximation of the actual formula for comp, - //which is a transcendental equation - float comp = (gain*((float)whiteclip)/scale - 1.f)*2.3f;// 2.3 instead of 2 to increase slightly comp - hlcompr=(int)(100.*comp/(max(0.0,expcomp) + 1.0)); - hlcompr = max(0,min(100,hlcompr)); + // compute clipping points based on the original histograms (linear, without exp comp.) + int clipped = 0; + int rawmax = (imax) - 1; - //now find brightness if gain didn't bring ave to midgray using - //the envelope of the actual 'control cage' brightness curve for simplicity - float midtmp = gain*sqrt(median*ave)/scale; - if (midtmp<0.1f) { - bright = (midgray-midtmp)*15.0/(midtmp); - } else { - bright = (midgray-midtmp)*15.0/(0.10833-0.0833*midtmp); - } + while (rawmax > 1 && histogram[rawmax] + clipped <= 0) { + clipped += histogram[rawmax]; + rawmax--; + } - bright = 0.25*/*(median/ave)*(hidev/lodev)*/max(0,bright); + //compute clipped white point + int clippable = (int)(sum * clip / 100.f ); + int somm = sum; + clipped = 0; + int whiteclip = (imax) - 1; - //compute contrast that spreads the average spacing of octiles - contr = (int) 50.0f*(1.1f-ospread); - contr = max(0,min(100,contr)); - //take gamma into account - double whiteclipg = (int)(CurveFactory::gamma2 (whiteclip * corr / 65536.0) * 65536.0); - - double gavg = 0.; - for (int i=0; i<65536>>histcompr; i++) - gavg += histogram[i] * CurveFactory::gamma2((float)(corr*(i< 1 && histogram[whiteclip] + clipped <= clippable) { + clipped += histogram[whiteclip]; + whiteclip--; + } - //diagnostics - //printf ("**************** AUTO LEVELS ****************\n"); - /* - if (settings->verbose) { - printf("sum=%i clip=%f clippable=%i clipWh=%i clipBl=%i\n",somm, clip, clippable,clipwh, clipbl); - printf ("expcomp1= %f expcomp2= %f gain= %f expcomp=%f\n",expcomp1,expcomp2,gain,expcomp); - printf ("expo=%f\n",expo); - printf ("median: %i average: %f median/average: %f\n",median,ave, median/ave); - printf ("average: %f\n",ave); - printf("comp=%f hlcomp: %i\n",comp, hlcompr); - printf ("median/average: %f\n",median/ave); - printf ("lodev: %f hidev: %f hidev/lodev: %f\n",lodev,hidev,hidev/lodev); - printf ("lodev: %f\n",lodev); - printf ("hidev: %f\n",hidev); - printf ("imax=%d rawmax= %d whiteclip= %d gain= %f\n",imax,rawmax,whiteclip,gain); - printf ("octiles: %f %f %f %f %f %f %f %f\n",octile[0],octile[1],octile[2],octile[3],octile[4],octile[5],octile[6],octile[7]); - printf ("ospread= %f\n",ospread); - printf ("overexp= %i\n",overex); - } - */ - /* - // %%%%%%%%%% LEGACY AUTOEXPOSURE CODE %%%%%%%%%%%%% - // black point selection is based on the linear result (yielding better visual results) - black = (int)(shc * corr); - // compute the white point of the exp. compensated gamma corrected image - double whiteclipg = (int)(CurveFactory::gamma2 (whiteclip * corr / 65536.0) * 65536.0); + int clipwh = clipped; + //compute clipped black point + clipped = 0; + int shc = 0; - // compute average intensity of the exp compensated, gamma corrected image - double gavg = 0; - for (int i=0; i<65536>>histcompr; i++) - gavg += histogram[i] * CurveFactory::gamma2((int)(corr*(i<12.0) expcomp = 12.0; - bright = max(-100,min(bright,100)); - } + //compute exposure compensation as geometric mean of the amount that + //sets the mean or median at middle gray, and the amount that sets the estimated top + //of the histogram at or near clipping. + float expo = log(midgray * scale / (ave - shc + midgray * shc)); + //float expcomp1 = (log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc))+log((hidev/lodev)))/log(2.f); + float expcomp1 = (log(/*(median/ave)*//*(hidev/lodev)*/midgray * scale / (ave - shc + midgray * shc))) / log(2.f); + float expcomp2; + + if(overex == 0) { // image is not overexposed + expcomp2 = 0.5f * ( (15.5f - histcompr - (2.f * oct7 - oct6)) + log(scale / rawmax) / log(2.f) ); + } else { + expcomp2 = 0.5f * ( (15.5f - histcompr - (2.f * octile[7] - octile[6])) + log(scale / rawmax) / log(2.f) ); + } + + if(fabs(expcomp1) - fabs(expcomp2) > 1.f) { //for great expcomp + expcomp = (expcomp1 * fabs(expcomp2) + expcomp2 * fabs(expcomp1)) / (fabs(expcomp1) + fabs(expcomp2)); + } else { + expcomp = 0.5 * (double)expcomp1 + 0.5 * (double) expcomp2; //for small expcomp + } + + float gain = exp((float)expcomp * log(2.f)); + + float corr = sqrt(gain * scale / rawmax); + black = (int) shc * corr; - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //now tune hlcompr to bring back rawmax to 65535 + hlcomprthresh = 33; + //this is a series approximation of the actual formula for comp, + //which is a transcendental equation + float comp = (gain * ((float)whiteclip) / scale - 1.f) * 2.3f; // 2.3 instead of 2 to increase slightly comp + hlcompr = (int)(100.*comp / (max(0.0, expcomp) + 1.0)); + hlcompr = max(0, min(100, hlcompr)); - double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_size) { - if (fname != "") { - rtengine::RawMetaDataLocation ri; - int w_raw=-1, h_raw=thumb_size; - int w_thumb=-1, h_thumb=thumb_size; + //now find brightness if gain didn't bring ave to midgray using + //the envelope of the actual 'control cage' brightness curve for simplicity + float midtmp = gain * sqrt(median * ave) / scale; - Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, w_thumb, h_thumb, 1, FALSE); - if (thumb == NULL) - return 0.0; + if (midtmp < 0.1f) { + bright = (midgray - midtmp) * 15.0 / (midtmp); + } else { + bright = (midgray - midtmp) * 15.0 / (0.10833 - 0.0833 * midtmp); + } - Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE); - if (raw == NULL) { - delete thumb; - return 0.0; - } + bright = 0.25 */*(median/ave)*(hidev/lodev)*/max(0, bright); - if (h_thumb != h_raw) { - delete thumb; - delete raw; - return 0.0; - } + //compute contrast that spreads the average spacing of octiles + contr = (int) 50.0f * (1.1f - ospread); + contr = max(0, min(100, contr)); + //take gamma into account + double whiteclipg = (int)(CurveFactory::gamma2 (whiteclip * corr / 65536.0) * 65536.0); - int width; + double gavg = 0.; - if (w_thumb > w_raw) - width = w_raw; - else - width = w_thumb; + for (int i = 0; i<65536 >> histcompr; i++) { + gavg += histogram[i] * CurveFactory::gamma2((float)(corr * (i << histcompr) < 65535 ? corr * (i << histcompr) : 65535)) / sum; + } - unsigned char* thumbGray; - unsigned char* rawGray; - thumbGray = thumb->getGrayscaleHistEQ (width); - rawGray = raw->getGrayscaleHistEQ (width); + if (black < gavg) { + int maxwhiteclip = (gavg - black) * 4 / 3 + black; // dont let whiteclip be such large that the histogram average goes above 3/4 - if (thumbGray == NULL || rawGray == NULL) { - if (thumbGray) delete thumbGray; - if (rawGray) delete rawGray; - delete thumb; - delete raw; - return 0.0; - } + if (whiteclipg < maxwhiteclip) { + whiteclipg = maxwhiteclip; + } + } - double dist_amount; - int dist_result = calcDistortion (thumbGray, rawGray, width, h_thumb, 1, dist_amount); - if(dist_result == -1) // not enough features found, try increasing max. number of features by factor 4 - dist_result = calcDistortion (thumbGray, rawGray, width, h_thumb, 4, dist_amount); - delete thumbGray; - delete rawGray; - delete thumb; - delete raw; - return dist_amount; - } - else - return 0.0; - } + whiteclipg = CurveFactory::igamma2 ((float)(whiteclipg / 65535.0)) * 65535.0; //need to inverse gamma transform to get correct exposure compensation parameter - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //corection with gamma + black = (int)((65535 * black) / whiteclipg); + //expcomp = log(65535.0 / (whiteclipg)) / log(2.0); + + //diagnostics + //printf ("**************** AUTO LEVELS ****************\n"); + /* + if (settings->verbose) { + printf("sum=%i clip=%f clippable=%i clipWh=%i clipBl=%i\n",somm, clip, clippable,clipwh, clipbl); + printf ("expcomp1= %f expcomp2= %f gain= %f expcomp=%f\n",expcomp1,expcomp2,gain,expcomp); + printf ("expo=%f\n",expo); + printf ("median: %i average: %f median/average: %f\n",median,ave, median/ave); + printf ("average: %f\n",ave); + printf("comp=%f hlcomp: %i\n",comp, hlcompr); + printf ("median/average: %f\n",median/ave); + printf ("lodev: %f hidev: %f hidev/lodev: %f\n",lodev,hidev,hidev/lodev); + printf ("lodev: %f\n",lodev); + printf ("hidev: %f\n",hidev); + printf ("imax=%d rawmax= %d whiteclip= %d gain= %f\n",imax,rawmax,whiteclip,gain); + printf ("octiles: %f %f %f %f %f %f %f %f\n",octile[0],octile[1],octile[2],octile[3],octile[4],octile[5],octile[6],octile[7]); + printf ("ospread= %f\n",ospread); + printf ("overexp= %i\n",overex); + } + */ + /* + // %%%%%%%%%% LEGACY AUTOEXPOSURE CODE %%%%%%%%%%%%% + // black point selection is based on the linear result (yielding better visual results) + black = (int)(shc * corr); + // compute the white point of the exp. compensated gamma corrected image + double whiteclipg = (int)(CurveFactory::gamma2 (whiteclip * corr / 65536.0) * 65536.0); + + // compute average intensity of the exp compensated, gamma corrected image + double gavg = 0; + for (int i=0; i<65536>>histcompr; i++) + gavg += histogram[i] * CurveFactory::gamma2((int)(corr*(i< 12.0) { + expcomp = 12.0; + } + + bright = max(-100, min(bright, 100)); +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_size) +{ + if (fname != "") { + rtengine::RawMetaDataLocation ri; + int w_raw = -1, h_raw = thumb_size; + int w_thumb = -1, h_thumb = thumb_size; + + Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, w_thumb, h_thumb, 1, FALSE); + + if (thumb == NULL) { + return 0.0; + } + + Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE); + + if (raw == NULL) { + delete thumb; + return 0.0; + } + + if (h_thumb != h_raw) { + delete thumb; + delete raw; + return 0.0; + } + + int width; + + if (w_thumb > w_raw) { + width = w_raw; + } else { + width = w_thumb; + } + + unsigned char* thumbGray; + unsigned char* rawGray; + thumbGray = thumb->getGrayscaleHistEQ (width); + rawGray = raw->getGrayscaleHistEQ (width); + + if (thumbGray == NULL || rawGray == NULL) { + if (thumbGray) { + delete thumbGray; + } + + if (rawGray) { + delete rawGray; + } + + delete thumb; + delete raw; + return 0.0; + } + + double dist_amount; + int dist_result = calcDistortion (thumbGray, rawGray, width, h_thumb, 1, dist_amount); + + if(dist_result == -1) { // not enough features found, try increasing max. number of features by factor 4 + dist_result = calcDistortion (thumbGray, rawGray, width, h_thumb, 4, dist_amount); + } + + delete thumbGray; + delete rawGray; + delete thumb; + delete raw; + return dist_amount; + } else { + return 0.0; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } #undef PIX_SORT diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 4400653a3..c18d7ea69 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -7,7 +7,7 @@ * 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 @@ -49,329 +49,342 @@ PIX_SORT(pp[4],pp[2]); median=pp[4];} //pp4 = median -namespace rtengine { +namespace rtengine +{ using namespace procparams; -class ImProcFunctions { +class ImProcFunctions +{ - static LUTf gamma2curve; + static LUTf gamma2curve; - cmsHTRANSFORM monitorTransform; + cmsHTRANSFORM monitorTransform; - const ProcParams* params; - double scale; - bool multiThread; + const ProcParams* params; + double scale; + bool multiThread; - void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul); + void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul); - void transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap); - void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH); - void transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap, bool fullImage); + void transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap); + void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH); + void transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap, bool fullImage); - void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H, SharpeningParams &sharpenParam); - void sharpenHaloCtrlcam (CieImage* ncie, float** blurmap, float** base, int W, int H); - void firstAnalysisThread(Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to); - void dcdamping (float** aI, float** aO, float damping, int W, int H); + void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H, SharpeningParams &sharpenParam); + void sharpenHaloCtrlcam (CieImage* ncie, float** blurmap, float** base, int W, int H); + void firstAnalysisThread(Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to); + void dcdamping (float** aI, float** aO, float damping, int W, int H); - bool needsCA (); - bool needsDistortion (); - bool needsRotation (); - bool needsPerspective (); - bool needsGradient (); - bool needsVignetting (); - bool needsLCP (); - // static cmsUInt8Number* Mempro = NULL; + bool needsCA (); + bool needsDistortion (); + bool needsRotation (); + bool needsPerspective (); + bool needsGradient (); + bool needsVignetting (); + bool needsLCP (); +// static cmsUInt8Number* Mempro = NULL; - inline void interpolateTransformCubic (Imagefloat* src, int xs, int ys, double Dx, double Dy, float *r, float *g, float *b, double mul) { - const double A=-0.85; + inline void interpolateTransformCubic (Imagefloat* src, int xs, int ys, double Dx, double Dy, float *r, float *g, float *b, double mul) + { + const double A = -0.85; - double w[4]; + double w[4]; - { - double t1, t2; - t1 = -A*(Dx-1.0)*Dx; - t2 = (3.0-2.0*Dx)*Dx*Dx; - w[3] = t1*Dx; - w[2] = t1*(Dx-1.0) + t2; - w[1] = -t1*Dx + 1.0 - t2; - w[0] = -t1*(Dx-1.0); - } + { + double t1, t2; + t1 = -A * (Dx - 1.0) * Dx; + t2 = (3.0 - 2.0 * Dx) * Dx * Dx; + w[3] = t1 * Dx; + w[2] = t1 * (Dx - 1.0) + t2; + w[1] = -t1 * Dx + 1.0 - t2; + w[0] = -t1 * (Dx - 1.0); + } - double rd, gd, bd; - double yr[4], yg[4], yb[4]; + double rd, gd, bd; + double yr[4], yg[4], yb[4]; - for (int k=ys, kx=0; kr(k,i) * w[ix]; - gd += src->g(k,i) * w[ix]; - bd += src->b(k,i) * w[ix]; - } - yr[kx] = rd; yg[kx] = gd; yb[kx] = bd; - } + for (int k = ys, kx = 0; k < ys + 4; k++, kx++) { + rd = gd = bd = 0.0; + + for (int i = xs, ix = 0; i < xs + 4; i++, ix++) { + rd += src->r(k, i) * w[ix]; + gd += src->g(k, i) * w[ix]; + bd += src->b(k, i) * w[ix]; + } + + yr[kx] = rd; + yg[kx] = gd; + yb[kx] = bd; + } - { - double t1, t2; + { + double t1, t2; - t1 = -A*(Dy-1.0)*Dy; - t2 = (3.0-2.0*Dy)*Dy*Dy; - w[3] = t1*Dy; - w[2] = t1*(Dy-1.0) + t2; - w[1] = -t1*Dy + 1.0 - t2; - w[0] = -t1*(Dy-1.0); - } + t1 = -A * (Dy - 1.0) * Dy; + t2 = (3.0 - 2.0 * Dy) * Dy * Dy; + w[3] = t1 * Dy; + w[2] = t1 * (Dy - 1.0) + t2; + w[1] = -t1 * Dy + 1.0 - t2; + w[0] = -t1 * (Dy - 1.0); + } - rd = gd = bd = 0.0; - for (int i=0; i<4; i++) { - rd += yr[i] * w[i]; - gd += yg[i] * w[i]; - bd += yb[i] * w[i]; - } + rd = gd = bd = 0.0; - *r = rd * mul; - *g = gd * mul; - *b = bd * mul; + for (int i = 0; i < 4; i++) { + rd += yr[i] * w[i]; + gd += yg[i] * w[i]; + bd += yb[i] * w[i]; + } - // if (xs==100 && ys==100) - // printf ("r=%g, g=%g\n", *r, *g); - } + *r = rd * mul; + *g = gd * mul; + *b = bd * mul; - inline void interpolateTransformChannelsCubic (float** src, int xs, int ys, double Dx, double Dy, float *r, double mul) { - const double A=-0.85; + // if (xs==100 && ys==100) + // printf ("r=%g, g=%g\n", *r, *g); + } - double w[4]; + inline void interpolateTransformChannelsCubic (float** src, int xs, int ys, double Dx, double Dy, float *r, double mul) + { + const double A = -0.85; - { - double t1, t2; - t1 = -A*(Dx-1.0)*Dx; - t2 = (3.0-2.0*Dx)*Dx*Dx; - w[3] = t1*Dx; - w[2] = t1*(Dx-1.0) + t2; - w[1] = -t1*Dx + 1.0 - t2; - w[0] = -t1*(Dx-1.0); - } + double w[4]; - double rd; - double yr[4]; + { + double t1, t2; + t1 = -A * (Dx - 1.0) * Dx; + t2 = (3.0 - 2.0 * Dx) * Dx * Dx; + w[3] = t1 * Dx; + w[2] = t1 * (Dx - 1.0) + t2; + w[1] = -t1 * Dx + 1.0 - t2; + w[0] = -t1 * (Dx - 1.0); + } - for (int k=ys, kx=0; kdefault - // CieImage *ciec; + bool WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]); + bool WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab, + const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb); + void ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madaL, float * vari, int edge); + void ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir, + float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * madaab = NULL, bool madCalculated = false); + void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b, int level, + int W_ab, int H_ab, int skip_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float noisevar_abr, float noisevar_abb, LabImage * noi, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, bool autoch, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, + float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb, bool multiThread); + void Noise_residualAB(wavelet_decomposition &WaveletCoeffs_ab, float &chresid, float &chmaxresid, bool denoiseMethodRgb); + void calcautodn_info (float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc); + float MadMax(float * HH_Coeffs, int &max, int datalen); + float Mad(float * DataList, const int datalen); + float MadRgb(float * DataList, const int datalen); - bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap=NULL); - bool transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LCPMapper *pLCPMap=NULL); - 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); + // pyramid wavelet + void dirpyr_equalizer (float ** src, float ** dst, int srcwidth, int srcheight, float ** l_a, float ** l_b, float ** dest_a, float ** dest_b, const double * mult, const double dirpyrThreshold, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale);//Emil's directional pyramid wavelet + void dirpyr_equalizercam (CieImage* ncie, float ** src, float ** dst, int srcwidth, int srcheight, float ** h_p, float ** C_p, const double * mult, const double dirpyrThreshold, const double skinprot, bool execdir, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice, int scale);//Emil's directional pyramid wavelet + void dirpyr_channel (float ** data_fine, float ** data_coarse, int width, int height, int level, int scale); + void idirpyr_eq_channel (float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, const bool gamutlab, float b_l, float t_l, float t_r, float b_r, int choice); + void idirpyr_eq_channelcam (float ** data_coarse, float ** data_fine, float ** buffer, int width, int height, int level, float multi[5], const double dirpyrThreshold, float ** l_a_h, float ** l_b_c, const double skinprot, float b_l, float t_l, float t_r); + void defringe (LabImage* lab); + void defringecam (CieImage* ncie); + void badpixcam (CieImage* ncie, double rad, int thr, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad); + void badpixlab (LabImage* lab, double rad, int thr, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom); + + void PF_correct_RT (LabImage * src, LabImage * dst, double radius, int thresh); + void PF_correct_RTcam (CieImage * src, CieImage * dst, double radius, int thresh); + void Badpixelscam(CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad); + void BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom); + + Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool standard_gamma); + Image16* lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw);// for gamma output + Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool bw);//without gamma ==>default + // CieImage *ciec; + + bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap = NULL); + bool transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LCPMapper *pLCPMap = NULL); + 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); }; } #endif diff --git a/rtengine/impulse_denoise.h b/rtengine/impulse_denoise.h index 3151e8ec0..1c89021e7 100644 --- a/rtengine/impulse_denoise.h +++ b/rtengine/impulse_denoise.h @@ -27,120 +27,140 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ SSEFUNCTION void ImProcFunctions::impulse_nr (LabImage* lab, double thresh) { - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // impulse noise removal - // local variables + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // impulse noise removal + // local variables - int width = lab->W; - int height = lab->H; + int width = lab->W; + int height = lab->H; - // buffer for the lowpass image + // buffer for the lowpass image float ** lpf = new float *[height]; - // buffer for the highpass image + // buffer for the highpass image float ** impish = new float *[height]; - for (int i=0; i (lab->L, lpf, impish /*used as buffer here*/, width, height, thresh, false); + //rangeblur (lab->L, lpf, impish /*used as buffer here*/, width, height, thresh, false); #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif { - AlignedBufferMP buffer(max(width,height)); + AlignedBufferMP buffer(max(width, height)); - gaussHorizontal (lab->L, lpf, buffer, width, height, max(2.0,thresh-1.0)); - gaussVertical (lpf, lpf, buffer, width, height, max(2.0,thresh-1.0)); + gaussHorizontal (lab->L, lpf, buffer, width, height, max(2.0, thresh - 1.0)); + gaussVertical (lpf, lpf, buffer, width, height, max(2.0, thresh - 1.0)); } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - float impthr = max(1.0,5.5-thresh); - float impthrDiv24 = impthr / 24.0f; //Issue 1671: moved the Division outside the loop, impthr can be optimized out too, but I let in the code at the moment + float impthr = max(1.0, 5.5 - thresh); + float impthrDiv24 = impthr / 24.0f; //Issue 1671: moved the Division outside the loop, impthr can be optimized out too, but I let in the code at the moment #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int i1,j1,j; - float hpfabs, hfnbrave; + { + int i1, j1, j; + float hpfabs, hfnbrave; #ifdef __SSE2__ - __m128 hfnbravev,hpfabsv; - __m128 impthrDiv24v = _mm_set1_ps( impthrDiv24 ); - __m128 onev = _mm_set1_ps( 1.0f ); + __m128 hfnbravev, hpfabsv; + __m128 impthrDiv24v = _mm_set1_ps( impthrDiv24 ); + __m128 onev = _mm_set1_ps( 1.0f ); #endif #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - hpfabs = fabs(lab->L[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++) { - hfnbrave += fabs(lab->L[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + hpfabs = fabs(lab->L[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++) { + hfnbrave += fabs(lab->L[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + #ifdef __SSE2__ - for (; j < width-5; j+=4) { - hfnbravev = _mm_setzero_ps( ); - hpfabsv = vabsf(LVFU(lab->L[i][j])-LVFU(lpf[i][j])); - //block average of high pass data - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++) { - hfnbravev += vabsf(LVFU(lab->L[i1][j1])-LVFU(lpf[i1][j1])); - } - _mm_storeu_ps(&impish[i][j], vself(vmaskf_gt(hpfabsv, (hfnbravev-hpfabsv)*impthrDiv24v), onev, _mm_setzero_ps())); - } - for (; j < width-2; j++) { - hpfabs = fabs(lab->L[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++) { - hfnbrave += fabs(lab->L[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } + + for (; j < width - 5; j += 4) { + hfnbravev = _mm_setzero_ps( ); + hpfabsv = vabsf(LVFU(lab->L[i][j]) - LVFU(lpf[i][j])); + + //block average of high pass data + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++) { + hfnbravev += vabsf(LVFU(lab->L[i1][j1]) - LVFU(lpf[i1][j1])); + } + + _mm_storeu_ps(&impish[i][j], vself(vmaskf_gt(hpfabsv, (hfnbravev - hpfabsv)*impthrDiv24v), onev, _mm_setzero_ps())); + } + + for (; j < width - 2; j++) { + hpfabs = fabs(lab->L[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++) { + hfnbrave += fabs(lab->L[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + #else - for (; j < width-2; j++) { - hpfabs = fabs(lab->L[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++) { - hfnbrave += fabs(lab->L[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } + + for (; j < width - 2; j++) { + hpfabs = fabs(lab->L[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++) { + hfnbrave += fabs(lab->L[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + #endif - for (; j < width; j++) { - hpfabs = fabs(lab->L[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1L[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } - } -} + + for (; j < width; j++) { + hpfabs = fabs(lab->L[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++) { + hfnbrave += fabs(lab->L[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + } + } //now impulsive values have been identified @@ -151,240 +171,301 @@ SSEFUNCTION void ImProcFunctions::impulse_nr (LabImage* lab, double thresh) // choice for the chunk_size than 16 // race conditions are avoided by the array impish #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int i1,j1,j; - float wtdsum[3], dirwt, norm; + { + int i1, j1, j; + float wtdsum[3], dirwt, norm; #ifdef _OPENMP -#pragma omp for schedule(dynamic,16) + #pragma omp for schedule(dynamic,16) #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - if (!impish[i][j]) continue; - norm=0.0; - wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (impish[i1][j1]) continue; - dirwt = 1/(SQR(lab->L[i1][j1]-lab->L[i][j])+eps);//use more sophisticated rangefn??? - wtdsum[0] += dirwt*lab->L[i1][j1]; - wtdsum[1] += dirwt*lab->a[i1][j1]; - wtdsum[2] += dirwt*lab->b[i1][j1]; - norm += dirwt; - } - if (norm) { - lab->L[i][j]=wtdsum[0]/norm;//low pass filter - lab->a[i][j]=wtdsum[1]/norm;//low pass filter - lab->b[i][j]=wtdsum[2]/norm;//low pass filter - } - } - for (; j < width-2; j++) { - if (!impish[i][j]) continue; - norm=0.0; - wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (impish[i1][j1]) continue; - dirwt = 1/(SQR(lab->L[i1][j1]-lab->L[i][j])+eps);//use more sophisticated rangefn??? - wtdsum[0] += dirwt*lab->L[i1][j1]; - wtdsum[1] += dirwt*lab->a[i1][j1]; - wtdsum[2] += dirwt*lab->b[i1][j1]; - norm += dirwt; - } - if (norm) { - lab->L[i][j]=wtdsum[0]/norm;//low pass filter - lab->a[i][j]=wtdsum[1]/norm;//low pass filter - lab->b[i][j]=wtdsum[2]/norm;//low pass filter - } - } - for (; j < width; j++) { - if (!impish[i][j]) continue; - norm=0.0; - wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1L[i1][j1]-lab->L[i][j])+eps);//use more sophisticated rangefn??? - wtdsum[0] += dirwt*lab->L[i1][j1]; - wtdsum[1] += dirwt*lab->a[i1][j1]; - wtdsum[2] += dirwt*lab->b[i1][j1]; - norm += dirwt; - } - if (norm) { - lab->L[i][j]=wtdsum[0]/norm;//low pass filter - lab->a[i][j]=wtdsum[1]/norm;//low pass filter - lab->b[i][j]=wtdsum[2]/norm;//low pass filter - } - } - } -} + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + if (!impish[i][j]) { + continue; + } + + norm = 0.0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (impish[i1][j1]) { + continue; + } + + dirwt = 1 / (SQR(lab->L[i1][j1] - lab->L[i][j]) + eps); //use more sophisticated rangefn??? + wtdsum[0] += dirwt * lab->L[i1][j1]; + wtdsum[1] += dirwt * lab->a[i1][j1]; + wtdsum[2] += dirwt * lab->b[i1][j1]; + norm += dirwt; + } + + if (norm) { + lab->L[i][j] = wtdsum[0] / norm; //low pass filter + lab->a[i][j] = wtdsum[1] / norm; //low pass filter + lab->b[i][j] = wtdsum[2] / norm; //low pass filter + } + } + + for (; j < width - 2; j++) { + if (!impish[i][j]) { + continue; + } + + norm = 0.0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (impish[i1][j1]) { + continue; + } + + dirwt = 1 / (SQR(lab->L[i1][j1] - lab->L[i][j]) + eps); //use more sophisticated rangefn??? + wtdsum[0] += dirwt * lab->L[i1][j1]; + wtdsum[1] += dirwt * lab->a[i1][j1]; + wtdsum[2] += dirwt * lab->b[i1][j1]; + norm += dirwt; + } + + if (norm) { + lab->L[i][j] = wtdsum[0] / norm; //low pass filter + lab->a[i][j] = wtdsum[1] / norm; //low pass filter + lab->b[i][j] = wtdsum[2] / norm; //low pass filter + } + } + + for (; j < width; j++) { + if (!impish[i][j]) { + continue; + } + + norm = 0.0; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (impish[i1][j1]) { + continue; + } + + dirwt = 1 / (SQR(lab->L[i1][j1] - lab->L[i][j]) + eps); //use more sophisticated rangefn??? + wtdsum[0] += dirwt * lab->L[i1][j1]; + wtdsum[1] += dirwt * lab->a[i1][j1]; + wtdsum[2] += dirwt * lab->b[i1][j1]; + norm += dirwt; + } + + if (norm) { + lab->L[i][j] = wtdsum[0] / norm; //low pass filter + lab->a[i][j] = wtdsum[1] / norm; //low pass filter + lab->b[i][j] = wtdsum[2] / norm; //low pass filter + } + } + } + } //now impulsive values have been corrected - for (int i=0; iW; - int height = ncie->H; + int width = ncie->W; + int height = ncie->H; - - float piid=3.14159265f/180.f; - // buffer for the lowpass image + float piid = 3.14159265f / 180.f; + + // buffer for the lowpass image float ** lpf = buffers[0]; - // buffer for the highpass image + // buffer for the highpass image float ** impish = buffers[1]; - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // modified bilateral filter for lowpass image, omitting input pixel; or Gaussian blur + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // modified bilateral filter for lowpass image, omitting input pixel; or Gaussian blur - - //The cleaning algorithm starts here - //rangeblur (lab->L, lpf, impish /*used as buffer here*/, width, height, thresh, false); + //The cleaning algorithm starts here + + //rangeblur (lab->L, lpf, impish /*used as buffer here*/, width, height, thresh, false); #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif { - AlignedBufferMP buffer(max(width,height)); - gaussHorizontal (ncie->sh_p, lpf, buffer, width, height, max(2.0,thresh-1.0)); - gaussVertical (lpf, lpf, buffer, width, height, max(2.0,thresh-1.0)); + AlignedBufferMP buffer(max(width, height)); + gaussHorizontal (ncie->sh_p, lpf, buffer, width, height, max(2.0, thresh - 1.0)); + gaussVertical (lpf, lpf, buffer, width, height, max(2.0, thresh - 1.0)); } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - float impthr = max(1.0f,5.0f-(float)thresh); - float impthrDiv24 = impthr / 24.0f; //Issue 1671: moved the Division outside the loop, impthr can be optimized out too, but I let in the code at the moment + float impthr = max(1.0f, 5.0f - (float)thresh); + float impthrDiv24 = impthr / 24.0f; //Issue 1671: moved the Division outside the loop, impthr can be optimized out too, but I let in the code at the moment #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int i1,j1,j; - float hpfabs, hfnbrave; + { + int i1, j1, j; + float hpfabs, hfnbrave; #ifdef __SSE2__ - __m128 hfnbravev,hpfabsv; - __m128 impthrDiv24v = _mm_set1_ps( impthrDiv24 ); - __m128 onev = _mm_set1_ps( 1.0f ); + __m128 hfnbravev, hpfabsv; + __m128 impthrDiv24v = _mm_set1_ps( impthrDiv24 ); + __m128 onev = _mm_set1_ps( 1.0f ); #endif #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - hpfabs = fabs(ncie->sh_p[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++) { - hfnbrave += fabs(ncie->sh_p[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + hpfabs = fabs(ncie->sh_p[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++) { + hfnbrave += fabs(ncie->sh_p[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + #ifdef __SSE2__ - for (; j < width-5; j+=4) { - hpfabsv = vabsf(LVFU(ncie->sh_p[i][j])-LVFU(lpf[i][j])); - hfnbravev = _mm_setzero_ps(); - //block average of high pass data - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) { - for (j1=j-2; j1<=j+2; j1++ ) { - hfnbravev += vabsf(LVFU(ncie->sh_p[i1][j1])-LVFU(lpf[i1][j1])); - } - _mm_storeu_ps(&impish[i][j], vself(vmaskf_gt(hpfabsv, (hfnbravev-hpfabsv)*impthrDiv24v), onev, _mm_setzero_ps())); - } - } - for (; j < width-2; j++) { - hpfabs = fabs(ncie->sh_p[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - hfnbrave += fabs(ncie->sh_p[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } + + for (; j < width - 5; j += 4) { + hpfabsv = vabsf(LVFU(ncie->sh_p[i][j]) - LVFU(lpf[i][j])); + hfnbravev = _mm_setzero_ps(); + + //block average of high pass data + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) { + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + hfnbravev += vabsf(LVFU(ncie->sh_p[i1][j1]) - LVFU(lpf[i1][j1])); + } + + _mm_storeu_ps(&impish[i][j], vself(vmaskf_gt(hpfabsv, (hfnbravev - hpfabsv)*impthrDiv24v), onev, _mm_setzero_ps())); + } + } + + for (; j < width - 2; j++) { + hpfabs = fabs(ncie->sh_p[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + hfnbrave += fabs(ncie->sh_p[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + #else - for (; j < width-2; j++) { - hpfabs = fabs(ncie->sh_p[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - hfnbrave += fabs(ncie->sh_p[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } + + for (; j < width - 2; j++) { + hpfabs = fabs(ncie->sh_p[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + hfnbrave += fabs(ncie->sh_p[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + #endif - for (; j < width; j++) { - hpfabs = fabs(ncie->sh_p[i][j]-lpf[i][j]); - //block average of high pass data - for (i1=max(0,i-2), hfnbrave=0; i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1sh_p[i1][j1]-lpf[i1][j1]); - } - impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); - } - } -} + + for (; j < width; j++) { + hpfabs = fabs(ncie->sh_p[i][j] - lpf[i][j]); + + //block average of high pass data + for (i1 = max(0, i - 2), hfnbrave = 0; i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + hfnbrave += fabs(ncie->sh_p[i1][j1] - lpf[i1][j1]); + } + + impish[i][j] = (hpfabs > ((hfnbrave - hpfabs) * impthrDiv24)); + } + } + } //now impulsive values have been identified - - const float eps = 1.0f; - float** sraa = buffers[0]; // we can reuse buffers[0] because lpf is not needed anymore at this point - float** srbb = buffers[2]; + const float eps = 1.0f; + + float** sraa = buffers[0]; // we can reuse buffers[0] because lpf is not needed anymore at this point + float** srbb = buffers[2]; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int j; - float2 sincosval; + { + int j; + float2 sincosval; #ifdef __SSE2__ - vfloat2 sincosvalv; - __m128 piidv = _mm_set1_ps( piid ); - __m128 tempv; + vfloat2 sincosvalv; + __m128 piidv = _mm_set1_ps( piid ); + __m128 tempv; #endif #ifdef _OPENMP -#pragma omp for -#endif - for (int i=0; ih_p[i][j])); - tempv = LVFU(ncie->C_p[i][j]); - _mm_storeu_ps(&sraa[i][j], tempv * sincosvalv.y); - _mm_storeu_ps(&srbb[i][j], tempv * sincosvalv.x); - } - for (; jh_p[i][j]); - sraa[i][j]=ncie->C_p[i][j]*sincosval.y; - srbb[i][j]=ncie->C_p[i][j]*sincosval.x; - } + + for (j = 0; j < width - 3; j += 4) { + sincosvalv = xsincosf(piidv * LVFU(ncie->h_p[i][j])); + tempv = LVFU(ncie->C_p[i][j]); + _mm_storeu_ps(&sraa[i][j], tempv * sincosvalv.y); + _mm_storeu_ps(&srbb[i][j], tempv * sincosvalv.x); + } + + for (; j < width; j++) { + sincosval = xsincosf(piid * ncie->h_p[i][j]); + sraa[i][j] = ncie->C_p[i][j] * sincosval.y; + srbb[i][j] = ncie->C_p[i][j] * sincosval.x; + } + #else - for (j=0; jh_p[i][j]); - sraa[i][j]=ncie->C_p[i][j]*sincosval.y; - srbb[i][j]=ncie->C_p[i][j]*sincosval.x; - } + + for (j = 0; j < width; j++) { + sincosval = xsincosf(piid * ncie->h_p[i][j]); + sraa[i][j] = ncie->C_p[i][j] * sincosval.y; + srbb[i][j] = ncie->C_p[i][j] * sincosval.x; + } + #endif - } -} - + } + } + // Issue 1671: // often, noise isn't evenly distributed, e.g. only a few noisy pixels in the bright sky, but many in the dark foreground, // so it's better to schedule dynamic and let every thread only process 16 rows, to avoid running big threads out of work @@ -392,117 +473,158 @@ SSEFUNCTION void ImProcFunctions::impulse_nrcam (CieImage* ncie, double thresh, // choice for the chunk_size than 16 // race conditions are avoided by the array impish #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - int i1,j1,j; - float wtdsum[3], dirwt, norm; + { + int i1, j1, j; + float wtdsum[3], dirwt, norm; #ifdef _OPENMP -#pragma omp for schedule(dynamic,16) + #pragma omp for schedule(dynamic,16) #endif - for (int i=0; i < height; i++) { - for (j=0; j < 2; j++) { - if (!impish[i][j]) continue; - norm=0.0f; - wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=0; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (impish[i1][j1]) continue; - dirwt = 1.f/(SQR(ncie->sh_p[i1][j1]-ncie->sh_p[i][j])+eps);//use more sophisticated rangefn??? - wtdsum[0] += dirwt*ncie->sh_p[i1][j1]; - wtdsum[1] += dirwt*sraa[i1][j1]; - wtdsum[2] += dirwt*srbb[i1][j1]; - norm += dirwt; - } - if (norm) { - ncie->sh_p[i][j]=wtdsum[0]/norm;//low pass filter - sraa[i][j]=wtdsum[1]/norm;//low pass filter - srbb[i][j]=wtdsum[2]/norm;//low pass filter - } - } - for (; j < width-2; j++) { - if (!impish[i][j]) continue; - norm=0.0f; - wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1<=j+2; j1++ ) { - if (i1==i && j1==j) continue; - if (impish[i1][j1]) continue; - dirwt = 1.f/(SQR(ncie->sh_p[i1][j1]-ncie->sh_p[i][j])+eps);//use more sophisticated rangefn??? - wtdsum[0] += dirwt*ncie->sh_p[i1][j1]; - wtdsum[1] += dirwt*sraa[i1][j1]; - wtdsum[2] += dirwt*srbb[i1][j1]; - norm += dirwt; - } - if (norm) { - ncie->sh_p[i][j]=wtdsum[0]/norm;//low pass filter - sraa[i][j]=wtdsum[1]/norm;//low pass filter - srbb[i][j]=wtdsum[2]/norm;//low pass filter - } - } - for (; j < width; j++) { - if (!impish[i][j]) continue; - norm=0.0f; - wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0f; - for (i1=max(0,i-2); i1<=min(i+2,height-1); i1++ ) - for (j1=j-2; j1sh_p[i1][j1]-ncie->sh_p[i][j])+eps);//use more sophisticated rangefn??? - wtdsum[0] += dirwt*ncie->sh_p[i1][j1]; - wtdsum[1] += dirwt*sraa[i1][j1]; - wtdsum[2] += dirwt*srbb[i1][j1]; - norm += dirwt; - } - if (norm) { - ncie->sh_p[i][j]=wtdsum[0]/norm;//low pass filter - sraa[i][j]=wtdsum[1]/norm;//low pass filter - srbb[i][j]=wtdsum[2]/norm;//low pass filter - } - } - } -} + + for (int i = 0; i < height; i++) { + for (j = 0; j < 2; j++) { + if (!impish[i][j]) { + continue; + } + + norm = 0.0f; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = 0; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (impish[i1][j1]) { + continue; + } + + dirwt = 1.f / (SQR(ncie->sh_p[i1][j1] - ncie->sh_p[i][j]) + eps); //use more sophisticated rangefn??? + wtdsum[0] += dirwt * ncie->sh_p[i1][j1]; + wtdsum[1] += dirwt * sraa[i1][j1]; + wtdsum[2] += dirwt * srbb[i1][j1]; + norm += dirwt; + } + + if (norm) { + ncie->sh_p[i][j] = wtdsum[0] / norm; //low pass filter + sraa[i][j] = wtdsum[1] / norm; //low pass filter + srbb[i][j] = wtdsum[2] / norm; //low pass filter + } + } + + for (; j < width - 2; j++) { + if (!impish[i][j]) { + continue; + } + + norm = 0.0f; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 <= j + 2; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (impish[i1][j1]) { + continue; + } + + dirwt = 1.f / (SQR(ncie->sh_p[i1][j1] - ncie->sh_p[i][j]) + eps); //use more sophisticated rangefn??? + wtdsum[0] += dirwt * ncie->sh_p[i1][j1]; + wtdsum[1] += dirwt * sraa[i1][j1]; + wtdsum[2] += dirwt * srbb[i1][j1]; + norm += dirwt; + } + + if (norm) { + ncie->sh_p[i][j] = wtdsum[0] / norm; //low pass filter + sraa[i][j] = wtdsum[1] / norm; //low pass filter + srbb[i][j] = wtdsum[2] / norm; //low pass filter + } + } + + for (; j < width; j++) { + if (!impish[i][j]) { + continue; + } + + norm = 0.0f; + wtdsum[0] = wtdsum[1] = wtdsum[2] = 0.0f; + + for (i1 = max(0, i - 2); i1 <= min(i + 2, height - 1); i1++ ) + for (j1 = j - 2; j1 < width; j1++ ) { + if (i1 == i && j1 == j) { + continue; + } + + if (impish[i1][j1]) { + continue; + } + + dirwt = 1.f / (SQR(ncie->sh_p[i1][j1] - ncie->sh_p[i][j]) + eps); //use more sophisticated rangefn??? + wtdsum[0] += dirwt * ncie->sh_p[i1][j1]; + wtdsum[1] += dirwt * sraa[i1][j1]; + wtdsum[2] += dirwt * srbb[i1][j1]; + norm += dirwt; + } + + if (norm) { + ncie->sh_p[i][j] = wtdsum[0] / norm; //low pass filter + sraa[i][j] = wtdsum[1] / norm; //low pass filter + srbb[i][j] = wtdsum[2] / norm; //low pass filter + } + } + } + } //now impulsive values have been corrected #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef __SSE2__ - __m128 interav,interbv; - __m128 piidv = _mm_set1_ps(piid); + __m128 interav, interbv; + __m128 piidv = _mm_set1_ps(piid); #endif // __SSE2__ - int j; + int j; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++ ) { + + for(int i = 0; i < height; i++ ) { #ifdef __SSE2__ - for(j = 0; j < width-3; j+=4) { - interav = LVFU(sraa[i][j]); - interbv = LVFU(srbb[i][j]); - _mm_storeu_ps(&ncie->h_p[i][j],(xatan2f(interbv,interav))/piidv); - _mm_storeu_ps(&ncie->C_p[i][j], _mm_sqrt_ps(SQRV(interbv)+SQRV(interav))); - } - for(; j < width; j++) { - float intera = sraa[i][j]; - float interb = srbb[i][j]; - ncie->h_p[i][j]=(xatan2f(interb,intera))/piid; - ncie->C_p[i][j]=sqrt(SQR(interb)+SQR(intera)); - } + + for(j = 0; j < width - 3; j += 4) { + interav = LVFU(sraa[i][j]); + interbv = LVFU(srbb[i][j]); + _mm_storeu_ps(&ncie->h_p[i][j], (xatan2f(interbv, interav)) / piidv); + _mm_storeu_ps(&ncie->C_p[i][j], _mm_sqrt_ps(SQRV(interbv) + SQRV(interav))); + } + + for(; j < width; j++) { + float intera = sraa[i][j]; + float interb = srbb[i][j]; + ncie->h_p[i][j] = (xatan2f(interb, intera)) / piid; + ncie->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); + } #else - for(j = 0; j < width; j++) { - float intera = sraa[i][j]; - float interb = srbb[i][j]; - ncie->h_p[i][j]=(xatan2f(interb,intera))/piid; - ncie->C_p[i][j]=sqrt(SQR(interb)+SQR(intera)); - } + + for(j = 0; j < width; j++) { + float intera = sraa[i][j]; + float interb = srbb[i][j]; + ncie->h_p[i][j] = (xatan2f(interb, intera)) / piid; + ncie->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); + } + #endif - } -} + } + } } diff --git a/rtengine/init.cc b/rtengine/init.cc index 19b0aa6b9..1fdcb6438 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -7,7 +7,7 @@ * 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 @@ -30,17 +30,19 @@ #include "../rtgui/profilestore.h" #include "../rtgui/threadutils.h" -namespace rtengine { +namespace rtengine +{ const Settings* settings; MyMutex* lcmsMutex = NULL; -int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir) { +int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir) +{ settings = s; iccStore->init (s->iccDirectory, baseDir + "/iccprofiles"); - iccStore->findDefaultMonitorProfile(); + iccStore->findDefaultMonitorProfile(); dcpStore->init (baseDir + "/dcpprofiles"); @@ -56,10 +58,11 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi lcmsMutex = new MyMutex; dfm.init( s->darkFramesPath ); ffm.init( s->flatFieldsPath ); - return 0; + return 0; } -void cleanup () { +void cleanup () +{ ProcParams::cleanup (); Color::cleanup (); @@ -69,24 +72,28 @@ void cleanup () { RawImageSource::cleanup (); } -StagedImageProcessor* StagedImageProcessor::create (InitialImage* initialImage) { +StagedImageProcessor* StagedImageProcessor::create (InitialImage* initialImage) +{ ImProcCoordinator* ipc = new ImProcCoordinator (); ipc->assign (initialImage->getImageSource ()); return ipc; } -void StagedImageProcessor::destroy (StagedImageProcessor* sip) { +void StagedImageProcessor::destroy (StagedImageProcessor* sip) +{ delete sip; } -Settings* Settings::create () { - +Settings* Settings::create () +{ + return new Settings; } -void Settings::destroy (Settings* s) { +void Settings::destroy (Settings* s) +{ delete s; } diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 44783afe6..169516181 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -27,21 +27,23 @@ #include "alignedbuffer.h" #include "color.h" -namespace rtengine { +namespace rtengine +{ #define CLIP01(a) ((a)>0?((a)<1?(a):1):0) - + extern const Settings* settings; - + const double (*wprof[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best}; const double (*iwprof[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz}; const char* wprofnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB", "Beta RGB", "BestRGB"}; const int numprof = 7; -void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) { - //gamutmap(lab); +void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) +{ + //gamutmap(lab); - if (monitorTransform) { + if (monitorTransform) { int W = lab->W; int H = lab->H; @@ -49,88 +51,102 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) { // cmsDoTransform is relatively expensive #ifdef _OPENMP -#pragma omp parallel firstprivate(lab, data, W, H) + #pragma omp parallel firstprivate(lab, data, W, H) #endif -{ - AlignedBuffer pBuf(3*lab->W); - double *buffer=pBuf.data; + { + AlignedBuffer pBuf(3 * lab->W); + double *buffer = pBuf.data; #ifdef _OPENMP -#pragma omp for schedule(dynamic,16) + #pragma omp for schedule(dynamic,16) #endif - for (int i=0; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; + const int ix = i * 3 * W; + int iy = 0; - float fy,fx,fz,x_,y_,z_,LL; + float* rL = lab->L[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; - for (int j=0; jW; int H = lab->H; unsigned char * data = image->data; #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) if (multiThread) + #pragma omp parallel for schedule(dynamic,16) if (multiThread) #endif - for (int i=0; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; - int ix = i * 3 * W; - float R,G,B; - float fy,fx,fz,x_,y_,z_,LL; + for (int i = 0; i < H; i++) { + float* rL = lab->L[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; + int ix = i * 3 * W; - for (int j=0; jColor::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; + float R, G, B; + float fy, fx, fz, x_, y_, z_, LL; - Color::xyz2srgb(x_,y_,z_,R,G,B); - - /* 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; - } - } - } + for (int j = 0; j < W; j++) { + + //float L1=rL[j],a1=ra[j],b1=rb[j];//for testing + + fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116 + fx = (0.002 * ra[j]) / 327.68 + fy; + fz = fy - (0.005 * rb[j]) / 327.68; + LL = rL[j] / 327.68; + + x_ = 65535.0 * Color::f2xyz(fx) * Color::D50x; + // y_ = 65535.0 * Color::f2xyz(fy); + z_ = 65535.0 * Color::f2xyz(fz) * Color::D50z; + y_ = (LL > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / Color::kappa; + + Color::xyz2srgb(x_, y_, z_, R, G, B); + + /* 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; + } + } + } } -Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool standard_gamma) { - //gamutmap(lab); - - if (cx<0) cx = 0; - if (cy<0) cy = 0; - if (cx+cw>lab->W) cw = lab->W-cx; - if (cy+ch>lab->H) ch = lab->H-cy; +Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool standard_gamma) +{ + //gamutmap(lab); + + if (cx < 0) { + cx = 0; + } + + if (cy < 0) { + cy = 0; + } + + if (cx + cw > lab->W) { + cw = lab->W - cx; + } + + if (cy + ch > lab->H) { + ch = lab->H - cy; + } Image8* image = new Image8 (cw, ch); @@ -138,13 +154,15 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, if (oprof) { cmsHPROFILE oprofG = oprof; + if (standard_gamma) { oprofG = ICCStore::makeStdGammaProfile(oprof); } + lcmsMutex->lock (); cmsHPROFILE hLab = cmsCreateLab4Profile(NULL); cmsHTRANSFORM hTransform = cmsCreateTransform (hLab, TYPE_Lab_DBL, oprofG, TYPE_RGB_8, settings->colorimetricIntent, - cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety + cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety cmsCloseProfile(hLab); lcmsMutex->unlock (); @@ -152,71 +170,78 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, // cmsDoTransform is relatively expensive #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - AlignedBuffer pBuf(3*cw); - double *buffer=pBuf.data; - int condition = cy+ch; + { + AlignedBuffer pBuf(3 * cw); + double *buffer = pBuf.data; + int condition = cy + ch; #ifdef _OPENMP -#pragma omp for firstprivate(lab) schedule(dynamic,16) + #pragma omp for firstprivate(lab) schedule(dynamic,16) #endif - for (int i=cy; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; - for (int j=cx; jL[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; + + for (int j = cx; j < cx + cw; j++) { + buffer[iy++] = rL[j] / 327.68f; + buffer[iy++] = ra[j] / 327.68f; + buffer[iy++] = rb[j] / 327.68f; + } + + cmsDoTransform (hTransform, buffer, data + ix, cw); } - - cmsDoTransform (hTransform, buffer, data + ix, cw); - } -} // End of parallelization + } // End of parallelization cmsDeleteTransform(hTransform); - if (oprofG != oprof) + + if (oprofG != oprof) { cmsCloseProfile(oprofG); + } } else { - - double rgb_xyz[3][3]; - - for (int i=0; iL[i]; float* ra = lab->a[i]; float* rb = lab->b[i]; - int ix = 3*i*cw; - for (int j=cx; jColor::epskap) ? 65535.0*fy*fy*fy : 65535.0*LL/Color::kappa; + int ix = 3 * i * cw; - Color::xyz2rgb(x_,y_,z_,R,G,B,rgb_xyz); + for (int j = cx; j < cx + cw; j++) { + + float fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116 + float fx = (0.002 * ra[j]) / 327.68 + fy; + float fz = fy - (0.005 * rb[j]) / 327.68; + float LL = rL[j] / 327.68; + + float x_ = 65535.0 * Color::f2xyz(fx) * Color::D50x; + //float y_ = 65535.0 * Color::f2xyz(fy); + float z_ = 65535.0 * Color::f2xyz(fz) * Color::D50z; + float y_ = (LL > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / Color::kappa; + + 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; @@ -224,164 +249,299 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, } } } + return image; } // for default (not gamma) -Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool bw) { - - //gamutmap(lab); +Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool bw) +{ - if (cx<0) cx = 0; - if (cy<0) cy = 0; - if (cx+cw>lab->W) cw = lab->W-cx; - if (cy+ch>lab->H) ch = lab->H-cy; + //gamutmap(lab); + + if (cx < 0) { + cx = 0; + } + + if (cy < 0) { + cy = 0; + } + + if (cx + cw > lab->W) { + cw = lab->W - cx; + } + + if (cy + ch > lab->H) { + ch = lab->H - cy; + } Image16* image = new Image16 (cw, ch); - cmsHPROFILE oprof = iccStore->getProfile (profile); - - + cmsHPROFILE oprof = iccStore->getProfile (profile); + + if (oprof) { - #pragma omp parallel for if (multiThread) - for (int i=cy; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; - short* xa = (short*)image->r(i-cy); - short* ya = (short*)image->g(i-cy); - short* za = (short*)image->b(i-cy); - for (int j=cx; jColor::epskap) ? 65535.0f*fy*fy*fy : 65535.0f*LL/Color::kappa; - - xa[j-cx] = CLIP((int) round(x_)); - ya[j-cx] = CLIP((int) round(y_)); - za[j-cx] = CLIP((int) round(z_)); - if(bw && y_ < 65535.f ){//force Bw value and take highlight into account - xa[j-cx] =(int) round(y_* Color::D50x ); - za[j-cx] =(int) round(y_* Color::D50z); - } - - } - } + #pragma omp parallel for if (multiThread) + + for (int i = cy; i < cy + ch; i++) { + float* rL = lab->L[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; + short* xa = (short*)image->r(i - cy); + short* ya = (short*)image->g(i - cy); + short* za = (short*)image->b(i - cy); + + for (int j = cx; j < cx + cw; j++) { + + float fy = (0.0086206897f * rL[j]) / 327.68f + 0.1379310345f; // (L+16)/116 + float fx = (0.002 * ra[j]) / 327.68f + fy; + float fz = fy - (0.005f * rb[j]) / 327.68f; + float LL = rL[j] / 327.68f; + + float x_ = 65535.0f * (float) Color::f2xyz(fx) * Color::D50x; + //float y_ = 65535.0 * Color::f2xyz(fy); + float z_ = 65535.0f * (float) Color::f2xyz(fz) * Color::D50z; + float y_ = (LL > Color::epskap) ? 65535.0f * fy * fy * fy : 65535.0f * LL / Color::kappa; + + xa[j - cx] = CLIP((int) round(x_)); + ya[j - cx] = CLIP((int) round(y_)); + za[j - cx] = CLIP((int) round(z_)); + + if(bw && y_ < 65535.f ) { //force Bw value and take highlight into account + xa[j - cx] = (int) round(y_ * Color::D50x ); + za[j - cx] = (int) round(y_ * Color::D50z); + } + + } + } cmsHPROFILE iprof = iccStore->getXYZProfile (); lcmsMutex->lock (); - cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_16, settings->colorimetricIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_16, settings->colorimetricIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); lcmsMutex->unlock (); image->ExecCMSTransform(hTransform); - cmsDeleteTransform(hTransform); - } else { - #pragma omp parallel for if (multiThread) - for (int i=cy; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; - for (int j=cx; jColor::epskap) ? (float) 65535.0f*fy*fy*fy : 65535.0f*LL/Color::kappa; + cmsDeleteTransform(hTransform); + } else { + #pragma omp parallel for if (multiThread) - Color::xyz2srgb(x_,y_,z_,R,G,B); + for (int i = cy; i < cy + ch; i++) { + float R, G, B; + float* rL = lab->L[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; + + for (int j = cx; j < cx + cw; j++) { + + float fy = (0.0086206897f * rL[j]) / 327.68f + 0.1379310345f; // (L+16)/116 + float fx = (0.002f * ra[j]) / 327.68f + fy; + float fz = fy - (0.005f * rb[j]) / 327.68f; + float LL = rL[j] / 327.68f; + + float x_ = 65535.0f * (float) Color::f2xyz(fx) * Color::D50x; + //float y_ = 65535.0 * Color::f2xyz(fy); + float z_ = 65535.0f * (float) Color::f2xyz(fz) * Color::D50z; + float y_ = (LL > Color::epskap) ? (float) 65535.0f * fy * fy * fy : 65535.0f * LL / Color::kappa; + + 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)gamma2curve[CLIP(R)]; - image->g(i-cy,j-cx) = (int)gamma2curve[CLIP(G)]; - image->b(i-cy,j-cx) = (int)gamma2curve[CLIP(B)]; - } - } - } return image; } // for gamma options (BT709...sRGB linear...) -Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw) { - - //gamutmap(lab); +Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw) +{ - if (cx<0) cx = 0; - if (cy<0) cy = 0; - if (cx+cw>lab->W) cw = lab->W-cx; - if (cy+ch>lab->H) ch = lab->H-cy; + //gamutmap(lab); + + if (cx < 0) { + cx = 0; + } + + if (cy < 0) { + cy = 0; + } + + if (cx + cw > lab->W) { + cw = lab->W - cx; + } + + if (cy + ch > lab->H) { + ch = lab->H - cy; + } Image16* image = new Image16 (cw, ch); - float p1,p2,p3,p4,p5,p6;//primaries - //double ga0,ga1,ga2,ga3,ga4,ga5=0.0,ga6=0.0;//gamma parameters - double g_a0,g_a1,g_a2,g_a3,g_a4,g_a5;//gamma parameters - double pwr; - double ts; - ga6=0.0; - pwr=1.0/gampos; - ts=slpos; - int mode=0, imax=0; - - int t50; - int select_temp =1;//5003K - const double eps=0.000000001;// not divide by zero - //primaries for 7 working profiles ==> output profiles - // eventually to adapt primaries if RT used special profiles ! - if(profi=="ProPhoto") {p1=0.7347; p2=0.2653; p3=0.1596; p4=0.8404; p5=0.0366; p6=0.0001;select_temp=1;}//Prophoto primaries - else if (profi=="WideGamut") {p1=0.7350; p2=0.2650; p3=0.1150; p4=0.8260; p5=0.1570; p6=0.0180;select_temp=1;}//Widegamut primaries - else if (profi=="Adobe RGB") {p1=0.6400; p2=0.3300; p3=0.2100; p4=0.7100; p5=0.1500; p6=0.0600;select_temp=2;}//Adobe primaries - else if (profi=="sRGB") {p1=0.6400; p2=0.3300; p3=0.3000; p4=0.6000; p5=0.1500; p6=0.0600;select_temp=2;} // sRGB primaries - else if (profi=="BruceRGB") {p1=0.6400; p2=0.3300; p3=0.2800; p4=0.6500; p5=0.1500; p6=0.0600;select_temp=2;} // Bruce primaries - else if (profi=="Beta RGB") {p1=0.6888; p2=0.3112; p3=0.1986; p4=0.7551; p5=0.1265; p6=0.0352;select_temp=1;} // Beta primaries - else if (profi=="BestRGB") {p1=0.7347; p2=0.2653; p3=0.2150; p4=0.7750; p5=0.1300; p6=0.0350;select_temp=1;} // Best primaries - if (!freegamma) {//if Free gamma not selected - // gamma : ga0,ga1,ga2,ga3,ga4,ga5 by calcul - if(gam=="BT709_g2.2_s4.5") {ga0=2.22;ga1=0.909995;ga2=0.090005;ga3=0.222222; ga4=0.081071;ga5=0.0;}//BT709 2.2 4.5 - my prefered as D.Coffin - else if (gam=="sRGB_g2.4_s12.92") {ga0=2.40; ga1=0.947858; ga2=0.052142;ga3=0.077399;ga4=0.039293;ga5=0.0;}//sRGB 2.4 12.92 - RT default as Lightroom - else if (gam=="High_g1.3_s3.35") {ga0=1.3 ; ga1=0.998279; ga2=0.001721;ga3=0.298507;ga4=0.005746;ga5=0.0;}//for high dynamic images - else if (gam== "Low_g2.6_s6.9") {ga0=2.6 ; ga1=0.891161; ga2=0.108839;ga3=0.144928;ga4=0.076332;ga5=0.0;} //gamma 2.6 variable : for low contrast images - else if (gam=="linear_g1.0") {ga0=1.0; ga1=1.;ga2=0.;ga3=1./eps;ga4=0.;ga5=0.0;}//gamma=1 linear : for high dynamic images (cf : D.Coffin...) - else if (gam=="standard_g2.2") {ga0=2.2; ga1=1.;ga2=0.;ga3=1./eps;ga4=0.;ga5=0.0;}//gamma=2.2 (as gamma of Adobe, Widegamut...) - else if (gam=="standard_g1.8") {ga0=1.8; ga1=1.;ga2=0.;ga3=1./eps;ga4=0.;ga5=0.0;}//gamma=1.8 (as gamma of Prophoto) - } - else //free gamma selected - { - if(slpos==0) slpos=eps; - Color::calcGamma(pwr, ts, mode, imax,g_a0,g_a1,g_a2,g_a3,g_a4,g_a5);// call to calcGamma with selected gamma and slope : return parameters for LCMS2 - ga4=g_a3*ts; - //printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4); - ga0=gampos;ga1=1./(1.0+g_a4);ga2=g_a4/(1.0 + g_a4);ga3=1./slpos;ga5=0.0; - //printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0,ga1,ga2,ga3,ga4); + float p1, p2, p3, p4, p5, p6; //primaries + //double ga0,ga1,ga2,ga3,ga4,ga5=0.0,ga6=0.0;//gamma parameters + double g_a0, g_a1, g_a2, g_a3, g_a4, g_a5; //gamma parameters + double pwr; + double ts; + ga6 = 0.0; + pwr = 1.0 / gampos; + ts = slpos; + int mode = 0, imax = 0; - } - if(select_temp==1) t50=5003;// for Widegamut, Prophoto Best, Beta D50 - else if (select_temp==2) t50=6504;// for sRGB, AdobeRGB, Bruce D65 + int t50; + int select_temp = 1; //5003K + const double eps = 0.000000001; // not divide by zero - cmsCIExyY xyD; - cmsCIExyYTRIPLE Primaries = {{p1, p2, 1.0},//red primaries - {p3, p4, 1.0}, // green - {p5, p6, 1.0} //blue - }; + //primaries for 7 working profiles ==> output profiles + // eventually to adapt primaries if RT used special profiles ! + if(profi == "ProPhoto") { + p1 = 0.7347; //Prophoto primaries + p2 = 0.2653; + p3 = 0.1596; + p4 = 0.8404; + p5 = 0.0366; + p6 = 0.0001; + select_temp = 1; + } else if (profi == "WideGamut") { + p1 = 0.7350; //Widegamut primaries + p2 = 0.2650; + p3 = 0.1150; + p4 = 0.8260; + p5 = 0.1570; + p6 = 0.0180; + select_temp = 1; + } else if (profi == "Adobe RGB") { + p1 = 0.6400; //Adobe primaries + p2 = 0.3300; + p3 = 0.2100; + p4 = 0.7100; + p5 = 0.1500; + p6 = 0.0600; + select_temp = 2; + } else if (profi == "sRGB") { + p1 = 0.6400; // sRGB primaries + p2 = 0.3300; + p3 = 0.3000; + p4 = 0.6000; + p5 = 0.1500; + p6 = 0.0600; + select_temp = 2; + } else if (profi == "BruceRGB") { + p1 = 0.6400; // Bruce primaries + p2 = 0.3300; + p3 = 0.2800; + p4 = 0.6500; + p5 = 0.1500; + p6 = 0.0600; + select_temp = 2; + } else if (profi == "Beta RGB") { + p1 = 0.6888; // Beta primaries + p2 = 0.3112; + p3 = 0.1986; + p4 = 0.7551; + p5 = 0.1265; + p6 = 0.0352; + select_temp = 1; + } else if (profi == "BestRGB") { + p1 = 0.7347; // Best primaries + p2 = 0.2653; + p3 = 0.2150; + p4 = 0.7750; + p5 = 0.1300; + p6 = 0.0350; + select_temp = 1; + } + + if (!freegamma) {//if Free gamma not selected + // gamma : ga0,ga1,ga2,ga3,ga4,ga5 by calcul + if(gam == "BT709_g2.2_s4.5") { + ga0 = 2.22; //BT709 2.2 4.5 - my prefered as D.Coffin + ga1 = 0.909995; + ga2 = 0.090005; + ga3 = 0.222222; + ga4 = 0.081071; + ga5 = 0.0; + } else if (gam == "sRGB_g2.4_s12.92") { + ga0 = 2.40; //sRGB 2.4 12.92 - RT default as Lightroom + ga1 = 0.947858; + ga2 = 0.052142; + ga3 = 0.077399; + ga4 = 0.039293; + ga5 = 0.0; + } else if (gam == "High_g1.3_s3.35") { + ga0 = 1.3 ; //for high dynamic images + ga1 = 0.998279; + ga2 = 0.001721; + ga3 = 0.298507; + ga4 = 0.005746; + ga5 = 0.0; + } else if (gam == "Low_g2.6_s6.9") { + ga0 = 2.6 ; //gamma 2.6 variable : for low contrast images + ga1 = 0.891161; + ga2 = 0.108839; + ga3 = 0.144928; + ga4 = 0.076332; + ga5 = 0.0; + } else if (gam == "linear_g1.0") { + ga0 = 1.0; //gamma=1 linear : for high dynamic images (cf : D.Coffin...) + ga1 = 1.; + ga2 = 0.; + ga3 = 1. / eps; + ga4 = 0.; + ga5 = 0.0; + } else if (gam == "standard_g2.2") { + ga0 = 2.2; //gamma=2.2 (as gamma of Adobe, Widegamut...) + ga1 = 1.; + ga2 = 0.; + ga3 = 1. / eps; + ga4 = 0.; + ga5 = 0.0; + } else if (gam == "standard_g1.8") { + ga0 = 1.8; //gamma=1.8 (as gamma of Prophoto) + ga1 = 1.; + ga2 = 0.; + ga3 = 1. / eps; + ga4 = 0.; + ga5 = 0.0; + } + } else { //free gamma selected + if(slpos == 0) { + slpos = eps; + } + + Color::calcGamma(pwr, ts, mode, imax, g_a0, g_a1, g_a2, g_a3, g_a4, g_a5); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 + ga4 = g_a3 * ts; + //printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4); + ga0 = gampos; + ga1 = 1. / (1.0 + g_a4); + ga2 = g_a4 / (1.0 + g_a4); + ga3 = 1. / slpos; + ga5 = 0.0; + //printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0,ga1,ga2,ga3,ga4); + + } + + if(select_temp == 1) { + t50 = 5003; // for Widegamut, Prophoto Best, Beta D50 + } else if (select_temp == 2) { + t50 = 6504; // for sRGB, AdobeRGB, Bruce D65 + } + + cmsCIExyY xyD; + cmsCIExyYTRIPLE Primaries = {{p1, p2, 1.0},//red primaries + {p3, p4, 1.0}, // green + {p5, p6, 1.0} //blue + }; cmsToneCurve* GammaTRC[3]; - cmsFloat64Number Parameters[7]; + cmsFloat64Number Parameters[7]; Parameters[0] = ga0; Parameters[1] = ga1; Parameters[2] = ga2; Parameters[3] = ga3; - Parameters[4] = ga4; - Parameters[5] = ga5; - Parameters[6] = ga6; + Parameters[4] = ga4; + Parameters[5] = ga5; + Parameters[6] = ga6; // 7 parameters for smoother curves cmsWhitePointFromTemp(&xyD, t50); GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, 5, Parameters);//5 = more smoother than 4 @@ -389,77 +549,82 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int cmsFreeToneCurve(GammaTRC[0]); - - if (oprofdef) { - #pragma omp parallel for if (multiThread) - for (int i=cy; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; - short* xa = (short*)image->r(i-cy); - short* ya = (short*)image->g(i-cy); - short* za = (short*)image->b(i-cy); - for (int j=cx; jColor::epskap) ? (float) 65535.0*fy*fy*fy : 65535.0f*LL/Color::kappa; - xa[j-cx] = CLIP((int) round(x_)) ; - ya[j-cx] = CLIP((int) round(y_)); - za[j-cx] = CLIP((int) round(z_)); - if(bw && y_ < 65535.f){//force Bw value and take highlight into account - xa[j-cx] =(int) round(y_ * Color::D50x); - za[j-cx] =(int) round(y_ * Color::D50z); - } - - } - } + if (oprofdef) { + #pragma omp parallel for if (multiThread) + + for (int i = cy; i < cy + ch; i++) { + float* rL = lab->L[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; + short* xa = (short*)image->r(i - cy); + short* ya = (short*)image->g(i - cy); + short* za = (short*)image->b(i - cy); + + for (int j = cx; j < cx + cw; j++) { + + float fy = (0.0086206897f * rL[j]) / 327.68f + 0.1379310345f; // (L+16)/116 + float fx = (0.002f * ra[j]) / 327.68f + fy; + float fz = fy - (0.005f * rb[j]) / 327.68f; + float LL = rL[j] / 327.68f; + + float x_ = 65535.0f * (float)Color::f2xyz(fx) * Color::D50x; + // float y_ = 65535.0 * Color::f2xyz(fy); + float z_ = 65535.0f * (float)Color::f2xyz(fz) * Color::D50z; + float y_ = (LL > Color::epskap) ? (float) 65535.0 * fy * fy * fy : 65535.0f * LL / Color::kappa; + + xa[j - cx] = CLIP((int) round(x_)) ; + ya[j - cx] = CLIP((int) round(y_)); + za[j - cx] = CLIP((int) round(z_)); + + if(bw && y_ < 65535.f) { //force Bw value and take highlight into account + xa[j - cx] = (int) round(y_ * Color::D50x); + za[j - cx] = (int) round(y_ * Color::D50z); + } + + } + } cmsHPROFILE iprof = iccStore->getXYZProfile (); lcmsMutex->lock (); - cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, settings->colorimetricIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, settings->colorimetricIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); lcmsMutex->unlock (); image->ExecCMSTransform(hTransform); - cmsDeleteTransform(hTransform); - } else { - // - #pragma omp parallel for if (multiThread) - for (int i=cy; iL[i]; - float* ra = lab->a[i]; - float* rb = lab->b[i]; - for (int j=cx; jColor::epskap) ? (float) 65535.0*fy*fy*fy : 65535.0f*LL/Color::kappa; + cmsDeleteTransform(hTransform); + } else { + // + #pragma omp parallel for if (multiThread) + for (int i = cy; i < cy + ch; i++) { + float R, G, B; + float* rL = lab->L[i]; + float* ra = lab->a[i]; + float* rb = lab->b[i]; - Color::xyz2srgb(x_,y_,z_,R,G,B); + for (int j = cx; j < cx + cw; j++) { + + float fy = (0.0086206897f * rL[j]) / 327.68f + 0.1379310345f; // (L+16)/116 + float fx = (0.002f * ra[j]) / 327.68f + fy; + float fz = fy - (0.005f * rb[j]) / 327.68f; + float LL = rL[j] / 327.68f; + + float x_ = 65535.0f * (float) Color::f2xyz(fx) * Color::D50x; + //float y_ = 65535.0 * Color::f2xyz(fy); + float z_ = 65535.0f * (float) Color::f2xyz(fz) * Color::D50z; + float y_ = (LL > Color::epskap) ? (float) 65535.0 * fy * fy * fy : 65535.0f * LL / Color::kappa; + + 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)gamma2curve[CLIP(R)]; - image->g(i-cy,j-cx) = (int)gamma2curve[CLIP(G)]; - image->b(i-cy,j-cx) = (int)gamma2curve[CLIP(B)]; - } - } - } return image; } - + //#include "sRGBgamutbdy.cc" } diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index 29e25107d..8bdc0a6cb 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -27,15 +27,16 @@ # include #endif -namespace rtengine { +namespace rtengine +{ static inline float Lanc(float x, float a) { - if (x * x < 1e-6f) + if (x * x < 1e-6f) { return 1.0f; - else if (x * x > a * a) + } else if (x * x > a * a) { return 0.0f; - else { + } else { x = static_cast(M_PI) * x; return a * xsinf(x) * xsinf(x / a) / (x * x); } @@ -49,122 +50,124 @@ void ImProcFunctions::Lanczos(const Image16* src, Image16* dst, float scale) const float sc = min(scale, 1.0f); const int support = static_cast(2.0f * a / sc) + 1; -#pragma omp parallel -{ - // storage for precomputed parameters for horisontal interpolation - float * wwh = new float[support * dst->width]; - int * jj0 = new int[dst->width]; - int * jj1 = new int[dst->width]; - - // temporal storage for vertically-interpolated row of pixels - float * lr = new float[src->width]; - float * lg = new float[src->width]; - float * lb = new float[src->width]; + #pragma omp parallel + { + // storage for precomputed parameters for horisontal interpolation + float * wwh = new float[support * dst->width]; + int * jj0 = new int[dst->width]; + int * jj1 = new int[dst->width]; - // Phase 1: precompute coefficients for horisontal interpolation - - for (int j = 0; j < dst->width; j++) { - - // x coord of the center of pixel on src image - float x0 = (static_cast(j) + 0.5f) * delta - 0.5f; + // temporal storage for vertically-interpolated row of pixels + float * lr = new float[src->width]; + float * lg = new float[src->width]; + float * lb = new float[src->width]; - // weights for interpolation in horisontal direction - float * w = wwh + j * support; - - // sum of weights used for normalization - float ws = 0.0f; + // Phase 1: precompute coefficients for horisontal interpolation - jj0[j] = max(0, static_cast(floorf(x0 - a / sc)) + 1); - jj1[j] = min(src->width, static_cast(floorf(x0 + a / sc)) + 1); + for (int j = 0; j < dst->width; j++) { - // calculate weights - for (int jj = jj0[j]; jj < jj1[j]; jj++) { - int k = jj - jj0[j]; - float z = sc * (x0 - static_cast(jj)); - w[k] = Lanc(z, a); - ws += w[k]; - } - - // normalize weights - for (int k = 0; k < support; k++) { - w[k] /= ws; - } - } - // Phase 2: do actual interpolation -#pragma omp for - for (int i = 0; i < dst->height; i++) { - - // y coord of the center of pixel on src image - float y0 = (static_cast(i) + 0.5f) * delta - 0.5f; - - // weights for interpolation in y direction - float w[support]; - - // sum of weights used for normalization - float ws= 0.0f; + // x coord of the center of pixel on src image + float x0 = (static_cast(j) + 0.5f) * delta - 0.5f; - int ii0 = max(0, static_cast(floorf(y0 - a / sc)) + 1); - int ii1 = min(src->height, static_cast(floorf(y0 + a / sc)) + 1); + // weights for interpolation in horisontal direction + float * w = wwh + j * support; - // calculate weights for vertical interpolation - for (int ii = ii0; ii < ii1; ii++) { - int k = ii - ii0; - float z = sc * (y0 - static_cast(ii)); - w[k] = Lanc(z, a); - ws += w[k]; - } + // sum of weights used for normalization + float ws = 0.0f; - // normalize weights - for (int k = 0; k < support; k++) { - w[k] /= ws; - } - - // Do vertical interpolation. Store results. - for (int j = 0; j < src->width; j++) { - - float r = 0.0f, g = 0.0f, b = 0.0f; - - for (int ii = ii0; ii < ii1; ii++) { - int k = ii - ii0; - - r += w[k] * src->r(ii,j); - g += w[k] * src->g(ii,j); - b += w[k] * src->b(ii,j); - } - - lr[j] = r; - lg[j] = g; - lb[j] = b; - } + jj0[j] = max(0, static_cast(floorf(x0 - a / sc)) + 1); + jj1[j] = min(src->width, static_cast(floorf(x0 + a / sc)) + 1); - // Do horizontal interpolation - for(int j = 0; j < dst->width; j++) { - - float * wh = wwh + support * j; - - float r = 0.0f, g = 0.0f, b = 0.0f; - + // calculate weights for (int jj = jj0[j]; jj < jj1[j]; jj++) { int k = jj - jj0[j]; - - r += wh[k] * lr[jj]; - g += wh[k] * lg[jj]; - b += wh[k] * lb[jj]; + float z = sc * (x0 - static_cast(jj)); + w[k] = Lanc(z, a); + ws += w[k]; + } + + // normalize weights + for (int k = 0; k < support; k++) { + w[k] /= ws; } - - dst->r(i,j) = CLIP(static_cast(r)); - dst->g(i,j) = CLIP(static_cast(g)); - dst->b(i,j) = CLIP(static_cast(b)); } + + // Phase 2: do actual interpolation + #pragma omp for + + for (int i = 0; i < dst->height; i++) { + + // y coord of the center of pixel on src image + float y0 = (static_cast(i) + 0.5f) * delta - 0.5f; + + // weights for interpolation in y direction + float w[support]; + + // sum of weights used for normalization + float ws = 0.0f; + + int ii0 = max(0, static_cast(floorf(y0 - a / sc)) + 1); + int ii1 = min(src->height, static_cast(floorf(y0 + a / sc)) + 1); + + // calculate weights for vertical interpolation + for (int ii = ii0; ii < ii1; ii++) { + int k = ii - ii0; + float z = sc * (y0 - static_cast(ii)); + w[k] = Lanc(z, a); + ws += w[k]; + } + + // normalize weights + for (int k = 0; k < support; k++) { + w[k] /= ws; + } + + // Do vertical interpolation. Store results. + for (int j = 0; j < src->width; j++) { + + float r = 0.0f, g = 0.0f, b = 0.0f; + + for (int ii = ii0; ii < ii1; ii++) { + int k = ii - ii0; + + r += w[k] * src->r(ii, j); + g += w[k] * src->g(ii, j); + b += w[k] * src->b(ii, j); + } + + lr[j] = r; + lg[j] = g; + lb[j] = b; + } + + // Do horizontal interpolation + for(int j = 0; j < dst->width; j++) { + + float * wh = wwh + support * j; + + float r = 0.0f, g = 0.0f, b = 0.0f; + + for (int jj = jj0[j]; jj < jj1[j]; jj++) { + int k = jj - jj0[j]; + + r += wh[k] * lr[jj]; + g += wh[k] * lg[jj]; + b += wh[k] * lb[jj]; + } + + dst->r(i, j) = CLIP(static_cast(r)); + dst->g(i, j) = CLIP(static_cast(g)); + dst->b(i, j) = CLIP(static_cast(b)); + } + } + + delete[] wwh; + delete[] jj0; + delete[] jj1; + delete[] lr; + delete[] lg; + delete[] lb; } - - delete[] wwh; - delete[] jj0; - delete[] jj1; - delete[] lr; - delete[] lg; - delete[] lb; -} } @@ -210,115 +213,122 @@ SSEFUNCTION void ImProcFunctions::Lanczos(const LabImage* src, LabImage* dst, fl } #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - // temporal storage for vertically-interpolated row of pixels - float * lL = new float[src->W]; - float * la = new float[src->W]; - float * lb = new float[src->W]; - // weights for interpolation in y direction - float w[support] ALIGNED64; + { + // temporal storage for vertically-interpolated row of pixels + float * lL = new float[src->W]; + float * la = new float[src->W]; + float * lb = new float[src->W]; + // weights for interpolation in y direction + float w[support] ALIGNED64; - // Phase 2: do actual interpolation + // Phase 2: do actual interpolation #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i = 0; i < dst->H; i++) { - // y coord of the center of pixel on src image - float y0 = (static_cast(i) + 0.5f) * delta - 0.5f; - // sum of weights used for normalization - float ws = 0.0f; + for (int i = 0; i < dst->H; i++) { + // y coord of the center of pixel on src image + float y0 = (static_cast(i) + 0.5f) * delta - 0.5f; - int ii0 = max(0, static_cast(floorf(y0 - a / sc)) + 1); - int ii1 = min(src->H, static_cast(floorf(y0 + a / sc)) + 1); + // sum of weights used for normalization + float ws = 0.0f; - // calculate weights for vertical interpolation - for (int ii = ii0; ii < ii1; ii++) { - int k = ii - ii0; - float z = sc * (y0 - static_cast(ii)); - w[k] = Lanc(z, a); - ws += w[k]; - } + int ii0 = max(0, static_cast(floorf(y0 - a / sc)) + 1); + int ii1 = min(src->H, static_cast(floorf(y0 + a / sc)) + 1); - // normalize weights - for (int k = 0; k < support; k++) { - w[k] /= ws; - } + // calculate weights for vertical interpolation + for (int ii = ii0; ii < ii1; ii++) { + int k = ii - ii0; + float z = sc * (y0 - static_cast(ii)); + w[k] = Lanc(z, a); + ws += w[k]; + } - // Do vertical interpolation. Store results. + // normalize weights + for (int k = 0; k < support; k++) { + w[k] /= ws; + } + + // Do vertical interpolation. Store results. #ifdef __SSE2__ - int j; - __m128 Lv,av,bv,wkv; - for (j = 0; j < src->W-3; j+=4) { - Lv = _mm_setzero_ps(); - av = _mm_setzero_ps(); - bv = _mm_setzero_ps(); + int j; + __m128 Lv, av, bv, wkv; - for (int ii = ii0; ii < ii1; ii++) { - int k = ii - ii0; - wkv = _mm_set1_ps(w[k]); - Lv += wkv * LVFU(src->L[ii][j]); - av += wkv * LVFU(src->a[ii][j]); - bv += wkv * LVFU(src->b[ii][j]); + for (j = 0; j < src->W - 3; j += 4) { + Lv = _mm_setzero_ps(); + av = _mm_setzero_ps(); + bv = _mm_setzero_ps(); + + for (int ii = ii0; ii < ii1; ii++) { + int k = ii - ii0; + wkv = _mm_set1_ps(w[k]); + Lv += wkv * LVFU(src->L[ii][j]); + av += wkv * LVFU(src->a[ii][j]); + bv += wkv * LVFU(src->b[ii][j]); + } + + STVF(lL[j], Lv); + STVF(la[j], av); + STVF(lb[j], bv); } - STVF(lL[j],Lv); - STVF(la[j],av); - STVF(lb[j],bv); - } #else - int j=0; + int j = 0; #endif - for (; j < src->W; j++) { - float L = 0.0f, a = 0.0f, b = 0.0f; - for (int ii = ii0; ii < ii1; ii++) { - int k = ii - ii0; + for (; j < src->W; j++) { + float L = 0.0f, a = 0.0f, b = 0.0f; - L += w[k] * src->L[ii][j]; - a += w[k] * src->a[ii][j]; - b += w[k] * src->b[ii][j]; + for (int ii = ii0; ii < ii1; ii++) { + int k = ii - ii0; + + L += w[k] * src->L[ii][j]; + a += w[k] * src->a[ii][j]; + b += w[k] * src->b[ii][j]; + } + + lL[j] = L; + la[j] = a; + lb[j] = b; } - lL[j] = L; - la[j] = a; - lb[j] = b; - } + // Do horizontal interpolation + for(int j = 0; j < dst->W; j++) { - // Do horizontal interpolation - for(int j = 0; j < dst->W; j++) { + float * wh = wwh + support * j; - float * wh = wwh + support * j; + float L = 0.0f, a = 0.0f, b = 0.0f; - float L = 0.0f, a = 0.0f, b = 0.0f; + for (int jj = jj0[j]; jj < jj1[j]; jj++) { + int k = jj - jj0[j]; - for (int jj = jj0[j]; jj < jj1[j]; jj++) { - int k = jj - jj0[j]; + L += wh[k] * lL[jj]; + a += wh[k] * la[jj]; + b += wh[k] * lb[jj]; + } - L += wh[k] * lL[jj]; - a += wh[k] * la[jj]; - b += wh[k] * lb[jj]; + dst->L[i][j] = L; + dst->a[i][j] = a; + dst->b[i][j] = b; } - - dst->L[i][j] = L; - dst->a[i][j] = a; - dst->b[i][j] = b; } + + delete[] lL; + delete[] la; + delete[] lb; } - delete[] lL; - delete[] la; - delete[] lb; -} delete[] jj0; delete[] jj1; - delete[] wwh; + delete[] wwh; } -float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh) { +float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh) +{ imw = fw; imh = fh; + if (!params || !params->resize.enabled) { return 1.0; } @@ -326,12 +336,12 @@ float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, in // get the resize parameters int refw, refh; double dScale; + if (params->crop.enabled && params->resize.appliesTo == "Cropped area") { // the resize values applies to the crop dimensions refw = params->crop.w; refh = params->crop.h; - } - else { + } else { // the resize values applies to the image dimensions // if a crop exists, it will be resized to the calculated scale refw = fw; @@ -341,69 +351,80 @@ float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, in switch(params->resize.dataspec) { case (1): // Width - dScale = (double)params->resize.width/(double)refw; + dScale = (double)params->resize.width / (double)refw; break; + case (2): // Height - dScale = (double)params->resize.height/(double)refh; + dScale = (double)params->resize.height / (double)refh; break; + case (3): + // FitBox - if ((double)refw/(double)refh > (double)params->resize.width/(double)params->resize.height) - dScale = (double)params->resize.width/(double)refw; - else - dScale = (double)params->resize.height/(double)refh; + if ((double)refw / (double)refh > (double)params->resize.width / (double)params->resize.height) { + dScale = (double)params->resize.width / (double)refw; + } else { + dScale = (double)params->resize.height / (double)refh; + } + break; + default: // Scale dScale = params->resize.scale; break; } - if (fabs(dScale-1.0)<=1e-5) { + if (fabs(dScale - 1.0) <= 1e-5) { return 1.0; } + if (params->crop.enabled && params->resize.appliesTo == "Full image") { imw = params->crop.w; imh = params->crop.h; - } - else { + } else { imw = refw; imh = refh; } + imw = (int)( (double)imw * dScale + 0.5 ); imh = (int)( (double)imh * dScale + 0.5 ); return (float)dScale; } -void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale) { +void ImProcFunctions::resize (Image16* src, Image16* dst, float dScale) +{ #ifdef PROFILE time_t t1 = clock(); #endif + if(params->resize.method != "Nearest" ) { Lanczos(src, dst, dScale); } else { - // Nearest neighbour algorithm + // Nearest neighbour algorithm #ifdef _OPENMP -#pragma omp parallel for if (multiThread) + #pragma omp parallel for if (multiThread) #endif - for (int i=0; iheight; i++) { - int sy = i/dScale; - sy = LIM(sy, 0, src->height-1); - for (int j=0; jwidth; j++) { - int sx = j/dScale; - sx = LIM(sx, 0, src->width-1); - dst->r(i,j) = src->r(sy,sx); - dst->g(i,j) = src->g(sy,sx); - dst->b(i,j) = src->b(sy,sx); + + for (int i = 0; i < dst->height; i++) { + int sy = i / dScale; + sy = LIM(sy, 0, src->height - 1); + + for (int j = 0; j < dst->width; j++) { + int sx = j / dScale; + sx = LIM(sx, 0, src->width - 1); + dst->r(i, j) = src->r(sy, sx); + dst->g(i, j) = src->g(sy, sx); + dst->b(i, j) = src->b(sy, sx); } } } -#ifdef PROFILE +#ifdef PROFILE time_t t2 = clock(); std::cout << "Resize: " << params->resize.method << ": " - << (float)(t2 - t1) / CLOCKS_PER_SEC << std::endl; + << (float)(t2 - t1) / CLOCKS_PER_SEC << std::endl; #endif } diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index ba369333a..302c07655 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -26,7 +26,8 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ #undef ABS @@ -35,287 +36,341 @@ namespace rtengine { extern const Settings* settings; -SSEFUNCTION void ImProcFunctions::dcdamping (float** aI, float** aO, float damping, int W, int H) { +SSEFUNCTION void ImProcFunctions::dcdamping (float** aI, float** aO, float damping, int W, int H) +{ - const float dampingFac=-2.0/(damping*damping); + const float dampingFac = -2.0 / (damping * damping); #ifdef __SSE2__ - __m128 Iv,Ov,Uv,zerov,onev,fourv,fivev,dampingFacv,Tv; + __m128 Iv, Ov, Uv, zerov, onev, fourv, fivev, dampingFacv, Tv; zerov = _mm_setzero_ps( ); onev = _mm_set1_ps( 1.0f ); fourv = _mm_set1_ps( 4.0f ); fivev = _mm_set1_ps( 5.0f ); dampingFacv = _mm_set1_ps( dampingFac ); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; iW, H = lab->H; + int W = lab->W, H = lab->H; - float** tmpI = new float*[H]; - for (int i=0; iL[i][j]; - } + float** tmpI = new float*[H]; - float** tmp = (float**)b2; + for (int i = 0; i < H; i++) { + tmpI[i] = new float[W]; + + for (int j = 0; j < W; j++) { + tmpI[i][j] = (float)lab->L[i][j]; + } + } + + float** tmp = (float**)b2; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - AlignedBufferMP buffer(max(W,H)); + { + AlignedBufferMP buffer(max(W, H)); - float damping = sharpenParam.deconvdamping / 5.0; - bool needdamp = sharpenParam.deconvdamping > 0; - for (int k=0; k 0; - // apply blur function (gaussian blur) - gaussHorizontal (tmpI, tmp, buffer, W, H, sharpenParam.deconvradius / scale); - gaussVertical (tmp, tmp, buffer, W, H, sharpenParam.deconvradius / scale); + for (int k = 0; k < sharpenParam.deconviter; k++) { - if (!needdamp) { + // apply blur function (gaussian blur) + gaussHorizontal (tmpI, tmp, buffer, W, H, sharpenParam.deconvradius / scale); + gaussVertical (tmp, tmp, buffer, W, H, sharpenParam.deconvradius / scale); + + if (!needdamp) { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i0) - tmp[i][j] = (float)lab->L[i][j] / tmp[i][j]; - } - else - dcdamping (tmp, lab->L, damping, W, H); - gaussHorizontal (tmp, tmp, buffer, W, H, sharpenParam.deconvradius / scale); - gaussVertical (tmp, tmp, buffer, W, H, sharpenParam.deconvradius / scale); + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) + if (tmp[i][j] > 0) { + tmp[i][j] = (float)lab->L[i][j] / tmp[i][j]; + } + } else { + dcdamping (tmp, lab->L, damping, W, H); + } + + gaussHorizontal (tmp, tmp, buffer, W, H, sharpenParam.deconvradius / scale); + gaussVertical (tmp, tmp, buffer, W, H, sharpenParam.deconvradius / scale); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; iL[i][j] = lab->L[i][j]*p1 + max(tmpI[i][j],0.0f)*p2; - } // end parallel + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + lab->L[i][j] = lab->L[i][j] * p1 + max(tmpI[i][j], 0.0f) * p2; + } - for (int i=0; iW<8 || lab->H<8) - return; + // Rest is UNSHARP MASK + if (sharpenParam.enabled == false || sharpenParam.amount < 1 || lab->W < 8 || lab->H < 8) { + return; + } - int W = lab->W, H = lab->H; - float** b3 = NULL; - float** labCopy = NULL; - - if (sharpenParam.edgesonly) { - b3 = new float*[H]; - for (int i=0; iW, H = lab->H; + float** b3 = NULL; + float** labCopy = NULL; + + if (sharpenParam.edgesonly) { + b3 = new float*[H]; + + for (int i = 0; i < H; i++) { + b3[i] = new float[W]; + } + } + + if (sharpenParam.halocontrol && !sharpenParam.edgesonly) { + // We only need the lab parameter copy in this special case + labCopy = new float*[H]; + + for( int i = 0; i < H; i++ ) { + labCopy[i] = new float[W]; + } + } - if (sharpenParam.halocontrol && !sharpenParam.edgesonly) { - // We only need the lab parameter copy in this special case - labCopy = new float*[H]; - for( int i=0; i buffer(max(W,H)); - if (sharpenParam.edgesonly==false) { + AlignedBufferMP buffer(max(W, H)); - gaussHorizontal (lab->L, b2, buffer, W, H, sharpenParam.radius / scale); - gaussVertical (b2, b2, buffer, W, H, sharpenParam.radius / scale); - } - else { - bilateral (lab->L, (float**)b3, b2, W, H, sharpenParam.edges_radius / scale, sharpenParam.edges_tolerance, multiThread); - gaussHorizontal (b3, b2, buffer, W, H, sharpenParam.radius / scale); - gaussVertical (b2, b2, buffer, W, H, sharpenParam.radius / scale); - } + if (sharpenParam.edgesonly == false) { - float** base = lab->L; - if (sharpenParam.edgesonly) - base = b3; + gaussHorizontal (lab->L, b2, buffer, W, H, sharpenParam.radius / scale); + gaussVertical (b2, b2, buffer, W, H, sharpenParam.radius / scale); + } else { + bilateral (lab->L, (float**)b3, b2, W, H, sharpenParam.edges_radius / scale, sharpenParam.edges_tolerance, multiThread); + gaussHorizontal (b3, b2, buffer, W, H, sharpenParam.radius / scale); + gaussVertical (b2, b2, buffer, W, H, sharpenParam.radius / scale); + } - if (sharpenParam.halocontrol==false) { + float** base = lab->L; + + if (sharpenParam.edgesonly) { + base = b3; + } + + if (sharpenParam.halocontrol == false) { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i( - min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field - sharpenParam.amount * diff * 0.01f // Y axis max value - ); - lab->L[i][j] = lab->L[i][j] + delta; - } - } - else { - if (!sharpenParam.edgesonly) { - // make a deep copy of lab->L + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! + float diff = base[i][j] - b2[i][j]; + float delta = sharpenParam.threshold.multiply( + min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field + sharpenParam.amount * diff * 0.01f // Y axis max value + ); + lab->L[i][j] = lab->L[i][j] + delta; + } + } else { + if (!sharpenParam.edgesonly) { + // make a deep copy of lab->L #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for( int i=0; iL[i][j]; - base = labCopy; - } - sharpenHaloCtrl (lab, b2, base, W, H, sharpenParam); - } - } // end parallel + for( int i = 0; i < H; i++ ) + for( int j = 0; j < W; j++ ) { + labCopy[i][j] = lab->L[i][j]; + } - if (sharpenParam.halocontrol && !sharpenParam.edgesonly) { - // delete the deep copy - for( int i=0; iL[i][j]; - if (max_ < labL) max_ = labL; - if (min_ > labL) min_ = labL; + for (int j = 2; j < W - 2; j++) { + // compute 3 iterations, only forward + np1 = 2.f * (nL[i - 2][j] + nL[i - 2][j + 1] + nL[i - 2][j + 2] + nL[i - 1][j] + nL[i - 1][j + 1] + nL[i - 1][j + 2] + nL[i] [j] + nL[i] [j + 1] + nL[i] [j + 2]) / 27.f + nL[i - 1][j + 1] / 3.f; + np2 = 2.f * (nL[i - 1][j] + nL[i - 1][j + 1] + nL[i - 1][j + 2] + nL[i] [j] + nL[i] [j + 1] + nL[i] [j + 2] + nL[i + 1][j] + nL[i + 1][j + 1] + nL[i + 1][j + 2]) / 27.f + nL[i] [j + 1] / 3.f; + np3 = 2.f * (nL[i] [j] + nL[i] [j + 1] + nL[i] [j + 2] + nL[i + 1][j] + nL[i + 1][j + 1] + nL[i + 1][j + 2] + nL[i + 2][j] + nL[i + 2][j + 1] + nL[i + 2][j + 2]) / 27.f + nL[i + 1][j + 1] / 3.f; - // deviation from the environment as measurement - float diff = nL[i][j] - blurmap[i][j]; + // Max/Min of all these deltas and the last two max/min + maxn = max(np1, np2, np3); + minn = min(np1, np2, np3); + max_ = max(max1, max2, maxn); + min_ = min(min1, min2, minn); - const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! - float delta = sharpenParam.threshold.multiply( - min(ABS(diff), upperBound), // X axis value = absolute value of the difference - sharpFac * diff // Y axis max value = sharpening.amount * signed difference - ); - float newL = labL + delta; - // applying halo control - if (newL > max_) - newL = max_ + (newL-max_) * scale; - else if (newL < min_) - newL = min_ - (min_-newL) * scale; + // Shift the queue + max1 = max2; + max2 = maxn; + min1 = min2; + min2 = minn; + labL = lab->L[i][j]; - lab->L[i][j] = newL; - } - } + if (max_ < labL) { + max_ = labL; + } + + if (min_ > labL) { + min_ = labL; + } + + // deviation from the environment as measurement + float diff = nL[i][j] - blurmap[i][j]; + + const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! + float delta = sharpenParam.threshold.multiply( + min(ABS(diff), upperBound), // X axis value = absolute value of the difference + sharpFac * diff // Y axis max value = sharpening.amount * signed difference + ); + float newL = labL + delta; + + // applying halo control + if (newL > max_) { + newL = max_ + (newL - max_) * scale; + } else if (newL < min_) { + newL = min_ - (min_ - newL) * scale; + } + + lab->L[i][j] = newL; + } + } } // To the extent possible under law, Manuel Llorens @@ -323,184 +378,234 @@ void ImProcFunctions::sharpenHaloCtrl (LabImage* lab, float** blurmap, float** b // This work is published from: Spain. // Thanks to Manuel for this excellent job (Jacques Desmis JDC or frej83) -void ImProcFunctions::MLsharpen (LabImage* lab) { - // JD: this algorithm maximize clarity of images; it does not play on accutance. It can remove (partialy) the effects of the AA filter) - // I think we can use this algorithm alone in most cases, or first to clarify image and if you want a very little USM (unsharp mask sharpening) after... - if (params->sharpenEdge.enabled==false) - return; - MyTime t1e,t2e; - t1e.set(); +void ImProcFunctions::MLsharpen (LabImage* lab) +{ + // JD: this algorithm maximize clarity of images; it does not play on accutance. It can remove (partialy) the effects of the AA filter) + // I think we can use this algorithm alone in most cases, or first to clarify image and if you want a very little USM (unsharp mask sharpening) after... + if (params->sharpenEdge.enabled == false) { + return; + } - int offset,c,i,j,p,width2; - int width = lab->W, height = lab->H; - float *L,lumH,lumV,lumD1,lumD2,v,contrast,s; - float difL,difR,difT,difB,difLT,difRB,difLB,difRT,wH,wV,wD1,wD2,chmax[3]; - float f1,f2,f3,f4; - float templab; - int iii,kkk; - width2 = 2*width; - const float epsil=0.01f;//prevent divide by zero - const float eps2=0.001f;//prevent divide by zero - float amount; - amount = params->sharpenEdge.amount / 100.0f; - if (amount < 0.00001f) - return; + MyTime t1e, t2e; + t1e.set(); - if (settings->verbose) - printf ("SharpenEdge amount %f\n", amount); + int offset, c, i, j, p, width2; + int width = lab->W, height = lab->H; + float *L, lumH, lumV, lumD1, lumD2, v, contrast, s; + float difL, difR, difT, difB, difLT, difRB, difLB, difRT, wH, wV, wD1, wD2, chmax[3]; + float f1, f2, f3, f4; + float templab; + int iii, kkk; + width2 = 2 * width; + const float epsil = 0.01f; //prevent divide by zero + const float eps2 = 0.001f; //prevent divide by zero + float amount; + amount = params->sharpenEdge.amount / 100.0f; - L = new float[width*height]; + if (amount < 0.00001f) { + return; + } - chmax[0] = 8.0f; - chmax[1] = 3.0f; - chmax[2] = 3.0f; + if (settings->verbose) { + printf ("SharpenEdge amount %f\n", amount); + } - int channels; - if (params->sharpenEdge.threechannels) channels=0; else channels=2; - if (settings->verbose) - printf ("SharpenEdge channels %d\n", channels); + L = new float[width * height]; - int passes=params->sharpenEdge.passes; - if (settings->verbose) - printf ("SharpenEdge passes %d\n", passes); + chmax[0] = 8.0f; + chmax[1] = 3.0f; + chmax[2] = 3.0f; - for (p=0; psharpenEdge.threechannels) { + channels = 0; + } else { + channels = 2; + } + + if (settings->verbose) { + printf ("SharpenEdge channels %d\n", channels); + } + + int passes = params->sharpenEdge.passes; + + if (settings->verbose) { + printf ("SharpenEdge passes %d\n", passes); + } + + for (p = 0; p < passes; p++) + for (c = 0; c <= channels; c++) { // c=0 Luminance only #ifdef _OPENMP -#pragma omp parallel for private(offset) shared(L) + #pragma omp parallel for private(offset) shared(L) #endif - for (offset=0; offsetL[ii][kk]/327.68f; // adjust to RT and to 0..100 - else if (c==1) L[offset] = lab->a[ii][kk]/327.68f; - else /*if (c==2) */ L[offset] = lab->b[ii][kk]/327.68f; - } + + for (offset = 0; offset < width * height; offset++) { + int ii = offset / width; + int kk = offset - ii * width; + + if (c == 0) { + L[offset] = lab->L[ii][kk] / 327.68f; // adjust to RT and to 0..100 + } else if (c == 1) { + L[offset] = lab->a[ii][kk] / 327.68f; + } else { /*if (c==2) */ + L[offset] = lab->b[ii][kk] / 327.68f; + } + } + #ifdef _OPENMP -#pragma omp parallel for private(j,i,iii,kkk, templab,offset,wH,wV,wD1,wD2,s,lumH,lumV,lumD1,lumD2,v,contrast,f1,f2,f3,f4,difT,difB,difL,difR,difLT,difLB,difRT,difRB) shared(lab,L,amount) + #pragma omp parallel for private(j,i,iii,kkk, templab,offset,wH,wV,wD1,wD2,s,lumH,lumV,lumD1,lumD2,v,contrast,f1,f2,f3,f4,difT,difB,difL,difR,difLT,difLB,difRT,difRB) shared(lab,L,amount) #endif - for(j=2; jL[ii][kk]/327.68f; - else if (c==1) lumH=lumV=lumD1=lumD2=v=lab->a[ii][kk]/327.68f; - else /* if (c==2) */ lumH=lumV=lumD1=lumD2=v=lab->b[ii][kk]/327.68f; + s = 1.0f + fabs(wH - wV) / 2.0f; + wD1 = eps2 + fabs(L[offset + width + 1] - L[offset - width - 1]) / s; + wD2 = eps2 + fabs(L[offset + width - 1] - L[offset - width + 1]) / s; + s = wD1; + wD1 /= wD2; + wD2 /= wD1; + + // initial values + int ii = offset / width; + int kk = offset - ii * width; + + if (c == 0) { + lumH = lumV = lumD1 = lumD2 = v = lab->L[ii][kk] / 327.68f; + } else if (c == 1) { + lumH = lumV = lumD1 = lumD2 = v = lab->a[ii][kk] / 327.68f; + } else { /* if (c==2) */ + lumH = lumV = lumD1 = lumD2 = v = lab->b[ii][kk] / 327.68f; + } - // contrast detection - contrast = sqrt(fabs(L[offset+1]-L[offset-1])*fabs(L[offset+1]-L[offset-1])+fabs(L[offset+width]-L[offset-width])*fabs(L[offset+width]-L[offset-width]))/chmax[c]; - if (contrast>1.0f) - contrast=1.0f; + // contrast detection + contrast = sqrt(fabs(L[offset + 1] - L[offset - 1]) * fabs(L[offset + 1] - L[offset - 1]) + fabs(L[offset + width] - L[offset - width]) * fabs(L[offset + width] - L[offset - width])) / chmax[c]; - // new possible values - if (((L[offset]L[offset+1])) || ((L[offset]>L[offset-1])&&(L[offset]epsil)&&(difL>epsil)){ - lumH = (L[offset-1]*difR+L[offset+1]*difL)/(difL+difR); - lumH = v*(1.f-contrast)+lumH*contrast; - } - } + if (contrast > 1.0f) { + contrast = 1.0f; + } - if (((L[offset]L[offset+width])) || ((L[offset]>L[offset-width])&&(L[offset]epsil)&&(difT>epsil)){ - lumV = (L[offset-width]*difB+L[offset+width]*difT)/(difT+difB); - lumV = v*(1.f-contrast)+lumV*contrast; - } - } + // new possible values + if (((L[offset] < L[offset - 1]) && (L[offset] > L[offset + 1])) || ((L[offset] > L[offset - 1]) && (L[offset] < L[offset + 1]))) { + f1 = fabs(L[offset - 2] - L[offset - 1]); + f2 = fabs(L[offset - 1] - L[offset]); + f3 = fabs(L[offset - 1] - L[offset - width]) * fabs(L[offset - 1] - L[offset + width]); + f4 = sqrt(fabs(L[offset - 1] - L[offset - width2]) * fabs(L[offset - 1] - L[offset + width2])); + difL = f1 * f2 * f2 * f3 * f3 * f4; + f1 = fabs(L[offset + 2] - L[offset + 1]); + f2 = fabs(L[offset + 1] - L[offset]); + f3 = fabs(L[offset + 1] - L[offset - width]) * fabs(L[offset + 1] - L[offset + width]); + f4 = sqrt(fabs(L[offset + 1] - L[offset - width2]) * fabs(L[offset + 1] - L[offset + width2])); + difR = f1 * f2 * f2 * f3 * f3 * f4; - if (((L[offset]L[offset+1+width])) || ((L[offset]>L[offset-1-width])&&(L[offset]epsil)&&(difRB>epsil)) { - lumD1 = (L[offset-1-width]*difRB+L[offset+1+width]*difLT)/(difLT+difRB); - lumD1 = v*(1.f-contrast)+lumD1*contrast; - } - } + if ((difR > epsil) && (difL > epsil)) { + lumH = (L[offset - 1] * difR + L[offset + 1] * difL) / (difL + difR); + lumH = v * (1.f - contrast) + lumH * contrast; + } + } - if (((L[offset]L[offset-1+width])) || ((L[offset]>L[offset+1-width])&&(L[offset]epsil)&&(difRT>epsil)) { - lumD2 = (L[offset+1-width]*difLB+L[offset-1+width]*difRT)/(difLB+difRT); - lumD2 = v*(1.f-contrast)+lumD2*contrast; - } - } + if (((L[offset] < L[offset - width]) && (L[offset] > L[offset + width])) || ((L[offset] > L[offset - width]) && (L[offset] < L[offset + width]))) { + f1 = fabs(L[offset - width2] - L[offset - width]); + f2 = fabs(L[offset - width] - L[offset]); + f3 = fabs(L[offset - width] - L[offset - 1]) * fabs(L[offset - width] - L[offset + 1]); + f4 = sqrt(fabs(L[offset - width] - L[offset - 2]) * fabs(L[offset - width] - L[offset + 2])); + difT = f1 * f2 * f2 * f3 * f3 * f4; + f1 = fabs(L[offset + width2] - L[offset + width]); + f2 = fabs(L[offset + width] - L[offset]); + f3 = fabs(L[offset + width] - L[offset - 1]) * fabs(L[offset + width] - L[offset + 1]); + f4 = sqrt(fabs(L[offset + width] - L[offset - 2]) * fabs(L[offset + width] - L[offset + 2])); + difB = f1 * f2 * f2 * f3 * f3 * f4; - s = amount; + if ((difB > epsil) && (difT > epsil)) { + lumV = (L[offset - width] * difB + L[offset + width] * difT) / (difT + difB); + lumV = v * (1.f - contrast) + lumV * contrast; + } + } - // avoid sharpening diagonals too much - if (((fabs(wH/wV)<0.45f)&&(fabs(wH/wV)>0.05f))||((fabs(wV/wH)<0.45f)&&(fabs(wV/wH)>0.05f))) - s = amount/3.0f; + if (((L[offset] < L[offset - 1 - width]) && (L[offset] > L[offset + 1 + width])) || ((L[offset] > L[offset - 1 - width]) && (L[offset] < L[offset + 1 + width]))) { + f1 = fabs(L[offset - 2 - width2] - L[offset - 1 - width]); + f2 = fabs(L[offset - 1 - width] - L[offset]); + f3 = fabs(L[offset - 1 - width] - L[offset - width + 1]) * fabs(L[offset - 1 - width] - L[offset + width - 1]); + f4 = sqrt(fabs(L[offset - 1 - width] - L[offset - width2 + 2]) * fabs(L[offset - 1 - width] - L[offset + width2 - 2])); + difLT = f1 * f2 * f2 * f3 * f3 * f4; + f1 = fabs(L[offset + 2 + width2] - L[offset + 1 + width]); + f2 = fabs(L[offset + 1 + width] - L[offset]); + f3 = fabs(L[offset + 1 + width] - L[offset - width + 1]) * fabs(L[offset + 1 + width] - L[offset + width - 1]); + f4 = sqrt(fabs(L[offset + 1 + width] - L[offset - width2 + 2]) * fabs(L[offset + 1 + width] - L[offset + width2 - 2])); + difRB = f1 * f2 * f2 * f3 * f3 * f4; - // final mix - if ((wH!=0.0f)&&(wV!=0.0f)&&(wD1!=0.0f)&&(wD2!=0.0f)) { - iii = offset/width; - kkk = offset-iii*width; - float provL=lab->L[iii][kkk]/327.68f; - if(c==0){ if(provL < 92.f) templab = v*(1.f-s)+(lumH*wH+lumV*wV+lumD1*wD1+lumD2*wD2)/(wH+wV+wD1+wD2)*s; else templab=provL;} - else templab = v*(1.f-s)+(lumH*wH+lumV*wV+lumD1*wD1+lumD2*wD2)/(wH+wV+wD1+wD2)*s; - if (c==0) lab->L[iii][kkk] = fabs(327.68f*templab); // fabs because lab->L always >0 - else if (c==1) lab->a[iii][kkk] = 327.68f*templab ; - else if (c==2) lab->b[iii][kkk] = 327.68f*templab ; - } + if ((difLT > epsil) && (difRB > epsil)) { + lumD1 = (L[offset - 1 - width] * difRB + L[offset + 1 + width] * difLT) / (difLT + difRB); + lumD1 = v * (1.f - contrast) + lumD1 * contrast; + } + } - } - } + if (((L[offset] < L[offset + 1 - width]) && (L[offset] > L[offset - 1 + width])) || ((L[offset] > L[offset + 1 - width]) && (L[offset] < L[offset - 1 + width]))) { + f1 = fabs(L[offset - 2 + width2] - L[offset - 1 + width]); + f2 = fabs(L[offset - 1 + width] - L[offset]); + f3 = fabs(L[offset - 1 + width] - L[offset - width - 1]) * fabs(L[offset - 1 + width] - L[offset + width + 1]); + f4 = sqrt(fabs(L[offset - 1 + width] - L[offset - width2 - 2]) * fabs(L[offset - 1 + width] - L[offset + width2 + 2])); + difLB = f1 * f2 * f2 * f3 * f3 * f4; + f1 = fabs(L[offset + 2 - width2] - L[offset + 1 - width]); + f2 = fabs(L[offset + 1 - width] - L[offset]) * fabs(L[offset + 1 - width] - L[offset]); + f3 = fabs(L[offset + 1 - width] - L[offset + width + 1]) * fabs(L[offset + 1 - width] - L[offset - width - 1]); + f4 = sqrt(fabs(L[offset + 1 - width] - L[offset + width2 + 2]) * fabs(L[offset + 1 - width] - L[offset - width2 - 2])); + difRT = f1 * f2 * f2 * f3 * f3 * f4; - delete [] L; + if ((difLB > epsil) && (difRT > epsil)) { + lumD2 = (L[offset + 1 - width] * difLB + L[offset - 1 + width] * difRT) / (difLB + difRT); + lumD2 = v * (1.f - contrast) + lumD2 * contrast; + } + } - t2e.set(); - if (settings->verbose) - printf("SharpenEdge gradient %d usec\n", t2e.etime(t1e)); + s = amount; + + // avoid sharpening diagonals too much + if (((fabs(wH / wV) < 0.45f) && (fabs(wH / wV) > 0.05f)) || ((fabs(wV / wH) < 0.45f) && (fabs(wV / wH) > 0.05f))) { + s = amount / 3.0f; + } + + // final mix + if ((wH != 0.0f) && (wV != 0.0f) && (wD1 != 0.0f) && (wD2 != 0.0f)) { + iii = offset / width; + kkk = offset - iii * width; + float provL = lab->L[iii][kkk] / 327.68f; + + if(c == 0) { + if(provL < 92.f) { + templab = v * (1.f - s) + (lumH * wH + lumV * wV + lumD1 * wD1 + lumD2 * wD2) / (wH + wV + wD1 + wD2) * s; + } else { + templab = provL; + } + } else { + templab = v * (1.f - s) + (lumH * wH + lumV * wV + lumD1 * wD1 + lumD2 * wD2) / (wH + wV + wD1 + wD2) * s; + } + + if (c == 0) { + lab->L[iii][kkk] = fabs(327.68f * templab); // fabs because lab->L always >0 + } else if (c == 1) { + lab->a[iii][kkk] = 327.68f * templab ; + } else if (c == 2) { + lab->b[iii][kkk] = 327.68f * templab ; + } + } + + } + } + + delete [] L; + + t2e.set(); + + if (settings->verbose) { + printf("SharpenEdge gradient %d usec\n", t2e.etime(t1e)); + } } // To the extent possible under law, Manuel Llorens @@ -512,201 +617,375 @@ void ImProcFunctions::MLsharpen (LabImage* lab) { //!
The purpose is maximize clarity of the image without creating halo's. //!
Addition from JD : pyramid + pondered contrast with matrix 5x5 //! \param lab LabImage Image in the CIELab colour space -void ImProcFunctions::MLmicrocontrast(LabImage* lab) { - if (params->sharpenMicro.enabled==false) - return; - MyTime t1e,t2e; - t1e.set(); - int k; - if (params->sharpenMicro.matrix == false) k=2; else k=1; - // k=2 matrix 5x5 k=1 matrix 3x3 - int offset,offset2,i,j,col,row,n; - float temp,temp2,temp3,temp4,tempL; - float *LM,v,s,contrast; - int signs[25]; - int width = lab->W, height = lab->H; - float uniform = params->sharpenMicro.uniformity;//between 0 to 100 - int unif; - unif = (int)(uniform/10.0f); //put unif between 0 to 10 - float amount = params->sharpenMicro.amount/1500.0f; //amount 2000.0 quasi no artefacts ==> 1500 = maximum, after artefacts - if (amount < 0.000001f) - return; - if (k==1) - amount *= 2.7f; //25/9 if 3x3 - if (settings->verbose) - printf ("Micro-contrast amount %f\n", amount); - if (settings->verbose) - printf ("Micro-contrast uniformity %i\n",unif); - //modulation uniformity in function of luminance - float L98[11] = {0.001f,0.0015f,0.002f,0.004f,0.006f,0.008f,0.01f,0.03f,0.05f,0.1f,0.1f}; - float L95[11] = {0.0012f,0.002f,0.005f,0.01f,0.02f,0.05f,0.1f,0.12f,0.15f,0.2f,0.25f}; - float L92[11] = {0.01f,0.015f,0.02f,0.06f,0.10f,0.13f,0.17f,0.25f,0.3f,0.32f,0.35f}; - float L90[11] = {0.015f,0.02f,0.04f,0.08f,0.12f,0.15f,0.2f,0.3f,0.4f,0.5f,0.6f}; - float L87[11] = {0.025f,0.03f,0.05f,0.1f,0.15f,0.25f,0.3f,0.4f,0.5f,0.63f,0.75f}; - float L83[11] = {0.055f,0.08f,0.1f,0.15f,0.2f,0.3f,0.4f,0.5f,0.6f,0.75f,0.85f}; - float L80[11] = {0.15f,0.2f,0.25f,0.3f,0.35f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f}; - float L75[11] = {0.22f,0.25f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.85f,0.9f,0.95f}; - float L70[11] = {0.35f,0.4f,0.5f,0.6f,0.7f,0.8f,0.97f,1.0f,1.0f,1.0f,1.0f}; - float L63[11] = {0.55f,0.6f,0.7f,0.8f,0.85f,0.9f,1.0f,1.0f,1.0f,1.0f,1.0f}; - float L58[11] = {0.75f,0.77f,0.8f,0.9f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f}; - //default 5 - //modulation contrast - float Cont0[11] = {0.05f,0.1f,0.2f,0.25f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f}; - float Cont1[11] = {0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,0.95f,1.0f}; - float Cont2[11] = {0.2f,0.40f,0.6f,0.7f,0.8f,0.85f,0.90f,0.95f,1.0f,1.05f,1.10f}; - float Cont3[11] = {0.5f,0.6f,0.7f,0.8f,0.85f,0.9f,1.0f,1.0f,1.05f,1.10f,1.20f}; - float Cont4[11] = {0.8f,0.85f,0.9f,0.95f,1.0f,1.05f,1.10f,1.150f,1.2f,1.25f,1.40f}; - float Cont5[11] = {1.0f,1.1f,1.2f,1.25f,1.3f,1.4f,1.45f,1.50f,1.6f,1.65f,1.80f}; +void ImProcFunctions::MLmicrocontrast(LabImage* lab) +{ + if (params->sharpenMicro.enabled == false) { + return; + } - float chmax=8.0f; - LM = new float[width*height];//allocation for Luminance + MyTime t1e, t2e; + t1e.set(); + int k; + + if (params->sharpenMicro.matrix == false) { + k = 2; + } else { + k = 1; + } + + // k=2 matrix 5x5 k=1 matrix 3x3 + int offset, offset2, i, j, col, row, n; + float temp, temp2, temp3, temp4, tempL; + float *LM, v, s, contrast; + int signs[25]; + int width = lab->W, height = lab->H; + float uniform = params->sharpenMicro.uniformity;//between 0 to 100 + int unif; + unif = (int)(uniform / 10.0f); //put unif between 0 to 10 + float amount = params->sharpenMicro.amount / 1500.0f; //amount 2000.0 quasi no artefacts ==> 1500 = maximum, after artefacts + + if (amount < 0.000001f) { + return; + } + + if (k == 1) { + amount *= 2.7f; //25/9 if 3x3 + } + + if (settings->verbose) { + printf ("Micro-contrast amount %f\n", amount); + } + + if (settings->verbose) { + printf ("Micro-contrast uniformity %i\n", unif); + } + + //modulation uniformity in function of luminance + float L98[11] = {0.001f, 0.0015f, 0.002f, 0.004f, 0.006f, 0.008f, 0.01f, 0.03f, 0.05f, 0.1f, 0.1f}; + float L95[11] = {0.0012f, 0.002f, 0.005f, 0.01f, 0.02f, 0.05f, 0.1f, 0.12f, 0.15f, 0.2f, 0.25f}; + float L92[11] = {0.01f, 0.015f, 0.02f, 0.06f, 0.10f, 0.13f, 0.17f, 0.25f, 0.3f, 0.32f, 0.35f}; + float L90[11] = {0.015f, 0.02f, 0.04f, 0.08f, 0.12f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f}; + float L87[11] = {0.025f, 0.03f, 0.05f, 0.1f, 0.15f, 0.25f, 0.3f, 0.4f, 0.5f, 0.63f, 0.75f}; + float L83[11] = {0.055f, 0.08f, 0.1f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.75f, 0.85f}; + float L80[11] = {0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; + float L75[11] = {0.22f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 0.95f}; + float L70[11] = {0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.97f, 1.0f, 1.0f, 1.0f, 1.0f}; + float L63[11] = {0.55f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + float L58[11] = {0.75f, 0.77f, 0.8f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + //default 5 + //modulation contrast + float Cont0[11] = {0.05f, 0.1f, 0.2f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; + float Cont1[11] = {0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.95f, 1.0f}; + float Cont2[11] = {0.2f, 0.40f, 0.6f, 0.7f, 0.8f, 0.85f, 0.90f, 0.95f, 1.0f, 1.05f, 1.10f}; + float Cont3[11] = {0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.05f, 1.10f, 1.20f}; + float Cont4[11] = {0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.05f, 1.10f, 1.150f, 1.2f, 1.25f, 1.40f}; + float Cont5[11] = {1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.45f, 1.50f, 1.6f, 1.65f, 1.80f}; + + float chmax = 8.0f; + LM = new float[width * height]; //allocation for Luminance #ifdef _OPENMP -#pragma omp parallel for private(offset, i,j) shared(LM) + #pragma omp parallel for private(offset, i,j) shared(LM) #endif - for(j=0; jL[j][i]/327.68f;// adjust to 0.100 and to RT variables - } + + for(j = 0; j < height; j++) + for(i = 0, offset = j * width + i; i < width; i++, offset++) { + LM[offset] = lab->L[j][i] / 327.68f; // adjust to 0.100 and to RT variables + } #ifdef _OPENMP -#pragma omp parallel for private(j,i,offset,s,signs,v,n,row,col,offset2,contrast,temp,temp2,temp3,tempL,temp4) shared(lab,LM,amount,chmax,unif,k,L98,L95,L92,L90,L87,L83,L80,L75,L70,L63,L58,Cont0,Cont1,Cont2,Cont3,Cont4,Cont5) + #pragma omp parallel for private(j,i,offset,s,signs,v,n,row,col,offset2,contrast,temp,temp2,temp3,tempL,temp4) shared(lab,LM,amount,chmax,unif,k,L98,L95,L92,L90,L87,L83,L80,L75,L70,L63,L58,Cont0,Cont1,Cont2,Cont3,Cont4,Cont5) #endif - for(j=k; jLM[offset2]) signs[n]=1; - n++; - } - if (k==1) contrast = sqrt(fabs(LM[offset+1]-LM[offset-1])*fabs(LM[offset+1]-LM[offset-1])+fabs(LM[offset+width]-LM[offset-width])*fabs(LM[offset+width]-LM[offset-width]))/chmax; //for 3x3 - else /* if (k==2) */ contrast = sqrt(fabs(LM[offset+1]-LM[offset-1])*fabs(LM[offset+1]-LM[offset-1])+fabs(LM[offset+width]-LM[offset-width])*fabs(LM[offset+width]-LM[offset-width]) - +fabs(LM[offset+2]-LM[offset-2])*fabs(LM[offset+2]-LM[offset-2])+fabs(LM[offset+2*width]-LM[offset-2*width])*fabs(LM[offset+2*width]-LM[offset-2*width]))/(2*chmax); //for 5x5 - if (contrast>1.0f) - contrast=1.0f; - //matrix 5x5 - temp=lab->L[j][i]/327.68f; //begin 3x3 - temp += CLIREF(v-LM[offset-width-1])*sqrtf(2.0f)*s; - temp += CLIREF(v-LM[offset-width])*s; - temp += CLIREF(v-LM[offset-width+1])*sqrtf(2.0f)*s; - temp += CLIREF(v-LM[offset-1])*s; - temp += CLIREF(v-LM[offset+1])*s; - temp += CLIREF(v-LM[offset+width-1])*sqrtf(2.0f)*s; - temp += CLIREF(v-LM[offset+width])*s; - temp += CLIREF(v-LM[offset+width+1])*sqrtf(2.0f)*s;//end 3x3 + for(j = k; j < height - k; j++) + for(i = k, offset = j * width + i; i < width - k; i++, offset++) { + s = amount; + v = LM[offset]; + n = 0; - // add JD continue 5x5 - if (k==2) { - temp += 2.0f*CLIREF(v-LM[offset+2*width])*s; - temp += 2.0f*CLIREF(v-LM[offset-2*width])*s; - temp += 2.0f*CLIREF(v-LM[offset-2 ])*s; - temp += 2.0f*CLIREF(v-LM[offset+2 ])*s; + for(row = j - k; row <= j + k; row++) + for(col = i - k, offset2 = row * width + col; col <= i + k; col++, offset2++) { + signs[n] = 0; - temp += 2.0f*CLIREF(v-LM[offset+2*width-1])*s*sqrtf(1.25f);// 1.25 = 1*1 + 0.5*0.5 - temp += 2.0f*CLIREF(v-LM[offset+2*width-2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset+2*width+1])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset+2*width+2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset+ width+2])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset+ width-2])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset-2*width-1])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset-2*width-2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset-2*width+1])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset-2*width+2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset- width+2])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset- width-2])*s*sqrtf(1.25f); - } - if (temp <0.0f) temp = 0.0f; - v=temp; + if (v < LM[offset2]) { + signs[n] = -1; + } - n=0; + if (v > LM[offset2]) { + signs[n] = 1; + } - for(row=j-k; row<=j+k; row++){ - for(col=i-k,offset2=row*width+col; col<=i+k; col++,offset2++){ - if (((v0))||((v>LM[offset2])&&(signs[n]<0))) { - temp = v*0.75f+LM[offset2]*0.25f;// 0.75 0.25 - } n++; - } + } + + if (k == 1) { + contrast = sqrt(fabs(LM[offset + 1] - LM[offset - 1]) * fabs(LM[offset + 1] - LM[offset - 1]) + fabs(LM[offset + width] - LM[offset - width]) * fabs(LM[offset + width] - LM[offset - width])) / chmax; //for 3x3 + } else /* if (k==2) */ contrast = sqrt(fabs(LM[offset + 1] - LM[offset - 1]) * fabs(LM[offset + 1] - LM[offset - 1]) + fabs(LM[offset + width] - LM[offset - width]) * fabs(LM[offset + width] - LM[offset - width]) + + fabs(LM[offset + 2] - LM[offset - 2]) * fabs(LM[offset + 2] - LM[offset - 2]) + fabs(LM[offset + 2 * width] - LM[offset - 2 * width]) * fabs(LM[offset + 2 * width] - LM[offset - 2 * width])) / (2 * chmax); //for 5x5 + + if (contrast > 1.0f) { + contrast = 1.0f; } - if (LM[offset]>95.0f || LM[offset]<5.0f) - contrast *= Cont0[unif]; //+ JD : luminance pyramid to adjust contrast by evaluation of LM[offset] - else if (LM[offset]>90.0f || LM[offset]<10.0f) - contrast *= Cont1[unif]; - else if (LM[offset]>80.0f || LM[offset]<20.0f) - contrast *= Cont2[unif]; - else if (LM[offset]>70.0f || LM[offset]<30.0f) - contrast *= Cont3[unif]; - else if (LM[offset]>60.0f || LM[offset]<40.0f) - contrast *= Cont4[unif]; - else - contrast *= Cont5[unif];//(2.0f/k)*Cont5[unif]; - if (contrast>1.0f) - contrast=1.0f; - tempL = 327.68f*(temp*(1.0f-contrast)+LM[offset]*contrast); - // JD: modulation of microcontrast in function of original Luminance and modulation of luminance - temp2 = tempL/(327.68f*LM[offset]);//for highlights - if (temp2>1.0f) { - if (temp2>1.70f) temp2=1.70f;//limit action - if (LM[offset]>98.0f) { lab->L[j][i]=LM[offset]*327.68f; } - else if (LM[offset]>95.0f) { temp3=temp2-1.0f; temp=(L95[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>92.0f) { temp3=temp2-1.0f; temp=(L92[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>90.0f) { temp3=temp2-1.0f; temp=(L90[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>87.0f) { temp3=temp2-1.0f; temp=(L87[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>83.0f) { temp3=temp2-1.0f; temp=(L83[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>80.0f) { temp3=temp2-1.0f; temp=(L80[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>75.0f) { temp3=temp2-1.0f; temp=(L75[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>70.0f) { temp3=temp2-1.0f; temp=(L70[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>63.0f) { temp3=temp2-1.0f; temp=(L63[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>58.0f) { temp3=temp2-1.0f; temp=(L58[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>42.0f) { temp3=temp2-1.0f; temp=(L58[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>37.0f) { temp3=temp2-1.0f; temp=(L63[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>30.0f) { temp3=temp2-1.0f; temp=(L70[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>25.0f) { temp3=temp2-1.0f; temp=(L75[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>20.0f) { temp3=temp2-1.0f; temp=(L80[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>17.0f) { temp3=temp2-1.0f; temp=(L83[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>13.0f) { temp3=temp2-1.0f; temp=(L87[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>10.0f) { temp3=temp2-1.0f; temp=(L90[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]> 5.0f) { temp3=temp2-1.0f; temp=(L95[unif]*temp3)+1.0f; lab->L[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]> 0.0f) { lab->L[j][i]=LM[offset]*327.68f;} - } - temp4 = (327.68f*LM[offset])/tempL;// - if (temp4>1.0f) { - if (temp4>1.7f) - temp4 = 1.7f;//limit action - if (LM[offset]< 2.0f) { temp3=temp4-1.0f; temp=(L98[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]< 5.0f) { temp3=temp4-1.0f; temp=(L95[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]< 8.0f) { temp3=temp4-1.0f; temp=(L92[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<10.0f) { temp3=temp4-1.0f; temp=(L90[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<13.0f) { temp3=temp4-1.0f; temp=(L87[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<17.0f) { temp3=temp4-1.0f; temp=(L83[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<20.0f) { temp3=temp4-1.0f; temp=(L80[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<25.0f) { temp3=temp4-1.0f; temp=(L75[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<30.0f) { temp3=temp4-1.0f; temp=(L70[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<37.0f) { temp3=temp4-1.0f; temp=(L63[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<42.0f) { temp3=temp4-1.0f; temp=(L58[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<58.0f) { temp3=temp4-1.0f; temp=(L58[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<63.0f) { temp3=temp4-1.0f; temp=(L63[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<70.0f) { temp3=temp4-1.0f; temp=(L70[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<75.0f) { temp3=temp4-1.0f; temp=(L75[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<80.0f) { temp3=temp4-1.0f; temp=(L80[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<83.0f) { temp3=temp4-1.0f; temp=(L83[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<87.0f) { temp3=temp4-1.0f; temp=(L87[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<90.0f) { temp3=temp4-1.0f; temp=(L90[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<95.0f) { temp3=temp4-1.0f; temp=(L95[unif]*temp3)+1.0f; lab->L[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<100.0f) { lab->L[j][i]=LM[offset]*327.68f; } - } + //matrix 5x5 + temp = lab->L[j][i] / 327.68f; //begin 3x3 + temp += CLIREF(v - LM[offset - width - 1]) * sqrtf(2.0f) * s; + temp += CLIREF(v - LM[offset - width]) * s; + temp += CLIREF(v - LM[offset - width + 1]) * sqrtf(2.0f) * s; + temp += CLIREF(v - LM[offset - 1]) * s; + temp += CLIREF(v - LM[offset + 1]) * s; + temp += CLIREF(v - LM[offset + width - 1]) * sqrtf(2.0f) * s; + temp += CLIREF(v - LM[offset + width]) * s; + temp += CLIREF(v - LM[offset + width + 1]) * sqrtf(2.0f) * s; //end 3x3 - } - delete [] LM; - t2e.set(); - if (settings->verbose) - printf("Micro-contrast %d usec\n", t2e.etime(t1e)); + // add JD continue 5x5 + if (k == 2) { + temp += 2.0f * CLIREF(v - LM[offset + 2 * width]) * s; + temp += 2.0f * CLIREF(v - LM[offset - 2 * width]) * s; + temp += 2.0f * CLIREF(v - LM[offset - 2 ]) * s; + temp += 2.0f * CLIREF(v - LM[offset + 2 ]) * s; + + temp += 2.0f * CLIREF(v - LM[offset + 2 * width - 1]) * s * sqrtf(1.25f); // 1.25 = 1*1 + 0.5*0.5 + temp += 2.0f * CLIREF(v - LM[offset + 2 * width - 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset + 2 * width + 1]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset + 2 * width + 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset + width + 2]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset + width - 2]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width - 1]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width - 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width + 1]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width + 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset - width + 2]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - width - 2]) * s * sqrtf(1.25f); + } + + if (temp < 0.0f) { + temp = 0.0f; + } + + v = temp; + + n = 0; + + for(row = j - k; row <= j + k; row++) { + for(col = i - k, offset2 = row * width + col; col <= i + k; col++, offset2++) { + if (((v < LM[offset2]) && (signs[n] > 0)) || ((v > LM[offset2]) && (signs[n] < 0))) { + temp = v * 0.75f + LM[offset2] * 0.25f; // 0.75 0.25 + } + + n++; + } + } + + if (LM[offset] > 95.0f || LM[offset] < 5.0f) { + contrast *= Cont0[unif]; //+ JD : luminance pyramid to adjust contrast by evaluation of LM[offset] + } else if (LM[offset] > 90.0f || LM[offset] < 10.0f) { + contrast *= Cont1[unif]; + } else if (LM[offset] > 80.0f || LM[offset] < 20.0f) { + contrast *= Cont2[unif]; + } else if (LM[offset] > 70.0f || LM[offset] < 30.0f) { + contrast *= Cont3[unif]; + } else if (LM[offset] > 60.0f || LM[offset] < 40.0f) { + contrast *= Cont4[unif]; + } else { + contrast *= Cont5[unif]; //(2.0f/k)*Cont5[unif]; + } + + if (contrast > 1.0f) { + contrast = 1.0f; + } + + tempL = 327.68f * (temp * (1.0f - contrast) + LM[offset] * contrast); + // JD: modulation of microcontrast in function of original Luminance and modulation of luminance + temp2 = tempL / (327.68f * LM[offset]); //for highlights + + if (temp2 > 1.0f) { + if (temp2 > 1.70f) { + temp2 = 1.70f; //limit action + } + + if (LM[offset] > 98.0f) { + lab->L[j][i] = LM[offset] * 327.68f; + } else if (LM[offset] > 95.0f) { + temp3 = temp2 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 92.0f) { + temp3 = temp2 - 1.0f; + temp = (L92[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 90.0f) { + temp3 = temp2 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 87.0f) { + temp3 = temp2 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 83.0f) { + temp3 = temp2 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 80.0f) { + temp3 = temp2 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 75.0f) { + temp3 = temp2 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 70.0f) { + temp3 = temp2 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 63.0f) { + temp3 = temp2 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 58.0f) { + temp3 = temp2 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 42.0f) { + temp3 = temp2 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 37.0f) { + temp3 = temp2 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 30.0f) { + temp3 = temp2 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 25.0f) { + temp3 = temp2 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 20.0f) { + temp3 = temp2 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 17.0f) { + temp3 = temp2 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 13.0f) { + temp3 = temp2 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 10.0f) { + temp3 = temp2 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 5.0f) { + temp3 = temp2 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + lab->L[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 0.0f) { + lab->L[j][i] = LM[offset] * 327.68f; + } + } + + temp4 = (327.68f * LM[offset]) / tempL; // + + if (temp4 > 1.0f) { + if (temp4 > 1.7f) { + temp4 = 1.7f; //limit action + } + + if (LM[offset] < 2.0f) { + temp3 = temp4 - 1.0f; + temp = (L98[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 5.0f) { + temp3 = temp4 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 8.0f) { + temp3 = temp4 - 1.0f; + temp = (L92[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 10.0f) { + temp3 = temp4 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 13.0f) { + temp3 = temp4 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 17.0f) { + temp3 = temp4 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 20.0f) { + temp3 = temp4 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 25.0f) { + temp3 = temp4 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 30.0f) { + temp3 = temp4 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 37.0f) { + temp3 = temp4 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 42.0f) { + temp3 = temp4 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 58.0f) { + temp3 = temp4 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 63.0f) { + temp3 = temp4 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 70.0f) { + temp3 = temp4 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 75.0f) { + temp3 = temp4 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 80.0f) { + temp3 = temp4 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 83.0f) { + temp3 = temp4 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 87.0f) { + temp3 = temp4 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 90.0f) { + temp3 = temp4 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 95.0f) { + temp3 = temp4 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + lab->L[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 100.0f) { + lab->L[j][i] = LM[offset] * 327.68f; + } + } + + } + + delete [] LM; + t2e.set(); + + if (settings->verbose) { + printf("Micro-contrast %d usec\n", t2e.etime(t1e)); + } } @@ -714,421 +993,642 @@ void ImProcFunctions::MLmicrocontrast(LabImage* lab) { //!
The purpose is maximize clarity of the image without creating halo's. //!
Addition from JD : pyramid + pondered contrast with matrix 5x5 //! \param ncie CieImage Image in the CIECAM02 colour space -void ImProcFunctions::MLmicrocontrastcam(CieImage* ncie) { - if (params->sharpenMicro.enabled==false) - return; - MyTime t1e,t2e; - t1e.set(); - int k; - if (params->sharpenMicro.matrix == false) k=2; else k=1; - // k=2 matrix 5x5 k=1 matrix 3x3 - int offset,offset2,i,j,col,row,n; - float temp,temp2,temp3,temp4,tempL; - float *LM,v,s,contrast; - int signs[25]; - int width = ncie->W, height = ncie->H; - float uniform = params->sharpenMicro.uniformity;//between 0 to 100 - int unif; - unif = (int)(uniform/10.0f); //put unif between 0 to 10 - float amount = params->sharpenMicro.amount/1500.0f; //amount 2000.0 quasi no artefacts ==> 1500 = maximum, after artefacts - if (amount < 0.000001f) - return; - if (k==1) - amount *= 2.7f; //25/9 if 3x3 - if (settings->verbose) - printf ("Micro-contrast amount %f\n", amount); - if (settings->verbose) - printf ("Micro-contrast uniformity %i\n",unif); - //modulation uniformity in function of luminance - float L98[11] = {0.001f,0.0015f,0.002f,0.004f,0.006f,0.008f,0.01f,0.03f,0.05f,0.1f,0.1f}; - float L95[11] = {0.0012f,0.002f,0.005f,0.01f,0.02f,0.05f,0.1f,0.12f,0.15f,0.2f,0.25f}; - float L92[11] = {0.01f,0.015f,0.02f,0.06f,0.10f,0.13f,0.17f,0.25f,0.3f,0.32f,0.35f}; - float L90[11] = {0.015f,0.02f,0.04f,0.08f,0.12f,0.15f,0.2f,0.3f,0.4f,0.5f,0.6f}; - float L87[11] = {0.025f,0.03f,0.05f,0.1f,0.15f,0.25f,0.3f,0.4f,0.5f,0.63f,0.75f}; - float L83[11] = {0.055f,0.08f,0.1f,0.15f,0.2f,0.3f,0.4f,0.5f,0.6f,0.75f,0.85f}; - float L80[11] = {0.15f,0.2f,0.25f,0.3f,0.35f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f}; - float L75[11] = {0.22f,0.25f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.85f,0.9f,0.95f}; - float L70[11] = {0.35f,0.4f,0.5f,0.6f,0.7f,0.8f,0.97f,1.0f,1.0f,1.0f,1.0f}; - float L63[11] = {0.55f,0.6f,0.7f,0.8f,0.85f,0.9f,1.0f,1.0f,1.0f,1.0f,1.0f}; - float L58[11] = {0.75f,0.77f,0.8f,0.9f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f}; - //default 5 - //modulation contrast - float Cont0[11] = {0.05f,0.1f,0.2f,0.25f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f}; - float Cont1[11] = {0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,0.95f,1.0f}; - float Cont2[11] = {0.2f,0.40f,0.6f,0.7f,0.8f,0.85f,0.90f,0.95f,1.0f,1.05f,1.10f}; - float Cont3[11] = {0.5f,0.6f,0.7f,0.8f,0.85f,0.9f,1.0f,1.0f,1.05f,1.10f,1.20f}; - float Cont4[11] = {0.8f,0.85f,0.9f,0.95f,1.0f,1.05f,1.10f,1.150f,1.2f,1.25f,1.40f}; - float Cont5[11] = {1.0f,1.1f,1.2f,1.25f,1.3f,1.4f,1.45f,1.50f,1.6f,1.65f,1.80f}; +void ImProcFunctions::MLmicrocontrastcam(CieImage* ncie) +{ + if (params->sharpenMicro.enabled == false) { + return; + } - float chmax=8.0f; - LM = new float[width*height];//allocation for Luminance + MyTime t1e, t2e; + t1e.set(); + int k; + + if (params->sharpenMicro.matrix == false) { + k = 2; + } else { + k = 1; + } + + // k=2 matrix 5x5 k=1 matrix 3x3 + int offset, offset2, i, j, col, row, n; + float temp, temp2, temp3, temp4, tempL; + float *LM, v, s, contrast; + int signs[25]; + int width = ncie->W, height = ncie->H; + float uniform = params->sharpenMicro.uniformity;//between 0 to 100 + int unif; + unif = (int)(uniform / 10.0f); //put unif between 0 to 10 + float amount = params->sharpenMicro.amount / 1500.0f; //amount 2000.0 quasi no artefacts ==> 1500 = maximum, after artefacts + + if (amount < 0.000001f) { + return; + } + + if (k == 1) { + amount *= 2.7f; //25/9 if 3x3 + } + + if (settings->verbose) { + printf ("Micro-contrast amount %f\n", amount); + } + + if (settings->verbose) { + printf ("Micro-contrast uniformity %i\n", unif); + } + + //modulation uniformity in function of luminance + float L98[11] = {0.001f, 0.0015f, 0.002f, 0.004f, 0.006f, 0.008f, 0.01f, 0.03f, 0.05f, 0.1f, 0.1f}; + float L95[11] = {0.0012f, 0.002f, 0.005f, 0.01f, 0.02f, 0.05f, 0.1f, 0.12f, 0.15f, 0.2f, 0.25f}; + float L92[11] = {0.01f, 0.015f, 0.02f, 0.06f, 0.10f, 0.13f, 0.17f, 0.25f, 0.3f, 0.32f, 0.35f}; + float L90[11] = {0.015f, 0.02f, 0.04f, 0.08f, 0.12f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f}; + float L87[11] = {0.025f, 0.03f, 0.05f, 0.1f, 0.15f, 0.25f, 0.3f, 0.4f, 0.5f, 0.63f, 0.75f}; + float L83[11] = {0.055f, 0.08f, 0.1f, 0.15f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.75f, 0.85f}; + float L80[11] = {0.15f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; + float L75[11] = {0.22f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 0.95f}; + float L70[11] = {0.35f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.97f, 1.0f, 1.0f, 1.0f, 1.0f}; + float L63[11] = {0.55f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + float L58[11] = {0.75f, 0.77f, 0.8f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + //default 5 + //modulation contrast + float Cont0[11] = {0.05f, 0.1f, 0.2f, 0.25f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f}; + float Cont1[11] = {0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 0.95f, 1.0f}; + float Cont2[11] = {0.2f, 0.40f, 0.6f, 0.7f, 0.8f, 0.85f, 0.90f, 0.95f, 1.0f, 1.05f, 1.10f}; + float Cont3[11] = {0.5f, 0.6f, 0.7f, 0.8f, 0.85f, 0.9f, 1.0f, 1.0f, 1.05f, 1.10f, 1.20f}; + float Cont4[11] = {0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.05f, 1.10f, 1.150f, 1.2f, 1.25f, 1.40f}; + float Cont5[11] = {1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.45f, 1.50f, 1.6f, 1.65f, 1.80f}; + + float chmax = 8.0f; + LM = new float[width * height]; //allocation for Luminance #ifdef _OPENMP -#pragma omp parallel for private(offset, i,j) shared(LM) + #pragma omp parallel for private(offset, i,j) shared(LM) #endif - for(j=0; jsh_p[j][i]/327.68f;// adjust to 0.100 and to RT variables - } + + for(j = 0; j < height; j++) + for(i = 0, offset = j * width + i; i < width; i++, offset++) { + LM[offset] = ncie->sh_p[j][i] / 327.68f; // adjust to 0.100 and to RT variables + } #ifdef _OPENMP -#pragma omp parallel for private(j,i,offset,s,signs,v,n,row,col,offset2,contrast,temp,temp2,temp3,tempL,temp4) shared(ncie,LM,amount,chmax,unif,k,L98,L95,L92,L90,L87,L83,L80,L75,L70,L63,L58,Cont0,Cont1,Cont2,Cont3,Cont4,Cont5) + #pragma omp parallel for private(j,i,offset,s,signs,v,n,row,col,offset2,contrast,temp,temp2,temp3,tempL,temp4) shared(ncie,LM,amount,chmax,unif,k,L98,L95,L92,L90,L87,L83,L80,L75,L70,L63,L58,Cont0,Cont1,Cont2,Cont3,Cont4,Cont5) #endif - for(j=k; jLM[offset2]) signs[n]=1; - n++; - } - if (k==1) contrast = sqrt(fabs(LM[offset+1]-LM[offset-1])*fabs(LM[offset+1]-LM[offset-1])+fabs(LM[offset+width]-LM[offset-width])*fabs(LM[offset+width]-LM[offset-width]))/chmax; //for 3x3 - else /* if (k==2) */ contrast = sqrt(fabs(LM[offset+1]-LM[offset-1])*fabs(LM[offset+1]-LM[offset-1])+fabs(LM[offset+width]-LM[offset-width])*fabs(LM[offset+width]-LM[offset-width]) - +fabs(LM[offset+2]-LM[offset-2])*fabs(LM[offset+2]-LM[offset-2])+fabs(LM[offset+2*width]-LM[offset-2*width])*fabs(LM[offset+2*width]-LM[offset-2*width]))/(2*chmax); //for 5x5 - if (contrast>1.0f) - contrast=1.0f; - //matrix 5x5 - temp=ncie->sh_p[j][i]/327.68f; //begin 3x3 - temp += CLIREF(v-LM[offset-width-1])*sqrtf(2.0f)*s; - temp += CLIREF(v-LM[offset-width])*s; - temp += CLIREF(v-LM[offset-width+1])*sqrtf(2.0f)*s; - temp += CLIREF(v-LM[offset-1])*s; - temp += CLIREF(v-LM[offset+1])*s; - temp += CLIREF(v-LM[offset+width-1])*sqrtf(2.0f)*s; - temp += CLIREF(v-LM[offset+width])*s; - temp += CLIREF(v-LM[offset+width+1])*sqrtf(2.0f)*s;//end 3x3 + for(j = k; j < height - k; j++) + for(i = k, offset = j * width + i; i < width - k; i++, offset++) { + s = amount; + v = LM[offset]; + n = 0; - // add JD continue 5x5 - if (k==2) { - temp += 2.0f*CLIREF(v-LM[offset+2*width])*s; - temp += 2.0f*CLIREF(v-LM[offset-2*width])*s; - temp += 2.0f*CLIREF(v-LM[offset-2 ])*s; - temp += 2.0f*CLIREF(v-LM[offset+2 ])*s; + for(row = j - k; row <= j + k; row++) + for(col = i - k, offset2 = row * width + col; col <= i + k; col++, offset2++) { + signs[n] = 0; - temp += 2.0f*CLIREF(v-LM[offset+2*width-1])*s*sqrtf(1.25f);// 1.25 = 1*1 + 0.5*0.5 - temp += 2.0f*CLIREF(v-LM[offset+2*width-2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset+2*width+1])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset+2*width+2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset+ width+2])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset+ width-2])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset-2*width-1])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset-2*width-2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset-2*width+1])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset-2*width+2])*s*sqrtf(2.00f); - temp += 2.0f*CLIREF(v-LM[offset- width+2])*s*sqrtf(1.25f); - temp += 2.0f*CLIREF(v-LM[offset- width-2])*s*sqrtf(1.25f); - } - if (temp <0.0f) temp = 0.0f; - v=temp; + if (v < LM[offset2]) { + signs[n] = -1; + } - n=0; + if (v > LM[offset2]) { + signs[n] = 1; + } - for(row=j-k; row<=j+k; row++){ - for(col=i-k,offset2=row*width+col; col<=i+k; col++,offset2++){ - if (((v0))||((v>LM[offset2])&&(signs[n]<0))) { - temp = v*0.75f+LM[offset2]*0.25f;// 0.75 0.25 - } n++; - } + } + + if (k == 1) { + contrast = sqrt(fabs(LM[offset + 1] - LM[offset - 1]) * fabs(LM[offset + 1] - LM[offset - 1]) + fabs(LM[offset + width] - LM[offset - width]) * fabs(LM[offset + width] - LM[offset - width])) / chmax; //for 3x3 + } else /* if (k==2) */ contrast = sqrt(fabs(LM[offset + 1] - LM[offset - 1]) * fabs(LM[offset + 1] - LM[offset - 1]) + fabs(LM[offset + width] - LM[offset - width]) * fabs(LM[offset + width] - LM[offset - width]) + + fabs(LM[offset + 2] - LM[offset - 2]) * fabs(LM[offset + 2] - LM[offset - 2]) + fabs(LM[offset + 2 * width] - LM[offset - 2 * width]) * fabs(LM[offset + 2 * width] - LM[offset - 2 * width])) / (2 * chmax); //for 5x5 + + if (contrast > 1.0f) { + contrast = 1.0f; } - if (LM[offset]>95.0f || LM[offset]<5.0f) - contrast *= Cont0[unif]; //+ JD : luminance pyramid to adjust contrast by evaluation of LM[offset] - else if (LM[offset]>90.0f || LM[offset]<10.0f) - contrast *= Cont1[unif]; - else if (LM[offset]>80.0f || LM[offset]<20.0f) - contrast *= Cont2[unif]; - else if (LM[offset]>70.0f || LM[offset]<30.0f) - contrast *= Cont3[unif]; - else if (LM[offset]>60.0f || LM[offset]<40.0f) - contrast *= Cont4[unif]; - else - contrast *= Cont5[unif];//(2.0f/k)*Cont5[unif]; - if (contrast>1.0f) - contrast=1.0f; - tempL = 327.68f*(temp*(1.0f-contrast)+LM[offset]*contrast); - // JD: modulation of microcontrast in function of original Luminance and modulation of luminance - temp2 = tempL/(327.68f*LM[offset]);//for highlights - if (temp2>1.0f) { - if (temp2>1.70f) temp2=1.70f;//limit action - if (LM[offset]>98.0f) { ncie->sh_p[j][i]=LM[offset]*327.68f; } - else if (LM[offset]>95.0f) { temp3=temp2-1.0f; temp=(L95[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>92.0f) { temp3=temp2-1.0f; temp=(L92[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>90.0f) { temp3=temp2-1.0f; temp=(L90[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>87.0f) { temp3=temp2-1.0f; temp=(L87[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>83.0f) { temp3=temp2-1.0f; temp=(L83[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>80.0f) { temp3=temp2-1.0f; temp=(L80[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>75.0f) { temp3=temp2-1.0f; temp=(L75[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>70.0f) { temp3=temp2-1.0f; temp=(L70[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>63.0f) { temp3=temp2-1.0f; temp=(L63[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>58.0f) { temp3=temp2-1.0f; temp=(L58[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>42.0f) { temp3=temp2-1.0f; temp=(L58[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>37.0f) { temp3=temp2-1.0f; temp=(L63[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>30.0f) { temp3=temp2-1.0f; temp=(L70[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>25.0f) { temp3=temp2-1.0f; temp=(L75[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>20.0f) { temp3=temp2-1.0f; temp=(L80[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>17.0f) { temp3=temp2-1.0f; temp=(L83[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>13.0f) { temp3=temp2-1.0f; temp=(L87[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]>10.0f) { temp3=temp2-1.0f; temp=(L90[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]> 5.0f) { temp3=temp2-1.0f; temp=(L95[unif]*temp3)+1.0f; ncie->sh_p[j][i]=temp*LM[offset]*327.68f; } - else if (LM[offset]> 0.0f) { ncie->sh_p[j][i]=LM[offset]*327.68f;} - } - temp4 = (327.68f*LM[offset])/tempL;// - if (temp4>1.0f) { - if (temp4>1.7f) - temp4 = 1.7f;//limit action - if (LM[offset]< 2.0f) { temp3=temp4-1.0f; temp=(L98[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]< 5.0f) { temp3=temp4-1.0f; temp=(L95[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]< 8.0f) { temp3=temp4-1.0f; temp=(L92[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<10.0f) { temp3=temp4-1.0f; temp=(L90[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<13.0f) { temp3=temp4-1.0f; temp=(L87[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<17.0f) { temp3=temp4-1.0f; temp=(L83[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<20.0f) { temp3=temp4-1.0f; temp=(L80[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<25.0f) { temp3=temp4-1.0f; temp=(L75[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<30.0f) { temp3=temp4-1.0f; temp=(L70[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<37.0f) { temp3=temp4-1.0f; temp=(L63[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<42.0f) { temp3=temp4-1.0f; temp=(L58[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<58.0f) { temp3=temp4-1.0f; temp=(L58[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<63.0f) { temp3=temp4-1.0f; temp=(L63[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<70.0f) { temp3=temp4-1.0f; temp=(L70[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<75.0f) { temp3=temp4-1.0f; temp=(L75[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<80.0f) { temp3=temp4-1.0f; temp=(L80[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<83.0f) { temp3=temp4-1.0f; temp=(L83[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<87.0f) { temp3=temp4-1.0f; temp=(L87[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<90.0f) { temp3=temp4-1.0f; temp=(L90[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<95.0f) { temp3=temp4-1.0f; temp=(L95[unif]*temp3)+1.0f; ncie->sh_p[j][i]=(LM[offset]*327.68f)/temp; } - else if (LM[offset]<100.0f) { ncie->sh_p[j][i]=LM[offset]*327.68f; } - } + //matrix 5x5 + temp = ncie->sh_p[j][i] / 327.68f; //begin 3x3 + temp += CLIREF(v - LM[offset - width - 1]) * sqrtf(2.0f) * s; + temp += CLIREF(v - LM[offset - width]) * s; + temp += CLIREF(v - LM[offset - width + 1]) * sqrtf(2.0f) * s; + temp += CLIREF(v - LM[offset - 1]) * s; + temp += CLIREF(v - LM[offset + 1]) * s; + temp += CLIREF(v - LM[offset + width - 1]) * sqrtf(2.0f) * s; + temp += CLIREF(v - LM[offset + width]) * s; + temp += CLIREF(v - LM[offset + width + 1]) * sqrtf(2.0f) * s; //end 3x3 - } - delete [] LM; - t2e.set(); - if (settings->verbose) - printf("Micro-contrast %d usec\n", t2e.etime(t1e)); + // add JD continue 5x5 + if (k == 2) { + temp += 2.0f * CLIREF(v - LM[offset + 2 * width]) * s; + temp += 2.0f * CLIREF(v - LM[offset - 2 * width]) * s; + temp += 2.0f * CLIREF(v - LM[offset - 2 ]) * s; + temp += 2.0f * CLIREF(v - LM[offset + 2 ]) * s; + + temp += 2.0f * CLIREF(v - LM[offset + 2 * width - 1]) * s * sqrtf(1.25f); // 1.25 = 1*1 + 0.5*0.5 + temp += 2.0f * CLIREF(v - LM[offset + 2 * width - 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset + 2 * width + 1]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset + 2 * width + 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset + width + 2]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset + width - 2]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width - 1]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width - 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width + 1]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - 2 * width + 2]) * s * sqrtf(2.00f); + temp += 2.0f * CLIREF(v - LM[offset - width + 2]) * s * sqrtf(1.25f); + temp += 2.0f * CLIREF(v - LM[offset - width - 2]) * s * sqrtf(1.25f); + } + + if (temp < 0.0f) { + temp = 0.0f; + } + + v = temp; + + n = 0; + + for(row = j - k; row <= j + k; row++) { + for(col = i - k, offset2 = row * width + col; col <= i + k; col++, offset2++) { + if (((v < LM[offset2]) && (signs[n] > 0)) || ((v > LM[offset2]) && (signs[n] < 0))) { + temp = v * 0.75f + LM[offset2] * 0.25f; // 0.75 0.25 + } + + n++; + } + } + + if (LM[offset] > 95.0f || LM[offset] < 5.0f) { + contrast *= Cont0[unif]; //+ JD : luminance pyramid to adjust contrast by evaluation of LM[offset] + } else if (LM[offset] > 90.0f || LM[offset] < 10.0f) { + contrast *= Cont1[unif]; + } else if (LM[offset] > 80.0f || LM[offset] < 20.0f) { + contrast *= Cont2[unif]; + } else if (LM[offset] > 70.0f || LM[offset] < 30.0f) { + contrast *= Cont3[unif]; + } else if (LM[offset] > 60.0f || LM[offset] < 40.0f) { + contrast *= Cont4[unif]; + } else { + contrast *= Cont5[unif]; //(2.0f/k)*Cont5[unif]; + } + + if (contrast > 1.0f) { + contrast = 1.0f; + } + + tempL = 327.68f * (temp * (1.0f - contrast) + LM[offset] * contrast); + // JD: modulation of microcontrast in function of original Luminance and modulation of luminance + temp2 = tempL / (327.68f * LM[offset]); //for highlights + + if (temp2 > 1.0f) { + if (temp2 > 1.70f) { + temp2 = 1.70f; //limit action + } + + if (LM[offset] > 98.0f) { + ncie->sh_p[j][i] = LM[offset] * 327.68f; + } else if (LM[offset] > 95.0f) { + temp3 = temp2 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 92.0f) { + temp3 = temp2 - 1.0f; + temp = (L92[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 90.0f) { + temp3 = temp2 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 87.0f) { + temp3 = temp2 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 83.0f) { + temp3 = temp2 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 80.0f) { + temp3 = temp2 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 75.0f) { + temp3 = temp2 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 70.0f) { + temp3 = temp2 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 63.0f) { + temp3 = temp2 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 58.0f) { + temp3 = temp2 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 42.0f) { + temp3 = temp2 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 37.0f) { + temp3 = temp2 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 30.0f) { + temp3 = temp2 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 25.0f) { + temp3 = temp2 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 20.0f) { + temp3 = temp2 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 17.0f) { + temp3 = temp2 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 13.0f) { + temp3 = temp2 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 10.0f) { + temp3 = temp2 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 5.0f) { + temp3 = temp2 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = temp * LM[offset] * 327.68f; + } else if (LM[offset] > 0.0f) { + ncie->sh_p[j][i] = LM[offset] * 327.68f; + } + } + + temp4 = (327.68f * LM[offset]) / tempL; // + + if (temp4 > 1.0f) { + if (temp4 > 1.7f) { + temp4 = 1.7f; //limit action + } + + if (LM[offset] < 2.0f) { + temp3 = temp4 - 1.0f; + temp = (L98[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 5.0f) { + temp3 = temp4 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 8.0f) { + temp3 = temp4 - 1.0f; + temp = (L92[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 10.0f) { + temp3 = temp4 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 13.0f) { + temp3 = temp4 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 17.0f) { + temp3 = temp4 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 20.0f) { + temp3 = temp4 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 25.0f) { + temp3 = temp4 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 30.0f) { + temp3 = temp4 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 37.0f) { + temp3 = temp4 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 42.0f) { + temp3 = temp4 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 58.0f) { + temp3 = temp4 - 1.0f; + temp = (L58[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 63.0f) { + temp3 = temp4 - 1.0f; + temp = (L63[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 70.0f) { + temp3 = temp4 - 1.0f; + temp = (L70[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 75.0f) { + temp3 = temp4 - 1.0f; + temp = (L75[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 80.0f) { + temp3 = temp4 - 1.0f; + temp = (L80[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 83.0f) { + temp3 = temp4 - 1.0f; + temp = (L83[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 87.0f) { + temp3 = temp4 - 1.0f; + temp = (L87[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 90.0f) { + temp3 = temp4 - 1.0f; + temp = (L90[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 95.0f) { + temp3 = temp4 - 1.0f; + temp = (L95[unif] * temp3) + 1.0f; + ncie->sh_p[j][i] = (LM[offset] * 327.68f) / temp; + } else if (LM[offset] < 100.0f) { + ncie->sh_p[j][i] = LM[offset] * 327.68f; + } + } + + } + + delete [] LM; + t2e.set(); + + if (settings->verbose) { + printf("Micro-contrast %d usec\n", t2e.etime(t1e)); + } } -void ImProcFunctions::deconvsharpeningcam (CieImage* ncie, float** b2) { +void ImProcFunctions::deconvsharpeningcam (CieImage* ncie, float** b2) +{ - if (params->sharpening.enabled==false || params->sharpening.deconvamount<1) - return; + if (params->sharpening.enabled == false || params->sharpening.deconvamount < 1) { + return; + } - int W = ncie->W, H = ncie->H; + int W = ncie->W, H = ncie->H; - float** tmpI = new float*[H]; - for (int i=0; ish_p[i][j]; - } + float** tmpI = new float*[H]; - float** tmp = (float**)b2; + for (int i = 0; i < H; i++) { + tmpI[i] = new float[W]; + + for (int j = 0; j < W; j++) { + tmpI[i][j] = (float)ncie->sh_p[i][j]; + } + } + + float** tmp = (float**)b2; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif - { - AlignedBufferMP buffer(max(W,H)); + { + AlignedBufferMP buffer(max(W, H)); - float damping = params->sharpening.deconvdamping / 5.0; - bool needdamp = params->sharpening.deconvdamping > 0; - for (int k=0; ksharpening.deconviter; k++) { + float damping = params->sharpening.deconvdamping / 5.0; + bool needdamp = params->sharpening.deconvdamping > 0; - // apply blur function (gaussian blur) - gaussHorizontal (tmpI, tmp, buffer, W, H, params->sharpening.deconvradius / scale); - gaussVertical (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale); + for (int k = 0; k < params->sharpening.deconviter; k++) { - if (!needdamp) { + // apply blur function (gaussian blur) + gaussHorizontal (tmpI, tmp, buffer, W, H, params->sharpening.deconvradius / scale); + gaussVertical (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale); + + if (!needdamp) { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; i0) - tmp[i][j] = (float)ncie->sh_p[i][j] / tmp[i][j]; - } - else - dcdamping (tmp, ncie->sh_p, damping, W, H); - gaussHorizontal (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale); - gaussVertical (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale); + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) + if (tmp[i][j] > 0) { + tmp[i][j] = (float)ncie->sh_p[i][j] / tmp[i][j]; + } + } else { + dcdamping (tmp, ncie->sh_p, damping, W, H); + } + + gaussHorizontal (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale); + gaussVertical (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; isharpening.deconvamount / 100.0; - float p2 = params->sharpening.deconvamount / 100.0; - float p1 = 1.0 - p2; + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + tmpI[i][j] = tmpI[i][j] * tmp[i][j]; + } + } // end for + +// float p2 = params->sharpening.deconvamount / 100.0; + float p2 = params->sharpening.deconvamount / 100.0; + float p1 = 1.0 - p2; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=0; iJ_p[i][j] > 8.0f && ncie->J_p[i][j] < 92.0f) ncie->sh_p[i][j] = ncie->sh_p[i][j]*p1 + max(tmpI[i][j],0.0f)*p2; - } // end parallel + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) + if(ncie->J_p[i][j] > 8.0f && ncie->J_p[i][j] < 92.0f) { + ncie->sh_p[i][j] = ncie->sh_p[i][j] * p1 + max(tmpI[i][j], 0.0f) * p2; + } - for (int i=0; isharpening.method=="rld") { - deconvsharpeningcam (ncie, b2); - return; - } + if (params->sharpening.method == "rld") { + deconvsharpeningcam (ncie, b2); + return; + } - // Rest is UNSHARP MASK - if (params->sharpening.enabled==false || params->sharpening.amount<1 || ncie->W<8 || ncie->H<8) - return; + // Rest is UNSHARP MASK + if (params->sharpening.enabled == false || params->sharpening.amount < 1 || ncie->W < 8 || ncie->H < 8) { + return; + } - int W = ncie->W, H = ncie->H; - float** b3; + int W = ncie->W, H = ncie->H; + float** b3; float** ncieCopy; - if (params->sharpening.edgesonly) { - b3 = new float*[H]; - for (int i=0; isharpening.edgesonly) { + b3 = new float*[H]; + + for (int i = 0; i < H; i++) { + b3[i] = new float[W]; + } + } if (params->sharpening.halocontrol && !params->sharpening.edgesonly) { // We only need the lab parameter copy in this special case ncieCopy = new float*[H]; - for( int i=0; i buffer(max(W,H)); + AlignedBufferMP buffer(max(W, H)); - if (params->sharpening.edgesonly==false) { + if (params->sharpening.edgesonly == false) { - gaussHorizontal (ncie->sh_p, b2, buffer, W, H, params->sharpening.radius / scale); - gaussVertical (b2, b2, buffer, W, H, params->sharpening.radius / scale); - } - else { - bilateral (ncie->sh_p, (float**)b3, b2, W, H, params->sharpening.edges_radius / scale, params->sharpening.edges_tolerance, multiThread); - gaussHorizontal (b3, b2, buffer, W, H, params->sharpening.radius / scale); - gaussVertical (b2, b2, buffer, W, H, params->sharpening.radius / scale); - } - - float** base = ncie->sh_p; - if (params->sharpening.edgesonly) - base = b3; - - if (params->sharpening.halocontrol==false) { -#ifdef _OPENMP -#pragma omp for -#endif - for (int i=0; isharpening.threshold.multiply( - min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field - params->sharpening.amount * diff * 0.01f // Y axis max value - ); - if(ncie->J_p[i][j] > 8.0f && ncie->J_p[i][j] < 92.0f) ncie->sh_p[i][j] = ncie->sh_p[i][j] + delta; - } - } - else { - if (!params->sharpening.edgesonly) { - // make a deep copy of lab->L -#ifdef _OPENMP -#pragma omp for -#endif - for( int i=0; ish_p[i][j]; - base = ncieCopy; + gaussHorizontal (ncie->sh_p, b2, buffer, W, H, params->sharpening.radius / scale); + gaussVertical (b2, b2, buffer, W, H, params->sharpening.radius / scale); + } else { + bilateral (ncie->sh_p, (float**)b3, b2, W, H, params->sharpening.edges_radius / scale, params->sharpening.edges_tolerance, multiThread); + gaussHorizontal (b3, b2, buffer, W, H, params->sharpening.radius / scale); + gaussVertical (b2, b2, buffer, W, H, params->sharpening.radius / scale); } - sharpenHaloCtrlcam (ncie, b2, base, W, H); - } - } // end parallel + float** base = ncie->sh_p; + + if (params->sharpening.edgesonly) { + base = b3; + } + + if (params->sharpening.halocontrol == false) { +#ifdef _OPENMP + #pragma omp for +#endif + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! + float diff = base[i][j] - b2[i][j]; + float delta = params->sharpening.threshold.multiply( + min(ABS(diff), upperBound), // X axis value = absolute value of the difference, truncated to the max value of this field + params->sharpening.amount * diff * 0.01f // Y axis max value + ); + + if(ncie->J_p[i][j] > 8.0f && ncie->J_p[i][j] < 92.0f) { + ncie->sh_p[i][j] = ncie->sh_p[i][j] + delta; + } + } + } else { + if (!params->sharpening.edgesonly) { + // make a deep copy of lab->L +#ifdef _OPENMP + #pragma omp for +#endif + + for( int i = 0; i < H; i++ ) + for( int j = 0; j < W; j++ ) { + ncieCopy[i][j] = ncie->sh_p[i][j]; + } + + base = ncieCopy; + } + + sharpenHaloCtrlcam (ncie, b2, base, W, H); + } + + } // end parallel if (params->sharpening.halocontrol && !params->sharpening.edgesonly) { // delete the deep copy - for( int i=0; isharpening.edgesonly) { - for (int i=0; isharpening.edgesonly) { + for (int i = 0; i < H; i++) { + delete [] b3[i]; + } + + delete [] b3; + } } -void ImProcFunctions::sharpenHaloCtrlcam (CieImage* ncie, float** blurmap, float** base, int W, int H) { +void ImProcFunctions::sharpenHaloCtrlcam (CieImage* ncie, float** blurmap, float** base, int W, int H) +{ - float scale = (100.f - params->sharpening.halocontrol_amount) * 0.01f; - float sharpFac = params->sharpening.amount * 0.01f; - float** nL = base; + float scale = (100.f - params->sharpening.halocontrol_amount) * 0.01f; + float sharpFac = params->sharpening.amount * 0.01f; + float** nL = base; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int i=2; ish_p[i][j]; - if (max_ < labL) max_ = labL; - if (min_ > labL) min_ = labL; + for (int j = 2; j < W - 2; j++) { + // compute 3 iterations, only forward + np1 = 2.f * (nL[i - 2][j] + nL[i - 2][j + 1] + nL[i - 2][j + 2] + nL[i - 1][j] + nL[i - 1][j + 1] + nL[i - 1][j + 2] + nL[i] [j] + nL[i] [j + 1] + nL[i] [j + 2]) / 27.f + nL[i - 1][j + 1] / 3.f; + np2 = 2.f * (nL[i - 1][j] + nL[i - 1][j + 1] + nL[i - 1][j + 2] + nL[i] [j] + nL[i] [j + 1] + nL[i] [j + 2] + nL[i + 1][j] + nL[i + 1][j + 1] + nL[i + 1][j + 2]) / 27.f + nL[i] [j + 1] / 3.f; + np3 = 2.f * (nL[i] [j] + nL[i] [j + 1] + nL[i] [j + 2] + nL[i + 1][j] + nL[i + 1][j + 1] + nL[i + 1][j + 2] + nL[i + 2][j] + nL[i + 2][j + 1] + nL[i + 2][j + 2]) / 27.f + nL[i + 1][j + 1] / 3.f; - // deviation from the environment as measurement - float diff = nL[i][j] - blurmap[i][j]; + // Max/Min of all these deltas and the last two max/min + maxn = max(np1, np2, np3); + minn = min(np1, np2, np3); + max_ = max(max1, max2, maxn); + min_ = min(min1, min2, minn); - const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! - float delta = params->sharpening.threshold.multiply( - min(ABS(diff), upperBound), // X axis value = absolute value of the difference - sharpFac * diff // Y axis max value = sharpening.amount * signed difference - ); - float newL = labL + delta; - // applying halo control - if (newL > max_) - newL = max_ + (newL-max_) * scale; - else if (newL < min_) - newL = min_ - (min_-newL) * scale; + // Shift the queue + max1 = max2; + max2 = maxn; + min1 = min2; + min2 = minn; + labL = ncie->sh_p[i][j]; - ncie->sh_p[i][j] = newL; - } - } + if (max_ < labL) { + max_ = labL; + } + + if (min_ > labL) { + min_ = labL; + } + + // deviation from the environment as measurement + float diff = nL[i][j] - blurmap[i][j]; + + const float upperBound = 2000.f; // WARNING: Duplicated value, it's baaaaaad ! + float delta = params->sharpening.threshold.multiply( + min(ABS(diff), upperBound), // X axis value = absolute value of the difference + sharpFac * diff // Y axis max value = sharpening.amount * signed difference + ); + float newL = labL + delta; + + // applying halo control + if (newL > max_) { + newL = max_ + (newL - max_) * scale; + } else if (newL < min_) { + newL = min_ - (min_ - newL) * scale; + } + + ncie->sh_p[i][j] = newL; + } + } } } diff --git a/rtengine/iptcpairs.h b/rtengine/iptcpairs.h index 018e7f1bf..363a4f6ab 100644 --- a/rtengine/iptcpairs.h +++ b/rtengine/iptcpairs.h @@ -7,7 +7,7 @@ * 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 @@ -27,22 +27,22 @@ struct IptcPair { }; const IptcPair strTags[] = { - {IPTC_TAG_CAPTION, 2000, "Caption"}, - {IPTC_TAG_WRITER_EDITOR, 32, "CaptionWriter"}, - {IPTC_TAG_HEADLINE, 256, "Headline"}, - {IPTC_TAG_SPECIAL_INSTRUCTIONS, 256, "Instructions"}, - {IPTC_TAG_CATEGORY, 3, "Category"}, - {IPTC_TAG_BYLINE, 32, "Author"}, - {IPTC_TAG_BYLINE_TITLE, 32, "AuthorsPosition"}, - {IPTC_TAG_CREDIT, 32, "Credit"}, - {IPTC_TAG_SOURCE, 32, "Source"}, - {IPTC_TAG_COPYRIGHT_NOTICE, 128, "Copyright"}, - {IPTC_TAG_CITY, 32, "City"}, - {IPTC_TAG_STATE, 32, "Province"}, - {IPTC_TAG_COUNTRY_NAME, 64, "Country"}, - {IPTC_TAG_OBJECT_NAME, 64, "Title"}, - {IPTC_TAG_ORIG_TRANS_REF, 32, "TransReference"}, - {IPTC_TAG_DATE_CREATED, 8, "DateCreated"} + {IPTC_TAG_CAPTION, 2000, "Caption"}, + {IPTC_TAG_WRITER_EDITOR, 32, "CaptionWriter"}, + {IPTC_TAG_HEADLINE, 256, "Headline"}, + {IPTC_TAG_SPECIAL_INSTRUCTIONS, 256, "Instructions"}, + {IPTC_TAG_CATEGORY, 3, "Category"}, + {IPTC_TAG_BYLINE, 32, "Author"}, + {IPTC_TAG_BYLINE_TITLE, 32, "AuthorsPosition"}, + {IPTC_TAG_CREDIT, 32, "Credit"}, + {IPTC_TAG_SOURCE, 32, "Source"}, + {IPTC_TAG_COPYRIGHT_NOTICE, 128, "Copyright"}, + {IPTC_TAG_CITY, 32, "City"}, + {IPTC_TAG_STATE, 32, "Province"}, + {IPTC_TAG_COUNTRY_NAME, 64, "Country"}, + {IPTC_TAG_OBJECT_NAME, 64, "Title"}, + {IPTC_TAG_ORIG_TRANS_REF, 32, "TransReference"}, + {IPTC_TAG_DATE_CREATED, 8, "DateCreated"} }; #endif diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 9d07565ee..a1078e84f 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -26,107 +26,116 @@ #include "sleef.c" using namespace std; -namespace rtengine { +namespace rtengine +{ #undef CLIPTOC #define CLIPTOC(a,b,c,d) ((a)>=(b)?((a)<=(c)?(a):(d=true,(c))):(d=true,(b))) #define RT_PI 3.141592653589 bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef, - const LCPMapper *pLCPMap) { + const LCPMapper *pLCPMap) +{ bool clipped = false; - red.clear (); green.clear (); blue.clear (); + red.clear (); + green.clear (); + blue.clear (); - if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap==NULL)) { - for (size_t i=0; ilensProf.useDist || pLCPMap == NULL)) { + for (size_t i = 0; i < src.size(); i++) { + red.push_back (Coord2D (src[i].x, src[i].y)); + green.push_back (Coord2D (src[i].x, src[i].y)); + blue.push_back (Coord2D (src[i].x, src[i].y)); + } return clipped; } double oW = W, oH = H; - double w2 = (double) oW / 2.0 - 0.5; - double h2 = (double) oH / 2.0 - 0.5; - double maxRadius = sqrt( (double)( oW*oW + oH*oH ) ) / 2; + double w2 = (double) oW / 2.0 - 0.5; + double h2 = (double) oH / 2.0 - 0.5; + double maxRadius = sqrt( (double)( oW * oW + oH * oH ) ) / 2; // auxiliary variables for distortion correction bool needsDist = needsDistortion(); // for performance - double distAmount = params->distortion.amount; + double distAmount = params->distortion.amount; // auxiliary variables for rotation - double cost = cos(params->rotate.degree * RT_PI/180.0); - double sint = sin(params->rotate.degree * RT_PI/180.0); + double cost = cos(params->rotate.degree * RT_PI / 180.0); + double sint = sin(params->rotate.degree * RT_PI / 180.0); // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; - double vpteta = fabs(vpalpha-RT_PI/2)<3e-4 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); - double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); + double vpteta = fabs(vpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-oW * oW * tan(vpalpha) * tan(vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(16 * maxRadius * maxRadius + oW * oW * tan(vpalpha) * tan(vpalpha))) / (maxRadius * maxRadius * 8))); + double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; - double hpteta = fabs(hpalpha-RT_PI/2)<3e-4 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); - double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); + double hpteta = fabs(hpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-oH * oH * tan(hpalpha) * tan(hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(16 * maxRadius * maxRadius + oH * oH * tan(hpalpha) * tan(hpalpha))) / (maxRadius * maxRadius * 8))); + double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); - double ascale = ascaleDef>0 ? ascaleDef : (params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0); + double ascale = ascaleDef > 0 ? ascaleDef : (params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0); - for (size_t i=0; ilensProf.useDist) pLCPMap->correctDistortion(x_d,y_d); // must be first transform + for (size_t i = 0; i < src.size(); i++) { + double x_d = src[i].x, y_d = src[i].y; - y_d = ascale * (y_d - h2); - x_d = ascale * (x_d - w2); + if (pLCPMap && params->lensProf.useDist) { + pLCPMap->correctDistortion(x_d, y_d); // must be first transform + } + + y_d = ascale * (y_d - h2); + x_d = ascale * (x_d - w2); if (needsPerspective()) { // horizontal perspective transformation - y_d *= maxRadius / (maxRadius + x_d*hptanpt); - x_d *= maxRadius * hpcospt / (maxRadius + x_d*hptanpt); + y_d *= maxRadius / (maxRadius + x_d * hptanpt); + x_d *= maxRadius * hpcospt / (maxRadius + x_d * hptanpt); // vertical perspective transformation - x_d *= maxRadius / (maxRadius - y_d*vptanpt); - y_d *= maxRadius * vpcospt / (maxRadius - y_d*vptanpt); + x_d *= maxRadius / (maxRadius - y_d * vptanpt); + y_d *= maxRadius * vpcospt / (maxRadius - y_d * vptanpt); } // rotate - double Dx = x_d * cost - y_d * sint; - double Dy = x_d * sint + y_d * cost; + double Dx = x_d * cost - y_d * sint; + double Dy = x_d * sint + y_d * cost; // distortion correction double s = 1; + if (needsDist) { - double r = sqrt(Dx*Dx + Dy*Dy) / maxRadius; // sqrt is slow + double r = sqrt(Dx * Dx + Dy * Dy) / maxRadius; // sqrt is slow s = 1.0 - distAmount + distAmount * r ; } // LCP CA is not reflected in preview (and very small), so don't add it here - red.push_back (Coord2D(Dx*(s+params->cacorrection.red)+w2, Dy*(s+params->cacorrection.red)+h2)); - green.push_back (Coord2D(Dx*s+w2, Dy*s+h2)); - blue.push_back (Coord2D(Dx*(s+params->cacorrection.blue)+w2, Dy*(s+params->cacorrection.blue)+h2)); - } + red.push_back (Coord2D(Dx * (s + params->cacorrection.red) + w2, Dy * (s + params->cacorrection.red) + h2)); + green.push_back (Coord2D(Dx * s + w2, Dy * s + h2)); + blue.push_back (Coord2D(Dx * (s + params->cacorrection.blue) + w2, Dy * (s + params->cacorrection.blue) + h2)); + } // Clip all points and track if they were any corrections - for (size_t i=0; ix2d) + + for (size_t i = 1; i < transCorners.size(); i++) + if (transCorners[i].x > x2d) { x2d = transCorners[i].x; + } + int x2v = (int)ceil(x2d); double y2d = transCorners[0].y; - for (size_t i=1; iy2d) + + for (size_t i = 1; i < transCorners.size(); i++) + if (transCorners[i].y > y2d) { y2d = transCorners[i].y; + } + int y2v = (int)ceil(y2d); xv = x1v; @@ -201,370 +231,439 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& } void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage) { + double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage) +{ - LCPMapper *pLCPMap=NULL; - if (needsLCP() && focalLen>0) { - LCPProfile *pLCPProf=lcpStore->getProfile(params->lensProf.lcpFile); - if (pLCPProf) pLCPMap=new LCPMapper(pLCPProf, focalLen, focalLen35mm, focusDist, 0, false, params->lensProf.useDist, - original->width, original->height, params->coarse, rawRotationDeg); + LCPMapper *pLCPMap = NULL; + + if (needsLCP() && focalLen > 0) { + LCPProfile *pLCPProf = lcpStore->getProfile(params->lensProf.lcpFile); + + if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm, focusDist, 0, false, params->lensProf.useDist, + original->width, original->height, params->coarse, rawRotationDeg); } - if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient())) + if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient())) { transformLuminanceOnly (original, transformed, cx, cy, oW, oH, fW, fH); - else if (!needsCA() && scale!=1) + } else if (!needsCA() && scale != 1) { transformPreview (original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap); - else + } else { transformHighQuality (original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap, fullImage); + } - if (pLCPMap) delete pLCPMap; + if (pLCPMap) { + delete pLCPMap; + } } // helper function void ImProcFunctions::calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul) { - // vignette center is a point with coordinates between -1 and +1 - double x = vignetting.centerX / 100.0; - double y = vignetting.centerY / 100.0; + // vignette center is a point with coordinates between -1 and +1 + double x = vignetting.centerX / 100.0; + double y = vignetting.centerY / 100.0; - // calculate vignette center in pixels - w2 = (double) oW / 2.0 - 0.5 + x * oW; - h2 = (double) oH / 2.0 - 0.5 + y * oH; + // calculate vignette center in pixels + w2 = (double) oW / 2.0 - 0.5 + x * oW; + h2 = (double) oH / 2.0 - 0.5 + y * oH; - // max vignette radius in pixels - maxRadius = sqrt( (double)( oW*oW + oH*oH ) ) / 2.; + // max vignette radius in pixels + maxRadius = sqrt( (double)( oW * oW + oH * oH ) ) / 2.; - // vignette variables with applied strength - v = 1.0 + vignetting.strength * fabs(vignetting.amount) * 3.0 / 400.0; - b = 1.0 + vignetting.radius * 7.0 / 100.0; - mul = (1.0-v) / tanh(b); + // vignette variables with applied strength + v = 1.0 + vignetting.strength * fabs(vignetting.amount) * 3.0 / 400.0; + b = 1.0 + vignetting.radius * 7.0 / 100.0; + mul = (1.0 - v) / tanh(b); } struct grad_params { - bool angle_is_zero, transpose, bright_top; - float ta, yc, xc; - float ys, ys_inv; - float scale, botmul, topmul; - float top_edge_0; - int h; + bool angle_is_zero, transpose, bright_top; + float ta, yc, xc; + float ys, ys_inv; + float scale, botmul, topmul; + float top_edge_0; + int h; }; static void calcGradientParams(int oW, int oH, const GradientParams& gradient, struct grad_params& gp) { - int w = oW; - int h = oH; - double gradient_stops = gradient.strength; - double gradient_span = gradient.feather / 100.0; - double gradient_center_x = gradient.centerX / 200.0 + 0.5; - double gradient_center_y = gradient.centerY / 200.0 + 0.5; - double gradient_angle = gradient.degree / 180.0 * M_PI; - //fprintf(stderr, "%f %f %f %f %f %d %d\n", gradient_stops, gradient_span, gradient_center_x, gradient_center_y, gradient_angle, w, h); + int w = oW; + int h = oH; + double gradient_stops = gradient.strength; + double gradient_span = gradient.feather / 100.0; + double gradient_center_x = gradient.centerX / 200.0 + 0.5; + double gradient_center_y = gradient.centerY / 200.0 + 0.5; + double gradient_angle = gradient.degree / 180.0 * M_PI; + //fprintf(stderr, "%f %f %f %f %f %d %d\n", gradient_stops, gradient_span, gradient_center_x, gradient_center_y, gradient_angle, w, h); - // make 0.0 <= gradient_angle < 2 * M_PI - gradient_angle = fmod(gradient_angle, 2 * M_PI); - if (gradient_angle < 0.0) { - gradient_angle += 2.0 * M_PI; - } + // make 0.0 <= gradient_angle < 2 * M_PI + gradient_angle = fmod(gradient_angle, 2 * M_PI); - gp.bright_top = false; - gp.transpose = false; - gp.angle_is_zero = false; - gp.h = h; - double cosgrad = cos(gradient_angle); - if (fabs(cosgrad) < 0.707) { - // we transpose to avoid division by zero at 90 degrees - // (actually we could transpose only for 90 degrees, but this way we avoid - // division with extremely small numbers - gp.transpose = true; - gradient_angle += 0.5 * M_PI; - cosgrad = cos(gradient_angle); - double gxc = gradient_center_x; - gradient_center_x = 1.0 - gradient_center_y; - gradient_center_y = gxc; - } - gradient_angle = fmod(gradient_angle, 2 * M_PI); - if (gradient_angle > 0.5 * M_PI && gradient_angle < M_PI) { - gradient_angle += M_PI; - gp.bright_top = true; - } else if (gradient_angle >= M_PI && gradient_angle < 1.5 * M_PI) { - gradient_angle -= M_PI; - gp.bright_top = true; - } - if (fabs(gradient_angle) < 0.001 || fabs(gradient_angle - 2 * M_PI) < 0.001) { - gradient_angle = 0; - gp.angle_is_zero = true; - } - if (gp.transpose) { - gp.bright_top = !gp.bright_top; - } - if (gp.transpose) { - int tmp = w; - w = h; - h = tmp; - } - gp.scale = 1.0 / pow(2, gradient_stops); - if (gp.bright_top) { - gp.topmul = 1.0; - gp.botmul = gp.scale; - } else { - gp.topmul = gp.scale; - gp.botmul = 1.0; - } - gp.ta = tan(gradient_angle); - gp.xc = w * gradient_center_x; - gp.yc = h * gradient_center_y; - gp.ys = sqrt((float)h * h + (float)w * w) * (gradient_span / cos(gradient_angle)); - gp.ys_inv = 1.0 / gp.ys; - gp.top_edge_0 = gp.yc - gp.ys/2.0; - if (gp.ys < 1.0 / h) { - gp.ys_inv = 0; - gp.ys = 0; - } + if (gradient_angle < 0.0) { + gradient_angle += 2.0 * M_PI; + } + + gp.bright_top = false; + gp.transpose = false; + gp.angle_is_zero = false; + gp.h = h; + double cosgrad = cos(gradient_angle); + + if (fabs(cosgrad) < 0.707) { + // we transpose to avoid division by zero at 90 degrees + // (actually we could transpose only for 90 degrees, but this way we avoid + // division with extremely small numbers + gp.transpose = true; + gradient_angle += 0.5 * M_PI; + cosgrad = cos(gradient_angle); + double gxc = gradient_center_x; + gradient_center_x = 1.0 - gradient_center_y; + gradient_center_y = gxc; + } + + gradient_angle = fmod(gradient_angle, 2 * M_PI); + + if (gradient_angle > 0.5 * M_PI && gradient_angle < M_PI) { + gradient_angle += M_PI; + gp.bright_top = true; + } else if (gradient_angle >= M_PI && gradient_angle < 1.5 * M_PI) { + gradient_angle -= M_PI; + gp.bright_top = true; + } + + if (fabs(gradient_angle) < 0.001 || fabs(gradient_angle - 2 * M_PI) < 0.001) { + gradient_angle = 0; + gp.angle_is_zero = true; + } + + if (gp.transpose) { + gp.bright_top = !gp.bright_top; + } + + if (gp.transpose) { + int tmp = w; + w = h; + h = tmp; + } + + gp.scale = 1.0 / pow(2, gradient_stops); + + if (gp.bright_top) { + gp.topmul = 1.0; + gp.botmul = gp.scale; + } else { + gp.topmul = gp.scale; + gp.botmul = 1.0; + } + + gp.ta = tan(gradient_angle); + gp.xc = w * gradient_center_x; + gp.yc = h * gradient_center_y; + gp.ys = sqrt((float)h * h + (float)w * w) * (gradient_span / cos(gradient_angle)); + gp.ys_inv = 1.0 / gp.ys; + gp.top_edge_0 = gp.yc - gp.ys / 2.0; + + if (gp.ys < 1.0 / h) { + gp.ys_inv = 0; + gp.ys = 0; + } } -static float calcGradientFactor(const struct grad_params& gp, int x, int y) { - if (gp.angle_is_zero) { - int gy = gp.transpose ? x : y; - int gx = gp.transpose ? y : x; - if (gy < gp.top_edge_0) { - return gp.topmul; - } else if (gy >= gp.top_edge_0 + gp.ys) { - return gp.botmul; - } else { - float val = ((float)(gy - gp.top_edge_0) * gp.ys_inv); - if (gp.bright_top) { - val = 1.0 - val; - } - if (gp.scale < 1.0) { - val = pow(xsinf(val*M_PI/2), 3); - } else { - val = 1.0 - pow(xcosf(val*M_PI/2), 3); - } - return gp.scale + val * (1.0 - gp.scale); - } - } else { - int gy = gp.transpose ? x : y; - int gx = gp.transpose ? gp.h - y - 1 : x; - float top_edge = gp.yc - gp.ys/2.0 - gp.ta * (gx - gp.xc); - if (gy < top_edge) { - return gp.topmul; - } else if (gy >= top_edge + gp.ys) { - return gp.botmul; - } else { - float val = ((float)(gy - top_edge) * gp.ys_inv); +static float calcGradientFactor(const struct grad_params& gp, int x, int y) +{ + if (gp.angle_is_zero) { + int gy = gp.transpose ? x : y; + int gx = gp.transpose ? y : x; - if (gp.bright_top) { - val = 1.0 - val; - } - if (gp.scale < 1.0) { - val = pow(xsinf(val*M_PI/2), 3); - } else { - val = 1.0 - pow(xcosf(val*M_PI/2), 3); - } - return gp.scale + val * (1.0 - gp.scale); - } - } + if (gy < gp.top_edge_0) { + return gp.topmul; + } else if (gy >= gp.top_edge_0 + gp.ys) { + return gp.botmul; + } else { + float val = ((float)(gy - gp.top_edge_0) * gp.ys_inv); + + if (gp.bright_top) { + val = 1.0 - val; + } + + if (gp.scale < 1.0) { + val = pow(xsinf(val * M_PI / 2), 3); + } else { + val = 1.0 - pow(xcosf(val * M_PI / 2), 3); + } + + return gp.scale + val * (1.0 - gp.scale); + } + } else { + int gy = gp.transpose ? x : y; + int gx = gp.transpose ? gp.h - y - 1 : x; + float top_edge = gp.yc - gp.ys / 2.0 - gp.ta * (gx - gp.xc); + + if (gy < top_edge) { + return gp.topmul; + } else if (gy >= top_edge + gp.ys) { + return gp.botmul; + } else { + float val = ((float)(gy - top_edge) * gp.ys_inv); + + if (gp.bright_top) { + val = 1.0 - val; + } + + if (gp.scale < 1.0) { + val = pow(xsinf(val * M_PI / 2), 3); + } else { + val = 1.0 - pow(xcosf(val * M_PI / 2), 3); + } + + return gp.scale + val * (1.0 - gp.scale); + } + } } struct pcv_params { - float oe_a, oe_b, oe1_a, oe1_b, oe2_a, oe2_b; - float ie_mul, ie1_mul, ie2_mul; - float sepmix, feather; - int w, h, x1, x2, y1, y2; - int sep; - bool is_super_ellipse_mode, is_portrait; - float scale; - float fadeout_mul; + float oe_a, oe_b, oe1_a, oe1_b, oe2_a, oe2_b; + float ie_mul, ie1_mul, ie2_mul; + float sepmix, feather; + int w, h, x1, x2, y1, y2; + int sep; + bool is_super_ellipse_mode, is_portrait; + float scale; + float fadeout_mul; }; -static void calcPCVignetteParams(int fW, int fH, int oW, int oH, const PCVignetteParams& pcvignette, const CropParams &crop, struct pcv_params& pcv) { +static void calcPCVignetteParams(int fW, int fH, int oW, int oH, const PCVignetteParams& pcvignette, const CropParams &crop, struct pcv_params& pcv) +{ - // ellipse formula: (x/a)^2 + (y/b)^2 = 1 - double roundness = pcvignette.roundness / 100.0; - pcv.feather = pcvignette.feather / 100.0; - if (crop.enabled) { - pcv.w = (crop.w * oW) / fW; - pcv.h = (crop.h * oH) / fH; - pcv.x1 = (crop.x * oW) / fW; - pcv.y1 = (crop.y * oH) / fH; - pcv.x2 = pcv.x1+pcv.w; - pcv.y2 = pcv.y1+pcv.h; - } else { - pcv.x1 = 0, pcv.y1 = 0; - pcv.x2 = oW, pcv.y2 = oH; - pcv.w = oW; - pcv.h = oH; - } - pcv.fadeout_mul = 1.0 / (0.05 * sqrtf(oW*oW+oH*oH)); - float short_side = (pcv.w < pcv.h) ? pcv.w : pcv.h; - float long_side = (pcv.w > pcv.h) ? pcv.w : pcv.h; + // ellipse formula: (x/a)^2 + (y/b)^2 = 1 + double roundness = pcvignette.roundness / 100.0; + pcv.feather = pcvignette.feather / 100.0; - pcv.sep = 2; - pcv.sepmix = 0; - pcv.oe_a = sqrt(2.0)*long_side*0.5; - pcv.oe_b = pcv.oe_a * short_side / long_side; - pcv.ie_mul = 1.0 / sqrt(2.0); - pcv.is_super_ellipse_mode = false; - pcv.is_portrait = (pcv.w < pcv.h); - if (roundness < 0.5) { - // make super-ellipse of higher and higher degree - pcv.is_super_ellipse_mode = true; - float sepf = 2 + 4*powf(1.0 - 2*roundness, 1.3); // gamma 1.3 used to balance the effect in the 0.0...0.5 roundness range - pcv.sep = ((int)sepf) & ~0x1; - pcv.sepmix = (sepf - pcv.sep) * 0.5; // 0.0 to 1.0 - pcv.oe1_a = powf(2.0, 1.0/pcv.sep)*long_side*0.5; - pcv.oe1_b = pcv.oe1_a * short_side / long_side; - pcv.ie1_mul = 1.0 / powf(2.0, 1.0/pcv.sep); - pcv.oe2_a = powf(2.0, 1.0/(pcv.sep+2))*long_side*0.5; - pcv.oe2_b = pcv.oe2_a * short_side / long_side; - pcv.ie2_mul = 1.0 / powf(2.0, 1.0/(pcv.sep+2)); - } - if (roundness > 0.5) { - // scale from fitted ellipse towards circle - float rad = sqrtf(pcv.w*pcv.w+pcv.h*pcv.h) / 2.0; - float diff_a = rad - pcv.oe_a; - float diff_b = rad - pcv.oe_b; - pcv.oe_a = pcv.oe_a + diff_a * 2*(roundness - 0.5); - pcv.oe_b = pcv.oe_b + diff_b * 2*(roundness - 0.5); - } - pcv.scale = powf(2, -pcvignette.strength); - if (pcvignette.strength >= 6.0) { - pcv.scale = 0.0; - } + if (crop.enabled) { + pcv.w = (crop.w * oW) / fW; + pcv.h = (crop.h * oH) / fH; + pcv.x1 = (crop.x * oW) / fW; + pcv.y1 = (crop.y * oH) / fH; + pcv.x2 = pcv.x1 + pcv.w; + pcv.y2 = pcv.y1 + pcv.h; + } else { + pcv.x1 = 0, pcv.y1 = 0; + pcv.x2 = oW, pcv.y2 = oH; + pcv.w = oW; + pcv.h = oH; + } + + pcv.fadeout_mul = 1.0 / (0.05 * sqrtf(oW * oW + oH * oH)); + float short_side = (pcv.w < pcv.h) ? pcv.w : pcv.h; + float long_side = (pcv.w > pcv.h) ? pcv.w : pcv.h; + + pcv.sep = 2; + pcv.sepmix = 0; + pcv.oe_a = sqrt(2.0) * long_side * 0.5; + pcv.oe_b = pcv.oe_a * short_side / long_side; + pcv.ie_mul = 1.0 / sqrt(2.0); + pcv.is_super_ellipse_mode = false; + pcv.is_portrait = (pcv.w < pcv.h); + + if (roundness < 0.5) { + // make super-ellipse of higher and higher degree + pcv.is_super_ellipse_mode = true; + float sepf = 2 + 4 * powf(1.0 - 2 * roundness, 1.3); // gamma 1.3 used to balance the effect in the 0.0...0.5 roundness range + pcv.sep = ((int)sepf) & ~0x1; + pcv.sepmix = (sepf - pcv.sep) * 0.5; // 0.0 to 1.0 + pcv.oe1_a = powf(2.0, 1.0 / pcv.sep) * long_side * 0.5; + pcv.oe1_b = pcv.oe1_a * short_side / long_side; + pcv.ie1_mul = 1.0 / powf(2.0, 1.0 / pcv.sep); + pcv.oe2_a = powf(2.0, 1.0 / (pcv.sep + 2)) * long_side * 0.5; + pcv.oe2_b = pcv.oe2_a * short_side / long_side; + pcv.ie2_mul = 1.0 / powf(2.0, 1.0 / (pcv.sep + 2)); + } + + if (roundness > 0.5) { + // scale from fitted ellipse towards circle + float rad = sqrtf(pcv.w * pcv.w + pcv.h * pcv.h) / 2.0; + float diff_a = rad - pcv.oe_a; + float diff_b = rad - pcv.oe_b; + pcv.oe_a = pcv.oe_a + diff_a * 2 * (roundness - 0.5); + pcv.oe_b = pcv.oe_b + diff_b * 2 * (roundness - 0.5); + } + + pcv.scale = powf(2, -pcvignette.strength); + + if (pcvignette.strength >= 6.0) { + pcv.scale = 0.0; + } } -static float calcPCVignetteFactor(const struct pcv_params& pcv, int x, int y) { +static float calcPCVignetteFactor(const struct pcv_params& pcv, int x, int y) +{ - float fo = 1.0; - if (x < pcv.x1 || x > pcv.x2 || y < pcv.y1 || y > pcv.y2) { - /* - The initial plan was to have 1.0 directly outside the crop box (ie no fading), but due to - rounding/trunction here and there I didn't succeed matching up exactly on the pixel with - the crop box. To hide that mismatch I made a fade. - */ - int dist_x = (x < pcv.x1) ? pcv.x1 - x : x - pcv.x2; - int dist_y = (y < pcv.y1) ? pcv.y1 - y : y - pcv.y2; - if (dist_x < 0) dist_x = 0; - if (dist_y < 0) dist_y = 0; - fo = sqrtf(dist_x*dist_x+dist_y*dist_y) * pcv.fadeout_mul; - if (fo >= 1.0) { - return 1.0; - } - } - float val, a, b; - if (pcv.is_portrait) { - a = fabs((y-pcv.y1)-pcv.h*0.5); - b = fabs((x-pcv.x1)-pcv.w*0.5); - } else { - a = fabs((x-pcv.x1)-pcv.w*0.5); - b = fabs((y-pcv.y1)-pcv.h*0.5); - } - float angle = xatan2f(b, a); - float dist = sqrtf(a*a+b*b); - float dist_oe, dist_ie; - float2 sincosval; - if(dist==0.0f) { - sincosval.y = 1.0f; // cos - sincosval.x = 0.0f; // sin - } else { - sincosval.y = a / dist; // cos - sincosval.x = b / dist; // sin - } - if (pcv.is_super_ellipse_mode) { - float dist_oe1 = pcv.oe1_a*pcv.oe1_b / pow_F(pow(pcv.oe1_b*sincosval.y, pcv.sep) + pow(pcv.oe1_a*sincosval.x, pcv.sep), 1.0/pcv.sep); - float dist_oe2 = pcv.oe2_a*pcv.oe2_b / pow_F(pow(pcv.oe2_b*sincosval.y, pcv.sep+2) + pow(pcv.oe2_a*sincosval.x, pcv.sep+2), 1.0/(pcv.sep+2)); - float dist_ie1 = pcv.ie1_mul * dist_oe1 * (1.0 - pcv.feather); - float dist_ie2 = pcv.ie2_mul * dist_oe2 * (1.0 - pcv.feather); - dist_oe = dist_oe1 * (1.0 - pcv.sepmix) + dist_oe2 * pcv.sepmix; - dist_ie = dist_ie1 * (1.0 - pcv.sepmix) + dist_ie2 * pcv.sepmix; - } else { - dist_oe = pcv.oe_a*pcv.oe_b / sqrtf(SQR(pcv.oe_b*sincosval.y) + SQR(pcv.oe_a*sincosval.x)); - dist_ie = pcv.ie_mul * dist_oe * (1.0 - pcv.feather); - } - if (dist <= dist_ie) { - return 1.0; - } + float fo = 1.0; - if (dist >= dist_oe) { - val = pcv.scale; - } else { - val = (dist - dist_ie) / (dist_oe - dist_ie); - if (pcv.scale < 1.0) { - val = pow(xcosf(val*M_PI/2), 4); - } else { - val = 1 - pow(xsinf(val*M_PI/2), 4); - } - val = pcv.scale + val * (1.0 - pcv.scale); - } - if (fo < 1.0) { - val = 1.0 * fo + val * (1.0 - fo); - } - return val; + if (x < pcv.x1 || x > pcv.x2 || y < pcv.y1 || y > pcv.y2) { + /* + The initial plan was to have 1.0 directly outside the crop box (ie no fading), but due to + rounding/trunction here and there I didn't succeed matching up exactly on the pixel with + the crop box. To hide that mismatch I made a fade. + */ + int dist_x = (x < pcv.x1) ? pcv.x1 - x : x - pcv.x2; + int dist_y = (y < pcv.y1) ? pcv.y1 - y : y - pcv.y2; + + if (dist_x < 0) { + dist_x = 0; + } + + if (dist_y < 0) { + dist_y = 0; + } + + fo = sqrtf(dist_x * dist_x + dist_y * dist_y) * pcv.fadeout_mul; + + if (fo >= 1.0) { + return 1.0; + } + } + + float val, a, b; + + if (pcv.is_portrait) { + a = fabs((y - pcv.y1) - pcv.h * 0.5); + b = fabs((x - pcv.x1) - pcv.w * 0.5); + } else { + a = fabs((x - pcv.x1) - pcv.w * 0.5); + b = fabs((y - pcv.y1) - pcv.h * 0.5); + } + + float angle = xatan2f(b, a); + float dist = sqrtf(a * a + b * b); + float dist_oe, dist_ie; + float2 sincosval; + + if(dist == 0.0f) { + sincosval.y = 1.0f; // cos + sincosval.x = 0.0f; // sin + } else { + sincosval.y = a / dist; // cos + sincosval.x = b / dist; // sin + } + + if (pcv.is_super_ellipse_mode) { + float dist_oe1 = pcv.oe1_a * pcv.oe1_b / pow_F(pow(pcv.oe1_b * sincosval.y, pcv.sep) + pow(pcv.oe1_a * sincosval.x, pcv.sep), 1.0 / pcv.sep); + float dist_oe2 = pcv.oe2_a * pcv.oe2_b / pow_F(pow(pcv.oe2_b * sincosval.y, pcv.sep + 2) + pow(pcv.oe2_a * sincosval.x, pcv.sep + 2), 1.0 / (pcv.sep + 2)); + float dist_ie1 = pcv.ie1_mul * dist_oe1 * (1.0 - pcv.feather); + float dist_ie2 = pcv.ie2_mul * dist_oe2 * (1.0 - pcv.feather); + dist_oe = dist_oe1 * (1.0 - pcv.sepmix) + dist_oe2 * pcv.sepmix; + dist_ie = dist_ie1 * (1.0 - pcv.sepmix) + dist_ie2 * pcv.sepmix; + } else { + dist_oe = pcv.oe_a * pcv.oe_b / sqrtf(SQR(pcv.oe_b * sincosval.y) + SQR(pcv.oe_a * sincosval.x)); + dist_ie = pcv.ie_mul * dist_oe * (1.0 - pcv.feather); + } + + if (dist <= dist_ie) { + return 1.0; + } + + if (dist >= dist_oe) { + val = pcv.scale; + } else { + val = (dist - dist_ie) / (dist_oe - dist_ie); + + if (pcv.scale < 1.0) { + val = pow(xcosf(val * M_PI / 2), 4); + } else { + val = 1 - pow(xsinf(val * M_PI / 2), 4); + } + + val = pcv.scale + val * (1.0 - pcv.scale); + } + + if (fo < 1.0) { + val = 1.0 * fo + val * (1.0 - fo); + } + + return val; } -void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH) { - const bool applyVignetting = needsVignetting(); - const bool applyGradient = needsGradient(); - const bool applyPCVignetting = needsPCVignetting(); +void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH) +{ + const bool applyVignetting = needsVignetting(); + const bool applyGradient = needsGradient(); + const bool applyPCVignetting = needsPCVignetting(); - double vig_w2, vig_h2, maxRadius, v, b, mul; - if (applyVignetting) { - calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); - } + double vig_w2, vig_h2, maxRadius, v, b, mul; - struct grad_params gp; - if (applyGradient) { - calcGradientParams(oW, oH, params->gradient, gp); - } + if (applyVignetting) { + calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); + } - struct pcv_params pcv; - if (applyPCVignetting) { - //fprintf(stderr, "%d %d | %d %d | %d %d | %d %d [%d %d]\n", fW, fH, oW, oH, transformed->width, transformed->height, cx, cy, params->crop.w, params->crop.h); - calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); - } - bool darkening = (params->vignetting.amount <= 0.0); - #pragma omp parallel for schedule(dynamic,16) if (multiThread) - for (int y=0; yheight; y++) { - double vig_y_d = (double) (y + cy) - vig_h2 ; - for (int x=0; xwidth; x++) { - double factor = 1.0; - if (applyVignetting) { - double vig_x_d = (double) (x + cx) - vig_w2 ; - double r = sqrt(vig_x_d*vig_x_d + vig_y_d*vig_y_d); - if(darkening) - factor /= std::max(v + mul * tanh (b*(maxRadius-r) / maxRadius), 0.001); - else - factor = v + mul * tanh (b*(maxRadius-r) / maxRadius); - } - if (applyGradient) { - factor *= calcGradientFactor(gp, cx+x, cy+y); - } - if (applyPCVignetting) { - factor *= calcPCVignetteFactor(pcv, cx+x, cy+y); - } - transformed->r(y,x) = original->r(y,x) * factor; - transformed->g(y,x) = original->g(y,x) * factor; - transformed->b(y,x) = original->b(y,x) * factor; - } - } + struct grad_params gp; + + if (applyGradient) { + calcGradientParams(oW, oH, params->gradient, gp); + } + + struct pcv_params pcv; + + if (applyPCVignetting) { + //fprintf(stderr, "%d %d | %d %d | %d %d | %d %d [%d %d]\n", fW, fH, oW, oH, transformed->width, transformed->height, cx, cy, params->crop.w, params->crop.h); + calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); + } + + bool darkening = (params->vignetting.amount <= 0.0); + #pragma omp parallel for schedule(dynamic,16) if (multiThread) + + for (int y = 0; y < transformed->height; y++) { + double vig_y_d = (double) (y + cy) - vig_h2 ; + + for (int x = 0; x < transformed->width; x++) { + double factor = 1.0; + + if (applyVignetting) { + double vig_x_d = (double) (x + cx) - vig_w2 ; + double r = sqrt(vig_x_d * vig_x_d + vig_y_d * vig_y_d); + + if(darkening) { + factor /= std::max(v + mul * tanh (b * (maxRadius - r) / maxRadius), 0.001); + } else { + factor = v + mul * tanh (b * (maxRadius - r) / maxRadius); + } + } + + if (applyGradient) { + factor *= calcGradientFactor(gp, cx + x, cy + y); + } + + if (applyPCVignetting) { + factor *= calcPCVignetteFactor(pcv, cx + x, cy + y); + } + + transformed->r(y, x) = original->r(y, x) * factor; + transformed->g(y, x) = original->g(y, x) * factor; + transformed->b(y, x) = original->b(y, x) * factor; + } + } } // Transform WITH scaling (opt.) and CA, cubic interpolation void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - const LCPMapper *pLCPMap, bool fullImage) { + const LCPMapper *pLCPMap, bool fullImage) +{ - double w2 = (double) oW / 2.0 - 0.5; - double h2 = (double) oH / 2.0 - 0.5; + double w2 = (double) oW / 2.0 - 0.5; + double h2 = (double) oH / 2.0 - 0.5; - double vig_w2,vig_h2,maxRadius,v,b,mul; - calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); + double vig_w2, vig_h2, maxRadius, v, b, mul; + calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); - struct grad_params gp; - if (needsGradient()) { - calcGradientParams(oW, oH, params->gradient, gp); - } - struct pcv_params pcv; - if (needsPCVignetting()) { - calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); - } + struct grad_params gp; + + if (needsGradient()) { + calcGradientParams(oW, oH, params->gradient, gp); + } + + struct pcv_params pcv; + + if (needsPCVignetting()) { + calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); + } float** chOrig[3]; chOrig[0] = original->r.ptrs; @@ -582,61 +681,70 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr chDist[1] = 0.0; chDist[2] = params->cacorrection.blue; - // auxiliary variables for distortion correction + // auxiliary variables for distortion correction bool needsDist = needsDistortion(); // for performance - double distAmount = params->distortion.amount; + double distAmount = params->distortion.amount; - // auxiliary variables for rotation - double cost = cos(params->rotate.degree * RT_PI/180.0); - double sint = sin(params->rotate.degree * RT_PI/180.0); + // auxiliary variables for rotation + double cost = cos(params->rotate.degree * RT_PI / 180.0); + double sint = sin(params->rotate.degree * RT_PI / 180.0); - // auxiliary variables for vertical perspective correction + // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI; - double vpteta = fabs(vpalpha-RT_PI/2)<3e-4 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-SQR(oW*tan(vpalpha)) + (vpdeg>0 ? 1.0 : -1.0) * - oW*tan(vpalpha)*sqrt(SQR(4*maxRadius)+SQR(oW*tan(vpalpha))))/(SQR(maxRadius)*8))); - double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); + double vpteta = fabs(vpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oW * tan(vpalpha)) + (vpdeg > 0 ? 1.0 : -1.0) * + oW * tan(vpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oW * tan(vpalpha)))) / (SQR(maxRadius) * 8))); + double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); - // auxiliary variables for horizontal perspective correction + // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; double hpalpha = (90.0 - hpdeg) / 180.0 * RT_PI; - double hpteta = fabs(hpalpha-RT_PI/2)<3e-4 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-SQR(oH*tan(hpalpha)) + (hpdeg>0 ? 1.0 : -1.0) * - oH*tan(hpalpha)*sqrt(SQR(4*maxRadius)+SQR(oH*tan(hpalpha))))/(SQR(maxRadius)*8))); - double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); + double hpteta = fabs(hpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-SQR(oH * tan(hpalpha)) + (hpdeg > 0 ? 1.0 : -1.0) * + oH * tan(hpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oH * tan(hpalpha)))) / (SQR(maxRadius) * 8))); + double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); - double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, fullImage ? pLCPMap : NULL) : 1.0; + double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, fullImage ? pLCPMap : NULL) : 1.0; // smaller crop images are a problem, so only when processing fully - bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage && pLCPMap->enableCA; + bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage && pLCPMap->enableCA; bool enableLCPDist = pLCPMap && params->lensProf.useDist && fullImage; - if (enableLCPCA) enableLCPDist=false; - bool enableCA = enableLCPCA || needsCA(); - // main cycle - bool darkening = (params->vignetting.amount <= 0.0); - #pragma omp parallel for if (multiThread) - for (int y=0; yheight; y++) { - for (int x=0; xwidth; x++) { - double x_d=x,y_d=y; - if (enableLCPDist) pLCPMap->correctDistortion(x_d,y_d); // must be first transform + if (enableLCPCA) { + enableLCPDist = false; + } - x_d = ascale * (x_d + cx - w2); // centering x coord & scale - y_d = ascale * (y_d + cy - h2); // centering y coord & scale + bool enableCA = enableLCPCA || needsCA(); + + // main cycle + bool darkening = (params->vignetting.amount <= 0.0); + #pragma omp parallel for if (multiThread) + + for (int y = 0; y < transformed->height; y++) { + for (int x = 0; x < transformed->width; x++) { + double x_d = x, y_d = y; + + if (enableLCPDist) { + pLCPMap->correctDistortion(x_d, y_d); // must be first transform + } + + x_d = ascale * (x_d + cx - w2); // centering x coord & scale + y_d = ascale * (y_d + cy - h2); // centering y coord & scale double vig_x_d, vig_y_d; + if (needsVignetting()) { - vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale - vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale + vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale + vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale } if (needsPerspective()) { - // horizontal perspective transformation - y_d *= maxRadius / (maxRadius + x_d*hptanpt); - x_d *= maxRadius * hpcospt / (maxRadius + x_d*hptanpt); + // horizontal perspective transformation + y_d *= maxRadius / (maxRadius + x_d * hptanpt); + x_d *= maxRadius * hpcospt / (maxRadius + x_d * hptanpt); - // vertical perspective transformation - x_d *= maxRadius / (maxRadius - y_d*vptanpt); - y_d *= maxRadius * vpcospt / (maxRadius - y_d*vptanpt); + // vertical perspective transformation + x_d *= maxRadius / (maxRadius - y_d * vptanpt); + y_d *= maxRadius * vpcospt / (maxRadius - y_d * vptanpt); } // rotate @@ -645,79 +753,92 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr // distortion correction double s = 1; + if (needsDist) { - double r = sqrt(Dxc*Dxc + Dyc*Dyc) / maxRadius; // sqrt is slow + double r = sqrt(Dxc * Dxc + Dyc * Dyc) / maxRadius; // sqrt is slow s = 1.0 - distAmount + distAmount * r ; } double r2; + if (needsVignetting()) { double vig_Dx = vig_x_d * cost - vig_y_d * sint; double vig_Dy = vig_x_d * sint + vig_y_d * cost; - r2=sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy); + r2 = sqrt(vig_Dx * vig_Dx + vig_Dy * vig_Dy); } - for (int c=0; c < (enableCA ? 3 : 1); c++) { + for (int c = 0; c < (enableCA ? 3 : 1); c++) { double Dx = Dxc * (s + chDist[c]); double Dy = Dyc * (s + chDist[c]); // de-center - Dx += w2; Dy += h2; + Dx += w2; + Dy += h2; // LCP CA - if (enableLCPCA) pLCPMap->correctCA(Dx,Dy,c); + if (enableLCPCA) { + pLCPMap->correctCA(Dx, Dy, c); + } // Extract integer and fractions of source screen coordinates - int xc = (int)Dx; Dx -= (double)xc; xc -= sx; - int yc = (int)Dy; Dy -= (double)yc; yc -= sy; + int xc = (int)Dx; + Dx -= (double)xc; + xc -= sx; + int yc = (int)Dy; + Dy -= (double)yc; + yc -= sy; // Convert only valid pixels - if (yc>=0 && ycheight && xc>=0 && xcwidth) { + if (yc >= 0 && yc < original->height && xc >= 0 && xc < original->width) { // multiplier for vignetting correction double vignmul = 1.0; + if (needsVignetting()) - if(darkening) - vignmul /= std::max(v + mul * tanh (b*(maxRadius-s*r2) / maxRadius), 0.001); - else - vignmul *= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius)); + if(darkening) { + vignmul /= std::max(v + mul * tanh (b * (maxRadius - s * r2) / maxRadius), 0.001); + } else { + vignmul *= (v + mul * tanh (b * (maxRadius - s * r2) / maxRadius)); + } + if (needsGradient()) { - vignmul *= calcGradientFactor(gp, cx+x, cy+y); - } - if (needsPCVignetting()) { - vignmul *= calcPCVignetteFactor(pcv, cx+x, cy+y); + vignmul *= calcGradientFactor(gp, cx + x, cy + y); } - if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) { + if (needsPCVignetting()) { + vignmul *= calcPCVignetteFactor(pcv, cx + x, cy + y); + } + + if (yc > 0 && yc < original->height - 2 && xc > 0 && xc < original->width - 2) { // all interpolation pixels inside image - if (enableCA) - interpolateTransformChannelsCubic (chOrig[c], xc-1, yc-1, Dx, Dy, &(chTrans[c][y][x]), vignmul); - else - interpolateTransformCubic (original, xc-1, yc-1, Dx, Dy, &(transformed->r(y,x)), &(transformed->g(y,x)), &(transformed->b(y,x)), vignmul); - } else { + if (enableCA) { + interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, &(chTrans[c][y][x]), vignmul); + } else { + interpolateTransformCubic (original, xc - 1, yc - 1, Dx, Dy, &(transformed->r(y, x)), &(transformed->g(y, x)), &(transformed->b(y, x)), vignmul); + } + } else { // edge pixels - int y1 = LIM(yc, 0, original->height-1); - int y2 = LIM(yc+1, 0, original->height-1); - int x1 = LIM(xc, 0, original->width-1); - int x2 = LIM(xc+1, 0, original->width-1); + int y1 = LIM(yc, 0, original->height - 1); + int y2 = LIM(yc + 1, 0, original->height - 1); + int x1 = LIM(xc, 0, original->width - 1); + int x2 = LIM(xc + 1, 0, original->width - 1); if (enableCA) { - chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1]*(1.0-Dx)*(1.0-Dy) + chOrig[c][y1][x2]*Dx*(1.0-Dy) + chOrig[c][y2][x1]*(1.0-Dx)*Dy + chOrig[c][y2][x2]*Dx*Dy); + chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); } else { - transformed->r(y,x) = vignmul*(original->r(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->r(y1,x2)*Dx*(1.0-Dy) + original->r(y2,x1)*(1.0-Dx)*Dy + original->r(y2,x2)*Dx*Dy); - transformed->g(y,x) = vignmul*(original->g(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->g(y1,x2)*Dx*(1.0-Dy) + original->g(y2,x1)*(1.0-Dx)*Dy + original->g(y2,x2)*Dx*Dy); - transformed->b(y,x) = vignmul*(original->b(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->b(y1,x2)*Dx*(1.0-Dy) + original->b(y2,x1)*(1.0-Dx)*Dy + original->b(y2,x2)*Dx*Dy); + transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); } } - } - else { + } else { if (enableCA) { // not valid (source pixel x,y not inside source image, etc.) chTrans[c][y][x] = 0; } else { - transformed->r(y,x) = 0; - transformed->g(y,x) = 0; - transformed->b(y,x) = 0; + transformed->r(y, x) = 0; + transformed->g(y, x) = 0; + transformed->b(y, x) = 0; } } } @@ -726,197 +847,229 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr } // Transform WITH scaling, WITHOUT CA, simple (and fast) interpolation. Used for preview -void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap) { +void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap) +{ - double w2 = (double) oW / 2.0 - 0.5; - double h2 = (double) oH / 2.0 - 0.5; + double w2 = (double) oW / 2.0 - 0.5; + double h2 = (double) oH / 2.0 - 0.5; - double vig_w2, vig_h2, maxRadius, v, b, mul; - calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); + double vig_w2, vig_h2, maxRadius, v, b, mul; + calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul); struct grad_params gp; + if (needsGradient()) { calcGradientParams(oW, oH, params->gradient, gp); } + struct pcv_params pcv; + if (needsPCVignetting()) { calcPCVignetteParams(fW, fH, oW, oH, params->pcvignette, params->crop, pcv); } - // auxiliary variables for distortion correction + // auxiliary variables for distortion correction bool needsDist = needsDistortion(); // for performance - double distAmount = params->distortion.amount; + double distAmount = params->distortion.amount; - // auxiliary variables for rotation - double cost = cos(params->rotate.degree * RT_PI/180.0); - double sint = sin(params->rotate.degree * RT_PI/180.0); + // auxiliary variables for rotation + double cost = cos(params->rotate.degree * RT_PI / 180.0); + double sint = sin(params->rotate.degree * RT_PI / 180.0); - // auxiliary variables for vertical perspective correction + // auxiliary variables for vertical perspective correction double vpdeg = params->perspective.vertical / 100.0 * 45.0; double vpalpha = (90 - vpdeg) / 180.0 * RT_PI; - double vpteta = fabs(vpalpha-RT_PI/2)<3e-4 ? 0.0 : acos ((vpdeg>0 ? 1.0 : -1.0) * sqrt((-oW*oW*tan(vpalpha)*tan(vpalpha) + (vpdeg>0 ? 1.0 : -1.0) * oW*tan(vpalpha)*sqrt(16*maxRadius*maxRadius+oW*oW*tan(vpalpha)*tan(vpalpha)))/(maxRadius*maxRadius*8))); - double vpcospt = (vpdeg>=0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); + double vpteta = fabs(vpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt((-oW * oW * tan(vpalpha) * tan(vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan(vpalpha) * sqrt(16 * maxRadius * maxRadius + oW * oW * tan(vpalpha) * tan(vpalpha))) / (maxRadius * maxRadius * 8))); + double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta); - // auxiliary variables for horizontal perspective correction + // auxiliary variables for horizontal perspective correction double hpdeg = params->perspective.horizontal / 100.0 * 45.0; double hpalpha = (90 - hpdeg) / 180.0 * RT_PI; - double hpteta = fabs(hpalpha-RT_PI/2)<3e-4 ? 0.0 : acos ((hpdeg>0 ? 1.0 : -1.0) * sqrt((-oH*oH*tan(hpalpha)*tan(hpalpha) + (hpdeg>0 ? 1.0 : -1.0) * oH*tan(hpalpha)*sqrt(16*maxRadius*maxRadius+oH*oH*tan(hpalpha)*tan(hpalpha)))/(maxRadius*maxRadius*8))); - double hpcospt = (hpdeg>=0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); + double hpteta = fabs(hpalpha - RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt((-oH * oH * tan(hpalpha) * tan(hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan(hpalpha) * sqrt(16 * maxRadius * maxRadius + oH * oH * tan(hpalpha) * tan(hpalpha))) / (maxRadius * maxRadius * 8))); + double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta); - double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0; + double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0; - bool darkening = (params->vignetting.amount <= 0.0); + bool darkening = (params->vignetting.amount <= 0.0); // main cycle - #pragma omp parallel for if (multiThread) - for (int y=0; yheight; y++) { - for (int x=0; xwidth; x++) { - double x_d=x,y_d=y; - if (pLCPMap && params->lensProf.useDist) pLCPMap->correctDistortion(x_d,y_d); // must be first transform + #pragma omp parallel for if (multiThread) - y_d = ascale * (y_d + cy - h2); // centering y coord & scale - x_d = ascale * (x_d + cx - w2); // centering x coord & scale + for (int y = 0; y < transformed->height; y++) { + for (int x = 0; x < transformed->width; x++) { + double x_d = x, y_d = y; + + if (pLCPMap && params->lensProf.useDist) { + pLCPMap->correctDistortion(x_d, y_d); // must be first transform + } + + y_d = ascale * (y_d + cy - h2); // centering y coord & scale + x_d = ascale * (x_d + cx - w2); // centering x coord & scale double vig_x_d, vig_y_d; + if (needsVignetting()) { - vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale - vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale + vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale + vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale } if (needsPerspective()) { - // horizontal perspective transformation - y_d *= maxRadius / (maxRadius + x_d*hptanpt); - x_d *= maxRadius * hpcospt / (maxRadius + x_d*hptanpt); + // horizontal perspective transformation + y_d *= maxRadius / (maxRadius + x_d * hptanpt); + x_d *= maxRadius * hpcospt / (maxRadius + x_d * hptanpt); - // vertical perspective transformation - x_d *= maxRadius / (maxRadius - y_d*vptanpt); - y_d *= maxRadius * vpcospt / (maxRadius - y_d*vptanpt); + // vertical perspective transformation + x_d *= maxRadius / (maxRadius - y_d * vptanpt); + y_d *= maxRadius * vpcospt / (maxRadius - y_d * vptanpt); } - // rotate + // rotate double Dx = x_d * cost - y_d * sint; double Dy = x_d * sint + y_d * cost; // distortion correction double s = 1; + if (needsDist) { - double r = sqrt(Dx*Dx + Dy*Dy) / maxRadius; // sqrt is slow + double r = sqrt(Dx * Dx + Dy * Dy) / maxRadius; // sqrt is slow s = 1.0 - distAmount + distAmount * r ; - Dx *= s; - Dy *= s; + Dx *= s; + Dy *= s; } double r2; - if (needsVignetting()) { - double vig_Dx = vig_x_d * cost - vig_y_d * sint; - double vig_Dy = vig_x_d * sint + vig_y_d * cost; - r2=sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy); + + if (needsVignetting()) { + double vig_Dx = vig_x_d * cost - vig_y_d * sint; + double vig_Dy = vig_x_d * sint + vig_y_d * cost; + r2 = sqrt(vig_Dx * vig_Dx + vig_Dy * vig_Dy); } // de-center - Dx += w2; Dy += h2; + Dx += w2; + Dy += h2; // Extract integer and fractions of source screen coordinates - int xc = (int)Dx; Dx -= (double)xc; xc -= sx; - int yc = (int)Dy; Dy -= (double)yc; yc -= sy; + int xc = (int)Dx; + Dx -= (double)xc; + xc -= sx; + int yc = (int)Dy; + Dy -= (double)yc; + yc -= sy; // Convert only valid pixels - if (yc>=0 && ycheight && xc>=0 && xcwidth) { + if (yc >= 0 && yc < original->height && xc >= 0 && xc < original->width) { // multiplier for vignetting correction double vignmul = 1.0; - if (needsVignetting()) - if(darkening) - vignmul /= std::max(v + mul * tanh (b*(maxRadius-s*r2) / maxRadius), 0.001); - else - vignmul = v + mul * tanh (b*(maxRadius-s*r2) / maxRadius); - if (needsGradient()) - vignmul *= calcGradientFactor(gp, cx+x, cy+y); - if (needsPCVignetting()) - vignmul *= calcPCVignetteFactor(pcv, cx+x, cy+y); - if (yc < original->height-1 && xc < original->width-1) { + if (needsVignetting()) + if(darkening) { + vignmul /= std::max(v + mul * tanh (b * (maxRadius - s * r2) / maxRadius), 0.001); + } else { + vignmul = v + mul * tanh (b * (maxRadius - s * r2) / maxRadius); + } + + if (needsGradient()) { + vignmul *= calcGradientFactor(gp, cx + x, cy + y); + } + + if (needsPCVignetting()) { + vignmul *= calcPCVignetteFactor(pcv, cx + x, cy + y); + } + + if (yc < original->height - 1 && xc < original->width - 1) { // all interpolation pixels inside image - transformed->r(y,x) = vignmul*(original->r(yc,xc)*(1.0-Dx)*(1.0-Dy) + original->r(yc,xc+1)*Dx*(1.0-Dy) + original->r(yc+1,xc)*(1.0-Dx)*Dy + original->r(yc+1,xc+1)*Dx*Dy); - transformed->g(y,x) = vignmul*(original->g(yc,xc)*(1.0-Dx)*(1.0-Dy) + original->g(yc,xc+1)*Dx*(1.0-Dy) + original->g(yc+1,xc)*(1.0-Dx)*Dy + original->g(yc+1,xc+1)*Dx*Dy); - transformed->b(y,x) = vignmul*(original->b(yc,xc)*(1.0-Dx)*(1.0-Dy) + original->b(yc,xc+1)*Dx*(1.0-Dy) + original->b(yc+1,xc)*(1.0-Dx)*Dy + original->b(yc+1,xc+1)*Dx*Dy); - } - else { + transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); + } else { // edge pixels - int y1 = LIM(yc, 0, original->height-1); - int y2 = LIM(yc+1, 0, original->height-1); - int x1 = LIM(xc, 0, original->width-1); - int x2 = LIM(xc+1, 0, original->width-1); - transformed->r(y,x) = vignmul*(original->r(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->r(y1,x2)*Dx*(1.0-Dy) + original->r(y2,x1)*(1.0-Dx)*Dy + original->r(y2,x2)*Dx*Dy); - transformed->g(y,x) = vignmul*(original->g(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->g(y1,x2)*Dx*(1.0-Dy) + original->g(y2,x1)*(1.0-Dx)*Dy + original->g(y2,x2)*Dx*Dy); - transformed->b(y,x) = vignmul*(original->b(y1,x1)*(1.0-Dx)*(1.0-Dy) + original->b(y1,x2)*Dx*(1.0-Dy) + original->b(y2,x1)*(1.0-Dx)*Dy + original->b(y2,x2)*Dx*Dy); + int y1 = LIM(yc, 0, original->height - 1); + int y2 = LIM(yc + 1, 0, original->height - 1); + int x1 = LIM(xc, 0, original->width - 1); + int x2 = LIM(xc + 1, 0, original->width - 1); + transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); } - } - else { + } else { // not valid (source pixel x,y not inside source image, etc.) - transformed->r(y,x) = 0; - transformed->g(y,x) = 0; - transformed->b(y,x) = 0; + transformed->r(y, x) = 0; + transformed->g(y, x) = 0; + transformed->b(y, x) = 0; } } } } -double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap) { - if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap==NULL)) +double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap) +{ + if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap == NULL)) { return 1; + } - double scaleU = 2, scaleL = 0.001; // upper and lower border, iterate inbetween + double scaleU = 2, scaleL = 0.001; // upper and lower border, iterate inbetween - do { - double scale = (scaleU + scaleL) * 0.5; + do { + double scale = (scaleU + scaleL) * 0.5; int orx, ory, orw, orh; bool clipped = transCoord (oW, oH, 0, 0, oW, oH, orx, ory, orw, orh, scale, pLCPMap); - if (clipped) - scaleU = scale; - else - scaleL = scale; - } while (scaleU - scaleL > 0.001); + if (clipped) { + scaleU = scale; + } else { + scaleL = scale; + } + } while (scaleU - scaleL > 0.001); - return scaleL; + return scaleL; } -bool ImProcFunctions::needsCA () { - return fabs (params->cacorrection.red) > 1e-15 || fabs (params->cacorrection.blue) > 1e-15; +bool ImProcFunctions::needsCA () +{ + return fabs (params->cacorrection.red) > 1e-15 || fabs (params->cacorrection.blue) > 1e-15; } -bool ImProcFunctions::needsDistortion () { - return fabs (params->distortion.amount) > 1e-15; +bool ImProcFunctions::needsDistortion () +{ + return fabs (params->distortion.amount) > 1e-15; } -bool ImProcFunctions::needsRotation () { - return fabs (params->rotate.degree) > 1e-15; +bool ImProcFunctions::needsRotation () +{ + return fabs (params->rotate.degree) > 1e-15; } -bool ImProcFunctions::needsPerspective () { - return params->perspective.horizontal || params->perspective.vertical; +bool ImProcFunctions::needsPerspective () +{ + return params->perspective.horizontal || params->perspective.vertical; } -bool ImProcFunctions::needsGradient () { - return params->gradient.enabled && fabs(params->gradient.strength) > 1e-15; +bool ImProcFunctions::needsGradient () +{ + return params->gradient.enabled && fabs(params->gradient.strength) > 1e-15; } -bool ImProcFunctions::needsPCVignetting () { - return params->pcvignette.enabled && fabs(params->pcvignette.strength) > 1e-15; +bool ImProcFunctions::needsPCVignetting () +{ + return params->pcvignette.enabled && fabs(params->pcvignette.strength) > 1e-15; } -bool ImProcFunctions::needsVignetting () { - return params->vignetting.amount; +bool ImProcFunctions::needsVignetting () +{ + return params->vignetting.amount; } -bool ImProcFunctions::needsLCP () { - return params->lensProf.lcpFile.length()>0; +bool ImProcFunctions::needsLCP () +{ + return params->lensProf.lcpFile.length() > 0; } -bool ImProcFunctions::needsTransform () { - return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP(); +bool ImProcFunctions::needsTransform () +{ + return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP(); } diff --git a/rtengine/ipvibrance.cc b/rtengine/ipvibrance.cc index db33d634c..2c91fbf01 100644 --- a/rtengine/ipvibrance.cc +++ b/rtengine/ipvibrance.cc @@ -35,7 +35,8 @@ using namespace std; -namespace rtengine { +namespace rtengine +{ using namespace procparams; @@ -43,24 +44,25 @@ using namespace procparams; extern const Settings* settings; -void fillCurveArrayVib(DiagonalCurve* diagCurve, LUTf &outCurve) { +void fillCurveArrayVib(DiagonalCurve* diagCurve, LUTf &outCurve) +{ - if (diagCurve) { + if (diagCurve) { #ifdef _OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for (int i=0; i<=0xffff; i++ ) { - // change to [0,1] range - // apply custom/parametric/NURBS curve, if any - // and store result in a temporary array - outCurve[i] = 65535.f*diagCurve->getVal( double(i)/65535.0 ); - } - } - else { - for (int i=0; i<=0xffff; i++) { - outCurve[i] = float(i); - } - } + + for (int i = 0; i <= 0xffff; i++ ) { + // change to [0,1] range + // apply custom/parametric/NURBS curve, if any + // and store result in a temporary array + outCurve[i] = 65535.f * diagCurve->getVal( double(i) / 65535.0 ); + } + } else { + for (int i = 0; i <= 0xffff; i++) { + outCurve[i] = float(i); + } + } } @@ -69,397 +71,689 @@ void fillCurveArrayVib(DiagonalCurve* diagCurve, LUTf &outCurve) { * copyright (c)2011 Jacques Desmis and Jean-Christophe Frisch * */ -void ImProcFunctions::vibrance (LabImage* lab) { - if (!params->vibrance.enabled) - return; +void ImProcFunctions::vibrance (LabImage* lab) +{ + if (!params->vibrance.enabled) { + return; + } -// int skip=1; //scale==1 ? 1 : 16; - bool skinCurveIsSet=false; - DiagonalCurve* dcurve = NULL; - dcurve = new DiagonalCurve (params->vibrance.skintonescurve, CURVES_MIN_POLY_POINTS); - if (dcurve) { - if (!dcurve->isIdentity()) { - skinCurveIsSet = true; - } - else { - delete dcurve; - dcurve = NULL; - } - } +// int skip=1; //scale==1 ? 1 : 16; + bool skinCurveIsSet = false; + DiagonalCurve* dcurve = NULL; + dcurve = new DiagonalCurve (params->vibrance.skintonescurve, CURVES_MIN_POLY_POINTS); - if (!skinCurveIsSet && !params->vibrance.pastels && !params->vibrance.saturated) { - if (dcurve) { - delete dcurve; - dcurve = NULL; - } - return; - } + if (dcurve) { + if (!dcurve->isIdentity()) { + skinCurveIsSet = true; + } else { + delete dcurve; + dcurve = NULL; + } + } - const int width = lab->W; - const int height = lab->H; + if (!skinCurveIsSet && !params->vibrance.pastels && !params->vibrance.saturated) { + if (dcurve) { + delete dcurve; + dcurve = NULL; + } + + return; + } + + const int width = lab->W; + const int height = lab->H; #ifdef _DEBUG - MyTime t1e,t2e; - t1e.set(); - int negat=0, moreRGB=0, negsat=0, moresat=0; + MyTime t1e, t2e; + t1e.set(); + int negat = 0, moreRGB = 0, negsat = 0, moresat = 0; #endif - // skin hue curve - // I use diagonal because I think it's better - LUTf skin_curve (65536,0); - if(skinCurveIsSet) - fillCurveArrayVib(dcurve, skin_curve); - if (dcurve) { - delete dcurve; - dcurve = NULL; - } + // skin hue curve + // I use diagonal because I think it's better + LUTf skin_curve (65536, 0); + + if(skinCurveIsSet) { + fillCurveArrayVib(dcurve, skin_curve); + } + + if (dcurve) { + delete dcurve; + dcurve = NULL; + } // skin_curve.dump("skin_curve"); - const float chromaPastel = float(params->vibrance.pastels) / 100.0f; - const float chromaSatur = float(params->vibrance.saturated) / 100.0f; - const float p00=0.07f; - const float limitpastelsatur = (static_cast(params->vibrance.psthreshold.value[ThresholdSelector::TS_TOPLEFT]) / 100.0f)*(1.0f-p00) + p00; - const float maxdp=(limitpastelsatur-p00)/4.0f; - const float maxds=(1.0-limitpastelsatur)/4.0f; - const float p0 = p00+maxdp; - const float p1 = p00+2.0f*maxdp; - const float p2 = p00+3.0f*maxdp; - const float s0 = limitpastelsatur + maxds; - const float s1 = limitpastelsatur + 2.0f*maxds; - const float s2 = limitpastelsatur + 3.0f*maxds; - const float transitionweighting = static_cast(params->vibrance.psthreshold.value[ThresholdSelector::TS_BOTTOMLEFT]) / 100.0f; - float chromamean=0.0f; - if(chromaPastel != chromaSatur){ - //if sliders pastels and saturated are different: transition with a double linear interpolation: between p2 and limitpastelsatur, and between limitpastelsatur and s0 - //modify the "mean" point in function of double threshold => differential transition - chromamean = maxdp * (chromaSatur-chromaPastel) / (s0-p2) + chromaPastel; - // move chromaMean up or down depending on transitionCtrl - if (transitionweighting > 0.0f) { - chromamean = (chromaSatur-chromamean) * transitionweighting + chromamean; - } - else if (transitionweighting < 0.0f) { - chromamean = (chromamean-chromaPastel) * transitionweighting + chromamean; - } - } - const float chromaPastel_a = (chromaPastel-chromamean)/(p2-limitpastelsatur); - const float chromaPastel_b = chromaPastel-chromaPastel_a*p2; + const float chromaPastel = float(params->vibrance.pastels) / 100.0f; + const float chromaSatur = float(params->vibrance.saturated) / 100.0f; + const float p00 = 0.07f; + const float limitpastelsatur = (static_cast(params->vibrance.psthreshold.value[ThresholdSelector::TS_TOPLEFT]) / 100.0f) * (1.0f - p00) + p00; + const float maxdp = (limitpastelsatur - p00) / 4.0f; + const float maxds = (1.0 - limitpastelsatur) / 4.0f; + const float p0 = p00 + maxdp; + const float p1 = p00 + 2.0f * maxdp; + const float p2 = p00 + 3.0f * maxdp; + const float s0 = limitpastelsatur + maxds; + const float s1 = limitpastelsatur + 2.0f * maxds; + const float s2 = limitpastelsatur + 3.0f * maxds; + const float transitionweighting = static_cast(params->vibrance.psthreshold.value[ThresholdSelector::TS_BOTTOMLEFT]) / 100.0f; + float chromamean = 0.0f; - const float chromaSatur_a=(chromaSatur-chromamean)/(s0-limitpastelsatur); - const float chromaSatur_b=chromaSatur-chromaSatur_a*s0; + if(chromaPastel != chromaSatur) { + //if sliders pastels and saturated are different: transition with a double linear interpolation: between p2 and limitpastelsatur, and between limitpastelsatur and s0 + //modify the "mean" point in function of double threshold => differential transition + chromamean = maxdp * (chromaSatur - chromaPastel) / (s0 - p2) + chromaPastel; - const float dhue=0.15f;//hue transition - const float dchr=20.0f;//chroma transition - const float skbeg=-0.05f;//begin hue skin - const float skend=1.60f;//end hue skin - const float xx=0.5f;//soft : between 0.3 and 1.0 - const float ask=65535.0f/(skend-skbeg); - const float bsk=-skbeg*ask; + // move chromaMean up or down depending on transitionCtrl + if (transitionweighting > 0.0f) { + chromamean = (chromaSatur - chromamean) * transitionweighting + chromamean; + } else if (transitionweighting < 0.0f) { + chromamean = (chromamean - chromaPastel) * transitionweighting + chromamean; + } + } + + const float chromaPastel_a = (chromaPastel - chromamean) / (p2 - limitpastelsatur); + const float chromaPastel_b = chromaPastel - chromaPastel_a * p2; + + const float chromaSatur_a = (chromaSatur - chromamean) / (s0 - limitpastelsatur); + const float chromaSatur_b = chromaSatur - chromaSatur_a * s0; + + const float dhue = 0.15f; //hue transition + const float dchr = 20.0f; //chroma transition + const float skbeg = -0.05f; //begin hue skin + const float skend = 1.60f; //end hue skin + const float xx = 0.5f; //soft : between 0.3 and 1.0 + const float ask = 65535.0f / (skend - skbeg); + const float bsk = -skbeg * ask; - const bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated - const bool protectskins = params->vibrance.protectskins; - const bool avoidcolorshift = params->vibrance.avoidcolorshift; + const bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated + const bool protectskins = params->vibrance.protectskins; + const bool avoidcolorshift = params->vibrance.avoidcolorshift; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); - //inverse matrix user select - const double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + //inverse matrix user select + const double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; #ifdef _DEBUG MunsellDebugInfo* MunsDebugInfo = NULL; - if (avoidcolorshift) - MunsDebugInfo = new MunsellDebugInfo(); -#pragma omp parallel default(shared) firstprivate(lab, width, height, chromaPastel, chromaSatur, highlight, limitpastelsatur, transitionweighting, protectskins, avoidcolorshift, MunsDebugInfo) reduction(+: negat, moreRGB, negsat, moresat) if (multiThread) -#else -#pragma omp parallel default(shared) if (multiThread) -#endif -{ - float sathue[5],sathue2[4];// adjust sat in function of hue - -/* - // Fitting limitpastelsatur into the real 0.07->1.0 range -// limitpastelsatur = limitpastelsatur*(1.0f-p00) + p00; - float p0,p1,p2;//adapt limit of pyramid to psThreshold - float s0,s1,s2; -*/ + if (avoidcolorshift) { + MunsDebugInfo = new MunsellDebugInfo(); + } + + #pragma omp parallel default(shared) firstprivate(lab, width, height, chromaPastel, chromaSatur, highlight, limitpastelsatur, transitionweighting, protectskins, avoidcolorshift, MunsDebugInfo) reduction(+: negat, moreRGB, negsat, moresat) if (multiThread) +#else + #pragma omp parallel default(shared) if (multiThread) +#endif + { + + float sathue[5], sathue2[4]; // adjust sat in function of hue + + /* + // Fitting limitpastelsatur into the real 0.07->1.0 range + // limitpastelsatur = limitpastelsatur*(1.0f-p00) + p00; + float p0,p1,p2;//adapt limit of pyramid to psThreshold + float s0,s1,s2; + */ #ifdef _OPENMP - if (settings->verbose && omp_get_thread_num()==0) { + + if (settings->verbose && omp_get_thread_num() == 0) { #else - if (settings->verbose) { -#endif - printf("vibrance: p0=%1.2f p1=%1.2f p2=%1.2f s0=%1.2f s1=%1.2f s2=%1.2f\n", p0,p1,p2,s0,s1,s2); - printf(" pastel=%f satur=%f limit= %1.2f chromamean=%0.5f\n",1.0f+chromaPastel,1.0f+chromaSatur, limitpastelsatur, chromamean); - } -#pragma omp for schedule(dynamic, 16) - for (int i=0; iL[i][j]/327.68f; - float CC=sqrt(SQR(lab->a[i][j])+ SQR(lab->b[i][j]))/327.68f; - float HH=xatan2f(lab->b[i][j],lab->a[i][j]); - - float satredu=1.0f; //reduct sat in function of skin - if(protectskins) { - Color::SkinSat (LL, HH, CC, satredu);// for skin colors - } - // here we work on Chromaticity and Hue - // variation of Chromaticity ==> saturation via RGB - // Munsell correction, then conversion to Lab - float Lprov=LL; - float Chprov=CC; - float R, G, B; - float2 sincosval; - if(CC==0.0f) { - sincosval.y = 1.f; - sincosval.x = 0.0f; - } else { - sincosval.y = lab->a[i][j]/(CC*327.68f); - sincosval.x = lab->b[i][j]/(CC*327.68f); - } + if (settings->verbose) { +#endif + printf("vibrance: p0=%1.2f p1=%1.2f p2=%1.2f s0=%1.2f s1=%1.2f s2=%1.2f\n", p0, p1, p2, s0, s1, s2); + printf(" pastel=%f satur=%f limit= %1.2f chromamean=%0.5f\n", 1.0f + chromaPastel, 1.0f + chromaSatur, limitpastelsatur, chromamean); + } + + #pragma omp for schedule(dynamic, 16) + + for (int i = 0; i < height; i++) + for (int j = 0; j < width; j++) { + float LL = lab->L[i][j] / 327.68f; + float CC = sqrt(SQR(lab->a[i][j]) + SQR(lab->b[i][j])) / 327.68f; + float HH = xatan2f(lab->b[i][j], lab->a[i][j]); + + float satredu = 1.0f; //reduct sat in function of skin + + if(protectskins) { + Color::SkinSat (LL, HH, CC, satredu);// for skin colors + } + + // here we work on Chromaticity and Hue + // variation of Chromaticity ==> saturation via RGB + // Munsell correction, then conversion to Lab + float Lprov = LL; + float Chprov = CC; + float R, G, B; + float2 sincosval; + + if(CC == 0.0f) { + sincosval.y = 1.f; + sincosval.x = 0.0f; + } else { + sincosval.y = lab->a[i][j] / (CC * 327.68f); + sincosval.x = lab->b[i][j] / (CC * 327.68f); + } #ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH, sincosval, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f, neg, more_rgb); - if(neg) negat++; - if(more_rgb) moreRGB++; + bool neg = false; + bool more_rgb = false; + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, sincosval, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f, neg, more_rgb); + + if(neg) { + negat++; + } + + if(more_rgb) { + moreRGB++; + } + #else - //gamut control : Lab values are in gamut - Color::gamutLchonly(HH, sincosval, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f); + //gamut control : Lab values are in gamut + Color::gamutLchonly(HH, sincosval, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f); #endif - if(Chprov > 6.0f) { - const float saturation=SAT(R,G,B); - if(saturation>0.0f) { - if(satredu!=1.0f) { - // for skin, no differentiation - sathue [0]=sathue [1]=sathue [2]=sathue [3]=sathue[4]=1.0f; - sathue2[0]=sathue2[1]=sathue2[2]=sathue2[3] =1.0f; - } else { - //double pyramid: LL and HH - //I try to take into account: Munsell response (human vision) and Gamut..(less response for red): preferably using Prophoto or WideGamut - //blue: -1.80 -3.14 green = 2.1 3.14 green-yellow=1.4 2.1 red:0 1.4 blue-purple:-0.7 -1.4 purple: 0 -0.7 - //these values allow a better and differential response - if(LL < 20.0f) {//more for blue-purple, blue and red modulate - if (/*HH> -3.1415f &&*/ HH< -1.5f ) {sathue[0]=1.3f;sathue[1]=1.2f;sathue[2]=1.1f;sathue[3]=1.05f;sathue[4]=0.4f;sathue2[0]=1.05f;sathue2[1]=1.1f ;sathue2[2]=1.05f;sathue2[3]=1.0f;}//blue - else if(/*HH>=-1.5f &&*/ HH< -0.7f ) {sathue[0]=1.6f;sathue[1]=1.4f;sathue[2]=1.3f;sathue[3]=1.2f ;sathue[4]=0.4f;sathue2[0]=1.2f ;sathue2[1]=1.15f;sathue2[2]=1.1f ;sathue2[3]=1.0f;}//blue purple 1.2 1.1 - else if(/*HH>=-0.7f &&*/ HH< 0.0f ) {sathue[0]=1.2f;sathue[1]=1.0f;sathue[2]=1.0f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//purple - // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=1.1f;sathue[1]=1.1f;sathue[2]=1.1f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//red 0.8 0.7 - else if(/*HH>= 0.0f &&*/ HH<= 1.4f ) {sathue[0]=1.3f;sathue[1]=1.2f;sathue[2]=1.1f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//red 0.8 0.7 - else if(/*HH> 1.4f &&*/ HH<= 2.1f ) {sathue[0]=1.0f;sathue[1]=1.0f;sathue[2]=1.0f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//green yellow 1.2 1.1 - else /*if(HH> 2.1f && HH<= 3.1415f)*/ {sathue[0]=1.4f;sathue[1]=1.3f;sathue[2]=1.2f;sathue[3]=1.15f;sathue[4]=0.4f;sathue2[0]=1.15f;sathue2[1]=1.1f ;sathue2[2]=1.05f;sathue2[3]=1.0f;}//green - } - else if (LL< 50.0f) {//more for blue and green, less for red and green-yellow - if (/*HH> -3.1415f &&*/ HH< -1.5f ) {sathue[0]=1.5f;sathue[1]=1.4f;sathue[2]=1.3f;sathue[3]=1.2f ;sathue[4]=0.4f;sathue2[0]=1.2f ;sathue2[1]=1.1f ;sathue2[2]=1.05f;sathue2[3]=1.0f;}//blue - else if(/*HH>=-1.5f &&*/ HH< -0.7f ) {sathue[0]=1.3f;sathue[1]=1.2f;sathue[2]=1.1f;sathue[3]=1.05f;sathue[4]=0.4f;sathue2[0]=1.05f;sathue2[1]=1.05f;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//blue purple 1.2 1.1 - else if(/*HH>=-0.7f &&*/ HH< 0.0f ) {sathue[0]=1.2f;sathue[1]=1.0f;sathue[2]=1.0f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//purple - // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=0.8f;sathue[1]=0.8f;sathue[2]=0.8f;sathue[3]=0.8f ;sathue[4]=0.4f;sathue2[0]=0.8f ;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 - else if(/*HH>= 0.0f &&*/ HH<= 1.4f ) {sathue[0]=1.1f;sathue[1]=1.0f;sathue[2]=0.9f;sathue[3]=0.8f ;sathue[4]=0.4f;sathue2[0]=0.8f ;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 - else if(/*HH> 1.4f &&*/ HH<= 2.1f ) {sathue[0]=1.1f;sathue[1]=1.1f;sathue[2]=1.1f;sathue[3]=1.05f;sathue[4]=0.4f;sathue2[0]=0.9f ;sathue2[1]=0.8f ;sathue2[2]=0.7f ;sathue2[3]=0.6f;}//green yellow 1.2 1.1 - else /*if(HH> 2.1f && HH<= 3.1415f)*/ {sathue[0]=1.5f;sathue[1]=1.4f;sathue[2]=1.3f;sathue[3]=1.2f ;sathue[4]=0.4f;sathue2[0]=1.2f ;sathue2[1]=1.1f ;sathue2[2]=1.05f;sathue2[3]=1.0f;}//green - } - else if (LL< 80.0f) {//more for green, less for red and green-yellow - if (/*HH> -3.1415f &&*/ HH< -1.5f ) {sathue[0]=1.3f;sathue[1]=1.2f;sathue[2]=1.15f;sathue[3]=1.1f ;sathue[4]=0.3f;sathue2[0]=1.1f ;sathue2[1]=1.1f ;sathue2[2]=1.05f;sathue2[3]=1.0f;}//blue - else if(/*HH>=-1.5f &&*/ HH< -0.7f ) {sathue[0]=1.3f;sathue[1]=1.2f;sathue[2]=1.15f;sathue[3]=1.1f ;sathue[4]=0.3f;sathue2[0]=1.1f ;sathue2[1]=1.05f;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//blue purple 1.2 1.1 - else if(/*HH>=-0.7f &&*/ HH< 0.0f ) {sathue[0]=1.2f;sathue[1]=1.0f;sathue[2]=1.0f ;sathue[3]=1.0f ;sathue[4]=0.3f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//purple - // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=0.8f;sathue[1]=0.8f;sathue[2]=0.8f ;sathue[3]=0.8f ;sathue[4]=0.3f;sathue2[0]=0.8f ;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 - else if(/*HH>= 0.0f &&*/ HH<= 1.4f ) {sathue[0]=1.1f;sathue[1]=1.0f;sathue[2]=0.9f ;sathue[3]=0.8f ;sathue[4]=0.3f;sathue2[0]=0.8f ;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 - else if(/*HH> 1.4f &&*/ HH<= 2.1f ) {sathue[0]=1.3f;sathue[1]=1.2f;sathue[2]=1.1f ;sathue[3]=1.05f;sathue[4]=0.3f;sathue2[0]=1.0f ;sathue2[1]=0.9f ;sathue2[2]=0.8f ;sathue2[3]=0.7f;}//green yellow 1.2 1.1 - else /*if(HH> 2.1f && HH<= 3.1415f)*/ {sathue[0]=1.6f;sathue[1]=1.4f;sathue[2]=1.3f ;sathue[3]=1.25f;sathue[4]=0.3f;sathue2[0]=1.25f;sathue2[1]=1.2f ;sathue2[2]=1.15f;sathue2[3]=1.05f;}//green - even with Prophoto green are too "little" 1.5 1.3 - } - else /*if (LL>=80.0f)*/ {//more for green-yellow, less for red and purple - if (/*HH> -3.1415f &&*/ HH< -1.5f ) {sathue[0]=1.0f;sathue[1]=1.0f;sathue[2]=0.9f;sathue[3]=0.8f;sathue[4]=0.2f;sathue2[0]=0.8f;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//blue - else if(/*HH>=-1.5f &&*/ HH< -0.7f ) {sathue[0]=1.0f;sathue[1]=1.0f;sathue[2]=0.9f;sathue[3]=0.8f;sathue[4]=0.2f;sathue2[0]=0.8f;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//blue purple 1.2 1.1 - else if(/*HH>=-0.7f &&*/ HH< 0.0f ) {sathue[0]=1.2f;sathue[1]=1.0f;sathue[2]=1.0f;sathue[3]=0.9f;sathue[4]=0.2f;sathue2[0]=0.9f;sathue2[1]=0.9f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//purple - // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=0.8f;sathue[1]=0.8f;sathue[2]=0.8f;sathue[3]=0.8f;sathue[4]=0.2f;sathue2[0]=0.8f;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 - else if(/*HH>= 0.0f &&*/ HH<= 1.4f ) {sathue[0]=1.1f;sathue[1]=1.0f;sathue[2]=0.9f;sathue[3]=0.8f;sathue[4]=0.2f;sathue2[0]=0.8f;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 - else if(/*HH> 1.4f &&*/ HH<= 2.1f ) {sathue[0]=1.6f;sathue[1]=1.5f;sathue[2]=1.4f;sathue[3]=1.2f;sathue[4]=0.2f;sathue2[0]=1.1f;sathue2[1]=1.05f;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//green yellow 1.2 1.1 - else /*if(HH> 2.1f && HH<= 3.1415f)*/ {sathue[0]=1.4f;sathue[1]=1.3f;sathue[2]=1.2f;sathue[3]=1.1f;sathue[4]=0.2f;sathue2[0]=1.1f;sathue2[1]=1.05f;sathue2[2]=1.05f;sathue2[3]=1.0f;}//green - } - } - float chmodpastel,chmodsat; - // variables to improve transitions - float pa, pb;// transition = pa*saturation + pb - float chl00 = chromaPastel*satredu*sathue[4]; - float chl0 = chromaPastel*satredu*sathue[0]; - float chl1 = chromaPastel*satredu*sathue[1]; - float chl2 = chromaPastel*satredu*sathue[2]; - float chl3 = chromaPastel*satredu*sathue[3]; - float chs0 = chromaSatur*satredu*sathue2[0]; - float chs1 = chromaSatur*satredu*sathue2[1]; - float chs2 = chromaSatur*satredu*sathue2[2]; - float chs3 = chromaSatur*satredu*sathue2[3]; - float s3 = 1.0f; - // We handle only positive values here ; improve transitions - if (saturation < p00) chmodpastel = chl00 ; //neutral tones - else if (saturation < p0 ) { pa=(chl00-chl0)/(p00-p0); pb=chl00-pa*p00; chmodpastel = pa*saturation + pb; } - else if (saturation < p1) { pa=(chl0-chl1)/(p0-p1); pb=chl0-pa*p0; chmodpastel = pa*saturation + pb; } - else if (saturation < p2) { pa=(chl1-chl2)/(p1-p2); pb=chl1-pa*p1; chmodpastel = pa*saturation + pb; } - else if (saturation < limitpastelsatur) { pa=(chl2- chl3)/(p2-limitpastelsatur); pb=chl2-pa*p2; chmodpastel = pa*saturation + pb; } - else if (saturation < s0) { pa=(chl3-chs0)/(limitpastelsatur-s0) ; pb=chl3-pa*limitpastelsatur; chmodsat = pa*saturation + pb; } - else if (saturation < s1) { pa=(chs0-chs1)/(s0-s1); pb=chs0-pa*s0; chmodsat = pa*saturation + pb; } - else if (saturation < s2) { pa=(chs1-chs2)/(s1-s2); pb=chs1-pa*s1; chmodsat = pa*saturation + pb; } - else { pa=(chs2-chs3)/(s2-s3); pb=chs2-pa*s2; chmodsat = pa*saturation + pb; } + if(Chprov > 6.0f) { + const float saturation = SAT(R, G, B); - if(chromaPastel != chromaSatur){ + if(saturation > 0.0f) { + if(satredu != 1.0f) { + // for skin, no differentiation + sathue [0] = sathue [1] = sathue [2] = sathue [3] = sathue[4] = 1.0f; + sathue2[0] = sathue2[1] = sathue2[2] = sathue2[3] = 1.0f; + } else { + //double pyramid: LL and HH + //I try to take into account: Munsell response (human vision) and Gamut..(less response for red): preferably using Prophoto or WideGamut + //blue: -1.80 -3.14 green = 2.1 3.14 green-yellow=1.4 2.1 red:0 1.4 blue-purple:-0.7 -1.4 purple: 0 -0.7 + //these values allow a better and differential response + if(LL < 20.0f) {//more for blue-purple, blue and red modulate + if (/*HH> -3.1415f &&*/ HH < -1.5f ) { + sathue[0] = 1.3f; //blue + sathue[1] = 1.2f; + sathue[2] = 1.1f; + sathue[3] = 1.05f; + sathue[4] = 0.4f; + sathue2[0] = 1.05f; + sathue2[1] = 1.1f ; + sathue2[2] = 1.05f; + sathue2[3] = 1.0f; + } else if(/*HH>=-1.5f &&*/ HH < -0.7f ) { + sathue[0] = 1.6f; //blue purple 1.2 1.1 + sathue[1] = 1.4f; + sathue[2] = 1.3f; + sathue[3] = 1.2f ; + sathue[4] = 0.4f; + sathue2[0] = 1.2f ; + sathue2[1] = 1.15f; + sathue2[2] = 1.1f ; + sathue2[3] = 1.0f; + } else if(/*HH>=-0.7f &&*/ HH < 0.0f ) { + sathue[0] = 1.2f; //purple + sathue[1] = 1.0f; + sathue[2] = 1.0f; + sathue[3] = 1.0f ; + sathue[4] = 0.4f; + sathue2[0] = 1.0f ; + sathue2[1] = 1.0f ; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } + // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=1.1f;sathue[1]=1.1f;sathue[2]=1.1f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//red 0.8 0.7 + else if(/*HH>= 0.0f &&*/ HH <= 1.4f ) { + sathue[0] = 1.3f; //red 0.8 0.7 + sathue[1] = 1.2f; + sathue[2] = 1.1f; + sathue[3] = 1.0f ; + sathue[4] = 0.4f; + sathue2[0] = 1.0f ; + sathue2[1] = 1.0f ; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } else if(/*HH> 1.4f &&*/ HH <= 2.1f ) { + sathue[0] = 1.0f; //green yellow 1.2 1.1 + sathue[1] = 1.0f; + sathue[2] = 1.0f; + sathue[3] = 1.0f ; + sathue[4] = 0.4f; + sathue2[0] = 1.0f ; + sathue2[1] = 1.0f ; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } else { /*if(HH> 2.1f && HH<= 3.1415f)*/ + sathue[0] = 1.4f; //green + sathue[1] = 1.3f; + sathue[2] = 1.2f; + sathue[3] = 1.15f; + sathue[4] = 0.4f; + sathue2[0] = 1.15f; + sathue2[1] = 1.1f ; + sathue2[2] = 1.05f; + sathue2[3] = 1.0f; + } + } else if (LL < 50.0f) { //more for blue and green, less for red and green-yellow + if (/*HH> -3.1415f &&*/ HH < -1.5f ) { + sathue[0] = 1.5f; //blue + sathue[1] = 1.4f; + sathue[2] = 1.3f; + sathue[3] = 1.2f ; + sathue[4] = 0.4f; + sathue2[0] = 1.2f ; + sathue2[1] = 1.1f ; + sathue2[2] = 1.05f; + sathue2[3] = 1.0f; + } else if(/*HH>=-1.5f &&*/ HH < -0.7f ) { + sathue[0] = 1.3f; //blue purple 1.2 1.1 + sathue[1] = 1.2f; + sathue[2] = 1.1f; + sathue[3] = 1.05f; + sathue[4] = 0.4f; + sathue2[0] = 1.05f; + sathue2[1] = 1.05f; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } else if(/*HH>=-0.7f &&*/ HH < 0.0f ) { + sathue[0] = 1.2f; //purple + sathue[1] = 1.0f; + sathue[2] = 1.0f; + sathue[3] = 1.0f ; + sathue[4] = 0.4f; + sathue2[0] = 1.0f ; + sathue2[1] = 1.0f ; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } + // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=0.8f;sathue[1]=0.8f;sathue[2]=0.8f;sathue[3]=0.8f ;sathue[4]=0.4f;sathue2[0]=0.8f ;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 + else if(/*HH>= 0.0f &&*/ HH <= 1.4f ) { + sathue[0] = 1.1f; //red 0.8 0.7 + sathue[1] = 1.0f; + sathue[2] = 0.9f; + sathue[3] = 0.8f ; + sathue[4] = 0.4f; + sathue2[0] = 0.8f ; + sathue2[1] = 0.8f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.8f; + } else if(/*HH> 1.4f &&*/ HH <= 2.1f ) { + sathue[0] = 1.1f; //green yellow 1.2 1.1 + sathue[1] = 1.1f; + sathue[2] = 1.1f; + sathue[3] = 1.05f; + sathue[4] = 0.4f; + sathue2[0] = 0.9f ; + sathue2[1] = 0.8f ; + sathue2[2] = 0.7f ; + sathue2[3] = 0.6f; + } else { /*if(HH> 2.1f && HH<= 3.1415f)*/ + sathue[0] = 1.5f; //green + sathue[1] = 1.4f; + sathue[2] = 1.3f; + sathue[3] = 1.2f ; + sathue[4] = 0.4f; + sathue2[0] = 1.2f ; + sathue2[1] = 1.1f ; + sathue2[2] = 1.05f; + sathue2[3] = 1.0f; + } - // Pastels - if(saturation > p2 && saturation < limitpastelsatur) { - float newchromaPastel = chromaPastel_a*saturation + chromaPastel_b; - chmodpastel = newchromaPastel*satredu*sathue[3]; - } + } else if (LL < 80.0f) { //more for green, less for red and green-yellow + if (/*HH> -3.1415f &&*/ HH < -1.5f ) { + sathue[0] = 1.3f; //blue + sathue[1] = 1.2f; + sathue[2] = 1.15f; + sathue[3] = 1.1f ; + sathue[4] = 0.3f; + sathue2[0] = 1.1f ; + sathue2[1] = 1.1f ; + sathue2[2] = 1.05f; + sathue2[3] = 1.0f; + } else if(/*HH>=-1.5f &&*/ HH < -0.7f ) { + sathue[0] = 1.3f; //blue purple 1.2 1.1 + sathue[1] = 1.2f; + sathue[2] = 1.15f; + sathue[3] = 1.1f ; + sathue[4] = 0.3f; + sathue2[0] = 1.1f ; + sathue2[1] = 1.05f; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } else if(/*HH>=-0.7f &&*/ HH < 0.0f ) { + sathue[0] = 1.2f; //purple + sathue[1] = 1.0f; + sathue[2] = 1.0f ; + sathue[3] = 1.0f ; + sathue[4] = 0.3f; + sathue2[0] = 1.0f ; + sathue2[1] = 1.0f ; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } + // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=0.8f;sathue[1]=0.8f;sathue[2]=0.8f ;sathue[3]=0.8f ;sathue[4]=0.3f;sathue2[0]=0.8f ;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 + else if(/*HH>= 0.0f &&*/ HH <= 1.4f ) { + sathue[0] = 1.1f; //red 0.8 0.7 + sathue[1] = 1.0f; + sathue[2] = 0.9f ; + sathue[3] = 0.8f ; + sathue[4] = 0.3f; + sathue2[0] = 0.8f ; + sathue2[1] = 0.8f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.8f; + } else if(/*HH> 1.4f &&*/ HH <= 2.1f ) { + sathue[0] = 1.3f; //green yellow 1.2 1.1 + sathue[1] = 1.2f; + sathue[2] = 1.1f ; + sathue[3] = 1.05f; + sathue[4] = 0.3f; + sathue2[0] = 1.0f ; + sathue2[1] = 0.9f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.7f; + } else { /*if(HH> 2.1f && HH<= 3.1415f)*/ + sathue[0] = 1.6f; //green - even with Prophoto green are too "little" 1.5 1.3 + sathue[1] = 1.4f; + sathue[2] = 1.3f ; + sathue[3] = 1.25f; + sathue[4] = 0.3f; + sathue2[0] = 1.25f; + sathue2[1] = 1.2f ; + sathue2[2] = 1.15f; + sathue2[3] = 1.05f; + } + } else { /*if (LL>=80.0f)*/ //more for green-yellow, less for red and purple + if (/*HH> -3.1415f &&*/ HH < -1.5f ) { + sathue[0] = 1.0f; //blue + sathue[1] = 1.0f; + sathue[2] = 0.9f; + sathue[3] = 0.8f; + sathue[4] = 0.2f; + sathue2[0] = 0.8f; + sathue2[1] = 0.8f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.8f; + } else if(/*HH>=-1.5f &&*/ HH < -0.7f ) { + sathue[0] = 1.0f; //blue purple 1.2 1.1 + sathue[1] = 1.0f; + sathue[2] = 0.9f; + sathue[3] = 0.8f; + sathue[4] = 0.2f; + sathue2[0] = 0.8f; + sathue2[1] = 0.8f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.8f; + } else if(/*HH>=-0.7f &&*/ HH < 0.0f ) { + sathue[0] = 1.2f; //purple + sathue[1] = 1.0f; + sathue[2] = 1.0f; + sathue[3] = 0.9f; + sathue[4] = 0.2f; + sathue2[0] = 0.9f; + sathue2[1] = 0.9f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.8f; + } + // else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=0.8f;sathue[1]=0.8f;sathue[2]=0.8f;sathue[3]=0.8f;sathue[4]=0.2f;sathue2[0]=0.8f;sathue2[1]=0.8f ;sathue2[2]=0.8f ;sathue2[3]=0.8f;}//red 0.8 0.7 + else if(/*HH>= 0.0f &&*/ HH <= 1.4f ) { + sathue[0] = 1.1f; //red 0.8 0.7 + sathue[1] = 1.0f; + sathue[2] = 0.9f; + sathue[3] = 0.8f; + sathue[4] = 0.2f; + sathue2[0] = 0.8f; + sathue2[1] = 0.8f ; + sathue2[2] = 0.8f ; + sathue2[3] = 0.8f; + } else if(/*HH> 1.4f &&*/ HH <= 2.1f ) { + sathue[0] = 1.6f; //green yellow 1.2 1.1 + sathue[1] = 1.5f; + sathue[2] = 1.4f; + sathue[3] = 1.2f; + sathue[4] = 0.2f; + sathue2[0] = 1.1f; + sathue2[1] = 1.05f; + sathue2[2] = 1.0f ; + sathue2[3] = 1.0f; + } else { /*if(HH> 2.1f && HH<= 3.1415f)*/ + sathue[0] = 1.4f; //green + sathue[1] = 1.3f; + sathue[2] = 1.2f; + sathue[3] = 1.1f; + sathue[4] = 0.2f; + sathue2[0] = 1.1f; + sathue2[1] = 1.05f; + sathue2[2] = 1.05f; + sathue2[3] = 1.0f; + } + } + } - // Saturated - if(saturation < s0 && saturation >=limitpastelsatur) { - float newchromaSatur=chromaSatur_a*saturation + chromaSatur_b; - chmodsat = newchromaSatur*satredu*sathue2[0]; - } - }// end transition + float chmodpastel, chmodsat; + // variables to improve transitions + float pa, pb;// transition = pa*saturation + pb + float chl00 = chromaPastel * satredu * sathue[4]; + float chl0 = chromaPastel * satredu * sathue[0]; + float chl1 = chromaPastel * satredu * sathue[1]; + float chl2 = chromaPastel * satredu * sathue[2]; + float chl3 = chromaPastel * satredu * sathue[3]; + float chs0 = chromaSatur * satredu * sathue2[0]; + float chs1 = chromaSatur * satredu * sathue2[1]; + float chs2 = chromaSatur * satredu * sathue2[2]; + float chs3 = chromaSatur * satredu * sathue2[3]; + float s3 = 1.0f; - if (saturation <= limitpastelsatur) { - if (chmodpastel > 2.0f ) - chmodpastel = 2.0f; //avoid too big values - else if(chmodpastel < -0.93f) - chmodpastel =-0.93f; //avoid negative values + // We handle only positive values here ; improve transitions + if (saturation < p00) { + chmodpastel = chl00 ; //neutral tones + } else if (saturation < p0 ) { + pa = (chl00 - chl0) / (p00 - p0); + pb = chl00 - pa * p00; + chmodpastel = pa * saturation + pb; + } else if (saturation < p1) { + pa = (chl0 - chl1) / (p0 - p1); + pb = chl0 - pa * p0; + chmodpastel = pa * saturation + pb; + } else if (saturation < p2) { + pa = (chl1 - chl2) / (p1 - p2); + pb = chl1 - pa * p1; + chmodpastel = pa * saturation + pb; + } else if (saturation < limitpastelsatur) { + pa = (chl2 - chl3) / (p2 - limitpastelsatur); + pb = chl2 - pa * p2; + chmodpastel = pa * saturation + pb; + } else if (saturation < s0) { + pa = (chl3 - chs0) / (limitpastelsatur - s0) ; + pb = chl3 - pa * limitpastelsatur; + chmodsat = pa * saturation + pb; + } else if (saturation < s1) { + pa = (chs0 - chs1) / (s0 - s1); + pb = chs0 - pa * s0; + chmodsat = pa * saturation + pb; + } else if (saturation < s2) { + pa = (chs1 - chs2) / (s1 - s2); + pb = chs1 - pa * s1; + chmodsat = pa * saturation + pb; + } else { + pa = (chs2 - chs3) / (s2 - s3); + pb = chs2 - pa * s2; + chmodsat = pa * saturation + pb; + } - Chprov *=(1.0f+chmodpastel); - if(Chprov<6.0f) - Chprov=6.0f; - } - else { //if (saturation > limitpastelsatur) - if (chmodsat > 1.8f ) - chmodsat = 1.8f; //saturated - else if(chmodsat < -0.93f) - chmodsat =-0.93f; + if(chromaPastel != chromaSatur) { - Chprov *= 1.0f+chmodsat; - if(Chprov < 6.0f) - Chprov=6.0f; - } - } - } + // Pastels + if(saturation > p2 && saturation < limitpastelsatur) { + float newchromaPastel = chromaPastel_a * saturation + chromaPastel_b; + chmodpastel = newchromaPastel * satredu * sathue[3]; + } - bool hhModified = false; - // Vibrance's Skin curve - if(skinCurveIsSet) { - if (HH>skbeg && HH transition - float HHsk=ask*HH+bsk; - float Hn=(skin_curve[HHsk]-bsk)/ask; - float Hc=(Hn*xx+HH*(1.0f-xx)); - HH=Hc; - hhModified = true; - } - else if(Chprov < (60.0f+dchr)) {//transition chroma - float HHsk=ask*HH+bsk; - float Hn=(skin_curve[HHsk]-bsk)/ask; - float Hc=(Hn*xx+HH*(1.0f-xx)); - float aa= (HH-Hc)/dchr ; float bb= HH-(60.0f+dchr)*aa; - HH=aa*Chprov+bb; - hhModified = true; - } - } - //transition hue - else if(HH>(skbeg-dhue) && HH<=skbeg && Chprov < (60.0f+dchr*0.5f)) { - float HHsk=ask*skbeg+bsk; - float Hn=(skin_curve[HHsk]-bsk)/ask; - float Hcc=(Hn*xx+skbeg*(1.0f-xx)); - float adh=(Hcc-(skbeg-dhue))/(dhue); - float bdh=Hcc-adh*skbeg; - HH=adh*HH+bdh; - hhModified = true; - } - else if(HH>=skend && HH<(skend+dhue) && Chprov < (60.0f+dchr*0.5f)) { - float HHsk=ask*skend+bsk; - float Hn=(skin_curve[HHsk]-bsk)/ask; - float Hcc=(Hn*xx+skend*(1.0f-xx)); - float adh=(skend+dhue-Hcc)/(dhue); - float bdh=Hcc-adh*skend; - HH=adh*HH+bdh; - hhModified = true; - } - } // end skin hue + // Saturated + if(saturation < s0 && saturation >= limitpastelsatur) { + float newchromaSatur = chromaSatur_a * saturation + chromaSatur_b; + chmodsat = newchromaSatur * satredu * sathue2[0]; + } + }// end transition - //Munsell correction -// float2 sincosval; - if(!avoidcolorshift && hhModified) - sincosval = xsincosf(HH); - float aprovn,bprovn; - bool inGamut; - do { - inGamut=true; - if(avoidcolorshift) { - float correctionHue=0.0f; - float correctlum=0.0f; + if (saturation <= limitpastelsatur) { + if (chmodpastel > 2.0f ) { + chmodpastel = 2.0f; //avoid too big values + } else if(chmodpastel < -0.93f) { + chmodpastel = -0.93f; //avoid negative values + } + + Chprov *= (1.0f + chmodpastel); + + if(Chprov < 6.0f) { + Chprov = 6.0f; + } + } else { //if (saturation > limitpastelsatur) + if (chmodsat > 1.8f ) { + chmodsat = 1.8f; //saturated + } else if(chmodsat < -0.93f) { + chmodsat = -0.93f; + } + + Chprov *= 1.0f + chmodsat; + + if(Chprov < 6.0f) { + Chprov = 6.0f; + } + } + } + } + + bool hhModified = false; + + // Vibrance's Skin curve + if(skinCurveIsSet) { + if (HH > skbeg && HH < skend) { + if(Chprov < 60.0f) {//skin hue : todo ==> transition + float HHsk = ask * HH + bsk; + float Hn = (skin_curve[HHsk] - bsk) / ask; + float Hc = (Hn * xx + HH * (1.0f - xx)); + HH = Hc; + hhModified = true; + } else if(Chprov < (60.0f + dchr)) { //transition chroma + float HHsk = ask * HH + bsk; + float Hn = (skin_curve[HHsk] - bsk) / ask; + float Hc = (Hn * xx + HH * (1.0f - xx)); + float aa = (HH - Hc) / dchr ; + float bb = HH - (60.0f + dchr) * aa; + HH = aa * Chprov + bb; + hhModified = true; + } + } + //transition hue + else if(HH > (skbeg - dhue) && HH <= skbeg && Chprov < (60.0f + dchr * 0.5f)) { + float HHsk = ask * skbeg + bsk; + float Hn = (skin_curve[HHsk] - bsk) / ask; + float Hcc = (Hn * xx + skbeg * (1.0f - xx)); + float adh = (Hcc - (skbeg - dhue)) / (dhue); + float bdh = Hcc - adh * skbeg; + HH = adh * HH + bdh; + hhModified = true; + } else if(HH >= skend && HH < (skend + dhue) && Chprov < (60.0f + dchr * 0.5f)) { + float HHsk = ask * skend + bsk; + float Hn = (skin_curve[HHsk] - bsk) / ask; + float Hcc = (Hn * xx + skend * (1.0f - xx)); + float adh = (skend + dhue - Hcc) / (dhue); + float bdh = Hcc - adh * skend; + HH = adh * HH + bdh; + hhModified = true; + } + } // end skin hue + + //Munsell correction +// float2 sincosval; + if(!avoidcolorshift && hhModified) { + sincosval = xsincosf(HH); + } + + float aprovn, bprovn; + bool inGamut; + + do { + inGamut = true; + + if(avoidcolorshift) { + float correctionHue = 0.0f; + float correctlum = 0.0f; #ifdef _DEBUG - Color::AllMunsellLch(/*lumaMuns*/false, Lprov,Lprov,HH,Chprov,CC,correctionHue,correctlum, MunsDebugInfo); + Color::AllMunsellLch(/*lumaMuns*/false, Lprov, Lprov, HH, Chprov, CC, correctionHue, correctlum, MunsDebugInfo); #else - Color::AllMunsellLch(/*lumaMuns*/false, Lprov,Lprov,HH,Chprov,CC,correctionHue,correctlum); + Color::AllMunsellLch(/*lumaMuns*/false, Lprov, Lprov, HH, Chprov, CC, correctionHue, correctlum); #endif - if(correctionHue != 0.f || hhModified) { - sincosval = xsincosf(HH+correctionHue); - hhModified = false; - } - } - aprovn=Chprov*sincosval.y; - bprovn=Chprov*sincosval.x; - float fyy = (0.00862069f *Lprov )+ 0.137932f; - float fxx = (0.002f * aprovn) + fyy; - float fzz = fyy - (0.005f * bprovn); - float xx_ = 65535.f * Color::f2xyz(fxx)*Color::D50x; - // float yy_ = 65535.0f * Color::f2xyz(fyy); - float zz_ = 65535.f * Color::f2xyz(fzz)*Color::D50z; - float yy_ = 65535.f * ((Lprov>Color::epskap) ? fyy*fyy*fyy : Lprov/Color::kappa); + if(correctionHue != 0.f || hhModified) { + sincosval = xsincosf(HH + correctionHue); + hhModified = false; + } + } - Color::xyz2rgb(xx_,yy_,zz_,R,G,B,wip); + aprovn = Chprov * sincosval.y; + bprovn = Chprov * sincosval.x; - if(R<0.0f || G<0.0f || B<0.0f) { + float fyy = (0.00862069f * Lprov ) + 0.137932f; + float fxx = (0.002f * aprovn) + fyy; + float fzz = fyy - (0.005f * bprovn); + float xx_ = 65535.f * Color::f2xyz(fxx) * Color::D50x; + // float yy_ = 65535.0f * Color::f2xyz(fyy); + float zz_ = 65535.f * Color::f2xyz(fzz) * Color::D50z; + float yy_ = 65535.f * ((Lprov > Color::epskap) ? fyy * fyy*fyy : Lprov / Color::kappa); + + Color::xyz2rgb(xx_, yy_, zz_, R, G, B, wip); + + if(R < 0.0f || G < 0.0f || B < 0.0f) { #ifdef _DEBUG - negsat++; + negsat++; #endif - Chprov *= 0.98f; - inGamut = false; - } + Chprov *= 0.98f; + inGamut = false; + } - // if "highlight reconstruction" enabled don't control Gamut for highlights - if((!highlight) && (R>65535.0f || G>65535.0f || B>65535.0f)) { + // if "highlight reconstruction" enabled don't control Gamut for highlights + if((!highlight) && (R > 65535.0f || G > 65535.0f || B > 65535.0f)) { #ifdef _DEBUG - moresat++; + moresat++; #endif - Chprov *= 0.98f; - inGamut = false; - } - } while (!inGamut); - - //put new values in Lab - lab->L[i][j]=Lprov*327.68f; - lab->a[i][j]=aprovn*327.68f; - lab->b[i][j]=bprovn*327.68f; - } + Chprov *= 0.98f; + inGamut = false; + } + } while (!inGamut); -} // end of parallelization + //put new values in Lab + lab->L[i][j] = Lprov * 327.68f; + lab->a[i][j] = aprovn * 327.68f; + lab->b[i][j] = bprovn * 327.68f; + } + + } // end of parallelization #ifdef _DEBUG - t2e.set(); - if (settings->verbose) { - printf("Vibrance (performed in %d usec):\n", t2e.etime(t1e)); - printf(" Gamut: G1negat=%iiter G165535=%iiter G2negsat=%iiter G265535=%iiter\n",negat,moreRGB,negsat,moresat); - if (MunsDebugInfo) - printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass); - } - if (MunsDebugInfo) - delete MunsDebugInfo; + t2e.set(); + + if (settings->verbose) { + printf("Vibrance (performed in %d usec):\n", t2e.etime(t1e)); + printf(" Gamut: G1negat=%iiter G165535=%iiter G2negsat=%iiter G265535=%iiter\n", negat, moreRGB, negsat, moresat); + + if (MunsDebugInfo) { + printf(" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%i\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass); + } + } + + if (MunsDebugInfo) { + delete MunsDebugInfo; + } + #endif } diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 80cc5206d..cae375e7e 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -5,18 +5,18 @@ // // code dated: December , 2014 // -// Ipwaveletcc 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. +// Ipwaveletcc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // * 2014 Jacques Desmis // * 2014 Ingo Weyrich @@ -46,10 +46,10 @@ #include "cplx_wavelet_dec.h" -#define TS 64 // Tile size -#define offset 25 // shift between tiles -#define fTS ((TS/2+1)) // second dimension of Fourier tiles -#define blkrad 1 // radius of block averaging +#define TS 64 // Tile size +#define offset 25 // shift between tiles +#define fTS ((TS/2+1)) // second dimension of Fourier tiles +#define blkrad 1 // radius of block averaging #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } @@ -74,86 +74,87 @@ PIX_SORT(pp[1],pp[2]) ; median=pp[2] ;} #define epsilon 0.001f/(TS*TS) //tolerance -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; struct cont_params { - float mul[10]; - int chrom; - int chro; - int contrast; - float th; - float thH; - float conres; - float conresH; - float chrores; - float hueres; - float sky; - float b_l,t_l,b_r,t_r; - float b_ly,t_ly,b_ry,t_ry; - float b_lsl,t_lsl,b_rsl,t_rsl; - float b_lhl,t_lhl,b_rhl,t_rhl; - float edg_low, edg_mean, edg_sd, edg_max; - float lev0s, lev0n, lev1s, lev1n, lev2s, lev2n, lev3s, lev3n; - float b_lpast,t_lpast,b_rpast,t_rpast; - float b_lsat,t_lsat,b_rsat,t_rsat; - int rad; - int val; - int til; - int numlevH, numlevS; - float mulC[9]; - float mulopaRG[9]; - float mulopaBY[9]; - bool curv; - bool opaBY; - bool opaRG; - bool edgcurv; - bool diagcurv; - int CHmet; - int CHSLmet; - int EDmet; - bool HSmet; - bool avoi; - float strength; - int reinforce; - bool detectedge; - int backm; - float eddet; - float eddetthr; - bool lips; - float eddetthrHi; - bool link; - bool lip3; - bool tonemap; - bool diag; - int TMmeth; - float tmstrength; - float balan; - int ite; - int contmet; - bool opaW; - int BAmet; - bool bam; - float blhigh; - float grhigh; - float blmed; - float grmed; - float bllow; - float grlow; - bool cbena; - bool contena; - bool chromena; - bool edgeena; - bool resena; - bool finena; - bool toningena; - bool noiseena; - int maxilev; - float edgsens; - float edgampl; - int neigh; - bool lipp; + float mul[10]; + int chrom; + int chro; + int contrast; + float th; + float thH; + float conres; + float conresH; + float chrores; + float hueres; + float sky; + float b_l, t_l, b_r, t_r; + float b_ly, t_ly, b_ry, t_ry; + float b_lsl, t_lsl, b_rsl, t_rsl; + float b_lhl, t_lhl, b_rhl, t_rhl; + float edg_low, edg_mean, edg_sd, edg_max; + float lev0s, lev0n, lev1s, lev1n, lev2s, lev2n, lev3s, lev3n; + float b_lpast, t_lpast, b_rpast, t_rpast; + float b_lsat, t_lsat, b_rsat, t_rsat; + int rad; + int val; + int til; + int numlevH, numlevS; + float mulC[9]; + float mulopaRG[9]; + float mulopaBY[9]; + bool curv; + bool opaBY; + bool opaRG; + bool edgcurv; + bool diagcurv; + int CHmet; + int CHSLmet; + int EDmet; + bool HSmet; + bool avoi; + float strength; + int reinforce; + bool detectedge; + int backm; + float eddet; + float eddetthr; + bool lips; + float eddetthrHi; + bool link; + bool lip3; + bool tonemap; + bool diag; + int TMmeth; + float tmstrength; + float balan; + int ite; + int contmet; + bool opaW; + int BAmet; + bool bam; + float blhigh; + float grhigh; + float blmed; + float grmed; + float bllow; + float grlow; + bool cbena; + bool contena; + bool chromena; + bool edgeena; + bool resena; + bool finena; + bool toningena; + bool noiseena; + int maxilev; + float edgsens; + float edgampl; + int neigh; + bool lipp; }; int wavNestedLevels = 1; @@ -163,848 +164,1162 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int { - MyTime t1e,t2e ; + MyTime t1e, t2e ; t1e.set(); #ifdef _DEBUG - // init variables to display Munsell corrections - MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); + // init variables to display Munsell corrections + MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); #endif - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; - const short int imheight=lab->H, imwidth=lab->W; - struct cont_params cp; - cp.avoi = params->wavelet.avoid; - if(params->wavelet.Medgreinf=="more") cp.reinforce = 1; - if(params->wavelet.Medgreinf=="none") cp.reinforce = 2; - if(params->wavelet.Medgreinf=="less") cp.reinforce = 3; - - if(params->wavelet.NPmethod=="none") cp.lip3 = false; - if(params->wavelet.NPmethod=="low") {cp.lip3 = true;cp.neigh=0;} - if(params->wavelet.NPmethod=="high") {cp.lip3 = true;cp.neigh=1;} - - cp.lipp = params->wavelet.lipst; - cp.diag = params->wavelet.tmr; - cp.balan = (float)params->wavelet.balance; - cp.ite = params->wavelet.iter; - cp.tonemap=false; - cp.bam=false; - if(params->wavelet.tmrs==0) cp.tonemap=false; - else cp.tonemap=true; - /*else if(params->wavelet.TMmethod=="std") {cp.TMmeth=1;cp.tonemap=true;} - else if(params->wavelet.TMmethod=="high") {cp.TMmeth=2;cp.tonemap=true;} - else if(params->wavelet.TMmethod=="lowhigh") {cp.TMmeth=3;cp.tonemap=true;} - */ - if(params->wavelet.TMmethod=="cont") cp.contmet=1; - else if(params->wavelet.TMmethod=="tm") cp.contmet=2; - - if(params->wavelet.BAmethod!="none") cp.bam=true; - if(params->wavelet.BAmethod=="sli") cp.BAmet=1; - if(params->wavelet.BAmethod=="cur") cp.BAmet=2; - - cp.tmstrength=params->wavelet.tmrs; - //cp.tonemap = params->wavelet.tmr; - cp.contena=true; - cp.contena=params->wavelet.expcontrast; - cp.chromena=true; - cp.chromena=params->wavelet.expchroma; - cp.edgeena=true; - cp.edgeena=params->wavelet.expedge; - cp.resena=true; - cp.resena=params->wavelet.expresid; - cp.finena=true; - cp.finena=params->wavelet.expfinal; - cp.toningena=true; - cp.toningena=params->wavelet.exptoning; - cp.noiseena=true; - cp.noiseena=params->wavelet.expnoise; - - if(params->wavelet.Backmethod=="black") cp.backm= 0; - if(params->wavelet.Backmethod=="grey") cp.backm = 1; - if(params->wavelet.Backmethod=="resid") cp.backm = 2; - cp.link=params->wavelet.linkedg; - cp.eddet=(float) params->wavelet.edgedetect; - cp.eddetthr=(float) params->wavelet.edgedetectthr; - cp.eddetthrHi=(float) params->wavelet.edgedetectthr2; - - cp.edgsens=60.f; - cp.edgampl=10.f; - if(cp.lipp) { - cp.edgsens=(float) params->wavelet.edgesensi; - cp.edgampl=(float) params->wavelet.edgeampli; - } - int N=imheight*imwidth; - int maxmul=params->wavelet.thres; - cp.maxilev=maxmul; - static const float scales[10] = {1.f,2.f,4.f,8.f,16.f,32.f,64.f,128.f,256.f,512.f}; - float scaleskip[10]; - for(int sc=0;sc<10;sc++) - scaleskip[sc]=scales[sc]/skip; - float atten0 = 0.40f; - float atten123=0.90f; + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; + const short int imheight = lab->H, imwidth = lab->W; + struct cont_params cp; + cp.avoi = params->wavelet.avoid; - //int DaubLen = settings->daubech ? 8 : 6; - int DaubLen; - if(params->wavelet.daubcoeffmethod=="2_") DaubLen=4; - if(params->wavelet.daubcoeffmethod=="4_") DaubLen=6; - if(params->wavelet.daubcoeffmethod=="6_") DaubLen=8; - if(params->wavelet.daubcoeffmethod=="10_") DaubLen=12; - if(params->wavelet.daubcoeffmethod=="14_") DaubLen=16; - - cp.CHSLmet=1; -// if(params->wavelet.CHSLmethod=="SL") cp.CHSLmet=1; -// if(params->wavelet.CHSLmethod=="CU") cp.CHSLmet=2; - cp.EDmet=1; - if(params->wavelet.EDmethod=="SL") cp.EDmet=1; - if(params->wavelet.EDmethod=="CU") cp.EDmet=2; - - cp.cbena= params->wavelet.cbenab; - cp.blhigh=(float)params->wavelet.bluehigh; - cp.grhigh=(float)params->wavelet.greenhigh; - cp.blmed=(float)params->wavelet.bluemed; - cp.grmed=(float)params->wavelet.greenmed; - cp.bllow=(float)params->wavelet.bluelow; - cp.grlow=(float)params->wavelet.greenlow; - cp.curv=false; - cp.edgcurv=false; - cp.diagcurv=false; - cp.opaRG=false; - cp.opaBY=false; - cp.opaW=false; - cp.CHmet=0; - cp.HSmet=false; - if(params->wavelet.CHmethod=="with") cp.CHmet=1; - if(params->wavelet.CHmethod=="link") cp.CHmet=2; - if(params->wavelet.HSmethod=="with") cp.HSmet=true; - - cp.strength = min(1.f,max(0.f,((float)params->wavelet.strength / 100.f))); - - for(int m=0;mwavelet.Medgreinf == "more") { + cp.reinforce = 1; } - - if(waOpacityCurveBY) cp.opaBY=true; - if(cp.opaBY) { - cp.mulopaBY[0]=200.f*(waOpacityCurveBY[0]-0.5f); - cp.mulopaBY[1]=200.f*(waOpacityCurveBY[62]-0.5f); - cp.mulopaBY[2]=200.f*(waOpacityCurveBY[125]-0.5f); - cp.mulopaBY[3]=200.f*(waOpacityCurveBY[187]-0.5f); - cp.mulopaBY[4]=200.f*(waOpacityCurveBY[250]-0.5f); - cp.mulopaBY[5]=200.f*(waOpacityCurveBY[312]-0.5f); - cp.mulopaBY[6]=200.f*(waOpacityCurveBY[375]-0.5f); - cp.mulopaBY[7]=200.f*(waOpacityCurveBY[438]-0.5f); - cp.mulopaBY[8]=200.f*(waOpacityCurveBY[500]-0.5f); - } - else { - for(int level=0;level<9;level++) - cp.mulopaBY[level] = 0.f; + + if(params->wavelet.Medgreinf == "none") { + cp.reinforce = 2; } - if(wavCLVCcurve) cp.edgcurv=true; - if(waOpacityCurveWL) cp.diagcurv=true; - for(int m=0;mverbose) printf("Wav mul 0=%f 1=%f 2=%f 3=%f 4=%f 5=%f 6=%f 7=%f 8=%f 9=%f\n",cp.mul[0],cp.mul[1],cp.mul[2],cp.mul[3],cp.mul[4],cp.mul[5],cp.mul[6],cp.mul[7],cp.mul[8],cp.mul[9]); - for(int sc=0;sc<9;sc++) {//reduce strength if zoom < 100% for chroma and tuning - if(sc==0) {if(scaleskip[sc] < 1.f) {cp.mulC[sc]*=(atten0*scaleskip[sc]);cp.mulopaRG[sc]*=(atten0*scaleskip[sc]);cp.mulopaBY[sc]*=(atten0*scaleskip[sc]);}} - else {if(scaleskip[sc] < 1.f) {cp.mulC[sc]*=(atten123*scaleskip[sc]);cp.mulopaRG[sc]*=(atten123*scaleskip[sc]);cp.mulopaBY[sc]*=(atten123*scaleskip[sc]);}} - } - - cp.chro=waparams.chro; - cp.chrom=waparams.chroma; - cp.contrast=waparams.contrast; - cp.rad=waparams.edgrad; - cp.val=waparams.edgval; - cp.til=waparams.edgthresh; - - cp.conres=waparams.rescon; - cp.conresH=waparams.resconH; - cp.chrores=waparams.reschro; - //cp.hueres=waparams.reshue; - cp.hueres=2.f; - cp.th=float(waparams.thr); - cp.thH=float(waparams.thrH); - cp.sky=waparams.sky; - //skin - cp.b_l = static_cast(params->wavelet.hueskin.value[0]) / 100.0f; - cp.t_l = static_cast(params->wavelet.hueskin.value[1]) / 100.0f; - cp.b_r = static_cast(params->wavelet.hueskin.value[2]) / 100.0f; - cp.t_r = static_cast(params->wavelet.hueskin.value[3]) / 100.0f; - - cp.b_ly = static_cast(params->wavelet.hueskin2.value[0]) / 100.0f; - cp.t_ly = static_cast(params->wavelet.hueskin2.value[1]) / 100.0f; - cp.b_ry = static_cast(params->wavelet.hueskin2.value[2]) / 100.0f; - cp.t_ry = static_cast(params->wavelet.hueskin2.value[3]) / 100.0f; - cp.numlevH=params->wavelet.threshold; - - //shadows - cp.b_lsl = static_cast(params->wavelet.bllev.value[0]); - cp.t_lsl = static_cast(params->wavelet.bllev.value[1]); - cp.b_rsl = static_cast(params->wavelet.bllev.value[2]); - cp.t_rsl = static_cast(params->wavelet.bllev.value[3]); - cp.numlevS=params->wavelet.threshold2; - int maxlevS=9-cp.numlevH; - cp.numlevS = MIN(cp.numlevS,maxlevS); - //printf("levHigh=%d levShad=%d\n",cp.numlevH,cp.numlevS); - //highlight - cp.b_lhl = static_cast(params->wavelet.hllev.value[0]); - cp.t_lhl = static_cast(params->wavelet.hllev.value[1]); - cp.b_rhl = static_cast(params->wavelet.hllev.value[2]); - cp.t_rhl = static_cast(params->wavelet.hllev.value[3]); - //printf("BL=%f TL=%f BR=%f TR=%f\n",cp.b_lhl,cp.t_lhl,cp.b_rhl,cp.t_rhl); - //pastel - cp.b_lpast = static_cast(params->wavelet.pastlev.value[0]); - cp.t_lpast = static_cast(params->wavelet.pastlev.value[1]); - cp.b_rpast = static_cast(params->wavelet.pastlev.value[2]); - cp.t_rpast = static_cast(params->wavelet.pastlev.value[3]); - //saturated - cp.b_lsat = static_cast(params->wavelet.satlev.value[0]); - cp.t_lsat = static_cast(params->wavelet.satlev.value[1]); - cp.b_rsat = static_cast(params->wavelet.satlev.value[2]); - cp.t_rsat = static_cast(params->wavelet.satlev.value[3]); - //edge local contrast - cp.edg_low = static_cast(params->wavelet.edgcont.value[0]); - cp.edg_mean = static_cast(params->wavelet.edgcont.value[1]); - cp.edg_max = static_cast(params->wavelet.edgcont.value[2]); - cp.edg_sd = static_cast(params->wavelet.edgcont.value[3]); - //level noise - cp.lev0s =static_cast(params->wavelet.level0noise.value[0]); - cp.lev0n =static_cast(params->wavelet.level0noise.value[1]); - cp.lev1s =static_cast(params->wavelet.level1noise.value[0]); - cp.lev1n =static_cast(params->wavelet.level1noise.value[1]); - cp.lev2s =static_cast(params->wavelet.level2noise.value[0]); - cp.lev2n =static_cast(params->wavelet.level2noise.value[1]); - cp.lev3s =static_cast(params->wavelet.level3noise.value[0]); - cp.lev3n =static_cast(params->wavelet.level3noise.value[1]); - cp.detectedge = false; - cp.detectedge = params->wavelet.medianlev; - //printf("low=%f mean=%f sd=%f max=%f\n",cp.edg_low,cp.edg_mean,cp.edg_sd,cp.edg_max); - int minwin=min(imwidth,imheight); - int maxlevelcrop=9; - if(cp.mul[9]!=0) - maxlevelcrop=10; - // adap maximum level wavelet to size of crop - if(minwin*skip < 1024) maxlevelcrop = 9;//sampling wavelet 512 - if(minwin*skip < 512) maxlevelcrop = 8;//sampling wavelet 256 - if(minwin*skip < 256) maxlevelcrop = 7;//sampling 128 - if(minwin*skip < 128) maxlevelcrop = 6; - if(minwin < 64) maxlevelcrop = 5; - // printf("minwin=%d maxcrop=%d\n",minwin, maxlevelcrop); - - int levwav=params->wavelet.thres; - if(levwav==9 && cp.mul[9]!=0) levwav=10; - levwav=min(maxlevelcrop,levwav); - // determine number of levels to process. - // for(levwav=min(maxlevelcrop,levwav);levwav>0;levwav--) - // if(cp.mul[levwav-1]!=0.f || cp.curv) - // if(cp.mul[levwav-1]!=0.f) - // break; - // I suppress this fonctionality ==> crash for level < 3 - if(levwav<1) - return; // nothing to do + if(params->wavelet.Medgreinf == "less") { + cp.reinforce = 3; + } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // begin tile processing of image + if(params->wavelet.NPmethod == "none") { + cp.lip3 = false; + } - //output buffer - int realtile; - if(params->wavelet.Tilesmethod=="big") realtile=22; - if(params->wavelet.Tilesmethod=="lit") realtile=12; - - int tilesize; - int overlap; - tilesize = 1024; - overlap = 128; - //tilesize=128*params->wavelet.tiles; - tilesize=128*realtile; - //overlap=(int) tilesize*params->wavelet.overl; - overlap=(int) tilesize*0.125f; - // printf("overl=%d\n",overlap); - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - if(params->wavelet.Tilesmethod=="full") kall=0; - Tile_calc (tilesize, overlap, kall, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + if(params->wavelet.NPmethod == "low") { + cp.lip3 = true; + cp.neigh = 0; + } - const int numtiles = numtiles_W*numtiles_H; - LabImage * dsttmp; - if(numtiles == 1) { - dsttmp = dst; - } else { - dsttmp = new LabImage(imwidth,imheight); - for (int n=0; n<3*imwidth*imheight; n++) dsttmp->data[n] = 0; - } - //now we have tile dimensions, overlaps - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - int minsizetile=min(tilewidth, tileheight); - int maxlev2=10; - if(minsizetile < 1024 && levwav==10) maxlev2 = 9; - if(minsizetile < 512) maxlev2 = 8; - if(minsizetile < 256) maxlev2 = 7; - if(minsizetile < 128) maxlev2 = 6; - levwav=min(maxlev2,levwav); - - //printf("levwav = %d\n",levwav); + if(params->wavelet.NPmethod == "high") { + cp.lip3 = true; + cp.neigh = 1; + } - int numthreads = 1; - int maxnumberofthreadsforwavelet =0; - //reduce memory for big tile size - if(kall!=0) { - if(realtile <= 22) maxnumberofthreadsforwavelet=2; - if(realtile <= 20) maxnumberofthreadsforwavelet=3; - if(realtile <= 18) maxnumberofthreadsforwavelet=4; - if(realtile <= 16) maxnumberofthreadsforwavelet=6; - if(realtile <= 14) maxnumberofthreadsforwavelet=8; - //printf("maxNRT=%d\n",maxnumberofthreadsforwavelet); - if((maxnumberofthreadsforwavelet==6 || maxnumberofthreadsforwavelet==8) && levwav==10) maxnumberofthreadsforwavelet-=2; - if(levwav <=7 && maxnumberofthreadsforwavelet ==8) maxnumberofthreadsforwavelet=0; - } - //printf("maxthre=%d\n",maxnumberofthreadsforwavelet); + cp.lipp = params->wavelet.lipst; + cp.diag = params->wavelet.tmr; + cp.balan = (float)params->wavelet.balance; + cp.ite = params->wavelet.iter; + cp.tonemap = false; + cp.bam = false; + + if(params->wavelet.tmrs == 0) { + cp.tonemap = false; + } else { + cp.tonemap = true; + } + + /*else if(params->wavelet.TMmethod=="std") {cp.TMmeth=1;cp.tonemap=true;} + else if(params->wavelet.TMmethod=="high") {cp.TMmeth=2;cp.tonemap=true;} + else if(params->wavelet.TMmethod=="lowhigh") {cp.TMmeth=3;cp.tonemap=true;} + */ + if(params->wavelet.TMmethod == "cont") { + cp.contmet = 1; + } else if(params->wavelet.TMmethod == "tm") { + cp.contmet = 2; + } + + if(params->wavelet.BAmethod != "none") { + cp.bam = true; + } + + if(params->wavelet.BAmethod == "sli") { + cp.BAmet = 1; + } + + if(params->wavelet.BAmethod == "cur") { + cp.BAmet = 2; + } + + cp.tmstrength = params->wavelet.tmrs; + //cp.tonemap = params->wavelet.tmr; + cp.contena = true; + cp.contena = params->wavelet.expcontrast; + cp.chromena = true; + cp.chromena = params->wavelet.expchroma; + cp.edgeena = true; + cp.edgeena = params->wavelet.expedge; + cp.resena = true; + cp.resena = params->wavelet.expresid; + cp.finena = true; + cp.finena = params->wavelet.expfinal; + cp.toningena = true; + cp.toningena = params->wavelet.exptoning; + cp.noiseena = true; + cp.noiseena = params->wavelet.expnoise; + + if(params->wavelet.Backmethod == "black") { + cp.backm = 0; + } + + if(params->wavelet.Backmethod == "grey") { + cp.backm = 1; + } + + if(params->wavelet.Backmethod == "resid") { + cp.backm = 2; + } + + cp.link = params->wavelet.linkedg; + cp.eddet = (float) params->wavelet.edgedetect; + cp.eddetthr = (float) params->wavelet.edgedetectthr; + cp.eddetthrHi = (float) params->wavelet.edgedetectthr2; + + cp.edgsens = 60.f; + cp.edgampl = 10.f; + + if(cp.lipp) { + cp.edgsens = (float) params->wavelet.edgesensi; + cp.edgampl = (float) params->wavelet.edgeampli; + } + + int N = imheight * imwidth; + int maxmul = params->wavelet.thres; + cp.maxilev = maxmul; + static const float scales[10] = {1.f, 2.f, 4.f, 8.f, 16.f, 32.f, 64.f, 128.f, 256.f, 512.f}; + float scaleskip[10]; + + for(int sc = 0; sc < 10; sc++) { + scaleskip[sc] = scales[sc] / skip; + } + + float atten0 = 0.40f; + float atten123 = 0.90f; + + //int DaubLen = settings->daubech ? 8 : 6; + int DaubLen; + + if(params->wavelet.daubcoeffmethod == "2_") { + DaubLen = 4; + } + + if(params->wavelet.daubcoeffmethod == "4_") { + DaubLen = 6; + } + + if(params->wavelet.daubcoeffmethod == "6_") { + DaubLen = 8; + } + + if(params->wavelet.daubcoeffmethod == "10_") { + DaubLen = 12; + } + + if(params->wavelet.daubcoeffmethod == "14_") { + DaubLen = 16; + } + + cp.CHSLmet = 1; +// if(params->wavelet.CHSLmethod=="SL") cp.CHSLmet=1; +// if(params->wavelet.CHSLmethod=="CU") cp.CHSLmet=2; + cp.EDmet = 1; + + if(params->wavelet.EDmethod == "SL") { + cp.EDmet = 1; + } + + if(params->wavelet.EDmethod == "CU") { + cp.EDmet = 2; + } + + cp.cbena = params->wavelet.cbenab; + cp.blhigh = (float)params->wavelet.bluehigh; + cp.grhigh = (float)params->wavelet.greenhigh; + cp.blmed = (float)params->wavelet.bluemed; + cp.grmed = (float)params->wavelet.greenmed; + cp.bllow = (float)params->wavelet.bluelow; + cp.grlow = (float)params->wavelet.greenlow; + cp.curv = false; + cp.edgcurv = false; + cp.diagcurv = false; + cp.opaRG = false; + cp.opaBY = false; + cp.opaW = false; + cp.CHmet = 0; + cp.HSmet = false; + + if(params->wavelet.CHmethod == "with") { + cp.CHmet = 1; + } + + if(params->wavelet.CHmethod == "link") { + cp.CHmet = 2; + } + + if(params->wavelet.HSmethod == "with") { + cp.HSmet = true; + } + + cp.strength = min(1.f, max(0.f, ((float)params->wavelet.strength / 100.f))); + + for(int m = 0; m < maxmul; m++) { + cp.mulC[m] = waparams.ch[m]; + } + + if(waOpacityCurveRG) { + cp.opaRG = true; + } + + if(cp.opaRG) { + cp.mulopaRG[0] = 200.f * (waOpacityCurveRG[0] - 0.5f); + cp.mulopaRG[1] = 200.f * (waOpacityCurveRG[62] - 0.5f); + cp.mulopaRG[2] = 200.f * (waOpacityCurveRG[125] - 0.5f); + cp.mulopaRG[3] = 200.f * (waOpacityCurveRG[187] - 0.5f); + cp.mulopaRG[4] = 200.f * (waOpacityCurveRG[250] - 0.5f); + cp.mulopaRG[5] = 200.f * (waOpacityCurveRG[312] - 0.5f); + cp.mulopaRG[6] = 200.f * (waOpacityCurveRG[375] - 0.5f); + cp.mulopaRG[7] = 200.f * (waOpacityCurveRG[438] - 0.5f); + cp.mulopaRG[8] = 200.f * (waOpacityCurveRG[500] - 0.5f); + } else { + for(int level = 0; level < 9; level++) { + cp.mulopaRG[level] = 0.f; + } + } + + if(waOpacityCurveBY) { + cp.opaBY = true; + } + + if(cp.opaBY) { + cp.mulopaBY[0] = 200.f * (waOpacityCurveBY[0] - 0.5f); + cp.mulopaBY[1] = 200.f * (waOpacityCurveBY[62] - 0.5f); + cp.mulopaBY[2] = 200.f * (waOpacityCurveBY[125] - 0.5f); + cp.mulopaBY[3] = 200.f * (waOpacityCurveBY[187] - 0.5f); + cp.mulopaBY[4] = 200.f * (waOpacityCurveBY[250] - 0.5f); + cp.mulopaBY[5] = 200.f * (waOpacityCurveBY[312] - 0.5f); + cp.mulopaBY[6] = 200.f * (waOpacityCurveBY[375] - 0.5f); + cp.mulopaBY[7] = 200.f * (waOpacityCurveBY[438] - 0.5f); + cp.mulopaBY[8] = 200.f * (waOpacityCurveBY[500] - 0.5f); + } else { + for(int level = 0; level < 9; level++) { + cp.mulopaBY[level] = 0.f; + } + } + + if(wavCLVCcurve) { + cp.edgcurv = true; + } + + if(waOpacityCurveWL) { + cp.diagcurv = true; + } + + for(int m = 0; m < maxmul; m++) { + cp.mul[m] = waparams.c[m]; + } + + cp.mul[9] = (float) waparams.sup; + + for(int sc = 0; sc < 10; sc++) { //reduce strength if zoom < 100% for contrast + if(sc == 0) { + if(scaleskip[sc] < 1.f) { + cp.mul[sc] *= (atten0 * scaleskip[sc]); + } + } else { + if(scaleskip[sc] < 1.f) { + cp.mul[sc] *= (atten123 * scaleskip[sc]); + } + } + } + +// if(settings->verbose) printf("Wav mul 0=%f 1=%f 2=%f 3=%f 4=%f 5=%f 6=%f 7=%f 8=%f 9=%f\n",cp.mul[0],cp.mul[1],cp.mul[2],cp.mul[3],cp.mul[4],cp.mul[5],cp.mul[6],cp.mul[7],cp.mul[8],cp.mul[9]); + for(int sc = 0; sc < 9; sc++) { //reduce strength if zoom < 100% for chroma and tuning + if(sc == 0) { + if(scaleskip[sc] < 1.f) { + cp.mulC[sc] *= (atten0 * scaleskip[sc]); + cp.mulopaRG[sc] *= (atten0 * scaleskip[sc]); + cp.mulopaBY[sc] *= (atten0 * scaleskip[sc]); + } + } else { + if(scaleskip[sc] < 1.f) { + cp.mulC[sc] *= (atten123 * scaleskip[sc]); + cp.mulopaRG[sc] *= (atten123 * scaleskip[sc]); + cp.mulopaBY[sc] *= (atten123 * scaleskip[sc]); + } + } + } + + cp.chro = waparams.chro; + cp.chrom = waparams.chroma; + cp.contrast = waparams.contrast; + cp.rad = waparams.edgrad; + cp.val = waparams.edgval; + cp.til = waparams.edgthresh; + + cp.conres = waparams.rescon; + cp.conresH = waparams.resconH; + cp.chrores = waparams.reschro; + //cp.hueres=waparams.reshue; + cp.hueres = 2.f; + cp.th = float(waparams.thr); + cp.thH = float(waparams.thrH); + cp.sky = waparams.sky; + //skin + cp.b_l = static_cast(params->wavelet.hueskin.value[0]) / 100.0f; + cp.t_l = static_cast(params->wavelet.hueskin.value[1]) / 100.0f; + cp.b_r = static_cast(params->wavelet.hueskin.value[2]) / 100.0f; + cp.t_r = static_cast(params->wavelet.hueskin.value[3]) / 100.0f; + + cp.b_ly = static_cast(params->wavelet.hueskin2.value[0]) / 100.0f; + cp.t_ly = static_cast(params->wavelet.hueskin2.value[1]) / 100.0f; + cp.b_ry = static_cast(params->wavelet.hueskin2.value[2]) / 100.0f; + cp.t_ry = static_cast(params->wavelet.hueskin2.value[3]) / 100.0f; + cp.numlevH = params->wavelet.threshold; + + //shadows + cp.b_lsl = static_cast(params->wavelet.bllev.value[0]); + cp.t_lsl = static_cast(params->wavelet.bllev.value[1]); + cp.b_rsl = static_cast(params->wavelet.bllev.value[2]); + cp.t_rsl = static_cast(params->wavelet.bllev.value[3]); + cp.numlevS = params->wavelet.threshold2; + int maxlevS = 9 - cp.numlevH; + cp.numlevS = MIN(cp.numlevS, maxlevS); + //printf("levHigh=%d levShad=%d\n",cp.numlevH,cp.numlevS); + //highlight + cp.b_lhl = static_cast(params->wavelet.hllev.value[0]); + cp.t_lhl = static_cast(params->wavelet.hllev.value[1]); + cp.b_rhl = static_cast(params->wavelet.hllev.value[2]); + cp.t_rhl = static_cast(params->wavelet.hllev.value[3]); + //printf("BL=%f TL=%f BR=%f TR=%f\n",cp.b_lhl,cp.t_lhl,cp.b_rhl,cp.t_rhl); + //pastel + cp.b_lpast = static_cast(params->wavelet.pastlev.value[0]); + cp.t_lpast = static_cast(params->wavelet.pastlev.value[1]); + cp.b_rpast = static_cast(params->wavelet.pastlev.value[2]); + cp.t_rpast = static_cast(params->wavelet.pastlev.value[3]); + //saturated + cp.b_lsat = static_cast(params->wavelet.satlev.value[0]); + cp.t_lsat = static_cast(params->wavelet.satlev.value[1]); + cp.b_rsat = static_cast(params->wavelet.satlev.value[2]); + cp.t_rsat = static_cast(params->wavelet.satlev.value[3]); + //edge local contrast + cp.edg_low = static_cast(params->wavelet.edgcont.value[0]); + cp.edg_mean = static_cast(params->wavelet.edgcont.value[1]); + cp.edg_max = static_cast(params->wavelet.edgcont.value[2]); + cp.edg_sd = static_cast(params->wavelet.edgcont.value[3]); + //level noise + cp.lev0s = static_cast(params->wavelet.level0noise.value[0]); + cp.lev0n = static_cast(params->wavelet.level0noise.value[1]); + cp.lev1s = static_cast(params->wavelet.level1noise.value[0]); + cp.lev1n = static_cast(params->wavelet.level1noise.value[1]); + cp.lev2s = static_cast(params->wavelet.level2noise.value[0]); + cp.lev2n = static_cast(params->wavelet.level2noise.value[1]); + cp.lev3s = static_cast(params->wavelet.level3noise.value[0]); + cp.lev3n = static_cast(params->wavelet.level3noise.value[1]); + + cp.detectedge = false; + cp.detectedge = params->wavelet.medianlev; + //printf("low=%f mean=%f sd=%f max=%f\n",cp.edg_low,cp.edg_mean,cp.edg_sd,cp.edg_max); + int minwin = min(imwidth, imheight); + int maxlevelcrop = 9; + + if(cp.mul[9] != 0) { + maxlevelcrop = 10; + } + + // adap maximum level wavelet to size of crop + if(minwin * skip < 1024) { + maxlevelcrop = 9; //sampling wavelet 512 + } + + if(minwin * skip < 512) { + maxlevelcrop = 8; //sampling wavelet 256 + } + + if(minwin * skip < 256) { + maxlevelcrop = 7; //sampling 128 + } + + if(minwin * skip < 128) { + maxlevelcrop = 6; + } + + if(minwin < 64) { + maxlevelcrop = 5; + } + + // printf("minwin=%d maxcrop=%d\n",minwin, maxlevelcrop); + + int levwav = params->wavelet.thres; + + if(levwav == 9 && cp.mul[9] != 0) { + levwav = 10; + } + + levwav = min(maxlevelcrop, levwav); + + // determine number of levels to process. + // for(levwav=min(maxlevelcrop,levwav);levwav>0;levwav--) + // if(cp.mul[levwav-1]!=0.f || cp.curv) + // if(cp.mul[levwav-1]!=0.f) + // break; + // I suppress this fonctionality ==> crash for level < 3 + if(levwav < 1) { + return; // nothing to do + } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // begin tile processing of image + + //output buffer + int realtile; + + if(params->wavelet.Tilesmethod == "big") { + realtile = 22; + } + + if(params->wavelet.Tilesmethod == "lit") { + realtile = 12; + } + + int tilesize; + int overlap; + tilesize = 1024; + overlap = 128; + //tilesize=128*params->wavelet.tiles; + tilesize = 128 * realtile; + //overlap=(int) tilesize*params->wavelet.overl; + overlap = (int) tilesize * 0.125f; + // printf("overl=%d\n",overlap); + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + + if(params->wavelet.Tilesmethod == "full") { + kall = 0; + } + + Tile_calc (tilesize, overlap, kall, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + + const int numtiles = numtiles_W * numtiles_H; + LabImage * dsttmp; + + if(numtiles == 1) { + dsttmp = dst; + } else { + dsttmp = new LabImage(imwidth, imheight); + + for (int n = 0; n < 3 * imwidth * imheight; n++) { + dsttmp->data[n] = 0; + } + } + + //now we have tile dimensions, overlaps + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + int minsizetile = min(tilewidth, tileheight); + int maxlev2 = 10; + + if(minsizetile < 1024 && levwav == 10) { + maxlev2 = 9; + } + + if(minsizetile < 512) { + maxlev2 = 8; + } + + if(minsizetile < 256) { + maxlev2 = 7; + } + + if(minsizetile < 128) { + maxlev2 = 6; + } + + levwav = min(maxlev2, levwav); + + //printf("levwav = %d\n",levwav); + + int numthreads = 1; + int maxnumberofthreadsforwavelet = 0; + + //reduce memory for big tile size + if(kall != 0) { + if(realtile <= 22) { + maxnumberofthreadsforwavelet = 2; + } + + if(realtile <= 20) { + maxnumberofthreadsforwavelet = 3; + } + + if(realtile <= 18) { + maxnumberofthreadsforwavelet = 4; + } + + if(realtile <= 16) { + maxnumberofthreadsforwavelet = 6; + } + + if(realtile <= 14) { + maxnumberofthreadsforwavelet = 8; + } + + //printf("maxNRT=%d\n",maxnumberofthreadsforwavelet); + if((maxnumberofthreadsforwavelet == 6 || maxnumberofthreadsforwavelet == 8) && levwav == 10) { + maxnumberofthreadsforwavelet -= 2; + } + + if(levwav <= 7 && maxnumberofthreadsforwavelet == 8) { + maxnumberofthreadsforwavelet = 0; + } + } + + //printf("maxthre=%d\n",maxnumberofthreadsforwavelet); #ifdef _OPENMP - // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles - if( options.rgbDenoiseThreadLimit>0) - maxnumberofthreadsforwavelet = min(max(options.rgbDenoiseThreadLimit / 2, 1), maxnumberofthreadsforwavelet); - - numthreads = MIN(numtiles,omp_get_max_threads()); - if(maxnumberofthreadsforwavelet > 0) - numthreads = MIN(numthreads,maxnumberofthreadsforwavelet); -#ifdef _RT_NESTED_OPENMP - wavNestedLevels = omp_get_max_threads() / numthreads; - bool oldNested = omp_get_nested(); - if(wavNestedLevels < 2) - wavNestedLevels = 1; - else - omp_set_nested(true); - if(maxnumberofthreadsforwavelet > 0) - while(wavNestedLevels*numthreads > maxnumberofthreadsforwavelet) - wavNestedLevels--; -#endif - if(settings->verbose) - printf("Ip Wavelet uses %d main thread(s) and up to %d nested thread(s) for each main thread\n",numthreads,wavNestedLevels); + // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles + if( options.rgbDenoiseThreadLimit > 0) { + maxnumberofthreadsforwavelet = min(max(options.rgbDenoiseThreadLimit / 2, 1), maxnumberofthreadsforwavelet); + } -#endif + numthreads = MIN(numtiles, omp_get_max_threads()); -#ifdef _OPENMP -#pragma omp parallel num_threads(numthreads) -#endif -{ - float *mean = new float [9]; - float *meanN = new float [9]; - float *sigma = new float [9]; - float *sigmaN = new float [9]; - float *MaxP = new float [9]; - float *MaxN = new float [9]; - - float** varhue = new float*[tileheight]; - for (int i=0; i we can use output buffer for labco - labco = dst; - if(cp.avoi) { // we need a buffer to hold a copy of the L channel - Lold = new float*[tileheight]; - LoldBuffer = new float[tilewidth*tileheight]; - memcpy(LoldBuffer, lab->L[0], tilewidth*tileheight*sizeof(float)); - for (int i=0; iL; - } + if(maxnumberofthreadsforwavelet > 0) { + numthreads = MIN(numthreads, maxnumberofthreadsforwavelet); + } #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) + wavNestedLevels = omp_get_max_threads() / numthreads; + bool oldNested = omp_get_nested(); + + if(wavNestedLevels < 2) { + wavNestedLevels = 1; + } else { + omp_set_nested(true); + } + + if(maxnumberofthreadsforwavelet > 0) + while(wavNestedLevels * numthreads > maxnumberofthreadsforwavelet) { + wavNestedLevels--; + } + #endif - for (int i=tiletop; iverbose) { + printf("Ip Wavelet uses %d main thread(s) and up to %d nested thread(s) for each main thread\n", numthreads, wavNestedLevels); + } + + +#endif + +#ifdef _OPENMP + #pragma omp parallel num_threads(numthreads) +#endif + { + float *mean = new float [9]; + float *meanN = new float [9]; + float *sigma = new float [9]; + float *sigmaN = new float [9]; + float *MaxP = new float [9]; + float *MaxN = new float [9]; + + float** varhue = new float*[tileheight]; + + for (int i = 0; i < tileheight; i++) { + varhue[i] = new float[tilewidth]; + } + + float** varchro = new float*[tileheight]; + + for (int i = 0; i < tileheight; i++) { + varchro[i] = new float[tilewidth]; + } + +#ifdef _OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int tiletop = 0; tiletop < imheight; tiletop += tileHskip) { + for (int tileleft = 0; tileleft < imwidth ; tileleft += tileWskip) { + int tileright = MIN(imwidth, tileleft + tilewidth); + int tilebottom = MIN(imheight, tiletop + tileheight); + int width = tileright - tileleft; + int height = tilebottom - tiletop; + LabImage * labco; + float **Lold; + float *LoldBuffer = NULL; + + if(numtiles == 1) { // untiled processing => we can use output buffer for labco + labco = dst; + + if(cp.avoi) { // we need a buffer to hold a copy of the L channel + Lold = new float*[tileheight]; + LoldBuffer = new float[tilewidth * tileheight]; + memcpy(LoldBuffer, lab->L[0], tilewidth * tileheight * sizeof(float)); + + for (int i = 0; i < tileheight; i++) { + Lold[i] = LoldBuffer + i * tilewidth; + } + } + + } else { + labco = new LabImage(width, height); + Lold = lab->L; + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + int j; #ifdef __SSE2__ - __m128 c327d68v = _mm_set1_ps(327.68f); - __m128 av, bv, huev, chrov; - for (j=tileleft; ja[i][j]); - bv = LVFU(lab->b[i][j]); - huev = xatan2f(bv,av); - chrov = _mm_sqrt_ps(SQRV(av)+SQRV(bv)) / c327d68v; - _mm_storeu_ps(&varhue[i1][j1],huev); - _mm_storeu_ps(&varchro[i1][j1], chrov); - if(labco != lab) { - _mm_storeu_ps(&(labco->L[i1][j1]),LVFU(lab->L[i][j])); - _mm_storeu_ps(&(labco->a[i1][j1]),av); - _mm_storeu_ps(&(labco->b[i1][j1]),bv); - } - } + __m128 c327d68v = _mm_set1_ps(327.68f); + __m128 av, bv, huev, chrov; + + for (j = tileleft; j < tileright - 3; j += 4) { + int j1 = j - tileleft; + av = LVFU(lab->a[i][j]); + bv = LVFU(lab->b[i][j]); + huev = xatan2f(bv, av); + chrov = _mm_sqrt_ps(SQRV(av) + SQRV(bv)) / c327d68v; + _mm_storeu_ps(&varhue[i1][j1], huev); + _mm_storeu_ps(&varchro[i1][j1], chrov); + + if(labco != lab) { + _mm_storeu_ps(&(labco->L[i1][j1]), LVFU(lab->L[i][j])); + _mm_storeu_ps(&(labco->a[i1][j1]), av); + _mm_storeu_ps(&(labco->b[i1][j1]), bv); + } + } + #else - j=tileleft; + j = tileleft; #endif - for (; ja[i][j]; - float b=lab->b[i][j]; - varhue[i1][j1]=xatan2f(b,a); - varchro[i1][j1]=(sqrtf(a*a+b*b))/327.68f; - if(labco != lab) { - labco->L[i1][j1] = lab->L[i][j]; - labco->a[i1][j1] = a; - labco->b[i1][j1] = b; - } - } - } - //to avoid artifacts in blue sky - if(params->wavelet.median) { - float** tmL; - int wid=labco->W; - int hei=labco->H; - int borderL = 1; - tmL = new float*[hei]; - for (int i=0; iL[i][j]; - } - } - -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) -#endif - for (int i=1; i - 2.5f) && (varchro[i][j] > 15.f && varchro[i][j] < 55.f) && labco->L[i][j] > 6000.f) //blue sky + med3x3 ==> after for more effect use denoise - med3(labco->L[i][j] ,labco->L[i-1][j], labco->L[i+1][j] ,labco->L[i][j+1],labco->L[i][j-1], labco->L[i-1][j-1],labco->L[i-1][j+1],labco->L[i+1][j-1],labco->L[i+1][j+1],tmL[i][j]);//3x3 - } - } - for(int i = borderL; i < hei-borderL; i++ ) { - for(int j = borderL; j < wid-borderL; j++) { - labco->L[i][j] = tmL[i][j]; - } - } - for (int i=0; ia[i][j]; + float b = lab->b[i][j]; + varhue[i1][j1] = xatan2f(b, a); + varchro[i1][j1] = (sqrtf(a * a + b * b)) / 327.68f; - if(numtiles == 1) { - // reduce the varhue array to get faster access in following processing and reduce peak memory usage - float temphue[(tilewidth+1)/2] ALIGNED64; - for (int i=0; i<(tileheight+1)/2; i++) { - for (int j=0; j<(tilewidth+1)/2; j++) { - temphue[j]=varhue[i*2][j*2]; - } - delete [] varhue[i]; - varhue[i] = new float[(tilewidth+1)/2]; - memcpy(varhue[i],temphue, ((tilewidth+1)/2) * sizeof(float)); - } - for(int i=(tileheight+1)/2;iL[i1][j1] = lab->L[i][j]; + labco->a[i1][j1] = a; + labco->b[i1][j1] = b; + } + } + } - int datalen = labco->W * labco->H; + //to avoid artifacts in blue sky + if(params->wavelet.median) { + float** tmL; + int wid = labco->W; + int hei = labco->H; + int borderL = 1; + tmL = new float*[hei]; - int levwavL = levwav; - bool ref0=false; - if((cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f || cp.lev3s > 0.f) && cp.noiseena) ref0=true; + for (int i = 0; i < hei; i++) { + tmL[i] = new float[wid]; + } - // printf("LevwavL before: %d\n",levwavL); - if(cp.contrast == 0.f && cp.tonemap==false && cp.conres == 0.f && cp.conresH == 0.f && cp.val ==0 && !ref0 && params->wavelet.CLmethod=="all") { // no processing of residual L or edge=> we probably can reduce the number of levels - while(levwavL > 0 && cp.mul[levwavL-1] == 0.f) // cp.mul[level] == 0.f means no changes to level - levwavL--; - } - // printf("LevwavL after: %d\n",levwavL); - // if(cp.noiseena){ - if(levwavL < 4 ) levwavL=4;//to allow edge => I always allocate 3 (4) levels..because if user select wavelet it is to do something !! - // } - // else { - // if(levwavL < 3) levwavL=3;//to allow edge => I always allocate 3 (4) levels..because if user select wavelet it is to do something !! - // } - if(levwavL > 0) { - wavelet_decomposition* Ldecomp = new wavelet_decomposition (labco->data, labco->W, labco->H, levwavL, 1, skip, max(1,wavNestedLevels), DaubLen ); - if(!Ldecomp->memoryAllocationFailed) { - - float madL[8][3]; - bool memoryAllocationFailed = false; -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for schedule(dynamic) collapse(2) num_threads(wavNestedLevels) if(wavNestedLevels>1) -#endif - for (int lvl=0; lvl<4; lvl++) { - for (int dir=1; dir<4; dir++) { - int Wlvl_L = Ldecomp->level_W(lvl); - int Hlvl_L = Ldecomp->level_H(lvl); - - float ** WavCoeffs_L = Ldecomp->level_coeffs(lvl); - - madL[lvl][dir-1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L*Hlvl_L)); - } - } - int ind=0; - bool ref=false; - if((cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f || cp.lev3s > 0.f) && cp.noiseena) ref=true; - bool contr=false; - for(int f=0;f 0 || ref || contr) {//edge - Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL); - } - //init for edge and denoise - float vari[4]; - - vari[0]=8.f*SQR((cp.lev0n/125.0)*(1.0+ cp.lev0n/25.0)); - vari[1]=8.f*SQR((cp.lev1n/125.0)*(1.0+ cp.lev1n/25.0)); - vari[2]=8.f*SQR((cp.lev2n/125.0)*(1.0+ cp.lev2n/25.0)); - vari[3]=8.f*SQR((cp.lev3n/125.0)*(1.0+ cp.lev3n/25.0)); - int edge=1; - if((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) { - vari[0] = max(0.0001f,vari[0]); - vari[1] = max(0.0001f,vari[1]); - vari[2] = max(0.0001f,vari[2]); - vari[3] = max(0.0001f,vari[3]); - float* noisevarlum = NULL; // we need a dummy to pass it to WaveletDenoiseAllL - if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge))// - memoryAllocationFailed = true; - } - ind=1; - //Flat curve for Contrast=f(H) in levels - FlatCurve* ChCurve = NULL;//curve C=f(H) - bool Chutili = false; - ChCurve = new FlatCurve(params->wavelet.Chcurve); - if (!ChCurve || ChCurve->isIdentity()) { - if (ChCurve) { - delete ChCurve; - ChCurve = NULL; - } - } else - Chutili = true; - - - WaveletcontAllL(labco, varhue, varchro, *Ldecomp, cp, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, waOpacityCurveWL, ChCurve, Chutili); - if(cp.val > 0 || ref || contr || cp.diagcurv) {//edge - Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL); - } - WaveletcontAllLfinal(labco, varhue, varchro, *Ldecomp, cp, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveWL, ChCurve, Chutili); - //Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL); - - Ldecomp->reconstruct(labco->data, cp.strength); - } - delete Ldecomp; - } - //Flat curve for H=f(H) in residual image - FlatCurve* hhCurve = NULL;//curve H=f(H) - bool hhutili = false; - hhCurve = new FlatCurve(params->wavelet.hhcurve); - if (!hhCurve || hhCurve->isIdentity()) { - if (hhCurve) { - delete hhCurve; - hhCurve = NULL; - } - } else - hhutili = true; - - - if(!hhutili) {//always a or b - int levwava = levwav; - // printf("Levwava before: %d\n",levwava); - if(cp.chrores == 0.f && params->wavelet.CLmethod=="all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels - while(levwava > 0 && !cp.diag &&(((cp.CHmet==2 && (cp.chro == 0.f || cp.mul[levwava-1] == 0.f )) || (cp.CHmet!=2 && (levwava == 10 || (!cp.curv || (cp.curv && cp.mulC[levwava-1] == 0.f)))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava-1] == 0.f)) && ((levwava == 10 ||(cp.CHSLmet==1 && cp.mulC[levwava-1] == 0.f)))) { - levwava--; - } - } - //printf("Levwava after: %d\n",levwava); - if(levwava > 0) { - wavelet_decomposition* adecomp = new wavelet_decomposition (labco->data+datalen, labco->W, labco->H,levwava, 1, skip, max(1,wavNestedLevels), DaubLen ); - if(!adecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true); - adecomp->reconstruct(labco->data+datalen, cp.strength); - } - delete adecomp; - } - int levwavb = levwav; - //printf("Levwavb before: %d\n",levwavb); - if(cp.chrores == 0.f && params->wavelet.CLmethod=="all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels - while(levwavb > 0 && !cp.diag && (((cp.CHmet==2 && (cp.chro == 0.f || cp.mul[levwavb-1] == 0.f )) || (cp.CHmet!=2 && (levwavb == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavb-1] == 0.f)))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb-1] == 0.f)) && ((levwavb == 10 ||(cp.CHSLmet==1 && cp.mulC[levwavb-1] == 0.f)))) { - levwavb--; - } - } - // printf("Levwavb after: %d\n",levwavb); - if(levwavb > 0) { - wavelet_decomposition* bdecomp = new wavelet_decomposition (labco->data+2*datalen, labco->W, labco->H, levwavb, 1, skip, max(1,wavNestedLevels), DaubLen ); - if(!bdecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false); - bdecomp->reconstruct(labco->data+2*datalen, cp.strength); - } - delete bdecomp; - } - } else {// a and b - int levwavab = levwav; - // printf("Levwavab before: %d\n",levwavab); - if(cp.chrores == 0.f && !hhutili && params->wavelet.CLmethod=="all") { // no processing of residual ab => we probably can reduce the number of levels - while(levwavab > 0 && (((cp.CHmet==2 && (cp.chro == 0.f || cp.mul[levwavab-1] == 0.f )) || (cp.CHmet!=2 && (levwavab == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavab-1] == 0.f)))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab-1] == 0.f)) && ((levwavab == 10 ||(cp.CHSLmet==1 && cp.mulC[levwavab-1] == 0.f)))) { - levwavab--; - } - } - // printf("Levwavab after: %d\n",levwavab); - if(levwavab > 0) { - wavelet_decomposition* adecomp = new wavelet_decomposition (labco->data+datalen, labco->W, labco->H,levwavab, 1, skip, max(1,wavNestedLevels), DaubLen ); - wavelet_decomposition* bdecomp = new wavelet_decomposition (labco->data+2*datalen, labco->W, labco->H, levwavab, 1, skip, max(1,wavNestedLevels), DaubLen ); - if(!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true); - WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false); - WaveletAandBAllAB(labco, varhue, varchro, *adecomp, *bdecomp, cp, waOpacityCurveW, hhCurve, hhutili ); - - adecomp->reconstruct(labco->data+datalen, cp.strength); - bdecomp->reconstruct(labco->data+2*datalen, cp.strength); - - } - delete adecomp; - delete bdecomp; - } - } - if (hhCurve) - delete hhCurve; - - if(numtiles > 1 || (numtiles == 1 /*&& cp.avoi*/)) {//in all case since I add contrast curve - //calculate mask for feathering output tile overlaps - float Vmask[height+overlap] ALIGNED16; - float Hmask[width+overlap] ALIGNED16; - - if(numtiles > 1) { - for (int i=0; i0) Vmask[i] = mask; - if (tilebottom0) Hmask[i] = mask; - if (tilerighttoneCurve.hrenabled; + for(int i = borderL; i < hei - borderL; i++ ) { + for(int j = borderL; j < wid - borderL; j++) { + tmL[i][j] = labco->L[i][j]; + } + } #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for schedule(dynamic,16) num_threads(wavNestedLevels) if(wavNestedLevels>1) + #pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif - for (int i=tiletop; i - 2.5f) && (varchro[i][j] > 15.f && varchro[i][j] < 55.f) && labco->L[i][j] > 6000.f) { //blue sky + med3x3 ==> after for more effect use denoise + med3(labco->L[i][j] , labco->L[i - 1][j], labco->L[i + 1][j] , labco->L[i][j + 1], labco->L[i][j - 1], labco->L[i - 1][j - 1], labco->L[i - 1][j + 1], labco->L[i + 1][j - 1], labco->L[i + 1][j + 1], tmL[i][j]); //3x3 + } + } + } + + for(int i = borderL; i < hei - borderL; i++ ) { + for(int j = borderL; j < wid - borderL; j++) { + labco->L[i][j] = tmL[i][j]; + } + } + + for (int i = 0; i < hei; i++) { + delete [] tmL[i]; + } + + delete [] tmL; + // end blue sky + } + + if(numtiles == 1) { + // reduce the varhue array to get faster access in following processing and reduce peak memory usage + float temphue[(tilewidth + 1) / 2] ALIGNED64; + + for (int i = 0; i < (tileheight + 1) / 2; i++) { + for (int j = 0; j < (tilewidth + 1) / 2; j++) { + temphue[j] = varhue[i * 2][j * 2]; + } + + delete [] varhue[i]; + varhue[i] = new float[(tilewidth + 1) / 2]; + memcpy(varhue[i], temphue, ((tilewidth + 1) / 2) * sizeof(float)); + } + + for(int i = (tileheight + 1) / 2; i < tileheight; i++) { + delete [] varhue[i]; + varhue[i] = NULL; + } + } else { // reduce the varhue array to get faster access in following processing + for (int i = 0; i < (tileheight + 1) / 2; i++) { + for (int j = 0; j < (tilewidth + 1) / 2; j++) { + varhue[i][j] = varhue[i * 2][j * 2]; + } + } + } + + int datalen = labco->W * labco->H; + + int levwavL = levwav; + bool ref0 = false; + + if((cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f || cp.lev3s > 0.f) && cp.noiseena) { + ref0 = true; + } + + // printf("LevwavL before: %d\n",levwavL); + if(cp.contrast == 0.f && cp.tonemap == false && cp.conres == 0.f && cp.conresH == 0.f && cp.val == 0 && !ref0 && params->wavelet.CLmethod == "all") { // no processing of residual L or edge=> we probably can reduce the number of levels + while(levwavL > 0 && cp.mul[levwavL - 1] == 0.f) { // cp.mul[level] == 0.f means no changes to level + levwavL--; + } + } + + // printf("LevwavL after: %d\n",levwavL); + // if(cp.noiseena){ + if(levwavL < 4 ) { + levwavL = 4; //to allow edge => I always allocate 3 (4) levels..because if user select wavelet it is to do something !! + } + + // } + // else { + // if(levwavL < 3) levwavL=3;//to allow edge => I always allocate 3 (4) levels..because if user select wavelet it is to do something !! + // } + if(levwavL > 0) { + wavelet_decomposition* Ldecomp = new wavelet_decomposition (labco->data, labco->W, labco->H, levwavL, 1, skip, max(1, wavNestedLevels), DaubLen ); + + if(!Ldecomp->memoryAllocationFailed) { + + float madL[8][3]; + bool memoryAllocationFailed = false; +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for schedule(dynamic) collapse(2) num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + + for (int lvl = 0; lvl < 4; lvl++) { + for (int dir = 1; dir < 4; dir++) { + int Wlvl_L = Ldecomp->level_W(lvl); + int Hlvl_L = Ldecomp->level_H(lvl); + + float ** WavCoeffs_L = Ldecomp->level_coeffs(lvl); + + madL[lvl][dir - 1] = SQR(Mad(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); + } + } + + int ind = 0; + bool ref = false; + + if((cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f || cp.lev3s > 0.f) && cp.noiseena) { + ref = true; + } + + bool contr = false; + + for(int f = 0; f < levwavL; f++) { + if(cp.mul[f] != 0.f) { + contr = true; + } + } + + if(cp.val > 0 || ref || contr) {//edge + Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL); + } + + //init for edge and denoise + float vari[4]; + + vari[0] = 8.f * SQR((cp.lev0n / 125.0) * (1.0 + cp.lev0n / 25.0)); + vari[1] = 8.f * SQR((cp.lev1n / 125.0) * (1.0 + cp.lev1n / 25.0)); + vari[2] = 8.f * SQR((cp.lev2n / 125.0) * (1.0 + cp.lev2n / 25.0)); + vari[3] = 8.f * SQR((cp.lev3n / 125.0) * (1.0 + cp.lev3n / 25.0)); + int edge = 1; + + if((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) { + vari[0] = max(0.0001f, vari[0]); + vari[1] = max(0.0001f, vari[1]); + vari[2] = max(0.0001f, vari[2]); + vari[3] = max(0.0001f, vari[3]); + float* noisevarlum = NULL; // we need a dummy to pass it to WaveletDenoiseAllL + + if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge)) { // + memoryAllocationFailed = true; + } + } + + ind = 1; + //Flat curve for Contrast=f(H) in levels + FlatCurve* ChCurve = NULL;//curve C=f(H) + bool Chutili = false; + ChCurve = new FlatCurve(params->wavelet.Chcurve); + + if (!ChCurve || ChCurve->isIdentity()) { + if (ChCurve) { + delete ChCurve; + ChCurve = NULL; + } + } else { + Chutili = true; + } + + + WaveletcontAllL(labco, varhue, varchro, *Ldecomp, cp, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, waOpacityCurveWL, ChCurve, Chutili); + + if(cp.val > 0 || ref || contr || cp.diagcurv) {//edge + Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL); + } + + WaveletcontAllLfinal(labco, varhue, varchro, *Ldecomp, cp, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveWL, ChCurve, Chutili); + //Evaluate2(*Ldecomp, cp, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL); + + Ldecomp->reconstruct(labco->data, cp.strength); + } + + delete Ldecomp; + } + + //Flat curve for H=f(H) in residual image + FlatCurve* hhCurve = NULL;//curve H=f(H) + bool hhutili = false; + hhCurve = new FlatCurve(params->wavelet.hhcurve); + + if (!hhCurve || hhCurve->isIdentity()) { + if (hhCurve) { + delete hhCurve; + hhCurve = NULL; + } + } else { + hhutili = true; + } + + + if(!hhutili) {//always a or b + int levwava = levwav; + + // printf("Levwava before: %d\n",levwava); + if(cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels + while(levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f )) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || (cp.curv && cp.mulC[levwava - 1] == 0.f)))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) { + levwava--; + } + } + + //printf("Levwava after: %d\n",levwava); + if(levwava > 0) { + wavelet_decomposition* adecomp = new wavelet_decomposition (labco->data + datalen, labco->W, labco->H, levwava, 1, skip, max(1, wavNestedLevels), DaubLen ); + + if(!adecomp->memoryAllocationFailed) { + WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true); + adecomp->reconstruct(labco->data + datalen, cp.strength); + } + + delete adecomp; + } + + int levwavb = levwav; + + //printf("Levwavb before: %d\n",levwavb); + if(cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels + while(levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f )) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavb - 1] == 0.f)))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) { + levwavb--; + } + } + + // printf("Levwavb after: %d\n",levwavb); + if(levwavb > 0) { + wavelet_decomposition* bdecomp = new wavelet_decomposition (labco->data + 2 * datalen, labco->W, labco->H, levwavb, 1, skip, max(1, wavNestedLevels), DaubLen ); + + if(!bdecomp->memoryAllocationFailed) { + WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false); + bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength); + } + + delete bdecomp; + } + } else {// a and b + int levwavab = levwav; + + // printf("Levwavab before: %d\n",levwavab); + if(cp.chrores == 0.f && !hhutili && params->wavelet.CLmethod == "all") { // no processing of residual ab => we probably can reduce the number of levels + while(levwavab > 0 && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavab - 1] == 0.f )) || (cp.CHmet != 2 && (levwavab == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavab - 1] == 0.f)))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab - 1] == 0.f)) && ((levwavab == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavab - 1] == 0.f)))) { + levwavab--; + } + } + + // printf("Levwavab after: %d\n",levwavab); + if(levwavab > 0) { + wavelet_decomposition* adecomp = new wavelet_decomposition (labco->data + datalen, labco->W, labco->H, levwavab, 1, skip, max(1, wavNestedLevels), DaubLen ); + wavelet_decomposition* bdecomp = new wavelet_decomposition (labco->data + 2 * datalen, labco->W, labco->H, levwavab, 1, skip, max(1, wavNestedLevels), DaubLen ); + + if(!adecomp->memoryAllocationFailed && !bdecomp->memoryAllocationFailed) { + WaveletcontAllAB(labco, varhue, varchro, *adecomp, waOpacityCurveW, cp, true); + WaveletcontAllAB(labco, varhue, varchro, *bdecomp, waOpacityCurveW, cp, false); + WaveletAandBAllAB(labco, varhue, varchro, *adecomp, *bdecomp, cp, waOpacityCurveW, hhCurve, hhutili ); + + adecomp->reconstruct(labco->data + datalen, cp.strength); + bdecomp->reconstruct(labco->data + 2 * datalen, cp.strength); + + } + + delete adecomp; + delete bdecomp; + } + } + + if (hhCurve) { + delete hhCurve; + } + + if(numtiles > 1 || (numtiles == 1 /*&& cp.avoi*/)) {//in all case since I add contrast curve + //calculate mask for feathering output tile overlaps + float Vmask[height + overlap] ALIGNED16; + float Hmask[width + overlap] ALIGNED16; + + if(numtiles > 1) { + for (int i = 0; i < height; i++) { + Vmask[i] = 1; + } + + for (int j = 0; j < width; j++) { + Hmask[j] = 1; + } + + for (int i = 0; i < overlap; i++) { + float mask = SQR(sin((M_PI * i) / (2 * overlap))); + + if (tiletop > 0) { + Vmask[i] = mask; + } + + if (tilebottom < imheight) { + Vmask[height - i] = mask; + } + + if (tileleft > 0) { + Hmask[i] = mask; + } + + if (tileright < imwidth) { + Hmask[width - i] = mask; + } + } + } + + bool highlight = params->toneCurve.hrenabled; + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for schedule(dynamic,16) num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + + for (int i = tiletop; i < tilebottom; i++) { + int i1 = i - tiletop; + float L, a, b; #ifdef __SSE2__ - int rowWidth = tileright - tileleft; - float atan2Buffer[rowWidth] ALIGNED64; - float chprovBuffer[rowWidth] ALIGNED64; - float xBuffer[rowWidth] ALIGNED64; - float yBuffer[rowWidth] ALIGNED64; - if(cp.avoi) { - int col; - __m128 av,bv; - __m128 cv,yv,xv; - __m128 zerov = _mm_setzero_ps(); - __m128 onev = _mm_set1_ps(1.f); - __m128 c327d68v = _mm_set1_ps(327.68f); - vmask xyMask; - for(col = 0;cola[i1][col]); - bv = LVFU(labco->b[i1][col]); - _mm_store_ps(&atan2Buffer[col],xatan2f(bv,av)); + int rowWidth = tileright - tileleft; + float atan2Buffer[rowWidth] ALIGNED64; + float chprovBuffer[rowWidth] ALIGNED64; + float xBuffer[rowWidth] ALIGNED64; + float yBuffer[rowWidth] ALIGNED64; - cv = _mm_sqrt_ps(SQRV(av)+SQRV(bv)); - yv = av / cv; - xv = bv / cv; - xyMask = vmaskf_eq(zerov, cv); - yv = vself(xyMask, onev, yv); - xv = vself(xyMask, zerov, xv); - _mm_store_ps(&yBuffer[col],yv); - _mm_store_ps(&xBuffer[col],xv); - _mm_store_ps(&chprovBuffer[col], cv / c327d68v); + if(cp.avoi) { + int col; + __m128 av, bv; + __m128 cv, yv, xv; + __m128 zerov = _mm_setzero_ps(); + __m128 onev = _mm_set1_ps(1.f); + __m128 c327d68v = _mm_set1_ps(327.68f); + vmask xyMask; + + for(col = 0; col < rowWidth - 3; col += 4) { + av = LVFU(labco->a[i1][col]); + bv = LVFU(labco->b[i1][col]); + _mm_store_ps(&atan2Buffer[col], xatan2f(bv, av)); + + cv = _mm_sqrt_ps(SQRV(av) + SQRV(bv)); + yv = av / cv; + xv = bv / cv; + xyMask = vmaskf_eq(zerov, cv); + yv = vself(xyMask, onev, yv); + xv = vself(xyMask, zerov, xv); + _mm_store_ps(&yBuffer[col], yv); + _mm_store_ps(&xBuffer[col], xv); + _mm_store_ps(&chprovBuffer[col], cv / c327d68v); + + } + + for(; col < rowWidth; col++) { + float a = labco->a[i1][col]; + float b = labco->b[i1][col]; + atan2Buffer[col] = xatan2f(b, a); + float Chprov1 = sqrtf(SQR(a) + SQR(b)); + yBuffer[col] = (Chprov1 == 0.f) ? 1.f : a / Chprov1; + xBuffer[col] = (Chprov1 == 0.f) ? 0.f : b / Chprov1; + chprovBuffer[col] = Chprov1 / 327.68; + } + } - } - for(;cola[i1][col]; - float b = labco->b[i1][col]; - atan2Buffer[col] = xatan2f(b,a); - float Chprov1=sqrtf(SQR(a) + SQR(b)); - yBuffer[col] = (Chprov1 == 0.f) ? 1.f : a/Chprov1; - xBuffer[col] = (Chprov1 == 0.f) ? 0.f : b/Chprov1; - chprovBuffer[col] = Chprov1/327.68; - } - } #endif - for (int j=tileleft; ja[i1][j1]; - b = labco->b[i1][j1]; - float HH=xatan2f(b,a); - float Chprov1=sqrtf(SQR(a) + SQR(b)); - float2 sincosv; - sincosv.y = (Chprov1==0.0f) ? 1.f : a/(Chprov1); - sincosv.x = (Chprov1==0.0f) ? 0.f : b/(Chprov1); - Chprov1 /= 327.68f; + a = labco->a[i1][j1]; + b = labco->b[i1][j1]; + float HH = xatan2f(b, a); + float Chprov1 = sqrtf(SQR(a) + SQR(b)); + float2 sincosv; + sincosv.y = (Chprov1 == 0.0f) ? 1.f : a / (Chprov1); + sincosv.x = (Chprov1 == 0.0f) ? 0.f : b / (Chprov1); + Chprov1 /= 327.68f; #endif - L = labco->L[i1][j1]; - const float Lin=labco->L[i1][j1]; + L = labco->L[i1][j1]; + const float Lin = labco->L[i1][j1]; - if(wavclCurve && cp.finena) {labco->L[i1][j1] =(0.5f*Lin + 1.5f*wavclCurve[Lin])/2.f;}//apply contrast curve - L = labco->L[i1][j1]; + if(wavclCurve && cp.finena) { + labco->L[i1][j1] = (0.5f * Lin + 1.5f * wavclCurve[Lin]) / 2.f; //apply contrast curve + } - float Lprov1=L/327.68f; - float Lprov2 = Lold[i][j]/327.68f; - float memChprov=varchro[i1][j1]; - float R,G,B; + L = labco->L[i1][j1]; + + float Lprov1 = L / 327.68f; + float Lprov2 = Lold[i][j] / 327.68f; + float memChprov = varchro[i1][j1]; + float R, G, B; #ifdef _DEBUG - bool neg=false; - bool more_rgb=false; - Color::gamutLchonly(HH,sincosv, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); + bool neg = false; + bool more_rgb = false; + Color::gamutLchonly(HH, sincosv, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); #else - Color::gamutLchonly(HH,sincosv, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); + Color::gamutLchonly(HH, sincosv, Lprov1, Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); #endif - L=Lprov1*327.68f; - - a=327.68f*Chprov1*sincosv.y;//gamut - b=327.68f*Chprov1*sincosv.x;//gamut - float correctionHue=0.0f; // Munsell's correction - float correctlum=0.0f; - Lprov1=L/327.68f; - float Chprov=sqrtf(SQR(a)+ SQR(b))/327.68f; + L = Lprov1 * 327.68f; + + a = 327.68f * Chprov1 * sincosv.y; //gamut + b = 327.68f * Chprov1 * sincosv.x; //gamut + float correctionHue = 0.0f; // Munsell's correction + float correctlum = 0.0f; + Lprov1 = L / 327.68f; + float Chprov = sqrtf(SQR(a) + SQR(b)) / 327.68f; #ifdef _DEBUG - Color::AllMunsellLch(true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo); + Color::AllMunsellLch(true, Lprov1, Lprov2, HH, Chprov, memChprov, correctionHue, correctlum, MunsDebugInfo); #else - Color::AllMunsellLch(true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum); + Color::AllMunsellLch(true, Lprov1, Lprov2, HH, Chprov, memChprov, correctionHue, correctlum); #endif - if(correctionHue!=0.f || correctlum!=0.f) { // only calculate sin and cos if HH changed - if(fabs(correctionHue) < 0.015f) - HH+=correctlum; // correct only if correct Munsell chroma very little. - sincosv = xsincosf(HH+correctionHue); - } - - a=327.68f*Chprov*sincosv.y;// apply Munsell - b=327.68f*Chprov*sincosv.x;//aply Munsell - } else {//general case - L = labco->L[i1][j1]; - const float Lin=labco->L[i1][j1]; - - if(wavclCurve && cp.finena) {labco->L[i1][j1] = (0.5f*Lin + 1.5f*wavclCurve[Lin])/2.f;}//apply contrast curve - L = labco->L[i1][j1]; - a = labco->a[i1][j1]; - b = labco->b[i1][j1]; - } - if(numtiles > 1) { - float factor = Vmask[i1]*Hmask[j1]; - dsttmp->L[i][j]+= factor*L; - dsttmp->a[i][j]+= factor*a; - dsttmp->b[i][j]+= factor*b; - } else { - dsttmp->L[i][j] = L; - dsttmp->a[i][j] = a; - dsttmp->b[i][j] = b; - - } - } - } - } - if(LoldBuffer != NULL) { - delete [] LoldBuffer; - delete [] Lold; - } - if(numtiles>1) - delete labco; - } - } - for (int i=0; iL[i1][j1]; + const float Lin = labco->L[i1][j1]; + + if(wavclCurve && cp.finena) { + labco->L[i1][j1] = (0.5f * Lin + 1.5f * wavclCurve[Lin]) / 2.f; //apply contrast curve + } + + L = labco->L[i1][j1]; + a = labco->a[i1][j1]; + b = labco->b[i1][j1]; + } + + if(numtiles > 1) { + float factor = Vmask[i1] * Hmask[j1]; + dsttmp->L[i][j] += factor * L; + dsttmp->a[i][j] += factor * a; + dsttmp->b[i][j] += factor * b; + } else { + dsttmp->L[i][j] = L; + dsttmp->a[i][j] = a; + dsttmp->b[i][j] = b; + + } + } + } + } + + if(LoldBuffer != NULL) { + delete [] LoldBuffer; + delete [] Lold; + } + + if(numtiles > 1) { + delete labco; + } + } + } + + for (int i = 0; i < tileheight; i++) + if(varhue[i] != NULL) { + delete [] varhue[i]; + } + + delete [] varhue; + + for (int i = 0; i < tileheight; i++) { + delete [] varchro[i]; + } + + delete [] varchro; + + delete [] mean; + delete [] meanN; + delete [] sigma; + delete [] sigmaN; + + } #ifdef _RT_NESTED_OPENMP -omp_set_nested(oldNested); -#endif - if(numtiles > 1) { - dst->CopyFrom(dsttmp); - delete dsttmp; - } - - if (settings->verbose) { - t2e.set(); - printf("Wavelet performed in %d usec:\n", t2e.etime(t1e)); - } - + omp_set_nested(oldNested); +#endif + + if(numtiles > 1) { + dst->CopyFrom(dsttmp); + delete dsttmp; + } + + if (settings->verbose) { + t2e.set(); + printf("Wavelet performed in %d usec:\n", t2e.etime(t1e)); + } + }//end o @@ -1015,2004 +1330,2484 @@ omp_set_nested(oldNested); #undef offset #undef epsilon - void ImProcFunctions::Aver( float * RESTRICT DataList, int datalen, float &averagePlus, float &averageNeg, float &max, float &min) { +void ImProcFunctions::Aver( float * RESTRICT DataList, int datalen, float &averagePlus, float &averageNeg, float &max, float &min) +{ - //find absolute mean - int countP = 0, countN = 0; - float averaP = 0.f, averaN = 0.f; - - float thres = 5.f;//different fom zero to take into account only data large enough - max=0.f; - min=0.f; + //find absolute mean + int countP = 0, countN = 0; + float averaP = 0.f, averaN = 0.f; + + float thres = 5.f;//different fom zero to take into account only data large enough + max = 0.f; + min = 0.f; #ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) + #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif -{ - float lmax = 0.f, lmin = 0.f; + { + float lmax = 0.f, lmin = 0.f; #ifdef _RT_NESTED_OPENMP -#pragma omp for reduction(+:averaP,averaN,countP,countN) nowait + #pragma omp for reduction(+:averaP,averaN,countP,countN) nowait #endif - for(int i=0;i= thres) { - averaP += DataList[i]; - if(DataList[i]> lmax) - lmax = DataList[i]; - countP++; - } - else if(DataList[i] < -thres) { - averaN += DataList[i]; - if(DataList[i] < lmin) - lmin = DataList[i]; - countN++; - } - } + + for(int i = 0; i < datalen; i++) { + if(DataList[i] >= thres) { + averaP += DataList[i]; + + if(DataList[i] > lmax) { + lmax = DataList[i]; + } + + countP++; + } else if(DataList[i] < -thres) { + averaN += DataList[i]; + + if(DataList[i] < lmin) { + lmin = DataList[i]; + } + + countN++; + } + } + #ifdef _RT_NESTED_OPENMP -#pragma omp critical + #pragma omp critical #endif -{ - max = max > lmax ? max : lmax; - min = min < lmin ? min : lmin; -} + { + max = max > lmax ? max : lmax; + min = min < lmin ? min : lmin; + } + } + + averagePlus = averaP / countP; + averageNeg = averaN / countN; + } - averagePlus=averaP/countP; - averageNeg=averaN/countN; - - } - - - void ImProcFunctions::Sigma( float * RESTRICT DataList, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg) { - int countP = 0, countN = 0; - float variP = 0.f, variN = 0.f; - float thres = 5.f;//different fom zero to take into account only data large enough + +void ImProcFunctions::Sigma( float * RESTRICT DataList, int datalen, float averagePlus, float averageNeg, float &sigmaPlus, float &sigmaNeg) +{ + int countP = 0, countN = 0; + float variP = 0.f, variN = 0.f; + float thres = 5.f;//different fom zero to take into account only data large enough #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for reduction(+:variP,variN,countP,countN) num_threads(wavNestedLevels) if(wavNestedLevels>1) + #pragma omp parallel for reduction(+:variP,variN,countP,countN) num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif - for(int i=0;i= thres) { - variP += SQR(DataList[i] - averagePlus); - countP++; - } - else if(DataList[i] <= -thres) { - variN += SQR(DataList[i] - averageNeg); - countN++; - } - } - - sigmaPlus=sqrt(variP/countP); - sigmaNeg=sqrt(variN/countN); - } - - void ImProcFunctions::Evaluate2(wavelet_decomposition &WaveletCoeffs_L, - struct cont_params cp, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float madL[8][3]){ + for(int i = 0; i < datalen; i++) { + if(DataList[i] >= thres) { + variP += SQR(DataList[i] - averagePlus); + countP++; + } else if(DataList[i] <= -thres) { + variN += SQR(DataList[i] - averageNeg); + countN++; + } + } + + sigmaPlus = sqrt(variP / countP); + sigmaNeg = sqrt(variN / countN); + +} + +void ImProcFunctions::Evaluate2(wavelet_decomposition &WaveletCoeffs_L, + struct cont_params cp, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float madL[8][3]) +{ //StopWatch Stop1("Evaluate2"); - int maxlvl = WaveletCoeffs_L.maxlevel(); - for (int lvl=0; lvlwavelet.thres; - for (int dir=1; dir<4; dir++) { - Aver(WavCoeffs_L[dir], W_L*H_L, avLP[dir], avLN[dir], maxL[dir], minL[dir]); - Sigma(WavCoeffs_L[dir], W_L*H_L, avLP[dir], avLN[dir], sigP[dir], sigN[dir]); - // printf("dir=%d level=%d avLP=%f max=%f avLN=%f min=%f sigP=%f sigN=%f\n",dir,level,avLP[dir] ,maxL[dir], avLN[dir] ,minL[dir], sigP[dir], sigN[dir]); - } - AvL=0.f;AvN=0.f;SL=0.f;SN=0.f;maxLP=0.f;maxLN=0.f;MADL=0.f; - for (int dir=1; dir<4; dir++) { - AvL +=avLP[dir]; - AvN +=avLN[dir]; - SL +=sigP[dir]; - SN +=sigN[dir]; - maxLP += maxL[dir]; - maxLN += minL[dir]; - MADL += madL[dir]; - } - AvL/=3; - AvN/=3; - SL/=3; - SN/=3; - maxLP/=3; - maxLN/=3; - MADL/=3; - if(level < 4) MADL=sqrt(MADL);else MADL=0.f; - mean[level]=AvL; - meanN[level]=AvN; - sigma[level]=SL; - sigmaN[level]=SN; - MaxP[level]=maxLP; - MaxN[level]=maxLN; - // if(params->wavelet.CLmethod!="all") {//display only if user choose different from all - // printf("Ind=%d Level=%d MadL=%f AvL=%f AvN=%f SL=%f SN=%f maxP=%f maxN=%f\n",ind, level,MADL,mean[level],meanN[level],sigma[level],sigmaN[level],MaxP[level],MaxN[level]); - // } - } + float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); -float *ImProcFunctions::ContrastDR(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 *Contrast){ - int n=W_L*H_L; - if(Contrast == NULL) Contrast = new float[n]; - memcpy(Contrast, Source, n*sizeof(float)); -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for -#endif - for (int i=0; i ave) { - float kh = ah*(Source[i]*100.f)+bh; - prov=32768.f*Source[i]; - Contrast[i]=ave+kh*(Source[i]*32768.f-ave); - } else { - float kl = al*(Source[i]*100.f)+bl; - prov=32768.f*Source[i]; - Contrast[i]=ave-kl*(ave-Source[i]*32768.f); - } - float diflc=Contrast[i]-prov; - diflc*=factorx; - Contrast[i] = (prov + diflc)/32768.f; - //contrast between 0 and 1 - } -*/ - Contrast[i] = Source[i] ; + Eval2 (WavCoeffs_L, lvl, cp, Wlvl_L, Hlvl_L, skip_L, ind, mean, meanN, sigma, sigmaN, MaxP, MaxN, madL[lvl]); + } - } - return Contrast; +} +void ImProcFunctions::Eval2 (float ** WavCoeffs_L, int level, struct cont_params cp, + int W_L, int H_L, int skip_L, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float *madL) +{ + const float eps = 0.01f; + + float ava[4], avb[4], avLP[4], avLN[4]; + float maxL[4], minL[4], maxa[4], maxb[4]; + float sigP[4], sigN[4]; + float AvL, AvN, SL, SN, maxLP, maxLN, MADL; + float madLlev[10]; + float thr = params->wavelet.thres; + + for (int dir = 1; dir < 4; dir++) { + Aver(WavCoeffs_L[dir], W_L * H_L, avLP[dir], avLN[dir], maxL[dir], minL[dir]); + Sigma(WavCoeffs_L[dir], W_L * H_L, avLP[dir], avLN[dir], sigP[dir], sigN[dir]); + // printf("dir=%d level=%d avLP=%f max=%f avLN=%f min=%f sigP=%f sigN=%f\n",dir,level,avLP[dir] ,maxL[dir], avLN[dir] ,minL[dir], sigP[dir], sigN[dir]); + } + + AvL = 0.f; + AvN = 0.f; + SL = 0.f; + SN = 0.f; + maxLP = 0.f; + maxLN = 0.f; + MADL = 0.f; + + for (int dir = 1; dir < 4; dir++) { + AvL += avLP[dir]; + AvN += avLN[dir]; + SL += sigP[dir]; + SN += sigN[dir]; + maxLP += maxL[dir]; + maxLN += minL[dir]; + MADL += madL[dir]; + } + + AvL /= 3; + AvN /= 3; + SL /= 3; + SN /= 3; + maxLP /= 3; + maxLN /= 3; + MADL /= 3; + + if(level < 4) { + MADL = sqrt(MADL); + } else { + MADL = 0.f; + } + + mean[level] = AvL; + meanN[level] = AvN; + sigma[level] = SL; + sigmaN[level] = SN; + MaxP[level] = maxLP; + MaxN[level] = maxLN; + // if(params->wavelet.CLmethod!="all") {//display only if user choose different from all + // printf("Ind=%d Level=%d MadL=%f AvL=%f AvN=%f SL=%f SN=%f maxP=%f maxN=%f\n",ind, level,MADL,mean[level],meanN[level],sigma[level],sigmaN[level],MaxP[level],MaxN[level]); + // } } -SSEFUNCTION float *ImProcFunctions::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){ +float *ImProcFunctions::ContrastDR(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 *Contrast) +{ + int n = W_L * H_L; + + if(Contrast == NULL) { + Contrast = new float[n]; + } + + memcpy(Contrast, Source, n * sizeof(float)); +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < W_L * H_L; i++) { //contrast + /* + //source between 0 and 1 + if(Source[i] < 1.f) { + float prov; + if( 32768.f*Source[i]> ave) { + float kh = ah*(Source[i]*100.f)+bh; + prov=32768.f*Source[i]; + Contrast[i]=ave+kh*(Source[i]*32768.f-ave); + } else { + float kl = al*(Source[i]*100.f)+bl; + prov=32768.f*Source[i]; + Contrast[i]=ave-kl*(ave-Source[i]*32768.f); + } + float diflc=Contrast[i]-prov; + diflc*=factorx; + Contrast[i] = (prov + diflc)/32768.f; + //contrast between 0 and 1 + } + */ + Contrast[i] = Source[i] ; + + } + + return Contrast; +} + +SSEFUNCTION float *ImProcFunctions::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) +{ + + const float eps = 0.000001f; + int n = W_L * H_L; - const float eps = 0.000001f; - int n=W_L*H_L; - #ifdef __SSE2__ #ifdef _RT_NESTED_OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - __m128 epsv = _mm_set1_ps( eps ); + { + __m128 epsv = _mm_set1_ps( eps ); #ifdef _RT_NESTED_OPENMP -#pragma omp for + #pragma omp for #endif - for(int ii = 0; ii < n-3; ii+=4) - _mm_storeu_ps( &Source[ii], xlogf(LVFU(Source[ii]) + epsv)); -} - for(int ii = n-(n%4); ii < n; ii++) - Source[ii] = xlogf(Source[ii] + eps); + + for(int ii = 0; ii < n - 3; ii += 4) { + _mm_storeu_ps( &Source[ii], xlogf(LVFU(Source[ii]) + epsv)); + } + } + + for(int ii = n - (n % 4); ii < n; ii++) { + Source[ii] = xlogf(Source[ii] + eps); + } #else #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for + #pragma omp parallel for #endif - for(int ii = 0; ii < n; ii++) - Source[ii] = xlogf(Source[ii] + eps); + + for(int ii = 0; ii < n; ii++) { + Source[ii] = xlogf(Source[ii] + eps); + } + #endif - - float *ucr =ContrastDR(Source, skip, cp, W_L, H_L, Compression,DetailBoost,max0, min0, ave, ah, bh, al, bl, factorx); - if(Compressed == NULL) Compressed = ucr; - float temp; - if(DetailBoost>0.f && DetailBoost < 0.05f ) { - float betemp=expf(-(2.f-DetailBoost+0.694f))-1.f;//0.694 = log(2) - temp = 1.2f*xlogf( -betemp); - temp /= 20.f; - } - else if(DetailBoost>=0.05f && DetailBoost < 0.25f ) { - float betemp=expf(-(2.f-DetailBoost+0.694f))-1.f;//0.694 = log(2) - temp = 1.2f*xlogf( -betemp); - temp /= (-75.f*DetailBoost+23.75f); - } - else if(DetailBoost>=0.25f) { - float betemp=expf(-(2.f-DetailBoost+0.694f))-1.f;//0.694 = log(2) - temp = 1.2f*xlogf( -betemp); - temp /= (-2.f*DetailBoost + 5.5f); - } - - else temp= (Compression - 1.0f)/20.f; -// printf("temp=%f \n", temp); - - + + float *ucr = ContrastDR(Source, skip, cp, W_L, H_L, Compression, DetailBoost, max0, min0, ave, ah, bh, al, bl, factorx); + + if(Compressed == NULL) { + Compressed = ucr; + } + + float temp; + + if(DetailBoost > 0.f && DetailBoost < 0.05f ) { + float betemp = expf(-(2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + temp = 1.2f * xlogf( -betemp); + temp /= 20.f; + } else if(DetailBoost >= 0.05f && DetailBoost < 0.25f ) { + float betemp = expf(-(2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + temp = 1.2f * xlogf( -betemp); + temp /= (-75.f * DetailBoost + 23.75f); + } else if(DetailBoost >= 0.25f) { + float betemp = expf(-(2.f - DetailBoost + 0.694f)) - 1.f; //0.694 = log(2) + temp = 1.2f * xlogf( -betemp); + temp /= (-2.f * DetailBoost + 5.5f); + } + + else { + temp = (Compression - 1.0f) / 20.f; + } + +// printf("temp=%f \n", temp); + + #ifdef __SSE2__ #ifdef _RT_NESTED_OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - __m128 cev, uev, sourcev; - __m128 epsv = _mm_set1_ps( eps ); - __m128 DetailBoostv = _mm_set1_ps( DetailBoost ); - __m128 tempv = _mm_set1_ps( temp ); + { + __m128 cev, uev, sourcev; + __m128 epsv = _mm_set1_ps( eps ); + __m128 DetailBoostv = _mm_set1_ps( DetailBoost ); + __m128 tempv = _mm_set1_ps( temp ); #ifdef _RT_NESTED_OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < n-3; i+=4){ - cev = xexpf(LVFU(Source[i]) + LVFU(ucr[i])*(tempv)) - epsv; - uev = xexpf(LVFU(ucr[i])) - epsv; - sourcev = xexpf(LVFU(Source[i])) - epsv; - _mm_storeu_ps( &Source[i], sourcev); - _mm_storeu_ps( &Compressed[i], cev + DetailBoostv * (sourcev - uev) ); - } -} - for(int i=n-(n%4); i < n; i++){ - float ce = xexpf(Source[i] + ucr[i]*(temp)) - eps; - float ue = xexpf(ucr[i]) - eps; - Source[i] = xexpf(Source[i]) - eps; - Compressed[i] = ce + DetailBoost*(Source[i] - ue); - } - + + for(int i = 0; i < n - 3; i += 4) { + cev = xexpf(LVFU(Source[i]) + LVFU(ucr[i]) * (tempv)) - epsv; + uev = xexpf(LVFU(ucr[i])) - epsv; + sourcev = xexpf(LVFU(Source[i])) - epsv; + _mm_storeu_ps( &Source[i], sourcev); + _mm_storeu_ps( &Compressed[i], cev + DetailBoostv * (sourcev - uev) ); + } + } + + for(int i = n - (n % 4); i < n; i++) { + float ce = xexpf(Source[i] + ucr[i] * (temp)) - eps; + float ue = xexpf(ucr[i]) - eps; + Source[i] = xexpf(Source[i]) - eps; + Compressed[i] = ce + DetailBoost * (Source[i] - ue); + } + #else #ifdef _RT_NESTED_OPENMP -#pragma omp parallel for -#endif - for(int i = 0; i < n; i++){ - float ce = xexpf(Source[i] + ucr[i]*(temp)) - eps; - float ue = xexpf(ucr[i]) - eps; - Source[i] = xexpf(Source[i]) - eps; - Compressed[i] = ce + DetailBoost*(Source[i] - ue); - } + #pragma omp parallel for #endif - if(Compressed != ucr) delete[] ucr; - return Compressed; - + for(int i = 0; i < n; i++) { + float ce = xexpf(Source[i] + ucr[i] * (temp)) - eps; + float ue = xexpf(ucr[i]) - eps; + Source[i] = xexpf(Source[i]) - eps; + Compressed[i] = ce + DetailBoost * (Source[i] - ue); + } -} - -void ImProcFunctions::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) { - float stren=cp.tmstrength; - float gamm=params->wavelet.gamma; - cp.TMmeth=2;//default after testing - if(cp.TMmeth ==1) {min0 = 0.0f;max0=32768.f;} - else if (cp.TMmeth ==2) {min0 = 0.0f;} -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for #endif - for(int i = 0; i < W_L*H_L; i++) - { WavCoeffs_L0[i]= (WavCoeffs_L0[i] - min0)/max0; - WavCoeffs_L0[i]*=gamm; - } - - float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. - float DetailBoost = stren; - if(stren < 0.0f) DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + + if(Compressed != ucr) { + delete[] ucr; + } + + return Compressed; - CompressDR(WavCoeffs_L0, skip, cp, W_L, H_L, Compression,DetailBoost,max0, min0, ave, ah, bh, al, bl, factorx, WavCoeffs_L0); - - -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for // removed schedule(dynamic,10) -#endif - for(int ii = 0; ii < W_L*H_L; ii++) - WavCoeffs_L0[ii] = WavCoeffs_L0[ii]*max0*(1.f/gamm) + min0; - } - - - - - void ImProcFunctions::EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params cp, int W_L, int H_L, float max0, float min0) { - - - float stren=cp.tmstrength; - float edgest=params->epd.edgeStopping; - float sca=params->epd.scale; - float gamm=params->wavelet.gamma; - float rew=params->epd.reweightingIterates; - EdgePreservingDecomposition epd2 = EdgePreservingDecomposition(W_L, H_L); - cp.TMmeth=2;//default after testing - if(cp.TMmeth ==1) {min0 = 0.0f;max0=32768.f;} - else if (cp.TMmeth ==2) {min0 = 0.0f;} - // max0=32768.f; -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for -#endif - for(int i = 0; i < W_L*H_L; i++) - { WavCoeffs_L0[i]= (WavCoeffs_L0[i] - min0)/max0; - WavCoeffs_L0[i]*=gamm; - } - - float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. - float DetailBoost = stren; - if(stren < 0.0f) DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. - - //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. - if(Iterates == 0) Iterates = (unsigned int)(edgest*15.0f); - - - epd2.CompressDynamicRange(WavCoeffs_L0, (float)sca/skip, edgest, Compression, DetailBoost, Iterates, rew, WavCoeffs_L0); - - //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel for // removed schedule(dynamic,10) -#endif - for(int ii = 0; ii < W_L*H_L; ii++) - WavCoeffs_L0[ii] = WavCoeffs_L0[ii]*max0*(1.f/gamm) + min0; - } - -void ImProcFunctions::WaveletcontAllLfinal(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L, - struct cont_params &cp, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili){ - - int maxlvl = WaveletCoeffs_L.maxlevel(); - int W_L = WaveletCoeffs_L.level_W(0); - int H_L = WaveletCoeffs_L.level_H(0); - float * WavCoeffs_L0 = WaveletCoeffs_L.coeff0; - - -#ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) -#endif - for (int dir=1; dir<4; dir++) { - for (int lvl=0; lvl1) -#endif - for (int i=0; i1) -#endif -{ - float lminL = FLT_MAX; - float lmaxL = 0.f; - -#ifdef _RT_NESTED_OPENMP -#pragma omp for -#endif - for(int i = 0; i < W_L*H_L; i++) { - if(WavCoeffs_L0[i] < lminL) lminL = WavCoeffs_L0[i]; - if(WavCoeffs_L0[i] > lmaxL) lmaxL = WavCoeffs_L0[i]; - - } -#ifdef _RT_NESTED_OPENMP -#pragma omp critical -#endif - { if(lminL < min0) min0 = lminL; - if(lmaxL > max0) max0 = lmaxL; - } - } - - } - - // printf("MAXmax0=%f MINmin0=%f\n",max0,min0); - + +void ImProcFunctions::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) +{ + float stren = cp.tmstrength; + float gamm = params->wavelet.gamma; + cp.TMmeth = 2; //default after testing + + if(cp.TMmeth == 1) { + min0 = 0.0f; + max0 = 32768.f; + } else if (cp.TMmeth == 2) { + min0 = 0.0f; + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L0[i] = (WavCoeffs_L0[i] - min0) / max0; + WavCoeffs_L0[i] *= gamm; + } + + float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. + float DetailBoost = stren; + + if(stren < 0.0f) { + DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + } + + + CompressDR(WavCoeffs_L0, skip, cp, W_L, H_L, Compression, DetailBoost, max0, min0, ave, ah, bh, al, bl, factorx, WavCoeffs_L0); + + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for // removed schedule(dynamic,10) +#endif + + for(int ii = 0; ii < W_L * H_L; ii++) { + WavCoeffs_L0[ii] = WavCoeffs_L0[ii] * max0 * (1.f / gamm) + min0; + } +} + + + + +void ImProcFunctions::EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params cp, int W_L, int H_L, float max0, float min0) +{ + + + float stren = cp.tmstrength; + float edgest = params->epd.edgeStopping; + float sca = params->epd.scale; + float gamm = params->wavelet.gamma; + float rew = params->epd.reweightingIterates; + EdgePreservingDecomposition epd2 = EdgePreservingDecomposition(W_L, H_L); + cp.TMmeth = 2; //default after testing + + if(cp.TMmeth == 1) { + min0 = 0.0f; + max0 = 32768.f; + } else if (cp.TMmeth == 2) { + min0 = 0.0f; + } + + // max0=32768.f; +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for +#endif + + for(int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L0[i] = (WavCoeffs_L0[i] - min0) / max0; + WavCoeffs_L0[i] *= gamm; + } + + float Compression = expf(-stren); //This modification turns numbers symmetric around 0 into exponents. + float DetailBoost = stren; + + if(stren < 0.0f) { + DetailBoost = 0.0f; //Go with effect of exponent only if uncompressing. + } + + //Auto select number of iterates. Note that p->EdgeStopping = 0 makes a Gaussian blur. + if(Iterates == 0) { + Iterates = (unsigned int)(edgest * 15.0f); + } + + + epd2.CompressDynamicRange(WavCoeffs_L0, (float)sca / skip, edgest, Compression, DetailBoost, Iterates, rew, WavCoeffs_L0); + + //Restore past range, also desaturate a bit per Mantiuk's Color correction for tone mapping. +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for // removed schedule(dynamic,10) +#endif + + for(int ii = 0; ii < W_L * H_L; ii++) { + WavCoeffs_L0[ii] = WavCoeffs_L0[ii] * max0 * (1.f / gamm) + min0; + } +} + +void ImProcFunctions::WaveletcontAllLfinal(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L, + struct cont_params &cp, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili) +{ + + int maxlvl = WaveletCoeffs_L.maxlevel(); + int W_L = WaveletCoeffs_L.level_W(0); + int H_L = WaveletCoeffs_L.level_H(0); + float * WavCoeffs_L0 = WaveletCoeffs_L.coeff0; + + +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int dir = 1; dir < 4; dir++) { + for (int lvl = 0; lvl < maxlvl; lvl++) { + + int Wlvl_L = WaveletCoeffs_L.level_W(lvl); + int Hlvl_L = WaveletCoeffs_L.level_H(lvl); + + float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); + + finalContAllL (maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveWL, ChCurve, Chutili); + + + } + } + +} + + +void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L, + struct cont_params &cp, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili) +{ + //StopWatch Stop1("WaveletcontAllL"); + int maxlvl = WaveletCoeffs_L.maxlevel(); + int W_L = WaveletCoeffs_L.level_W(0); + int H_L = WaveletCoeffs_L.level_H(0); + float * WavCoeffs_L0 = WaveletCoeffs_L.coeff0; + + float maxh = 2.5f; //amplification contrast above mean + float maxl = 2.5f; //reduction contrast under mean + float contrast = cp.contrast; + float multL = (float)contrast * (maxl - 1.f) / 100.f + 1.f; + float multH = (float) contrast * (maxh - 1.f) / 100.f + 1.f; + double avedbl = 0.f; // use double precision for big summations + float max0 = 0.f; + float min0 = FLT_MAX; + + if(contrast != 0.f || cp.tonemap && cp.resena) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel for reduction(+:avedbl) num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + + for (int i = 0; i < W_L * H_L; i++) { + avedbl += WavCoeffs_L0[i]; + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + { + float lminL = FLT_MAX; + float lmaxL = 0.f; + +#ifdef _RT_NESTED_OPENMP + #pragma omp for +#endif + + for(int i = 0; i < W_L * H_L; i++) { + if(WavCoeffs_L0[i] < lminL) { + lminL = WavCoeffs_L0[i]; + } + + if(WavCoeffs_L0[i] > lmaxL) { + lmaxL = WavCoeffs_L0[i]; + } + + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp critical +#endif + { + if(lminL < min0) { + min0 = lminL; + } + + if(lmaxL > max0) { + max0 = lmaxL; + } + } + + } + + } + + // printf("MAXmax0=%f MINmin0=%f\n",max0,min0); + //tone mapping -if(cp.tonemap && cp.contmet==2 && cp.resena) { - //iterate = 5 - EPDToneMapResid(WavCoeffs_L0, 5, skip, cp, W_L, H_L, max0, min0); - -} + if(cp.tonemap && cp.contmet == 2 && cp.resena) { + //iterate = 5 + EPDToneMapResid(WavCoeffs_L0, 5, skip, cp, W_L, H_L, max0, min0); + + } + //end tonemapping - - - max0/=327.68f; - min0/=327.68f; - float ave = avedbl / (double)(W_L*H_L); - float av=ave/327.68f; - float ah=(multH-1.f)/(av-max0);// - float bh=1.f-max0*ah; - float al=(multL-1.f)/(av-min0); - float bl=1.f-min0*al; - float factorx=1.f; -// float *koeLi[9]; -// float maxkoeLi[9]; - float *koeLi[12]; - float maxkoeLi[12]; - - float *koeLibuffer = NULL; - bool lipschitz =false; - lipschitz=true; - if(lipschitz==true) { - for(int y=0;y<12;y++) maxkoeLi[y]=0.f;//9 - koeLibuffer = new float[12*H_L*W_L];//12 - for (int i=0; i<12; i++) {//9 - koeLi[i] = &koeLibuffer[i*W_L*H_L]; - } - - for(int j=0;j<12;j++)//9 - for (int i=0; i1) + #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif -{ - if(contrast != 0.f && cp.resena) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step - { + { + if(contrast != 0.f && cp.resena) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step + { #ifdef _RT_NESTED_OPENMP -#pragma omp for -#endif - for (int i=0; i ave) { - float kh = ah*(WavCoeffs_L0[i]/327.68f)+bh; - prov=WavCoeffs_L0[i]; - WavCoeffs_L0[i]=ave+kh*(WavCoeffs_L0[i]-ave); - } else { - float kl = al*(WavCoeffs_L0[i]/327.68f)+bl; - prov=WavCoeffs_L0[i]; - WavCoeffs_L0[i]=ave-kl*(ave-WavCoeffs_L0[i]); - } - float diflc=WavCoeffs_L0[i]-prov; - diflc*=factorx; - WavCoeffs_L0[i] = prov + diflc; - } - } - } - } - -if(cp.tonemap && cp.contmet==1 && cp.resena) { - float maxp=max0*256.f; - float minp=min0*256.f; -#ifdef _RT_NESTED_OPENMP -#pragma omp single + #pragma omp for #endif - ContrastResid(WavCoeffs_L0, 5, skip, cp, W_L, H_L, maxp, minp, ave, ah, bh, al, bl, factorx ); + + for (int i = 0; i < W_L * H_L; i++) { //contrast + if(WavCoeffs_L0[i] < 32768.f) { + float prov; + + if( WavCoeffs_L0[i] > ave) { + float kh = ah * (WavCoeffs_L0[i] / 327.68f) + bh; + prov = WavCoeffs_L0[i]; + WavCoeffs_L0[i] = ave + kh * (WavCoeffs_L0[i] - ave); + } else { + float kl = al * (WavCoeffs_L0[i] / 327.68f) + bl; + prov = WavCoeffs_L0[i]; + WavCoeffs_L0[i] = ave - kl * (ave - WavCoeffs_L0[i]); + } + + float diflc = WavCoeffs_L0[i] - prov; + diflc *= factorx; + WavCoeffs_L0[i] = prov + diflc; + } + } + } + } + + if(cp.tonemap && cp.contmet == 1 && cp.resena) { + float maxp = max0 * 256.f; + float minp = min0 * 256.f; +#ifdef _RT_NESTED_OPENMP + #pragma omp single +#endif + ContrastResid(WavCoeffs_L0, 5, skip, cp, W_L, H_L, maxp, minp, ave, ah, bh, al, bl, factorx ); + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp barrier +#endif + + if((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step +#ifdef _RT_NESTED_OPENMP + #pragma omp for nowait +#endif + + for (int i = 0; i < W_L * H_L; i++) { + float LL = WavCoeffs_L0[i]; + float LL100 = LL / 327.68f; + float tran = 5.f;//transition + //shadow + float alp = 3.f; //increase contrast sahdow in lowlights between 1 and ?? + + if(cp.th > (100.f - tran)) { + tran = 100.f - cp.th; + } + + if(LL100 < cp.th) { + float aalp = (1.f - alp) / cp.th; //no changes for LL100 = cp.th + float kk = aalp * LL100 + alp; + WavCoeffs_L0[i] *= (1.f + kk * cp.conres / 200.f); + } else if(LL100 < cp.th + tran) { + float ath = -cp.conres / tran; + float bth = cp.conres - ath * cp.th; + WavCoeffs_L0[i] *= (1.f + (LL100 * ath + bth) / 200.f); + } + + //highlight + tran = 5.f; + + if(cp.thH < (tran)) { + tran = cp.thH; + } + + if(LL100 > cp.thH) { + WavCoeffs_L0[i] *= (1.f + cp.conresH / 200.f); + } else if(LL100 > (cp.thH - tran)) { + float athH = cp.conresH / tran; + float bthH = cp.conresH - athH * cp.thH; + WavCoeffs_L0[i] *= (1.f + (LL100 * athH + bthH) / 200.f); + } + } + } + + //enabled Lipschitz..replace simple by complex edge detection + // I found this concept on the web (doctoral thesis on medical Imaging) + // I was inspired by the principle of Canny and Lipschitz (continuity and derivability) + // I adapted the principle but have profoundly changed the algorithm + // One can 1) change all parameters and found good parameters; + //one can also chnage in calckoe + float edd = settings->ed_detec; + float eddlow = settings->ed_low; //5 to 40 + // float eddlipinfl=settings->ed_lipinfl; + // float eddlipampl=settings->ed_lipampl; + float eddlipinfl = 0.005f * cp.edgsens + 0.4f; + float eddlipampl = 1.f + cp.edgampl / 50.f; + // float eddlow=5.f + cp.edgampl/2.f;//settings->ed_low;//5 to 40 + + + if(cp.detectedge && lipschitz == true) { //enabled Lipschitz control...more memory..more time... + float *tmCBuffer = new float[H_L * W_L]; + float *tmC[H_L]; + + for (int i = 0; i < H_L; i++) { + tmC[i] = &tmCBuffer[i * W_L]; + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int lvl = 0; lvl < 4; lvl++) { + for (int dir = 1; dir < 4; dir++) { + int W_L = WaveletCoeffs_L.level_W(lvl); + int H_L = WaveletCoeffs_L.level_H(lvl); + + float ** WavCoeffs_LL = WaveletCoeffs_L.level_coeffs(lvl); + calckoe(WavCoeffs_LL, cp, koeLi, lvl , dir, W_L, H_L, edd, maxkoeLi, tmC); + // return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag + } + } + + delete [] tmCBuffer; + + float aamp = 1.f + cp.eddetthrHi / 100.f; + + for (int lvl = 0; lvl < 4; lvl++) { +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int i = 1; i < H_L - 1; i++) { + for (int j = 1; j < W_L - 1; j++) { + //treatment of koeLi and maxkoeLi + float interm = 0.f; + + if(cp.lip3 && cp.lipp) { + // comparaison betwwen pixel and neighbours + float kneigh, somm; + + if(cp.neigh == 0) { + kneigh = 38.f; + somm = 50.f; + } else if(cp.neigh == 1) { + kneigh = 28.f; + somm = 40.f; + } + + for (int dir = 1; dir < 4; dir++) { //neighbours proxi + koeLi[lvl * 3 + dir - 1][i * W_L + j] = (kneigh * koeLi[lvl * 3 + dir - 1][i * W_L + j] + 2.f * koeLi[lvl * 3 + dir - 1][(i - 1) * W_L + j] + 2.f * koeLi[lvl * 3 + dir - 1][(i + 1) * W_L + j] + + 2.f * koeLi[lvl * 3 + dir - 1][i * W_L + j + 1] + 2.f * koeLi[lvl * 3 + dir - 1][i * W_L + j - 1] + koeLi[lvl * 3 + dir - 1][(i - 1) * W_L + j - 1] + + koeLi[lvl * 3 + dir - 1][(i - 1) * W_L + j + 1] + koeLi[lvl * 3 + dir - 1][(i + 1) * W_L + j - 1] + koeLi[lvl * 3 + dir - 1][(i + 1) * W_L + j + 1]) / somm; + } + } + + for (int dir = 1; dir < 4; dir++) { + //here I evaluate combinaison of vert / diag / horiz...we are with multiplicators of the signal + interm += SQR(koeLi[lvl * 3 + dir - 1][i * W_L + j]); + } + + interm = sqrt(interm); + +// interm /= 1.732f;//interm = pseudo variance koeLi + interm *= 0.57736721f; + float kampli = 1.f; + float eps = 0.0001f; + // I think this double ratio (alph, beta) is better than arctg + + float alph = koeLi[lvl * 3][i * W_L + j] / (koeLi[lvl * 3 + 1][i * W_L + j] + eps); //ratio between horizontal and vertical + float beta = koeLi[lvl * 3 + 2][i * W_L + j] / (koeLi[lvl * 3 + 1][i * W_L + j] + eps); //ratio between diagonal and horizontal + + float alipinfl = (eddlipampl - 1.f) / (1.f - eddlipinfl); + float blipinfl = eddlipampl - alipinfl; + + //alph evaluate the direction of the gradient regularity Lipschitz + // if = 1 we are on an edge + // if 0 we are not + // we can change and use log..or Arctg but why ?? we can change if need ... + //Liamp=1 for eddlipinfl + //liamp > 1 for alp >eddlipinfl and alph < 1 + //Liamp < 1 for alp < eddlipinfl and alph > 0 + if(alph > 1.f) { + alph = 1.f / alph; + } + + if(beta > 1.f) { + beta = 1.f / beta; + } + + //take into account diagonal + //if in same value OK + //if not no edge or reduction + float bet = 1.f; + + //if(cp.lip3) {//enhance algorithm + if(alph > eddlipinfl && beta < 0.85f * eddlipinfl) { //0.85 arbitrary value ==> eliminate from edge if H V D too different + bet = beta; + } + + //} + float AmpLip = 1.f; + + if(alph > eddlipinfl) { + AmpLip = alipinfl * alph + blipinfl; //If beta low reduce kampli + kampli = SQR(bet) * AmpLip * aamp; + } else { + AmpLip = (1.f / eddlipinfl) * SQR(SQR(alph * bet)); //Strong Reduce if beta low + kampli = AmpLip / aamp; + } + + // comparaison betwwen pixel and neighbours to do ==> I think 3 dir above is better + /* if(cp.lip3){ + koeLi[lvl*3][i*W_L + j] = (koeLi[lvl*3][i*W_L + j] + koeLi[lvl*3][(i-1)*W_L + j] + koeLi[lvl*3][(i+1)*W_L + j] + + koeLi[lvl*3][i*W_L + j+1] + koeLi[lvl*3][i*W_L + j-1] + koeLi[lvl*3][(i-1)*W_L + j-1] + + koeLi[lvl*3][(i-1)*W_L + j+1] +koeLi[lvl*3][(i+1)*W_L + j-1] +koeLi[lvl*3][(i+1)*W_L + j+1])/9.f; + } + */ + // apply to each direction Wavelet level : horizontal / vertiacle / diagonal + //interm += SQR(koeLi[lvl*3 + dir-1][i*W_L + j]); + + interm *= kampli; + + if(interm < cp.eddetthr / eddlow) { + interm = 0.01f; //eliminate too low values + } + + //we can change this part of algo==> not equal but ponderate + koeLi[lvl * 3][i * W_L + j] = koeLi[lvl * 3 + 1][i * W_L + j] = koeLi[lvl * 3 + 2][i * W_L + j] = interm; //new value + //here KoeLi contains values where gradient is high and coef high, and eliminate low values... + } + } + } + + // end + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int dir = 1; dir < 4; dir++) { + for (int lvl = 0; lvl < maxlvl; lvl++) { + + int Wlvl_L = WaveletCoeffs_L.level_W(lvl); + int Hlvl_L = WaveletCoeffs_L.level_H(lvl); + + float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); + + ContAllL (koeLi, maxkoeLi, lipschitz, maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili); + + + } + } + } + + //delete edge detection + if(koeLibuffer) { + delete [] koeLibuffer; + } } -#ifdef _RT_NESTED_OPENMP -#pragma omp barrier -#endif - - if((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step -#ifdef _RT_NESTED_OPENMP -#pragma omp for nowait -#endif - for (int i=0; i (100.f-tran)) - tran=100.f-cp.th; - if(LL100 < cp.th){ - float aalp=(1.f-alp)/cp.th;//no changes for LL100 = cp.th - float kk=aalp*LL100+alp; - WavCoeffs_L0[i] *= (1.f+kk*cp.conres/200.f); - } - else if(LL100 < cp.th + tran) { - float ath = -cp.conres/tran; - float bth = cp.conres-ath*cp.th; - WavCoeffs_L0[i] *= (1.f+(LL100*ath+bth)/200.f); - } - //highlight - tran=5.f; - if(cp.thH < (tran)) - tran = cp.thH; - if(LL100 > cp.thH) - WavCoeffs_L0[i] *= (1.f+cp.conresH/200.f); - else if(LL100 > (cp.thH - tran)) { - float athH = cp.conresH/tran; - float bthH = cp.conresH-athH*cp.thH; - WavCoeffs_L0[i] *= (1.f+(LL100*athH+bthH)/200.f); - } - } - } - //enabled Lipschitz..replace simple by complex edge detection - // I found this concept on the web (doctoral thesis on medical Imaging) - // I was inspired by the principle of Canny and Lipschitz (continuity and derivability) - // I adapted the principle but have profoundly changed the algorithm - // One can 1) change all parameters and found good parameters; - //one can also chnage in calckoe - float edd=settings->ed_detec; - float eddlow=settings->ed_low;//5 to 40 - // float eddlipinfl=settings->ed_lipinfl; - // float eddlipampl=settings->ed_lipampl; - float eddlipinfl=0.005f*cp.edgsens + 0.4f; - float eddlipampl=1.f + cp.edgampl/50.f; - // float eddlow=5.f + cp.edgampl/2.f;//settings->ed_low;//5 to 40 - -if(cp.detectedge && lipschitz==true) { //enabled Lipschitz control...more memory..more time... - float *tmCBuffer = new float[H_L*W_L]; - float *tmC[H_L]; - for (int i=0; i 1 for alp >eddlipinfl and alph < 1 - //Liamp < 1 for alp < eddlipinfl and alph > 0 - if(alph > 1.f) {alph = 1.f/ alph;} - if(beta > 1.f) {beta=1.f/beta;} - //take into account diagonal - //if in same value OK - //if not no edge or reduction - float bet=1.f; - //if(cp.lip3) {//enhance algorithm - if(alph > eddlipinfl && beta < 0.85f*eddlipinfl) {//0.85 arbitrary value ==> eliminate from edge if H V D too different - bet=beta; - } - //} - float AmpLip=1.f; - - if(alph > eddlipinfl) {AmpLip=alipinfl*alph+blipinfl;kampli=SQR(bet)*AmpLip*aamp;}//If beta low reduce kampli - else {AmpLip=(1.f/eddlipinfl)*SQR(SQR(alph*bet));kampli=AmpLip/aamp;}//Strong Reduce if beta low - // comparaison betwwen pixel and neighbours to do ==> I think 3 dir above is better - /* if(cp.lip3){ - koeLi[lvl*3][i*W_L + j] = (koeLi[lvl*3][i*W_L + j] + koeLi[lvl*3][(i-1)*W_L + j] + koeLi[lvl*3][(i+1)*W_L + j] - + koeLi[lvl*3][i*W_L + j+1] + koeLi[lvl*3][i*W_L + j-1] + koeLi[lvl*3][(i-1)*W_L + j-1] - + koeLi[lvl*3][(i-1)*W_L + j+1] +koeLi[lvl*3][(i+1)*W_L + j-1] +koeLi[lvl*3][(i+1)*W_L + j+1])/9.f; - } - */ - // apply to each direction Wavelet level : horizontal / vertiacle / diagonal - //interm += SQR(koeLi[lvl*3 + dir-1][i*W_L + j]); - - interm*=kampli; - if(interm < cp.eddetthr/eddlow) interm = 0.01f;//eliminate too low values - //we can change this part of algo==> not equal but ponderate - koeLi[lvl*3][i*W_L + j]=koeLi[lvl*3 + 1][i*W_L + j]=koeLi[lvl*3 + 2][i*W_L + j]=interm;//new value - //here KoeLi contains values where gradient is high and coef high, and eliminate low values... - } - } - } - // end -} - -#ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) -#endif - for (int dir=1; dir<4; dir++) { - for (int lvl=0; lvl1) -#endif +void ImProcFunctions::WaveletAandBAllAB(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, wavelet_decomposition &WaveletCoeffs_b, + struct cont_params &cp, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* hhCurve, bool hhutili) { + // StopWatch Stop1("WaveletAandBAllAB"); + if (hhutili && cp.resena) { // H=f(H) + int W_L = WaveletCoeffs_a.level_W(0); + int H_L = WaveletCoeffs_a.level_H(0); + + float * WavCoeffs_a0 = WaveletCoeffs_a.coeff0; + float * WavCoeffs_b0 = WaveletCoeffs_b.coeff0; +#ifdef _RT_NESTED_OPENMP + #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + { #ifdef __SSE2__ - float huebuffer[W_L] ALIGNED64; - float chrbuffer[W_L] ALIGNED64; + float huebuffer[W_L] ALIGNED64; + float chrbuffer[W_L] ALIGNED64; #endif // __SSE2__ #ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic,16) + #pragma omp for schedule(dynamic,16) #endif - for (int i=0; iv(i,j) = valpar; - } - */ - float valparam = float((hhCurve->getVal(Color::huelab_to_huehsv2(hueR))-0.5f) * 1.7f) +hueR;//get H=f(H) 1.7 optimisation ! - float2 sincosval = xsincosf(valparam); - WavCoeffs_a0[i*W_L+j]=chR*sincosval.y; - WavCoeffs_b0[i*W_L+j]=chR*sincosval.x; - } - } -} - } - + /* if (editID == EUID_WW_HHCurve) {//H pipette + float valpar =Color::huelab_to_huehsv2(hueR); + editWhatever->v(i,j) = valpar; + } + */ + float valparam = float((hhCurve->getVal(Color::huelab_to_huehsv2(hueR)) - 0.5f) * 1.7f) + hueR; //get H=f(H) 1.7 optimisation ! + float2 sincosval = xsincosf(valparam); + WavCoeffs_a0[i * W_L + j] = chR * sincosval.y; + WavCoeffs_b0[i * W_L + j] = chR * sincosval.x; + } + } + } + } + } - - void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_ab,const WavOpacityCurveW & waOpacityCurveW, - struct cont_params &cp, const bool useChannelA){ - - int maxlvl = WaveletCoeffs_ab.maxlevel(); - int W_L = WaveletCoeffs_ab.level_W(0); - int H_L = WaveletCoeffs_ab.level_H(0); - - float * WavCoeffs_ab0 = WaveletCoeffs_ab.coeff0; - -#ifdef _RT_NESTED_OPENMP -#pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) -#endif + +void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_ab, const WavOpacityCurveW & waOpacityCurveW, + struct cont_params &cp, const bool useChannelA) { - if(cp.chrores != 0.f && cp.resena) { // cp.chrores == 0.f means all will be multiplied by 1.f, so we can skip the processing of residual + + int maxlvl = WaveletCoeffs_ab.maxlevel(); + int W_L = WaveletCoeffs_ab.level_W(0); + int H_L = WaveletCoeffs_ab.level_H(0); + + float * WavCoeffs_ab0 = WaveletCoeffs_ab.coeff0; #ifdef _RT_NESTED_OPENMP -#pragma omp for nowait -#endif - for (int i=0; i 0.f){ - if((modhue < cp.t_ry && modhue > cp.t_ly)) { - scale=(100.f-cp.sky)/100.1f; - } else if((modhue >= cp.t_ry && modhue < cp.b_ry)) { - scale=(100.f-cp.sky)/100.1f; - float ar=(scale-1.f)/(cp.t_ry- cp.b_ry); - float br=scale-cp.t_ry*ar; - scale=ar*modhue+br; - } else if((modhue > cp.b_ly && modhue < cp.t_ly)) { - scale=(100.f-cp.sky)/100.1f; - float al=(scale-1.f)/(-cp.b_ly + cp.t_ly); - float bl=scale-cp.t_ly*al; - scale=al*modhue+bl; - } - } else if(skyprot < 0.f){ - if((modhue > cp.t_ry || modhue < cp.t_ly)){ - scale=(100.f+cp.sky)/100.1f; - } - /* else if((modhue >= cp.t_ry && modhue < cp.b_ry)) { - scale=(100.f+cp.sky)/100.1f; - float ar=(scale-1.f)/(cp.t_ry- cp.b_ry); - float br=scale-cp.t_ry*ar; - scale=ar*modhue+br; - } - else if((modhue > cp.b_ly && modhue < cp.t_ly)) { - scale=(100.f+cp.sky)/100.1f; - float al=(scale-1.f)/(-cp.b_ly + cp.t_ly); - float bl=scale-cp.t_ly*al; - scale=al*modhue+bl; - } - */ - } - WavCoeffs_ab0[i]*=(1.f+cp.chrores*(scale)/100.f); - - } - } - - if(cp.cbena && cp.resena) {//if user select Toning and color balance - + #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) +#endif + { + if(cp.chrores != 0.f && cp.resena) { // cp.chrores == 0.f means all will be multiplied by 1.f, so we can skip the processing of residual + #ifdef _RT_NESTED_OPENMP -#pragma omp for nowait -#endif - for (int i=0; iL[ii*2][jj*2])/327.68f;//I use labco but I can use also WavCoeffs_L0 (more exact but more memory) + #pragma omp for nowait +#endif + + for (int i = 0; i < W_L * H_L; i++) { + const float skyprot = cp.sky; + //chroma + int ii = i / W_L; + int jj = i - ii * W_L; + float modhue = varhue[ii][jj]; + float scale = 1.f; + + if(skyprot > 0.f) { + if((modhue < cp.t_ry && modhue > cp.t_ly)) { + scale = (100.f - cp.sky) / 100.1f; + } else if((modhue >= cp.t_ry && modhue < cp.b_ry)) { + scale = (100.f - cp.sky) / 100.1f; + float ar = (scale - 1.f) / (cp.t_ry - cp.b_ry); + float br = scale - cp.t_ry * ar; + scale = ar * modhue + br; + } else if((modhue > cp.b_ly && modhue < cp.t_ly)) { + scale = (100.f - cp.sky) / 100.1f; + float al = (scale - 1.f) / (-cp.b_ly + cp.t_ly); + float bl = scale - cp.t_ly * al; + scale = al * modhue + bl; + } + } else if(skyprot < 0.f) { + if((modhue > cp.t_ry || modhue < cp.t_ly)) { + scale = (100.f + cp.sky) / 100.1f; + } + + /* else if((modhue >= cp.t_ry && modhue < cp.b_ry)) { + scale=(100.f+cp.sky)/100.1f; + float ar=(scale-1.f)/(cp.t_ry- cp.b_ry); + float br=scale-cp.t_ry*ar; + scale=ar*modhue+br; + } + else if((modhue > cp.b_ly && modhue < cp.t_ly)) { + scale=(100.f+cp.sky)/100.1f; + float al=(scale-1.f)/(-cp.b_ly + cp.t_ly); + float bl=scale-cp.t_ly*al; + scale=al*modhue+bl; + } + */ + } + + WavCoeffs_ab0[i] *= (1.f + cp.chrores * (scale) / 100.f); + + } + } + + if(cp.cbena && cp.resena) {//if user select Toning and color balance - float sca=1.f;//amplifer - reducter...about 1, but perhaps 0.6 or 1.3 - if(useChannelA) {//green red (little magenta) - //transition to avoid artifacts with 6 between 30 to 36 and 63 to 69 - float aa=(cp.grmed-cp.grlow)/6.f; - float bb= cp.grlow-30.f*aa; - float aaa=(cp.grhigh-cp.grmed)/6.f; - float bbb= cp.grmed-63.f*aaa; - - if(LL < 30.f)//shadows - WavCoeffs_ab0[i]+=cp.grlow*(sca)*300.f; - else if(LL >= 30.f && LL < 36.f) {//transition - float tr=aa*LL+bb; - WavCoeffs_ab0[i]+= tr*(sca)*300.f; - } - else if(LL >= 36.f && LL < 63.f)//midtones - WavCoeffs_ab0[i]+=cp.grmed*(sca)*300.f; - else if(LL >= 63.f && LL < 69.f) {//transition - float trh=aaa*LL+bbb; - WavCoeffs_ab0[i]+=trh*(sca)*300.f; - } - else if(LL >= 69.f)//highlights - WavCoeffs_ab0[i]+=cp.grhigh*(sca)*300.f; - } - else {//blue yellow - //transition with 6 between 30 to 36 and 63 to 69 - float aa1=(cp.blmed-cp.bllow)/6.f; - float bb1= cp.bllow-30.f*aa1; - float aaa1=(cp.blhigh-cp.blmed)/6.f; - float bbb1= cp.blmed-63.f*aaa1; - - if(LL < 30.f) - WavCoeffs_ab0[i]+=cp.bllow*(sca)*300.f; - else if(LL >= 30.f && LL < 36.f) { - float tr1=aa1*LL+bb1; - WavCoeffs_ab0[i]+=tr1*(sca)*300.f; - } - else if(LL >= 36.f && LL < 63.f) - WavCoeffs_ab0[i]+=cp.blmed*(sca)*300.f; - else if(LL >= 63.f && LL < 69.f) { - float trh1=aaa1*LL+bbb1; - WavCoeffs_ab0[i]+=trh1*(sca)*300.f; - } - else if(LL >= 69.f) - WavCoeffs_ab0[i]+=cp.blhigh*(sca)*300.f; - } - } - } - #ifdef _RT_NESTED_OPENMP -#pragma omp for schedule(dynamic) collapse(2) -#endif - for (int dir=1; dir<4; dir++) { - for (int lvl=0; lvlL[ii * 2][jj * 2]) / 327.68f; //I use labco but I can use also WavCoeffs_L0 (more exact but more memory) + + float sca = 1.f; //amplifer - reducter...about 1, but perhaps 0.6 or 1.3 + + if(useChannelA) {//green red (little magenta) + //transition to avoid artifacts with 6 between 30 to 36 and 63 to 69 + float aa = (cp.grmed - cp.grlow) / 6.f; + float bb = cp.grlow - 30.f * aa; + float aaa = (cp.grhigh - cp.grmed) / 6.f; + float bbb = cp.grmed - 63.f * aaa; + + if(LL < 30.f) { //shadows + WavCoeffs_ab0[i] += cp.grlow * (sca) * 300.f; + } else if(LL >= 30.f && LL < 36.f) { //transition + float tr = aa * LL + bb; + WavCoeffs_ab0[i] += tr * (sca) * 300.f; + } else if(LL >= 36.f && LL < 63.f) { //midtones + WavCoeffs_ab0[i] += cp.grmed * (sca) * 300.f; + } else if(LL >= 63.f && LL < 69.f) { //transition + float trh = aaa * LL + bbb; + WavCoeffs_ab0[i] += trh * (sca) * 300.f; + } else if(LL >= 69.f) { //highlights + WavCoeffs_ab0[i] += cp.grhigh * (sca) * 300.f; + } + } else { //blue yellow + //transition with 6 between 30 to 36 and 63 to 69 + float aa1 = (cp.blmed - cp.bllow) / 6.f; + float bb1 = cp.bllow - 30.f * aa1; + float aaa1 = (cp.blhigh - cp.blmed) / 6.f; + float bbb1 = cp.blmed - 63.f * aaa1; + + if(LL < 30.f) { + WavCoeffs_ab0[i] += cp.bllow * (sca) * 300.f; + } else if(LL >= 30.f && LL < 36.f) { + float tr1 = aa1 * LL + bb1; + WavCoeffs_ab0[i] += tr1 * (sca) * 300.f; + } else if(LL >= 36.f && LL < 63.f) { + WavCoeffs_ab0[i] += cp.blmed * (sca) * 300.f; + } else if(LL >= 63.f && LL < 69.f) { + float trh1 = aaa1 * LL + bbb1; + WavCoeffs_ab0[i] += trh1 * (sca) * 300.f; + } else if(LL >= 69.f) { + WavCoeffs_ab0[i] += cp.blhigh * (sca) * 300.f; + } + } + } + } + +#ifdef _RT_NESTED_OPENMP + #pragma omp for schedule(dynamic) collapse(2) +#endif + + for (int dir = 1; dir < 4; dir++) { + for (int lvl = 0; lvl < maxlvl; lvl++) { + + int Wlvl_ab = WaveletCoeffs_ab.level_W(lvl); + int Hlvl_ab = WaveletCoeffs_ab.level_H(lvl); - int skip_ab = WaveletCoeffs_ab.level_stride(lvl); - //printf("lev=%d skipL=%d skipab=%d\n",lvl, skip_L,skip_ab); - float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); - ContAllAB (labco, maxlvl, varhue, varchrom, WavCoeffs_ab, WavCoeffs_ab0, lvl, dir, waOpacityCurveW, cp, Wlvl_ab, Hlvl_ab, useChannelA); - } - } - - -} - } + int skip_ab = WaveletCoeffs_ab.level_stride(lvl); + //printf("lev=%d skipL=%d skipab=%d\n",lvl, skip_L,skip_ab); + float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); + ContAllAB (labco, maxlvl, varhue, varchrom, WavCoeffs_ab, WavCoeffs_ab0, lvl, dir, waOpacityCurveW, cp, Wlvl_ab, Hlvl_ab, useChannelA); + } + } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void ImProcFunctions::calckoe(float ** WavCoeffs_LL, struct cont_params cp, float *koeLi[12], int level, int dir, int W_L, int H_L, float edd, float *maxkoeLi, float **tmC){ - int borderL = 2; -// printf("cpedth=%f\n",cp.eddetthr); - if(cp.eddetthr < 30.f) { - borderL = 1; - // I calculate coefficients with r size matrix 3x3 r=1 ; 5x5 r=2; 7x7 r=3 - /* - float k[2*r][2*r]; - for(int i=1;i<=(2*r+1);i++) { - for(int j=1;j<=(2*r+1);j++) { - k[i][j]=(1.f/6.283*sigma*sigma)*exp(-SQR(i-r-1)+SQR(j-r-1)/2.f*SQR(sigma)); - } - } - //I could also use Gauss.h for 3x3 - // If necessary I can put a 7x7 matrix - */ - for (int i=1; i= 30.f && cp.eddetthr < 50.f) { - borderL = 1; + } +} - for (int i=1; i= 50.f && cp.eddetthr < 75.f) { - borderL = 1; - for (int i=1; i= 75.f) { - borderL = 2; - //if(cp.lip3 && level > 1) { - if(level > 1) {// do not activate 5x5 if level 0 or 1 +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - for (int i=2; i lees good results==> probably because structure data different and also I compare to original value which have + and - - for(int i = borderL; i < H_L-borderL; i++ ) {//[-1 0 1] x==>j - for(int j = borderL; j < W_L-borderL; j++) { - tmC[i][j]=- WavCoeffs_LL[dir][(i)*W_L + j-1] + WavCoeffs_LL[dir][(i)*W_L + j+1]; - } - } - for(int i = borderL; i < H_L-borderL; i++ ) {//[1 0 -1] y==>i - for(int j = borderL; j < W_L-borderL; j++) { - tmC[i][j]= - WavCoeffs_LL[dir][(i-1)*W_L + j] + WavCoeffs_LL[dir][(i+1)*W_L + j]; - } - } - */ - - float thr=40.f;//avoid artifact eg. noise...to test - float thr2=1.5f*edd;//edd can be modified in option ed_detect - thr2+=cp.eddet/30.f;//to test - float diffFactor = (cp.eddet/100.f); - for(int i = 0; i < H_L; i++ ) { - for(int j = 0; j < W_L; j++) { - koeLi[level*3 + dir-1][i*W_L + j]=1.f; - } - } - for(int i = borderL; i < H_L-borderL; i++ ) { - for(int j = borderL; j < W_L-borderL; j++) { - // my own algo : probably a little false, but simpler as Lipschitz ! - // Thr2 = maximum of the function ==> Lipsitch says = probably edge -// float temp = WavCoeffs_LL[dir][i*W_L + j]; -// if(temp>=0.f && temp < thr) temp = thr; -// if(temp < 0.f && temp > -thr) temp = -thr; - float temp = max(fabsf(WavCoeffs_LL[dir][i*W_L + j]), thr ); - koeLi[level*3 + dir-1][i*W_L + j]= min(thr2,fabs(tmC[i][j]/temp));// limit maxi - //it will be more complicated to calculate both Wh and Wv, but we have also Wd==> pseudo Lipschitz - if(koeLi[level*3+ dir-1][i*W_L + j] > maxkoeLi[level*3+ dir-1]) - maxkoeLi[level*3+ dir-1] = koeLi[level*3 + dir-1][i*W_L + j]; - float diff = maxkoeLi[level*3+ dir-1] - koeLi[level*3 + dir-1][i*W_L + j]; - diff *= diffFactor; - koeLi[level*3 + dir-1][i*W_L + j] = maxkoeLi[level*3 + dir-1] - diff; - } - } + // I calculate coefficients with r size matrix 3x3 r=1 ; 5x5 r=2; 7x7 r=3 + /* + float k[2*r][2*r]; + for(int i=1;i<=(2*r+1);i++) { + for(int j=1;j<=(2*r+1);j++) { + k[i][j]=(1.f/6.283*sigma*sigma)*exp(-SQR(i-r-1)+SQR(j-r-1)/2.f*SQR(sigma)); + } + } + //I could also use Gauss.h for 3x3 + // If necessary I can put a 7x7 matrix + */ + for (int i = 1; i < H_L - 1; i++) { //sigma=0.55 + for (int j = 1; j < W_L - 1; j++) { + tmC[i][j] = (8.94f * WavCoeffs_LL[dir][i * W_L + j] + 1.71f * (WavCoeffs_LL[dir][(i - 1) * W_L + j] + 1.71f * WavCoeffs_LL[dir][(i + 1) * W_L + j] + + 1.71f * WavCoeffs_LL[dir][i * W_L + j + 1] + 1.71f * WavCoeffs_LL[dir][i * W_L + j - 1]) + 0.33f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1] + + 0.33f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 0.33f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 0.33f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]) * 0.0584795f; + // apply to each direction Wavelet level : horizontal / vertiacle / diagonal + + + } + } + } else if(cp.eddetthr >= 30.f && cp.eddetthr < 50.f) { + borderL = 1; + + for (int i = 1; i < H_L - 1; i++) { //sigma=0.85 + for (int j = 1; j < W_L - 1; j++) { + tmC[i][j] = (4.0091f * WavCoeffs_LL[dir][i * W_L + j] + 2.0068f * (WavCoeffs_LL[dir][(i - 1) * W_L + j] + 2.0068f * WavCoeffs_LL[dir][(i + 1) * W_L + j] + + 2.0068f * WavCoeffs_LL[dir][i * W_L + j + 1] + 2.0068f * WavCoeffs_LL[dir][i * W_L + j - 1]) + 1.0045f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1] + + 1.0045f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 1.0045f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 1.0045f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]) * 0.062288f; + // apply to each direction Wavelet level : horizontal / vertiacle / diagonal + + + } + } + } + + + else if(cp.eddetthr >= 50.f && cp.eddetthr < 75.f) { + borderL = 1; + + for (int i = 1; i < H_L - 1; i++) { + for (int j = 1; j < W_L - 1; j++) { //sigma=1.1 + tmC[i][j] = (3.025f * WavCoeffs_LL[dir][i * W_L + j] + 2.001f * (WavCoeffs_LL[dir][(i - 1) * W_L + j] + 2.001f * WavCoeffs_LL[dir][(i + 1) * W_L + j] + + 2.001f * WavCoeffs_LL[dir][i * W_L + j + 1] + 2.001f * WavCoeffs_LL[dir][i * W_L + j - 1]) + 1.323f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1] + + 1.323f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 1.323f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 1.323f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1]) * 0.06127f; + } + } + } + + else if(cp.eddetthr >= 75.f) { + borderL = 2; + + //if(cp.lip3 && level > 1) { + if(level > 1) {// do not activate 5x5 if level 0 or 1 + + for (int i = 2; i < H_L - 2; i++) { + for (int j = 2; j < W_L - 2; j++) { + // Gaussian 1.1 + // 0.5 2 3 2 0.5 + // 2 7 10 7 2 + // 3 10 15 10 3 + // 2 7 10 7 2 + // 0.5 2 3 2 0.5 + // divi 113 + //Gaussian 1.4 + // 2 4 5 4 2 + // 4 9 12 9 4 + // 5 12 15 12 5 + // 4 9 12 9 4 + // 2 4 5 4 2 + // divi 159 + if(cp.eddetthr < 85.f) { //sigma=1.1 + tmC[i][j] = (15.f * WavCoeffs_LL[dir][i * W_L + j] + 10.f * WavCoeffs_LL[dir][(i - 1) * W_L + j] + 10.f * WavCoeffs_LL[dir][(i + 1) * W_L + j] + + 10.f * WavCoeffs_LL[dir][i * W_L + j + 1] + 10.f * WavCoeffs_LL[dir][i * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1] + + 7.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 7.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 7.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1] + + 3.f * WavCoeffs_LL[dir][(i - 2) * W_L + j] + 3.f * WavCoeffs_LL[dir][(i + 2) * W_L + j] + 3.f * WavCoeffs_LL[dir][i * W_L + j - 2] + 3.f * WavCoeffs_LL[dir][i * W_L + j + 2] + + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 1] + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 1] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 1] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 1] + + 2.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 2] + 2.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 2] + 2.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 2] + 2.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 2] + + 0.5f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 2] + 0.5f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 2] + 0.5f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 2] + 0.5f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 2] + ) * 0.0088495f; + + } + + else {//sigma=1.4 + tmC[i][j] = (15.f * WavCoeffs_LL[dir][i * W_L + j] + 12.f * WavCoeffs_LL[dir][(i - 1) * W_L + j] + 12.f * WavCoeffs_LL[dir][(i + 1) * W_L + j] + + 12.f * WavCoeffs_LL[dir][i * W_L + j + 1] + 12.f * WavCoeffs_LL[dir][i * W_L + j - 1] + 9.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 1] + + 9.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 1] + 9.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 1] + 9.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 1] + + 5.f * WavCoeffs_LL[dir][(i - 2) * W_L + j] + 5.f * WavCoeffs_LL[dir][(i + 2) * W_L + j] + 5.f * WavCoeffs_LL[dir][i * W_L + j - 2] + 5.f * WavCoeffs_LL[dir][i * W_L + j + 2] + + 4.f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 1] + 4.f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 1] + 4.f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 1] + 4.f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 1] + + 4.f * WavCoeffs_LL[dir][(i - 1) * W_L + j - 2] + 4.f * WavCoeffs_LL[dir][(i - 1) * W_L + j + 2] + 4.f * WavCoeffs_LL[dir][(i + 1) * W_L + j + 2] + 4.f * WavCoeffs_LL[dir][(i + 1) * W_L + j - 2] + + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j - 2] + 2.f * WavCoeffs_LL[dir][(i - 2) * W_L + j + 2] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j - 2] + 2.f * WavCoeffs_LL[dir][(i + 2) * W_L + j + 2] + ) * 0.0062893f; + } + + + // apply to each direction Wavelet level : horizontal / vertiacle / diagonal + } + } + } + + } + + + /* + // I suppress these 2 convolutions ==> lees good results==> probably because structure data different and also I compare to original value which have + and - + for(int i = borderL; i < H_L-borderL; i++ ) {//[-1 0 1] x==>j + for(int j = borderL; j < W_L-borderL; j++) { + tmC[i][j]=- WavCoeffs_LL[dir][(i)*W_L + j-1] + WavCoeffs_LL[dir][(i)*W_L + j+1]; + } + } + for(int i = borderL; i < H_L-borderL; i++ ) {//[1 0 -1] y==>i + for(int j = borderL; j < W_L-borderL; j++) { + tmC[i][j]= - WavCoeffs_LL[dir][(i-1)*W_L + j] + WavCoeffs_LL[dir][(i+1)*W_L + j]; + } + } + */ + + float thr = 40.f; //avoid artifact eg. noise...to test + float thr2 = 1.5f * edd; //edd can be modified in option ed_detect + thr2 += cp.eddet / 30.f; //to test + float diffFactor = (cp.eddet / 100.f); + + for(int i = 0; i < H_L; i++ ) { + for(int j = 0; j < W_L; j++) { + koeLi[level * 3 + dir - 1][i * W_L + j] = 1.f; + } + } + + for(int i = borderL; i < H_L - borderL; i++ ) { + for(int j = borderL; j < W_L - borderL; j++) { + // my own algo : probably a little false, but simpler as Lipschitz ! + // Thr2 = maximum of the function ==> Lipsitch says = probably edge +// float temp = WavCoeffs_LL[dir][i*W_L + j]; +// if(temp>=0.f && temp < thr) temp = thr; +// if(temp < 0.f && temp > -thr) temp = -thr; + float temp = max(fabsf(WavCoeffs_LL[dir][i * W_L + j]), thr ); + koeLi[level * 3 + dir - 1][i * W_L + j] = min(thr2, fabs(tmC[i][j] / temp)); // limit maxi + + //it will be more complicated to calculate both Wh and Wv, but we have also Wd==> pseudo Lipschitz + if(koeLi[level * 3 + dir - 1][i * W_L + j] > maxkoeLi[level * 3 + dir - 1]) { + maxkoeLi[level * 3 + dir - 1] = koeLi[level * 3 + dir - 1][i * W_L + j]; + } + + float diff = maxkoeLi[level * 3 + dir - 1] - koeLi[level * 3 + dir - 1][i * W_L + j]; + diff *= diffFactor; + koeLi[level * 3 + dir - 1][i * W_L + j] = maxkoeLi[level * 3 + dir - 1] - diff; + } + } } - - void ImProcFunctions::finalContAllL (int maxlvl, LabImage * labco, float ** varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp, - int W_L, int H_L, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili) - { - bool lipschitz=true; - float edge=1.f; - bool curvdiag=true; - if(curvdiag && cp.finena) {//curve - float insigma=0.666f;//SD - float logmax=log(MaxP[level]);//log Max - float rapX=(mean[level]+sigma[level])/MaxP[level];//rapport between sD / max - float inx=log(insigma); - float iny=log(rapX); - float rap=inx/iny;//koef - float asig=0.166f/sigma[level]; - float bsig=0.5f-asig*mean[level]; - float amean=0.5f/mean[level]; - float absciss; - float kinterm; - float kmul; - for (int i=0; i= (mean[level]+sigma[level])){//for max - float valcour=log(fabs(WavCoeffs_L[dir][i])); - float valc=valcour-logmax; - float vald=valc*rap; - absciss=exp(vald); - - } - else if(fabs(WavCoeffs_L[dir][i])>=mean[level] && fabs(WavCoeffs_L[dir][i]) < (mean[level]+sigma[level])){ - absciss=asig*fabs(WavCoeffs_L[dir][i])+bsig; - } - // else if(fabs(WavCoeffs_L[dir][i]) < mean[level]){ - else - absciss=amean*fabs(WavCoeffs_L[dir][i]); - // } - kinterm=1.f; - kmul=1.f; - float kc = kmul*(waOpacityCurveWL[absciss*500.f]-0.5f); - float reduceeffect=1.5f; - if(kc <=0.f) reduceeffect=1.f; - kinterm = 1.f + reduceeffect*kmul*(waOpacityCurveWL[absciss*500.f]-0.5f); - - if(kinterm<0.f) kinterm=0.01f; - } - - WavCoeffs_L[dir][i] *= kinterm; - } - } - int choicelevel = atoi(params->wavelet.Lmethod.data())-1; - choicelevel = choicelevel == -1 ? 4 : choicelevel; - - int choiceClevel=0; - if(params->wavelet.CLmethod=="one") choiceClevel=0; - else if(params->wavelet.CLmethod=="inf") choiceClevel=1; - else if(params->wavelet.CLmethod=="sup") choiceClevel=2; - else if(params->wavelet.CLmethod=="all") choiceClevel=3; - int choiceDir=0; - if(params->wavelet.Dirmethod=="one") choiceDir=1; - else if(params->wavelet.Dirmethod=="two") choiceDir=2; - else if(params->wavelet.Dirmethod=="thr") choiceDir=3; - else if(params->wavelet.Dirmethod=="all") choiceDir=0; +void ImProcFunctions::finalContAllL (int maxlvl, LabImage * labco, float ** varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp, + int W_L, int H_L, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveWL & waOpacityCurveWL, FlatCurve* ChCurve, bool Chutili) +{ + bool lipschitz = true; + float edge = 1.f; + bool curvdiag = true; - int dir1 = (choiceDir == 2) ? 1 : 2; - int dir2 = (choiceDir == 3) ? 1 : 3; - if(choiceClevel<3) { // not all levels visible, paint residual - if(level == 0) { - if(cp.backm!=2) { // nothing to change when residual is used as background - float backGroundColor = (cp.backm==1) ? 12000.f : 0.f; - for (int i=0; i= cp.maxilev) { - for (int dir=1; dir<4; dir++) { - for (int i=0; i choicelevel) { - for (int dir=1; dir<4; dir++) { - for (int i=0; i= choicelevel - if(level > choicelevel) { - for (int i=0; i= choicelevel - if(choicelevel >= cp.maxilev) { - for (int dir=1; dir<4; dir++) { - for (int i=0; itop_right; - float t_l=settings->top_left; - float b_r=settings->bot_right; - float b_l=settings->bot_left; - float edd=settings->ed_detec; - float eddlow=settings->ed_low; - float eddstrength=settings->ed_detecStr; - float aedstr=(eddstrength-1.f)/90.f; - float bedstr=1.f-10.f*aedstr; - - bool refi=false; - // if(cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f) refi=true; - // if(cp.val > 0 || refi) {//edge - if(cp.val > 0 && cp.edgeena) { - float * koe; - float maxkoe=0.f; - if(lipschitz==false) { - koe = new float [H_L*W_L]; - for (int i=0; i=0.f && temp < thr) temp= thr; - if(temp < 0.f && temp > -thr) temp= -thr; - koe[i*W_L + j]= min(thr2,fabs(tmC[i][j]/temp)); - - if(koe[i*W_L + j] > maxkoe) maxkoe=koe[i*W_L + j]; - float diff=maxkoe-koe[i*W_L + j]; - diff *=(cp.eddet/100.f); - float interm=maxkoe-diff; - if(interm < cp.eddetthr/30.f) interm = 0.01f; - - koe[i*W_L + j]=interm; - - } - } - //printf("maxkoe=%f \n",maxkoe); + if(cp.diagcurv) { + if(fabs(WavCoeffs_L[dir][i]) >= (mean[level] + sigma[level])) { //for max + float valcour = log(fabs(WavCoeffs_L[dir][i])); + float valc = valcour - logmax; + float vald = valc * rap; + absciss = exp(vald); - for (int i=0; i not too high value to avoid artifacts - float value = ((float)cp.val)/8.f;//strength - if (scaleskip[1] < 1.f) value *= (atten01234*scaleskip[1]);//for zoom < 100% reduce strength...I choose level 1...but!! - float edge=1.f; - float lim0=20.f;//arbitrary limit for low radius and level between 2 or 3 to 30 maxi - float lev = float (level); - float repart=(float)cp.til; - float brepart; - if(cp.reinforce==1) brepart=3.f; - if(cp.reinforce==3) brepart=0.5f; //arbitrary value to increase / decrease repart, between 1 and 0 - float arepart=-(brepart-1.f)/(lim0/60.f); - if (cp.reinforce !=2) {if(rad < lim0/60.f) repart *= (arepart*rad + brepart);}//linear repartition of repart - - float al0 = 1.f + (repart)/50.f; - float al10 =1.0f;//arbitrary value ==> less = take into account high levels - // float ak =-(al0-al10)/10.f;//10 = maximum levels - float ak =-(al0-al10)/10.f;//10 = maximum levels - float bk =al0; - float koef = ak*level+bk;//modulate for levels : more levels high, more koef low ==> concentrated action on low levels, without or near for high levels - float expkoef= -pow(fabs(rad - lev),koef);//reduce effect for high levels - if (cp.reinforce==3) {if(rad < lim0/60.f && level==0) expkoef *= repart;}//reduce effect for low values of rad and level=0==> quasi only level 1 is effective - if (cp.reinforce==1) {if(rad < lim0/60.f && level==1) expkoef /= repart;}//increase effect for low values of rad and level=1==> quasi only level 0 is effective - float coefsd=0.85f;//arbitray value to reduce effect after sigma in all case - float coefmean=0.85f;//arbitray value to reduce effect after sigma in all case -// edge = 1.f + value * exp (expkoef);//estimate edge "pseudo variance" - //take into account local contrast - float refin= value * exp (expkoef); - if(cp.link==true && cp.noiseena){//combi - { - if(level==0) refin *= (1.f + cp.lev0s/50.f);// we can change this sensibility! - if(level==1) refin *= (1.f + cp.lev1s/50.f); - if(level==2) refin *= (1.f + cp.lev2s/50.f); - if(level==3) refin *= (1.f + cp.lev3s/50.f); - } - } - float edgePrecalc = 1.f + refin; //estimate edge "pseudo variance" - //bool exa=false; - if(cp.EDmet==2) {//curve - // if(exa) {//curve - float insigma=0.666f;//SD - float logmax=log(MaxP[level]);//log Max - float rapX=(mean[level]+sigma[level])/MaxP[level];//rapport between sD / max - float inx=log(insigma); - float iny=log(rapX); - float rap=inx/iny;//koef - float asig=0.166f/sigma[level]; - float bsig=0.5f-asig*mean[level]; - float amean=0.5f/mean[level]; - float absciss; - float kinterm; - float kmul; - // for (int i=0; i 10.f) edge=(aedstr*cp.eddet+bedstr)*(edgePrecalc*(1.f+koe[k]))/(1.f+0.9f*maxkoe); - else edge=(edgePrecalc*(1.f+koe[k]))/(1.f+0.9f*maxkoe); - } - if(lipschitz==true) { - if(level < 4) edge = 1.f +(edgePrecalc-1.f)*(koeLi[level*3][k])/(1.f+0.9f*maxkoeLi[level*3+ dir-1]); - else edge = edgePrecalc; - } - } - else edge = edgePrecalc; - - if(cp.edgcurv) { - if(fabs(WavCoeffs_L[dir][k])>= (mean[level]+sigma[level])){//for max - float valcour=log(fabs(WavCoeffs_L[dir][k])); - float valc=valcour-logmax; - float vald=valc*rap; - absciss=exp(vald); - - } - else if(fabs(WavCoeffs_L[dir][k])>=mean[level] && fabs(WavCoeffs_L[dir][k]) < (mean[level]+sigma[level])){ - absciss=asig*fabs(WavCoeffs_L[dir][k])+bsig; - } - else if(fabs(WavCoeffs_L[dir][k]) < mean[level]){ - absciss=amean*fabs(WavCoeffs_L[dir][k]); - } - // Threshold adjuster settings==> approximative for curve - //kmul about average cbrt(3--40 / 10)==>1.5 to 2.5 - //kmul about SD 10--60 / 35 ==> 2 - // kmul about low cbrt((5.f+cp.edg_low)/5.f);==> 1.5 - // kmul about max ==> 9 - // we can change these values - // result is different not best or bad than threshold slider...but similar - float abssd=4.f;//amplification reference - float bbssd=2.f;//mini ampli - float maxamp=2.5f;//maxi ampli at end - float maxampd=10.f;//maxi ampli at end - float a_abssd=(maxamp - abssd)/0.333f; - float b_abssd=maxamp-a_abssd; - float da_abssd=(maxampd - abssd)/0.333f; - float db_abssd=maxampd-da_abssd; - float am=(abssd-bbssd)/0.666f; - float kmuld=0.f; - if(absciss>0.666f && absciss < 1.f) {kmul=a_abssd*absciss + b_abssd;kmuld=da_abssd*absciss + db_abssd;}//about max ==> kinterm - else kmul = kmuld = absciss*am+bbssd; - kinterm=1.f; - float kc= kmul*(wavCLVCcurve[absciss*500.f]-0.5f); - float kcd= kmuld*(wavCLVCcurve[absciss*500.f]-0.5f); - float reduceeffect=0.6f; - if(kc >=0.f) - kinterm = 1.f + reduceeffect*kmul*(wavCLVCcurve[absciss*500.f]-0.5f);//about 1 to 3 general and big amplification for max (under 0) - else - kinterm = 1.f - (SQR(kcd))/10.f; - - if(kinterm<0.f) kinterm=0.01f; - edge *= kinterm; - if(edge < 1.f) - edge=1.f; - } - WavCoeffs_L[dir][k] *= edge; - } - } - } - else if(cp.EDmet==1) {//threshold adjuster - float MaxPCompare = MaxP[level]*SQR(cp.edg_max/100.f);//100 instead of b_r...case if b_r < 100 - float MaxNCompare = MaxN[level]*SQR(cp.edg_max/100.f);//always rduce a little edge for near max values - float edgeSdCompare = (mean[level]+1.5f*sigma[level])*SQR(cp.edg_sd/t_r);// 1.5 standard deviation #80% range between mean 50% and 80% - float edgeMeanCompare = mean[level]*SQR(cp.edg_mean/t_l); - float edgeLowCompare = (5.f+SQR(cp.edg_low)); - float edgeMeanFactor = cbrt(cp.edg_mean/t_l); - float interm; - if(cp.edg_low < 10.f) interm= cbrt((5.f+cp.edg_low)/5.f); - else interm=1.437f;//cbrt(3); - float edgeLowFactor = interm; - float edgeSdFactor = cp.edg_sd/t_r; - float edgeMaxFactor = SQR(cp.edg_max/b_r); - float edgMaxFsup=(cp.edg_max/b_r);//reduce increase of effect for high values contrast..if slider > b_r - - //for (int i=0; i= mean[level] && fabs(WavCoeffs_L[dir][i]) < (mean[level] + sigma[level])) { + absciss = asig * fabs(WavCoeffs_L[dir][i]) + bsig; + } + // else if(fabs(WavCoeffs_L[dir][i]) < mean[level]){ + else { + absciss = amean * fabs(WavCoeffs_L[dir][i]); + } - if(cp.detectedge) { - if(lipschitz==false) { - if(cp.eddet > 10.f) edge=(aedstr*cp.eddet+bedstr)*(edgePrecalc*(1.f+koe[k]))/(1.f+0.9f*maxkoe); - else edge=(edgePrecalc*(1.f+koe[k]))/(1.f+0.9f*maxkoe); - } - if(lipschitz==true) { - if(level < 4) edge = 1.f +(edgePrecalc-1.f)*(koeLi[level*3][k])/(1.f+0.9f*maxkoeLi[level*3+ dir-1]); - else edge = edgePrecalc; - } - } - else edge = edgePrecalc; - - //algorithm that take into account local contrast - // I use a thresholdadjuster with - // Bottom left ==> minimal low value for local contrast (not 0, but 5...we can change) - // 0 10*10 35*35 100*100 substantially correspond to the true distribution of low value, mean, standard-deviation and max (ed 5, 50, 400, 4000 - // Top left ==> mean reference value (for each level), we can change cbrt(cp.edg_mean/10.f) - // Top Right==> standard deviation (for each level) we can change (cp.edg_sd/35.f) - // bottom right ==> Max for positif and negatif contrast we can change cp.edg_max/100.f - // If we move sliders to the left, local contrast is reduced - // if we move sliders to the right local contrast is increased - // MaxP, MaxN, mean, sigma are calculated if necessary (val > 0) by evaluate2(), eval2(), aver() , sigma() - if(b_r < 100.f && cp.edg_max/b_r > 1.f) {//in case of b_r < 100 and slider move to right - if (WavCoeffs_L[dir][k] > MaxPCompare*cp.edg_max/b_r) { - edge *= edgMaxFsup; - if(edge < 1.f) - edge=1.f; - } - else if (WavCoeffs_L[dir][k] < MaxNCompare*cp.edg_max/b_r) { - edge *= edgMaxFsup; - if(edge < 1.f) - edge=1.f; - } - } - - if (WavCoeffs_L[dir][k] > MaxPCompare) { - edge *= edgeMaxFactor; - if(edge < 1.f) - edge=1.f; - }//reduce edge if > new max - else if (WavCoeffs_L[dir][k] < MaxNCompare) { - edge *= edgeMaxFactor; - if(edge < 1.f) - edge=1.f; - } - - if (fabs(WavCoeffs_L[dir][k]) >= edgeMeanCompare && fabs(WavCoeffs_L[dir][k]) < edgeSdCompare) { - //if (fabs(WavCoeffs_L[dir][i]) > edgeSdCompare) { - edge *= edgeSdFactor; - if(edge < 1.f) - edge=1.f; - }//mofify effect if sd change - if (fabs(WavCoeffs_L[dir][k]) < edgeMeanCompare) { - edge *= edgeMeanFactor; - if(edge < 1.f) - edge=1.f; - } // modify effect if mean change - if (fabs(WavCoeffs_L[dir][k]) < edgeLowCompare) { - edge *= edgeLowFactor; - if(edge < 1.f) - edge=1.f; - } - WavCoeffs_L[dir][k] *= edge; - } - } - } - if(lipschitz==false) { - delete [] koe; - } - } - - - if(cp.link==false && cp.noiseena) { //used both with denoise 1 2 3 - float refine=0.f; - for (int i=0; iwavelet.skinprotect; - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg/100.f); - - //to adjust increase contrast with local contrast - - //for each pixel and each level - float beta; - float mea[9]; - mea[0]=mean[level]/6.f; - mea[1]=mean[level]/2.f; - mea[2]=mean[level];// 50% data - mea[3]=mean[level] + sigma[level]/2.f; - mea[4]=mean[level] + sigma[level];//66% - mea[5]=mean[level] + 1.2f*sigma[level]; - mea[6]=mean[level] + 1.5f*sigma[level];// - mea[7]=mean[level] + 2.f*sigma[level];//95% - mea[8]=mean[level] + 2.5f*sigma[level];//99% - - bool skinControl = (skinprot != 0.f); - bool useChromAndHue = (skinprot != 0.f || cp.HSmet); - float modchro, kLlev; - - for (int i=0; iL[ii*2][jj*2]; - LL100=LL100init=LL/327.68f; - LL100res=WavCoeffs_L0[i]/327.68f; - float delta=fabs(LL100init-LL100res)/(maxlvl/2); - for(int ml=0;mlL[ii*2][jj*2]; - LL100=LL100init=LL/327.68f; - LL100res=WavCoeffs_L0[i]/327.68f; - float delta=fabs(LL100init-LL100res)/(maxlvl/2); - for(int ml=0;ml 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); //0 for skin and extand - } else if(skinprot < 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); - if (scale == 1.f) - scale=factorHard; - else - scale=1.f; - } - - } - if(Chutili){ - int i_i=i/W_L; - int j_j=i-i_i*W_L; - double lr; - float modhue2 = varhue[i_i][j_j]; - float valparam = float((ChCurve->getVal(lr=Color::huelab_to_huehsv2(modhue2))-0.5f));//get valparam=f(H) - - if(valparam > 0.f) scale2=1.f + 3.f* valparam;//arbitrary value - else scale2 = 1.f + 1.9f*valparam;//near 0 but not zero if curve # 0 - - //curve Contrast / hue - - } - // - //linear transition HL - float diagacc=1.f; - /* - if(cp.diag) { - if(dir <=2) diagacc=0.75f; - if(dir ==3) diagacc=1.5f; - } - */ - float alpha = (1024.f + 15.f *(float) cpMul*scale*scale2*beta*diagacc)/1024.f ; - if(cp.HSmet && cp.chromena){ - float aaal=(1.f-alpha)/((cp.b_lhl-cp.t_lhl)*kH[level]); - float bbal=1.f-aaal*cp.b_lhl*kH[level]; - float aaar=(alpha-1.f)/(cp.t_rhl-cp.b_rhl)*kH[level]; - float bbbr=1.f-cp.b_rhl*aaar*kH[level]; - //linear transition Shadows - float aaalS=(1.f-alpha)/(cp.b_lsl-cp.t_lsl); - float bbalS=1.f-aaalS*cp.b_lsl; - float aaarS=(alpha-1.f)/(cp.t_rsl-cp.b_rsl); - float bbbrS=1.f-cp.b_rsl*aaarS; - if(level <=cp.numlevH) {//in function of levels - if((LL100 > cp.t_lhl*kH[level] && LL100 < cp.t_rhl*kH[level])) {kLlev=alpha;} - else if((LL100 > cp.b_lhl*kH[level] && LL100 <= cp.t_lhl*kH[level])) kLlev=aaal*LL100+bbal; - else if((LL100 > cp.t_rhl*kH[level] && LL100 <= cp.b_rhl*kH[level])) kLlev=aaar*LL100+bbbr; - else kLlev=1.f; - } - if(level >=(9-cp.numlevS)) { - if((LL100 > cp.t_lsl && LL100 < cp.t_rsl)) kLlev=alpha; - else if((LL100 > cp.b_lsl && LL100 <= cp.t_lsl)) kLlev=aaalS*LL100+bbalS; - else if((LL100 > cp.t_rsl && LL100 <= cp.b_rsl)) kLlev=aaarS*LL100+bbbrS; - else kLlev=1.f; - } - - } - else kLlev=alpha; - - WavCoeffs_L[dir][i]*=(kLlev); - } - } -if(waOpacityCurveW) cp.opaW=true; - -if(cp.bam && cp.finena) { -if(cp.opaW && cp.BAmet==2){ - int iteration = cp.ite; - int itplus=7+iteration; - int itmoins= 7-iteration; - int med = maxlvl/2; - int it; - if(level < med) {it=itmoins; } - else if(level == med) it=7; - else if(level > med) it=itplus; - - for(int j=0; j < it; j++) { - //float bal = cp.balan;//-100 +100 - float kba=1.f; - float k1; - float k2; - // if(dir <3) kba= 1.f + bal/600.f; - // if(dir==3) kba = 1.f - bal/300.f; - for (int i=0; iL[ii*2][jj*2]/327.68f; - k1=600.f; - k2=300.f; - k1=0.3f*(waOpacityCurveW[6.f*LL100]-0.5f);//k1 between 0 and 0.5 0.5==> 1/6=0.16 - k2=k1*2.f; - if(dir <3) kba= 1.f + k1; - if(dir==3) kba = 1.f - k2; - - WavCoeffs_L[dir][i] *=(kba); - } - } -} -if(cp.BAmet==1){ - int iteration = cp.ite; - int itplus=7+iteration; - int itmoins= 7-iteration; - int med = maxlvl/2; - int it; - if(level < med) {it=itmoins; } - else if(level == med) it=7; - else if(level > med) it=itplus; - - for(int j=0; j < it; j++) { - float bal = cp.balan;//-100 +100 - float kba=1.f; - float k1; - float k2; - // if(dir <3) kba= 1.f + bal/600.f; - // if(dir==3) kba = 1.f - bal/300.f; - for (int i=0; iL[ii*2][jj*2]/327.68f; - float aa=4970.f; - float bb=-397000.f; - float b0=100000.f; - float a0=-4970.f; - if(LL100> 80.f) {k1=aa*LL100 + bb;k2=0.5f*k1;} - if(LL100< 20.f) {k1=a0*LL100 + b0;k2=0.5f*k1;} - //k1=600.f; - //k2=300.f; - //k1=0.3f*(waOpacityCurveW[6.f*LL100]-0.5f);//k1 between 0 and 0.5 0.5==> 1/6=0.16 - //k2=k1*2.f; - if(dir <3) kba= 1.f + bal/k1; - if(dir==3) kba = 1.f - bal/k2; - - WavCoeffs_L[dir][i] *=(kba); - } - } -} - -} - - // to see each level of wavelet ...level from 0 to 8 - int choicelevel = atoi(params->wavelet.Lmethod.data())-1; - choicelevel = choicelevel == -1 ? 4 : choicelevel; - } + float kc = kmul * (waOpacityCurveWL[absciss * 500.f] - 0.5f); + float reduceeffect = 1.5f; - void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, float **varchrom, float ** WavCoeffs_ab, float * WavCoeffs_ab0, int level, int dir, const WavOpacityCurveW & waOpacityCurveW, struct cont_params &cp, - int W_ab, int H_ab, const bool useChannelA) - { - float cpMul = cp.mul[level]; - if(cpMul != 0.f && cp.CHmet==2 && cp.chro != 0.f && cp.chromena) { // cpMul == 0.f or cp.chro = 0.f means all will be multiplied by 1.f, so we can skip this - const float skinprot = params->wavelet.skinprotect; - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg/100.f); - const float cpChrom = cp.chro; + if(kc <= 0.f) { + reduceeffect = 1.f; + } - //to adjust increase contrast with local contrast - bool useSkinControl = (skinprot != 0.f); - float alphaC =(1024.f + 15.f *cpMul*cpChrom/50.f)/1024.f ; - for (int i=0; iL[ii*2][jj*2]/327.68f; - float modhue = varhue[ii][jj]; - float modchro = varchrom[ii*2][jj*2]; - // hue chroma skin with initial lab datas - float scale=1.f; - if(skinprot > 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); //0 for skin and extand - } else if(skinprot < 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); - scale = (scale == 1.f) ? factorHard : 1.f; - } - alphaC =(1024.f + 15.f *cpMul*cpChrom*scale/50.f)/1024.f ; - } - WavCoeffs_ab[dir][i] *= alphaC; - } - } - //Curve chro - - float cpMulC = cp.mulC[level]; - // if( (cp.curv || cp.CHSLmet==1) && cp.CHmet!=2 && level < 9 && cpMulC != 0.f) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip - if( cp.CHmet!=2 && level < 9 && cpMulC != 0.f && cp.chromena) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip - float modchro, modhue, kClev; - const float skinprot = params->wavelet.skinprotect; - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg/100.f); - bool useSkinControl = (skinprot != 0.f); - - for (int i=0; iL[ii*2][jj*2]; - float LL100=LL/327.68f; - float scale=1.f; - modchro = varchrom[ii*2][jj*2]; - - if(useSkinControl) { - // hue chroma skin with initial lab datas - modhue = varhue[ii][jj]; - scale=1.f; - if(skinprot > 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); //1 for curve - } - else if(skinprot < 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); - scale = (scale == 1.f) ? factorHard : 1.f; - } - } - float beta = (1024.f + 20.f * cpMulC * scale)/1024.f ; - if(beta < 0.02f) - beta=0.02f; - kClev = beta; - if(cp.CHmet==1){ - if(level < cp.chrom) { - //linear for saturated - if((modchro > cp.t_lsat && modchro < cp.t_rsat)) - kClev=beta; - else if((modchro > cp.b_lsat && modchro <= cp.t_lsat)) { - float aaal=(1.f-beta)/(cp.b_lsat-cp.t_lsat); - float bbal=1.f-aaal*cp.b_lsat; - kClev=aaal*modchro+bbal; - } else if((modchro > cp.t_rsat && modchro <= cp.b_rsat)) { - float aaar=(beta-1.f)/(cp.t_rsat-cp.b_rsat); - float bbbr=1.f-cp.b_rsat*aaar; - kClev=aaar*modchro+bbbr; - } else - kClev=1.f; - } else { - //linear for pastel - if((modchro > cp.t_lpast && modchro < cp.t_rpast)) - kClev=beta; - else if((modchro > cp.b_lpast && modchro <= cp.t_lpast)) { - float aaalS=(1.f-beta)/(cp.b_lpast-cp.t_lpast); - float bbalS=1.f-aaalS*cp.b_lpast; - kClev=aaalS*modchro+bbalS; - } else if((modchro > cp.t_rpast && modchro <= cp.b_rpast)) { - float aaarS=(beta-1.f)/(cp.t_rpast-cp.b_rpast); - float bbbrS=1.f-cp.b_rpast*aaarS; - kClev=aaarS*modchro+bbbrS; - } else - kClev=1.f; - } - } - else if(cp.CHmet==0) - kClev=beta; - WavCoeffs_ab[dir][i] *= kClev; - } - } + kinterm = 1.f + reduceeffect * kmul * (waOpacityCurveWL[absciss * 500.f] - 0.5f); - bool useOpacity; - float mulOpacity; - if(useChannelA) { - useOpacity = cp.opaRG; - mulOpacity = cp.mulopaRG[level]; - } - else { - useOpacity = cp.opaBY; - mulOpacity = cp.mulopaBY[level]; - } + if(kinterm < 0.f) { + kinterm = 0.01f; + } + } - if((useOpacity && level < 9 && mulOpacity != 0.f) && cp.toningena) { //toning + WavCoeffs_L[dir][i] *= kinterm; + } + } - float beta = (1024.f + 20.f * mulOpacity)/1024.f ; - //float beta = (1000.f * mulOpacity); - for (int i=0; iwavelet.Lmethod.data()) - 1; + choicelevel = choicelevel == -1 ? 4 : choicelevel; + + int choiceClevel = 0; + + if(params->wavelet.CLmethod == "one") { + choiceClevel = 0; + } else if(params->wavelet.CLmethod == "inf") { + choiceClevel = 1; + } else if(params->wavelet.CLmethod == "sup") { + choiceClevel = 2; + } else if(params->wavelet.CLmethod == "all") { + choiceClevel = 3; + } + + int choiceDir = 0; + + if(params->wavelet.Dirmethod == "one") { + choiceDir = 1; + } else if(params->wavelet.Dirmethod == "two") { + choiceDir = 2; + } else if(params->wavelet.Dirmethod == "thr") { + choiceDir = 3; + } else if(params->wavelet.Dirmethod == "all") { + choiceDir = 0; + } + + int dir1 = (choiceDir == 2) ? 1 : 2; + int dir2 = (choiceDir == 3) ? 1 : 3; + + if(choiceClevel < 3) { // not all levels visible, paint residual + if(level == 0) { + if(cp.backm != 2) { // nothing to change when residual is used as background + float backGroundColor = (cp.backm == 1) ? 12000.f : 0.f; + + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L0[i] = backGroundColor; + } + } + } + } + + if(choiceClevel == 0) { // Only one level + + if(choiceDir == 0) { // All directions + if(level != choicelevel) { // zero all for the levels != choicelevel + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir][i] = 0.f; + } + } + } + } else { // zero the unwanted directions for level == choicelevel + + if(choicelevel >= cp.maxilev) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir][i] = 0.f; + } + } + } else if(level != choicelevel) { // zero all for the levels != choicelevel + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir1][i] = WavCoeffs_L[dir2][i] = 0.f; + } + } + } + } else if(choiceClevel == 1) { // Only below level + if(choiceDir == 0) { // All directions + if(level > choicelevel) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir][i] = 0.f; + } + } + } + } else { // zero the unwanted directions for level >= choicelevel + if(level > choicelevel) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir1][i] = WavCoeffs_L[dir2][i] = 0.f; + } + } + } + } else if(choiceClevel == 2) { // Only above level + if(choiceDir == 0) { // All directions + if(level <= choicelevel) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir][i] = 0.f; + } + } + } + } else { // zero the unwanted directions for level >= choicelevel + if(choicelevel >= cp.maxilev) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir][i] = 0.f; + } + } + } + + + else if(level <= choicelevel) { + for (int i = 0; i < W_L * H_L; i++) { + WavCoeffs_L[dir1][i] = WavCoeffs_L[dir2][i] = 0.f; + } + } + } + } + + +} + +void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschitz, int maxlvl, LabImage * labco, float ** varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params &cp, + int W_L, int H_L, int skip, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, const WavCurve & wavCLVCcurve, const WavOpacityCurveW & waOpacityCurveW, FlatCurve* ChCurve, bool Chutili) +{ + + static const float scales[10] = {1.f, 2.f, 4.f, 8.f, 16.f, 32.f, 64.f, 128.f, 256.f, 512.f}; + float scaleskip[10]; + + for(int sc = 0; sc < 10; sc++) { + scaleskip[sc] = scales[sc] / skip; + } + + float atten01234 = 0.80f; + float t_r = settings->top_right; + float t_l = settings->top_left; + float b_r = settings->bot_right; + float b_l = settings->bot_left; + float edd = settings->ed_detec; + float eddlow = settings->ed_low; + float eddstrength = settings->ed_detecStr; + float aedstr = (eddstrength - 1.f) / 90.f; + float bedstr = 1.f - 10.f * aedstr; + + bool refi = false; + + // if(cp.lev0s > 0.f || cp.lev1s > 0.f || cp.lev2s > 0.f) refi=true; + // if(cp.val > 0 || refi) {//edge + if(cp.val > 0 && cp.edgeena) { + float * koe; + float maxkoe = 0.f; + + if(lipschitz == false) { + koe = new float [H_L * W_L]; + + for (int i = 0; i < W_L * H_L; i++) { + koe[i] = 0.f; + } + + maxkoe = 0.f; + + if(cp.detectedge) {// + float** tmC; + int borderL = 1; + tmC = new float*[H_L]; + + for (int i = 0; i < H_L; i++) { + tmC[i] = new float[W_L]; + } + + { + for (int i = 1; i < H_L - 1; i++) { + for (int j = 1; j < W_L - 1; j++) { + //edge detection wavelet TMC Canny + // also possible to detect noise with 5x5 instead of 3x3 + tmC[i][j] = (4.f * WavCoeffs_L[dir][i * W_L + j] + 2.f * WavCoeffs_L[dir][(i - 1) * W_L + j] + 2.f * WavCoeffs_L[dir][(i + 1) * W_L + j] + + 2.f * WavCoeffs_L[dir][i * W_L + j + 1] + 2.f * WavCoeffs_L[dir][i * W_L + j - 1] + WavCoeffs_L[dir][(i - 1) * W_L + j - 1] + + WavCoeffs_L[dir][(i - 1) * W_L + j + 1] + WavCoeffs_L[dir][(i + 1) * W_L + j - 1] + WavCoeffs_L[dir][(i + 1) * W_L + j + 1]) / 16.f; + + // apply to each direction Wavelet level : horizontal / vertiacle / diagonal + } + } + } + + + + + for(int i = borderL; i < H_L - borderL; i++ ) { + for(int j = borderL; j < W_L - borderL; j++) { + // my own algo : probably a little false, but simpler as Lipschitz ! + float thr = 40.f; //avoid artifact eg. noise...to test + float thr2 = edd; //edd can be modified in option ed_detect + thr2 += cp.eddet / 30.f; //to test + float temp = WavCoeffs_L[dir][i * W_L + j]; + + if(temp >= 0.f && temp < thr) { + temp = thr; + } + + if(temp < 0.f && temp > -thr) { + temp = -thr; + } + + koe[i * W_L + j] = min(thr2, fabs(tmC[i][j] / temp)); + + if(koe[i * W_L + j] > maxkoe) { + maxkoe = koe[i * W_L + j]; + } + + float diff = maxkoe - koe[i * W_L + j]; + diff *= (cp.eddet / 100.f); + float interm = maxkoe - diff; + + if(interm < cp.eddetthr / 30.f) { + interm = 0.01f; + } + + koe[i * W_L + j] = interm; + + } + } + + //printf("maxkoe=%f \n",maxkoe); + + for (int i = 0; i < H_L; i++) { + delete [] tmC[i]; + } + + delete [] tmC; + + } + } + + //end detect edge + float rad = ((float)cp.rad) / 60.f; //radius ==> not too high value to avoid artifacts + float value = ((float)cp.val) / 8.f; //strength + + if (scaleskip[1] < 1.f) { + value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!! + } + + float edge = 1.f; + float lim0 = 20.f; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi + float lev = float (level); + float repart = (float)cp.til; + float brepart; + + if(cp.reinforce == 1) { + brepart = 3.f; + } + + if(cp.reinforce == 3) { + brepart = 0.5f; //arbitrary value to increase / decrease repart, between 1 and 0 + } + + float arepart = -(brepart - 1.f) / (lim0 / 60.f); + + if (cp.reinforce != 2) { + if(rad < lim0 / 60.f) { + repart *= (arepart * rad + brepart); //linear repartition of repart + } + } + + float al0 = 1.f + (repart) / 50.f; + float al10 = 1.0f; //arbitrary value ==> less = take into account high levels + // float ak =-(al0-al10)/10.f;//10 = maximum levels + float ak = -(al0 - al10) / 10.f; //10 = maximum levels + float bk = al0; + float koef = ak * level + bk; //modulate for levels : more levels high, more koef low ==> concentrated action on low levels, without or near for high levels + float expkoef = -pow(fabs(rad - lev), koef); //reduce effect for high levels + + if (cp.reinforce == 3) { + if(rad < lim0 / 60.f && level == 0) { + expkoef *= repart; //reduce effect for low values of rad and level=0==> quasi only level 1 is effective + } + } + + if (cp.reinforce == 1) { + if(rad < lim0 / 60.f && level == 1) { + expkoef /= repart; //increase effect for low values of rad and level=1==> quasi only level 0 is effective + } + } + + float coefsd = 0.85f; //arbitray value to reduce effect after sigma in all case + float coefmean = 0.85f; //arbitray value to reduce effect after sigma in all case +// edge = 1.f + value * exp (expkoef);//estimate edge "pseudo variance" + //take into account local contrast + float refin = value * exp (expkoef); + + if(cp.link == true && cp.noiseena) { //combi + { + if(level == 0) { + refin *= (1.f + cp.lev0s / 50.f); // we can change this sensibility! + } + + if(level == 1) { + refin *= (1.f + cp.lev1s / 50.f); + } + + if(level == 2) { + refin *= (1.f + cp.lev2s / 50.f); + } + + if(level == 3) { + refin *= (1.f + cp.lev3s / 50.f); + } + } + } + + float edgePrecalc = 1.f + refin; //estimate edge "pseudo variance" + + //bool exa=false; + if(cp.EDmet == 2) { //curve + // if(exa) {//curve + float insigma = 0.666f; //SD + float logmax = log(MaxP[level]); //log Max + float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max + float inx = log(insigma); + float iny = log(rapX); + float rap = inx / iny; //koef + float asig = 0.166f / sigma[level]; + float bsig = 0.5f - asig * mean[level]; + float amean = 0.5f / mean[level]; + float absciss; + float kinterm; + float kmul; + // for (int i=0; i 10.f) { + edge = (aedstr * cp.eddet + bedstr) * (edgePrecalc * (1.f + koe[k])) / (1.f + 0.9f * maxkoe); + } else { + edge = (edgePrecalc * (1.f + koe[k])) / (1.f + 0.9f * maxkoe); + } + } + + if(lipschitz == true) { + if(level < 4) { + edge = 1.f + (edgePrecalc - 1.f) * (koeLi[level * 3][k]) / (1.f + 0.9f * maxkoeLi[level * 3 + dir - 1]); + } else { + edge = edgePrecalc; + } + } + } else { + edge = edgePrecalc; + } + + if(cp.edgcurv) { + if(fabs(WavCoeffs_L[dir][k]) >= (mean[level] + sigma[level])) { //for max + float valcour = log(fabs(WavCoeffs_L[dir][k])); + float valc = valcour - logmax; + float vald = valc * rap; + absciss = exp(vald); + + } else if(fabs(WavCoeffs_L[dir][k]) >= mean[level] && fabs(WavCoeffs_L[dir][k]) < (mean[level] + sigma[level])) { + absciss = asig * fabs(WavCoeffs_L[dir][k]) + bsig; + } else if(fabs(WavCoeffs_L[dir][k]) < mean[level]) { + absciss = amean * fabs(WavCoeffs_L[dir][k]); + } + + // Threshold adjuster settings==> approximative for curve + //kmul about average cbrt(3--40 / 10)==>1.5 to 2.5 + //kmul about SD 10--60 / 35 ==> 2 + // kmul about low cbrt((5.f+cp.edg_low)/5.f);==> 1.5 + // kmul about max ==> 9 + // we can change these values + // result is different not best or bad than threshold slider...but similar + float abssd = 4.f; //amplification reference + float bbssd = 2.f; //mini ampli + float maxamp = 2.5f; //maxi ampli at end + float maxampd = 10.f; //maxi ampli at end + float a_abssd = (maxamp - abssd) / 0.333f; + float b_abssd = maxamp - a_abssd; + float da_abssd = (maxampd - abssd) / 0.333f; + float db_abssd = maxampd - da_abssd; + float am = (abssd - bbssd) / 0.666f; + float kmuld = 0.f; + + if(absciss > 0.666f && absciss < 1.f) { + kmul = a_abssd * absciss + b_abssd; //about max ==> kinterm + kmuld = da_abssd * absciss + db_abssd; + } else { + kmul = kmuld = absciss * am + bbssd; + } + + kinterm = 1.f; + float kc = kmul * (wavCLVCcurve[absciss * 500.f] - 0.5f); + float kcd = kmuld * (wavCLVCcurve[absciss * 500.f] - 0.5f); + float reduceeffect = 0.6f; + + if(kc >= 0.f) { + kinterm = 1.f + reduceeffect * kmul * (wavCLVCcurve[absciss * 500.f] - 0.5f); //about 1 to 3 general and big amplification for max (under 0) + } else { + kinterm = 1.f - (SQR(kcd)) / 10.f; + } + + if(kinterm < 0.f) { + kinterm = 0.01f; + } + + edge *= kinterm; + + if(edge < 1.f) { + edge = 1.f; + } + } + + WavCoeffs_L[dir][k] *= edge; + } + } + } else if(cp.EDmet == 1) { //threshold adjuster + float MaxPCompare = MaxP[level] * SQR(cp.edg_max / 100.f); //100 instead of b_r...case if b_r < 100 + float MaxNCompare = MaxN[level] * SQR(cp.edg_max / 100.f); //always rduce a little edge for near max values + float edgeSdCompare = (mean[level] + 1.5f * sigma[level]) * SQR(cp.edg_sd / t_r); // 1.5 standard deviation #80% range between mean 50% and 80% + float edgeMeanCompare = mean[level] * SQR(cp.edg_mean / t_l); + float edgeLowCompare = (5.f + SQR(cp.edg_low)); + float edgeMeanFactor = cbrt(cp.edg_mean / t_l); + float interm; + + if(cp.edg_low < 10.f) { + interm = cbrt((5.f + cp.edg_low) / 5.f); + } else { + interm = 1.437f; //cbrt(3); + } + + float edgeLowFactor = interm; + float edgeSdFactor = cp.edg_sd / t_r; + float edgeMaxFactor = SQR(cp.edg_max / b_r); + float edgMaxFsup = (cp.edg_max / b_r); //reduce increase of effect for high values contrast..if slider > b_r + + //for (int i=0; i 10.f) { + edge = (aedstr * cp.eddet + bedstr) * (edgePrecalc * (1.f + koe[k])) / (1.f + 0.9f * maxkoe); + } else { + edge = (edgePrecalc * (1.f + koe[k])) / (1.f + 0.9f * maxkoe); + } + } + + if(lipschitz == true) { + if(level < 4) { + edge = 1.f + (edgePrecalc - 1.f) * (koeLi[level * 3][k]) / (1.f + 0.9f * maxkoeLi[level * 3 + dir - 1]); + } else { + edge = edgePrecalc; + } + } + } else { + edge = edgePrecalc; + } + + //algorithm that take into account local contrast + // I use a thresholdadjuster with + // Bottom left ==> minimal low value for local contrast (not 0, but 5...we can change) + // 0 10*10 35*35 100*100 substantially correspond to the true distribution of low value, mean, standard-deviation and max (ed 5, 50, 400, 4000 + // Top left ==> mean reference value (for each level), we can change cbrt(cp.edg_mean/10.f) + // Top Right==> standard deviation (for each level) we can change (cp.edg_sd/35.f) + // bottom right ==> Max for positif and negatif contrast we can change cp.edg_max/100.f + // If we move sliders to the left, local contrast is reduced + // if we move sliders to the right local contrast is increased + // MaxP, MaxN, mean, sigma are calculated if necessary (val > 0) by evaluate2(), eval2(), aver() , sigma() + if(b_r < 100.f && cp.edg_max / b_r > 1.f) { //in case of b_r < 100 and slider move to right + if (WavCoeffs_L[dir][k] > MaxPCompare * cp.edg_max / b_r) { + edge *= edgMaxFsup; + + if(edge < 1.f) { + edge = 1.f; + } + } else if (WavCoeffs_L[dir][k] < MaxNCompare * cp.edg_max / b_r) { + edge *= edgMaxFsup; + + if(edge < 1.f) { + edge = 1.f; + } + } + } + + if (WavCoeffs_L[dir][k] > MaxPCompare) { + edge *= edgeMaxFactor; + + if(edge < 1.f) { + edge = 1.f; + } + }//reduce edge if > new max + else if (WavCoeffs_L[dir][k] < MaxNCompare) { + edge *= edgeMaxFactor; + + if(edge < 1.f) { + edge = 1.f; + } + } + + if (fabs(WavCoeffs_L[dir][k]) >= edgeMeanCompare && fabs(WavCoeffs_L[dir][k]) < edgeSdCompare) { + //if (fabs(WavCoeffs_L[dir][i]) > edgeSdCompare) { + edge *= edgeSdFactor; + + if(edge < 1.f) { + edge = 1.f; + } + }//mofify effect if sd change + + if (fabs(WavCoeffs_L[dir][k]) < edgeMeanCompare) { + edge *= edgeMeanFactor; + + if(edge < 1.f) { + edge = 1.f; + } + } // modify effect if mean change + + if (fabs(WavCoeffs_L[dir][k]) < edgeLowCompare) { + edge *= edgeLowFactor; + + if(edge < 1.f) { + edge = 1.f; + } + } + + WavCoeffs_L[dir][k] *= edge; + } + } + } + + if(lipschitz == false) { + delete [] koe; + } + } + + + if(cp.link == false && cp.noiseena) { //used both with denoise 1 2 3 + float refine = 0.f; + + for (int i = 0; i < W_L * H_L; i++) { + if(level == 0) { + refine = cp.lev0s / 40.f; + } + + if(level == 1) { + refine = cp.lev1s / 40.f; + } + + if(level == 2) { + refine = cp.lev2s / 40.f; + } + + if(level == 3) { + refine = cp.lev3s / 40.f; + } + + WavCoeffs_L[dir][i] *= (1.f + refine); + } + } + + + float cpMul = cp.mul[level]; + + if(cpMul != 0.f && cp.contena) { // cpMul == 0.f means all will be multiplied by 1.f, so we can skip this + + const float skinprot = params->wavelet.skinprotect; + const float skinprotneg = -skinprot; + const float factorHard = (1.f - skinprotneg / 100.f); + + //to adjust increase contrast with local contrast + + //for each pixel and each level + float beta; + float mea[9]; + mea[0] = mean[level] / 6.f; + mea[1] = mean[level] / 2.f; + mea[2] = mean[level]; // 50% data + mea[3] = mean[level] + sigma[level] / 2.f; + mea[4] = mean[level] + sigma[level]; //66% + mea[5] = mean[level] + 1.2f * sigma[level]; + mea[6] = mean[level] + 1.5f * sigma[level]; // + mea[7] = mean[level] + 2.f * sigma[level]; //95% + mea[8] = mean[level] + 2.5f * sigma[level]; //99% + + bool skinControl = (skinprot != 0.f); + bool useChromAndHue = (skinprot != 0.f || cp.HSmet); + float modchro, kLlev; + + for (int i = 0; i < W_L * H_L; i++) { + kLlev = 1.f; + + if(cpMul < 0.f) { + beta = 1.f; // disabled for negatives values "less contrast" + } else { + float WavCL = fabsf(WavCoeffs_L[dir][i]); + + //reduction amplification: max action between mean / 2 and mean + sigma + // arbitrary coefficient, we can add a slider !! + if(WavCL < mea[0]) { + beta = 0.6f; //preserve very low contrast (sky...) + } else if(WavCL < mea[1]) { + beta = 0.8f; + } else if(WavCL < mea[2]) { + beta = 1.f; //standard + } else if(WavCL < mea[3]) { + beta = 1.f; + } else if(WavCL < mea[4]) { + beta = 0.8f; //+sigma + } else if(WavCL < mea[5]) { + beta = 0.6f; + } else if(WavCL < mea[6]) { + beta = 0.4f; + } else if(WavCL < mea[7]) { + beta = 0.2f; // + 2 sigma + } else if(WavCL < mea[8]) { + beta = 0.1f; + } else { + beta = 0.0f; + } + } + + float scale = 1.f; + float scale2 = 1.f; + + float LL100, LL100res, LL100init, kH[maxlvl]; + int ii = i / W_L; + int jj = i - ii * W_L; + float LL = labco->L[ii * 2][jj * 2]; + LL100 = LL100init = LL / 327.68f; + LL100res = WavCoeffs_L0[i] / 327.68f; + float delta = fabs(LL100init - LL100res) / (maxlvl / 2); + + for(int ml = 0; ml < maxlvl; ml++) { + if(ml < maxlvl / 2) { + kH[ml] = (LL100res + ml * delta) / LL100res; // fixed a priori max to level middle + } else { + kH[ml] = (LL100init - ml * delta) / LL100res; + } + } + + + if(useChromAndHue) { + /* + int ii=i/W_L; + int jj=i-ii*W_L; + float LL = labco->L[ii*2][jj*2]; + LL100=LL100init=LL/327.68f; + LL100res=WavCoeffs_L0[i]/327.68f; + float delta=fabs(LL100init-LL100res)/(maxlvl/2); + for(int ml=0;ml 0.f) { + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); //0 for skin and extand + } else if(skinprot < 0.f) { + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); + + if (scale == 1.f) { + scale = factorHard; + } else { + scale = 1.f; + } + } + + } + + if(Chutili) { + int i_i = i / W_L; + int j_j = i - i_i * W_L; + double lr; + float modhue2 = varhue[i_i][j_j]; + float valparam = float((ChCurve->getVal(lr = Color::huelab_to_huehsv2(modhue2)) - 0.5f)); //get valparam=f(H) + + if(valparam > 0.f) { + scale2 = 1.f + 3.f * valparam; //arbitrary value + } else { + scale2 = 1.f + 1.9f * valparam; //near 0 but not zero if curve # 0 + } + + //curve Contrast / hue + + } + + // + //linear transition HL + float diagacc = 1.f; + /* + if(cp.diag) { + if(dir <=2) diagacc=0.75f; + if(dir ==3) diagacc=1.5f; + } + */ + float alpha = (1024.f + 15.f * (float) cpMul * scale * scale2 * beta * diagacc) / 1024.f ; + + if(cp.HSmet && cp.chromena) { + float aaal = (1.f - alpha) / ((cp.b_lhl - cp.t_lhl) * kH[level]); + float bbal = 1.f - aaal * cp.b_lhl * kH[level]; + float aaar = (alpha - 1.f) / (cp.t_rhl - cp.b_rhl) * kH[level]; + float bbbr = 1.f - cp.b_rhl * aaar * kH[level]; + //linear transition Shadows + float aaalS = (1.f - alpha) / (cp.b_lsl - cp.t_lsl); + float bbalS = 1.f - aaalS * cp.b_lsl; + float aaarS = (alpha - 1.f) / (cp.t_rsl - cp.b_rsl); + float bbbrS = 1.f - cp.b_rsl * aaarS; + + if(level <= cp.numlevH) { //in function of levels + if((LL100 > cp.t_lhl * kH[level] && LL100 < cp.t_rhl * kH[level])) { + kLlev = alpha; + } else if((LL100 > cp.b_lhl * kH[level] && LL100 <= cp.t_lhl * kH[level])) { + kLlev = aaal * LL100 + bbal; + } else if((LL100 > cp.t_rhl * kH[level] && LL100 <= cp.b_rhl * kH[level])) { + kLlev = aaar * LL100 + bbbr; + } else { + kLlev = 1.f; + } + } + + if(level >= (9 - cp.numlevS)) { + if((LL100 > cp.t_lsl && LL100 < cp.t_rsl)) { + kLlev = alpha; + } else if((LL100 > cp.b_lsl && LL100 <= cp.t_lsl)) { + kLlev = aaalS * LL100 + bbalS; + } else if((LL100 > cp.t_rsl && LL100 <= cp.b_rsl)) { + kLlev = aaarS * LL100 + bbbrS; + } else { + kLlev = 1.f; + } + } + + } else { + kLlev = alpha; + } + + WavCoeffs_L[dir][i] *= (kLlev); + } + } + + if(waOpacityCurveW) { + cp.opaW = true; + } + + if(cp.bam && cp.finena) { + if(cp.opaW && cp.BAmet == 2) { + int iteration = cp.ite; + int itplus = 7 + iteration; + int itmoins = 7 - iteration; + int med = maxlvl / 2; + int it; + + if(level < med) { + it = itmoins; + } else if(level == med) { + it = 7; + } else if(level > med) { + it = itplus; + } + + for(int j = 0; j < it; j++) { + //float bal = cp.balan;//-100 +100 + float kba = 1.f; + float k1; + float k2; + + // if(dir <3) kba= 1.f + bal/600.f; + // if(dir==3) kba = 1.f - bal/300.f; + for (int i = 0; i < W_L * H_L; i++) { + int ii = i / W_L; + int jj = i - ii * W_L; + float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; + k1 = 600.f; + k2 = 300.f; + k1 = 0.3f * (waOpacityCurveW[6.f * LL100] - 0.5f); //k1 between 0 and 0.5 0.5==> 1/6=0.16 + k2 = k1 * 2.f; + + if(dir < 3) { + kba = 1.f + k1; + } + + if(dir == 3) { + kba = 1.f - k2; + } + + WavCoeffs_L[dir][i] *= (kba); + } + } + } + + if(cp.BAmet == 1) { + int iteration = cp.ite; + int itplus = 7 + iteration; + int itmoins = 7 - iteration; + int med = maxlvl / 2; + int it; + + if(level < med) { + it = itmoins; + } else if(level == med) { + it = 7; + } else if(level > med) { + it = itplus; + } + + for(int j = 0; j < it; j++) { + float bal = cp.balan;//-100 +100 + float kba = 1.f; + float k1; + float k2; + + // if(dir <3) kba= 1.f + bal/600.f; + // if(dir==3) kba = 1.f - bal/300.f; + for (int i = 0; i < W_L * H_L; i++) { + int ii = i / W_L; + int jj = i - ii * W_L; + k1 = 600.f; + k2 = 300.f; + float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; + float aa = 4970.f; + float bb = -397000.f; + float b0 = 100000.f; + float a0 = -4970.f; + + if(LL100 > 80.f) { + k1 = aa * LL100 + bb; + k2 = 0.5f * k1; + } + + if(LL100 < 20.f) { + k1 = a0 * LL100 + b0; + k2 = 0.5f * k1; + } + + //k1=600.f; + //k2=300.f; + //k1=0.3f*(waOpacityCurveW[6.f*LL100]-0.5f);//k1 between 0 and 0.5 0.5==> 1/6=0.16 + //k2=k1*2.f; + if(dir < 3) { + kba = 1.f + bal / k1; + } + + if(dir == 3) { + kba = 1.f - bal / k2; + } + + WavCoeffs_L[dir][i] *= (kba); + } + } + } + + } + + // to see each level of wavelet ...level from 0 to 8 + int choicelevel = atoi(params->wavelet.Lmethod.data()) - 1; + choicelevel = choicelevel == -1 ? 4 : choicelevel; +} + +void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, float **varchrom, float ** WavCoeffs_ab, float * WavCoeffs_ab0, int level, int dir, const WavOpacityCurveW & waOpacityCurveW, struct cont_params &cp, + int W_ab, int H_ab, const bool useChannelA) +{ + float cpMul = cp.mul[level]; + + if(cpMul != 0.f && cp.CHmet == 2 && cp.chro != 0.f && cp.chromena) { // cpMul == 0.f or cp.chro = 0.f means all will be multiplied by 1.f, so we can skip this + const float skinprot = params->wavelet.skinprotect; + const float skinprotneg = -skinprot; + const float factorHard = (1.f - skinprotneg / 100.f); + const float cpChrom = cp.chro; + + //to adjust increase contrast with local contrast + bool useSkinControl = (skinprot != 0.f); + float alphaC = (1024.f + 15.f * cpMul * cpChrom / 50.f) / 1024.f ; + + for (int i = 0; i < W_ab * H_ab; i++) { + if(useSkinControl) { + int ii = i / W_ab; + int jj = i - ii * W_ab; + float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; + float modhue = varhue[ii][jj]; + float modchro = varchrom[ii * 2][jj * 2]; + // hue chroma skin with initial lab datas + float scale = 1.f; + + if(skinprot > 0.f) { + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); //0 for skin and extand + } else if(skinprot < 0.f) { + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); + scale = (scale == 1.f) ? factorHard : 1.f; + } + + alphaC = (1024.f + 15.f * cpMul * cpChrom * scale / 50.f) / 1024.f ; + } + + WavCoeffs_ab[dir][i] *= alphaC; + } + } + + //Curve chro + + float cpMulC = cp.mulC[level]; + + // if( (cp.curv || cp.CHSLmet==1) && cp.CHmet!=2 && level < 9 && cpMulC != 0.f) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip + if( cp.CHmet != 2 && level < 9 && cpMulC != 0.f && cp.chromena) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip + float modchro, modhue, kClev; + const float skinprot = params->wavelet.skinprotect; + const float skinprotneg = -skinprot; + const float factorHard = (1.f - skinprotneg / 100.f); + bool useSkinControl = (skinprot != 0.f); + + for (int i = 0; i < W_ab * H_ab; i++) { + int ii = i / W_ab; + int jj = i - ii * W_ab; + //WL and W_ab are identical + float LL = labco->L[ii * 2][jj * 2]; + float LL100 = LL / 327.68f; + float scale = 1.f; + modchro = varchrom[ii * 2][jj * 2]; + + if(useSkinControl) { + // hue chroma skin with initial lab datas + modhue = varhue[ii][jj]; + scale = 1.f; + + if(skinprot > 0.f) { + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); //1 for curve + } else if(skinprot < 0.f) { + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); + scale = (scale == 1.f) ? factorHard : 1.f; + } + } + + float beta = (1024.f + 20.f * cpMulC * scale) / 1024.f ; + + if(beta < 0.02f) { + beta = 0.02f; + } + + kClev = beta; + + if(cp.CHmet == 1) { + if(level < cp.chrom) { + //linear for saturated + if((modchro > cp.t_lsat && modchro < cp.t_rsat)) { + kClev = beta; + } else if((modchro > cp.b_lsat && modchro <= cp.t_lsat)) { + float aaal = (1.f - beta) / (cp.b_lsat - cp.t_lsat); + float bbal = 1.f - aaal * cp.b_lsat; + kClev = aaal * modchro + bbal; + } else if((modchro > cp.t_rsat && modchro <= cp.b_rsat)) { + float aaar = (beta - 1.f) / (cp.t_rsat - cp.b_rsat); + float bbbr = 1.f - cp.b_rsat * aaar; + kClev = aaar * modchro + bbbr; + } else { + kClev = 1.f; + } + } else { + //linear for pastel + if((modchro > cp.t_lpast && modchro < cp.t_rpast)) { + kClev = beta; + } else if((modchro > cp.b_lpast && modchro <= cp.t_lpast)) { + float aaalS = (1.f - beta) / (cp.b_lpast - cp.t_lpast); + float bbalS = 1.f - aaalS * cp.b_lpast; + kClev = aaalS * modchro + bbalS; + } else if((modchro > cp.t_rpast && modchro <= cp.b_rpast)) { + float aaarS = (beta - 1.f) / (cp.t_rpast - cp.b_rpast); + float bbbrS = 1.f - cp.b_rpast * aaarS; + kClev = aaarS * modchro + bbbrS; + } else { + kClev = 1.f; + } + } + } else if(cp.CHmet == 0) { + kClev = beta; + } + + WavCoeffs_ab[dir][i] *= kClev; + } + } + + bool useOpacity; + float mulOpacity; + + if(useChannelA) { + useOpacity = cp.opaRG; + mulOpacity = cp.mulopaRG[level]; + } else { + useOpacity = cp.opaBY; + mulOpacity = cp.mulopaBY[level]; + } + + if((useOpacity && level < 9 && mulOpacity != 0.f) && cp.toningena) { //toning + + float beta = (1024.f + 20.f * mulOpacity) / 1024.f ; + + //float beta = (1000.f * mulOpacity); + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir][i] *= beta; + } + + // WavCoeffs_ab[dir][i] += beta; + } + + if(waOpacityCurveW) { + cp.opaW = true; + } + + if(cp.bam && cp.diag) { //printf("OK Chroma\n"); -if(cp.opaW && cp.BAmet==2){ - int iteration = cp.ite; - int itplus=7+iteration; - int itmoins= 7-iteration; - int med = maxlvl/2; - int it; - if(level < med) {it=itmoins; } - else if(level == med) it=7; - else if(level > med) it=itplus; - - for(int j=0; j < it; j++) { - //float bal = cp.balan;//-100 +100 - float kba=1.f; - float k1; - float k2; - // if(dir <3) kba= 1.f + bal/600.f; - // if(dir==3) kba = 1.f - bal/300.f; - for (int i=0; iL[ii*2][jj*2]/327.68f; - k1=600.f; - k2=300.f; - k1=0.3f*(waOpacityCurveW[6.f*LL100]-0.5f);//k1 between 0 and 0.5 0.5==> 1/6=0.16 - k2=k1*2.f; - if(dir <3) kba= 1.f + k1; - if(dir==3) kba = 1.f - k2; - - WavCoeffs_ab[dir][i] *=(kba); - } - } -} -if(cp.BAmet==1){ - int iteration = cp.ite; - int itplus=7+iteration; - int itmoins= 7-iteration; - int med = maxlvl/2; - int it; - if(level < med) {it=itmoins; } - else if(level == med) it=7; - else if(level > med) it=itplus; - - for(int j=0; j < it; j++) { - float bal = cp.balan;//-100 +100 - float kba=1.f; - float k1; - float k2; - // if(dir <3) kba= 1.f + bal/600.f; - // if(dir==3) kba = 1.f - bal/300.f; - for (int i=0; iL[ii*2][jj*2]/327.68f; - float aa=4970.f; - float bb=-397000.f; - float b0=100000.f; - float a0=-4970.f; - if(LL100> 80.f) {k1=aa*LL100 + bb;k2=0.5f*k1;} - if(LL100< 20.f) {k1=a0*LL100 + b0;k2=0.5f*k1;} - //k1=600.f; - //k2=300.f; - //k1=0.3f*(waOpacityCurveW[6.f*LL100]-0.5f);//k1 between 0 and 0.5 0.5==> 1/6=0.16 - //k2=k1*2.f; - if(dir <3) kba= 1.f + bal/k1; - if(dir==3) kba = 1.f - bal/k2; - - WavCoeffs_ab[dir][i] *=(kba); - } - } -} - -} - - // to see each level of wavelet ...level from 0 to 8 - int choicelevel = atoi(params->wavelet.Lmethod.data())-1; - choicelevel = choicelevel == -1 ? 4 : choicelevel; - int choiceClevel=0; - if(params->wavelet.CLmethod=="one") choiceClevel=0; - else if(params->wavelet.CLmethod=="inf") choiceClevel=1; - else if(params->wavelet.CLmethod=="sup") choiceClevel=2; - else if(params->wavelet.CLmethod=="all") choiceClevel=3; - int choiceDir=0; - if(params->wavelet.Dirmethod=="one") choiceDir=1; - else if(params->wavelet.Dirmethod=="two") choiceDir=2; - else if(params->wavelet.Dirmethod=="thr") choiceDir=3; - else if(params->wavelet.Dirmethod=="all") choiceDir=0; + if(cp.opaW && cp.BAmet == 2) { + int iteration = cp.ite; + int itplus = 7 + iteration; + int itmoins = 7 - iteration; + int med = maxlvl / 2; + int it; - int dir1 = (choiceDir == 2) ? 1 : 2; - int dir2 = (choiceDir == 3) ? 1 : 3; - if(choiceClevel<3) { // not all levels visible, paint residual - if(level == 0) { - if(cp.backm!=2) { // nothing to change when residual is used as background - float backGroundChroma = (cp.backm==1) ? 0.f : 0.f;//we can change first to colorized... - for (int i=0; i= cp.maxilev) { - for (int dir=1; dir<4; dir++) { - for (int i=0; i choicelevel) { - for (int dir=1; dir<4; dir++) { - for (int i=0; i= choicelevel - if(level > choicelevel) { - for (int i=0; i= choicelevel - if(choicelevel >= cp.maxilev) { - for (int dir=1; dir<4; dir++) { - for (int i=0; i med) { + it = itplus; + } + + for(int j = 0; j < it; j++) { + //float bal = cp.balan;//-100 +100 + float kba = 1.f; + float k1; + float k2; + + // if(dir <3) kba= 1.f + bal/600.f; + // if(dir==3) kba = 1.f - bal/300.f; + for (int i = 0; i < W_ab * H_ab; i++) { + int ii = i / W_ab; + int jj = i - ii * W_ab; + float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; + k1 = 600.f; + k2 = 300.f; + k1 = 0.3f * (waOpacityCurveW[6.f * LL100] - 0.5f); //k1 between 0 and 0.5 0.5==> 1/6=0.16 + k2 = k1 * 2.f; + + if(dir < 3) { + kba = 1.f + k1; + } + + if(dir == 3) { + kba = 1.f - k2; + } + + WavCoeffs_ab[dir][i] *= (kba); + } + } + } + + if(cp.BAmet == 1) { + int iteration = cp.ite; + int itplus = 7 + iteration; + int itmoins = 7 - iteration; + int med = maxlvl / 2; + int it; + + if(level < med) { + it = itmoins; + } else if(level == med) { + it = 7; + } else if(level > med) { + it = itplus; + } + + for(int j = 0; j < it; j++) { + float bal = cp.balan;//-100 +100 + float kba = 1.f; + float k1; + float k2; + + // if(dir <3) kba= 1.f + bal/600.f; + // if(dir==3) kba = 1.f - bal/300.f; + for (int i = 0; i < W_ab * H_ab; i++) { + int ii = i / W_ab; + int jj = i - ii * W_ab; + k1 = 600.f; + k2 = 300.f; + float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; + float aa = 4970.f; + float bb = -397000.f; + float b0 = 100000.f; + float a0 = -4970.f; + + if(LL100 > 80.f) { + k1 = aa * LL100 + bb; + k2 = 0.5f * k1; + } + + if(LL100 < 20.f) { + k1 = a0 * LL100 + b0; + k2 = 0.5f * k1; + } + + //k1=600.f; + //k2=300.f; + //k1=0.3f*(waOpacityCurveW[6.f*LL100]-0.5f);//k1 between 0 and 0.5 0.5==> 1/6=0.16 + //k2=k1*2.f; + if(dir < 3) { + kba = 1.f + bal / k1; + } + + if(dir == 3) { + kba = 1.f - bal / k2; + } + + WavCoeffs_ab[dir][i] *= (kba); + } + } + } + + } + + // to see each level of wavelet ...level from 0 to 8 + int choicelevel = atoi(params->wavelet.Lmethod.data()) - 1; + choicelevel = choicelevel == -1 ? 4 : choicelevel; + int choiceClevel = 0; + + if(params->wavelet.CLmethod == "one") { + choiceClevel = 0; + } else if(params->wavelet.CLmethod == "inf") { + choiceClevel = 1; + } else if(params->wavelet.CLmethod == "sup") { + choiceClevel = 2; + } else if(params->wavelet.CLmethod == "all") { + choiceClevel = 3; + } + + int choiceDir = 0; + + if(params->wavelet.Dirmethod == "one") { + choiceDir = 1; + } else if(params->wavelet.Dirmethod == "two") { + choiceDir = 2; + } else if(params->wavelet.Dirmethod == "thr") { + choiceDir = 3; + } else if(params->wavelet.Dirmethod == "all") { + choiceDir = 0; + } + + int dir1 = (choiceDir == 2) ? 1 : 2; + int dir2 = (choiceDir == 3) ? 1 : 3; + + if(choiceClevel < 3) { // not all levels visible, paint residual + if(level == 0) { + if(cp.backm != 2) { // nothing to change when residual is used as background + float backGroundChroma = (cp.backm == 1) ? 0.f : 0.f; //we can change first to colorized... + + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab0[i] = backGroundChroma; + } + } + } + } + + if(choiceClevel == 0) { // Only one level + if(choiceDir == 0) { // All directions + if(level != choicelevel) { // zero all for the levels != choicelevel + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir][i] = 0.f; + } + } + } + } else { // zero the unwanted directions for level == choicelevel + if(choicelevel >= cp.maxilev) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir][i] = 0.f; + } + } + } else if(level != choicelevel) { // zero all for the levels != choicelevel + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir1][i] = WavCoeffs_ab[dir2][i] = 0.f; + } + } + } + } else if(choiceClevel == 1) { // Only below level + if(choiceDir == 0) { // All directions + if(level > choicelevel) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir][i] = 0.f; + } + } + } + } else { // zero the unwanted directions for level >= choicelevel + if(level > choicelevel) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir1][i] = WavCoeffs_ab[dir2][i] = 0.f; + } + } + } + } else if(choiceClevel == 2) { // Only above level + if(choiceDir == 0) { // All directions + if(level <= choicelevel) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir][i] = 0.f; + } + } + } + } else { // zero the unwanted directions for level >= choicelevel + if(choicelevel >= cp.maxilev) { + for (int dir = 1; dir < 4; dir++) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir][i] = 0.f; + } + } + } else if(level <= choicelevel) { + for (int i = 0; i < W_ab * H_ab; i++) { + WavCoeffs_ab[dir1][i] = WavCoeffs_ab[dir2][i] = 0.f; + } + } + } + } +} } diff --git a/rtengine/jdatasrc.cc b/rtengine/jdatasrc.cc index 92cc3492f..c8567387b 100644 --- a/rtengine/jdatasrc.cc +++ b/rtengine/jdatasrc.cc @@ -34,17 +34,17 @@ /* Expanded data source object for stdio input */ typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - jmp_buf error_jmp_buf; /* error handler for this instance */ + struct jpeg_source_mgr pub; /* public fields */ + jmp_buf error_jmp_buf; /* error handler for this instance */ - FILE * infile; /* source stream */ - JOCTET * buffer; /* start of buffer */ - boolean start_of_file; /* have we gotten any data yet? */ + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; -#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ /* @@ -55,13 +55,13 @@ typedef my_source_mgr * my_src_ptr; METHODDEF(void) my_init_source (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; } @@ -101,29 +101,32 @@ my_init_source (j_decompress_ptr cinfo) METHODDEF(boolean) my_fill_input_buffer (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; - size_t nbytes; + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; - nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); - if (nbytes == 0) { - if (src->start_of_file) /* Treat empty input file as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - WARNMS(cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - } + if (nbytes == 0) { + if (src->start_of_file) { /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + } - if (src->start_of_file) - src->buffer[0] = (JOCTET) 0xFF; + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; + if (src->start_of_file) { + src->buffer[0] = (JOCTET) 0xFF; + } - return TRUE; + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; } @@ -142,23 +145,24 @@ my_fill_input_buffer (j_decompress_ptr cinfo) METHODDEF(void) my_skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) my_fill_input_buffer(cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) my_fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } } @@ -183,7 +187,7 @@ my_skip_input_data (j_decompress_ptr cinfo, long num_bytes) METHODDEF(void) my_term_source (j_decompress_ptr cinfo) { - /* no work necessary here */ + /* no work necessary here */ } @@ -196,48 +200,48 @@ my_term_source (j_decompress_ptr cinfo) GLOBAL(void) my_jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) { - my_src_ptr src; + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * sizeof(JOCTET)); + } - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_stdio_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof(my_source_mgr)); src = (my_src_ptr) cinfo->src; - src->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * sizeof(JOCTET)); - } - - src = (my_src_ptr) cinfo->src; - src->pub.init_source = my_init_source; - src->pub.fill_input_buffer = my_fill_input_buffer; - src->pub.skip_input_data = my_skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = my_term_source; - src->infile = infile; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ + src->pub.init_source = my_init_source; + src->pub.fill_input_buffer = my_fill_input_buffer; + src->pub.skip_input_data = my_skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = my_term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ } METHODDEF(void) my_error_exit (j_common_ptr cinfo) { - /* Always display the message */ - (*cinfo->err->output_message) (cinfo); + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); - /* Let the memory manager delete any temp files before we die */ - //jpeg_destroy(cinfo); + /* Let the memory manager delete any temp files before we die */ + //jpeg_destroy(cinfo); - j_decompress_ptr dinfo = (j_decompress_ptr)cinfo; + j_decompress_ptr dinfo = (j_decompress_ptr)cinfo; // longjmp (((rt_jpeg_error_mgr*)(dinfo->src))->error_jmp_buf, 1); - longjmp ((reinterpret_cast(dinfo->src)) ->error_jmp_buf, 1); + longjmp ((reinterpret_cast(dinfo->src)) ->error_jmp_buf, 1); } @@ -266,18 +270,18 @@ extern const char * const jpeg_std_message_table[]; METHODDEF(void) output_message (j_common_ptr cinfo) { - char buffer[JMSG_LENGTH_MAX]; + char buffer[JMSG_LENGTH_MAX]; - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffer); + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); #ifdef USE_WINDOWS_MESSAGEBOX - /* Display it in a message dialog box */ - MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", - MB_OK | MB_ICONERROR); + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); #else - /* Send it to stderr, adding a newline */ - fprintf(stderr, "%s\n", buffer); + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); #endif } @@ -296,22 +300,25 @@ output_message (j_common_ptr cinfo) METHODDEF(void) emit_message (j_common_ptr cinfo, int msg_level) { - struct jpeg_error_mgr * err = cinfo->err; + struct jpeg_error_mgr * err = cinfo->err; - if (msg_level < 0) { - /* It's a warning message. Since corrupt files may generate many warnings, - * the policy implemented here is to show only the first warning, - * unless trace_level >= 3. - */ - if (err->num_warnings == 0 || err->trace_level >= 3) - (*err->output_message) (cinfo); - /* Always count warnings in num_warnings. */ - err->num_warnings++; - } else { - /* It's a trace message. Show it if trace_level >= msg_level. */ - if (err->trace_level >= msg_level) - (*err->output_message) (cinfo); - } + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) { + (*err->output_message) (cinfo); + } + + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) { + (*err->output_message) (cinfo); + } + } } @@ -325,47 +332,51 @@ emit_message (j_common_ptr cinfo, int msg_level) METHODDEF(void) format_message (j_common_ptr cinfo, char * buffer) { - struct jpeg_error_mgr * err = cinfo->err; - int msg_code = err->msg_code; - const char * msgtext = NULL; - const char * msgptr; - char ch; - boolean isstring; + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; - /* Look up message string in proper table */ - if (msg_code > 0 && msg_code <= err->last_jpeg_message) { - msgtext = err->jpeg_message_table[msg_code]; - } else if (err->addon_message_table != NULL && - msg_code >= err->first_addon_message && - msg_code <= err->last_addon_message) { - msgtext = err->addon_message_table[msg_code - err->first_addon_message]; - } - - /* Defend against bogus message number */ - if (msgtext == NULL) { - err->msg_parm.i[0] = msg_code; - msgtext = err->jpeg_message_table[0]; - } - - /* Check for string parameter, as indicated by %s in the message text */ - isstring = FALSE; - msgptr = msgtext; - while ((ch = *msgptr++) != '\0') { - if (ch == '%') { - if (*msgptr == 's') isstring = TRUE; - break; + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; } - } - /* Format the message into the passed buffer */ - if (isstring) - sprintf(buffer, msgtext, err->msg_parm.s); - else - sprintf(buffer, msgtext, - err->msg_parm.i[0], err->msg_parm.i[1], - err->msg_parm.i[2], err->msg_parm.i[3], - err->msg_parm.i[4], err->msg_parm.i[5], - err->msg_parm.i[6], err->msg_parm.i[7]); + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') { + isstring = TRUE; + } + + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) { + sprintf(buffer, msgtext, err->msg_parm.s); + } else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); } @@ -380,9 +391,9 @@ format_message (j_common_ptr cinfo, char * buffer) METHODDEF(void) reset_error_mgr (j_common_ptr cinfo) { - cinfo->err->num_warnings = 0; - /* trace_level is not reset since it is an application-supplied parameter */ - cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ } @@ -390,23 +401,23 @@ GLOBAL(struct jpeg_error_mgr *) my_jpeg_std_error (struct jpeg_error_mgr * err) { - err->error_exit = my_error_exit; - err->emit_message = emit_message; - err->output_message = output_message; - err->format_message = format_message; - err->reset_error_mgr = reset_error_mgr; + err->error_exit = my_error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; - err->trace_level = 0; /* default = no tracing */ - err->num_warnings = 0; /* no warnings emitted yet */ - err->msg_code = 0; /* may be useful as a flag for "no error" */ + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ - /* Initialize message table pointers */ - err->jpeg_message_table = jpeg_std_message_table; - err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; - err->addon_message_table = NULL; - err->first_addon_message = 0; /* for safety */ - err->last_addon_message = 0; + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; - return err; + return err; } diff --git a/rtengine/jpeg.h b/rtengine/jpeg.h index 7e3dded10..99baecc5a 100644 --- a/rtengine/jpeg.h +++ b/rtengine/jpeg.h @@ -18,11 +18,10 @@ my_jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile); GLOBAL(void) jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize); -/** +/** * @brief jpeg from file and memory use this as base to managers */ -typedef struct -{ +typedef struct { struct jpeg_source_mgr pub; /* public fields */ jmp_buf error_jmp_buf; /* error handler for this instance */ } rt_jpeg_error_mgr; diff --git a/rtengine/jpeg_memsrc.cc b/rtengine/jpeg_memsrc.cc index 7d5970fb3..75a0b25bc 100644 --- a/rtengine/jpeg_memsrc.cc +++ b/rtengine/jpeg_memsrc.cc @@ -28,10 +28,10 @@ /* Expanded data source object for memory input */ typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - jmp_buf error_jmp_buf; /* error handler for this instance */ + struct jpeg_source_mgr pub; /* public fields */ + jmp_buf error_jmp_buf; /* error handler for this instance */ - JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */ + JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; @@ -45,10 +45,10 @@ typedef my_source_mgr * my_src_ptr; static void init_source (j_decompress_ptr cinfo) { - /* No work, since jpeg_memory_src set up the buffer pointer and count. - * Indeed, if we want to read multiple JPEG images from one buffer, - * this *must* not do anything to the pointer. - */ + /* No work, since jpeg_memory_src set up the buffer pointer and count. + * Indeed, if we want to read multiple JPEG images from one buffer, + * this *must* not do anything to the pointer. + */ } @@ -68,17 +68,17 @@ init_source (j_decompress_ptr cinfo) static boolean fill_input_buffer(j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - WARNMS(cinfo, JWRN_JPEG_EOF); + WARNMS(cinfo, JWRN_JPEG_EOF); - /* Create a fake EOI marker */ - src->eoi_buffer[0] = (JOCTET) 0xFF; - src->eoi_buffer[1] = (JOCTET) JPEG_EOI; - src->pub.next_input_byte = src->eoi_buffer; - src->pub.bytes_in_buffer = 2; + /* Create a fake EOI marker */ + src->eoi_buffer[0] = (JOCTET) 0xFF; + src->eoi_buffer[1] = (JOCTET) JPEG_EOI; + src->pub.next_input_byte = src->eoi_buffer; + src->pub.bytes_in_buffer = 2; - return TRUE; + return TRUE; } @@ -95,19 +95,20 @@ fill_input_buffer(j_decompress_ptr cinfo) static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } } @@ -132,7 +133,7 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes) static void term_source (j_decompress_ptr cinfo) { - /* no work necessary here */ + /* no work necessary here */ } @@ -143,27 +144,27 @@ term_source (j_decompress_ptr cinfo) GLOBAL(void) jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize) { - my_src_ptr src; + my_src_ptr src; - /* The source object is made permanent so that a series of JPEG images - * can be read from a single buffer by calling jpeg_memory_src - * only before the first one. - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof(my_source_mgr)); - } + /* The source object is made permanent so that a series of JPEG images + * can be read from a single buffer by calling jpeg_memory_src + * only before the first one. + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(my_source_mgr)); + } - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; - src->pub.next_input_byte = buffer; - src->pub.bytes_in_buffer = bufsize; + src->pub.next_input_byte = buffer; + src->pub.bytes_in_buffer = bufsize; } diff --git a/rtengine/labimage.cc b/rtengine/labimage.cc index e3511afaf..36d3e0f67 100644 --- a/rtengine/labimage.cc +++ b/rtengine/labimage.cc @@ -1,28 +1,34 @@ #include "labimage.h" #include -namespace rtengine { +namespace rtengine +{ -LabImage::LabImage (int w, int h) : fromImage(false), W(w), H(h) { - allocLab(w,h); +LabImage::LabImage (int w, int h) : fromImage(false), W(w), H(h) +{ + allocLab(w, h); } -LabImage::~LabImage () { - deleteLab(); +LabImage::~LabImage () +{ + deleteLab(); } -void LabImage::CopyFrom(LabImage *Img){ - memcpy(data, Img->data, W*H*3*sizeof(float)); +void LabImage::CopyFrom(LabImage *Img) +{ + memcpy(data, Img->data, W * H * 3 * sizeof(float)); } -void LabImage::getPipetteData (float &v1, float &v2, float &v3, int posX, int posY, int squareSize) { +void LabImage::getPipetteData (float &v1, float &v2, float &v3, int posX, int posY, int squareSize) +{ float accumulator_L = 0.f; float accumulator_a = 0.f; float accumulator_b = 0.f; unsigned long int n = 0; - int halfSquare = squareSize/2; - for (int iy=posY-halfSquare; iy=0 && iy>=0 && ix= 0 && iy >= 0 && ix < W && iy < H) { accumulator_L += L[iy][ix]; accumulator_a += a[iy][ix]; accumulator_b += b[iy][ix]; @@ -30,9 +36,10 @@ void LabImage::getPipetteData (float &v1, float &v2, float &v3, int posX, int po } } } - v1 = n ? accumulator_L/float(n) : 0.f; - v2 = n ? accumulator_a/float(n) : 0.f; - v3 = n ? accumulator_b/float(n) : 0.f; + + v1 = n ? accumulator_L / float(n) : 0.f; + v2 = n ? accumulator_a / float(n) : 0.f; + v3 = n ? accumulator_b / float(n) : 0.f; } } diff --git a/rtengine/labimage.h b/rtengine/labimage.h index a66147b82..4b7db93c0 100644 --- a/rtengine/labimage.h +++ b/rtengine/labimage.h @@ -19,50 +19,64 @@ #ifndef _LABIMAGE_H_ #define _LABIMAGE_H_ -namespace rtengine { +namespace rtengine +{ -class LabImage { +class LabImage +{ private: - bool fromImage; - void allocLab(int w, int h) { - L = new float*[H]; - a = new float*[H]; - b = new float*[H]; + bool fromImage; + void allocLab(int w, int h) + { + L = new float*[H]; + a = new float*[H]; + b = new float*[H]; - data = new float [W*H*3]; - float * index = data; - for (int i=0; ifullWidth) Dmax=fullHeight; + int Dmax = fullWidth; + + if (fullHeight > fullWidth) { + Dmax = fullHeight; + } // correct focLens - if (focLenX<0) { // they may not be given + if (focLenX < 0) { // they may not be given // and 35mm may not be given either - if (focalLength35mm<1) focalLength35mm = focalLength*sensorFormatFactor; + if (focalLength35mm < 1) { + focalLength35mm = focalLength * sensorFormatFactor; + } - focLenX=focLenY=focalLength / ( 35*focalLength/focalLength35mm); // focLen must be calculated in pixels + focLenX = focLenY = focalLength / ( 35 * focalLength / focalLength35mm); // focLen must be calculated in pixels } if (swapXY) { - x0 = (mirrorX ? 1.-imgYCenter : imgYCenter) * fullWidth; - y0 = (mirrorY ? 1.-imgXCenter : imgXCenter) * fullHeight; + x0 = (mirrorX ? 1. - imgYCenter : imgYCenter) * fullWidth; + y0 = (mirrorY ? 1. - imgXCenter : imgXCenter) * fullHeight; fx = focLenY * Dmax; fy = focLenX * Dmax; } else { - x0 = (mirrorX ? 1.-imgXCenter : imgXCenter) * fullWidth; - y0 = (mirrorY ? 1.-imgYCenter : imgYCenter) * fullHeight; - fx = focLenX * Dmax; + x0 = (mirrorX ? 1. - imgXCenter : imgXCenter) * fullWidth; + y0 = (mirrorY ? 1. - imgYCenter : imgYCenter) * fullHeight; + fx = focLenX * Dmax; fy = focLenY * Dmax; } + //printf("FW %i /X0 %g FH %i /Y0 %g %g\n",fullWidth,x0,fullHeight,y0, imgYCenter); } -LCPPersModel::LCPPersModel() { - focLen=focDist=aperture=0; +LCPPersModel::LCPPersModel() +{ + focLen = focDist = aperture = 0; } // mode: 0=distortion, 1=vignette, 2=CA -bool LCPPersModel::hasModeData(int mode) const { - return (mode==0 && !vignette.empty() && !vignette.badErr) || (mode==1 && !base.empty() && !base.badErr) - || (mode==2 && !chromRG.empty() && !chromG.empty() && !chromBG.empty() && - !chromRG.badErr && !chromG.badErr && !chromBG.badErr); +bool LCPPersModel::hasModeData(int mode) const +{ + return (mode == 0 && !vignette.empty() && !vignette.badErr) || (mode == 1 && !base.empty() && !base.badErr) + || (mode == 2 && !chromRG.empty() && !chromG.empty() && !chromBG.empty() && + !chromRG.badErr && !chromG.badErr && !chromBG.badErr); } -void LCPPersModel::print() const { +void LCPPersModel::print() const +{ printf("--- PersModel focLen %g; focDist %g; aperture %g\n", focLen, focDist, aperture); - printf("Base:\n"); base.print(); - if (!chromRG.empty()) { printf("ChromRG:\n"); chromRG.print(); } - if (!chromG.empty()) { printf("ChromG:\n"); chromG.print(); } - if (!chromBG.empty()) { printf("ChromBG:\n"); chromBG.print(); } - if (!vignette.empty()) { printf("Vignette:\n"); vignette.print(); } + printf("Base:\n"); + base.print(); + + if (!chromRG.empty()) { + printf("ChromRG:\n"); + chromRG.print(); + } + + if (!chromG.empty()) { + printf("ChromG:\n"); + chromG.print(); + } + + if (!chromBG.empty()) { + printf("ChromBG:\n"); + chromBG.print(); + } + + if (!vignette.empty()) { + printf("Vignette:\n"); + vignette.print(); + } + printf("\n"); } // if !vignette then geometric and CA -LCPMapper::LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, - int fullWidth, int fullHeight, const CoarseTransformParams& coarse, int rawRotationDeg) +LCPMapper::LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, + int fullWidth, int fullHeight, const CoarseTransformParams& coarse, int rawRotationDeg) { - if (pProf==NULL) return; + if (pProf == NULL) { + return; + } - useCADist=useCADistP; + useCADist = useCADistP; // determine in what the image with the RAW landscape in comparison (calibration target) // in vignetting, the rotation has not taken place yet int rot = 0; - if (rawRotationDeg>=0) rot=(coarse.rotate+rawRotationDeg) % 360; - swapXY = (rot==90 || rot==270); - bool mirrorX = (rot==90 || rot==180); - bool mirrorY = (rot==180 || rot==270); - //printf("Vign: %i, fullWidth: %i/%i, focLen %g SwapXY: %i / MirX/Y %i / %i on rot:%i from %i\n",vignette, fullWidth, fullHeight, focalLength, swapXY, mirrorX, mirrorY, rot, rawRotationDeg); - - pProf->calcParams(vignette?0:1, focalLength, focusDist, aperture, &mc, NULL, NULL); - mc.prepareParams(fullWidth, fullHeight, focalLength, focalLength35mm, pProf->sensorFormatFactor, swapXY, mirrorX, mirrorY); - - if (!vignette) { - pProf->calcParams(2, focalLength, focusDist, aperture, &chrom[0], &chrom[1], &chrom[2]); - for (int i=0;i<3;i++) chrom[i].prepareParams(fullWidth, fullHeight, focalLength, focalLength35mm, pProf->sensorFormatFactor, swapXY, mirrorX, mirrorY); + if (rawRotationDeg >= 0) { + rot = (coarse.rotate + rawRotationDeg) % 360; } - enableCA = !vignette && focusDist>0; + swapXY = (rot == 90 || rot == 270); + bool mirrorX = (rot == 90 || rot == 180); + bool mirrorY = (rot == 180 || rot == 270); + //printf("Vign: %i, fullWidth: %i/%i, focLen %g SwapXY: %i / MirX/Y %i / %i on rot:%i from %i\n",vignette, fullWidth, fullHeight, focalLength, swapXY, mirrorX, mirrorY, rot, rawRotationDeg); + + pProf->calcParams(vignette ? 0 : 1, focalLength, focusDist, aperture, &mc, NULL, NULL); + mc.prepareParams(fullWidth, fullHeight, focalLength, focalLength35mm, pProf->sensorFormatFactor, swapXY, mirrorX, mirrorY); + + if (!vignette) { + pProf->calcParams(2, focalLength, focusDist, aperture, &chrom[0], &chrom[1], &chrom[2]); + + for (int i = 0; i < 3; i++) { + chrom[i].prepareParams(fullWidth, fullHeight, focalLength, focalLength35mm, pProf->sensorFormatFactor, swapXY, mirrorX, mirrorY); + } + } + + enableCA = !vignette && focusDist > 0; } -void LCPMapper::correctDistortion(double& x, double& y) const { - double xd=(x-mc.x0)/mc.fx, yd=(y-mc.y0)/mc.fy; +void LCPMapper::correctDistortion(double& x, double& y) const +{ + double xd = (x - mc.x0) / mc.fx, yd = (y - mc.y0) / mc.fy; const float* aDist = mc.param; - double rsqr = xd*xd+yd*yd; - double xfac=aDist[swapXY?3:4], yfac=aDist[swapXY?4:3]; + double rsqr = xd * xd + yd * yd; + double xfac = aDist[swapXY ? 3 : 4], yfac = aDist[swapXY ? 4 : 3]; - double commonFac = (((aDist[2]*rsqr + aDist[1])*rsqr + aDist[0])*rsqr + 1.) - + 2. * (yfac * yd + xfac * xd); + double commonFac = (((aDist[2] * rsqr + aDist[1]) * rsqr + aDist[0]) * rsqr + 1.) + + 2. * (yfac * yd + xfac * xd); double xnew = xd * commonFac + xfac * rsqr; double ynew = yd * commonFac + yfac * rsqr; @@ -165,87 +215,105 @@ void LCPMapper::correctDistortion(double& x, double& y) const { y = ynew * mc.fy + mc.y0; } -void LCPMapper::correctCA(double& x, double& y, int channel) const { - if (!enableCA) return; +void LCPMapper::correctCA(double& x, double& y, int channel) const +{ + if (!enableCA) { + return; + } double rsqr, xgreen, ygreen; // First calc the green channel like normal distortion // the other are just deviations from it - double xd=(x-chrom[1].x0)/chrom[1].fx, yd=(y-chrom[1].y0)/chrom[1].fy; + double xd = (x - chrom[1].x0) / chrom[1].fx, yd = (y - chrom[1].y0) / chrom[1].fy; // Green contains main distortion, just like base if (useCADist) { const float* aDist = chrom[1].param; - double rsqr = xd*xd+yd*yd; - double xfac=aDist[swapXY?3:4], yfac=aDist[swapXY?4:3]; + double rsqr = xd * xd + yd * yd; + double xfac = aDist[swapXY ? 3 : 4], yfac = aDist[swapXY ? 4 : 3]; - double commonFac = (((aDist[2]*rsqr + aDist[1])*rsqr + aDist[0])*rsqr + 1.) - + 2. * (yfac * yd + xfac * xd); + double commonFac = (((aDist[2] * rsqr + aDist[1]) * rsqr + aDist[0]) * rsqr + 1.) + + 2. * (yfac * yd + xfac * xd); xgreen = xd * commonFac + aDist[4] * rsqr; ygreen = yd * commonFac + aDist[3] * rsqr; } else { - xgreen=xd; ygreen=yd; + xgreen = xd; + ygreen = yd; } - if (channel==1) { + if (channel == 1) { // green goes directly x = xgreen * chrom[1].fx + chrom[1].x0; y = ygreen * chrom[1].fy + chrom[1].y0; } else { // others are diffs from green - xd=xgreen; yd=ygreen; - rsqr=xd*xd+yd*yd; + xd = xgreen; + yd = ygreen; + rsqr = xd * xd + yd * yd; - const float* aCA =chrom[channel].param; - double xfac=aCA[swapXY?3:4], yfac=aCA[swapXY?4:3]; - double commonSum = 1. + rsqr * (aCA[0] + rsqr * (aCA[1] + aCA[2]*rsqr)) + 2. * (yfac*yd + xfac*xd); + const float* aCA = chrom[channel].param; + double xfac = aCA[swapXY ? 3 : 4], yfac = aCA[swapXY ? 4 : 3]; + double commonSum = 1. + rsqr * (aCA[0] + rsqr * (aCA[1] + aCA[2] * rsqr)) + 2. * (yfac * yd + xfac * xd); - x = (chrom[channel].scaleFac * ( xd * commonSum + xfac*rsqr )) * chrom[channel].fx + chrom[channel].x0; - y = (chrom[channel].scaleFac * ( yd * commonSum + yfac*rsqr )) * chrom[channel].fy + chrom[channel].y0; + x = (chrom[channel].scaleFac * ( xd * commonSum + xfac * rsqr )) * chrom[channel].fx + chrom[channel].x0; + y = (chrom[channel].scaleFac * ( yd * commonSum + yfac * rsqr )) * chrom[channel].fy + chrom[channel].y0; } } -float LCPMapper::calcVignetteFac(int x, int y) const { +float LCPMapper::calcVignetteFac(int x, int y) const +{ // No need for swapXY, since vignette is in RAW and always before rotation - double xd=((double)x-mc.x0)/mc.fx, yd=((double)y-mc.y0)/mc.fy; + double xd = ((double)x - mc.x0) / mc.fx, yd = ((double)y - mc.y0) / mc.fy; - const float* aVig= mc.param; - double rsqr = xd*xd+yd*yd; - double param0Sqr = aVig[0]*aVig[0]; + const float* aVig = mc.param; + double rsqr = xd * xd + yd * yd; + double param0Sqr = aVig[0] * aVig[0]; return 1. + rsqr * (-aVig[0] + rsqr * ((param0Sqr - aVig[1]) - - (param0Sqr*aVig[0] - 2.*aVig[0]*aVig[1] + aVig[2]) *rsqr - + (param0Sqr*param0Sqr + aVig[1]*aVig[1] - + 2.*aVig[0]*aVig[2] - 3.*param0Sqr*aVig[1]) *rsqr*rsqr)); + - (param0Sqr * aVig[0] - 2.*aVig[0] * aVig[1] + aVig[2]) * rsqr + + (param0Sqr * param0Sqr + aVig[1] * aVig[1] + + 2.*aVig[0] * aVig[2] - 3.*param0Sqr * aVig[1]) * rsqr * rsqr)); } -LCPProfile::LCPProfile(Glib::ustring fname) { - const int BufferSize=8192; +LCPProfile::LCPProfile(Glib::ustring fname) +{ + const int BufferSize = 8192; char buf[BufferSize]; XML_Parser parser = XML_ParserCreate(NULL); - if (!parser) throw "Couldn't allocate memory for XML parser"; + + if (!parser) { + throw "Couldn't allocate memory for XML parser"; + } XML_SetElementHandler(parser, XmlStartHandler, XmlEndHandler); XML_SetCharacterDataHandler(parser, XmlTextHandler); XML_SetUserData(parser, (void *)this); - isFisheye=inCamProfiles=firstLIDone=inPerspect=inAlternateLensID=inAlternateLensNames=false; - sensorFormatFactor=1; - for (int i=0;ihasModeData(0)) { - errVignette+=aPersModel[pm]->vignette.meanErr; + errVignette += aPersModel[pm]->vignette.meanErr; vignetteCount++; } if (aPersModel[pm]->hasModeData(1)) { - errBase+=aPersModel[pm]->base.meanErr; + errBase += aPersModel[pm]->base.meanErr; baseCount++; } if (aPersModel[pm]->hasModeData(2)) { - errChrom+=std::max(std::max(aPersModel[pm]->chromRG.meanErr,aPersModel[pm]->chromG.meanErr),aPersModel[pm]->chromBG.meanErr); + errChrom += std::max(std::max(aPersModel[pm]->chromRG.meanErr, aPersModel[pm]->chromG.meanErr), aPersModel[pm]->chromBG.meanErr); chromCount++; } } // Only if we have enough frames, filter out errors - int filtered=0; + int filtered = 0; - if (baseCount+chromCount+vignetteCount>=minFramesLeft) { - if (baseCount>0) errBase/=(double)baseCount; - if (chromCount>0) errChrom/=(double)chromCount; - if (vignetteCount>0) errVignette/=(double)vignetteCount; + if (baseCount + chromCount + vignetteCount >= minFramesLeft) { + if (baseCount > 0) { + errBase /= (double)baseCount; + } + + if (chromCount > 0) { + errChrom /= (double)chromCount; + } + + if (vignetteCount > 0) { + errVignette /= (double)vignetteCount; + } // Now mark all the bad ones as bad, and hasModeData will return false; - for (int pm=0;pmhasModeData(0) && aPersModel[pm]->vignette.meanErr > maxAvgDevFac * errVignette) { - aPersModel[pm]->vignette.badErr=true; + aPersModel[pm]->vignette.badErr = true; filtered++; } if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.meanErr > maxAvgDevFac * errBase) { - aPersModel[pm]->base.badErr=true; + aPersModel[pm]->base.badErr = true; filtered++; } - if (aPersModel[pm]->hasModeData(2) && - (aPersModel[pm]->chromRG.meanErr > maxAvgDevFac * errChrom || aPersModel[pm]->chromG.meanErr > maxAvgDevFac * errChrom - || aPersModel[pm]->chromBG.meanErr > maxAvgDevFac * errChrom)) { - aPersModel[pm]->chromRG.badErr=aPersModel[pm]->chromG.badErr=aPersModel[pm]->chromBG.badErr=true; + if (aPersModel[pm]->hasModeData(2) && + (aPersModel[pm]->chromRG.meanErr > maxAvgDevFac * errChrom || aPersModel[pm]->chromG.meanErr > maxAvgDevFac * errChrom + || aPersModel[pm]->chromBG.meanErr > maxAvgDevFac * errChrom)) { + aPersModel[pm]->chromRG.badErr = aPersModel[pm]->chromG.badErr = aPersModel[pm]->chromBG.badErr = true; filtered++; } } @@ -318,86 +396,92 @@ int LCPProfile::filterBadFrames(double maxAvgDevFac, int minFramesLeft) { // mode: 0=vignette, 1=distortion, 2=CA -void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float aperture, LCPModelCommon *pCorr1, LCPModelCommon *pCorr2, LCPModelCommon *pCorr3) const { - float euler=exp(1.0); +void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float aperture, LCPModelCommon *pCorr1, LCPModelCommon *pCorr2, LCPModelCommon *pCorr3) const +{ + float euler = exp(1.0); // find the frames with the least distance, focal length wise - LCPPersModel *pLow=NULL, *pHigh=NULL; + LCPPersModel *pLow = NULL, *pHigh = NULL; - float focalLengthLog=log(focalLength); //, apertureLog=aperture>0 ? log(aperture) : 0; - float focusDistLog=focusDist>0? log(focusDist)+euler : 0; + float focalLengthLog = log(focalLength); //, apertureLog=aperture>0 ? log(aperture) : 0; + float focusDistLog = focusDist > 0 ? log(focusDist) + euler : 0; // Pass 1: determining best focal length, if possible different focusDistances (for the focDist is not given case) - for (int pm=0;pmfocLen; + for (int pm = 0; pm < persModelCount; pm++) { + float f = aPersModel[pm]->focLen; if (aPersModel[pm]->hasModeData(mode)) { - if (f <= focalLength && (pLow==NULL || f > pLow->focLen || (focusDist==0 && f==pLow->focLen && pLow->focDist>aPersModel[pm]->focDist))) { - pLow=aPersModel[pm]; + if (f <= focalLength && (pLow == NULL || f > pLow->focLen || (focusDist == 0 && f == pLow->focLen && pLow->focDist > aPersModel[pm]->focDist))) { + pLow = aPersModel[pm]; } - if (f >= focalLength && (pHigh==NULL || f < pHigh->focLen || (focusDist==0 && f==pHigh->focLen && pHigh->focDistfocDist))) { - pHigh=aPersModel[pm]; + + if (f >= focalLength && (pHigh == NULL || f < pHigh->focLen || (focusDist == 0 && f == pHigh->focLen && pHigh->focDist < aPersModel[pm]->focDist))) { + pHigh = aPersModel[pm]; } } } - if (!pLow) - pLow=pHigh; - else if (!pHigh) - pHigh=pLow; - else { + if (!pLow) { + pLow = pHigh; + } else if (!pHigh) { + pHigh = pLow; + } else { // Pass 2: We have some, so take the best aperture for vignette and best focus for CA and distortion // there are usually several frame per focal length. In the end pLow will have both flen and apterure/focdis below the target, // and vice versa pHigh - float bestFocLenLow=pLow->focLen, bestFocLenHigh=pHigh->focLen; + float bestFocLenLow = pLow->focLen, bestFocLenHigh = pHigh->focLen; - for (int pm=0;pmaperture; // float aperLog=log(aper); - float focDist=aPersModel[pm]->focDist; float focDistLog=log(focDist)+euler; + for (int pm = 0; pm < persModelCount; pm++) { + float aper = aPersModel[pm]->aperture; // float aperLog=log(aper); + float focDist = aPersModel[pm]->focDist; + float focDistLog = log(focDist) + euler; double meanErr; if (aPersModel[pm]->hasModeData(mode)) { - if (mode==0) { - meanErr=aPersModel[pm]->vignette.meanErr; + if (mode == 0) { + meanErr = aPersModel[pm]->vignette.meanErr; // by aperture (vignette), and max out focus distance // tests showed doing this by log(aperture) is not as advisable - if (aPersModel[pm]->focLen==bestFocLenLow && ( - (aper==aperture && pLow->vignette.meanErr>meanErr) - || (aper>=aperture && aperaperture && pLow->aperture > aperture) - || (aper<=aperture && (pLow->aperture>aperture || fabs(aperture-aper)aperture))))) { - pLow=aPersModel[pm]; - } - if (aPersModel[pm]->focLen==bestFocLenHigh && ( - (aper==aperture && pHigh->vignette.meanErr>meanErr) - || (aper<=aperture && aper>pHigh->aperture && pHigh->aperture < aperture) - || (aper>=aperture && (pHigh->apertureaperture))))) { - pHigh=aPersModel[pm]; - } - } else { - meanErr = (mode==1 ? aPersModel[pm]->base.meanErr : aPersModel[pm]->chromG.meanErr); + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (aper == aperture && pLow->vignette.meanErr > meanErr) + || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) + || (aper <= aperture && (pLow->aperture > aperture || fabs(aperture - aper) < fabs(aperture - pLow->aperture))))) { + pLow = aPersModel[pm]; + } - if (focusDist>0) { - // by focus distance - if (aPersModel[pm]->focLen==bestFocLenLow && ( - (focDist==focusDist && (mode==1 ? pLow->base.meanErr : pLow->chromG.meanErr)>meanErr) - || (focDist>=focusDist && focDistfocDist && pLow->focDist > focusDist) - || (focDist<=focusDist && (pLow->focDist>focusDist || fabs(focusDistLog-focDistLog)focDist)+euler)))))) { - pLow=aPersModel[pm]; - } - if (aPersModel[pm]->focLen==bestFocLenHigh && ( - (focDist==focusDist && (mode==1 ? pHigh->base.meanErr : pHigh->chromG.meanErr)>meanErr) - || (focDist<=focusDist && focDist>pHigh->focDist && pHigh->focDist < focusDist) - || (focDist>=focusDist && (pHigh->focDistfocDist)+euler)))))) { - pHigh=aPersModel[pm]; + if (aPersModel[pm]->focLen == bestFocLenHigh && ( + (aper == aperture && pHigh->vignette.meanErr > meanErr) + || (aper <= aperture && aper > pHigh->aperture && pHigh->aperture < aperture) + || (aper >= aperture && (pHigh->aperture < aperture || fabs(aperture - aper) < fabs(aperture - pHigh->aperture))))) { + pHigh = aPersModel[pm]; } + } else { + meanErr = (mode == 1 ? aPersModel[pm]->base.meanErr : aPersModel[pm]->chromG.meanErr); + + if (focusDist > 0) { + // by focus distance + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (focDist == focusDist && (mode == 1 ? pLow->base.meanErr : pLow->chromG.meanErr) > meanErr) + || (focDist >= focusDist && focDist < pLow->focDist && pLow->focDist > focusDist) + || (focDist <= focusDist && (pLow->focDist > focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pLow->focDist) + euler)))))) { + pLow = aPersModel[pm]; + } + + if (aPersModel[pm]->focLen == bestFocLenHigh && ( + (focDist == focusDist && (mode == 1 ? pHigh->base.meanErr : pHigh->chromG.meanErr) > meanErr) + || (focDist <= focusDist && focDist > pHigh->focDist && pHigh->focDist < focusDist) + || (focDist >= focusDist && (pHigh->focDist < focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pHigh->focDist) + euler)))))) { + pHigh = aPersModel[pm]; + } } else { // no focus distance available, just error - if (aPersModel[pm]->focLen==bestFocLenLow && (mode==1 ? pLow->base.meanErr : pLow->chromG.meanErr)>meanErr) { - pLow=aPersModel[pm]; + if (aPersModel[pm]->focLen == bestFocLenLow && (mode == 1 ? pLow->base.meanErr : pLow->chromG.meanErr) > meanErr) { + pLow = aPersModel[pm]; } - if (aPersModel[pm]->focLen==bestFocLenHigh && (mode==1 ? pHigh->base.meanErr : pHigh->chromG.meanErr)>meanErr) { - pHigh=aPersModel[pm]; + + if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.meanErr : pHigh->chromG.meanErr) > meanErr) { + pHigh = aPersModel[pm]; } } } @@ -405,27 +489,27 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float } } - if (pLow!=NULL && pHigh!=NULL) { + if (pLow != NULL && pHigh != NULL) { // average out the factors, linear interpolation in logarithmic scale - float facLow=0.5; - bool focLenOnSpot=false; // pretty often, since max/min are often as frames in LCP + float facLow = 0.5; + bool focLenOnSpot = false; // pretty often, since max/min are often as frames in LCP // There is as foclen range, take that as basis if (pLow->focLen < pHigh->focLen) { - facLow = (log(pHigh->focLen)-focalLengthLog) / (log(pHigh->focLen) - log(pLow->focLen)); + facLow = (log(pHigh->focLen) - focalLengthLog) / (log(pHigh->focLen) - log(pLow->focLen)); } else { - focLenOnSpot=pLow->focLen==pHigh->focLen && pLow->focLen==focalLength; + focLenOnSpot = pLow->focLen == pHigh->focLen && pLow->focLen == focalLength; } - + // and average the other factor if available - if (mode==0 && pLow->aperture < aperture && pHigh->aperture > aperture) { + if (mode == 0 && pLow->aperture < aperture && pHigh->aperture > aperture) { // Mix in aperture float facAperLow = (pHigh->aperture - aperture) / (pHigh->aperture - pLow->aperture); - facLow = focLenOnSpot ? facAperLow : (0.5*facLow + 0.5*facAperLow); - } else if (mode!=0 && focusDist>0 && pLow->focDist < focusDist && pHigh->focDist > focusDist) { + facLow = focLenOnSpot ? facAperLow : (0.5 * facLow + 0.5 * facAperLow); + } else if (mode != 0 && focusDist > 0 && pLow->focDist < focusDist && pHigh->focDist > focusDist) { // focus distance for all else (if focus distance is given) - float facDistLow = (log(pHigh->focDist)+euler - focusDistLog) / (log(pHigh->focDist) - log(pLow->focDist)); - facLow = focLenOnSpot ? facDistLow : (0.8*facLow + 0.2*facDistLow); + float facDistLow = (log(pHigh->focDist) + euler - focusDistLog) / (log(pHigh->focDist) - log(pLow->focDist)); + facLow = focLenOnSpot ? facDistLow : (0.8 * facLow + 0.2 * facDistLow); } switch (mode) { @@ -444,183 +528,252 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float break; } - //printf("LCP mode=%i, dist: %g found frames: Fno %g-%g; FocLen %g-%g; Dist %g-%g with weight %g\n", mode, focusDist, pLow->aperture, pHigh->aperture, pLow->focLen, pHigh->focLen, pLow->focDist, pHigh->focDist, facLow); - } else printf("Error: LCP file contained no %s parameters\n",mode==0 ? "vignette" : mode == 1 ? "distortion" : "CA" ); + //printf("LCP mode=%i, dist: %g found frames: Fno %g-%g; FocLen %g-%g; Dist %g-%g with weight %g\n", mode, focusDist, pLow->aperture, pHigh->aperture, pLow->focLen, pHigh->focLen, pLow->focDist, pHigh->focDist, facLow); + } else { + printf("Error: LCP file contained no %s parameters\n", mode == 0 ? "vignette" : mode == 1 ? "distortion" : "CA" ); + } } -void LCPProfile::print() const { +void LCPProfile::print() const +{ printf("=== Profile %s\n", profileName.c_str()); - printf("Frames: %i, RAW: %i; Fisheye: %i; Sensorformat: %f\n",persModelCount,isRaw,isFisheye,sensorFormatFactor); - for (int pm=0;pmprint(); + printf("Frames: %i, RAW: %i; Fisheye: %i; Sensorformat: %f\n", persModelCount, isRaw, isFisheye, sensorFormatFactor); + + for (int pm = 0; pm < persModelCount; pm++) { + aPersModel[pm]->print(); + } } -void XMLCALL LCPProfile::XmlStartHandler(void *pLCPProfile, const char *el, const char **attr) { - LCPProfile *pProf=static_cast(pLCPProfile); - bool parseAttr=false; +void XMLCALL LCPProfile::XmlStartHandler(void *pLCPProfile, const char *el, const char **attr) +{ + LCPProfile *pProf = static_cast(pLCPProfile); + bool parseAttr = false; - if (*pProf->inInvalidTag) return; // We ignore everything in dirty tag till it's gone + if (*pProf->inInvalidTag) { + return; // We ignore everything in dirty tag till it's gone + } // clean up tagname - const char* src=strrchr(el,':'); - if (src==NULL) src=const_cast(el); else src++; + const char* src = strrchr(el, ':'); - strcpy(pProf->lastTag,src); + if (src == NULL) { + src = const_cast(el); + } else { + src++; + } - if (!strcmp("VignetteModelPiecewiseParam",src)) strcpy(pProf->inInvalidTag,src); + strcpy(pProf->lastTag, src); - if (!strcmp("CameraProfiles",src)) pProf->inCamProfiles=true; - if (!strcmp("AlternateLensIDs",src)) pProf->inAlternateLensID=true; - if (!strcmp("AlternateLensNames",src)) pProf->inAlternateLensNames=true; - if (!pProf->inCamProfiles || pProf->inAlternateLensID || pProf->inAlternateLensNames) return; + if (!strcmp("VignetteModelPiecewiseParam", src)) { + strcpy(pProf->inInvalidTag, src); + } - if (!strcmp("li",src)) { - pProf->pCurPersModel=new LCPPersModel(); - pProf->pCurCommon=&pProf->pCurPersModel->base; // iterated to next tags within persModel + if (!strcmp("CameraProfiles", src)) { + pProf->inCamProfiles = true; + } + + if (!strcmp("AlternateLensIDs", src)) { + pProf->inAlternateLensID = true; + } + + if (!strcmp("AlternateLensNames", src)) { + pProf->inAlternateLensNames = true; + } + + if (!pProf->inCamProfiles || pProf->inAlternateLensID || pProf->inAlternateLensNames) { return; } - if (!strcmp("PerspectiveModel",src)) { - pProf->firstLIDone=true; pProf->inPerspect=true; + if (!strcmp("li", src)) { + pProf->pCurPersModel = new LCPPersModel(); + pProf->pCurCommon = &pProf->pCurPersModel->base; // iterated to next tags within persModel return; - } else if (!strcmp("FisheyeModel",src)) { - pProf->firstLIDone=true; pProf->inPerspect=true; - pProf->isFisheye=true; // just misses third param, and different path, rest is the same + } + + if (!strcmp("PerspectiveModel", src)) { + pProf->firstLIDone = true; + pProf->inPerspect = true; return; - } else if (!strcmp("Description",src)) parseAttr=true; + } else if (!strcmp("FisheyeModel", src)) { + pProf->firstLIDone = true; + pProf->inPerspect = true; + pProf->isFisheye = true; // just misses third param, and different path, rest is the same + return; + } else if (!strcmp("Description", src)) { + parseAttr = true; + } // Move pointer to general section if (pProf->inPerspect) { - if (!strcmp("ChromaticRedGreenModel",src)) { - pProf->pCurCommon=&pProf->pCurPersModel->chromRG; - parseAttr=true; - } else if (!strcmp("ChromaticGreenModel",src)) { - pProf->pCurCommon=&pProf->pCurPersModel->chromG; - parseAttr=true; - } else if (!strcmp("ChromaticBlueGreenModel",src)) { - pProf->pCurCommon=&pProf->pCurPersModel->chromBG; - parseAttr=true; - } else if (!strcmp("VignetteModel",src)) { - pProf->pCurCommon=&pProf->pCurPersModel->vignette; - parseAttr=true; + if (!strcmp("ChromaticRedGreenModel", src)) { + pProf->pCurCommon = &pProf->pCurPersModel->chromRG; + parseAttr = true; + } else if (!strcmp("ChromaticGreenModel", src)) { + pProf->pCurCommon = &pProf->pCurPersModel->chromG; + parseAttr = true; + } else if (!strcmp("ChromaticBlueGreenModel", src)) { + pProf->pCurCommon = &pProf->pCurPersModel->chromBG; + parseAttr = true; + } else if (!strcmp("VignetteModel", src)) { + pProf->pCurCommon = &pProf->pCurPersModel->vignette; + parseAttr = true; } } // some profiles (espc. Pentax) have a different structure that is attributes based // simulate tags by feeding them in - if (parseAttr && attr!=NULL) { + if (parseAttr && attr != NULL) { for (int i = 0; attr[i]; i += 2) { - const char* nameStart=strrchr(attr[i],':'); - if (nameStart==NULL) nameStart=const_cast(attr[i]); else nameStart++; + const char* nameStart = strrchr(attr[i], ':'); + + if (nameStart == NULL) { + nameStart = const_cast(attr[i]); + } else { + nameStart++; + } strcpy(pProf->lastTag, nameStart); - XmlTextHandler(pLCPProfile, attr[i+1], strlen(attr[i+1])); + XmlTextHandler(pLCPProfile, attr[i + 1], strlen(attr[i + 1])); } } } -void XMLCALL LCPProfile::XmlTextHandler(void *pLCPProfile, const XML_Char *s, int len) { - LCPProfile *pProf=static_cast(pLCPProfile); +void XMLCALL LCPProfile::XmlTextHandler(void *pLCPProfile, const XML_Char *s, int len) +{ + LCPProfile *pProf = static_cast(pLCPProfile); - if (!pProf->inCamProfiles || pProf->inAlternateLensID || pProf->inAlternateLensNames || *pProf->inInvalidTag) return; + if (!pProf->inCamProfiles || pProf->inAlternateLensID || pProf->inAlternateLensNames || *pProf->inInvalidTag) { + return; + } // Check if it contains non-whitespaces (there are several calls to this for one tag unfortunately) - bool onlyWhiteSpace=true; - int i=0; - while (ilastTag; + char raw[len + 1]; + memcpy(raw, s, len); + raw[len] = 0; + char* tag = pProf->lastTag; // Common data section if (!pProf->firstLIDone) { // Generic tags are the same for all - if (!strcmp("ProfileName",tag)) - pProf->profileName=Glib::ustring(raw); - else if (!strcmp("Model",tag)) - pProf->camera=Glib::ustring(raw); - else if (!strcmp("Lens",tag)) - pProf->lens=Glib::ustring(raw); - else if (!strcmp("CameraPrettyName",tag)) - pProf->cameraPrettyName=Glib::ustring(raw); - else if (!strcmp("LensPrettyName",tag)) - pProf->lensPrettyName=Glib::ustring(raw); - else if (!strcmp("CameraRawProfile",tag)) - pProf->isRaw=!strcmp("True",raw); + if (!strcmp("ProfileName", tag)) { + pProf->profileName = Glib::ustring(raw); + } else if (!strcmp("Model", tag)) { + pProf->camera = Glib::ustring(raw); + } else if (!strcmp("Lens", tag)) { + pProf->lens = Glib::ustring(raw); + } else if (!strcmp("CameraPrettyName", tag)) { + pProf->cameraPrettyName = Glib::ustring(raw); + } else if (!strcmp("LensPrettyName", tag)) { + pProf->lensPrettyName = Glib::ustring(raw); + } else if (!strcmp("CameraRawProfile", tag)) { + pProf->isRaw = !strcmp("True", raw); + } } // --- Now all floating points. Must replace local dot characters // WARNING: called by different threads, that may run on different local settings, // so don't use system params - if (atof("1,2345")==1.2345) { - char* p=raw; - while (*p) { - if (*p=='.') *p=','; + if (atof("1,2345") == 1.2345) { + char* p = raw; + + while (*p) { + if (*p == '.') { + *p = ','; + } + p++; } } if (!pProf->firstLIDone) { - if (!strcmp("SensorFormatFactor",tag)) - pProf->sensorFormatFactor=atof(raw); + if (!strcmp("SensorFormatFactor", tag)) { + pProf->sensorFormatFactor = atof(raw); + } } // Perspective model base data - if (!strcmp("FocalLength",tag)) - pProf->pCurPersModel->focLen=atof(raw); - else if (!strcmp("FocusDistance",tag)) { - double focDist=atof(raw); - pProf->pCurPersModel->focDist=focDist<10000?focDist:10000; + if (!strcmp("FocalLength", tag)) { + pProf->pCurPersModel->focLen = atof(raw); + } else if (!strcmp("FocusDistance", tag)) { + double focDist = atof(raw); + pProf->pCurPersModel->focDist = focDist < 10000 ? focDist : 10000; + } else if (!strcmp("ApertureValue", tag)) { + pProf->pCurPersModel->aperture = atof(raw); } - else if (!strcmp("ApertureValue",tag)) - pProf->pCurPersModel->aperture=atof(raw); // Section depended - if (!strcmp("FocalLengthX",tag)) - pProf->pCurCommon->focLenX=atof(raw); - else if (!strcmp("FocalLengthY",tag)) - pProf->pCurCommon->focLenY=atof(raw); - else if (!strcmp("ImageXCenter",tag)) - pProf->pCurCommon->imgXCenter=atof(raw); - else if (!strcmp("ImageYCenter",tag)) - pProf->pCurCommon->imgYCenter=atof(raw); - else if (!strcmp("ScaleFactor",tag)) - pProf->pCurCommon->scaleFac=atof(raw); - else if (!strcmp("ResidualMeanError",tag)) - pProf->pCurCommon->meanErr=atof(raw); - else if (!strcmp("RadialDistortParam1",tag) || !strcmp("VignetteModelParam1",tag)) - pProf->pCurCommon->param[0]=atof(raw); - else if (!strcmp("RadialDistortParam2",tag) || !strcmp("VignetteModelParam2",tag)) - pProf->pCurCommon->param[1]=atof(raw); - else if (!strcmp("RadialDistortParam3",tag) || !strcmp("VignetteModelParam3",tag)) - pProf->pCurCommon->param[2]=atof(raw); - else if (!strcmp("RadialDistortParam4",tag) || !strcmp("TangentialDistortParam1",tag)) - pProf->pCurCommon->param[3]=atof(raw); - else if (!strcmp("RadialDistortParam5",tag) || !strcmp("TangentialDistortParam2",tag)) - pProf->pCurCommon->param[4]=atof(raw); + if (!strcmp("FocalLengthX", tag)) { + pProf->pCurCommon->focLenX = atof(raw); + } else if (!strcmp("FocalLengthY", tag)) { + pProf->pCurCommon->focLenY = atof(raw); + } else if (!strcmp("ImageXCenter", tag)) { + pProf->pCurCommon->imgXCenter = atof(raw); + } else if (!strcmp("ImageYCenter", tag)) { + pProf->pCurCommon->imgYCenter = atof(raw); + } else if (!strcmp("ScaleFactor", tag)) { + pProf->pCurCommon->scaleFac = atof(raw); + } else if (!strcmp("ResidualMeanError", tag)) { + pProf->pCurCommon->meanErr = atof(raw); + } else if (!strcmp("RadialDistortParam1", tag) || !strcmp("VignetteModelParam1", tag)) { + pProf->pCurCommon->param[0] = atof(raw); + } else if (!strcmp("RadialDistortParam2", tag) || !strcmp("VignetteModelParam2", tag)) { + pProf->pCurCommon->param[1] = atof(raw); + } else if (!strcmp("RadialDistortParam3", tag) || !strcmp("VignetteModelParam3", tag)) { + pProf->pCurCommon->param[2] = atof(raw); + } else if (!strcmp("RadialDistortParam4", tag) || !strcmp("TangentialDistortParam1", tag)) { + pProf->pCurCommon->param[3] = atof(raw); + } else if (!strcmp("RadialDistortParam5", tag) || !strcmp("TangentialDistortParam2", tag)) { + pProf->pCurCommon->param[4] = atof(raw); + } } -void XMLCALL LCPProfile::XmlEndHandler(void *pLCPProfile, const char *el) { - LCPProfile *pProf=static_cast(pLCPProfile); +void XMLCALL LCPProfile::XmlEndHandler(void *pLCPProfile, const char *el) +{ + LCPProfile *pProf = static_cast(pLCPProfile); // We ignore everything in dirty tag till it's gone if (*pProf->inInvalidTag) { - if (strstr(el,pProf->inInvalidTag)) *pProf->inInvalidTag=0; + if (strstr(el, pProf->inInvalidTag)) { + *pProf->inInvalidTag = 0; + } + return; } - if (strstr(el,":CameraProfiles")) pProf->inCamProfiles=false; - if (strstr(el,":AlternateLensIDs")) pProf->inAlternateLensID=false; - if (strstr(el,":AlternateLensNames")) pProf->inAlternateLensNames=false; + if (strstr(el, ":CameraProfiles")) { + pProf->inCamProfiles = false; + } - if (!pProf->inCamProfiles || pProf->inAlternateLensID || pProf->inAlternateLensNames) return; + if (strstr(el, ":AlternateLensIDs")) { + pProf->inAlternateLensID = false; + } - if (strstr(el,":PerspectiveModel") || strstr(el,":FisheyeModel")) - pProf->inPerspect=false; - else if (strstr(el, ":li")) { - pProf->aPersModel[pProf->persModelCount]=pProf->pCurPersModel; - pProf->pCurPersModel=NULL; + if (strstr(el, ":AlternateLensNames")) { + pProf->inAlternateLensNames = false; + } + + if (!pProf->inCamProfiles || pProf->inAlternateLensID || pProf->inAlternateLensNames) { + return; + } + + if (strstr(el, ":PerspectiveModel") || strstr(el, ":FisheyeModel")) { + pProf->inPerspect = false; + } else if (strstr(el, ":li")) { + pProf->aPersModel[pProf->persModelCount] = pProf->pCurPersModel; + pProf->pCurPersModel = NULL; pProf->persModelCount++; } } @@ -629,50 +782,67 @@ void XMLCALL LCPProfile::XmlEndHandler(void *pLCPProfile, const char *el) { LCPStore* LCPStore::getInstance() { static LCPStore* instance_ = 0; - if ( instance_ == 0 ) - { + + if ( instance_ == 0 ) { static MyMutex smutex_; MyMutex::MyLock lock(smutex_); - if ( instance_ == 0 ) - { + + if ( instance_ == 0 ) { instance_ = new LCPStore(); } } + return instance_; } -LCPProfile* LCPStore::getProfile (Glib::ustring filename) { - if (filename.length()==0 || !isValidLCPFileName(filename)) return NULL; +LCPProfile* LCPStore::getProfile (Glib::ustring filename) +{ + if (filename.length() == 0 || !isValidLCPFileName(filename)) { + return NULL; + } MyMutex::MyLock lock(mtx); std::map::iterator r = profileCache.find (filename); - if (r!=profileCache.end()) return r->second; + + if (r != profileCache.end()) { + return r->second; + } // Add profile (if exists) - profileCache[filename]=new LCPProfile(filename); + profileCache[filename] = new LCPProfile(filename); //profileCache[filename]->print(); return profileCache[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)) return false; - size_t pos=filename.find_last_of ('.'); - return pos>0 && !filename.casefold().compare (pos, 4, ".lcp"); +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)) { + return false; + } + + size_t pos = filename.find_last_of ('.'); + return pos > 0 && !filename.casefold().compare (pos, 4, ".lcp"); } -Glib::ustring LCPStore::getDefaultCommonDirectory() const { +Glib::ustring LCPStore::getDefaultCommonDirectory() const +{ Glib::ustring dir; #ifdef WIN32 - WCHAR pathW[MAX_PATH]={0}; char pathA[MAX_PATH]; + WCHAR pathW[MAX_PATH] = {0}; + char pathA[MAX_PATH]; - if (SHGetSpecialFolderPathW(NULL,pathW,CSIDL_COMMON_APPDATA,false)) { + if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_COMMON_APPDATA, false)) { char pathA[MAX_PATH]; - 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)) dir=fullDir; + 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)) { + dir = fullDir; + } } + #endif // TODO: Add Mac paths here diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 6d3707f74..fa60a6013 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -7,7 +7,7 @@ * 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 @@ -28,105 +28,111 @@ #include #include -namespace rtengine { - // Perspective model common data, also used for Vignette and Fisheye - class LCPModelCommon { - public: - float focLenX, focLenY, imgXCenter, imgYCenter; - float param[5]; // k1..k5, resp. alpha1..5 - float scaleFac; // alpha0 - double meanErr; - bool badErr; +namespace rtengine +{ +// Perspective model common data, also used for Vignette and Fisheye +class LCPModelCommon +{ +public: + float focLenX, focLenY, imgXCenter, imgYCenter; + float param[5]; // k1..k5, resp. alpha1..5 + float scaleFac; // alpha0 + double meanErr; + bool badErr; - double x0,y0,fx,fy; // prepared params + double x0, y0, fx, fy; // prepared params - LCPModelCommon(); - bool empty() const; // is it empty - void print() const; // printf all values - void merge(const LCPModelCommon& a, const LCPModelCommon& b, float facA); - void prepareParams(int fullWidth, int fullHeight, float focalLength, float focalLength35mm, float sensorFormatFactor, bool swapXY, bool mirrorX, bool mirrorY); - }; + LCPModelCommon(); + bool empty() const; // is it empty + void print() const; // printf all values + void merge(const LCPModelCommon& a, const LCPModelCommon& b, float facA); + void prepareParams(int fullWidth, int fullHeight, float focalLength, float focalLength35mm, float sensorFormatFactor, bool swapXY, bool mirrorX, bool mirrorY); +}; - class LCPPersModel { - public: - float focLen, focDist, aperture; // this is what it refers to +class LCPPersModel +{ +public: + float focLen, focDist, aperture; // this is what it refers to - LCPModelCommon base; // base perspective correction - LCPModelCommon chromRG, chromG, chromBG; // red/green, green, blue/green (may be empty) - LCPModelCommon vignette; // vignette (may be empty) + LCPModelCommon base; // base perspective correction + LCPModelCommon chromRG, chromG, chromBG; // red/green, green, blue/green (may be empty) + LCPModelCommon vignette; // vignette (may be empty) - LCPPersModel(); - bool hasModeData(int mode) const; - void print() const; - }; + LCPPersModel(); + bool hasModeData(int mode) const; + void print() const; +}; - class LCPProfile { - // Temporary data for parsing - bool inCamProfiles,firstLIDone,inPerspect,inAlternateLensID,inAlternateLensNames; - char lastTag[256],inInvalidTag[256]; - LCPPersModel* pCurPersModel; - LCPModelCommon* pCurCommon; +class LCPProfile +{ + // Temporary data for parsing + bool inCamProfiles, firstLIDone, inPerspect, inAlternateLensID, inAlternateLensNames; + char lastTag[256], inInvalidTag[256]; + LCPPersModel* pCurPersModel; + LCPModelCommon* pCurCommon; - static void XMLCALL XmlStartHandler(void *pLCPProfile, const char *el, const char **attr); - static void XMLCALL XmlTextHandler (void *pLCPProfile, const XML_Char *s, int len); - static void XMLCALL XmlEndHandler (void *pLCPProfile, const char *el); + static void XMLCALL XmlStartHandler(void *pLCPProfile, const char *el, const char **attr); + static void XMLCALL XmlTextHandler (void *pLCPProfile, const XML_Char *s, int len); + static void XMLCALL XmlEndHandler (void *pLCPProfile, const char *el); - int filterBadFrames(double maxAvgDevFac, int minFramesLeft); + int filterBadFrames(double maxAvgDevFac, int minFramesLeft); - public: - // Common data - Glib::ustring profileName, lensPrettyName, cameraPrettyName, lens, camera; // lens/camera(=model) can be auto-matched with DNG - bool isRaw,isFisheye; - float sensorFormatFactor; - int persModelCount; +public: + // Common data + Glib::ustring profileName, lensPrettyName, cameraPrettyName, lens, camera; // lens/camera(=model) can be auto-matched with DNG + bool isRaw, isFisheye; + float sensorFormatFactor; + int persModelCount; - // The correction frames - static const int MaxPersModelCount=3000; - LCPPersModel* aPersModel[MaxPersModelCount]; // Do NOT use std::list or something, it's buggy in GCC! + // The correction frames + static const int MaxPersModelCount = 3000; + LCPPersModel* aPersModel[MaxPersModelCount]; // Do NOT use std::list or something, it's buggy in GCC! - LCPProfile(Glib::ustring fname); + LCPProfile(Glib::ustring fname); - void calcParams(int mode, float focalLength, float focusDist, float aperture, LCPModelCommon *pCorr1, LCPModelCommon *pCorr2, LCPModelCommon *pCorr3) const; // Interpolates between the persModels frames + void calcParams(int mode, float focalLength, float focusDist, float aperture, LCPModelCommon *pCorr1, LCPModelCommon *pCorr2, LCPModelCommon *pCorr3) const; // Interpolates between the persModels frames - void print() const; - }; + void print() const; +}; - class LCPStore { - MyMutex mtx; +class LCPStore +{ + MyMutex mtx; - // Maps file name to profile as cache - std::map profileCache; + // Maps file name to profile as cache + std::map profileCache; - public: - Glib::ustring getDefaultCommonDirectory() const; - bool isValidLCPFileName(Glib::ustring filename) const; - LCPProfile* getProfile(Glib::ustring filename); +public: + Glib::ustring getDefaultCommonDirectory() const; + bool isValidLCPFileName(Glib::ustring filename) const; + LCPProfile* getProfile(Glib::ustring filename); - static LCPStore* getInstance(); - }; + static LCPStore* getInstance(); +}; #define lcpStore LCPStore::getInstance() - // Once precalculated class to correct a point - class LCPMapper { +// Once precalculated class to correct a point +class LCPMapper +{ - bool useCADist; // should the distortion in the CA info be used? - bool swapXY; - LCPModelCommon mc; - LCPModelCommon chrom[3]; // in order RedGreen/Green/BlueGreen + bool useCADist; // should the distortion in the CA info be used? + bool swapXY; + LCPModelCommon mc; + LCPModelCommon chrom[3]; // in order RedGreen/Green/BlueGreen - public: - bool enableCA; // is the mapper capable if CA correction? +public: + bool enableCA; // is the mapper capable if CA correction? - // precalculates the mapper. - LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, int fullWidth, int fullHeight, - const CoarseTransformParams& coarse, int rawRotationDeg); + // precalculates the mapper. + LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, int fullWidth, int fullHeight, + const CoarseTransformParams& coarse, int rawRotationDeg); - void correctDistortion(double& x, double& y) const; // MUST be the first stage - void correctCA(double& x, double& y, int channel) const; - float calcVignetteFac (int x, int y) const; // MUST be in RAW - }; + void correctDistortion(double& x, double& y) const; // MUST be the first stage + void correctCA(double& x, double& y, int channel) const; + float calcVignetteFac (int x, int y) const; // MUST be in RAW +}; } #endif diff --git a/rtengine/loadinitial.cc b/rtengine/loadinitial.cc index 382ff4e09..cd4c4e8d6 100644 --- a/rtengine/loadinitial.cc +++ b/rtengine/loadinitial.cc @@ -7,7 +7,7 @@ * 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 @@ -20,27 +20,33 @@ #include "stdimagesource.h" #include "rawimagesource.h" -namespace rtengine { +namespace rtengine +{ -InitialImage* InitialImage::load (const Glib::ustring& fname, bool isRaw, int* errorCode, ProgressListener* pl) { +InitialImage* InitialImage::load (const Glib::ustring& fname, bool isRaw, int* errorCode, ProgressListener* pl) +{ ImageSource* isrc; - if (!isRaw) + if (!isRaw) { isrc = new StdImageSource (); - else + } else { isrc = new RawImageSource (); + } isrc->setProgressListener (pl); - if(isRaw && pl == NULL) + if(isRaw && pl == NULL) { *errorCode = isrc->load (fname, true); - else + } else { *errorCode = isrc->load (fname); + } + if (*errorCode) { - delete isrc; + delete isrc; return NULL; } + return isrc; } } diff --git a/rtengine/median.h b/rtengine/median.h index 185a7e409..61da0d5a0 100644 --- a/rtengine/median.h +++ b/rtengine/median.h @@ -7,7 +7,7 @@ * 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 diff --git a/rtengine/minmax.h b/rtengine/minmax.h index c85bb3463..69e939b72 100644 --- a/rtengine/minmax.h +++ b/rtengine/minmax.h @@ -7,7 +7,7 @@ * 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 @@ -58,7 +58,7 @@ if ((a)<(b)) { \ else \ (min) = (b); \ } \ -} +} #define MAX3(a,b,c,min) \ { \ @@ -73,4 +73,4 @@ if ((a)>(b)) { \ else \ (max) = (b); \ } \ -} +} diff --git a/rtengine/myfile.cc b/rtengine/myfile.cc index e5c6d2514..1ff457234 100644 --- a/rtengine/myfile.cc +++ b/rtengine/myfile.cc @@ -7,7 +7,7 @@ * 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 @@ -39,21 +39,21 @@ void* mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { - HANDLE handle = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, PAGE_WRITECOPY, 0, 0, NULL); + HANDLE handle = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, PAGE_WRITECOPY, 0, 0, NULL); - if (handle != NULL) { - start = MapViewOfFile(handle, FILE_MAP_COPY, 0, offset, length); - CloseHandle(handle); - return start; - } + if (handle != NULL) { + start = MapViewOfFile(handle, FILE_MAP_COPY, 0, offset, length); + CloseHandle(handle); + return start; + } - return MAP_FAILED; + return MAP_FAILED; } int munmap(void *start, size_t length) { - UnmapViewOfFile(start); - return 0; + UnmapViewOfFile(start); + return 0; } #else // WIN32 @@ -68,315 +68,362 @@ int munmap(void *start, size_t length) IMFILE* fopen (const char* fname) { - int fd = safe_open_ReadOnly(fname); - if ( fd < 0 ) - return 0; + int fd = safe_open_ReadOnly(fname); - struct stat stat_buffer; - if ( fstat(fd,&stat_buffer) < 0 ) - { - printf("no stat\n"); - close(fd); - return 0; - } + if ( fd < 0 ) { + return 0; + } - void* data = mmap(0,stat_buffer.st_size,PROT_READ,MAP_PRIVATE,fd,0); - if ( data == MAP_FAILED ) - { - printf("no mmap\n"); - close(fd); - return 0; - } + struct stat stat_buffer; - IMFILE* mf = new IMFILE; + if ( fstat(fd, &stat_buffer) < 0 ) { + printf("no stat\n"); + close(fd); + return 0; + } - memset(mf, 0, sizeof(*mf)); - mf->fd = fd; - mf->pos = 0; - mf->size = stat_buffer.st_size; - mf->data = (char*)data; - mf->eof = false; + void* data = mmap(0, stat_buffer.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + + if ( data == MAP_FAILED ) { + printf("no mmap\n"); + close(fd); + return 0; + } + + IMFILE* mf = new IMFILE; + + memset(mf, 0, sizeof(*mf)); + mf->fd = fd; + mf->pos = 0; + mf->size = stat_buffer.st_size; + mf->data = (char*)data; + mf->eof = false; #ifdef BZIP_SUPPORT - { - bool bzip = false; - Glib::ustring bname = Glib::path_get_basename(fname); - size_t lastdot = bname.find_last_of ('.'); - if (lastdot!=bname.npos) - bzip = bname.substr (lastdot).casefold() == Glib::ustring(".bz2").casefold(); - - if (bzip) { - int ret; + { + bool bzip = false; + Glib::ustring bname = Glib::path_get_basename(fname); + size_t lastdot = bname.find_last_of ('.'); - // initialize bzip stream structure - bz_stream stream; - stream.bzalloc = 0; - stream.bzfree = 0; - stream.opaque = 0; - ret = BZ2_bzDecompressInit(&stream, 0, 0); + if (lastdot != bname.npos) { + bzip = bname.substr (lastdot).casefold() == Glib::ustring(".bz2").casefold(); + } - if (ret != BZ_OK) { - printf("bzip initialization failed with error %d\n", ret); - } - else { - // allocate initial buffer for decompressed data - unsigned int buffer_out_count = 0; // bytes of decompressed data - unsigned int buffer_size = 10*1024*1024; // 10 MB, extended dynamically if needed - char* buffer = 0; + if (bzip) { + int ret; - stream.next_in = mf->data; // input data address - stream.avail_in = mf->size; + // initialize bzip stream structure + bz_stream stream; + stream.bzalloc = 0; + stream.bzfree = 0; + stream.opaque = 0; + ret = BZ2_bzDecompressInit(&stream, 0, 0); - while (ret == BZ_OK) { - buffer = static_cast( realloc(buffer, buffer_size)); // allocate/resize buffer - if (!buffer) free(buffer); + if (ret != BZ_OK) { + printf("bzip initialization failed with error %d\n", ret); + } else { + // allocate initial buffer for decompressed data + unsigned int buffer_out_count = 0; // bytes of decompressed data + unsigned int buffer_size = 10 * 1024 * 1024; // 10 MB, extended dynamically if needed + char* buffer = 0; - stream.next_out = buffer + buffer_out_count; // output data adress - stream.avail_out = buffer_size - buffer_out_count; + stream.next_in = mf->data; // input data address + stream.avail_in = mf->size; - ret = BZ2_bzDecompress(&stream); + while (ret == BZ_OK) { + buffer = static_cast( realloc(buffer, buffer_size)); // allocate/resize buffer - buffer_size *= 2; // increase buffer size for next iteration - buffer_out_count = stream.total_out_lo32; - if (stream.total_out_hi32 > 0) - printf("bzip decompressed data byte count high byte is nonzero: %d\n", stream.total_out_hi32); - } + if (!buffer) { + free(buffer); + } - if (ret == BZ_STREAM_END) { - //delete [] mf->data; - // close memory mapping, setting fd -1 will ensure deletion of mf->data upon fclose() - mf->fd = -1; - munmap((void*)mf->data,mf->size); - close(mf->fd); + stream.next_out = buffer + buffer_out_count; // output data adress + stream.avail_out = buffer_size - buffer_out_count; - char* realData = new char [buffer_out_count]; - memcpy(realData, buffer, buffer_out_count); + ret = BZ2_bzDecompress(&stream); - mf->data = realData; - mf->size = buffer_out_count; - } - else - printf("bzip decompression failed with error %d\n", ret); + buffer_size *= 2; // increase buffer size for next iteration + buffer_out_count = stream.total_out_lo32; - // cleanup - free(buffer); - ret = BZ2_bzDecompressEnd(&stream); - if (ret != BZ_OK) - printf("bzip cleanup failed with error %d\n", ret); - } - } - } + if (stream.total_out_hi32 > 0) { + printf("bzip decompressed data byte count high byte is nonzero: %d\n", stream.total_out_hi32); + } + } + + if (ret == BZ_STREAM_END) { + //delete [] mf->data; + // close memory mapping, setting fd -1 will ensure deletion of mf->data upon fclose() + mf->fd = -1; + munmap((void*)mf->data, mf->size); + close(mf->fd); + + char* realData = new char [buffer_out_count]; + memcpy(realData, buffer, buffer_out_count); + + mf->data = realData; + mf->size = buffer_out_count; + } else { + printf("bzip decompression failed with error %d\n", ret); + } + + // cleanup + free(buffer); + ret = BZ2_bzDecompressEnd(&stream); + + if (ret != BZ_OK) { + printf("bzip cleanup failed with error %d\n", ret); + } + } + } + } #endif // BZIP_SUPPORT - return mf; -} - -IMFILE* gfopen (const char* fname) -{ - return fopen(fname); -} -#else - -IMFILE* fopen (const char* fname) { - - FILE* f = g_fopen (fname, "rb"); - if (!f) - return NULL; - IMFILE* mf = new IMFILE; - memset(mf, 0, sizeof(*mf)); - fseek (f, 0, SEEK_END); - mf->size = ftell (f); - mf->data = new char [mf->size]; - fseek (f, 0, SEEK_SET); - fread (mf->data, 1, mf->size, f); - fclose (f); - mf->pos = 0; - mf->eof = false; - return mf; } -IMFILE* gfopen (const char* fname) { +IMFILE* gfopen (const char* fname) +{ + return fopen(fname); +} +#else - FILE* f = g_fopen (fname, "rb"); - if (!f) +IMFILE* fopen (const char* fname) +{ + + FILE* f = g_fopen (fname, "rb"); + + if (!f) { return NULL; + } + IMFILE* mf = new IMFILE; - memset(mf, 0, sizeof(*mf)); - fseek (f, 0, SEEK_END); - mf->size = ftell (f); - mf->data = new char [mf->size]; - fseek (f, 0, SEEK_SET); - fread (mf->data, 1, mf->size, f); - fclose (f); - mf->pos = 0; - mf->eof = false; + memset(mf, 0, sizeof(*mf)); + fseek (f, 0, SEEK_END); + mf->size = ftell (f); + mf->data = new char [mf->size]; + fseek (f, 0, SEEK_SET); + fread (mf->data, 1, mf->size, f); + fclose (f); + mf->pos = 0; + mf->eof = false; + + return mf; +} + +IMFILE* gfopen (const char* fname) +{ + + FILE* f = g_fopen (fname, "rb"); + + if (!f) { + return NULL; + } + + IMFILE* mf = new IMFILE; + memset(mf, 0, sizeof(*mf)); + fseek (f, 0, SEEK_END); + mf->size = ftell (f); + mf->data = new char [mf->size]; + fseek (f, 0, SEEK_SET); + fread (mf->data, 1, mf->size, f); + fclose (f); + mf->pos = 0; + mf->eof = false; #ifdef BZIP_SUPPORT { - bool bzip = false; - Glib::ustring bname = Glib::path_get_basename(fname); - size_t lastdot = bname.find_last_of ('.'); - if (lastdot!=bname.npos) - bzip = bname.substr (lastdot).casefold() == Glib::ustring(".bz2").casefold(); - - if (bzip) { - int ret; + bool bzip = false; + Glib::ustring bname = Glib::path_get_basename(fname); + size_t lastdot = bname.find_last_of ('.'); - // initialize bzip stream structure - bz_stream stream; - stream.bzalloc = 0; - stream.bzfree = 0; - stream.opaque = 0; - ret = BZ2_bzDecompressInit(&stream, 0, 0); + if (lastdot != bname.npos) { + bzip = bname.substr (lastdot).casefold() == Glib::ustring(".bz2").casefold(); + } - if (ret != BZ_OK) { - printf("bzip initialization failed with error %d\n", ret); - } - else { - // allocate initial buffer for decompressed data - unsigned int buffer_out_count = 0; // bytes of decompressed data - unsigned int buffer_size = 10*1024*1024; // 10 MB, extended dynamically if needed - char* buffer = 0; + if (bzip) { + int ret; - stream.next_in = mf->data; // input data address - stream.avail_in = mf->size; + // initialize bzip stream structure + bz_stream stream; + stream.bzalloc = 0; + stream.bzfree = 0; + stream.opaque = 0; + ret = BZ2_bzDecompressInit(&stream, 0, 0); - while (ret == BZ_OK) { - buffer = static_cast( realloc(buffer, buffer_size)); // allocate/resize buffer - if (!buffer) free(buffer); + if (ret != BZ_OK) { + printf("bzip initialization failed with error %d\n", ret); + } else { + // allocate initial buffer for decompressed data + unsigned int buffer_out_count = 0; // bytes of decompressed data + unsigned int buffer_size = 10 * 1024 * 1024; // 10 MB, extended dynamically if needed + char* buffer = 0; - stream.next_out = buffer + buffer_out_count; // output data adress - stream.avail_out = buffer_size - buffer_out_count; + stream.next_in = mf->data; // input data address + stream.avail_in = mf->size; - ret = BZ2_bzDecompress(&stream); + while (ret == BZ_OK) { + buffer = static_cast( realloc(buffer, buffer_size)); // allocate/resize buffer - buffer_size *= 2; // increase buffer size for next iteration - buffer_out_count = stream.total_out_lo32; - if (stream.total_out_hi32 > 0) - printf("bzip decompressed data byte count high byte is nonzero: %d\n", stream.total_out_hi32); - } + if (!buffer) { + free(buffer); + } - if (ret == BZ_STREAM_END) { - delete [] mf->data; - char* realData = new char [buffer_out_count]; - memcpy(realData, buffer, buffer_out_count); + stream.next_out = buffer + buffer_out_count; // output data adress + stream.avail_out = buffer_size - buffer_out_count; - mf->data = realData; - mf->size = buffer_out_count; - } - else - printf("bzip decompression failed with error %d\n", ret); + ret = BZ2_bzDecompress(&stream); - // cleanup - free(buffer); - ret = BZ2_bzDecompressEnd(&stream); - if (ret != BZ_OK) - printf("bzip cleanup failed with error %d\n", ret); - } - } + buffer_size *= 2; // increase buffer size for next iteration + buffer_out_count = stream.total_out_lo32; + + if (stream.total_out_hi32 > 0) { + printf("bzip decompressed data byte count high byte is nonzero: %d\n", stream.total_out_hi32); + } + } + + if (ret == BZ_STREAM_END) { + delete [] mf->data; + char* realData = new char [buffer_out_count]; + memcpy(realData, buffer, buffer_out_count); + + mf->data = realData; + mf->size = buffer_out_count; + } else { + printf("bzip decompression failed with error %d\n", ret); + } + + // cleanup + free(buffer); + ret = BZ2_bzDecompressEnd(&stream); + + if (ret != BZ_OK) { + printf("bzip cleanup failed with error %d\n", ret); + } + } + } } #endif // BZIP_SUPPORT return mf; } #endif //MYFILE_MMAP -IMFILE* fopen (unsigned* buf, int size) { +IMFILE* fopen (unsigned* buf, int size) +{ - IMFILE* mf = new IMFILE; - memset(mf, 0, sizeof(*mf)); - mf->fd = -1; - mf->size = size; - mf->data = new char [mf->size]; - memcpy ((void*)mf->data, buf, size); - mf->pos = 0; - mf->eof = false; - return mf; + IMFILE* mf = new IMFILE; + memset(mf, 0, sizeof(*mf)); + mf->fd = -1; + mf->size = size; + mf->data = new char [mf->size]; + memcpy ((void*)mf->data, buf, size); + mf->pos = 0; + mf->eof = false; + return mf; } -void fclose (IMFILE* f) { +void fclose (IMFILE* f) +{ #ifdef MYFILE_MMAP - if ( f->fd == -1 ) - { - delete [] f->data; - } - else - { - munmap((void*)f->data,f->size); - close(f->fd); - } + + if ( f->fd == -1 ) { + delete [] f->data; + } else { + munmap((void*)f->data, f->size); + close(f->fd); + } + #else - delete [] f->data; + delete [] f->data; #endif - delete f; + delete f; } -int fscanf (IMFILE* f, const char* s ...) { - // fscanf not easily wrapped since we have no terminating \0 at end - // of file data and vsscanf() won't tell us how many characters that - // were parsed. However, only dcraw.cc code use it and only for "%f" and - // "%d", so we make a dummy fscanf here just to support dcraw case. - char buf[50], *endptr; - int copy_sz = f->size - f->pos; - if (copy_sz > sizeof(buf)) { - copy_sz = sizeof(buf) - 1; +int fscanf (IMFILE* f, const char* s ...) +{ + // fscanf not easily wrapped since we have no terminating \0 at end + // of file data and vsscanf() won't tell us how many characters that + // were parsed. However, only dcraw.cc code use it and only for "%f" and + // "%d", so we make a dummy fscanf here just to support dcraw case. + char buf[50], *endptr; + int copy_sz = f->size - f->pos; + + if (copy_sz > sizeof(buf)) { + copy_sz = sizeof(buf) - 1; + } + + memcpy(buf, &f->data[f->pos], copy_sz); + buf[copy_sz] = '\0'; + va_list ap; + va_start (ap, s); + + if (strcmp(s, "%d") == 0) { + int i = strtol(buf, &endptr, 10); + + if (endptr == buf) { + return 0; } - memcpy(buf, &f->data[f->pos], copy_sz); - buf[copy_sz] = '\0'; - va_list ap; - va_start (ap, s); - if (strcmp(s, "%d") == 0) { - int i = strtol(buf, &endptr, 10); - if (endptr == buf) { - return 0; - } - int *pi = va_arg(ap, int*); - *pi = i; - } else if (strcmp(s, "%f") == 0) { - float f = strtof(buf, &endptr); - if (endptr == buf) { - return 0; - } - float *pf = va_arg(ap, float*); - *pf = f; + + int *pi = va_arg(ap, int*); + *pi = i; + } else if (strcmp(s, "%f") == 0) { + float f = strtof(buf, &endptr); + + if (endptr == buf) { + return 0; } - va_end (ap); - f->pos += endptr - buf; - return 1; + + float *pf = va_arg(ap, float*); + *pf = f; + } + + va_end (ap); + f->pos += endptr - buf; + return 1; } -char* fgets (char* s, int n, IMFILE* f) { +char* fgets (char* s, int n, IMFILE* f) +{ - if (f->pos>=f->size) { - f->eof = true; - return NULL; - } - int i = 0; - do s[i++] = f->data[f->pos++]; - while (ipossize); - return s; + if (f->pos >= f->size) { + f->eof = true; + return NULL; + } + + int i = 0; + + do { + s[i++] = f->data[f->pos++]; + } while (i < n && f->pos < f->size); + + return s; } -void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range) { - f->plistener = plistener; - f->progress_range = progress_range; - f->progress_next = f->size / 10 + 1; - f->progress_current = 0; +void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, double progress_range) +{ + f->plistener = plistener; + f->progress_range = progress_range; + f->progress_next = f->size / 10 + 1; + f->progress_current = 0; } -void imfile_update_progress(IMFILE *f) { - if (!f->plistener || f->progress_current < f->progress_next) { - return; - } - do { - f->progress_next += f->size / 10 + 1; - } while (f->progress_next < f->progress_current); - double p = (double)f->progress_current / f->size; - if (p > 1.0) { - /* this can happen if same bytes are read over and over again. Progress bar is not intended - to be exact, just give some progress indication for normal raw file access patterns */ - p = 1.0; - } - f->plistener->setProgress(p * f->progress_range); +void imfile_update_progress(IMFILE *f) +{ + if (!f->plistener || f->progress_current < f->progress_next) { + return; + } + + do { + f->progress_next += f->size / 10 + 1; + } while (f->progress_next < f->progress_current); + + double p = (double)f->progress_current / f->size; + + if (p > 1.0) { + /* this can happen if same bytes are read over and over again. Progress bar is not intended + to be exact, just give some progress indication for normal raw file access patterns */ + p = 1.0; + } + + f->plistener->setProgress(p * f->progress_range); } diff --git a/rtengine/myfile.h b/rtengine/myfile.h index 8870c66a8..9e9039a7a 100644 --- a/rtengine/myfile.h +++ b/rtengine/myfile.h @@ -7,7 +7,7 @@ * 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 @@ -24,15 +24,15 @@ #include #include "rtengine.h" struct IMFILE { - int fd; - ssize_t pos; - ssize_t size; - char* data; - bool eof; - rtengine::ProgressListener *plistener; - double progress_range; - ssize_t progress_next; - ssize_t progress_current; + int fd; + ssize_t pos; + ssize_t size; + char* data; + bool eof; + rtengine::ProgressListener *plistener; + double progress_range; + ssize_t progress_next; + ssize_t progress_current; }; /* @@ -44,74 +44,89 @@ void imfile_set_plistener(IMFILE *f, rtengine::ProgressListener *plistener, doub void imfile_update_progress(IMFILE *f); IMFILE* fopen (const char* fname); -IMFILE* gfopen (const char* fname);IMFILE* fopen (unsigned* buf, int size); +IMFILE* gfopen (const char* fname); +IMFILE* fopen (unsigned* buf, int size); void fclose (IMFILE* f); -inline int ftell (IMFILE* f) { +inline int ftell (IMFILE* f) +{ - return f->pos; + return f->pos; } -inline int feof (IMFILE* f) { +inline int feof (IMFILE* f) +{ - return f->eof; + return f->eof; } -inline void fseek (IMFILE* f, int p, int how) { - int fpos = f->pos; +inline void fseek (IMFILE* f, int p, int how) +{ + int fpos = f->pos; - if (how==SEEK_SET) - f->pos = p; - else if (how==SEEK_CUR) - f->pos += p; - else if (how==SEEK_END) - f->pos = f->size+p; + if (how == SEEK_SET) { + f->pos = p; + } else if (how == SEEK_CUR) { + f->pos += p; + } else if (how == SEEK_END) { + f->pos = f->size + p; + } - if (f->pos < 0 || f->pos> f->size) - f->pos = fpos; + if (f->pos < 0 || f->pos > f->size) { + f->pos = fpos; + } } -inline int fgetc (IMFILE* f) { +inline int fgetc (IMFILE* f) +{ - if (f->possize) { - if (f->plistener && ++f->progress_current >= f->progress_next) { - imfile_update_progress(f); - } - return (unsigned char)f->data[f->pos++]; - } - f->eof = true; - return EOF; + if (f->pos < f->size) { + if (f->plistener && ++f->progress_current >= f->progress_next) { + imfile_update_progress(f); + } + + return (unsigned char)f->data[f->pos++]; + } + + f->eof = true; + return EOF; } -inline int getc (IMFILE* f) { +inline int getc (IMFILE* f) +{ - return fgetc(f); + return fgetc(f); } -inline int fread (void* dst, int es, int count, IMFILE* f) { +inline int fread (void* dst, int es, int count, IMFILE* f) +{ - int s = es*count; - int avail = f->size - f->pos; - if (s<=avail) { - memcpy (dst, f->data+f->pos, s); - f->pos += s; - if (f->plistener) { - f->progress_current += s; - if (f->progress_current >= f->progress_next) { - imfile_update_progress(f); - } - } - return count; - } - else { - memcpy (dst, f->data+f->pos, avail); - f->pos += avail; - f->eof = true; - return avail/es; - } + int s = es * count; + int avail = f->size - f->pos; + + if (s <= avail) { + memcpy (dst, f->data + f->pos, s); + f->pos += s; + + if (f->plistener) { + f->progress_current += s; + + if (f->progress_current >= f->progress_next) { + imfile_update_progress(f); + } + } + + return count; + } else { + memcpy (dst, f->data + f->pos, avail); + f->pos += avail; + f->eof = true; + return avail / es; + } } -inline unsigned char* fdata(int offset, IMFILE* f) { - return (unsigned char*)f->data + offset; +inline unsigned char* fdata(int offset, IMFILE* f) +{ + return (unsigned char*)f->data + offset; } int fscanf (IMFILE* f, const char* s ...); diff --git a/rtengine/mytime.h b/rtengine/mytime.h index 19b963ca8..f73d563d2 100644 --- a/rtengine/mytime.h +++ b/rtengine/mytime.h @@ -7,7 +7,7 @@ * 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 @@ -25,47 +25,51 @@ #include #else #include -#endif - -class MyTime { - - public: -#ifndef WIN32 - timespec t; -#else - LONGLONG t; - LONGLONG baseFrequency; - MyTime(){ - LARGE_INTEGER ulf; - QueryPerformanceFrequency(&ulf); - baseFrequency = ulf.QuadPart; - QueryPerformanceCounter(&ulf); - t = ulf.QuadPart; - } #endif - void set () { +class MyTime +{ + +public: +#ifndef WIN32 + timespec t; +#else + LONGLONG t; + LONGLONG baseFrequency; + MyTime() + { + LARGE_INTEGER ulf; + QueryPerformanceFrequency(&ulf); + baseFrequency = ulf.QuadPart; + QueryPerformanceCounter(&ulf); + t = ulf.QuadPart; + } +#endif + + void set () + { #ifdef WIN32 - LARGE_INTEGER ulf; - QueryPerformanceCounter(&ulf); - t = ulf.QuadPart; + LARGE_INTEGER ulf; + QueryPerformanceCounter(&ulf); + t = ulf.QuadPart; #elif defined __APPLE__ - struct timeval tv; - gettimeofday(&tv, NULL); - t.tv_sec = tv.tv_sec; - t.tv_nsec = tv.tv_usec*1000; + struct timeval tv; + gettimeofday(&tv, NULL); + t.tv_sec = tv.tv_sec; + t.tv_nsec = tv.tv_usec * 1000; #else - clock_gettime (CLOCK_REALTIME, &t); -#endif -} - - int etime (MyTime a) { -#ifndef WIN32 - return (t.tv_sec-a.t.tv_sec)*1000000 + (t.tv_nsec-a.t.tv_nsec)/1000; -#else - return (t - a.t)*1000/(baseFrequency/1000); + clock_gettime (CLOCK_REALTIME, &t); #endif - } + } + + int etime (MyTime a) + { +#ifndef WIN32 + return (t.tv_sec - a.t.tv_sec) * 1000000 + (t.tv_nsec - a.t.tv_nsec) / 1000; +#else + return (t - a.t) * 1000 / (baseFrequency / 1000); +#endif + } }; diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h index 2f7099687..1da03190b 100644 --- a/rtengine/opthelper.h +++ b/rtengine/opthelper.h @@ -1,75 +1,75 @@ //////////////////////////////////////////////////////////////// // // opthelper.h includes some #defines which help to make optimizations easier and better readable -// -// copyright (c) 2013 Ingo Weyrich // -// this 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. +// copyright (c) 2013 Ingo Weyrich // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// this 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. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // //////////////////////////////////////////////////////////////// #ifndef OPTHELPER_H - #define OPTHELPER_H +#define OPTHELPER_H - #ifdef __SSE2__ - #include "sleefsseavx.c" - #ifdef __GNUC__ - #if defined(WIN32) && !defined( __x86_64__ ) - // needed for actual versions of GCC with 32-Bit Windows - #define SSEFUNCTION __attribute__((force_align_arg_pointer)) - #else - #define SSEFUNCTION - #endif - #else - #define SSEFUNCTION - #endif - #else - #ifdef __SSE__ - #ifdef __GNUC__ - #if defined(WIN32) && !defined( __x86_64__ ) - // needed for actual versions of GCC with 32-Bit Windows - #define SSEFUNCTION __attribute__((force_align_arg_pointer)) - #else - #define SSEFUNCTION - #endif - #else - #define SSEFUNCTION - #endif - #else - #define SSEFUNCTION - #endif - #endif - - #ifdef __GNUC__ - #define RESTRICT __restrict__ - #define LIKELY(x) __builtin_expect (!!(x), 1) - #define UNLIKELY(x) __builtin_expect (!!(x), 0) - #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 - #define ALIGNED64 __attribute__ ((aligned (64))) - #define ALIGNED16 __attribute__ ((aligned (16))) - #else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3 - #define ALIGNED64 - #define ALIGNED16 - #endif - #else - #define RESTRICT - #define LIKELY(x) (x) - #define UNLIKELY(x) (x) - #define ALIGNED64 - #define ALIGNED16 - #endif - #ifndef __clang__ - #define _RT_NESTED_OPENMP _OPENMP - #endif +#ifdef __SSE2__ +#include "sleefsseavx.c" +#ifdef __GNUC__ +#if defined(WIN32) && !defined( __x86_64__ ) +// needed for actual versions of GCC with 32-Bit Windows +#define SSEFUNCTION __attribute__((force_align_arg_pointer)) +#else +#define SSEFUNCTION +#endif +#else +#define SSEFUNCTION +#endif +#else +#ifdef __SSE__ +#ifdef __GNUC__ +#if defined(WIN32) && !defined( __x86_64__ ) +// needed for actual versions of GCC with 32-Bit Windows +#define SSEFUNCTION __attribute__((force_align_arg_pointer)) +#else +#define SSEFUNCTION +#endif +#else +#define SSEFUNCTION +#endif +#else +#define SSEFUNCTION +#endif +#endif + +#ifdef __GNUC__ +#define RESTRICT __restrict__ +#define LIKELY(x) __builtin_expect (!!(x), 1) +#define UNLIKELY(x) __builtin_expect (!!(x), 0) +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 +#define ALIGNED64 __attribute__ ((aligned (64))) +#define ALIGNED16 __attribute__ ((aligned (16))) +#else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3 +#define ALIGNED64 +#define ALIGNED16 +#endif +#else +#define RESTRICT +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#define ALIGNED64 +#define ALIGNED16 +#endif +#ifndef __clang__ +#define _RT_NESTED_OPENMP _OPENMP +#endif #endif diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index 480d228f5..0c2509e7d 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -28,166 +28,188 @@ using namespace rtengine; using namespace procparams; -PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext, const PreviewImageMode mode) { - rtengine::Thumbnail* tpp=NULL; - - if (mode==PIM_EmbeddedPreviewOnly || mode==PIM_EmbeddedOrRaw) { - - const unsigned char *data = NULL; - - int width=-1, height=-1; - if (ext.lowercase()=="jpg" || ext.lowercase()=="jpeg") { - // int deg = infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true); - if (tpp) - data = tpp->getImage8Data(); - } - else if (ext.lowercase()=="png") { - tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true); - if (tpp) - data = tpp->getImage8Data(); - } - else if (ext.lowercase()=="tif" || ext.lowercase()=="tiff") { - // int deg = infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true); - if (tpp) - data = tpp->getImage8Data(); - } - else { - rtengine::RawMetaDataLocation ri; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, width, height, 1, true, true); - if (tpp) - data = tpp->getImage8Data(); - } - - if (tpp) { - if (data) { - int w, h; - double scale = 1.; - if (tpp) - tpp->getDimensions(w, h, scale); - previewImage = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h); - previewImage->flush(); - -#pragma omp parallel +PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext, const PreviewImageMode mode) { - const unsigned char *src; - unsigned char *dst; -#pragma omp for schedule(static,10) - for (unsigned int i=0; i<(unsigned int)(h); i++) { - src = data + i*w*3; - dst = previewImage->get_data() + i*w*4; - for (unsigned int j=0; j<(unsigned int)(w); j++) { - unsigned char r = *(src++); - unsigned char g = *(src++); - unsigned char b = *(src++); + rtengine::Thumbnail* tpp = NULL; + + if (mode == PIM_EmbeddedPreviewOnly || mode == PIM_EmbeddedOrRaw) { + + const unsigned char *data = NULL; + + int width = -1, height = -1; + + if (ext.lowercase() == "jpg" || ext.lowercase() == "jpeg") { + // int deg = infoFromImage (fname); + tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true); + + if (tpp) { + data = tpp->getImage8Data(); + } + } else if (ext.lowercase() == "png") { + tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true); + + if (tpp) { + data = tpp->getImage8Data(); + } + } else if (ext.lowercase() == "tif" || ext.lowercase() == "tiff") { + // int deg = infoFromImage (fname); + tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true); + + if (tpp) { + data = tpp->getImage8Data(); + } + } else { + rtengine::RawMetaDataLocation ri; + tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, width, height, 1, true, true); + + if (tpp) { + data = tpp->getImage8Data(); + } + } + + if (tpp) { + if (data) { + int w, h; + double scale = 1.; + + if (tpp) { + tpp->getDimensions(w, h, scale); + } + + previewImage = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h); + previewImage->flush(); + + #pragma omp parallel + { + const unsigned char *src; + unsigned char *dst; + #pragma omp for schedule(static,10) + + for (unsigned int i = 0; i < (unsigned int)(h); i++) { + src = data + i * w * 3; + dst = previewImage->get_data() + i * w * 4; + + for (unsigned int j = 0; j < (unsigned int)(w); j++) { + unsigned char r = *(src++); + unsigned char g = *(src++); + unsigned char b = *(src++); #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ - *(dst++) = b; - *(dst++) = g; - *(dst++) = r; - *(dst++) = 0; + *(dst++) = b; + *(dst++) = g; + *(dst++) = r; + *(dst++) = 0; #else - *(dst++) = 0; - *(dst++) = r; - *(dst++) = g; - *(dst++) = b; + *(dst++) = 0; + *(dst++) = r; + *(dst++) = g; + *(dst++) = b; #endif - } - } -} - previewImage->mark_dirty(); - } - } - } + } + } + } + previewImage->mark_dirty(); + } + } + } - if ((mode==PIM_EmbeddedOrRaw && !tpp) || mode==PIM_ForceRaw) { - RawImageSource rawImage; - int error = rawImage.load(fname, true); - if (!error) { - rtengine::Image8 *output = NULL; - const unsigned char *data = NULL; - int fw, fh; - procparams::ProcParams params; - /*rtengine::RAWParams raw; - rtengine::LensProfParams lensProf; - rtengine::procparams::ToneCurveParams toneCurve; - rtengine::procparams::ColorManagementParams icm; - rtengine::CoarseTransformParams coarse;*/ - ColorTemp wb = rawImage.getWB (); - rawImage.getFullSize (fw, fh, TR_NONE); - PreviewProps pp (0, 0, fw, fh, 1); - params.icm.input = Glib::ustring("(embedded)"); - params.raw.bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast]; - params.raw.deadPixelFilter = false; - params.raw.ca_autocorrect = false; - params.raw.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast]; - rawImage.preprocess(params.raw, params.lensProf, params.coarse); - rawImage.demosaic(params.raw); - Imagefloat* image = new rtengine::Imagefloat (fw, fh); - 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; ir(i,j) = Color::gamma2curve[image->r(i,j)]; - image->g(i,j) = Color::gamma2curve[image->g(i,j)]; - image->b(i,j) = Color::gamma2curve[image->b(i,j)]; - } - Stop1.stop(); + if ((mode == PIM_EmbeddedOrRaw && !tpp) || mode == PIM_ForceRaw) { + RawImageSource rawImage; + int error = rawImage.load(fname, true); - image->resizeImgTo(fw, fh, TI_Nearest, output); - data = output->getData(); + if (!error) { + rtengine::Image8 *output = NULL; + const unsigned char *data = NULL; + int fw, fh; + procparams::ProcParams params; + /*rtengine::RAWParams raw; + rtengine::LensProfParams lensProf; + rtengine::procparams::ToneCurveParams toneCurve; + rtengine::procparams::ColorManagementParams icm; + rtengine::CoarseTransformParams coarse;*/ + ColorTemp wb = rawImage.getWB (); + rawImage.getFullSize (fw, fh, TR_NONE); + PreviewProps pp (0, 0, fw, fh, 1); + params.icm.input = Glib::ustring("(embedded)"); + params.raw.bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast]; + params.raw.deadPixelFilter = false; + params.raw.ca_autocorrect = false; + params.raw.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast]; + rawImage.preprocess(params.raw, params.lensProf, params.coarse); + rawImage.demosaic(params.raw); + Imagefloat* image = new rtengine::Imagefloat (fw, fh); + 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)]; + image->g(i, j) = Color::gamma2curve[image->g(i, j)]; + image->b(i, j) = Color::gamma2curve[image->b(i, j)]; + } + + Stop1.stop(); + + image->resizeImgTo(fw, fh, TI_Nearest, output); + data = output->getData(); - if (data) { - int w, h; - double scale = 1.; - w = output->getWidth(); - h = output->getHeight(); - previewImage = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h); - previewImage->flush(); + if (data) { + int w, h; + double scale = 1.; + w = output->getWidth(); + h = output->getHeight(); + previewImage = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h); + previewImage->flush(); -#pragma omp parallel -{ - const unsigned char *src; - unsigned char *dst; -#pragma omp for schedule(static,10) - for (unsigned int i=0; i<(unsigned int)(h); i++) { - src = data + i*w*3; - dst = previewImage->get_data() + i*w*4; - for (unsigned int j=0; j<(unsigned int)(w); j++) { - unsigned char r = *(src++); - unsigned char g = *(src++); - unsigned char b = *(src++); + #pragma omp parallel + { + const unsigned char *src; + unsigned char *dst; + #pragma omp for schedule(static,10) + + for (unsigned int i = 0; i < (unsigned int)(h); i++) { + src = data + i * w * 3; + dst = previewImage->get_data() + i * w * 4; + + for (unsigned int j = 0; j < (unsigned int)(w); j++) { + unsigned char r = *(src++); + unsigned char g = *(src++); + unsigned char b = *(src++); #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ - *(dst++) = b; - *(dst++) = g; - *(dst++) = r; - *(dst++) = 0; + *(dst++) = b; + *(dst++) = g; + *(dst++) = r; + *(dst++) = 0; #else - *(dst++) = 0; - *(dst++) = r; - *(dst++) = g; - *(dst++) = b; + *(dst++) = 0; + *(dst++) = r; + *(dst++) = g; + *(dst++) = b; #endif - } - } -} - if (output) - delete output; - previewImage->mark_dirty(); - } - } - } + } + } + } - if (tpp) - delete tpp; + if (output) { + delete output; + } + + previewImage->mark_dirty(); + } + } + } + + if (tpp) { + delete tpp; + } } -Cairo::RefPtr PreviewImage::getImage() { - return previewImage; +Cairo::RefPtr PreviewImage::getImage() +{ + return previewImage; } diff --git a/rtengine/previewimage.h b/rtengine/previewimage.h index 46c90b0b8..5135ddd9a 100644 --- a/rtengine/previewimage.h +++ b/rtengine/previewimage.h @@ -22,7 +22,8 @@ #include #include "cairomm/cairomm.h" -namespace rtengine { +namespace rtengine +{ /** @brief Get a quick preview image out of a raw or standard file * @@ -31,21 +32,22 @@ namespace rtengine { * * For standard image, it simply read it with fast conversion for 32 bits images */ -class PreviewImage { +class PreviewImage +{ private: - Cairo::RefPtr previewImage; + Cairo::RefPtr previewImage; public: - typedef enum mode { - PIM_EmbeddedPreviewOnly, /// Get the embedded image only, fail if doesn't exist - PIM_EmbeddedOrRaw, /// Get the embedded image if it exist, or use the raw file otherwise - PIM_ForceRaw /// Get a preview of the raw file, even if an embedded image exist - } PreviewImageMode; + typedef enum mode { + PIM_EmbeddedPreviewOnly, /// Get the embedded image only, fail if doesn't exist + PIM_EmbeddedOrRaw, /// Get the embedded image if it exist, or use the raw file otherwise + PIM_ForceRaw /// Get a preview of the raw file, even if an embedded image exist + } PreviewImageMode; - PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext, const PreviewImageMode mode); + PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext, const PreviewImageMode mode); - Cairo::RefPtr getImage(); + Cairo::RefPtr getImage(); }; diff --git a/rtengine/processingjob.cc b/rtengine/processingjob.cc index 6b1c30d28..612edc2a2 100644 --- a/rtengine/processingjob.cc +++ b/rtengine/processingjob.cc @@ -7,7 +7,7 @@ * 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 @@ -18,21 +18,25 @@ */ #include "processingjob.h" -namespace rtengine { +namespace rtengine +{ -ProcessingJob* ProcessingJob::create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams) { +ProcessingJob* ProcessingJob::create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams) +{ return new ProcessingJobImpl (fname, isRaw, pparams); } -ProcessingJob* ProcessingJob::create (InitialImage* initialImage, const procparams::ProcParams& pparams) { +ProcessingJob* ProcessingJob::create (InitialImage* initialImage, const procparams::ProcParams& pparams) +{ return new ProcessingJobImpl (initialImage, pparams); } -void ProcessingJob::destroy (ProcessingJob* job) { +void ProcessingJob::destroy (ProcessingJob* job) +{ - delete static_cast(job); + delete static_cast(job); } } diff --git a/rtengine/processingjob.h b/rtengine/processingjob.h index 800b58820..3364e6daf 100644 --- a/rtengine/processingjob.h +++ b/rtengine/processingjob.h @@ -7,7 +7,7 @@ * 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 @@ -21,23 +21,37 @@ #include "rtengine.h" -namespace rtengine { +namespace rtengine +{ -class ProcessingJobImpl : public ProcessingJob { +class ProcessingJobImpl : public ProcessingJob +{ - public: - Glib::ustring fname; - bool isRaw; - InitialImage* initialImage; - procparams::ProcParams pparams; - - ProcessingJobImpl (const Glib::ustring& fn, bool iR, const procparams::ProcParams& pp) - : fname(fn), isRaw(iR), initialImage(NULL) { pparams = pp; } +public: + Glib::ustring fname; + bool isRaw; + InitialImage* initialImage; + procparams::ProcParams pparams; - ProcessingJobImpl (InitialImage* iImage, const procparams::ProcParams& pp) - : fname(""), initialImage(iImage) { pparams = pp; iImage->increaseRef(); } - - ~ProcessingJobImpl () { if (initialImage) initialImage->decreaseRef(); } + ProcessingJobImpl (const Glib::ustring& fn, bool iR, const procparams::ProcParams& pp) + : fname(fn), isRaw(iR), initialImage(NULL) + { + pparams = pp; + } + + ProcessingJobImpl (InitialImage* iImage, const procparams::ProcParams& pp) + : fname(""), initialImage(iImage) + { + pparams = pp; + iImage->increaseRef(); + } + + ~ProcessingJobImpl () + { + if (initialImage) { + initialImage->decreaseRef(); + } + } }; } diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 4efb37a4a..cb2868dd6 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -7,7 +7,7 @@ * 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 @@ -19,418 +19,419 @@ #ifndef __PROCEVENT__ #define __PROCEVENT__ -namespace rtengine { +namespace rtengine +{ enum ProcEvent { - EvPhotoLoaded=0, - EvProfileLoaded=1, - EvProfileChanged=2, - EvHistoryBrowsed=3, - EvBrightness=4, - EvContrast=5, - EvBlack=6, - EvExpComp=7, - EvHLCompr=8, - EvSHCompr=9, - EvToneCurve1=10, - EvAutoExp=11, - EvClip=12, - EvLBrightness=13, - EvLContrast=14, - EvLBlack=15, - EvLHLCompr=16, - EvLSHCompr=17, - EvLLCurve=18, - EvShrEnabled=19, - EvShrRadius=20, - EvShrAmount=21, - EvShrThresh=22, - EvShrEdgeOnly=23, - EvShrEdgeRadius=24, - EvShrEdgeTolerance=25, - EvShrHaloControl=26, - EvShrHaloAmount=27, - EvShrMethod=28, - EvShrDRadius=29, - EvShrDAmount=30, - EvShrDDamping=31, - EvShrDIterations=32, - EvLCPUseDist=33, - EvLCPUseVign=34, - EvLCPUseCA=35, - EvFixedExp=36, - EvWBMethod=37, - EvWBTemp=38, - EvWBGreen=39, - EvToneCurveMode1=40, - EvToneCurve2=41, - EvToneCurveMode2=42, - EvLDNRadius=43, // obsolete - EvLDNEdgeTolerance=44, // obsolete - EvCDNEnabled=45, // obsolete - EvBlendCMSMatrix=46, - EvDCPToneCurve=47, - EvDCPIlluminant=48, - EvSHEnabled=49, - EvSHHighlights=50, - EvSHShadows=51, - EvSHHLTonalW=52, - EvSHSHTonalW=53, - EvSHLContrast=54, - EvSHRadius=55, - EvCTRotate=56, - EvCTHFlip=57, - EvCTVFlip=58, - EvROTDegree=59, - EvTransAutoFill=60, - EvDISTAmount=61, - EvBookmarkSelected=62, - EvCrop=63, - EvCACorr=64, - EvHREnabled=65, - EvHRAmount=66, //obsolete - EvHRMethod=67, - EvWProfile=68, - EvOProfile=69, - EvIProfile=70, - EvVignettingAmount=71, - EvChMixer=72, - EvResizeScale=73, - EvResizeMethod=74, - EvExif=75, - EvIPTC=76, - EvResizeSpec=77, - EvResizeWidth=78, - EvResizeHeight=79, - EvResizeEnabled=80, - EvProfileChangeNotification=81, - EvSHHighQuality=82, - EvPerspCorr=83, - EvLCPFile=84, - EvRGBrCurveLumamode=85, - EvIDNEnabled=86, - EvIDNThresh=87, - EvDPDNEnabled=88, - EvDPDNLuma=89, - EvDPDNChroma=90, - EvDPDNGamma=91, - EvDirPyrEqualizer=92, - EvDirPyrEqlEnabled=93, - EvLSaturation=94, - EvLaCurve=95, - EvLbCurve=96, - EvDemosaicMethod=97, - EvPreProcessHotPixel=98, - EvSaturation=99, - EvHSVEqualizerH=100, - EvHSVEqualizerS=101, - EvHSVEqualizerV=102, - EvHSVEqEnabled=103, - EvDefringeEnabled=104, - EvDefringeRadius=105, - EvDefringeThreshold=106, - EvHLComprThreshold=107, - EvResizeBoundingBox=108, - EvResizeAppliesTo=109, - EvLAvoidColorShift=110, - EvLSatLimiter=111, // obsolete - EvLRSTProtection=112, - EvDemosaicDCBIter=113, - EvDemosaicFalseColorIter=114, - EvDemosaicDCBEnhanced=115, - EvPreProcessCARed=116, - EvPreProcessCABlue=117, - EvPreProcessLineDenoise=118, - EvPreProcessGEquilThresh=119, - EvPreProcessAutoCA=120, - EvPreProcessAutoDF=121, - EvPreProcessDFFile=122, - EvPreProcessExpCorrLinear=123, - EvPreProcessExpCorrPH=124, - EvFlatFieldFile=125, - EvFlatFieldAutoSelect=126, - EvFlatFieldBlurRadius=127, - EvFlatFieldBlurType=128, - EvAutoDIST=129, - EvDPDNLumCurve=130, - EvDPDNChromCurve=131, - EvGAMMA=132, - EvGAMPOS=133, - EvGAMFREE=134, - EvSLPOS=135, - EvPreProcessExpBlackzero=136, - EvPreProcessExpBlackone=137, - EvPreProcessExpBlacktwo=138, - EvPreProcessExpBlackthree=139, - EvPreProcessExptwoGreen=140, - EvSharpenEdgePasses=141, - EvSharpenEdgeAmount=142, - EvSharpenMicroAmount=143, - EvSharpenMicroUniformity=144, - EvSharpenEdgeEnabled=145, - EvSharpenEdgeThreechannels=146, - EvSharpenMicroEnabled=147, - EvSharpenMicroMatrix=148, - EvDemosaicALLEnhanced=149, // Disabled but not removed for now, may be reintroduced some day - EvVibranceEnabled=150, - EvVibrancePastels=151, - EvVibranceSaturated=152, - EvVibranceProtectSkins=153, - EvVibranceAvoidColorShift=154, - EvVibrancePastSatTog=155, - EvVibrancePastSatThreshold=156, - EvEPDStrength=157, - EvEPDEdgeStopping=158, - EvEPDScale=159, - EvEPDReweightingIterates=160, - EvEPDEnabled=161, - EvRGBrCurve=162, - EvRGBgCurve=163, - EvRGBbCurve=164, - EvNeutralExp=165, - EvDemosaicMethodPreProc=166, - EvLCCCurve=167, - EvLCHCurve=168, - EvVibranceSkinTonesCurve=169, - EvLLCCurve=170, - EvLLCredsk=171, - EvDPDNLdetail=172, - EvCATEnabled=173, - EvCATDegree=174, - EvCATMethodsur=175, - EvCATAdapscen=176, - EvCATAdapLum=177, - EvCATMethodWB=178, - EvCATJLight=179, - EvCATChroma=180, - EvCATAutoDegree=181, - EvCATContrast=182, - EvCATsurr=183, - EvCATgamut=184, - EvCATMethodalg=185, - EvCATRstpro=186, - EvCATQbright=187, - EvCATQContrast=188, - EvCATSChroma=189, - EvCATMChroma=190, - EvCAThue=191, - EvCATCurve1=192, - EvCATCurve2=193, - EvCATCurveMode1=194, - EvCATCurveMode2=195, - EvCATCurve3=196, - EvCATCurveMode3=197, - EvCATdatacie=198, - EvCATtonecie=199, - EvDPDNredchro=200, - EvDPDNbluechro=201, - EvDPDNmet=202, -// EvDPDNperform=201, - EvDemosaicLMMSEIter=203, - EvCATbadpix=204, - EvCATAutoAdap=205, - EvPFCurve=206, - EvWBequal=207, - EvWBequalbo=208, - EvGradientDegree=209, - EvGradientEnabled=210, - EvPCVignetteStrength=211, - EvPCVignetteEnabled=212, - EvBWChmixEnabled=213, - EvBWred=214, - EvBWgreen=215, - EvBWblue=216, - EvBWredgam=217, - EvBWgreengam=218, - EvBWbluegam=219, - EvBWfilter=220, - EvBWsetting=221, - EvBWoran=222, - EvBWyell=223, - EvBWcyan=224, - EvBWmag=225, - EvBWpur=226, - EvBWLuminanceEqual=227, - EvBWChmixEnabledLm=228, - EvBWmethod=229, - EvBWBeforeCurve=230, - EvBWBeforeCurveMode=231, - EvBWAfterCurve=232, - EvBWAfterCurveMode=233, - EvAutoch=234, -// EvFixedch=235, -- can be reused -- - EvNeutralBW=236, - EvGradientFeather=237, - EvGradientStrength=238, - EvGradientCenter=239, - EvPCVignetteFeather=240, - EvPCVignetteRoundness=241, - EvVignettingRadius=242, - EvVignettingStrenght=243, - EvVignettingCenter=244, - EvLCLCurve=245, - EvLLHCurve=246, - EvLHHCurve=247, - EvDirPyrEqualizerThreshold=248, - EvDPDNenhance=249, - EvBWMethodalg=250, - EvDirPyrEqualizerSkin=251, - EvDirPyrEqlgamutlab=252, - EvDirPyrEqualizerHueskin=253, -// EvDirPyrEqualizeralg=254, - EvDPDNmedian=254, - EvDPDNmedmet=255, - EvColorToningEnabled=256, - EvColorToningColor =257, - EvColorToningOpacity=258, - EvColorToningCLCurve=259, - EvColorToningMethod=260, -// EvColorToningTwocolor=259, - EvColorToningLLCurve=261, - EvColorToningredlow=262, - EvColorToninggreenlow=263, - EvColorToningbluelow=264, - EvColorToningredmed=265, - EvColorToninggreenmed=266, - EvColorToningbluemed=267, - EvColorToningredhigh=268, - EvColorToninggreenhigh=269, - EvColorToningbluehigh=270, - EvColorToningbalance=271, - EvColorToningNeutral=272, - EvColorToningsatlow=273, - EvColorToningsathigh=274, - EvColorToningTwocolor=275, - EvColorToningNeutralcur=276, - EvColorToningLumamode=277, - EvColorToningShadows=278, - EvColorToningHighights=279, - EvColorToningSatProtection=280, - EvColorToningSatThreshold=281, - EvColorToningStrength=282, - EvColorToningautosat=283, - EvDPDNmetmed=284, - EvDPDNrgbmet=285, - EvDPDNpasses=286, - EvFlatFieldClipControl=287, - EvFlatFieldAutoClipControl=288, - EvPreProcessExpBlackRed=289, - EvPreProcessExpBlackGreen=290, - EvPreProcessExpBlackBlue=291, - EvFilmSimulationEnabled=292, - EvFilmSimulationStrength=293, - EvFilmSimulationFilename=294, - EvDPDNLCurve=295, - EvDPDNsmet=296, - EvPreProcessDeadPixel=297, - EvDPDNCCCurve=298, - EvDPDNautochroma=299, - EvDPDNLmet=300, - EvDPDNCmet=301, - EvDPDNC2met=302, - EvWavelet=303, - EvWavEnabled=304, - EvWavLmet=305, - EvWavCLmet=306, - EvWavDirmeto=307, - EvWavtiles=308, - EvWavsky=309, - EvWavthres=310, - EvWavthr=311, - EvWavchroma=312, - EvWavmedian=313, - EvWavunif=314, - EvWavSkin=315, - EvWavHueskin=316, - EvWavThreshold=317, - EvWavlhl=318, - EvWavlbl=319, - EvWavThreshold2=320, - EvWavavoid=321, - EvWavCCCurve=322, - EvWavpast=323, - EvWavsat=324, - EvWavCHmet=325, - EvWavHSmet=326, - EvWavchro=327, - EvWavColor=328, - EvWavOpac=329, - EvWavsup=330, - EvWavTilesmet=331, - EvWavrescon=332, - EvWavreschro=333, - EvWavresconH=334, - EvWavthrH=335, - EvWavHueskin2=336, - EvWavedgrad=337, - EvWavedgval=338, - EvWavStrength=339, - EvWavdaubcoeffmet=340, - EvWavedgreinf=341, - EvWaveletch=342, - EvWavCHSLmet=343, - EvWavedgcont=344, - EvWavEDmet=345, - EvWavlev0nois=346, - EvWavlev1nois=347, - EvWavlev2nois=348, - EvWavmedianlev=349, - EvWavHHCurve=350, - EvWavBackmet=351, - EvWavedgedetect=352, - EvWavlipst=353, - EvWavedgedetectthr=354, - EvWavedgedetectthr2=355, - EvWavlinkedg=356, - EvWavCHCurve=357, - EvPreProcessHotDeadThresh=358, - EvEPDgamma=359, - EvWavtmr=360, - EvWavTMmet=361, - EvWavtmrs=362, - EvWavbalance=363, - EvWaviter=364, - EvWavgamma=365, - EvWavCLCurve=366, - EvWavopacity=367, - EvWavBAmet=368, - EvWavopacityWL=369, - EvPrShrEnabled=370, - EvPrShrRadius=371, - EvPrShrAmount=372, - EvPrShrThresh=373, - EvPrShrEdgeOnly=374, - EvPrShrEdgeRadius=375, - EvPrShrEdgeTolerance=376, - EvPrShrHaloControl=377, - EvPrShrHaloAmount=378, - EvPrShrMethod=379, - EvPrShrDRadius=380, - EvPrShrDAmount=381, - EvPrShrDDamping=382, - EvPrShrDIterations=383, - EvWavcbenab=384, - EvWavgreenhigh=385, - EvWavbluehigh=386, - EvWavgreenmed=387, - EvWavbluemed=388, - EvWavgreenlow=389, - EvWavbluelow=390, - EvWavNeutral=391, - EvDCPApplyLookTable=392, - EvDCPApplyBaselineExposureOffset=393, - EvDCPApplyHueSatMap=394, - EvWavenacont=395, - EvWavenachrom=396, - EvWavenaedge=397, - EvWavenares=398, - EvWavenafin=399, - EvWavenatoning=400, - EvWavenanoise=401, - EvWavedgesensi=402, - EvWavedgeampli=403, - EvWavlev3nois=404, - EvWavNPmet=405, + EvPhotoLoaded = 0, + EvProfileLoaded = 1, + EvProfileChanged = 2, + EvHistoryBrowsed = 3, + EvBrightness = 4, + EvContrast = 5, + EvBlack = 6, + EvExpComp = 7, + EvHLCompr = 8, + EvSHCompr = 9, + EvToneCurve1 = 10, + EvAutoExp = 11, + EvClip = 12, + EvLBrightness = 13, + EvLContrast = 14, + EvLBlack = 15, + EvLHLCompr = 16, + EvLSHCompr = 17, + EvLLCurve = 18, + EvShrEnabled = 19, + EvShrRadius = 20, + EvShrAmount = 21, + EvShrThresh = 22, + EvShrEdgeOnly = 23, + EvShrEdgeRadius = 24, + EvShrEdgeTolerance = 25, + EvShrHaloControl = 26, + EvShrHaloAmount = 27, + EvShrMethod = 28, + EvShrDRadius = 29, + EvShrDAmount = 30, + EvShrDDamping = 31, + EvShrDIterations = 32, + EvLCPUseDist = 33, + EvLCPUseVign = 34, + EvLCPUseCA = 35, + EvFixedExp = 36, + EvWBMethod = 37, + EvWBTemp = 38, + EvWBGreen = 39, + EvToneCurveMode1 = 40, + EvToneCurve2 = 41, + EvToneCurveMode2 = 42, + EvLDNRadius = 43, // obsolete + EvLDNEdgeTolerance = 44, // obsolete + EvCDNEnabled = 45, // obsolete + EvBlendCMSMatrix = 46, + EvDCPToneCurve = 47, + EvDCPIlluminant = 48, + EvSHEnabled = 49, + EvSHHighlights = 50, + EvSHShadows = 51, + EvSHHLTonalW = 52, + EvSHSHTonalW = 53, + EvSHLContrast = 54, + EvSHRadius = 55, + EvCTRotate = 56, + EvCTHFlip = 57, + EvCTVFlip = 58, + EvROTDegree = 59, + EvTransAutoFill = 60, + EvDISTAmount = 61, + EvBookmarkSelected = 62, + EvCrop = 63, + EvCACorr = 64, + EvHREnabled = 65, + EvHRAmount = 66, //obsolete + EvHRMethod = 67, + EvWProfile = 68, + EvOProfile = 69, + EvIProfile = 70, + EvVignettingAmount = 71, + EvChMixer = 72, + EvResizeScale = 73, + EvResizeMethod = 74, + EvExif = 75, + EvIPTC = 76, + EvResizeSpec = 77, + EvResizeWidth = 78, + EvResizeHeight = 79, + EvResizeEnabled = 80, + EvProfileChangeNotification = 81, + EvSHHighQuality = 82, + EvPerspCorr = 83, + EvLCPFile = 84, + EvRGBrCurveLumamode = 85, + EvIDNEnabled = 86, + EvIDNThresh = 87, + EvDPDNEnabled = 88, + EvDPDNLuma = 89, + EvDPDNChroma = 90, + EvDPDNGamma = 91, + EvDirPyrEqualizer = 92, + EvDirPyrEqlEnabled = 93, + EvLSaturation = 94, + EvLaCurve = 95, + EvLbCurve = 96, + EvDemosaicMethod = 97, + EvPreProcessHotPixel = 98, + EvSaturation = 99, + EvHSVEqualizerH = 100, + EvHSVEqualizerS = 101, + EvHSVEqualizerV = 102, + EvHSVEqEnabled = 103, + EvDefringeEnabled = 104, + EvDefringeRadius = 105, + EvDefringeThreshold = 106, + EvHLComprThreshold = 107, + EvResizeBoundingBox = 108, + EvResizeAppliesTo = 109, + EvLAvoidColorShift = 110, + EvLSatLimiter = 111, // obsolete + EvLRSTProtection = 112, + EvDemosaicDCBIter = 113, + EvDemosaicFalseColorIter = 114, + EvDemosaicDCBEnhanced = 115, + EvPreProcessCARed = 116, + EvPreProcessCABlue = 117, + EvPreProcessLineDenoise = 118, + EvPreProcessGEquilThresh = 119, + EvPreProcessAutoCA = 120, + EvPreProcessAutoDF = 121, + EvPreProcessDFFile = 122, + EvPreProcessExpCorrLinear = 123, + EvPreProcessExpCorrPH = 124, + EvFlatFieldFile = 125, + EvFlatFieldAutoSelect = 126, + EvFlatFieldBlurRadius = 127, + EvFlatFieldBlurType = 128, + EvAutoDIST = 129, + EvDPDNLumCurve = 130, + EvDPDNChromCurve = 131, + EvGAMMA = 132, + EvGAMPOS = 133, + EvGAMFREE = 134, + EvSLPOS = 135, + EvPreProcessExpBlackzero = 136, + EvPreProcessExpBlackone = 137, + EvPreProcessExpBlacktwo = 138, + EvPreProcessExpBlackthree = 139, + EvPreProcessExptwoGreen = 140, + EvSharpenEdgePasses = 141, + EvSharpenEdgeAmount = 142, + EvSharpenMicroAmount = 143, + EvSharpenMicroUniformity = 144, + EvSharpenEdgeEnabled = 145, + EvSharpenEdgeThreechannels = 146, + EvSharpenMicroEnabled = 147, + EvSharpenMicroMatrix = 148, + EvDemosaicALLEnhanced = 149, // Disabled but not removed for now, may be reintroduced some day + EvVibranceEnabled = 150, + EvVibrancePastels = 151, + EvVibranceSaturated = 152, + EvVibranceProtectSkins = 153, + EvVibranceAvoidColorShift = 154, + EvVibrancePastSatTog = 155, + EvVibrancePastSatThreshold = 156, + EvEPDStrength = 157, + EvEPDEdgeStopping = 158, + EvEPDScale = 159, + EvEPDReweightingIterates = 160, + EvEPDEnabled = 161, + EvRGBrCurve = 162, + EvRGBgCurve = 163, + EvRGBbCurve = 164, + EvNeutralExp = 165, + EvDemosaicMethodPreProc = 166, + EvLCCCurve = 167, + EvLCHCurve = 168, + EvVibranceSkinTonesCurve = 169, + EvLLCCurve = 170, + EvLLCredsk = 171, + EvDPDNLdetail = 172, + EvCATEnabled = 173, + EvCATDegree = 174, + EvCATMethodsur = 175, + EvCATAdapscen = 176, + EvCATAdapLum = 177, + EvCATMethodWB = 178, + EvCATJLight = 179, + EvCATChroma = 180, + EvCATAutoDegree = 181, + EvCATContrast = 182, + EvCATsurr = 183, + EvCATgamut = 184, + EvCATMethodalg = 185, + EvCATRstpro = 186, + EvCATQbright = 187, + EvCATQContrast = 188, + EvCATSChroma = 189, + EvCATMChroma = 190, + EvCAThue = 191, + EvCATCurve1 = 192, + EvCATCurve2 = 193, + EvCATCurveMode1 = 194, + EvCATCurveMode2 = 195, + EvCATCurve3 = 196, + EvCATCurveMode3 = 197, + EvCATdatacie = 198, + EvCATtonecie = 199, + EvDPDNredchro = 200, + EvDPDNbluechro = 201, + EvDPDNmet = 202, +// EvDPDNperform=201, + EvDemosaicLMMSEIter = 203, + EvCATbadpix = 204, + EvCATAutoAdap = 205, + EvPFCurve = 206, + EvWBequal = 207, + EvWBequalbo = 208, + EvGradientDegree = 209, + EvGradientEnabled = 210, + EvPCVignetteStrength = 211, + EvPCVignetteEnabled = 212, + EvBWChmixEnabled = 213, + EvBWred = 214, + EvBWgreen = 215, + EvBWblue = 216, + EvBWredgam = 217, + EvBWgreengam = 218, + EvBWbluegam = 219, + EvBWfilter = 220, + EvBWsetting = 221, + EvBWoran = 222, + EvBWyell = 223, + EvBWcyan = 224, + EvBWmag = 225, + EvBWpur = 226, + EvBWLuminanceEqual = 227, + EvBWChmixEnabledLm = 228, + EvBWmethod = 229, + EvBWBeforeCurve = 230, + EvBWBeforeCurveMode = 231, + EvBWAfterCurve = 232, + EvBWAfterCurveMode = 233, + EvAutoch = 234, +// EvFixedch=235, -- can be reused -- + EvNeutralBW = 236, + EvGradientFeather = 237, + EvGradientStrength = 238, + EvGradientCenter = 239, + EvPCVignetteFeather = 240, + EvPCVignetteRoundness = 241, + EvVignettingRadius = 242, + EvVignettingStrenght = 243, + EvVignettingCenter = 244, + EvLCLCurve = 245, + EvLLHCurve = 246, + EvLHHCurve = 247, + EvDirPyrEqualizerThreshold = 248, + EvDPDNenhance = 249, + EvBWMethodalg = 250, + EvDirPyrEqualizerSkin = 251, + EvDirPyrEqlgamutlab = 252, + EvDirPyrEqualizerHueskin = 253, +// EvDirPyrEqualizeralg=254, + EvDPDNmedian = 254, + EvDPDNmedmet = 255, + EvColorToningEnabled = 256, + EvColorToningColor = 257, + EvColorToningOpacity = 258, + EvColorToningCLCurve = 259, + EvColorToningMethod = 260, +// EvColorToningTwocolor=259, + EvColorToningLLCurve = 261, + EvColorToningredlow = 262, + EvColorToninggreenlow = 263, + EvColorToningbluelow = 264, + EvColorToningredmed = 265, + EvColorToninggreenmed = 266, + EvColorToningbluemed = 267, + EvColorToningredhigh = 268, + EvColorToninggreenhigh = 269, + EvColorToningbluehigh = 270, + EvColorToningbalance = 271, + EvColorToningNeutral = 272, + EvColorToningsatlow = 273, + EvColorToningsathigh = 274, + EvColorToningTwocolor = 275, + EvColorToningNeutralcur = 276, + EvColorToningLumamode = 277, + EvColorToningShadows = 278, + EvColorToningHighights = 279, + EvColorToningSatProtection = 280, + EvColorToningSatThreshold = 281, + EvColorToningStrength = 282, + EvColorToningautosat = 283, + EvDPDNmetmed = 284, + EvDPDNrgbmet = 285, + EvDPDNpasses = 286, + EvFlatFieldClipControl = 287, + EvFlatFieldAutoClipControl = 288, + EvPreProcessExpBlackRed = 289, + EvPreProcessExpBlackGreen = 290, + EvPreProcessExpBlackBlue = 291, + EvFilmSimulationEnabled = 292, + EvFilmSimulationStrength = 293, + EvFilmSimulationFilename = 294, + EvDPDNLCurve = 295, + EvDPDNsmet = 296, + EvPreProcessDeadPixel = 297, + EvDPDNCCCurve = 298, + EvDPDNautochroma = 299, + EvDPDNLmet = 300, + EvDPDNCmet = 301, + EvDPDNC2met = 302, + EvWavelet = 303, + EvWavEnabled = 304, + EvWavLmet = 305, + EvWavCLmet = 306, + EvWavDirmeto = 307, + EvWavtiles = 308, + EvWavsky = 309, + EvWavthres = 310, + EvWavthr = 311, + EvWavchroma = 312, + EvWavmedian = 313, + EvWavunif = 314, + EvWavSkin = 315, + EvWavHueskin = 316, + EvWavThreshold = 317, + EvWavlhl = 318, + EvWavlbl = 319, + EvWavThreshold2 = 320, + EvWavavoid = 321, + EvWavCCCurve = 322, + EvWavpast = 323, + EvWavsat = 324, + EvWavCHmet = 325, + EvWavHSmet = 326, + EvWavchro = 327, + EvWavColor = 328, + EvWavOpac = 329, + EvWavsup = 330, + EvWavTilesmet = 331, + EvWavrescon = 332, + EvWavreschro = 333, + EvWavresconH = 334, + EvWavthrH = 335, + EvWavHueskin2 = 336, + EvWavedgrad = 337, + EvWavedgval = 338, + EvWavStrength = 339, + EvWavdaubcoeffmet = 340, + EvWavedgreinf = 341, + EvWaveletch = 342, + EvWavCHSLmet = 343, + EvWavedgcont = 344, + EvWavEDmet = 345, + EvWavlev0nois = 346, + EvWavlev1nois = 347, + EvWavlev2nois = 348, + EvWavmedianlev = 349, + EvWavHHCurve = 350, + EvWavBackmet = 351, + EvWavedgedetect = 352, + EvWavlipst = 353, + EvWavedgedetectthr = 354, + EvWavedgedetectthr2 = 355, + EvWavlinkedg = 356, + EvWavCHCurve = 357, + EvPreProcessHotDeadThresh = 358, + EvEPDgamma = 359, + EvWavtmr = 360, + EvWavTMmet = 361, + EvWavtmrs = 362, + EvWavbalance = 363, + EvWaviter = 364, + EvWavgamma = 365, + EvWavCLCurve = 366, + EvWavopacity = 367, + EvWavBAmet = 368, + EvWavopacityWL = 369, + EvPrShrEnabled = 370, + EvPrShrRadius = 371, + EvPrShrAmount = 372, + EvPrShrThresh = 373, + EvPrShrEdgeOnly = 374, + EvPrShrEdgeRadius = 375, + EvPrShrEdgeTolerance = 376, + EvPrShrHaloControl = 377, + EvPrShrHaloAmount = 378, + EvPrShrMethod = 379, + EvPrShrDRadius = 380, + EvPrShrDAmount = 381, + EvPrShrDDamping = 382, + EvPrShrDIterations = 383, + EvWavcbenab = 384, + EvWavgreenhigh = 385, + EvWavbluehigh = 386, + EvWavgreenmed = 387, + EvWavbluemed = 388, + EvWavgreenlow = 389, + EvWavbluelow = 390, + EvWavNeutral = 391, + EvDCPApplyLookTable = 392, + EvDCPApplyBaselineExposureOffset = 393, + EvDCPApplyHueSatMap = 394, + EvWavenacont = 395, + EvWavenachrom = 396, + EvWavenaedge = 397, + EvWavenares = 398, + EvWavenafin = 399, + EvWavenatoning = 400, + EvWavenanoise = 401, + EvWavedgesensi = 402, + EvWavedgeampli = 403, + EvWavlev3nois = 404, + EvWavNPmet = 405, NUMOFEVENTS }; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 66b285d64..66cb76b3b 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -7,7 +7,7 @@ * 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 @@ -33,133 +33,158 @@ using namespace std; extern Options options; -namespace rtengine { -namespace procparams { - const int tr=(int) options.rtSettings.top_right; - const int br=(int) options.rtSettings.bot_right; - const int tl=(int) options.rtSettings.top_left; - const int bl=(int) options.rtSettings.bot_left; - - const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods]={"amaze","igv","lmmse","eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none" }; - const char *RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::numMethods]={"3-pass (best)", "1-pass (medium)", "fast", "mono", "none" }; +namespace rtengine +{ +namespace procparams +{ +const int tr = (int) options.rtSettings.top_right; +const int br = (int) options.rtSettings.bot_right; +const int tl = (int) options.rtSettings.top_left; +const int bl = (int) options.rtSettings.bot_left; -const char *RAWParams::ff_BlurTypestring[RAWParams::numFlatFileBlurTypes]={/*"Parametric",*/ "Area Flatfield", "Vertical Flatfield", "Horizontal Flatfield", "V+H Flatfield"}; +const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods] = {"amaze", "igv", "lmmse", "eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none" }; +const char *RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::numMethods] = {"3-pass (best)", "1-pass (medium)", "fast", "mono", "none" }; + +const char *RAWParams::ff_BlurTypestring[RAWParams::numFlatFileBlurTypes] = {/*"Parametric",*/ "Area Flatfield", "Vertical Flatfield", "Horizontal Flatfield", "V+H Flatfield"}; std::vector WBParams::wbEntries; -bool ToneCurveParams::HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw) { +bool ToneCurveParams::HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw) +{ if (options.rtSettings.verbose) printf("histRedRaw[ 0]=%07d, histGreenRaw[ 0]=%07d, histBlueRaw[ 0]=%07d\nhistRedRaw[255]=%07d, histGreenRaw[255]=%07d, histBlueRaw[255]=%07d\n", - histRedRaw[0], histGreenRaw[0], histBlueRaw[0], histRedRaw[255], histGreenRaw[255], histBlueRaw[255]); + histRedRaw[0], histGreenRaw[0], histBlueRaw[0], histRedRaw[255], histGreenRaw[255], histBlueRaw[255]); - return histRedRaw[255]>50 || histGreenRaw[255]>50 || histBlueRaw[255]>50 || histRedRaw[0]>50 || histGreenRaw[0]>50 || histBlueRaw[0]>50; + return histRedRaw[255] > 50 || histGreenRaw[255] > 50 || histBlueRaw[255] > 50 || histRedRaw[0] > 50 || histGreenRaw[0] > 50 || histBlueRaw[0] > 50; } -void WBParams::init() { +void WBParams::init() +{ // Creation of the different methods and its associated temperature value - wbEntries.push_back(new WBEntry("Camera" ,WBT_CAMERA, M("TP_WBALANCE_CAMERA"), 0, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Auto" ,WBT_AUTO, M("TP_WBALANCE_AUTO"), 0, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Daylight" ,WBT_DAYLIGHT, M("TP_WBALANCE_DAYLIGHT"), 5300, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Cloudy" ,WBT_CLOUDY, M("TP_WBALANCE_CLOUDY"), 6200, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Shade" ,WBT_SHADE, M("TP_WBALANCE_SHADE"), 7600, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Water 1" ,WBT_WATER, M("TP_WBALANCE_WATER1"), 35000, 0.3f, 1.1f)); - wbEntries.push_back(new WBEntry("Water 2" ,WBT_WATER, M("TP_WBALANCE_WATER2"), 48000, 0.63f, 1.38f)); - wbEntries.push_back(new WBEntry("Tungsten" ,WBT_TUNGSTEN, M("TP_WBALANCE_TUNGSTEN"), 2856, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F1" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO1"), 6430, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F2" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO2"), 4230, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F3" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO3"), 3450, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F4" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO4"), 2940, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F5" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO5"), 6350, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F6" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO6"), 4150, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F7" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO7"), 6500, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F8" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO8"), 5020, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F9" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO9"), 4330, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F10" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO10"), 5300, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F11" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO11"), 4000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Fluo F12" ,WBT_FLUORESCENT, M("TP_WBALANCE_FLUO12"), 3000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("HMI Lamp" ,WBT_LAMP, M("TP_WBALANCE_HMI"), 4800, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("GTI Lamp" ,WBT_LAMP, M("TP_WBALANCE_GTI"), 5000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("JudgeIII Lamp" ,WBT_LAMP, M("TP_WBALANCE_JUDGEIII"), 5100, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Solux Lamp 3500K" ,WBT_LAMP, M("TP_WBALANCE_SOLUX35"), 3480, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Solux Lamp 4100K" ,WBT_LAMP, M("TP_WBALANCE_SOLUX41"), 3930, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Solux Lamp 4700K" ,WBT_LAMP, M("TP_WBALANCE_SOLUX47"), 4700, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("NG Solux Lamp 4700K" ,WBT_LAMP, M("TP_WBALANCE_SOLUX47_NG"), 4480, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("LED LSI Lumelex 2040",WBT_LED, M("TP_WBALANCE_LED_LSI"), 2970, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("LED CRS SP12 WWMR16" ,WBT_LED, M("TP_WBALANCE_LED_CRS"), 3050, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Flash 5500K" ,WBT_FLASH, M("TP_WBALANCE_FLASH55"), 5500, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Flash 6000K" ,WBT_FLASH, M("TP_WBALANCE_FLASH60"), 6000, 1.f, 1.f)); - wbEntries.push_back(new WBEntry("Flash 6500K" ,WBT_FLASH, M("TP_WBALANCE_FLASH65"), 6500, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Camera" , WBT_CAMERA, M("TP_WBALANCE_CAMERA"), 0, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Auto" , WBT_AUTO, M("TP_WBALANCE_AUTO"), 0, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Daylight" , WBT_DAYLIGHT, M("TP_WBALANCE_DAYLIGHT"), 5300, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Cloudy" , WBT_CLOUDY, M("TP_WBALANCE_CLOUDY"), 6200, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Shade" , WBT_SHADE, M("TP_WBALANCE_SHADE"), 7600, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Water 1" , WBT_WATER, M("TP_WBALANCE_WATER1"), 35000, 0.3f, 1.1f)); + wbEntries.push_back(new WBEntry("Water 2" , WBT_WATER, M("TP_WBALANCE_WATER2"), 48000, 0.63f, 1.38f)); + wbEntries.push_back(new WBEntry("Tungsten" , WBT_TUNGSTEN, M("TP_WBALANCE_TUNGSTEN"), 2856, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F1" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO1"), 6430, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F2" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO2"), 4230, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F3" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO3"), 3450, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F4" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO4"), 2940, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F5" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO5"), 6350, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F6" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO6"), 4150, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F7" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO7"), 6500, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F8" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO8"), 5020, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F9" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO9"), 4330, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F10" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO10"), 5300, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F11" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO11"), 4000, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Fluo F12" , WBT_FLUORESCENT, M("TP_WBALANCE_FLUO12"), 3000, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("HMI Lamp" , WBT_LAMP, M("TP_WBALANCE_HMI"), 4800, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("GTI Lamp" , WBT_LAMP, M("TP_WBALANCE_GTI"), 5000, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("JudgeIII Lamp" , WBT_LAMP, M("TP_WBALANCE_JUDGEIII"), 5100, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Solux Lamp 3500K" , WBT_LAMP, M("TP_WBALANCE_SOLUX35"), 3480, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Solux Lamp 4100K" , WBT_LAMP, M("TP_WBALANCE_SOLUX41"), 3930, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47"), 4700, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("NG Solux Lamp 4700K" , WBT_LAMP, M("TP_WBALANCE_SOLUX47_NG"), 4480, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("LED LSI Lumelex 2040", WBT_LED, M("TP_WBALANCE_LED_LSI"), 2970, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("LED CRS SP12 WWMR16" , WBT_LED, M("TP_WBALANCE_LED_CRS"), 3050, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Flash 5500K" , WBT_FLASH, M("TP_WBALANCE_FLASH55"), 5500, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Flash 6000K" , WBT_FLASH, M("TP_WBALANCE_FLASH60"), 6000, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Flash 6500K" , WBT_FLASH, M("TP_WBALANCE_FLASH65"), 6500, 1.f, 1.f)); // Should remain the last one - wbEntries.push_back(new WBEntry("Custom" ,WBT_CUSTOM, M("TP_WBALANCE_CUSTOM"), 0, 1.f, 1.f)); + wbEntries.push_back(new WBEntry("Custom" , WBT_CUSTOM, M("TP_WBALANCE_CUSTOM"), 0, 1.f, 1.f)); } -void WBParams::cleanup() { - for (unsigned int i=0; i &curve) { - double v[8]= { 0.050, 0.62, 0.25, 0.25, - 0.585, 0.11, 0.25, 0.25 }; +void ColorToningParams::getDefaultColorCurve(std::vector &curve) +{ + double v[8] = { 0.050, 0.62, 0.25, 0.25, + 0.585, 0.11, 0.25, 0.25 + }; curve.resize(9); curve.at(0) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - double v[16]={ 0.00, 0.3, 0.35, 0.00, - 0.25, 0.8, 0.35, 0.35, - 0.70, 0.8, 0.35, 0.35, - 1.00, 0.3, 0.00, 0.00 }; +void ColorToningParams::getDefaultOpacityCurve(std::vector &curve) +{ + double v[16] = { 0.00, 0.3, 0.35, 0.00, + 0.25, 0.8, 0.35, 0.35, + 0.70, 0.8, 0.35, 0.35, + 1.00, 0.3, 0.00, 0.00 + }; curve.resize(17); curve.at(0 ) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - double v[6]= { 0.00, 0.00, - 0.35, 0.65, - 1.00, 1.00 }; +void ColorToningParams::getDefaultCLCurve(std::vector &curve) +{ + double v[6] = { 0.00, 0.00, + 0.35, 0.65, + 1.00, 1.00 + }; curve.resize(7); curve.at(0) = double(DCT_NURBS); - for (size_t i=1; i &curve) { - double v[6]= { 0.00, 0.00, - 0.35, 0.65, - 1.00, 1.00 }; +void ColorToningParams::getDefaultCL2Curve(std::vector &curve) +{ + double v[6] = { 0.00, 0.00, + 0.35, 0.65, + 1.00, 1.00 + }; curve.resize(7); curve.at(0) = double(DCT_NURBS); - for (size_t i=1; i &colorCurve, std::vector &opacityCurve) const { +void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const +{ // check if non null first if (!redlow && !greenlow && !bluelow && !redmed && !greenmed && !bluemed && !redhigh && !greenhigh && !bluehigh) { colorCurve.resize(1); @@ -207,80 +233,128 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto float minTmp, maxTmp; // Fill the shadow mixer values of the Color TOning tool - low[0] = float(redlow )/100.f; // [-1. ; +1.] - low[1] = float(greenlow)/100.f; // [-1. ; +1.] - low[2] = float(bluelow )/100.f; // [-1. ; +1.] + low[0] = float(redlow ) / 100.f; // [-1. ; +1.] + low[1] = float(greenlow) / 100.f; // [-1. ; +1.] + low[2] = float(bluelow ) / 100.f; // [-1. ; +1.] minTmp = min(low[0], low[1], low[2]); maxTmp = max(low[0], low[1], low[2]); - if (maxTmp-minTmp > 0.005f) { + + if (maxTmp - minTmp > 0.005f) { float v[3]; - lowSat = (maxTmp-minTmp)/2.f; - if (low[0] == minTmp) v[0] = 0.f; - else if (low[1] == minTmp) v[1] = 0.f; - else if (low[2] == minTmp) v[2] = 0.f; - if (low[0] == maxTmp) v[0] = 1.f; - else if (low[1] == maxTmp) v[1] = 1.f; - else if (low[2] == maxTmp) v[2] = 1.f; - if (low[0] != minTmp && low[0] != maxTmp) v[0] = (low[0]-minTmp)/(maxTmp-minTmp); - else if (low[1] != minTmp && low[1] != maxTmp) v[1] = (low[1]-minTmp)/(maxTmp-minTmp); - else if (low[2] != minTmp && low[2] != maxTmp) v[2] = (low[2]-minTmp)/(maxTmp-minTmp); + lowSat = (maxTmp - minTmp) / 2.f; + + if (low[0] == minTmp) { + v[0] = 0.f; + } else if (low[1] == minTmp) { + v[1] = 0.f; + } else if (low[2] == minTmp) { + v[2] = 0.f; + } + + if (low[0] == maxTmp) { + v[0] = 1.f; + } else if (low[1] == maxTmp) { + v[1] = 1.f; + } else if (low[2] == maxTmp) { + v[2] = 1.f; + } + + if (low[0] != minTmp && low[0] != maxTmp) { + v[0] = (low[0] - minTmp) / (maxTmp - minTmp); + } else if (low[1] != minTmp && low[1] != maxTmp) { + v[1] = (low[1] - minTmp) / (maxTmp - minTmp); + } else if (low[2] != minTmp && low[2] != maxTmp) { + v[2] = (low[2] - minTmp) / (maxTmp - minTmp); + } + low[0] = v[0]; low[1] = v[1]; low[2] = v[2]; - } - else { + } else { low[0] = low[1] = low[2] = 1.f; } // Fill the mid-tones mixer values of the Color TOning tool - med[0] = float(redmed )/100.f; // [-1. ; +1.] - med[1] = float(greenmed)/100.f; // [-1. ; +1.] - med[2] = float(bluemed )/100.f; // [-1. ; +1.] + med[0] = float(redmed ) / 100.f; // [-1. ; +1.] + med[1] = float(greenmed) / 100.f; // [-1. ; +1.] + med[2] = float(bluemed ) / 100.f; // [-1. ; +1.] minTmp = min(med[0], med[1], med[2]); maxTmp = max(med[0], med[1], med[2]); - if (maxTmp-minTmp > 0.005f) { + + if (maxTmp - minTmp > 0.005f) { float v[3]; - medSat = (maxTmp-minTmp)/2.f; - if (med[0] == minTmp) v[0] = 0.f; - else if (med[1] == minTmp) v[1] = 0.f; - else if (med[2] == minTmp) v[2] = 0.f; - if (med[0] == maxTmp) v[0] = 1.f; - else if (med[1] == maxTmp) v[1] = 1.f; - else if (med[2] == maxTmp) v[2] = 1.f; - if (med[0] != minTmp && med[0] != maxTmp) v[0] = (med[0]-minTmp)/(maxTmp-minTmp); - else if (med[1] != minTmp && med[1] != maxTmp) v[1] = (med[1]-minTmp)/(maxTmp-minTmp); - else if (med[2] != minTmp && med[2] != maxTmp) v[2] = (med[2]-minTmp)/(maxTmp-minTmp); + medSat = (maxTmp - minTmp) / 2.f; + + if (med[0] == minTmp) { + v[0] = 0.f; + } else if (med[1] == minTmp) { + v[1] = 0.f; + } else if (med[2] == minTmp) { + v[2] = 0.f; + } + + if (med[0] == maxTmp) { + v[0] = 1.f; + } else if (med[1] == maxTmp) { + v[1] = 1.f; + } else if (med[2] == maxTmp) { + v[2] = 1.f; + } + + if (med[0] != minTmp && med[0] != maxTmp) { + v[0] = (med[0] - minTmp) / (maxTmp - minTmp); + } else if (med[1] != minTmp && med[1] != maxTmp) { + v[1] = (med[1] - minTmp) / (maxTmp - minTmp); + } else if (med[2] != minTmp && med[2] != maxTmp) { + v[2] = (med[2] - minTmp) / (maxTmp - minTmp); + } + med[0] = v[0]; med[1] = v[1]; med[2] = v[2]; - } - else { + } else { med[0] = med[1] = med[2] = 1.f; } // Fill the highlight mixer values of the Color TOning tool - high[0] = float(redhigh )/100.f; // [-1. ; +1.] - high[1] = float(greenhigh)/100.f; // [-1. ; +1.] - high[2] = float(bluehigh )/100.f; // [-1. ; +1.] + high[0] = float(redhigh ) / 100.f; // [-1. ; +1.] + high[1] = float(greenhigh) / 100.f; // [-1. ; +1.] + high[2] = float(bluehigh ) / 100.f; // [-1. ; +1.] minTmp = min(high[0], high[1], high[2]); maxTmp = max(high[0], high[1], high[2]); - if (maxTmp-minTmp > 0.005f) { + + if (maxTmp - minTmp > 0.005f) { float v[3]; - highSat = (maxTmp-minTmp)/2.f; - if (high[0] == minTmp) v[0] = 0.f; - else if (high[1] == minTmp) v[1] = 0.f; - else if (high[2] == minTmp) v[2] = 0.f; - if (high[0] == maxTmp) v[0] = 1.f; - else if (high[1] == maxTmp) v[1] = 1.f; - else if (high[2] == maxTmp) v[2] = 1.f; - if (high[0] != minTmp && high[0] != maxTmp) v[0] = (high[0]-minTmp)/(maxTmp-minTmp); - else if (high[1] != minTmp && high[1] != maxTmp) v[1] = (high[1]-minTmp)/(maxTmp-minTmp); - else if (high[2] != minTmp && high[2] != maxTmp) v[2] = (high[2]-minTmp)/(maxTmp-minTmp); + highSat = (maxTmp - minTmp) / 2.f; + + if (high[0] == minTmp) { + v[0] = 0.f; + } else if (high[1] == minTmp) { + v[1] = 0.f; + } else if (high[2] == minTmp) { + v[2] = 0.f; + } + + if (high[0] == maxTmp) { + v[0] = 1.f; + } else if (high[1] == maxTmp) { + v[1] = 1.f; + } else if (high[2] == maxTmp) { + v[2] = 1.f; + } + + if (high[0] != minTmp && high[0] != maxTmp) { + v[0] = (high[0] - minTmp) / (maxTmp - minTmp); + } else if (high[1] != minTmp && high[1] != maxTmp) { + v[1] = (high[1] - minTmp) / (maxTmp - minTmp); + } else if (high[2] != minTmp && high[2] != maxTmp) { + v[2] = (high[2] - minTmp) / (maxTmp - minTmp); + } + high[0] = v[0]; high[1] = v[1]; high[2] = v[2]; - } - else { + } else { high[0] = high[1] = high[2] = 1.f; } @@ -293,7 +367,7 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto - colorCurve.resize( medSat!=0.f ? 13 : 9 ); + colorCurve.resize( medSat != 0.f ? 13 : 9 ); colorCurve.at(0) = FCT_MinMaxCPoints; opacityCurve.resize(13); opacityCurve.at(0) = FCT_MinMaxCPoints; @@ -302,13 +376,15 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto int idx = 1; if (lowSat == 0.f) { - if (medSat != 0.f) + if (medSat != 0.f) { Color::rgb2hsl(med[0], med[1], med[2], h, s, l); - else// highSat can't be null if the 2 other ones are! + } else { // highSat can't be null if the 2 other ones are! Color::rgb2hsl(high[0], high[1], high[2], h, s, l); - } - else + } + } else { Color::rgb2hsl(low[0], low[1], low[2], h, s, l); + } + colorCurve.at(idx++) = xPosLow; colorCurve.at(idx++) = h; colorCurve.at(idx++) = 0.35; @@ -323,13 +399,15 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto } if (highSat == 0.f) { - if (medSat != 0.f) + if (medSat != 0.f) { Color::rgb2hsl(med[0], med[1], med[2], h, s, l); - else// lowSat can't be null if the 2 other ones are! + } else { // lowSat can't be null if the 2 other ones are! Color::rgb2hsl(low[0], low[1], low[2], h, s, l); - } - else + } + } else { Color::rgb2hsl(high[0], high[1], high[2], h, s, l); + } + colorCurve.at(idx++) = xPosHigh; colorCurve.at(idx++) = h; colorCurve.at(idx++) = 0.35; @@ -349,8 +427,9 @@ void ColorToningParams::mixerToCurve(std::vector &colorCurve, std::vecto opacityCurve.at(12) = 0.35; } -void ColorToningParams::slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const { - if (hlColSat.value[0]==0 && shadowsColSat.value[0]==0) { // if both opacity are null, set both curves to Linear +void ColorToningParams::slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const +{ + if (hlColSat.value[0] == 0 && shadowsColSat.value[0] == 0) { // if both opacity are null, set both curves to Linear colorCurve.resize(1); colorCurve.at(0) = FCT_Linear; opacityCurve.resize(1); @@ -360,142 +439,171 @@ void ColorToningParams::slidersToCurve(std::vector &colorCurve, std::vec colorCurve.resize(9); colorCurve.at(0) = FCT_MinMaxCPoints; - colorCurve.at(1) = 0.26 + 0.12*double(balance)/100.; - colorCurve.at(2) = double(shadowsColSat.value[1])/360.; + colorCurve.at(1) = 0.26 + 0.12 * double(balance) / 100.; + colorCurve.at(2) = double(shadowsColSat.value[1]) / 360.; colorCurve.at(3) = 0.35; colorCurve.at(4) = 0.35; - colorCurve.at(5) = 0.64 + 0.12*double(balance)/100.; - colorCurve.at(6) = double(hlColSat.value[1])/360.; + colorCurve.at(5) = 0.64 + 0.12 * double(balance) / 100.; + colorCurve.at(6) = double(hlColSat.value[1]) / 360.; colorCurve.at(7) = 0.35; colorCurve.at(8) = 0.35; opacityCurve.resize(9); opacityCurve.at(0) = FCT_MinMaxCPoints; opacityCurve.at(1) = colorCurve.at(1); - opacityCurve.at(2) = double(shadowsColSat.value[0])/100.; + opacityCurve.at(2) = double(shadowsColSat.value[0]) / 100.; opacityCurve.at(3) = 0.35; opacityCurve.at(4) = 0.35; opacityCurve.at(5) = colorCurve.at(5); - opacityCurve.at(6) = double(hlColSat.value[0])/100.; + opacityCurve.at(6) = double(hlColSat.value[0]) / 100.; opacityCurve.at(7) = 0.35; opacityCurve.at(8) = 0.35; } -void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3], bool &opautili) const { - float satur=0.8f; - float lumin=0.5f;//middle of luminance for optimization of gamut - no real importance...as we work in XYZ and gamut control +void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3], bool &opautili) const +{ + float satur = 0.8f; + float lumin = 0.5f; //middle of luminance for optimization of gamut - no real importance...as we work in XYZ and gamut control // Transform slider values to control points std::vector cCurve, oCurve; - if (method=="RGBSliders" || method=="Splitlr") + + if (method == "RGBSliders" || method == "Splitlr") { slidersToCurve(cCurve, oCurve); - else if (method=="Splitco") + } else if (method == "Splitco") { mixerToCurve(cCurve, oCurve); - else { + } else { cCurve = this->colorCurve; oCurve = this->opacityCurve; } - if(method=="Lab") { - if(twocolor=="Separ") satur=0.9f; - if(twocolor=="All" || twocolor=="Two") satur=0.9f; - colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin); - opacityCurveLUT.Set(oCurve, opautili); - } - else if(method=="Splitlr" || method=="Splitco") { + if(method == "Lab") { + if(twocolor == "Separ") { + satur = 0.9f; + } + + if(twocolor == "All" || twocolor == "Two") { + satur = 0.9f; + } + colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin); opacityCurveLUT.Set(oCurve, opautili); - } - else if(method.substr(0,3)=="RGB") { + } else if(method == "Splitlr" || method == "Splitco") { + colorCurveLUT.SetXYZ(cCurve, xyz_rgb, rgb_xyz, satur, lumin); + opacityCurveLUT.Set(oCurve, opautili); + } else if(method.substr(0, 3) == "RGB") { colorCurveLUT.SetRGB(cCurve, xyz_rgb, rgb_xyz); opacityCurveLUT.Set(oCurve, opautili); - } + } } //WaveletParams::WaveletParams (): hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), bllev(0, 2, 50, 25, false), pastlev(0, 2, 30, 20, false), satlev(30, 45, 130, 100, false), edgcont(0, 20, 100, 75, false){ -WaveletParams::WaveletParams (): hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), bllev(0, 2, 50, 25, false), - pastlev(0, 2, 30, 20, false), satlev(30, 45, 130, 100, false), edgcont(bl, tl, br, tr, false), /* edgcont(0, 10, 75, 40, false),*/level0noise(0, 0, false),level1noise(0, 0, false), level2noise(0, 0, false),level3noise(0, 0, false){ - setDefaults (); +WaveletParams::WaveletParams (): hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), bllev(0, 2, 50, 25, false), + pastlev(0, 2, 30, 20, false), satlev(30, 45, 130, 100, false), edgcont(bl, tl, br, tr, false), /* edgcont(0, 10, 75, 40, false),*/level0noise(0, 0, false), level1noise(0, 0, false), level2noise(0, 0, false), level3noise(0, 0, false) +{ + setDefaults (); } -void WaveletParams::getDefaultOpacityCurveRG(std::vector &curve) { - double v[8]= { 0.0, 0.50,0.35,0.35, - 1.00, 0.50,0.35,0.35}; +void WaveletParams::getDefaultOpacityCurveRG(std::vector &curve) +{ + double v[8] = { 0.0, 0.50, 0.35, 0.35, + 1.00, 0.50, 0.35, 0.35 + }; curve.resize(9); curve.at(0) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - double v[8]= { 0.0, 0.50,0.35,0.35, - 1.00, 0.50,0.35,0.35}; - +void WaveletParams::getDefaultOpacityCurveBY(std::vector &curve) +{ + double v[8] = { 0.0, 0.50, 0.35, 0.35, + 1.00, 0.50, 0.35, 0.35 + }; + curve.resize(9); curve.at(0 ) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - double v[16]={ 0.00, 0.35, 0.35, 0.00, - 0.35, 0.75, 0.35, 0.35, - 0.60, 0.75, 0.35, 0.35, - 1.00, 0.35, 0.00, 0.00 }; +void WaveletParams::getDefaultOpacityCurveW(std::vector &curve) +{ + double v[16] = { 0.00, 0.35, 0.35, 0.00, + 0.35, 0.75, 0.35, 0.35, + 0.60, 0.75, 0.35, 0.35, + 1.00, 0.35, 0.00, 0.00 + }; curve.resize(17); curve.at(0) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - double v[8]= { 0.0, 0.50,0.35,0.35, - 1.00, 0.50,0.35,0.35}; +void WaveletParams::getDefaultOpacityCurveWL(std::vector &curve) +{ + double v[8] = { 0.0, 0.50, 0.35, 0.35, + 1.00, 0.50, 0.35, 0.35 + }; - /*double v[12]={ 0.00, 0.53, 0.35, 0.00, - 0.42, 0.53, 0.35, 0.35, - 1.00, 0.15, 0.00, 0.00 }; - */ + /*double v[12]={ 0.00, 0.53, 0.35, 0.00, + 0.42, 0.53, 0.35, 0.35, + 1.00, 0.15, 0.00, 0.00 }; + */ curve.resize(9); curve.at(0) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - double v[12]= { 0.0, 0.25, 0.35, 0.35, - 0.50, 0.75, 0.35, 0.35, 0.90, 0.0, 0.35, 0.35}; - +void WaveletParams::getDefaultCCWCurve(std::vector &curve) +{ + double v[12] = { 0.0, 0.25, 0.35, 0.35, + 0.50, 0.75, 0.35, 0.35, 0.90, 0.0, 0.35, 0.35 + }; + curve.resize(13); curve.at(0 ) = double(FCT_MinMaxCPoints); - for (size_t i=1; iccwcurve); - opacityCurveLUTRG.Set(this->opacityCurveRG); - opacityCurveLUTBY.Set(this->opacityCurveBY); - opacityCurveLUTW.Set(this->opacityCurveW); - opacityCurveLUTWL.Set(this->opacityCurveWL); - +void WaveletParams::getCurves(WavCurve &cCurve, WavOpacityCurveRG &opacityCurveLUTRG, WavOpacityCurveBY &opacityCurveLUTBY, WavOpacityCurveW &opacityCurveLUTW, WavOpacityCurveWL &opacityCurveLUTWL) const +{ + cCurve.Set(this->ccwcurve); + opacityCurveLUTRG.Set(this->opacityCurveRG); + opacityCurveLUTBY.Set(this->opacityCurveBY); + opacityCurveLUTW.Set(this->opacityCurveW); + opacityCurveLUTWL.Set(this->opacityCurveWL); + } -void WaveletParams::setDefaults() { - getDefaultCCWCurve(ccwcurve); +void WaveletParams::setDefaults() +{ + getDefaultCCWCurve(ccwcurve); getDefaultOpacityCurveRG(opacityCurveRG); - getDefaultOpacityCurveBY(opacityCurveBY); - getDefaultOpacityCurveW(opacityCurveW); - getDefaultOpacityCurveWL(opacityCurveWL); - enabled = false; - median = false; - medianlev = false; - linkedg = true; - cbenab = false; - lipst = false; + getDefaultOpacityCurveBY(opacityCurveBY); + getDefaultOpacityCurveW(opacityCurveW); + getDefaultOpacityCurveWL(opacityCurveWL); + enabled = false; + median = false; + medianlev = false; + linkedg = true; + cbenab = false; + lipst = false; Medgreinf = "less"; //"none"; avoid = false; tmr = false; @@ -505,51 +613,51 @@ void WaveletParams::setDefaults() { wavclCurve.clear (); wavclCurve.push_back(DCT_Linear); - Lmethod = "4_"; - CHmethod = "without"; - CHSLmethod = "SL"; - EDmethod = "CU"; - NPmethod = "none"; - BAmethod = "none"; - TMmethod = "cont"; - HSmethod = "with"; - CLmethod = "all"; - Backmethod = "grey"; - Dirmethod = "all"; - Tilesmethod = "full"; - daubcoeffmethod = "4_"; - rescon = 0; - resconH = 0; - reschro = 0; - tmrs = 0; - gamma = 1; - sky = 0.; - sup = 0; - thres = 7; - chroma = 5; - chro = 0; - contrast = 0; - edgrad =15; - edgval = 0; - edgthresh = 10; - thr = 35; - thrH = 65; + Lmethod = "4_"; + CHmethod = "without"; + CHSLmethod = "SL"; + EDmethod = "CU"; + NPmethod = "none"; + BAmethod = "none"; + TMmethod = "cont"; + HSmethod = "with"; + CLmethod = "all"; + Backmethod = "grey"; + Dirmethod = "all"; + Tilesmethod = "full"; + daubcoeffmethod = "4_"; + rescon = 0; + resconH = 0; + reschro = 0; + tmrs = 0; + gamma = 1; + sky = 0.; + sup = 0; + thres = 7; + chroma = 5; + chro = 0; + contrast = 0; + edgrad = 15; + edgval = 0; + edgthresh = 10; + thr = 35; + thrH = 65; skinprotect = 0.; - hueskin.setValues(-5, 25, 170, 120); - hueskin2.setValues(-260, -250, -130, -140); - threshold=5; - threshold2=4; - edgedetect=90; - edgedetectthr=20; - edgedetectthr2=0; - edgesensi=60; - edgeampli=10; - hllev.setValues(50, 75, 100, 98); - bllev.setValues(0, 2, 50, 25); - pastlev.setValues(0, 2, 30, 20); - satlev.setValues(30, 45, 130, 100); -// edgcont.setValues(bl, tl, br, tr); - edgcont.setValues(0, 10, 75, 40); + hueskin.setValues(-5, 25, 170, 120); + hueskin2.setValues(-260, -250, -130, -140); + threshold = 5; + threshold2 = 4; + edgedetect = 90; + edgedetectthr = 20; + edgedetectthr2 = 0; + edgesensi = 60; + edgeampli = 10; + hllev.setValues(50, 75, 100, 98); + bllev.setValues(0, 2, 50, 25); + pastlev.setValues(0, 2, 30, 20); + satlev.setValues(30, 45, 130, 100); +// edgcont.setValues(bl, tl, br, tr); + edgcont.setValues(0, 10, 75, 40); level0noise.setValues(0, 0); level1noise.setValues(0, 0); level2noise.setValues(0, 0); @@ -558,53 +666,62 @@ void WaveletParams::setDefaults() { hhcurve.push_back(FCT_Linear); Chcurve.clear (); Chcurve.push_back(FCT_Linear); - expcontrast=true; - expchroma=true; - expedge=true; - expresid=true; - expfinal=true; - exptoning=true; - expnoise=true; - - for(int i = 0; i < 9; i ++) - { + expcontrast = true; + expchroma = true; + expedge = true; + expresid = true; + expfinal = true; + exptoning = true; + expnoise = true; + + for(int i = 0; i < 9; i ++) { c[i] = 0; } - for(int i = 0; i < 9; i ++) - { + + for(int i = 0; i < 9; i ++) { ch[i] = 0; } } -DirPyrDenoiseParams::DirPyrDenoiseParams () { +DirPyrDenoiseParams::DirPyrDenoiseParams () +{ setDefaults (); } -void DirPyrDenoiseParams::getDefaultNoisCurve(std::vector &curve) { - double v[8]={ 0.05, 0.15, 0.35, 0.35, - 0.55, 0.04, 0.35, 0.35}; +void DirPyrDenoiseParams::getDefaultNoisCurve(std::vector &curve) +{ + double v[8] = { 0.05, 0.15, 0.35, 0.35, + 0.55, 0.04, 0.35, 0.35 + }; curve.resize(9); curve.at(0 ) = double(FCT_MinMaxCPoints); - for (size_t i=1; i &curve) { - // double v[8]= { 0.15, 0.00,0.35,0.35, - // 0.60, 0.05,0.35,0.35}; - double v[8]= { 0.05, 0.50,0.35,0.35, - 0.35, 0.05,0.35,0.35}; +void DirPyrDenoiseParams::getDefaultCCCurve(std::vector &curve) +{ + // double v[8]= { 0.15, 0.00,0.35,0.35, + // 0.60, 0.05,0.35,0.35}; + double v[8] = { 0.05, 0.50, 0.35, 0.35, + 0.35, 0.05, 0.35, 0.35 + }; curve.resize(9); curve.at(0 ) = double(FCT_MinMaxCPoints); - for (size_t i=1; ilcurve); cCurve.Set(this->cccurve); } -void ToneCurveParams::setDefaults() { +void ToneCurveParams::setDefaults() +{ autoexp = false; clip = 0.02; expcomp = 0; @@ -656,19 +775,22 @@ void ToneCurveParams::setDefaults() { method = "Blend"; } -void LensProfParams::setDefaults() { - lcpFile=""; - useDist=useVign=true; - useCA=false; +void LensProfParams::setDefaults() +{ + lcpFile = ""; + useDist = useVign = true; + useCA = false; } -void CoarseTransformParams::setDefaults() { +void CoarseTransformParams::setDefaults() +{ rotate = 0; hflip = false; vflip = false; } -void RAWParams::setDefaults() { +void RAWParams::setDefaults() +{ bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze]; bayersensor.ccSteps = 0; bayersensor.dcb_iterations = 2; @@ -689,8 +811,8 @@ void RAWParams::setDefaults() { xtranssensor.blackgreen = 0.0; xtranssensor.blackblue = 0.0; - expos=1.0; - preser=0.0; + expos = 1.0; + preser = 0.0; df_autoselect = false; ff_AutoSelect = false; ff_BlurRadius = 32; @@ -705,7 +827,8 @@ void RAWParams::setDefaults() { hotdeadpix_thresh = 100; } -void ColorManagementParams::setDefaults() { +void ColorManagementParams::setDefaults() +{ input = "(cameraICC)"; blendCMSMatrix = false; toneCurve = true; @@ -716,37 +839,43 @@ void ColorManagementParams::setDefaults() { working = "ProPhoto"; output = "RT_sRGB"; gamma = "default"; - gampos =2.22; - slpos=4.5; + gampos = 2.22; + slpos = 4.5; freegamma = false; } -ProcParams::ProcParams () { +ProcParams::ProcParams () +{ - setDefaults (); + setDefaults (); } -void ProcParams::init () { +void ProcParams::init () +{ WBParams::init(); } -void ProcParams::cleanup () { +void ProcParams::cleanup () +{ WBParams::cleanup(); } -ProcParams* ProcParams::create () { +ProcParams* ProcParams::create () +{ return new ProcParams(); } -void ProcParams::destroy (ProcParams* pp) { +void ProcParams::destroy (ProcParams* pp) +{ delete pp; } -void ProcParams::setDefaults () { +void ProcParams::setDefaults () +{ toneCurve.setDefaults(); @@ -832,7 +961,7 @@ void ProcParams::setDefaults () { vibrance.psthreshold.setValues(0, 75); vibrance.protectskins = false; vibrance.avoidcolorshift = true; - vibrance.pastsattog = true; + vibrance.pastsattog = true; vibrance.skintonescurve.clear (); vibrance.skintonescurve.push_back(DCT_Linear); @@ -864,12 +993,12 @@ void ProcParams::setDefaults () { // colorappearance.badpix = false; colorappearance.datacie = false; colorappearance.tonecie = false; - // colorappearance.sharpcie = false; +// colorappearance.sharpcie = false; colorappearance.curve.clear (); colorappearance.curve.push_back(DCT_Linear); colorappearance.curve2.clear (); colorappearance.curve2.push_back(DCT_Linear); - colorappearance.curveMode =ColorAppearanceParams::TC_MODE_LIGHT; + colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT; colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT; colorappearance.curve3.clear (); colorappearance.curve3.push_back(DCT_Linear); @@ -925,7 +1054,7 @@ void ProcParams::setDefaults () { sh.stonalwidth = 80; sh.localcontrast = 0; sh.radius = 40; - + crop.enabled = false; crop.x = -1; crop.y = -1; @@ -933,17 +1062,17 @@ void ProcParams::setDefaults () { crop.h = 15000; crop.fixratio = false; crop.ratio = "3:2"; - crop.orientation= "As Image"; + crop.orientation = "As Image"; crop.guide = "Rule of thirds"; - + coarse.setDefaults(); - + commonTrans.autofill = true; rotate.degree = 0; distortion.amount = 0; - + perspective.horizontal = 0; perspective.vertical = 0; @@ -961,7 +1090,7 @@ void ProcParams::setDefaults () { cacorrection.red = 0; cacorrection.blue = 0; - + vignetting.amount = 0; vignetting.radius = 50; @@ -981,7 +1110,7 @@ void ProcParams::setDefaults () { chmixer.blue[1] = 0; chmixer.blue[2] = 100; - blackwhite.autoc = false; + blackwhite.autoc = false; blackwhite.enabledcc = true; blackwhite.enabled = false; blackwhite.mixerRed = 33; @@ -1017,17 +1146,18 @@ void ProcParams::setDefaults () { resize.height = 900; icm.setDefaults(); - + dirpyrequalizer.enabled = false; dirpyrequalizer.gamutlab = false; - for(int i = 0; i < 6; i ++) - { + + for(int i = 0; i < 6; i ++) { dirpyrequalizer.mult[i] = 1.0; } + dirpyrequalizer.threshold = 0.2; dirpyrequalizer.skinprotect = 0.; dirpyrequalizer.hueskin.setValues(-5, 25, 170, 120); //default (b_l 0, t_l 30, b_r 170, t_r 120); - // dirpyrequalizer.algo = "FI"; +// dirpyrequalizer.algo = "FI"; hsvequalizer.hcurve.clear (); hsvequalizer.hcurve.push_back (FCT_Linear); @@ -1046,128 +1176,203 @@ void ProcParams::setDefaults () { rank = 0; colorlabel = 0; inTrash = false; - + ppVersion = PPVERSION; } -static Glib::ustring expandRelativePath(Glib::ustring procparams_fname, Glib::ustring prefix, Glib::ustring embedded_fname) { +static Glib::ustring expandRelativePath(Glib::ustring procparams_fname, Glib::ustring prefix, Glib::ustring embedded_fname) +{ if (embedded_fname == "" || !Glib::path_is_absolute(procparams_fname)) { return embedded_fname; } + if (prefix != "") { if (embedded_fname.length() < prefix.length() || embedded_fname.substr(0, prefix.length()) != prefix) { return embedded_fname; } + embedded_fname = embedded_fname.substr(prefix.length()); } + if (Glib::path_is_absolute(embedded_fname)) { return prefix + embedded_fname; } + Glib::ustring absPath = prefix + Glib::path_get_dirname(procparams_fname) + G_DIR_SEPARATOR_S + embedded_fname; return absPath; } -static Glib::ustring relativePathIfInside(Glib::ustring procparams_fname, bool fnameAbsolute, Glib::ustring embedded_fname) { +static Glib::ustring relativePathIfInside(Glib::ustring procparams_fname, bool fnameAbsolute, Glib::ustring embedded_fname) +{ if (fnameAbsolute || embedded_fname == "" || !Glib::path_is_absolute(procparams_fname)) { return embedded_fname; } + Glib::ustring prefix = ""; + if (embedded_fname.length() > 5 && embedded_fname.substr(0, 5) == "file:") { embedded_fname = embedded_fname.substr(5); prefix = "file:"; } + if (!Glib::path_is_absolute(embedded_fname)) { return prefix + embedded_fname; } + Glib::ustring dir1 = Glib::path_get_dirname(procparams_fname) + G_DIR_SEPARATOR_S; Glib::ustring dir2 = Glib::path_get_dirname(embedded_fname) + G_DIR_SEPARATOR_S; + if (dir2.substr(0, dir1.length()) != dir1) { // it's in a different directory, ie not inside return prefix + embedded_fname; } + return prefix + embedded_fname.substr(dir1.length()); } -int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsolute, ParamsEdited* pedited) { +int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsolute, ParamsEdited* pedited) +{ - if (!fname.length() && !fname2.length()) + if (!fname.length() && !fname2.length()) { return 0; + } SafeKeyFile keyFile; keyFile.set_string ("Version", "AppVersion", APPVERSION); keyFile.set_integer ("Version", "Version", PPVERSION); - if (!pedited || pedited->general.rank) keyFile.set_integer ("General", "Rank", rank); - if (!pedited || pedited->general.colorlabel) keyFile.set_integer ("General", "ColorLabel", colorlabel); - if (!pedited || pedited->general.intrash) keyFile.set_boolean ("General", "InTrash", inTrash); + if (!pedited || pedited->general.rank) { + keyFile.set_integer ("General", "Rank", rank); + } + + if (!pedited || pedited->general.colorlabel) { + keyFile.set_integer ("General", "ColorLabel", colorlabel); + } + + if (!pedited || pedited->general.intrash) { + keyFile.set_boolean ("General", "InTrash", inTrash); + } // save tone curve - if (!pedited || pedited->toneCurve.autoexp) keyFile.set_boolean ("Exposure", "Auto", toneCurve.autoexp); - if (!pedited || pedited->toneCurve.clip) keyFile.set_double ("Exposure", "Clip", toneCurve.clip); - if (!pedited || pedited->toneCurve.expcomp) keyFile.set_double ("Exposure", "Compensation", toneCurve.expcomp); - if (!pedited || pedited->toneCurve.brightness) keyFile.set_integer ("Exposure", "Brightness", toneCurve.brightness); - if (!pedited || pedited->toneCurve.contrast) keyFile.set_integer ("Exposure", "Contrast", toneCurve.contrast); - if (!pedited || pedited->toneCurve.saturation) keyFile.set_integer ("Exposure", "Saturation", toneCurve.saturation); - if (!pedited || pedited->toneCurve.black) keyFile.set_integer ("Exposure", "Black", toneCurve.black); - if (!pedited || pedited->toneCurve.hlcompr) keyFile.set_integer ("Exposure", "HighlightCompr", toneCurve.hlcompr); - if (!pedited || pedited->toneCurve.hlcomprthresh) keyFile.set_integer ("Exposure", "HighlightComprThreshold", toneCurve.hlcomprthresh); - if (!pedited || pedited->toneCurve.shcompr) keyFile.set_integer ("Exposure", "ShadowCompr", toneCurve.shcompr); + if (!pedited || pedited->toneCurve.autoexp) { + keyFile.set_boolean ("Exposure", "Auto", toneCurve.autoexp); + } + + if (!pedited || pedited->toneCurve.clip) { + keyFile.set_double ("Exposure", "Clip", toneCurve.clip); + } + + if (!pedited || pedited->toneCurve.expcomp) { + keyFile.set_double ("Exposure", "Compensation", toneCurve.expcomp); + } + + if (!pedited || pedited->toneCurve.brightness) { + keyFile.set_integer ("Exposure", "Brightness", toneCurve.brightness); + } + + if (!pedited || pedited->toneCurve.contrast) { + keyFile.set_integer ("Exposure", "Contrast", toneCurve.contrast); + } + + if (!pedited || pedited->toneCurve.saturation) { + keyFile.set_integer ("Exposure", "Saturation", toneCurve.saturation); + } + + if (!pedited || pedited->toneCurve.black) { + keyFile.set_integer ("Exposure", "Black", toneCurve.black); + } + + if (!pedited || pedited->toneCurve.hlcompr) { + keyFile.set_integer ("Exposure", "HighlightCompr", toneCurve.hlcompr); + } + + if (!pedited || pedited->toneCurve.hlcomprthresh) { + keyFile.set_integer ("Exposure", "HighlightComprThreshold", toneCurve.hlcomprthresh); + } + + if (!pedited || pedited->toneCurve.shcompr) { + keyFile.set_integer ("Exposure", "ShadowCompr", toneCurve.shcompr); + } + // save highlight recovery settings - if (!pedited || pedited->toneCurve.hrenabled) keyFile.set_boolean ("HLRecovery", "Enabled", toneCurve.hrenabled); - if (!pedited || pedited->toneCurve.method) keyFile.set_string ("HLRecovery", "Method", toneCurve.method); + if (!pedited || pedited->toneCurve.hrenabled) { + keyFile.set_boolean ("HLRecovery", "Enabled", toneCurve.hrenabled); + } + + if (!pedited || pedited->toneCurve.method) { + keyFile.set_string ("HLRecovery", "Method", toneCurve.method); + } + if (!pedited || pedited->toneCurve.curveMode) { Glib::ustring method; + switch (toneCurve.curveMode) { case (ToneCurveParams::TC_MODE_STD): method = "Standard"; break; + case (ToneCurveParams::TC_MODE_FILMLIKE): method = "FilmLike"; break; + case (ToneCurveParams::TC_MODE_SATANDVALBLENDING): method = "SatAndValueBlending"; break; + case (ToneCurveParams::TC_MODE_WEIGHTEDSTD): method = "WeightedStd"; break; + case (ToneCurveParams::TC_MODE_LUMINANCE): method = "Luminance"; break; + case (ToneCurveParams::TC_MODE_PERCEPTUAL): method = "Perceptual"; break; } + keyFile.set_string ("Exposure", "CurveMode", method); } + if (!pedited || pedited->toneCurve.curveMode2) { Glib::ustring method; + switch (toneCurve.curveMode2) { case (ToneCurveParams::TC_MODE_STD): method = "Standard"; break; + case (ToneCurveParams::TC_MODE_FILMLIKE): method = "FilmLike"; break; + case (ToneCurveParams::TC_MODE_SATANDVALBLENDING): method = "SatAndValueBlending"; break; + case (ToneCurveParams::TC_MODE_WEIGHTEDSTD): method = "WeightedStd"; break; + case (ToneCurveParams::TC_MODE_LUMINANCE): method = "Luminance"; break; + case (ToneCurveParams::TC_MODE_PERCEPTUAL): method = "Perceptual"; break; } + keyFile.set_string ("Exposure", "CurveMode2", method); } + if (!pedited || pedited->toneCurve.curve) { Glib::ArrayHandle tcurve = toneCurve.curve; keyFile.set_double_list("Exposure", "Curve", tcurve); } + if (!pedited || pedited->toneCurve.curve2) { Glib::ArrayHandle tcurve = toneCurve.curve2; keyFile.set_double_list("Exposure", "Curve2", tcurve); @@ -1178,70 +1383,135 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle rmix (chmixer.red, 3, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Channel Mixer", "Red", rmix); } + if (!pedited || pedited->chmixer.green[0] || pedited->chmixer.green[1] || pedited->chmixer.green[2]) { Glib::ArrayHandle gmix (chmixer.green, 3, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Channel Mixer", "Green", gmix); } + if (!pedited || pedited->chmixer.blue[0] || pedited->chmixer.blue[1] || pedited->chmixer.blue[2]) { Glib::ArrayHandle bmix (chmixer.blue, 3, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Channel Mixer", "Blue", bmix); } //save Black & White - if (!pedited || pedited->blackwhite.enabled) keyFile.set_boolean ("Black & White", "Enabled", blackwhite.enabled); - if (!pedited || pedited->blackwhite.method) keyFile.set_string ("Black & White", "Method", blackwhite.method ); - if (!pedited || pedited->blackwhite.autoc) keyFile.set_boolean ("Black & White", "Auto", blackwhite.autoc); - if (!pedited || pedited->blackwhite.enabledcc) keyFile.set_boolean ("Black & White", "ComplementaryColors", blackwhite.enabledcc); - if (!pedited || pedited->blackwhite.setting) keyFile.set_string ("Black & White", "Setting", blackwhite.setting ); - if (!pedited || pedited->blackwhite.filter) keyFile.set_string ("Black & White", "Filter", blackwhite.filter ); - if (!pedited || pedited->blackwhite.mixerRed) keyFile.set_integer ("Black & White", "MixerRed", blackwhite.mixerRed); - if (!pedited || pedited->blackwhite.mixerOrange) keyFile.set_integer ("Black & White", "MixerOrange", blackwhite.mixerOrange); - if (!pedited || pedited->blackwhite.mixerYellow) keyFile.set_integer ("Black & White", "MixerYellow", blackwhite.mixerYellow); - if (!pedited || pedited->blackwhite.mixerGreen) keyFile.set_integer ("Black & White", "MixerGreen", blackwhite.mixerGreen); - if (!pedited || pedited->blackwhite.mixerCyan) keyFile.set_integer ("Black & White", "MixerCyan", blackwhite.mixerCyan); - if (!pedited || pedited->blackwhite.mixerBlue) keyFile.set_integer ("Black & White", "MixerBlue", blackwhite.mixerBlue); - if (!pedited || pedited->blackwhite.mixerMagenta) keyFile.set_integer ("Black & White", "MixerMagenta", blackwhite.mixerMagenta); - if (!pedited || pedited->blackwhite.mixerPurple) keyFile.set_integer ("Black & White", "MixerPurple", blackwhite.mixerPurple); - if (!pedited || pedited->blackwhite.gammaRed) keyFile.set_integer ("Black & White", "GammaRed", blackwhite.gammaRed); - if (!pedited || pedited->blackwhite.gammaGreen) keyFile.set_integer ("Black & White", "GammaGreen", blackwhite.gammaGreen); - if (!pedited || pedited->blackwhite.gammaBlue) keyFile.set_integer ("Black & White", "GammaBlue", blackwhite.gammaBlue); - if (!pedited || pedited->blackwhite.algo) keyFile.set_string ("Black & White", "Algorithm", blackwhite.algo); + if (!pedited || pedited->blackwhite.enabled) { + keyFile.set_boolean ("Black & White", "Enabled", blackwhite.enabled); + } + + if (!pedited || pedited->blackwhite.method) { + keyFile.set_string ("Black & White", "Method", blackwhite.method ); + } + + if (!pedited || pedited->blackwhite.autoc) { + keyFile.set_boolean ("Black & White", "Auto", blackwhite.autoc); + } + + if (!pedited || pedited->blackwhite.enabledcc) { + keyFile.set_boolean ("Black & White", "ComplementaryColors", blackwhite.enabledcc); + } + + if (!pedited || pedited->blackwhite.setting) { + keyFile.set_string ("Black & White", "Setting", blackwhite.setting ); + } + + if (!pedited || pedited->blackwhite.filter) { + keyFile.set_string ("Black & White", "Filter", blackwhite.filter ); + } + + if (!pedited || pedited->blackwhite.mixerRed) { + keyFile.set_integer ("Black & White", "MixerRed", blackwhite.mixerRed); + } + + if (!pedited || pedited->blackwhite.mixerOrange) { + keyFile.set_integer ("Black & White", "MixerOrange", blackwhite.mixerOrange); + } + + if (!pedited || pedited->blackwhite.mixerYellow) { + keyFile.set_integer ("Black & White", "MixerYellow", blackwhite.mixerYellow); + } + + if (!pedited || pedited->blackwhite.mixerGreen) { + keyFile.set_integer ("Black & White", "MixerGreen", blackwhite.mixerGreen); + } + + if (!pedited || pedited->blackwhite.mixerCyan) { + keyFile.set_integer ("Black & White", "MixerCyan", blackwhite.mixerCyan); + } + + if (!pedited || pedited->blackwhite.mixerBlue) { + keyFile.set_integer ("Black & White", "MixerBlue", blackwhite.mixerBlue); + } + + if (!pedited || pedited->blackwhite.mixerMagenta) { + keyFile.set_integer ("Black & White", "MixerMagenta", blackwhite.mixerMagenta); + } + + if (!pedited || pedited->blackwhite.mixerPurple) { + keyFile.set_integer ("Black & White", "MixerPurple", blackwhite.mixerPurple); + } + + if (!pedited || pedited->blackwhite.gammaRed) { + keyFile.set_integer ("Black & White", "GammaRed", blackwhite.gammaRed); + } + + if (!pedited || pedited->blackwhite.gammaGreen) { + keyFile.set_integer ("Black & White", "GammaGreen", blackwhite.gammaGreen); + } + + if (!pedited || pedited->blackwhite.gammaBlue) { + keyFile.set_integer ("Black & White", "GammaBlue", blackwhite.gammaBlue); + } + + if (!pedited || pedited->blackwhite.algo) { + keyFile.set_string ("Black & White", "Algorithm", blackwhite.algo); + } if (!pedited || pedited->blackwhite.luminanceCurve) { Glib::ArrayHandle luminanceCurve = blackwhite.luminanceCurve; keyFile.set_double_list("Black & White", "LuminanceCurve", luminanceCurve); } + if (!pedited || pedited->blackwhite.beforeCurveMode) { Glib::ustring mode; + switch (blackwhite.beforeCurveMode) { case (BlackWhiteParams::TC_MODE_STD_BW): mode = "Standard"; break; + case (BlackWhiteParams::TC_MODE_FILMLIKE_BW): mode = "FilmLike"; break; + case (BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW): mode = "SatAndValueBlending"; break; + case (BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW): mode = "WeightedStd"; break; } + keyFile.set_string ("Black & White", "BeforeCurveMode", mode); } if (!pedited || pedited->blackwhite.afterCurveMode) { Glib::ustring mode; + switch (blackwhite.afterCurveMode) { case (BlackWhiteParams::TC_MODE_STD_BW): mode = "Standard"; break; + case (BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW): mode = "WeightedStd"; break; + default: break; } + keyFile.set_string ("Black & White", "AfterCurveMode", mode); } @@ -1249,43 +1519,67 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle tcurvebw = blackwhite.beforeCurve; keyFile.set_double_list("Black & White", "BeforeCurve", tcurvebw); } + if (!pedited || pedited->blackwhite.afterCurve) { Glib::ArrayHandle tcurvebw = blackwhite.afterCurve; keyFile.set_double_list("Black & White", "AfterCurve", tcurvebw); } // save luma curve - if (!pedited || pedited->labCurve.brightness) keyFile.set_integer ("Luminance Curve", "Brightness", labCurve.brightness); - if (!pedited || pedited->labCurve.contrast) keyFile.set_integer ("Luminance Curve", "Contrast", labCurve.contrast); - if (!pedited || pedited->labCurve.chromaticity) keyFile.set_integer ("Luminance Curve", "Chromaticity", labCurve.chromaticity); - if (!pedited || pedited->labCurve.avoidcolorshift) keyFile.set_boolean ("Luminance Curve", "AvoidColorShift", labCurve.avoidcolorshift); - if (!pedited || pedited->labCurve.rstprotection) keyFile.set_double ("Luminance Curve", "RedAndSkinTonesProtection", labCurve.rstprotection); - if (!pedited || pedited->labCurve.lcredsk) keyFile.set_boolean ("Luminance Curve", "LCredsk", labCurve.lcredsk); - + if (!pedited || pedited->labCurve.brightness) { + keyFile.set_integer ("Luminance Curve", "Brightness", labCurve.brightness); + } + + if (!pedited || pedited->labCurve.contrast) { + keyFile.set_integer ("Luminance Curve", "Contrast", labCurve.contrast); + } + + if (!pedited || pedited->labCurve.chromaticity) { + keyFile.set_integer ("Luminance Curve", "Chromaticity", labCurve.chromaticity); + } + + if (!pedited || pedited->labCurve.avoidcolorshift) { + keyFile.set_boolean ("Luminance Curve", "AvoidColorShift", labCurve.avoidcolorshift); + } + + if (!pedited || pedited->labCurve.rstprotection) { + keyFile.set_double ("Luminance Curve", "RedAndSkinTonesProtection", labCurve.rstprotection); + } + + if (!pedited || pedited->labCurve.lcredsk) { + keyFile.set_boolean ("Luminance Curve", "LCredsk", labCurve.lcredsk); + } + if (!pedited || pedited->labCurve.lcurve) { Glib::ArrayHandle lcurve = labCurve.lcurve; keyFile.set_double_list("Luminance Curve", "LCurve", lcurve); } + if (!pedited || pedited->labCurve.acurve) { Glib::ArrayHandle acurve = labCurve.acurve; keyFile.set_double_list("Luminance Curve", "aCurve", acurve); } + if (!pedited || pedited->labCurve.bcurve) { Glib::ArrayHandle bcurve = labCurve.bcurve; keyFile.set_double_list("Luminance Curve", "bCurve", bcurve); } + if (!pedited || pedited->labCurve.cccurve) { Glib::ArrayHandle cccurve = labCurve.cccurve; keyFile.set_double_list("Luminance Curve", "ccCurve", cccurve); } + if (!pedited || pedited->labCurve.chcurve) { Glib::ArrayHandle chcurve = labCurve.chcurve; keyFile.set_double_list("Luminance Curve", "chCurve", chcurve); } + if (!pedited || pedited->labCurve.lhcurve) { Glib::ArrayHandle lhcurve = labCurve.lhcurve; keyFile.set_double_list("Luminance Curve", "lhCurve", lhcurve); } + if (!pedited || pedited->labCurve.hhcurve) { Glib::ArrayHandle hhcurve = labCurve.hhcurve; keyFile.set_double_list("Luminance Curve", "hhCurve", hhcurve); @@ -1295,528 +1589,1231 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle lccurve = labCurve.lccurve; keyFile.set_double_list("Luminance Curve", "LcCurve", lccurve); } + if (!pedited || pedited->labCurve.clcurve) { Glib::ArrayHandle clcurve = labCurve.clcurve; keyFile.set_double_list("Luminance Curve", "ClCurve", clcurve); } // save sharpening - if (!pedited || pedited->sharpening.enabled) keyFile.set_boolean ("Sharpening", "Enabled", sharpening.enabled); - if (!pedited || pedited->sharpening.method) keyFile.set_string ("Sharpening", "Method", sharpening.method); - if (!pedited || pedited->sharpening.radius) keyFile.set_double ("Sharpening", "Radius", sharpening.radius); - if (!pedited || pedited->sharpening.amount) keyFile.set_integer ("Sharpening", "Amount", sharpening.amount); + if (!pedited || pedited->sharpening.enabled) { + keyFile.set_boolean ("Sharpening", "Enabled", sharpening.enabled); + } + + if (!pedited || pedited->sharpening.method) { + keyFile.set_string ("Sharpening", "Method", sharpening.method); + } + + if (!pedited || pedited->sharpening.radius) { + keyFile.set_double ("Sharpening", "Radius", sharpening.radius); + } + + if (!pedited || pedited->sharpening.amount) { + keyFile.set_integer ("Sharpening", "Amount", sharpening.amount); + } + if (!pedited || pedited->sharpening.threshold) { Glib::ArrayHandle thresh (sharpening.threshold.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Sharpening", "Threshold", thresh); } - if (!pedited || pedited->sharpening.edgesonly) keyFile.set_boolean ("Sharpening", "OnlyEdges", sharpening.edgesonly); - if (!pedited || pedited->sharpening.edges_radius) keyFile.set_double ("Sharpening", "EdgedetectionRadius", sharpening.edges_radius); - if (!pedited || pedited->sharpening.edges_tolerance) keyFile.set_integer ("Sharpening", "EdgeTolerance", sharpening.edges_tolerance); - if (!pedited || pedited->sharpening.halocontrol) keyFile.set_boolean ("Sharpening", "HalocontrolEnabled", sharpening.halocontrol); - if (!pedited || pedited->sharpening.halocontrol_amount) keyFile.set_integer ("Sharpening", "HalocontrolAmount", sharpening.halocontrol_amount); - if (!pedited || pedited->sharpening.deconvradius) keyFile.set_double ("Sharpening", "DeconvRadius", sharpening.deconvradius); - if (!pedited || pedited->sharpening.deconvamount) keyFile.set_integer ("Sharpening", "DeconvAmount", sharpening.deconvamount); - if (!pedited || pedited->sharpening.deconvdamping) keyFile.set_integer ("Sharpening", "DeconvDamping", sharpening.deconvdamping); - if (!pedited || pedited->sharpening.deconviter) keyFile.set_integer ("Sharpening", "DeconvIterations", sharpening.deconviter); + + if (!pedited || pedited->sharpening.edgesonly) { + keyFile.set_boolean ("Sharpening", "OnlyEdges", sharpening.edgesonly); + } + + if (!pedited || pedited->sharpening.edges_radius) { + keyFile.set_double ("Sharpening", "EdgedetectionRadius", sharpening.edges_radius); + } + + if (!pedited || pedited->sharpening.edges_tolerance) { + keyFile.set_integer ("Sharpening", "EdgeTolerance", sharpening.edges_tolerance); + } + + if (!pedited || pedited->sharpening.halocontrol) { + keyFile.set_boolean ("Sharpening", "HalocontrolEnabled", sharpening.halocontrol); + } + + if (!pedited || pedited->sharpening.halocontrol_amount) { + keyFile.set_integer ("Sharpening", "HalocontrolAmount", sharpening.halocontrol_amount); + } + + if (!pedited || pedited->sharpening.deconvradius) { + keyFile.set_double ("Sharpening", "DeconvRadius", sharpening.deconvradius); + } + + if (!pedited || pedited->sharpening.deconvamount) { + keyFile.set_integer ("Sharpening", "DeconvAmount", sharpening.deconvamount); + } + + if (!pedited || pedited->sharpening.deconvdamping) { + keyFile.set_integer ("Sharpening", "DeconvDamping", sharpening.deconvdamping); + } + + if (!pedited || pedited->sharpening.deconviter) { + keyFile.set_integer ("Sharpening", "DeconvIterations", sharpening.deconviter); + } // save vibrance - if (!pedited || pedited->vibrance.enabled) keyFile.set_boolean ("Vibrance", "Enabled", vibrance.enabled); - if (!pedited || pedited->vibrance.pastels) keyFile.set_integer ("Vibrance", "Pastels", vibrance.pastels); - if (!pedited || pedited->vibrance.saturated) keyFile.set_integer ("Vibrance", "Saturated", vibrance.saturated); + if (!pedited || pedited->vibrance.enabled) { + keyFile.set_boolean ("Vibrance", "Enabled", vibrance.enabled); + } + + if (!pedited || pedited->vibrance.pastels) { + keyFile.set_integer ("Vibrance", "Pastels", vibrance.pastels); + } + + if (!pedited || pedited->vibrance.saturated) { + keyFile.set_integer ("Vibrance", "Saturated", vibrance.saturated); + } + if (!pedited || pedited->vibrance.psthreshold) { Glib::ArrayHandle thresh (vibrance.psthreshold.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Vibrance", "PSThreshold", thresh); } - if (!pedited || pedited->vibrance.protectskins) keyFile.set_boolean ("Vibrance", "ProtectSkins", vibrance.protectskins); - if (!pedited || pedited->vibrance.avoidcolorshift) keyFile.set_boolean ("Vibrance", "AvoidColorShift", vibrance.avoidcolorshift); - if (!pedited || pedited->vibrance.pastsattog) keyFile.set_boolean ("Vibrance", "PastSatTog", vibrance.pastsattog); + + if (!pedited || pedited->vibrance.protectskins) { + keyFile.set_boolean ("Vibrance", "ProtectSkins", vibrance.protectskins); + } + + if (!pedited || pedited->vibrance.avoidcolorshift) { + keyFile.set_boolean ("Vibrance", "AvoidColorShift", vibrance.avoidcolorshift); + } + + if (!pedited || pedited->vibrance.pastsattog) { + keyFile.set_boolean ("Vibrance", "PastSatTog", vibrance.pastsattog); + } + if (!pedited || pedited->vibrance.skintonescurve) { Glib::ArrayHandle skintonescurve = vibrance.skintonescurve; keyFile.set_double_list("Vibrance", "SkinTonesCurve", skintonescurve); } //save edge sharpening - if (!pedited || pedited->sharpenEdge.enabled) keyFile.set_boolean ("SharpenEdge", "Enabled", sharpenEdge.enabled); - if (!pedited || pedited->sharpenEdge.passes) keyFile.set_integer ("SharpenEdge", "Passes", sharpenEdge.passes); - if (!pedited || pedited->sharpenEdge.amount) keyFile.set_double ("SharpenEdge", "Strength", sharpenEdge.amount); - if (!pedited || pedited->sharpenEdge.threechannels) keyFile.set_boolean ("SharpenEdge", "ThreeChannels", sharpenEdge.threechannels); + if (!pedited || pedited->sharpenEdge.enabled) { + keyFile.set_boolean ("SharpenEdge", "Enabled", sharpenEdge.enabled); + } + + if (!pedited || pedited->sharpenEdge.passes) { + keyFile.set_integer ("SharpenEdge", "Passes", sharpenEdge.passes); + } + + if (!pedited || pedited->sharpenEdge.amount) { + keyFile.set_double ("SharpenEdge", "Strength", sharpenEdge.amount); + } + + if (!pedited || pedited->sharpenEdge.threechannels) { + keyFile.set_boolean ("SharpenEdge", "ThreeChannels", sharpenEdge.threechannels); + } //save micro-contrast sharpening - if (!pedited || pedited->sharpenMicro.enabled) keyFile.set_boolean ("SharpenMicro", "Enabled", sharpenMicro.enabled); - if (!pedited || pedited->sharpenMicro.matrix) keyFile.set_boolean ("SharpenMicro", "Matrix", sharpenMicro.matrix); - if (!pedited || pedited->sharpenMicro.amount) keyFile.set_double ("SharpenMicro", "Strength", sharpenMicro.amount); - if (!pedited || pedited->sharpenMicro.uniformity) keyFile.set_double ("SharpenMicro", "Uniformity", sharpenMicro.uniformity); + if (!pedited || pedited->sharpenMicro.enabled) { + keyFile.set_boolean ("SharpenMicro", "Enabled", sharpenMicro.enabled); + } -/* - // save colorBoost - if (!pedited || pedited->colorBoost.amount) keyFile.set_integer ("Color Boost", "Amount", colorBoost.amount); - if (!pedited || pedited->colorBoost.avoidclip) keyFile.set_boolean ("Color Boost", "AvoidColorClipping", colorBoost.avoidclip); - if (!pedited || pedited->colorBoost.enable_saturationlimiter) keyFile.set_boolean ("Color Boost", "SaturationLimiter", colorBoost.enable_saturationlimiter); - if (!pedited || pedited->colorBoost.saturationlimit) keyFile.set_double ("Color Boost", "SaturationLimit", colorBoost.saturationlimit); -*/ + if (!pedited || pedited->sharpenMicro.matrix) { + keyFile.set_boolean ("SharpenMicro", "Matrix", sharpenMicro.matrix); + } + + if (!pedited || pedited->sharpenMicro.amount) { + keyFile.set_double ("SharpenMicro", "Strength", sharpenMicro.amount); + } + + if (!pedited || pedited->sharpenMicro.uniformity) { + keyFile.set_double ("SharpenMicro", "Uniformity", sharpenMicro.uniformity); + } + + /* + // save colorBoost + if (!pedited || pedited->colorBoost.amount) keyFile.set_integer ("Color Boost", "Amount", colorBoost.amount); + if (!pedited || pedited->colorBoost.avoidclip) keyFile.set_boolean ("Color Boost", "AvoidColorClipping", colorBoost.avoidclip); + if (!pedited || pedited->colorBoost.enable_saturationlimiter) keyFile.set_boolean ("Color Boost", "SaturationLimiter", colorBoost.enable_saturationlimiter); + if (!pedited || pedited->colorBoost.saturationlimit) keyFile.set_double ("Color Boost", "SaturationLimit", colorBoost.saturationlimit); + */ // save wb - if (!pedited || pedited->wb.method) keyFile.set_string ("White Balance", "Setting", wb.method); - if (!pedited || pedited->wb.temperature) keyFile.set_integer ("White Balance", "Temperature", wb.temperature); - if (!pedited || pedited->wb.green) keyFile.set_double ("White Balance", "Green", wb.green); - if (!pedited || pedited->wb.equal) keyFile.set_double ("White Balance", "Equal", wb.equal); + if (!pedited || pedited->wb.method) { + keyFile.set_string ("White Balance", "Setting", wb.method); + } -/* - // save colorShift - if (!pedited || pedited->colorShift.a) keyFile.set_double ("Color Shift", "ChannelA", colorShift.a); - if (!pedited || pedited->colorShift.b) keyFile.set_double ("Color Shift", "ChannelB", colorShift.b); -*/ + if (!pedited || pedited->wb.temperature) { + keyFile.set_integer ("White Balance", "Temperature", wb.temperature); + } + + if (!pedited || pedited->wb.green) { + keyFile.set_double ("White Balance", "Green", wb.green); + } + + if (!pedited || pedited->wb.equal) { + keyFile.set_double ("White Balance", "Equal", wb.equal); + } + + /* + // save colorShift + if (!pedited || pedited->colorShift.a) keyFile.set_double ("Color Shift", "ChannelA", colorShift.a); + if (!pedited || pedited->colorShift.b) keyFile.set_double ("Color Shift", "ChannelB", colorShift.b); + */ // save colorappearance - if (!pedited || pedited->colorappearance.enabled) keyFile.set_boolean ("Color appearance", "Enabled", colorappearance.enabled); - if (!pedited || pedited->colorappearance.degree) keyFile.set_integer ("Color appearance", "Degree", colorappearance.degree); - if (!pedited || pedited->colorappearance.autodegree) keyFile.set_boolean ("Color appearance", "AutoDegree", colorappearance.autodegree); - if (!pedited || pedited->colorappearance.surround) keyFile.set_string ("Color appearance", "Surround", colorappearance.surround); - // if (!pedited || pedited->colorappearance.backgrd) keyFile.set_integer ("Color appearance", "Background", colorappearance.backgrd); - if (!pedited || pedited->colorappearance.adaplum) keyFile.set_double ("Color appearance", "AdaptLum", colorappearance.adaplum); - if (!pedited || pedited->colorappearance.badpixsl) keyFile.set_integer ("Color appearance", "Badpixsl", colorappearance.badpixsl); - if (!pedited || pedited->colorappearance.wbmodel) keyFile.set_string ("Color appearance", "Model", colorappearance.wbmodel); - if (!pedited || pedited->colorappearance.algo) keyFile.set_string ("Color appearance", "Algorithm", colorappearance.algo); + if (!pedited || pedited->colorappearance.enabled) { + keyFile.set_boolean ("Color appearance", "Enabled", colorappearance.enabled); + } - if (!pedited || pedited->colorappearance.jlight) keyFile.set_double ("Color appearance", "J-Light", colorappearance.jlight); - if (!pedited || pedited->colorappearance.qbright) keyFile.set_double ("Color appearance", "Q-Bright", colorappearance.qbright); - if (!pedited || pedited->colorappearance.chroma) keyFile.set_double ("Color appearance", "C-Chroma", colorappearance.chroma); - if (!pedited || pedited->colorappearance.schroma) keyFile.set_double ("Color appearance", "S-Chroma", colorappearance.schroma); - if (!pedited || pedited->colorappearance.mchroma) keyFile.set_double ("Color appearance", "M-Chroma", colorappearance.mchroma); - if (!pedited || pedited->colorappearance.contrast) keyFile.set_double ("Color appearance", "J-Contrast", colorappearance.contrast); - if (!pedited || pedited->colorappearance.qcontrast) keyFile.set_double ("Color appearance", "Q-Contrast", colorappearance.qcontrast); - if (!pedited || pedited->colorappearance.colorh) keyFile.set_double ("Color appearance", "H-Hue", colorappearance.colorh); - if (!pedited || pedited->colorappearance.rstprotection) keyFile.set_double ("Color appearance", "RSTProtection", colorappearance.rstprotection); + if (!pedited || pedited->colorappearance.degree) { + keyFile.set_integer ("Color appearance", "Degree", colorappearance.degree); + } + + if (!pedited || pedited->colorappearance.autodegree) { + keyFile.set_boolean ("Color appearance", "AutoDegree", colorappearance.autodegree); + } + + if (!pedited || pedited->colorappearance.surround) { + keyFile.set_string ("Color appearance", "Surround", colorappearance.surround); + } + +// if (!pedited || pedited->colorappearance.backgrd) keyFile.set_integer ("Color appearance", "Background", colorappearance.backgrd); + if (!pedited || pedited->colorappearance.adaplum) { + keyFile.set_double ("Color appearance", "AdaptLum", colorappearance.adaplum); + } + + if (!pedited || pedited->colorappearance.badpixsl) { + keyFile.set_integer ("Color appearance", "Badpixsl", colorappearance.badpixsl); + } + + if (!pedited || pedited->colorappearance.wbmodel) { + keyFile.set_string ("Color appearance", "Model", colorappearance.wbmodel); + } + + if (!pedited || pedited->colorappearance.algo) { + keyFile.set_string ("Color appearance", "Algorithm", colorappearance.algo); + } + + if (!pedited || pedited->colorappearance.jlight) { + keyFile.set_double ("Color appearance", "J-Light", colorappearance.jlight); + } + + if (!pedited || pedited->colorappearance.qbright) { + keyFile.set_double ("Color appearance", "Q-Bright", colorappearance.qbright); + } + + if (!pedited || pedited->colorappearance.chroma) { + keyFile.set_double ("Color appearance", "C-Chroma", colorappearance.chroma); + } + + if (!pedited || pedited->colorappearance.schroma) { + keyFile.set_double ("Color appearance", "S-Chroma", colorappearance.schroma); + } + + if (!pedited || pedited->colorappearance.mchroma) { + keyFile.set_double ("Color appearance", "M-Chroma", colorappearance.mchroma); + } + + if (!pedited || pedited->colorappearance.contrast) { + keyFile.set_double ("Color appearance", "J-Contrast", colorappearance.contrast); + } + + if (!pedited || pedited->colorappearance.qcontrast) { + keyFile.set_double ("Color appearance", "Q-Contrast", colorappearance.qcontrast); + } + + if (!pedited || pedited->colorappearance.colorh) { + keyFile.set_double ("Color appearance", "H-Hue", colorappearance.colorh); + } + + if (!pedited || pedited->colorappearance.rstprotection) { + keyFile.set_double ("Color appearance", "RSTProtection", colorappearance.rstprotection); + } + + if (!pedited || pedited->colorappearance.adapscen) { + keyFile.set_double ("Color appearance", "AdaptScene", colorappearance.adapscen); + } + + if (!pedited || pedited->colorappearance.autoadapscen) { + keyFile.set_boolean ("Color appearance", "AutoAdapscen", colorappearance.autoadapscen); + } + + if (!pedited || pedited->colorappearance.surrsource) { + keyFile.set_boolean ("Color appearance", "SurrSource", colorappearance.surrsource); + } + + if (!pedited || pedited->colorappearance.gamut) { + keyFile.set_boolean ("Color appearance", "Gamut", colorappearance.gamut); + } - if (!pedited || pedited->colorappearance.adapscen) keyFile.set_double ("Color appearance", "AdaptScene", colorappearance.adapscen); - if (!pedited || pedited->colorappearance.autoadapscen) keyFile.set_boolean ("Color appearance", "AutoAdapscen", colorappearance.autoadapscen); - if (!pedited || pedited->colorappearance.surrsource) keyFile.set_boolean ("Color appearance", "SurrSource", colorappearance.surrsource); - if (!pedited || pedited->colorappearance.gamut) keyFile.set_boolean ("Color appearance", "Gamut", colorappearance.gamut); // if (!pedited || pedited->colorappearance.badpix) keyFile.set_boolean ("Color appearance", "Badpix", colorappearance.badpix); - if (!pedited || pedited->colorappearance.datacie) keyFile.set_boolean ("Color appearance", "Datacie", colorappearance.datacie); - if (!pedited || pedited->colorappearance.tonecie) keyFile.set_boolean ("Color appearance", "Tonecie", colorappearance.tonecie); + if (!pedited || pedited->colorappearance.datacie) { + keyFile.set_boolean ("Color appearance", "Datacie", colorappearance.datacie); + } + + if (!pedited || pedited->colorappearance.tonecie) { + keyFile.set_boolean ("Color appearance", "Tonecie", colorappearance.tonecie); + } + // if (!pedited || pedited->colorappearance.sharpcie) keyFile.set_boolean ("Color appearance", "Sharpcie", colorappearance.sharpcie); if (!pedited || pedited->colorappearance.curveMode) { Glib::ustring method; + switch (colorappearance.curveMode) { case (ColorAppearanceParams::TC_MODE_LIGHT): method = "Lightness"; break; + case (ColorAppearanceParams::TC_MODE_BRIGHT): method = "Brightness"; break; } + keyFile.set_string ("Color appearance", "CurveMode", method); } + if (!pedited || pedited->colorappearance.curveMode2) { Glib::ustring method; + switch (colorappearance.curveMode2) { case (ColorAppearanceParams::TC_MODE_LIGHT): method = "Lightness"; break; + case (ColorAppearanceParams::TC_MODE_BRIGHT): method = "Brightness"; break; } + keyFile.set_string ("Color appearance", "CurveMode2", method); } + if (!pedited || pedited->colorappearance.curveMode3) { Glib::ustring method; + switch (colorappearance.curveMode3) { case (ColorAppearanceParams::TC_MODE_CHROMA): method = "Chroma"; break; + case (ColorAppearanceParams::TC_MODE_SATUR): method = "Saturation"; break; + case (ColorAppearanceParams::TC_MODE_COLORF): method = "Colorfullness"; break; - + } + keyFile.set_string ("Color appearance", "CurveMode3", method); } - + if (!pedited || pedited->colorappearance.curve) { Glib::ArrayHandle tcurve = colorappearance.curve; keyFile.set_double_list("Color appearance", "Curve", tcurve); } + if (!pedited || pedited->colorappearance.curve2) { Glib::ArrayHandle tcurve = colorappearance.curve2; keyFile.set_double_list("Color appearance", "Curve2", tcurve); } + if (!pedited || pedited->colorappearance.curve3) { Glib::ArrayHandle tcurve = colorappearance.curve3; keyFile.set_double_list("Color appearance", "Curve3", tcurve); } - + // save impulseDenoise - if (!pedited || pedited->impulseDenoise.enabled) keyFile.set_boolean ("Impulse Denoising", "Enabled", impulseDenoise.enabled); - if (!pedited || pedited->impulseDenoise.thresh) keyFile.set_integer ("Impulse Denoising", "Threshold", impulseDenoise.thresh); + if (!pedited || pedited->impulseDenoise.enabled) { + keyFile.set_boolean ("Impulse Denoising", "Enabled", impulseDenoise.enabled); + } + + if (!pedited || pedited->impulseDenoise.thresh) { + keyFile.set_integer ("Impulse Denoising", "Threshold", impulseDenoise.thresh); + } // save defringe - if (!pedited || pedited->defringe.enabled) keyFile.set_boolean ("Defringing", "Enabled", defringe.enabled); - if (!pedited || pedited->defringe.radius) keyFile.set_double ("Defringing", "Radius", defringe.radius); - if (!pedited || pedited->defringe.threshold) keyFile.set_integer ("Defringing", "Threshold", defringe.threshold); + if (!pedited || pedited->defringe.enabled) { + keyFile.set_boolean ("Defringing", "Enabled", defringe.enabled); + } + + if (!pedited || pedited->defringe.radius) { + keyFile.set_double ("Defringing", "Radius", defringe.radius); + } + + if (!pedited || pedited->defringe.threshold) { + keyFile.set_integer ("Defringing", "Threshold", defringe.threshold); + } + if (!pedited || pedited->defringe.huecurve) { Glib::ArrayHandle huecurve = defringe.huecurve; keyFile.set_double_list("Defringing", "HueCurve", huecurve); } // save dirpyrDenoise - if (!pedited || pedited->dirpyrDenoise.enabled) keyFile.set_boolean ("Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled); - if (!pedited || pedited->dirpyrDenoise.enhance) keyFile.set_boolean ("Directional Pyramid Denoising", "Enhance", dirpyrDenoise.enhance); - if (!pedited || pedited->dirpyrDenoise.median) keyFile.set_boolean ("Directional Pyramid Denoising", "Median", dirpyrDenoise.median); - if (!pedited || pedited->dirpyrDenoise.autochroma) keyFile.set_boolean ("Directional Pyramid Denoising", "Auto", dirpyrDenoise.autochroma); - // if (!pedited || pedited->dirpyrDenoise.perform) keyFile.set_boolean ("Directional Pyramid Denoising", "Perform", dirpyrDenoise.perform); - if (!pedited || pedited->dirpyrDenoise.luma) keyFile.set_double ("Directional Pyramid Denoising", "Luma", dirpyrDenoise.luma); - if (!pedited || pedited->dirpyrDenoise.Ldetail) keyFile.set_double ("Directional Pyramid Denoising", "Ldetail", dirpyrDenoise.Ldetail); - if (!pedited || pedited->dirpyrDenoise.chroma) keyFile.set_double ("Directional Pyramid Denoising", "Chroma", dirpyrDenoise.chroma); - if (!pedited || pedited->dirpyrDenoise.dmethod) keyFile.set_string ("Directional Pyramid Denoising", "Method", dirpyrDenoise.dmethod); - if (!pedited || pedited->dirpyrDenoise.Lmethod) keyFile.set_string ("Directional Pyramid Denoising", "LMethod", dirpyrDenoise.Lmethod); + if (!pedited || pedited->dirpyrDenoise.enabled) { + keyFile.set_boolean ("Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled); + } + + if (!pedited || pedited->dirpyrDenoise.enhance) { + keyFile.set_boolean ("Directional Pyramid Denoising", "Enhance", dirpyrDenoise.enhance); + } + + if (!pedited || pedited->dirpyrDenoise.median) { + keyFile.set_boolean ("Directional Pyramid Denoising", "Median", dirpyrDenoise.median); + } + + if (!pedited || pedited->dirpyrDenoise.autochroma) { + keyFile.set_boolean ("Directional Pyramid Denoising", "Auto", dirpyrDenoise.autochroma); + } + +// if (!pedited || pedited->dirpyrDenoise.perform) keyFile.set_boolean ("Directional Pyramid Denoising", "Perform", dirpyrDenoise.perform); + if (!pedited || pedited->dirpyrDenoise.luma) { + keyFile.set_double ("Directional Pyramid Denoising", "Luma", dirpyrDenoise.luma); + } + + if (!pedited || pedited->dirpyrDenoise.Ldetail) { + keyFile.set_double ("Directional Pyramid Denoising", "Ldetail", dirpyrDenoise.Ldetail); + } + + if (!pedited || pedited->dirpyrDenoise.chroma) { + keyFile.set_double ("Directional Pyramid Denoising", "Chroma", dirpyrDenoise.chroma); + } + + if (!pedited || pedited->dirpyrDenoise.dmethod) { + keyFile.set_string ("Directional Pyramid Denoising", "Method", dirpyrDenoise.dmethod); + } + + if (!pedited || pedited->dirpyrDenoise.Lmethod) { + keyFile.set_string ("Directional Pyramid Denoising", "LMethod", dirpyrDenoise.Lmethod); + } + // never save 'auto chroma preview mode' to pp3 - if (!pedited || pedited->dirpyrDenoise.Cmethod) { - if(dirpyrDenoise.Cmethod=="PRE") - dirpyrDenoise.Cmethod = "MAN"; - keyFile.set_string ("Directional Pyramid Denoising", "CMethod", dirpyrDenoise.Cmethod); + if (!pedited || pedited->dirpyrDenoise.Cmethod) { + if(dirpyrDenoise.Cmethod == "PRE") { + dirpyrDenoise.Cmethod = "MAN"; + } + + keyFile.set_string ("Directional Pyramid Denoising", "CMethod", dirpyrDenoise.Cmethod); } + if (!pedited || pedited->dirpyrDenoise.C2method) { - if(dirpyrDenoise.C2method=="PREV") - dirpyrDenoise.C2method = "MANU"; - keyFile.set_string ("Directional Pyramid Denoising", "C2Method", dirpyrDenoise.C2method); + if(dirpyrDenoise.C2method == "PREV") { + dirpyrDenoise.C2method = "MANU"; + } + + keyFile.set_string ("Directional Pyramid Denoising", "C2Method", dirpyrDenoise.C2method); } - if (!pedited || pedited->dirpyrDenoise.smethod) keyFile.set_string ("Directional Pyramid Denoising", "SMethod", dirpyrDenoise.smethod); - if (!pedited || pedited->dirpyrDenoise.medmethod) keyFile.set_string ("Directional Pyramid Denoising", "MedMethod", dirpyrDenoise.medmethod); - if (!pedited || pedited->dirpyrDenoise.rgbmethod) keyFile.set_string ("Directional Pyramid Denoising", "RGBMethod", dirpyrDenoise.rgbmethod); - if (!pedited || pedited->dirpyrDenoise.methodmed) keyFile.set_string ("Directional Pyramid Denoising", "MethodMed", dirpyrDenoise.methodmed); - if (!pedited || pedited->dirpyrDenoise.redchro) keyFile.set_double ("Directional Pyramid Denoising", "Redchro", dirpyrDenoise.redchro); - if (!pedited || pedited->dirpyrDenoise.bluechro)keyFile.set_double ("Directional Pyramid Denoising", "Bluechro", dirpyrDenoise.bluechro); - if (!pedited || pedited->dirpyrDenoise.gamma) keyFile.set_double ("Directional Pyramid Denoising", "Gamma", dirpyrDenoise.gamma); - if (!pedited || pedited->dirpyrDenoise.passes) keyFile.set_integer ("Directional Pyramid Denoising", "Passes", dirpyrDenoise.passes); + + if (!pedited || pedited->dirpyrDenoise.smethod) { + keyFile.set_string ("Directional Pyramid Denoising", "SMethod", dirpyrDenoise.smethod); + } + + if (!pedited || pedited->dirpyrDenoise.medmethod) { + keyFile.set_string ("Directional Pyramid Denoising", "MedMethod", dirpyrDenoise.medmethod); + } + + if (!pedited || pedited->dirpyrDenoise.rgbmethod) { + keyFile.set_string ("Directional Pyramid Denoising", "RGBMethod", dirpyrDenoise.rgbmethod); + } + + if (!pedited || pedited->dirpyrDenoise.methodmed) { + keyFile.set_string ("Directional Pyramid Denoising", "MethodMed", dirpyrDenoise.methodmed); + } + + if (!pedited || pedited->dirpyrDenoise.redchro) { + keyFile.set_double ("Directional Pyramid Denoising", "Redchro", dirpyrDenoise.redchro); + } + + if (!pedited || pedited->dirpyrDenoise.bluechro) { + keyFile.set_double ("Directional Pyramid Denoising", "Bluechro", dirpyrDenoise.bluechro); + } + + if (!pedited || pedited->dirpyrDenoise.gamma) { + keyFile.set_double ("Directional Pyramid Denoising", "Gamma", dirpyrDenoise.gamma); + } + + if (!pedited || pedited->dirpyrDenoise.passes) { + keyFile.set_integer ("Directional Pyramid Denoising", "Passes", dirpyrDenoise.passes); + } + if (!pedited || pedited->dirpyrDenoise.lcurve) { Glib::ArrayHandle lcurve = dirpyrDenoise.lcurve; keyFile.set_double_list("Directional Pyramid Denoising", "LCurve", lcurve); } + if (!pedited || pedited->dirpyrDenoise.cccurve) { Glib::ArrayHandle cccurve = dirpyrDenoise.cccurve; keyFile.set_double_list("Directional Pyramid Denoising", "CCCurve", cccurve); } //Save epd. - if (!pedited || pedited->epd.enabled) keyFile.set_boolean ("EPD", "Enabled", epd.enabled); - if (!pedited || pedited->epd.strength) keyFile.set_double ("EPD", "Strength", epd.strength); - if (!pedited || pedited->epd.gamma) keyFile.set_double ("EPD", "Gamma", epd.gamma); - if (!pedited || pedited->epd.edgeStopping) keyFile.set_double ("EPD", "EdgeStopping", epd.edgeStopping); - if (!pedited || pedited->epd.scale) keyFile.set_double ("EPD", "Scale", epd.scale); - if (!pedited || pedited->epd.reweightingIterates) keyFile.set_integer ("EPD", "ReweightingIterates", epd.reweightingIterates); + if (!pedited || pedited->epd.enabled) { + keyFile.set_boolean ("EPD", "Enabled", epd.enabled); + } -/* - // save lumaDenoise - if (!pedited || pedited->lumaDenoise.enabled) keyFile.set_boolean ("Luminance Denoising", "Enabled", lumaDenoise.enabled); - if (!pedited || pedited->lumaDenoise.radius) keyFile.set_double ("Luminance Denoising", "Radius", lumaDenoise.radius); - if (!pedited || pedited->lumaDenoise.edgetolerance) keyFile.set_integer ("Luminance Denoising", "EdgeTolerance", lumaDenoise.edgetolerance); -*/ + if (!pedited || pedited->epd.strength) { + keyFile.set_double ("EPD", "Strength", epd.strength); + } -/* - // save colorDenoise - //if (!pedited || pedited->colorDenoise.enabled) keyFile.set_boolean ("Chrominance Denoising", "Enabled", colorDenoise.enabled); - if (!pedited || pedited->colorDenoise.amount) keyFile.set_integer ("Chrominance Denoising", "Amount", colorDenoise.amount); -*/ + if (!pedited || pedited->epd.gamma) { + keyFile.set_double ("EPD", "Gamma", epd.gamma); + } + + if (!pedited || pedited->epd.edgeStopping) { + keyFile.set_double ("EPD", "EdgeStopping", epd.edgeStopping); + } + + if (!pedited || pedited->epd.scale) { + keyFile.set_double ("EPD", "Scale", epd.scale); + } + + if (!pedited || pedited->epd.reweightingIterates) { + keyFile.set_integer ("EPD", "ReweightingIterates", epd.reweightingIterates); + } + + /* + // save lumaDenoise + if (!pedited || pedited->lumaDenoise.enabled) keyFile.set_boolean ("Luminance Denoising", "Enabled", lumaDenoise.enabled); + if (!pedited || pedited->lumaDenoise.radius) keyFile.set_double ("Luminance Denoising", "Radius", lumaDenoise.radius); + if (!pedited || pedited->lumaDenoise.edgetolerance) keyFile.set_integer ("Luminance Denoising", "EdgeTolerance", lumaDenoise.edgetolerance); + */ + + /* + // save colorDenoise + //if (!pedited || pedited->colorDenoise.enabled) keyFile.set_boolean ("Chrominance Denoising", "Enabled", colorDenoise.enabled); + if (!pedited || pedited->colorDenoise.amount) keyFile.set_integer ("Chrominance Denoising", "Amount", colorDenoise.amount); + */ // save sh - if (!pedited || pedited->sh.enabled) keyFile.set_boolean ("Shadows & Highlights", "Enabled", sh.enabled); - if (!pedited || pedited->sh.hq) keyFile.set_boolean ("Shadows & Highlights", "HighQuality", sh.hq); - if (!pedited || pedited->sh.highlights) keyFile.set_integer ("Shadows & Highlights", "Highlights", sh.highlights); - if (!pedited || pedited->sh.htonalwidth) keyFile.set_integer ("Shadows & Highlights", "HighlightTonalWidth", sh.htonalwidth); - if (!pedited || pedited->sh.shadows) keyFile.set_integer ("Shadows & Highlights", "Shadows", sh.shadows); - if (!pedited || pedited->sh.stonalwidth) keyFile.set_integer ("Shadows & Highlights", "ShadowTonalWidth", sh.stonalwidth); - if (!pedited || pedited->sh.localcontrast) keyFile.set_integer ("Shadows & Highlights", "LocalContrast", sh.localcontrast); - if (!pedited || pedited->sh.radius) keyFile.set_integer ("Shadows & Highlights", "Radius", sh.radius); + if (!pedited || pedited->sh.enabled) { + keyFile.set_boolean ("Shadows & Highlights", "Enabled", sh.enabled); + } + + if (!pedited || pedited->sh.hq) { + keyFile.set_boolean ("Shadows & Highlights", "HighQuality", sh.hq); + } + + if (!pedited || pedited->sh.highlights) { + keyFile.set_integer ("Shadows & Highlights", "Highlights", sh.highlights); + } + + if (!pedited || pedited->sh.htonalwidth) { + keyFile.set_integer ("Shadows & Highlights", "HighlightTonalWidth", sh.htonalwidth); + } + + if (!pedited || pedited->sh.shadows) { + keyFile.set_integer ("Shadows & Highlights", "Shadows", sh.shadows); + } + + if (!pedited || pedited->sh.stonalwidth) { + keyFile.set_integer ("Shadows & Highlights", "ShadowTonalWidth", sh.stonalwidth); + } + + if (!pedited || pedited->sh.localcontrast) { + keyFile.set_integer ("Shadows & Highlights", "LocalContrast", sh.localcontrast); + } + + if (!pedited || pedited->sh.radius) { + keyFile.set_integer ("Shadows & Highlights", "Radius", sh.radius); + } // save crop - if (!pedited || pedited->crop.enabled) keyFile.set_boolean ("Crop", "Enabled", crop.enabled); - if (!pedited || pedited->crop.x) keyFile.set_integer ("Crop", "X", crop.x); - if (!pedited || pedited->crop.y) keyFile.set_integer ("Crop", "Y", crop.y); - if (!pedited || pedited->crop.w) keyFile.set_integer ("Crop", "W", crop.w); - if (!pedited || pedited->crop.h) keyFile.set_integer ("Crop", "H", crop.h); - if (!pedited || pedited->crop.fixratio) keyFile.set_boolean ("Crop", "FixedRatio", crop.fixratio); - if (!pedited || pedited->crop.ratio) keyFile.set_string ("Crop", "Ratio", crop.ratio); - if (!pedited || pedited->crop.orientation) keyFile.set_string ("Crop", "Orientation", crop.orientation); - if (!pedited || pedited->crop.guide) keyFile.set_string ("Crop", "Guide", crop.guide); - + if (!pedited || pedited->crop.enabled) { + keyFile.set_boolean ("Crop", "Enabled", crop.enabled); + } + + if (!pedited || pedited->crop.x) { + keyFile.set_integer ("Crop", "X", crop.x); + } + + if (!pedited || pedited->crop.y) { + keyFile.set_integer ("Crop", "Y", crop.y); + } + + if (!pedited || pedited->crop.w) { + keyFile.set_integer ("Crop", "W", crop.w); + } + + if (!pedited || pedited->crop.h) { + keyFile.set_integer ("Crop", "H", crop.h); + } + + if (!pedited || pedited->crop.fixratio) { + keyFile.set_boolean ("Crop", "FixedRatio", crop.fixratio); + } + + if (!pedited || pedited->crop.ratio) { + keyFile.set_string ("Crop", "Ratio", crop.ratio); + } + + if (!pedited || pedited->crop.orientation) { + keyFile.set_string ("Crop", "Orientation", crop.orientation); + } + + if (!pedited || pedited->crop.guide) { + keyFile.set_string ("Crop", "Guide", crop.guide); + } + // save coarse - if (!pedited || pedited->coarse.rotate) keyFile.set_integer ("Coarse Transformation", "Rotate", coarse.rotate); - if (!pedited || pedited->coarse.hflip) keyFile.set_boolean ("Coarse Transformation", "HorizontalFlip", coarse.hflip); - if (!pedited || pedited->coarse.vflip) keyFile.set_boolean ("Coarse Transformation", "VerticalFlip", coarse.vflip); - + if (!pedited || pedited->coarse.rotate) { + keyFile.set_integer ("Coarse Transformation", "Rotate", coarse.rotate); + } + + if (!pedited || pedited->coarse.hflip) { + keyFile.set_boolean ("Coarse Transformation", "HorizontalFlip", coarse.hflip); + } + + if (!pedited || pedited->coarse.vflip) { + keyFile.set_boolean ("Coarse Transformation", "VerticalFlip", coarse.vflip); + } + // save commonTrans - if (!pedited || pedited->commonTrans.autofill) keyFile.set_boolean ("Common Properties for Transformations", "AutoFill", commonTrans.autofill); + if (!pedited || pedited->commonTrans.autofill) { + keyFile.set_boolean ("Common Properties for Transformations", "AutoFill", commonTrans.autofill); + } // save rotate - if (!pedited || pedited->rotate.degree) keyFile.set_double ("Rotation", "Degree", rotate.degree); + if (!pedited || pedited->rotate.degree) { + keyFile.set_double ("Rotation", "Degree", rotate.degree); + } // save distortion - if (!pedited || pedited->distortion.amount) keyFile.set_double ("Distortion", "Amount", distortion.amount); + if (!pedited || pedited->distortion.amount) { + keyFile.set_double ("Distortion", "Amount", distortion.amount); + } // lens profile - if (!pedited || pedited->lensProf.lcpFile) keyFile.set_string ("LensProfile", "LCPFile", relativePathIfInside(fname, fnameAbsolute, lensProf.lcpFile)); - if (!pedited || pedited->lensProf.useDist) keyFile.set_boolean ("LensProfile", "UseDistortion", lensProf.useDist); - if (!pedited || pedited->lensProf.useVign) keyFile.set_boolean ("LensProfile", "UseVignette", lensProf.useVign); - if (!pedited || pedited->lensProf.useCA) keyFile.set_boolean ("LensProfile", "UseCA", lensProf.useCA); + if (!pedited || pedited->lensProf.lcpFile) { + keyFile.set_string ("LensProfile", "LCPFile", relativePathIfInside(fname, fnameAbsolute, lensProf.lcpFile)); + } + + if (!pedited || pedited->lensProf.useDist) { + keyFile.set_boolean ("LensProfile", "UseDistortion", lensProf.useDist); + } + + if (!pedited || pedited->lensProf.useVign) { + keyFile.set_boolean ("LensProfile", "UseVignette", lensProf.useVign); + } + + if (!pedited || pedited->lensProf.useCA) { + keyFile.set_boolean ("LensProfile", "UseCA", lensProf.useCA); + } // save perspective correction - if (!pedited || pedited->perspective.horizontal) keyFile.set_double ("Perspective", "Horizontal", perspective.horizontal); - if (!pedited || pedited->perspective.vertical) keyFile.set_double ("Perspective", "Vertical", perspective.vertical); + if (!pedited || pedited->perspective.horizontal) { + keyFile.set_double ("Perspective", "Horizontal", perspective.horizontal); + } + + if (!pedited || pedited->perspective.vertical) { + keyFile.set_double ("Perspective", "Vertical", perspective.vertical); + } // save gradient - if (!pedited || pedited->gradient.enabled) keyFile.set_boolean ("Gradient", "Enabled", gradient.enabled); - if (!pedited || pedited->gradient.degree) keyFile.set_double ("Gradient", "Degree", gradient.degree); - if (!pedited || pedited->gradient.feather) keyFile.set_integer ("Gradient", "Feather", gradient.feather); - if (!pedited || pedited->gradient.strength) keyFile.set_double ("Gradient", "Strength", gradient.strength); - if (!pedited || pedited->gradient.centerX) keyFile.set_integer ("Gradient", "CenterX", gradient.centerX); - if (!pedited || pedited->gradient.centerY) keyFile.set_integer ("Gradient", "CenterY", gradient.centerY); + if (!pedited || pedited->gradient.enabled) { + keyFile.set_boolean ("Gradient", "Enabled", gradient.enabled); + } + + if (!pedited || pedited->gradient.degree) { + keyFile.set_double ("Gradient", "Degree", gradient.degree); + } + + if (!pedited || pedited->gradient.feather) { + keyFile.set_integer ("Gradient", "Feather", gradient.feather); + } + + if (!pedited || pedited->gradient.strength) { + keyFile.set_double ("Gradient", "Strength", gradient.strength); + } + + if (!pedited || pedited->gradient.centerX) { + keyFile.set_integer ("Gradient", "CenterX", gradient.centerX); + } + + if (!pedited || pedited->gradient.centerY) { + keyFile.set_integer ("Gradient", "CenterY", gradient.centerY); + } // save post-crop vignette - if (!pedited || pedited->pcvignette.enabled) keyFile.set_boolean ("PCVignette", "Enabled", pcvignette.enabled); - if (!pedited || pedited->pcvignette.strength) keyFile.set_double ("PCVignette", "Strength", pcvignette.strength); - if (!pedited || pedited->pcvignette.feather) keyFile.set_integer ("PCVignette", "Feather", pcvignette.feather); - if (!pedited || pedited->pcvignette.roundness) keyFile.set_integer ("PCVignette", "Roundness", pcvignette.roundness); + if (!pedited || pedited->pcvignette.enabled) { + keyFile.set_boolean ("PCVignette", "Enabled", pcvignette.enabled); + } + + if (!pedited || pedited->pcvignette.strength) { + keyFile.set_double ("PCVignette", "Strength", pcvignette.strength); + } + + if (!pedited || pedited->pcvignette.feather) { + keyFile.set_integer ("PCVignette", "Feather", pcvignette.feather); + } + + if (!pedited || pedited->pcvignette.roundness) { + keyFile.set_integer ("PCVignette", "Roundness", pcvignette.roundness); + } // save C/A correction - if (!pedited || pedited->cacorrection.red) keyFile.set_double ("CACorrection", "Red", cacorrection.red); - if (!pedited || pedited->cacorrection.blue) keyFile.set_double ("CACorrection", "Blue", cacorrection.blue); + if (!pedited || pedited->cacorrection.red) { + keyFile.set_double ("CACorrection", "Red", cacorrection.red); + } + + if (!pedited || pedited->cacorrection.blue) { + keyFile.set_double ("CACorrection", "Blue", cacorrection.blue); + } // save vignetting correction - if (!pedited || pedited->vignetting.amount) keyFile.set_integer ("Vignetting Correction", "Amount", vignetting.amount); - if (!pedited || pedited->vignetting.radius) keyFile.set_integer ("Vignetting Correction", "Radius", vignetting.radius); - if (!pedited || pedited->vignetting.strength) keyFile.set_integer ("Vignetting Correction", "Strength", vignetting.strength); - if (!pedited || pedited->vignetting.centerX) keyFile.set_integer ("Vignetting Correction", "CenterX", vignetting.centerX); - if (!pedited || pedited->vignetting.centerY) keyFile.set_integer ("Vignetting Correction", "CenterY", vignetting.centerY); + if (!pedited || pedited->vignetting.amount) { + keyFile.set_integer ("Vignetting Correction", "Amount", vignetting.amount); + } + + if (!pedited || pedited->vignetting.radius) { + keyFile.set_integer ("Vignetting Correction", "Radius", vignetting.radius); + } + + if (!pedited || pedited->vignetting.strength) { + keyFile.set_integer ("Vignetting Correction", "Strength", vignetting.strength); + } + + if (!pedited || pedited->vignetting.centerX) { + keyFile.set_integer ("Vignetting Correction", "CenterX", vignetting.centerX); + } + + if (!pedited || pedited->vignetting.centerY) { + keyFile.set_integer ("Vignetting Correction", "CenterY", vignetting.centerY); + } - if (!pedited || pedited->resize.enabled) keyFile.set_boolean ("Resize", "Enabled",resize.enabled); - if (!pedited || pedited->resize.scale) keyFile.set_double ("Resize", "Scale", resize.scale); - if (!pedited || pedited->resize.appliesTo) keyFile.set_string ("Resize", "AppliesTo", resize.appliesTo); - if (!pedited || pedited->resize.method) keyFile.set_string ("Resize", "Method", resize.method); - if (!pedited || pedited->resize.dataspec) keyFile.set_integer ("Resize", "DataSpecified", resize.dataspec); - if (!pedited || pedited->resize.width) keyFile.set_integer ("Resize", "Width", resize.width); - if (!pedited || pedited->resize.height) keyFile.set_integer ("Resize", "Height", resize.height); + if (!pedited || pedited->resize.enabled) { + keyFile.set_boolean ("Resize", "Enabled", resize.enabled); + } + + if (!pedited || pedited->resize.scale) { + keyFile.set_double ("Resize", "Scale", resize.scale); + } + + if (!pedited || pedited->resize.appliesTo) { + keyFile.set_string ("Resize", "AppliesTo", resize.appliesTo); + } + + if (!pedited || pedited->resize.method) { + keyFile.set_string ("Resize", "Method", resize.method); + } + + if (!pedited || pedited->resize.dataspec) { + keyFile.set_integer ("Resize", "DataSpecified", resize.dataspec); + } + + if (!pedited || pedited->resize.width) { + keyFile.set_integer ("Resize", "Width", resize.width); + } + + if (!pedited || pedited->resize.height) { + keyFile.set_integer ("Resize", "Height", resize.height); + } + + if (!pedited || pedited->prsharpening.enabled) { + keyFile.set_boolean ("PostResizeSharpening", "Enabled", prsharpening.enabled); + } + + if (!pedited || pedited->prsharpening.method) { + keyFile.set_string ("PostResizeSharpening", "Method", prsharpening.method); + } + + if (!pedited || pedited->prsharpening.radius) { + keyFile.set_double ("PostResizeSharpening", "Radius", prsharpening.radius); + } + + if (!pedited || pedited->prsharpening.amount) { + keyFile.set_integer ("PostResizeSharpening", "Amount", prsharpening.amount); + } - if (!pedited || pedited->prsharpening.enabled) keyFile.set_boolean ("PostResizeSharpening", "Enabled", prsharpening.enabled); - if (!pedited || pedited->prsharpening.method) keyFile.set_string ("PostResizeSharpening", "Method", prsharpening.method); - if (!pedited || pedited->prsharpening.radius) keyFile.set_double ("PostResizeSharpening", "Radius", prsharpening.radius); - if (!pedited || pedited->prsharpening.amount) keyFile.set_integer ("PostResizeSharpening", "Amount", prsharpening.amount); if (!pedited || pedited->prsharpening.threshold) { Glib::ArrayHandle thresh (prsharpening.threshold.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("PostResizeSharpening", "Threshold", thresh); } - if (!pedited || pedited->prsharpening.edgesonly) keyFile.set_boolean ("PostResizeSharpening", "OnlyEdges", prsharpening.edgesonly); - if (!pedited || pedited->prsharpening.edges_radius) keyFile.set_double ("PostResizeSharpening", "EdgedetectionRadius", prsharpening.edges_radius); - if (!pedited || pedited->prsharpening.edges_tolerance) keyFile.set_integer ("PostResizeSharpening", "EdgeTolerance", prsharpening.edges_tolerance); - if (!pedited || pedited->prsharpening.halocontrol) keyFile.set_boolean ("PostResizeSharpening", "HalocontrolEnabled", prsharpening.halocontrol); - if (!pedited || pedited->prsharpening.halocontrol_amount) keyFile.set_integer ("PostResizeSharpening", "HalocontrolAmount", prsharpening.halocontrol_amount); - if (!pedited || pedited->prsharpening.deconvradius) keyFile.set_double ("PostResizeSharpening", "DeconvRadius", prsharpening.deconvradius); - if (!pedited || pedited->prsharpening.deconvamount) keyFile.set_integer ("PostResizeSharpening", "DeconvAmount", prsharpening.deconvamount); - if (!pedited || pedited->prsharpening.deconvdamping) keyFile.set_integer ("PostResizeSharpening", "DeconvDamping", prsharpening.deconvdamping); - if (!pedited || pedited->prsharpening.deconviter) keyFile.set_integer ("PostResizeSharpening", "DeconvIterations", prsharpening.deconviter); + + if (!pedited || pedited->prsharpening.edgesonly) { + keyFile.set_boolean ("PostResizeSharpening", "OnlyEdges", prsharpening.edgesonly); + } + + if (!pedited || pedited->prsharpening.edges_radius) { + keyFile.set_double ("PostResizeSharpening", "EdgedetectionRadius", prsharpening.edges_radius); + } + + if (!pedited || pedited->prsharpening.edges_tolerance) { + keyFile.set_integer ("PostResizeSharpening", "EdgeTolerance", prsharpening.edges_tolerance); + } + + if (!pedited || pedited->prsharpening.halocontrol) { + keyFile.set_boolean ("PostResizeSharpening", "HalocontrolEnabled", prsharpening.halocontrol); + } + + if (!pedited || pedited->prsharpening.halocontrol_amount) { + keyFile.set_integer ("PostResizeSharpening", "HalocontrolAmount", prsharpening.halocontrol_amount); + } + + if (!pedited || pedited->prsharpening.deconvradius) { + keyFile.set_double ("PostResizeSharpening", "DeconvRadius", prsharpening.deconvradius); + } + + if (!pedited || pedited->prsharpening.deconvamount) { + keyFile.set_integer ("PostResizeSharpening", "DeconvAmount", prsharpening.deconvamount); + } + + if (!pedited || pedited->prsharpening.deconvdamping) { + keyFile.set_integer ("PostResizeSharpening", "DeconvDamping", prsharpening.deconvdamping); + } + + if (!pedited || pedited->prsharpening.deconviter) { + keyFile.set_integer ("PostResizeSharpening", "DeconvIterations", prsharpening.deconviter); + } // save color management settings - if (!pedited || pedited->icm.input) keyFile.set_string ("Color Management", "InputProfile", relativePathIfInside(fname, fnameAbsolute, icm.input)); - if (!pedited || pedited->icm.toneCurve) keyFile.set_boolean ("Color Management", "ToneCurve", icm.toneCurve); - if (!pedited || pedited->icm.applyLookTable) keyFile.set_boolean ("Color Management", "ApplyLookTable", icm.applyLookTable); - if (!pedited || pedited->icm.applyBaselineExposureOffset) keyFile.set_boolean ("Color Management", "ApplyBaselineExposureOffset", icm.applyBaselineExposureOffset); - if (!pedited || pedited->icm.applyHueSatMap) keyFile.set_boolean ("Color Management", "ApplyHueSatMap", icm.applyHueSatMap); - if (!pedited || pedited->icm.blendCMSMatrix) keyFile.set_boolean ("Color Management", "BlendCMSMatrix", icm.blendCMSMatrix); - if (!pedited || pedited->icm.dcpIlluminant) keyFile.set_integer ("Color Management", "DCPIlluminant", icm.dcpIlluminant); - if (!pedited || pedited->icm.working) keyFile.set_string ("Color Management", "WorkingProfile", icm.working); - if (!pedited || pedited->icm.output) keyFile.set_string ("Color Management", "OutputProfile", icm.output); - if (!pedited || pedited->icm.gamma) keyFile.set_string ("Color Management", "Gammafree", icm.gamma); - if (!pedited || pedited->icm.freegamma) keyFile.set_boolean ("Color Management", "Freegamma", icm.freegamma); - if (!pedited || pedited->icm.gampos) keyFile.set_double ("Color Management", "GammaValue", icm.gampos); - if (!pedited || pedited->icm.slpos) keyFile.set_double ("Color Management", "GammaSlope", icm.slpos); + if (!pedited || pedited->icm.input) { + keyFile.set_string ("Color Management", "InputProfile", relativePathIfInside(fname, fnameAbsolute, icm.input)); + } + + if (!pedited || pedited->icm.toneCurve) { + keyFile.set_boolean ("Color Management", "ToneCurve", icm.toneCurve); + } + + if (!pedited || pedited->icm.applyLookTable) { + keyFile.set_boolean ("Color Management", "ApplyLookTable", icm.applyLookTable); + } + + if (!pedited || pedited->icm.applyBaselineExposureOffset) { + keyFile.set_boolean ("Color Management", "ApplyBaselineExposureOffset", icm.applyBaselineExposureOffset); + } + + if (!pedited || pedited->icm.applyHueSatMap) { + keyFile.set_boolean ("Color Management", "ApplyHueSatMap", icm.applyHueSatMap); + } + + if (!pedited || pedited->icm.blendCMSMatrix) { + keyFile.set_boolean ("Color Management", "BlendCMSMatrix", icm.blendCMSMatrix); + } + + if (!pedited || pedited->icm.dcpIlluminant) { + keyFile.set_integer ("Color Management", "DCPIlluminant", icm.dcpIlluminant); + } + + if (!pedited || pedited->icm.working) { + keyFile.set_string ("Color Management", "WorkingProfile", icm.working); + } + + if (!pedited || pedited->icm.output) { + keyFile.set_string ("Color Management", "OutputProfile", icm.output); + } + + if (!pedited || pedited->icm.gamma) { + keyFile.set_string ("Color Management", "Gammafree", icm.gamma); + } + + if (!pedited || pedited->icm.freegamma) { + keyFile.set_boolean ("Color Management", "Freegamma", icm.freegamma); + } + + if (!pedited || pedited->icm.gampos) { + keyFile.set_double ("Color Management", "GammaValue", icm.gampos); + } + + if (!pedited || pedited->icm.slpos) { + keyFile.set_double ("Color Management", "GammaSlope", icm.slpos); + } // save wavelet parameters - if (!pedited || pedited->wavelet.enabled) keyFile.set_boolean ("Wavelet", "Enabled", wavelet.enabled); - if (!pedited || pedited->wavelet.strength) keyFile.set_integer ("Wavelet", "Strength", wavelet.strength); - if (!pedited || pedited->wavelet.balance) keyFile.set_integer ("Wavelet", "Balance", wavelet.balance); - if (!pedited || pedited->wavelet.iter) keyFile.set_integer ("Wavelet", "Iter", wavelet.iter); - if (!pedited || pedited->wavelet.thres) keyFile.set_integer ("Wavelet", "MaxLev", wavelet.thres); - if (!pedited || pedited->wavelet.Tilesmethod) keyFile.set_string ("Wavelet", "TilesMethod", wavelet.Tilesmethod); - if (!pedited || pedited->wavelet.daubcoeffmethod) keyFile.set_string ("Wavelet", "DaubMethod", wavelet.daubcoeffmethod); - if (!pedited || pedited->wavelet.CLmethod) keyFile.set_string ("Wavelet", "ChoiceLevMethod", wavelet.CLmethod); - if (!pedited || pedited->wavelet.Backmethod) keyFile.set_string ("Wavelet", "BackMethod", wavelet.Backmethod); - if (!pedited || pedited->wavelet.Lmethod) keyFile.set_string ("Wavelet", "LevMethod", wavelet.Lmethod); - if (!pedited || pedited->wavelet.Dirmethod) keyFile.set_string ("Wavelet", "DirMethod", wavelet.Dirmethod); - if (!pedited || pedited->wavelet.greenhigh) keyFile.set_integer ("Wavelet", "CBgreenhigh", wavelet.greenhigh); - if (!pedited || pedited->wavelet.greenmed) keyFile.set_integer ("Wavelet", "CBgreenmed", wavelet.greenmed); - if (!pedited || pedited->wavelet.greenlow) keyFile.set_integer ("Wavelet", "CBgreenlow", wavelet.greenlow); - if (!pedited || pedited->wavelet.bluehigh) keyFile.set_integer ("Wavelet", "CBbluehigh", wavelet.bluehigh); - if (!pedited || pedited->wavelet.bluemed) keyFile.set_integer ("Wavelet", "CBbluemed", wavelet.bluemed); - if (!pedited || pedited->wavelet.bluelow) keyFile.set_integer ("Wavelet", "CBbluelow", wavelet.bluelow); - if (!pedited || pedited->wavelet.expcontrast) keyFile.set_boolean ("Wavelet", "Expcontrast", wavelet.expcontrast); - if (!pedited || pedited->wavelet.expchroma) keyFile.set_boolean ("Wavelet", "Expchroma", wavelet.expchroma); - if (!pedited || pedited->wavelet.expedge) keyFile.set_boolean ("Wavelet", "Expedge", wavelet.expedge); - if (!pedited || pedited->wavelet.expresid) keyFile.set_boolean ("Wavelet", "Expresid", wavelet.expresid); - if (!pedited || pedited->wavelet.expfinal) keyFile.set_boolean ("Wavelet", "Expfinal", wavelet.expfinal); - if (!pedited || pedited->wavelet.exptoning) keyFile.set_boolean ("Wavelet", "Exptoning", wavelet.exptoning); - if (!pedited || pedited->wavelet.expnoise) keyFile.set_boolean ("Wavelet", "Expnoise", wavelet.expnoise); - - for(int i = 0; i < 9; i++) - { - std::stringstream ss; - ss << "Contrast" << (i+1); - if (!pedited || pedited->wavelet.c[i]) keyFile.set_integer("Wavelet", ss.str(), wavelet.c[i]); + if (!pedited || pedited->wavelet.enabled) { + keyFile.set_boolean ("Wavelet", "Enabled", wavelet.enabled); } - for(int i = 0; i < 9; i++) - { - std::stringstream ss; - ss << "Chroma" << (i+1); - if (!pedited || pedited->wavelet.ch[i]) keyFile.set_integer("Wavelet", ss.str(), wavelet.ch[i]); + + if (!pedited || pedited->wavelet.strength) { + keyFile.set_integer ("Wavelet", "Strength", wavelet.strength); } - - if (!pedited || pedited->wavelet.sup) keyFile.set_integer ("Wavelet", "ContExtra", wavelet.sup); - if (!pedited || pedited->wavelet.HSmethod) keyFile.set_string ("Wavelet", "HSMethod", wavelet.HSmethod); + + if (!pedited || pedited->wavelet.balance) { + keyFile.set_integer ("Wavelet", "Balance", wavelet.balance); + } + + if (!pedited || pedited->wavelet.iter) { + keyFile.set_integer ("Wavelet", "Iter", wavelet.iter); + } + + if (!pedited || pedited->wavelet.thres) { + keyFile.set_integer ("Wavelet", "MaxLev", wavelet.thres); + } + + if (!pedited || pedited->wavelet.Tilesmethod) { + keyFile.set_string ("Wavelet", "TilesMethod", wavelet.Tilesmethod); + } + + if (!pedited || pedited->wavelet.daubcoeffmethod) { + keyFile.set_string ("Wavelet", "DaubMethod", wavelet.daubcoeffmethod); + } + + if (!pedited || pedited->wavelet.CLmethod) { + keyFile.set_string ("Wavelet", "ChoiceLevMethod", wavelet.CLmethod); + } + + if (!pedited || pedited->wavelet.Backmethod) { + keyFile.set_string ("Wavelet", "BackMethod", wavelet.Backmethod); + } + + if (!pedited || pedited->wavelet.Lmethod) { + keyFile.set_string ("Wavelet", "LevMethod", wavelet.Lmethod); + } + + if (!pedited || pedited->wavelet.Dirmethod) { + keyFile.set_string ("Wavelet", "DirMethod", wavelet.Dirmethod); + } + + if (!pedited || pedited->wavelet.greenhigh) { + keyFile.set_integer ("Wavelet", "CBgreenhigh", wavelet.greenhigh); + } + + if (!pedited || pedited->wavelet.greenmed) { + keyFile.set_integer ("Wavelet", "CBgreenmed", wavelet.greenmed); + } + + if (!pedited || pedited->wavelet.greenlow) { + keyFile.set_integer ("Wavelet", "CBgreenlow", wavelet.greenlow); + } + + if (!pedited || pedited->wavelet.bluehigh) { + keyFile.set_integer ("Wavelet", "CBbluehigh", wavelet.bluehigh); + } + + if (!pedited || pedited->wavelet.bluemed) { + keyFile.set_integer ("Wavelet", "CBbluemed", wavelet.bluemed); + } + + if (!pedited || pedited->wavelet.bluelow) { + keyFile.set_integer ("Wavelet", "CBbluelow", wavelet.bluelow); + } + + if (!pedited || pedited->wavelet.expcontrast) { + keyFile.set_boolean ("Wavelet", "Expcontrast", wavelet.expcontrast); + } + + if (!pedited || pedited->wavelet.expchroma) { + keyFile.set_boolean ("Wavelet", "Expchroma", wavelet.expchroma); + } + + if (!pedited || pedited->wavelet.expedge) { + keyFile.set_boolean ("Wavelet", "Expedge", wavelet.expedge); + } + + if (!pedited || pedited->wavelet.expresid) { + keyFile.set_boolean ("Wavelet", "Expresid", wavelet.expresid); + } + + if (!pedited || pedited->wavelet.expfinal) { + keyFile.set_boolean ("Wavelet", "Expfinal", wavelet.expfinal); + } + + if (!pedited || pedited->wavelet.exptoning) { + keyFile.set_boolean ("Wavelet", "Exptoning", wavelet.exptoning); + } + + if (!pedited || pedited->wavelet.expnoise) { + keyFile.set_boolean ("Wavelet", "Expnoise", wavelet.expnoise); + } + + for(int i = 0; i < 9; i++) { + std::stringstream ss; + ss << "Contrast" << (i + 1); + + if (!pedited || pedited->wavelet.c[i]) { + keyFile.set_integer("Wavelet", ss.str(), wavelet.c[i]); + } + } + + for(int i = 0; i < 9; i++) { + std::stringstream ss; + ss << "Chroma" << (i + 1); + + if (!pedited || pedited->wavelet.ch[i]) { + keyFile.set_integer("Wavelet", ss.str(), wavelet.ch[i]); + } + } + + if (!pedited || pedited->wavelet.sup) { + keyFile.set_integer ("Wavelet", "ContExtra", wavelet.sup); + } + + if (!pedited || pedited->wavelet.HSmethod) { + keyFile.set_string ("Wavelet", "HSMethod", wavelet.HSmethod); + } + if (!pedited || pedited->wavelet.hllev) { Glib::ArrayHandle thresh (wavelet.hllev.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "HLRange", thresh); } + if (!pedited || pedited->wavelet.bllev) { Glib::ArrayHandle thresh (wavelet.bllev.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "SHRange", thresh); } + if (!pedited || pedited->wavelet.edgcont) { Glib::ArrayHandle thresh (wavelet.edgcont.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "Edgcont", thresh); } + if (!pedited || pedited->wavelet.level0noise) { Glib::ArrayHandle thresh (wavelet.level0noise.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_double_list("Wavelet", "Level0noise", thresh); } + if (!pedited || pedited->wavelet.level1noise) { Glib::ArrayHandle thresh (wavelet.level1noise.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_double_list("Wavelet", "Level1noise", thresh); } + if (!pedited || pedited->wavelet.level2noise) { Glib::ArrayHandle thresh (wavelet.level2noise.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_double_list("Wavelet", "Level2noise", thresh); } + if (!pedited || pedited->wavelet.level3noise) { Glib::ArrayHandle thresh (wavelet.level3noise.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_double_list("Wavelet", "Level3noise", thresh); } - - if (!pedited || pedited->wavelet.threshold) keyFile.set_integer ("Wavelet", "ThresholdHighlight", wavelet.threshold); - if (!pedited || pedited->wavelet.threshold2) keyFile.set_integer ("Wavelet", "ThresholdShadow", wavelet.threshold2); - if (!pedited || pedited->wavelet.edgedetect) keyFile.set_integer ("Wavelet", "Edgedetect", wavelet.edgedetect); - if (!pedited || pedited->wavelet.edgedetectthr) keyFile.set_integer ("Wavelet", "Edgedetectthr", wavelet.edgedetectthr); - if (!pedited || pedited->wavelet.edgedetectthr2) keyFile.set_integer ("Wavelet", "EdgedetectthrHi", wavelet.edgedetectthr2); - if (!pedited || pedited->wavelet.edgesensi) keyFile.set_integer ("Wavelet", "Edgesensi", wavelet.edgesensi); - if (!pedited || pedited->wavelet.edgeampli) keyFile.set_integer ("Wavelet", "Edgeampli", wavelet.edgeampli); - if (!pedited || pedited->wavelet.chroma) keyFile.set_integer ("Wavelet", "ThresholdChroma", wavelet.chroma); - if (!pedited || pedited->wavelet.CHmethod) keyFile.set_string ("Wavelet", "CHromaMethod", wavelet.CHmethod); - if (!pedited || pedited->wavelet.Medgreinf) keyFile.set_string ("Wavelet", "Medgreinf", wavelet.Medgreinf); - if (!pedited || pedited->wavelet.CHSLmethod) keyFile.set_string ("Wavelet", "CHSLromaMethod", wavelet.CHSLmethod); - if (!pedited || pedited->wavelet.EDmethod) keyFile.set_string ("Wavelet", "EDMethod", wavelet.EDmethod); - if (!pedited || pedited->wavelet.NPmethod) keyFile.set_string ("Wavelet", "NPMethod", wavelet.NPmethod); - if (!pedited || pedited->wavelet.BAmethod) keyFile.set_string ("Wavelet", "BAMethod", wavelet.BAmethod); - if (!pedited || pedited->wavelet.TMmethod) keyFile.set_string ("Wavelet", "TMMethod", wavelet.TMmethod); - if (!pedited || pedited->wavelet.chro) keyFile.set_integer ("Wavelet", "ChromaLink", wavelet.chro); + + if (!pedited || pedited->wavelet.threshold) { + keyFile.set_integer ("Wavelet", "ThresholdHighlight", wavelet.threshold); + } + + if (!pedited || pedited->wavelet.threshold2) { + keyFile.set_integer ("Wavelet", "ThresholdShadow", wavelet.threshold2); + } + + if (!pedited || pedited->wavelet.edgedetect) { + keyFile.set_integer ("Wavelet", "Edgedetect", wavelet.edgedetect); + } + + if (!pedited || pedited->wavelet.edgedetectthr) { + keyFile.set_integer ("Wavelet", "Edgedetectthr", wavelet.edgedetectthr); + } + + if (!pedited || pedited->wavelet.edgedetectthr2) { + keyFile.set_integer ("Wavelet", "EdgedetectthrHi", wavelet.edgedetectthr2); + } + + if (!pedited || pedited->wavelet.edgesensi) { + keyFile.set_integer ("Wavelet", "Edgesensi", wavelet.edgesensi); + } + + if (!pedited || pedited->wavelet.edgeampli) { + keyFile.set_integer ("Wavelet", "Edgeampli", wavelet.edgeampli); + } + + if (!pedited || pedited->wavelet.chroma) { + keyFile.set_integer ("Wavelet", "ThresholdChroma", wavelet.chroma); + } + + if (!pedited || pedited->wavelet.CHmethod) { + keyFile.set_string ("Wavelet", "CHromaMethod", wavelet.CHmethod); + } + + if (!pedited || pedited->wavelet.Medgreinf) { + keyFile.set_string ("Wavelet", "Medgreinf", wavelet.Medgreinf); + } + + if (!pedited || pedited->wavelet.CHSLmethod) { + keyFile.set_string ("Wavelet", "CHSLromaMethod", wavelet.CHSLmethod); + } + + if (!pedited || pedited->wavelet.EDmethod) { + keyFile.set_string ("Wavelet", "EDMethod", wavelet.EDmethod); + } + + if (!pedited || pedited->wavelet.NPmethod) { + keyFile.set_string ("Wavelet", "NPMethod", wavelet.NPmethod); + } + + if (!pedited || pedited->wavelet.BAmethod) { + keyFile.set_string ("Wavelet", "BAMethod", wavelet.BAmethod); + } + + if (!pedited || pedited->wavelet.TMmethod) { + keyFile.set_string ("Wavelet", "TMMethod", wavelet.TMmethod); + } + + if (!pedited || pedited->wavelet.chro) { + keyFile.set_integer ("Wavelet", "ChromaLink", wavelet.chro); + } + if (!pedited || pedited->wavelet.ccwcurve) { Glib::ArrayHandle ccwcurve = wavelet.ccwcurve; keyFile.set_double_list("Wavelet", "ContrastCurve", ccwcurve); } + if (!pedited || pedited->wavelet.pastlev) { Glib::ArrayHandle thresh (wavelet.pastlev.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "Pastlev", thresh); } + if (!pedited || pedited->wavelet.satlev) { Glib::ArrayHandle thresh (wavelet.satlev.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "Satlev", thresh); } - + if (!pedited || pedited->wavelet.opacityCurveRG) { Glib::ArrayHandle curve = wavelet.opacityCurveRG; keyFile.set_double_list("Wavelet", "OpacityCurveRG", curve); } + if (!pedited || pedited->wavelet.opacityCurveBY) { Glib::ArrayHandle curve = wavelet.opacityCurveBY; keyFile.set_double_list("Wavelet", "OpacityCurveBY", curve); } + if (!pedited || pedited->wavelet.opacityCurveW) { Glib::ArrayHandle curve = wavelet.opacityCurveW; keyFile.set_double_list("Wavelet", "OpacityCurveW", curve); } + if (!pedited || pedited->wavelet.opacityCurveWL) { Glib::ArrayHandle curve = wavelet.opacityCurveWL; keyFile.set_double_list("Wavelet", "OpacityCurveWL", curve); } - + if (!pedited || pedited->wavelet.hhcurve) { Glib::ArrayHandle curve = wavelet.hhcurve; keyFile.set_double_list("Wavelet", "HHcurve", curve); } + if (!pedited || pedited->wavelet.Chcurve) { Glib::ArrayHandle curve = wavelet.Chcurve; keyFile.set_double_list("Wavelet", "CHcurve", curve); } + if (!pedited || pedited->wavelet.wavclCurve) { Glib::ArrayHandle wavclCurve = wavelet.wavclCurve; keyFile.set_double_list("Wavelet", "WavclCurve", wavclCurve); } - - - if (!pedited || pedited->wavelet.median) keyFile.set_boolean ("Wavelet", "Median", wavelet.median); - if (!pedited || pedited->wavelet.medianlev) keyFile.set_boolean ("Wavelet", "Medianlev", wavelet.medianlev); - if (!pedited || pedited->wavelet.linkedg) keyFile.set_boolean ("Wavelet", "Linkedg", wavelet.linkedg); - if (!pedited || pedited->wavelet.cbenab) keyFile.set_boolean ("Wavelet", "CBenab", wavelet.cbenab); - if (!pedited || pedited->wavelet.lipst) keyFile.set_boolean ("Wavelet", "Lipst", wavelet.lipst); - // if (!pedited || pedited->wavelet.edgreinf) keyFile.set_boolean ("Wavelet", "Edgreinf", wavelet.edgreinf); - if (!pedited || pedited->wavelet.skinprotect) keyFile.set_double ("Wavelet", "Skinprotect", wavelet.skinprotect); - if (!pedited || pedited->wavelet.hueskin) { + + + if (!pedited || pedited->wavelet.median) { + keyFile.set_boolean ("Wavelet", "Median", wavelet.median); + } + + if (!pedited || pedited->wavelet.medianlev) { + keyFile.set_boolean ("Wavelet", "Medianlev", wavelet.medianlev); + } + + if (!pedited || pedited->wavelet.linkedg) { + keyFile.set_boolean ("Wavelet", "Linkedg", wavelet.linkedg); + } + + if (!pedited || pedited->wavelet.cbenab) { + keyFile.set_boolean ("Wavelet", "CBenab", wavelet.cbenab); + } + + if (!pedited || pedited->wavelet.lipst) { + keyFile.set_boolean ("Wavelet", "Lipst", wavelet.lipst); + } + +// if (!pedited || pedited->wavelet.edgreinf) keyFile.set_boolean ("Wavelet", "Edgreinf", wavelet.edgreinf); + if (!pedited || pedited->wavelet.skinprotect) { + keyFile.set_double ("Wavelet", "Skinprotect", wavelet.skinprotect); + } + + if (!pedited || pedited->wavelet.hueskin) { Glib::ArrayHandle thresh (wavelet.hueskin.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "Hueskin", thresh); } - - if (!pedited || pedited->wavelet.edgrad) keyFile.set_integer ("Wavelet", "Edgrad", wavelet.edgrad); - if (!pedited || pedited->wavelet.edgval) keyFile.set_integer ("Wavelet", "Edgval", wavelet.edgval); - if (!pedited || pedited->wavelet.edgthresh) keyFile.set_integer ("Wavelet", "ThrEdg", wavelet.edgthresh); - // if (!pedited || pedited->wavelet.strength) keyFile.set_integer ("Wavelet", "Strength", wavelet.strength); - // if (!pedited || pedited->wavelet.balance) keyFile.set_integer ("Wavelet", "Balance", wavelet.balance); - if (!pedited || pedited->wavelet.avoid) keyFile.set_boolean ("Wavelet", "AvoidColorShift", wavelet.avoid); - if (!pedited || pedited->wavelet.tmr) keyFile.set_boolean ("Wavelet", "TMr", wavelet.tmr); - if (!pedited || pedited->wavelet.rescon) keyFile.set_integer ("Wavelet", "ResidualcontShadow", wavelet.rescon); - if (!pedited || pedited->wavelet.resconH) keyFile.set_integer ("Wavelet", "ResidualcontHighlight", wavelet.resconH); - if (!pedited || pedited->wavelet.thr) keyFile.set_integer ("Wavelet", "ThresholdResidShadow", wavelet.thr); - if (!pedited || pedited->wavelet.thrH) keyFile.set_integer ("Wavelet", "ThresholdResidHighLight", wavelet.thrH); - if (!pedited || pedited->wavelet.reschro) keyFile.set_integer ("Wavelet", "Residualchroma", wavelet.reschro); - if (!pedited || pedited->wavelet.tmrs) keyFile.set_double ("Wavelet", "ResidualTM", wavelet.tmrs); - if (!pedited || pedited->wavelet.gamma) keyFile.set_double ("Wavelet", "Residualgamma", wavelet.gamma); - if (!pedited || pedited->wavelet.sky) keyFile.set_double ("Wavelet", "HueRangeResidual", wavelet.sky); + if (!pedited || pedited->wavelet.edgrad) { + keyFile.set_integer ("Wavelet", "Edgrad", wavelet.edgrad); + } + + if (!pedited || pedited->wavelet.edgval) { + keyFile.set_integer ("Wavelet", "Edgval", wavelet.edgval); + } + + if (!pedited || pedited->wavelet.edgthresh) { + keyFile.set_integer ("Wavelet", "ThrEdg", wavelet.edgthresh); + } + +// if (!pedited || pedited->wavelet.strength) keyFile.set_integer ("Wavelet", "Strength", wavelet.strength); + // if (!pedited || pedited->wavelet.balance) keyFile.set_integer ("Wavelet", "Balance", wavelet.balance); + + if (!pedited || pedited->wavelet.avoid) { + keyFile.set_boolean ("Wavelet", "AvoidColorShift", wavelet.avoid); + } + + if (!pedited || pedited->wavelet.tmr) { + keyFile.set_boolean ("Wavelet", "TMr", wavelet.tmr); + } + + if (!pedited || pedited->wavelet.rescon) { + keyFile.set_integer ("Wavelet", "ResidualcontShadow", wavelet.rescon); + } + + if (!pedited || pedited->wavelet.resconH) { + keyFile.set_integer ("Wavelet", "ResidualcontHighlight", wavelet.resconH); + } + + if (!pedited || pedited->wavelet.thr) { + keyFile.set_integer ("Wavelet", "ThresholdResidShadow", wavelet.thr); + } + + if (!pedited || pedited->wavelet.thrH) { + keyFile.set_integer ("Wavelet", "ThresholdResidHighLight", wavelet.thrH); + } + + if (!pedited || pedited->wavelet.reschro) { + keyFile.set_integer ("Wavelet", "Residualchroma", wavelet.reschro); + } + + if (!pedited || pedited->wavelet.tmrs) { + keyFile.set_double ("Wavelet", "ResidualTM", wavelet.tmrs); + } + + if (!pedited || pedited->wavelet.gamma) { + keyFile.set_double ("Wavelet", "Residualgamma", wavelet.gamma); + } + + if (!pedited || pedited->wavelet.sky) { + keyFile.set_double ("Wavelet", "HueRangeResidual", wavelet.sky); + } + if (!pedited || pedited->wavelet.hueskin2) { Glib::ArrayHandle thresh (wavelet.hueskin2.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "HueRange", thresh); } - if (!pedited || pedited->wavelet.contrast) keyFile.set_integer ("Wavelet", "Contrast", wavelet.contrast); - - + + if (!pedited || pedited->wavelet.contrast) { + keyFile.set_integer ("Wavelet", "Contrast", wavelet.contrast); + } + + // save directional pyramid wavelet parameters - if (!pedited || pedited->dirpyrequalizer.enabled) keyFile.set_boolean ("Directional Pyramid Equalizer", "Enabled", dirpyrequalizer.enabled); - if (!pedited || pedited->dirpyrequalizer.gamutlab) keyFile.set_boolean ("Directional Pyramid Equalizer", "Gamutlab", dirpyrequalizer.gamutlab); - for(int i = 0; i < 6; i++) - { + if (!pedited || pedited->dirpyrequalizer.enabled) { + keyFile.set_boolean ("Directional Pyramid Equalizer", "Enabled", dirpyrequalizer.enabled); + } + + if (!pedited || pedited->dirpyrequalizer.gamutlab) { + keyFile.set_boolean ("Directional Pyramid Equalizer", "Gamutlab", dirpyrequalizer.gamutlab); + } + + for(int i = 0; i < 6; i++) { std::stringstream ss; ss << "Mult" << i; - if (!pedited || pedited->dirpyrequalizer.mult[i]) keyFile.set_double("Directional Pyramid Equalizer", ss.str(), dirpyrequalizer.mult[i]); + + if (!pedited || pedited->dirpyrequalizer.mult[i]) { + keyFile.set_double("Directional Pyramid Equalizer", ss.str(), dirpyrequalizer.mult[i]); + } } - if (!pedited || pedited->dirpyrequalizer.threshold) keyFile.set_double ("Directional Pyramid Equalizer", "Threshold", dirpyrequalizer.threshold); - if (!pedited || pedited->dirpyrequalizer.skinprotect) keyFile.set_double ("Directional Pyramid Equalizer", "Skinprotect", dirpyrequalizer.skinprotect); - // if (!pedited || pedited->dirpyrequalizer.algo) keyFile.set_string ("Directional Pyramid Equalizer", "Algorithm", dirpyrequalizer.algo); + + if (!pedited || pedited->dirpyrequalizer.threshold) { + keyFile.set_double ("Directional Pyramid Equalizer", "Threshold", dirpyrequalizer.threshold); + } + + if (!pedited || pedited->dirpyrequalizer.skinprotect) { + keyFile.set_double ("Directional Pyramid Equalizer", "Skinprotect", dirpyrequalizer.skinprotect); + } + + // if (!pedited || pedited->dirpyrequalizer.algo) keyFile.set_string ("Directional Pyramid Equalizer", "Algorithm", dirpyrequalizer.algo); if (!pedited || pedited->dirpyrequalizer.hueskin) { Glib::ArrayHandle thresh (dirpyrequalizer.hueskin.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Directional Pyramid Equalizer", "Hueskin", thresh); @@ -1827,1142 +2824,4146 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle hcurve = hsvequalizer.hcurve; keyFile.set_double_list("HSV Equalizer", "HCurve", hcurve); } + if (!pedited || pedited->hsvequalizer.scurve) { Glib::ArrayHandle scurve = hsvequalizer.scurve; keyFile.set_double_list("HSV Equalizer", "SCurve", scurve); } + if (!pedited || pedited->hsvequalizer.vcurve) { Glib::ArrayHandle vcurve = hsvequalizer.vcurve; keyFile.set_double_list("HSV Equalizer", "VCurve", vcurve); } //save film simulation parameters - if ( !pedited || pedited->filmSimulation.enabled ) keyFile.set_boolean( "Film Simulation", "Enabled", filmSimulation.enabled ); - if ( !pedited || pedited->filmSimulation.clutFilename ) keyFile.set_string ( "Film Simulation", "ClutFilename", filmSimulation.clutFilename ); - if ( !pedited || pedited->filmSimulation.strength ) keyFile.set_integer( "Film Simulation", "Strength", filmSimulation.strength ); + if ( !pedited || pedited->filmSimulation.enabled ) { + keyFile.set_boolean( "Film Simulation", "Enabled", filmSimulation.enabled ); + } + + if ( !pedited || pedited->filmSimulation.clutFilename ) { + keyFile.set_string ( "Film Simulation", "ClutFilename", filmSimulation.clutFilename ); + } + + if ( !pedited || pedited->filmSimulation.strength ) { + keyFile.set_integer( "Film Simulation", "Strength", filmSimulation.strength ); + } - if (!pedited || pedited->rgbCurves.lumamode) keyFile.set_boolean ("RGB Curves", "LumaMode", rgbCurves.lumamode); + if (!pedited || pedited->rgbCurves.lumamode) { + keyFile.set_boolean ("RGB Curves", "LumaMode", rgbCurves.lumamode); + } if (!pedited || pedited->rgbCurves.rcurve) { Glib::ArrayHandle RGBrcurve = rgbCurves.rcurve; keyFile.set_double_list("RGB Curves", "rCurve", RGBrcurve); } + if (!pedited || pedited->rgbCurves.gcurve) { Glib::ArrayHandle RGBgcurve = rgbCurves.gcurve; keyFile.set_double_list("RGB Curves", "gCurve", RGBgcurve); } + if (!pedited || pedited->rgbCurves.bcurve) { Glib::ArrayHandle RGBbcurve = rgbCurves.bcurve; keyFile.set_double_list("RGB Curves", "bCurve", RGBbcurve); } // save Color Toning - if (!pedited || pedited->colorToning.enabled) keyFile.set_boolean ("ColorToning", "Enabled", colorToning.enabled); - if (!pedited || pedited->colorToning.method) keyFile.set_string ("ColorToning", "Method", colorToning.method); - if (!pedited || pedited->colorToning.lumamode) keyFile.set_boolean ("ColorToning", "Lumamode", colorToning.lumamode); - if (!pedited || pedited->colorToning.twocolor) keyFile.set_string ("ColorToning", "Twocolor", colorToning.twocolor); - if (!pedited || pedited->colorToning.redlow) keyFile.set_double ("ColorToning", "Redlow", colorToning.redlow); - if (!pedited || pedited->colorToning.greenlow) keyFile.set_double ("ColorToning", "Greenlow", colorToning.greenlow); - if (!pedited || pedited->colorToning.bluelow) keyFile.set_double ("ColorToning", "Bluelow", colorToning.bluelow); - if (!pedited || pedited->colorToning.satlow) keyFile.set_double ("ColorToning", "Satlow", colorToning.satlow); - if (!pedited || pedited->colorToning.balance) keyFile.set_integer ("ColorToning", "Balance", colorToning.balance); - if (!pedited || pedited->colorToning.sathigh) keyFile.set_double ("ColorToning", "Sathigh", colorToning.sathigh); - if (!pedited || pedited->colorToning.redmed) keyFile.set_double ("ColorToning", "Redmed", colorToning.redmed); - if (!pedited || pedited->colorToning.greenmed) keyFile.set_double ("ColorToning", "Greenmed", colorToning.greenmed); - if (!pedited || pedited->colorToning.bluemed) keyFile.set_double ("ColorToning", "Bluemed", colorToning.bluemed); - if (!pedited || pedited->colorToning.redhigh) keyFile.set_double ("ColorToning", "Redhigh", colorToning.redhigh); - if (!pedited || pedited->colorToning.greenhigh) keyFile.set_double ("ColorToning", "Greenhigh", colorToning.greenhigh); - if (!pedited || pedited->colorToning.bluehigh) keyFile.set_double ("ColorToning", "Bluehigh", colorToning.bluehigh); - if (!pedited || pedited->colorToning.autosat) keyFile.set_boolean ("ColorToning", "Autosat", colorToning.autosat); + if (!pedited || pedited->colorToning.enabled) { + keyFile.set_boolean ("ColorToning", "Enabled", colorToning.enabled); + } + + if (!pedited || pedited->colorToning.method) { + keyFile.set_string ("ColorToning", "Method", colorToning.method); + } + + if (!pedited || pedited->colorToning.lumamode) { + keyFile.set_boolean ("ColorToning", "Lumamode", colorToning.lumamode); + } + + if (!pedited || pedited->colorToning.twocolor) { + keyFile.set_string ("ColorToning", "Twocolor", colorToning.twocolor); + } + + if (!pedited || pedited->colorToning.redlow) { + keyFile.set_double ("ColorToning", "Redlow", colorToning.redlow); + } + + if (!pedited || pedited->colorToning.greenlow) { + keyFile.set_double ("ColorToning", "Greenlow", colorToning.greenlow); + } + + if (!pedited || pedited->colorToning.bluelow) { + keyFile.set_double ("ColorToning", "Bluelow", colorToning.bluelow); + } + + if (!pedited || pedited->colorToning.satlow) { + keyFile.set_double ("ColorToning", "Satlow", colorToning.satlow); + } + + if (!pedited || pedited->colorToning.balance) { + keyFile.set_integer ("ColorToning", "Balance", colorToning.balance); + } + + if (!pedited || pedited->colorToning.sathigh) { + keyFile.set_double ("ColorToning", "Sathigh", colorToning.sathigh); + } + + if (!pedited || pedited->colorToning.redmed) { + keyFile.set_double ("ColorToning", "Redmed", colorToning.redmed); + } + + if (!pedited || pedited->colorToning.greenmed) { + keyFile.set_double ("ColorToning", "Greenmed", colorToning.greenmed); + } + + if (!pedited || pedited->colorToning.bluemed) { + keyFile.set_double ("ColorToning", "Bluemed", colorToning.bluemed); + } + + if (!pedited || pedited->colorToning.redhigh) { + keyFile.set_double ("ColorToning", "Redhigh", colorToning.redhigh); + } + + if (!pedited || pedited->colorToning.greenhigh) { + keyFile.set_double ("ColorToning", "Greenhigh", colorToning.greenhigh); + } + + if (!pedited || pedited->colorToning.bluehigh) { + keyFile.set_double ("ColorToning", "Bluehigh", colorToning.bluehigh); + } + + if (!pedited || pedited->colorToning.autosat) { + keyFile.set_boolean ("ColorToning", "Autosat", colorToning.autosat); + } if (!pedited || pedited->colorToning.opacityCurve) { Glib::ArrayHandle curve = colorToning.opacityCurve; keyFile.set_double_list("ColorToning", "OpacityCurve", curve); } + if (!pedited || pedited->colorToning.colorCurve) { Glib::ArrayHandle curve = colorToning.colorCurve; keyFile.set_double_list("ColorToning", "ColorCurve", curve); } - if (!pedited || pedited->colorToning.satprotectionthreshold) keyFile.set_integer ("ColorToning", "SatProtectionThreshold", colorToning.satProtectionThreshold ); - if (!pedited || pedited->colorToning.saturatedopacity) keyFile.set_integer ("ColorToning", "SaturatedOpacity", colorToning.saturatedOpacity ); - if (!pedited || pedited->colorToning.strength) keyFile.set_integer ("ColorToning", "Strength", colorToning.strength ); + + if (!pedited || pedited->colorToning.satprotectionthreshold) { + keyFile.set_integer ("ColorToning", "SatProtectionThreshold", colorToning.satProtectionThreshold ); + } + + if (!pedited || pedited->colorToning.saturatedopacity) { + keyFile.set_integer ("ColorToning", "SaturatedOpacity", colorToning.saturatedOpacity ); + } + + if (!pedited || pedited->colorToning.strength) { + keyFile.set_integer ("ColorToning", "Strength", colorToning.strength ); + } if (!pedited || pedited->colorToning.hlColSat) { Glib::ArrayHandle thresh (colorToning.hlColSat.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("ColorToning", "HighlightsColorSaturation", thresh); } + if (!pedited || pedited->colorToning.shadowsColSat) { Glib::ArrayHandle thresh (colorToning.shadowsColSat.value, 2, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("ColorToning", "ShadowsColorSaturation", thresh); } + if (!pedited || pedited->colorToning.clcurve) { Glib::ArrayHandle clcurve = colorToning.clcurve; keyFile.set_double_list("ColorToning", "ClCurve", clcurve); } + if (!pedited || pedited->colorToning.cl2curve) { Glib::ArrayHandle cl2curve = colorToning.cl2curve; keyFile.set_double_list("ColorToning", "Cl2Curve", cl2curve); } // save raw parameters - if (!pedited || pedited->raw.darkFrame) keyFile.set_string ("RAW", "DarkFrame", relativePathIfInside(fname, fnameAbsolute, raw.dark_frame) ); - if (!pedited || pedited->raw.dfAuto) keyFile.set_boolean ("RAW", "DarkFrameAuto", raw.df_autoselect ); - if (!pedited || pedited->raw.ff_file) keyFile.set_string ("RAW", "FlatFieldFile", relativePathIfInside(fname, fnameAbsolute, raw.ff_file) ); - if (!pedited || pedited->raw.ff_AutoSelect) keyFile.set_boolean ("RAW", "FlatFieldAutoSelect", raw.ff_AutoSelect ); - if (!pedited || pedited->raw.ff_BlurRadius) keyFile.set_integer ("RAW", "FlatFieldBlurRadius", raw.ff_BlurRadius ); - if (!pedited || pedited->raw.ff_BlurType) keyFile.set_string ("RAW", "FlatFieldBlurType", raw.ff_BlurType ); - if (!pedited || pedited->raw.ff_AutoClipControl) keyFile.set_boolean ("RAW", "FlatFieldAutoClipControl", raw.ff_AutoClipControl ); - if (!pedited || pedited->raw.ff_clipControl) keyFile.set_boolean ("RAW", "FlatFieldClipControl", raw.ff_clipControl ); - if (!pedited || pedited->raw.caCorrection) keyFile.set_boolean ("RAW", "CA", raw.ca_autocorrect ); - if (!pedited || pedited->raw.caRed) keyFile.set_double ("RAW", "CARed", raw.cared ); - if (!pedited || pedited->raw.caBlue) keyFile.set_double ("RAW", "CABlue", raw.cablue ); - if (!pedited || pedited->raw.hotPixelFilter) keyFile.set_boolean ("RAW", "HotPixelFilter", raw.hotPixelFilter ); - if (!pedited || pedited->raw.deadPixelFilter) keyFile.set_boolean ("RAW", "DeadPixelFilter", raw.deadPixelFilter ); - if (!pedited || pedited->raw.hotDeadPixelThresh) keyFile.set_integer ("RAW", "HotDeadPixelThresh", raw.hotdeadpix_thresh ); + if (!pedited || pedited->raw.darkFrame) { + keyFile.set_string ("RAW", "DarkFrame", relativePathIfInside(fname, fnameAbsolute, raw.dark_frame) ); + } + + if (!pedited || pedited->raw.dfAuto) { + keyFile.set_boolean ("RAW", "DarkFrameAuto", raw.df_autoselect ); + } + + if (!pedited || pedited->raw.ff_file) { + keyFile.set_string ("RAW", "FlatFieldFile", relativePathIfInside(fname, fnameAbsolute, raw.ff_file) ); + } + + if (!pedited || pedited->raw.ff_AutoSelect) { + keyFile.set_boolean ("RAW", "FlatFieldAutoSelect", raw.ff_AutoSelect ); + } + + if (!pedited || pedited->raw.ff_BlurRadius) { + keyFile.set_integer ("RAW", "FlatFieldBlurRadius", raw.ff_BlurRadius ); + } + + if (!pedited || pedited->raw.ff_BlurType) { + keyFile.set_string ("RAW", "FlatFieldBlurType", raw.ff_BlurType ); + } + + if (!pedited || pedited->raw.ff_AutoClipControl) { + keyFile.set_boolean ("RAW", "FlatFieldAutoClipControl", raw.ff_AutoClipControl ); + } + + if (!pedited || pedited->raw.ff_clipControl) { + keyFile.set_boolean ("RAW", "FlatFieldClipControl", raw.ff_clipControl ); + } + + if (!pedited || pedited->raw.caCorrection) { + keyFile.set_boolean ("RAW", "CA", raw.ca_autocorrect ); + } + + if (!pedited || pedited->raw.caRed) { + keyFile.set_double ("RAW", "CARed", raw.cared ); + } + + if (!pedited || pedited->raw.caBlue) { + keyFile.set_double ("RAW", "CABlue", raw.cablue ); + } + + if (!pedited || pedited->raw.hotPixelFilter) { + keyFile.set_boolean ("RAW", "HotPixelFilter", raw.hotPixelFilter ); + } + + if (!pedited || pedited->raw.deadPixelFilter) { + keyFile.set_boolean ("RAW", "DeadPixelFilter", raw.deadPixelFilter ); + } + + if (!pedited || pedited->raw.hotDeadPixelThresh) { + keyFile.set_integer ("RAW", "HotDeadPixelThresh", raw.hotdeadpix_thresh ); + } + + if (!pedited || pedited->raw.bayersensor.method) { + keyFile.set_string ("RAW Bayer", "Method", raw.bayersensor.method ); + } + + if (!pedited || pedited->raw.bayersensor.ccSteps) { + keyFile.set_integer ("RAW Bayer", "CcSteps", raw.bayersensor.ccSteps); + } + + if (!pedited || pedited->raw.bayersensor.exBlack0) { + keyFile.set_double ("RAW Bayer", "PreBlack0", raw.bayersensor.black0 ); + } + + if (!pedited || pedited->raw.bayersensor.exBlack1) { + keyFile.set_double ("RAW Bayer", "PreBlack1", raw.bayersensor.black1 ); + } + + if (!pedited || pedited->raw.bayersensor.exBlack2) { + keyFile.set_double ("RAW Bayer", "PreBlack2", raw.bayersensor.black2 ); + } + + if (!pedited || pedited->raw.bayersensor.exBlack3) { + keyFile.set_double ("RAW Bayer", "PreBlack3", raw.bayersensor.black3 ); + } + + if (!pedited || pedited->raw.bayersensor.exTwoGreen) { + keyFile.set_boolean ("RAW Bayer", "PreTwoGreen", raw.bayersensor.twogreen ); + } + + if (!pedited || pedited->raw.bayersensor.linenoise) { + keyFile.set_integer ("RAW Bayer", "LineDenoise", raw.bayersensor.linenoise); + } + + if (!pedited || pedited->raw.bayersensor.greenEq) { + keyFile.set_integer ("RAW Bayer", "GreenEqThreshold", raw.bayersensor.greenthresh); + } + + if (!pedited || pedited->raw.bayersensor.dcbIterations) { + keyFile.set_integer ("RAW Bayer", "DCBIterations", raw.bayersensor.dcb_iterations ); + } + + if (!pedited || pedited->raw.bayersensor.dcbEnhance) { + keyFile.set_boolean ("RAW Bayer", "DCBEnhance", raw.bayersensor.dcb_enhance ); + } + + if (!pedited || pedited->raw.bayersensor.lmmseIterations) { + keyFile.set_integer ("RAW Bayer", "LMMSEIterations", raw.bayersensor.lmmse_iterations ); + } - if (!pedited || pedited->raw.bayersensor.method) keyFile.set_string ("RAW Bayer", "Method", raw.bayersensor.method ); - if (!pedited || pedited->raw.bayersensor.ccSteps) keyFile.set_integer ("RAW Bayer", "CcSteps", raw.bayersensor.ccSteps); - if (!pedited || pedited->raw.bayersensor.exBlack0) keyFile.set_double ("RAW Bayer", "PreBlack0", raw.bayersensor.black0 ); - if (!pedited || pedited->raw.bayersensor.exBlack1) keyFile.set_double ("RAW Bayer", "PreBlack1", raw.bayersensor.black1 ); - if (!pedited || pedited->raw.bayersensor.exBlack2) keyFile.set_double ("RAW Bayer", "PreBlack2", raw.bayersensor.black2 ); - if (!pedited || pedited->raw.bayersensor.exBlack3) keyFile.set_double ("RAW Bayer", "PreBlack3", raw.bayersensor.black3 ); - if (!pedited || pedited->raw.bayersensor.exTwoGreen) keyFile.set_boolean ("RAW Bayer", "PreTwoGreen", raw.bayersensor.twogreen ); - if (!pedited || pedited->raw.bayersensor.linenoise) keyFile.set_integer ("RAW Bayer", "LineDenoise", raw.bayersensor.linenoise); - if (!pedited || pedited->raw.bayersensor.greenEq) keyFile.set_integer ("RAW Bayer", "GreenEqThreshold", raw.bayersensor.greenthresh); - if (!pedited || pedited->raw.bayersensor.dcbIterations) keyFile.set_integer ("RAW Bayer", "DCBIterations", raw.bayersensor.dcb_iterations ); - if (!pedited || pedited->raw.bayersensor.dcbEnhance) keyFile.set_boolean ("RAW Bayer", "DCBEnhance", raw.bayersensor.dcb_enhance ); - if (!pedited || pedited->raw.bayersensor.lmmseIterations) keyFile.set_integer ("RAW Bayer", "LMMSEIterations", raw.bayersensor.lmmse_iterations ); //if (!pedited || pedited->raw.bayersensor.allEnhance) keyFile.set_boolean ("RAW Bayer", "ALLEnhance", raw.bayersensor.all_enhance ); - if (!pedited || pedited->raw.xtranssensor.method) keyFile.set_string ("RAW X-Trans", "Method", raw.xtranssensor.method ); - if (!pedited || pedited->raw.xtranssensor.ccSteps) keyFile.set_integer ("RAW X-Trans", "CcSteps", raw.xtranssensor.ccSteps); - if (!pedited || pedited->raw.xtranssensor.exBlackRed) keyFile.set_double ("RAW X-Trans", "PreBlackRed", raw.xtranssensor.blackred ); - if (!pedited || pedited->raw.xtranssensor.exBlackGreen) keyFile.set_double ("RAW X-Trans", "PreBlackGreen", raw.xtranssensor.blackgreen ); - if (!pedited || pedited->raw.xtranssensor.exBlackBlue) keyFile.set_double ("RAW X-Trans", "PreBlackBlue", raw.xtranssensor.blackblue ); + if (!pedited || pedited->raw.xtranssensor.method) { + keyFile.set_string ("RAW X-Trans", "Method", raw.xtranssensor.method ); + } + + if (!pedited || pedited->raw.xtranssensor.ccSteps) { + keyFile.set_integer ("RAW X-Trans", "CcSteps", raw.xtranssensor.ccSteps); + } + + if (!pedited || pedited->raw.xtranssensor.exBlackRed) { + keyFile.set_double ("RAW X-Trans", "PreBlackRed", raw.xtranssensor.blackred ); + } + + if (!pedited || pedited->raw.xtranssensor.exBlackGreen) { + keyFile.set_double ("RAW X-Trans", "PreBlackGreen", raw.xtranssensor.blackgreen ); + } + + if (!pedited || pedited->raw.xtranssensor.exBlackBlue) { + keyFile.set_double ("RAW X-Trans", "PreBlackBlue", raw.xtranssensor.blackblue ); + } // save raw exposition - if (!pedited || pedited->raw.exPos) keyFile.set_double ("RAW", "PreExposure", raw.expos ); - if (!pedited || pedited->raw.exPreser) keyFile.set_double ("RAW", "PrePreserv", raw.preser ); + if (!pedited || pedited->raw.exPos) { + keyFile.set_double ("RAW", "PreExposure", raw.expos ); + } + + if (!pedited || pedited->raw.exPreser) { + keyFile.set_double ("RAW", "PrePreserv", raw.preser ); + } // save exif change list if (!pedited || pedited->exif) { - for (ExifPairs::const_iterator i=exif.begin(); i!=exif.end(); i++) + for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); i++) { keyFile.set_string ("Exif", i->first, i->second); + } } // save iptc change list if (!pedited || pedited->iptc) { - for (IPTCPairs::const_iterator i=iptc.begin(); i!=iptc.end(); i++) { + for (IPTCPairs::const_iterator i = iptc.begin(); i != iptc.end(); i++) { Glib::ArrayHandle values = i->second; keyFile.set_string_list ("IPTC", i->first, values); } } - + Glib::ustring sPParams = keyFile.to_data(); int error1, error2; error1 = write (fname , sPParams); + if (fname2.length()) { error2 = write (fname2, sPParams); // If at least one file has been saved, it's a success return error1 & error2; - } - else + } else { return error1; + } } -int ProcParams::write (Glib::ustring &fname, Glib::ustring &content) const { +int ProcParams::write (Glib::ustring &fname, Glib::ustring &content) const +{ int error = 0; + if (fname.length()) { FILE *f; f = safe_g_fopen (fname, "wt"); - if (f==NULL) + if (f == NULL) { error = 1; - else { + } else { fprintf (f, "%s", content.c_str()); fclose (f); } } + return error; } -int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) { +int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) +{ setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - if (fname.empty()) + + if (fname.empty()) { return 1; + } SafeKeyFile keyFile; + try { //setDefaults (); - if (pedited) + if (pedited) { pedited->set(false); + } FILE* f = safe_g_fopen (fname, "rt"); - if (!f) + + if (!f) { return 1; + } + char* buffer = new char[1024]; std::ostringstream ostr; - while (fgets (buffer, 1024, f)) + + while (fgets (buffer, 1024, f)) { ostr << buffer << "\n"; + } + delete [] buffer; - if (!keyFile.load_from_data (ostr.str())) + + if (!keyFile.load_from_data (ostr.str())) { return 1; + } + fclose (f); - // load tonecurve: + // load tonecurve: + + ppVersion = PPVERSION; + appVersion = APPVERSION; + + if (keyFile.has_group ("Version")) { + if (keyFile.has_key ("Version", "AppVersion")) { + appVersion = keyFile.get_string ("Version", "AppVersion"); + } + + if (keyFile.has_key ("Version", "Version")) { + ppVersion = keyFile.get_integer ("Version", "Version"); + } + } -ppVersion = PPVERSION; -appVersion = APPVERSION; -if (keyFile.has_group ("Version")) { - if (keyFile.has_key ("Version", "AppVersion")) appVersion = keyFile.get_string ("Version", "AppVersion"); - if (keyFile.has_key ("Version", "Version")) ppVersion = keyFile.get_integer ("Version", "Version"); -} //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"); if (pedited) pedited->general.rank = true; } - if (keyFile.has_key ("General", "ColorLabel")) { colorlabel = keyFile.get_integer ("General", "ColorLabel"); if (pedited) pedited->general.colorlabel = true; } - if (keyFile.has_key ("General", "InTrash")) { inTrash = keyFile.get_boolean ("General", "InTrash"); if (pedited) pedited->general.intrash = true; } -} + if (keyFile.has_group ("General")) { + if (keyFile.has_key ("General", "Rank")) { + rank = keyFile.get_integer ("General", "Rank"); -if (keyFile.has_group ("Exposure")) { - if (ppVersiontoneCurve.autoexp = true; } + if (pedited) { + pedited->general.rank = true; + } + } - if (keyFile.has_key ("Exposure", "Clip")) { toneCurve.clip = keyFile.get_double ("Exposure", "Clip"); if (pedited) pedited->toneCurve.clip = true; } - if (keyFile.has_key ("Exposure", "Compensation")) { toneCurve.expcomp = keyFile.get_double ("Exposure", "Compensation"); if (pedited) pedited->toneCurve.expcomp = true; } - if (keyFile.has_key ("Exposure", "Brightness")) { toneCurve.brightness = keyFile.get_integer ("Exposure", "Brightness"); if (pedited) pedited->toneCurve.brightness = true; } - if (keyFile.has_key ("Exposure", "Contrast")) { toneCurve.contrast = keyFile.get_integer ("Exposure", "Contrast"); if (pedited) pedited->toneCurve.contrast = true; } - if (keyFile.has_key ("Exposure", "Saturation")) { toneCurve.saturation = keyFile.get_integer ("Exposure", "Saturation"); if (pedited) pedited->toneCurve.saturation = true; } - if (keyFile.has_key ("Exposure", "Black")) { toneCurve.black = keyFile.get_integer ("Exposure", "Black"); if (pedited) pedited->toneCurve.black = true; } - if (keyFile.has_key ("Exposure", "HighlightCompr")) { toneCurve.hlcompr = keyFile.get_integer ("Exposure", "HighlightCompr"); if (pedited) pedited->toneCurve.hlcompr = true; } - if (keyFile.has_key ("Exposure", "HighlightComprThreshold")) { toneCurve.hlcomprthresh = keyFile.get_integer ("Exposure", "HighlightComprThreshold"); if (pedited) pedited->toneCurve.hlcomprthresh = true; } - if (keyFile.has_key ("Exposure", "ShadowCompr")) { toneCurve.shcompr = keyFile.get_integer ("Exposure", "ShadowCompr"); if (pedited) pedited->toneCurve.shcompr = true; } - // load highlight recovery settings - if (toneCurve.shcompr > 100) toneCurve.shcompr = 100; // older pp3 files can have values above 100. - if (keyFile.has_key ("Exposure", "CurveMode")) { - Glib::ustring sMode = keyFile.get_string ("Exposure", "CurveMode"); - if (sMode == "Standard") toneCurve.curveMode = ToneCurveParams::TC_MODE_STD; - else if (sMode == "FilmLike") toneCurve.curveMode = ToneCurveParams::TC_MODE_FILMLIKE; - else if (sMode == "SatAndValueBlending") toneCurve.curveMode = ToneCurveParams::TC_MODE_SATANDVALBLENDING; - else if (sMode == "WeightedStd") toneCurve.curveMode = ToneCurveParams::TC_MODE_WEIGHTEDSTD; - else if (sMode == "Luminance") toneCurve.curveMode = ToneCurveParams::TC_MODE_LUMINANCE; - else if (sMode == "Perceptual") toneCurve.curveMode = ToneCurveParams::TC_MODE_PERCEPTUAL; - if (pedited) pedited->toneCurve.curveMode = true; - } - if (keyFile.has_key ("Exposure", "CurveMode2")) { - Glib::ustring sMode = keyFile.get_string ("Exposure", "CurveMode2"); - if (sMode == "Standard") toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD; - else if (sMode == "FilmLike") toneCurve.curveMode2 = ToneCurveParams::TC_MODE_FILMLIKE; - else if (sMode == "SatAndValueBlending") toneCurve.curveMode2 = ToneCurveParams::TC_MODE_SATANDVALBLENDING; - else if (sMode == "WeightedStd") toneCurve.curveMode2 = ToneCurveParams::TC_MODE_WEIGHTEDSTD; - else if (sMode == "Luminance") toneCurve.curveMode2 = ToneCurveParams::TC_MODE_LUMINANCE; - else if (sMode == "Perceptual") toneCurve.curveMode2 = ToneCurveParams::TC_MODE_PERCEPTUAL; - if (pedited) pedited->toneCurve.curveMode2 = true; - } - if (ppVersion>200) { - if (keyFile.has_key ("Exposure", "Curve")) { toneCurve.curve = keyFile.get_double_list ("Exposure", "Curve"); if (pedited) pedited->toneCurve.curve = true; } - if (keyFile.has_key ("Exposure", "Curve2")) { toneCurve.curve2 = keyFile.get_double_list ("Exposure", "Curve2"); if (pedited) pedited->toneCurve.curve2 = true; } - } -} -if (keyFile.has_group ("HLRecovery")) { - if (keyFile.has_key ("HLRecovery", "Enabled")) { toneCurve.hrenabled = keyFile.get_boolean ("HLRecovery", "Enabled"); if (pedited) pedited->toneCurve.hrenabled = true; } - if (keyFile.has_key ("HLRecovery", "Method")) { toneCurve.method = keyFile.get_string ("HLRecovery", "Method"); if (pedited) pedited->toneCurve.method = true; } -} + if (keyFile.has_key ("General", "ColorLabel")) { + colorlabel = keyFile.get_integer ("General", "ColorLabel"); - // load channel mixer curve -if (keyFile.has_group ("Channel Mixer")) { - if (keyFile.has_key ("Channel Mixer", "Red") && keyFile.has_key ("Channel Mixer", "Green") && keyFile.has_key ("Channel Mixer", "Blue")) { - if (pedited) { - pedited->chmixer.red[0] = pedited->chmixer.red[1] = pedited->chmixer.red[2] = true; - pedited->chmixer.green[0] = pedited->chmixer.green[1] = pedited->chmixer.green[2] = true; - pedited->chmixer.blue[0] = pedited->chmixer.blue[1] = pedited->chmixer.blue[2] = true; - } + if (pedited) { + pedited->general.colorlabel = true; + } + } - Glib::ArrayHandle rmix = keyFile.get_integer_list ("Channel Mixer", "Red"); - Glib::ArrayHandle gmix = keyFile.get_integer_list ("Channel Mixer", "Green"); - Glib::ArrayHandle bmix = keyFile.get_integer_list ("Channel Mixer", "Blue"); - memcpy (chmixer.red, rmix.data(), 3*sizeof(int)); - memcpy (chmixer.green, gmix.data(), 3*sizeof(int)); - memcpy (chmixer.blue, bmix.data(), 3*sizeof(int)); - } -} + if (keyFile.has_key ("General", "InTrash")) { + inTrash = keyFile.get_boolean ("General", "InTrash"); - // load black & white -if (keyFile.has_group ("Black & White")) { - if (keyFile.has_key ("Black & White", "Enabled")) { blackwhite.enabled = keyFile.get_boolean ("Black & White", "Enabled"); if (pedited) pedited->blackwhite.enabled = true; } - if (keyFile.has_key ("Black & White", "Method")) { blackwhite.method = keyFile.get_string ("Black & White", "Method"); if (pedited) pedited->blackwhite.method = true; } - - if (keyFile.has_key ("Black & White", "Auto")) { blackwhite.autoc = keyFile.get_boolean ("Black & White", "Auto"); if (pedited) pedited->blackwhite.autoc = true; } - if (keyFile.has_key ("Black & White", "ComplementaryColors")) { blackwhite.enabledcc = keyFile.get_boolean ("Black & White", "ComplementaryColors"); if (pedited) pedited->blackwhite.enabledcc = true; } - if (keyFile.has_key ("Black & White", "MixerRed")) { blackwhite.mixerRed = keyFile.get_integer ("Black & White", "MixerRed"); if (pedited) pedited->blackwhite.mixerRed = true; } - if (keyFile.has_key ("Black & White", "MixerOrange")) { blackwhite.mixerOrange = keyFile.get_integer ("Black & White", "MixerOrange"); if (pedited) pedited->blackwhite.mixerOrange = true; } - if (keyFile.has_key ("Black & White", "MixerYellow")) { blackwhite.mixerYellow = keyFile.get_integer ("Black & White", "MixerYellow"); if (pedited) pedited->blackwhite.mixerYellow = true; } - if (keyFile.has_key ("Black & White", "MixerGreen")) { blackwhite.mixerGreen = keyFile.get_integer ("Black & White", "MixerGreen"); if (pedited) pedited->blackwhite.mixerGreen = true; } - if (keyFile.has_key ("Black & White", "MixerCyan")) { blackwhite.mixerCyan = keyFile.get_integer ("Black & White", "MixerCyan"); if (pedited) pedited->blackwhite.mixerCyan = true; } - if (keyFile.has_key ("Black & White", "MixerBlue")) { blackwhite.mixerBlue = keyFile.get_integer ("Black & White", "MixerBlue"); if (pedited) pedited->blackwhite.mixerBlue = true; } - if (keyFile.has_key ("Black & White", "MixerMagenta")) { blackwhite.mixerMagenta = keyFile.get_integer ("Black & White", "MixerMagenta"); if (pedited) pedited->blackwhite.mixerMagenta = true; } - if (keyFile.has_key ("Black & White", "MixerPurple")) { blackwhite.mixerPurple = keyFile.get_integer ("Black & White", "MixerPurple"); if (pedited) pedited->blackwhite.mixerPurple = true; } - if (keyFile.has_key ("Black & White", "GammaRed")) { blackwhite.gammaRed = keyFile.get_integer ("Black & White", "GammaRed"); if (pedited) pedited->blackwhite.gammaRed = true; } - if (keyFile.has_key ("Black & White", "GammaGreen")) { blackwhite.gammaGreen = keyFile.get_integer ("Black & White", "GammaGreen"); if (pedited) pedited->blackwhite.gammaGreen = true; } - if (keyFile.has_key ("Black & White", "GammaBlue")) { blackwhite.gammaBlue = keyFile.get_integer ("Black & White", "GammaBlue"); if (pedited) pedited->blackwhite.gammaBlue = true; } - if (keyFile.has_key ("Black & White", "Filter")) { blackwhite.filter = keyFile.get_string ("Black & White", "Filter"); if (pedited) pedited->blackwhite.filter = true; } - if (keyFile.has_key ("Black & White", "Setting")) { blackwhite.setting = keyFile.get_string ("Black & White", "Setting"); if (pedited) pedited->blackwhite.setting = true; } - if (keyFile.has_key ("Black & White", "LuminanceCurve")) { blackwhite.luminanceCurve = keyFile.get_double_list ("Black & White", "LuminanceCurve"); if (pedited) pedited->blackwhite.luminanceCurve = true; } - if (keyFile.has_key ("Black & White", "BeforeCurve")) { blackwhite.beforeCurve = keyFile.get_double_list ("Black & White", "BeforeCurve"); if (pedited) pedited->blackwhite.beforeCurve = true; } - if (keyFile.has_key ("Black & White", "Algorithm")) { blackwhite.algo = keyFile.get_string ("Black & White", "Algorithm"); if (pedited) pedited->blackwhite.algo = true; } - if (keyFile.has_key ("Black & White", "BeforeCurveMode")) { - Glib::ustring sMode = keyFile.get_string ("Black & White", "BeforeCurveMode"); - if (sMode == "Standard") blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_STD_BW; - else if (sMode == "FilmLike") blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_FILMLIKE_BW; - else if (sMode == "SatAndValueBlending") blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW; - else if (sMode == "WeightedStd") blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW; - if (pedited) pedited->blackwhite.beforeCurveMode = true; - } - if (keyFile.has_key ("Black & White", "AfterCurve")) { blackwhite.afterCurve = keyFile.get_double_list ("Black & White", "AfterCurve"); if (pedited) pedited->blackwhite.afterCurve = true; } - if (keyFile.has_key ("Black & White", "AfterCurveMode")) { - Glib::ustring sMode2 = keyFile.get_string ("Black & White", "AfterCurveMode"); - if (sMode2 == "Standard") blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_STD_BW; - else if (sMode2 == "WeightedStd") blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW; - if (pedited) pedited->blackwhite.afterCurveMode = true; - } -} - - // load luma curve -if (keyFile.has_group ("Luminance Curve")) { - if (keyFile.has_key ("Luminance Curve", "Brightness")) { labCurve.brightness = keyFile.get_integer ("Luminance Curve", "Brightness"); if (pedited) pedited->labCurve.brightness = true; } - if (keyFile.has_key ("Luminance Curve", "Contrast")) { labCurve.contrast = keyFile.get_integer ("Luminance Curve", "Contrast"); if (pedited) pedited->labCurve.contrast = true; } - - if (ppVersion < 303) { - // transform Saturation into Chromaticity - // if Saturation == 0, should we set BWToning on? - if (keyFile.has_key ("Luminance Curve", "Saturation")) { labCurve.chromaticity = keyFile.get_integer ("Luminance Curve", "Saturation"); if (pedited) pedited->labCurve.chromaticity = true; } - // transform AvoidColorClipping into AvoidColorShift - if (keyFile.has_key ("Luminance Curve", "AvoidColorClipping")) { labCurve.avoidcolorshift = keyFile.get_boolean ("Luminance Curve", "AvoidColorClipping"); if (pedited) pedited->labCurve.avoidcolorshift = true; } - } - else { - if (keyFile.has_key ("Luminance Curve", "Chromaticity")) { labCurve.chromaticity = keyFile.get_integer ("Luminance Curve", "Chromaticity"); if (pedited) pedited->labCurve.chromaticity = true; } - if (keyFile.has_key ("Luminance Curve", "AvoidColorShift")) { labCurve.avoidcolorshift = keyFile.get_boolean ("Luminance Curve", "AvoidColorShift"); if (pedited) pedited->labCurve.avoidcolorshift = true; } - if (keyFile.has_key ("Luminance Curve", "RedAndSkinTonesProtection")) { labCurve.rstprotection = keyFile.get_double ("Luminance Curve", "RedAndSkinTonesProtection"); if (pedited) pedited->labCurve.rstprotection = true; } - } - if (keyFile.has_key ("Luminance Curve", "LCredsk")) { labCurve.lcredsk = keyFile.get_boolean ("Luminance Curve", "LCredsk"); if (pedited) pedited->labCurve.lcredsk = true; } - if (ppVersion < 314) - // Backward compatibility: If BWtoning is true, Chromaticity has to be set to -100, which will produce the same effect - // and will enable the b&w toning mode ('a' & 'b' curves) - if (keyFile.has_key ("Luminance Curve", "BWtoning")) { - if ( keyFile.get_boolean ("Luminance Curve", "BWtoning")) { - labCurve.chromaticity = -100; - if (pedited) pedited->labCurve.chromaticity = true; + if (pedited) { + pedited->general.intrash = true; + } } } - if (keyFile.has_key ("Luminance Curve", "LCurve")) { labCurve.lcurve = keyFile.get_double_list ("Luminance Curve", "LCurve"); if (pedited) pedited->labCurve.lcurve = true; } - if (keyFile.has_key ("Luminance Curve", "aCurve")) { labCurve.acurve = keyFile.get_double_list ("Luminance Curve", "aCurve"); if (pedited) pedited->labCurve.acurve = true; } - if (keyFile.has_key ("Luminance Curve", "bCurve")) { labCurve.bcurve = keyFile.get_double_list ("Luminance Curve", "bCurve"); if (pedited) pedited->labCurve.bcurve = true; } - if (keyFile.has_key ("Luminance Curve", "ccCurve")) { labCurve.cccurve = keyFile.get_double_list ("Luminance Curve", "ccCurve"); if (pedited) pedited->labCurve.cccurve = true; } - if (keyFile.has_key ("Luminance Curve", "chCurve")) { labCurve.chcurve = keyFile.get_double_list ("Luminance Curve", "chCurve"); if (pedited) pedited->labCurve.chcurve = true; } - if (keyFile.has_key ("Luminance Curve", "lhCurve")) { labCurve.lhcurve = keyFile.get_double_list ("Luminance Curve", "lhCurve"); if (pedited) pedited->labCurve.lhcurve = true; } - if (keyFile.has_key ("Luminance Curve", "hhCurve")) { labCurve.hhcurve = keyFile.get_double_list ("Luminance Curve", "hhCurve"); if (pedited) pedited->labCurve.hhcurve = true; } - if (keyFile.has_key ("Luminance Curve", "LcCurve")) { labCurve.lccurve = keyFile.get_double_list ("Luminance Curve", "LcCurve"); if (pedited) pedited->labCurve.lccurve = true; } - if (keyFile.has_key ("Luminance Curve", "ClCurve")) { labCurve.clcurve = keyFile.get_double_list ("Luminance Curve", "ClCurve"); if (pedited) pedited->labCurve.clcurve = true; } - } + if (keyFile.has_group ("Exposure")) { + if (ppVersion < PPVERSION_AEXP) { + toneCurve.autoexp = false; // prevent execution of autoexp when opening file created with earlier verions of autoexp algorithm + } else if (keyFile.has_key ("Exposure", "Auto")) { + toneCurve.autoexp = keyFile.get_boolean ("Exposure", "Auto"); - // load sharpening -if (keyFile.has_group ("Sharpening")) { - if (keyFile.has_key ("Sharpening", "Enabled")) { sharpening.enabled = keyFile.get_boolean ("Sharpening", "Enabled"); if (pedited) pedited->sharpening.enabled = true; } - if (keyFile.has_key ("Sharpening", "Radius")) { sharpening.radius = keyFile.get_double ("Sharpening", "Radius"); if (pedited) pedited->sharpening.radius = true; } - if (keyFile.has_key ("Sharpening", "Amount")) { sharpening.amount = keyFile.get_integer ("Sharpening", "Amount"); if (pedited) pedited->sharpening.amount = true; } - if (keyFile.has_key ("Sharpening", "Threshold")) { - if (ppVersion < 302) { - int thresh = min(keyFile.get_integer ("Sharpening", "Threshold"), 2000); - sharpening.threshold.setValues(thresh, thresh, 2000, 2000); // TODO: 2000 is the maximum value and is taken of rtgui/sharpening.cc ; should be changed by the tool modularization + if (pedited) { + pedited->toneCurve.autoexp = true; + } + } + + if (keyFile.has_key ("Exposure", "Clip")) { + toneCurve.clip = keyFile.get_double ("Exposure", "Clip"); + + if (pedited) { + pedited->toneCurve.clip = true; + } + } + + if (keyFile.has_key ("Exposure", "Compensation")) { + toneCurve.expcomp = keyFile.get_double ("Exposure", "Compensation"); + + if (pedited) { + pedited->toneCurve.expcomp = true; + } + } + + if (keyFile.has_key ("Exposure", "Brightness")) { + toneCurve.brightness = keyFile.get_integer ("Exposure", "Brightness"); + + if (pedited) { + pedited->toneCurve.brightness = true; + } + } + + if (keyFile.has_key ("Exposure", "Contrast")) { + toneCurve.contrast = keyFile.get_integer ("Exposure", "Contrast"); + + if (pedited) { + pedited->toneCurve.contrast = true; + } + } + + if (keyFile.has_key ("Exposure", "Saturation")) { + toneCurve.saturation = keyFile.get_integer ("Exposure", "Saturation"); + + if (pedited) { + pedited->toneCurve.saturation = true; + } + } + + if (keyFile.has_key ("Exposure", "Black")) { + toneCurve.black = keyFile.get_integer ("Exposure", "Black"); + + if (pedited) { + pedited->toneCurve.black = true; + } + } + + if (keyFile.has_key ("Exposure", "HighlightCompr")) { + toneCurve.hlcompr = keyFile.get_integer ("Exposure", "HighlightCompr"); + + if (pedited) { + pedited->toneCurve.hlcompr = true; + } + } + + if (keyFile.has_key ("Exposure", "HighlightComprThreshold")) { + toneCurve.hlcomprthresh = keyFile.get_integer ("Exposure", "HighlightComprThreshold"); + + if (pedited) { + pedited->toneCurve.hlcomprthresh = true; + } + } + + if (keyFile.has_key ("Exposure", "ShadowCompr")) { + toneCurve.shcompr = keyFile.get_integer ("Exposure", "ShadowCompr"); + + if (pedited) { + pedited->toneCurve.shcompr = true; + } + } + + // load highlight recovery settings + if (toneCurve.shcompr > 100) { + toneCurve.shcompr = 100; // older pp3 files can have values above 100. + } + + if (keyFile.has_key ("Exposure", "CurveMode")) { + Glib::ustring sMode = keyFile.get_string ("Exposure", "CurveMode"); + + if (sMode == "Standard") { + toneCurve.curveMode = ToneCurveParams::TC_MODE_STD; + } else if (sMode == "FilmLike") { + toneCurve.curveMode = ToneCurveParams::TC_MODE_FILMLIKE; + } else if (sMode == "SatAndValueBlending") { + toneCurve.curveMode = ToneCurveParams::TC_MODE_SATANDVALBLENDING; + } else if (sMode == "WeightedStd") { + toneCurve.curveMode = ToneCurveParams::TC_MODE_WEIGHTEDSTD; + } else if (sMode == "Luminance") { + toneCurve.curveMode = ToneCurveParams::TC_MODE_LUMINANCE; + } else if (sMode == "Perceptual") { + toneCurve.curveMode = ToneCurveParams::TC_MODE_PERCEPTUAL; + } + + if (pedited) { + pedited->toneCurve.curveMode = true; + } + } + + if (keyFile.has_key ("Exposure", "CurveMode2")) { + Glib::ustring sMode = keyFile.get_string ("Exposure", "CurveMode2"); + + if (sMode == "Standard") { + toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD; + } else if (sMode == "FilmLike") { + toneCurve.curveMode2 = ToneCurveParams::TC_MODE_FILMLIKE; + } else if (sMode == "SatAndValueBlending") { + toneCurve.curveMode2 = ToneCurveParams::TC_MODE_SATANDVALBLENDING; + } else if (sMode == "WeightedStd") { + toneCurve.curveMode2 = ToneCurveParams::TC_MODE_WEIGHTEDSTD; + } else if (sMode == "Luminance") { + toneCurve.curveMode2 = ToneCurveParams::TC_MODE_LUMINANCE; + } else if (sMode == "Perceptual") { + toneCurve.curveMode2 = ToneCurveParams::TC_MODE_PERCEPTUAL; + } + + if (pedited) { + pedited->toneCurve.curveMode2 = true; + } + } + + if (ppVersion > 200) { + if (keyFile.has_key ("Exposure", "Curve")) { + toneCurve.curve = keyFile.get_double_list ("Exposure", "Curve"); + + if (pedited) { + pedited->toneCurve.curve = true; + } + } + + if (keyFile.has_key ("Exposure", "Curve2")) { + toneCurve.curve2 = keyFile.get_double_list ("Exposure", "Curve2"); + + if (pedited) { + pedited->toneCurve.curve2 = true; + } + } + } } - else { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Sharpening", "Threshold"); - sharpening.threshold.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 2000), min(thresh.data()[3], 2000)); + + if (keyFile.has_group ("HLRecovery")) { + if (keyFile.has_key ("HLRecovery", "Enabled")) { + toneCurve.hrenabled = keyFile.get_boolean ("HLRecovery", "Enabled"); + + if (pedited) { + pedited->toneCurve.hrenabled = true; + } + } + + if (keyFile.has_key ("HLRecovery", "Method")) { + toneCurve.method = keyFile.get_string ("HLRecovery", "Method"); + + if (pedited) { + pedited->toneCurve.method = true; + } + } } - if (pedited) pedited->sharpening.threshold = true; - } - if (keyFile.has_key ("Sharpening", "OnlyEdges")) { sharpening.edgesonly = keyFile.get_boolean ("Sharpening", "OnlyEdges"); if (pedited) pedited->sharpening.edgesonly = true; } - if (keyFile.has_key ("Sharpening", "EdgedetectionRadius")) { sharpening.edges_radius = keyFile.get_double ("Sharpening", "EdgedetectionRadius"); if (pedited) pedited->sharpening.edges_radius = true; } - if (keyFile.has_key ("Sharpening", "EdgeTolerance")) { sharpening.edges_tolerance = keyFile.get_integer ("Sharpening", "EdgeTolerance"); if (pedited) pedited->sharpening.edges_tolerance = true; } - if (keyFile.has_key ("Sharpening", "HalocontrolEnabled")) { sharpening.halocontrol = keyFile.get_boolean ("Sharpening", "HalocontrolEnabled"); if (pedited) pedited->sharpening.halocontrol = true; } - if (keyFile.has_key ("Sharpening", "HalocontrolAmount")) { sharpening.halocontrol_amount = keyFile.get_integer ("Sharpening", "HalocontrolAmount"); if (pedited) pedited->sharpening.halocontrol_amount = true; } - if (keyFile.has_key ("Sharpening", "Method")) { sharpening.method = keyFile.get_string ("Sharpening", "Method"); if (pedited) pedited->sharpening.method = true; } - if (keyFile.has_key ("Sharpening", "DeconvRadius")) { sharpening.deconvradius = keyFile.get_double ("Sharpening", "DeconvRadius"); if (pedited) pedited->sharpening.deconvradius = true; } - if (keyFile.has_key ("Sharpening", "DeconvAmount")) { sharpening.deconvamount = keyFile.get_integer ("Sharpening", "DeconvAmount"); if (pedited) pedited->sharpening.deconvamount = true; } - if (keyFile.has_key ("Sharpening", "DeconvDamping")) { sharpening.deconvdamping = keyFile.get_integer ("Sharpening", "DeconvDamping"); if (pedited) pedited->sharpening.deconvdamping = true; } - if (keyFile.has_key ("Sharpening", "DeconvIterations")) { sharpening.deconviter = keyFile.get_integer ("Sharpening", "DeconvIterations"); if (pedited) pedited->sharpening.deconviter = true; } -} - // load edge sharpening -if (keyFile.has_group ("SharpenEdge")) { - if (keyFile.has_key ("SharpenEdge", "Enabled")) { sharpenEdge.enabled = keyFile.get_boolean ("SharpenEdge", "Enabled"); if (pedited) pedited->sharpenEdge.enabled = true; } - if (keyFile.has_key ("SharpenEdge", "Passes")) { sharpenEdge.passes = keyFile.get_integer ("SharpenEdge", "Passes"); if (pedited) pedited->sharpenEdge.passes = true; } - if (keyFile.has_key ("SharpenEdge", "Strength")) { sharpenEdge.amount = keyFile.get_double ("SharpenEdge", "Strength"); if (pedited) pedited->sharpenEdge.amount = true; } - if (keyFile.has_key ("SharpenEdge", "ThreeChannels")) { sharpenEdge.threechannels = keyFile.get_boolean ("SharpenEdge", "ThreeChannels"); if (pedited) pedited->sharpenEdge.threechannels = true; } -} + // load channel mixer curve + if (keyFile.has_group ("Channel Mixer")) { + if (keyFile.has_key ("Channel Mixer", "Red") && keyFile.has_key ("Channel Mixer", "Green") && keyFile.has_key ("Channel Mixer", "Blue")) { + if (pedited) { + pedited->chmixer.red[0] = pedited->chmixer.red[1] = pedited->chmixer.red[2] = true; + pedited->chmixer.green[0] = pedited->chmixer.green[1] = pedited->chmixer.green[2] = true; + pedited->chmixer.blue[0] = pedited->chmixer.blue[1] = pedited->chmixer.blue[2] = true; + } - // load micro-contrast sharpening -if (keyFile.has_group ("SharpenMicro")) { - if (keyFile.has_key ("SharpenMicro", "Enabled")) { sharpenMicro.enabled = keyFile.get_boolean ("SharpenMicro", "Enabled"); if (pedited) pedited->sharpenMicro.enabled = true; } - if (keyFile.has_key ("SharpenMicro", "Matrix")) { sharpenMicro.matrix = keyFile.get_boolean ("SharpenMicro", "Matrix"); if (pedited) pedited->sharpenMicro.matrix = true; } - if (keyFile.has_key ("SharpenMicro", "Strength")) { sharpenMicro.amount = keyFile.get_double ("SharpenMicro", "Strength"); if (pedited) pedited->sharpenMicro.amount = true; } - if (keyFile.has_key ("SharpenMicro", "Uniformity")) { sharpenMicro.uniformity = keyFile.get_double ("SharpenMicro", "Uniformity"); if (pedited) pedited->sharpenMicro.uniformity = true; } -} - - // load vibrance -if (keyFile.has_group ("Vibrance")) { - if (keyFile.has_key ("Vibrance", "Enabled")) { vibrance.enabled = keyFile.get_boolean ("Vibrance", "Enabled"); if (pedited) pedited->vibrance.enabled = true; } - if (keyFile.has_key ("Vibrance", "Pastels")) { vibrance.pastels = keyFile.get_integer ("Vibrance", "Pastels"); if (pedited) pedited->vibrance.pastels = true; } - if (keyFile.has_key ("Vibrance", "Saturated")) { vibrance.saturated = keyFile.get_integer ("Vibrance", "Saturated"); if (pedited) pedited->vibrance.saturated = true; } - if (keyFile.has_key ("Vibrance", "PSThreshold")) { - if (ppVersion < 302) { - int thresh = keyFile.get_integer ("Vibrance", "PSThreshold"); - vibrance.psthreshold.setValues(thresh, thresh); + Glib::ArrayHandle rmix = keyFile.get_integer_list ("Channel Mixer", "Red"); + Glib::ArrayHandle gmix = keyFile.get_integer_list ("Channel Mixer", "Green"); + Glib::ArrayHandle bmix = keyFile.get_integer_list ("Channel Mixer", "Blue"); + memcpy (chmixer.red, rmix.data(), 3 * sizeof(int)); + memcpy (chmixer.green, gmix.data(), 3 * sizeof(int)); + memcpy (chmixer.blue, bmix.data(), 3 * sizeof(int)); + } } - else { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Vibrance", "PSThreshold"); - vibrance.psthreshold.setValues(thresh.data()[0], thresh.data()[1]); + + // load black & white + if (keyFile.has_group ("Black & White")) { + if (keyFile.has_key ("Black & White", "Enabled")) { + blackwhite.enabled = keyFile.get_boolean ("Black & White", "Enabled"); + + if (pedited) { + pedited->blackwhite.enabled = true; + } + } + + if (keyFile.has_key ("Black & White", "Method")) { + blackwhite.method = keyFile.get_string ("Black & White", "Method"); + + if (pedited) { + pedited->blackwhite.method = true; + } + } + + if (keyFile.has_key ("Black & White", "Auto")) { + blackwhite.autoc = keyFile.get_boolean ("Black & White", "Auto"); + + if (pedited) { + pedited->blackwhite.autoc = true; + } + } + + if (keyFile.has_key ("Black & White", "ComplementaryColors")) { + blackwhite.enabledcc = keyFile.get_boolean ("Black & White", "ComplementaryColors"); + + if (pedited) { + pedited->blackwhite.enabledcc = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerRed")) { + blackwhite.mixerRed = keyFile.get_integer ("Black & White", "MixerRed"); + + if (pedited) { + pedited->blackwhite.mixerRed = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerOrange")) { + blackwhite.mixerOrange = keyFile.get_integer ("Black & White", "MixerOrange"); + + if (pedited) { + pedited->blackwhite.mixerOrange = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerYellow")) { + blackwhite.mixerYellow = keyFile.get_integer ("Black & White", "MixerYellow"); + + if (pedited) { + pedited->blackwhite.mixerYellow = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerGreen")) { + blackwhite.mixerGreen = keyFile.get_integer ("Black & White", "MixerGreen"); + + if (pedited) { + pedited->blackwhite.mixerGreen = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerCyan")) { + blackwhite.mixerCyan = keyFile.get_integer ("Black & White", "MixerCyan"); + + if (pedited) { + pedited->blackwhite.mixerCyan = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerBlue")) { + blackwhite.mixerBlue = keyFile.get_integer ("Black & White", "MixerBlue"); + + if (pedited) { + pedited->blackwhite.mixerBlue = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerMagenta")) { + blackwhite.mixerMagenta = keyFile.get_integer ("Black & White", "MixerMagenta"); + + if (pedited) { + pedited->blackwhite.mixerMagenta = true; + } + } + + if (keyFile.has_key ("Black & White", "MixerPurple")) { + blackwhite.mixerPurple = keyFile.get_integer ("Black & White", "MixerPurple"); + + if (pedited) { + pedited->blackwhite.mixerPurple = true; + } + } + + if (keyFile.has_key ("Black & White", "GammaRed")) { + blackwhite.gammaRed = keyFile.get_integer ("Black & White", "GammaRed"); + + if (pedited) { + pedited->blackwhite.gammaRed = true; + } + } + + if (keyFile.has_key ("Black & White", "GammaGreen")) { + blackwhite.gammaGreen = keyFile.get_integer ("Black & White", "GammaGreen"); + + if (pedited) { + pedited->blackwhite.gammaGreen = true; + } + } + + if (keyFile.has_key ("Black & White", "GammaBlue")) { + blackwhite.gammaBlue = keyFile.get_integer ("Black & White", "GammaBlue"); + + if (pedited) { + pedited->blackwhite.gammaBlue = true; + } + } + + if (keyFile.has_key ("Black & White", "Filter")) { + blackwhite.filter = keyFile.get_string ("Black & White", "Filter"); + + if (pedited) { + pedited->blackwhite.filter = true; + } + } + + if (keyFile.has_key ("Black & White", "Setting")) { + blackwhite.setting = keyFile.get_string ("Black & White", "Setting"); + + if (pedited) { + pedited->blackwhite.setting = true; + } + } + + if (keyFile.has_key ("Black & White", "LuminanceCurve")) { + blackwhite.luminanceCurve = keyFile.get_double_list ("Black & White", "LuminanceCurve"); + + if (pedited) { + pedited->blackwhite.luminanceCurve = true; + } + } + + if (keyFile.has_key ("Black & White", "BeforeCurve")) { + blackwhite.beforeCurve = keyFile.get_double_list ("Black & White", "BeforeCurve"); + + if (pedited) { + pedited->blackwhite.beforeCurve = true; + } + } + + if (keyFile.has_key ("Black & White", "Algorithm")) { + blackwhite.algo = keyFile.get_string ("Black & White", "Algorithm"); + + if (pedited) { + pedited->blackwhite.algo = true; + } + } + + if (keyFile.has_key ("Black & White", "BeforeCurveMode")) { + Glib::ustring sMode = keyFile.get_string ("Black & White", "BeforeCurveMode"); + + if (sMode == "Standard") { + blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_STD_BW; + } else if (sMode == "FilmLike") { + blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_FILMLIKE_BW; + } else if (sMode == "SatAndValueBlending") { + blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW; + } else if (sMode == "WeightedStd") { + blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW; + } + + if (pedited) { + pedited->blackwhite.beforeCurveMode = true; + } + } + + if (keyFile.has_key ("Black & White", "AfterCurve")) { + blackwhite.afterCurve = keyFile.get_double_list ("Black & White", "AfterCurve"); + + if (pedited) { + pedited->blackwhite.afterCurve = true; + } + } + + if (keyFile.has_key ("Black & White", "AfterCurveMode")) { + Glib::ustring sMode2 = keyFile.get_string ("Black & White", "AfterCurveMode"); + + if (sMode2 == "Standard") { + blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_STD_BW; + } else if (sMode2 == "WeightedStd") { + blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW; + } + + if (pedited) { + pedited->blackwhite.afterCurveMode = true; + } + } } - if (pedited) pedited->vibrance.psthreshold = true; - } - if (keyFile.has_key ("Vibrance", "ProtectSkins")) { vibrance.protectskins = keyFile.get_boolean ("Vibrance", "ProtectSkins"); if (pedited) pedited->vibrance.protectskins = true; } - if (keyFile.has_key ("Vibrance", "AvoidColorShift")) { vibrance.avoidcolorshift = keyFile.get_boolean ("Vibrance", "AvoidColorShift"); if (pedited) pedited->vibrance.avoidcolorshift = true; } - if (keyFile.has_key ("Vibrance", "PastSatTog")) { vibrance.pastsattog = keyFile.get_boolean ("Vibrance", "PastSatTog"); if (pedited) pedited->vibrance.pastsattog = true; } - if (keyFile.has_key ("Vibrance", "SkinTonesCurve")) { vibrance.skintonescurve = keyFile.get_double_list ("Vibrance", "SkinTonesCurve"); if (pedited) pedited->vibrance.skintonescurve = true; } -} - // load colorBoost -/*if (keyFile.has_group ("Color Boost")) { - if (keyFile.has_key ("Color Boost", "Amount")) { colorBoost.amount = keyFile.get_integer ("Color Boost", "Amount"); if (pedited) pedited->colorBoost.amount = true; } - else { - int a=0, b=0; - if (keyFile.has_key ("Color Boost", "ChannelA")) { a = keyFile.get_integer ("Color Boost", "ChannelA"); } - if (keyFile.has_key ("Color Boost", "ChannelB")) { b = keyFile.get_integer ("Color Boost", "ChannelB"); } - colorBoost.amount = (a+b) / 2; - if (pedited) pedited->colorBoost.amount = true; - } - if (keyFile.has_key ("Color Boost", "AvoidColorClipping")) { colorBoost.avoidclip = keyFile.get_boolean ("Color Boost", "AvoidColorClipping"); if (pedited) pedited->colorBoost.avoidclip = true; } - if (keyFile.has_key ("Color Boost", "SaturationLimiter")) { colorBoost.enable_saturationlimiter= keyFile.get_boolean ("Color Boost", "SaturationLimiter"); if (pedited) pedited->colorBoost.enable_saturationlimiter = true; } - if (keyFile.has_key ("Color Boost", "SaturationLimit")) { colorBoost.saturationlimit = keyFile.get_double ("Color Boost", "SaturationLimit"); if (pedited) pedited->colorBoost.saturationlimit = true; } -}*/ + // load luma curve + if (keyFile.has_group ("Luminance Curve")) { + if (keyFile.has_key ("Luminance Curve", "Brightness")) { + labCurve.brightness = keyFile.get_integer ("Luminance Curve", "Brightness"); - // load wb -if (keyFile.has_group ("White Balance")) { - if (keyFile.has_key ("White Balance", "Setting")) { wb.method = keyFile.get_string ("White Balance", "Setting"); if (pedited) pedited->wb.method = true; } - if (keyFile.has_key ("White Balance", "Temperature")) { wb.temperature = keyFile.get_integer ("White Balance", "Temperature"); if (pedited) pedited->wb.temperature = true; } - if (keyFile.has_key ("White Balance", "Green")) { wb.green = keyFile.get_double ("White Balance", "Green"); if (pedited) pedited->wb.green = true; } - if (keyFile.has_key ("White Balance", "Equal")) { wb.equal = keyFile.get_double ("White Balance", "Equal"); if (pedited) pedited->wb.equal = true; } -} + if (pedited) { + pedited->labCurve.brightness = true; + } + } - // load colorShift -/*if (keyFile.has_group ("Color Shift")) { - if (keyFile.has_key ("Color Shift", "ChannelA")) { colorShift.a = keyFile.get_double ("Color Shift", "ChannelA"); if (pedited) pedited->colorShift.a = true; } - if (keyFile.has_key ("Color Shift", "ChannelB")) { colorShift.b = keyFile.get_double ("Color Shift", "ChannelB"); if (pedited) pedited->colorShift.b = true; } -}*/ + if (keyFile.has_key ("Luminance Curve", "Contrast")) { + labCurve.contrast = keyFile.get_integer ("Luminance Curve", "Contrast"); + + if (pedited) { + pedited->labCurve.contrast = true; + } + } + + if (ppVersion < 303) { + // transform Saturation into Chromaticity + // if Saturation == 0, should we set BWToning on? + if (keyFile.has_key ("Luminance Curve", "Saturation")) { + labCurve.chromaticity = keyFile.get_integer ("Luminance Curve", "Saturation"); + + if (pedited) { + pedited->labCurve.chromaticity = true; + } + } + + // transform AvoidColorClipping into AvoidColorShift + if (keyFile.has_key ("Luminance Curve", "AvoidColorClipping")) { + labCurve.avoidcolorshift = keyFile.get_boolean ("Luminance Curve", "AvoidColorClipping"); + + if (pedited) { + pedited->labCurve.avoidcolorshift = true; + } + } + } else { + if (keyFile.has_key ("Luminance Curve", "Chromaticity")) { + labCurve.chromaticity = keyFile.get_integer ("Luminance Curve", "Chromaticity"); + + if (pedited) { + pedited->labCurve.chromaticity = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "AvoidColorShift")) { + labCurve.avoidcolorshift = keyFile.get_boolean ("Luminance Curve", "AvoidColorShift"); + + if (pedited) { + pedited->labCurve.avoidcolorshift = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "RedAndSkinTonesProtection")) { + labCurve.rstprotection = keyFile.get_double ("Luminance Curve", "RedAndSkinTonesProtection"); + + if (pedited) { + pedited->labCurve.rstprotection = true; + } + } + } + + if (keyFile.has_key ("Luminance Curve", "LCredsk")) { + labCurve.lcredsk = keyFile.get_boolean ("Luminance Curve", "LCredsk"); + + if (pedited) { + pedited->labCurve.lcredsk = true; + } + } + + if (ppVersion < 314) + + // Backward compatibility: If BWtoning is true, Chromaticity has to be set to -100, which will produce the same effect + // and will enable the b&w toning mode ('a' & 'b' curves) + if (keyFile.has_key ("Luminance Curve", "BWtoning")) { + if ( keyFile.get_boolean ("Luminance Curve", "BWtoning")) { + labCurve.chromaticity = -100; + + if (pedited) { + pedited->labCurve.chromaticity = true; + } + } + } + + if (keyFile.has_key ("Luminance Curve", "LCurve")) { + labCurve.lcurve = keyFile.get_double_list ("Luminance Curve", "LCurve"); + + if (pedited) { + pedited->labCurve.lcurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "aCurve")) { + labCurve.acurve = keyFile.get_double_list ("Luminance Curve", "aCurve"); + + if (pedited) { + pedited->labCurve.acurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "bCurve")) { + labCurve.bcurve = keyFile.get_double_list ("Luminance Curve", "bCurve"); + + if (pedited) { + pedited->labCurve.bcurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "ccCurve")) { + labCurve.cccurve = keyFile.get_double_list ("Luminance Curve", "ccCurve"); + + if (pedited) { + pedited->labCurve.cccurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "chCurve")) { + labCurve.chcurve = keyFile.get_double_list ("Luminance Curve", "chCurve"); + + if (pedited) { + pedited->labCurve.chcurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "lhCurve")) { + labCurve.lhcurve = keyFile.get_double_list ("Luminance Curve", "lhCurve"); + + if (pedited) { + pedited->labCurve.lhcurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "hhCurve")) { + labCurve.hhcurve = keyFile.get_double_list ("Luminance Curve", "hhCurve"); + + if (pedited) { + pedited->labCurve.hhcurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "LcCurve")) { + labCurve.lccurve = keyFile.get_double_list ("Luminance Curve", "LcCurve"); + + if (pedited) { + pedited->labCurve.lccurve = true; + } + } + + if (keyFile.has_key ("Luminance Curve", "ClCurve")) { + labCurve.clcurve = keyFile.get_double_list ("Luminance Curve", "ClCurve"); + + if (pedited) { + pedited->labCurve.clcurve = true; + } + } + + } + + // load sharpening + if (keyFile.has_group ("Sharpening")) { + if (keyFile.has_key ("Sharpening", "Enabled")) { + sharpening.enabled = keyFile.get_boolean ("Sharpening", "Enabled"); + + if (pedited) { + pedited->sharpening.enabled = true; + } + } + + if (keyFile.has_key ("Sharpening", "Radius")) { + sharpening.radius = keyFile.get_double ("Sharpening", "Radius"); + + if (pedited) { + pedited->sharpening.radius = true; + } + } + + if (keyFile.has_key ("Sharpening", "Amount")) { + sharpening.amount = keyFile.get_integer ("Sharpening", "Amount"); + + if (pedited) { + pedited->sharpening.amount = true; + } + } + + if (keyFile.has_key ("Sharpening", "Threshold")) { + if (ppVersion < 302) { + int thresh = min(keyFile.get_integer ("Sharpening", "Threshold"), 2000); + sharpening.threshold.setValues(thresh, thresh, 2000, 2000); // TODO: 2000 is the maximum value and is taken of rtgui/sharpening.cc ; should be changed by the tool modularization + } else { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Sharpening", "Threshold"); + sharpening.threshold.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 2000), min(thresh.data()[3], 2000)); + } + + if (pedited) { + pedited->sharpening.threshold = true; + } + } + + if (keyFile.has_key ("Sharpening", "OnlyEdges")) { + sharpening.edgesonly = keyFile.get_boolean ("Sharpening", "OnlyEdges"); + + if (pedited) { + pedited->sharpening.edgesonly = true; + } + } + + if (keyFile.has_key ("Sharpening", "EdgedetectionRadius")) { + sharpening.edges_radius = keyFile.get_double ("Sharpening", "EdgedetectionRadius"); + + if (pedited) { + pedited->sharpening.edges_radius = true; + } + } + + if (keyFile.has_key ("Sharpening", "EdgeTolerance")) { + sharpening.edges_tolerance = keyFile.get_integer ("Sharpening", "EdgeTolerance"); + + if (pedited) { + pedited->sharpening.edges_tolerance = true; + } + } + + if (keyFile.has_key ("Sharpening", "HalocontrolEnabled")) { + sharpening.halocontrol = keyFile.get_boolean ("Sharpening", "HalocontrolEnabled"); + + if (pedited) { + pedited->sharpening.halocontrol = true; + } + } + + if (keyFile.has_key ("Sharpening", "HalocontrolAmount")) { + sharpening.halocontrol_amount = keyFile.get_integer ("Sharpening", "HalocontrolAmount"); + + if (pedited) { + pedited->sharpening.halocontrol_amount = true; + } + } + + if (keyFile.has_key ("Sharpening", "Method")) { + sharpening.method = keyFile.get_string ("Sharpening", "Method"); + + if (pedited) { + pedited->sharpening.method = true; + } + } + + if (keyFile.has_key ("Sharpening", "DeconvRadius")) { + sharpening.deconvradius = keyFile.get_double ("Sharpening", "DeconvRadius"); + + if (pedited) { + pedited->sharpening.deconvradius = true; + } + } + + if (keyFile.has_key ("Sharpening", "DeconvAmount")) { + sharpening.deconvamount = keyFile.get_integer ("Sharpening", "DeconvAmount"); + + if (pedited) { + pedited->sharpening.deconvamount = true; + } + } + + if (keyFile.has_key ("Sharpening", "DeconvDamping")) { + sharpening.deconvdamping = keyFile.get_integer ("Sharpening", "DeconvDamping"); + + if (pedited) { + pedited->sharpening.deconvdamping = true; + } + } + + if (keyFile.has_key ("Sharpening", "DeconvIterations")) { + sharpening.deconviter = keyFile.get_integer ("Sharpening", "DeconvIterations"); + + if (pedited) { + pedited->sharpening.deconviter = true; + } + } + } + + // load edge sharpening + if (keyFile.has_group ("SharpenEdge")) { + if (keyFile.has_key ("SharpenEdge", "Enabled")) { + sharpenEdge.enabled = keyFile.get_boolean ("SharpenEdge", "Enabled"); + + if (pedited) { + pedited->sharpenEdge.enabled = true; + } + } + + if (keyFile.has_key ("SharpenEdge", "Passes")) { + sharpenEdge.passes = keyFile.get_integer ("SharpenEdge", "Passes"); + + if (pedited) { + pedited->sharpenEdge.passes = true; + } + } + + if (keyFile.has_key ("SharpenEdge", "Strength")) { + sharpenEdge.amount = keyFile.get_double ("SharpenEdge", "Strength"); + + if (pedited) { + pedited->sharpenEdge.amount = true; + } + } + + if (keyFile.has_key ("SharpenEdge", "ThreeChannels")) { + sharpenEdge.threechannels = keyFile.get_boolean ("SharpenEdge", "ThreeChannels"); + + if (pedited) { + pedited->sharpenEdge.threechannels = true; + } + } + } + + // load micro-contrast sharpening + if (keyFile.has_group ("SharpenMicro")) { + if (keyFile.has_key ("SharpenMicro", "Enabled")) { + sharpenMicro.enabled = keyFile.get_boolean ("SharpenMicro", "Enabled"); + + if (pedited) { + pedited->sharpenMicro.enabled = true; + } + } + + if (keyFile.has_key ("SharpenMicro", "Matrix")) { + sharpenMicro.matrix = keyFile.get_boolean ("SharpenMicro", "Matrix"); + + if (pedited) { + pedited->sharpenMicro.matrix = true; + } + } + + if (keyFile.has_key ("SharpenMicro", "Strength")) { + sharpenMicro.amount = keyFile.get_double ("SharpenMicro", "Strength"); + + if (pedited) { + pedited->sharpenMicro.amount = true; + } + } + + if (keyFile.has_key ("SharpenMicro", "Uniformity")) { + sharpenMicro.uniformity = keyFile.get_double ("SharpenMicro", "Uniformity"); + + if (pedited) { + pedited->sharpenMicro.uniformity = true; + } + } + } + + // load vibrance + if (keyFile.has_group ("Vibrance")) { + if (keyFile.has_key ("Vibrance", "Enabled")) { + vibrance.enabled = keyFile.get_boolean ("Vibrance", "Enabled"); + + if (pedited) { + pedited->vibrance.enabled = true; + } + } + + if (keyFile.has_key ("Vibrance", "Pastels")) { + vibrance.pastels = keyFile.get_integer ("Vibrance", "Pastels"); + + if (pedited) { + pedited->vibrance.pastels = true; + } + } + + if (keyFile.has_key ("Vibrance", "Saturated")) { + vibrance.saturated = keyFile.get_integer ("Vibrance", "Saturated"); + + if (pedited) { + pedited->vibrance.saturated = true; + } + } + + if (keyFile.has_key ("Vibrance", "PSThreshold")) { + if (ppVersion < 302) { + int thresh = keyFile.get_integer ("Vibrance", "PSThreshold"); + vibrance.psthreshold.setValues(thresh, thresh); + } else { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Vibrance", "PSThreshold"); + vibrance.psthreshold.setValues(thresh.data()[0], thresh.data()[1]); + } + + if (pedited) { + pedited->vibrance.psthreshold = true; + } + } + + if (keyFile.has_key ("Vibrance", "ProtectSkins")) { + vibrance.protectskins = keyFile.get_boolean ("Vibrance", "ProtectSkins"); + + if (pedited) { + pedited->vibrance.protectskins = true; + } + } + + if (keyFile.has_key ("Vibrance", "AvoidColorShift")) { + vibrance.avoidcolorshift = keyFile.get_boolean ("Vibrance", "AvoidColorShift"); + + if (pedited) { + pedited->vibrance.avoidcolorshift = true; + } + } + + if (keyFile.has_key ("Vibrance", "PastSatTog")) { + vibrance.pastsattog = keyFile.get_boolean ("Vibrance", "PastSatTog"); + + if (pedited) { + pedited->vibrance.pastsattog = true; + } + } + + if (keyFile.has_key ("Vibrance", "SkinTonesCurve")) { + vibrance.skintonescurve = keyFile.get_double_list ("Vibrance", "SkinTonesCurve"); + + if (pedited) { + pedited->vibrance.skintonescurve = true; + } + } + } + + // load colorBoost + /*if (keyFile.has_group ("Color Boost")) { + if (keyFile.has_key ("Color Boost", "Amount")) { colorBoost.amount = keyFile.get_integer ("Color Boost", "Amount"); if (pedited) pedited->colorBoost.amount = true; } + else { + int a=0, b=0; + if (keyFile.has_key ("Color Boost", "ChannelA")) { a = keyFile.get_integer ("Color Boost", "ChannelA"); } + if (keyFile.has_key ("Color Boost", "ChannelB")) { b = keyFile.get_integer ("Color Boost", "ChannelB"); } + colorBoost.amount = (a+b) / 2; + if (pedited) pedited->colorBoost.amount = true; + } + if (keyFile.has_key ("Color Boost", "AvoidColorClipping")) { colorBoost.avoidclip = keyFile.get_boolean ("Color Boost", "AvoidColorClipping"); if (pedited) pedited->colorBoost.avoidclip = true; } + if (keyFile.has_key ("Color Boost", "SaturationLimiter")) { colorBoost.enable_saturationlimiter= keyFile.get_boolean ("Color Boost", "SaturationLimiter"); if (pedited) pedited->colorBoost.enable_saturationlimiter = true; } + if (keyFile.has_key ("Color Boost", "SaturationLimit")) { colorBoost.saturationlimit = keyFile.get_double ("Color Boost", "SaturationLimit"); if (pedited) pedited->colorBoost.saturationlimit = true; } + }*/ + + // load wb + if (keyFile.has_group ("White Balance")) { + if (keyFile.has_key ("White Balance", "Setting")) { + wb.method = keyFile.get_string ("White Balance", "Setting"); + + if (pedited) { + pedited->wb.method = true; + } + } + + if (keyFile.has_key ("White Balance", "Temperature")) { + wb.temperature = keyFile.get_integer ("White Balance", "Temperature"); + + if (pedited) { + pedited->wb.temperature = true; + } + } + + if (keyFile.has_key ("White Balance", "Green")) { + wb.green = keyFile.get_double ("White Balance", "Green"); + + if (pedited) { + pedited->wb.green = true; + } + } + + if (keyFile.has_key ("White Balance", "Equal")) { + wb.equal = keyFile.get_double ("White Balance", "Equal"); + + if (pedited) { + pedited->wb.equal = true; + } + } + } + + // load colorShift + /*if (keyFile.has_group ("Color Shift")) { + if (keyFile.has_key ("Color Shift", "ChannelA")) { colorShift.a = keyFile.get_double ("Color Shift", "ChannelA"); if (pedited) pedited->colorShift.a = true; } + if (keyFile.has_key ("Color Shift", "ChannelB")) { colorShift.b = keyFile.get_double ("Color Shift", "ChannelB"); if (pedited) pedited->colorShift.b = true; } + }*/ + + // load defringe + if (keyFile.has_group ("Defringing")) { + if (keyFile.has_key ("Defringing", "Enabled")) { + defringe.enabled = keyFile.get_boolean ("Defringing", "Enabled"); + + if (pedited) { + pedited->defringe.enabled = true; + } + } + + if (keyFile.has_key ("Defringing", "Radius")) { + defringe.radius = keyFile.get_double ("Defringing", "Radius"); + + if (pedited) { + pedited->defringe.radius = true; + } + } + + if (keyFile.has_key ("Defringing", "Threshold")) { + defringe.threshold = (float)keyFile.get_integer ("Defringing", "Threshold"); + + if (pedited) { + pedited->defringe.threshold = true; + } + } + + if (ppVersion < 310) { + defringe.threshold = sqrt(defringe.threshold * 33.f / 5.f); + } + + if (keyFile.has_key ("Defringing", "HueCurve")) { + defringe.huecurve = keyFile.get_double_list ("Defringing", "HueCurve"); + + if (pedited) { + pedited->defringe.huecurve = true; + } + } + } + + // load colorappearance + if (keyFile.has_group ("Color appearance")) { + if (keyFile.has_key ("Color appearance", "Enabled")) { + colorappearance.enabled = keyFile.get_boolean ("Color appearance", "Enabled"); + + if (pedited) { + pedited->colorappearance.enabled = true; + } + } + + if (keyFile.has_key ("Color appearance", "Degree")) { + colorappearance.degree = keyFile.get_integer ("Color appearance", "Degree"); + + if (pedited) { + pedited->colorappearance.degree = true; + } + } + + if (keyFile.has_key ("Color appearance", "AutoDegree")) { + colorappearance.autodegree = keyFile.get_boolean ("Color appearance", "AutoDegree"); + + if (pedited) { + pedited->colorappearance.autodegree = true; + } + } + + if (keyFile.has_key ("Color appearance", "Surround")) { + colorappearance.surround = keyFile.get_string ("Color appearance", "Surround"); + + if (pedited) { + pedited->colorappearance.surround = true; + } + } - // load defringe -if (keyFile.has_group ("Defringing")) { - if (keyFile.has_key ("Defringing", "Enabled")) { defringe.enabled = keyFile.get_boolean ("Defringing", "Enabled"); if (pedited) pedited->defringe.enabled = true; } - if (keyFile.has_key ("Defringing", "Radius")) { defringe.radius = keyFile.get_double ("Defringing", "Radius"); if (pedited) pedited->defringe.radius = true; } - if (keyFile.has_key ("Defringing", "Threshold")) { defringe.threshold = (float)keyFile.get_integer ("Defringing", "Threshold"); if (pedited) pedited->defringe.threshold = true; } - if (ppVersion < 310) { - defringe.threshold = sqrt(defringe.threshold * 33.f/5.f); - } - if (keyFile.has_key ("Defringing", "HueCurve")) { defringe.huecurve = keyFile.get_double_list ("Defringing", "HueCurve"); if (pedited) pedited->defringe.huecurve = true; } -} - // load colorappearance -if (keyFile.has_group ("Color appearance")) { - if (keyFile.has_key ("Color appearance", "Enabled")) {colorappearance.enabled = keyFile.get_boolean ("Color appearance", "Enabled"); if (pedited) pedited->colorappearance.enabled = true; } - if (keyFile.has_key ("Color appearance", "Degree")) {colorappearance.degree = keyFile.get_integer ("Color appearance", "Degree"); if (pedited) pedited->colorappearance.degree = true; } - if (keyFile.has_key ("Color appearance", "AutoDegree")) {colorappearance.autodegree = keyFile.get_boolean ("Color appearance", "AutoDegree"); if (pedited) pedited->colorappearance.autodegree = true; } - if (keyFile.has_key ("Color appearance", "Surround")) {colorappearance.surround = keyFile.get_string ("Color appearance", "Surround"); if (pedited) pedited->colorappearance.surround = true; } // if (keyFile.has_key ("Color appearance", "Background")) {colorappearance.backgrd = keyFile.get_integer ("Color appearance", "Background"); if (pedited) pedited->colorappearance.backgrd = true; } - if (keyFile.has_key ("Color appearance", "AdaptLum")) {colorappearance.adaplum = keyFile.get_double ("Color appearance", "AdaptLum"); if (pedited) pedited->colorappearance.adaplum = true; } - if (keyFile.has_key ("Color appearance", "Badpixsl")) {colorappearance.badpixsl = keyFile.get_integer ("Color appearance", "Badpixsl"); if (pedited) pedited->colorappearance.badpixsl = true; } - if (keyFile.has_key ("Color appearance", "Model")) {colorappearance.wbmodel = keyFile.get_string ("Color appearance", "Model"); if (pedited) pedited->colorappearance.wbmodel = true; } - if (keyFile.has_key ("Color appearance", "Algorithm")) {colorappearance.algo = keyFile.get_string ("Color appearance", "Algorithm"); if (pedited) pedited->colorappearance.algo = true; } - if (keyFile.has_key ("Color appearance", "J-Light")) {colorappearance.jlight = keyFile.get_double ("Color appearance", "J-Light"); if (pedited) pedited->colorappearance.jlight = true; } - if (keyFile.has_key ("Color appearance", "Q-Bright")) {colorappearance.qbright = keyFile.get_double ("Color appearance", "Q-Bright"); if (pedited) pedited->colorappearance.qbright = true; } - if (keyFile.has_key ("Color appearance", "C-Chroma")) {colorappearance.chroma = keyFile.get_double ("Color appearance", "C-Chroma"); if (pedited) pedited->colorappearance.chroma = true; } - if (keyFile.has_key ("Color appearance", "S-Chroma")) {colorappearance.schroma = keyFile.get_double ("Color appearance", "S-Chroma"); if (pedited) pedited->colorappearance.schroma = true; } - if (keyFile.has_key ("Color appearance", "M-Chroma")) {colorappearance.mchroma = keyFile.get_double ("Color appearance", "M-Chroma"); if (pedited) pedited->colorappearance.mchroma = true; } - if (keyFile.has_key ("Color appearance", "RSTProtection")) {colorappearance.rstprotection = keyFile.get_double ("Color appearance", "RSTProtection"); if (pedited) pedited->colorappearance.rstprotection = true; } - if (keyFile.has_key ("Color appearance", "J-Contrast")) {colorappearance.contrast = keyFile.get_double ("Color appearance", "J-Contrast"); if (pedited) pedited->colorappearance.contrast = true; } - if (keyFile.has_key ("Color appearance", "Q-Contrast")) {colorappearance.qcontrast = keyFile.get_double ("Color appearance", "Q-Contrast"); if (pedited) pedited->colorappearance.qcontrast = true; } - if (keyFile.has_key ("Color appearance", "H-Hue")) {colorappearance.colorh = keyFile.get_double ("Color appearance", "H-Hue"); if (pedited) pedited->colorappearance.colorh = true; } - if (keyFile.has_key ("Color appearance", "AdaptScene")) {colorappearance.adapscen = keyFile.get_double ("Color appearance", "AdaptScene"); if (pedited) pedited->colorappearance.adapscen = true; } - if (keyFile.has_key ("Color appearance", "AutoAdapscen")) {colorappearance.autoadapscen = keyFile.get_boolean ("Color appearance", "AutoAdapscen"); if (pedited) pedited->colorappearance.autoadapscen = true; } - if (keyFile.has_key ("Color appearance", "SurrSource")) {colorappearance.surrsource = keyFile.get_boolean ("Color appearance", "SurrSource"); if (pedited) pedited->colorappearance.surrsource = true; } - if (keyFile.has_key ("Color appearance", "Gamut")) {colorappearance.gamut = keyFile.get_boolean ("Color appearance", "Gamut"); if (pedited) pedited->colorappearance.gamut = true; } + if (keyFile.has_key ("Color appearance", "AdaptLum")) { + colorappearance.adaplum = keyFile.get_double ("Color appearance", "AdaptLum"); + + if (pedited) { + pedited->colorappearance.adaplum = true; + } + } + + if (keyFile.has_key ("Color appearance", "Badpixsl")) { + colorappearance.badpixsl = keyFile.get_integer ("Color appearance", "Badpixsl"); + + if (pedited) { + pedited->colorappearance.badpixsl = true; + } + } + + if (keyFile.has_key ("Color appearance", "Model")) { + colorappearance.wbmodel = keyFile.get_string ("Color appearance", "Model"); + + if (pedited) { + pedited->colorappearance.wbmodel = true; + } + } + + if (keyFile.has_key ("Color appearance", "Algorithm")) { + colorappearance.algo = keyFile.get_string ("Color appearance", "Algorithm"); + + if (pedited) { + pedited->colorappearance.algo = true; + } + } + + if (keyFile.has_key ("Color appearance", "J-Light")) { + colorappearance.jlight = keyFile.get_double ("Color appearance", "J-Light"); + + if (pedited) { + pedited->colorappearance.jlight = true; + } + } + + if (keyFile.has_key ("Color appearance", "Q-Bright")) { + colorappearance.qbright = keyFile.get_double ("Color appearance", "Q-Bright"); + + if (pedited) { + pedited->colorappearance.qbright = true; + } + } + + if (keyFile.has_key ("Color appearance", "C-Chroma")) { + colorappearance.chroma = keyFile.get_double ("Color appearance", "C-Chroma"); + + if (pedited) { + pedited->colorappearance.chroma = true; + } + } + + if (keyFile.has_key ("Color appearance", "S-Chroma")) { + colorappearance.schroma = keyFile.get_double ("Color appearance", "S-Chroma"); + + if (pedited) { + pedited->colorappearance.schroma = true; + } + } + + if (keyFile.has_key ("Color appearance", "M-Chroma")) { + colorappearance.mchroma = keyFile.get_double ("Color appearance", "M-Chroma"); + + if (pedited) { + pedited->colorappearance.mchroma = true; + } + } + + if (keyFile.has_key ("Color appearance", "RSTProtection")) { + colorappearance.rstprotection = keyFile.get_double ("Color appearance", "RSTProtection"); + + if (pedited) { + pedited->colorappearance.rstprotection = true; + } + } + + if (keyFile.has_key ("Color appearance", "J-Contrast")) { + colorappearance.contrast = keyFile.get_double ("Color appearance", "J-Contrast"); + + if (pedited) { + pedited->colorappearance.contrast = true; + } + } + + if (keyFile.has_key ("Color appearance", "Q-Contrast")) { + colorappearance.qcontrast = keyFile.get_double ("Color appearance", "Q-Contrast"); + + if (pedited) { + pedited->colorappearance.qcontrast = true; + } + } + + if (keyFile.has_key ("Color appearance", "H-Hue")) { + colorappearance.colorh = keyFile.get_double ("Color appearance", "H-Hue"); + + if (pedited) { + pedited->colorappearance.colorh = true; + } + } + + if (keyFile.has_key ("Color appearance", "AdaptScene")) { + colorappearance.adapscen = keyFile.get_double ("Color appearance", "AdaptScene"); + + if (pedited) { + pedited->colorappearance.adapscen = true; + } + } + + if (keyFile.has_key ("Color appearance", "AutoAdapscen")) { + colorappearance.autoadapscen = keyFile.get_boolean ("Color appearance", "AutoAdapscen"); + + if (pedited) { + pedited->colorappearance.autoadapscen = true; + } + } + + if (keyFile.has_key ("Color appearance", "SurrSource")) { + colorappearance.surrsource = keyFile.get_boolean ("Color appearance", "SurrSource"); + + if (pedited) { + pedited->colorappearance.surrsource = true; + } + } + + if (keyFile.has_key ("Color appearance", "Gamut")) { + colorappearance.gamut = keyFile.get_boolean ("Color appearance", "Gamut"); + + if (pedited) { + pedited->colorappearance.gamut = true; + } + } + // if (keyFile.has_key ("Color appearance", "Badpix")) {colorappearance.badpix = keyFile.get_boolean ("Color appearance", "Badpix"); if (pedited) pedited->colorappearance.badpix = true; } - if (keyFile.has_key ("Color appearance", "Datacie")) {colorappearance.datacie = keyFile.get_boolean ("Color appearance", "Datacie"); if (pedited) pedited->colorappearance.datacie = true; } - if (keyFile.has_key ("Color appearance", "Tonecie")) {colorappearance.tonecie = keyFile.get_boolean ("Color appearance", "Tonecie"); if (pedited) pedited->colorappearance.tonecie = true; } + if (keyFile.has_key ("Color appearance", "Datacie")) { + colorappearance.datacie = keyFile.get_boolean ("Color appearance", "Datacie"); + + if (pedited) { + pedited->colorappearance.datacie = true; + } + } + + if (keyFile.has_key ("Color appearance", "Tonecie")) { + colorappearance.tonecie = keyFile.get_boolean ("Color appearance", "Tonecie"); + + if (pedited) { + pedited->colorappearance.tonecie = true; + } + } + // if (keyFile.has_key ("Color appearance", "Sharpcie")) {colorappearance.sharpcie = keyFile.get_boolean ("Color appearance", "Sharpcie"); if (pedited) pedited->colorappearance.sharpcie = true; } - if (keyFile.has_key ("Color appearance", "CurveMode")) { - Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode"); - if (sMode == "Lightness") colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT; - else if (sMode == "Brightness") colorappearance.curveMode = ColorAppearanceParams::TC_MODE_BRIGHT; - if (pedited) pedited->colorappearance.curveMode = true; - } - if (keyFile.has_key ("Color appearance", "CurveMode2")) { - Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode2"); - if (sMode == "Lightness") colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT; - else if (sMode == "Brightness") colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_BRIGHT; - if (pedited) pedited->colorappearance.curveMode2 = true; - } - if (keyFile.has_key ("Color appearance", "CurveMode3")) { - Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode3"); - if (sMode == "Chroma") colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA; - else if (sMode == "Saturation") colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_SATUR; - else if (sMode == "Colorfullness") colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_COLORF; + if (keyFile.has_key ("Color appearance", "CurveMode")) { + Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode"); - if (pedited) pedited->colorappearance.curveMode3 = true; - } - - if (ppVersion>200) { - if (keyFile.has_key ("Color appearance", "Curve")) { colorappearance.curve = keyFile.get_double_list ("Color appearance", "Curve"); if (pedited) pedited->colorappearance.curve = true; } - if (keyFile.has_key ("Color appearance", "Curve2")) { colorappearance.curve2 = keyFile.get_double_list ("Color appearance", "Curve2"); if (pedited) pedited->colorappearance.curve2 = true; } - if (keyFile.has_key ("Color appearance", "Curve3")) { colorappearance.curve3 = keyFile.get_double_list ("Color appearance", "Curve3"); if (pedited) pedited->colorappearance.curve3 = true; } - } - - } + if (sMode == "Lightness") { + colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT; + } else if (sMode == "Brightness") { + colorappearance.curveMode = ColorAppearanceParams::TC_MODE_BRIGHT; + } - // load impulseDenoise -if (keyFile.has_group ("Impulse Denoising")) { - if (keyFile.has_key ("Impulse Denoising", "Enabled")) { impulseDenoise.enabled = keyFile.get_boolean ("Impulse Denoising", "Enabled"); if (pedited) pedited->impulseDenoise.enabled = true; } - if (keyFile.has_key ("Impulse Denoising", "Threshold")) { impulseDenoise.thresh = keyFile.get_integer ("Impulse Denoising", "Threshold"); if (pedited) pedited->impulseDenoise.thresh = true; } -} + if (pedited) { + pedited->colorappearance.curveMode = true; + } + } - // load dirpyrDenoise -if (keyFile.has_group ("Directional Pyramid Denoising")) {//TODO: No longer an accurate description for FT denoise - if (keyFile.has_key ("Directional Pyramid Denoising", "Enabled")) { dirpyrDenoise.enabled = keyFile.get_boolean ("Directional Pyramid Denoising", "Enabled"); if (pedited) pedited->dirpyrDenoise.enabled = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Enhance")) { dirpyrDenoise.enhance = keyFile.get_boolean ("Directional Pyramid Denoising", "Enhance"); if (pedited) pedited->dirpyrDenoise.enhance = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Median")) { dirpyrDenoise.median = keyFile.get_boolean ("Directional Pyramid Denoising", "Median"); if (pedited) pedited->dirpyrDenoise.median = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Auto")) { dirpyrDenoise.autochroma = keyFile.get_boolean ("Directional Pyramid Denoising", "Auto"); if (pedited) pedited->dirpyrDenoise.autochroma = true; } - // if (keyFile.has_key ("Directional Pyramid Denoising", "Perform")) { dirpyrDenoise.perform = keyFile.get_boolean ("Directional Pyramid Denoising", "Perform"); if (pedited) pedited->dirpyrDenoise.perform = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Luma")) { dirpyrDenoise.luma = keyFile.get_double ("Directional Pyramid Denoising", "Luma"); if (pedited) pedited->dirpyrDenoise.luma = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Ldetail")) { dirpyrDenoise.Ldetail = keyFile.get_double ("Directional Pyramid Denoising", "Ldetail"); if (pedited) pedited->dirpyrDenoise.Ldetail = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Chroma")) { dirpyrDenoise.chroma = keyFile.get_double ("Directional Pyramid Denoising", "Chroma"); if (pedited) pedited->dirpyrDenoise.chroma = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Method")) {dirpyrDenoise.dmethod = keyFile.get_string ("Directional Pyramid Denoising", "Method"); if (pedited) pedited->dirpyrDenoise.dmethod = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "LMethod")) {dirpyrDenoise.Lmethod = keyFile.get_string ("Directional Pyramid Denoising", "LMethod"); if (pedited) pedited->dirpyrDenoise.Lmethod = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "CMethod")) {dirpyrDenoise.Cmethod = keyFile.get_string ("Directional Pyramid Denoising", "CMethod"); if (pedited) pedited->dirpyrDenoise.Cmethod = true; } - // never load 'auto chroma preview mode' from pp3 - if(dirpyrDenoise.Cmethod=="PRE") - dirpyrDenoise.Cmethod = "MAN"; - if (keyFile.has_key ("Directional Pyramid Denoising", "C2Method")) {dirpyrDenoise.C2method = keyFile.get_string ("Directional Pyramid Denoising", "C2Method"); if (pedited) pedited->dirpyrDenoise.C2method = true; } - if(dirpyrDenoise.C2method=="PREV") - dirpyrDenoise.C2method = "MANU"; - if (keyFile.has_key ("Directional Pyramid Denoising", "SMethod")) {dirpyrDenoise.smethod = keyFile.get_string ("Directional Pyramid Denoising", "SMethod"); if (pedited) pedited->dirpyrDenoise.smethod = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "MedMethod")) {dirpyrDenoise.medmethod = keyFile.get_string ("Directional Pyramid Denoising", "MedMethod"); if (pedited) pedited->dirpyrDenoise.medmethod = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "MethodMed")) {dirpyrDenoise.methodmed = keyFile.get_string ("Directional Pyramid Denoising", "MethodMed"); if (pedited) pedited->dirpyrDenoise.methodmed = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "RGBMethod")) {dirpyrDenoise.rgbmethod = keyFile.get_string ("Directional Pyramid Denoising", "RGBMethod"); if (pedited) pedited->dirpyrDenoise.rgbmethod = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "LCurve")) {dirpyrDenoise.lcurve = keyFile.get_double_list ("Directional Pyramid Denoising", "LCurve"); if (pedited) pedited->dirpyrDenoise.lcurve = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "CCCurve")) {dirpyrDenoise.cccurve = keyFile.get_double_list ("Directional Pyramid Denoising", "CCCurve"); if (pedited) pedited->dirpyrDenoise.cccurve = true; } + if (keyFile.has_key ("Color appearance", "CurveMode2")) { + Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode2"); - if (keyFile.has_key ("Directional Pyramid Denoising", "Redchro")) { dirpyrDenoise.redchro = keyFile.get_double ("Directional Pyramid Denoising", "Redchro"); if (pedited) pedited->dirpyrDenoise.redchro = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Bluechro")) { dirpyrDenoise.bluechro = keyFile.get_double ("Directional Pyramid Denoising", "Bluechro"); if (pedited) pedited->dirpyrDenoise.bluechro = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Gamma")) { dirpyrDenoise.gamma = keyFile.get_double ("Directional Pyramid Denoising", "Gamma"); if (pedited) pedited->dirpyrDenoise.gamma = true; } - if (keyFile.has_key ("Directional Pyramid Denoising", "Passes")) { dirpyrDenoise.passes = keyFile.get_integer ("Directional Pyramid Denoising", "Passes"); if (pedited) pedited->dirpyrDenoise.passes = true; } -} + if (sMode == "Lightness") { + colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT; + } else if (sMode == "Brightness") { + colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_BRIGHT; + } - //Load EPD. -if (keyFile.has_group ("EPD")) { - if(keyFile.has_key("EPD", "Enabled")) { epd.enabled = keyFile.get_boolean ("EPD", "Enabled"); if (pedited) pedited->epd.enabled = true; } - if(keyFile.has_key("EPD", "Strength")) { epd.strength = keyFile.get_double ("EPD", "Strength"); if (pedited) pedited->epd.strength = true; } - if(keyFile.has_key("EPD", "Gamma")) { epd.gamma = keyFile.get_double ("EPD", "Gamma"); if (pedited) pedited->epd.gamma = true; } - if(keyFile.has_key("EPD", "EdgeStopping")) { epd.edgeStopping = keyFile.get_double ("EPD", "EdgeStopping"); if (pedited) pedited->epd.edgeStopping = true; } - if(keyFile.has_key("EPD", "Scale")) { epd.scale = keyFile.get_double ("EPD", "Scale"); if (pedited) pedited->epd.scale = true; } - if(keyFile.has_key("EPD", "ReweightingIterates")) { epd.reweightingIterates = keyFile.get_integer ("EPD", "ReweightingIterates"); if (pedited) pedited->epd.reweightingIterates = true; } -} + if (pedited) { + pedited->colorappearance.curveMode2 = true; + } + } - // load lumaDenoise -/*if (keyFile.has_group ("Luminance Denoising")) { - if (keyFile.has_key ("Luminance Denoising", "Enabled")) { lumaDenoise.enabled = keyFile.get_boolean ("Luminance Denoising", "Enabled"); if (pedited) pedited->lumaDenoise.enabled = true; } - if (keyFile.has_key ("Luminance Denoising", "Radius")) { lumaDenoise.radius = keyFile.get_double ("Luminance Denoising", "Radius"); if (pedited) pedited->lumaDenoise.radius = true; } - if (keyFile.has_key ("Luminance Denoising", "EdgeTolerance")) { lumaDenoise.edgetolerance = keyFile.get_integer ("Luminance Denoising", "EdgeTolerance"); if (pedited) pedited->lumaDenoise.edgetolerance = true; } -}*/ + if (keyFile.has_key ("Color appearance", "CurveMode3")) { + Glib::ustring sMode = keyFile.get_string ("Color appearance", "CurveMode3"); - // load colorDenoise -/*if (keyFile.has_group ("Chrominance Denoising")) { - if (keyFile.has_key ("Chrominance Denoising", "Enabled")) { colorDenoise.enabled = keyFile.get_boolean ("Chrominance Denoising", "Enabled"); if (pedited) pedited->colorDenoise.enabled = true; } - // WARNING: radius doesn't exist anymore; is there any compatibility issue that require to keep the following line? - if (keyFile.has_key ("Chrominance Denoising", "Radius")) { colorDenoise.amount = 10*keyFile.get_double ("Chrominance Denoising", "Radius"); } - if (keyFile.has_key ("Chrominance Denoising", "Amount")) { colorDenoise.amount = keyFile.get_integer ("Chrominance Denoising", "Amount"); if (pedited) pedited->colorDenoise.amount = true; } -}*/ + if (sMode == "Chroma") { + colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA; + } else if (sMode == "Saturation") { + colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_SATUR; + } else if (sMode == "Colorfullness") { + colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_COLORF; + } - // load sh -if (keyFile.has_group ("Shadows & Highlights")) { - if (keyFile.has_key ("Shadows & Highlights", "Enabled")) { sh.enabled = keyFile.get_boolean ("Shadows & Highlights", "Enabled"); if (pedited) pedited->sh.enabled = true; } - if (keyFile.has_key ("Shadows & Highlights", "HighQuality")) { sh.hq = keyFile.get_boolean ("Shadows & Highlights", "HighQuality"); if (pedited) pedited->sh.hq = true; } - if (keyFile.has_key ("Shadows & Highlights", "Highlights")) { sh.highlights = keyFile.get_integer ("Shadows & Highlights", "Highlights"); if (pedited) pedited->sh.highlights = true; } - if (keyFile.has_key ("Shadows & Highlights", "HighlightTonalWidth")) { sh.htonalwidth = keyFile.get_integer ("Shadows & Highlights", "HighlightTonalWidth"); if (pedited) pedited->sh.htonalwidth = true; } - if (keyFile.has_key ("Shadows & Highlights", "Shadows")) { sh.shadows = keyFile.get_integer ("Shadows & Highlights", "Shadows"); if (pedited) pedited->sh.shadows = true; } - if (keyFile.has_key ("Shadows & Highlights", "ShadowTonalWidth")) { sh.stonalwidth = keyFile.get_integer ("Shadows & Highlights", "ShadowTonalWidth"); if (pedited) pedited->sh.stonalwidth = true; } - if (keyFile.has_key ("Shadows & Highlights", "LocalContrast")) { sh.localcontrast = keyFile.get_integer ("Shadows & Highlights", "LocalContrast"); if (pedited) pedited->sh.localcontrast = true; } - if (keyFile.has_key ("Shadows & Highlights", "Radius")) { sh.radius = keyFile.get_integer ("Shadows & Highlights", "Radius"); if (pedited) pedited->sh.radius = true; } -} - - // load crop -if (keyFile.has_group ("Crop")) { - if (keyFile.has_key ("Crop", "Enabled")) { crop.enabled = keyFile.get_boolean ("Crop", "Enabled"); if (pedited) pedited->crop.enabled = true; } - if (keyFile.has_key ("Crop", "X")) { crop.x = keyFile.get_integer ("Crop", "X"); if (pedited) pedited->crop.x = true; } - if (keyFile.has_key ("Crop", "Y")) { crop.y = keyFile.get_integer ("Crop", "Y"); if (pedited) pedited->crop.y = true; } - if (keyFile.has_key ("Crop", "W")) { crop.w = keyFile.get_integer ("Crop", "W"); if (pedited) pedited->crop.w = true; } - if (keyFile.has_key ("Crop", "H")) { crop.h = keyFile.get_integer ("Crop", "H"); if (pedited) pedited->crop.h = true; } - if (keyFile.has_key ("Crop", "FixedRatio")) { crop.fixratio = keyFile.get_boolean ("Crop", "FixedRatio"); if (pedited) pedited->crop.fixratio = true; } - if (keyFile.has_key ("Crop", "Ratio")) { - crop.ratio = keyFile.get_string ("Crop", "Ratio"); - if (pedited) pedited->crop.ratio = true; - //backwards compatibility for crop.ratio - if (crop.ratio=="DIN") crop.ratio = "1.414 - DIN EN ISO 216"; - if (crop.ratio=="8.5:11") crop.ratio = "8.5:11 - US Letter"; - if (crop.ratio=="11:17") crop.ratio = "11:17 - Tabloid"; - } - if (keyFile.has_key ("Crop", "Orientation")) { crop.orientation= keyFile.get_string ("Crop", "Orientation"); if (pedited) pedited->crop.orientation = true; } - if (keyFile.has_key ("Crop", "Guide")) { crop.guide = keyFile.get_string ("Crop", "Guide"); if (pedited) pedited->crop.guide = true; } -} + if (pedited) { + pedited->colorappearance.curveMode3 = true; + } + } - // load coarse -if (keyFile.has_group ("Coarse Transformation")) { - if (keyFile.has_key ("Coarse Transformation", "Rotate")) { coarse.rotate = keyFile.get_integer ("Coarse Transformation", "Rotate"); if (pedited) pedited->coarse.rotate = true; } - if (keyFile.has_key ("Coarse Transformation", "HorizontalFlip")) { coarse.hflip = keyFile.get_boolean ("Coarse Transformation", "HorizontalFlip"); if (pedited) pedited->coarse.hflip = true; } - if (keyFile.has_key ("Coarse Transformation", "VerticalFlip")) { coarse.vflip = keyFile.get_boolean ("Coarse Transformation", "VerticalFlip"); if (pedited) pedited->coarse.vflip = true; } -} + if (ppVersion > 200) { + if (keyFile.has_key ("Color appearance", "Curve")) { + colorappearance.curve = keyFile.get_double_list ("Color appearance", "Curve"); - // load rotate -if (keyFile.has_group ("Rotation")) { - if (keyFile.has_key ("Rotation", "Degree")) { rotate.degree = keyFile.get_double ("Rotation", "Degree"); if (pedited) pedited->rotate.degree = true; } -} - // load commonTrans -if (keyFile.has_group ("Common Properties for Transformations")) { - if (keyFile.has_key ("Common Properties for Transformations", "AutoFill")) { commonTrans.autofill = keyFile.get_boolean ("Common Properties for Transformations", "AutoFill"); if (pedited) pedited->commonTrans.autofill = true; } -} + if (pedited) { + pedited->colorappearance.curve = true; + } + } - // load distortion -if (keyFile.has_group ("Distortion")) { - if (keyFile.has_key ("Distortion", "Amount")) { distortion.amount = keyFile.get_double ("Distortion", "Amount"); if (pedited) pedited->distortion.amount = true; } -} + if (keyFile.has_key ("Color appearance", "Curve2")) { + colorappearance.curve2 = keyFile.get_double_list ("Color appearance", "Curve2"); - // lens profile -if (keyFile.has_group ("LensProfile")) { - if (keyFile.has_key ("LensProfile", "LCPFile")) { lensProf.lcpFile = expandRelativePath(fname, "", keyFile.get_string ("LensProfile", "LCPFile")); if (pedited) pedited->lensProf.lcpFile = true; } - if (keyFile.has_key ("LensProfile", "UseDistortion")) { lensProf.useDist = keyFile.get_boolean ("LensProfile", "UseDistortion"); if (pedited) pedited->lensProf.useDist = true; } - if (keyFile.has_key ("LensProfile", "UseVignette")) { lensProf.useVign = keyFile.get_boolean ("LensProfile", "UseVignette"); if (pedited) pedited->lensProf.useVign = true; } - if (keyFile.has_key ("LensProfile", "UseCA")) { lensProf.useCA = keyFile.get_boolean ("LensProfile", "UseCA"); if (pedited) pedited->lensProf.useCA = true; } -} - - // load perspective correction -if (keyFile.has_group ("Perspective")) { - if (keyFile.has_key ("Perspective", "Horizontal")) { perspective.horizontal = keyFile.get_double ("Perspective", "Horizontal"); if (pedited) pedited->perspective.horizontal = true; } - if (keyFile.has_key ("Perspective", "Vertical")) { perspective.vertical = keyFile.get_double ("Perspective", "Vertical"); if (pedited) pedited->perspective.vertical = true; } -} + if (pedited) { + pedited->colorappearance.curve2 = true; + } + } - // load gradient -if (keyFile.has_group ("Gradient")) { - if (keyFile.has_key ("Gradient", "Enabled")) { gradient.enabled = keyFile.get_boolean ("Gradient", "Enabled"); if (pedited) pedited->gradient.enabled = true; } - if (keyFile.has_key ("Gradient", "Degree")) { gradient.degree = keyFile.get_double ("Gradient", "Degree"); if (pedited) pedited->gradient.degree = true; } - if (keyFile.has_key ("Gradient", "Feather")) { gradient.feather = keyFile.get_integer ("Gradient", "Feather"); if (pedited) pedited->gradient.feather = true; } - if (keyFile.has_key ("Gradient", "Strength")) { gradient.strength = keyFile.get_double ("Gradient", "Strength");if (pedited) pedited->gradient.strength = true; } - if (keyFile.has_key ("Gradient", "CenterX")) { gradient.centerX = keyFile.get_integer ("Gradient", "CenterX"); if (pedited) pedited->gradient.centerX = true; } - if (keyFile.has_key ("Gradient", "CenterY")) { gradient.centerY = keyFile.get_integer ("Gradient", "CenterY"); if (pedited) pedited->gradient.centerY = true; } -} + if (keyFile.has_key ("Color appearance", "Curve3")) { + colorappearance.curve3 = keyFile.get_double_list ("Color appearance", "Curve3"); -if (keyFile.has_group ("PCVignette")) { - if (keyFile.has_key ("PCVignette", "Enabled")) { pcvignette.enabled = keyFile.get_boolean ("PCVignette", "Enabled"); if (pedited) pedited->pcvignette.enabled = true; } - if (keyFile.has_key ("PCVignette", "Strength")) { pcvignette.strength = keyFile.get_double ("PCVignette", "Strength");if (pedited) pedited->pcvignette.strength = true; } - if (keyFile.has_key ("PCVignette", "Feather")) { pcvignette.feather = keyFile.get_integer ("PCVignette", "Feather"); if (pedited) pedited->pcvignette.feather = true; } - if (keyFile.has_key ("PCVignette", "Roundness")) { pcvignette.roundness = keyFile.get_integer ("PCVignette", "Roundness"); if (pedited) pedited->pcvignette.roundness = true; } -} + if (pedited) { + pedited->colorappearance.curve3 = true; + } + } + } + + } + + // load impulseDenoise + if (keyFile.has_group ("Impulse Denoising")) { + if (keyFile.has_key ("Impulse Denoising", "Enabled")) { + impulseDenoise.enabled = keyFile.get_boolean ("Impulse Denoising", "Enabled"); + + if (pedited) { + pedited->impulseDenoise.enabled = true; + } + } + + if (keyFile.has_key ("Impulse Denoising", "Threshold")) { + impulseDenoise.thresh = keyFile.get_integer ("Impulse Denoising", "Threshold"); + + if (pedited) { + pedited->impulseDenoise.thresh = true; + } + } + } + + // load dirpyrDenoise + if (keyFile.has_group ("Directional Pyramid Denoising")) {//TODO: No longer an accurate description for FT denoise + if (keyFile.has_key ("Directional Pyramid Denoising", "Enabled")) { + dirpyrDenoise.enabled = keyFile.get_boolean ("Directional Pyramid Denoising", "Enabled"); + + if (pedited) { + pedited->dirpyrDenoise.enabled = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Enhance")) { + dirpyrDenoise.enhance = keyFile.get_boolean ("Directional Pyramid Denoising", "Enhance"); + + if (pedited) { + pedited->dirpyrDenoise.enhance = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Median")) { + dirpyrDenoise.median = keyFile.get_boolean ("Directional Pyramid Denoising", "Median"); + + if (pedited) { + pedited->dirpyrDenoise.median = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Auto")) { + dirpyrDenoise.autochroma = keyFile.get_boolean ("Directional Pyramid Denoising", "Auto"); + + if (pedited) { + pedited->dirpyrDenoise.autochroma = true; + } + } + +// if (keyFile.has_key ("Directional Pyramid Denoising", "Perform")) { dirpyrDenoise.perform = keyFile.get_boolean ("Directional Pyramid Denoising", "Perform"); if (pedited) pedited->dirpyrDenoise.perform = true; } + if (keyFile.has_key ("Directional Pyramid Denoising", "Luma")) { + dirpyrDenoise.luma = keyFile.get_double ("Directional Pyramid Denoising", "Luma"); + + if (pedited) { + pedited->dirpyrDenoise.luma = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Ldetail")) { + dirpyrDenoise.Ldetail = keyFile.get_double ("Directional Pyramid Denoising", "Ldetail"); + + if (pedited) { + pedited->dirpyrDenoise.Ldetail = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Chroma")) { + dirpyrDenoise.chroma = keyFile.get_double ("Directional Pyramid Denoising", "Chroma"); + + if (pedited) { + pedited->dirpyrDenoise.chroma = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Method")) { + dirpyrDenoise.dmethod = keyFile.get_string ("Directional Pyramid Denoising", "Method"); + + if (pedited) { + pedited->dirpyrDenoise.dmethod = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "LMethod")) { + dirpyrDenoise.Lmethod = keyFile.get_string ("Directional Pyramid Denoising", "LMethod"); + + if (pedited) { + pedited->dirpyrDenoise.Lmethod = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "CMethod")) { + dirpyrDenoise.Cmethod = keyFile.get_string ("Directional Pyramid Denoising", "CMethod"); + + if (pedited) { + pedited->dirpyrDenoise.Cmethod = true; + } + } + + // never load 'auto chroma preview mode' from pp3 + if(dirpyrDenoise.Cmethod == "PRE") { + dirpyrDenoise.Cmethod = "MAN"; + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "C2Method")) { + dirpyrDenoise.C2method = keyFile.get_string ("Directional Pyramid Denoising", "C2Method"); + + if (pedited) { + pedited->dirpyrDenoise.C2method = true; + } + } + + if(dirpyrDenoise.C2method == "PREV") { + dirpyrDenoise.C2method = "MANU"; + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "SMethod")) { + dirpyrDenoise.smethod = keyFile.get_string ("Directional Pyramid Denoising", "SMethod"); + + if (pedited) { + pedited->dirpyrDenoise.smethod = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "MedMethod")) { + dirpyrDenoise.medmethod = keyFile.get_string ("Directional Pyramid Denoising", "MedMethod"); + + if (pedited) { + pedited->dirpyrDenoise.medmethod = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "MethodMed")) { + dirpyrDenoise.methodmed = keyFile.get_string ("Directional Pyramid Denoising", "MethodMed"); + + if (pedited) { + pedited->dirpyrDenoise.methodmed = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "RGBMethod")) { + dirpyrDenoise.rgbmethod = keyFile.get_string ("Directional Pyramid Denoising", "RGBMethod"); + + if (pedited) { + pedited->dirpyrDenoise.rgbmethod = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "LCurve")) { + dirpyrDenoise.lcurve = keyFile.get_double_list ("Directional Pyramid Denoising", "LCurve"); + + if (pedited) { + pedited->dirpyrDenoise.lcurve = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "CCCurve")) { + dirpyrDenoise.cccurve = keyFile.get_double_list ("Directional Pyramid Denoising", "CCCurve"); + + if (pedited) { + pedited->dirpyrDenoise.cccurve = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Redchro")) { + dirpyrDenoise.redchro = keyFile.get_double ("Directional Pyramid Denoising", "Redchro"); + + if (pedited) { + pedited->dirpyrDenoise.redchro = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Bluechro")) { + dirpyrDenoise.bluechro = keyFile.get_double ("Directional Pyramid Denoising", "Bluechro"); + + if (pedited) { + pedited->dirpyrDenoise.bluechro = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Gamma")) { + dirpyrDenoise.gamma = keyFile.get_double ("Directional Pyramid Denoising", "Gamma"); + + if (pedited) { + pedited->dirpyrDenoise.gamma = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Denoising", "Passes")) { + dirpyrDenoise.passes = keyFile.get_integer ("Directional Pyramid Denoising", "Passes"); + + if (pedited) { + pedited->dirpyrDenoise.passes = true; + } + } + } + + //Load EPD. + if (keyFile.has_group ("EPD")) { + if(keyFile.has_key("EPD", "Enabled")) { + epd.enabled = keyFile.get_boolean ("EPD", "Enabled"); + + if (pedited) { + pedited->epd.enabled = true; + } + } + + if(keyFile.has_key("EPD", "Strength")) { + epd.strength = keyFile.get_double ("EPD", "Strength"); + + if (pedited) { + pedited->epd.strength = true; + } + } + + if(keyFile.has_key("EPD", "Gamma")) { + epd.gamma = keyFile.get_double ("EPD", "Gamma"); + + if (pedited) { + pedited->epd.gamma = true; + } + } + + if(keyFile.has_key("EPD", "EdgeStopping")) { + epd.edgeStopping = keyFile.get_double ("EPD", "EdgeStopping"); + + if (pedited) { + pedited->epd.edgeStopping = true; + } + } + + if(keyFile.has_key("EPD", "Scale")) { + epd.scale = keyFile.get_double ("EPD", "Scale"); + + if (pedited) { + pedited->epd.scale = true; + } + } + + if(keyFile.has_key("EPD", "ReweightingIterates")) { + epd.reweightingIterates = keyFile.get_integer ("EPD", "ReweightingIterates"); + + if (pedited) { + pedited->epd.reweightingIterates = true; + } + } + } + + // load lumaDenoise + /*if (keyFile.has_group ("Luminance Denoising")) { + if (keyFile.has_key ("Luminance Denoising", "Enabled")) { lumaDenoise.enabled = keyFile.get_boolean ("Luminance Denoising", "Enabled"); if (pedited) pedited->lumaDenoise.enabled = true; } + if (keyFile.has_key ("Luminance Denoising", "Radius")) { lumaDenoise.radius = keyFile.get_double ("Luminance Denoising", "Radius"); if (pedited) pedited->lumaDenoise.radius = true; } + if (keyFile.has_key ("Luminance Denoising", "EdgeTolerance")) { lumaDenoise.edgetolerance = keyFile.get_integer ("Luminance Denoising", "EdgeTolerance"); if (pedited) pedited->lumaDenoise.edgetolerance = true; } + }*/ + + // load colorDenoise + /*if (keyFile.has_group ("Chrominance Denoising")) { + if (keyFile.has_key ("Chrominance Denoising", "Enabled")) { colorDenoise.enabled = keyFile.get_boolean ("Chrominance Denoising", "Enabled"); if (pedited) pedited->colorDenoise.enabled = true; } + // WARNING: radius doesn't exist anymore; is there any compatibility issue that require to keep the following line? + if (keyFile.has_key ("Chrominance Denoising", "Radius")) { colorDenoise.amount = 10*keyFile.get_double ("Chrominance Denoising", "Radius"); } + if (keyFile.has_key ("Chrominance Denoising", "Amount")) { colorDenoise.amount = keyFile.get_integer ("Chrominance Denoising", "Amount"); if (pedited) pedited->colorDenoise.amount = true; } + }*/ + + // load sh + if (keyFile.has_group ("Shadows & Highlights")) { + if (keyFile.has_key ("Shadows & Highlights", "Enabled")) { + sh.enabled = keyFile.get_boolean ("Shadows & Highlights", "Enabled"); + + if (pedited) { + pedited->sh.enabled = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "HighQuality")) { + sh.hq = keyFile.get_boolean ("Shadows & Highlights", "HighQuality"); + + if (pedited) { + pedited->sh.hq = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "Highlights")) { + sh.highlights = keyFile.get_integer ("Shadows & Highlights", "Highlights"); + + if (pedited) { + pedited->sh.highlights = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "HighlightTonalWidth")) { + sh.htonalwidth = keyFile.get_integer ("Shadows & Highlights", "HighlightTonalWidth"); + + if (pedited) { + pedited->sh.htonalwidth = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "Shadows")) { + sh.shadows = keyFile.get_integer ("Shadows & Highlights", "Shadows"); + + if (pedited) { + pedited->sh.shadows = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "ShadowTonalWidth")) { + sh.stonalwidth = keyFile.get_integer ("Shadows & Highlights", "ShadowTonalWidth"); + + if (pedited) { + pedited->sh.stonalwidth = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "LocalContrast")) { + sh.localcontrast = keyFile.get_integer ("Shadows & Highlights", "LocalContrast"); + + if (pedited) { + pedited->sh.localcontrast = true; + } + } + + if (keyFile.has_key ("Shadows & Highlights", "Radius")) { + sh.radius = keyFile.get_integer ("Shadows & Highlights", "Radius"); + + if (pedited) { + pedited->sh.radius = true; + } + } + } + + // load crop + if (keyFile.has_group ("Crop")) { + if (keyFile.has_key ("Crop", "Enabled")) { + crop.enabled = keyFile.get_boolean ("Crop", "Enabled"); + + if (pedited) { + pedited->crop.enabled = true; + } + } + + if (keyFile.has_key ("Crop", "X")) { + crop.x = keyFile.get_integer ("Crop", "X"); + + if (pedited) { + pedited->crop.x = true; + } + } + + if (keyFile.has_key ("Crop", "Y")) { + crop.y = keyFile.get_integer ("Crop", "Y"); + + if (pedited) { + pedited->crop.y = true; + } + } + + if (keyFile.has_key ("Crop", "W")) { + crop.w = keyFile.get_integer ("Crop", "W"); + + if (pedited) { + pedited->crop.w = true; + } + } + + if (keyFile.has_key ("Crop", "H")) { + crop.h = keyFile.get_integer ("Crop", "H"); + + if (pedited) { + pedited->crop.h = true; + } + } + + if (keyFile.has_key ("Crop", "FixedRatio")) { + crop.fixratio = keyFile.get_boolean ("Crop", "FixedRatio"); + + if (pedited) { + pedited->crop.fixratio = true; + } + } + + if (keyFile.has_key ("Crop", "Ratio")) { + crop.ratio = keyFile.get_string ("Crop", "Ratio"); + + if (pedited) { + pedited->crop.ratio = true; + } + + //backwards compatibility for crop.ratio + if (crop.ratio == "DIN") { + crop.ratio = "1.414 - DIN EN ISO 216"; + } + + if (crop.ratio == "8.5:11") { + crop.ratio = "8.5:11 - US Letter"; + } + + if (crop.ratio == "11:17") { + crop.ratio = "11:17 - Tabloid"; + } + } + + if (keyFile.has_key ("Crop", "Orientation")) { + crop.orientation = keyFile.get_string ("Crop", "Orientation"); + + if (pedited) { + pedited->crop.orientation = true; + } + } + + if (keyFile.has_key ("Crop", "Guide")) { + crop.guide = keyFile.get_string ("Crop", "Guide"); + + if (pedited) { + pedited->crop.guide = true; + } + } + } + + // load coarse + if (keyFile.has_group ("Coarse Transformation")) { + if (keyFile.has_key ("Coarse Transformation", "Rotate")) { + coarse.rotate = keyFile.get_integer ("Coarse Transformation", "Rotate"); + + if (pedited) { + pedited->coarse.rotate = true; + } + } + + if (keyFile.has_key ("Coarse Transformation", "HorizontalFlip")) { + coarse.hflip = keyFile.get_boolean ("Coarse Transformation", "HorizontalFlip"); + + if (pedited) { + pedited->coarse.hflip = true; + } + } + + if (keyFile.has_key ("Coarse Transformation", "VerticalFlip")) { + coarse.vflip = keyFile.get_boolean ("Coarse Transformation", "VerticalFlip"); + + if (pedited) { + pedited->coarse.vflip = true; + } + } + } + + // load rotate + if (keyFile.has_group ("Rotation")) { + if (keyFile.has_key ("Rotation", "Degree")) { + rotate.degree = keyFile.get_double ("Rotation", "Degree"); + + if (pedited) { + pedited->rotate.degree = true; + } + } + } + + // load commonTrans + if (keyFile.has_group ("Common Properties for Transformations")) { + if (keyFile.has_key ("Common Properties for Transformations", "AutoFill")) { + commonTrans.autofill = keyFile.get_boolean ("Common Properties for Transformations", "AutoFill"); + + if (pedited) { + pedited->commonTrans.autofill = true; + } + } + } + + // load distortion + if (keyFile.has_group ("Distortion")) { + if (keyFile.has_key ("Distortion", "Amount")) { + distortion.amount = keyFile.get_double ("Distortion", "Amount"); + + if (pedited) { + pedited->distortion.amount = true; + } + } + } + + // lens profile + if (keyFile.has_group ("LensProfile")) { + if (keyFile.has_key ("LensProfile", "LCPFile")) { + lensProf.lcpFile = expandRelativePath(fname, "", keyFile.get_string ("LensProfile", "LCPFile")); + + if (pedited) { + pedited->lensProf.lcpFile = true; + } + } + + if (keyFile.has_key ("LensProfile", "UseDistortion")) { + lensProf.useDist = keyFile.get_boolean ("LensProfile", "UseDistortion"); + + if (pedited) { + pedited->lensProf.useDist = true; + } + } + + if (keyFile.has_key ("LensProfile", "UseVignette")) { + lensProf.useVign = keyFile.get_boolean ("LensProfile", "UseVignette"); + + if (pedited) { + pedited->lensProf.useVign = true; + } + } + + if (keyFile.has_key ("LensProfile", "UseCA")) { + lensProf.useCA = keyFile.get_boolean ("LensProfile", "UseCA"); + + if (pedited) { + pedited->lensProf.useCA = true; + } + } + } + + // load perspective correction + if (keyFile.has_group ("Perspective")) { + if (keyFile.has_key ("Perspective", "Horizontal")) { + perspective.horizontal = keyFile.get_double ("Perspective", "Horizontal"); + + if (pedited) { + pedited->perspective.horizontal = true; + } + } + + if (keyFile.has_key ("Perspective", "Vertical")) { + perspective.vertical = keyFile.get_double ("Perspective", "Vertical"); + + if (pedited) { + pedited->perspective.vertical = true; + } + } + } + + // load gradient + if (keyFile.has_group ("Gradient")) { + if (keyFile.has_key ("Gradient", "Enabled")) { + gradient.enabled = keyFile.get_boolean ("Gradient", "Enabled"); + + if (pedited) { + pedited->gradient.enabled = true; + } + } + + if (keyFile.has_key ("Gradient", "Degree")) { + gradient.degree = keyFile.get_double ("Gradient", "Degree"); + + if (pedited) { + pedited->gradient.degree = true; + } + } + + if (keyFile.has_key ("Gradient", "Feather")) { + gradient.feather = keyFile.get_integer ("Gradient", "Feather"); + + if (pedited) { + pedited->gradient.feather = true; + } + } + + if (keyFile.has_key ("Gradient", "Strength")) { + gradient.strength = keyFile.get_double ("Gradient", "Strength"); + + if (pedited) { + pedited->gradient.strength = true; + } + } + + if (keyFile.has_key ("Gradient", "CenterX")) { + gradient.centerX = keyFile.get_integer ("Gradient", "CenterX"); + + if (pedited) { + pedited->gradient.centerX = true; + } + } + + if (keyFile.has_key ("Gradient", "CenterY")) { + gradient.centerY = keyFile.get_integer ("Gradient", "CenterY"); + + if (pedited) { + pedited->gradient.centerY = true; + } + } + } + + if (keyFile.has_group ("PCVignette")) { + if (keyFile.has_key ("PCVignette", "Enabled")) { + pcvignette.enabled = keyFile.get_boolean ("PCVignette", "Enabled"); + + if (pedited) { + pedited->pcvignette.enabled = true; + } + } + + if (keyFile.has_key ("PCVignette", "Strength")) { + pcvignette.strength = keyFile.get_double ("PCVignette", "Strength"); + + if (pedited) { + pedited->pcvignette.strength = true; + } + } + + if (keyFile.has_key ("PCVignette", "Feather")) { + pcvignette.feather = keyFile.get_integer ("PCVignette", "Feather"); + + if (pedited) { + pedited->pcvignette.feather = true; + } + } + + if (keyFile.has_key ("PCVignette", "Roundness")) { + pcvignette.roundness = keyFile.get_integer ("PCVignette", "Roundness"); + + if (pedited) { + pedited->pcvignette.roundness = true; + } + } + } // load c/a correction -if (keyFile.has_group ("CACorrection")) { - if (keyFile.has_key ("CACorrection", "Red")) { cacorrection.red = keyFile.get_double ("CACorrection", "Red"); if (pedited) pedited->cacorrection.red = true; } - if (keyFile.has_key ("CACorrection", "Blue")) { cacorrection.blue = keyFile.get_double ("CACorrection", "Blue"); if (pedited) pedited->cacorrection.blue = true; } -} + if (keyFile.has_group ("CACorrection")) { + if (keyFile.has_key ("CACorrection", "Red")) { + cacorrection.red = keyFile.get_double ("CACorrection", "Red"); - // load vignetting correction -if (keyFile.has_group ("Vignetting Correction")) { - if (keyFile.has_key ("Vignetting Correction", "Amount")) { vignetting.amount = keyFile.get_integer ("Vignetting Correction", "Amount"); if (pedited) pedited->vignetting.amount = true; } - if (keyFile.has_key ("Vignetting Correction", "Radius")) { vignetting.radius = keyFile.get_integer ("Vignetting Correction", "Radius"); if (pedited) pedited->vignetting.radius = true; } - if (keyFile.has_key ("Vignetting Correction", "Strength")) { vignetting.strength = keyFile.get_integer ("Vignetting Correction", "Strength"); if (pedited) pedited->vignetting.strength = true; } - if (keyFile.has_key ("Vignetting Correction", "CenterX")) { vignetting.centerX = keyFile.get_integer ("Vignetting Correction", "CenterX"); if (pedited) pedited->vignetting.centerX = true; } - if (keyFile.has_key ("Vignetting Correction", "CenterY")) { vignetting.centerY = keyFile.get_integer ("Vignetting Correction", "CenterY"); if (pedited) pedited->vignetting.centerY = true; } -} + if (pedited) { + pedited->cacorrection.red = true; + } + } - // load resize settings -if (keyFile.has_group ("Resize")) { - if (keyFile.has_key ("Resize", "Enabled")) { resize.enabled = keyFile.get_boolean ("Resize", "Enabled"); if (pedited) pedited->resize.enabled = true; } - if (keyFile.has_key ("Resize", "Scale")) { resize.scale = keyFile.get_double ("Resize", "Scale"); if (pedited) pedited->resize.scale = true; } - if (keyFile.has_key ("Resize", "AppliesTo")) { resize.appliesTo = keyFile.get_string ("Resize", "AppliesTo"); if (pedited) pedited->resize.appliesTo = true; } - if (keyFile.has_key ("Resize", "Method")) { resize.method = keyFile.get_string ("Resize", "Method"); if (pedited) pedited->resize.method = true; } - if (keyFile.has_key ("Resize", "DataSpecified")) { resize.dataspec = keyFile.get_integer ("Resize", "DataSpecified"); if (pedited) pedited->resize.dataspec = true; } - if (keyFile.has_key ("Resize", "Width")) { resize.width = keyFile.get_integer ("Resize", "Width"); if (pedited) pedited->resize.width = true; } - if (keyFile.has_key ("Resize", "Height")) { resize.height = keyFile.get_integer ("Resize", "Height"); if (pedited) pedited->resize.height = true; } -} + if (keyFile.has_key ("CACorrection", "Blue")) { + cacorrection.blue = keyFile.get_double ("CACorrection", "Blue"); - // load post resize sharpening -if (keyFile.has_group ("PostResizeSharpening")) { - if (keyFile.has_key ("PostResizeSharpening", "Enabled")) { prsharpening.enabled = keyFile.get_boolean ("PostResizeSharpening", "Enabled"); if (pedited) pedited->prsharpening.enabled = true; } - if (keyFile.has_key ("PostResizeSharpening", "Radius")) { prsharpening.radius = keyFile.get_double ("PostResizeSharpening", "Radius"); if (pedited) pedited->prsharpening.radius = true; } - if (keyFile.has_key ("PostResizeSharpening", "Amount")) { prsharpening.amount = keyFile.get_integer ("PostResizeSharpening", "Amount"); if (pedited) pedited->prsharpening.amount = true; } - if (keyFile.has_key ("PostResizeSharpening", "Threshold")) { - if (ppVersion < 302) { - int thresh = min(keyFile.get_integer ("PostResizeSharpening", "Threshold"), 2000); - prsharpening.threshold.setValues(thresh, thresh, 2000, 2000); // TODO: 2000 is the maximum value and is taken of rtgui/sharpening.cc ; should be changed by the tool modularization - } - else { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("PostResizeSharpening", "Threshold"); - prsharpening.threshold.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 2000), min(thresh.data()[3], 2000)); - } - if (pedited) pedited->prsharpening.threshold = true; - } - if (keyFile.has_key ("PostResizeSharpening", "OnlyEdges")) { prsharpening.edgesonly = keyFile.get_boolean ("PostResizeSharpening", "OnlyEdges"); if (pedited) pedited->prsharpening.edgesonly = true; } - if (keyFile.has_key ("PostResizeSharpening", "EdgedetectionRadius")) { prsharpening.edges_radius = keyFile.get_double ("PostResizeSharpening", "EdgedetectionRadius"); if (pedited) pedited->prsharpening.edges_radius = true; } - if (keyFile.has_key ("PostResizeSharpening", "EdgeTolerance")) { prsharpening.edges_tolerance = keyFile.get_integer ("PostResizeSharpening", "EdgeTolerance"); if (pedited) pedited->prsharpening.edges_tolerance = true; } - if (keyFile.has_key ("PostResizeSharpening", "HalocontrolEnabled")) { prsharpening.halocontrol = keyFile.get_boolean ("PostResizeSharpening", "HalocontrolEnabled"); if (pedited) pedited->prsharpening.halocontrol = true; } - if (keyFile.has_key ("PostResizeSharpening", "HalocontrolAmount")) { prsharpening.halocontrol_amount = keyFile.get_integer ("PostResizeSharpening", "HalocontrolAmount"); if (pedited) pedited->prsharpening.halocontrol_amount = true; } - if (keyFile.has_key ("PostResizeSharpening", "Method")) { prsharpening.method = keyFile.get_string ("PostResizeSharpening", "Method"); if (pedited) pedited->prsharpening.method = true; } - if (keyFile.has_key ("PostResizeSharpening", "DeconvRadius")) { prsharpening.deconvradius = keyFile.get_double ("PostResizeSharpening", "DeconvRadius"); if (pedited) pedited->prsharpening.deconvradius = true; } - if (keyFile.has_key ("PostResizeSharpening", "DeconvAmount")) { prsharpening.deconvamount = keyFile.get_integer ("PostResizeSharpening", "DeconvAmount"); if (pedited) pedited->prsharpening.deconvamount = true; } - if (keyFile.has_key ("PostResizeSharpening", "DeconvDamping")) { prsharpening.deconvdamping = keyFile.get_integer ("PostResizeSharpening", "DeconvDamping"); if (pedited) pedited->prsharpening.deconvdamping = true; } - if (keyFile.has_key ("PostResizeSharpening", "DeconvIterations")) { prsharpening.deconviter = keyFile.get_integer ("PostResizeSharpening", "DeconvIterations"); if (pedited) pedited->prsharpening.deconviter = true; } -} - - // load color management settings -if (keyFile.has_group ("Color Management")) { - if (keyFile.has_key ("Color Management", "InputProfile")) { icm.input = expandRelativePath(fname, "file:", keyFile.get_string ("Color Management", "InputProfile")); if (pedited) pedited->icm.input = true; } - if (keyFile.has_key ("Color Management", "ToneCurve")) { icm.toneCurve = keyFile.get_boolean ("Color Management", "ToneCurve"); if (pedited) pedited->icm.toneCurve = true; } - if (keyFile.has_key ("Color Management", "ApplyLookTable")) { icm.applyLookTable = keyFile.get_boolean ("Color Management", "ApplyLookTable"); if (pedited) pedited->icm.applyLookTable = true; } - if (keyFile.has_key ("Color Management", "ApplyBaselineExposureOffset")) { icm.applyBaselineExposureOffset = keyFile.get_boolean ("Color Management", "ApplyBaselineExposureOffset"); if (pedited) pedited->icm.applyBaselineExposureOffset = true; } - if (keyFile.has_key ("Color Management", "ApplyHueSatMap")) { icm.applyHueSatMap = keyFile.get_boolean ("Color Management", "ApplyHueSatMap"); if (pedited) pedited->icm.applyHueSatMap = true; } - if (keyFile.has_key ("Color Management", "BlendCMSMatrix")) { icm.blendCMSMatrix = keyFile.get_boolean ("Color Management", "BlendCMSMatrix"); if (pedited) pedited->icm.blendCMSMatrix = true; } - if (keyFile.has_key ("Color Management", "DCPIlluminant")) { icm.dcpIlluminant = keyFile.get_integer ("Color Management", "DCPIlluminant"); if (pedited) pedited->icm.dcpIlluminant = true; } - if (keyFile.has_key ("Color Management", "WorkingProfile")) { icm.working = keyFile.get_string ("Color Management", "WorkingProfile"); if (pedited) pedited->icm.working = true; } - if (keyFile.has_key ("Color Management", "OutputProfile")) { icm.output = keyFile.get_string ("Color Management", "OutputProfile"); if (pedited) pedited->icm.output = true; } - if (keyFile.has_key ("Color Management", "Gammafree")) { icm.gamma = keyFile.get_string ("Color Management", "Gammafree"); if (pedited) pedited->icm.gamfree = true; } - if (keyFile.has_key ("Color Management", "Freegamma")) { icm.freegamma = keyFile.get_boolean ("Color Management", "Freegamma"); if (pedited) pedited->icm.freegamma = true; } - if (keyFile.has_key ("Color Management", "GammaValue")) { icm.gampos = keyFile.get_double ("Color Management", "GammaValue"); if (pedited) pedited->icm.gampos = true; } - if (keyFile.has_key ("Color Management", "GammaSlope")) { icm.slpos = keyFile.get_double ("Color Management", "GammaSlope"); if (pedited) pedited->icm.slpos = true; } - -} - // load wavelet wavelet parameters -if (keyFile.has_group ("Wavelet")) { - if (keyFile.has_key ("Wavelet", "Enabled")) { wavelet.enabled = keyFile.get_boolean ("Wavelet", "Enabled"); if (pedited) pedited->wavelet.enabled = true; } - if (keyFile.has_key ("Wavelet", "Strength")) { wavelet.strength = keyFile.get_integer ("Wavelet", "Strength"); if (pedited) pedited->wavelet.strength = true; } - if (keyFile.has_key ("Wavelet", "Balance")) { wavelet.balance = keyFile.get_integer ("Wavelet", "Balance"); if (pedited) pedited->wavelet.balance = true; } - if (keyFile.has_key ("Wavelet", "Iter")) { wavelet.iter = keyFile.get_integer ("Wavelet", "Iter"); if (pedited) pedited->wavelet.iter = true; } - if (keyFile.has_key ("Wavelet", "Median")) {wavelet.median = keyFile.get_boolean ("Wavelet", "Median");if (pedited) pedited->wavelet.median = true;} - if (keyFile.has_key ("Wavelet", "Medianlev")) {wavelet.medianlev = keyFile.get_boolean ("Wavelet", "Medianlev");if (pedited) pedited->wavelet.medianlev = true;} - if (keyFile.has_key ("Wavelet", "Linkedg")) {wavelet.linkedg = keyFile.get_boolean ("Wavelet", "Linkedg");if (pedited) pedited->wavelet.linkedg = true;} - if (keyFile.has_key ("Wavelet", "CBenab")) {wavelet.cbenab = keyFile.get_boolean ("Wavelet", "CBenab");if (pedited) pedited->wavelet.cbenab = true;} - if (keyFile.has_key ("Wavelet", "CBgreenhigh")) { wavelet.greenhigh = keyFile.get_integer ("Wavelet", "CBgreenhigh"); if (pedited) pedited->wavelet.greenhigh = true; } - if (keyFile.has_key ("Wavelet", "CBgreenmed")) { wavelet.greenmed = keyFile.get_integer ("Wavelet", "CBgreenmed"); if (pedited) pedited->wavelet.greenmed = true; } - if (keyFile.has_key ("Wavelet", "CBgreenlow")) { wavelet.greenlow = keyFile.get_integer ("Wavelet", "CBgreenlow"); if (pedited) pedited->wavelet.greenlow = true; } - if (keyFile.has_key ("Wavelet", "CBbluehigh")) { wavelet.bluehigh = keyFile.get_integer ("Wavelet", "CBbluehigh"); if (pedited) pedited->wavelet.bluehigh = true; } - if (keyFile.has_key ("Wavelet", "CBbluemed")) { wavelet.bluemed = keyFile.get_integer ("Wavelet", "CBbluemed"); if (pedited) pedited->wavelet.bluemed = true; } - if (keyFile.has_key ("Wavelet", "CBbluelow")) { wavelet.bluelow = keyFile.get_integer ("Wavelet", "CBbluelow"); if (pedited) pedited->wavelet.bluelow = true; } - // if (keyFile.has_key ("Wavelet", "Edgreinf")) {wavelet.edgreinf = keyFile.get_boolean ("Wavelet", "Edgreinf");if (pedited) pedited->wavelet.edgreinf = true;} - if (keyFile.has_key ("Wavelet", "Lipst")) {wavelet.lipst = keyFile.get_boolean ("Wavelet", "Lipst");if (pedited) pedited->wavelet.lipst = true;} - if (keyFile.has_key ("Wavelet", "AvoidColorShift")) {wavelet.avoid = keyFile.get_boolean ("Wavelet", "AvoidColorShift");if (pedited) pedited->wavelet.avoid = true;} - if (keyFile.has_key ("Wavelet", "TMr")) {wavelet.tmr = keyFile.get_boolean ("Wavelet", "TMr");if (pedited) pedited->wavelet.tmr = true;} - if (keyFile.has_key ("Wavelet", "LevMethod")) {wavelet.Lmethod = keyFile.get_string ("Wavelet", "LevMethod"); if (pedited) pedited->wavelet.Lmethod = true; } - if (keyFile.has_key ("Wavelet", "ChoiceLevMethod")) {wavelet.CLmethod = keyFile.get_string ("Wavelet", "ChoiceLevMethod"); if (pedited) pedited->wavelet.CLmethod = true; } - if (keyFile.has_key ("Wavelet", "BackMethod")) {wavelet.Backmethod = keyFile.get_string ("Wavelet", "BackMethod"); if (pedited) pedited->wavelet.Backmethod = true; } - if (keyFile.has_key ("Wavelet", "TilesMethod")) {wavelet.Tilesmethod = keyFile.get_string ("Wavelet", "TilesMethod"); if (pedited) pedited->wavelet.Tilesmethod = true; } - if (keyFile.has_key ("Wavelet", "DaubMethod")) {wavelet.daubcoeffmethod = keyFile.get_string ("Wavelet", "DaubMethod"); if (pedited) pedited->wavelet.daubcoeffmethod = true; } - if (keyFile.has_key ("Wavelet", "CHromaMethod")) {wavelet.CHmethod = keyFile.get_string ("Wavelet", "CHromaMethod"); if (pedited) pedited->wavelet.CHmethod = true; } - if (keyFile.has_key ("Wavelet", "Medgreinf")) {wavelet.Medgreinf = keyFile.get_string ("Wavelet", "Medgreinf"); if (pedited) pedited->wavelet.Medgreinf = true; } - if (keyFile.has_key ("Wavelet", "CHSLromaMethod")) {wavelet.CHSLmethod = keyFile.get_string ("Wavelet", "CHSLromaMethod"); if (pedited) pedited->wavelet.CHSLmethod = true; } - if (keyFile.has_key ("Wavelet", "EDMethod")) {wavelet.EDmethod = keyFile.get_string ("Wavelet", "EDMethod"); if (pedited) pedited->wavelet.EDmethod = true; } - if (keyFile.has_key ("Wavelet", "NPMethod")) {wavelet.NPmethod = keyFile.get_string ("Wavelet", "NPMethod"); if (pedited) pedited->wavelet.NPmethod = true; } - if (keyFile.has_key ("Wavelet", "BAMethod")) {wavelet.BAmethod = keyFile.get_string ("Wavelet", "BAMethod"); if (pedited) pedited->wavelet.BAmethod = true; } - if (keyFile.has_key ("Wavelet", "TMMethod")) {wavelet.TMmethod = keyFile.get_string ("Wavelet", "TMMethod"); if (pedited) pedited->wavelet.TMmethod = true; } - if (keyFile.has_key ("Wavelet", "HSMethod")) {wavelet.HSmethod = keyFile.get_string ("Wavelet", "HSMethod"); if (pedited) pedited->wavelet.HSmethod = true; } - if (keyFile.has_key ("Wavelet", "DirMethod")) {wavelet.Dirmethod = keyFile.get_string ("Wavelet", "DirMethod"); if (pedited) pedited->wavelet.Dirmethod = true; } - if (keyFile.has_key ("Wavelet", "ResidualcontShadow")) {wavelet.rescon = keyFile.get_integer ("Wavelet", "ResidualcontShadow"); if (pedited) pedited->wavelet.rescon = true; } - if (keyFile.has_key ("Wavelet", "ResidualcontHighlight")) {wavelet.resconH = keyFile.get_integer ("Wavelet", "ResidualcontHighlight"); if (pedited) pedited->wavelet.resconH = true; } - if (keyFile.has_key ("Wavelet", "Residualchroma")) {wavelet.reschro = keyFile.get_integer ("Wavelet", "Residualchroma"); if (pedited) pedited->wavelet.reschro = true; } - if (keyFile.has_key ("Wavelet", "ResidualTM")) {wavelet.tmrs = keyFile.get_double ("Wavelet", "ResidualTM"); if (pedited) pedited->wavelet.tmrs = true; } - if (keyFile.has_key ("Wavelet", "Residualgamma")) {wavelet.gamma = keyFile.get_double ("Wavelet", "Residualgamma"); if (pedited) pedited->wavelet.gamma = true; } - if (keyFile.has_key ("Wavelet", "ContExtra")) {wavelet.sup = keyFile.get_integer ("Wavelet", "ContExtra"); if (pedited) pedited->wavelet.sup = true; } - if (keyFile.has_key ("Wavelet", "HueRangeResidual")) {wavelet.sky = keyFile.get_double ("Wavelet", "HueRangeResidual"); if (pedited) pedited->wavelet.sky = true; } - if (keyFile.has_key ("Wavelet", "MaxLev")) {wavelet.thres = keyFile.get_integer ("Wavelet", "MaxLev"); if (pedited) pedited->wavelet.thres = true; } - if (keyFile.has_key ("Wavelet", "ThresholdHighLight")) {wavelet.threshold = keyFile.get_integer ("Wavelet", "ThresholdHighLight"); if (pedited) pedited->wavelet.threshold = true; } - if (keyFile.has_key ("Wavelet", "ThresholdShadow")) {wavelet.threshold2 = keyFile.get_integer ("Wavelet", "ThresholdShadow"); if (pedited) pedited->wavelet.threshold2 = true; } - if (keyFile.has_key ("Wavelet", "Edgedetect")) {wavelet.edgedetect = keyFile.get_integer ("Wavelet", "Edgedetect"); if (pedited) pedited->wavelet.edgedetect = true; } - if (keyFile.has_key ("Wavelet", "Edgedetectthr")) {wavelet.edgedetectthr = keyFile.get_integer ("Wavelet", "Edgedetectthr"); if (pedited) pedited->wavelet.edgedetectthr = true; } - if (keyFile.has_key ("Wavelet", "EdgedetectthrHi")) {wavelet.edgedetectthr2 = keyFile.get_integer ("Wavelet", "EdgedetectthrHi"); if (pedited) pedited->wavelet.edgedetectthr2 = true; } - if (keyFile.has_key ("Wavelet", "Edgesensi")) {wavelet.edgesensi = keyFile.get_integer ("Wavelet", "Edgesensi"); if (pedited) pedited->wavelet.edgesensi = true; } - if (keyFile.has_key ("Wavelet", "Edgeampli")) {wavelet.edgeampli = keyFile.get_integer ("Wavelet", "Edgeampli"); if (pedited) pedited->wavelet.edgeampli = true; } - if (keyFile.has_key ("Wavelet", "ThresholdChroma")) {wavelet.chroma = keyFile.get_integer ("Wavelet", "ThresholdChroma"); if (pedited) pedited->wavelet.chroma = true; } - if (keyFile.has_key ("Wavelet", "ChromaLink")) {wavelet.chro = keyFile.get_integer ("Wavelet", "ChromaLink"); if (pedited) pedited->wavelet.chro = true; } - if (keyFile.has_key ("Wavelet", "Contrast")) {wavelet.contrast = keyFile.get_integer ("Wavelet", "Contrast"); if (pedited) pedited->wavelet.contrast = true; } - if (keyFile.has_key ("Wavelet", "Edgrad")) {wavelet.edgrad = keyFile.get_integer ("Wavelet", "Edgrad"); if (pedited) pedited->wavelet.edgrad = true; } - if (keyFile.has_key ("Wavelet", "Edgval")) {wavelet.edgval = keyFile.get_integer ("Wavelet", "Edgval"); if (pedited) pedited->wavelet.edgval = true; } - if (keyFile.has_key ("Wavelet", "ThrEdg")) {wavelet.edgthresh = keyFile.get_integer ("Wavelet", "ThrEdg"); if (pedited) pedited->wavelet.edgthresh = true; } - if (keyFile.has_key ("Wavelet", "ThresholdResidShadow")) {wavelet.thr = keyFile.get_integer ("Wavelet", "ThresholdResidShadow"); if (pedited) pedited->wavelet.thr = true; } - if (keyFile.has_key ("Wavelet", "ThresholdResidHighLight")) {wavelet.thrH = keyFile.get_integer ("Wavelet", "ThresholdResidHighLight"); if (pedited) pedited->wavelet.thrH = true; } - if (keyFile.has_key ("Wavelet", "ContrastCurve")) {wavelet.ccwcurve = keyFile.get_double_list ("Wavelet", "ContrastCurve"); if (pedited) pedited->wavelet.ccwcurve = true; } - if (keyFile.has_key ("Wavelet", "OpacityCurveRG")) { wavelet.opacityCurveRG = keyFile.get_double_list ("Wavelet", "OpacityCurveRG"); if (pedited) pedited->wavelet.opacityCurveRG = true; } - if (keyFile.has_key ("Wavelet", "OpacityCurveBY")) { wavelet.opacityCurveBY = keyFile.get_double_list ("Wavelet", "OpacityCurveBY"); if (pedited) pedited->wavelet.opacityCurveBY = true; } - if (keyFile.has_key ("Wavelet", "OpacityCurveW")) { wavelet.opacityCurveW = keyFile.get_double_list ("Wavelet", "OpacityCurveW"); if (pedited) pedited->wavelet.opacityCurveW = true; } - if (keyFile.has_key ("Wavelet", "OpacityCurveWL")) { wavelet.opacityCurveWL = keyFile.get_double_list ("Wavelet", "OpacityCurveWL"); if (pedited) pedited->wavelet.opacityCurveWL = true; } - if (keyFile.has_key ("Wavelet", "HHcurve")) { wavelet.hhcurve = keyFile.get_double_list ("Wavelet", "HHcurve"); if (pedited) pedited->wavelet.hhcurve = true; } - if (keyFile.has_key ("Wavelet", "CHcurve")) { wavelet.Chcurve = keyFile.get_double_list ("Wavelet", "CHcurve"); if (pedited) pedited->wavelet.Chcurve = true; } - if (keyFile.has_key ("Wavelet", "WavclCurve")) { wavelet.wavclCurve = keyFile.get_double_list ("Wavelet", "WavclCurve"); if (pedited) pedited->wavelet.wavclCurve = true; } - if (keyFile.has_key ("Wavelet", "Hueskin")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Hueskin"); - wavelet.hueskin.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.hueskin = true; - } - if (keyFile.has_key ("Wavelet", "HueRange")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "HueRange"); - wavelet.hueskin2.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.hueskin2 = true; - } - - if (keyFile.has_key ("Wavelet", "HLRange")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "HLRange"); - wavelet.hllev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.hllev = true; - } - if (keyFile.has_key ("Wavelet", "SHRange")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "SHRange"); - wavelet.bllev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.bllev = true; - } - if (keyFile.has_key ("Wavelet", "Edgcont")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Edgcont"); - wavelet.edgcont.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.edgcont = true; - } - if (keyFile.has_key ("Wavelet", "Level0noise")) { - Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level0noise"); - wavelet.level0noise.setValues(thresh.data()[0], thresh.data()[1]); - if (pedited) pedited->wavelet.level0noise = true; - } - if (keyFile.has_key ("Wavelet", "Level1noise")) { - Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level1noise"); - wavelet.level1noise.setValues(thresh.data()[0], thresh.data()[1]); - if (pedited) pedited->wavelet.level1noise = true; - } - if (keyFile.has_key ("Wavelet", "Level2noise")) { - Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level2noise"); - wavelet.level2noise.setValues(thresh.data()[0], thresh.data()[1]); - if (pedited) pedited->wavelet.level2noise = true; - } - if (keyFile.has_key ("Wavelet", "Level3noise")) { - Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level3noise"); - wavelet.level3noise.setValues(thresh.data()[0], thresh.data()[1]); - if (pedited) pedited->wavelet.level3noise = true; - } - - - if (keyFile.has_key ("Wavelet", "Pastlev")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Pastlev"); - wavelet.pastlev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.pastlev = true; - } - if (keyFile.has_key ("Wavelet", "Satlev")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Satlev"); - wavelet.satlev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->wavelet.satlev = true; - } - - - if(keyFile.has_key ("Wavelet", "Skinprotect")) { wavelet.skinprotect = keyFile.get_double ("Wavelet", "Skinprotect"); if (pedited) pedited->wavelet.skinprotect = true; } - if (keyFile.has_key ("Wavelet", "Expcontrast")) {wavelet.expcontrast = keyFile.get_boolean ("Wavelet", "Expcontrast");if (pedited) pedited->wavelet.expcontrast = true;} - if (keyFile.has_key ("Wavelet", "Expchroma")) {wavelet.expchroma = keyFile.get_boolean ("Wavelet", "Expchroma");if (pedited) pedited->wavelet.expchroma = true;} - for(int i = 0; i < 9; i ++) - { - std::stringstream ss; - ss << "Contrast" << (i+1); - if(keyFile.has_key ("Wavelet", ss.str())) {wavelet.c[i] = keyFile.get_integer ("Wavelet", ss.str()); if (pedited) pedited->wavelet.c[i] = true;} - } - for(int i = 0; i < 9; i ++) - { - std::stringstream ss; - ss << "Chroma" << (i+1); - if(keyFile.has_key ("Wavelet", ss.str())) {wavelet.ch[i] = keyFile.get_integer ("Wavelet", ss.str()); if (pedited) pedited->wavelet.ch[i] = true;} - } - if (keyFile.has_key ("Wavelet", "Expedge")) {wavelet.expedge = keyFile.get_boolean ("Wavelet", "Expedge");if (pedited) pedited->wavelet.expedge = true;} - if (keyFile.has_key ("Wavelet", "Expresid")) {wavelet.expresid = keyFile.get_boolean ("Wavelet", "Expresid");if (pedited) pedited->wavelet.expresid = true;} - if (keyFile.has_key ("Wavelet", "Expfinal")) {wavelet.expfinal = keyFile.get_boolean ("Wavelet", "Expfinal");if (pedited) pedited->wavelet.expfinal = true;} - if (keyFile.has_key ("Wavelet", "Exptoning")) {wavelet.exptoning = keyFile.get_boolean ("Wavelet", "Exptoning");if (pedited) pedited->wavelet.exptoning = true;} - if (keyFile.has_key ("Wavelet", "Expnoise")) {wavelet.expnoise = keyFile.get_boolean ("Wavelet", "Expnoise");if (pedited) pedited->wavelet.expnoise = true;} - - -} - - // load directional pyramid equalizer parameters -if (keyFile.has_group ("Directional Pyramid Equalizer")) { - if (keyFile.has_key ("Directional Pyramid Equalizer", "Enabled")) { dirpyrequalizer.enabled = keyFile.get_boolean ("Directional Pyramid Equalizer", "Enabled"); if (pedited) pedited->dirpyrequalizer.enabled = true; } - if (keyFile.has_key ("Directional Pyramid Equalizer", "Gamutlab")) { dirpyrequalizer.gamutlab = keyFile.get_boolean ("Directional Pyramid Equalizer", "Gamutlab"); if (pedited) pedited->dirpyrequalizer.gamutlab = 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"); - dirpyrequalizer.hueskin.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); - if (pedited) pedited->dirpyrequalizer.hueskin = true; - } - - if (ppVersion < 316) { - for(int i = 0; i < 5; i ++) { - std::stringstream ss; - ss << "Mult" << i; - if(keyFile.has_key ("Directional Pyramid Equalizer", ss.str())) { - if(i==4) { dirpyrequalizer.threshold = keyFile.get_double ("Directional Pyramid Equalizer", ss.str()); if (pedited) pedited->dirpyrequalizer.threshold = true; } - else { dirpyrequalizer.mult[i] = keyFile.get_double ("Directional Pyramid Equalizer", ss.str()); if (pedited) pedited->dirpyrequalizer.mult[i] = true; } + if (pedited) { + pedited->cacorrection.blue = true; + } } } - dirpyrequalizer.mult[4] = 1.0; - } - else { - // 5 level wavelet + dedicated threshold parameter - for(int i = 0; i < 6; i ++) { - std::stringstream ss; - ss << "Mult" << i; - if(keyFile.has_key ("Directional Pyramid Equalizer", ss.str())) { dirpyrequalizer.mult[i] = keyFile.get_double ("Directional Pyramid Equalizer", ss.str()); if (pedited) pedited->dirpyrequalizer.mult[i] = true; } + + // load vignetting correction + if (keyFile.has_group ("Vignetting Correction")) { + if (keyFile.has_key ("Vignetting Correction", "Amount")) { + vignetting.amount = keyFile.get_integer ("Vignetting Correction", "Amount"); + + if (pedited) { + pedited->vignetting.amount = true; + } + } + + if (keyFile.has_key ("Vignetting Correction", "Radius")) { + vignetting.radius = keyFile.get_integer ("Vignetting Correction", "Radius"); + + if (pedited) { + pedited->vignetting.radius = true; + } + } + + if (keyFile.has_key ("Vignetting Correction", "Strength")) { + vignetting.strength = keyFile.get_integer ("Vignetting Correction", "Strength"); + + if (pedited) { + pedited->vignetting.strength = true; + } + } + + if (keyFile.has_key ("Vignetting Correction", "CenterX")) { + vignetting.centerX = keyFile.get_integer ("Vignetting Correction", "CenterX"); + + if (pedited) { + pedited->vignetting.centerX = true; + } + } + + if (keyFile.has_key ("Vignetting Correction", "CenterY")) { + vignetting.centerY = keyFile.get_integer ("Vignetting Correction", "CenterY"); + + if (pedited) { + pedited->vignetting.centerY = true; + } + } } - if(keyFile.has_key ("Directional Pyramid Equalizer", "Threshold")) { dirpyrequalizer.threshold = keyFile.get_double ("Directional Pyramid Equalizer", "Threshold"); if (pedited) pedited->dirpyrequalizer.threshold = true; } - if(keyFile.has_key ("Directional Pyramid Equalizer", "Skinprotect")) { dirpyrequalizer.skinprotect = keyFile.get_double ("Directional Pyramid Equalizer", "Skinprotect"); if (pedited) pedited->dirpyrequalizer.skinprotect = true; } - } -} - // load CLUT parameters -if ( keyFile.has_group( "Film Simulation" ) ) -{ - if ( keyFile.has_key( "Film Simulation", "Enabled" ) ) { filmSimulation.enabled = keyFile.get_boolean( "Film Simulation", "Enabled" ); if ( pedited ) pedited->filmSimulation.enabled = true; } - if ( keyFile.has_key( "Film Simulation", "ClutFilename" ) ) { filmSimulation.clutFilename = keyFile.get_string( "Film Simulation", "ClutFilename" ); if ( pedited ) pedited->filmSimulation.clutFilename = true; } - if ( keyFile.has_key( "Film Simulation", "Strength" ) ) { - if (ppVersion < 321) - filmSimulation.strength = int(keyFile.get_double( "Film Simulation", "Strength" )*100 + 0.1); - else - filmSimulation.strength = keyFile.get_integer( "Film Simulation", "Strength" ); - if ( pedited ) pedited->filmSimulation.strength = true; - } -} + // load resize settings + if (keyFile.has_group ("Resize")) { + if (keyFile.has_key ("Resize", "Enabled")) { + resize.enabled = keyFile.get_boolean ("Resize", "Enabled"); - // load HSV wavelet parameters -if (keyFile.has_group ("HSV Equalizer")) { - if (ppVersion>=300) { - if (keyFile.has_key ("HSV Equalizer", "HCurve")) { hsvequalizer.hcurve = keyFile.get_double_list ("HSV Equalizer", "HCurve"); if (pedited) pedited->hsvequalizer.hcurve = true; } - if (keyFile.has_key ("HSV Equalizer", "SCurve")) { hsvequalizer.scurve = keyFile.get_double_list ("HSV Equalizer", "SCurve"); if (pedited) pedited->hsvequalizer.scurve = true; } - if (keyFile.has_key ("HSV Equalizer", "VCurve")) { hsvequalizer.vcurve = keyFile.get_double_list ("HSV Equalizer", "VCurve"); if (pedited) pedited->hsvequalizer.vcurve = true; } - } -} + if (pedited) { + pedited->resize.enabled = true; + } + } - // load RGB curves -if (keyFile.has_group ("RGB Curves")) { - if (keyFile.has_key ("RGB Curves", "LumaMode")) { rgbCurves.lumamode = keyFile.get_boolean ("RGB Curves", "LumaMode"); if (pedited) pedited->rgbCurves.lumamode = true; } - if (keyFile.has_key ("RGB Curves", "rCurve")) { rgbCurves.rcurve = keyFile.get_double_list ("RGB Curves", "rCurve"); if (pedited) pedited->rgbCurves.rcurve = true; } - if (keyFile.has_key ("RGB Curves", "gCurve")) { rgbCurves.gcurve = keyFile.get_double_list ("RGB Curves", "gCurve"); if (pedited) pedited->rgbCurves.gcurve = true; } - if (keyFile.has_key ("RGB Curves", "bCurve")) { rgbCurves.bcurve = keyFile.get_double_list ("RGB Curves", "bCurve"); if (pedited) pedited->rgbCurves.bcurve = true; } -} + if (keyFile.has_key ("Resize", "Scale")) { + resize.scale = keyFile.get_double ("Resize", "Scale"); - // load Color Toning -if (keyFile.has_group ("ColorToning")) { - if (keyFile.has_key ("ColorToning", "Enabled")) { colorToning.enabled = keyFile.get_boolean ("ColorToning", "Enabled"); if (pedited) pedited->colorToning.enabled = true; } - if (keyFile.has_key ("ColorToning", "Method")) { colorToning.method = keyFile.get_string ("ColorToning", "Method"); if (pedited) pedited->colorToning.method = true; } - if (keyFile.has_key ("ColorToning", "Lumamode")) { colorToning.lumamode = keyFile.get_boolean ("ColorToning", "Lumamode"); if (pedited) pedited->colorToning.lumamode = true; } - if (keyFile.has_key ("ColorToning", "Twocolor")) { colorToning.twocolor = keyFile.get_string ("ColorToning", "Twocolor"); if (pedited) pedited->colorToning.twocolor = true; } - if (keyFile.has_key ("ColorToning", "OpacityCurve")) { colorToning.opacityCurve = keyFile.get_double_list ("ColorToning", "OpacityCurve"); if (pedited) pedited->colorToning.opacityCurve = true; } - if (keyFile.has_key ("ColorToning", "ColorCurve")) { colorToning.colorCurve = keyFile.get_double_list ("ColorToning", "ColorCurve"); if (pedited) pedited->colorToning.colorCurve = true; } - if (keyFile.has_key ("ColorToning", "Autosat")) { colorToning.autosat = keyFile.get_boolean ("ColorToning", "Autosat"); if (pedited) pedited->colorToning.autosat = true; } - if (keyFile.has_key ("ColorToning", "SatProtectionThreshold")) { colorToning.satProtectionThreshold = keyFile.get_integer ("ColorToning", "SatProtectionThreshold"); if (pedited) pedited->colorToning.satprotectionthreshold = true; } - if (keyFile.has_key ("ColorToning", "SaturatedOpacity")) { colorToning.saturatedOpacity = keyFile.get_integer ("ColorToning", "SaturatedOpacity"); if (pedited) pedited->colorToning.saturatedopacity = true; } - if (keyFile.has_key ("ColorToning", "Strength")) { colorToning.strength = keyFile.get_integer ("ColorToning", "Strength"); if (pedited) pedited->colorToning.strength = true; } - if (keyFile.has_key ("ColorToning", "HighlightsColorSaturation")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("ColorToning", "HighlightsColorSaturation"); - colorToning.hlColSat.setValues(thresh.data()[0], thresh.data()[1]); - if (pedited) pedited->colorToning.hlColSat = true; - } - if (keyFile.has_key ("ColorToning", "ShadowsColorSaturation")) { - Glib::ArrayHandle thresh = keyFile.get_integer_list ("ColorToning", "ShadowsColorSaturation"); - colorToning.shadowsColSat.setValues(thresh.data()[0], thresh.data()[1]); - if (pedited) pedited->colorToning.shadowsColSat = true; - } - if (keyFile.has_key ("ColorToning", "ClCurve")) { colorToning.clcurve = keyFile.get_double_list ("ColorToning", "ClCurve"); if (pedited) pedited->colorToning.clcurve = true; } - if (keyFile.has_key ("ColorToning", "Cl2Curve")) { colorToning.cl2curve = keyFile.get_double_list ("ColorToning", "Cl2Curve"); if (pedited) pedited->colorToning.cl2curve = true; } - if (keyFile.has_key ("ColorToning", "Redlow")) { colorToning.redlow = keyFile.get_double ("ColorToning", "Redlow"); if (pedited) pedited->colorToning.redlow = true; } - if (keyFile.has_key ("ColorToning", "Greenlow")) { colorToning.greenlow = keyFile.get_double ("ColorToning", "Greenlow"); if (pedited) pedited->colorToning.greenlow = true; } - if (keyFile.has_key ("ColorToning", "Bluelow")) { colorToning.bluelow = keyFile.get_double ("ColorToning", "Bluelow"); if (pedited) pedited->colorToning.bluelow = true; } - if (keyFile.has_key ("ColorToning", "Satlow")) { colorToning.satlow = keyFile.get_double ("ColorToning", "Satlow"); if (pedited) pedited->colorToning.satlow = true; } - if (keyFile.has_key ("ColorToning", "Balance")) { colorToning.balance = keyFile.get_integer ("ColorToning", "Balance"); if (pedited) pedited->colorToning.balance = true; } - if (keyFile.has_key ("ColorToning", "Sathigh")) { colorToning.sathigh = keyFile.get_double ("ColorToning", "Sathigh"); if (pedited) pedited->colorToning.sathigh = true; } - if (keyFile.has_key ("ColorToning", "Redmed")) { colorToning.redmed = keyFile.get_double ("ColorToning", "Redmed"); if (pedited) pedited->colorToning.redmed = true; } - if (keyFile.has_key ("ColorToning", "Greenmed")) { colorToning.greenmed = keyFile.get_double ("ColorToning", "Greenmed"); if (pedited) pedited->colorToning.greenmed = true; } - if (keyFile.has_key ("ColorToning", "Bluemed")) { colorToning.bluemed = keyFile.get_double ("ColorToning", "Bluemed"); if (pedited) pedited->colorToning.bluemed = true; } - if (keyFile.has_key ("ColorToning", "Redhigh")) { colorToning.redhigh = keyFile.get_double ("ColorToning", "Redhigh"); if (pedited) pedited->colorToning.redhigh = true; } - if (keyFile.has_key ("ColorToning", "Greenhigh")) { colorToning.greenhigh = keyFile.get_double ("ColorToning", "Greenhigh"); if (pedited) pedited->colorToning.greenhigh = true; } - if (keyFile.has_key ("ColorToning", "Bluehigh")) { colorToning.bluehigh = keyFile.get_double ("ColorToning", "Bluehigh"); if (pedited) pedited->colorToning.bluehigh = true; } -} + if (pedited) { + pedited->resize.scale = true; + } + } - // load raw settings -if (keyFile.has_group ("RAW")) { - if (keyFile.has_key ("RAW", "DarkFrame")) { raw.dark_frame = expandRelativePath(fname, "", keyFile.get_string ("RAW", "DarkFrame" )); if (pedited) pedited->raw.darkFrame = true; } - if (keyFile.has_key ("RAW", "DarkFrameAuto")) { raw.df_autoselect = keyFile.get_boolean ("RAW", "DarkFrameAuto" ); if (pedited) pedited->raw.dfAuto = true; } - if (keyFile.has_key ("RAW", "FlatFieldFile")) { raw.ff_file = expandRelativePath(fname, "", keyFile.get_string ("RAW", "FlatFieldFile" )); if (pedited) pedited->raw.ff_file = true; } - if (keyFile.has_key ("RAW", "FlatFieldAutoSelect")) { raw.ff_AutoSelect = keyFile.get_boolean ("RAW", "FlatFieldAutoSelect" ); if (pedited) pedited->raw.ff_AutoSelect = true; } - if (keyFile.has_key ("RAW", "FlatFieldBlurRadius")) { raw.ff_BlurRadius = keyFile.get_integer ("RAW", "FlatFieldBlurRadius" ); if (pedited) pedited->raw.ff_BlurRadius = true; } - if (keyFile.has_key ("RAW", "FlatFieldBlurType")) { raw.ff_BlurType = keyFile.get_string ("RAW", "FlatFieldBlurType" ); if (pedited) pedited->raw.ff_BlurType = true; } - if (keyFile.has_key ("RAW", "FlatFieldAutoClipControl")) { raw.ff_AutoClipControl = keyFile.get_boolean ("RAW", "FlatFieldAutoClipControl" ); if (pedited) pedited->raw.ff_AutoClipControl = true; } - if (keyFile.has_key ("RAW", "FlatFieldClipControl")) { raw.ff_clipControl = keyFile.get_boolean ("RAW", "FlatFieldClipControl" ); if (pedited) pedited->raw.ff_clipControl = true; } - if (keyFile.has_key ("RAW", "CA")) { raw.ca_autocorrect = keyFile.get_boolean ("RAW", "CA" ); if (pedited) pedited->raw.caCorrection = true; } - if (keyFile.has_key ("RAW", "CARed")) { raw.cared = keyFile.get_double ("RAW", "CARed" ); if (pedited) pedited->raw.caRed = true; } - if (keyFile.has_key ("RAW", "CABlue")) { raw.cablue = keyFile.get_double ("RAW", "CABlue" ); if (pedited) pedited->raw.caBlue = true; } - // for compatibility to elder pp3 versions - if (keyFile.has_key ("RAW", "HotDeadPixels")) { raw.deadPixelFilter = raw.hotPixelFilter = keyFile.get_boolean ("RAW", "HotDeadPixels" ); if (pedited) pedited->raw.hotPixelFilter = pedited->raw.deadPixelFilter = true; } - if (keyFile.has_key ("RAW", "HotPixelFilter")) { raw.hotPixelFilter = keyFile.get_boolean ("RAW", "HotPixelFilter" ); if (pedited) pedited->raw.hotPixelFilter = true; } - if (keyFile.has_key ("RAW", "DeadPixelFilter")) { raw.deadPixelFilter = keyFile.get_boolean ("RAW", "DeadPixelFilter" ); if (pedited) pedited->raw.deadPixelFilter = true; } - - if (keyFile.has_key ("RAW", "HotDeadPixelThresh")) { raw.hotdeadpix_thresh = keyFile.get_integer ("RAW", "HotDeadPixelThresh" ); if (pedited) pedited->raw.hotDeadPixelThresh = true; } - if (keyFile.has_key ("RAW", "PreExposure")) { raw.expos =keyFile.get_double("RAW", "PreExposure"); if (pedited) pedited->raw.exPos = true; } - if (keyFile.has_key ("RAW", "PrePreserv")) { raw.preser =keyFile.get_double("RAW", "PrePreserv"); if (pedited) pedited->raw.exPreser = true; } + if (keyFile.has_key ("Resize", "AppliesTo")) { + resize.appliesTo = keyFile.get_string ("Resize", "AppliesTo"); - if (ppVersion < 320) { - if (keyFile.has_key ("RAW", "Method")) { raw.bayersensor.method = keyFile.get_string ("RAW", "Method"); if (pedited) pedited->raw.bayersensor.method = true; } - if (keyFile.has_key ("RAW", "CcSteps")) { raw.bayersensor.ccSteps = keyFile.get_integer ("RAW", "CcSteps"); if (pedited) pedited->raw.bayersensor.ccSteps = true; } - if (keyFile.has_key ("RAW", "LineDenoise")) { raw.bayersensor.linenoise = keyFile.get_integer ("RAW", "LineDenoise" ); if (pedited) pedited->raw.bayersensor.linenoise = true; } - if (keyFile.has_key ("RAW", "GreenEqThreshold")) { raw.bayersensor.greenthresh= keyFile.get_integer ("RAW", "GreenEqThreshold"); if (pedited) pedited->raw.bayersensor.greenEq = true; } - if (keyFile.has_key ("RAW", "DCBIterations")) { raw.bayersensor.dcb_iterations = keyFile.get_integer("RAW", "DCBIterations"); if (pedited) pedited->raw.bayersensor.dcbIterations = true; } - if (keyFile.has_key ("RAW", "DCBEnhance")) { raw.bayersensor.dcb_enhance = keyFile.get_boolean("RAW", "DCBEnhance"); if (pedited) pedited->raw.bayersensor.dcbEnhance = true; } - if (keyFile.has_key ("RAW", "LMMSEIterations")) { raw.bayersensor.lmmse_iterations = keyFile.get_integer("RAW", "LMMSEIterations"); if (pedited) pedited->raw.bayersensor.lmmseIterations = true; } - if (keyFile.has_key ("RAW", "PreBlackzero")) { raw.bayersensor.black0 = keyFile.get_double("RAW", "PreBlackzero"); if (pedited) pedited->raw.bayersensor.exBlack0 = true; } - if (keyFile.has_key ("RAW", "PreBlackone")) { raw.bayersensor.black1 = keyFile.get_double("RAW", "PreBlackone"); if (pedited) pedited->raw.bayersensor.exBlack1 = true; } - if (keyFile.has_key ("RAW", "PreBlacktwo")) { raw.bayersensor.black2 = keyFile.get_double("RAW", "PreBlacktwo"); if (pedited) pedited->raw.bayersensor.exBlack2 = true; } - if (keyFile.has_key ("RAW", "PreBlackthree")) { raw.bayersensor.black3 = keyFile.get_double("RAW", "PreBlackthree"); if (pedited) pedited->raw.bayersensor.exBlack3 = true; } - if (keyFile.has_key ("RAW", "PreTwoGreen")) { raw.bayersensor.twogreen = keyFile.get_boolean("RAW", "PreTwoGreen"); if (pedited) pedited->raw.bayersensor.exTwoGreen = true; } - //if (keyFile.has_key ("RAW", "ALLEnhance")) { raw.bayersensor.all_enhance = keyFile.get_boolean("RAW", "ALLEnhance"); if (pedited) pedited->raw.bayersensor.allEnhance = true; } - } -} + if (pedited) { + pedited->resize.appliesTo = true; + } + } + + if (keyFile.has_key ("Resize", "Method")) { + resize.method = keyFile.get_string ("Resize", "Method"); + + if (pedited) { + pedited->resize.method = true; + } + } + + if (keyFile.has_key ("Resize", "DataSpecified")) { + resize.dataspec = keyFile.get_integer ("Resize", "DataSpecified"); + + if (pedited) { + pedited->resize.dataspec = true; + } + } + + if (keyFile.has_key ("Resize", "Width")) { + resize.width = keyFile.get_integer ("Resize", "Width"); + + if (pedited) { + pedited->resize.width = true; + } + } + + if (keyFile.has_key ("Resize", "Height")) { + resize.height = keyFile.get_integer ("Resize", "Height"); + + if (pedited) { + pedited->resize.height = true; + } + } + } + + // load post resize sharpening + if (keyFile.has_group ("PostResizeSharpening")) { + if (keyFile.has_key ("PostResizeSharpening", "Enabled")) { + prsharpening.enabled = keyFile.get_boolean ("PostResizeSharpening", "Enabled"); + + if (pedited) { + pedited->prsharpening.enabled = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "Radius")) { + prsharpening.radius = keyFile.get_double ("PostResizeSharpening", "Radius"); + + if (pedited) { + pedited->prsharpening.radius = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "Amount")) { + prsharpening.amount = keyFile.get_integer ("PostResizeSharpening", "Amount"); + + if (pedited) { + pedited->prsharpening.amount = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "Threshold")) { + if (ppVersion < 302) { + int thresh = min(keyFile.get_integer ("PostResizeSharpening", "Threshold"), 2000); + prsharpening.threshold.setValues(thresh, thresh, 2000, 2000); // TODO: 2000 is the maximum value and is taken of rtgui/sharpening.cc ; should be changed by the tool modularization + } else { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("PostResizeSharpening", "Threshold"); + prsharpening.threshold.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 2000), min(thresh.data()[3], 2000)); + } + + if (pedited) { + pedited->prsharpening.threshold = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "OnlyEdges")) { + prsharpening.edgesonly = keyFile.get_boolean ("PostResizeSharpening", "OnlyEdges"); + + if (pedited) { + pedited->prsharpening.edgesonly = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "EdgedetectionRadius")) { + prsharpening.edges_radius = keyFile.get_double ("PostResizeSharpening", "EdgedetectionRadius"); + + if (pedited) { + pedited->prsharpening.edges_radius = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "EdgeTolerance")) { + prsharpening.edges_tolerance = keyFile.get_integer ("PostResizeSharpening", "EdgeTolerance"); + + if (pedited) { + pedited->prsharpening.edges_tolerance = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "HalocontrolEnabled")) { + prsharpening.halocontrol = keyFile.get_boolean ("PostResizeSharpening", "HalocontrolEnabled"); + + if (pedited) { + pedited->prsharpening.halocontrol = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "HalocontrolAmount")) { + prsharpening.halocontrol_amount = keyFile.get_integer ("PostResizeSharpening", "HalocontrolAmount"); + + if (pedited) { + pedited->prsharpening.halocontrol_amount = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "Method")) { + prsharpening.method = keyFile.get_string ("PostResizeSharpening", "Method"); + + if (pedited) { + pedited->prsharpening.method = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "DeconvRadius")) { + prsharpening.deconvradius = keyFile.get_double ("PostResizeSharpening", "DeconvRadius"); + + if (pedited) { + pedited->prsharpening.deconvradius = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "DeconvAmount")) { + prsharpening.deconvamount = keyFile.get_integer ("PostResizeSharpening", "DeconvAmount"); + + if (pedited) { + pedited->prsharpening.deconvamount = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "DeconvDamping")) { + prsharpening.deconvdamping = keyFile.get_integer ("PostResizeSharpening", "DeconvDamping"); + + if (pedited) { + pedited->prsharpening.deconvdamping = true; + } + } + + if (keyFile.has_key ("PostResizeSharpening", "DeconvIterations")) { + prsharpening.deconviter = keyFile.get_integer ("PostResizeSharpening", "DeconvIterations"); + + if (pedited) { + pedited->prsharpening.deconviter = true; + } + } + } + + // load color management settings + if (keyFile.has_group ("Color Management")) { + if (keyFile.has_key ("Color Management", "InputProfile")) { + icm.input = expandRelativePath(fname, "file:", keyFile.get_string ("Color Management", "InputProfile")); + + if (pedited) { + pedited->icm.input = true; + } + } + + if (keyFile.has_key ("Color Management", "ToneCurve")) { + icm.toneCurve = keyFile.get_boolean ("Color Management", "ToneCurve"); + + if (pedited) { + pedited->icm.toneCurve = true; + } + } + + if (keyFile.has_key ("Color Management", "ApplyLookTable")) { + icm.applyLookTable = keyFile.get_boolean ("Color Management", "ApplyLookTable"); + + if (pedited) { + pedited->icm.applyLookTable = true; + } + } + + if (keyFile.has_key ("Color Management", "ApplyBaselineExposureOffset")) { + icm.applyBaselineExposureOffset = keyFile.get_boolean ("Color Management", "ApplyBaselineExposureOffset"); + + if (pedited) { + pedited->icm.applyBaselineExposureOffset = true; + } + } + + if (keyFile.has_key ("Color Management", "ApplyHueSatMap")) { + icm.applyHueSatMap = keyFile.get_boolean ("Color Management", "ApplyHueSatMap"); + + if (pedited) { + pedited->icm.applyHueSatMap = true; + } + } + + if (keyFile.has_key ("Color Management", "BlendCMSMatrix")) { + icm.blendCMSMatrix = keyFile.get_boolean ("Color Management", "BlendCMSMatrix"); + + if (pedited) { + pedited->icm.blendCMSMatrix = true; + } + } + + if (keyFile.has_key ("Color Management", "DCPIlluminant")) { + icm.dcpIlluminant = keyFile.get_integer ("Color Management", "DCPIlluminant"); + + if (pedited) { + pedited->icm.dcpIlluminant = true; + } + } + + if (keyFile.has_key ("Color Management", "WorkingProfile")) { + icm.working = keyFile.get_string ("Color Management", "WorkingProfile"); + + if (pedited) { + pedited->icm.working = true; + } + } + + if (keyFile.has_key ("Color Management", "OutputProfile")) { + icm.output = keyFile.get_string ("Color Management", "OutputProfile"); + + if (pedited) { + pedited->icm.output = true; + } + } + + if (keyFile.has_key ("Color Management", "Gammafree")) { + icm.gamma = keyFile.get_string ("Color Management", "Gammafree"); + + if (pedited) { + pedited->icm.gamfree = true; + } + } + + if (keyFile.has_key ("Color Management", "Freegamma")) { + icm.freegamma = keyFile.get_boolean ("Color Management", "Freegamma"); + + if (pedited) { + pedited->icm.freegamma = true; + } + } + + if (keyFile.has_key ("Color Management", "GammaValue")) { + icm.gampos = keyFile.get_double ("Color Management", "GammaValue"); + + if (pedited) { + pedited->icm.gampos = true; + } + } + + if (keyFile.has_key ("Color Management", "GammaSlope")) { + icm.slpos = keyFile.get_double ("Color Management", "GammaSlope"); + + if (pedited) { + pedited->icm.slpos = true; + } + } + + } + + // load wavelet wavelet parameters + if (keyFile.has_group ("Wavelet")) { + if (keyFile.has_key ("Wavelet", "Enabled")) { + wavelet.enabled = keyFile.get_boolean ("Wavelet", "Enabled"); + + if (pedited) { + pedited->wavelet.enabled = true; + } + } + + if (keyFile.has_key ("Wavelet", "Strength")) { + wavelet.strength = keyFile.get_integer ("Wavelet", "Strength"); + + if (pedited) { + pedited->wavelet.strength = true; + } + } + + if (keyFile.has_key ("Wavelet", "Balance")) { + wavelet.balance = keyFile.get_integer ("Wavelet", "Balance"); + + if (pedited) { + pedited->wavelet.balance = true; + } + } + + if (keyFile.has_key ("Wavelet", "Iter")) { + wavelet.iter = keyFile.get_integer ("Wavelet", "Iter"); + + if (pedited) { + pedited->wavelet.iter = true; + } + } + + if (keyFile.has_key ("Wavelet", "Median")) { + wavelet.median = keyFile.get_boolean ("Wavelet", "Median"); + + if (pedited) { + pedited->wavelet.median = true; + } + } + + if (keyFile.has_key ("Wavelet", "Medianlev")) { + wavelet.medianlev = keyFile.get_boolean ("Wavelet", "Medianlev"); + + if (pedited) { + pedited->wavelet.medianlev = true; + } + } + + if (keyFile.has_key ("Wavelet", "Linkedg")) { + wavelet.linkedg = keyFile.get_boolean ("Wavelet", "Linkedg"); + + if (pedited) { + pedited->wavelet.linkedg = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBenab")) { + wavelet.cbenab = keyFile.get_boolean ("Wavelet", "CBenab"); + + if (pedited) { + pedited->wavelet.cbenab = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBgreenhigh")) { + wavelet.greenhigh = keyFile.get_integer ("Wavelet", "CBgreenhigh"); + + if (pedited) { + pedited->wavelet.greenhigh = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBgreenmed")) { + wavelet.greenmed = keyFile.get_integer ("Wavelet", "CBgreenmed"); + + if (pedited) { + pedited->wavelet.greenmed = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBgreenlow")) { + wavelet.greenlow = keyFile.get_integer ("Wavelet", "CBgreenlow"); + + if (pedited) { + pedited->wavelet.greenlow = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBbluehigh")) { + wavelet.bluehigh = keyFile.get_integer ("Wavelet", "CBbluehigh"); + + if (pedited) { + pedited->wavelet.bluehigh = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBbluemed")) { + wavelet.bluemed = keyFile.get_integer ("Wavelet", "CBbluemed"); + + if (pedited) { + pedited->wavelet.bluemed = true; + } + } + + if (keyFile.has_key ("Wavelet", "CBbluelow")) { + wavelet.bluelow = keyFile.get_integer ("Wavelet", "CBbluelow"); + + if (pedited) { + pedited->wavelet.bluelow = true; + } + } + +// if (keyFile.has_key ("Wavelet", "Edgreinf")) {wavelet.edgreinf = keyFile.get_boolean ("Wavelet", "Edgreinf");if (pedited) pedited->wavelet.edgreinf = true;} + if (keyFile.has_key ("Wavelet", "Lipst")) { + wavelet.lipst = keyFile.get_boolean ("Wavelet", "Lipst"); + + if (pedited) { + pedited->wavelet.lipst = true; + } + } + + if (keyFile.has_key ("Wavelet", "AvoidColorShift")) { + wavelet.avoid = keyFile.get_boolean ("Wavelet", "AvoidColorShift"); + + if (pedited) { + pedited->wavelet.avoid = true; + } + } + + if (keyFile.has_key ("Wavelet", "TMr")) { + wavelet.tmr = keyFile.get_boolean ("Wavelet", "TMr"); + + if (pedited) { + pedited->wavelet.tmr = true; + } + } + + if (keyFile.has_key ("Wavelet", "LevMethod")) { + wavelet.Lmethod = keyFile.get_string ("Wavelet", "LevMethod"); + + if (pedited) { + pedited->wavelet.Lmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "ChoiceLevMethod")) { + wavelet.CLmethod = keyFile.get_string ("Wavelet", "ChoiceLevMethod"); + + if (pedited) { + pedited->wavelet.CLmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "BackMethod")) { + wavelet.Backmethod = keyFile.get_string ("Wavelet", "BackMethod"); + + if (pedited) { + pedited->wavelet.Backmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "TilesMethod")) { + wavelet.Tilesmethod = keyFile.get_string ("Wavelet", "TilesMethod"); + + if (pedited) { + pedited->wavelet.Tilesmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "DaubMethod")) { + wavelet.daubcoeffmethod = keyFile.get_string ("Wavelet", "DaubMethod"); + + if (pedited) { + pedited->wavelet.daubcoeffmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "CHromaMethod")) { + wavelet.CHmethod = keyFile.get_string ("Wavelet", "CHromaMethod"); + + if (pedited) { + pedited->wavelet.CHmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "Medgreinf")) { + wavelet.Medgreinf = keyFile.get_string ("Wavelet", "Medgreinf"); + + if (pedited) { + pedited->wavelet.Medgreinf = true; + } + } + + if (keyFile.has_key ("Wavelet", "CHSLromaMethod")) { + wavelet.CHSLmethod = keyFile.get_string ("Wavelet", "CHSLromaMethod"); + + if (pedited) { + pedited->wavelet.CHSLmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "EDMethod")) { + wavelet.EDmethod = keyFile.get_string ("Wavelet", "EDMethod"); + + if (pedited) { + pedited->wavelet.EDmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "NPMethod")) { + wavelet.NPmethod = keyFile.get_string ("Wavelet", "NPMethod"); + + if (pedited) { + pedited->wavelet.NPmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "BAMethod")) { + wavelet.BAmethod = keyFile.get_string ("Wavelet", "BAMethod"); + + if (pedited) { + pedited->wavelet.BAmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "TMMethod")) { + wavelet.TMmethod = keyFile.get_string ("Wavelet", "TMMethod"); + + if (pedited) { + pedited->wavelet.TMmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "HSMethod")) { + wavelet.HSmethod = keyFile.get_string ("Wavelet", "HSMethod"); + + if (pedited) { + pedited->wavelet.HSmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "DirMethod")) { + wavelet.Dirmethod = keyFile.get_string ("Wavelet", "DirMethod"); + + if (pedited) { + pedited->wavelet.Dirmethod = true; + } + } + + if (keyFile.has_key ("Wavelet", "ResidualcontShadow")) { + wavelet.rescon = keyFile.get_integer ("Wavelet", "ResidualcontShadow"); + + if (pedited) { + pedited->wavelet.rescon = true; + } + } + + if (keyFile.has_key ("Wavelet", "ResidualcontHighlight")) { + wavelet.resconH = keyFile.get_integer ("Wavelet", "ResidualcontHighlight"); + + if (pedited) { + pedited->wavelet.resconH = true; + } + } + + if (keyFile.has_key ("Wavelet", "Residualchroma")) { + wavelet.reschro = keyFile.get_integer ("Wavelet", "Residualchroma"); + + if (pedited) { + pedited->wavelet.reschro = true; + } + } + + if (keyFile.has_key ("Wavelet", "ResidualTM")) { + wavelet.tmrs = keyFile.get_double ("Wavelet", "ResidualTM"); + + if (pedited) { + pedited->wavelet.tmrs = true; + } + } + + if (keyFile.has_key ("Wavelet", "Residualgamma")) { + wavelet.gamma = keyFile.get_double ("Wavelet", "Residualgamma"); + + if (pedited) { + pedited->wavelet.gamma = true; + } + } + + if (keyFile.has_key ("Wavelet", "ContExtra")) { + wavelet.sup = keyFile.get_integer ("Wavelet", "ContExtra"); + + if (pedited) { + pedited->wavelet.sup = true; + } + } + + if (keyFile.has_key ("Wavelet", "HueRangeResidual")) { + wavelet.sky = keyFile.get_double ("Wavelet", "HueRangeResidual"); + + if (pedited) { + pedited->wavelet.sky = true; + } + } + + if (keyFile.has_key ("Wavelet", "MaxLev")) { + wavelet.thres = keyFile.get_integer ("Wavelet", "MaxLev"); + + if (pedited) { + pedited->wavelet.thres = true; + } + } + + if (keyFile.has_key ("Wavelet", "ThresholdHighLight")) { + wavelet.threshold = keyFile.get_integer ("Wavelet", "ThresholdHighLight"); + + if (pedited) { + pedited->wavelet.threshold = true; + } + } + + if (keyFile.has_key ("Wavelet", "ThresholdShadow")) { + wavelet.threshold2 = keyFile.get_integer ("Wavelet", "ThresholdShadow"); + + if (pedited) { + pedited->wavelet.threshold2 = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgedetect")) { + wavelet.edgedetect = keyFile.get_integer ("Wavelet", "Edgedetect"); + + if (pedited) { + pedited->wavelet.edgedetect = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgedetectthr")) { + wavelet.edgedetectthr = keyFile.get_integer ("Wavelet", "Edgedetectthr"); + + if (pedited) { + pedited->wavelet.edgedetectthr = true; + } + } + + if (keyFile.has_key ("Wavelet", "EdgedetectthrHi")) { + wavelet.edgedetectthr2 = keyFile.get_integer ("Wavelet", "EdgedetectthrHi"); + + if (pedited) { + pedited->wavelet.edgedetectthr2 = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgesensi")) { + wavelet.edgesensi = keyFile.get_integer ("Wavelet", "Edgesensi"); + + if (pedited) { + pedited->wavelet.edgesensi = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgeampli")) { + wavelet.edgeampli = keyFile.get_integer ("Wavelet", "Edgeampli"); + + if (pedited) { + pedited->wavelet.edgeampli = true; + } + } + + if (keyFile.has_key ("Wavelet", "ThresholdChroma")) { + wavelet.chroma = keyFile.get_integer ("Wavelet", "ThresholdChroma"); + + if (pedited) { + pedited->wavelet.chroma = true; + } + } + + if (keyFile.has_key ("Wavelet", "ChromaLink")) { + wavelet.chro = keyFile.get_integer ("Wavelet", "ChromaLink"); + + if (pedited) { + pedited->wavelet.chro = true; + } + } + + if (keyFile.has_key ("Wavelet", "Contrast")) { + wavelet.contrast = keyFile.get_integer ("Wavelet", "Contrast"); + + if (pedited) { + pedited->wavelet.contrast = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgrad")) { + wavelet.edgrad = keyFile.get_integer ("Wavelet", "Edgrad"); + + if (pedited) { + pedited->wavelet.edgrad = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgval")) { + wavelet.edgval = keyFile.get_integer ("Wavelet", "Edgval"); + + if (pedited) { + pedited->wavelet.edgval = true; + } + } + + if (keyFile.has_key ("Wavelet", "ThrEdg")) { + wavelet.edgthresh = keyFile.get_integer ("Wavelet", "ThrEdg"); + + if (pedited) { + pedited->wavelet.edgthresh = true; + } + } + + if (keyFile.has_key ("Wavelet", "ThresholdResidShadow")) { + wavelet.thr = keyFile.get_integer ("Wavelet", "ThresholdResidShadow"); + + if (pedited) { + pedited->wavelet.thr = true; + } + } + + if (keyFile.has_key ("Wavelet", "ThresholdResidHighLight")) { + wavelet.thrH = keyFile.get_integer ("Wavelet", "ThresholdResidHighLight"); + + if (pedited) { + pedited->wavelet.thrH = true; + } + } + + if (keyFile.has_key ("Wavelet", "ContrastCurve")) { + wavelet.ccwcurve = keyFile.get_double_list ("Wavelet", "ContrastCurve"); + + if (pedited) { + pedited->wavelet.ccwcurve = true; + } + } + + if (keyFile.has_key ("Wavelet", "OpacityCurveRG")) { + wavelet.opacityCurveRG = keyFile.get_double_list ("Wavelet", "OpacityCurveRG"); + + if (pedited) { + pedited->wavelet.opacityCurveRG = true; + } + } + + if (keyFile.has_key ("Wavelet", "OpacityCurveBY")) { + wavelet.opacityCurveBY = keyFile.get_double_list ("Wavelet", "OpacityCurveBY"); + + if (pedited) { + pedited->wavelet.opacityCurveBY = true; + } + } + + if (keyFile.has_key ("Wavelet", "OpacityCurveW")) { + wavelet.opacityCurveW = keyFile.get_double_list ("Wavelet", "OpacityCurveW"); + + if (pedited) { + pedited->wavelet.opacityCurveW = true; + } + } + + if (keyFile.has_key ("Wavelet", "OpacityCurveWL")) { + wavelet.opacityCurveWL = keyFile.get_double_list ("Wavelet", "OpacityCurveWL"); + + if (pedited) { + pedited->wavelet.opacityCurveWL = true; + } + } + + if (keyFile.has_key ("Wavelet", "HHcurve")) { + wavelet.hhcurve = keyFile.get_double_list ("Wavelet", "HHcurve"); + + if (pedited) { + pedited->wavelet.hhcurve = true; + } + } + + if (keyFile.has_key ("Wavelet", "CHcurve")) { + wavelet.Chcurve = keyFile.get_double_list ("Wavelet", "CHcurve"); + + if (pedited) { + pedited->wavelet.Chcurve = true; + } + } + + if (keyFile.has_key ("Wavelet", "WavclCurve")) { + wavelet.wavclCurve = keyFile.get_double_list ("Wavelet", "WavclCurve"); + + if (pedited) { + pedited->wavelet.wavclCurve = true; + } + } + + if (keyFile.has_key ("Wavelet", "Hueskin")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Hueskin"); + wavelet.hueskin.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.hueskin = true; + } + } + + if (keyFile.has_key ("Wavelet", "HueRange")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "HueRange"); + wavelet.hueskin2.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.hueskin2 = true; + } + } + + if (keyFile.has_key ("Wavelet", "HLRange")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "HLRange"); + wavelet.hllev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.hllev = true; + } + } + + if (keyFile.has_key ("Wavelet", "SHRange")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "SHRange"); + wavelet.bllev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.bllev = true; + } + } + + if (keyFile.has_key ("Wavelet", "Edgcont")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Edgcont"); + wavelet.edgcont.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.edgcont = true; + } + } + + if (keyFile.has_key ("Wavelet", "Level0noise")) { + Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level0noise"); + wavelet.level0noise.setValues(thresh.data()[0], thresh.data()[1]); + + if (pedited) { + pedited->wavelet.level0noise = true; + } + } + + if (keyFile.has_key ("Wavelet", "Level1noise")) { + Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level1noise"); + wavelet.level1noise.setValues(thresh.data()[0], thresh.data()[1]); + + if (pedited) { + pedited->wavelet.level1noise = true; + } + } + + if (keyFile.has_key ("Wavelet", "Level2noise")) { + Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level2noise"); + wavelet.level2noise.setValues(thresh.data()[0], thresh.data()[1]); + + if (pedited) { + pedited->wavelet.level2noise = true; + } + } + + if (keyFile.has_key ("Wavelet", "Level3noise")) { + Glib::ArrayHandle thresh = keyFile.get_double_list ("Wavelet", "Level3noise"); + wavelet.level3noise.setValues(thresh.data()[0], thresh.data()[1]); + + if (pedited) { + pedited->wavelet.level3noise = true; + } + } + + + if (keyFile.has_key ("Wavelet", "Pastlev")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Pastlev"); + wavelet.pastlev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.pastlev = true; + } + } + + if (keyFile.has_key ("Wavelet", "Satlev")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("Wavelet", "Satlev"); + wavelet.satlev.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->wavelet.satlev = true; + } + } + + + if(keyFile.has_key ("Wavelet", "Skinprotect")) { + wavelet.skinprotect = keyFile.get_double ("Wavelet", "Skinprotect"); + + if (pedited) { + pedited->wavelet.skinprotect = true; + } + } + + if (keyFile.has_key ("Wavelet", "Expcontrast")) { + wavelet.expcontrast = keyFile.get_boolean ("Wavelet", "Expcontrast"); + + if (pedited) { + pedited->wavelet.expcontrast = true; + } + } + + if (keyFile.has_key ("Wavelet", "Expchroma")) { + wavelet.expchroma = keyFile.get_boolean ("Wavelet", "Expchroma"); + + if (pedited) { + pedited->wavelet.expchroma = true; + } + } + + for(int i = 0; i < 9; i ++) { + std::stringstream ss; + ss << "Contrast" << (i + 1); + + if(keyFile.has_key ("Wavelet", ss.str())) { + wavelet.c[i] = keyFile.get_integer ("Wavelet", ss.str()); + + if (pedited) { + pedited->wavelet.c[i] = true; + } + } + } + + for(int i = 0; i < 9; i ++) { + std::stringstream ss; + ss << "Chroma" << (i + 1); + + if(keyFile.has_key ("Wavelet", ss.str())) { + wavelet.ch[i] = keyFile.get_integer ("Wavelet", ss.str()); + + if (pedited) { + pedited->wavelet.ch[i] = true; + } + } + } + + if (keyFile.has_key ("Wavelet", "Expedge")) { + wavelet.expedge = keyFile.get_boolean ("Wavelet", "Expedge"); + + if (pedited) { + pedited->wavelet.expedge = true; + } + } + + if (keyFile.has_key ("Wavelet", "Expresid")) { + wavelet.expresid = keyFile.get_boolean ("Wavelet", "Expresid"); + + if (pedited) { + pedited->wavelet.expresid = true; + } + } + + if (keyFile.has_key ("Wavelet", "Expfinal")) { + wavelet.expfinal = keyFile.get_boolean ("Wavelet", "Expfinal"); + + if (pedited) { + pedited->wavelet.expfinal = true; + } + } + + if (keyFile.has_key ("Wavelet", "Exptoning")) { + wavelet.exptoning = keyFile.get_boolean ("Wavelet", "Exptoning"); + + if (pedited) { + pedited->wavelet.exptoning = true; + } + } + + if (keyFile.has_key ("Wavelet", "Expnoise")) { + wavelet.expnoise = keyFile.get_boolean ("Wavelet", "Expnoise"); + + if (pedited) { + pedited->wavelet.expnoise = true; + } + } + + + } + + // load directional pyramid equalizer parameters + if (keyFile.has_group ("Directional Pyramid Equalizer")) { + if (keyFile.has_key ("Directional Pyramid Equalizer", "Enabled")) { + dirpyrequalizer.enabled = keyFile.get_boolean ("Directional Pyramid Equalizer", "Enabled"); + + if (pedited) { + pedited->dirpyrequalizer.enabled = true; + } + } + + if (keyFile.has_key ("Directional Pyramid Equalizer", "Gamutlab")) { + dirpyrequalizer.gamutlab = keyFile.get_boolean ("Directional Pyramid Equalizer", "Gamutlab"); + + if (pedited) { + pedited->dirpyrequalizer.gamutlab = 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"); + dirpyrequalizer.hueskin.setValues(thresh.data()[0], thresh.data()[1], min(thresh.data()[2], 300), min(thresh.data()[3], 300)); + + if (pedited) { + pedited->dirpyrequalizer.hueskin = true; + } + } + + if (ppVersion < 316) { + for(int i = 0; i < 5; i ++) { + std::stringstream ss; + ss << "Mult" << i; + + if(keyFile.has_key ("Directional Pyramid Equalizer", ss.str())) { + if(i == 4) { + dirpyrequalizer.threshold = keyFile.get_double ("Directional Pyramid Equalizer", ss.str()); + + if (pedited) { + pedited->dirpyrequalizer.threshold = true; + } + } else { + dirpyrequalizer.mult[i] = keyFile.get_double ("Directional Pyramid Equalizer", ss.str()); + + if (pedited) { + pedited->dirpyrequalizer.mult[i] = true; + } + } + } + } + + dirpyrequalizer.mult[4] = 1.0; + } else { + // 5 level wavelet + dedicated threshold parameter + for(int i = 0; i < 6; i ++) { + std::stringstream ss; + ss << "Mult" << i; + + if(keyFile.has_key ("Directional Pyramid Equalizer", ss.str())) { + dirpyrequalizer.mult[i] = keyFile.get_double ("Directional Pyramid Equalizer", ss.str()); + + if (pedited) { + pedited->dirpyrequalizer.mult[i] = true; + } + } + } + + if(keyFile.has_key ("Directional Pyramid Equalizer", "Threshold")) { + dirpyrequalizer.threshold = keyFile.get_double ("Directional Pyramid Equalizer", "Threshold"); + + if (pedited) { + pedited->dirpyrequalizer.threshold = true; + } + } + + if(keyFile.has_key ("Directional Pyramid Equalizer", "Skinprotect")) { + dirpyrequalizer.skinprotect = keyFile.get_double ("Directional Pyramid Equalizer", "Skinprotect"); + + if (pedited) { + pedited->dirpyrequalizer.skinprotect = true; + } + } + } + } + + // load CLUT parameters + if ( keyFile.has_group( "Film Simulation" ) ) { + if ( keyFile.has_key( "Film Simulation", "Enabled" ) ) { + filmSimulation.enabled = keyFile.get_boolean( "Film Simulation", "Enabled" ); + + if ( pedited ) { + pedited->filmSimulation.enabled = true; + } + } + + if ( keyFile.has_key( "Film Simulation", "ClutFilename" ) ) { + filmSimulation.clutFilename = keyFile.get_string( "Film Simulation", "ClutFilename" ); + + if ( pedited ) { + pedited->filmSimulation.clutFilename = true; + } + } + + if ( keyFile.has_key( "Film Simulation", "Strength" ) ) { + if (ppVersion < 321) { + filmSimulation.strength = int(keyFile.get_double( "Film Simulation", "Strength" ) * 100 + 0.1); + } else { + filmSimulation.strength = keyFile.get_integer( "Film Simulation", "Strength" ); + } + + if ( pedited ) { + pedited->filmSimulation.strength = true; + } + } + } + + // load HSV wavelet parameters + if (keyFile.has_group ("HSV Equalizer")) { + if (ppVersion >= 300) { + if (keyFile.has_key ("HSV Equalizer", "HCurve")) { + hsvequalizer.hcurve = keyFile.get_double_list ("HSV Equalizer", "HCurve"); + + if (pedited) { + pedited->hsvequalizer.hcurve = true; + } + } + + if (keyFile.has_key ("HSV Equalizer", "SCurve")) { + hsvequalizer.scurve = keyFile.get_double_list ("HSV Equalizer", "SCurve"); + + if (pedited) { + pedited->hsvequalizer.scurve = true; + } + } + + if (keyFile.has_key ("HSV Equalizer", "VCurve")) { + hsvequalizer.vcurve = keyFile.get_double_list ("HSV Equalizer", "VCurve"); + + if (pedited) { + pedited->hsvequalizer.vcurve = true; + } + } + } + } + + // load RGB curves + if (keyFile.has_group ("RGB Curves")) { + if (keyFile.has_key ("RGB Curves", "LumaMode")) { + rgbCurves.lumamode = keyFile.get_boolean ("RGB Curves", "LumaMode"); + + if (pedited) { + pedited->rgbCurves.lumamode = true; + } + } + + if (keyFile.has_key ("RGB Curves", "rCurve")) { + rgbCurves.rcurve = keyFile.get_double_list ("RGB Curves", "rCurve"); + + if (pedited) { + pedited->rgbCurves.rcurve = true; + } + } + + if (keyFile.has_key ("RGB Curves", "gCurve")) { + rgbCurves.gcurve = keyFile.get_double_list ("RGB Curves", "gCurve"); + + if (pedited) { + pedited->rgbCurves.gcurve = true; + } + } + + if (keyFile.has_key ("RGB Curves", "bCurve")) { + rgbCurves.bcurve = keyFile.get_double_list ("RGB Curves", "bCurve"); + + if (pedited) { + pedited->rgbCurves.bcurve = true; + } + } + } + + // load Color Toning + if (keyFile.has_group ("ColorToning")) { + if (keyFile.has_key ("ColorToning", "Enabled")) { + colorToning.enabled = keyFile.get_boolean ("ColorToning", "Enabled"); + + if (pedited) { + pedited->colorToning.enabled = true; + } + } + + if (keyFile.has_key ("ColorToning", "Method")) { + colorToning.method = keyFile.get_string ("ColorToning", "Method"); + + if (pedited) { + pedited->colorToning.method = true; + } + } + + if (keyFile.has_key ("ColorToning", "Lumamode")) { + colorToning.lumamode = keyFile.get_boolean ("ColorToning", "Lumamode"); + + if (pedited) { + pedited->colorToning.lumamode = true; + } + } + + if (keyFile.has_key ("ColorToning", "Twocolor")) { + colorToning.twocolor = keyFile.get_string ("ColorToning", "Twocolor"); + + if (pedited) { + pedited->colorToning.twocolor = true; + } + } + + if (keyFile.has_key ("ColorToning", "OpacityCurve")) { + colorToning.opacityCurve = keyFile.get_double_list ("ColorToning", "OpacityCurve"); + + if (pedited) { + pedited->colorToning.opacityCurve = true; + } + } + + if (keyFile.has_key ("ColorToning", "ColorCurve")) { + colorToning.colorCurve = keyFile.get_double_list ("ColorToning", "ColorCurve"); + + if (pedited) { + pedited->colorToning.colorCurve = true; + } + } + + if (keyFile.has_key ("ColorToning", "Autosat")) { + colorToning.autosat = keyFile.get_boolean ("ColorToning", "Autosat"); + + if (pedited) { + pedited->colorToning.autosat = true; + } + } + + if (keyFile.has_key ("ColorToning", "SatProtectionThreshold")) { + colorToning.satProtectionThreshold = keyFile.get_integer ("ColorToning", "SatProtectionThreshold"); + + if (pedited) { + pedited->colorToning.satprotectionthreshold = true; + } + } + + if (keyFile.has_key ("ColorToning", "SaturatedOpacity")) { + colorToning.saturatedOpacity = keyFile.get_integer ("ColorToning", "SaturatedOpacity"); + + if (pedited) { + pedited->colorToning.saturatedopacity = true; + } + } + + if (keyFile.has_key ("ColorToning", "Strength")) { + colorToning.strength = keyFile.get_integer ("ColorToning", "Strength"); + + if (pedited) { + pedited->colorToning.strength = true; + } + } + + if (keyFile.has_key ("ColorToning", "HighlightsColorSaturation")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("ColorToning", "HighlightsColorSaturation"); + colorToning.hlColSat.setValues(thresh.data()[0], thresh.data()[1]); + + if (pedited) { + pedited->colorToning.hlColSat = true; + } + } + + if (keyFile.has_key ("ColorToning", "ShadowsColorSaturation")) { + Glib::ArrayHandle thresh = keyFile.get_integer_list ("ColorToning", "ShadowsColorSaturation"); + colorToning.shadowsColSat.setValues(thresh.data()[0], thresh.data()[1]); + + if (pedited) { + pedited->colorToning.shadowsColSat = true; + } + } + + if (keyFile.has_key ("ColorToning", "ClCurve")) { + colorToning.clcurve = keyFile.get_double_list ("ColorToning", "ClCurve"); + + if (pedited) { + pedited->colorToning.clcurve = true; + } + } + + if (keyFile.has_key ("ColorToning", "Cl2Curve")) { + colorToning.cl2curve = keyFile.get_double_list ("ColorToning", "Cl2Curve"); + + if (pedited) { + pedited->colorToning.cl2curve = true; + } + } + + if (keyFile.has_key ("ColorToning", "Redlow")) { + colorToning.redlow = keyFile.get_double ("ColorToning", "Redlow"); + + if (pedited) { + pedited->colorToning.redlow = true; + } + } + + if (keyFile.has_key ("ColorToning", "Greenlow")) { + colorToning.greenlow = keyFile.get_double ("ColorToning", "Greenlow"); + + if (pedited) { + pedited->colorToning.greenlow = true; + } + } + + if (keyFile.has_key ("ColorToning", "Bluelow")) { + colorToning.bluelow = keyFile.get_double ("ColorToning", "Bluelow"); + + if (pedited) { + pedited->colorToning.bluelow = true; + } + } + + if (keyFile.has_key ("ColorToning", "Satlow")) { + colorToning.satlow = keyFile.get_double ("ColorToning", "Satlow"); + + if (pedited) { + pedited->colorToning.satlow = true; + } + } + + if (keyFile.has_key ("ColorToning", "Balance")) { + colorToning.balance = keyFile.get_integer ("ColorToning", "Balance"); + + if (pedited) { + pedited->colorToning.balance = true; + } + } + + if (keyFile.has_key ("ColorToning", "Sathigh")) { + colorToning.sathigh = keyFile.get_double ("ColorToning", "Sathigh"); + + if (pedited) { + pedited->colorToning.sathigh = true; + } + } + + if (keyFile.has_key ("ColorToning", "Redmed")) { + colorToning.redmed = keyFile.get_double ("ColorToning", "Redmed"); + + if (pedited) { + pedited->colorToning.redmed = true; + } + } + + if (keyFile.has_key ("ColorToning", "Greenmed")) { + colorToning.greenmed = keyFile.get_double ("ColorToning", "Greenmed"); + + if (pedited) { + pedited->colorToning.greenmed = true; + } + } + + if (keyFile.has_key ("ColorToning", "Bluemed")) { + colorToning.bluemed = keyFile.get_double ("ColorToning", "Bluemed"); + + if (pedited) { + pedited->colorToning.bluemed = true; + } + } + + if (keyFile.has_key ("ColorToning", "Redhigh")) { + colorToning.redhigh = keyFile.get_double ("ColorToning", "Redhigh"); + + if (pedited) { + pedited->colorToning.redhigh = true; + } + } + + if (keyFile.has_key ("ColorToning", "Greenhigh")) { + colorToning.greenhigh = keyFile.get_double ("ColorToning", "Greenhigh"); + + if (pedited) { + pedited->colorToning.greenhigh = true; + } + } + + if (keyFile.has_key ("ColorToning", "Bluehigh")) { + colorToning.bluehigh = keyFile.get_double ("ColorToning", "Bluehigh"); + + if (pedited) { + pedited->colorToning.bluehigh = true; + } + } + } + + // load raw settings + if (keyFile.has_group ("RAW")) { + if (keyFile.has_key ("RAW", "DarkFrame")) { + raw.dark_frame = expandRelativePath(fname, "", keyFile.get_string ("RAW", "DarkFrame" )); + + if (pedited) { + pedited->raw.darkFrame = true; + } + } + + if (keyFile.has_key ("RAW", "DarkFrameAuto")) { + raw.df_autoselect = keyFile.get_boolean ("RAW", "DarkFrameAuto" ); + + if (pedited) { + pedited->raw.dfAuto = true; + } + } + + if (keyFile.has_key ("RAW", "FlatFieldFile")) { + raw.ff_file = expandRelativePath(fname, "", keyFile.get_string ("RAW", "FlatFieldFile" )); + + if (pedited) { + pedited->raw.ff_file = true; + } + } + + if (keyFile.has_key ("RAW", "FlatFieldAutoSelect")) { + raw.ff_AutoSelect = keyFile.get_boolean ("RAW", "FlatFieldAutoSelect" ); + + if (pedited) { + pedited->raw.ff_AutoSelect = true; + } + } + + if (keyFile.has_key ("RAW", "FlatFieldBlurRadius")) { + raw.ff_BlurRadius = keyFile.get_integer ("RAW", "FlatFieldBlurRadius" ); + + if (pedited) { + pedited->raw.ff_BlurRadius = true; + } + } + + if (keyFile.has_key ("RAW", "FlatFieldBlurType")) { + raw.ff_BlurType = keyFile.get_string ("RAW", "FlatFieldBlurType" ); + + if (pedited) { + pedited->raw.ff_BlurType = true; + } + } + + if (keyFile.has_key ("RAW", "FlatFieldAutoClipControl")) { + raw.ff_AutoClipControl = keyFile.get_boolean ("RAW", "FlatFieldAutoClipControl" ); + + if (pedited) { + pedited->raw.ff_AutoClipControl = true; + } + } + + if (keyFile.has_key ("RAW", "FlatFieldClipControl")) { + raw.ff_clipControl = keyFile.get_boolean ("RAW", "FlatFieldClipControl" ); + + if (pedited) { + pedited->raw.ff_clipControl = true; + } + } + + if (keyFile.has_key ("RAW", "CA")) { + raw.ca_autocorrect = keyFile.get_boolean ("RAW", "CA" ); + + if (pedited) { + pedited->raw.caCorrection = true; + } + } + + if (keyFile.has_key ("RAW", "CARed")) { + raw.cared = keyFile.get_double ("RAW", "CARed" ); + + if (pedited) { + pedited->raw.caRed = true; + } + } + + if (keyFile.has_key ("RAW", "CABlue")) { + raw.cablue = keyFile.get_double ("RAW", "CABlue" ); + + if (pedited) { + pedited->raw.caBlue = true; + } + } + + // for compatibility to elder pp3 versions + if (keyFile.has_key ("RAW", "HotDeadPixels")) { + raw.deadPixelFilter = raw.hotPixelFilter = keyFile.get_boolean ("RAW", "HotDeadPixels" ); + + if (pedited) { + pedited->raw.hotPixelFilter = pedited->raw.deadPixelFilter = true; + } + } + + if (keyFile.has_key ("RAW", "HotPixelFilter")) { + raw.hotPixelFilter = keyFile.get_boolean ("RAW", "HotPixelFilter" ); + + if (pedited) { + pedited->raw.hotPixelFilter = true; + } + } + + if (keyFile.has_key ("RAW", "DeadPixelFilter")) { + raw.deadPixelFilter = keyFile.get_boolean ("RAW", "DeadPixelFilter" ); + + if (pedited) { + pedited->raw.deadPixelFilter = true; + } + } + + if (keyFile.has_key ("RAW", "HotDeadPixelThresh")) { + raw.hotdeadpix_thresh = keyFile.get_integer ("RAW", "HotDeadPixelThresh" ); + + if (pedited) { + pedited->raw.hotDeadPixelThresh = true; + } + } + + if (keyFile.has_key ("RAW", "PreExposure")) { + raw.expos = keyFile.get_double("RAW", "PreExposure"); + + if (pedited) { + pedited->raw.exPos = true; + } + } + + if (keyFile.has_key ("RAW", "PrePreserv")) { + raw.preser = keyFile.get_double("RAW", "PrePreserv"); + + if (pedited) { + pedited->raw.exPreser = true; + } + } + + if (ppVersion < 320) { + if (keyFile.has_key ("RAW", "Method")) { + raw.bayersensor.method = keyFile.get_string ("RAW", "Method"); + + if (pedited) { + pedited->raw.bayersensor.method = true; + } + } + + if (keyFile.has_key ("RAW", "CcSteps")) { + raw.bayersensor.ccSteps = keyFile.get_integer ("RAW", "CcSteps"); + + if (pedited) { + pedited->raw.bayersensor.ccSteps = true; + } + } + + if (keyFile.has_key ("RAW", "LineDenoise")) { + raw.bayersensor.linenoise = keyFile.get_integer ("RAW", "LineDenoise" ); + + if (pedited) { + pedited->raw.bayersensor.linenoise = true; + } + } + + if (keyFile.has_key ("RAW", "GreenEqThreshold")) { + raw.bayersensor.greenthresh = keyFile.get_integer ("RAW", "GreenEqThreshold"); + + if (pedited) { + pedited->raw.bayersensor.greenEq = true; + } + } + + if (keyFile.has_key ("RAW", "DCBIterations")) { + raw.bayersensor.dcb_iterations = keyFile.get_integer("RAW", "DCBIterations"); + + if (pedited) { + pedited->raw.bayersensor.dcbIterations = true; + } + } + + if (keyFile.has_key ("RAW", "DCBEnhance")) { + raw.bayersensor.dcb_enhance = keyFile.get_boolean("RAW", "DCBEnhance"); + + if (pedited) { + pedited->raw.bayersensor.dcbEnhance = true; + } + } + + if (keyFile.has_key ("RAW", "LMMSEIterations")) { + raw.bayersensor.lmmse_iterations = keyFile.get_integer("RAW", "LMMSEIterations"); + + if (pedited) { + pedited->raw.bayersensor.lmmseIterations = true; + } + } + + if (keyFile.has_key ("RAW", "PreBlackzero")) { + raw.bayersensor.black0 = keyFile.get_double("RAW", "PreBlackzero"); + + if (pedited) { + pedited->raw.bayersensor.exBlack0 = true; + } + } + + if (keyFile.has_key ("RAW", "PreBlackone")) { + raw.bayersensor.black1 = keyFile.get_double("RAW", "PreBlackone"); + + if (pedited) { + pedited->raw.bayersensor.exBlack1 = true; + } + } + + if (keyFile.has_key ("RAW", "PreBlacktwo")) { + raw.bayersensor.black2 = keyFile.get_double("RAW", "PreBlacktwo"); + + if (pedited) { + pedited->raw.bayersensor.exBlack2 = true; + } + } + + if (keyFile.has_key ("RAW", "PreBlackthree")) { + raw.bayersensor.black3 = keyFile.get_double("RAW", "PreBlackthree"); + + if (pedited) { + pedited->raw.bayersensor.exBlack3 = true; + } + } + + if (keyFile.has_key ("RAW", "PreTwoGreen")) { + raw.bayersensor.twogreen = keyFile.get_boolean("RAW", "PreTwoGreen"); + + if (pedited) { + pedited->raw.bayersensor.exTwoGreen = true; + } + } + + //if (keyFile.has_key ("RAW", "ALLEnhance")) { raw.bayersensor.all_enhance = keyFile.get_boolean("RAW", "ALLEnhance"); if (pedited) pedited->raw.bayersensor.allEnhance = true; } + } + } // load Bayer sensors' raw settings -if (keyFile.has_group ("RAW Bayer")) { - if (keyFile.has_key ("RAW Bayer", "Method")) { raw.bayersensor.method = keyFile.get_string ("RAW Bayer", "Method"); if (pedited) pedited->raw.bayersensor.method = true; } - if (keyFile.has_key ("RAW Bayer", "CcSteps")) { raw.bayersensor.ccSteps = keyFile.get_integer ("RAW Bayer", "CcSteps"); if (pedited) pedited->raw.bayersensor.ccSteps = true; } - if (keyFile.has_key ("RAW Bayer", "PreBlack0")) { raw.bayersensor.black0 = keyFile.get_double("RAW Bayer", "PreBlack0"); if (pedited) pedited->raw.bayersensor.exBlack0 = true; } - if (keyFile.has_key ("RAW Bayer", "PreBlack1")) { raw.bayersensor.black1 = keyFile.get_double("RAW Bayer", "PreBlack1"); if (pedited) pedited->raw.bayersensor.exBlack1 = true; } - if (keyFile.has_key ("RAW Bayer", "PreBlack2")) { raw.bayersensor.black2 = keyFile.get_double("RAW Bayer", "PreBlack2"); if (pedited) pedited->raw.bayersensor.exBlack2 = true; } - if (keyFile.has_key ("RAW Bayer", "PreBlack3")) { raw.bayersensor.black3 = keyFile.get_double("RAW Bayer", "PreBlack3"); if (pedited) pedited->raw.bayersensor.exBlack3 = true; } - if (keyFile.has_key ("RAW Bayer", "PreTwoGreen")) { raw.bayersensor.twogreen = keyFile.get_boolean("RAW Bayer", "PreTwoGreen"); if (pedited) pedited->raw.bayersensor.exTwoGreen = true; } - if (keyFile.has_key ("RAW Bayer", "LineDenoise")) { raw.bayersensor.linenoise = keyFile.get_integer ("RAW Bayer", "LineDenoise" ); if (pedited) pedited->raw.bayersensor.linenoise = true; } - if (keyFile.has_key ("RAW Bayer", "GreenEqThreshold")) { raw.bayersensor.greenthresh= keyFile.get_integer ("RAW Bayer", "GreenEqThreshold"); if (pedited) pedited->raw.bayersensor.greenEq = true; } - if (keyFile.has_key ("RAW Bayer", "DCBIterations")) { raw.bayersensor.dcb_iterations = keyFile.get_integer("RAW Bayer", "DCBIterations"); if (pedited) pedited->raw.bayersensor.dcbIterations = true; } - if (keyFile.has_key ("RAW Bayer", "DCBEnhance")) { raw.bayersensor.dcb_enhance = keyFile.get_boolean("RAW Bayer", "DCBEnhance"); if (pedited) pedited->raw.bayersensor.dcbEnhance = true; } - if (keyFile.has_key ("RAW Bayer", "LMMSEIterations")) { raw.bayersensor.lmmse_iterations = keyFile.get_integer("RAW Bayer", "LMMSEIterations"); if (pedited) pedited->raw.bayersensor.lmmseIterations = true; } - //if (keyFile.has_key ("RAW Bayer", "ALLEnhance")) { raw.bayersensor.all_enhance = keyFile.get_boolean("RAW Bayer", "ALLEnhance"); if (pedited) pedited->raw.bayersensor.allEnhance = true; } -} + if (keyFile.has_group ("RAW Bayer")) { + if (keyFile.has_key ("RAW Bayer", "Method")) { + raw.bayersensor.method = keyFile.get_string ("RAW Bayer", "Method"); + + if (pedited) { + pedited->raw.bayersensor.method = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "CcSteps")) { + raw.bayersensor.ccSteps = keyFile.get_integer ("RAW Bayer", "CcSteps"); + + if (pedited) { + pedited->raw.bayersensor.ccSteps = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PreBlack0")) { + raw.bayersensor.black0 = keyFile.get_double("RAW Bayer", "PreBlack0"); + + if (pedited) { + pedited->raw.bayersensor.exBlack0 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PreBlack1")) { + raw.bayersensor.black1 = keyFile.get_double("RAW Bayer", "PreBlack1"); + + if (pedited) { + pedited->raw.bayersensor.exBlack1 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PreBlack2")) { + raw.bayersensor.black2 = keyFile.get_double("RAW Bayer", "PreBlack2"); + + if (pedited) { + pedited->raw.bayersensor.exBlack2 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PreBlack3")) { + raw.bayersensor.black3 = keyFile.get_double("RAW Bayer", "PreBlack3"); + + if (pedited) { + pedited->raw.bayersensor.exBlack3 = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "PreTwoGreen")) { + raw.bayersensor.twogreen = keyFile.get_boolean("RAW Bayer", "PreTwoGreen"); + + if (pedited) { + pedited->raw.bayersensor.exTwoGreen = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "LineDenoise")) { + raw.bayersensor.linenoise = keyFile.get_integer ("RAW Bayer", "LineDenoise" ); + + if (pedited) { + pedited->raw.bayersensor.linenoise = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "GreenEqThreshold")) { + raw.bayersensor.greenthresh = keyFile.get_integer ("RAW Bayer", "GreenEqThreshold"); + + if (pedited) { + pedited->raw.bayersensor.greenEq = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "DCBIterations")) { + raw.bayersensor.dcb_iterations = keyFile.get_integer("RAW Bayer", "DCBIterations"); + + if (pedited) { + pedited->raw.bayersensor.dcbIterations = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "DCBEnhance")) { + raw.bayersensor.dcb_enhance = keyFile.get_boolean("RAW Bayer", "DCBEnhance"); + + if (pedited) { + pedited->raw.bayersensor.dcbEnhance = true; + } + } + + if (keyFile.has_key ("RAW Bayer", "LMMSEIterations")) { + raw.bayersensor.lmmse_iterations = keyFile.get_integer("RAW Bayer", "LMMSEIterations"); + + if (pedited) { + pedited->raw.bayersensor.lmmseIterations = true; + } + } + + //if (keyFile.has_key ("RAW Bayer", "ALLEnhance")) { raw.bayersensor.all_enhance = keyFile.get_boolean("RAW Bayer", "ALLEnhance"); if (pedited) pedited->raw.bayersensor.allEnhance = true; } + } // load X-Trans sensors' raw settings -if (keyFile.has_group ("RAW X-Trans")) { - if (keyFile.has_key ("RAW X-Trans", "Method")) { raw.xtranssensor.method = keyFile.get_string ("RAW X-Trans", "Method"); if (pedited) pedited->raw.xtranssensor.method = true; } - if (keyFile.has_key ("RAW X-Trans", "CcSteps")) { raw.xtranssensor.ccSteps = keyFile.get_integer ("RAW X-Trans", "CcSteps"); if (pedited) pedited->raw.xtranssensor.ccSteps = true; } - if (keyFile.has_key ("RAW X-Trans", "PreBlackRed")) { raw.xtranssensor.blackred = keyFile.get_double("RAW X-Trans", "PreBlackRed"); if (pedited) pedited->raw.xtranssensor.exBlackRed = true; } - if (keyFile.has_key ("RAW X-Trans", "PreBlackGreen")) { raw.xtranssensor.blackgreen = keyFile.get_double("RAW X-Trans", "PreBlackGreen"); if (pedited) pedited->raw.xtranssensor.exBlackGreen = true; } - if (keyFile.has_key ("RAW X-Trans", "PreBlackBlue")) { raw.xtranssensor.blackblue = keyFile.get_double("RAW X-Trans", "PreBlackBlue"); if (pedited) pedited->raw.xtranssensor.exBlackBlue = true; } -} + if (keyFile.has_group ("RAW X-Trans")) { + if (keyFile.has_key ("RAW X-Trans", "Method")) { + raw.xtranssensor.method = keyFile.get_string ("RAW X-Trans", "Method"); - // load exif change settings -if (keyFile.has_group ("Exif")) { - std::vector keys = keyFile.get_keys ("Exif"); - for (int i=0; i<(int)keys.size(); i++) { - Glib::ustring tmpStr = keyFile.get_string ("Exif", keys[i]); - exif[keys[i]] = keyFile.get_string ("Exif", keys[i]); - if (pedited) pedited->exif = true; - } -} + if (pedited) { + pedited->raw.xtranssensor.method = true; + } + } - /* - * Load iptc change settings - * - * Existing values are preserved, and the stored values - * are added to the list. To reset a field, the user has to - * save the profile with the field leaved empty, but still - * terminated by a semi-column ";" - * - * Please note that the old Keywords and SupplementalCategories - * tag content is fully replaced by the new one, - * i.e. they don't merge - */ -if (keyFile.has_group ("IPTC")) { - std::vector keys = keyFile.get_keys ("IPTC"); - IPTCPairs::iterator element; - for (unsigned int i=0; isecond.clear(); + if (keyFile.has_key ("RAW X-Trans", "CcSteps")) { + raw.xtranssensor.ccSteps = keyFile.get_integer ("RAW X-Trans", "CcSteps"); + + if (pedited) { + pedited->raw.xtranssensor.ccSteps = true; + } + } + + if (keyFile.has_key ("RAW X-Trans", "PreBlackRed")) { + raw.xtranssensor.blackred = keyFile.get_double("RAW X-Trans", "PreBlackRed"); + + if (pedited) { + pedited->raw.xtranssensor.exBlackRed = true; + } + } + + if (keyFile.has_key ("RAW X-Trans", "PreBlackGreen")) { + raw.xtranssensor.blackgreen = keyFile.get_double("RAW X-Trans", "PreBlackGreen"); + + if (pedited) { + pedited->raw.xtranssensor.exBlackGreen = true; + } + } + + if (keyFile.has_key ("RAW X-Trans", "PreBlackBlue")) { + raw.xtranssensor.blackblue = keyFile.get_double("RAW X-Trans", "PreBlackBlue"); + + if (pedited) { + pedited->raw.xtranssensor.exBlackBlue = true; + } + } } - // TODO: look out if merging Keywords and SupplementalCategories from the procparams chain would be interesting - std::vector currIptc = keyFile.get_string_list ("IPTC", keys[i]); - for ( - std::vector::iterator currLoadedTagValue=currIptc.begin(); - currLoadedTagValue!=currIptc.end(); - currLoadedTagValue++) - { - iptc[keys[i]].push_back(currLoadedTagValue->data()); + // load exif change settings + if (keyFile.has_group ("Exif")) { + std::vector keys = keyFile.get_keys ("Exif"); + + for (int i = 0; i < (int)keys.size(); i++) { + Glib::ustring tmpStr = keyFile.get_string ("Exif", keys[i]); + exif[keys[i]] = keyFile.get_string ("Exif", keys[i]); + + if (pedited) { + pedited->exif = true; + } + } + } + + /* + * Load iptc change settings + * + * Existing values are preserved, and the stored values + * are added to the list. To reset a field, the user has to + * save the profile with the field leaved empty, but still + * terminated by a semi-column ";" + * + * Please note that the old Keywords and SupplementalCategories + * tag content is fully replaced by the new one, + * i.e. they don't merge + */ + if (keyFile.has_group ("IPTC")) { + std::vector keys = keyFile.get_keys ("IPTC"); + IPTCPairs::iterator element; + + for (unsigned int i = 0; i < keys.size(); i++) { + // does this key already exist? + element = iptc.find(keys[i]); + + if (element != iptc.end()) { + // it already exist so we cleanup the values + element->second.clear(); + } + + // TODO: look out if merging Keywords and SupplementalCategories from the procparams chain would be interesting + std::vector currIptc = keyFile.get_string_list ("IPTC", keys[i]); + + for ( + std::vector::iterator currLoadedTagValue = currIptc.begin(); + currLoadedTagValue != currIptc.end(); + currLoadedTagValue++) { + iptc[keys[i]].push_back(currLoadedTagValue->data()); + } + + if (pedited) { + pedited->iptc = true; + } + } } - if (pedited) pedited->iptc = true; - } -} return 0; - } - catch (const Glib::Error& e) { + } catch (const Glib::Error& e) { printf ("-->%s\n", e.what().c_str()); return 1; - } - catch (...) { + } catch (...) { printf ("-->unknown exception!\n"); return 1; } + return 0; } const Glib::ustring ColorManagementParams::NoICMString = Glib::ustring("No ICM: sRGB output"); -bool operator==(const WaveletParams & a, const WaveletParams & b) { - if(a.enabled != b.enabled) +bool operator==(const WaveletParams & a, const WaveletParams & b) +{ + if(a.enabled != b.enabled) { return false; + } for(int i = 0; i < 9; i++) { - if(a.c[i] != b.c[i]) + if(a.c[i] != b.c[i]) { return false; + } } + for(int i = 0; i < 9; i++) { - if(a.ch[i] != b.ch[i]) + if(a.ch[i] != b.ch[i]) { return false; + } } - + return true; } -bool operator==(const DirPyrEqualizerParams & a, const DirPyrEqualizerParams & b) { - if(a.enabled != b.enabled) - return false; - - for(int i = 0; i < 6; i++) { - if(a.mult[i] != b.mult[i]) - return false; - } - if (a.threshold != b.threshold) - return false; +bool operator==(const DirPyrEqualizerParams & a, const DirPyrEqualizerParams & b) +{ + if(a.enabled != b.enabled) { + return false; + } - return true; + for(int i = 0; i < 6; i++) { + if(a.mult[i] != b.mult[i]) { + return false; + } + } + + if (a.threshold != b.threshold) { + return false; + } + + return true; } /*bool operator==(const ExifPairs& a, const ExifPairs& b) { @@ -2974,465 +6975,486 @@ bool operator==(const IPTCPairs& a, const IPTCPairs& b) { return a.field == b.field && a.values == b.values; }*/ -bool ProcParams::operator== (const ProcParams& other) { +bool ProcParams::operator== (const ProcParams& other) +{ - return - toneCurve.curve == other.toneCurve.curve - && toneCurve.curve2 == other.toneCurve.curve2 - && toneCurve.brightness == other.toneCurve.brightness - && toneCurve.black == other.toneCurve.black - && toneCurve.contrast == other.toneCurve.contrast - && toneCurve.saturation == other.toneCurve.saturation - && toneCurve.shcompr == other.toneCurve.shcompr - && toneCurve.hlcompr == other.toneCurve.hlcompr - && toneCurve.hlcomprthresh == other.toneCurve.hlcomprthresh - && toneCurve.autoexp == other.toneCurve.autoexp - && toneCurve.clip == other.toneCurve.clip - && toneCurve.expcomp == other.toneCurve.expcomp - && toneCurve.curveMode == other.toneCurve.curveMode - && toneCurve.curveMode2 == other.toneCurve.curveMode2 - && toneCurve.hrenabled == other.toneCurve.hrenabled - && toneCurve.method == other.toneCurve.method - && labCurve.lcurve == other.labCurve.lcurve - && labCurve.acurve == other.labCurve.acurve - && labCurve.bcurve == other.labCurve.bcurve - && labCurve.cccurve == other.labCurve.cccurve - && labCurve.chcurve == other.labCurve.chcurve - && labCurve.lhcurve == other.labCurve.lhcurve - && labCurve.hhcurve == other.labCurve.hhcurve - && labCurve.lccurve == other.labCurve.lccurve - && labCurve.clcurve == other.labCurve.clcurve - && labCurve.brightness == other.labCurve.brightness - && labCurve.contrast == other.labCurve.contrast - && labCurve.chromaticity == other.labCurve.chromaticity - && labCurve.avoidcolorshift == other.labCurve.avoidcolorshift - && labCurve.rstprotection == other.labCurve.rstprotection - && labCurve.lcredsk == other.labCurve.lcredsk - && sharpenEdge.enabled == other.sharpenEdge.enabled - && sharpenEdge.passes == other.sharpenEdge.passes - && sharpenEdge.amount == other.sharpenEdge.amount - && sharpenEdge.threechannels == other.sharpenEdge.threechannels - && sharpenMicro.enabled == other.sharpenMicro.enabled - && sharpenMicro.matrix == other.sharpenMicro.matrix - && sharpenMicro.amount == other.sharpenMicro.amount - && sharpenMicro.uniformity == other.sharpenMicro.uniformity - && sharpening.enabled == other.sharpening.enabled - && sharpening.radius == other.sharpening.radius - && sharpening.amount == other.sharpening.amount - && sharpening.threshold == other.sharpening.threshold - && sharpening.edgesonly == other.sharpening.edgesonly - && sharpening.edges_radius == other.sharpening.edges_radius - && sharpening.edges_tolerance == other.sharpening.edges_tolerance - && sharpening.halocontrol == other.sharpening.halocontrol - && sharpening.halocontrol_amount== other.sharpening.halocontrol_amount - && sharpening.method == other.sharpening.method - && sharpening.deconvamount == other.sharpening.deconvamount - && sharpening.deconvradius == other.sharpening.deconvradius - && sharpening.deconviter == other.sharpening.deconviter - && sharpening.deconvdamping == other.sharpening.deconvdamping - && prsharpening.enabled == other.prsharpening.enabled - && prsharpening.radius == other.prsharpening.radius - && prsharpening.amount == other.prsharpening.amount - && prsharpening.threshold == other.prsharpening.threshold - && prsharpening.edgesonly == other.prsharpening.edgesonly - && prsharpening.edges_radius == other.prsharpening.edges_radius - && prsharpening.edges_tolerance == other.prsharpening.edges_tolerance - && prsharpening.halocontrol == other.prsharpening.halocontrol - && prsharpening.halocontrol_amount== other.prsharpening.halocontrol_amount - && prsharpening.method == other.prsharpening.method - && prsharpening.deconvamount == other.prsharpening.deconvamount - && prsharpening.deconvradius == other.prsharpening.deconvradius - && prsharpening.deconviter == other.prsharpening.deconviter - && prsharpening.deconvdamping == other.prsharpening.deconvdamping - && vibrance.enabled == other.vibrance.enabled - && vibrance.pastels == other.vibrance.pastels - && vibrance.saturated == other.vibrance.saturated - && vibrance.psthreshold == other.vibrance.psthreshold - && vibrance.protectskins == other.vibrance.protectskins - && vibrance.avoidcolorshift == other.vibrance.avoidcolorshift - && vibrance.pastsattog == other.vibrance.pastsattog - && vibrance.skintonescurve == other.vibrance.skintonescurve - //&& colorBoost.amount == other.colorBoost.amount - //&& colorBoost.avoidclip == other.colorBoost.avoidclip - //&& colorBoost.enable_saturationlimiter == other.colorBoost.enable_saturationlimiter - //&& colorBoost.saturationlimit == other.colorBoost.saturationlimit - && wb.method == other.wb.method - && wb.green == other.wb.green - && wb.temperature == other.wb.temperature - && wb.equal == other.wb.equal - //&& colorShift.a == other.colorShift.a - //&& colorShift.b == other.colorShift.b - && colorappearance.enabled == other.colorappearance.enabled - && colorappearance.degree == other.colorappearance.degree - && colorappearance.autodegree == other.colorappearance.autodegree - && colorappearance.surround == other.colorappearance.surround - && colorappearance.adapscen == other.colorappearance.adapscen - && colorappearance.autoadapscen == other.colorappearance.autoadapscen - && colorappearance.adaplum == other.colorappearance.adaplum - && colorappearance.badpixsl == other.colorappearance.badpixsl - && colorappearance.wbmodel == other.colorappearance.wbmodel - && colorappearance.algo == other.colorappearance.algo - && colorappearance.curveMode == other.colorappearance.curveMode - && colorappearance.curveMode2 == other.colorappearance.curveMode2 - && colorappearance.curveMode3 == other.colorappearance.curveMode3 - && colorappearance.jlight == other.colorappearance.jlight - && colorappearance.qbright == other.colorappearance.qbright - && colorappearance.chroma == other.colorappearance.chroma - && colorappearance.schroma == other.colorappearance.schroma - && colorappearance.mchroma == other.colorappearance.mchroma - && colorappearance.rstprotection == other.colorappearance.rstprotection - && colorappearance.contrast == other.colorappearance.contrast - && colorappearance.qcontrast == other.colorappearance.qcontrast - && colorappearance.colorh == other.colorappearance.colorh - && impulseDenoise.enabled == other.impulseDenoise.enabled - && impulseDenoise.thresh == other.impulseDenoise.thresh - && dirpyrDenoise.enabled == other.dirpyrDenoise.enabled - && dirpyrDenoise.enhance == other.dirpyrDenoise.enhance - && dirpyrDenoise.median == other.dirpyrDenoise.median - && dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma -// && dirpyrDenoise.perform == other.dirpyrDenoise.perform - && dirpyrDenoise.luma == other.dirpyrDenoise.luma - && dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve - && dirpyrDenoise.cccurve == other.dirpyrDenoise.cccurve - && dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail - && dirpyrDenoise.chroma == other.dirpyrDenoise.chroma - && dirpyrDenoise.dmethod == other.dirpyrDenoise.dmethod - && dirpyrDenoise.Lmethod == other.dirpyrDenoise.Lmethod - && dirpyrDenoise.Cmethod == other.dirpyrDenoise.Cmethod - && dirpyrDenoise.C2method == other.dirpyrDenoise.C2method - && dirpyrDenoise.smethod == other.dirpyrDenoise.smethod - && dirpyrDenoise.medmethod == other.dirpyrDenoise.medmethod - && dirpyrDenoise.methodmed == other.dirpyrDenoise.methodmed - && dirpyrDenoise.rgbmethod == other.dirpyrDenoise.rgbmethod - && dirpyrDenoise.redchro == other.dirpyrDenoise.redchro - && dirpyrDenoise.bluechro == other.dirpyrDenoise.bluechro - && dirpyrDenoise.gamma == other.dirpyrDenoise.gamma - && dirpyrDenoise.passes == other.dirpyrDenoise.passes - && epd.enabled == other.epd.enabled - && epd.strength == other.epd.strength - && epd.gamma == other.epd.gamma - && epd.edgeStopping == other.epd.edgeStopping - && epd.scale == other.epd.scale - && epd.reweightingIterates == other.epd.reweightingIterates - && defringe.enabled == other.defringe.enabled - && defringe.radius == other.defringe.radius - && defringe.threshold == other.defringe.threshold - && defringe.huecurve == other.defringe.huecurve - - //&& lumaDenoise.enabled == other.lumaDenoise.enabled - //&& lumaDenoise.radius == other.lumaDenoise.radius - //&& lumaDenoise.edgetolerance == other.lumaDenoise.edgetolerance - //&& colorDenoise.enabled == other.colorDenoise.enabled - //&& colorDenoise.edgetolerance == other.colorDenoise.edgetolerance - //&& colorDenoise.edgesensitive == other.colorDenoise.edgesensitive - && sh.enabled == other.sh.enabled - && sh.hq == other.sh.hq - && sh.highlights == other.sh.highlights - && sh.htonalwidth == other.sh.htonalwidth - && sh.shadows == other.sh.shadows - && sh.stonalwidth == other.sh.stonalwidth - && sh.localcontrast == other.sh.localcontrast - && sh.radius == other.sh.radius - && crop.enabled == other.crop.enabled - && crop.x == other.crop.x - && crop.y == other.crop.y - && crop.w == other.crop.w - && crop.h == other.crop.h - && crop.fixratio == other.crop.fixratio - && crop.ratio == other.crop.ratio - && crop.orientation == other.crop.orientation - && crop.guide == other.crop.guide - && coarse.rotate == other.coarse.rotate - && coarse.hflip == other.coarse.hflip - && coarse.vflip == other.coarse.vflip - && rotate.degree == other.rotate.degree - && commonTrans.autofill == other.commonTrans.autofill - && distortion.amount == other.distortion.amount - && lensProf.lcpFile == other.lensProf.lcpFile - && lensProf.useDist == other.lensProf.useDist - && lensProf.useVign == other.lensProf.useVign - && lensProf.useCA == other.lensProf.useCA - && perspective.horizontal == other.perspective.horizontal - && perspective.vertical == other.perspective.vertical - && gradient.enabled == other.gradient.enabled - && gradient.degree == other.gradient.degree - && gradient.feather == other.gradient.feather - && gradient.strength == other.gradient.strength - && gradient.centerX == other.gradient.centerX - && gradient.centerY == other.gradient.centerY - && pcvignette.enabled == other.pcvignette.enabled - && pcvignette.strength == other.pcvignette.strength - && pcvignette.feather == other.pcvignette.feather - && pcvignette.roundness == other.pcvignette.roundness - && cacorrection.red == other.cacorrection.red - && cacorrection.blue == other.cacorrection.blue - && vignetting.amount == other.vignetting.amount - && vignetting.radius == other.vignetting.radius - && vignetting.strength == other.vignetting.strength - && vignetting.centerX == other.vignetting.centerX - && vignetting.centerY == other.vignetting.centerY - && !memcmp (&chmixer.red, &other.chmixer.red, 3*sizeof(int)) - && !memcmp (&chmixer.green, &other.chmixer.green, 3*sizeof(int)) - && !memcmp (&chmixer.blue, &other.chmixer.blue, 3*sizeof(int)) - && blackwhite.mixerRed == other.blackwhite.mixerRed - && blackwhite.mixerOrange == other.blackwhite.mixerOrange - && blackwhite.mixerYellow == other.blackwhite.mixerYellow - && blackwhite.mixerGreen == other.blackwhite.mixerGreen - && blackwhite.mixerCyan == other.blackwhite.mixerCyan - && blackwhite.mixerBlue == other.blackwhite.mixerBlue - && blackwhite.mixerMagenta == other.blackwhite.mixerMagenta - && blackwhite.mixerPurple == other.blackwhite.mixerPurple - && blackwhite.gammaRed == other.blackwhite.gammaRed - && blackwhite.gammaGreen == other.blackwhite.gammaGreen - && blackwhite.gammaBlue == other.blackwhite.gammaBlue - && blackwhite.filter == other.blackwhite.filter - && blackwhite.setting == other.blackwhite.setting - && blackwhite.method == other.blackwhite.method - && blackwhite.luminanceCurve == other.blackwhite.luminanceCurve - && blackwhite.beforeCurve == other.blackwhite.beforeCurve - && blackwhite.afterCurve == other.blackwhite.afterCurve - && blackwhite.beforeCurveMode == other.blackwhite.beforeCurveMode - && blackwhite.afterCurveMode == other.blackwhite.afterCurveMode - && blackwhite.autoc == other.blackwhite.autoc - && blackwhite.algo == other.blackwhite.algo - && resize.scale == other.resize.scale - && resize.appliesTo == other.resize.appliesTo - && resize.method == other.resize.method - && resize.dataspec == other.resize.dataspec - && resize.width == other.resize.width - && resize.height == other.resize.height - && raw.bayersensor.method == other.raw.bayersensor.method - && raw.bayersensor.ccSteps == other.raw.bayersensor.ccSteps - && raw.bayersensor.black0==other.raw.bayersensor.black0 - && raw.bayersensor.black1==other.raw.bayersensor.black1 - && raw.bayersensor.black2==other.raw.bayersensor.black2 - && raw.bayersensor.black3==other.raw.bayersensor.black3 - && raw.bayersensor.twogreen==other.raw.bayersensor.twogreen - && raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh - && raw.bayersensor.linenoise == other.raw.bayersensor.linenoise - && raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance - && raw.bayersensor.dcb_iterations == other.raw.bayersensor.dcb_iterations - && raw.xtranssensor.method == other.raw.xtranssensor.method - && raw.xtranssensor.ccSteps == other.raw.xtranssensor.ccSteps - && raw.xtranssensor.blackred==other.raw.xtranssensor.blackred - && raw.xtranssensor.blackgreen==other.raw.xtranssensor.blackgreen - && raw.xtranssensor.blackblue==other.raw.xtranssensor.blackblue - && raw.dark_frame == other.raw.dark_frame - && raw.df_autoselect == other.raw.df_autoselect - && raw.ff_file == other.raw.ff_file - && raw.ff_AutoSelect == other.raw.ff_AutoSelect - && raw.ff_BlurRadius == other.raw.ff_BlurRadius - && raw.ff_BlurType == other.raw.ff_BlurType - && raw.ff_AutoClipControl == other.raw.ff_AutoClipControl - && raw.ff_clipControl == other.raw.ff_clipControl - && raw.expos==other.raw.expos - && raw.preser==other.raw.preser - && raw.ca_autocorrect == other.raw.ca_autocorrect - && raw.cared == other.raw.cared - && raw.cablue == other.raw.cablue - && raw.hotPixelFilter == other.raw.hotPixelFilter - && raw.deadPixelFilter == other.raw.deadPixelFilter - && raw.hotdeadpix_thresh == other.raw.hotdeadpix_thresh - && icm.input == other.icm.input - && icm.toneCurve == other.icm.toneCurve - && icm.applyLookTable == other.icm.applyLookTable - && icm.applyBaselineExposureOffset == other.icm.applyBaselineExposureOffset - && icm.applyHueSatMap == other.icm.applyHueSatMap - && icm.blendCMSMatrix == other.icm.blendCMSMatrix - && icm.dcpIlluminant == other.icm.dcpIlluminant - && icm.working == other.icm.working - && icm.output == other.icm.output - && icm.gamma == other.icm.gamma - && icm.freegamma == other.icm.freegamma - && icm.gampos == other.icm.gampos - && icm.slpos == other.icm.slpos - && wavelet == other.wavelet - && wavelet.Lmethod == other.wavelet.Lmethod - && wavelet.CLmethod == other.wavelet.CLmethod - && wavelet.Backmethod == other.wavelet.Backmethod - && wavelet.Tilesmethod == other.wavelet.Tilesmethod - && wavelet.daubcoeffmethod == other.wavelet.daubcoeffmethod - && wavelet.CHmethod == other.wavelet.CHmethod - && wavelet.CHSLmethod == other.wavelet.CHSLmethod - && wavelet.EDmethod == other.wavelet.EDmethod - && wavelet.NPmethod == other.wavelet.NPmethod - && wavelet.BAmethod == other.wavelet.BAmethod - && wavelet.TMmethod == other.wavelet.TMmethod - && wavelet.HSmethod == other.wavelet.HSmethod - && wavelet.Dirmethod == other.wavelet.Dirmethod - && wavelet.rescon == other.wavelet.rescon - && wavelet.resconH == other.wavelet.resconH - && wavelet.reschro == other.wavelet.reschro - && wavelet.tmrs == other.wavelet.tmrs - && wavelet.gamma == other.wavelet.gamma - && wavelet.sup == other.wavelet.sup - && wavelet.sky == other.wavelet.sky - && wavelet.thres == other.wavelet.thres - && wavelet.threshold == other.wavelet.threshold - && wavelet.chroma == other.wavelet.chroma - && wavelet.chro == other.wavelet.chro - && wavelet.tmr == other.wavelet.tmr - && wavelet.contrast == other.wavelet.contrast - && wavelet.median == other.wavelet.median - && wavelet.expcontrast == other.wavelet.expcontrast - && wavelet.expchroma == other.wavelet.expchroma - && wavelet.expedge == other.wavelet.expedge - && wavelet.expresid == other.wavelet.expresid - && wavelet.expfinal == other.wavelet.expfinal - && wavelet.exptoning == other.wavelet.exptoning - && wavelet.expnoise == other.wavelet.expnoise - && wavelet.medianlev == other.wavelet.medianlev - && wavelet.linkedg == other.wavelet.linkedg - && wavelet.cbenab == other.wavelet.cbenab - && wavelet.lipst == other.wavelet.lipst - && wavelet.Medgreinf == other.wavelet.Medgreinf - && wavelet.edgrad == other.wavelet.edgrad - && wavelet.edgval == other.wavelet.edgval - && wavelet.edgthresh == other.wavelet.edgthresh - && wavelet.thr == other.wavelet.thr - && wavelet.thrH == other.wavelet.thrH - && wavelet.threshold == other.wavelet.threshold - && wavelet.threshold2 == other.wavelet.threshold2 - && wavelet.edgedetect == other.wavelet.edgedetect - && wavelet.edgedetectthr == other.wavelet.edgedetectthr - && wavelet.edgedetectthr2 == other.wavelet.edgedetectthr2 - && wavelet.edgesensi == other.wavelet.edgesensi - && wavelet.edgeampli == other.wavelet.edgeampli - && wavelet.hueskin == other.wavelet.hueskin - && wavelet.hueskin2 == other.wavelet.hueskin2 - && wavelet.hllev == other.wavelet.hllev - && wavelet.bllev == other.wavelet.bllev - && wavelet.edgcont == other.wavelet.edgcont - && wavelet.level0noise == other.wavelet.level0noise - && wavelet.level1noise == other.wavelet.level1noise - && wavelet.level2noise == other.wavelet.level2noise - && wavelet.level3noise == other.wavelet.level3noise - && wavelet.pastlev == other.wavelet.pastlev - && wavelet.satlev == other.wavelet.satlev - && wavelet.opacityCurveRG == other.wavelet.opacityCurveRG - && wavelet.opacityCurveBY == other.wavelet.opacityCurveBY - && wavelet.opacityCurveW == other.wavelet.opacityCurveW - && wavelet.opacityCurveWL == other.wavelet.opacityCurveWL - && wavelet.hhcurve == other.wavelet.hhcurve - && wavelet.Chcurve == other.wavelet.Chcurve - && wavelet.ccwcurve == other.wavelet.ccwcurve - && wavelet.wavclCurve == other.wavelet.wavclCurve - && wavelet.skinprotect == other.wavelet.skinprotect - && wavelet.strength == other.wavelet.strength - && wavelet.balance == other.wavelet.balance - && wavelet.greenhigh == other.wavelet.greenhigh - && wavelet.greenmed == other.wavelet.greenmed - && wavelet.greenlow == other.wavelet.greenlow - && wavelet.bluehigh == other.wavelet.bluehigh - && wavelet.bluemed == other.wavelet.bluemed - && wavelet.bluelow == other.wavelet.bluelow - && wavelet.iter == other.wavelet.iter - && dirpyrequalizer == other.dirpyrequalizer - // && dirpyrequalizer.algo == other.dirpyrequalizer.algo - && dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin - && dirpyrequalizer.threshold == other.dirpyrequalizer.threshold - && dirpyrequalizer.skinprotect == other.dirpyrequalizer.skinprotect - && hsvequalizer.hcurve == other.hsvequalizer.hcurve - && hsvequalizer.scurve == other.hsvequalizer.scurve - && hsvequalizer.vcurve == other.hsvequalizer.vcurve - && filmSimulation.enabled == other.filmSimulation.enabled - && filmSimulation.clutFilename == other.filmSimulation.clutFilename - && filmSimulation.strength == other.filmSimulation.strength - && rgbCurves.rcurve == other.rgbCurves.rcurve - && rgbCurves.gcurve == other.rgbCurves.gcurve - && rgbCurves.bcurve == other.rgbCurves.bcurve - && colorToning.enabled == other.colorToning.enabled - && colorToning.twocolor == other.colorToning.twocolor - && colorToning.method == other.colorToning.method - && colorToning.colorCurve == other.colorToning.colorCurve - && colorToning.opacityCurve == other.colorToning.opacityCurve - && colorToning.autosat == other.colorToning.autosat - && colorToning.satProtectionThreshold == other.colorToning.satProtectionThreshold - && colorToning.saturatedOpacity == other.colorToning.saturatedOpacity - && colorToning.strength == other.colorToning.strength - && colorToning.hlColSat == other.colorToning.hlColSat - && colorToning.shadowsColSat == other.colorToning.shadowsColSat - && colorToning.balance == other.colorToning.balance - && colorToning.clcurve == other.colorToning.clcurve - && colorToning.cl2curve == other.colorToning.cl2curve - && colorToning.redlow == other.colorToning.redlow - && colorToning.greenlow == other.colorToning.greenlow - && colorToning.bluelow == other.colorToning.bluelow - && colorToning.satlow == other.colorToning.satlow - && colorToning.sathigh == other.colorToning.sathigh - && colorToning.redmed == other.colorToning.redmed - && colorToning.greenmed == other.colorToning.greenmed - && colorToning.bluemed == other.colorToning.bluemed - && colorToning.redhigh == other.colorToning.redhigh - && colorToning.greenhigh == other.colorToning.greenhigh - && colorToning.bluehigh == other.colorToning.bluehigh - && exif==other.exif - && iptc==other.iptc; + return + toneCurve.curve == other.toneCurve.curve + && toneCurve.curve2 == other.toneCurve.curve2 + && toneCurve.brightness == other.toneCurve.brightness + && toneCurve.black == other.toneCurve.black + && toneCurve.contrast == other.toneCurve.contrast + && toneCurve.saturation == other.toneCurve.saturation + && toneCurve.shcompr == other.toneCurve.shcompr + && toneCurve.hlcompr == other.toneCurve.hlcompr + && toneCurve.hlcomprthresh == other.toneCurve.hlcomprthresh + && toneCurve.autoexp == other.toneCurve.autoexp + && toneCurve.clip == other.toneCurve.clip + && toneCurve.expcomp == other.toneCurve.expcomp + && toneCurve.curveMode == other.toneCurve.curveMode + && toneCurve.curveMode2 == other.toneCurve.curveMode2 + && toneCurve.hrenabled == other.toneCurve.hrenabled + && toneCurve.method == other.toneCurve.method + && labCurve.lcurve == other.labCurve.lcurve + && labCurve.acurve == other.labCurve.acurve + && labCurve.bcurve == other.labCurve.bcurve + && labCurve.cccurve == other.labCurve.cccurve + && labCurve.chcurve == other.labCurve.chcurve + && labCurve.lhcurve == other.labCurve.lhcurve + && labCurve.hhcurve == other.labCurve.hhcurve + && labCurve.lccurve == other.labCurve.lccurve + && labCurve.clcurve == other.labCurve.clcurve + && labCurve.brightness == other.labCurve.brightness + && labCurve.contrast == other.labCurve.contrast + && labCurve.chromaticity == other.labCurve.chromaticity + && labCurve.avoidcolorshift == other.labCurve.avoidcolorshift + && labCurve.rstprotection == other.labCurve.rstprotection + && labCurve.lcredsk == other.labCurve.lcredsk + && sharpenEdge.enabled == other.sharpenEdge.enabled + && sharpenEdge.passes == other.sharpenEdge.passes + && sharpenEdge.amount == other.sharpenEdge.amount + && sharpenEdge.threechannels == other.sharpenEdge.threechannels + && sharpenMicro.enabled == other.sharpenMicro.enabled + && sharpenMicro.matrix == other.sharpenMicro.matrix + && sharpenMicro.amount == other.sharpenMicro.amount + && sharpenMicro.uniformity == other.sharpenMicro.uniformity + && sharpening.enabled == other.sharpening.enabled + && sharpening.radius == other.sharpening.radius + && sharpening.amount == other.sharpening.amount + && sharpening.threshold == other.sharpening.threshold + && sharpening.edgesonly == other.sharpening.edgesonly + && sharpening.edges_radius == other.sharpening.edges_radius + && sharpening.edges_tolerance == other.sharpening.edges_tolerance + && sharpening.halocontrol == other.sharpening.halocontrol + && sharpening.halocontrol_amount == other.sharpening.halocontrol_amount + && sharpening.method == other.sharpening.method + && sharpening.deconvamount == other.sharpening.deconvamount + && sharpening.deconvradius == other.sharpening.deconvradius + && sharpening.deconviter == other.sharpening.deconviter + && sharpening.deconvdamping == other.sharpening.deconvdamping + && prsharpening.enabled == other.prsharpening.enabled + && prsharpening.radius == other.prsharpening.radius + && prsharpening.amount == other.prsharpening.amount + && prsharpening.threshold == other.prsharpening.threshold + && prsharpening.edgesonly == other.prsharpening.edgesonly + && prsharpening.edges_radius == other.prsharpening.edges_radius + && prsharpening.edges_tolerance == other.prsharpening.edges_tolerance + && prsharpening.halocontrol == other.prsharpening.halocontrol + && prsharpening.halocontrol_amount == other.prsharpening.halocontrol_amount + && prsharpening.method == other.prsharpening.method + && prsharpening.deconvamount == other.prsharpening.deconvamount + && prsharpening.deconvradius == other.prsharpening.deconvradius + && prsharpening.deconviter == other.prsharpening.deconviter + && prsharpening.deconvdamping == other.prsharpening.deconvdamping + && vibrance.enabled == other.vibrance.enabled + && vibrance.pastels == other.vibrance.pastels + && vibrance.saturated == other.vibrance.saturated + && vibrance.psthreshold == other.vibrance.psthreshold + && vibrance.protectskins == other.vibrance.protectskins + && vibrance.avoidcolorshift == other.vibrance.avoidcolorshift + && vibrance.pastsattog == other.vibrance.pastsattog + && vibrance.skintonescurve == other.vibrance.skintonescurve + //&& colorBoost.amount == other.colorBoost.amount + //&& colorBoost.avoidclip == other.colorBoost.avoidclip + //&& colorBoost.enable_saturationlimiter == other.colorBoost.enable_saturationlimiter + //&& colorBoost.saturationlimit == other.colorBoost.saturationlimit + && wb.method == other.wb.method + && wb.green == other.wb.green + && wb.temperature == other.wb.temperature + && wb.equal == other.wb.equal + //&& colorShift.a == other.colorShift.a + //&& colorShift.b == other.colorShift.b + && colorappearance.enabled == other.colorappearance.enabled + && colorappearance.degree == other.colorappearance.degree + && colorappearance.autodegree == other.colorappearance.autodegree + && colorappearance.surround == other.colorappearance.surround + && colorappearance.adapscen == other.colorappearance.adapscen + && colorappearance.autoadapscen == other.colorappearance.autoadapscen + && colorappearance.adaplum == other.colorappearance.adaplum + && colorappearance.badpixsl == other.colorappearance.badpixsl + && colorappearance.wbmodel == other.colorappearance.wbmodel + && colorappearance.algo == other.colorappearance.algo + && colorappearance.curveMode == other.colorappearance.curveMode + && colorappearance.curveMode2 == other.colorappearance.curveMode2 + && colorappearance.curveMode3 == other.colorappearance.curveMode3 + && colorappearance.jlight == other.colorappearance.jlight + && colorappearance.qbright == other.colorappearance.qbright + && colorappearance.chroma == other.colorappearance.chroma + && colorappearance.schroma == other.colorappearance.schroma + && colorappearance.mchroma == other.colorappearance.mchroma + && colorappearance.rstprotection == other.colorappearance.rstprotection + && colorappearance.contrast == other.colorappearance.contrast + && colorappearance.qcontrast == other.colorappearance.qcontrast + && colorappearance.colorh == other.colorappearance.colorh + && impulseDenoise.enabled == other.impulseDenoise.enabled + && impulseDenoise.thresh == other.impulseDenoise.thresh + && dirpyrDenoise.enabled == other.dirpyrDenoise.enabled + && dirpyrDenoise.enhance == other.dirpyrDenoise.enhance + && dirpyrDenoise.median == other.dirpyrDenoise.median + && dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma +// && dirpyrDenoise.perform == other.dirpyrDenoise.perform + && dirpyrDenoise.luma == other.dirpyrDenoise.luma + && dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve + && dirpyrDenoise.cccurve == other.dirpyrDenoise.cccurve + && dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail + && dirpyrDenoise.chroma == other.dirpyrDenoise.chroma + && dirpyrDenoise.dmethod == other.dirpyrDenoise.dmethod + && dirpyrDenoise.Lmethod == other.dirpyrDenoise.Lmethod + && dirpyrDenoise.Cmethod == other.dirpyrDenoise.Cmethod + && dirpyrDenoise.C2method == other.dirpyrDenoise.C2method + && dirpyrDenoise.smethod == other.dirpyrDenoise.smethod + && dirpyrDenoise.medmethod == other.dirpyrDenoise.medmethod + && dirpyrDenoise.methodmed == other.dirpyrDenoise.methodmed + && dirpyrDenoise.rgbmethod == other.dirpyrDenoise.rgbmethod + && dirpyrDenoise.redchro == other.dirpyrDenoise.redchro + && dirpyrDenoise.bluechro == other.dirpyrDenoise.bluechro + && dirpyrDenoise.gamma == other.dirpyrDenoise.gamma + && dirpyrDenoise.passes == other.dirpyrDenoise.passes + && epd.enabled == other.epd.enabled + && epd.strength == other.epd.strength + && epd.gamma == other.epd.gamma + && epd.edgeStopping == other.epd.edgeStopping + && epd.scale == other.epd.scale + && epd.reweightingIterates == other.epd.reweightingIterates + && defringe.enabled == other.defringe.enabled + && defringe.radius == other.defringe.radius + && defringe.threshold == other.defringe.threshold + && defringe.huecurve == other.defringe.huecurve + + //&& lumaDenoise.enabled == other.lumaDenoise.enabled + //&& lumaDenoise.radius == other.lumaDenoise.radius + //&& lumaDenoise.edgetolerance == other.lumaDenoise.edgetolerance + //&& colorDenoise.enabled == other.colorDenoise.enabled + //&& colorDenoise.edgetolerance == other.colorDenoise.edgetolerance + //&& colorDenoise.edgesensitive == other.colorDenoise.edgesensitive + && sh.enabled == other.sh.enabled + && sh.hq == other.sh.hq + && sh.highlights == other.sh.highlights + && sh.htonalwidth == other.sh.htonalwidth + && sh.shadows == other.sh.shadows + && sh.stonalwidth == other.sh.stonalwidth + && sh.localcontrast == other.sh.localcontrast + && sh.radius == other.sh.radius + && crop.enabled == other.crop.enabled + && crop.x == other.crop.x + && crop.y == other.crop.y + && crop.w == other.crop.w + && crop.h == other.crop.h + && crop.fixratio == other.crop.fixratio + && crop.ratio == other.crop.ratio + && crop.orientation == other.crop.orientation + && crop.guide == other.crop.guide + && coarse.rotate == other.coarse.rotate + && coarse.hflip == other.coarse.hflip + && coarse.vflip == other.coarse.vflip + && rotate.degree == other.rotate.degree + && commonTrans.autofill == other.commonTrans.autofill + && distortion.amount == other.distortion.amount + && lensProf.lcpFile == other.lensProf.lcpFile + && lensProf.useDist == other.lensProf.useDist + && lensProf.useVign == other.lensProf.useVign + && lensProf.useCA == other.lensProf.useCA + && perspective.horizontal == other.perspective.horizontal + && perspective.vertical == other.perspective.vertical + && gradient.enabled == other.gradient.enabled + && gradient.degree == other.gradient.degree + && gradient.feather == other.gradient.feather + && gradient.strength == other.gradient.strength + && gradient.centerX == other.gradient.centerX + && gradient.centerY == other.gradient.centerY + && pcvignette.enabled == other.pcvignette.enabled + && pcvignette.strength == other.pcvignette.strength + && pcvignette.feather == other.pcvignette.feather + && pcvignette.roundness == other.pcvignette.roundness + && cacorrection.red == other.cacorrection.red + && cacorrection.blue == other.cacorrection.blue + && vignetting.amount == other.vignetting.amount + && vignetting.radius == other.vignetting.radius + && vignetting.strength == other.vignetting.strength + && vignetting.centerX == other.vignetting.centerX + && vignetting.centerY == other.vignetting.centerY + && !memcmp (&chmixer.red, &other.chmixer.red, 3 * sizeof(int)) + && !memcmp (&chmixer.green, &other.chmixer.green, 3 * sizeof(int)) + && !memcmp (&chmixer.blue, &other.chmixer.blue, 3 * sizeof(int)) + && blackwhite.mixerRed == other.blackwhite.mixerRed + && blackwhite.mixerOrange == other.blackwhite.mixerOrange + && blackwhite.mixerYellow == other.blackwhite.mixerYellow + && blackwhite.mixerGreen == other.blackwhite.mixerGreen + && blackwhite.mixerCyan == other.blackwhite.mixerCyan + && blackwhite.mixerBlue == other.blackwhite.mixerBlue + && blackwhite.mixerMagenta == other.blackwhite.mixerMagenta + && blackwhite.mixerPurple == other.blackwhite.mixerPurple + && blackwhite.gammaRed == other.blackwhite.gammaRed + && blackwhite.gammaGreen == other.blackwhite.gammaGreen + && blackwhite.gammaBlue == other.blackwhite.gammaBlue + && blackwhite.filter == other.blackwhite.filter + && blackwhite.setting == other.blackwhite.setting + && blackwhite.method == other.blackwhite.method + && blackwhite.luminanceCurve == other.blackwhite.luminanceCurve + && blackwhite.beforeCurve == other.blackwhite.beforeCurve + && blackwhite.afterCurve == other.blackwhite.afterCurve + && blackwhite.beforeCurveMode == other.blackwhite.beforeCurveMode + && blackwhite.afterCurveMode == other.blackwhite.afterCurveMode + && blackwhite.autoc == other.blackwhite.autoc + && blackwhite.algo == other.blackwhite.algo + && resize.scale == other.resize.scale + && resize.appliesTo == other.resize.appliesTo + && resize.method == other.resize.method + && resize.dataspec == other.resize.dataspec + && resize.width == other.resize.width + && resize.height == other.resize.height + && raw.bayersensor.method == other.raw.bayersensor.method + && raw.bayersensor.ccSteps == other.raw.bayersensor.ccSteps + && raw.bayersensor.black0 == other.raw.bayersensor.black0 + && raw.bayersensor.black1 == other.raw.bayersensor.black1 + && raw.bayersensor.black2 == other.raw.bayersensor.black2 + && raw.bayersensor.black3 == other.raw.bayersensor.black3 + && raw.bayersensor.twogreen == other.raw.bayersensor.twogreen + && raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh + && raw.bayersensor.linenoise == other.raw.bayersensor.linenoise + && raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance + && raw.bayersensor.dcb_iterations == other.raw.bayersensor.dcb_iterations + && raw.xtranssensor.method == other.raw.xtranssensor.method + && raw.xtranssensor.ccSteps == other.raw.xtranssensor.ccSteps + && raw.xtranssensor.blackred == other.raw.xtranssensor.blackred + && raw.xtranssensor.blackgreen == other.raw.xtranssensor.blackgreen + && raw.xtranssensor.blackblue == other.raw.xtranssensor.blackblue + && raw.dark_frame == other.raw.dark_frame + && raw.df_autoselect == other.raw.df_autoselect + && raw.ff_file == other.raw.ff_file + && raw.ff_AutoSelect == other.raw.ff_AutoSelect + && raw.ff_BlurRadius == other.raw.ff_BlurRadius + && raw.ff_BlurType == other.raw.ff_BlurType + && raw.ff_AutoClipControl == other.raw.ff_AutoClipControl + && raw.ff_clipControl == other.raw.ff_clipControl + && raw.expos == other.raw.expos + && raw.preser == other.raw.preser + && raw.ca_autocorrect == other.raw.ca_autocorrect + && raw.cared == other.raw.cared + && raw.cablue == other.raw.cablue + && raw.hotPixelFilter == other.raw.hotPixelFilter + && raw.deadPixelFilter == other.raw.deadPixelFilter + && raw.hotdeadpix_thresh == other.raw.hotdeadpix_thresh + && icm.input == other.icm.input + && icm.toneCurve == other.icm.toneCurve + && icm.applyLookTable == other.icm.applyLookTable + && icm.applyBaselineExposureOffset == other.icm.applyBaselineExposureOffset + && icm.applyHueSatMap == other.icm.applyHueSatMap + && icm.blendCMSMatrix == other.icm.blendCMSMatrix + && icm.dcpIlluminant == other.icm.dcpIlluminant + && icm.working == other.icm.working + && icm.output == other.icm.output + && icm.gamma == other.icm.gamma + && icm.freegamma == other.icm.freegamma + && icm.gampos == other.icm.gampos + && icm.slpos == other.icm.slpos + && wavelet == other.wavelet + && wavelet.Lmethod == other.wavelet.Lmethod + && wavelet.CLmethod == other.wavelet.CLmethod + && wavelet.Backmethod == other.wavelet.Backmethod + && wavelet.Tilesmethod == other.wavelet.Tilesmethod + && wavelet.daubcoeffmethod == other.wavelet.daubcoeffmethod + && wavelet.CHmethod == other.wavelet.CHmethod + && wavelet.CHSLmethod == other.wavelet.CHSLmethod + && wavelet.EDmethod == other.wavelet.EDmethod + && wavelet.NPmethod == other.wavelet.NPmethod + && wavelet.BAmethod == other.wavelet.BAmethod + && wavelet.TMmethod == other.wavelet.TMmethod + && wavelet.HSmethod == other.wavelet.HSmethod + && wavelet.Dirmethod == other.wavelet.Dirmethod + && wavelet.rescon == other.wavelet.rescon + && wavelet.resconH == other.wavelet.resconH + && wavelet.reschro == other.wavelet.reschro + && wavelet.tmrs == other.wavelet.tmrs + && wavelet.gamma == other.wavelet.gamma + && wavelet.sup == other.wavelet.sup + && wavelet.sky == other.wavelet.sky + && wavelet.thres == other.wavelet.thres + && wavelet.threshold == other.wavelet.threshold + && wavelet.chroma == other.wavelet.chroma + && wavelet.chro == other.wavelet.chro + && wavelet.tmr == other.wavelet.tmr + && wavelet.contrast == other.wavelet.contrast + && wavelet.median == other.wavelet.median + && wavelet.expcontrast == other.wavelet.expcontrast + && wavelet.expchroma == other.wavelet.expchroma + && wavelet.expedge == other.wavelet.expedge + && wavelet.expresid == other.wavelet.expresid + && wavelet.expfinal == other.wavelet.expfinal + && wavelet.exptoning == other.wavelet.exptoning + && wavelet.expnoise == other.wavelet.expnoise + && wavelet.medianlev == other.wavelet.medianlev + && wavelet.linkedg == other.wavelet.linkedg + && wavelet.cbenab == other.wavelet.cbenab + && wavelet.lipst == other.wavelet.lipst + && wavelet.Medgreinf == other.wavelet.Medgreinf + && wavelet.edgrad == other.wavelet.edgrad + && wavelet.edgval == other.wavelet.edgval + && wavelet.edgthresh == other.wavelet.edgthresh + && wavelet.thr == other.wavelet.thr + && wavelet.thrH == other.wavelet.thrH + && wavelet.threshold == other.wavelet.threshold + && wavelet.threshold2 == other.wavelet.threshold2 + && wavelet.edgedetect == other.wavelet.edgedetect + && wavelet.edgedetectthr == other.wavelet.edgedetectthr + && wavelet.edgedetectthr2 == other.wavelet.edgedetectthr2 + && wavelet.edgesensi == other.wavelet.edgesensi + && wavelet.edgeampli == other.wavelet.edgeampli + && wavelet.hueskin == other.wavelet.hueskin + && wavelet.hueskin2 == other.wavelet.hueskin2 + && wavelet.hllev == other.wavelet.hllev + && wavelet.bllev == other.wavelet.bllev + && wavelet.edgcont == other.wavelet.edgcont + && wavelet.level0noise == other.wavelet.level0noise + && wavelet.level1noise == other.wavelet.level1noise + && wavelet.level2noise == other.wavelet.level2noise + && wavelet.level3noise == other.wavelet.level3noise + && wavelet.pastlev == other.wavelet.pastlev + && wavelet.satlev == other.wavelet.satlev + && wavelet.opacityCurveRG == other.wavelet.opacityCurveRG + && wavelet.opacityCurveBY == other.wavelet.opacityCurveBY + && wavelet.opacityCurveW == other.wavelet.opacityCurveW + && wavelet.opacityCurveWL == other.wavelet.opacityCurveWL + && wavelet.hhcurve == other.wavelet.hhcurve + && wavelet.Chcurve == other.wavelet.Chcurve + && wavelet.ccwcurve == other.wavelet.ccwcurve + && wavelet.wavclCurve == other.wavelet.wavclCurve + && wavelet.skinprotect == other.wavelet.skinprotect + && wavelet.strength == other.wavelet.strength + && wavelet.balance == other.wavelet.balance + && wavelet.greenhigh == other.wavelet.greenhigh + && wavelet.greenmed == other.wavelet.greenmed + && wavelet.greenlow == other.wavelet.greenlow + && wavelet.bluehigh == other.wavelet.bluehigh + && wavelet.bluemed == other.wavelet.bluemed + && wavelet.bluelow == other.wavelet.bluelow + && wavelet.iter == other.wavelet.iter + && dirpyrequalizer == other.dirpyrequalizer + // && dirpyrequalizer.algo == other.dirpyrequalizer.algo + && dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin + && dirpyrequalizer.threshold == other.dirpyrequalizer.threshold + && dirpyrequalizer.skinprotect == other.dirpyrequalizer.skinprotect + && hsvequalizer.hcurve == other.hsvequalizer.hcurve + && hsvequalizer.scurve == other.hsvequalizer.scurve + && hsvequalizer.vcurve == other.hsvequalizer.vcurve + && filmSimulation.enabled == other.filmSimulation.enabled + && filmSimulation.clutFilename == other.filmSimulation.clutFilename + && filmSimulation.strength == other.filmSimulation.strength + && rgbCurves.rcurve == other.rgbCurves.rcurve + && rgbCurves.gcurve == other.rgbCurves.gcurve + && rgbCurves.bcurve == other.rgbCurves.bcurve + && colorToning.enabled == other.colorToning.enabled + && colorToning.twocolor == other.colorToning.twocolor + && colorToning.method == other.colorToning.method + && colorToning.colorCurve == other.colorToning.colorCurve + && colorToning.opacityCurve == other.colorToning.opacityCurve + && colorToning.autosat == other.colorToning.autosat + && colorToning.satProtectionThreshold == other.colorToning.satProtectionThreshold + && colorToning.saturatedOpacity == other.colorToning.saturatedOpacity + && colorToning.strength == other.colorToning.strength + && colorToning.hlColSat == other.colorToning.hlColSat + && colorToning.shadowsColSat == other.colorToning.shadowsColSat + && colorToning.balance == other.colorToning.balance + && colorToning.clcurve == other.colorToning.clcurve + && colorToning.cl2curve == other.colorToning.cl2curve + && colorToning.redlow == other.colorToning.redlow + && colorToning.greenlow == other.colorToning.greenlow + && colorToning.bluelow == other.colorToning.bluelow + && colorToning.satlow == other.colorToning.satlow + && colorToning.sathigh == other.colorToning.sathigh + && colorToning.redmed == other.colorToning.redmed + && colorToning.greenmed == other.colorToning.greenmed + && colorToning.bluemed == other.colorToning.bluemed + && colorToning.redhigh == other.colorToning.redhigh + && colorToning.greenhigh == other.colorToning.greenhigh + && colorToning.bluehigh == other.colorToning.bluehigh + && exif == other.exif + && iptc == other.iptc; } -bool ProcParams::operator!= (const ProcParams& other) { +bool ProcParams::operator!= (const ProcParams& other) +{ - return !(*this==other); + return !(*this == other); } -PartialProfile::PartialProfile(bool createInstance, bool paramsEditedValue) { +PartialProfile::PartialProfile(bool createInstance, bool paramsEditedValue) +{ if (createInstance) { pparams = new ProcParams(); pedited = new ParamsEdited(paramsEditedValue); - } - else { + } else { pparams = NULL; pedited = NULL; } } -PartialProfile::PartialProfile(ProcParams* pp, ParamsEdited* pe, bool fullCopy) { +PartialProfile::PartialProfile(ProcParams* pp, ParamsEdited* pe, bool fullCopy) +{ if (fullCopy && pp) { pparams = new ProcParams(*pp); - } - else + } else { pparams = pp; + } if (fullCopy && pe) { pedited = new ParamsEdited(*pe); - } - else + } else { pedited = pe; + } } -PartialProfile::PartialProfile(const ProcParams* pp, const ParamsEdited* pe) { +PartialProfile::PartialProfile(const ProcParams* pp, const ParamsEdited* pe) +{ if (pp) { pparams = new ProcParams(*pp); - } - else + } else { pparams = NULL; + } if (pe) { pedited = new ParamsEdited(*pe); - } - else + } else { pedited = NULL; + } } -int PartialProfile::load (Glib::ustring fName) { - if (!pparams) pparams = new ProcParams(); - if (!pedited) pedited = new ParamsEdited(); - if (fName == DEFPROFILE_INTERNAL) +int PartialProfile::load (Glib::ustring fName) +{ + if (!pparams) { + pparams = new ProcParams(); + } + + if (!pedited) { + pedited = new ParamsEdited(); + } + + if (fName == DEFPROFILE_INTERNAL) { return 0; - else + } else { return pparams->load(fName, pedited); + } } -void PartialProfile::deleteInstance () { - if (pparams) { delete pparams; pparams = NULL; } - if (pedited) { delete pedited; pedited = NULL; } +void PartialProfile::deleteInstance () +{ + if (pparams) { + delete pparams; + pparams = NULL; + } + + if (pedited) { + delete pedited; + pedited = NULL; + } } /* * Set the all values of the General section to false * in order to preserve them in applyTo */ -void PartialProfile::clearGeneral () { +void PartialProfile::clearGeneral () +{ if (pedited) { pedited->general.colorlabel = false; pedited->general.intrash = false; @@ -3440,14 +7462,18 @@ void PartialProfile::clearGeneral () { } } -const void PartialProfile::applyTo(ProcParams *destParams) const { +const void PartialProfile::applyTo(ProcParams *destParams) const +{ if (destParams && pparams && pedited) { pedited->combine(*destParams, *pparams, true); } } -void PartialProfile::set(bool v) { - if (pedited) pedited->set(v); +void PartialProfile::set(bool v) +{ + if (pedited) { + pedited->set(v); + } } } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index fdf41ccb3..47dccb47f 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -7,7 +7,7 @@ * 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 @@ -27,7 +27,8 @@ class ParamsEdited; -namespace rtengine { +namespace rtengine +{ class ColorGradientCurve; class OpacityCurve; @@ -38,347 +39,390 @@ class WavOpacityCurveBY; class WavOpacityCurveW; class WavOpacityCurveWL; -namespace procparams { +namespace procparams +{ template -class Threshold { - public: - T value[4]; +class Threshold +{ +public: + T value[4]; - protected: - bool initEq1; - bool _isDouble; +protected: + bool initEq1; + bool _isDouble; #ifndef NDEBUG - unsigned int part[5]; + unsigned int part[5]; #endif - public: - Threshold (T bottom, T top, bool startAtOne) { - initEq1 = startAtOne; - value[0] = bottom; - value[1] = top; - value[2] = T(0); - value[3] = T(0); - _isDouble = false; - } +public: + Threshold (T bottom, T top, bool startAtOne) + { + initEq1 = startAtOne; + value[0] = bottom; + value[1] = top; + value[2] = T(0); + value[3] = T(0); + _isDouble = false; + } - Threshold (T bottomLeft, T topLeft, T bottomRight, T topRight, bool startAtOne) { - initEq1 = startAtOne; - value[0] = bottomLeft; - value[1] = topLeft; - value[2] = bottomRight; - value[3] = topRight; - _isDouble = true; - } + Threshold (T bottomLeft, T topLeft, T bottomRight, T topRight, bool startAtOne) + { + initEq1 = startAtOne; + value[0] = bottomLeft; + value[1] = topLeft; + value[2] = bottomRight; + value[3] = topRight; + _isDouble = true; + } - // for convenience, since 'values' is public - void setValues(T bottom, T top) { - value[0] = bottom; - value[1] = top; - } + // for convenience, since 'values' is public + void setValues(T bottom, T top) + { + value[0] = bottom; + value[1] = top; + } - // for convenience, since 'values' is public - void setValues(T bottomLeft, T topLeft, T bottomRight, T topRight) { - value[0] = bottomLeft; - value[1] = topLeft; - value[2] = bottomRight; - value[3] = topRight; - } + // for convenience, since 'values' is public + void setValues(T bottomLeft, T topLeft, T bottomRight, T topRight) + { + value[0] = bottomLeft; + value[1] = topLeft; + value[2] = bottomRight; + value[3] = topRight; + } - bool isDouble() const { return _isDouble; } + bool isDouble() const + { + return _isDouble; + } - // RT: Type of the returned value - // RV: Type of the value on the X axis - // RV2: Type of the maximum value on the Y axis - template - RT multiply(RV x, RV2 yMax) const { - double val = double(x); - if (initEq1) { - if (_isDouble) { - if (val == double(value[2]) && double(value[2]) == double(value[3])) - // this handle the special case where the 2 right values are the same, then bottom one is sent back, - // useful if one wants to keep the bottom value even beyond the x max bound - return RT(0.); - if (val >= double(value[3])) - return RT(yMax); - if (val > double(value[2])) - return RT(double(yMax)*(val-double(value[2]))/(double(value[3])-double(value[2]))); + // RT: Type of the returned value + // RV: Type of the value on the X axis + // RV2: Type of the maximum value on the Y axis + template + RT multiply(RV x, RV2 yMax) const + { + double val = double(x); + + if (initEq1) { + if (_isDouble) { + if (val == double(value[2]) && double(value[2]) == double(value[3])) + // this handle the special case where the 2 right values are the same, then bottom one is sent back, + // useful if one wants to keep the bottom value even beyond the x max bound + { + return RT(0.); } - if (val >= double(value[0])) + + if (val >= double(value[3])) { + return RT(yMax); + } + + if (val > double(value[2])) { + return RT(double(yMax) * (val - double(value[2])) / (double(value[3]) - double(value[2]))); + } + } + + if (val >= double(value[0])) { + return RT(0); + } + + if (val > double(value[1])) { + return RT(double(yMax) * (1. - (val - double(value[0])) / (double(value[1]) - double(value[0])))); + } + + return RT(yMax); + } else { + if (_isDouble) { + if (val == double(value[2]) && double(value[2]) == double(value[3])) + // this handle the special case where the 2 right values are the same, then top one is sent back, + // useful if one wants to keep the top value even beyond the x max bound + { + return RT(yMax); + } + + if (val >= double(value[2])) { return RT(0); - if (val > double(value[1])) - return RT(double(yMax)*(1.-(val-double(value[0]))/(double(value[1])-double(value[0])))); + } + + if (val > double(value[3])) { + return RT(double(yMax) * (1. - (val - double(value[3])) / (double(value[2]) - double(value[3])))); + } + } + + if (val >= double(value[1])) { return RT(yMax); } - else { - if (_isDouble) { - if (val == double(value[2]) && double(value[2]) == double(value[3])) - // this handle the special case where the 2 right values are the same, then top one is sent back, - // useful if one wants to keep the top value even beyond the x max bound - return RT(yMax); - if (val >= double(value[2])) - return RT(0); - if (val > double(value[3])) - return RT(double(yMax)*(1.-(val-double(value[3]))/(double(value[2])-double(value[3])))); - } - if (val >= double(value[1])) - return RT(yMax); - if (val > double(value[0])) - return RT(double(yMax)*(val-double(value[0]))/(double(value[1])-double(value[0]))); - return RT(0); - } - } - // RT: Type of the returned value - // RV: Type of the value on the X axis - /*template - RT getRatio(RV val) const { - double val = double(val); - if (initEq1) { - if (_isDouble) { // assuming that simple thresholds will be more frequent - if (val >= double(value[3])) - return RT(1); - if (val > double(value[2])) - return (val-double(value[2]))/(double(value[3])-double(value[2])); - } - if (val >= double(value[1])) - return RT(0); - if (val > double(value[0])) - return 1.-(val-double(value[0]))/(double(value[1])-double(value[0])); - return RT(1); + if (val > double(value[0])) { + return RT(double(yMax) * (val - double(value[0])) / (double(value[1]) - double(value[0]))); } - else { - if (_isDouble) { // assuming that simple thresholds will be more frequent - if (val >= double(value[3])) - return RT(0); - if (val > double(value[2])) - return 1.-(val-double(value[2]))/(double(value[3])-double(value[2])); - } - if (val >= double(value[1])) + + return RT(0); + } + } + + // RT: Type of the returned value + // RV: Type of the value on the X axis + /*template + RT getRatio(RV val) const { + double val = double(val); + if (initEq1) { + if (_isDouble) { // assuming that simple thresholds will be more frequent + if (val >= double(value[3])) return RT(1); - if (val > double(value[0])) - return (val-double(value[0]))/(double(value[1])-double(value[0])); - return RT(0); + if (val > double(value[2])) + return (val-double(value[2]))/(double(value[3])-double(value[2])); } - }*/ - - Threshold & operator= (const Threshold &rhs) { - value[0] = rhs.value[0]; - value[1] = rhs.value[1]; - value[2] = rhs.value[2]; - value[3] = rhs.value[3]; - initEq1 = rhs.initEq1; - _isDouble = rhs._isDouble; - return *this; + if (val >= double(value[1])) + return RT(0); + if (val > double(value[0])) + return 1.-(val-double(value[0]))/(double(value[1])-double(value[0])); + return RT(1); } - - bool operator== (const Threshold &rhs) const { - if (_isDouble) - return fabs(value[0]-rhs.value[0])<1e-10 - && fabs(value[1]-rhs.value[1])<1e-10 - && fabs(value[2]-rhs.value[2])<1e-10 - && fabs(value[3]-rhs.value[3])<1e-10; - else - return fabs(value[0]-rhs.value[0])<1e-10 - && fabs(value[1]-rhs.value[1])<1e-10; + else { + if (_isDouble) { // assuming that simple thresholds will be more frequent + if (val >= double(value[3])) + return RT(0); + if (val > double(value[2])) + return 1.-(val-double(value[2]))/(double(value[3])-double(value[2])); + } + if (val >= double(value[1])) + return RT(1); + if (val > double(value[0])) + return (val-double(value[0]))/(double(value[1])-double(value[0])); + return RT(0); } + }*/ + + Threshold & operator= (const Threshold &rhs) + { + value[0] = rhs.value[0]; + value[1] = rhs.value[1]; + value[2] = rhs.value[2]; + value[3] = rhs.value[3]; + initEq1 = rhs.initEq1; + _isDouble = rhs._isDouble; + return *this; + } + + bool operator== (const Threshold &rhs) const + { + if (_isDouble) + return fabs(value[0] - rhs.value[0]) < 1e-10 + && fabs(value[1] - rhs.value[1]) < 1e-10 + && fabs(value[2] - rhs.value[2]) < 1e-10 + && fabs(value[3] - rhs.value[3]) < 1e-10; + else + return fabs(value[0] - rhs.value[0]) < 1e-10 + && fabs(value[1] - rhs.value[1]) < 1e-10; + } }; /** - * Parameters of the tone curve + * Parameters of the tone curve */ -class ToneCurveParams { +class ToneCurveParams +{ - public: +public: - enum eTCModeId { - TC_MODE_STD, // Standard modes, the curve is applied on all component individually - TC_MODE_WEIGHTEDSTD, // Weighted standard mode - TC_MODE_FILMLIKE, // Film-like mode, as defined in Adobe's reference code - TC_MODE_SATANDVALBLENDING, // Modify the Saturation and Value channel - TC_MODE_LUMINANCE, // Modify the Luminance channel with coefficients from Rec 709's - TC_MODE_PERCEPTUAL // Keep color appearance constant using perceptual modeling - }; + enum eTCModeId { + TC_MODE_STD, // Standard modes, the curve is applied on all component individually + TC_MODE_WEIGHTEDSTD, // Weighted standard mode + TC_MODE_FILMLIKE, // Film-like mode, as defined in Adobe's reference code + TC_MODE_SATANDVALBLENDING, // Modify the Saturation and Value channel + TC_MODE_LUMINANCE, // Modify the Luminance channel with coefficients from Rec 709's + TC_MODE_PERCEPTUAL // Keep color appearance constant using perceptual modeling + }; - bool autoexp; - double clip; - bool hrenabled; // Highlight Reconstruction enabled - Glib::ustring method; // Highlight Reconstruction's method - double expcomp; - std::vector curve; - std::vector curve2; - eTCModeId curveMode; - eTCModeId curveMode2; - int brightness; - int black; - int contrast; - int saturation; - int shcompr; - int hlcompr; // Highlight Recovery's compression - int hlcomprthresh; // Highlight Recovery's threshold + bool autoexp; + double clip; + bool hrenabled; // Highlight Reconstruction enabled + Glib::ustring method; // Highlight Reconstruction's method + double expcomp; + std::vector curve; + std::vector curve2; + eTCModeId curveMode; + eTCModeId curveMode2; + int brightness; + int black; + int contrast; + int saturation; + int shcompr; + int hlcompr; // Highlight Recovery's compression + int hlcomprthresh; // Highlight Recovery's threshold - ToneCurveParams () { - setDefaults(); - } - void setDefaults(); - static bool HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw); + ToneCurveParams () + { + setDefaults(); + } + void setDefaults(); + static bool HLReconstructionNecessary(LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw); }; /** * Parameters of the luminance curve */ -class LCurveParams { +class LCurveParams +{ - public: - std::vector lcurve; - std::vector acurve; - std::vector bcurve; - std::vector cccurve; - std::vector chcurve; - std::vector lhcurve; - std::vector hhcurve; - std::vector lccurve; - std::vector clcurve; - int brightness; - int contrast; - int chromaticity; - bool avoidcolorshift; - double rstprotection; - bool lcredsk; +public: + std::vector lcurve; + std::vector acurve; + std::vector bcurve; + std::vector cccurve; + std::vector chcurve; + std::vector lhcurve; + std::vector hhcurve; + std::vector lccurve; + std::vector clcurve; + int brightness; + int contrast; + int chromaticity; + bool avoidcolorshift; + double rstprotection; + bool lcredsk; }; /** * Parameters of the RGB curves */ -class RGBCurvesParams { +class RGBCurvesParams +{ - public: - bool lumamode; - std::vector rcurve; - std::vector gcurve; - std::vector bcurve; +public: + bool lumamode; + std::vector rcurve; + std::vector gcurve; + std::vector bcurve; }; /** * Parameters of the Color Toning */ -class ColorToningParams { +class ColorToningParams +{ - public: - bool enabled; - bool autosat; - std::vector opacityCurve; - std::vector colorCurve; - int satProtectionThreshold; - int saturatedOpacity; - int strength; - int balance; - Threshold hlColSat; - Threshold shadowsColSat; - std::vector clcurve; - std::vector cl2curve; +public: + bool enabled; + bool autosat; + std::vector opacityCurve; + std::vector colorCurve; + int satProtectionThreshold; + int saturatedOpacity; + int strength; + int balance; + Threshold hlColSat; + Threshold shadowsColSat; + std::vector clcurve; + std::vector cl2curve; - /* Can be either: - * Splitlr : - * Splitco : - * Splitbal : - * Lab : - * Lch : - * RGBSliders : - * RGBCurves : - */ - Glib::ustring method; + /* Can be either: + * Splitlr : + * Splitco : + * Splitbal : + * Lab : + * Lch : + * RGBSliders : + * RGBCurves : + */ + Glib::ustring method; - /* Can be either: - * Std : - * All : - * Separ : - * Two : - */ - Glib::ustring twocolor; - double redlow; - double greenlow; - double bluelow; - double redmed; - double greenmed; - double bluemed; - double redhigh; - double greenhigh; - double bluehigh; - double satlow; - double sathigh; - bool lumamode; + /* Can be either: + * Std : + * All : + * Separ : + * Two : + */ + Glib::ustring twocolor; + double redlow; + double greenlow; + double bluelow; + double redmed; + double greenmed; + double bluemed; + double redhigh; + double greenhigh; + double bluehigh; + double satlow; + double sathigh; + bool lumamode; - ColorToningParams (); - void setDefaults(); // SHOULD BE GENERALIZED TO ALL CLASSES! - /// @brief Transform the mixer values to their curve equivalences - void mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const; - /// @brief Specifically transform the sliders values to their curve equivalences - void slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const; - /// @brief Fill the ColorGradientCurve and OpacityCurve LUTf from the control points curve or sliders value - void getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3], bool &opautili) const; + ColorToningParams (); + void setDefaults(); // SHOULD BE GENERALIZED TO ALL CLASSES! + /// @brief Transform the mixer values to their curve equivalences + void mixerToCurve(std::vector &colorCurve, std::vector &opacityCurve) const; + /// @brief Specifically transform the sliders values to their curve equivalences + void slidersToCurve(std::vector &colorCurve, std::vector &opacityCurve) const; + /// @brief Fill the ColorGradientCurve and OpacityCurve LUTf from the control points curve or sliders value + void getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurve &opacityCurveLUT, const double xyz_rgb[3][3], const double rgb_xyz[3][3], bool &opautili) const; - static void getDefaultColorCurve(std::vector &curve); - static void getDefaultOpacityCurve(std::vector &curve); - static void getDefaultCLCurve(std::vector &curve); - static void getDefaultCL2Curve(std::vector &curve); + static void getDefaultColorCurve(std::vector &curve); + static void getDefaultOpacityCurve(std::vector &curve); + static void getDefaultCLCurve(std::vector &curve); + static void getDefaultCL2Curve(std::vector &curve); }; /** * Parameters of the sharpening */ -class SharpeningParams { +class SharpeningParams +{ - public: - bool enabled; - double radius; - int amount; - Threshold threshold; - bool edgesonly; - double edges_radius; - int edges_tolerance; - bool halocontrol; - int halocontrol_amount; - Glib::ustring method; - int deconvamount; - double deconvradius; - int deconviter; - int deconvdamping; +public: + bool enabled; + double radius; + int amount; + Threshold threshold; + bool edgesonly; + double edges_radius; + int edges_tolerance; + bool halocontrol; + int halocontrol_amount; + Glib::ustring method; + int deconvamount; + double deconvradius; + int deconviter; + int deconvdamping; - SharpeningParams() : threshold(20, 80, 2000, 1200, false) {}; + SharpeningParams() : threshold(20, 80, 2000, 1200, false) {}; }; -class SharpenEdgeParams { - public: - bool enabled; - int passes; - double amount; - bool threechannels; +class SharpenEdgeParams +{ +public: + bool enabled; + int passes; + double amount; + bool threechannels; }; -class SharpenMicroParams { - public: - bool enabled; - bool matrix; - double amount; - double uniformity; +class SharpenMicroParams +{ +public: + bool enabled; + bool matrix; + double amount; + double uniformity; }; /** * Parameters of the vibrance */ -class VibranceParams { +class VibranceParams +{ - public: - bool enabled; - int pastels; - int saturated; - Threshold psthreshold; - bool protectskins; - bool avoidcolorshift; - bool pastsattog; - std::vector skintonescurve; +public: + bool enabled; + int pastels; + int saturated; + Threshold psthreshold; + bool protectskins; + bool avoidcolorshift; + bool pastsattog; + std::vector skintonescurve; - VibranceParams() : psthreshold(0, 75, false) {}; + VibranceParams() : psthreshold(0, 75, false) {}; }; /** @@ -386,7 +430,7 @@ class VibranceParams { */ /*class ColorBoostParams { - public: + public: int amount; bool avoidclip; bool enable_saturationlimiter; @@ -413,7 +457,8 @@ enum WBTypes { WBT_CUSTOM }; -class WBEntry { +class WBEntry +{ public: Glib::ustring ppLabel; enum WBTypes type; @@ -425,71 +470,73 @@ public: WBEntry(Glib::ustring p, enum WBTypes t, Glib::ustring l, int temp, double green, double equal) : ppLabel(p), type(t), GUILabel(l), temperature(temp), green(green), equal(equal) {}; }; -class WBParams { +class WBParams +{ - public: - static std::vector wbEntries; - Glib::ustring method; - int temperature; - double green; - double equal; +public: + static std::vector wbEntries; + Glib::ustring method; + int temperature; + double green; + double equal; - static void init(); - static void cleanup(); + static void init(); + static void cleanup(); }; /** * Parameters of colorappearance */ -class ColorAppearanceParams { +class ColorAppearanceParams +{ - public: - enum eTCModeId { - TC_MODE_LIGHT, // Lightness mode - TC_MODE_BRIGHT, // Brightness mode - }; - - enum eCTCModeId { - TC_MODE_CHROMA, // chroma mode - TC_MODE_SATUR, // saturation mode - TC_MODE_COLORF, // colorfullness mode - }; - - bool enabled; - int degree; - bool autodegree; - std::vector curve; - std::vector curve2; - std::vector curve3; - eTCModeId curveMode; - eTCModeId curveMode2; - eCTCModeId curveMode3; - - Glib::ustring surround; - double adapscen; - bool autoadapscen; - - double adaplum; - int badpixsl; - Glib::ustring wbmodel; - Glib::ustring algo; - double contrast; - double qcontrast; - double jlight; - double qbright; - double chroma; - double schroma; - double mchroma; - double colorh; - double rstprotection; - bool surrsource; - bool gamut; - // bool badpix; - bool datacie; - bool tonecie; - // bool sharpcie; +public: + enum eTCModeId { + TC_MODE_LIGHT, // Lightness mode + TC_MODE_BRIGHT, // Brightness mode }; + enum eCTCModeId { + TC_MODE_CHROMA, // chroma mode + TC_MODE_SATUR, // saturation mode + TC_MODE_COLORF, // colorfullness mode + }; + + bool enabled; + int degree; + bool autodegree; + std::vector curve; + std::vector curve2; + std::vector curve3; + eTCModeId curveMode; + eTCModeId curveMode2; + eCTCModeId curveMode3; + + Glib::ustring surround; + double adapscen; + bool autoadapscen; + + double adaplum; + int badpixsl; + Glib::ustring wbmodel; + Glib::ustring algo; + double contrast; + double qcontrast; + double jlight; + double qbright; + double chroma; + double schroma; + double mchroma; + double colorh; + double rstprotection; + bool surrsource; + bool gamut; + // bool badpix; + bool datacie; + bool tonecie; + // bool sharpcie; +}; + /** * Parameters of the color shift */ @@ -520,170 +567,183 @@ class ColorAppearanceParams { bool enabled; int edgetolerance; bool edgesensitive; - int amount; + int amount; };*/ /** * Parameters of defringing */ -class DefringeParams { +class DefringeParams +{ - public: - bool enabled; - double radius; - float threshold; - std::vector huecurve; +public: + bool enabled; + double radius; + float threshold; + std::vector huecurve; }; /** * Parameters of impulse denoising */ -class ImpulseDenoiseParams { +class ImpulseDenoiseParams +{ - public: - bool enabled; - int thresh; +public: + bool enabled; + int thresh; }; /** * Parameters of the directional pyramid denoising */ -class DirPyrDenoiseParams { +class DirPyrDenoiseParams +{ - public: - std::vector lcurve; - std::vector cccurve; - - bool enabled; - bool enhance; - bool median; - bool autochroma; - - bool perform; - double luma; - double Ldetail; - double chroma; - double redchro; - double bluechro; - double gamma; - Glib::ustring dmethod; - Glib::ustring Lmethod; - Glib::ustring Cmethod; - Glib::ustring C2method; - Glib::ustring smethod; - Glib::ustring medmethod; - Glib::ustring methodmed; - Glib::ustring rgbmethod; - int passes; - - DirPyrDenoiseParams (); - void setDefaults(); // SHOULD BE GENERALIZED TO ALL CLASSES! - void getCurves(NoiseCurve &lCurve, NoiseCurve &cCurve) const; +public: + std::vector lcurve; + std::vector cccurve; + + bool enabled; + bool enhance; + bool median; + bool autochroma; + + bool perform; + double luma; + double Ldetail; + double chroma; + double redchro; + double bluechro; + double gamma; + Glib::ustring dmethod; + Glib::ustring Lmethod; + Glib::ustring Cmethod; + Glib::ustring C2method; + Glib::ustring smethod; + Glib::ustring medmethod; + Glib::ustring methodmed; + Glib::ustring rgbmethod; + int passes; + + DirPyrDenoiseParams (); + void setDefaults(); // SHOULD BE GENERALIZED TO ALL CLASSES! + void getCurves(NoiseCurve &lCurve, NoiseCurve &cCurve) const; + + static void getDefaultNoisCurve(std::vector &curve); + static void getDefaultCCCurve(std::vector &curve); - static void getDefaultNoisCurve(std::vector &curve); - static void getDefaultCCCurve(std::vector &curve); - }; //EPD related parameters. -class EPDParams{ - public: - bool enabled; - double strength; - double gamma; - double edgeStopping; - double scale; - int reweightingIterates; +class EPDParams +{ +public: + bool enabled; + double strength; + double gamma; + double edgeStopping; + double scale; + int reweightingIterates; }; /** * Parameters of the shadow/highlight enhancement */ -class SHParams { +class SHParams +{ - public: - bool enabled; - bool hq; - int highlights; - int htonalwidth; - int shadows; - int stonalwidth; - int localcontrast; - int radius; +public: + bool enabled; + bool hq; + int highlights; + int htonalwidth; + int shadows; + int stonalwidth; + int localcontrast; + int radius; }; /** * Parameters of the cropping */ -class CropParams { +class CropParams +{ - public: - bool enabled; - int x; - int y; - int w; - int h; - bool fixratio; - Glib::ustring ratio; - Glib::ustring orientation; - Glib::ustring guide; +public: + bool enabled; + int x; + int y; + int w; + int h; + bool fixratio; + Glib::ustring ratio; + Glib::ustring orientation; + Glib::ustring guide; - CropParams() :enabled(false), x(0),y(0),w(0),h(0),fixratio(false) {}; - void mapToResized(int resizedWidth, int resizedHeight, int scale, int &x1, int &x2, int &y1, int &y2) const; + CropParams() : enabled(false), x(0), y(0), w(0), h(0), fixratio(false) {}; + void mapToResized(int resizedWidth, int resizedHeight, int scale, int &x1, int &x2, int &y1, int &y2) const; }; /** * Parameters of the coarse transformations like 90 deg rotations and h/v flipping */ -class CoarseTransformParams { +class CoarseTransformParams +{ - public: - int rotate; - bool hflip; - bool vflip; +public: + int rotate; + bool hflip; + bool vflip; - CoarseTransformParams() { - setDefaults(); - } - void setDefaults(); + CoarseTransformParams() + { + setDefaults(); + } + void setDefaults(); }; /** * Common transformation parameters */ -class CommonTransformParams { +class CommonTransformParams +{ - public: - bool autofill; +public: + bool autofill; }; /** * Parameters of the rotation */ -class RotateParams { - - public: - double degree; +class RotateParams +{ + +public: + double degree; }; /** * Parameters of the distortion correction */ -class DistortionParams { +class DistortionParams +{ - public: - double amount; +public: + double amount; }; // Lens profile correction parameters -class LensProfParams { - +class LensProfParams +{ + public: Glib::ustring lcpFile; bool useDist, useVign, useCA; - LensProfParams() { + LensProfParams() + { setDefaults(); } void setDefaults(); @@ -692,161 +752,171 @@ public: /** * Parameters of the perspective correction */ -class PerspectiveParams { +class PerspectiveParams +{ - public: - double horizontal; - double vertical; +public: + double horizontal; + double vertical; }; /** * Parameters of the gradient filter */ -class GradientParams { +class GradientParams +{ - public: - bool enabled; - double degree; - int feather; - double strength; - int centerX; - int centerY; +public: + bool enabled; + double degree; + int feather; + double strength; + int centerX; + int centerY; }; /** * Parameters of the post-crop vignette filter */ -class PCVignetteParams { +class PCVignetteParams +{ - public: - bool enabled; - double strength; - int feather; - int roundness; +public: + bool enabled; + double strength; + int feather; + int roundness; }; /** * Parameters of the vignetting correction */ -class VignettingParams { +class VignettingParams +{ - public: - int amount; - int radius; - int strength; - int centerX; - int centerY; +public: + int amount; + int radius; + int strength; + int centerX; + int centerY; }; /** * Parameters of the color mixer */ -class ChannelMixerParams { +class ChannelMixerParams +{ - public: - int red[3]; - int green[3]; - int blue[3]; +public: + int red[3]; + int green[3]; + int blue[3]; }; -class BlackWhiteParams { +class BlackWhiteParams +{ - public: - enum eTCModeId { - TC_MODE_STD_BW, // Standard modes, the curve is applied on all component individually - TC_MODE_WEIGHTEDSTD_BW, // Weighted standard mode - TC_MODE_FILMLIKE_BW, // Film-like mode, as defined in Adobe's reference code - TC_MODE_SATANDVALBLENDING_BW // Modify the Saturation and Value channel - }; +public: + enum eTCModeId { + TC_MODE_STD_BW, // Standard modes, the curve is applied on all component individually + TC_MODE_WEIGHTEDSTD_BW, // Weighted standard mode + TC_MODE_FILMLIKE_BW, // Film-like mode, as defined in Adobe's reference code + TC_MODE_SATANDVALBLENDING_BW // Modify the Saturation and Value channel + }; - std::vector beforeCurve; - eTCModeId beforeCurveMode; - std::vector afterCurve; - eTCModeId afterCurveMode; - Glib::ustring algo; + std::vector beforeCurve; + eTCModeId beforeCurveMode; + std::vector afterCurve; + eTCModeId afterCurveMode; + Glib::ustring algo; - std::vector luminanceCurve; - bool autoc; - bool enabledcc; - bool enabled; - Glib::ustring filter; - Glib::ustring setting; - Glib::ustring method; - int mixerRed; - int mixerOrange; - int mixerYellow; - int mixerGreen; - int mixerCyan; - int mixerBlue; - int mixerMagenta; - int mixerPurple; - int gammaRed; - int gammaGreen; - int gammaBlue; + std::vector luminanceCurve; + bool autoc; + bool enabledcc; + bool enabled; + Glib::ustring filter; + Glib::ustring setting; + Glib::ustring method; + int mixerRed; + int mixerOrange; + int mixerYellow; + int mixerGreen; + int mixerCyan; + int mixerBlue; + int mixerMagenta; + int mixerPurple; + int gammaRed; + int gammaGreen; + int gammaBlue; }; /** * Parameters of the c/a correction */ -class CACorrParams { +class CACorrParams +{ - public: - double red; - double blue; +public: + double red; + double blue; }; /** * Parameters of the highlight recovery */ - /* +/* class HRecParams { - public: - bool enabled; - Glib::ustring method; + public: + bool enabled; + Glib::ustring method; }; */ /** * Parameters of the resizing */ -class ResizeParams { +class ResizeParams +{ - public: - bool enabled; - double scale; - Glib::ustring appliesTo; - Glib::ustring method; - int dataspec; - int width; - int height; +public: + bool enabled; + double scale; + Glib::ustring appliesTo; + Glib::ustring method; + int dataspec; + int width; + int height; }; /** * Parameters of the color spaces used during the processing */ -class ColorManagementParams { +class ColorManagementParams +{ - public: - Glib::ustring input; - bool toneCurve; - bool applyLookTable; - bool applyBaselineExposureOffset; - bool applyHueSatMap; - bool blendCMSMatrix; // setting no longer used - int dcpIlluminant; - Glib::ustring working; - Glib::ustring output; - static const Glib::ustring NoICMString; +public: + Glib::ustring input; + bool toneCurve; + bool applyLookTable; + bool applyBaselineExposureOffset; + bool applyHueSatMap; + bool blendCMSMatrix; // setting no longer used + int dcpIlluminant; + Glib::ustring working; + Glib::ustring output; + static const Glib::ustring NoICMString; - Glib::ustring gamma; - double gampos; - double slpos; - bool freegamma; + Glib::ustring gamma; + double gampos; + double slpos; + bool freegamma; - ColorManagementParams() { - setDefaults(); - } - void setDefaults(); + ColorManagementParams() + { + setDefaults(); + } + void setDefaults(); }; /** @@ -860,135 +930,138 @@ typedef std::map ExifPairs; typedef std::map > IPTCPairs; -class WaveletParams { +class WaveletParams +{ + +public: + std::vector ccwcurve; + std::vector opacityCurveRG; + std::vector opacityCurveBY; + std::vector opacityCurveW; + std::vector opacityCurveWL; + std::vector hhcurve; + std::vector Chcurve; + std::vector wavclCurve; + bool enabled; + bool median; + bool medianlev; + bool linkedg; + bool cbenab; + double greenlow; + double bluelow; + double greenmed; + double bluemed; + double greenhigh; + double bluehigh; + + bool lipst; + // bool edgreinf; + bool avoid; + bool tmr; + int strength; + int balance; + int iter; + bool expcontrast; + bool expchroma; + int c[9]; + int ch[9]; + bool expedge; + bool expresid; + bool expfinal; + bool exptoning; + bool expnoise; + + Glib::ustring Lmethod; + Glib::ustring CLmethod; + Glib::ustring Backmethod; + Glib::ustring Tilesmethod; + Glib::ustring daubcoeffmethod; + Glib::ustring CHmethod; + Glib::ustring Medgreinf; + Glib::ustring CHSLmethod; + Glib::ustring EDmethod; + Glib::ustring NPmethod; + Glib::ustring BAmethod; + Glib::ustring TMmethod; + Glib::ustring Dirmethod; + Glib::ustring HSmethod; + int rescon; + int resconH; + int reschro; + double tmrs; + double gamma; + int sup; + double sky; + int thres; + int chroma; + int chro; + int threshold; + int threshold2; + int edgedetect; + int edgedetectthr; + int edgedetectthr2; + int edgesensi; + int edgeampli; + int contrast; + int edgrad; + int edgval; + int edgthresh; + int thr; + int thrH; + double skinprotect; + Threshold hueskin; + Threshold hueskin2; + Threshold hllev; + Threshold bllev; + Threshold pastlev; + Threshold satlev; + Threshold edgcont; + Threshold level0noise; + Threshold level1noise; + Threshold level2noise; + Threshold level3noise; + + + WaveletParams (); + void setDefaults(); + void getCurves(WavCurve &cCurve, WavOpacityCurveRG &opacityCurveLUTRG , WavOpacityCurveBY &opacityCurveLUTBY, WavOpacityCurveW &opacityCurveLUTW, WavOpacityCurveWL &opacityCurveLUTWL) const; + static void getDefaultCCWCurve(std::vector &curve); + static void getDefaultOpacityCurveRG(std::vector &curve); + static void getDefaultOpacityCurveBY(std::vector &curve); + static void getDefaultOpacityCurveW(std::vector &curve); + static void getDefaultOpacityCurveWL(std::vector &curve); - public: - std::vector ccwcurve; - std::vector opacityCurveRG; - std::vector opacityCurveBY; - std::vector opacityCurveW; - std::vector opacityCurveWL; - std::vector hhcurve; - std::vector Chcurve; - std::vector wavclCurve; - bool enabled; - bool median; - bool medianlev; - bool linkedg; - bool cbenab; - double greenlow; - double bluelow; - double greenmed; - double bluemed; - double greenhigh; - double bluehigh; - - bool lipst; - // bool edgreinf; - bool avoid; - bool tmr; - int strength; - int balance; - int iter; - bool expcontrast; - bool expchroma; - int c[9]; - int ch[9]; - bool expedge; - bool expresid; - bool expfinal; - bool exptoning; - bool expnoise; - - Glib::ustring Lmethod; - Glib::ustring CLmethod; - Glib::ustring Backmethod; - Glib::ustring Tilesmethod; - Glib::ustring daubcoeffmethod; - Glib::ustring CHmethod; - Glib::ustring Medgreinf; - Glib::ustring CHSLmethod; - Glib::ustring EDmethod; - Glib::ustring NPmethod; - Glib::ustring BAmethod; - Glib::ustring TMmethod; - Glib::ustring Dirmethod; - Glib::ustring HSmethod; - int rescon; - int resconH; - int reschro; - double tmrs; - double gamma; - int sup; - double sky; - int thres; - int chroma; - int chro; - int threshold; - int threshold2; - int edgedetect; - int edgedetectthr; - int edgedetectthr2; - int edgesensi; - int edgeampli; - int contrast; - int edgrad; - int edgval; - int edgthresh; - int thr; - int thrH; - double skinprotect; - Threshold hueskin; - Threshold hueskin2; - Threshold hllev; - Threshold bllev; - Threshold pastlev; - Threshold satlev; - Threshold edgcont; - Threshold level0noise; - Threshold level1noise; - Threshold level2noise; - Threshold level3noise; - - - WaveletParams (); - void setDefaults(); - void getCurves(WavCurve &cCurve,WavOpacityCurveRG &opacityCurveLUTRG , WavOpacityCurveBY &opacityCurveLUTBY, WavOpacityCurveW &opacityCurveLUTW, WavOpacityCurveWL &opacityCurveLUTWL) const; - static void getDefaultCCWCurve(std::vector &curve); - static void getDefaultOpacityCurveRG(std::vector &curve); - static void getDefaultOpacityCurveBY(std::vector &curve); - static void getDefaultOpacityCurveW(std::vector &curve); - static void getDefaultOpacityCurveWL(std::vector &curve); - }; /** * Directional pyramid equalizer params */ -class DirPyrEqualizerParams { +class DirPyrEqualizerParams +{ - public: - bool enabled; - bool gamutlab; - double mult[6]; - double threshold; - double skinprotect; - Threshold hueskin; - //Glib::ustring algo; +public: + bool enabled; + bool gamutlab; + double mult[6]; + double threshold; + double skinprotect; + Threshold hueskin; + //Glib::ustring algo; - DirPyrEqualizerParams() : hueskin(20, 80, 2000, 1200, false) {}; + DirPyrEqualizerParams() : hueskin(20, 80, 2000, 1200, false) {}; }; /** * HSV equalizer params */ -class HSVEqualizerParams { +class HSVEqualizerParams +{ - public: - std::vector hcurve; - std::vector scurve; - std::vector vcurve; +public: + std::vector hcurve; + std::vector scurve; + std::vector vcurve; }; @@ -999,12 +1072,14 @@ struct FilmSimulationParams { bool enabled; Glib::ustring clutFilename; int strength; - - FilmSimulationParams() { + + FilmSimulationParams() + { setDefaults(); } - void setDefaults() { + void setDefaults() + { enabled = false; clutFilename = Glib::ustring(); strength = 100; @@ -1015,190 +1090,198 @@ struct FilmSimulationParams { /** * Parameters for RAW demosaicing, common to all sensor type */ -class RAWParams { +class RAWParams +{ +public: + /** + * Parameters for RAW demosaicing specific to Bayer sensors + */ + class BayerSensor + { public: - /** - * Parameters for RAW demosaicing specific to Bayer sensors - */ - class BayerSensor { - public: - //enum eMethod{ eahd,hphd,vng4,dcb,amaze,ahd,IGV_noise,fast, - //numMethods }; // This MUST be the last enum - enum eMethod{ amaze, igv, lmmse, eahd, hphd, vng4, dcb, ahd, fast, mono, none, - numMethods }; // This MUST be the last enum - static const char *methodstring[numMethods]; + //enum eMethod{ eahd,hphd,vng4,dcb,amaze,ahd,IGV_noise,fast, + //numMethods }; // This MUST be the last enum + enum eMethod { amaze, igv, lmmse, eahd, hphd, vng4, dcb, ahd, fast, mono, none, + numMethods + }; // This MUST be the last enum + static const char *methodstring[numMethods]; - Glib::ustring method; - int ccSteps; - double black0; - double black1; - double black2; - double black3; - bool twogreen; - int linenoise; - int greenthresh; - int dcb_iterations; - int lmmse_iterations; - bool dcb_enhance; - //bool all_enhance; - }; + Glib::ustring method; + int ccSteps; + double black0; + double black1; + double black2; + double black3; + bool twogreen; + int linenoise; + int greenthresh; + int dcb_iterations; + int lmmse_iterations; + bool dcb_enhance; + //bool all_enhance; + }; - /** - * Parameters for RAW demosaicing specific to X-Trans sensors - */ - class XTransSensor { - public: - enum eMethod{ threePass, onePass, fast, mono, none, - numMethods }; // This MUST be the last enum - static const char *methodstring[numMethods]; + /** + * Parameters for RAW demosaicing specific to X-Trans sensors + */ + class XTransSensor + { + public: + enum eMethod { threePass, onePass, fast, mono, none, + numMethods + }; // This MUST be the last enum + static const char *methodstring[numMethods]; - Glib::ustring method; - int ccSteps; - double blackred; - double blackgreen; - double blackblue; - }; + Glib::ustring method; + int ccSteps; + double blackred; + double blackgreen; + double blackblue; + }; - BayerSensor bayersensor; ///< RAW parameters for Bayer sensors - XTransSensor xtranssensor; ///< RAW parameters for X-Trans sensors + BayerSensor bayersensor; ///< RAW parameters for Bayer sensors + XTransSensor xtranssensor; ///< RAW parameters for X-Trans sensors - enum eFlatFileBlurType{ /*parametric,*/area_ff,v_ff,h_ff,vh_ff, - numFlatFileBlurTypes }; // This MUST be the last enum + enum eFlatFileBlurType { /*parametric,*/area_ff, v_ff, h_ff, vh_ff, + numFlatFileBlurTypes + }; // This MUST be the last enum - static const char *ff_BlurTypestring[numFlatFileBlurTypes]; + static const char *ff_BlurTypestring[numFlatFileBlurTypes]; - Glib::ustring dark_frame; - bool df_autoselect; + Glib::ustring dark_frame; + bool df_autoselect; - Glib::ustring ff_file; - bool ff_AutoSelect; - int ff_BlurRadius; - Glib::ustring ff_BlurType; - bool ff_AutoClipControl; - int ff_clipControl; + Glib::ustring ff_file; + bool ff_AutoSelect; + int ff_BlurRadius; + Glib::ustring ff_BlurType; + bool ff_AutoClipControl; + int ff_clipControl; - bool ca_autocorrect; - double cared; - double cablue; + bool ca_autocorrect; + double cared; + double cablue; - // exposure before interpolation - double expos; - double preser; + // exposure before interpolation + double expos; + double preser; - bool hotPixelFilter; - bool deadPixelFilter; - int hotdeadpix_thresh; + bool hotPixelFilter; + bool deadPixelFilter; + int hotdeadpix_thresh; - RAWParams() { - setDefaults(); - } - void setDefaults(); + RAWParams() + { + setDefaults(); + } + void setDefaults(); }; /** * This class holds all the processing parameters applied on the images */ -class ProcParams { +class ProcParams +{ - public: - ToneCurveParams toneCurve; ///< Tone curve parameters - LCurveParams labCurve; ///< CIELAB luminance curve parameters - RGBCurvesParams rgbCurves; ///< RGB curves parameters - ColorToningParams colorToning; ///< Color Toning parameters - SharpeningParams sharpening; ///< Sharpening parameters - SharpeningParams prsharpening; ///< Sharpening parameters for post resize sharpening - SharpenEdgeParams sharpenEdge; ///< Sharpen edge parameters - SharpenMicroParams sharpenMicro; ///< Sharpen microcontrast parameters - VibranceParams vibrance; ///< Vibrance parameters - //ColorBoostParams colorBoost; ///< Color boost parameters - WBParams wb; ///< White balance parameters - ColorAppearanceParams colorappearance; - //ColorShiftParams colorShift; ///< Color shift parameters - //LumaDenoiseParams lumaDenoise; ///< Luminance denoising parameters - //ColorDenoiseParams colorDenoise; ///< Color denoising parameters - DefringeParams defringe; ///< Defringing parameters - ImpulseDenoiseParams impulseDenoise; ///< Impulse denoising parameters - DirPyrDenoiseParams dirpyrDenoise; ///< Directional Pyramid denoising parameters - EPDParams epd; ///< Edge Preserving Decomposition parameters - SHParams sh; ///< Shadow/highlight enhancement parameters - CropParams crop; ///< Crop parameters - CoarseTransformParams coarse; ///< Coarse transformation (90, 180, 270 deg rotation, h/v flipping) parameters - CommonTransformParams commonTrans; ///< Common transformation parameters (autofill) - RotateParams rotate; ///< Rotation parameters - DistortionParams distortion; ///< Lens distortion correction parameters - LensProfParams lensProf; ///< Lens correction profile parameters - PerspectiveParams perspective; ///< Perspective correction parameters - GradientParams gradient; ///< Gradient filter parameters - PCVignetteParams pcvignette; ///< Post-crop vignette filter parameters - CACorrParams cacorrection; ///< Lens c/a correction parameters - VignettingParams vignetting; ///< Lens vignetting correction parameters - ChannelMixerParams chmixer; ///< Channel mixer parameters - BlackWhiteParams blackwhite; ///< Black & White parameters - ResizeParams resize; ///< Resize parameters - ColorManagementParams icm; ///< profiles/color spaces used during the image processing - RAWParams raw; ///< RAW parameters before demosaicing - WaveletParams wavelet; ///< wavelet wavelet parameters - DirPyrEqualizerParams dirpyrequalizer; ///< directional pyramid wavelet parameters - HSVEqualizerParams hsvequalizer; ///< hsv wavelet parameters - FilmSimulationParams filmSimulation; ///< film simulation parameters - char rank; ///< Custom image quality ranking - char colorlabel; ///< Custom color label - bool inTrash; ///< Marks deleted image - Glib::ustring appVersion; ///< Version of the application that generated the parameters - int ppVersion; ///< Version of the PP file from which the parameters have been read +public: + ToneCurveParams toneCurve; ///< Tone curve parameters + LCurveParams labCurve; ///< CIELAB luminance curve parameters + RGBCurvesParams rgbCurves; ///< RGB curves parameters + ColorToningParams colorToning; ///< Color Toning parameters + SharpeningParams sharpening; ///< Sharpening parameters + SharpeningParams prsharpening; ///< Sharpening parameters for post resize sharpening + SharpenEdgeParams sharpenEdge; ///< Sharpen edge parameters + SharpenMicroParams sharpenMicro; ///< Sharpen microcontrast parameters + VibranceParams vibrance; ///< Vibrance parameters + //ColorBoostParams colorBoost; ///< Color boost parameters + WBParams wb; ///< White balance parameters + ColorAppearanceParams colorappearance; + //ColorShiftParams colorShift; ///< Color shift parameters + //LumaDenoiseParams lumaDenoise; ///< Luminance denoising parameters + //ColorDenoiseParams colorDenoise; ///< Color denoising parameters + DefringeParams defringe; ///< Defringing parameters + ImpulseDenoiseParams impulseDenoise; ///< Impulse denoising parameters + DirPyrDenoiseParams dirpyrDenoise; ///< Directional Pyramid denoising parameters + EPDParams epd; ///< Edge Preserving Decomposition parameters + SHParams sh; ///< Shadow/highlight enhancement parameters + CropParams crop; ///< Crop parameters + CoarseTransformParams coarse; ///< Coarse transformation (90, 180, 270 deg rotation, h/v flipping) parameters + CommonTransformParams commonTrans; ///< Common transformation parameters (autofill) + RotateParams rotate; ///< Rotation parameters + DistortionParams distortion; ///< Lens distortion correction parameters + LensProfParams lensProf; ///< Lens correction profile parameters + PerspectiveParams perspective; ///< Perspective correction parameters + GradientParams gradient; ///< Gradient filter parameters + PCVignetteParams pcvignette; ///< Post-crop vignette filter parameters + CACorrParams cacorrection; ///< Lens c/a correction parameters + VignettingParams vignetting; ///< Lens vignetting correction parameters + ChannelMixerParams chmixer; ///< Channel mixer parameters + BlackWhiteParams blackwhite; ///< Black & White parameters + ResizeParams resize; ///< Resize parameters + ColorManagementParams icm; ///< profiles/color spaces used during the image processing + RAWParams raw; ///< RAW parameters before demosaicing + WaveletParams wavelet; ///< wavelet wavelet parameters + DirPyrEqualizerParams dirpyrequalizer; ///< directional pyramid wavelet parameters + HSVEqualizerParams hsvequalizer; ///< hsv wavelet parameters + FilmSimulationParams filmSimulation; ///< film simulation parameters + char rank; ///< Custom image quality ranking + char colorlabel; ///< Custom color label + bool inTrash; ///< Marks deleted image + Glib::ustring appVersion; ///< Version of the application that generated the parameters + int ppVersion; ///< Version of the PP file from which the parameters have been read - ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image - IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image + ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image + IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image - /** - * The constructor only sets the hand-wired defaults. - */ - ProcParams (); - /** - * Sets the hand-wired defaults parameters. - */ - void setDefaults (); - /** - * Saves the parameters to possibly two files. This is a performance improvement if a function has to - * save the same file in two different location, i.e. the cache and the image's directory - * @param fname the name of the first file (can be an empty string) - * @param fname2 the name of the second file (can be an empty string) (optional) - * @param fnameAbsolute set to false if embedded filenames (if any, darkframe/flatfield) should be stored as relative - * filenames if they are inside the same directory or in a sub-directory to fname's directory. - * @param pedited pointer to a ParamsEdited object (optional) to store which values has to be saved - * @return Error code (=0 if all supplied filenames where created correctly) - */ - int save (Glib::ustring fname, Glib::ustring fname2 = "", bool fnameAbsolute = true, ParamsEdited* pedited=NULL); - /** - * Loads the parameters from a file. - * @param fname the name of the file - * @params pedited pointer to a ParamsEdited object (optional) to store which values has been loaded - * @return Error code (=0 if no error) - */ - int load (Glib::ustring fname, ParamsEdited* pedited=NULL); + /** + * The constructor only sets the hand-wired defaults. + */ + ProcParams (); + /** + * Sets the hand-wired defaults parameters. + */ + void setDefaults (); + /** + * Saves the parameters to possibly two files. This is a performance improvement if a function has to + * save the same file in two different location, i.e. the cache and the image's directory + * @param fname the name of the first file (can be an empty string) + * @param fname2 the name of the second file (can be an empty string) (optional) + * @param fnameAbsolute set to false if embedded filenames (if any, darkframe/flatfield) should be stored as relative + * filenames if they are inside the same directory or in a sub-directory to fname's directory. + * @param pedited pointer to a ParamsEdited object (optional) to store which values has to be saved + * @return Error code (=0 if all supplied filenames where created correctly) + */ + int save (Glib::ustring fname, Glib::ustring fname2 = "", bool fnameAbsolute = true, ParamsEdited* pedited = NULL); + /** + * Loads the parameters from a file. + * @param fname the name of the file + * @params pedited pointer to a ParamsEdited object (optional) to store which values has been loaded + * @return Error code (=0 if no error) + */ + int load (Glib::ustring fname, ParamsEdited* pedited = NULL); - /** Creates a new instance of ProcParams. - * @return a pointer to the new ProcParams instance. */ - static ProcParams* create (); + /** Creates a new instance of ProcParams. + * @return a pointer to the new ProcParams instance. */ + static ProcParams* create (); - /** Destroys an instance of ProcParams. - * @param pp a pointer to the ProcParams instance to destroy. */ - static void destroy (ProcParams* pp); + /** Destroys an instance of ProcParams. + * @param pp a pointer to the ProcParams instance to destroy. */ + static void destroy (ProcParams* pp); - static void init (); - static void cleanup (); + static void init (); + static void cleanup (); - bool operator== (const ProcParams& other); - bool operator!= (const ProcParams& other); + bool operator== (const ProcParams& other); + bool operator!= (const ProcParams& other); - private: - /** Write the ProcParams's text in the file of the given name. - * @param fname the name of the file - * @param content the text to write - * @return Error code (=0 if no error) - * */ - int write (Glib::ustring &fname, Glib::ustring &content) const; +private: + /** Write the ProcParams's text in the file of the given name. + * @param fname the name of the file + * @param content the text to write + * @return Error code (=0 if no error) + * */ + int write (Glib::ustring &fname, Glib::ustring &content) const; }; @@ -1211,20 +1294,26 @@ class ProcParams { * and hence is not responsible of their destructions. The function that instanciate * PartialProfile object has to handle all this itself. */ -class PartialProfile { - public: - rtengine::procparams::ProcParams* pparams; - ParamsEdited* pedited; - PartialProfile& operator=(PartialProfile& rhs) { pparams=rhs.pparams; pedited=rhs.pedited; return *this; }; +class PartialProfile +{ +public: + rtengine::procparams::ProcParams* pparams; + ParamsEdited* pedited; + PartialProfile& operator=(PartialProfile& rhs) + { + pparams = rhs.pparams; + pedited = rhs.pedited; + return *this; + }; - PartialProfile (bool createInstance=false, bool paramsEditedValue=false); - PartialProfile (ProcParams* pp, ParamsEdited* pe=NULL, bool fullCopy=false); - PartialProfile (const ProcParams* pp, const ParamsEdited* pe=NULL); - void deleteInstance (); - void clearGeneral (); - int load (Glib::ustring fName); - void set (bool v); - const void applyTo (ProcParams *destParams) const ; + PartialProfile (bool createInstance = false, bool paramsEditedValue = false); + PartialProfile (ProcParams* pp, ParamsEdited* pe = NULL, bool fullCopy = false); + PartialProfile (const ProcParams* pp, const ParamsEdited* pe = NULL); + void deleteInstance (); + void clearGeneral (); + int load (Glib::ustring fName); + void set (bool v); + const void applyTo (ProcParams *destParams) const ; }; /** @@ -1232,10 +1321,14 @@ class PartialProfile { * and automatically delete them in the destructor. This class has been mostly created * to be used with vectors, which use the default constructor/destructor */ -class AutoPartialProfile : public PartialProfile { - public: - AutoPartialProfile() : PartialProfile(true) {} - ~AutoPartialProfile() { deleteInstance(); } +class AutoPartialProfile : public PartialProfile +{ +public: + AutoPartialProfile() : PartialProfile(true) {} + ~AutoPartialProfile() + { + deleteInstance(); + } }; } diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 3638ebeca..7eb057b67 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -15,588 +15,755 @@ #endif #include "safegtk.h" -namespace rtengine{ +namespace rtengine +{ extern const Settings* settings; RawImage::RawImage( const Glib::ustring name ) -:data(NULL) -,prefilters(0) -,filename(name) -,profile_data(NULL) -,allocation(NULL) + : data(NULL) + , prefilters(0) + , filename(name) + , profile_data(NULL) + , allocation(NULL) { - memset(maximum_c4, 0, sizeof(maximum_c4)); - RT_matrix_from_constant = 0; - RT_blacklevel_from_constant = 0; - RT_whitelevel_from_constant = 0; + memset(maximum_c4, 0, sizeof(maximum_c4)); + RT_matrix_from_constant = 0; + RT_blacklevel_from_constant = 0; + RT_whitelevel_from_constant = 0; } RawImage::~RawImage() { - if(ifp) - fclose(ifp); - if( image ) - free(image); - if(allocation){ delete [] allocation; allocation=NULL;} - if(float_raw_image) { delete [] float_raw_image; float_raw_image = NULL; } - if(data){ delete [] data; data=NULL;} - if(profile_data){ delete [] profile_data; profile_data=NULL;} + if(ifp) { + fclose(ifp); + } + + if( image ) { + free(image); + } + + if(allocation) { + delete [] allocation; + allocation = NULL; + } + + if(float_raw_image) { + delete [] float_raw_image; + float_raw_image = NULL; + } + + if(data) { + delete [] data; + data = NULL; + } + + if(profile_data) { + delete [] profile_data; + profile_data = NULL; + } } -eSensorType RawImage::getSensorType() { - if (isBayer()) - return ST_BAYER; - else if (isXtrans()) - return ST_FUJI_XTRANS; - else if (isFoveon()) - return ST_FOVEON; +eSensorType RawImage::getSensorType() +{ + if (isBayer()) { + return ST_BAYER; + } else if (isXtrans()) { + return ST_FUJI_XTRANS; + } else if (isFoveon()) { + return ST_FOVEON; + } - return ST_NONE; + return ST_NONE; } /* Similar to dcraw scale_colors for coeff. calculation, but without actual pixels scaling. * need pixels in data[][] available */ -void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblack_, bool forceAutoWB) { - unsigned row, col, x, y, c, sum[8]; - unsigned W = this->get_width(); - unsigned H = this->get_height(); - float val; - double dsum[8], dmin, dmax; - - if ((this->get_cblack(4)+1)/2 == 1 && (this->get_cblack(5)+1)/2 == 1) { - for (int c = 0; c < 4; c++){ - cblack_[FC(c/2,c%2)] = this->get_cblack(6 + c/2 % this->get_cblack(4) * this->get_cblack(5) + c%2 % this->get_cblack(5)); - pre_mul_[c] = this->get_pre_mul(c); - } - } else if(isXtrans()) { - // for xtrans files dcraw stores black levels in cblack[6] .. cblack[41], but all are equal, so we just use cblack[6] - for (int c = 0; c < 4; c++){ - cblack_[c] = (float) this->get_cblack(6); - pre_mul_[c] = this->get_pre_mul(c); - } - } else { - for (int c = 0; c < 4; c++){ - cblack_[c] = (float) this->get_cblack(c); - pre_mul_[c] = this->get_pre_mul(c); - } - } - if ( this->get_cam_mul(0) == -1 || forceAutoWB) { - memset(dsum, 0, sizeof dsum); - if (this->isBayer()) { - // calculate number of pixels per color - dsum[FC(0,0)+4] += (int)(((W+1)/2) * ((H+1)/2)); - dsum[FC(0,1)+4] += (int)(((W/2) * ((H+1)/2))); - dsum[FC(1,0)+4] += (int)(((W+1)/2) * (H/2)); - dsum[FC(1,1)+4] += (int)((W/2) * (H/2)); - -#pragma omp parallel private(val,row,col,x,y) +void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblack_, bool forceAutoWB) { - double dsumthr[8]; - memset(dsumthr, 0, sizeof dsumthr); - float sum[4]; - // make local copies of the black and white values to avoid calculations and conversions - float cblackfloat[4]; - float whitefloat[4]; - for (int c = 0; c < 4; c++) { - cblackfloat[c] = cblack_[c]; - whitefloat[c] = this->get_white(c) - 25; - } - float *tempdata = data[0]; -#pragma omp for nowait - for (row = 0; row < H; row += 8) { - int ymax = row + 8 < H ? row + 8 : H; - for (col = 0; col < W ; col += 8) { - int xmax = col + 8 < W ? col + 8 : W; - memset(sum, 0, sizeof sum); - for (y = row; y < ymax; y++) - for (x = col; x < xmax; x++) { - int c = FC(y, x); - val = tempdata[y*W+x]; - if (val > whitefloat[c]) { // calculate number of pixels to be substracted from sum and skip the block - dsumthr[FC(row,col)+4] += (int)(((xmax - col + 1)/2) * ((ymax - row + 1)/2)); - dsumthr[FC(row,col+1)+4] += (int)(((xmax - col)/2) * ((ymax - row + 1)/2)); - dsumthr[FC(row+1,col)+4] += (int)(((xmax - col + 1)/2) * ((ymax - row)/2)); - dsumthr[FC(row+1,col+1)+4] += (int)(((xmax - col)/2) * ((ymax - row)/2)); - goto skip_block2; - } - if (val < cblackfloat[c]) - val = cblackfloat[c]; - sum[c] += val; - } - for (int c = 0; c < 4; c++) - dsumthr[c] += sum[c]; -skip_block2: ; - } - } -#pragma omp critical -{ - for (int c = 0; c < 4; c++) - dsum[c] += dsumthr[c]; - for (int c = 4; c < 8; c++) - dsum[c] -= dsumthr[c]; - -} -} - for(int c=0;c<4;c++) - dsum[c] -= cblack_[c] * dsum[c+4]; + unsigned row, col, x, y, c, sum[8]; + unsigned W = this->get_width(); + unsigned H = this->get_height(); + float val; + double dsum[8], dmin, dmax; - } else if(isXtrans()) { -#pragma omp parallel -{ - double dsumthr[8]; - memset(dsumthr, 0, sizeof dsumthr); - float sum[8]; - // make local copies of the black and white values to avoid calculations and conversions - float whitefloat[4]; - for (int c = 0; c < 4; c++) { - whitefloat[c] = this->get_white(c) - 25; - } + if ((this->get_cblack(4) + 1) / 2 == 1 && (this->get_cblack(5) + 1) / 2 == 1) { + for (int c = 0; c < 4; c++) { + cblack_[FC(c / 2, c % 2)] = this->get_cblack(6 + c / 2 % this->get_cblack(4) * this->get_cblack(5) + c % 2 % this->get_cblack(5)); + pre_mul_[c] = this->get_pre_mul(c); + } + } else if(isXtrans()) { + // for xtrans files dcraw stores black levels in cblack[6] .. cblack[41], but all are equal, so we just use cblack[6] + for (int c = 0; c < 4; c++) { + cblack_[c] = (float) this->get_cblack(6); + pre_mul_[c] = this->get_pre_mul(c); + } + } else { + for (int c = 0; c < 4; c++) { + cblack_[c] = (float) this->get_cblack(c); + pre_mul_[c] = this->get_pre_mul(c); + } + } -#pragma omp for nowait - for (int row = 0; row < H; row += 8) - for (int col = 0; col < W ; col += 8) { - memset(sum, 0, sizeof sum); - for (int y = row; y < row + 8 && y < H; y++) - for (int x = col; x < col + 8 && x < W; x++) { - int c = XTRANSFC(y, x); - float val = data[y][x]; - if (val > whitefloat[c]) - goto skip_block3; - if ((val -= cblack_[c]) < 0) - val = 0; - sum[c] += val; - sum[c + 4]++; - } - for (int c = 0; c < 8; c++) - dsumthr[c] += sum[c]; -skip_block3: ; - } -#pragma omp critical -{ - for (int c = 0; c < 8; c++) - dsum[c] += dsumthr[c]; + if ( this->get_cam_mul(0) == -1 || forceAutoWB) { + memset(dsum, 0, sizeof dsum); -} -} - } else if (colors == 1) { - for (int c = 0; c < 4; c++) - pre_mul_[c] = 1; - } else { - for (row = 0; row < H; row += 8) - for (col = 0; col < W ; col += 8) { - memset(sum, 0, sizeof sum); - for (y = row; y < row + 8 && y < H; y++) - for (x = col; x < col + 8 && x < W; x++) - for (int c = 0; c < 3; c++) { - if (this->isBayer()) { - c = FC(y, x); - val = data[y][x]; - } else - val = data[y][3*x+c]; - if (val > this->get_white(c) - 25) - goto skip_block; - if ((val -= cblack_[c]) < 0) - val = 0; - sum[c] += val; - sum[c + 4]++; - if ( this->isBayer()) - break; - } - for (c = 0; c < 8; c++) - dsum[c] += sum[c]; -skip_block: ; - } - } - for (int c = 0; c < 4; c++) - if (dsum[c]) - pre_mul_[c] = dsum[c + 4] / dsum[c]; - }else{ - memset(sum, 0, sizeof sum); - for (row = 0; row < 8; row++) - for (col = 0; col < 8; col++) { - int c = FC(row, col); - if ((val = white[row][col] - cblack_[c]) > 0) - sum[c] += val; - sum[c + 4]++; - } - if (sum[0] && sum[1] && sum[2] && sum[3]) - for (int c = 0; c < 4; c++) - pre_mul_[c] = (float) sum[c + 4] / sum[c]; - else if (this->get_cam_mul(0) && this->get_cam_mul(2)){ - pre_mul_[0] = this->get_cam_mul(0); - pre_mul_[1] = this->get_cam_mul(1); - pre_mul_[2] = this->get_cam_mul(2); - pre_mul_[3] = this->get_cam_mul(3); - }else - fprintf(stderr, "Cannot use camera white balance.\n"); - } - if (pre_mul_[3] == 0) - pre_mul_[3] = this->get_colors() < 4 ? pre_mul_[1] : 1; - else if (this->get_colors() < 4) - pre_mul_[3] = pre_mul_[1] = (pre_mul_[3] + pre_mul_[1]) / 2; + if (this->isBayer()) { + // calculate number of pixels per color + dsum[FC(0, 0) + 4] += (int)(((W + 1) / 2) * ((H + 1) / 2)); + dsum[FC(0, 1) + 4] += (int)(((W / 2) * ((H + 1) / 2))); + dsum[FC(1, 0) + 4] += (int)(((W + 1) / 2) * (H / 2)); + dsum[FC(1, 1) + 4] += (int)((W / 2) * (H / 2)); - if (colors == 1) - for (c = 1; c < 4; c++) - cblack_[c] = cblack_[0]; + #pragma omp parallel private(val,row,col,x,y) + { + double dsumthr[8]; + memset(dsumthr, 0, sizeof dsumthr); + float sum[4]; + // make local copies of the black and white values to avoid calculations and conversions + float cblackfloat[4]; + float whitefloat[4]; - bool multiple_whites = false; - int largest_white = this->get_white(0); - for (c = 1; c < 4; c++) { - if (this->get_white(c) != this->get_white(0)) { - multiple_whites = true; - if (this->get_white(c) > largest_white) { - largest_white = this->get_white(c); - } - } - } - if (multiple_whites) { - // dcraw's pre_mul/cam_mul expects a single white, so if we have provided multiple whites we need - // to adapt scaling to avoid color shifts. - for (c = 0; c < 4; c++) { - // we don't really need to do the largest_white division but do so just to keep pre_mul in similar - // range as before adjustment so they don't look strangely large if someone would print them - pre_mul_[c] *= (float)this->get_white(c) / largest_white; - } - } + for (int c = 0; c < 4; c++) { + cblackfloat[c] = cblack_[c]; + whitefloat[c] = this->get_white(c) - 25; + } - for (dmin = DBL_MAX, dmax = c = 0; c < 4; c++) { - if (dmin > pre_mul_[c]) - dmin = pre_mul_[c]; - if (dmax < pre_mul_[c]) - dmax = pre_mul_[c]; - } + float *tempdata = data[0]; + #pragma omp for nowait - for (c = 0; c < 4; c++) { - int sat = this->get_white(c) - cblack_[c]; - scale_mul_[c] = (pre_mul_[c] /= dmax) * 65535.0 / sat; - } - if (settings->verbose) { - float asn[4] = { 1/cam_mul[0], 1/cam_mul[1], 1/cam_mul[2], 1/cam_mul[3] }; - for (dmax = c = 0; c < 4; c++) { - if (cam_mul[c] == 0) asn[c] = 0; - if (asn[c] > dmax) dmax = asn[c]; - } - for (c = 0; c < 4; c++) asn[c] /= dmax; - printf("cam_mul:[%f %f %f %f], AsShotNeutral:[%f %f %f %f]\n", - cam_mul[0], cam_mul[1], cam_mul[2], cam_mul[3], asn[0], asn[1], asn[2], asn[3]); - printf("pre_mul:[%f %f %f %f], scale_mul:[%f %f %f %f], cblack:[%f %f %f %f]\n", - pre_mul_[0], pre_mul_[1], pre_mul_[2], pre_mul_[3], - scale_mul_[0], scale_mul_[1], scale_mul_[2], scale_mul_[3], - cblack_[0], cblack_[1], cblack_[2], cblack_[3]); - printf("rgb_cam:[ [ %f %f %f], [%f %f %f], [%f %f %f] ]%s\n", - rgb_cam[0][0], rgb_cam[1][0], rgb_cam[2][0], - rgb_cam[0][1], rgb_cam[1][1], rgb_cam[2][1], - rgb_cam[0][2], rgb_cam[1][2], rgb_cam[2][2], - (!this->isBayer()) ? " (not bayer)" : ""); + for (row = 0; row < H; row += 8) { + int ymax = row + 8 < H ? row + 8 : H; - } + for (col = 0; col < W ; col += 8) { + int xmax = col + 8 < W ? col + 8 : W; + memset(sum, 0, sizeof sum); + + for (y = row; y < ymax; y++) + for (x = col; x < xmax; x++) { + int c = FC(y, x); + val = tempdata[y * W + x]; + + if (val > whitefloat[c]) { // calculate number of pixels to be substracted from sum and skip the block + dsumthr[FC(row, col) + 4] += (int)(((xmax - col + 1) / 2) * ((ymax - row + 1) / 2)); + dsumthr[FC(row, col + 1) + 4] += (int)(((xmax - col) / 2) * ((ymax - row + 1) / 2)); + dsumthr[FC(row + 1, col) + 4] += (int)(((xmax - col + 1) / 2) * ((ymax - row) / 2)); + dsumthr[FC(row + 1, col + 1) + 4] += (int)(((xmax - col) / 2) * ((ymax - row) / 2)); + goto skip_block2; + } + + if (val < cblackfloat[c]) { + val = cblackfloat[c]; + } + + sum[c] += val; + } + + for (int c = 0; c < 4; c++) { + dsumthr[c] += sum[c]; + } + +skip_block2: + ; + } + } + + #pragma omp critical + { + for (int c = 0; c < 4; c++) { + dsum[c] += dsumthr[c]; + } + + for (int c = 4; c < 8; c++) { + dsum[c] -= dsumthr[c]; + } + + } + } + + for(int c = 0; c < 4; c++) { + dsum[c] -= cblack_[c] * dsum[c + 4]; + } + + } else if(isXtrans()) { + #pragma omp parallel + { + double dsumthr[8]; + memset(dsumthr, 0, sizeof dsumthr); + float sum[8]; + // make local copies of the black and white values to avoid calculations and conversions + float whitefloat[4]; + + for (int c = 0; c < 4; c++) + { + whitefloat[c] = this->get_white(c) - 25; + } + + #pragma omp for nowait + + for (int row = 0; row < H; row += 8) + for (int col = 0; col < W ; col += 8) + { + memset(sum, 0, sizeof sum); + + for (int y = row; y < row + 8 && y < H; y++) + for (int x = col; x < col + 8 && x < W; x++) { + int c = XTRANSFC(y, x); + float val = data[y][x]; + + if (val > whitefloat[c]) { + goto skip_block3; + } + + if ((val -= cblack_[c]) < 0) { + val = 0; + } + + sum[c] += val; + sum[c + 4]++; + } + + for (int c = 0; c < 8; c++) { + dsumthr[c] += sum[c]; + } + +skip_block3: + ; + } + + #pragma omp critical + { + for (int c = 0; c < 8; c++) + { + dsum[c] += dsumthr[c]; + } + + } + } + } else if (colors == 1) { + for (int c = 0; c < 4; c++) { + pre_mul_[c] = 1; + } + } else { + for (row = 0; row < H; row += 8) + for (col = 0; col < W ; col += 8) { + memset(sum, 0, sizeof sum); + + for (y = row; y < row + 8 && y < H; y++) + for (x = col; x < col + 8 && x < W; x++) + for (int c = 0; c < 3; c++) { + if (this->isBayer()) { + c = FC(y, x); + val = data[y][x]; + } else { + val = data[y][3 * x + c]; + } + + if (val > this->get_white(c) - 25) { + goto skip_block; + } + + if ((val -= cblack_[c]) < 0) { + val = 0; + } + + sum[c] += val; + sum[c + 4]++; + + if ( this->isBayer()) { + break; + } + } + + for (c = 0; c < 8; c++) { + dsum[c] += sum[c]; + } + +skip_block: + ; + } + } + + for (int c = 0; c < 4; c++) + if (dsum[c]) { + pre_mul_[c] = dsum[c + 4] / dsum[c]; + } + } else { + memset(sum, 0, sizeof sum); + + for (row = 0; row < 8; row++) + for (col = 0; col < 8; col++) { + int c = FC(row, col); + + if ((val = white[row][col] - cblack_[c]) > 0) { + sum[c] += val; + } + + sum[c + 4]++; + } + + if (sum[0] && sum[1] && sum[2] && sum[3]) + for (int c = 0; c < 4; c++) { + pre_mul_[c] = (float) sum[c + 4] / sum[c]; + } + else if (this->get_cam_mul(0) && this->get_cam_mul(2)) { + pre_mul_[0] = this->get_cam_mul(0); + pre_mul_[1] = this->get_cam_mul(1); + pre_mul_[2] = this->get_cam_mul(2); + pre_mul_[3] = this->get_cam_mul(3); + } else { + fprintf(stderr, "Cannot use camera white balance.\n"); + } + } + + if (pre_mul_[3] == 0) { + pre_mul_[3] = this->get_colors() < 4 ? pre_mul_[1] : 1; + } else if (this->get_colors() < 4) { + pre_mul_[3] = pre_mul_[1] = (pre_mul_[3] + pre_mul_[1]) / 2; + } + + if (colors == 1) + for (c = 1; c < 4; c++) { + cblack_[c] = cblack_[0]; + } + + bool multiple_whites = false; + int largest_white = this->get_white(0); + + for (c = 1; c < 4; c++) { + if (this->get_white(c) != this->get_white(0)) { + multiple_whites = true; + + if (this->get_white(c) > largest_white) { + largest_white = this->get_white(c); + } + } + } + + if (multiple_whites) { + // dcraw's pre_mul/cam_mul expects a single white, so if we have provided multiple whites we need + // to adapt scaling to avoid color shifts. + for (c = 0; c < 4; c++) { + // we don't really need to do the largest_white division but do so just to keep pre_mul in similar + // range as before adjustment so they don't look strangely large if someone would print them + pre_mul_[c] *= (float)this->get_white(c) / largest_white; + } + } + + for (dmin = DBL_MAX, dmax = c = 0; c < 4; c++) { + if (dmin > pre_mul_[c]) { + dmin = pre_mul_[c]; + } + + if (dmax < pre_mul_[c]) { + dmax = pre_mul_[c]; + } + } + + for (c = 0; c < 4; c++) { + int sat = this->get_white(c) - cblack_[c]; + scale_mul_[c] = (pre_mul_[c] /= dmax) * 65535.0 / sat; + } + + if (settings->verbose) { + float asn[4] = { 1 / cam_mul[0], 1 / cam_mul[1], 1 / cam_mul[2], 1 / cam_mul[3] }; + + for (dmax = c = 0; c < 4; c++) { + if (cam_mul[c] == 0) { + asn[c] = 0; + } + + if (asn[c] > dmax) { + dmax = asn[c]; + } + } + + for (c = 0; c < 4; c++) { + asn[c] /= dmax; + } + + printf("cam_mul:[%f %f %f %f], AsShotNeutral:[%f %f %f %f]\n", + cam_mul[0], cam_mul[1], cam_mul[2], cam_mul[3], asn[0], asn[1], asn[2], asn[3]); + printf("pre_mul:[%f %f %f %f], scale_mul:[%f %f %f %f], cblack:[%f %f %f %f]\n", + pre_mul_[0], pre_mul_[1], pre_mul_[2], pre_mul_[3], + scale_mul_[0], scale_mul_[1], scale_mul_[2], scale_mul_[3], + cblack_[0], cblack_[1], cblack_[2], cblack_[3]); + printf("rgb_cam:[ [ %f %f %f], [%f %f %f], [%f %f %f] ]%s\n", + rgb_cam[0][0], rgb_cam[1][0], rgb_cam[2][0], + rgb_cam[0][1], rgb_cam[1][1], rgb_cam[2][1], + rgb_cam[0][2], rgb_cam[1][2], rgb_cam[2][2], + (!this->isBayer()) ? " (not bayer)" : ""); + + } } int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistener, double progressRange) { - ifname = filename.c_str(); - image = NULL; - verbose = settings->verbose; - oprof = NULL; + ifname = filename.c_str(); + image = NULL; + verbose = settings->verbose; + oprof = NULL; - ifp = gfopen (ifname); // Maps to either file map or direct fopen - if (!ifp) return 3; - imfile_set_plistener(ifp, plistener, 0.9 * progressRange); + ifp = gfopen (ifname); // Maps to either file map or direct fopen - thumb_length = 0; - thumb_offset = 0; - thumb_load_raw = 0; - use_camera_wb = 0; - highlight = 1; - half_size = 0; - raw_image = 0; - - //***************** Read ALL raw file info - identify (); - if (!is_raw) { - fclose(ifp); - ifp=NULL; - if (plistener) { - plistener->setProgress(1.0 * progressRange); + if (!ifp) { + return 3; } - return 2; - } - if (flip==5) - this->rotate_deg = 270; - else if (flip==3) - this->rotate_deg = 180; - else if (flip==6) - this->rotate_deg = 90; - else if (flip % 90 == 0 && flip < 360) - this->rotate_deg = flip; - else - this->rotate_deg = 0; + imfile_set_plistener(ifp, plistener, 0.9 * progressRange); - if( loadData ){ + thumb_length = 0; + thumb_offset = 0; + thumb_load_raw = 0; + use_camera_wb = 0; + highlight = 1; + half_size = 0; + raw_image = 0; - use_camera_wb = 1; - shrink = 0; - if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, filename.c_str()); - iheight = height; - iwidth = width; + //***************** Read ALL raw file info + identify (); - if (filters || colors == 1) { - raw_image = (ushort *) calloc ((raw_height+7)*raw_width, 2); - merror (raw_image, "main()"); - } + if (!is_raw) { + fclose(ifp); + ifp = NULL; - // dcraw needs this global variable to hold pixel data - image = (dcrawImage_t)calloc (height*width*sizeof *image + meta_length, 1); - meta_data = (char *) (image + height*width); - if(!image) - return 200; -/* Issue 2467 - if (setjmp (failure)) { - if (image) { free (image); image=NULL; } - if (raw_image) { free(raw_image); raw_image=NULL; } - fclose(ifp); ifp=NULL; - return 100; - } -*/ - // Load raw pixels data - fseek (ifp, data_offset, SEEK_SET); - (this->*load_raw)(); - if (plistener) { - plistener->setProgress(0.9 * progressRange); - } + if (plistener) { + plistener->setProgress(1.0 * progressRange); + } - CameraConstantsStore* ccs = CameraConstantsStore::getInstance(); - CameraConst *cc = ccs->get(make, model); + return 2; + } - if (raw_image) { - if (cc && cc->has_rawCrop()) { - int lm, tm, w, h; - cc->get_rawCrop(lm, tm, w, h); - if(((int)top_margin - tm) & 1) // we have an odd border difference - filters = (filters << 4) | (filters >> 28); // left rotate filters by 4 bits - left_margin = lm; - top_margin = tm; - if (w < 0) { - iwidth += w; - iwidth -= left_margin; - width += w; - width -= left_margin; - } else if (w > 0) { - iwidth = width = min((int)width,w); - } - if (h < 0) { - iheight += h; - iheight -= top_margin; - height += h; - height -= top_margin; - } else if (h > 0) { - iheight = height = min((int)height,h); - } - } - if (cc && cc->has_rawMask(0)) { - for (int i = 0; i < 8 && cc->has_rawMask(i); i++) { - cc->get_rawMask(i, mask[i][0], mask[i][1], mask[i][2], mask[i][3]); - } - } - crop_masked_pixels(); - free (raw_image); - raw_image=NULL; - } else { - if (cc && cc->has_rawCrop()) { // foveon images - int lm, tm, w, h; - cc->get_rawCrop(lm, tm, w, h); - left_margin = lm; - top_margin = tm; - if (w < 0) { - width += w; - width -= left_margin; - } else if (w > 0) { - width = min((int)width,w); - } - if (h < 0) { - height += h; - height -= top_margin; - } else if (h > 0) { - height = min((int)height,h); - } - } - } + if (flip == 5) { + this->rotate_deg = 270; + } else if (flip == 3) { + this->rotate_deg = 180; + } else if (flip == 6) { + this->rotate_deg = 90; + } else if (flip % 90 == 0 && flip < 360) { + this->rotate_deg = flip; + } else { + this->rotate_deg = 0; + } - // Load embedded profile - if (profile_length) { - profile_data = new char[profile_length]; - fseek ( ifp, profile_offset, SEEK_SET); - fread ( profile_data, 1, profile_length, ifp); - } + if( loadData ) { - /* - Setting the black level, there are three sources: - dcraw single value 'black' or multi-value 'cblack', can be calculated or come - from a hard-coded table or come from a stored value in the raw file, and - finally there's 'black_c4' which are table values provided by RT camera constants. - Any of these may or may not be set. + use_camera_wb = 1; + shrink = 0; - We reduce these sources to one four channel black level, and do this by picking - the highest found. - */ - int black_c4[4] = { -1, -1, -1, -1 }; + if (settings->verbose) { + printf ("Loading %s %s image from %s...\n", make, model, filename.c_str()); + } - bool white_from_cc = false; - bool black_from_cc = false; - if (cc) { - for (int i = 0; i < 4; i++) { + iheight = height; + iwidth = width; + + if (filters || colors == 1) { + raw_image = (ushort *) calloc ((raw_height + 7) * raw_width, 2); + merror (raw_image, "main()"); + } + + // dcraw needs this global variable to hold pixel data + image = (dcrawImage_t)calloc (height * width * sizeof * image + meta_length, 1); + meta_data = (char *) (image + height * width); + + if(!image) { + return 200; + } + + /* Issue 2467 + if (setjmp (failure)) { + if (image) { free (image); image=NULL; } + if (raw_image) { free(raw_image); raw_image=NULL; } + fclose(ifp); ifp=NULL; + return 100; + } + */ + // Load raw pixels data + fseek (ifp, data_offset, SEEK_SET); + (this->*load_raw)(); + + if (plistener) { + plistener->setProgress(0.9 * progressRange); + } + + CameraConstantsStore* ccs = CameraConstantsStore::getInstance(); + CameraConst *cc = ccs->get(make, model); + + if (raw_image) { + if (cc && cc->has_rawCrop()) { + int lm, tm, w, h; + cc->get_rawCrop(lm, tm, w, h); + + if(((int)top_margin - tm) & 1) { // we have an odd border difference + filters = (filters << 4) | (filters >> 28); // left rotate filters by 4 bits + } + + left_margin = lm; + top_margin = tm; + + if (w < 0) { + iwidth += w; + iwidth -= left_margin; + width += w; + width -= left_margin; + } else if (w > 0) { + iwidth = width = min((int)width, w); + } + + if (h < 0) { + iheight += h; + iheight -= top_margin; + height += h; + height -= top_margin; + } else if (h > 0) { + iheight = height = min((int)height, h); + } + } + + if (cc && cc->has_rawMask(0)) { + for (int i = 0; i < 8 && cc->has_rawMask(i); i++) { + cc->get_rawMask(i, mask[i][0], mask[i][1], mask[i][2], mask[i][3]); + } + } + + crop_masked_pixels(); + free (raw_image); + raw_image = NULL; + } else { + if (cc && cc->has_rawCrop()) { // foveon images + int lm, tm, w, h; + cc->get_rawCrop(lm, tm, w, h); + left_margin = lm; + top_margin = tm; + + if (w < 0) { + width += w; + width -= left_margin; + } else if (w > 0) { + width = min((int)width, w); + } + + if (h < 0) { + height += h; + height -= top_margin; + } else if (h > 0) { + height = min((int)height, h); + } + } + } + + // Load embedded profile + if (profile_length) { + profile_data = new char[profile_length]; + fseek ( ifp, profile_offset, SEEK_SET); + fread ( profile_data, 1, profile_length, ifp); + } + + /* + Setting the black level, there are three sources: + dcraw single value 'black' or multi-value 'cblack', can be calculated or come + from a hard-coded table or come from a stored value in the raw file, and + finally there's 'black_c4' which are table values provided by RT camera constants. + Any of these may or may not be set. + + We reduce these sources to one four channel black level, and do this by picking + the highest found. + */ + int black_c4[4] = { -1, -1, -1, -1 }; + + bool white_from_cc = false; + bool black_from_cc = false; + + if (cc) { + for (int i = 0; i < 4; i++) { if (RT_blacklevel_from_constant) { black_c4[i] = cblack[i] + cc->get_BlackLevel(i, iso_speed); } + // load 4 channel white level here, will be used if available if (RT_whitelevel_from_constant) { maximum_c4[i] = cc->get_WhiteLevel(i, iso_speed, aperture); + if(tiff_bps > 0 && maximum_c4[i] > 0 && !isFoveon()) { unsigned compare = ((uint64_t)1 << tiff_bps) - 1; // use uint64_t to avoid overflow if tiff_bps == 32 - while(maximum_c4[i] > compare) + + while(maximum_c4[i] > compare) { maximum_c4[i] >>= 1; + } } } - } - } - if (black_c4[0] == -1) { - if(isXtrans()) - for (int c=0; c < 4; c++) black_c4[c] = cblack[6]; - else - // RT constants not set, bring in the DCRAW single channel black constant - for (int c=0; c < 4; c++) black_c4[c] = black + cblack[c]; - } else { - black_from_cc = true; - } - if (maximum_c4[0] > 0) { - white_from_cc = true; - } - for (int c=0; c < 4; c++) { - if (cblack[c] < black_c4[c]) { - cblack[c] = black_c4[c]; - } - } - if (settings->verbose) { - if (cc) { - printf("constants exists for \"%s %s\" in camconst.json\n", make, model); - } else { - printf("no constants in camconst.json exists for \"%s %s\" (relying only on dcraw defaults)\n", make, model); - } - printf("black levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_cblack(0), get_cblack(1), get_cblack(2), get_cblack(3), - black_from_cc ? "provided by camconst.json" : "provided by dcraw"); - printf("white levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_white(0), get_white(1), get_white(2), get_white(3), - white_from_cc ? "provided by camconst.json" : "provided by dcraw"); - printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, (cc && cc->has_rawCrop()) ? "camconst.json" : "dcraw"); - printf("color matrix provided by %s\n", (cc && cc->has_dcrawMatrix()) ? "camconst.json" : "dcraw"); - } - } + } + } - if ( closeFile ) { - fclose(ifp); ifp=NULL; - } - if (plistener) { - plistener->setProgress(1.0 * progressRange); - } + if (black_c4[0] == -1) { + if(isXtrans()) + for (int c = 0; c < 4; c++) { + black_c4[c] = cblack[6]; + } + else - return 0; + // RT constants not set, bring in the DCRAW single channel black constant + for (int c = 0; c < 4; c++) { + black_c4[c] = black + cblack[c]; + } + } else { + black_from_cc = true; + } + + if (maximum_c4[0] > 0) { + white_from_cc = true; + } + + for (int c = 0; c < 4; c++) { + if (cblack[c] < black_c4[c]) { + cblack[c] = black_c4[c]; + } + } + + if (settings->verbose) { + if (cc) { + printf("constants exists for \"%s %s\" in camconst.json\n", make, model); + } else { + printf("no constants in camconst.json exists for \"%s %s\" (relying only on dcraw defaults)\n", make, model); + } + + printf("black levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_cblack(0), get_cblack(1), get_cblack(2), get_cblack(3), + black_from_cc ? "provided by camconst.json" : "provided by dcraw"); + printf("white levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_white(0), get_white(1), get_white(2), get_white(3), + white_from_cc ? "provided by camconst.json" : "provided by dcraw"); + printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, (cc && cc->has_rawCrop()) ? "camconst.json" : "dcraw"); + printf("color matrix provided by %s\n", (cc && cc->has_dcrawMatrix()) ? "camconst.json" : "dcraw"); + } + } + + if ( closeFile ) { + fclose(ifp); + ifp = NULL; + } + + if (plistener) { + plistener->setProgress(1.0 * progressRange); + } + + return 0; } float** RawImage::compress_image() { - if( !image ) - return NULL; - if (isBayer() || isXtrans()) { - if (!allocation) { - allocation = new float[height * width]; - data = new float*[height]; - for (int i = 0; i < height; i++) - data[i] = allocation + i * width; - } - } else if (colors == 1) { - // Monochrome - if (!allocation) { - allocation = new float[height * width]; - data = new float*[height]; - for (int i = 0; i < height; i++) - data[i] = allocation + i * width; - } - } else { - if (!allocation) { - allocation = new float[3 * height * width]; - data = new float*[height]; - for (int i = 0; i < height; i++) - data[i] = allocation + 3 * i * width; - } - } + if( !image ) { + return NULL; + } + + if (isBayer() || isXtrans()) { + if (!allocation) { + allocation = new float[height * width]; + data = new float*[height]; + + for (int i = 0; i < height; i++) { + data[i] = allocation + i * width; + } + } + } else if (colors == 1) { + // Monochrome + if (!allocation) { + allocation = new float[height * width]; + data = new float*[height]; + + for (int i = 0; i < height; i++) { + data[i] = allocation + i * width; + } + } + } else { + if (!allocation) { + allocation = new float[3 * height * width]; + data = new float*[height]; + + for (int i = 0; i < height; i++) { + data[i] = allocation + 3 * i * width; + } + } + } // copy pixel raw data: the compressed format earns space if( float_raw_image ) { #pragma omp parallel for + for (int row = 0; row < height; row++) - for (int col = 0; col < width; col++) + for (int col = 0; col < width; col++) { this->data[row][col] = float_raw_image[(row + top_margin) * raw_width + col + left_margin]; - delete [] float_raw_image; + } + + delete [] float_raw_image; float_raw_image = NULL; } else if (filters != 0 && !isXtrans()) { #pragma omp parallel for - for (int row = 0; row < height; row++) - for (int col = 0; col < width; col++) - this->data[row][col] = image[row * width + col][FC(row, col)]; - } else if (isXtrans()) { + + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + this->data[row][col] = image[row * width + col][FC(row, col)]; + } + } else if (isXtrans()) { #pragma omp parallel for - for (int row = 0; row < height; row++) - for (int col = 0; col < width; col++) - this->data[row][col] = image[row * width + col][XTRANSFC(row, col)]; - } else if (colors == 1) { + + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + this->data[row][col] = image[row * width + col][XTRANSFC(row, col)]; + } + } else if (colors == 1) { #pragma omp parallel for - for (int row = 0; row < height; row++) - for (int col = 0; col < width; col++) - this->data[row][col] = image[row * width + col][0]; - } else { + + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + this->data[row][col] = image[row * width + col][0]; + } + } else { #pragma omp parallel for - for (int row = 0; row < height; row++) - for (int col = 0; col < width; col++) { - this->data[row][3 * col + 0] = image[(row+top_margin) * iwidth + col+left_margin][0]; - this->data[row][3 * col + 1] = image[(row+top_margin) * iwidth + col+left_margin][1]; - this->data[row][3 * col + 2] = image[(row+top_margin) * iwidth + col+left_margin][2]; - } - } - free(image); // we don't need this anymore - image=NULL; + + for (int row = 0; row < height; row++) + for (int col = 0; col < width; col++) { + this->data[row][3 * col + 0] = image[(row + top_margin) * iwidth + col + left_margin][0]; + this->data[row][3 * col + 1] = image[(row + top_margin) * iwidth + col + left_margin][1]; + this->data[row][3 * col + 2] = image[(row + top_margin) * iwidth + col + left_margin][2]; + } + } + + free(image); // we don't need this anymore + image = NULL; return data; } -bool -RawImage::is_supportedThumb() const +bool +RawImage::is_supportedThumb() const { return ( (thumb_width * thumb_height) > 0 && - ( write_thumb == &rtengine::RawImage::jpeg_thumb || - write_thumb == &rtengine::RawImage::ppm_thumb) && - !thumb_load_raw ); + ( write_thumb == &rtengine::RawImage::jpeg_thumb || + write_thumb == &rtengine::RawImage::ppm_thumb) && + !thumb_load_raw ); } void RawImage::getXtransMatrix( char XtransMatrix[6][6]) { - for(int row=0;row<6;row++) - for(int col=0;col<6;col++) - XtransMatrix[row][col] = xtrans[row][col]; + for(int row = 0; row < 6; row++) + for(int col = 0; col < 6; col++) { + XtransMatrix[row][col] = xtrans[row][col]; + } } void RawImage::getRgbCam (float rgbcam[3][4]) { - for(int row=0;row<3;row++) - for(int col=0;col<4;col++) - rgbcam[row][col] = rgb_cam[row][col]; - + for(int row = 0; row < 3; row++) + for(int col = 0; col < 4; col++) { + rgbcam[row][col] = rgb_cam[row][col]; + } + } -bool +bool RawImage::get_thumbSwap() const { - return ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) ? true : false; + return ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) ? true : false; } } //namespace rtengine @@ -611,130 +778,232 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is short trans[12]; // set first value to 0 for no change } table[] = { - { "Canon EOS 5D Mark III", -1, 0x3a98, /* RT */ - { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } }, - { "Canon EOS 5D", -1, 0xe6c, /* RT */ - { 6319,-793,-614,-5809,13342,2738,-1132,1559,7971 } }, - { "Canon EOS 6D", -1, 0x3c82, - { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, - { "Canon EOS 7D", -1, 0x3510, /* RT - Colin Walker */ - { 5962,-171,-732,-4189,12307,2099,-911,1981,6304 } }, - { "Canon EOS 20D", -1, 0xfff, /* RT */ - { 7590,-1646,-673,-4697,12411,2568,-627,1118,7295 } }, - { "Canon EOS 40D", -1, 0x3f60, /* RT */ - { 6070,-531,-883,-5763,13647,2315,-1533,2582,6801 } }, - { "Canon EOS 60D", -1, 0x2ff7, /* RT - Colin Walker */ - { 5678,-179,-718,-4389,12381,2243,-869,1819,6380 } }, - { "Canon EOS 450D", -1, 0x390d, /* RT */ - { 6246,-1272,-523,-5075,12357,3075,-1035,1825,7333 } }, - { "Canon EOS 550D", -1, 0x3dd7, /* RT - Lebedev*/ - { 6519,-772,-703,-4994,12737,2519,-1387,2492,6175 } }, - { "Canon EOS-1D Mark III", 0, 0x3bb0, /* RT */ - { 7406,-1592,-646,-4856,12457,2698,-432,726,7921 } }, - { "Canon PowerShot G10", -1, -1, /* RT */ - { 12535,-5030,-796,-2711,10134,3006,-413,1605,5264 } }, - { "Canon PowerShot G12", -1, -1, /* RT */ - { 12222,-4097,-1380,-2876,11016,2130,-888,1630,4434 } }, + { + "Canon EOS 5D Mark III", -1, 0x3a98, /* RT */ + { 6722, -635, -963, -4287, 12460, 2028, -908, 2162, 5668 } + }, + { + "Canon EOS 5D", -1, 0xe6c, /* RT */ + { 6319, -793, -614, -5809, 13342, 2738, -1132, 1559, 7971 } + }, + { + "Canon EOS 6D", -1, 0x3c82, + { 7034, -804, -1014, -4420, 12564, 2058, -851, 1994, 5758 } + }, + { + "Canon EOS 7D", -1, 0x3510, /* RT - Colin Walker */ + { 5962, -171, -732, -4189, 12307, 2099, -911, 1981, 6304 } + }, + { + "Canon EOS 20D", -1, 0xfff, /* RT */ + { 7590, -1646, -673, -4697, 12411, 2568, -627, 1118, 7295 } + }, + { + "Canon EOS 40D", -1, 0x3f60, /* RT */ + { 6070, -531, -883, -5763, 13647, 2315, -1533, 2582, 6801 } + }, + { + "Canon EOS 60D", -1, 0x2ff7, /* RT - Colin Walker */ + { 5678, -179, -718, -4389, 12381, 2243, -869, 1819, 6380 } + }, + { + "Canon EOS 450D", -1, 0x390d, /* RT */ + { 6246, -1272, -523, -5075, 12357, 3075, -1035, 1825, 7333 } + }, + { + "Canon EOS 550D", -1, 0x3dd7, /* RT - Lebedev*/ + { 6519, -772, -703, -4994, 12737, 2519, -1387, 2492, 6175 } + }, + { + "Canon EOS-1D Mark III", 0, 0x3bb0, /* RT */ + { 7406, -1592, -646, -4856, 12457, 2698, -432, 726, 7921 } + }, + { + "Canon PowerShot G10", -1, -1, /* RT */ + { 12535, -5030, -796, -2711, 10134, 3006, -413, 1605, 5264 } + }, + { + "Canon PowerShot G12", -1, -1, /* RT */ + { 12222, -4097, -1380, -2876, 11016, 2130, -888, 1630, 4434 } + }, - { "Fujifilm X100", -1, -1, /* RT - Colin Walker */ - { 10841,-3288,-807,-4652,12552,2344,-642,1355,7206 } }, + { + "Fujifilm X100", -1, -1, /* RT - Colin Walker */ + { 10841, -3288, -807, -4652, 12552, 2344, -642, 1355, 7206 } + }, - { "Nikon D200", -1, 0xfbc, /* RT */ - { 8498,-2633,-295,-5423,12869,2860,-777,1077,8124 } }, - { "Nikon D3000", -1, -1, /* RT */ - { 9211,-2521,-104,-6487,14280,2394,-754,1122,8033 } }, - { "Nikon D3100", -1, -1, /* RT */ - { 7729,-2212,-481,-5709,13148,2858,-1295,1908,8936 } }, - { "Nikon D3S", -1, -1, /* RT */ - { 8792,-2663,-344,-5221,12764,2752,-1491,2165,8121 } }, - { "Nikon D5200", -1, -1, // color matrix copied from D5200 DNG D65 matrix - { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, - { "Nikon D7000", -1, -1, /* RT - Tanveer(tsk1979) */ - { 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 } }, - { "Nikon D7100", -1, -1, // color matrix and WP copied from D7100 DNG D65 matrix - { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, - { "Nikon D700", -1, -1, /* RT */ - { 8364,-2503,-352,-6307,14026,2492,-1134,1512,8156 } }, - { "Nikon COOLPIX A", -1, 0x3e00, // color matrix and WP copied from "COOLPIX A" DNG D65 matrix - { 8198,-2239,-724,-4871,12389,2798,-1043,205,7181 } }, + { + "Nikon D200", -1, 0xfbc, /* RT */ + { 8498, -2633, -295, -5423, 12869, 2860, -777, 1077, 8124 } + }, + { + "Nikon D3000", -1, -1, /* RT */ + { 9211, -2521, -104, -6487, 14280, 2394, -754, 1122, 8033 } + }, + { + "Nikon D3100", -1, -1, /* RT */ + { 7729, -2212, -481, -5709, 13148, 2858, -1295, 1908, 8936 } + }, + { + "Nikon D3S", -1, -1, /* RT */ + { 8792, -2663, -344, -5221, 12764, 2752, -1491, 2165, 8121 } + }, + { + "Nikon D5200", -1, -1, // color matrix copied from D5200 DNG D65 matrix + { 8322, -3112, -1047, -6367, 14342, 2179, -988, 1638, 6394 } + }, + { + "Nikon D7000", -1, -1, /* RT - Tanveer(tsk1979) */ + { 7530, -1942, -255, -4318, 11390, 3362, -926, 1694, 7649 } + }, + { + "Nikon D7100", -1, -1, // color matrix and WP copied from D7100 DNG D65 matrix + { 8322, -3112, -1047, -6367, 14342, 2179, -988, 1638, 6394 } + }, + { + "Nikon D700", -1, -1, /* RT */ + { 8364, -2503, -352, -6307, 14026, 2492, -1134, 1512, 8156 } + }, + { + "Nikon COOLPIX A", -1, 0x3e00, // color matrix and WP copied from "COOLPIX A" DNG D65 matrix + { 8198, -2239, -724, -4871, 12389, 2798, -1043, 205, 7181 } + }, - { "Olympus E-30", -1, 0xfbc, /* RT - Colin Walker */ - { 8510,-2355,-693,-4819,12520,2578,-1029,2067,7752 } }, - { "Olympus E-5", -1, 0xeec, /* RT - Colin Walker */ - { 9732,-2629,-999,-4899,12931,2173,-1243,2353,7457 } }, - { "Olympus E-P1", -1, 0xffd, /* RT - Colin Walker */ - { 8834,-2344,-804,-4691,12503,2448,-978,1919,7603 } }, - { "Olympus E-P2", -1, 0xffd, /* RT - Colin Walker */ - { 7758,-1619,-800,-5002,12886,2349,-985,1964,8305 } }, - { "Olympus E-P3", -1, -1, /* RT - Colin Walker */ - { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, - { "Olympus E-PL1s", -1, -1, /* RT - Colin Walker */ - { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, - { "Olympus E-PL1", -1, -1, /* RT - Colin Walker */ - { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, - { "Olympus E-PL2", -1, -1, /* RT - Colin Walker */ - { 11975,-3351,-1184,-4500,12639,2061,-1230,2353,7009 } }, - { "Olympus E-PL3", -1, -1, /* RT - Colin Walker */ - { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, - { "Olympus XZ-1", -1, -1, /* RT - Colin Walker */ - { 8665,-2247,-762,-2424,10372,2382,-1011,2286,5189 } }, + { + "Olympus E-30", -1, 0xfbc, /* RT - Colin Walker */ + { 8510, -2355, -693, -4819, 12520, 2578, -1029, 2067, 7752 } + }, + { + "Olympus E-5", -1, 0xeec, /* RT - Colin Walker */ + { 9732, -2629, -999, -4899, 12931, 2173, -1243, 2353, 7457 } + }, + { + "Olympus E-P1", -1, 0xffd, /* RT - Colin Walker */ + { 8834, -2344, -804, -4691, 12503, 2448, -978, 1919, 7603 } + }, + { + "Olympus E-P2", -1, 0xffd, /* RT - Colin Walker */ + { 7758, -1619, -800, -5002, 12886, 2349, -985, 1964, 8305 } + }, + { + "Olympus E-P3", -1, -1, /* RT - Colin Walker */ + { 7041, -1794, -336, -3790, 11192, 2984, -1364, 2625, 6217 } + }, + { + "Olympus E-PL1s", -1, -1, /* RT - Colin Walker */ + { 9010, -2271, -838, -4792, 12753, 2263, -1059, 2058, 7589 } + }, + { + "Olympus E-PL1", -1, -1, /* RT - Colin Walker */ + { 9010, -2271, -838, -4792, 12753, 2263, -1059, 2058, 7589 } + }, + { + "Olympus E-PL2", -1, -1, /* RT - Colin Walker */ + { 11975, -3351, -1184, -4500, 12639, 2061, -1230, 2353, 7009 } + }, + { + "Olympus E-PL3", -1, -1, /* RT - Colin Walker */ + { 7041, -1794, -336, -3790, 11192, 2984, -1364, 2625, 6217 } + }, + { + "Olympus XZ-1", -1, -1, /* RT - Colin Walker */ + { 8665, -2247, -762, -2424, 10372, 2382, -1011, 2286, 5189 } + }, - /* since Dcraw_v9.21 Panasonic BlackLevel is read from exif (tags 0x001c BlackLevelRed, 0x001d BlackLevelGreen, 0x001e BlackLevelBlue - and we define here the needed offset of around 15. The total BL is BL + BLoffset (cblack + black) */ + /* since Dcraw_v9.21 Panasonic BlackLevel is read from exif (tags 0x001c BlackLevelRed, 0x001d BlackLevelGreen, 0x001e BlackLevelBlue + and we define here the needed offset of around 15. The total BL is BL + BLoffset (cblack + black) */ - { "Panasonic DMC-FZ150", 15, 0xfd2, /* RT */ - { 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 } }, - { "Panasonic DMC-G10", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */ - { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, - { "Panasonic DMC-G1", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */ - { 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 } }, - { "Panasonic DMC-G2", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */ - { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, - { "Panasonic DMC-G3", 15, 0xfdc, /* RT - Colin Walker - WL 4060 */ - { 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 } }, - { "Panasonic DMC-G5", 15, 0xfdc, /* RT - WL 4060 */ - { 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 } }, - { "Panasonic DMC-GF1", 15, 0xf50, /* RT - Colin Walker - Variable WL 3920 - 4080 */ - { 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 } }, - { "Panasonic DMC-GF2", 15, 0xfd2, /* RT - Colin Walker - WL 4050 */ - { 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 } }, - { "Panasonic DMC-GF3", 15, 0xfd2, /* RT - Colin Walker - WL 4050 */ - { 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 } }, - { "Panasonic DMC-GH1", 15, 0xf5a, /* RT - Colin Walker - variable WL 3930 - 4080 */ - { 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 } }, - { "Panasonic DMC-GH2", 15, 0xf5a, /* RT - Colin Walker - variable WL 3930 - 4080 */ + { + "Panasonic DMC-FZ150", 15, 0xfd2, /* RT */ + { 10435, -3208, -72, -2293, 10506, 2067, -486, 1725, 4682 } + }, + { + "Panasonic DMC-G10", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */ + { 8310, -1811, -960, -4941, 12990, 2151, -1378, 2468, 6860 } + }, + { + "Panasonic DMC-G1", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */ + { 7477, -1615, -651, -5016, 12769, 2506, -1380, 2475, 7240 } + }, + { + "Panasonic DMC-G2", 15, 0xf50, /* RT - Colin Walker - variable WL 3920 - 4080 */ + { 8310, -1811, -960, -4941, 12990, 2151, -1378, 2468, 6860 } + }, + { + "Panasonic DMC-G3", 15, 0xfdc, /* RT - Colin Walker - WL 4060 */ + { 6051, -1406, -671, -4015, 11505, 2868, -1654, 2667, 6219 } + }, + { + "Panasonic DMC-G5", 15, 0xfdc, /* RT - WL 4060 */ + { 7122, -2092, -419, -4643, 11769, 3283, -1363, 2413, 5944 } + }, + { + "Panasonic DMC-GF1", 15, 0xf50, /* RT - Colin Walker - Variable WL 3920 - 4080 */ + { 7863, -2080, -668, -4623, 12331, 2578, -1020, 2066, 7266 } + }, + { + "Panasonic DMC-GF2", 15, 0xfd2, /* RT - Colin Walker - WL 4050 */ + { 7694, -1791, -745, -4917, 12818, 2332, -1221, 2322, 7197 } + }, + { + "Panasonic DMC-GF3", 15, 0xfd2, /* RT - Colin Walker - WL 4050 */ + { 8074, -1846, -861, -5026, 12999, 2239, -1320, 2375, 7422 } + }, + { + "Panasonic DMC-GH1", 15, 0xf5a, /* RT - Colin Walker - variable WL 3930 - 4080 */ + { 6360, -1557, -375, -4201, 11504, 3086, -1378, 2518, 5843 } + }, + { + "Panasonic DMC-GH2", 15, 0xf5a, /* RT - Colin Walker - variable WL 3930 - 4080 */ // { 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 } }, disabled due to problems with underwater WB - { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, // dcraw original + { 7780, -2410, -806, -3913, 11724, 2484, -1018, 2390, 5298 } + }, // dcraw original - { "Pentax K200D", -1, -1, /* RT */ - { 10962,-4428,-542,-5486,13023,2748,-569,842,8390 } }, + { + "Pentax K200D", -1, -1, /* RT */ + { 10962, -4428, -542, -5486, 13023, 2748, -569, 842, 8390 } + }, - { "Leica Camera AG M9 Digital Camera", -1, -1, /* RT */ - { 7181,-1706,-55,-3557,11409,2450,-621,2072,7533 } }, + { + "Leica Camera AG M9 Digital Camera", -1, -1, /* RT */ + { 7181, -1706, -55, -3557, 11409, 2450, -621, 2072, 7533 } + }, - { "SONY NEX-3", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ - { 5145,-741,-123,-4915,12310,2945,-794,1489,6906 } }, - { "SONY NEX-5", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ - { 5154,-716,-115,-5065,12506,2882,-988,1715,6800 } }, - { "Sony NEX-5N", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ - { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, - { "Sony NEX-5R", 128 << dcraw_arw2_scaling_bugfix_shift, -1, - { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "SONY NEX-C3", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ - { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, - { "Sony SLT-A77", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ - { 5126,-830,-261,-4788,12196,2934,-948,1602,7068 } }, + { + "SONY NEX-3", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ + { 5145, -741, -123, -4915, 12310, 2945, -794, 1489, 6906 } + }, + { + "SONY NEX-5", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ + { 5154, -716, -115, -5065, 12506, 2882, -988, 1715, 6800 } + }, + { + "Sony NEX-5N", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ + { 5130, -1055, -269, -4473, 11797, 3050, -701, 1310, 7121 } + }, + { + "Sony NEX-5R", 128 << dcraw_arw2_scaling_bugfix_shift, -1, + { 6129, -1545, -418, -4930, 12490, 2743, -977, 1693, 6615 } + }, + { + "SONY NEX-C3", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ + { 5130, -1055, -269, -4473, 11797, 3050, -701, 1310, 7121 } + }, + { + "Sony SLT-A77", 128 << dcraw_arw2_scaling_bugfix_shift, -1, /* RT - Colin Walker */ + { 5126, -830, -261, -4788, 12196, 2934, -948, 1602, 7068 } + }, }; *black_level = -1; *white_level = -1; - memset(trans, 0, sizeof(*trans)*12); + memset(trans, 0, sizeof(*trans) * 12); // indicate that DCRAW wants these from constants (rather than having loaded these from RAW file // note: this is simplified so far, in some cases dcraw calls this when it has say the black level @@ -745,33 +1014,42 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is RT_blacklevel_from_constant = 1; RT_matrix_from_constant = 1; - { // test if we have any information in the camera constants store, if so we take that. + { + // test if we have any information in the camera constants store, if so we take that. rtengine::CameraConstantsStore* ccs = rtengine::CameraConstantsStore::getInstance(); rtengine::CameraConst *cc = ccs->get(make, model); + if (cc) { *black_level = cc->get_BlackLevel(0, iso_speed); *white_level = cc->get_WhiteLevel(0, iso_speed, aperture); + if (cc->has_dcrawMatrix()) { const short *mx = cc->get_dcrawMatrix(); + for (int j = 0; j < 12; j++) { trans[j] = mx[j]; } } + return true; } } char name[strlen(make) + strlen(model) + 32]; sprintf(name, "%s %s", make, model); + for (int i = 0; i < sizeof table / sizeof(table[0]); i++) { if (strcasecmp(name, table[i].prefix) == 0) { *black_level = table[i].black_level; *white_level = table[i].white_level; + for (int j = 0; j < 12; j++) { trans[j] = table[i].trans[j]; } + return true; } } + return false; } diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 4f7dae634..fcc615997 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -7,7 +7,7 @@ * 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 @@ -23,63 +23,75 @@ #include "dcraw.h" #include "imageio.h" -namespace rtengine { - -struct badPix +namespace rtengine { - uint16_t x; - uint16_t y; - badPix( uint16_t xc, uint16_t yc ):x(xc),y(yc){} + +struct badPix { + uint16_t x; + uint16_t y; + badPix( uint16_t xc, uint16_t yc ): x(xc), y(yc) {} }; -class PixelsMap{ - int w; // line width in base_t units - int h; // height - typedef unsigned long base_t; - static const size_t base_t_size=sizeof(base_t); - base_t *pm; +class PixelsMap +{ + int w; // line width in base_t units + int h; // height + typedef unsigned long base_t; + static const size_t base_t_size = sizeof(base_t); + base_t *pm; public: - PixelsMap(int width, int height ) - :h(height){ - w = (width+base_t_size-1) /base_t_size; - pm = new base_t [h * w ]; - memset(pm,0,h * w *base_t_size ); - } - ~PixelsMap(){ - delete [] pm; - } - int width() const { return w; } - int height() const { return h; } + PixelsMap(int width, int height ) + : h(height) + { + w = (width + base_t_size - 1) / base_t_size; + pm = new base_t [h * w ]; + memset(pm, 0, h * w * base_t_size ); + } + ~PixelsMap() + { + delete [] pm; + } + int width() const + { + return w; + } + int height() const + { + return h; + } - // if a pixel is set returns true - bool get(int x, int y) - { - return (pm[y*w+ x/(base_t_size*8) ] & (base_t)1<<(x%(base_t_size*8)) )!=0; - } + // if a pixel is set returns true + bool get(int x, int y) + { + return (pm[y * w + x / (base_t_size * 8) ] & (base_t)1 << (x % (base_t_size * 8)) ) != 0; + } - // set a pixel - void set(int x, int y) - { - pm[y*w+ x/(base_t_size*8) ] |= (base_t)1<<(x%(base_t_size*8)) ; - } + // set a pixel + void set(int x, int y) + { + pm[y * w + x / (base_t_size * 8) ] |= (base_t)1 << (x % (base_t_size * 8)) ; + } - // set pixels from a list - int set( std::vector &bp) - { - for(std::vector::iterator iter = bp.begin(); iter != bp.end(); ++iter) - set( iter->x,iter->y); + // set pixels from a list + int set( std::vector &bp) + { + for(std::vector::iterator iter = bp.begin(); iter != bp.end(); ++iter) { + set( iter->x, iter->y); + } - return bp.size(); - } + return bp.size(); + } - void clear(){ - memset(pm,0,h * w *base_t_size ); - } - // return 0 if at least one pixel in the word(base_t) is set, otherwise return the number of pixels to skip to the next word base_t - int skipIfZero(int x, int y){ - return pm[y*w+ x/(base_t_size*8) ]==0 ? base_t_size*8 -x%(base_t_size*8):0; - } + void clear() + { + memset(pm, 0, h * w * base_t_size ); + } + // return 0 if at least one pixel in the word(base_t) is set, otherwise return the number of pixels to skip to the next word base_t + int skipIfZero(int x, int y) + { + return pm[y * w + x / (base_t_size * 8) ] == 0 ? base_t_size * 8 - x % (base_t_size * 8) : 0; + } }; @@ -87,96 +99,257 @@ class RawImage: public DCraw { public: - RawImage( const Glib::ustring name ); - ~RawImage(); + RawImage( const Glib::ustring name ); + ~RawImage(); - int loadRaw (bool loadData=true, bool closeFile=true, ProgressListener *plistener=0, double progressRange=1.0); - void get_colorsCoeff( float* pre_mul_, float* scale_mul_, float* cblack_, bool forceAutoWB ); - void set_prefilters(){ - if (isBayer() && get_colors() == 3) { - prefilters = filters; - filters &= ~((filters & 0x55555555) << 1); - } - } - dcrawImage_t get_image() { return image; } - float** compress_image(); // revert to compressed pixels format and release image data - float** data; // holds pixel values, data[i][j] corresponds to the ith row and jth column - unsigned prefilters; // original filters saved ( used for 4 color processing ) + int loadRaw (bool loadData = true, bool closeFile = true, ProgressListener *plistener = 0, double progressRange = 1.0); + void get_colorsCoeff( float* pre_mul_, float* scale_mul_, float* cblack_, bool forceAutoWB ); + void set_prefilters() + { + if (isBayer() && get_colors() == 3) { + prefilters = filters; + filters &= ~((filters & 0x55555555) << 1); + } + } + dcrawImage_t get_image() + { + return image; + } + float** compress_image(); // revert to compressed pixels format and release image data + float** data; // holds pixel values, data[i][j] corresponds to the ith row and jth column + unsigned prefilters; // original filters saved ( used for 4 color processing ) protected: - Glib::ustring filename; // complete filename - int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif - char* profile_data; // Embedded ICC color profile - float* allocation; // pointer to allocated memory - int maximum_c4[4]; - bool isBayer() const { return (filters!=0 && filters!=9); } - bool isXtrans() const { return filters==9; } - bool isFoveon() const { return is_foveon; } + Glib::ustring filename; // complete filename + int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif + char* profile_data; // Embedded ICC color profile + float* allocation; // pointer to allocated memory + int maximum_c4[4]; + bool isBayer() const + { + return (filters != 0 && filters != 9); + } + bool isXtrans() const + { + return filters == 9; + } + bool isFoveon() const + { + return is_foveon; + } public: - static void initCameraConstants(Glib::ustring baseDir); - std::string get_filename() const { return filename;} - int get_width() const { return width; } - int get_height() const { return height; } - int get_iwidth() const { return iwidth; } - int get_iheight() const { return iheight; } - int get_leftmargin() const { return left_margin; } - int get_topmargin() const { return top_margin; } - int get_FujiWidth() const { return fuji_width; } - eSensorType getSensorType(); + static void initCameraConstants(Glib::ustring baseDir); + std::string get_filename() const + { + return filename; + } + int get_width() const + { + return width; + } + int get_height() const + { + return height; + } + int get_iwidth() const + { + return iwidth; + } + int get_iheight() const + { + return iheight; + } + int get_leftmargin() const + { + return left_margin; + } + int get_topmargin() const + { + return top_margin; + } + int get_FujiWidth() const + { + return fuji_width; + } + eSensorType getSensorType(); - void getRgbCam (float rgbcam[3][4]); - void getXtransMatrix ( char xtransMatrix[6][6]); - void clearXtransCblack( ) { for(int c=0;c<4;c++) cblack[c] = 0;} - unsigned get_filters() const { return filters; } - int get_colors() const { return colors;} - int get_cblack(int i) const {return cblack[i];} - int get_white(int i) const { if (maximum_c4[0] > 0) return maximum_c4[i]; else return maximum;} - unsigned short get_whiteSample( int r, int c ) const { return white[r][c];} + void getRgbCam (float rgbcam[3][4]); + void getXtransMatrix ( char xtransMatrix[6][6]); + void clearXtransCblack( ) + { + for(int c = 0; c < 4; c++) { + cblack[c] = 0; + } + } + unsigned get_filters() const + { + return filters; + } + int get_colors() const + { + return colors; + } + int get_cblack(int i) const + { + return cblack[i]; + } + int get_white(int i) const + { + if (maximum_c4[0] > 0) { + return maximum_c4[i]; + } else { + return maximum; + } + } + unsigned short get_whiteSample( int r, int c ) const + { + return white[r][c]; + } - double get_ISOspeed() const {return iso_speed;} - double get_shutter() const {return shutter; } - double get_aperture() const {return aperture; } - time_t get_timestamp() const { return timestamp;} - int get_rotateDegree() const { return rotate_deg;} - const std::string get_maker() const { return std::string(make); } - const std::string get_model() const { return std::string(model); } + double get_ISOspeed() const + { + return iso_speed; + } + double get_shutter() const + { + return shutter; + } + double get_aperture() const + { + return aperture; + } + time_t get_timestamp() const + { + return timestamp; + } + int get_rotateDegree() const + { + return rotate_deg; + } + const std::string get_maker() const + { + return std::string(make); + } + const std::string get_model() const + { + return std::string(model); + } - float get_cam_mul(int c )const {return cam_mul[c];} - float get_pre_mul(int c )const {return pre_mul[c];} - float get_rgb_cam( int r, int c) const { return rgb_cam[r][c];} + float get_cam_mul(int c )const + { + return cam_mul[c]; + } + float get_pre_mul(int c )const + { + return pre_mul[c]; + } + float get_rgb_cam( int r, int c) const + { + return rgb_cam[r][c]; + } - int get_exifBase() const {return exif_base; } - int get_ciffBase() const {return ciff_base; } - int get_ciffLen() const {return ciff_len; } + int get_exifBase() const + { + return exif_base; + } + int get_ciffBase() const + { + return ciff_base; + } + int get_ciffLen() const + { + return ciff_len; + } - int get_profileLen() const {return profile_length;} - char* get_profile() const { return profile_data;} - IMFILE *get_file() { return ifp; } - bool is_supportedThumb() const ; - int get_thumbOffset(){ return int(thumb_offset);} - int get_thumbWidth(){ return int(thumb_width);} - int get_thumbHeight(){ return int(thumb_height);} - int get_thumbBPS(){ return thumb_load_raw ? 16 : 8; } - bool get_thumbSwap() const; - unsigned get_thumbLength(){ return thumb_length;} - bool zeroIsBad() {return zero_is_bad == 1 ? true : false;} + int get_profileLen() const + { + return profile_length; + } + char* get_profile() const + { + return profile_data; + } + IMFILE *get_file() + { + return ifp; + } + bool is_supportedThumb() const ; + int get_thumbOffset() + { + return int(thumb_offset); + } + int get_thumbWidth() + { + return int(thumb_width); + } + int get_thumbHeight() + { + return int(thumb_height); + } + int get_thumbBPS() + { + return thumb_load_raw ? 16 : 8; + } + bool get_thumbSwap() const; + unsigned get_thumbLength() + { + return thumb_length; + } + bool zeroIsBad() + { + return zero_is_bad == 1 ? true : false; + } public: - // dcraw functions - void scale_colors(){ if(isXtrans()) clearXtransCblack( ); DCraw::scale_colors(); } - void pre_interpolate() { DCraw::pre_interpolate(); } + // dcraw functions + void scale_colors() + { + if(isXtrans()) { + clearXtransCblack( ); + } + + DCraw::scale_colors(); + } + void pre_interpolate() + { + DCraw::pre_interpolate(); + } public: - bool ISRED (unsigned row, unsigned col) const { return ((filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==0);} - bool ISGREEN(unsigned row, unsigned col) const { return ((filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1);} - bool ISBLUE (unsigned row, unsigned col) const { return ((filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==2);} - unsigned FC (unsigned row, unsigned col) const { return (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3); } - bool ISXTRANSRED (unsigned row, unsigned col) const { return ((xtrans[(row)%6][(col)%6])==0);} - bool ISXTRANSGREEN(unsigned row, unsigned col) const { return ((xtrans[(row)%6][(col)%6])==1);} - bool ISXTRANSBLUE (unsigned row, unsigned col) const { return ((xtrans[(row)%6][(col)%6])==2);} - unsigned XTRANSFC (unsigned row, unsigned col) const { return (xtrans[(row)%6][(col)%6]);} - + bool ISRED (unsigned row, unsigned col) const + { + return ((filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) == 0); + } + bool ISGREEN(unsigned row, unsigned col) const + { + return ((filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) == 1); + } + bool ISBLUE (unsigned row, unsigned col) const + { + return ((filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) == 2); + } + unsigned FC (unsigned row, unsigned col) const + { + return (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3); + } + bool ISXTRANSRED (unsigned row, unsigned col) const + { + return ((xtrans[(row) % 6][(col) % 6]) == 0); + } + bool ISXTRANSGREEN(unsigned row, unsigned col) const + { + return ((xtrans[(row) % 6][(col) % 6]) == 1); + } + bool ISXTRANSBLUE (unsigned row, unsigned col) const + { + return ((xtrans[(row) % 6][(col) % 6]) == 2); + } + unsigned XTRANSFC (unsigned row, unsigned col) const + { + return (xtrans[(row) % 6][(col) % 6]); + } + }; } diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 41f7f9cca..b425a9f88 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -7,7 +7,7 @@ * 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 @@ -41,7 +41,8 @@ #endif #include "opthelper.h" -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; #undef ABS @@ -49,9 +50,9 @@ extern const Settings* settings; #define ABS(a) ((a)<0?-(a):(a)) #define DIST(a,b) (ABS(a-b)) - + #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } - + #define med3x3(a0,a1,a2,a3,a4,a5,a6,a7,a8,median) { \ p[0]=a0; p[1]=a1; p[2]=a2; p[3]=a3; p[4]=a4; p[5]=a5; p[6]=a6; p[7]=a7; p[8]=a8; \ PIX_SORT(p[1],p[2]); PIX_SORT(p[4],p[5]); PIX_SORT(p[7],p[8]); \ @@ -61,42 +62,44 @@ 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]); median=p[4];} //a4 is the median - + #define med5(a0,a1,a2,a3,a4,median) { \ p[0]=a0; p[1]=a1; p[2]=a2; p[3]=a3; p[4]=a4; \ PIX_SORT(p[0],p[1]) ; PIX_SORT(p[3],p[4]) ; PIX_SORT(p[0],p[3]) ; \ PIX_SORT(p[1],p[4]) ; PIX_SORT(p[1],p[2]) ; PIX_SORT(p[2],p[3]) ; \ PIX_SORT(p[1],p[2]) ; median=p[2] ;} - + RawImageSource::RawImageSource () -:ImageSource() -,plistener(NULL) -,border(4) -,ri(NULL) -,cache(NULL) -,rawData(0,0) -,green(0,0) -,red(0,0) -,blue(0,0) + : ImageSource() + , plistener(NULL) + , border(4) + , ri(NULL) + , cache(NULL) + , rawData(0, 0) + , green(0, 0) + , red(0, 0) + , blue(0, 0) { hrmap[0] = NULL; hrmap[1] = NULL; hrmap[2] = NULL; - //needhr = NULL; + //needhr = NULL; //hpmap = NULL; - camProfile = NULL; - embProfile = NULL; - rgbSourceModified = false; - hlmax[0] = hlmax[1] = hlmax[2] = hlmax[3] = 0.f; - clmax[0] = clmax[1] = clmax[2] = clmax[3] = 0.f; + camProfile = NULL; + embProfile = NULL; + rgbSourceModified = false; + hlmax[0] = hlmax[1] = hlmax[2] = hlmax[3] = 0.f; + clmax[0] = clmax[1] = clmax[2] = clmax[3] = 0.f; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -RawImageSource::~RawImageSource () { +RawImageSource::~RawImageSource () +{ delete idata; + if (ri) { delete ri; } @@ -104,27 +107,34 @@ RawImageSource::~RawImageSource () { flushRGB(); flushRawData(); - if( cache ) + if( cache ) { delete [] cache; - if (hrmap[0]!=NULL) { - int dh = H/HR_SCALE; + } + + if (hrmap[0] != NULL) { + int dh = H / HR_SCALE; freeArray(hrmap[0], dh); freeArray(hrmap[1], dh); freeArray(hrmap[2], dh); } + //if (needhr) // freeArray(needhr, H); //if (hpmap) // freeArray(hpmap, H); - if (camProfile) + if (camProfile) { cmsCloseProfile (camProfile); - if (embProfile) + } + + if (embProfile) { cmsCloseProfile (embProfile); + } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &ssy1, int &width, int &height, int &fw) { +void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &ssy1, int &width, int &height, int &fw) +{ pp.x += border; pp.y += border; @@ -132,74 +142,82 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s if (d1x) { if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { pp.x /= 2; - pp.w = pp.w/2+1; - } - else { + pp.w = pp.w / 2 + 1; + } else { pp.y /= 2; - pp.h = pp.h/2+1; + pp.h = pp.h / 2 + 1; } } int w = W, h = H; + if (fuji) { w = ri->get_FujiWidth() * 2 + 1; - h = (H - ri->get_FujiWidth())*2 + 1; + h = (H - ri->get_FujiWidth()) * 2 + 1; } - - int sw = w, sh = h; + + int sw = w, sh = h; + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { sw = h; sh = w; } - if( pp.w > sw-2*border) pp.w = sw-2*border; - if( pp.h > sh-2*border) pp.h = sh-2*border; + + if( pp.w > sw - 2 * border) { + pp.w = sw - 2 * border; + } + + if( pp.h > sh - 2 * border) { + pp.h = sh - 2 * border; + } int ppx = pp.x, ppy = pp.y; - if (tran & TR_HFLIP) + + if (tran & TR_HFLIP) { ppx = sw - pp.x - pp.w; - if (tran & TR_VFLIP) + } + + if (tran & TR_VFLIP) { ppy = sh - pp.y - pp.h; + } int sx1 = ppx; // assuming it's >=0 int sy1 = ppy; // assuming it's >=0 - int sx2 = max(ppx + pp.w, w-1); - int sy2 = max(ppy + pp.h, h-1); + int sx2 = max(ppx + pp.w, w - 1); + int sy2 = max(ppy + pp.h, h - 1); if ((tran & TR_ROT) == TR_R180) { sx1 = max(w - ppx - pp.w, 0); sy1 = max(h - ppy - pp.h, 0); - sx2 = min(sx1 + pp.w, w-1); - sy2 = min(sy1 + pp.h, h-1); - } - else if ((tran & TR_ROT) == TR_R90) { + sx2 = min(sx1 + pp.w, w - 1); + sy2 = min(sy1 + pp.h, h - 1); + } else if ((tran & TR_ROT) == TR_R90) { sx1 = ppy; sy1 = max(h - ppx - pp.w, 0); - sx2 = min(sx1 + pp.h, w-1); - sy2 = min(sy1 + pp.w, h-1); - } - else if ((tran & TR_ROT) == TR_R270) { + sx2 = min(sx1 + pp.h, w - 1); + sy2 = min(sy1 + pp.w, h - 1); + } else if ((tran & TR_ROT) == TR_R270) { sx1 = max(w - ppy - pp.h, 0); sy1 = ppx; - sx2 = min(sx1 + pp.h, w-1); - sy2 = min(sy1 + pp.w, h-1); + sx2 = min(sx1 + pp.h, w - 1); + sy2 = min(sy1 + pp.w, h - 1); } if (fuji) { // atszamoljuk a koordinatakat fuji-ra: // recalculate the coordinates fuji-ra: - ssx1 = (sx1+sy1) / 2; + ssx1 = (sx1 + sy1) / 2; ssy1 = (sy1 - sx2 ) / 2 + ri->get_FujiWidth(); - int ssx2 = (sx2+sy2) / 2 + 1; + int ssx2 = (sx2 + sy2) / 2 + 1; int ssy2 = (sy2 - sx1) / 2 + ri->get_FujiWidth(); fw = (sx2 - sx1) / 2 / pp.skip; width = (ssx2 - ssx1) / pp.skip + ((ssx2 - ssx1) % pp.skip > 0); - height = (ssy2 - ssy1) / pp.skip + ((ssy2 - ssy1) % pp.skip > 0); - } - else { + height = (ssy2 - ssy1) / pp.skip + ((ssy2 - ssy1) % pp.skip > 0); + } else { ssx1 = sx1; ssy1 = sy1; width = (sx2 - sx1) / pp.skip + ((sx2 - sx1) % pp.skip > 0); - height = (sy2 - sy1) / pp.skip + ((sy2 - sy1) % pp.skip > 0); + height = (sy2 - sy1) / pp.skip + ((sy2 - sy1) % pp.skip > 0); } } @@ -213,17 +231,22 @@ calculate_scale_mul(float scale_mul[4], const float pre_mul_[4], const float c_w } } else { float pre_mul[4]; + for (int c = 0; c < 4; c++) { pre_mul[c] = pre_mul_[c]; } + if (pre_mul[3] == 0) { pre_mul[3] = pre_mul[1]; // G2 == G1 } + float maxpremul = max(pre_mul[0], pre_mul[1], pre_mul[2], pre_mul[3]); + for (int c = 0; c < 4; c++) { scale_mul[c] = (pre_mul[c] / maxpremul) * 65535.0 / (c_white[c] - c_black[c]); } } + float gain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); return gain; } @@ -237,6 +260,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre // compute channel multipliers double r, g, b; float rm, gm, bm; + if (ctemp.getTemp() < 0) { // no white balance, ie revert the pre-process white balance to restore original unbalanced raw camera color rm = ri->get_pre_mul(0); @@ -244,9 +268,9 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre bm = ri->get_pre_mul(2); } else { ctemp.getMultipliers (r, g, b); - rm = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; - gm = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; - bm = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; + rm = imatrices.cam_rgb[0][0] * r + imatrices.cam_rgb[0][1] * g + imatrices.cam_rgb[0][2] * b; + gm = imatrices.cam_rgb[1][0] * r + imatrices.cam_rgb[1][1] * g + imatrices.cam_rgb[1][2] * b; + bm = imatrices.cam_rgb[2][0] * r + imatrices.cam_rgb[2][1] * g + imatrices.cam_rgb[2][2] * b; } if (true) { @@ -254,8 +278,8 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre const float new_pre_mul[4] = { ri->get_pre_mul(0) / rm, ri->get_pre_mul(1) / gm, ri->get_pre_mul(2) / bm, ri->get_pre_mul(3) / gm }; float new_scale_mul[4]; - bool isMono = (ri->getSensorType()==ST_FUJI_XTRANS && raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono]) - || (ri->getSensorType()==ST_BAYER && raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]); + bool isMono = (ri->getSensorType() == ST_FUJI_XTRANS && raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono]) + || (ri->getSensorType() == ST_BAYER && raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]); float gain = calculate_scale_mul(new_scale_mul, new_pre_mul, c_white, cblacksom, isMono, ri->get_colors()); rm = new_scale_mul[0] / scale_mul[0] * gain; gm = new_scale_mul[1] / scale_mul[1] * gain; @@ -279,202 +303,244 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre bm *= camInitialGain; } - defGain=0.0; + defGain = 0.0; // compute image area to render in order to provide the requested part of the image int sx1, sy1, imwidth, imheight, fw; transformRect (pp, tran, sx1, sy1, imwidth, imheight, fw); // check possible overflows int maximwidth, maximheight; + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { maximwidth = image->height; maximheight = image->width; - } - else { + } else { maximwidth = image->width; maximheight = image->height; } - if (d1x) + + if (d1x) { maximheight /= 2; - + } + // correct if overflow (very rare), but not fuji because it is corrected in transline - if (!fuji && imwidth>maximwidth) + if (!fuji && imwidth > maximwidth) { imwidth = maximwidth; - if (!fuji && imheight>maximheight) + } + + if (!fuji && imheight > maximheight) { imheight = maximheight; - - int maxx=this->W,maxy=this->H,skip=pp.skip; + } + + int maxx = this->W, maxy = this->H, skip = pp.skip; // raw clip levels after white balance - hlmax[0]=clmax[0]*rm; - hlmax[1]=clmax[1]*gm; - hlmax[2]=clmax[2]*bm; + hlmax[0] = clmax[0] * rm; + hlmax[1] = clmax[1] * gm; + hlmax[2] = clmax[2] * bm; const bool has_clipping = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]); //if (sx1+skip*imwidth>maxx) imwidth --; // very hard to fix this situation without an 'if' in the loop. - float area=skip*skip; - rm/=area; - gm/=area; - bm/=area; - + float area = skip * skip; + rm /= area; + gm /= area; + bm /= area; + #ifdef _OPENMP -#pragma omp parallel if(!d1x) // omp disabled for D1x to avoid race conditions (see Issue 1088 http://code.google.com/p/rawtherapee/issues/detail?id=1088) + #pragma omp parallel if(!d1x) // omp disabled for D1x to avoid race conditions (see Issue 1088 http://code.google.com/p/rawtherapee/issues/detail?id=1088) { #endif - // render the requested image part - float* line_red = new float[imwidth]; - float* line_grn = new float[imwidth]; - float* line_blue = new float[imwidth]; - //printf("clip[0]=%f clip[1]=%f clip[2]=%f\n",hlmax[0],hlmax[1],hlmax[2]); + // render the requested image part + float* line_red = new float[imwidth]; + float* line_grn = new float[imwidth]; + float* line_blue = new float[imwidth]; + //printf("clip[0]=%f clip[1]=%f clip[2]=%f\n",hlmax[0],hlmax[1],hlmax[2]); #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for (int ix=0; ix=maxy-skip) i=maxy-skip-1; // avoid trouble - if (ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS || ri->get_colors() == 1) { - for (int j=0,jx=sx1; j=maxx-skip) jx=maxx-skip-1; // avoid trouble - float rtot,gtot,btot; - rtot=gtot=btot=0; - for (int m=0; m= maxy - skip) { + i = maxy - skip - 1; // avoid trouble } - } else { - for (int j=0,jx=sx1; jmaxx-skip) jx=maxx-skip-1; - float rtot,gtot,btot; - rtot=gtot=btot=0; - for (int m=0; mgetSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) { + for (int j = 0, jx = sx1; j < imwidth; j++, jx += skip) { + if (jx >= maxx - skip) { + jx = maxx - skip - 1; // avoid trouble + } + + float rtot, gtot, btot; + rtot = gtot = btot = 0; + + for (int m = 0; m < skip; m++) + for (int n = 0; n < skip; n++) { + rtot += red[i + m][jx + n]; + gtot += green[i + m][jx + n]; + btot += blue[i + m][jx + n]; + } + + rtot *= rm; + gtot *= gm; + btot *= bm; + + if (!hrp.hrenabled && has_clipping) { + // note: as hlmax[] can be larger than CLIP and we can later apply negative + // exposure this means that we can clip away local highlights which actually + // are not clipped. We have to do that though as we only check pixel by pixel + // and don't know if this will transition into a clipped area, if so we need + // to clip also surrounding to make a good color transition + rtot = CLIP(rtot); + gtot = CLIP(gtot); + btot = CLIP(btot); + } + + line_red[j] = rtot; + line_grn[j] = gtot; + line_blue[j] = btot; + } + } else { + for (int j = 0, jx = sx1; j < imwidth; j++, jx += skip) { + if (jx > maxx - skip) { + jx = maxx - skip - 1; + } + + float rtot, gtot, btot; + rtot = gtot = btot = 0; + + for (int m = 0; m < skip; m++) + for (int n = 0; n < skip; n++) { + rtot += rawData[i + m][(jx + n) * 3 + 0]; + gtot += rawData[i + m][(jx + n) * 3 + 1]; + btot += rawData[i + m][(jx + n) * 3 + 2]; + } + + rtot *= rm; + gtot *= gm; + btot *= bm; + + if (!hrp.hrenabled && has_clipping) { + rtot = CLIP(rtot); + gtot = CLIP(gtot); + btot = CLIP(btot); + } + + line_red[j] = rtot; + line_grn[j] = gtot; + line_blue[j] = btot; + + } } + + //process all highlight recovery other than "Color" + if (hrp.hrenabled && hrp.method != "Color") { + hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip, raw, hlmax); + } + + transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, fw); + } - //process all highlight recovery other than "Color" - if (hrp.hrenabled && hrp.method!="Color") - hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip, raw, hlmax); - - transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, fw); - - } - - delete [] line_red; - delete [] line_grn; - delete [] line_blue; + delete [] line_red; + delete [] line_grn; + delete [] line_blue; #ifdef _OPENMP } #endif - if (fuji) { - int a = ((tran & TR_ROT) == TR_R90 && image->width%2==0) || ((tran & TR_ROT) == TR_R180 && image->height%2+image->width%2==1) || ((tran & TR_ROT) == TR_R270 && image->height%2==0); + + if (fuji) { + int a = ((tran & TR_ROT) == TR_R90 && image->width % 2 == 0) || ((tran & TR_ROT) == TR_R180 && image->height % 2 + image->width % 2 == 1) || ((tran & TR_ROT) == TR_R270 && image->height % 2 == 0); + // first row - for (int j=1+a; jwidth-1; j+=2) { - image->r(0,j) = (image->r(1,j) + image->r(0,j+1) + image->r(0,j-1)) / 3; - image->g(0,j) = (image->g(1,j) + image->g(0,j+1) + image->g(0,j-1)) / 3; - image->b(0,j) = (image->b(1,j) + image->b(0,j+1) + image->b(0,j-1)) / 3; + for (int j = 1 + a; j < image->width - 1; j += 2) { + image->r(0, j) = (image->r(1, j) + image->r(0, j + 1) + image->r(0, j - 1)) / 3; + image->g(0, j) = (image->g(1, j) + image->g(0, j + 1) + image->g(0, j - 1)) / 3; + image->b(0, j) = (image->b(1, j) + image->b(0, j + 1) + image->b(0, j - 1)) / 3; } + // other rows - for (int i=1; iheight-1; i++) { - for (int j=2-(a+i+1)%2; jwidth-1; j+=2) { - // edge-adaptive interpolation - double dh = (ABS(image->r(i,j+1) - image->r(i,j-1)) + ABS(image->g(i,j+1) - image->g(i,j-1)) + ABS(image->b(i,j+1) - image->b(i,j-1))) / 1.0; - double dv = (ABS(image->r(i+1,j) - image->r(i-1,j)) + ABS(image->g(i+1,j) - image->g(i-1,j)) + ABS(image->b(i+1,j) - image->b(i-1,j))) / 1.0; - double eh = 1.0 / (1.0 + dh); - double ev = 1.0 / (1.0 + dv); - image->r(i,j) = (eh * (image->r(i,j+1) + image->r(i,j-1)) + ev * (image->r(i+1,j) + image->r(i-1,j))) / (2.0 * (eh + ev)); - image->g(i,j) = (eh * (image->g(i,j+1) + image->g(i,j-1)) + ev * (image->g(i+1,j) + image->g(i-1,j))) / (2.0 * (eh + ev)); - image->b(i,j) = (eh * (image->b(i,j+1) + image->b(i,j-1)) + ev * (image->b(i+1,j) + image->b(i-1,j))) / (2.0 * (eh + ev)); - } - // first pixel - if (2-(a+i+1)%2==2) { - image->r(i,0) = (image->r(i+1,0) + image->r(i-1,0) + image->r(i,1)) / 3; - image->g(i,0) = (image->g(i+1,0) + image->g(i-1,0) + image->g(i,1)) / 3; - image->b(i,0) = (image->b(i+1,0) + image->b(i-1,0) + image->b(i,1)) / 3; - } - // last pixel - if (2-(a+i+image->width)%2==2) { - image->r(i,image->width-1) = (image->r(i+1,image->width-1) + image->r(i-1,image->width-1) + image->r(i,image->width-2)) / 3; - image->g(i,image->width-1) = (image->g(i+1,image->width-1) + image->g(i-1,image->width-1) + image->g(i,image->width-2)) / 3; - image->b(i,image->width-1) = (image->b(i+1,image->width-1) + image->b(i-1,image->width-1) + image->b(i,image->width-2)) / 3; - } + for (int i = 1; i < image->height - 1; i++) { + for (int j = 2 - (a + i + 1) % 2; j < image->width - 1; j += 2) { + // edge-adaptive interpolation + double dh = (ABS(image->r(i, j + 1) - image->r(i, j - 1)) + ABS(image->g(i, j + 1) - image->g(i, j - 1)) + ABS(image->b(i, j + 1) - image->b(i, j - 1))) / 1.0; + double dv = (ABS(image->r(i + 1, j) - image->r(i - 1, j)) + ABS(image->g(i + 1, j) - image->g(i - 1, j)) + ABS(image->b(i + 1, j) - image->b(i - 1, j))) / 1.0; + double eh = 1.0 / (1.0 + dh); + double ev = 1.0 / (1.0 + dv); + image->r(i, j) = (eh * (image->r(i, j + 1) + image->r(i, j - 1)) + ev * (image->r(i + 1, j) + image->r(i - 1, j))) / (2.0 * (eh + ev)); + image->g(i, j) = (eh * (image->g(i, j + 1) + image->g(i, j - 1)) + ev * (image->g(i + 1, j) + image->g(i - 1, j))) / (2.0 * (eh + ev)); + image->b(i, j) = (eh * (image->b(i, j + 1) + image->b(i, j - 1)) + ev * (image->b(i + 1, j) + image->b(i - 1, j))) / (2.0 * (eh + ev)); + } + + // first pixel + if (2 - (a + i + 1) % 2 == 2) { + image->r(i, 0) = (image->r(i + 1, 0) + image->r(i - 1, 0) + image->r(i, 1)) / 3; + image->g(i, 0) = (image->g(i + 1, 0) + image->g(i - 1, 0) + image->g(i, 1)) / 3; + image->b(i, 0) = (image->b(i + 1, 0) + image->b(i - 1, 0) + image->b(i, 1)) / 3; + } + + // last pixel + if (2 - (a + i + image->width) % 2 == 2) { + image->r(i, image->width - 1) = (image->r(i + 1, image->width - 1) + image->r(i - 1, image->width - 1) + image->r(i, image->width - 2)) / 3; + image->g(i, image->width - 1) = (image->g(i + 1, image->width - 1) + image->g(i - 1, image->width - 1) + image->g(i, image->width - 2)) / 3; + image->b(i, image->width - 1) = (image->b(i + 1, image->width - 1) + image->b(i - 1, image->width - 1) + image->b(i, image->width - 2)) / 3; + } } + // last row - int b = (a==1 && image->height%2) || (a==0 && image->height%2==0); - for (int j=1+b; jwidth-1; j+=2) { - image->r(image->height-1,j) = (image->r(image->height-2,j) + image->r(image->height-1,j+1) + image->r(image->height-1,j-1)) / 3; - image->g(image->height-1,j) = (image->g(image->height-2,j) + image->g(image->height-1,j+1) + image->g(image->height-1,j-1)) / 3; - image->b(image->height-1,j) = (image->b(image->height-2,j) + image->b(image->height-1,j+1) + image->b(image->height-1,j-1)) / 3; + int b = (a == 1 && image->height % 2) || (a == 0 && image->height % 2 == 0); + + for (int j = 1 + b; j < image->width - 1; j += 2) { + image->r(image->height - 1, j) = (image->r(image->height - 2, j) + image->r(image->height - 1, j + 1) + image->r(image->height - 1, j - 1)) / 3; + image->g(image->height - 1, j) = (image->g(image->height - 2, j) + image->g(image->height - 1, j + 1) + image->g(image->height - 1, j - 1)) / 3; + image->b(image->height - 1, j) = (image->b(image->height - 2, j) + image->b(image->height - 1, j + 1) + image->b(image->height - 1, j - 1)) / 3; } } - + // Flip if needed - if (tran & TR_HFLIP) + if (tran & TR_HFLIP) { hflip (image); - if (tran & TR_VFLIP) + } + + if (tran & TR_VFLIP) { vflip (image); + } // Color correction (only when running on full resolution) - if (ri->getSensorType()!=ST_NONE && pp.skip==1) { - if (ri->getSensorType()==ST_BAYER) + if (ri->getSensorType() != ST_NONE && pp.skip == 1) { + if (ri->getSensorType() == ST_BAYER) { processFalseColorCorrection (image, raw.bayersensor.ccSteps); - else if (ri->getSensorType()==ST_FUJI_XTRANS) + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { processFalseColorCorrection (image, raw.xtranssensor.ccSteps); + } } } -DCPProfile *RawImageSource::getDCP(ColorManagementParams cmp, ColorTemp &wb) { +DCPProfile *RawImageSource::getDCP(ColorManagementParams cmp, ColorTemp &wb) +{ DCPProfile *dcpProf = NULL; cmsHPROFILE dummy; findInputProfile(cmp.input, NULL, (static_cast(getMetaData()))->getCamera(), &dcpProf, dummy); + if (dcpProf == NULL) { return NULL; } + dcpProf->setStep2ApplyState(cmp.working, cmp.toneCurve, cmp.applyLookTable, cmp.applyBaselineExposureOffset); return dcpProf; } - -void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb) { + +void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb) +{ double pre_mul[3] = { ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2) }; colorSpaceConversion (image, cmp, wb, pre_mul, embProfile, camProfile, imatrices.xyz_cam, (static_cast(getMetaData()))->getCamera()); } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* interpolateBadPixelsBayer: correct raw pixels looking at the bitmap @@ -482,100 +548,114 @@ void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams */ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) { - static const float eps=1.f; - int counter=0; -#pragma omp parallel for reduction(+:counter) schedule(dynamic,16) - for( int row = 2; row < H-2; row++ ){ - for(int col = 2; col weighting is 0.70710678 - // For green channel following pixels will be used for interpolation. Pixel to be interpolated is in center. - // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad - // 0 0 0 0 0 - // 0 1 0 1 0 - // 0 0 0 0 0 - // 0 1 0 1 0 - // 0 0 0 0 0 - for( int dx=-1;dx<=1;dx+=2){ - if( bitmapBads.get(col+dx,row-1) || bitmapBads.get(col-dx,row+1)) - continue; - float dirwt = 0.70710678f/( fabsf( rawData[row-1][col+dx]- rawData[row+1][col-dx])+eps); - wtdsum += dirwt * (rawData[row-1][col+dx] + rawData[row+1][col-dx]); - norm += dirwt; - } - } else { - // red and blue channel. Distance to center pixel is sqrt(8) => weighting is 0.35355339 - // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center. - // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad - // 1 0 0 0 1 - // 0 0 0 0 0 - // 0 0 0 0 0 - // 0 0 0 0 0 - // 1 0 0 0 1 - for( int dx=-2;dx<=2;dx+=4){ - if( bitmapBads.get(col+dx,row-2) || bitmapBads.get(col-dx,row+2)) - continue; - float dirwt = 0.35355339f/( fabsf( rawData[row-2][col+dx]- rawData[row+2][col-dx])+eps); - wtdsum += dirwt * (rawData[row-2][col+dx] + rawData[row+2][col-dx]); - norm += dirwt; - } - } - // channel independent. Distance to center pixel is 2 => weighting is 0.5 - // Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in center. - // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad - // 0 0 1 0 0 - // 0 0 0 0 0 - // 1 0 0 0 1 - // 0 0 0 0 0 - // 0 0 1 0 0 - - // horizontal interpolation - if(!(bitmapBads.get(col-2,row) || bitmapBads.get(col+2,row))) { - float dirwt = 0.5f/( fabsf( rawData[row][col-2]- rawData[row][col+2])+eps); - wtdsum += dirwt * (rawData[row][col-2] + rawData[row][col+2]); - norm += dirwt; - } - - // vertical interpolation - if(!(bitmapBads.get(col,row-2) || bitmapBads.get(col,row+2))) { - float dirwt = 0.5f/( fabsf( rawData[row-2][col]- rawData[row+2][col])+eps); - wtdsum += dirwt * (rawData[row-2][col] + rawData[row+2][col]); - norm += dirwt; - } + for( int row = 2; row < H - 2; row++ ) { + for(int col = 2; col < W - 2; col++ ) { + int sk = bitmapBads.skipIfZero(col, row); //optimization for a stripe all zero - if (LIKELY(norm > 0.f)){ // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% - rawData[row][col]= wtdsum / (2.f * norm);//gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps - counter++; - } else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens - int tot = 0; - float sum = 0; - for( int dy=-2;dy<=2;dy+=2){ - for( int dx=-2;dx<=2;dx+=2){ - if(bitmapBads.get(col+dx,row+dy)) - continue; - sum += rawData[row+dy][col+dx]; - tot++; - } - } - if (tot > 0) { - rawData[row][col] = sum/tot; - counter ++; - } - } - } - } - return counter; // Number of interpolated pixels. + if( sk ) { + col += sk - 1; //-1 is because of col++ in cycle + continue; + } + + if(!bitmapBads.get(col, row)) { + continue; + } + + float wtdsum = 0.f, norm = 0.f; + + // diagonal interpolation + if(FC(row, col) == 1) { + // green channel. We can use closer pixels than for red or blue channel. Distance to center pixel is sqrt(2) => weighting is 0.70710678 + // For green channel following pixels will be used for interpolation. Pixel to be interpolated is in center. + // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad + // 0 0 0 0 0 + // 0 1 0 1 0 + // 0 0 0 0 0 + // 0 1 0 1 0 + // 0 0 0 0 0 + for( int dx = -1; dx <= 1; dx += 2) { + if( bitmapBads.get(col + dx, row - 1) || bitmapBads.get(col - dx, row + 1)) { + continue; + } + + float dirwt = 0.70710678f / ( fabsf( rawData[row - 1][col + dx] - rawData[row + 1][col - dx]) + eps); + wtdsum += dirwt * (rawData[row - 1][col + dx] + rawData[row + 1][col - dx]); + norm += dirwt; + } + } else { + // red and blue channel. Distance to center pixel is sqrt(8) => weighting is 0.35355339 + // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center. + // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad + // 1 0 0 0 1 + // 0 0 0 0 0 + // 0 0 0 0 0 + // 0 0 0 0 0 + // 1 0 0 0 1 + for( int dx = -2; dx <= 2; dx += 4) { + if( bitmapBads.get(col + dx, row - 2) || bitmapBads.get(col - dx, row + 2)) { + continue; + } + + float dirwt = 0.35355339f / ( fabsf( rawData[row - 2][col + dx] - rawData[row + 2][col - dx]) + eps); + wtdsum += dirwt * (rawData[row - 2][col + dx] + rawData[row + 2][col - dx]); + norm += dirwt; + } + } + + // channel independent. Distance to center pixel is 2 => weighting is 0.5 + // Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in center. + // 1 means that pixel is used in this step, if itself and his counterpart are not marked bad + // 0 0 1 0 0 + // 0 0 0 0 0 + // 1 0 0 0 1 + // 0 0 0 0 0 + // 0 0 1 0 0 + + // horizontal interpolation + if(!(bitmapBads.get(col - 2, row) || bitmapBads.get(col + 2, row))) { + float dirwt = 0.5f / ( fabsf( rawData[row][col - 2] - rawData[row][col + 2]) + eps); + wtdsum += dirwt * (rawData[row][col - 2] + rawData[row][col + 2]); + norm += dirwt; + } + + // vertical interpolation + if(!(bitmapBads.get(col, row - 2) || bitmapBads.get(col, row + 2))) { + float dirwt = 0.5f / ( fabsf( rawData[row - 2][col] - rawData[row + 2][col]) + eps); + wtdsum += dirwt * (rawData[row - 2][col] + rawData[row + 2][col]); + norm += dirwt; + } + + if (LIKELY(norm > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% + rawData[row][col] = wtdsum / (2.f * norm); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps + counter++; + } else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens + int tot = 0; + float sum = 0; + + for( int dy = -2; dy <= 2; dy += 2) { + for( int dx = -2; dx <= 2; dx += 2) { + if(bitmapBads.get(col + dx, row + dy)) { + continue; + } + + sum += rawData[row + dy][col + dx]; + tot++; + } + } + + if (tot > 0) { + rawData[row][col] = sum / tot; + counter ++; + } + } + } + } + + return counter; // Number of interpolated pixels. } /* interpolateBadPixels3Colours: correct raw pixels looking at the bitmap @@ -583,237 +663,279 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads ) */ int RawImageSource::interpolateBadPixelsNColours( PixelsMap &bitmapBads, const int colours ) { - static const float eps=1.f; - int counter=0; -#pragma omp parallel for reduction(+:counter) schedule(dynamic,16) - for( int row = 2; row < H-2; row++ ){ - for(int col = 2; col 0.f)){ // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% - for(int c=0;c 0) { - for(int c=0;c 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% + for(int c = 0; c < colours; c++) { + rawData[row][col * colours + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps + } + + counter++; + } else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens + int tot = 0; + float sum[colours]; + + for (int i = 0; i < colours; ++i) { + sum[i] = 0.f; + } + + for( int dy = -2; dy <= 2; dy += 2) { + for( int dx = -2; dx <= 2; dx += 2) { + if(bitmapBads.get(col + dx, row + dy)) { + continue; + } + + for(int c = 0; c < colours; c++) { + sum[c] += rawData[row + dy][(col + dx) * colours + c]; + } + + tot++; + } + } + + if (tot > 0) { + for(int c = 0; c < colours; c++) { + rawData[row][col * colours + c] = sum[c] / tot; + } + + counter ++; + } + } + } + } + + return counter; // Number of interpolated pixels. } /* interpolateBadPixelsXtrans: correct raw pixels looking at the bitmap * takes into consideration if there are multiple bad pixels in the neighborhood */ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads ) { - static const float eps=1.f; - int counter=0; -#pragma omp parallel for reduction(+:counter) schedule(dynamic,16) - for( int row = 2; row < H-2; row++ ){ - for(int col = 2; col XTRANSFC(row,col); - float oldval = rawData[row][col]; - if(pixelColor==1) { - // green channel. A green pixel can either be a solitary green pixel or a member of a 2x2 square of green pixels - if(ri->XTRANSFC(row,col-1)==ri->XTRANSFC(row,col+1)) { - // If left and right neighbour have same color, then this is a solitary green pixel - // For these the following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P. - // Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad - // 0 means, the pixel has a different color and will not be used - // 0 1 0 2 0 - // 3 5 0 6 4 - // 0 0 P 0 0 - // 4 6 0 5 3 - // 0 2 0 1 0 - for( int dx=-1;dx<=1;dx+=2){ // pixels marked 5 or 6 in above example. Distance to P is sqrt(2) => weighting is 0.70710678f - if( bitmapBads.get(col+dx,row-1) || bitmapBads.get(col-dx,row+1)) - continue; - float dirwt = 0.70710678f/( fabsf( rawData[row-1][col+dx]- rawData[row+1][col-dx])+eps); - wtdsum += dirwt * (rawData[row-1][col+dx] + rawData[row+1][col-dx]); - norm += dirwt; - } - for( int dx=-1;dx<=1;dx+=2){ // pixels marked 1 or 2 on above example. Distance to P is sqrt(5) => weighting is 0.44721359f - if( bitmapBads.get(col+dx,row-2) || bitmapBads.get(col-dx,row+2)) - continue; - float dirwt = 0.44721359f/( fabsf( rawData[row-2][col+dx]- rawData[row+2][col-dx])+eps); - wtdsum += dirwt * (rawData[row-2][col+dx] + rawData[row+2][col-dx]); - norm += dirwt; - } - for( int dx=-2;dx<=2;dx+=4){ // pixels marked 3 or 4 on above example. Distance to P is sqrt(5) => weighting is 0.44721359f - if( bitmapBads.get(col+dx,row-1) || bitmapBads.get(col-dx,row+1)) - continue; - float dirwt = 0.44721359f/( fabsf( rawData[row-1][col+dx]- rawData[row+1][col-dx])+eps); - wtdsum += dirwt * (rawData[row-1][col+dx] + rawData[row+1][col-dx]); - norm += dirwt; - } - } else { - // this is a member of a 2x2 square of green pixels - // For these the following pixels will be used for interpolation. Pixel to be interpolated is at position P in the example. - // Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad - // 0 means, the pixel has a different color and will not be used - // 1 0 0 3 - // 0 P 2 0 - // 0 2 1 0 - // 3 0 0 0 - int offset1 = ri->XTRANSFC(row-1,col-1) == ri->XTRANSFC(row+1,col+1) ? 1 : -1; // pixels marked 1 in above example. Distance to P is sqrt(2) => weighting is 0.70710678f - if( !(bitmapBads.get(col-offset1,row-1) || bitmapBads.get(col+offset1,row+1))) { - float dirwt = 0.70710678f/( fabsf( rawData[row-1][col-offset1]- rawData[row+1][col+offset1])+eps); - wtdsum += dirwt * (rawData[row-1][col-offset1] + rawData[row+1][col+offset1]); - norm += dirwt; - } - int offsety = (ri->XTRANSFC(row-1,col) != 1 ? 1 : -1); - int offsetx = offset1 * offsety; - if( !(bitmapBads.get(col+offsetx,row) || bitmapBads.get(col,row+offsety))) { - float dirwt = 1.f/( fabsf( rawData[row][col+offsetx]- rawData[row+offsety][col])+eps); - wtdsum += dirwt * (rawData[row][col+offsetx] + rawData[row+offsety][col]); - norm += dirwt; - } - int offsety2 = -offsety; - int offsetx2 = -offsetx; - offsetx *=2; - offsety *=2; - // pixels marked 3 in above example. Distance to P is sqrt(5) => weighting is 0.44721359f - if( !(bitmapBads.get(col+offsetx,row+offsety2) || bitmapBads.get(col+offsetx2,row+offsety))) { - float dirwt = 0.44721359f/( fabsf( rawData[row+offsety2][col+offsetx]- rawData[row+offsety][col+offsetx2])+eps); - wtdsum += dirwt * (rawData[row+offsety2][col+offsetx] + rawData[row+offsety][col+offsetx2]); - norm += dirwt; - } - } - } else { - // red and blue channel. - // Each red or blue pixel has exactly one neigbour of same color in distance 2 and four neighbours of same color which can be reached by a move of a knight in chess. - // For the distance 2 pixel (marked with an X) we generate a virtual counterpart (marked with a V) - // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P. - // Pairs of pixels used in this step are numbered except for distance 2 pixels which are marked X and V. A pair will be used if none of the pixels of the pair is marked bad - // 0 1 0 0 0 0 0 X 0 0 remaining cases are symmetric - // 0 0 0 0 2 1 0 0 0 2 - // X 0 P 0 V 0 0 P 0 0 - // 0 0 0 0 1 0 0 0 0 0 - // 0 2 0 0 0 0 2 V 1 0 + for( int row = 2; row < H - 2; row++ ) { + for(int col = 2; col < W - 2; col++ ) { + int skip = bitmapBads.skipIfZero(col, row); //optimization for a stripe all zero - // Find two knight moves landing on a pixel of same color as the pixel to be interpolated. - // If we look at first and last row of 5x5 square, we will find exactly two knight pixels. - // Additionally we know that the column of this pixel has 1 or -1 horizontal distance to the center pixel - // When we find a knight pixel, we get its counterpart, which has distance (+-3,+-3), where the signs of distance depend on the corner of the found knight pixel. - // These pixels are marked 1 or 2 in above examples. Distance to P is sqrt(5) => weighting is 0.44721359f - // The following loop simply scans the four possible places. To keep things simple, it doesn't stop after finding two knight pixels, because it will not find more than two - for(int d1=-2,offsety=3;d1<=2;d1+=4,offsety-=6) { - for(int d2=-1,offsetx=3;d2<1;d2+=2,offsetx-=6) { - if(ri->XTRANSFC(row+d1,col+d2) == pixelColor) { - if( !(bitmapBads.get(col+d2,row+d1) || bitmapBads.get(col+d2+offsetx,row+d1+offsety))) { - float dirwt = 0.44721359f/( fabsf( rawData[row+d1][col+d2]- rawData[row+d1+offsety][col+d2+offsetx])+eps); - wtdsum += dirwt * (rawData[row+d1][col+d2] + rawData[row+d1+offsety][col+d2+offsetx]); - norm += dirwt; - } - } - } - } + if( skip ) { + col += skip - 1; //-1 is because of col++ in cycle + continue; + } - // now scan for the pixel of same colour in distance 2 in each direction (marked with an X in above examples). - bool distance2PixelFound = false; - int dx,dy; - // check horizontal - for(dx=-2,dy=0;dx<=2 && !distance2PixelFound;dx+=4) - if(ri->XTRANSFC(row,col+dx) == pixelColor) - distance2PixelFound = true; + if(!bitmapBads.get(col, row)) { + continue; + } - if(!distance2PixelFound) - // no distance 2 pixel on horizontal, check vertical - for(dx=0,dy=-2;dy<=2 && !distance2PixelFound;dy+=4) - if(ri->XTRANSFC(row+dy,col) == pixelColor) - distance2PixelFound = true; - - // calculate the value of its virtual counterpart (marked with a V in above examples) - float virtualPixel; - if(dy==0) { - virtualPixel = 0.5f*(rawData[row-1][col-dx] + rawData[row+1][col-dx]); - } - else { - virtualPixel = 0.5f*(rawData[row-dy][col-1] + rawData[row-dy][col+1]); - } - // and weight as usual. Distance to P is 2 => weighting is 0.5f - float dirwt = 0.5f/( fabsf( virtualPixel- rawData[row+dy][col+dx])+eps); - wtdsum += dirwt * (virtualPixel + rawData[row+dy][col+dx]); - norm += dirwt; - } + float wtdsum = 0.f, norm = 0.f; + int pixelColor = ri->XTRANSFC(row, col); + float oldval = rawData[row][col]; - if (LIKELY(norm > 0.f)){ // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% - rawData[row][col]= wtdsum / (2.f * norm);//gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps + if(pixelColor == 1) { + // green channel. A green pixel can either be a solitary green pixel or a member of a 2x2 square of green pixels + if(ri->XTRANSFC(row, col - 1) == ri->XTRANSFC(row, col + 1)) { + // If left and right neighbour have same color, then this is a solitary green pixel + // For these the following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P. + // Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad + // 0 means, the pixel has a different color and will not be used + // 0 1 0 2 0 + // 3 5 0 6 4 + // 0 0 P 0 0 + // 4 6 0 5 3 + // 0 2 0 1 0 + for( int dx = -1; dx <= 1; dx += 2) { // pixels marked 5 or 6 in above example. Distance to P is sqrt(2) => weighting is 0.70710678f + if( bitmapBads.get(col + dx, row - 1) || bitmapBads.get(col - dx, row + 1)) { + continue; + } + + float dirwt = 0.70710678f / ( fabsf( rawData[row - 1][col + dx] - rawData[row + 1][col - dx]) + eps); + wtdsum += dirwt * (rawData[row - 1][col + dx] + rawData[row + 1][col - dx]); + norm += dirwt; + } + + for( int dx = -1; dx <= 1; dx += 2) { // pixels marked 1 or 2 on above example. Distance to P is sqrt(5) => weighting is 0.44721359f + if( bitmapBads.get(col + dx, row - 2) || bitmapBads.get(col - dx, row + 2)) { + continue; + } + + float dirwt = 0.44721359f / ( fabsf( rawData[row - 2][col + dx] - rawData[row + 2][col - dx]) + eps); + wtdsum += dirwt * (rawData[row - 2][col + dx] + rawData[row + 2][col - dx]); + norm += dirwt; + } + + for( int dx = -2; dx <= 2; dx += 4) { // pixels marked 3 or 4 on above example. Distance to P is sqrt(5) => weighting is 0.44721359f + if( bitmapBads.get(col + dx, row - 1) || bitmapBads.get(col - dx, row + 1)) { + continue; + } + + float dirwt = 0.44721359f / ( fabsf( rawData[row - 1][col + dx] - rawData[row + 1][col - dx]) + eps); + wtdsum += dirwt * (rawData[row - 1][col + dx] + rawData[row + 1][col - dx]); + norm += dirwt; + } + } else { + // this is a member of a 2x2 square of green pixels + // For these the following pixels will be used for interpolation. Pixel to be interpolated is at position P in the example. + // Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad + // 0 means, the pixel has a different color and will not be used + // 1 0 0 3 + // 0 P 2 0 + // 0 2 1 0 + // 3 0 0 0 + int offset1 = ri->XTRANSFC(row - 1, col - 1) == ri->XTRANSFC(row + 1, col + 1) ? 1 : -1; // pixels marked 1 in above example. Distance to P is sqrt(2) => weighting is 0.70710678f + + if( !(bitmapBads.get(col - offset1, row - 1) || bitmapBads.get(col + offset1, row + 1))) { + float dirwt = 0.70710678f / ( fabsf( rawData[row - 1][col - offset1] - rawData[row + 1][col + offset1]) + eps); + wtdsum += dirwt * (rawData[row - 1][col - offset1] + rawData[row + 1][col + offset1]); + norm += dirwt; + } + + int offsety = (ri->XTRANSFC(row - 1, col) != 1 ? 1 : -1); + int offsetx = offset1 * offsety; + + if( !(bitmapBads.get(col + offsetx, row) || bitmapBads.get(col, row + offsety))) { + float dirwt = 1.f / ( fabsf( rawData[row][col + offsetx] - rawData[row + offsety][col]) + eps); + wtdsum += dirwt * (rawData[row][col + offsetx] + rawData[row + offsety][col]); + norm += dirwt; + } + + int offsety2 = -offsety; + int offsetx2 = -offsetx; + offsetx *= 2; + offsety *= 2; + + // pixels marked 3 in above example. Distance to P is sqrt(5) => weighting is 0.44721359f + if( !(bitmapBads.get(col + offsetx, row + offsety2) || bitmapBads.get(col + offsetx2, row + offsety))) { + float dirwt = 0.44721359f / ( fabsf( rawData[row + offsety2][col + offsetx] - rawData[row + offsety][col + offsetx2]) + eps); + wtdsum += dirwt * (rawData[row + offsety2][col + offsetx] + rawData[row + offsety][col + offsetx2]); + norm += dirwt; + } + } + } else { + // red and blue channel. + // Each red or blue pixel has exactly one neigbour of same color in distance 2 and four neighbours of same color which can be reached by a move of a knight in chess. + // For the distance 2 pixel (marked with an X) we generate a virtual counterpart (marked with a V) + // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P. + // Pairs of pixels used in this step are numbered except for distance 2 pixels which are marked X and V. A pair will be used if none of the pixels of the pair is marked bad + // 0 1 0 0 0 0 0 X 0 0 remaining cases are symmetric + // 0 0 0 0 2 1 0 0 0 2 + // X 0 P 0 V 0 0 P 0 0 + // 0 0 0 0 1 0 0 0 0 0 + // 0 2 0 0 0 0 2 V 1 0 + + // Find two knight moves landing on a pixel of same color as the pixel to be interpolated. + // If we look at first and last row of 5x5 square, we will find exactly two knight pixels. + // Additionally we know that the column of this pixel has 1 or -1 horizontal distance to the center pixel + // When we find a knight pixel, we get its counterpart, which has distance (+-3,+-3), where the signs of distance depend on the corner of the found knight pixel. + // These pixels are marked 1 or 2 in above examples. Distance to P is sqrt(5) => weighting is 0.44721359f + // The following loop simply scans the four possible places. To keep things simple, it doesn't stop after finding two knight pixels, because it will not find more than two + for(int d1 = -2, offsety = 3; d1 <= 2; d1 += 4, offsety -= 6) { + for(int d2 = -1, offsetx = 3; d2 < 1; d2 += 2, offsetx -= 6) { + if(ri->XTRANSFC(row + d1, col + d2) == pixelColor) { + if( !(bitmapBads.get(col + d2, row + d1) || bitmapBads.get(col + d2 + offsetx, row + d1 + offsety))) { + float dirwt = 0.44721359f / ( fabsf( rawData[row + d1][col + d2] - rawData[row + d1 + offsety][col + d2 + offsetx]) + eps); + wtdsum += dirwt * (rawData[row + d1][col + d2] + rawData[row + d1 + offsety][col + d2 + offsetx]); + norm += dirwt; + } + } + } + } + + // now scan for the pixel of same colour in distance 2 in each direction (marked with an X in above examples). + bool distance2PixelFound = false; + int dx, dy; + + // check horizontal + for(dx = -2, dy = 0; dx <= 2 && !distance2PixelFound; dx += 4) + if(ri->XTRANSFC(row, col + dx) == pixelColor) { + distance2PixelFound = true; + } + + if(!distance2PixelFound) + + // no distance 2 pixel on horizontal, check vertical + for(dx = 0, dy = -2; dy <= 2 && !distance2PixelFound; dy += 4) + if(ri->XTRANSFC(row + dy, col) == pixelColor) { + distance2PixelFound = true; + } + + // calculate the value of its virtual counterpart (marked with a V in above examples) + float virtualPixel; + + if(dy == 0) { + virtualPixel = 0.5f * (rawData[row - 1][col - dx] + rawData[row + 1][col - dx]); + } else { + virtualPixel = 0.5f * (rawData[row - dy][col - 1] + rawData[row - dy][col + 1]); + } + + // and weight as usual. Distance to P is 2 => weighting is 0.5f + float dirwt = 0.5f / ( fabsf( virtualPixel - rawData[row + dy][col + dx]) + eps); + wtdsum += dirwt * (virtualPixel + rawData[row + dy][col + dx]); + norm += dirwt; + } + + if (LIKELY(norm > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% + rawData[row][col] = wtdsum / (2.f * norm); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps //#pragma omp critical -// printf("%s Pixel at (col/row) : (%4d/%4d) : Original : %f, interpolated: %f\n",pixelColor == 0 ? "Red " : pixelColor==1 ? "Green" : "Blue ", col-7,row-7,oldval, rawData[row][col]); - counter++; - } - } - } - return counter; // Number of interpolated pixels. +// printf("%s Pixel at (col/row) : (%4d/%4d) : Original : %f, interpolated: %f\n",pixelColor == 0 ? "Red " : pixelColor==1 ? "Green" : "Blue ", col-7,row-7,oldval, rawData[row][col]); + counter++; + } + } + } + + return counter; // Number of interpolated pixels. } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -824,330 +946,376 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads ) */ int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels ) { - float varthresh = (20.0*(thresh/100.0) + 1.0 ); + float varthresh = (20.0 * (thresh / 100.0) + 1.0 ); - // counter for dead or hot pixels - int counter=0; - - // allocate temporary buffer - float (*cfablur); - cfablur = (float (*)) malloc (H*W * sizeof *cfablur); - -#pragma omp parallel -{ -#pragma omp for - for (int i=0; iH-3) {inext=i-2;} else {inext=i+2;} - for (int j=0; jW-3) {jnext=j-2;} else {jnext=j+2;} - med3x3(rawData[iprev][jprev],rawData[iprev][j],rawData[iprev][jnext], - rawData[i][jprev],rawData[i][j],rawData[i][jnext], - rawData[inext][jprev],rawData[inext][j],rawData[inext][jnext],temp); - cfablur[i*W+j] = rawData[i][j]-temp; - } - } -#pragma omp for reduction(+:counter) schedule (dynamic,16) - //cfa pixel heat/death evaluation - for (int rr=0; rr < H; rr++) { - int top=max(0,rr-2); - int bottom=min(H-1,rr+2); - int rrmWpcc = rr*W; - for (int cc=0; cc < W; cc++,rrmWpcc++) { - //evaluate pixel for heat/death - float pixdev = cfablur[rrmWpcc]; - if((!findDeadPixels) && pixdev <= 0) - continue; - if((!findHotPixels) && pixdev >= 0) - continue; - pixdev = fabsf(pixdev); - float hfnbrave = -pixdev; - int left=max(0,cc-2); - int right=min(W-1,cc+2); - for (int mm=top; mm<=bottom; mm++) { - int mmmWpnn = mm*W+left; - for (int nn=left; nn<=right; nn++,mmmWpnn++) { - hfnbrave += fabsf(cfablur[mmmWpnn]); - } - } - if (pixdev * ((bottom-top+1)*(right-left+1)-1) > varthresh*hfnbrave) { - // mark the pixel as "bad" - bpMap.set(cc,rr); - counter++; - } - }//end of pixel evaluation - } -}//end of parallel processing - free (cfablur); - return counter; + // counter for dead or hot pixels + int counter = 0; + + // allocate temporary buffer + float (*cfablur); + cfablur = (float (*)) malloc (H * W * sizeof * cfablur); + + #pragma omp parallel + { + #pragma omp for + + for (int i = 0; i < H; i++) { + int iprev, inext, jprev, jnext; + float p[9], temp; + + if (i < 2) { + iprev = i + 2; + } else { + iprev = i - 2; + } + + if (i > H - 3) { + inext = i - 2; + } else { + inext = i + 2; + } + + for (int j = 0; j < W; j++) { + if (j < 2) { + jprev = j + 2; + } else { + jprev = j - 2; + } + + if (j > W - 3) { + jnext = j - 2; + } else { + jnext = j + 2; + } + + med3x3(rawData[iprev][jprev], rawData[iprev][j], rawData[iprev][jnext], + rawData[i][jprev], rawData[i][j], rawData[i][jnext], + rawData[inext][jprev], rawData[inext][j], rawData[inext][jnext], temp); + cfablur[i * W + j] = rawData[i][j] - temp; + } + } + + #pragma omp for reduction(+:counter) schedule (dynamic,16) + + //cfa pixel heat/death evaluation + for (int rr = 0; rr < H; rr++) { + int top = max(0, rr - 2); + int bottom = min(H - 1, rr + 2); + int rrmWpcc = rr * W; + + for (int cc = 0; cc < W; cc++, rrmWpcc++) { + //evaluate pixel for heat/death + float pixdev = cfablur[rrmWpcc]; + + if((!findDeadPixels) && pixdev <= 0) { + continue; + } + + if((!findHotPixels) && pixdev >= 0) { + continue; + } + + pixdev = fabsf(pixdev); + float hfnbrave = -pixdev; + int left = max(0, cc - 2); + int right = min(W - 1, cc + 2); + + for (int mm = top; mm <= bottom; mm++) { + int mmmWpnn = mm * W + left; + + for (int nn = left; nn <= right; nn++, mmmWpnn++) { + hfnbrave += fabsf(cfablur[mmmWpnn]); + } + } + + if (pixdev * ((bottom - top + 1) * (right - left + 1) - 1) > varthresh * hfnbrave) { + // mark the pixel as "bad" + bpMap.set(cc, rr); + counter++; + } + }//end of pixel evaluation + } + }//end of parallel processing + free (cfablur); + return counter; } -void RawImageSource::rotateLine (float* line, PlanarPtr &channel, int tran, int i, int w, int h) { +void RawImageSource::rotateLine (float* line, PlanarPtr &channel, int tran, int i, int w, int h) +{ - if ((tran & TR_ROT) == TR_R180) - for (int j=0; j=0 && yheight && y>=0 && xwidth) { - image->r(image->height-1-y,image->width-1-x) = red[j]; - image->g(image->height-1-y,image->width-1-x) = green[j]; - image->b(image->height-1-y,image->width-1-x) = blue[j]; - } - } - } - else if ((tran & TR_ROT) == TR_R270) { - int end = min(h+fw-i, w-fw+i); - for (int j=start; j=0 && xheight && y>=0 && ywidth) { - image->r(image->height-1-x,y) = red[j]; - image->g(image->height-1-x,y) = green[j]; - image->b(image->height-1-x,y) = blue[j]; - } - } - } - else if ((tran & TR_ROT) == TR_R90) { - int end = min(h+fw-i, w-fw+i); - for (int j=start; j=0 && ywidth && y>=0 && xheight) { - image->r(x,image->width-1-y) = red[j]; - image->g(x,image->width-1-y) = green[j]; - image->b(x,image->width-1-y) = blue[j]; - } - } - } - else { - int end = min(h+fw-i, w-fw+i); - for (int j=start; j=0 && yheight && y>=0 && xwidth) { - image->r(y,x) = red[j]; - image->g(y,x) = green[j]; - image->b(y,x) = blue[j]; - } - } - } - } - // Nikon D1X vertical interpolation + coarse rotation - else if (d1x) { - // copy new pixels - if ((tran & TR_ROT) == TR_R180) { - for (int j=0; jr(2*imheight-2-2*i,imwidth-1-j) = red[j]; - image->g(2*imheight-2-2*i,imwidth-1-j) = green[j]; - image->b(2*imheight-2-2*i,imwidth-1-j) = blue[j]; - } + if ((tran & TR_ROT) == TR_R180) { + int end = min(h + fw - i, w - fw + i); - if (i==1 || i==2) { // linear interpolation - int row = 2*imheight-1-2*i; - for (int j=0; jr(row,col) = (red[j] + image->r(row+1,col)) /2; - image->g(row,col) = (green[j] + image->g(row+1,col)) /2; - image->b(row,col) = (blue[j] + image->b(row+1,col)) /2; + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && y < image->height && y >= 0 && x < image->width) { + image->r(image->height - 1 - y, image->width - 1 - x) = red[j]; + image->g(image->height - 1 - y, image->width - 1 - x) = green[j]; + image->b(image->height - 1 - y, image->width - 1 - x) = blue[j]; + } + } + } else if ((tran & TR_ROT) == TR_R270) { + int end = min(h + fw - i, w - fw + i); + + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && x < image->height && y >= 0 && y < image->width) { + image->r(image->height - 1 - x, y) = red[j]; + image->g(image->height - 1 - x, y) = green[j]; + image->b(image->height - 1 - x, y) = blue[j]; + } + } + } else if ((tran & TR_ROT) == TR_R90) { + int end = min(h + fw - i, w - fw + i); + + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && y < image->width && y >= 0 && x < image->height) { + image->r(x, image->width - 1 - y) = red[j]; + image->g(x, image->width - 1 - y) = green[j]; + image->b(x, image->width - 1 - y) = blue[j]; + } + } + } else { + int end = min(h + fw - i, w - fw + i); + + for (int j = start; j < end; j++) { + int y = i + j - fw; + int x = fw - i + j; + + if (x >= 0 && y < image->height && y >= 0 && x < image->width) { + image->r(y, x) = red[j]; + image->g(y, x) = green[j]; + image->b(y, x) = blue[j]; + } + } } - } - else if (i==imheight-1) { - int row = 2*imheight-1-2*i; - for (int j=0; jr(row,col) = (red[j] + image->r(row+1,col)) /2; - image->g(row,col) = (green[j] + image->g(row+1,col)) /2; - image->b(row,col) = (blue[j] + image->b(row+1,col)) /2; - } - row = 2*imheight-1-2*i+2; - for (int j=0; jr(row,col) = (red[j] + image->r(row+1,col)) /2; - image->g(row,col) = (green[j] + image->g(row+1,col)) /2; - image->b(row,col) = (blue[j] + image->b(row+1,col)) /2; - } - } - else if (i>2 && ir(row,col) = CLIP((int)(-0.0625*red[j] + 0.5625*image->r(row-1,col) + 0.5625*image->r(row+1,col) - 0.0625*image->r(row+3,col))); - image->g(row,col) = CLIP((int)(-0.0625*green[j] + 0.5625*image->g(row-1,col) + 0.5625*image->g(row+1,col) - 0.0625*image->g(row+3,col))); - image->b(row,col) = CLIP((int)(-0.0625*blue[j] + 0.5625*image->b(row-1,col) + 0.5625*image->b(row+1,col) - 0.0625*image->b(row+3,col))); - } - } } - else if ((tran & TR_ROT) == TR_R90) { - for (int j=0; jr(j,2*imheight-2-2*i) = red[j]; - image->g(j,2*imheight-2-2*i) = green[j]; - image->b(j,2*imheight-2-2*i) = blue[j]; - } - if (i==1 || i==2) { // linear interpolation - int col = 2*imheight-1-2*i; - for (int j=0; jr(j,col) = (red[j] + image->r(j,col+1)) /2; - image->g(j,col) = (green[j] + image->g(j,col+1)) /2; - image->b(j,col) = (blue[j] + image->b(j,col+1)) /2; + // Nikon D1X vertical interpolation + coarse rotation + else if (d1x) { + // copy new pixels + if ((tran & TR_ROT) == TR_R180) { + for (int j = 0; j < imwidth; j++) { + image->r(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = red[j]; + image->g(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = green[j]; + image->b(2 * imheight - 2 - 2 * i, imwidth - 1 - j) = blue[j]; + } + + if (i == 1 || i == 2) { // linear interpolation + int row = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; + image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; + } + } else if (i == imheight - 1) { + int row = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; + image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; + } + + row = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = (red[j] + image->r(row + 1, col)) / 2; + image->g(row, col) = (green[j] + image->g(row + 1, col)) / 2; + image->b(row, col) = (blue[j] + image->b(row + 1, col)) / 2; + } + } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolation + int row = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + int col = imwidth - 1 - j; + image->r(row, col) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(row - 1, col) + 0.5625 * image->r(row + 1, col) - 0.0625 * image->r(row + 3, col))); + image->g(row, col) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(row - 1, col) + 0.5625 * image->g(row + 1, col) - 0.0625 * image->g(row + 3, col))); + image->b(row, col) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(row - 1, col) + 0.5625 * image->b(row + 1, col) - 0.0625 * image->b(row + 3, col))); + } + } + } else if ((tran & TR_ROT) == TR_R90) { + for (int j = 0; j < imwidth; j++) { + image->r(j, 2 * imheight - 2 - 2 * i) = red[j]; + image->g(j, 2 * imheight - 2 - 2 * i) = green[j]; + image->b(j, 2 * imheight - 2 - 2 * i) = blue[j]; + } + + if (i == 1 || i == 2) { // linear interpolation + int col = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; + image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; + image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + } + } else if (i == imheight - 1) { + int col = 2 * imheight - 1 - 2 * i; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; + image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; + image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + } + + col = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = (red[j] + image->r(j, col + 1)) / 2; + image->g(j, col) = (green[j] + image->g(j, col + 1)) / 2; + image->b(j, col) = (blue[j] + image->b(j, col + 1)) / 2; + } + } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolation + int col = 2 * imheight - 1 - 2 * i + 2; + + for (int j = 0; j < imwidth; j++) { + image->r(j, col) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(j, col - 1) + 0.5625 * image->r(j, col + 1) - 0.0625 * image->r(j, col + 3))); + image->g(j, col) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(j, col - 1) + 0.5625 * image->g(j, col + 1) - 0.0625 * image->g(j, col + 3))); + image->b(j, col) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(j, col - 1) + 0.5625 * image->b(j, col + 1) - 0.0625 * image->b(j, col + 3))); + } + } + } else if ((tran & TR_ROT) == TR_R270) { + for (int j = 0; j < imwidth; j++) { + image->r(imwidth - 1 - j, 2 * i) = red[j]; + image->g(imwidth - 1 - j, 2 * i) = green[j]; + image->b(imwidth - 1 - j, 2 * i) = blue[j]; + } + + if (i == 1 || i == 2) { // linear interpolation + for (int j = 0; j < imwidth; j++) { + int row = imwidth - 1 - j; + image->r(row, 2 * i - 1) = (red[j] + image->r(row, 2 * i - 2)) * 0.5f; + image->g(row, 2 * i - 1) = (green[j] + image->g(row, 2 * i - 2)) * 0.5f; + image->b(row, 2 * i - 1) = (blue[j] + image->b(row, 2 * i - 2)) * 0.5f; + } + } else if (i == imheight - 1) { + for (int j = 0; j < imwidth; j++) { + int row = imwidth - 1 - j; + image->r(row, 2 * i - 1) = (red[j] + image->r(row, 2 * i - 2)) * 0.5f; + image->g(row, 2 * i - 1) = (green[j] + image->g(row, 2 * i - 2)) * 0.5f; + image->b(row, 2 * i - 1) = (blue[j] + image->b(row, 2 * i - 2)) * 0.5f; + image->r(row, 2 * i - 3) = (image->r(row, 2 * i - 2) + image->r(row, 2 * i - 4)) * 0.5f; + image->g(row, 2 * i - 3) = (image->g(row, 2 * i - 2) + image->g(row, 2 * i - 4)) * 0.5f; + image->b(row, 2 * i - 3) = (image->b(row, 2 * i - 2) + image->b(row, 2 * i - 4)) * 0.5f; + } + } else if (i > 0 && i < imheight - 1) { // vertical bicubic interpolationi + for (int j = 0; j < imwidth; j++) { + int row = imwidth - 1 - j; + image->r(row, 2 * i - 3) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(row, 2 * i - 2) + 0.5625 * image->r(row, 2 * i - 4) - 0.0625 * image->r(row, 2 * i - 6))); + image->g(row, 2 * i - 3) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(row, 2 * i - 2) + 0.5625 * image->g(row, 2 * i - 4) - 0.0625 * image->g(row, 2 * i - 6))); + image->b(row, 2 * i - 3) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(row, 2 * i - 2) + 0.5625 * image->b(row, 2 * i - 4) - 0.0625 * image->b(row, 2 * i - 6))); + } + } + } else { + rotateLine (red, image->r, tran, 2 * i, imwidth, imheight); + rotateLine (green, image->g, tran, 2 * i, imwidth, imheight); + rotateLine (blue, image->b, tran, 2 * i, imwidth, imheight); + + if (i == 1 || i == 2) { // linear interpolation + for (int j = 0; j < imwidth; j++) { + image->r(2 * i - 1, j) = (red[j] + image->r(2 * i - 2, j)) / 2; + image->g(2 * i - 1, j) = (green[j] + image->g(2 * i - 2, j)) / 2; + image->b(2 * i - 1, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; + } + } else if (i == imheight - 1) { + for (int j = 0; j < imwidth; j++) { + image->r(2 * i - 3, j) = (image->r(2 * i - 4, j) + image->r(2 * i - 2, j)) / 2; + image->g(2 * i - 3, j) = (image->g(2 * i - 4, j) + image->g(2 * i - 2, j)) / 2; + image->b(2 * i - 3, j) = (image->b(2 * i - 4, j) + image->b(2 * i - 2, j)) / 2; + image->r(2 * i - 1, j) = (red[j] + image->r(2 * i - 2, j)) / 2; + image->g(2 * i - 1, j) = (green[j] + image->g(2 * i - 2, j)) / 2; + image->b(2 * i - 1, j) = (blue[j] + image->b(2 * i - 2, j)) / 2; + } + } else if (i > 2 && i < imheight - 1) { // vertical bicubic interpolationi + for (int j = 0; j < imwidth; j++) { + image->r(2 * i - 3, j) = CLIP((int)(-0.0625 * red[j] + 0.5625 * image->r(2 * i - 2, j) + 0.5625 * image->r(2 * i - 4, j) - 0.0625 * image->r(2 * i - 6, j))); + image->g(2 * i - 3, j) = CLIP((int)(-0.0625 * green[j] + 0.5625 * image->g(2 * i - 2, j) + 0.5625 * image->g(2 * i - 4, j) - 0.0625 * image->g(2 * i - 6, j))); + image->b(2 * i - 3, j) = CLIP((int)(-0.0625 * blue[j] + 0.5625 * image->b(2 * i - 2, j) + 0.5625 * image->b(2 * i - 4, j) - 0.0625 * image->b(2 * i - 6, j))); + } + } } - } - else if (i==imheight-1) { - int col = 2*imheight-1-2*i; - for (int j=0; jr(j,col) = (red[j] + image->r(j,col+1)) /2; - image->g(j,col) = (green[j] + image->g(j,col+1)) /2; - image->b(j,col) = (blue[j] + image->b(j,col+1)) /2; - } - col = 2*imheight-1-2*i+2; - for (int j=0; jr(j,col) = (red[j] + image->r(j,col+1)) /2; - image->g(j,col) = (green[j] + image->g(j,col+1)) /2; - image->b(j,col) = (blue[j] + image->b(j,col+1)) /2; - } - } - else if (i>2 && ir(j,col) = CLIP((int)(-0.0625*red[j] + 0.5625*image->r(j,col-1) + 0.5625*image->r(j,col+1) - 0.0625*image->r(j,col+3))); - image->g(j,col) = CLIP((int)(-0.0625*green[j] + 0.5625*image->g(j,col-1) + 0.5625*image->g(j,col+1) - 0.0625*image->g(j,col+3))); - image->b(j,col) = CLIP((int)(-0.0625*blue[j] + 0.5625*image->b(j,col-1) + 0.5625*image->b(j,col+1) - 0.0625*image->b(j,col+3))); - } - } - } - else if ((tran & TR_ROT) == TR_R270) { - for (int j=0; jr(imwidth-1-j,2*i) = red[j]; - image->g(imwidth-1-j,2*i) = green[j]; - image->b(imwidth-1-j,2*i) = blue[j]; - } - if (i==1 || i==2) { // linear interpolation - for (int j=0; jr(row,2*i-1) = (red[j] + image->r(row,2*i-2)) * 0.5f; - image->g(row,2*i-1) = (green[j] + image->g(row,2*i-2)) * 0.5f; - image->b(row,2*i-1) = (blue[j] + image->b(row,2*i-2)) * 0.5f; - } - } - else if (i==imheight-1) { - for (int j=0; jr(row,2*i-1) = (red[j] + image->r(row,2*i-2)) * 0.5f; - image->g(row,2*i-1) = (green[j] + image->g(row,2*i-2)) * 0.5f; - image->b(row,2*i-1) = (blue[j] + image->b(row,2*i-2)) * 0.5f; - image->r(row,2*i-3) = (image->r(row,2*i-2) + image->r(row,2*i-4)) * 0.5f; - image->g(row,2*i-3) = (image->g(row,2*i-2) + image->g(row,2*i-4)) * 0.5f; - image->b(row,2*i-3) = (image->b(row,2*i-2) + image->b(row,2*i-4)) * 0.5f; - } - } - else if (i>0 && ir(row,2*i-3) = CLIP((int)(-0.0625*red[j] + 0.5625*image->r(row,2*i-2) + 0.5625*image->r(row,2*i-4) - 0.0625*image->r(row,2*i-6))); - image->g(row,2*i-3) = CLIP((int)(-0.0625*green[j] + 0.5625*image->g(row,2*i-2) + 0.5625*image->g(row,2*i-4) - 0.0625*image->g(row,2*i-6))); - image->b(row,2*i-3) = CLIP((int)(-0.0625*blue[j] + 0.5625*image->b(row,2*i-2) + 0.5625*image->b(row,2*i-4) - 0.0625*image->b(row,2*i-6))); - } - } - } + } // if nikon dx1 + // other (conventional) CCD coarse rotation else { - rotateLine (red, image->r, tran, 2*i, imwidth, imheight); - rotateLine (green, image->g, tran, 2*i, imwidth, imheight); - rotateLine (blue, image->b, tran, 2*i, imwidth, imheight); - - if (i==1 || i==2) { // linear interpolation - for (int j=0; jr(2*i-1,j) = (red[j] + image->r(2*i-2,j)) /2; - image->g(2*i-1,j) = (green[j] + image->g(2*i-2,j)) /2; - image->b(2*i-1,j) = (blue[j] + image->b(2*i-2,j)) /2; - } - } - else if (i==imheight-1) { - for (int j=0; jr(2*i-3,j) = (image->r(2*i-4,j) + image->r(2*i-2,j)) /2; - image->g(2*i-3,j) = (image->g(2*i-4,j) + image->g(2*i-2,j)) /2; - image->b(2*i-3,j) = (image->b(2*i-4,j) + image->b(2*i-2,j)) /2; - image->r(2*i-1,j) = (red[j] + image->r(2*i-2,j)) /2; - image->g(2*i-1,j) = (green[j] + image->g(2*i-2,j)) /2; - image->b(2*i-1,j) = (blue[j] + image->b(2*i-2,j)) /2; - } - } - else if (i>2 && ir(2*i-3,j) = CLIP((int)(-0.0625*red[j] + 0.5625*image->r(2*i-2,j) + 0.5625*image->r(2*i-4,j) - 0.0625*image->r(2*i-6,j))); - image->g(2*i-3,j) = CLIP((int)(-0.0625*green[j] + 0.5625*image->g(2*i-2,j) + 0.5625*image->g(2*i-4,j) - 0.0625*image->g(2*i-6,j))); - image->b(2*i-3,j) = CLIP((int)(-0.0625*blue[j] + 0.5625*image->b(2*i-2,j) + 0.5625*image->b(2*i-4,j) - 0.0625*image->b(2*i-6,j))); - } - } + rotateLine (red, image->r, tran, i, imwidth, imheight); + rotateLine (green, image->g, tran, i, imwidth, imheight); + rotateLine (blue, image->b, tran, i, imwidth, imheight); } - } // if nikon dx1 - // other (conventional) CCD coarse rotation - else { - rotateLine (red, image->r, tran, i, imwidth, imheight); - rotateLine (green, image->g, tran, i, imwidth, imheight); - rotateLine (blue, image->b, tran, i, imwidth, imheight); - } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::getFullSize (int& w, int& h, int tr) { +void RawImageSource::getFullSize (int& w, int& h, int tr) +{ tr = defTransform (tr); if (fuji) { w = ri->get_FujiWidth() * 2 + 1; - h = (H - ri->get_FujiWidth())*2 + 1; - } - else if (d1x) { + h = (H - ri->get_FujiWidth()) * 2 + 1; + } else if (d1x) { w = W; - h = 2*H-1; - } - else { + h = 2 * H - 1; + } else { w = W; h = H; } - + if ((tr & TR_ROT) == TR_R90 || (tr & TR_ROT) == TR_R270) { int tmp = w; w = h; h = tmp; } + w -= 2 * border; h -= 2 * border; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::getSize (int tran, PreviewProps pp, int& w, int& h) { + +void RawImageSource::getSize (int tran, PreviewProps pp, int& w, int& h) +{ tran = defTransform (tran); @@ -1158,30 +1326,33 @@ void RawImageSource::getSize (int tran, PreviewProps pp, int& w, int& h) { // return; // } // else { - w = pp.w / pp.skip + (pp.w % pp.skip > 0); - h = pp.h / pp.skip + (pp.h % pp.skip > 0); + w = pp.w / pp.skip + (pp.w % pp.skip > 0); + h = pp.h / pp.skip + (pp.h % pp.skip > 0); // } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::hflip (Imagefloat* image) { +void RawImageSource::hflip (Imagefloat* image) +{ image->hflip(); } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::vflip (Imagefloat* image) { +void RawImageSource::vflip (Imagefloat* image) +{ image->vflip(); } - - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -int RawImageSource::load (Glib::ustring fname, bool batch) { - MyTime t1,t2; - t1.set(); + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +int RawImageSource::load (Glib::ustring fname, bool batch) +{ + + MyTime t1, t2; + t1.set(); fileName = fname; if (plistener) { @@ -1191,111 +1362,128 @@ int RawImageSource::load (Glib::ustring fname, bool batch) { ri = new RawImage(fname); int errCode = ri->loadRaw (true, true, plistener, 0.8); - if (errCode) return errCode; + + if (errCode) { + return errCode; + } ri->compress_image(); + if (plistener) { plistener->setProgress (0.9); } -/***** Copy once constant data extracted from raw *******/ + + /***** Copy once constant data extracted from raw *******/ W = ri->get_width(); H = ri->get_height(); - fuji = ri->get_FujiWidth()!=0; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - imatrices.rgb_cam[i][j] = ri->get_rgb_cam(i,j); + fuji = ri->get_FujiWidth() != 0; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + imatrices.rgb_cam[i][j] = ri->get_rgb_cam(i, j); + } + // compute inverse of the color transformation matrix - // first arg is matrix, second arg is inverse + // first arg is matrix, second arg is inverse inverse33 (imatrices.rgb_cam, imatrices.cam_rgb); d1x = ! ri->get_model().compare("D1X"); - if (d1x) + + if (d1x) { border = 8; + } - if(ri->getSensorType()==ST_FUJI_XTRANS) - border = 7; - else if(ri->getSensorType()==ST_FOVEON) - border = 0; + if(ri->getSensorType() == ST_FUJI_XTRANS) { + border = 7; + } else if(ri->getSensorType() == ST_FOVEON) { + border = 0; + } - if ( ri->get_profile() ) + if ( ri->get_profile() ) { embProfile = cmsOpenProfileFromMem (ri->get_profile(), ri->get_profileLen()); + } // create profile memset (imatrices.xyz_cam, 0, sizeof(imatrices.xyz_cam)); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) - imatrices.xyz_cam[i][j] += xyz_sRGB[i][k] * imatrices.rgb_cam[k][j]; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { + imatrices.xyz_cam[i][j] += xyz_sRGB[i][k] * imatrices.rgb_cam[k][j]; + } + camProfile = iccStore->createFromMatrix (imatrices.xyz_cam, false, "Camera"); inverse33 (imatrices.xyz_cam, imatrices.cam_xyz); - for (int c = 0; c < 4; c++) { - c_white[c] = ri->get_white(c); - } - // First we get the "as shot" ("Camera") white balance and store it - float pre_mul[4]; - // FIXME: get_colorsCoeff not so much used nowadays, when we have calculate_scale_mul() function here - ri->get_colorsCoeff( pre_mul, scale_mul, c_black, false);//modify for black level - camInitialGain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); + for (int c = 0; c < 4; c++) { + c_white[c] = ri->get_white(c); + } - double camwb_red = ri->get_pre_mul(0) / pre_mul[0]; - double camwb_green = ri->get_pre_mul(1) / pre_mul[1]; - double camwb_blue = ri->get_pre_mul(2) / pre_mul[2]; - double cam_r = imatrices.rgb_cam[0][0]*camwb_red + imatrices.rgb_cam[0][1]*camwb_green + imatrices.rgb_cam[0][2]*camwb_blue; - double cam_g = imatrices.rgb_cam[1][0]*camwb_red + imatrices.rgb_cam[1][1]*camwb_green + imatrices.rgb_cam[1][2]*camwb_blue; - double cam_b = imatrices.rgb_cam[2][0]*camwb_red + imatrices.rgb_cam[2][1]*camwb_green + imatrices.rgb_cam[2][2]*camwb_blue; - camera_wb = ColorTemp (cam_r, cam_g, cam_b, 1.); // as shot WB + // First we get the "as shot" ("Camera") white balance and store it + float pre_mul[4]; + // FIXME: get_colorsCoeff not so much used nowadays, when we have calculate_scale_mul() function here + ri->get_colorsCoeff( pre_mul, scale_mul, c_black, false);//modify for black level + camInitialGain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); - ColorTemp ReferenceWB; - double ref_r, ref_g, ref_b; - { - // ...then we re-get the constants but now with auto which gives us better demosaicing and CA auto-correct - // performance for strange white balance settings (such as UniWB) - ri->get_colorsCoeff( ref_pre_mul, scale_mul, c_black, true); - refwb_red = ri->get_pre_mul(0) / ref_pre_mul[0]; - refwb_green = ri->get_pre_mul(1) / ref_pre_mul[1]; - refwb_blue = ri->get_pre_mul(2) / ref_pre_mul[2]; - initialGain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); - ref_r = imatrices.rgb_cam[0][0]*refwb_red + imatrices.rgb_cam[0][1]*refwb_green + imatrices.rgb_cam[0][2]*refwb_blue; - ref_g = imatrices.rgb_cam[1][0]*refwb_red + imatrices.rgb_cam[1][1]*refwb_green + imatrices.rgb_cam[1][2]*refwb_blue; - ref_b = imatrices.rgb_cam[2][0]*refwb_red + imatrices.rgb_cam[2][1]*refwb_green + imatrices.rgb_cam[2][2]*refwb_blue; - ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1.); - } - if (settings->verbose) { - printf("Raw As Shot White balance: temp %f, tint %f\n", camera_wb.getTemp(), camera_wb.getGreen()); - printf("Raw Reference (auto) white balance: temp %f, tint %f, multipliers [%f %f %f | %f %f %f]\n", ReferenceWB.getTemp(), ReferenceWB.getGreen(), ref_r, ref_g, ref_b, refwb_red, refwb_blue, refwb_green); - } + double camwb_red = ri->get_pre_mul(0) / pre_mul[0]; + double camwb_green = ri->get_pre_mul(1) / pre_mul[1]; + double camwb_blue = ri->get_pre_mul(2) / pre_mul[2]; + double cam_r = imatrices.rgb_cam[0][0] * camwb_red + imatrices.rgb_cam[0][1] * camwb_green + imatrices.rgb_cam[0][2] * camwb_blue; + double cam_g = imatrices.rgb_cam[1][0] * camwb_red + imatrices.rgb_cam[1][1] * camwb_green + imatrices.rgb_cam[1][2] * camwb_blue; + double cam_b = imatrices.rgb_cam[2][0] * camwb_red + imatrices.rgb_cam[2][1] * camwb_green + imatrices.rgb_cam[2][2] * camwb_blue; + camera_wb = ColorTemp (cam_r, cam_g, cam_b, 1.); // as shot WB - /*{ - // Test code: if you want to test a specific white balance - ColorTemp d50wb = ColorTemp(5000.0, 1.0, 1.0, "Custom"); - double rm,gm,bm,r,g,b; - d50wb.getMultipliers(r, g, b); - camwb_red = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; - camwb_green = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; - camwb_blue = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; - double pre_mul[3], dmax = 0; - pre_mul[0] = ri->get_pre_mul(0) / camwb_red; - pre_mul[1] = ri->get_pre_mul(1) / camwb_green; - pre_mul[2] = ri->get_pre_mul(2) / camwb_blue; - for (int c = 0; c < 3; c++) { - if (dmax < pre_mul[c]) - dmax = pre_mul[c]; + ColorTemp ReferenceWB; + double ref_r, ref_g, ref_b; + { + // ...then we re-get the constants but now with auto which gives us better demosaicing and CA auto-correct + // performance for strange white balance settings (such as UniWB) + ri->get_colorsCoeff( ref_pre_mul, scale_mul, c_black, true); + refwb_red = ri->get_pre_mul(0) / ref_pre_mul[0]; + refwb_green = ri->get_pre_mul(1) / ref_pre_mul[1]; + refwb_blue = ri->get_pre_mul(2) / ref_pre_mul[2]; + initialGain = max(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min(scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); + ref_r = imatrices.rgb_cam[0][0] * refwb_red + imatrices.rgb_cam[0][1] * refwb_green + imatrices.rgb_cam[0][2] * refwb_blue; + ref_g = imatrices.rgb_cam[1][0] * refwb_red + imatrices.rgb_cam[1][1] * refwb_green + imatrices.rgb_cam[1][2] * refwb_blue; + ref_b = imatrices.rgb_cam[2][0] * refwb_red + imatrices.rgb_cam[2][1] * refwb_green + imatrices.rgb_cam[2][2] * refwb_blue; + ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1.); + } + + if (settings->verbose) { + printf("Raw As Shot White balance: temp %f, tint %f\n", camera_wb.getTemp(), camera_wb.getGreen()); + printf("Raw Reference (auto) white balance: temp %f, tint %f, multipliers [%f %f %f | %f %f %f]\n", ReferenceWB.getTemp(), ReferenceWB.getGreen(), ref_r, ref_g, ref_b, refwb_red, refwb_blue, refwb_green); + } + + /*{ + // Test code: if you want to test a specific white balance + ColorTemp d50wb = ColorTemp(5000.0, 1.0, 1.0, "Custom"); + double rm,gm,bm,r,g,b; + d50wb.getMultipliers(r, g, b); + camwb_red = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; + camwb_green = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; + camwb_blue = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; + double pre_mul[3], dmax = 0; + pre_mul[0] = ri->get_pre_mul(0) / camwb_red; + pre_mul[1] = ri->get_pre_mul(1) / camwb_green; + pre_mul[2] = ri->get_pre_mul(2) / camwb_blue; + for (int c = 0; c < 3; c++) { + if (dmax < pre_mul[c]) + dmax = pre_mul[c]; } for (int c = 0; c < 3; c++) { - pre_mul[c] /= dmax; + pre_mul[c] /= dmax; } camwb_red *= dmax; camwb_green *= dmax; camwb_blue *= dmax; for (int c = 0; c < 3; c++) { - int sat = ri->get_white(c) - ri->get_cblack(c); - scale_mul[c] = pre_mul[c] * 65535.0 / sat; + int sat = ri->get_white(c) - ri->get_cblack(c); + scale_mul[c] = pre_mul[c] * 65535.0 / sat; } scale_mul[3] = pre_mul[1] * 65535.0 / (ri->get_white(3) - ri->get_cblack(3)); initialGain = 1.0 / min(pre_mul[0], pre_mul[1], pre_mul[2]); - }*/ - + }*/ + ri->set_prefilters(); @@ -1306,113 +1494,133 @@ int RawImageSource::load (Glib::ustring fname, bool batch) { rml.ciffLength = ri->get_ciffLen(); idata = new ImageData (fname, &rml); - green(W,H); - red(W,H); - blue(W,H); + green(W, H); + red(W, H); + blue(W, H); //hpmap = allocArray(W, H); if (plistener) { plistener->setProgress (1.0); } - plistener=NULL; // This must be reset, because only load() is called through progressConnector + + plistener = NULL; // This must be reset, because only load() is called through progressConnector t2.set(); - if( settings->verbose ) - printf("Load %s: %d usec\n",fname.c_str(), t2.etime(t1)); + + if( settings->verbose ) { + printf("Load %s: %d usec\n", fname.c_str(), t2.etime(t1)); + } return 0; // OK! } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse) { - MyTime t1,t2; - t1.set(); + MyTime t1, t2; + t1.set(); - Glib::ustring newDF = raw.dark_frame; - RawImage *rid=NULL; - if (!raw.df_autoselect) { - if( !raw.dark_frame.empty()) - rid = dfm.searchDarkFrame( raw.dark_frame ); - } else { - rid = dfm.searchDarkFrame( ri->get_maker(), ri->get_model(), ri->get_ISOspeed(), ri->get_shutter(), ri->get_timestamp()); - } - if( rid && settings->verbose){ - printf( "Subtracting Darkframe:%s\n",rid->get_filename().c_str()); - } + Glib::ustring newDF = raw.dark_frame; + RawImage *rid = NULL; - PixelsMap bitmapBads(W,H); - int totBP=0; // Hold count of bad pixels to correct + if (!raw.df_autoselect) { + if( !raw.dark_frame.empty()) { + rid = dfm.searchDarkFrame( raw.dark_frame ); + } + } else { + rid = dfm.searchDarkFrame( ri->get_maker(), ri->get_model(), ri->get_ISOspeed(), ri->get_shutter(), ri->get_timestamp()); + } - if(ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica) -#pragma omp parallel for reduction(+:totBP) - for(int i=0;idata[i][j] == 0.f) { - bitmapBads.set(j,i); - totBP++; - } - } - if( settings->verbose) { - printf( "%d pixels with value zero marked as bad pixels\n",totBP); - } - } + if( rid && settings->verbose) { + printf( "Subtracting Darkframe:%s\n", rid->get_filename().c_str()); + } - //FLATFIELD start - Glib::ustring newFF = raw.ff_file; - RawImage *rif=NULL; - if (!raw.ff_AutoSelect) { - if( !raw.ff_file.empty()) - rif = ffm.searchFlatField( raw.ff_file ); - } else { - rif = ffm.searchFlatField( idata->getMake(), idata->getModel(),idata->getLens(),idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS()); - } + PixelsMap bitmapBads(W, H); + int totBP = 0; // Hold count of bad pixels to correct + + if(ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica) + #pragma omp parallel for reduction(+:totBP) + for(int i = 0; i < H; i++) + for(int j = 0; j < W; j++) { + if(ri->data[i][j] == 0.f) { + bitmapBads.set(j, i); + totBP++; + } + } + + if( settings->verbose) { + printf( "%d pixels with value zero marked as bad pixels\n", totBP); + } + } + + //FLATFIELD start + Glib::ustring newFF = raw.ff_file; + RawImage *rif = NULL; + + if (!raw.ff_AutoSelect) { + if( !raw.ff_file.empty()) { + rif = ffm.searchFlatField( raw.ff_file ); + } + } else { + rif = ffm.searchFlatField( idata->getMake(), idata->getModel(), idata->getLens(), idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS()); + } - bool hasFlatField = (rif!=NULL); - if( hasFlatField && settings->verbose) { - printf( "Flat Field Correction:%s\n",rif->get_filename().c_str()); - } + bool hasFlatField = (rif != NULL); - copyOriginalPixels(raw, ri, rid, rif); - //FLATFIELD end - + if( hasFlatField && settings->verbose) { + printf( "Flat Field Correction:%s\n", rif->get_filename().c_str()); + } - // Always correct camera badpixels from .badpixels file - std::vector *bp = dfm.getBadPixels( ri->get_maker(), ri->get_model(), idata->getSerialNumber() ); - if( bp ){ - totBP+=bitmapBads.set( *bp ); - if( settings->verbose ){ - std::cout << "Correcting " << bp->size() << " pixels from .badpixels" << std::endl; - } - } - - // If darkframe selected, correct hotpixels found on darkframe - bp = 0; - if( raw.df_autoselect ){ - bp = dfm.getHotPixels( ri->get_maker(), ri->get_model(), ri->get_ISOspeed(), ri->get_shutter(), ri->get_timestamp()); - }else if( !raw.dark_frame.empty() ) - bp = dfm.getHotPixels( raw.dark_frame ); - if(bp){ - totBP+=bitmapBads.set( *bp ); - if( settings->verbose && !bp->empty()){ - std::cout << "Correcting " << bp->size() << " hotpixels from darkframe" << std::endl; - } - } + copyOriginalPixels(raw, ri, rid, rif); + //FLATFIELD end - scaleColors( 0,0, W, H, raw);//+ + raw parameters for black level(raw.blackxx) + // Always correct camera badpixels from .badpixels file + std::vector *bp = dfm.getBadPixels( ri->get_maker(), ri->get_model(), idata->getSerialNumber() ); + + if( bp ) { + totBP += bitmapBads.set( *bp ); + + if( settings->verbose ) { + std::cout << "Correcting " << bp->size() << " pixels from .badpixels" << std::endl; + } + } + + // If darkframe selected, correct hotpixels found on darkframe + bp = 0; + + if( raw.df_autoselect ) { + bp = dfm.getHotPixels( ri->get_maker(), ri->get_model(), ri->get_ISOspeed(), ri->get_shutter(), ri->get_timestamp()); + } else if( !raw.dark_frame.empty() ) { + bp = dfm.getHotPixels( raw.dark_frame ); + } + + if(bp) { + totBP += bitmapBads.set( *bp ); + + if( settings->verbose && !bp->empty()) { + std::cout << "Correcting " << bp->size() << " hotpixels from darkframe" << std::endl; + } + } + + + scaleColors( 0, 0, W, H, raw); //+ + raw parameters for black level(raw.blackxx) // Correct vignetting of lens profile if (!hasFlatField && lensProf.useVign) { - LCPProfile *pLCPProf=lcpStore->getProfile(lensProf.lcpFile); + LCPProfile *pLCPProf = lcpStore->getProfile(lensProf.lcpFile); + if (pLCPProf && idata->getFocalLen() > 0.f) { LCPMapper map(pLCPProf, idata->getFocalLen(), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1); - + #pragma omp parallel for - for (int y=0; y0) rawData[y][x] *= map.calcVignetteFac(x,y); + + for (int y = 0; y < H; y++) { + for (int x = 0; x < W; x++) { + if (rawData[y][x] > 0) { + rawData[y][x] *= map.calcVignetteFac(x, y); + } } } } @@ -1420,382 +1628,440 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le defGain = 0.0;//log(initialGain) / log(2.0); - if ( ri->getSensorType()==ST_BAYER && (raw.hotPixelFilter>0 || raw.deadPixelFilter>0)) { - if (plistener) { - plistener->setProgressStr ("Hot/Dead Pixel Filter..."); - plistener->setProgress (0.0); - } - int nFound = findHotDeadPixels( bitmapBads, raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter ); - totBP += nFound; - if( settings->verbose && nFound>0){ - printf( "Correcting %d hot/dead pixels found inside image\n",nFound ); - } - } + if ( ri->getSensorType() == ST_BAYER && (raw.hotPixelFilter > 0 || raw.deadPixelFilter > 0)) { + if (plistener) { + plistener->setProgressStr ("Hot/Dead Pixel Filter..."); + plistener->setProgress (0.0); + } + + int nFound = findHotDeadPixels( bitmapBads, raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter ); + totBP += nFound; + + if( settings->verbose && nFound > 0) { + printf( "Correcting %d hot/dead pixels found inside image\n", nFound ); + } + } // check if it is an olympus E camera, if yes, compute G channel pre-compensation factors - if ( ri->getSensorType()==ST_BAYER && (raw.bayersensor.greenthresh || (((idata->getMake().size()>=7 && idata->getMake().substr(0,7)=="OLYMPUS" && idata->getModel()[0]=='E') || (idata->getMake().size()>=9 && idata->getMake().substr(0,9)=="Panasonic")) && raw.bayersensor.method != RAWParams::BayerSensor::methodstring[ RAWParams::BayerSensor::vng4])) ) { + if ( ri->getSensorType() == ST_BAYER && (raw.bayersensor.greenthresh || (((idata->getMake().size() >= 7 && idata->getMake().substr(0, 7) == "OLYMPUS" && idata->getModel()[0] == 'E') || (idata->getMake().size() >= 9 && idata->getMake().substr(0, 9) == "Panasonic")) && raw.bayersensor.method != RAWParams::BayerSensor::methodstring[ RAWParams::BayerSensor::vng4])) ) { // global correction - int ng1=0, ng2=0, i=0; - double avgg1=0., avgg2=0.; + int ng1 = 0, ng2 = 0, i = 0; + double avgg1 = 0., avgg2 = 0.; -#pragma omp parallel for default(shared) private(i) reduction(+: ng1, ng2, avgg1, avgg2) - for (i=border; iISGREEN(i,j)) { - if (i&1) { - avgg2 += rawData[i][j]; + #pragma omp parallel for default(shared) private(i) reduction(+: ng1, ng2, avgg1, avgg2) + + for (i = border; i < H - border; i++) + for (int j = border; j < W - border; j++) + if (ri->ISGREEN(i, j)) { + if (i & 1) { + avgg2 += rawData[i][j]; ng2++; - } - else { + } else { avgg1 += rawData[i][j]; ng1++; } } - double corrg1 = ((double)avgg1/ng1 + (double)avgg2/ng2) / 2.0 / ((double)avgg1/ng1); - double corrg2 = ((double)avgg1/ng1 + (double)avgg2/ng2) / 2.0 / ((double)avgg2/ng2); -#pragma omp parallel for default(shared) - for (int i=border; iISGREEN(i,j)) { + double corrg1 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg1 / ng1); + double corrg2 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg2 / ng2); + + #pragma omp parallel for default(shared) + + for (int i = border; i < H - border; i++) + for (int j = border; j < W - border; j++) + if (ri->ISGREEN(i, j)) { float currData; - currData = (float)(rawData[i][j] * ((i&1) ? corrg2 : corrg1)); + currData = (float)(rawData[i][j] * ((i & 1) ? corrg2 : corrg1)); rawData[i][j] = (currData); } - } + } - if ( ri->getSensorType()==ST_BAYER && raw.bayersensor.greenthresh >0) { - if (plistener) { - plistener->setProgressStr ("Green equilibrate..."); - plistener->setProgress (0.0); - } - green_equilibrate(0.01*(raw.bayersensor.greenthresh)); + if ( ri->getSensorType() == ST_BAYER && raw.bayersensor.greenthresh > 0) { + if (plistener) { + plistener->setProgressStr ("Green equilibrate..."); + plistener->setProgress (0.0); + } + + green_equilibrate(0.01 * (raw.bayersensor.greenthresh)); } - if( totBP ) - if ( ri->getSensorType()==ST_BAYER ) - interpolateBadPixelsBayer( bitmapBads ); - else if ( ri->getSensorType()==ST_FUJI_XTRANS ) - interpolateBadPixelsXtrans( bitmapBads ); - else + if( totBP ) + if ( ri->getSensorType() == ST_BAYER ) { + interpolateBadPixelsBayer( bitmapBads ); + } else if ( ri->getSensorType() == ST_FUJI_XTRANS ) { + interpolateBadPixelsXtrans( bitmapBads ); + } else { interpolateBadPixelsNColours( bitmapBads, ri->get_colors() ); - - if ( ri->getSensorType()==ST_BAYER && raw.bayersensor.linenoise >0 ) { - if (plistener) { - plistener->setProgressStr ("Line Denoise..."); - plistener->setProgress (0.0); - } + } - cfa_linedn(0.00002*(raw.bayersensor.linenoise)); - } - - if ( (raw.ca_autocorrect || fabs(raw.cared)>0.001 || fabs(raw.cablue)>0.001) && ri->getSensorType() == ST_BAYER ) { // Auto CA correction disabled for X-Trans, for now... - if (plistener) { - plistener->setProgressStr ("CA Auto Correction..."); - plistener->setProgress (0.0); - } - - CA_correct_RT(raw.cared, raw.cablue); - } - - if ( raw.expos !=1 ) processRawWhitepoint(raw.expos, raw.preser); - - if(dirpyrdenoiseExpComp == INFINITY) { - LUTu aehist; int aehistcompr; - double clip=0; + if ( ri->getSensorType() == ST_BAYER && raw.bayersensor.linenoise > 0 ) { + if (plistener) { + plistener->setProgressStr ("Line Denoise..."); + plistener->setProgress (0.0); + } + + cfa_linedn(0.00002 * (raw.bayersensor.linenoise)); + } + + if ( (raw.ca_autocorrect || fabs(raw.cared) > 0.001 || fabs(raw.cablue) > 0.001) && ri->getSensorType() == ST_BAYER ) { // Auto CA correction disabled for X-Trans, for now... + if (plistener) { + plistener->setProgressStr ("CA Auto Correction..."); + plistener->setProgress (0.0); + } + + CA_correct_RT(raw.cared, raw.cablue); + } + + if ( raw.expos != 1 ) { + processRawWhitepoint(raw.expos, raw.preser); + } + + if(dirpyrdenoiseExpComp == INFINITY) { + LUTu aehist; + int aehistcompr; + double clip = 0; int brightness, contrast, black, hlcompr, hlcomprthresh; getAutoExpHistogram (aehist, aehistcompr); ImProcFunctions::getAutoExp (aehist, aehistcompr, getDefGain(), clip, dirpyrdenoiseExpComp, brightness, contrast, black, hlcompr, hlcomprthresh); - } - + } + t2.set(); - if( settings->verbose ) - printf("Preprocessing: %d usec\n", t2.etime(t1)); + + if( settings->verbose ) { + printf("Preprocessing: %d usec\n", t2.etime(t1)); + } + return; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + void RawImageSource::demosaic(const RAWParams &raw) { - MyTime t1,t2; - t1.set(); + MyTime t1, t2; + t1.set(); - if (ri->getSensorType()==ST_BAYER) { - if ( raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::hphd] ) - hphd_demosaic (); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::vng4] ) - vng4_demosaic (); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::ahd] ) - ahd_demosaic (0,0,W,H); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze] ) - amaze_demosaic_RT (0,0,W,H); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::dcb] ) - dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::eahd]) - eahd_demosaic (); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv]) - igv_interpolate(W,H); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::lmmse]) - lmmse_interpolate_omp(W,H,raw.bayersensor.lmmse_iterations); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast] ) - fast_demosaic (0,0,W,H); - else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono] ) - nodemosaic(true); - else - nodemosaic(false); - - //if (raw.all_enhance) refinement_lassus(); + if (ri->getSensorType() == ST_BAYER) { + if ( raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::hphd] ) { + hphd_demosaic (); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::vng4] ) { + vng4_demosaic (); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::ahd] ) { + ahd_demosaic (0, 0, W, H); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze] ) { + amaze_demosaic_RT (0, 0, W, H); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::dcb] ) { + dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::eahd]) { + eahd_demosaic (); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv]) { + igv_interpolate(W, H); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::lmmse]) { + lmmse_interpolate_omp(W, H, raw.bayersensor.lmmse_iterations); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast] ) { + fast_demosaic (0, 0, W, H); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono] ) { + nodemosaic(true); + } else { + nodemosaic(false); + } - } else if (ri->getSensorType()==ST_FUJI_XTRANS) { - if (raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast] ) - fast_xtrans_interpolate(); - else if (raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::onePass]) - xtrans_interpolate(1,false); - else if (raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::threePass] ) - xtrans_interpolate(3,true); - else if(raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono] ) - nodemosaic(true); - else - nodemosaic(false); + //if (raw.all_enhance) refinement_lassus(); + + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { + if (raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast] ) { + fast_xtrans_interpolate(); + } else if (raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::onePass]) { + xtrans_interpolate(1, false); + } else if (raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::threePass] ) { + xtrans_interpolate(3, true); + } else if(raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono] ) { + nodemosaic(true); + } else { + nodemosaic(false); + } } else if (ri->get_colors() == 1) { // Monochrome nodemosaic(true); } + t2.set(); rgbSourceModified = false; + if( settings->verbose ) { - if (getSensorType() == ST_BAYER) - printf("Demosaicing Bayer data: %s - %d usec\n",raw.bayersensor.method.c_str(), t2.etime(t1)); - else if (getSensorType() == ST_FUJI_XTRANS) - printf("Demosaicing X-Trans data: %s - %d usec\n",raw.xtranssensor.method.c_str(), t2.etime(t1)); + if (getSensorType() == ST_BAYER) { + printf("Demosaicing Bayer data: %s - %d usec\n", raw.bayersensor.method.c_str(), t2.etime(t1)); + } else if (getSensorType() == ST_FUJI_XTRANS) { + printf("Demosaicing X-Trans data: %s - %d usec\n", raw.xtranssensor.method.c_str(), t2.etime(t1)); + } } } -void RawImageSource::flushRawData() { +void RawImageSource::flushRawData() +{ if(cache) { delete [] cache; cache = 0; } + if (rawData) { - rawData(0,0); + rawData(0, 0); } } -void RawImageSource::flushRGB() { +void RawImageSource::flushRGB() +{ if (green) { - green(0,0); + green(0, 0); } + if (red) { - red(0,0); + red(0, 0); } + if (blue) { - blue(0,0); + blue(0, 0); } } void RawImageSource::HLRecovery_Global(ToneCurveParams hrp ) { - if (hrp.hrenabled && hrp.method=="Color"){ - if(!rgbSourceModified) { - if (settings->verbose) printf ("Applying Highlight Recovery: Color propagation...\n"); - HLRecovery_inpaint (red,green,blue); - rgbSourceModified = true; - } - } + if (hrp.hrenabled && hrp.method == "Color") { + if(!rgbSourceModified) { + if (settings->verbose) { + printf ("Applying Highlight Recovery: Color propagation...\n"); + } + + HLRecovery_inpaint (red, green, blue); + rgbSourceModified = true; + } + } } void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]) { - float (*cfablur); - cfablur = (float (*)) calloc (H*W, sizeof *cfablur); - int BS = raw.ff_BlurRadius; - BS += BS&1; - - //function call to cfabloxblur - if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::v_ff]) - cfaboxblur(riFlatFile, cfablur, 2*BS, 0); - else if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::h_ff]) - cfaboxblur(riFlatFile, cfablur, 0, 2*BS); - else if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::vh_ff]) - //slightly more complicated blur if trying to correct both vertical and horizontal anomalies - cfaboxblur(riFlatFile, cfablur, BS, BS);//first do area blur to correct vignette - else //(raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::area_ff]) - cfaboxblur(riFlatFile, cfablur, BS, BS); - - if(ri->getSensorType()==ST_BAYER) { - float refcolor[2][2]; - //find center ave values by channel - for (int m=0; m<2; m++) - for (int n=0; n<2; n++) { - int row = 2*(H>>2)+m; - int col = 2*(W>>2)+n; - int c = FC(row, col); - int c4 = ( c == 1 && !(row&1) ) ? 3 : c; - refcolor[m][n] = max(0.0f,cfablur[row*W+col] - black[c4]); - } + float (*cfablur); + cfablur = (float (*)) calloc (H * W, sizeof * cfablur); + int BS = raw.ff_BlurRadius; + BS += BS & 1; - float limitFactor = 1.f; - if(raw.ff_AutoClipControl) { - int clipControlGui = 0; - for (int m=0; m<2; m++) - for (int n=0; n<2; n++) { - float maxval = 0.f; - int c = FC(m, n); - int c4 = ( c == 1 && !(m&1) ) ? 3 : c; -#pragma omp parallel -{ - float maxvalthr = 0.f; -#pragma omp for - for (int row = 0; row< H-m; row+=2) { - for (int col = 0; col < W-n; col+=2) { - float tempval = (rawData[row+m][col+n]-black[c4]) * ( refcolor[m][n]/max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4]) ); - if(tempval > maxvalthr) - maxvalthr = tempval; - } - } -#pragma omp critical -{ + //function call to cfabloxblur + if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::v_ff]) { + cfaboxblur(riFlatFile, cfablur, 2 * BS, 0); + } else if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::h_ff]) { + cfaboxblur(riFlatFile, cfablur, 0, 2 * BS); + } else if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::vh_ff]) + //slightly more complicated blur if trying to correct both vertical and horizontal anomalies + { + cfaboxblur(riFlatFile, cfablur, BS, BS); //first do area blur to correct vignette + } else { //(raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::area_ff]) + cfaboxblur(riFlatFile, cfablur, BS, BS); + } - if(maxvalthr>maxval) - maxval = maxvalthr; - -} -} - // now we have the max value for the channel - // if it clips, calculate factor to avoid clipping - if(maxval + black[c4] >= ri->get_white(c4)) - limitFactor = min(limitFactor,ri->get_white(c4) / (maxval + black[c4])); - } - clipControlGui = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui - } else { - limitFactor = max((float)(100 - raw.ff_clipControl)/100.f,0.01f); - } - for (int m=0; m<2; m++) - for (int n=0; n<2; n++) - refcolor[m][n] *= limitFactor; - - - for (int m=0; m<2; m++) - for (int n=0; n<2; n++) { -#pragma omp parallel -{ - int c = FC(m, n); - int c4 = ( c == 1 && !(m&1) ) ? 3 : c; -#pragma omp for - for (int row = 0; row< H-m; row+=2) { - for (int col = 0; col < W-n; col+=2) { - float vignettecorr = ( refcolor[m][n]/max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4]) ); - rawData[row+m][col+n] = (rawData[row+m][col+n]-black[c4]) * vignettecorr + black[c4]; - } - } -} - } - } else if(ri->getSensorType()==ST_FUJI_XTRANS) { - float refcolor[3] = {0.f}; - int cCount[3] = {0}; - //find center ave values by channel - for (int m=-3; m<3; m++) - for (int n=-3; n<3; n++) { - int row = 2*(H>>2)+m; - int col = 2*(W>>2)+n; - int c = riFlatFile->XTRANSFC(row, col); - refcolor[c] += max(0.0f,cfablur[row*W+col] - black[c]); - cCount[c] ++; - } - for(int c=0;c<3;c++) - refcolor[c] = refcolor[c] / cCount[c]; + if(ri->getSensorType() == ST_BAYER) { + float refcolor[2][2]; - float limitFactor = 1.f; + //find center ave values by channel + for (int m = 0; m < 2; m++) + for (int n = 0; n < 2; n++) { + int row = 2 * (H >> 2) + m; + int col = 2 * (W >> 2) + n; + int c = FC(row, col); + int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; + refcolor[m][n] = max(0.0f, cfablur[row * W + col] - black[c4]); + } - if(raw.ff_AutoClipControl) { - // determine maximum calculated value to avoid clipping - int clipControlGui = 0; - float maxval = 0.f; - // xtrans files have only one black level actually, so we can simplify the code a bit -#pragma omp parallel -{ - float maxvalthr = 0.f; -#pragma omp for schedule(dynamic,16) nowait - for (int row = 0; row< H; row++) { - for (int col = 0; col < W; col++) { - float tempval = (rawData[row][col]-black[0]) * ( refcolor[ri->XTRANSFC(row, col)]/max(1e-5f,cfablur[(row)*W+col]-black[0]) ); - if(tempval > maxvalthr) - maxvalthr = tempval; - } - } -#pragma omp critical -{ - if(maxvalthr>maxval) - maxval = maxvalthr; -} -} - // there's only one white level for xtrans - if(maxval + black[0] > ri->get_white(0)) { - limitFactor = ri->get_white(0) / (maxval + black[0]); - clipControlGui = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui - } - } else { - limitFactor = max((float)(100 - raw.ff_clipControl)/100.f,0.01f); - } + float limitFactor = 1.f; + + if(raw.ff_AutoClipControl) { + int clipControlGui = 0; + + for (int m = 0; m < 2; m++) + for (int n = 0; n < 2; n++) { + float maxval = 0.f; + int c = FC(m, n); + int c4 = ( c == 1 && !(m & 1) ) ? 3 : c; + #pragma omp parallel + { + float maxvalthr = 0.f; + #pragma omp for + + for (int row = 0; row < H - m; row += 2) { + for (int col = 0; col < W - n; col += 2) { + float tempval = (rawData[row + m][col + n] - black[c4]) * ( refcolor[m][n] / max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4]) ); + + if(tempval > maxvalthr) { + maxvalthr = tempval; + } + } + } + + #pragma omp critical + { + + if(maxvalthr > maxval) { + maxval = maxvalthr; + } + + } + } + + // now we have the max value for the channel + // if it clips, calculate factor to avoid clipping + if(maxval + black[c4] >= ri->get_white(c4)) { + limitFactor = min(limitFactor, ri->get_white(c4) / (maxval + black[c4])); + } + } + + clipControlGui = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui + } else { + limitFactor = max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f); + } + + for (int m = 0; m < 2; m++) + for (int n = 0; n < 2; n++) { + refcolor[m][n] *= limitFactor; + } - for(int c=0;c<3;c++) - refcolor[c] *= limitFactor; - -#pragma omp parallel for - for (int row = 0; row< H; row++) { - for (int col = 0; col < W; col++) { - int c = ri->XTRANSFC(row, col); - float vignettecorr = ( refcolor[c]/max(1e-5f,cfablur[(row)*W+col]-black[c]) ); - rawData[row][col] = (rawData[row][col]-black[c]) * vignettecorr + black[c]; - } - } - } - if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::vh_ff]) { - float (*cfablur1); - cfablur1 = (float (*)) calloc (H*W, sizeof *cfablur1); - float (*cfablur2); - cfablur2 = (float (*)) calloc (H*W, sizeof *cfablur2); - //slightly more complicated blur if trying to correct both vertical and horizontal anomalies - cfaboxblur(riFlatFile, cfablur1, 0, 2*BS);//now do horizontal blur - cfaboxblur(riFlatFile, cfablur2, 2*BS, 0);//now do vertical blur - - if(ri->getSensorType()==ST_BAYER) { - for (int m=0; m<2; m++) - for (int n=0; n<2; n++) { -#pragma omp parallel for - for (int row = 0; row< H-m; row+=2) { - int c = FC(row, 0); - int c4 = ( c == 1 && !(row&1) ) ? 3 : c; - for (int col = 0; col < W-n; col+=2) { - float hlinecorr = (max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4])/max(1e-5f,cfablur1[(row+m)*W+col+n]-black[c4]) ); - float vlinecorr = (max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4])/max(1e-5f,cfablur2[(row+m)*W+col+n]-black[c4]) ); - rawData[row+m][col+n] = ((rawData[row+m][col+n]-black[c4]) * hlinecorr * vlinecorr + black[c4]); - } - } - } - } else if(ri->getSensorType()==ST_FUJI_XTRANS) { -#pragma omp parallel for - for (int row = 0; row< H; row++) { - for (int col = 0; col < W; col++) { - int c = ri->XTRANSFC(row, col); - float hlinecorr = (max(1e-5f,cfablur[(row)*W+col]-black[c])/max(1e-5f,cfablur1[(row)*W+col]-black[c]) ); - float vlinecorr = (max(1e-5f,cfablur[(row)*W+col]-black[c])/max(1e-5f,cfablur2[(row)*W+col]-black[c]) ); - rawData[row][col] = ((rawData[row][col]-black[c]) * hlinecorr * vlinecorr + black[c]); - } - } - - } - free (cfablur1); - free (cfablur2); - } - - free (cfablur); + for (int m = 0; m < 2; m++) + for (int n = 0; n < 2; n++) { + #pragma omp parallel + { + int c = FC(m, n); + int c4 = ( c == 1 && !(m & 1) ) ? 3 : c; + #pragma omp for + + for (int row = 0; row < H - m; row += 2) + { + for (int col = 0; col < W - n; col += 2) { + float vignettecorr = ( refcolor[m][n] / max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4]) ); + rawData[row + m][col + n] = (rawData[row + m][col + n] - black[c4]) * vignettecorr + black[c4]; + } + } + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + float refcolor[3] = {0.f}; + int cCount[3] = {0}; + + //find center ave values by channel + for (int m = -3; m < 3; m++) + for (int n = -3; n < 3; n++) { + int row = 2 * (H >> 2) + m; + int col = 2 * (W >> 2) + n; + int c = riFlatFile->XTRANSFC(row, col); + refcolor[c] += max(0.0f, cfablur[row * W + col] - black[c]); + cCount[c] ++; + } + + for(int c = 0; c < 3; c++) { + refcolor[c] = refcolor[c] / cCount[c]; + } + + float limitFactor = 1.f; + + if(raw.ff_AutoClipControl) { + // determine maximum calculated value to avoid clipping + int clipControlGui = 0; + float maxval = 0.f; + // xtrans files have only one black level actually, so we can simplify the code a bit + #pragma omp parallel + { + float maxvalthr = 0.f; + #pragma omp for schedule(dynamic,16) nowait + + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + float tempval = (rawData[row][col] - black[0]) * ( refcolor[ri->XTRANSFC(row, col)] / max(1e-5f, cfablur[(row) * W + col] - black[0]) ); + + if(tempval > maxvalthr) { + maxvalthr = tempval; + } + } + } + + #pragma omp critical + { + if(maxvalthr > maxval) { + maxval = maxvalthr; + } + } + } + + // there's only one white level for xtrans + if(maxval + black[0] > ri->get_white(0)) { + limitFactor = ri->get_white(0) / (maxval + black[0]); + clipControlGui = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui + } + } else { + limitFactor = max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f); + } + + + for(int c = 0; c < 3; c++) { + refcolor[c] *= limitFactor; + } + + #pragma omp parallel for + + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + int c = ri->XTRANSFC(row, col); + float vignettecorr = ( refcolor[c] / max(1e-5f, cfablur[(row) * W + col] - black[c]) ); + rawData[row][col] = (rawData[row][col] - black[c]) * vignettecorr + black[c]; + } + } + } + + if (raw.ff_BlurType == RAWParams::ff_BlurTypestring[RAWParams::vh_ff]) { + float (*cfablur1); + cfablur1 = (float (*)) calloc (H * W, sizeof * cfablur1); + float (*cfablur2); + cfablur2 = (float (*)) calloc (H * W, sizeof * cfablur2); + //slightly more complicated blur if trying to correct both vertical and horizontal anomalies + cfaboxblur(riFlatFile, cfablur1, 0, 2 * BS); //now do horizontal blur + cfaboxblur(riFlatFile, cfablur2, 2 * BS, 0); //now do vertical blur + + if(ri->getSensorType() == ST_BAYER) { + for (int m = 0; m < 2; m++) + for (int n = 0; n < 2; n++) { + #pragma omp parallel for + + for (int row = 0; row < H - m; row += 2) { + int c = FC(row, 0); + int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; + + for (int col = 0; col < W - n; col += 2) { + float hlinecorr = (max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4]) / max(1e-5f, cfablur1[(row + m) * W + col + n] - black[c4]) ); + float vlinecorr = (max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4]) / max(1e-5f, cfablur2[(row + m) * W + col + n] - black[c4]) ); + rawData[row + m][col + n] = ((rawData[row + m][col + n] - black[c4]) * hlinecorr * vlinecorr + black[c4]); + } + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + #pragma omp parallel for + + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + int c = ri->XTRANSFC(row, col); + float hlinecorr = (max(1e-5f, cfablur[(row) * W + col] - black[c]) / max(1e-5f, cfablur1[(row) * W + col] - black[c]) ); + float vlinecorr = (max(1e-5f, cfablur[(row) * W + col] - black[c]) / max(1e-5f, cfablur2[(row) * W + col] - black[c]) ); + rawData[row][col] = ((rawData[row][col] - black[c]) * hlinecorr * vlinecorr + black[c]); + } + } + + } + + free (cfablur1); + free (cfablur2); + } + + free (cfablur); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1805,573 +2071,676 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile */ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile ) { - unsigned short black[4]={ri->get_cblack(0),ri->get_cblack(1),ri->get_cblack(2),ri->get_cblack(3)}; + unsigned short black[4] = {ri->get_cblack(0), ri->get_cblack(1), ri->get_cblack(2), ri->get_cblack(3)}; - if (ri->getSensorType()==ST_BAYER || ri->getSensorType()==ST_FUJI_XTRANS) { - if (!rawData) - rawData(W,H); - if (riDark && W == riDark->get_width() && H == riDark->get_height()) { // This works also for xtrans-sensors, because black[0] to black[4] are equal for these - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - int c = FC(row, col); - int c4 = ( c == 1 && !(row&1) ) ? 3 : c; - rawData[row][col] = max(src->data[row][col]+black[c4] - riDark->data[row][col], 0.0f); - } - } - }else{ - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - rawData[row][col] = src->data[row][col]; - } - } - } - - - if (riFlatFile && W == riFlatFile->get_width() && H == riFlatFile->get_height()) { - processFlatField(raw, riFlatFile, black); - } // flatfield - } else if (ri->get_colors() == 1) { - // Monochrome - if (!rawData) rawData(W,H); + if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) { + if (!rawData) { + rawData(W, H); + } - if (riDark && W == riDark->get_width() && H == riDark->get_height()) { - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - rawData[row][col] = max(src->data[row][col]+black[0] - riDark->data[row][col], 0.0f); - } - } - } else { - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - rawData[row][col] = src->data[row][col]; - } - } - } - } else { + if (riDark && W == riDark->get_width() && H == riDark->get_height()) { // This works also for xtrans-sensors, because black[0] to black[4] are equal for these + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + int c = FC(row, col); + int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; + rawData[row][col] = max(src->data[row][col] + black[c4] - riDark->data[row][col], 0.0f); + } + } + } else { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + rawData[row][col] = src->data[row][col]; + } + } + } + + + if (riFlatFile && W == riFlatFile->get_width() && H == riFlatFile->get_height()) { + processFlatField(raw, riFlatFile, black); + } // flatfield + } else if (ri->get_colors() == 1) { + // Monochrome + if (!rawData) { + rawData(W, H); + } + + if (riDark && W == riDark->get_width() && H == riDark->get_height()) { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + rawData[row][col] = max(src->data[row][col] + black[0] - riDark->data[row][col], 0.0f); + } + } + } else { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + rawData[row][col] = src->data[row][col]; + } + } + } + } else { // No bayer pattern // TODO: Is there a flat field correction possible? - if (!rawData) rawData(3*W,H); + if (!rawData) { + rawData(3 * W, H); + } - if (riDark && W == riDark->get_width() && H == riDark->get_height()) { - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - int c = FC(row, col); - int c4 = ( c == 1 && !(row&1) ) ? 3 : c; - rawData[row][3*col+0] = max(src->data[row][3*col+0]+black[c4] - riDark->data[row][3*col+0], 0.0f); - rawData[row][3*col+1] = max(src->data[row][3*col+1]+black[c4] - riDark->data[row][3*col+1], 0.0f); - rawData[row][3*col+2] = max(src->data[row][3*col+2]+black[c4] - riDark->data[row][3*col+2], 0.0f); - } - } - } else { - for (int row = 0; row < H; row++) { - for (int col = 0; col < W; col++) { - rawData[row][3*col+0] = src->data[row][3*col+0]; - rawData[row][3*col+1] = src->data[row][3*col+1]; - rawData[row][3*col+2] = src->data[row][3*col+2]; - } - } - } - } + if (riDark && W == riDark->get_width() && H == riDark->get_height()) { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + int c = FC(row, col); + int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; + rawData[row][3 * col + 0] = max(src->data[row][3 * col + 0] + black[c4] - riDark->data[row][3 * col + 0], 0.0f); + rawData[row][3 * col + 1] = max(src->data[row][3 * col + 1] + black[c4] - riDark->data[row][3 * col + 1], 0.0f); + rawData[row][3 * col + 2] = max(src->data[row][3 * col + 2] + black[c4] - riDark->data[row][3 * col + 2], 0.0f); + } + } + } else { + for (int row = 0; row < H; row++) { + for (int col = 0; col < W; col++) { + rawData[row][3 * col + 0] = src->data[row][3 * col + 0]; + rawData[row][3 * col + 1] = src->data[row][3 * col + 1]; + rawData[row][3 * col + 2] = src->data[row][3 * col + 2]; + } + } + } + } } -SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur, const int boxH, const int boxW ) { - - float (*cfatmp); - cfatmp = (float (*)) calloc (H*W, sizeof *cfatmp); -// const float hotdeadthresh = 0.5; - -#pragma omp parallel +SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur, const int boxH, const int boxW ) { -#pragma omp for - for (int i=0; iH-3) {inext=i-2;} else {inext=i+2;} - for (int j=0; jW-3) {jnext=j-2;} else {jnext=j+2;} - //med3x3(riFlatFile->data[iprev][jprev], riFlatFile->data[iprev][j], riFlatFile->data[iprev][jnext], - // riFlatFile->data[i][jprev], riFlatFile->data[i][j], riFlatFile->data[i][jnext], - // riFlatFile->data[inext][jprev], riFlatFile->data[inext][j], riFlatFile->data[inext][jnext], cfatmp[i*W+j]); - med5(riFlatFile->data[iprev][j], riFlatFile->data[i][jprev],riFlatFile->data[i][j], - riFlatFile->data[i][jnext], riFlatFile->data[inext][j],median); - -// if (riFlatFile->data[i][j]>hotdeadthresh*median || median>hotdeadthresh*riFlatFile->data[i][j]) { - if (((int)riFlatFile->data[i][j]<<1)>median || (median<<1) > riFlatFile->data[i][j]) { - cfatmp[i*W+j] = median; - } else { - cfatmp[i*W+j] = riFlatFile->data[i][j]; - } - } - } - - //box blur cfa image; box size = BS - //horizontal blur -#pragma omp for - for (int row = 0; row < H; row++) { - int len = boxW/2 + 1; - cfatmp[row*W+0] = cfatmp[row*W+0]/len; - cfatmp[row*W+1] = cfatmp[row*W+1]/len; - for (int j=2; j<=boxW; j+=2) { - cfatmp[row*W+0] += cfatmp[row*W+j]/len; - cfatmp[row*W+1] += cfatmp[row*W+j+1]/len; - } - for (int col=2; col<=boxW; col+=2) { - cfatmp[row*W+col] = (cfatmp[row*W+col-2]*len + cfatmp[row*W+boxW+col])/(len+1); - cfatmp[row*W+col+1] = (cfatmp[row*W+col-1]*len + cfatmp[row*W+boxW+col+1])/(len+1); - len ++; - } - for (int col = boxW+2; col < W-boxW; col++) { - cfatmp[row*W+col] = cfatmp[row*W+col-2] + (cfatmp[row*W+boxW+col]-cfatmp[row*W+col-boxW-2])/len; - } - for (int col=W-boxW; col H - 3) { + inext = i - 2; + } else { + inext = i + 2; + } + + for (int j = 0; j < W; j++) { + if (j < 2) { + jprev = j + 2; + } else { + jprev = j - 2; + } + + if (j > W - 3) { + jnext = j - 2; + } else { + jnext = j + 2; + } + + //med3x3(riFlatFile->data[iprev][jprev], riFlatFile->data[iprev][j], riFlatFile->data[iprev][jnext], + // riFlatFile->data[i][jprev], riFlatFile->data[i][j], riFlatFile->data[i][jnext], + // riFlatFile->data[inext][jprev], riFlatFile->data[inext][j], riFlatFile->data[inext][jnext], cfatmp[i*W+j]); + med5(riFlatFile->data[iprev][j], riFlatFile->data[i][jprev], riFlatFile->data[i][j], + riFlatFile->data[i][jnext], riFlatFile->data[inext][j], median); + +// if (riFlatFile->data[i][j]>hotdeadthresh*median || median>hotdeadthresh*riFlatFile->data[i][j]) { + if (((int)riFlatFile->data[i][j] << 1) > median || (median << 1) > riFlatFile->data[i][j]) { + cfatmp[i * W + j] = median; + } else { + cfatmp[i * W + j] = riFlatFile->data[i][j]; + } + + } + } + + //box blur cfa image; box size = BS + //horizontal blur + #pragma omp for + + for (int row = 0; row < H; row++) { + int len = boxW / 2 + 1; + cfatmp[row * W + 0] = cfatmp[row * W + 0] / len; + cfatmp[row * W + 1] = cfatmp[row * W + 1] / len; + + for (int j = 2; j <= boxW; j += 2) { + cfatmp[row * W + 0] += cfatmp[row * W + j] / len; + cfatmp[row * W + 1] += cfatmp[row * W + j + 1] / len; + } + + for (int col = 2; col <= boxW; col += 2) { + cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len + cfatmp[row * W + boxW + col]) / (len + 1); + cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len + cfatmp[row * W + boxW + col + 1]) / (len + 1); + len ++; + } + + for (int col = boxW + 2; col < W - boxW; col++) { + cfatmp[row * W + col] = cfatmp[row * W + col - 2] + (cfatmp[row * W + boxW + col] - cfatmp[row * W + col - boxW - 2]) / len; + } + + for (int col = W - boxW; col < W; col += 2) { + cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len - cfatmp[row * W + col - boxW - 2]) / (len - 1); + + if (col + 1 < W) { + cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len - cfatmp[row * W + col - boxW - 1]) / (len - 1); + } + + len --; + } + } + + //vertical blur #ifdef __SSE2__ - __m128 leninitv = _mm_set1_ps( (float)((int)(boxH/2 + 1))); - __m128 onev = _mm_set1_ps( 1.0f ); - __m128 temp1v,temp2v,lenv,lenp1v,lenm1v; - int row; -#pragma omp for - for (int col = 0; col < W-3; col+=4) { - lenv = leninitv; - temp1v = LVFU(cfatmp[0*W+col]) / lenv; - temp2v = LVFU(cfatmp[1*W+col]) / lenv; - - for (int i=2; iget_colors()); // recalculate scale colors with adjusted levels - //fprintf(stderr, "recalc: %f [%f %f %f %f]\n", initialGain, scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); - for(int i=0; i<4 ;i++) clmax[i] = (c_white[i] - cblacksom[i]) * scale_mul[i]; // raw clip level - - // this seems strange, but it works + isMono = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::mono] == raw.xtranssensor.method; + } - // scale image colors + for(int i = 0; i < 4 ; i++) { + cblacksom[i] = max( c_black[i] + black_lev[i], 0.0f ); // adjust black level + } - if( ri->getSensorType()==ST_BAYER){ -#pragma omp parallel -{ - float tmpchmax[3]; - tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; + initialGain = calculate_scale_mul(scale_mul, ref_pre_mul, c_white, cblacksom, isMono, ri->get_colors()); // recalculate scale colors with adjusted levels -#pragma omp for nowait - for (int row = winy; row < winy+winh; row ++){ - for (int col = winx; col < winx+winw; col++) { - float val = rawData[row][col]; - int c = FC(row, col); // three colors, 0=R, 1=G, 2=B - int c4 = ( c == 1 && !(row&1) ) ? 3 : c; // four colors, 0=R, 1=G1, 2=B, 3=G2 - val-=cblacksom[c4]; - val*=scale_mul[c4]; - rawData[row][col] = (val); - tmpchmax[c] = max(tmpchmax[c],val); - } - } -#pragma omp critical -{ - chmax[0] = max(tmpchmax[0],chmax[0]); - chmax[1] = max(tmpchmax[1],chmax[1]); - chmax[2] = max(tmpchmax[2],chmax[2]); -} -} - } else if ( ri->get_colors() == 1 ) { -#pragma omp parallel -{ - float tmpchmax = 0.0f; + //fprintf(stderr, "recalc: %f [%f %f %f %f]\n", initialGain, scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); + for(int i = 0; i < 4 ; i++) { + clmax[i] = (c_white[i] - cblacksom[i]) * scale_mul[i]; // raw clip level + } -#pragma omp for nowait - for (int row = winy; row < winy+winh; row ++){ - for (int col = winx; col < winx+winw; col++) { - float val = rawData[row][col]; - val -= cblacksom[0]; - val *= scale_mul[0]; - rawData[row][col] = (val); - tmpchmax = max(tmpchmax,val); - } - } -#pragma omp critical -{ - chmax[0] = chmax[1] = chmax[2] = chmax[3] = max(tmpchmax,chmax[0]); -} -} - } else if(ri->getSensorType()==ST_FUJI_XTRANS) { -#pragma omp parallel -{ - float tmpchmax[3]; - tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; + // this seems strange, but it works -#pragma omp for nowait - for (int row = winy; row < winy+winh; row ++){ - for (int col = winx; col < winx+winw; col++) { - float val = rawData[row][col]; - int c = ri->XTRANSFC(row, col); - val-=cblacksom[c]; - val*=scale_mul[c]; - - rawData[row][col] = (val); - tmpchmax[c] = max(tmpchmax[c],val); - } - } -#pragma omp critical -{ - chmax[0] = max(tmpchmax[0],chmax[0]); - chmax[1] = max(tmpchmax[1],chmax[1]); - chmax[2] = max(tmpchmax[2],chmax[2]); -} -} - } else { -#pragma omp parallel -{ - float tmpchmax[3]; - tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; + // scale image colors -#pragma omp for nowait - for (int row = winy; row < winy+winh; row ++){ - for (int col = winx; col < winx+winw; col++) { - for (int c=0; c<3; c++) { // three colors, 0=R, 1=G, 2=B - float val = rawData[row][3*col+c]; - val -= cblacksom[c]; - val *= scale_mul[c]; - rawData[row][3*col+c] = (val); - tmpchmax[c] = max(tmpchmax[c],val); - } - } - } -#pragma omp critical -{ - chmax[0] = max(tmpchmax[0],chmax[0]); - chmax[1] = max(tmpchmax[1],chmax[1]); - chmax[2] = max(tmpchmax[2],chmax[2]); -} -} - chmax[3]=chmax[1]; - } + if( ri->getSensorType() == ST_BAYER) { + #pragma omp parallel + { + float tmpchmax[3]; + tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; + + #pragma omp for nowait + + for (int row = winy; row < winy + winh; row ++) + { + for (int col = winx; col < winx + winw; col++) { + float val = rawData[row][col]; + int c = FC(row, col); // three colors, 0=R, 1=G, 2=B + int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; // four colors, 0=R, 1=G1, 2=B, 3=G2 + val -= cblacksom[c4]; + val *= scale_mul[c4]; + rawData[row][col] = (val); + tmpchmax[c] = max(tmpchmax[c], val); + } + } + + #pragma omp critical + { + chmax[0] = max(tmpchmax[0], chmax[0]); + chmax[1] = max(tmpchmax[1], chmax[1]); + chmax[2] = max(tmpchmax[2], chmax[2]); + } + } + } else if ( ri->get_colors() == 1 ) { + #pragma omp parallel + { + float tmpchmax = 0.0f; + + #pragma omp for nowait + + for (int row = winy; row < winy + winh; row ++) + { + for (int col = winx; col < winx + winw; col++) { + float val = rawData[row][col]; + val -= cblacksom[0]; + val *= scale_mul[0]; + rawData[row][col] = (val); + tmpchmax = max(tmpchmax, val); + } + } + + #pragma omp critical + { + chmax[0] = chmax[1] = chmax[2] = chmax[3] = max(tmpchmax, chmax[0]); + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + #pragma omp parallel + { + float tmpchmax[3]; + tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; + + #pragma omp for nowait + + for (int row = winy; row < winy + winh; row ++) + { + for (int col = winx; col < winx + winw; col++) { + float val = rawData[row][col]; + int c = ri->XTRANSFC(row, col); + val -= cblacksom[c]; + val *= scale_mul[c]; + + rawData[row][col] = (val); + tmpchmax[c] = max(tmpchmax[c], val); + } + } + + #pragma omp critical + { + chmax[0] = max(tmpchmax[0], chmax[0]); + chmax[1] = max(tmpchmax[1], chmax[1]); + chmax[2] = max(tmpchmax[2], chmax[2]); + } + } + } else { + #pragma omp parallel + { + float tmpchmax[3]; + tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; + + #pragma omp for nowait + + for (int row = winy; row < winy + winh; row ++) + { + for (int col = winx; col < winx + winw; col++) { + for (int c = 0; c < 3; c++) { // three colors, 0=R, 1=G, 2=B + float val = rawData[row][3 * col + c]; + val -= cblacksom[c]; + val *= scale_mul[c]; + rawData[row][3 * col + c] = (val); + tmpchmax[c] = max(tmpchmax[c], val); + } + } + } + + #pragma omp critical + { + chmax[0] = max(tmpchmax[0], chmax[0]); + chmax[1] = max(tmpchmax[1], chmax[1]); + chmax[2] = max(tmpchmax[2], chmax[2]); + } + } + chmax[3] = chmax[1]; + } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -int RawImageSource::defTransform (int tran) { +int RawImageSource::defTransform (int tran) +{ int deg = ri->get_rotateDegree(); - if ((tran & TR_ROT) == TR_R180) + + if ((tran & TR_ROT) == TR_R180) { deg += 180; - else if ((tran & TR_ROT) == TR_R90) + } else if ((tran & TR_ROT) == TR_R90) { deg += 90; - else if ((tran & TR_ROT) == TR_R270) + } else if ((tran & TR_ROT) == TR_R270) { deg += 270; + } + deg %= 360; int ret = 0; - if (deg==90) + + if (deg == 90) { ret |= TR_R90; - else if (deg==180) + } else if (deg == 180) { ret |= TR_R180; - else if (deg==270) + } else if (deg == 270) { ret |= TR_R270; - if (tran & TR_HFLIP) + } + + if (tran & TR_HFLIP) { ret |= TR_HFLIP; - if (tran & TR_VFLIP) + } + + if (tran & TR_VFLIP) { ret |= TR_VFLIP; + } + return ret; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Thread called part -void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, int row_from, int row_to) { - - int W = im->width; +void RawImageSource::processFalseColorCorrectionThread (Imagefloat* im, int row_from, int row_to) +{ - array2D rbconv_Y (W,3); - array2D rbconv_I (W,3); - array2D rbconv_Q (W,3); - array2D rbout_I (W,3); - array2D rbout_Q (W,3); + int W = im->width; - float* row_I = new float[W]; - float* row_Q = new float[W]; + array2D rbconv_Y (W, 3); + array2D rbconv_I (W, 3); + array2D rbconv_Q (W, 3); + array2D rbout_I (W, 3); + array2D rbout_Q (W, 3); - float* pre1_I = new float[3]; - float* pre2_I = new float[3]; - float* post1_I = new float[3]; - float* post2_I = new float[3]; - float middle_I[6]; - float* pre1_Q = new float[3]; - float* pre2_Q = new float[3]; - float* post1_Q = new float[3]; - float* post2_Q = new float[3]; - float middle_Q[6]; - float* tmp; + float* row_I = new float[W]; + float* row_Q = new float[W]; - int px=(row_from-1)%3, cx=row_from%3, nx=0; - - convert_row_to_YIQ (im->r(row_from-1), im->g(row_from-1), im->b(row_from-1), rbconv_Y[px], rbconv_I[px], rbconv_Q[px], W); + float* pre1_I = new float[3]; + float* pre2_I = new float[3]; + float* post1_I = new float[3]; + float* post2_I = new float[3]; + float middle_I[6]; + float* pre1_Q = new float[3]; + float* pre2_Q = new float[3]; + float* post1_Q = new float[3]; + float* post2_Q = new float[3]; + float middle_Q[6]; + float* tmp; + + int px = (row_from - 1) % 3, cx = row_from % 3, nx = 0; + + convert_row_to_YIQ (im->r(row_from - 1), im->g(row_from - 1), im->b(row_from - 1), rbconv_Y[px], rbconv_I[px], rbconv_Q[px], W); convert_row_to_YIQ (im->r(row_from), im->g(row_from), im->b(row_from), rbconv_Y[cx], rbconv_I[cx], rbconv_Q[cx], W); - for (int j=0; jr(i+1), im->g(i+1), im->b(i+1), rbconv_Y[nx], rbconv_I[nx], rbconv_Q[nx], W); + px = (i - 1) % 3; + cx = i % 3; + nx = (i + 1) % 3; - SORT3(rbconv_I[px][0],rbconv_I[cx][0],rbconv_I[nx][0],pre1_I[0],pre1_I[1],pre1_I[2]); - SORT3(rbconv_I[px][1],rbconv_I[cx][1],rbconv_I[nx][1],pre2_I[0],pre2_I[1],pre2_I[2]); - SORT3(rbconv_Q[px][0],rbconv_Q[cx][0],rbconv_Q[nx][0],pre1_Q[0],pre1_Q[1],pre1_Q[2]); - SORT3(rbconv_Q[px][1],rbconv_Q[cx][1],rbconv_Q[nx][1],pre2_Q[0],pre2_Q[1],pre2_Q[2]); + convert_row_to_YIQ (im->r(i + 1), im->g(i + 1), im->b(i + 1), rbconv_Y[nx], rbconv_I[nx], rbconv_Q[nx], W); - // median I channel - for (int j=1; jrow_from) { - for (int j=1; jr(i-1), im->g(i-1), im->b(i-1), rbconv_Y[px], row_I, row_Q, W); - } + + // median Q channel + for (int j = 1; j < W - 2; j += 2) { + SORT3(rbconv_Q[px][j + 1], rbconv_Q[cx][j + 1], rbconv_Q[nx][j + 1], post1_Q[0], post1_Q[1], post1_Q[2]); + SORT3(rbconv_Q[px][j + 2], rbconv_Q[cx][j + 2], rbconv_Q[nx][j + 2], post2_Q[0], post2_Q[1], post2_Q[2]); + MERGESORT(pre2_Q[0], pre2_Q[1], pre2_Q[2], post1_Q[0], post1_Q[1], post1_Q[2], middle_Q[0], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], middle_Q[5]); + MEDIAN7(pre1_Q[0], pre1_Q[1], pre1_Q[2], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], rbout_Q[cx][j]); + MEDIAN7(post2_Q[0], post2_Q[1], post2_Q[2], middle_Q[1], middle_Q[2], middle_Q[3], middle_Q[4], rbout_Q[cx][j + 1]); + tmp = pre1_Q; + pre1_Q = post1_Q; + post1_Q = tmp; + tmp = pre2_Q; + pre2_Q = post2_Q; + post2_Q = tmp; + } + + // fill first and last element in rbout + rbout_I[cx][0] = rbconv_I[cx][0]; + rbout_I[cx][W - 1] = rbconv_I[cx][W - 1]; + rbout_I[cx][W - 2] = rbconv_I[cx][W - 2]; + rbout_Q[cx][0] = rbconv_Q[cx][0]; + rbout_Q[cx][W - 1] = rbconv_Q[cx][W - 1]; + rbout_Q[cx][W - 2] = rbconv_Q[cx][W - 2]; + + // blur i-1th row + if (i > row_from) { + for (int j = 1; j < W - 1; j++) { + row_I[j] = (rbout_I[px][j - 1] + rbout_I[px][j] + rbout_I[px][j + 1] + rbout_I[cx][j - 1] + rbout_I[cx][j] + rbout_I[cx][j + 1] + rbout_I[nx][j - 1] + rbout_I[nx][j] + rbout_I[nx][j + 1]) / 9; + row_Q[j] = (rbout_Q[px][j - 1] + rbout_Q[px][j] + rbout_Q[px][j + 1] + rbout_Q[cx][j - 1] + rbout_Q[cx][j] + rbout_Q[cx][j + 1] + rbout_Q[nx][j - 1] + rbout_Q[nx][j] + rbout_Q[nx][j + 1]) / 9; + } + + row_I[0] = rbout_I[px][0]; + row_Q[0] = rbout_Q[px][0]; + row_I[W - 1] = rbout_I[px][W - 1]; + row_Q[W - 1] = rbout_Q[px][W - 1]; + convert_row_to_RGB (im->r(i - 1), im->g(i - 1), im->b(i - 1), rbconv_Y[px], row_I, row_Q, W); + } } + // blur last 3 row and finalize H-1th row - for (int j=1; jr(row_to-1), im->g(row_to-1), im->b(row_to-1), rbconv_Y[cx], row_I, row_Q, W); + row_I[W - 1] = rbout_I[cx][W - 1]; + row_Q[W - 1] = rbout_Q[cx][W - 1]; + convert_row_to_RGB (im->r(row_to - 1), im->g(row_to - 1), im->b(row_to - 1), rbconv_Y[cx], row_I, row_Q, W); - delete [] row_I; - delete [] row_Q; - delete [] pre1_I; - delete [] pre2_I; - delete [] post1_I; - delete [] post2_I; - delete [] pre1_Q; - delete [] pre2_Q; - delete [] post1_Q; - delete [] post2_Q; + delete [] row_I; + delete [] row_Q; + delete [] pre1_I; + delete [] pre2_I; + delete [] post1_I; + delete [] post2_I; + delete [] pre1_Q; + delete [] pre2_Q; + delete [] post1_Q; + delete [] post2_Q; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // correction_YIQ_LQ -void RawImageSource::processFalseColorCorrection (Imagefloat* im, int steps) { +void RawImageSource::processFalseColorCorrection (Imagefloat* im, int steps) +{ - if (im->height<4) + if (im->height < 4) { return; + } - for (int t=0; theight-2)/nthreads; + #pragma omp parallel + { + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = (im->height - 2) / nthreads; - if (tidheight - 1); - } + if (tid < nthreads - 1) + { + processFalseColorCorrectionThread (im, 1 + tid * blk, 1 + (tid + 1)*blk); + } else + { processFalseColorCorrectionThread (im, 1 + tid * blk, im->height - 1); } + } #else - processFalseColorCorrectionThread (im, 1 , im->height - 1); + processFalseColorCorrectionThread (im, 1 , im->height - 1); #endif } } - + // Some camera input profiles need gamma preprocessing // gamma is applied before the CMS, correct line fac=lineFac*rawPixel+LineSum after the CMS -void RawImageSource::getProfilePreprocParams(cmsHPROFILE in, float& gammaFac, float& lineFac, float& lineSum) { - gammaFac=0; lineFac=1; lineSum=0; +void RawImageSource::getProfilePreprocParams(cmsHPROFILE in, float& gammaFac, float& lineFac, float& lineSum) +{ + gammaFac = 0; + lineFac = 1; + lineSum = 0; char copyright[256]; - copyright[0]=0; + copyright[0] = 0; - if (cmsGetProfileInfoASCII(in, cmsInfoCopyright, cmsNoLanguage, cmsNoCountry, copyright, 256)>0) { - if (strstr(copyright,"Phase One")!=NULL) - gammaFac=0.55556; // 1.8 - else if (strstr(copyright,"Nikon Corporation")!=NULL) { - gammaFac=0.5; lineFac=-0.4; lineSum=1.35; // determined in reverse by measuring NX an RT developed colorchecker PNGs + if (cmsGetProfileInfoASCII(in, cmsInfoCopyright, cmsNoLanguage, cmsNoCountry, copyright, 256) > 0) { + if (strstr(copyright, "Phase One") != NULL) { + gammaFac = 0.55556; // 1.8 + } else if (strstr(copyright, "Nikon Corporation") != NULL) { + gammaFac = 0.5; + lineFac = -0.4; + lineSum = 1.35; // determined in reverse by measuring NX an RT developed colorchecker PNGs } } } @@ -2385,43 +2754,48 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b) float Y; float Z; #define CLIP01(a) ((a)>0?((a)<1?(a):1):0) - { // convert from Lab to XYZ + { + // convert from Lab to XYZ float x, y, z, fx, fy, fz; - fy = (L + 16.0f)/116.0f; - fx = A/500.0f + fy; - fz = fy - B/200.0f; + fy = (L + 16.0f) / 116.0f; + fx = A / 500.0f + fy; + fz = fy - B / 200.0f; - if (fy > 24.0f/116.0f) { - y = fy*fy*fy; + if (fy > 24.0f / 116.0f) { + y = fy * fy * fy; } else { - y = (fy - 16.0f/116.0f)/7.787036979f; + y = (fy - 16.0f / 116.0f) / 7.787036979f; } - if (fx > 24.0f/116.0f) { - x = fx*fx*fx; + + if (fx > 24.0f / 116.0f) { + x = fx * fx * fx; } else { - x = (fx - 16.0/116.0)/7.787036979f; + x = (fx - 16.0 / 116.0) / 7.787036979f; } - if (fz > 24.0f/116.0f) { - z = fz*fz*fz; + + if (fz > 24.0f / 116.0f) { + z = fz * fz * fz; } else { - z = (fz - 16.0f/116.0f)/7.787036979f; + z = (fz - 16.0f / 116.0f) / 7.787036979f; } + //0.9642, 1.0000, 0.8249 D50 X = x * 0.9642; Y = y; Z = z * 0.8249; } - r = prophoto_xyz[0][0]*X + prophoto_xyz[0][1]*Y + prophoto_xyz[0][2]*Z; - g = prophoto_xyz[1][0]*X + prophoto_xyz[1][1]*Y + prophoto_xyz[1][2]*Z; - b = prophoto_xyz[2][0]*X + prophoto_xyz[2][1]*Y + prophoto_xyz[2][2]*Z; + r = prophoto_xyz[0][0] * X + prophoto_xyz[0][1] * Y + prophoto_xyz[0][2] * Z; + g = prophoto_xyz[1][0] * X + prophoto_xyz[1][1] * Y + prophoto_xyz[1][2] * Z; + b = prophoto_xyz[2][0] * X + prophoto_xyz[2][1] * Y + prophoto_xyz[2][2] * Z; r = CLIP01(r); g = CLIP01(g); b = CLIP01(b); } // Converts raw image including ICC input profile to working space - floating point version -void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) { +void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) +{ // MyTime t1, t2, t3; // t1.set (); @@ -2432,36 +2806,39 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam return; } - if (dcpProf!=NULL) { + if (dcpProf != NULL) { // DCP processing dcpProf->Apply(im, cmp.dcpIlluminant, cmp.working, wb, pre_mul, camMatrix, false, cmp.applyHueSatMap, false); return; } - if (in==NULL) { + if (in == NULL) { // use default camprofile, supplied by dcraw // in this case we avoid using the slllllooooooowwww lcms // Calculate matrix for direct conversion raw>working space TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) - mat[i][j] += work[i][k] * camMatrix[k][j]; // rgb_xyz * imatrices.xyz_cam + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { + mat[i][j] += work[i][k] * camMatrix[k][j]; // rgb_xyz * imatrices.xyz_cam + } #pragma omp parallel for - for (int i=0; iheight; i++) - for (int j=0; jwidth; j++) { - float newr = mat[0][0]*im->r(i,j) + mat[0][1]*im->g(i,j) + mat[0][2]*im->b(i,j); - float newg = mat[1][0]*im->r(i,j) + mat[1][1]*im->g(i,j) + mat[1][2]*im->b(i,j); - float newb = mat[2][0]*im->r(i,j) + mat[2][1]*im->g(i,j) + mat[2][2]*im->b(i,j); + for (int i = 0; i < im->height; i++) + for (int j = 0; j < im->width; j++) { - im->r(i,j) = newr; - im->g(i,j) = newg; - im->b(i,j) = newb; + float newr = mat[0][0] * im->r(i, j) + mat[0][1] * im->g(i, j) + mat[0][2] * im->b(i, j); + float newg = mat[1][0] * im->r(i, j) + mat[1][1] * im->g(i, j) + mat[1][2] * im->b(i, j); + float newb = mat[2][0] * im->r(i, j) + mat[2][1] * im->g(i, j) + mat[2][2] * im->b(i, j); + + im->r(i, j) = newr; + im->g(i, j) = newg; + im->b(i, j) = newb; } } else { @@ -2500,30 +2877,31 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam } camera_icc_type = CAMERA_ICC_TYPE_GENERIC; float leaf_prophoto_mat[3][3]; - { // identify ICC type + { + // identify ICC type char copyright[256] = ""; char description[256] = ""; cmsGetProfileInfoASCII(in, cmsInfoCopyright, cmsNoLanguage, cmsNoCountry, copyright, 256); cmsGetProfileInfoASCII(in, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, description, 256); camera_icc_type = CAMERA_ICC_TYPE_GENERIC; + // Note: order the identification with the most detailed matching first since the more general ones may also match the more detailed if ((strstr(copyright, "Leaf") != NULL || - strstr(copyright, "Phase One A/S") != NULL || - strstr(copyright, "Kodak") != NULL || - strstr(copyright, "Creo") != NULL) && - (strstr(description,"LF2 ") == description || - strstr(description,"LF3 ") == description || - strstr(description,"LeafLF2") == description || - strstr(description,"LeafLF3") == description || - strstr(description,"LeafLF4") == description || - strstr(description,"MamiyaLF2") == description || - strstr(description,"MamiyaLF3") == description)) - { + strstr(copyright, "Phase One A/S") != NULL || + strstr(copyright, "Kodak") != NULL || + strstr(copyright, "Creo") != NULL) && + (strstr(description, "LF2 ") == description || + strstr(description, "LF3 ") == description || + strstr(description, "LeafLF2") == description || + strstr(description, "LeafLF3") == description || + strstr(description, "LeafLF4") == description || + strstr(description, "MamiyaLF2") == description || + strstr(description, "MamiyaLF3") == description)) { camera_icc_type = CAMERA_ICC_TYPE_LEAF; } else if (strstr(copyright, "Phase One A/S") != NULL) { camera_icc_type = CAMERA_ICC_TYPE_PHASE_ONE; - } else if (strstr(copyright,"Nikon Corporation")!=NULL) { + } else if (strstr(copyright, "Nikon Corporation") != NULL) { camera_icc_type = CAMERA_ICC_TYPE_NIKON; } } @@ -2534,6 +2912,7 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam bool transform_via_pcs_lab = false; bool separate_pcs_lab_highlights = false; lcmsMutex->lock (); + switch (camera_icc_type) { case CAMERA_ICC_TYPE_PHASE_ONE: case CAMERA_ICC_TYPE_LEAF: { @@ -2542,15 +2921,20 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam separate_pcs_lab_highlights = true; // We transform to Lab because we can and that we avoid getting an unnecessary unmatched gamma conversion which we would need to revert. hTransform = cmsCreateTransform (in, TYPE_RGB_FLT, NULL, TYPE_Lab_FLT, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); - for (int i=0; i<3; i++) { - for (int j=0; j<3; j++) { + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { leaf_prophoto_mat[i][j] = 0; - for (int k=0; k<3; k++) + + for (int k = 0; k < 3; k++) { leaf_prophoto_mat[i][j] += prophoto_xyz[i][k] * camMatrix[k][j]; + } } } + break; } + case CAMERA_ICC_TYPE_NIKON: case CAMERA_ICC_TYPE_GENERIC: default: @@ -2559,30 +2943,34 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam } lcmsMutex->unlock (); + if (hTransform == NULL) { // Fallback: create transform from camera profile. Should not happen normally. lcmsMutex->lock (); hTransform = cmsCreateTransform (camprofile, TYPE_RGB_FLT, prophoto, TYPE_RGB_FLT, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); lcmsMutex->unlock (); } + TMatrix toxyz, torgb; + if (!working_space_is_prophoto) { toxyz = iccStore->workingSpaceMatrix ("ProPhoto"); torgb = iccStore->workingSpaceInverseMatrix (cmp.working); //sRGB .. Adobe...Wide... } - #ifdef _OPENMP +#ifdef _OPENMP #pragma omp parallel - #endif +#endif { - AlignedBuffer buffer(im->width*3); - AlignedBuffer hl_buffer(im->width*3); + AlignedBuffer buffer(im->width * 3); + AlignedBuffer hl_buffer(im->width * 3); AlignedBuffer hl_scale(im->width); - #ifdef _OPENMP +#ifdef _OPENMP #pragma omp for schedule(static) - #endif +#endif + for ( int h = 0; h < im->height; ++h ) { - float *p=buffer.data, *pR=im->r(h), *pG=im->g(h), *pB=im->b(h); + float *p = buffer.data, *pR = im->r(h), *pG = im->g(h), *pB = im->b(h); // Apply pre-processing for ( int w = 0; w < im->width; ++w ) { @@ -2595,7 +2983,8 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam g /= 65535.0f; b /= 65535.0f; - float maxc = max(r,g,b); + float maxc = max(r, g, b); + if (maxc <= 1.0) { hl_scale.data[w] = 1.0; } else { @@ -2614,49 +3003,59 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam // We will revert this curve after we've made the color transform. However when we revert the curve, we'll notice that // highlight rendering suffers due to that the LUT transform don't expand well, therefore we do a less compressed // conversion too and mix them, this gives us the highest quality and most flexible result. - hl_buffer.data[3*w+0] = pow_F(r, 1.0/1.8); - hl_buffer.data[3*w+1] = pow_F(g, 1.0/1.8); - hl_buffer.data[3*w+2] = pow_F(b, 1.0/1.8); + hl_buffer.data[3 * w + 0] = pow_F(r, 1.0 / 1.8); + hl_buffer.data[3 * w + 1] = pow_F(g, 1.0 / 1.8); + hl_buffer.data[3 * w + 2] = pow_F(b, 1.0 / 1.8); r = phaseOneIccCurveInv->getVal(r); g = phaseOneIccCurveInv->getVal(g); b = phaseOneIccCurveInv->getVal(b); break; + case CAMERA_ICC_TYPE_LEAF: { // Leaf profiles expect that the camera native RGB has been converted to Prophoto RGB - float newr = leaf_prophoto_mat[0][0]*r + leaf_prophoto_mat[0][1]*g + leaf_prophoto_mat[0][2]*b; - float newg = leaf_prophoto_mat[1][0]*r + leaf_prophoto_mat[1][1]*g + leaf_prophoto_mat[1][2]*b; - float newb = leaf_prophoto_mat[2][0]*r + leaf_prophoto_mat[2][1]*g + leaf_prophoto_mat[2][2]*b; - hl_buffer.data[3*w+0] = pow_F(newr, 1.0/1.8); - hl_buffer.data[3*w+1] = pow_F(newg, 1.0/1.8); - hl_buffer.data[3*w+2] = pow_F(newb, 1.0/1.8); + float newr = leaf_prophoto_mat[0][0] * r + leaf_prophoto_mat[0][1] * g + leaf_prophoto_mat[0][2] * b; + float newg = leaf_prophoto_mat[1][0] * r + leaf_prophoto_mat[1][1] * g + leaf_prophoto_mat[1][2] * b; + float newb = leaf_prophoto_mat[2][0] * r + leaf_prophoto_mat[2][1] * g + leaf_prophoto_mat[2][2] * b; + hl_buffer.data[3 * w + 0] = pow_F(newr, 1.0 / 1.8); + hl_buffer.data[3 * w + 1] = pow_F(newg, 1.0 / 1.8); + hl_buffer.data[3 * w + 2] = pow_F(newb, 1.0 / 1.8); r = phaseOneIccCurveInv->getVal(newr); g = phaseOneIccCurveInv->getVal(newg); b = phaseOneIccCurveInv->getVal(newb); break; } + case CAMERA_ICC_TYPE_NIKON: // gamma 0.5 r = sqrtf(r); g = sqrtf(g); b = sqrtf(b); break; + case CAMERA_ICC_TYPE_GENERIC: default: // do nothing break; } - *(p++) = r; *(p++) = g; *(p++) = b; + *(p++) = r; + *(p++) = g; + *(p++) = b; } // Run icc transform cmsDoTransform (hTransform, buffer.data, buffer.data, im->width); + if (separate_pcs_lab_highlights) { cmsDoTransform (hTransform, hl_buffer.data, hl_buffer.data, im->width); } // Apply post-processing - p=buffer.data; pR=im->r(h); pG=im->g(h); pB=im->b(h); + p = buffer.data; + pR = im->r(h); + pG = im->g(h); + pB = im->b(h); + for ( int w = 0; w < im->width; ++w ) { float r, g, b, hr, hg, hb; @@ -2667,8 +3066,9 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam float B = *(p++); // profile connection space CIELAB should have D50 illuminant lab2ProphotoRgbD50(L, A, B, r, g, b); + if (separate_pcs_lab_highlights) { - lab2ProphotoRgbD50(hl_buffer.data[3*w+0], hl_buffer.data[3*w+1], hl_buffer.data[3*w+2], hr, hg, hb); + lab2ProphotoRgbD50(hl_buffer.data[3 * w + 0], hl_buffer.data[3 * w + 1], hl_buffer.data[3 * w + 2], hr, hg, hb); } } else { r = *(p++); @@ -2680,23 +3080,27 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam switch (camera_icc_type) { default: break; + case CAMERA_ICC_TYPE_PHASE_ONE: case CAMERA_ICC_TYPE_LEAF: { // note the 1/1.8 gamma, it's the gamma that the profile has applied, which we must revert before we can revert the curve - r = phaseOneIccCurve->getVal(pow_F(r, 1.0/1.8)); - g = phaseOneIccCurve->getVal(pow_F(g, 1.0/1.8)); - b = phaseOneIccCurve->getVal(pow_F(b, 1.0/1.8)); + r = phaseOneIccCurve->getVal(pow_F(r, 1.0 / 1.8)); + g = phaseOneIccCurve->getVal(pow_F(g, 1.0 / 1.8)); + b = phaseOneIccCurve->getVal(pow_F(b, 1.0 / 1.8)); const float mix = 0.25; // may seem a low number, but remember this is linear space, mixing starts 2 stops from clipping const float maxc = max(r, g, b); + if (maxc > mix) { float fac = (maxc - mix) / (1.0 - mix); fac = sqrtf(sqrtf(fac)); // gamma 0.25 to mix in highlight render relatively quick - r = (1.0-fac) * r + fac * hr; - g = (1.0-fac) * g + fac * hg; - b = (1.0-fac) * b + fac * hb; + r = (1.0 - fac) * r + fac * hr; + g = (1.0 - fac) * g + fac * hg; + b = (1.0 - fac) * b + fac * hb; } + break; } + case CAMERA_ICC_TYPE_NIKON: { const float lineFac = -0.4; const float lineSum = 1.35; @@ -2723,9 +3127,9 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam float y = (toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b ) ; float z = (toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b ) ; //convert from XYZ to cmp.working (sRGB...Adobe...Wide..) - r = ((torgb[0][0]*x + torgb[0][1]*y + torgb[0][2]*z)) ; - g = ((torgb[1][0]*x + torgb[1][1]*y + torgb[1][2]*z)) ; - b = ((torgb[2][0]*x + torgb[2][1]*y + torgb[2][2]*z)) ; + r = ((torgb[0][0] * x + torgb[0][1] * y + torgb[0][2] * z)) ; + g = ((torgb[1][0] * x + torgb[1][1] * y + torgb[1][2] * z)) ; + b = ((torgb[2][0] * x + torgb[2][1] * y + torgb[2][2] * z)) ; } // return to the 0.0 - 65535.0 range (with possible negative and > max values present) @@ -2733,13 +3137,15 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam g *= 65535.0; b *= 65535.0; - *(pR++) = r; *(pG++) = g; *(pB++) = b; + *(pR++) = r; + *(pG++) = g; + *(pB++) = b; } } } // End of parallelization cmsDeleteTransform(hTransform); } - + //t3.set (); // printf ("ICM TIME: %d usec\n", t3.etime(t1)); } @@ -2831,28 +3237,42 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam }*/ // Determine RAW input and output profiles. Returns TRUE on success -bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in) { - in=NULL; // cam will be taken on NULL - *dcpProf=NULL; +bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in) +{ + in = NULL; // cam will be taken on NULL + *dcpProf = NULL; - if (inProfile == "(none)") return false; + if (inProfile == "(none)") { + return false; + } if (inProfile == "(embedded)" && embedded) { - in = embedded; - } else if (inProfile=="(cameraICC)") { + in = embedded; + } else if (inProfile == "(cameraICC)") { // DCPs have higher quality, so use them first - *dcpProf=dcpStore->getStdProfile(camName); - if (*dcpProf==NULL) in = iccStore->getStdProfile(camName); - } else if (inProfile!="(camera)" && inProfile!="") { - Glib::ustring normalName=inProfile; - if (!inProfile.compare (0, 5, "file:")) normalName=inProfile.substr(5); + *dcpProf = dcpStore->getStdProfile(camName); - if (dcpStore->isValidDCPFileName(normalName)) *dcpProf=dcpStore->getProfile(normalName); - if (*dcpProf==NULL) in = iccStore->getProfile (inProfile); + if (*dcpProf == NULL) { + in = iccStore->getStdProfile(camName); + } + } else if (inProfile != "(camera)" && inProfile != "") { + Glib::ustring normalName = inProfile; + + if (!inProfile.compare (0, 5, "file:")) { + normalName = inProfile.substr(5); + } + + if (dcpStore->isValidDCPFileName(normalName)) { + *dcpProf = dcpStore->getProfile(normalName); + } + + if (*dcpProf == NULL) { + in = iccStore->getProfile (inProfile); + } } - + // "in" might be NULL because of "not found". That's ok, we take the cam profile then - + return true; } @@ -2860,702 +3280,849 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed // derived from Dcraw "blend_highlights()" // very effective to reduce (or remove) the magenta, but with levels of grey ! void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int width, float maxval, float* hlmax) - { - const int ColorCount=3; +{ + const int ColorCount = 3; + + // Transform matrixes rgb>lab and back + static const float trans[2][ColorCount][ColorCount] = { + { { 1, 1, 1 }, { 1.7320508, -1.7320508, 0 }, { -1, -1, 2 } }, + { { 1, 1, 1 }, { 1, -1, 1 }, { 1, 1, -1 } } + }; + static const float itrans[2][ColorCount][ColorCount] = { + { { 1, 0.8660254, -0.5 }, { 1, -0.8660254, -0.5 }, { 1, 0, 1 } }, + { { 1, 1, 1 }, { 1, -1, 1 }, { 1, 1, -1 } } + }; - // Transform matrixes rgb>lab and back - static const float trans[2][ColorCount][ColorCount] = - { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, - { { 1,1,1 }, { 1,-1,1 }, { 1,1,-1 } } }; - static const float itrans[2][ColorCount][ColorCount] = - { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, - { { 1,1,1 }, { 1,-1,1 }, { 1,1,-1 } } }; - #define FOREACHCOLOR for (int c=0; c < ColorCount; c++) - - float minpt=min(hlmax[0],hlmax[1],hlmax[2]);//min of the raw clip points - //float maxpt=max(hlmax[0],hlmax[1],hlmax[2]);//max of the raw clip points - //float medpt=hlmax[0]+hlmax[1]+hlmax[2]-minpt-maxpt;//median of the raw clip points - float maxave=(hlmax[0]+hlmax[1]+hlmax[2])/3;//ave of the raw clip points - //some thresholds: - const float clipthresh = 0.95; - const float fixthresh = 0.5; - const float satthresh = 0.5; - float clip[3]; - FOREACHCOLOR clip[c]=min(maxave,hlmax[c]); - - // Determine the maximum level (clip) of all channels - const float clippt = clipthresh*maxval; - const float fixpt = fixthresh*minpt; - const float desatpt = satthresh*maxave+(1-satthresh)*maxval; + float minpt = min(hlmax[0], hlmax[1], hlmax[2]); //min of the raw clip points + //float maxpt=max(hlmax[0],hlmax[1],hlmax[2]);//max of the raw clip points + //float medpt=hlmax[0]+hlmax[1]+hlmax[2]-minpt-maxpt;//median of the raw clip points + float maxave = (hlmax[0] + hlmax[1] + hlmax[2]) / 3; //ave of the raw clip points + //some thresholds: + const float clipthresh = 0.95; + const float fixthresh = 0.5; + const float satthresh = 0.5; - for (int col=0; col clippt) break; } - if (c == ColorCount) continue; - - // Initialize cam with raw input [0] and potentially clipped input [1] - FOREACHCOLOR { - lratio += min(rgb[c],clip[c]); - cam[0][c] = rgb[c]; - cam[1][c] = min(cam[0][c],maxval); - } - - // Calculate the lightness correction ratio (chratio) - for (int i=0; i<2; i++) { - FOREACHCOLOR { - lab[i][c]=0; - for (int j=0; j < ColorCount; j++) - lab[i][c] += trans[ColorCount-3][c][j] * cam[i][j]; - } - - sum[i]=0; - for (int c=1; c < ColorCount; c++) - sum[i] += SQR(lab[i][c]); - } - chratio = (sqrt(sum[1]/sum[0])); - - // Apply ratio to lightness in LCH space - for (int c=1; c < ColorCount; c++) - lab[0][c] *= chratio; - - // Transform back from LCH to RGB - FOREACHCOLOR { - cam[0][c]=0; - for (int j=0; j < ColorCount; j++) { - cam[0][c] += itrans[ColorCount-3][c][j] * lab[0][j]; - } - } - FOREACHCOLOR rgb[c] = cam[0][c] / ColorCount; + float clip[3]; + FOREACHCOLOR clip[c] = min(maxave, hlmax[c]); - // Copy converted pixel back - if (rin[col] > fixpt) { - float rfrac = SQR((min(clip[0],rin[col])-fixpt)/(clip[0]-fixpt)); - rin[col]= min(maxave,rfrac*rgb[0]+(1-rfrac)*rin[col]); - } - if (gin[col] > fixpt) { - float gfrac = SQR((min(clip[1],gin[col])-fixpt)/(clip[1]-fixpt)); - gin[col]= min(maxave,gfrac*rgb[1]+(1-gfrac)*gin[col]); - } - if (bin[col] > fixpt) { - float bfrac = SQR((min(clip[2],bin[col])-fixpt)/(clip[2]-fixpt)); - bin[col]= min(maxave,bfrac*rgb[2]+(1-bfrac)*bin[col]); - } - - lratio /= (rin[col]+gin[col]+bin[col]); - L = (rin[col]+gin[col]+bin[col])/3; - C = lratio * 1.732050808 * (rin[col] - gin[col]); - H = lratio * (2 * bin[col] - rin[col] - gin[col]); - rin[col] = L - H / 6.0 + C / 3.464101615; - gin[col] = L - H / 6.0 - C / 3.464101615; - bin[col] = L + H / 3.0; - - if ((L=(rin[col]+gin[col]+bin[col])/3) > desatpt) { - Lfrac = max(0.0f,(maxave-L)/(maxave-desatpt)); - C = Lfrac * 1.732050808 * (rin[col] - gin[col]); - H = Lfrac * (2 * bin[col] - rin[col] - gin[col]); - rin[col] = L - H / 6.0 + C / 3.464101615; - gin[col] = L - H / 6.0 - C / 3.464101615; - bin[col] = L + H / 3.0; - } - } - } + // Determine the maximum level (clip) of all channels + const float clippt = clipthresh * maxval; + const float fixpt = fixthresh * minpt; + const float desatpt = satthresh * maxave + (1 - satthresh) * maxval; -void RawImageSource::HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval) { + for (int col = 0; col < width; col++) { + float rgb[ColorCount], cam[2][ColorCount], lab[2][ColorCount], sum[2], chratio, lratio = 0; + float L, C, H, Lfrac; - for (int i=0; i clippt) { + break; + } + } + + if (c == ColorCount) { + continue; + } + + // Initialize cam with raw input [0] and potentially clipped input [1] + FOREACHCOLOR { + lratio += min(rgb[c], clip[c]); + cam[0][c] = rgb[c]; + cam[1][c] = min(cam[0][c], maxval); + } + + // Calculate the lightness correction ratio (chratio) + for (int i = 0; i < 2; i++) { + FOREACHCOLOR { + lab[i][c] = 0; + + for (int j = 0; j < ColorCount; j++) + { + lab[i][c] += trans[ColorCount - 3][c][j] * cam[i][j]; + } + } + + sum[i] = 0; + + for (int c = 1; c < ColorCount; c++) { + sum[i] += SQR(lab[i][c]); + } + } + + chratio = (sqrt(sum[1] / sum[0])); + + // Apply ratio to lightness in LCH space + for (int c = 1; c < ColorCount; c++) { + lab[0][c] *= chratio; + } + + // Transform back from LCH to RGB + FOREACHCOLOR { + cam[0][c] = 0; + + for (int j = 0; j < ColorCount; j++) + { + cam[0][c] += itrans[ColorCount - 3][c][j] * lab[0][j]; + } + } + FOREACHCOLOR rgb[c] = cam[0][c] / ColorCount; + + // Copy converted pixel back + if (rin[col] > fixpt) { + float rfrac = SQR((min(clip[0], rin[col]) - fixpt) / (clip[0] - fixpt)); + rin[col] = min(maxave, rfrac * rgb[0] + (1 - rfrac) * rin[col]); + } + + if (gin[col] > fixpt) { + float gfrac = SQR((min(clip[1], gin[col]) - fixpt) / (clip[1] - fixpt)); + gin[col] = min(maxave, gfrac * rgb[1] + (1 - gfrac) * gin[col]); + } + + if (bin[col] > fixpt) { + float bfrac = SQR((min(clip[2], bin[col]) - fixpt) / (clip[2] - fixpt)); + bin[col] = min(maxave, bfrac * rgb[2] + (1 - bfrac) * bin[col]); + } + + lratio /= (rin[col] + gin[col] + bin[col]); + L = (rin[col] + gin[col] + bin[col]) / 3; + C = lratio * 1.732050808 * (rin[col] - gin[col]); + H = lratio * (2 * bin[col] - rin[col] - gin[col]); + rin[col] = L - H / 6.0 + C / 3.464101615; + gin[col] = L - H / 6.0 - C / 3.464101615; + bin[col] = L + H / 3.0; + + if ((L = (rin[col] + gin[col] + bin[col]) / 3) > desatpt) { + Lfrac = max(0.0f, (maxave - L) / (maxave - desatpt)); + C = Lfrac * 1.732050808 * (rin[col] - gin[col]); + H = Lfrac * (2 * bin[col] - rin[col] - gin[col]); + rin[col] = L - H / 6.0 + C / 3.464101615; + gin[col] = L - H / 6.0 - C / 3.464101615; + bin[col] = L + H / 3.0; + } + } +} + +void RawImageSource::HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval) +{ + + for (int i = 0; i < width; i++) { float r = rin[i], g = gin[i], b = bin[i]; - if (r>maxval || g>maxval || b>maxval) { - float ro = min(r, maxval); - float go = min(g, maxval); - float bo = min(b, maxval); + + if (r > maxval || g > maxval || b > maxval) { + float ro = min(r, maxval); + float go = min(g, maxval); + float bo = min(b, maxval); double L = r + g + b; double C = 1.732050808 * (r - g); double H = 2 * b - r - g; double Co = 1.732050808 * (ro - go); double Ho = 2 * bo - ro - go; - if (r!=g && g!=b) { - double ratio = sqrt ((Co*Co+Ho*Ho) / (C*C+H*H)); + + if (r != g && g != b) { + double ratio = sqrt ((Co * Co + Ho * Ho) / (C * C + H * H)); C *= ratio; H *= ratio; } + float rr = L / 3.0 - H / 6.0 + C / 3.464101615; float gr = L / 3.0 - H / 6.0 - C / 3.464101615; float br = L / 3.0 + H / 3.0; - rout[i] = rr; - gout[i] = gr; - bout[i] = br; - } - else { + rout[i] = rr; + gout[i] = gr; + bout[i] = br; + } else { rout[i] = rin[i]; gout[i] = gin[i]; bout[i] = bin[i]; } } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, - int width, float maxval, double xyz_cam[3][3], double cam_xyz[3][3]) { + int width, float maxval, double xyz_cam[3][3], double cam_xyz[3][3]) +{ //static bool crTableReady = false; - - // lookup table for Lab conversion - // perhaps should be centralized, universally defined so we don't keep remaking it??? + + // lookup table for Lab conversion + // perhaps should be centralized, universally defined so we don't keep remaking it??? /*for (int ix=0; ix < 0x10000; ix++) { - float rx = ix / 65535.0; - fv[ix] = rx > 0.008856 ? exp(1.0/3 * log(rx)) : 7.787*rx + 16/116.0; - }*/ - //crTableReady = true; + float rx = ix / 65535.0; + fv[ix] = rx > 0.008856 ? exp(1.0/3 * log(rx)) : 7.787*rx + 16/116.0; + }*/ + //crTableReady = true; - for (int i=0; imaxval || g>maxval || b>maxval) { - float ro = min(r, maxval); - 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 ))); + + if (r > maxval || g > maxval || b > maxval) { + float ro = min(r, maxval); + 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 ))); // 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 ))); + 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 ))); // convert back to rgb double fz = fy - y + z; double fx = fy + x - y; - double zr = Color::f2xyz(fz); + double zr = Color::f2xyz(fz); double xr = Color::f2xyz(fx); - x = xr*65535.0 ; + x = xr * 65535.0 ; y = yy; - z = zr*65535.0 ; - float rr = cam_xyz[0][0]*x + cam_xyz[0][1]*y + cam_xyz[0][2]*z; - float gr = cam_xyz[1][0]*x + cam_xyz[1][1]*y + cam_xyz[1][2]*z; - float br = cam_xyz[2][0]*x + cam_xyz[2][1]*y + cam_xyz[2][2]*z; - rout[i] = (rr); - gout[i] = (gr); - bout[i] = (br); - } - else { + z = zr * 65535.0 ; + float rr = cam_xyz[0][0] * x + cam_xyz[0][1] * y + cam_xyz[0][2] * z; + float gr = cam_xyz[1][0] * x + cam_xyz[1][1] * y + cam_xyz[1][2] * z; + float br = cam_xyz[2][0] * x + cam_xyz[2][1] * y + cam_xyz[2][2] * z; + rout[i] = (rr); + gout[i] = (gr); + bout[i] = (br); + } else { rout[i] = (rin[i]); gout[i] = (gin[i]); bout[i] = (bin[i]); } } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip,const RAWParams &raw, float* hlmax ) { - - if (method=="Luminance") +void RawImageSource::hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip, const RAWParams &raw, float* hlmax ) +{ + + if (method == "Luminance") { HLRecovery_Luminance (red, green, blue, red, green, blue, width, 65535.0); - else if (method=="CIELab blending") + } else if (method == "CIELab blending") { HLRecovery_CIELab (red, green, blue, red, green, blue, width, 65535.0, imatrices.xyz_cam, imatrices.cam_xyz); + } /*else if (method=="Color") HLRecovery_ColorPropagation (red, green, blue, i, sx1, width, skip);*/ - else if (method=="Blend") // derived from Dcraw + else if (method == "Blend") { // derived from Dcraw HLRecovery_blend(red, green, blue, width, 65535.0, hlmax); + } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) { +void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) +{ histcompr = 3; - histogram(65536>>histcompr); + histogram(65536 >> histcompr); histogram.clear(); -#pragma omp parallel -{ - LUTu tmphistogram(65536>>histcompr); - tmphistogram.clear(); -#pragma omp for nowait - for (int i=border; i> histcompr); + tmphistogram.clear(); + #pragma omp for nowait - if (ri->getSensorType()==ST_BAYER) { - for (int j=start; jISGREEN(i,j)) tmphistogram[CLIP((int)(refwb_green*rawData[i][j]))>>histcompr]+=4; - else if (ri->ISRED(i,j)) tmphistogram[CLIP((int)(refwb_red* rawData[i][j]))>>histcompr]+=4; - else if (ri->ISBLUE(i,j)) tmphistogram[CLIP((int)(refwb_blue* rawData[i][j]))>>histcompr]+=4; - } - } else if (ri->getSensorType()==ST_FUJI_XTRANS) { - for (int j=start; jISXTRANSGREEN(i,j)) tmphistogram[CLIP((int)(refwb_green*rawData[i][j]))>>histcompr]+=4; - else if (ri->ISXTRANSRED(i,j)) tmphistogram[CLIP((int)(refwb_red* rawData[i][j]))>>histcompr]+=4; - else if (ri->ISXTRANSBLUE(i,j)) tmphistogram[CLIP((int)(refwb_blue* rawData[i][j]))>>histcompr]+=4; - } - } else if (ri->get_colors() == 1) { - for (int j=start; j>histcompr]++; - } - } else { - for (int j=start; j>histcompr]++; - tmphistogram[CLIP((int)(refwb_green*rawData[i][3*j+1]))>>histcompr]+=2; - tmphistogram[CLIP((int)(refwb_blue* rawData[i][3*j+2]))>>histcompr]++; - } - } + for (int i = border; i < H - border; i++) { + int start, end; + getRowStartEnd (i, start, end); + + if (ri->getSensorType() == ST_BAYER) { + for (int j = start; j < end; j++) { + if (ri->ISGREEN(i, j)) { + tmphistogram[CLIP((int)(refwb_green * rawData[i][j])) >> histcompr] += 4; + } else if (ri->ISRED(i, j)) { + tmphistogram[CLIP((int)(refwb_red * rawData[i][j])) >> histcompr] += 4; + } else if (ri->ISBLUE(i, j)) { + tmphistogram[CLIP((int)(refwb_blue * rawData[i][j])) >> histcompr] += 4; + } + } + } else if (ri->getSensorType() == ST_FUJI_XTRANS) { + for (int j = start; j < end; j++) { + if (ri->ISXTRANSGREEN(i, j)) { + tmphistogram[CLIP((int)(refwb_green * rawData[i][j])) >> histcompr] += 4; + } else if (ri->ISXTRANSRED(i, j)) { + tmphistogram[CLIP((int)(refwb_red * rawData[i][j])) >> histcompr] += 4; + } else if (ri->ISXTRANSBLUE(i, j)) { + tmphistogram[CLIP((int)(refwb_blue * rawData[i][j])) >> histcompr] += 4; + } + } + } else if (ri->get_colors() == 1) { + for (int j = start; j < end; j++) { + tmphistogram[CLIP((int)(refwb_red * rawData[i][j])) >> histcompr]++; + } + } else { + for (int j = start; j < end; j++) { + tmphistogram[CLIP((int)(refwb_red * rawData[i][3 * j + 0])) >> histcompr]++; + tmphistogram[CLIP((int)(refwb_green * rawData[i][3 * j + 1])) >> histcompr] += 2; + tmphistogram[CLIP((int)(refwb_blue * rawData[i][3 * j + 2])) >> histcompr]++; + } + } + } + + #pragma omp critical + { + for(int i = 0; i < (65536 >> histcompr); i++) { + histogram[i] += tmphistogram[i]; + } + } } -#pragma omp critical -{ - for(int i=0; i<(65536>>histcompr);i++) - histogram[i] += tmphistogram[i]; } -} -} - + // Histogram MUST be 256 in size; gamma is applied, blackpoint and gain also -void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) { - - histRedRaw.clear(); histGreenRaw.clear(); histBlueRaw.clear(); - const float mult[4] = { 65535.0 / ri->get_white(0), 65535.0 / ri->get_white(1), 65535.0 / ri->get_white(2), 65535.0 / ri->get_white(3) }; - -#ifdef _OPENMP - int numThreads; - // reduce the number of threads under certain conditions to avoid overhaed of too many critical regions - numThreads = sqrt((((H-2*border)*(W-2*border))/262144.f)); - numThreads = std::min(std::max(numThreads,1), omp_get_max_threads()); - -#pragma omp parallel num_threads(numThreads) -#endif +void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) { - // we need one LUT per color and thread, which corresponds to 1 MB per thread - LUTu tmphist[4]; - tmphist[0](65536);tmphist[0].clear(); - tmphist[1](65536);tmphist[1].clear(); - tmphist[2](65536);tmphist[2].clear(); - tmphist[3](65536);tmphist[3].clear(); - -#ifdef _OPENMP -#pragma omp for nowait -#endif - for (int i=border; igetSensorType()==ST_BAYER) { - int j; - int c1 = FC(i,start); - c1 = ( c1 == 1 && !(i&1) ) ? 3 : c1; - int c2 = FC(i,start+1); - c2 = ( c2 == 1 && !(i&1) ) ? 3 : c2; - for (j=start; jdata[i][j]]++; - tmphist[c2][(int)ri->data[i][j+1]]++; - } - if(jdata[i][j]]++; - } - } else if (ri->get_colors() == 1) { - for (int j=start; jdata[i][j]]++; - } - } - } else if(ri->getSensorType()==ST_FUJI_XTRANS) { - for (int j=start; jXTRANSFC(i,j); - tmphist[c][(int)ri->data[i][j]]++; - } - } else { - for (int j=start; jdata[i][3*j+c]]++; - } - } - } - } + histRedRaw.clear(); + histGreenRaw.clear(); + histBlueRaw.clear(); + const float mult[4] = { 65535.0 / ri->get_white(0), 65535.0 / ri->get_white(1), 65535.0 / ri->get_white(2), 65535.0 / ri->get_white(3) }; + #ifdef _OPENMP -#pragma omp critical -#endif -{ - for(int i=0;i<65536;i++){ - int idx; - idx = CLIP((int)Color::gamma(mult[0]*(i-(cblacksom[0]/*+black_lev[0]*/)))); - histRedRaw[idx>>8] += tmphist[0][i]; - idx = CLIP((int)Color::gamma(mult[1]*(i-(cblacksom[1]/*+black_lev[1]*/)))); - histGreenRaw[idx>>8] += tmphist[1][i]; - idx = CLIP((int)Color::gamma(mult[3]*(i-(cblacksom[3]/*+black_lev[3]*/)))); - histGreenRaw[idx>>8] += tmphist[3][i]; - idx = CLIP((int)Color::gamma(mult[2]*(i-(cblacksom[2]/*+black_lev[2]*/)))); - histBlueRaw[idx>>8] += tmphist[2][i]; - } -} // end of critical region -} // end of parallel region + int numThreads; + // reduce the number of threads under certain conditions to avoid overhaed of too many critical regions + numThreads = sqrt((((H - 2 * border) * (W - 2 * border)) / 262144.f)); + numThreads = std::min(std::max(numThreads, 1), omp_get_max_threads()); + + #pragma omp parallel num_threads(numThreads) +#endif + { + // we need one LUT per color and thread, which corresponds to 1 MB per thread + LUTu tmphist[4]; + tmphist[0](65536); + tmphist[0].clear(); + tmphist[1](65536); + tmphist[1].clear(); + tmphist[2](65536); + tmphist[2].clear(); + tmphist[3](65536); + tmphist[3].clear(); + +#ifdef _OPENMP + #pragma omp for nowait +#endif + + for (int i = border; i < H - border; i++) { + int start, end; + getRowStartEnd (i, start, end); + + if (ri->getSensorType() == ST_BAYER) { + int j; + int c1 = FC(i, start); + c1 = ( c1 == 1 && !(i & 1) ) ? 3 : c1; + int c2 = FC(i, start + 1); + c2 = ( c2 == 1 && !(i & 1) ) ? 3 : c2; + + for (j = start; j < end - 1; j += 2) { + tmphist[c1][(int)ri->data[i][j]]++; + tmphist[c2][(int)ri->data[i][j + 1]]++; + } + + if(j < end) { // last pixel of row if width is odd + tmphist[c1][(int)ri->data[i][j]]++; + } + } else if (ri->get_colors() == 1) { + for (int j = start; j < end; j++) { + for (int c = 0; c < 3; c++) { + tmphist[c][(int)ri->data[i][j]]++; + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + for (int j = start; j < end - 1; j += 2) { + int c = ri->XTRANSFC(i, j); + tmphist[c][(int)ri->data[i][j]]++; + } + } else { + for (int j = start; j < end; j++) { + for (int c = 0; c < 3; c++) { + tmphist[c][(int)ri->data[i][3 * j + c]]++; + } + } + } + } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + for(int i = 0; i < 65536; i++) { + int idx; + idx = CLIP((int)Color::gamma(mult[0] * (i - (cblacksom[0]/*+black_lev[0]*/)))); + histRedRaw[idx >> 8] += tmphist[0][i]; + idx = CLIP((int)Color::gamma(mult[1] * (i - (cblacksom[1]/*+black_lev[1]*/)))); + histGreenRaw[idx >> 8] += tmphist[1][i]; + idx = CLIP((int)Color::gamma(mult[3] * (i - (cblacksom[3]/*+black_lev[3]*/)))); + histGreenRaw[idx >> 8] += tmphist[3][i]; + idx = CLIP((int)Color::gamma(mult[2] * (i - (cblacksom[2]/*+black_lev[2]*/)))); + histBlueRaw[idx >> 8] += tmphist[2][i]; + } + } // end of critical region + } // end of parallel region + + + if (ri->getSensorType() == ST_BAYER) // since there are twice as many greens, correct for it + for (int i = 0; i < 256; i++) { + histGreenRaw[i] >>= 1; + } + else if(ri->getSensorType() == ST_FUJI_XTRANS) // since Xtrans has 2.5 as many greens, correct for it + for (int i = 0; i < 256; i++) { + histGreenRaw[i] = (histGreenRaw[i] * 2) / 5; + } - - if (ri->getSensorType()==ST_BAYER) // since there are twice as many greens, correct for it - for (int i=0;i<256;i++) - histGreenRaw[i]>>=1; - else if(ri->getSensorType()==ST_FUJI_XTRANS) // since Xtrans has 2.5 as many greens, correct for it - for (int i=0;i<256;i++) - histGreenRaw[i] = (histGreenRaw[i]*2)/5; - } -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::getRowStartEnd (int x, int &start, int &end) { +void RawImageSource::getRowStartEnd (int x, int &start, int &end) +{ if (fuji) { int fw = ri->get_FujiWidth(); - start = ABS(fw-x) + border; - end = min(H+ W-fw-x, fw+x) - border; - } - else { + start = ABS(fw - x) + border; + end = min(H + W - fw - x, fw + x) - border; + } else { start = border; - end = W-border; + end = W - border; } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) { +void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) +{ - if (ri->get_colors() == 1) { - rm = gm = bm = 1; - return; - } - if (redAWBMul != -1.) { - rm = redAWBMul; - gm = greenAWBMul; - bm = blueAWBMul; - return; - } + if (ri->get_colors() == 1) { + rm = gm = bm = 1; + return; + } - if (!isWBProviderReady()) { - rm = -1.0; - gm = -1.0; - bm = -1.0; - return; - } + if (redAWBMul != -1.) { + rm = redAWBMul; + gm = greenAWBMul; + bm = blueAWBMul; + return; + } - double avg_r = 0; - double avg_g = 0; - double avg_b = 0; - int rn = 0, gn = 0, bn = 0; - - if (fuji) { - for (int i=32; iget_FujiWidth(); - int start = ABS(fw-i) + 32; - int end = min(H+W-fw-i, fw+i) - 32; - for (int j=start; jgetSensorType()!=ST_BAYER) { - double dr = CLIP(initialGain*(rawData[i][3*j] )); - double dg = CLIP(initialGain*(rawData[i][3*j+1])); - double db = CLIP(initialGain*(rawData[i][3*j+2])); - if (dr>64000. || dg>64000. || db>64000.) continue; - avg_r += dr; - avg_g += dg; - avg_b += db; - rn = gn = ++bn; - } - else { - int c = FC( i, j); - double d = CLIP(initialGain*(rawData[i][j])); - if (d>64000.) - continue; - // Let's test green first, because they are more numerous - if (c==1) { - avg_g += d; - gn++; - } - else if (c==0) { - avg_r += d; - rn++; - } - else /*if (c==2)*/ { - avg_b += d; - bn++; - } - } - } - } - } - else { - if (ri->getSensorType()!=ST_BAYER) { - if(ri->getSensorType()==ST_FUJI_XTRANS) { - for (int i=32; iISXTRANSRED(i,j)) { - float dr = CLIP(initialGain*(rawData[i][j])); - if (dr>64000.f) - continue; - avg_r += dr; - rn ++; - } - if(ri->ISXTRANSGREEN(i,j)) { - float dg = CLIP(initialGain*(rawData[i][j])); - if (dg>64000.f) - continue; - avg_g += dg; - gn ++; - } - if(ri->ISXTRANSBLUE(i,j)) { - float db = CLIP(initialGain*(rawData[i][j])); - if (db>64000.f) - continue; - avg_b += db; - bn ++; - } - } - } else { - for (int i=32; i64000. || dg>64000. || db>64000.) continue; - avg_r += dr; rn++; - avg_g += dg; - avg_b += db; - } - gn = rn; bn=rn; - } - } else { - //determine GRBG coset; (ey,ex) is the offset of the R subarray - int ey, ex; - if (ri->ISGREEN(0,0)) {//first pixel is G - if (ri->ISRED(0,1)) {ey=0; ex=1;} else {ey=1; ex=0;} - } else {//first pixel is R or B - if (ri->ISRED(0,0)) {ey=0; ex=0;} else {ey=1; ex=1;} - } - double d[2][2]; - for (int i=32; iverbose ) - printf ("AVG: %g %g %g\n", avg_r/rn, avg_g/gn, avg_b/bn); - - // return ColorTemp (pow(avg_r/rn, 1.0/6.0)*img_r, pow(avg_g/gn, 1.0/6.0)*img_g, pow(avg_b/bn, 1.0/6.0)*img_b); - - double reds = avg_r/rn * refwb_red; - double greens = avg_g/gn * refwb_green; - double blues = avg_b/bn * refwb_blue; - - redAWBMul = rm = imatrices.rgb_cam[0][0]*reds + imatrices.rgb_cam[0][1]*greens + imatrices.rgb_cam[0][2]*blues; - greenAWBMul = gm = imatrices.rgb_cam[1][0]*reds + imatrices.rgb_cam[1][1]*greens + imatrices.rgb_cam[1][2]*blues; - blueAWBMul = bm = imatrices.rgb_cam[2][0]*reds + imatrices.rgb_cam[2][1]*greens + imatrices.rgb_cam[2][2]*blues; - } - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) { - - int x; int y; - double reds = 0, greens = 0, blues = 0; - int rn = 0; - - if (ri->getSensorType()!=ST_BAYER) { - if(ri->getSensorType()==ST_FUJI_XTRANS) { - int d[9][2] = {{0,0}, {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}}; - double rloc, gloc, bloc; - int rnbrs, gnbrs, bnbrs; - for (size_t i=0; i=0 && yv>=0 && xvISXTRANSRED(yv,xv)) { //RED - rloc += (rawData[yv][xv]); - rnbrs++; - continue; - } else if (ri->ISXTRANSBLUE(yv,xv)) { //BLUE - bloc += (rawData[yv][xv]); - bnbrs++; - continue; - } else { // GREEN - gloc += (rawData[yv][xv]); - gnbrs++; - continue; - } - } - } - rloc /= rnbrs; gloc /= gnbrs; bloc /= bnbrs; - if (rloc*initialGain<64000. && gloc*initialGain<64000. && bloc*initialGain<64000.) { - reds += rloc; greens += gloc; blues += bloc; rn++; - } - } - - } else { - int xmin, xmax, ymin, ymax; - int xr, xg, xb, yr, yg, yb; - for (size_t i=0; i52500 || - initialGain*(rawData[yg][3*xg+1])>52500 || - initialGain*(rawData[yb][3*xb+2])>52500) continue; - xmin = min(xr,xg,xb); - xmax = max(xr,xg,xb); - ymin = min(yr,yg,yb); - ymax = max(yr,yg,yb); - if (xmin>=0 && ymin>=0 && xmax=0 && yv>=0 && xv=0 && yv>=0 && xv=0 && yv>=0 && xvget_FujiWidth(); + int start = ABS(fw - i) + 32; + int end = min(H + W - fw - i, fw + i) - 32; + + for (int j = start; j < end; j++) { + if (ri->getSensorType() != ST_BAYER) { + double dr = CLIP(initialGain * (rawData[i][3 * j] )); + double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); + double db = CLIP(initialGain * (rawData[i][3 * j + 2])); + + if (dr > 64000. || dg > 64000. || db > 64000.) { + continue; + } + + avg_r += dr; + avg_g += dg; + avg_b += db; + rn = gn = ++bn; + } else { + int c = FC( i, j); + double d = CLIP(initialGain * (rawData[i][j])); + + if (d > 64000.) { + continue; + } + + // Let's test green first, because they are more numerous + if (c == 1) { + avg_g += d; + gn++; + } else if (c == 0) { + avg_r += d; + rn++; + } else { /*if (c==2)*/ + avg_b += d; + bn++; + } + } + } + } + } else { + if (ri->getSensorType() != ST_BAYER) { + if(ri->getSensorType() == ST_FUJI_XTRANS) { + for (int i = 32; i < H - 32; i++) + for (int j = 32; j < W - 32; j++) { + // each loop read 1 rgb triplet value + if(ri->ISXTRANSRED(i, j)) { + float dr = CLIP(initialGain * (rawData[i][j])); + + if (dr > 64000.f) { + continue; + } + + avg_r += dr; + rn ++; + } + + if(ri->ISXTRANSGREEN(i, j)) { + float dg = CLIP(initialGain * (rawData[i][j])); + + if (dg > 64000.f) { + continue; + } + + avg_g += dg; + gn ++; + } + + if(ri->ISXTRANSBLUE(i, j)) { + float db = CLIP(initialGain * (rawData[i][j])); + + if (db > 64000.f) { + continue; + } + + avg_b += db; + bn ++; + } + } + } else { + for (int i = 32; i < H - 32; i++) + for (int j = 32; j < W - 32; j++) { + // each loop read 1 rgb triplet value + + double dr = CLIP(initialGain * (rawData[i][3 * j] )); + double dg = CLIP(initialGain * (rawData[i][3 * j + 1])); + double db = CLIP(initialGain * (rawData[i][3 * j + 2])); + + if (dr > 64000. || dg > 64000. || db > 64000.) { + continue; + } + + avg_r += dr; + rn++; + avg_g += dg; + avg_b += db; + } + + gn = rn; + bn = rn; + } + } else { + //determine GRBG coset; (ey,ex) is the offset of the R subarray + int ey, ex; + + if (ri->ISGREEN(0, 0)) { //first pixel is G + if (ri->ISRED(0, 1)) { + ey = 0; + ex = 1; + } else { + ey = 1; + ex = 0; + } + } else {//first pixel is R or B + if (ri->ISRED(0, 0)) { + ey = 0; + ex = 0; + } else { + ey = 1; + ex = 1; + } + } + + double d[2][2]; + + for (int i = 32; i < H - 32; i += 2) + for (int j = 32; j < W - 32; j += 2) { + //average each Bayer quartet component individually if non-clipped + d[0][0] = CLIP(initialGain * (rawData[i][j] )); + d[0][1] = CLIP(initialGain * (rawData[i][j + 1] )); + d[1][0] = CLIP(initialGain * (rawData[i + 1][j] )); + d[1][1] = CLIP(initialGain * (rawData[i + 1][j + 1])); + + if (d[ey][ex] <= 64000.) { + avg_r += d[ey][ex]; + rn++; + } + + if (d[1 - ey][ex] <= 64000.) { + avg_g += d[1 - ey][ex]; + gn++; + } + + if (d[ey][1 - ex] <= 64000.) { + avg_g += d[ey][1 - ex]; + gn++; + } + + if (d[1 - ey][1 - ex] <= 64000.) { + avg_b += d[1 - ey][1 - ex]; + bn++; + } + } + } + } + + if( settings->verbose ) { + printf ("AVG: %g %g %g\n", avg_r / rn, avg_g / gn, avg_b / bn); + } + + // return ColorTemp (pow(avg_r/rn, 1.0/6.0)*img_r, pow(avg_g/gn, 1.0/6.0)*img_g, pow(avg_b/bn, 1.0/6.0)*img_b); + + double reds = avg_r / rn * refwb_red; + double greens = avg_g / gn * refwb_green; + double blues = avg_b / bn * refwb_blue; + + redAWBMul = rm = imatrices.rgb_cam[0][0] * reds + imatrices.rgb_cam[0][1] * greens + imatrices.rgb_cam[0][2] * blues; + greenAWBMul = gm = imatrices.rgb_cam[1][0] * reds + imatrices.rgb_cam[1][1] * greens + imatrices.rgb_cam[1][2] * blues; + blueAWBMul = bm = imatrices.rgb_cam[2][0] * reds + imatrices.rgb_cam[2][1] * greens + imatrices.rgb_cam[2][2] * blues; +} //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::transformPosition (int x, int y, int tran, int& ttx, int& tty) { + +ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) +{ + + int x; + int y; + double reds = 0, greens = 0, blues = 0; + int rn = 0; + + if (ri->getSensorType() != ST_BAYER) { + if(ri->getSensorType() == ST_FUJI_XTRANS) { + int d[9][2] = {{0, 0}, { -1, -1}, { -1, 0}, { -1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; + double rloc, gloc, bloc; + int rnbrs, gnbrs, bnbrs; + + for (size_t i = 0; i < red.size(); i++) { + transformPosition (red[i].x, red[i].y, tran, x, y); + rloc = gloc = bloc = rnbrs = gnbrs = bnbrs = 0; + + for (int k = 0; k < 9; k++) { + int xv = x + d[k][0]; + int yv = y + d[k][1]; + + if(xv >= 0 && yv >= 0 && xv < W && yv < H) { + if (ri->ISXTRANSRED(yv, xv)) { //RED + rloc += (rawData[yv][xv]); + rnbrs++; + continue; + } else if (ri->ISXTRANSBLUE(yv, xv)) { //BLUE + bloc += (rawData[yv][xv]); + bnbrs++; + continue; + } else { // GREEN + gloc += (rawData[yv][xv]); + gnbrs++; + continue; + } + } + } + + rloc /= rnbrs; + gloc /= gnbrs; + bloc /= bnbrs; + + if (rloc * initialGain < 64000. && gloc * initialGain < 64000. && bloc * initialGain < 64000.) { + reds += rloc; + greens += gloc; + blues += bloc; + rn++; + } + } + + } else { + int xmin, xmax, ymin, ymax; + int xr, xg, xb, yr, yg, yb; + + for (size_t i = 0; i < red.size(); i++) { + transformPosition (red[i].x, red[i].y, tran, xr, yr); + transformPosition (green[i].x, green[i].y, tran, xg, yg); + transformPosition (blue[i].x, blue[i].y, tran, xb, yb); + + if (initialGain * (rawData[yr][3 * xr] ) > 52500 || + initialGain * (rawData[yg][3 * xg + 1]) > 52500 || + initialGain * (rawData[yb][3 * xb + 2]) > 52500) { + continue; + } + + xmin = min(xr, xg, xb); + xmax = max(xr, xg, xb); + ymin = min(yr, yg, yb); + ymax = max(yr, yg, yb); + + if (xmin >= 0 && ymin >= 0 && xmax < W && ymax < H) { + reds += (rawData[yr][3 * xr] ); + greens += (rawData[yg][3 * xg + 1]); + blues += (rawData[yb][3 * xb + 2]); + rn++; + } + } + } + + } else { + + int d[9][2] = {{0, 0}, { -1, -1}, { -1, 0}, { -1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; + double rloc, gloc, bloc; + int rnbrs, gnbrs, bnbrs; + + for (size_t i = 0; i < red.size(); i++) { + transformPosition (red[i].x, red[i].y, tran, x, y); + rloc = gloc = bloc = rnbrs = gnbrs = bnbrs = 0; + + for (int k = 0; k < 9; k++) { + int xv = x + d[k][0]; + int yv = y + d[k][1]; + int c = FC(yv, xv); + + if(xv >= 0 && yv >= 0 && xv < W && yv < H) { + if (c == 0) { //RED + rloc += (rawData[yv][xv]); + rnbrs++; + continue; + } else if (c == 2) { //BLUE + bloc += (rawData[yv][xv]); + bnbrs++; + continue; + } else { // GREEN + gloc += (rawData[yv][xv]); + gnbrs++; + continue; + } + } + } + + rloc /= rnbrs; + gloc /= gnbrs; + bloc /= bnbrs; + + if (rloc * initialGain < 64000. && gloc * initialGain < 64000. && bloc * initialGain < 64000.) { + reds += rloc; + greens += gloc; + blues += bloc; + rn++; + } + + transformPosition (green[i].x, green[i].y, tran, x, y);//these are redundant now ??? if not, repeat for these blocks same as for red[] + rloc = gloc = bloc = rnbrs = gnbrs = bnbrs = 0; + + for (int k = 0; k < 9; k++) { + int xv = x + d[k][0]; + int yv = y + d[k][1]; + int c = FC(yv, xv); + + if(xv >= 0 && yv >= 0 && xv < W && yv < H) { + if (c == 0) { //RED + rloc += (rawData[yv][xv]); + rnbrs++; + continue; + } else if (c == 2) { //BLUE + bloc += (rawData[yv][xv]); + bnbrs++; + continue; + } else { // GREEN + gloc += (rawData[yv][xv]); + gnbrs++; + continue; + } + } + } + + rloc /= rnbrs; + gloc /= gnbrs; + bloc /= bnbrs; + + if (rloc * initialGain < 64000. && gloc * initialGain < 64000. && bloc * initialGain < 64000.) { + reds += rloc; + greens += gloc; + blues += bloc; + rn++; + } + + transformPosition (blue[i].x, blue[i].y, tran, x, y); + rloc = gloc = bloc = rnbrs = gnbrs = bnbrs = 0; + + for (int k = 0; k < 9; k++) { + int xv = x + d[k][0]; + int yv = y + d[k][1]; + int c = FC(yv, xv); + + if(xv >= 0 && yv >= 0 && xv < W && yv < H) { + if (c == 0) { //RED + rloc += (rawData[yv][xv]); + rnbrs++; + continue; + } else if (c == 2) { //BLUE + bloc += (rawData[yv][xv]); + bnbrs++; + continue; + } else { // GREEN + gloc += (rawData[yv][xv]); + gnbrs++; + continue; + } + } + } + + rloc /= rnbrs; + gloc /= gnbrs; + bloc /= bnbrs; + + if (rloc * initialGain < 64000. && gloc * initialGain < 64000. && bloc * initialGain < 64000.) { + reds += rloc; + greens += gloc; + blues += bloc; + rn++; + } + } + } + + if (2 * rn < red.size()) { + return ColorTemp (equal); + } else { + reds = reds / rn * refwb_red; + greens = greens / rn * refwb_green; + blues = blues / rn * refwb_blue; + + double rm = imatrices.rgb_cam[0][0] * reds + imatrices.rgb_cam[0][1] * greens + imatrices.rgb_cam[0][2] * blues; + double gm = imatrices.rgb_cam[1][0] * reds + imatrices.rgb_cam[1][1] * greens + imatrices.rgb_cam[1][2] * blues; + double bm = imatrices.rgb_cam[2][0] * reds + imatrices.rgb_cam[2][1] * greens + imatrices.rgb_cam[2][2] * blues; + + return ColorTemp (rm, gm, bm, equal); + } +} + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::transformPosition (int x, int y, int tran, int& ttx, int& tty) +{ tran = defTransform (tran); @@ -3563,78 +4130,86 @@ void RawImageSource::transformPosition (int x, int y, int tran, int& ttx, int& t y += border; if (d1x) { - if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { x /= 2; - else + } else { y /= 2; + } } - int w = W, h = H; + int w = W, h = H; + if (fuji) { w = ri->get_FujiWidth() * 2 + 1; - h = (H - ri->get_FujiWidth())*2 + 1; + h = (H - ri->get_FujiWidth()) * 2 + 1; } - int sw = w, sh = h; + + int sw = w, sh = h; + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { sw = h; sh = w; } - + int ppx = x, ppy = y; - if (tran & TR_HFLIP) + + if (tran & TR_HFLIP) { ppx = sw - 1 - x ; - if (tran & TR_VFLIP) + } + + if (tran & TR_VFLIP) { ppy = sh - 1 - y; - + } + int tx = ppx; int ty = ppy; - + if ((tran & TR_ROT) == TR_R180) { tx = w - 1 - ppx; ty = h - 1 - ppy; - } - else if ((tran & TR_ROT) == TR_R90) { + } else if ((tran & TR_ROT) == TR_R90) { tx = ppy; ty = h - 1 - ppx; - } - else if ((tran & TR_ROT) == TR_R270) { + } else if ((tran & TR_ROT) == TR_R270) { tx = w - 1 - ppy; ty = ppx; - } + } if (fuji) { - ttx = (tx+ty) / 2; - tty = (ty-tx) / 2 + ri->get_FujiWidth(); - } - else { + ttx = (tx + ty) / 2; + tty = (ty - tx) / 2 + ri->get_FujiWidth(); + } else { ttx = tx; tty = ty; } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::inverse33 (const double (*rgb_cam)[3], double (*cam_rgb)[3]) { - double nom = (rgb_cam[0][2]*rgb_cam[1][1]*rgb_cam[2][0] - rgb_cam[0][1]*rgb_cam[1][2]*rgb_cam[2][0] - - rgb_cam[0][2]*rgb_cam[1][0]*rgb_cam[2][1] + rgb_cam[0][0]*rgb_cam[1][2]*rgb_cam[2][1] + - rgb_cam[0][1]*rgb_cam[1][0]*rgb_cam[2][2] - rgb_cam[0][0]*rgb_cam[1][1]*rgb_cam[2][2] ); - cam_rgb[0][0] = (rgb_cam[1][2]*rgb_cam[2][1]-rgb_cam[1][1]*rgb_cam[2][2]) / nom; - cam_rgb[0][1] = -(rgb_cam[0][2]*rgb_cam[2][1]-rgb_cam[0][1]*rgb_cam[2][2]) / nom; - cam_rgb[0][2] = (rgb_cam[0][2]*rgb_cam[1][1]-rgb_cam[0][1]*rgb_cam[1][2]) / nom; - cam_rgb[1][0] = -(rgb_cam[1][2]*rgb_cam[2][0]-rgb_cam[1][0]*rgb_cam[2][2]) / nom; - cam_rgb[1][1] = (rgb_cam[0][2]*rgb_cam[2][0]-rgb_cam[0][0]*rgb_cam[2][2]) / nom; - cam_rgb[1][2] = -(rgb_cam[0][2]*rgb_cam[1][0]-rgb_cam[0][0]*rgb_cam[1][2]) / nom; - cam_rgb[2][0] = (rgb_cam[1][1]*rgb_cam[2][0]-rgb_cam[1][0]*rgb_cam[2][1]) / nom; - cam_rgb[2][1] = -(rgb_cam[0][1]*rgb_cam[2][0]-rgb_cam[0][0]*rgb_cam[2][1]) / nom; - cam_rgb[2][2] = (rgb_cam[0][1]*rgb_cam[1][0]-rgb_cam[0][0]*rgb_cam[1][1]) / nom; +void RawImageSource::inverse33 (const double (*rgb_cam)[3], double (*cam_rgb)[3]) +{ + double nom = (rgb_cam[0][2] * rgb_cam[1][1] * rgb_cam[2][0] - rgb_cam[0][1] * rgb_cam[1][2] * rgb_cam[2][0] - + rgb_cam[0][2] * rgb_cam[1][0] * rgb_cam[2][1] + rgb_cam[0][0] * rgb_cam[1][2] * rgb_cam[2][1] + + rgb_cam[0][1] * rgb_cam[1][0] * rgb_cam[2][2] - rgb_cam[0][0] * rgb_cam[1][1] * rgb_cam[2][2] ); + cam_rgb[0][0] = (rgb_cam[1][2] * rgb_cam[2][1] - rgb_cam[1][1] * rgb_cam[2][2]) / nom; + cam_rgb[0][1] = -(rgb_cam[0][2] * rgb_cam[2][1] - rgb_cam[0][1] * rgb_cam[2][2]) / nom; + cam_rgb[0][2] = (rgb_cam[0][2] * rgb_cam[1][1] - rgb_cam[0][1] * rgb_cam[1][2]) / nom; + cam_rgb[1][0] = -(rgb_cam[1][2] * rgb_cam[2][0] - rgb_cam[1][0] * rgb_cam[2][2]) / nom; + cam_rgb[1][1] = (rgb_cam[0][2] * rgb_cam[2][0] - rgb_cam[0][0] * rgb_cam[2][2]) / nom; + cam_rgb[1][2] = -(rgb_cam[0][2] * rgb_cam[1][0] - rgb_cam[0][0] * rgb_cam[1][2]) / nom; + cam_rgb[2][0] = (rgb_cam[1][1] * rgb_cam[2][0] - rgb_cam[1][0] * rgb_cam[2][1]) / nom; + cam_rgb[2][1] = -(rgb_cam[0][1] * rgb_cam[2][0] - rgb_cam[0][0] * rgb_cam[2][1]) / nom; + cam_rgb[2][2] = (rgb_cam[0][1] * rgb_cam[1][0] - rgb_cam[0][0] * rgb_cam[1][1]) / nom; } DiagonalCurve* RawImageSource::phaseOneIccCurve; DiagonalCurve* RawImageSource::phaseOneIccCurveInv; -void RawImageSource::init () { +void RawImageSource::init () +{ - { // Initialize Phase One ICC curves + { + // Initialize Phase One ICC curves /* This curve is derived from TIFFTAG_TRANSFERFUNCTION of a Capture One P25+ image with applied film curve, exported to TIFF with embedded camera ICC. It's assumed to be similar to most standard curves in @@ -3660,35 +4235,38 @@ void RawImageSource::init () { cForwardPoints.push_back(double(DCT_Spline)); // The first value is the curve type std::vector cInversePoints; cInversePoints.push_back(double(DCT_Spline)); // The first value is the curve type - for (int i = 0; i < sizeof(phase_one_forward)/sizeof(phase_one_forward[0]); i += 2) { - cForwardPoints.push_back(phase_one_forward[i+0]); - cForwardPoints.push_back(phase_one_forward[i+1]); - cInversePoints.push_back(phase_one_forward[i+1]); - cInversePoints.push_back(phase_one_forward[i+0]); + + for (int i = 0; i < sizeof(phase_one_forward) / sizeof(phase_one_forward[0]); i += 2) { + cForwardPoints.push_back(phase_one_forward[i + 0]); + cForwardPoints.push_back(phase_one_forward[i + 1]); + cInversePoints.push_back(phase_one_forward[i + 1]); + cInversePoints.push_back(phase_one_forward[i + 0]); } + phaseOneIccCurve = new DiagonalCurve(cForwardPoints, CURVES_MIN_POLY_POINTS); phaseOneIccCurveInv = new DiagonalCurve(cInversePoints, CURVES_MIN_POLY_POINTS); } } -void RawImageSource::cleanup () { +void RawImageSource::cleanup () +{ delete phaseOneIccCurve; delete phaseOneIccCurveInv; } - - + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //#include "demosaic_algos.cc" - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//Emil's code +//Emil's code /* * Now compiled separately * -#include "fast_demo.cc"//fast demosaic -#include "amaze_demosaic_RT.cc"//AMaZE demosaic +#include "fast_demo.cc"//fast demosaic +#include "amaze_demosaic_RT.cc"//AMaZE demosaic #include "CA_correct_RT.cc"//Emil's CA auto correction #include "cfa_linedn_RT.cc"//Emil's line denoise #include "green_equil_RT.cc"//Emil's green channel equilibration diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 108b30614..d4ebf9928 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -28,235 +28,277 @@ #define HR_SCALE 2 -namespace rtengine { +namespace rtengine +{ // these two functions "simulate" and jagged array, but just use two allocs -template T** allocArray (int W, int H, bool initZero=false) { +template T** allocArray (int W, int H, bool initZero = false) +{ T** t = new T*[H]; - t[0] = new T[H*W]; + t[0] = new T[H * W]; - if (initZero) memset(t[0],0,sizeof(T)*W*H); + if (initZero) { + memset(t[0], 0, sizeof(T)*W * H); + } - for (int i=1; i void freeArray (T** a, int H) { +template void freeArray (T** a, int H) +{ delete [] a[0]; delete [] a; } -template void freeArray2 (T** a, int H) { - //for (int i=0; i void freeArray2 (T** a, int H) +{ + //for (int i=0; i rawData; // holds preprocessed pixel values, rowData[i][j] corresponds to the ith row and jth column + array2D rawData; // holds preprocessed pixel values, rowData[i][j] corresponds to the ith row and jth column - // the interpolated green plane: - array2D green; - // the interpolated red plane: - array2D red; - // the interpolated blue plane: - array2D blue; + // the interpolated green plane: + array2D green; + // the interpolated red plane: + array2D red; + // the interpolated blue plane: + array2D blue; - void hphd_vertical (float** hpmap, int col_from, int col_to); - void hphd_horizontal (float** hpmap, int row_from, int row_to); - void hphd_green (float** hpmap); - void processFalseColorCorrectionThread (Imagefloat* im, int row_from, int row_to); - void hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip, const RAWParams &raw, float* hlmax); - int defTransform (int tran); - void rotateLine (float* line, PlanarPtr &channel, int tran, int i, int w, int h); - void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); - void transformPosition (int x, int y, int tran, int& tx, int& ty); + void hphd_vertical (float** hpmap, int col_from, int col_to); + void hphd_horizontal (float** hpmap, int row_from, int row_to); + void hphd_green (float** hpmap); + void processFalseColorCorrectionThread (Imagefloat* im, int row_from, int row_to); + void hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip, const RAWParams &raw, float* hlmax); + int defTransform (int tran); + void rotateLine (float* line, PlanarPtr &channel, int tran, int i, int w, int h); + void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); + void transformPosition (int x, int y, int tran, int& tx, int& ty); - void updateHLRecoveryMap_ColorPropagation (); - void HLRecovery_ColorPropagation (float* red, float* green, float* blue, int i, int sx1, int width, int skip); - unsigned FC(int row, int col){ return ri->FC(row,col); } - inline void getRowStartEnd (int x, int &start, int &end); - static void getProfilePreprocParams(cmsHPROFILE in, float& gammafac, float& lineFac, float& lineSum); + void updateHLRecoveryMap_ColorPropagation (); + void HLRecovery_ColorPropagation (float* red, float* green, float* blue, int i, int sx1, int width, int skip); + unsigned FC(int row, int col) + { + return ri->FC(row, col); + } + inline void getRowStartEnd (int x, int &start, int &end); + static void getProfilePreprocParams(cmsHPROFILE in, float& gammafac, float& lineFac, float& lineSum); - public: - RawImageSource (); - ~RawImageSource (); +public: + RawImageSource (); + ~RawImageSource (); - int load (Glib::ustring fname, bool batch = false); - void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse); - void demosaic (const RAWParams &raw); - void flushRawData (); - void flushRGB (); - void HLRecovery_Global (ToneCurveParams hrp); - void refinement_lassus (int PassCount); - void refinement(int PassCount); + int load (Glib::ustring fname, bool batch = false); + void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse); + void demosaic (const RAWParams &raw); + void flushRawData (); + void flushRGB (); + void HLRecovery_Global (ToneCurveParams hrp); + void refinement_lassus (int PassCount); + void refinement(int PassCount); - bool IsrgbSourceModified() {return rgbSourceModified;} // tracks whether cached rgb output of demosaic has been modified + bool IsrgbSourceModified() + { + return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified + } - void processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]); - void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile ); - void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW ); - void scaleColors (int winx,int winy,int winw,int winh, const RAWParams &raw);// raw for cblack + void processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]); + void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile ); + void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW ); + void scaleColors (int winx, int winy, int winw, int winh, const RAWParams &raw); // raw for cblack - void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw); - eSensorType getSensorType () { return ri!=NULL ? ri->getSensorType() : ST_NONE; } - ColorTemp getWB () { return camera_wb; } - void getAutoWBMultipliers (double &rm, double &gm, double &bm); - ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal); - bool isWBProviderReady () { return rawData; } + void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw); + eSensorType getSensorType () + { + return ri != NULL ? ri->getSensorType() : ST_NONE; + } + ColorTemp getWB () + { + return camera_wb; + } + void getAutoWBMultipliers (double &rm, double &gm, double &bm); + ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal); + bool isWBProviderReady () + { + return rawData; + } - double getDefGain () { return defGain; } + double getDefGain () + { + return defGain; + } - void getFullSize (int& w, int& h, int tr = TR_NONE); - void getSize (int tran, PreviewProps pp, int& w, int& h); - int getRotateDegree() const { return ri->get_rotateDegree(); } + void getFullSize (int& w, int& h, int tr = TR_NONE); + void getSize (int tran, PreviewProps pp, int& w, int& h); + int getRotateDegree() const + { + return ri->get_rotateDegree(); + } - ImageData* getImageData () { return idata; } - ImageMatrices* getImageMatrices () { return &imatrices; } - bool isRAW() const { return true; } + ImageData* getImageData () + { + return idata; + } + ImageMatrices* getImageMatrices () + { + return &imatrices; + } + bool isRAW() const + { + return true; + } - void setProgressListener (ProgressListener* pl) { plistener = pl; } - void getAutoExpHistogram (LUTu & histogram, int& histcompr); - void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw); - DCPProfile *getDCP(ColorManagementParams cmp, ColorTemp &wb); - - void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb); - static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName) { - colorSpaceConversion_ (im, cmp, wb, pre_mul, embedded, camprofile, cam, camName); - } - static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]); + void setProgressListener (ProgressListener* pl) + { + plistener = pl; + } + void getAutoExpHistogram (LUTu & histogram, int& histcompr); + void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw); + DCPProfile *getDCP(ColorManagementParams cmp, ColorTemp &wb); - void boxblur2(float** src, float** dst, int H, int W, int box ); - void boxblur_resamp(float **src, float **dst, int H, int W, int box, int samp ); + void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb); + static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); + static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName) + { + colorSpaceConversion_ (im, cmp, wb, pre_mul, embedded, camprofile, cam, camName); + } + static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]); - //void boxblur_resamp(float **red, float **green, float **blue, int H, int W, float thresh[3], float max[3], - // multi_array2D & hfsize, multi_array2D & hilite, int box ); - void HLRecovery_inpaint (float** red, float** green, float** blue); - //void HLRecovery_inpaint (); + void boxblur2(float** src, float** dst, int H, int W, int box ); + void boxblur_resamp(float **src, float **dst, int H, int W, int box, int samp ); - static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); - static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); - static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax); - static void init (); - static void cleanup (); + //void boxblur_resamp(float **red, float **green, float **blue, int H, int W, float thresh[3], float max[3], + // multi_array2D & hfsize, multi_array2D & hilite, int box ); + void HLRecovery_inpaint (float** red, float** green, float** blue); + //void HLRecovery_inpaint (); - protected: - typedef unsigned short ushort; - void processFalseColorCorrection (Imagefloat* i, int steps); - inline void convert_row_to_YIQ (float* r, float* g, float* b, float* Y, float* I, float* Q, int W); - inline void convert_row_to_RGB (float* r, float* g, float* b, float* Y, float* I, float* Q, int W); + static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); + static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); + static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax); + static void init (); + static void cleanup (); - inline void convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob); - inline void interpolate_row_g (float* agh, float* agv, int i); - 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); +protected: + typedef unsigned short ushort; + void processFalseColorCorrection (Imagefloat* i, int steps); + inline void convert_row_to_YIQ (float* r, float* g, float* b, float* Y, float* I, float* Q, int W); + inline void convert_row_to_RGB (float* r, float* g, float* b, float* Y, float* I, float* Q, int W); - int LinEqSolve( int nDim, double* pfMatr, double* pfVect, double* pfSolution);//Emil's CA auto correction - void CA_correct_RT (double cared, double cablue); - void ddct8x8s(int isgn, float a[8][8]); - void processRawWhitepoint (float expos, float preser); // exposure before interpolation + inline void convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob); + inline void interpolate_row_g (float* agh, float* agv, int i); + 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 interpolateBadPixelsBayer( PixelsMap &bitmapBads ); - int interpolateBadPixelsNColours( PixelsMap &bitmapBads, const int colours ); - int interpolateBadPixelsXtrans( PixelsMap &bitmapBads ); - int findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels ); + int LinEqSolve( int nDim, double* pfMatr, double* pfVect, double* pfSolution);//Emil's CA auto correction + void CA_correct_RT (double cared, double cablue); + void ddct8x8s(int isgn, float a[8][8]); + void processRawWhitepoint (float expos, float preser); // exposure before interpolation - void cfa_linedn (float linenoiselevel);//Emil's line denoise + int interpolateBadPixelsBayer( PixelsMap &bitmapBads ); + int interpolateBadPixelsNColours( PixelsMap &bitmapBads, const int colours ); + int interpolateBadPixelsXtrans( PixelsMap &bitmapBads ); + int findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels ); - void green_equilibrate (float greenthresh);//Emil's green equilibration + void cfa_linedn (float linenoiselevel);//Emil's line denoise - void nodemosaic(bool bw); - void eahd_demosaic(); - void hphd_demosaic(); - void vng4_demosaic(); - void ppg_demosaic(); - void jdl_interpolate_omp(); - void igv_interpolate(int winw, int winh); - void lmmse_interpolate_omp(int winw, int winh, int iterations); + void green_equilibrate (float greenthresh);//Emil's green equilibration - void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE - void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing - void dcb_demosaic(int iterations, bool dcb_enhance); - void ahd_demosaic(int winx, int winy, int winw, int winh); - void border_interpolate(unsigned int border, float (*image)[4], unsigned int start = 0, unsigned int end = 0); - void border_interpolate2(int winw, int winh, int lborders); - void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); - void fill_raw( float (*cache )[4], int x0, int y0, float** rawData); - void fill_border( float (*cache )[4], int border, int x0, int y0); - void copy_to_buffer(float (*image2)[3], float (*image)[4]); - void dcb_hid(float (*image)[4], float (*bufferH)[3], float (*bufferV)[3], int x0, int y0); - void dcb_color(float (*image)[4], int x0, int y0); - void dcb_hid2(float (*image)[4], int x0, int y0); - void dcb_map(float (*image)[4], int x0, int y0); - void dcb_correction(float (*image)[4], int x0, int y0); - void dcb_pp(float (*image)[4], int x0, int y0); - void dcb_correction2(float (*image)[4], int x0, int y0); - void restore_from_buffer(float (*image)[4], float (*image2)[3]); - void dcb_refinement(float (*image)[4], int x0, int y0); - void dcb_color_full(float (*image)[4], int x0, int y0, float (*chroma)[2]); - void cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]); - void xtransborder_interpolate (int border); - void xtrans_interpolate (int passes, bool useCieLab); - void fast_xtrans_interpolate (); - void transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imw, int imh, int fw); - void hflip (Imagefloat* im); - void vflip (Imagefloat* im); + void nodemosaic(bool bw); + void eahd_demosaic(); + void hphd_demosaic(); + void vng4_demosaic(); + void ppg_demosaic(); + void jdl_interpolate_omp(); + void igv_interpolate(int winw, int winh); + void lmmse_interpolate_omp(int winw, int winh, int iterations); + + void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE + void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing + void dcb_demosaic(int iterations, bool dcb_enhance); + void ahd_demosaic(int winx, int winy, int winw, int winh); + void border_interpolate(unsigned int border, float (*image)[4], unsigned int start = 0, unsigned int end = 0); + void border_interpolate2(int winw, int winh, int lborders); + void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border); + void fill_raw( float (*cache )[4], int x0, int y0, float** rawData); + void fill_border( float (*cache )[4], int border, int x0, int y0); + void copy_to_buffer(float (*image2)[3], float (*image)[4]); + void dcb_hid(float (*image)[4], float (*bufferH)[3], float (*bufferV)[3], int x0, int y0); + void dcb_color(float (*image)[4], int x0, int y0); + void dcb_hid2(float (*image)[4], int x0, int y0); + void dcb_map(float (*image)[4], int x0, int y0); + void dcb_correction(float (*image)[4], int x0, int y0); + void dcb_pp(float (*image)[4], int x0, int y0); + void dcb_correction2(float (*image)[4], int x0, int y0); + void restore_from_buffer(float (*image)[4], float (*image2)[3]); + void dcb_refinement(float (*image)[4], int x0, int y0); + void dcb_color_full(float (*image)[4], int x0, int y0, float (*chroma)[2]); + void cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]); + void xtransborder_interpolate (int border); + void xtrans_interpolate (int passes, bool useCieLab); + void fast_xtrans_interpolate (); + void transLine (float* red, float* green, float* blue, int i, Imagefloat* image, int tran, int imw, int imh, int fw); + void hflip (Imagefloat* im); + void vflip (Imagefloat* im); }; } diff --git a/rtengine/rawimagesource_i.h b/rtengine/rawimagesource_i.h index 5115a9ec1..a3cd28253 100644 --- a/rtengine/rawimagesource_i.h +++ b/rtengine/rawimagesource_i.h @@ -7,7 +7,7 @@ * 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 @@ -24,304 +24,354 @@ #include "curves.h" -namespace rtengine { +namespace rtengine +{ -inline void RawImageSource::convert_row_to_YIQ (float* r, float* g, float* b, float* Y, float* I, float* Q, int W) { - for (int j=0; jthreshold) - oL[j] = cache[(int)y]; - else - oL[j] = float(903.3 * y / MAXVALD); + double x = lc00 * r + lc01 * g + lc02 * b; + double y = lc10 * r + lc11 * g + lc12 * b; + double z = lc20 * r + lc21 * g + lc22 * b; - oa[j] = float(500.0 * ((x>threshold ? cache[(int)x] : 7.787*x/MAXVALD+16.0/116.0) - (y>threshold ? cache[(int)y] : 7.787*y/MAXVALD+16.0/116.0))); - ob[j] = float(200.0 * ((y>threshold ? cache[(int)y] : 7.787*y/MAXVALD+16.0/116.0) - (z>threshold ? cache[(int)z] : 7.787*z/MAXVALD+16.0/116.0))); - } + if (y > threshold) { + oL[j] = cache[(int)y]; + } else { + oL[j] = float(903.3 * y / MAXVALD); + } + + oa[j] = float(500.0 * ((x > threshold ? cache[(int)x] : 7.787 * x / MAXVALD + 16.0 / 116.0) - (y > threshold ? cache[(int)y] : 7.787 * y / MAXVALD + 16.0 / 116.0))); + ob[j] = float(200.0 * ((y > threshold ? cache[(int)y] : 7.787 * y / MAXVALD + 16.0 / 116.0) - (z > threshold ? cache[(int)z] : 7.787 * z / MAXVALD + 16.0 / 116.0))); + } } -inline void RawImageSource::interpolate_row_g (float* agh, float* agv, int i) { +inline void RawImageSource::interpolate_row_g (float* agh, float* agv, int i) +{ - for (int j=0; jISGREEN(i,j)) { - agh[j] = rawData[i][j]; - agv[j] = rawData[i][j]; - } - else { - int gh=0; - int gv=0; - if (j>1 && jmaxgh) - gh = maxgh; - else if (gh1 && imaxgv) - gv = maxgv; - else if (gvISGREEN(i, j)) { + agh[j] = rawData[i][j]; + agv[j] = rawData[i][j]; + } else { + int gh = 0; + int gv = 0; - agh[j] = gh; - agv[j] = gv; + if (j > 1 && j < W - 2) { + gh = (-rawData[i][j - 2] + 2 * rawData[i][j - 1] + 2 * rawData[i][j] + 2 * rawData[i][j + 1] - rawData[i][j + 2]) / 4; + int maxgh = max(rawData[i][j - 1], rawData[i][j + 1]); + int mingh = min(rawData[i][j - 1], rawData[i][j + 1]); + + if (gh > maxgh) { + gh = maxgh; + } else if (gh < mingh) { + gh = mingh; + } + } else if (j == 0) { + gh = rawData[i][1]; + } else if (j == 1) { + gh = (rawData[i][0] + rawData[i][2]) / 2; + } else if (j == W - 1) { + gh = rawData[i][W - 2]; + } else if (j == W - 2) { + gh = (rawData[i][W - 1] + rawData[i][W - 3]) / 2; + } + + if (i > 1 && i < H - 2) { + gv = (-rawData[i - 2][j] + 2 * rawData[i - 1][j] + 2 * rawData[i][j] + 2 * rawData[i + 1][j] - rawData[i + 2][j]) / 4; + int maxgv = max(rawData[i - 1][j], rawData[i + 1][j]); + int mingv = min(rawData[i - 1][j], rawData[i + 1][j]); + + if (gv > maxgv) { + gv = maxgv; + } else if (gv < mingv) { + gv = mingv; + } + } else if (i == 0) { + gv = rawData[1][j]; + } else if (i == 1) { + gv = (rawData[0][j] + rawData[2][j]) / 2; + } else if (i == H - 1) { + gv = rawData[H - 2][j]; + } else if (i == H - 2) { + gv = (rawData[H - 1][j] + rawData[H - 3][j]) / 2; + } + + agh[j] = gh; + agv[j] = gv; + } } - } } -inline void RawImageSource::interpolate_row_rb (float* ar, float* ab, float* pg, float* cg, float* ng, int i) { - if (ri->ISRED(i,0) || ri->ISRED(i,1)) { - // RGRGR or GRGRGR line - for (int j=0; jISRED(i,j)) { - // red is simple - ar[j] = rawData[i][j]; - // blue: cross interpolation - int b = 0; - int n = 0; - if (i>0 && j>0) { - b += rawData[i-1][j-1] - pg[j-1]; - n++; - } - if (i>0 && j0) { - b += rawData[i+1][j-1] - ng[j-1]; - n++; - } - if (iISBLUE(i,j)) { - // red is simple - ab[j] = rawData[i][j]; - // blue: cross interpolation - int r = 0; - int n = 0; - if (i>0 && j>0) { - r += rawData[i-1][j-1] - pg[j-1]; - n++; - } - if (i>0 && j0) { - r += rawData[i+1][j-1] - ng[j-1]; - n++; - } - if (iISRED(i, 0) || ri->ISRED(i, 1)) { + // RGRGR or GRGRGR line + for (int j = 0; j < W; j++) { + if (ri->ISRED(i, j)) { + // red is simple + ar[j] = rawData[i][j]; + // blue: cross interpolation + int b = 0; + int n = 0; - ar[j] = r; - } - else { - // linear B-G interp. horizontally - int b; - if (j==0) - b = cg[0] + rawData[i][1] - cg[1]; - else if (j==W-1) - b = cg[W-1] + rawData[i][W-2] - cg[W-2]; - else - b = cg[j] + (rawData[i][j-1] - cg[j-1] + rawData[i][j+1] - cg[j+1]) / 2; - ab[j] = CLIP(b); - // linear R-G interp. vertically - int r; - if (i==0) - r = ng[j] + rawData[1][j] - cg[j]; - else if (i==H-1) - r = pg[j] + rawData[H-2][j] - cg[j]; - else - r = cg[j] + (rawData[i-1][j] - pg[j] + rawData[i+1][j] - ng[j]) / 2; - ar[j] = r; - } + if (i > 0 && j > 0) { + b += rawData[i - 1][j - 1] - pg[j - 1]; + n++; + } + + if (i > 0 && j < W - 1) { + b += rawData[i - 1][j + 1] - pg[j + 1]; + n++; + } + + if (i < H - 1 && j > 0) { + b += rawData[i + 1][j - 1] - ng[j - 1]; + n++; + } + + if (i < H - 1 && j < W - 1) { + b += rawData[i + 1][j + 1] - ng[j + 1]; + n++; + } + + b = cg[j] + b / n; + ab[j] = b; + } else { + // linear R-G interp. horizontally + int r; + + if (j == 0) { + r = cg[0] + rawData[i][1] - cg[1]; + } else if (j == W - 1) { + r = cg[W - 1] + rawData[i][W - 2] - cg[W - 2]; + } else { + r = cg[j] + (rawData[i][j - 1] - cg[j - 1] + rawData[i][j + 1] - cg[j + 1]) / 2; + } + + ar[j] = CLIP(r); + // linear B-G interp. vertically + int b; + + if (i == 0) { + b = ng[j] + rawData[1][j] - cg[j]; + } else if (i == H - 1) { + b = pg[j] + rawData[H - 2][j] - cg[j]; + } else { + b = cg[j] + (rawData[i - 1][j] - pg[j] + rawData[i + 1][j] - ng[j]) / 2; + } + + ab[j] = b; + } + } + } else { + // BGBGB or GBGBGB line + for (int j = 0; j < W; j++) { + if (ri->ISBLUE(i, j)) { + // red is simple + ab[j] = rawData[i][j]; + // blue: cross interpolation + int r = 0; + int n = 0; + + if (i > 0 && j > 0) { + r += rawData[i - 1][j - 1] - pg[j - 1]; + n++; + } + + if (i > 0 && j < W - 1) { + r += rawData[i - 1][j + 1] - pg[j + 1]; + n++; + } + + if (i < H - 1 && j > 0) { + r += rawData[i + 1][j - 1] - ng[j - 1]; + n++; + } + + if (i < H - 1 && j < W - 1) { + r += rawData[i + 1][j + 1] - ng[j + 1]; + n++; + } + + r = cg[j] + r / n; + + ar[j] = r; + } else { + // linear B-G interp. horizontally + int b; + + if (j == 0) { + b = cg[0] + rawData[i][1] - cg[1]; + } else if (j == W - 1) { + b = cg[W - 1] + rawData[i][W - 2] - cg[W - 2]; + } else { + b = cg[j] + (rawData[i][j - 1] - cg[j - 1] + rawData[i][j + 1] - cg[j + 1]) / 2; + } + + ab[j] = CLIP(b); + // linear R-G interp. vertically + int r; + + if (i == 0) { + r = ng[j] + rawData[1][j] - cg[j]; + } else if (i == H - 1) { + r = pg[j] + rawData[H - 2][j] - cg[j]; + } else { + r = cg[j] + (rawData[i - 1][j] - pg[j] + rawData[i + 1][j] - ng[j]) / 2; + } + + ar[j] = r; + } + } } - } } -inline void RawImageSource::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) { +inline void RawImageSource::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) +{ - if (ri->ISRED(i,0) || ri->ISRED(i,1)) { - // RGRGR or GRGRGR line - for (int j=x1, jx=0; jxISRED(i,j)) { - // red is simple - ar[jx] = r_mul * rawData[i][j]; - // blue: cross interpolation - float b = 0; - int n = 0; - if (i>0 && j>0) { - b += b_mul*rawData[i-1][j-1] - g_mul*pg[j-1]; - n++; - } - if (i>0 && j0) { - b += b_mul*rawData[i+1][j-1] - g_mul*ng[j-1]; - n++; - } - if (iISBLUE(i,j)) { - // red is simple - ab[jx] = b_mul*rawData[i][j]; - // blue: cross interpolation - float r = 0; - int n = 0; - if (i>0 && j>0) { - r += r_mul*rawData[i-1][j-1] - g_mul*pg[j-1]; - n++; - } - if (i>0 && j0) { - r += r_mul*rawData[i+1][j-1] - g_mul*ng[j-1]; - n++; - } - if (iISRED(i, 0) || ri->ISRED(i, 1)) { + // RGRGR or GRGRGR line + for (int j = x1, jx = 0; jx < width; j += skip, jx++) { + if (ri->ISRED(i, j)) { + // red is simple + ar[jx] = r_mul * rawData[i][j]; + // blue: cross interpolation + float b = 0; + int n = 0; - ar[jx] = r; - } - else { - // linear B-G interp. horizontally - float b; - if (j==0) - b = g_mul*cg[0] + b_mul*rawData[i][1] - g_mul*cg[1]; - else if (j==W-1) - b = g_mul*cg[W-1] + b_mul*rawData[i][W-2] - g_mul*cg[W-2]; - else - b = g_mul*cg[j] + (b_mul*rawData[i][j-1] - g_mul*cg[j-1] + b_mul*rawData[i][j+1] - g_mul*cg[j+1]) / 2; - ab[jx] = b; - // linear R-G interp. vertically - float r; - if (i==0) - r = g_mul*ng[j] + r_mul*rawData[1][j] - g_mul*cg[j]; - else if (i==H-1) - r = g_mul*pg[j] + r_mul*rawData[H-2][j] - g_mul*cg[j]; - else - r = g_mul*cg[j] + (r_mul*rawData[i-1][j] - g_mul*pg[j] + r_mul*rawData[i+1][j] - g_mul*ng[j]) / 2; - ar[jx] = r; - } + if (i > 0 && j > 0) { + b += b_mul * rawData[i - 1][j - 1] - g_mul * pg[j - 1]; + n++; + } + + if (i > 0 && j < W - 1) { + b += b_mul * rawData[i - 1][j + 1] - g_mul * pg[j + 1]; + n++; + } + + if (i < H - 1 && j > 0) { + b += b_mul * rawData[i + 1][j - 1] - g_mul * ng[j - 1]; + n++; + } + + if (i < H - 1 && j < W - 1) { + b += b_mul * rawData[i + 1][j + 1] - g_mul * ng[j + 1]; + n++; + } + + b = g_mul * cg[j] + b / n; + ab[jx] = b; + } else { + // linear R-G interp. horizontally + float r; + + if (j == 0) { + r = g_mul * cg[0] + r_mul * rawData[i][1] - g_mul * cg[1]; + } else if (j == W - 1) { + r = g_mul * cg[W - 1] + r_mul * rawData[i][W - 2] - g_mul * cg[W - 2]; + } else { + r = g_mul * cg[j] + (r_mul * rawData[i][j - 1] - g_mul * cg[j - 1] + r_mul * rawData[i][j + 1] - g_mul * cg[j + 1]) / 2; + } + + ar[jx] = r; + // linear B-G interp. vertically + float b; + + if (i == 0) { + b = g_mul * ng[j] + b_mul * rawData[1][j] - g_mul * cg[j]; + } else if (i == H - 1) { + b = g_mul * pg[j] + b_mul * rawData[H - 2][j] - g_mul * cg[j]; + } else { + b = g_mul * cg[j] + (b_mul * rawData[i - 1][j] - g_mul * pg[j] + b_mul * rawData[i + 1][j] - g_mul * ng[j]) / 2; + } + + ab[jx] = b; + } + } + } else { + // BGBGB or GBGBGB line + for (int j = x1, jx = 0; jx < width; j += skip, jx++) { + if (ri->ISBLUE(i, j)) { + // red is simple + ab[jx] = b_mul * rawData[i][j]; + // blue: cross interpolation + float r = 0; + int n = 0; + + if (i > 0 && j > 0) { + r += r_mul * rawData[i - 1][j - 1] - g_mul * pg[j - 1]; + n++; + } + + if (i > 0 && j < W - 1) { + r += r_mul * rawData[i - 1][j + 1] - g_mul * pg[j + 1]; + n++; + } + + if (i < H - 1 && j > 0) { + r += r_mul * rawData[i + 1][j - 1] - g_mul * ng[j - 1]; + n++; + } + + if (i < H - 1 && j < W - 1) { + r += r_mul * rawData[i + 1][j + 1] - g_mul * ng[j + 1]; + n++; + } + + r = g_mul * cg[j] + r / n; + + ar[jx] = r; + } else { + // linear B-G interp. horizontally + float b; + + if (j == 0) { + b = g_mul * cg[0] + b_mul * rawData[i][1] - g_mul * cg[1]; + } else if (j == W - 1) { + b = g_mul * cg[W - 1] + b_mul * rawData[i][W - 2] - g_mul * cg[W - 2]; + } else { + b = g_mul * cg[j] + (b_mul * rawData[i][j - 1] - g_mul * cg[j - 1] + b_mul * rawData[i][j + 1] - g_mul * cg[j + 1]) / 2; + } + + ab[jx] = b; + // linear R-G interp. vertically + float r; + + if (i == 0) { + r = g_mul * ng[j] + r_mul * rawData[1][j] - g_mul * cg[j]; + } else if (i == H - 1) { + r = g_mul * pg[j] + r_mul * rawData[H - 2][j] - g_mul * cg[j]; + } else { + r = g_mul * cg[j] + (r_mul * rawData[i - 1][j] - g_mul * pg[j] + r_mul * rawData[i + 1][j] - g_mul * ng[j]) / 2; + } + + ar[jx] = r; + } + } } - } } } diff --git a/rtengine/rawmetadatalocation.h b/rtengine/rawmetadatalocation.h index 646384d63..d029d2a13 100644 --- a/rtengine/rawmetadatalocation.h +++ b/rtengine/rawmetadatalocation.h @@ -7,7 +7,7 @@ * 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 @@ -19,13 +19,14 @@ #ifndef _RAWMETADATALOCATION_ #define _RAWMETADATALOCATION_ -namespace rtengine { +namespace rtengine +{ - struct RawMetaDataLocation { - int exifBase; - int ciffBase; - int ciffLength; - }; +struct RawMetaDataLocation { + int exifBase; + int ciffBase; + int ciffLength; +}; } #endif diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 1a8952f28..c22cf25fa 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -7,7 +7,7 @@ * 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 @@ -20,414 +20,414 @@ #include "procevents.h" int refreshmap[rtengine::NUMOFEVENTS] = { -ALL, // EvPhotoLoaded, -ALL, // EvProfileLoaded, -ALL, // EvProfileChanged, -ALL, // EvHistoryBrowsed, -RGBCURVE, // EvBrightness, -RGBCURVE, // EvContrast, -RGBCURVE, // EvBlack, -RGBCURVE, // EvExpComp, -RGBCURVE, // EvHLCompr, -RGBCURVE, // EvSHCompr, -RGBCURVE, // EvToneCurve1, -AUTOEXP, // EvAutoExp, -AUTOEXP, // EvClip, -LUMINANCECURVE, // EvLBrightness, -LUMINANCECURVE, // EvLContrast, -LUMINANCECURVE, // EvLBlack, -LUMINANCECURVE, // EvLHLCompr, -LUMINANCECURVE, // EvLSHCompr, -LUMINANCECURVE, // EvLLCurve, -SHARPENING, // EvShrEnabled, -SHARPENING, // EvShrRadius, -SHARPENING, // EvShrAmount, -SHARPENING, // EvShrThresh, -SHARPENING, // EvShrEdgeOnly, -SHARPENING, // EvShrEdgeRadius, -SHARPENING, // EvShrEdgeTolerance, -SHARPENING, // EvShrHaloControl, -SHARPENING, // EvShrHaloAmount, -SHARPENING, // EvShrMethod, -SHARPENING, // EvShrDRadius, -SHARPENING, // EvShrDAmount, -SHARPENING, // EvShrDDamping, -SHARPENING, // EvShrDIterations, -TRANSFORM, // EvLCPUseDist, -DARKFRAME, // EvLCPUseVign, -TRANSFORM, // EvLCPUseCA, -M_VOID, // EvFixedExp -WHITEBALANCE, // EvWBMethod, -WHITEBALANCE, // EvWBTemp, -WHITEBALANCE, // EvWBGreen, -RGBCURVE, // EvToneCurveMode1, -RGBCURVE, // EvToneCurve2, -RGBCURVE, // EvToneCurveMode2, -0, // EvLDNRadius: obsolete, -0, // EvLDNEdgeTolerance: obsolete, -0, // EvCDNEnabled:obsolete, -ALL, // EvBlendCMSMatrix, -RGBCURVE, // EvDCPToneCurve, -INPUTPROFILE, // EvDCPIlluminant, -RETINEX, // EvSHEnabled, -RGBCURVE, // EvSHHighlights, -RGBCURVE, // EvSHShadows, -RGBCURVE, // EvSHHLTonalW, -RGBCURVE, // EvSHSHTonalW, -RGBCURVE, // EvSHLContrast, -RETINEX, // EvSHRadius, -ALL, // EvCTRotate, -ALL, // EvCTHFlip, -ALL, // EvCTVFlip, -TRANSFORM, // EvROTDegree, -TRANSFORM, // EvTransAutoFill, -TRANSFORM, // EvDISTAmount, -ALL, // EvBookmarkSelected, -CROP, // EvCrop, -TRANSFORM, // EvCACorr, -ALLNORAW, // EvHREnabled, -ALLNORAW, // EvHRAmount, -ALLNORAW, // EvHRMethod, -ALLNORAW, // EvWProfile, -OUTPUTPROFILE, // EvOProfile, -INPUTPROFILE, // EvIProfile, -TRANSFORM, // EvVignettingAmount, -RGBCURVE, // EvChMixer, -RESIZE, // EvResizeScale, -RESIZE, // EvResizeMethod, -EXIF, // EvExif, -IPTC, // EvIPTC -RESIZE, // EvResizeSpec, -RESIZE, // EvResizeWidth -RESIZE, // EvResizeHeight -RESIZE, // EvResizeEnabled -ALL, // EvProfileChangeNotification -RETINEX, // EvShrHighQuality -TRANSFORM, // EvPerspCorr -DARKFRAME, // EvLCPFile -RGBCURVE, // EvRGBrCurveLumamode -IMPULSEDENOISE, // EvIDNEnabled, -IMPULSEDENOISE, // EvIDNThresh, -ALLNORAW, // EvDPDNEnabled, -ALLNORAW, // EvDPDNLuma, -ALLNORAW, // EvDPDNChroma, -ALLNORAW, // EvDPDNGamma, -DIRPYREQUALIZER, // EvDirPyrEqualizer, -DIRPYREQUALIZER, // EvDirPyrEqlEnabled, -LUMINANCECURVE, // EvLSaturation, -LUMINANCECURVE, // EvLaCurve, -LUMINANCECURVE, // EvLbCurve, -DEMOSAIC, // EvDemosaicMethod -DARKFRAME, // EvPreProcessHotPixel -RGBCURVE, // EvSaturation, -RGBCURVE, // EvHSVEqualizerH, -RGBCURVE, // EvHSVEqualizerS, -RGBCURVE, // EvHSVEqualizerV, -RGBCURVE, // EvHSVEqEnabled, -DEFRINGE, // EvDefringeEnabled, -DEFRINGE, // EvDefringeRadius, -DEFRINGE, // EvDefringeThreshold, -RGBCURVE, // EvHLComprThreshold, -RESIZE, // EvResizeBoundingBox -RESIZE, // EvResizeAppliesTo -LUMINANCECURVE, // EvCBAvoidClip, -LUMINANCECURVE, // EvCBSatLimiter, -LUMINANCECURVE, // EvCBSatLimit, -DEMOSAIC, // EvDemosaicDCBIter -DEMOSAIC, // EvDemosaicFalseColorIter -DEMOSAIC, // EvDemosaicDCBEnhanced -DARKFRAME, // EvPreProcessCARed -DARKFRAME, // EvPreProcessCABlue -DARKFRAME, // EvPreProcessLineDenoise -DARKFRAME, // EvPreProcessGEquilThresh -DARKFRAME, // EvPreProcessAutoCA -DARKFRAME, // EvPreProcessAutoDF -DARKFRAME, // EvPreProcessDFFile -DARKFRAME, // EvPreProcessExpCorrLinear -DARKFRAME, // EvPreProcessExpCorrPH -FLATFIELD, // EvFlatFieldFile, -FLATFIELD, // EvFlatFieldAutoSelect, -FLATFIELD, // EvFlatFieldBlurRadius, -FLATFIELD, // EvFlatFieldBlurType, -TRANSFORM, // EvAutoDIST, -ALLNORAW, // EvDPDNLumCurve, -ALLNORAW, // EvDPDNChromCurve, -GAMMA, // EvGAMMA -GAMMA, // EvGAMPOS -GAMMA, // EvGAMFREE -GAMMA, // EvSLPOS -DARKFRAME, // EvPreProcessExpBlackzero -DARKFRAME, // EvPreProcessExpBlackone -DARKFRAME, // EvPreProcessExpBlacktwo -DARKFRAME, // EvPreProcessExpBlackthree -DARKFRAME, // EvPreProcessExptwoGreen -SHARPENING, // EvSharpenEdgePasses -SHARPENING, // EvSharpenEdgeStrength -SHARPENING, // EvSharpenMicroStrength -SHARPENING, // EvSharpenMicroUniformity -SHARPENING, // EvSharpenEdgeEnabled -SHARPENING, // EvSharpenEdgeThreechannels -SHARPENING, // EvSharpenMicroEnabled -SHARPENING, // EvSharpenMicroMatrix -DEMOSAIC, // EvDemosaicALLEnhanced // Disabled but not removed for now, may be reintroduced some day -RGBCURVE, // EvVibranceEnabled -RGBCURVE, // EvVibrancePastels -RGBCURVE, // EvVibranceSaturated -RGBCURVE, // EvVibranceProtectSkins -RGBCURVE, // EvVibranceAvoidColorShift -RGBCURVE, // EvVibrancePastSatTog -RGBCURVE, // EvVibrancePastSatThreshold -SHARPENING, // EvEPDStrength -SHARPENING, // EvEPDEdgeStopping -SHARPENING, // EvEPDScale -SHARPENING, // EvEPDReweightingIterates -SHARPENING, // EvEPDEnabled -RGBCURVE, // EvRGBrCurve -RGBCURVE, // EvRGBgCurve -RGBCURVE, // EvRGBbCurve -RGBCURVE, // EvNeutralExp -DEMOSAIC|M_PREPROC, // EvDemosaicMethodPreProc -LUMINANCECURVE, // EvLCCurve -LUMINANCECURVE, // EvLCHCurve -RGBCURVE, // EvVibranceSkinTonesCurve -LUMINANCECURVE, // EvLLCCurve -LUMINANCECURVE, // EvLLCredsk -ALLNORAW, // EvDPDNLdetail -LUMINANCECURVE, // EvCATEnabled -LUMINANCECURVE, // EvCATDegree -LUMINANCECURVE, // EvCATMethodsur -LUMINANCECURVE, // EvCATAdapscen -LUMINANCECURVE, // EvCATAdapLum -LUMINANCECURVE, // EvCATMethodWB -LUMINANCECURVE, // EvCATJLight -LUMINANCECURVE, // EvCATChroma -LUMINANCECURVE, // EvCATAutoDegree -LUMINANCECURVE, // EvCATContrast -LUMINANCECURVE, // EvCATSurr -LUMINANCECURVE, // EvCATgamut -LUMINANCECURVE, // EvCATmethodalg -LUMINANCECURVE, // EvCATRstpro -LUMINANCECURVE, // EvCATQbright -LUMINANCECURVE, // EvCATQContrast -LUMINANCECURVE, // EvCATSChroma -LUMINANCECURVE, // EvCATMchroma -LUMINANCECURVE, // EvCAThue -LUMINANCECURVE, // EvCATcurve1 -LUMINANCECURVE, // EvCATcurve2 -LUMINANCECURVE, // EvCATcurvemode1 -LUMINANCECURVE, // EvCATcurvemode2 -LUMINANCECURVE, // EvCATcurve3 -LUMINANCECURVE, // EvCATcurvemode3 -LUMINANCECURVE, // EvCATdatacie -LUMINANCECURVE, // EvCATtonecie -ALLNORAW, // EvDPDNbluechro -ALLNORAW, // EvDPDNperform -ALLNORAW, // EvDPDNmet -DEMOSAIC, // EvDemosaicLMMSEIter -LUMINANCECURVE, // EvCATbadpix -LUMINANCECURVE, // EvCATAutoadap -DEFRINGE, // EvPFCurve -WHITEBALANCE, // EvWBequal -WHITEBALANCE, // EvWBequalbo -TRANSFORM, // EvGradientDegree -TRANSFORM, // EvGradientEnabled -TRANSFORM, // EvPCVignetteStrength -TRANSFORM, // EvPCVignetteEnabled -RGBCURVE, // EvBWChmixEnabled -RGBCURVE, // EvBWred -RGBCURVE, // EvBWgreen -RGBCURVE, // EvBWblue -RGBCURVE, // EvBWredgam -RGBCURVE, // EvBWgreengam -RGBCURVE, // EvBWbluegam -RGBCURVE, // EvBWfilter -RGBCURVE, // EvBWsetting -RGBCURVE, // EvBWoran -RGBCURVE, // EvBWyell -RGBCURVE, // EvBWcyan -RGBCURVE, // EvBWmag -RGBCURVE, // EvBpur -RGBCURVE, // EvBWLuminanceEqual -RGBCURVE, // EvBWChmixEnabledLm -RGBCURVE, // EvBWmethod -RGBCURVE, // EvBWBeforeCurve -RGBCURVE, // EvBWBeforeCurveMode -RGBCURVE, // EvBWAfterCurve -RGBCURVE, // EvBWAfterCurveMode -RGBCURVE, // EvAutoch -NONE, // --unused-- -RGBCURVE, // EvNeutralBW -TRANSFORM, // EvGradientFeather -TRANSFORM, // EvGradientStrength -TRANSFORM, // EvGradientCenter -TRANSFORM, // EvPCVignetteFeather -TRANSFORM, // EvPCVignetteRoundness -TRANSFORM, // EvVignettingRadius, -TRANSFORM, // EvVignettingStrength -TRANSFORM, // EvVignettingCenter -LUMINANCECURVE, // EvLCLCurve -LUMINANCECURVE, // EvLLHCurve -LUMINANCECURVE, // EvLHHCurve -DIRPYREQUALIZER, // EvDirPyrEqualizerThreshold -ALLNORAW, // EvDPDNenhance -RGBCURVE, // EvBWMethodalg -DIRPYREQUALIZER, // EvDirPyrEqualizerSkin -DIRPYREQUALIZER, // EvDirPyrEqlgamutlab -DIRPYREQUALIZER, // EvDirPyrEqualizerHueskin -ALLNORAW, // EvDPDNmedian -ALLNORAW, //EvDPDNmedmet + ALL, // EvPhotoLoaded, + ALL, // EvProfileLoaded, + ALL, // EvProfileChanged, + ALL, // EvHistoryBrowsed, + RGBCURVE, // EvBrightness, + RGBCURVE, // EvContrast, + RGBCURVE, // EvBlack, + RGBCURVE, // EvExpComp, + RGBCURVE, // EvHLCompr, + RGBCURVE, // EvSHCompr, + RGBCURVE, // EvToneCurve1, + AUTOEXP, // EvAutoExp, + AUTOEXP, // EvClip, + LUMINANCECURVE, // EvLBrightness, + LUMINANCECURVE, // EvLContrast, + LUMINANCECURVE, // EvLBlack, + LUMINANCECURVE, // EvLHLCompr, + LUMINANCECURVE, // EvLSHCompr, + LUMINANCECURVE, // EvLLCurve, + SHARPENING, // EvShrEnabled, + SHARPENING, // EvShrRadius, + SHARPENING, // EvShrAmount, + SHARPENING, // EvShrThresh, + SHARPENING, // EvShrEdgeOnly, + SHARPENING, // EvShrEdgeRadius, + SHARPENING, // EvShrEdgeTolerance, + SHARPENING, // EvShrHaloControl, + SHARPENING, // EvShrHaloAmount, + SHARPENING, // EvShrMethod, + SHARPENING, // EvShrDRadius, + SHARPENING, // EvShrDAmount, + SHARPENING, // EvShrDDamping, + SHARPENING, // EvShrDIterations, + TRANSFORM, // EvLCPUseDist, + DARKFRAME, // EvLCPUseVign, + TRANSFORM, // EvLCPUseCA, + M_VOID, // EvFixedExp + WHITEBALANCE, // EvWBMethod, + WHITEBALANCE, // EvWBTemp, + WHITEBALANCE, // EvWBGreen, + RGBCURVE, // EvToneCurveMode1, + RGBCURVE, // EvToneCurve2, + RGBCURVE, // EvToneCurveMode2, + 0, // EvLDNRadius: obsolete, + 0, // EvLDNEdgeTolerance: obsolete, + 0, // EvCDNEnabled:obsolete, + ALL, // EvBlendCMSMatrix, + RGBCURVE, // EvDCPToneCurve, + INPUTPROFILE, // EvDCPIlluminant, + RETINEX, // EvSHEnabled, + RGBCURVE, // EvSHHighlights, + RGBCURVE, // EvSHShadows, + RGBCURVE, // EvSHHLTonalW, + RGBCURVE, // EvSHSHTonalW, + RGBCURVE, // EvSHLContrast, + RETINEX, // EvSHRadius, + ALL, // EvCTRotate, + ALL, // EvCTHFlip, + ALL, // EvCTVFlip, + TRANSFORM, // EvROTDegree, + TRANSFORM, // EvTransAutoFill, + TRANSFORM, // EvDISTAmount, + ALL, // EvBookmarkSelected, + CROP, // EvCrop, + TRANSFORM, // EvCACorr, + ALLNORAW, // EvHREnabled, + ALLNORAW, // EvHRAmount, + ALLNORAW, // EvHRMethod, + ALLNORAW, // EvWProfile, + OUTPUTPROFILE, // EvOProfile, + INPUTPROFILE, // EvIProfile, + TRANSFORM, // EvVignettingAmount, + RGBCURVE, // EvChMixer, + RESIZE, // EvResizeScale, + RESIZE, // EvResizeMethod, + EXIF, // EvExif, + IPTC, // EvIPTC + RESIZE, // EvResizeSpec, + RESIZE, // EvResizeWidth + RESIZE, // EvResizeHeight + RESIZE, // EvResizeEnabled + ALL, // EvProfileChangeNotification + RETINEX, // EvShrHighQuality + TRANSFORM, // EvPerspCorr + DARKFRAME, // EvLCPFile + RGBCURVE, // EvRGBrCurveLumamode + IMPULSEDENOISE, // EvIDNEnabled, + IMPULSEDENOISE, // EvIDNThresh, + ALLNORAW, // EvDPDNEnabled, + ALLNORAW, // EvDPDNLuma, + ALLNORAW, // EvDPDNChroma, + ALLNORAW, // EvDPDNGamma, + DIRPYREQUALIZER, // EvDirPyrEqualizer, + DIRPYREQUALIZER, // EvDirPyrEqlEnabled, + LUMINANCECURVE, // EvLSaturation, + LUMINANCECURVE, // EvLaCurve, + LUMINANCECURVE, // EvLbCurve, + DEMOSAIC, // EvDemosaicMethod + DARKFRAME, // EvPreProcessHotPixel + RGBCURVE, // EvSaturation, + RGBCURVE, // EvHSVEqualizerH, + RGBCURVE, // EvHSVEqualizerS, + RGBCURVE, // EvHSVEqualizerV, + RGBCURVE, // EvHSVEqEnabled, + DEFRINGE, // EvDefringeEnabled, + DEFRINGE, // EvDefringeRadius, + DEFRINGE, // EvDefringeThreshold, + RGBCURVE, // EvHLComprThreshold, + RESIZE, // EvResizeBoundingBox + RESIZE, // EvResizeAppliesTo + LUMINANCECURVE, // EvCBAvoidClip, + LUMINANCECURVE, // EvCBSatLimiter, + LUMINANCECURVE, // EvCBSatLimit, + DEMOSAIC, // EvDemosaicDCBIter + DEMOSAIC, // EvDemosaicFalseColorIter + DEMOSAIC, // EvDemosaicDCBEnhanced + DARKFRAME, // EvPreProcessCARed + DARKFRAME, // EvPreProcessCABlue + DARKFRAME, // EvPreProcessLineDenoise + DARKFRAME, // EvPreProcessGEquilThresh + DARKFRAME, // EvPreProcessAutoCA + DARKFRAME, // EvPreProcessAutoDF + DARKFRAME, // EvPreProcessDFFile + DARKFRAME, // EvPreProcessExpCorrLinear + DARKFRAME, // EvPreProcessExpCorrPH + FLATFIELD, // EvFlatFieldFile, + FLATFIELD, // EvFlatFieldAutoSelect, + FLATFIELD, // EvFlatFieldBlurRadius, + FLATFIELD, // EvFlatFieldBlurType, + TRANSFORM, // EvAutoDIST, + ALLNORAW, // EvDPDNLumCurve, + ALLNORAW, // EvDPDNChromCurve, + GAMMA, // EvGAMMA + GAMMA, // EvGAMPOS + GAMMA, // EvGAMFREE + GAMMA, // EvSLPOS + DARKFRAME, // EvPreProcessExpBlackzero + DARKFRAME, // EvPreProcessExpBlackone + DARKFRAME, // EvPreProcessExpBlacktwo + DARKFRAME, // EvPreProcessExpBlackthree + DARKFRAME, // EvPreProcessExptwoGreen + SHARPENING, // EvSharpenEdgePasses + SHARPENING, // EvSharpenEdgeStrength + SHARPENING, // EvSharpenMicroStrength + SHARPENING, // EvSharpenMicroUniformity + SHARPENING, // EvSharpenEdgeEnabled + SHARPENING, // EvSharpenEdgeThreechannels + SHARPENING, // EvSharpenMicroEnabled + SHARPENING, // EvSharpenMicroMatrix + DEMOSAIC, // EvDemosaicALLEnhanced // Disabled but not removed for now, may be reintroduced some day + RGBCURVE, // EvVibranceEnabled + RGBCURVE, // EvVibrancePastels + RGBCURVE, // EvVibranceSaturated + RGBCURVE, // EvVibranceProtectSkins + RGBCURVE, // EvVibranceAvoidColorShift + RGBCURVE, // EvVibrancePastSatTog + RGBCURVE, // EvVibrancePastSatThreshold + SHARPENING, // EvEPDStrength + SHARPENING, // EvEPDEdgeStopping + SHARPENING, // EvEPDScale + SHARPENING, // EvEPDReweightingIterates + SHARPENING, // EvEPDEnabled + RGBCURVE, // EvRGBrCurve + RGBCURVE, // EvRGBgCurve + RGBCURVE, // EvRGBbCurve + RGBCURVE, // EvNeutralExp + DEMOSAIC | M_PREPROC, // EvDemosaicMethodPreProc + LUMINANCECURVE, // EvLCCurve + LUMINANCECURVE, // EvLCHCurve + RGBCURVE, // EvVibranceSkinTonesCurve + LUMINANCECURVE, // EvLLCCurve + LUMINANCECURVE, // EvLLCredsk + ALLNORAW, // EvDPDNLdetail + LUMINANCECURVE, // EvCATEnabled + LUMINANCECURVE, // EvCATDegree + LUMINANCECURVE, // EvCATMethodsur + LUMINANCECURVE, // EvCATAdapscen + LUMINANCECURVE, // EvCATAdapLum + LUMINANCECURVE, // EvCATMethodWB + LUMINANCECURVE, // EvCATJLight + LUMINANCECURVE, // EvCATChroma + LUMINANCECURVE, // EvCATAutoDegree + LUMINANCECURVE, // EvCATContrast + LUMINANCECURVE, // EvCATSurr + LUMINANCECURVE, // EvCATgamut + LUMINANCECURVE, // EvCATmethodalg + LUMINANCECURVE, // EvCATRstpro + LUMINANCECURVE, // EvCATQbright + LUMINANCECURVE, // EvCATQContrast + LUMINANCECURVE, // EvCATSChroma + LUMINANCECURVE, // EvCATMchroma + LUMINANCECURVE, // EvCAThue + LUMINANCECURVE, // EvCATcurve1 + LUMINANCECURVE, // EvCATcurve2 + LUMINANCECURVE, // EvCATcurvemode1 + LUMINANCECURVE, // EvCATcurvemode2 + LUMINANCECURVE, // EvCATcurve3 + LUMINANCECURVE, // EvCATcurvemode3 + LUMINANCECURVE, // EvCATdatacie + LUMINANCECURVE, // EvCATtonecie + ALLNORAW, // EvDPDNbluechro + ALLNORAW, // EvDPDNperform + ALLNORAW, // EvDPDNmet + DEMOSAIC, // EvDemosaicLMMSEIter + LUMINANCECURVE, // EvCATbadpix + LUMINANCECURVE, // EvCATAutoadap + DEFRINGE, // EvPFCurve + WHITEBALANCE, // EvWBequal + WHITEBALANCE, // EvWBequalbo + TRANSFORM, // EvGradientDegree + TRANSFORM, // EvGradientEnabled + TRANSFORM, // EvPCVignetteStrength + TRANSFORM, // EvPCVignetteEnabled + RGBCURVE, // EvBWChmixEnabled + RGBCURVE, // EvBWred + RGBCURVE, // EvBWgreen + RGBCURVE, // EvBWblue + RGBCURVE, // EvBWredgam + RGBCURVE, // EvBWgreengam + RGBCURVE, // EvBWbluegam + RGBCURVE, // EvBWfilter + RGBCURVE, // EvBWsetting + RGBCURVE, // EvBWoran + RGBCURVE, // EvBWyell + RGBCURVE, // EvBWcyan + RGBCURVE, // EvBWmag + RGBCURVE, // EvBpur + RGBCURVE, // EvBWLuminanceEqual + RGBCURVE, // EvBWChmixEnabledLm + RGBCURVE, // EvBWmethod + RGBCURVE, // EvBWBeforeCurve + RGBCURVE, // EvBWBeforeCurveMode + RGBCURVE, // EvBWAfterCurve + RGBCURVE, // EvBWAfterCurveMode + RGBCURVE, // EvAutoch + NONE, // --unused-- + RGBCURVE, // EvNeutralBW + TRANSFORM, // EvGradientFeather + TRANSFORM, // EvGradientStrength + TRANSFORM, // EvGradientCenter + TRANSFORM, // EvPCVignetteFeather + TRANSFORM, // EvPCVignetteRoundness + TRANSFORM, // EvVignettingRadius, + TRANSFORM, // EvVignettingStrength + TRANSFORM, // EvVignettingCenter + LUMINANCECURVE, // EvLCLCurve + LUMINANCECURVE, // EvLLHCurve + LUMINANCECURVE, // EvLHHCurve + DIRPYREQUALIZER, // EvDirPyrEqualizerThreshold + ALLNORAW, // EvDPDNenhance + RGBCURVE, // EvBWMethodalg + DIRPYREQUALIZER, // EvDirPyrEqualizerSkin + DIRPYREQUALIZER, // EvDirPyrEqlgamutlab + DIRPYREQUALIZER, // EvDirPyrEqualizerHueskin + ALLNORAW, // EvDPDNmedian + ALLNORAW, //EvDPDNmedmet //DIRPYREQUALIZER // EvDirPyrEqualizeralg -RGBCURVE, // EvColorToningEnabled -RGBCURVE, // EvColorToningColor -RGBCURVE, // EvColorToningOpacity -RGBCURVE, // EvColorToningCLCurve -RGBCURVE, // EvColorToningMethod + RGBCURVE, // EvColorToningEnabled + RGBCURVE, // EvColorToningColor + RGBCURVE, // EvColorToningOpacity + RGBCURVE, // EvColorToningCLCurve + RGBCURVE, // EvColorToningMethod //RGBCURVE, // EvColorToningTwocolor -RGBCURVE, // EvColorToningLLCurve -RGBCURVE, // EvColorToningredlow -RGBCURVE, // EvColorToninggreenlow -RGBCURVE, // EvColorToningbluelow -RGBCURVE, // EvColorToningredmed -RGBCURVE, // EvColorToninggreenmed -RGBCURVE, // EvColorToningbluemed -RGBCURVE, // EvColorToningredhigh -RGBCURVE, // EvColorToninggreenhigh -RGBCURVE, // EvColorToningbluehigh -RGBCURVE, // EvColorToningbalance -RGBCURVE, // EvColorToningNeutral -RGBCURVE, // EvColorToningsatlow -RGBCURVE, // EvColorToningsathigh -RGBCURVE, // EvColorToningTwocolor -RGBCURVE, // EvColorToningNeutralcur -RGBCURVE, // EvColorToningLumamode -RGBCURVE, // EvColorToningShadows -RGBCURVE, // EvColorToningHighights -RGBCURVE, // EvColorToningSatProtection -RGBCURVE, // EvColorToningSatThreshold -RGBCURVE, //EvColorToningStrength -RGBCURVE, //EvColorToningautosat -ALLNORAW, //EvDPDNmetmed -ALLNORAW, //EvDPDNrgbmet -ALLNORAW, //EvDPDNpasses -FLATFIELD, // EvFlatFieldClipControl -FLATFIELD, // EvFlatFieldAutoClipControl -DARKFRAME, // EvPreProcessExpBlackRed -DARKFRAME, // EvPreProcessExpBlackGreen -DARKFRAME, // EvPreProcessExpBlackBlue -RGBCURVE, //EvFilmSimulationEnabled -RGBCURVE, //EvFilmSimulationStrength -RGBCURVE, //EvFilmSimulationFilename -ALLNORAW, // EvDPDNLCurve -ALLNORAW, // EvDPDNsmet -DARKFRAME, // EvPreProcessDeadPixel -ALLNORAW, //EvDPDNCCCurve -ALLNORAW, //EvDPDNautochroma -ALLNORAW, // EvDPDNLmet -ALLNORAW, // EvDPDNCmet -ALLNORAW, // EvDPDNC2met -DIRPYREQUALIZER, // EvWavelet -DIRPYREQUALIZER, // EvEnabled -DIRPYREQUALIZER, // EvWavLmethod -DIRPYREQUALIZER, // EvWavCLmethod -DIRPYREQUALIZER, // EvWavDirmethod -DIRPYREQUALIZER, // EvWavtiles -DIRPYREQUALIZER, // EvWavsky -DIRPYREQUALIZER, // EvWavthres -DIRPYREQUALIZER, // EvWavthr -DIRPYREQUALIZER, // EvWavchroma -DIRPYREQUALIZER, // EvWavmedian -DIRPYREQUALIZER, // EvWavunif -DIRPYREQUALIZER, // EvWavSkin -DIRPYREQUALIZER, // EvWavHueSkin -DIRPYREQUALIZER, // EvWavThreshold -DIRPYREQUALIZER, // EvWavlhl -DIRPYREQUALIZER, // EvWavbhl -DIRPYREQUALIZER, // EvWavThresHold2 -DIRPYREQUALIZER, // EvWavavoid -DIRPYREQUALIZER, // EvWavCCCurve -DIRPYREQUALIZER, // EvWavpast -DIRPYREQUALIZER, // EvWavsat -DIRPYREQUALIZER, // EvWavCHmet -DIRPYREQUALIZER, // EvWavHSmet -DIRPYREQUALIZER, // EvWavchro -DIRPYREQUALIZER, // EvWavColor -DIRPYREQUALIZER, // EvWavOpac -DIRPYREQUALIZER, // EvWavsup -DIRPYREQUALIZER, // EvWavTilesmet -DIRPYREQUALIZER, // EvWavrescon -DIRPYREQUALIZER, // EvWavreschro -DIRPYREQUALIZER, // EvWavresconH -DIRPYREQUALIZER, // EvWavthrH -DIRPYREQUALIZER, // EvWavHueskin2 -DIRPYREQUALIZER, // EvWavedgrad -DIRPYREQUALIZER, // EvWavedgval -DIRPYREQUALIZER, // EvWavStrngth -DIRPYREQUALIZER, // EvWavdaubcoeffmet -DIRPYREQUALIZER, // EvWavedgreinf -DIRPYREQUALIZER, // EvWaveletch -DIRPYREQUALIZER, //EvWavCHSLmet -DIRPYREQUALIZER, //EvWavedgcont -DIRPYREQUALIZER, //EvWavEDmet -DIRPYREQUALIZER, //EvWavlev0nois -DIRPYREQUALIZER, //EvWavlev1nois -DIRPYREQUALIZER, //EvWavlev2nois -DIRPYREQUALIZER, //EvWavmedianlev -DIRPYREQUALIZER, //EvWavHHCurve -DIRPYREQUALIZER, //EvWavBackmet -DIRPYREQUALIZER, //EvWavedgedetect -DIRPYREQUALIZER, //EvWavlipst -DIRPYREQUALIZER, //EvWavedgedetectthr -DIRPYREQUALIZER, //EvWavedgedetectthr2 -DIRPYREQUALIZER, //EvWavlinkedg -DIRPYREQUALIZER, //EvWavCHCurve -DARKFRAME, //EvPreProcessHotDeadThresh -SHARPENING, //EvEPDgamma -DIRPYREQUALIZER, //EvWavtmr -DIRPYREQUALIZER, //EvWavTMmet -DIRPYREQUALIZER, //EvWavtmrs -DIRPYREQUALIZER, //EvWavbalance -DIRPYREQUALIZER, //EvWaviter -DIRPYREQUALIZER, //EvWavgamma -DIRPYREQUALIZER, //EvWavCLCurve -DIRPYREQUALIZER, //EvWavopacity -DIRPYREQUALIZER, //EvWavBAmet -DIRPYREQUALIZER, //EvWavopacityWL -RESIZE, // EvPrShrEnabled -RESIZE, // EvPrShrRadius -RESIZE, // EvPrShrAmount -RESIZE, // EvPrShrThresh -RESIZE, // EvPrShrEdgeOnly -RESIZE, // EvPrShrEdgeRadius=375, -RESIZE, // EvPrShrEdgeTolerance=376, -RESIZE, // EvPrShrHaloControl=377, -RESIZE, // EvPrShrHaloAmount=378, -RESIZE, // EvPrShrMethod=379, -RESIZE, // EvPrShrDRadius=380, -RESIZE, // EvPrShrDAmount=381, -RESIZE, // EvPrShrDDamping=382, -RESIZE, // EvPrShrDIterations=383, -DIRPYREQUALIZER, // EvWavcbenab -DIRPYREQUALIZER, // EvWavgreenhigh -DIRPYREQUALIZER, // EvWavbluehigh -DIRPYREQUALIZER, // EvWavgreenmed -DIRPYREQUALIZER, // EvWavbluemed -DIRPYREQUALIZER, // EvWavgreenlow -DIRPYREQUALIZER, // EvWavbluelow -DIRPYREQUALIZER, // EvWavNeutral -RGBCURVE, // EvDCPApplyLookTable, -RGBCURVE, // EvDCPApplyBaselineExposureOffset, -INPUTPROFILE, // EvDCPApplyHueSatMap -DIRPYREQUALIZER, // EvWavenacont -DIRPYREQUALIZER, // EvWavenachrom -DIRPYREQUALIZER, // EvWavenaedge -DIRPYREQUALIZER, // EvWavenares -DIRPYREQUALIZER, // EvWavenafin -DIRPYREQUALIZER, // EvWavenatoning -DIRPYREQUALIZER, // EvWavenanoise -DIRPYREQUALIZER, // EvWavedgesensi -DIRPYREQUALIZER, // EvWavedgeampli -DIRPYREQUALIZER, //EvWavlev3nois -DIRPYREQUALIZER //EvWavNPmet + RGBCURVE, // EvColorToningLLCurve + RGBCURVE, // EvColorToningredlow + RGBCURVE, // EvColorToninggreenlow + RGBCURVE, // EvColorToningbluelow + RGBCURVE, // EvColorToningredmed + RGBCURVE, // EvColorToninggreenmed + RGBCURVE, // EvColorToningbluemed + RGBCURVE, // EvColorToningredhigh + RGBCURVE, // EvColorToninggreenhigh + RGBCURVE, // EvColorToningbluehigh + RGBCURVE, // EvColorToningbalance + RGBCURVE, // EvColorToningNeutral + RGBCURVE, // EvColorToningsatlow + RGBCURVE, // EvColorToningsathigh + RGBCURVE, // EvColorToningTwocolor + RGBCURVE, // EvColorToningNeutralcur + RGBCURVE, // EvColorToningLumamode + RGBCURVE, // EvColorToningShadows + RGBCURVE, // EvColorToningHighights + RGBCURVE, // EvColorToningSatProtection + RGBCURVE, // EvColorToningSatThreshold + RGBCURVE, //EvColorToningStrength + RGBCURVE, //EvColorToningautosat + ALLNORAW, //EvDPDNmetmed + ALLNORAW, //EvDPDNrgbmet + ALLNORAW, //EvDPDNpasses + FLATFIELD, // EvFlatFieldClipControl + FLATFIELD, // EvFlatFieldAutoClipControl + DARKFRAME, // EvPreProcessExpBlackRed + DARKFRAME, // EvPreProcessExpBlackGreen + DARKFRAME, // EvPreProcessExpBlackBlue + RGBCURVE, //EvFilmSimulationEnabled + RGBCURVE, //EvFilmSimulationStrength + RGBCURVE, //EvFilmSimulationFilename + ALLNORAW, // EvDPDNLCurve + ALLNORAW, // EvDPDNsmet + DARKFRAME, // EvPreProcessDeadPixel + ALLNORAW, //EvDPDNCCCurve + ALLNORAW, //EvDPDNautochroma + ALLNORAW, // EvDPDNLmet + ALLNORAW, // EvDPDNCmet + ALLNORAW, // EvDPDNC2met + DIRPYREQUALIZER, // EvWavelet + DIRPYREQUALIZER, // EvEnabled + DIRPYREQUALIZER, // EvWavLmethod + DIRPYREQUALIZER, // EvWavCLmethod + DIRPYREQUALIZER, // EvWavDirmethod + DIRPYREQUALIZER, // EvWavtiles + DIRPYREQUALIZER, // EvWavsky + DIRPYREQUALIZER, // EvWavthres + DIRPYREQUALIZER, // EvWavthr + DIRPYREQUALIZER, // EvWavchroma + DIRPYREQUALIZER, // EvWavmedian + DIRPYREQUALIZER, // EvWavunif + DIRPYREQUALIZER, // EvWavSkin + DIRPYREQUALIZER, // EvWavHueSkin + DIRPYREQUALIZER, // EvWavThreshold + DIRPYREQUALIZER, // EvWavlhl + DIRPYREQUALIZER, // EvWavbhl + DIRPYREQUALIZER, // EvWavThresHold2 + DIRPYREQUALIZER, // EvWavavoid + DIRPYREQUALIZER, // EvWavCCCurve + DIRPYREQUALIZER, // EvWavpast + DIRPYREQUALIZER, // EvWavsat + DIRPYREQUALIZER, // EvWavCHmet + DIRPYREQUALIZER, // EvWavHSmet + DIRPYREQUALIZER, // EvWavchro + DIRPYREQUALIZER, // EvWavColor + DIRPYREQUALIZER, // EvWavOpac + DIRPYREQUALIZER, // EvWavsup + DIRPYREQUALIZER, // EvWavTilesmet + DIRPYREQUALIZER, // EvWavrescon + DIRPYREQUALIZER, // EvWavreschro + DIRPYREQUALIZER, // EvWavresconH + DIRPYREQUALIZER, // EvWavthrH + DIRPYREQUALIZER, // EvWavHueskin2 + DIRPYREQUALIZER, // EvWavedgrad + DIRPYREQUALIZER, // EvWavedgval + DIRPYREQUALIZER, // EvWavStrngth + DIRPYREQUALIZER, // EvWavdaubcoeffmet + DIRPYREQUALIZER, // EvWavedgreinf + DIRPYREQUALIZER, // EvWaveletch + DIRPYREQUALIZER, //EvWavCHSLmet + DIRPYREQUALIZER, //EvWavedgcont + DIRPYREQUALIZER, //EvWavEDmet + DIRPYREQUALIZER, //EvWavlev0nois + DIRPYREQUALIZER, //EvWavlev1nois + DIRPYREQUALIZER, //EvWavlev2nois + DIRPYREQUALIZER, //EvWavmedianlev + DIRPYREQUALIZER, //EvWavHHCurve + DIRPYREQUALIZER, //EvWavBackmet + DIRPYREQUALIZER, //EvWavedgedetect + DIRPYREQUALIZER, //EvWavlipst + DIRPYREQUALIZER, //EvWavedgedetectthr + DIRPYREQUALIZER, //EvWavedgedetectthr2 + DIRPYREQUALIZER, //EvWavlinkedg + DIRPYREQUALIZER, //EvWavCHCurve + DARKFRAME, //EvPreProcessHotDeadThresh + SHARPENING, //EvEPDgamma + DIRPYREQUALIZER, //EvWavtmr + DIRPYREQUALIZER, //EvWavTMmet + DIRPYREQUALIZER, //EvWavtmrs + DIRPYREQUALIZER, //EvWavbalance + DIRPYREQUALIZER, //EvWaviter + DIRPYREQUALIZER, //EvWavgamma + DIRPYREQUALIZER, //EvWavCLCurve + DIRPYREQUALIZER, //EvWavopacity + DIRPYREQUALIZER, //EvWavBAmet + DIRPYREQUALIZER, //EvWavopacityWL + RESIZE, // EvPrShrEnabled + RESIZE, // EvPrShrRadius + RESIZE, // EvPrShrAmount + RESIZE, // EvPrShrThresh + RESIZE, // EvPrShrEdgeOnly + RESIZE, // EvPrShrEdgeRadius=375, + RESIZE, // EvPrShrEdgeTolerance=376, + RESIZE, // EvPrShrHaloControl=377, + RESIZE, // EvPrShrHaloAmount=378, + RESIZE, // EvPrShrMethod=379, + RESIZE, // EvPrShrDRadius=380, + RESIZE, // EvPrShrDAmount=381, + RESIZE, // EvPrShrDDamping=382, + RESIZE, // EvPrShrDIterations=383, + DIRPYREQUALIZER, // EvWavcbenab + DIRPYREQUALIZER, // EvWavgreenhigh + DIRPYREQUALIZER, // EvWavbluehigh + DIRPYREQUALIZER, // EvWavgreenmed + DIRPYREQUALIZER, // EvWavbluemed + DIRPYREQUALIZER, // EvWavgreenlow + DIRPYREQUALIZER, // EvWavbluelow + DIRPYREQUALIZER, // EvWavNeutral + RGBCURVE, // EvDCPApplyLookTable, + RGBCURVE, // EvDCPApplyBaselineExposureOffset, + INPUTPROFILE, // EvDCPApplyHueSatMap + DIRPYREQUALIZER, // EvWavenacont + DIRPYREQUALIZER, // EvWavenachrom + DIRPYREQUALIZER, // EvWavenaedge + DIRPYREQUALIZER, // EvWavenares + DIRPYREQUALIZER, // EvWavenafin + DIRPYREQUALIZER, // EvWavenatoning + DIRPYREQUALIZER, // EvWavenanoise + DIRPYREQUALIZER, // EvWavedgesensi + DIRPYREQUALIZER, // EvWavedgeampli + DIRPYREQUALIZER, //EvWavlev3nois + DIRPYREQUALIZER //EvWavNPmet }; diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h index 1f8e5868a..16ccc73a8 100644 --- a/rtengine/refreshmap.h +++ b/rtengine/refreshmap.h @@ -7,7 +7,7 @@ * 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 @@ -25,7 +25,7 @@ // Must NOT be used with other event (i.e. will be used for MINUPDATE only) #define M_MINUPDATE (1<<14) // Force high quality -#define M_HIGHQUAL (1<<13) +#define M_HIGHQUAL (1<<13) // Elementary functions that can be done to // the preview image when an event occurs @@ -63,7 +63,7 @@ #define RESIZE M_VOID #define EXIF M_VOID #define IPTC M_VOID -#define DIRPYREQUALIZER (M_COLOR|M_LUMINANCE) +#define DIRPYREQUALIZER (M_COLOR|M_LUMINANCE) #define OUTPUTPROFILE (M_COLOR|M_LUMINANCE) #define INPUTPROFILE WHITEBALANCE #define GAMMA (M_COLOR|M_LUMINANCE) @@ -72,4 +72,4 @@ #define ALLNORAW (M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) extern int refreshmap[]; -#endif +#endif diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index 9cdb6828c..060f0c4ff 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -4,67 +4,79 @@ #include -namespace rtengine { - static const int MAXVAL = 0xffff; - static const float MAXVALF = float(MAXVAL); // float version of MAXVAL - static const double MAXVALD = double(MAXVAL); // double version of MAXVAL +namespace rtengine +{ +static const int MAXVAL = 0xffff; +static const float MAXVALF = float(MAXVAL); // float version of MAXVAL +static const double MAXVALD = double(MAXVAL); // double version of MAXVAL - template - inline const _Tp SQR (_Tp x) { -// return std::pow(x,2); Slower than: - return (x*x); - } +template +inline const _Tp SQR (_Tp x) +{ +// return std::pow(x,2); Slower than: + return (x * x); +} - template - inline const _Tp& min(const _Tp& a, const _Tp& b) { - return std::min(a,b); - } +template +inline const _Tp& min(const _Tp& a, const _Tp& b) +{ + return std::min(a, b); +} - template - inline const _Tp& max(const _Tp& a, const _Tp& b) { - return std::max(a,b); - } +template +inline const _Tp& max(const _Tp& a, const _Tp& b) +{ + return std::max(a, b); +} - template - inline const _Tp LIM(const _Tp& a, const _Tp& b, const _Tp& c) { - return std::max(b,std::min(a,c)); - } +template +inline const _Tp LIM(const _Tp& a, const _Tp& b, const _Tp& c) +{ + return std::max(b, std::min(a, c)); +} - template - inline const _Tp LIM01(const _Tp& a) { - return std::max(_Tp(0),std::min(a,_Tp(1))); - } +template +inline const _Tp LIM01(const _Tp& a) +{ + return std::max(_Tp(0), std::min(a, _Tp(1))); +} - template - inline const _Tp ULIM(const _Tp& a, const _Tp& b, const _Tp& c) { - return ((b < c) ? LIM(a,b,c) : LIM(a,c,b)); - } +template +inline const _Tp ULIM(const _Tp& a, const _Tp& b, const _Tp& c) +{ + return ((b < c) ? LIM(a, b, c) : LIM(a, c, b)); +} - template - inline const _Tp CLIP(const _Tp& a) { - return LIM(a, static_cast<_Tp>(0), static_cast<_Tp>(MAXVAL)); - } +template +inline const _Tp CLIP(const _Tp& a) +{ + return LIM(a, static_cast<_Tp>(0), static_cast<_Tp>(MAXVAL)); +} - template - inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c) { - return std::min(c,std::min(a,b)); - } +template +inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c) +{ + return std::min(c, std::min(a, b)); +} - template - inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c) { - return std::max(c,std::max(a,b)); - } +template +inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c) +{ + return std::max(c, std::max(a, b)); +} - template - inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) { - return std::min(d,std::min(c,std::min(a,b))); - } +template +inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) +{ + return std::min(d, std::min(c, std::min(a, b))); +} - template - inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) { - return std::max(d,std::max(c,std::max(a,b))); - } +template +inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) +{ + return std::max(d, std::max(c, std::max(a, b))); +} } #endif diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 46a8a0d6b..6c727ac87 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -7,7 +7,7 @@ * 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 @@ -34,440 +34,467 @@ #include "settings.h" #include "LUT.h" /** - * @file + * @file * This file contains the main functionality of the raw therapee engine. * */ - class EditDataProvider; +class EditDataProvider; -namespace rtengine { +namespace rtengine +{ - class IImage8; - class IImage16; - class IImagefloat; +class IImage8; +class IImage16; +class IImagefloat; - /** - * This class represents provides functions to obtain exif and IPTC metadata information - * from the image file - */ - class ImageMetaData { +/** + * This class represents provides functions to obtain exif and IPTC metadata information + * from the image file + */ +class ImageMetaData +{ - public: - /** Checks the availability of exif metadata tags. - * @return Returns true if image contains exif metadata tags */ - virtual bool hasExif () const =0; - /** Returns the directory of exif metadata tags. - * @return The directory of exif metadata tags */ - virtual const rtexif::TagDirectory* getExifData () const =0; - /** Checks the availability of IPTC tags. - * @return Returns true if image contains IPTC tags */ - virtual bool hasIPTC () const =0; - /** Returns the directory of IPTC tags. - * @return The directory of IPTC tags */ - virtual const procparams::IPTCPairs getIPTCData () const =0; - /** @return a struct containing the date and time of the image */ - virtual struct tm getDateTime () const =0; - /** @return a timestamp containing the date and time of the image */ - virtual time_t getDateTimeAsTS() const =0; - /** @return the ISO of the image */ - virtual int getISOSpeed () const =0; - /** @return the F number of the image */ - virtual double getFNumber () const =0; - /** @return the focal length used at the exposure */ - virtual double getFocalLen () const =0; - /** @return the focal length in 35mm used at the exposure */ - virtual double getFocalLen35mm () const =0; - /** @return the focus distance in meters, 0=unknown, 10000=infinity */ - virtual float getFocusDist () const =0; - /** @return the shutter speed */ - virtual double getShutterSpeed () const =0; - /** @return the exposure compensation */ - virtual double getExpComp () const =0; - /** @return the maker of the camera */ - virtual std::string getMake () const =0; - /** @return the model of the camera */ - virtual std::string getModel () const =0; +public: + /** Checks the availability of exif metadata tags. + * @return Returns true if image contains exif metadata tags */ + virtual bool hasExif () const = 0; + /** Returns the directory of exif metadata tags. + * @return The directory of exif metadata tags */ + virtual const rtexif::TagDirectory* getExifData () const = 0; + /** Checks the availability of IPTC tags. + * @return Returns true if image contains IPTC tags */ + virtual bool hasIPTC () const = 0; + /** Returns the directory of IPTC tags. + * @return The directory of IPTC tags */ + virtual const procparams::IPTCPairs getIPTCData () const = 0; + /** @return a struct containing the date and time of the image */ + virtual struct tm getDateTime () const = 0; + /** @return a timestamp containing the date and time of the image */ + virtual time_t getDateTimeAsTS() const = 0; + /** @return the ISO of the image */ + virtual int getISOSpeed () const = 0; + /** @return the F number of the image */ + virtual double getFNumber () const = 0; + /** @return the focal length used at the exposure */ + virtual double getFocalLen () const = 0; + /** @return the focal length in 35mm used at the exposure */ + virtual double getFocalLen35mm () const = 0; + /** @return the focus distance in meters, 0=unknown, 10000=infinity */ + virtual float getFocusDist () const = 0; + /** @return the shutter speed */ + virtual double getShutterSpeed () const = 0; + /** @return the exposure compensation */ + virtual double getExpComp () const = 0; + /** @return the maker of the camera */ + virtual std::string getMake () const = 0; + /** @return the model of the camera */ + virtual std::string getModel () const = 0; - std::string getCamera () const { return getMake() + " " + getModel(); } + std::string getCamera () const + { + return getMake() + " " + getModel(); + } - /** @return the lens on the camera */ - virtual std::string getLens () const =0; - /** @return the orientation of the image */ - virtual std::string getOrientation () const =0; - /** Functions to convert between floating point and string representation of shutter and aperture */ - static std::string apertureToString (double aperture); - /** Functions to convert between floating point and string representation of shutter and aperture */ - static std::string shutterToString (double shutter); - /** Functions to convert between floating point and string representation of shutter and aperture */ - static double apertureFromString (std::string shutter); - /** Functions to convert between floating point and string representation of shutter and aperture */ - static double shutterFromString (std::string shutter); - /** Functions to convert between floating point and string representation of exposure compensation */ - static std::string expcompToString (double expcomp, bool maskZeroexpcomp); - - virtual ~ImageMetaData () {} + /** @return the lens on the camera */ + virtual std::string getLens () const = 0; + /** @return the orientation of the image */ + virtual std::string getOrientation () const = 0; + /** Functions to convert between floating point and string representation of shutter and aperture */ + static std::string apertureToString (double aperture); + /** Functions to convert between floating point and string representation of shutter and aperture */ + static std::string shutterToString (double shutter); + /** Functions to convert between floating point and string representation of shutter and aperture */ + static double apertureFromString (std::string shutter); + /** Functions to convert between floating point and string representation of shutter and aperture */ + static double shutterFromString (std::string shutter); + /** Functions to convert between floating point and string representation of exposure compensation */ + static std::string expcompToString (double expcomp, bool maskZeroexpcomp); - /** Reads metadata from file. - * @param fname is the name of the file - * @param rml is a struct containing information about metadata location. Use it only for raw files. In case - * of jpgs and tiffs pass a NULL pointer. - * @return The metadata */ - static ImageMetaData* fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml); - }; + virtual ~ImageMetaData () {} - /** This listener interface is used to indicate the progress of time consuming operations */ - class ProgressListener { - - public: - virtual ~ProgressListener() {} - /** This member function is called when the percentage of the progress has been changed. - * @param p is a number between 0 and 1 */ - virtual void setProgress (double p) {} - /** This member function is called when a textual information corresponding to the progress has been changed. - * @param str is the textual information corresponding to the progress */ - virtual void setProgressStr (Glib::ustring str) {} - /** This member function is called when the state of the processing has been changed. - * @param inProcessing =true if the processing has been started, =false if it has been stopped */ - virtual void setProgressState (bool inProcessing) {} - /** This member function is called when an error occurs during the operation. - * @param descr is the error message */ - virtual void error (Glib::ustring descr) {} - }; - - class ImageSource; + /** Reads metadata from file. + * @param fname is the name of the file + * @param rml is a struct containing information about metadata location. Use it only for raw files. In case + * of jpgs and tiffs pass a NULL pointer. + * @return The metadata */ + static ImageMetaData* fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml); +}; - /** - * This class represents an image loaded into the memory. It is the basis of further processing. - * The embedded icc profile and metadata information can be obtained through this class, too. - */ - class InitialImage { +/** This listener interface is used to indicate the progress of time consuming operations */ +class ProgressListener +{ - public: - /** Returns the file name of the image. - * @return The file name of the image */ - virtual Glib::ustring getFileName () =0; - /** Returns the embedded icc profile of the image. - * @return The handle of the embedded profile */ - virtual cmsHPROFILE getEmbeddedProfile () =0; - /** Returns a class providing access to the exif and iptc metadata tags of the image. - * @return An instance of the ImageMetaData class */ - virtual const ImageMetaData* getMetaData () =0; - /** This is a function used for internal purposes only. */ - virtual ImageSource* getImageSource () =0; - /** This class has manual reference counting. You have to call this function each time to make a new reference to an instance. */ - virtual void increaseRef () {} - /** This class has manual reference counting. You have to call this function each time to remove a reference - * (the last one deletes the instance automatically). */ - virtual void decreaseRef () {} +public: + virtual ~ProgressListener() {} + /** This member function is called when the percentage of the progress has been changed. + * @param p is a number between 0 and 1 */ + virtual void setProgress (double p) {} + /** This member function is called when a textual information corresponding to the progress has been changed. + * @param str is the textual information corresponding to the progress */ + virtual void setProgressStr (Glib::ustring str) {} + /** This member function is called when the state of the processing has been changed. + * @param inProcessing =true if the processing has been started, =false if it has been stopped */ + virtual void setProgressState (bool inProcessing) {} + /** This member function is called when an error occurs during the operation. + * @param descr is the error message */ + virtual void error (Glib::ustring descr) {} +}; - virtual ~InitialImage () {} +class ImageSource; - /** Loads an image into the memory. - * @param fname the name of the file - * @param isRaw shall be true if it is a raw file - * @param errorCode is a pointer to a variable that is set to nonzero if an error happened (output) - * @param pl is a pointer pointing to an object implementing a progress listener. It can be NULL, in this case progress is not reported. - * @return an object representing the loaded and pre-processed image */ - static InitialImage* load (const Glib::ustring& fname, bool isRaw, int* errorCode, ProgressListener* pl = NULL); - }; +/** + * This class represents an image loaded into the memory. It is the basis of further processing. + * The embedded icc profile and metadata information can be obtained through this class, too. + */ +class InitialImage +{ - /** When the preview image is ready for display during staged processing (thus the changes have been updated), - * the staged processor notifies the listener class implementing a PreviewImageListener. - * It is important to note that the file passed to the listener can be used in a shared manner (copying it is not - * needed) as long as the mutex corresponding to the image is used every time the image is accessed. - * If the scale of the preview image is >1, no sharpening, no denoising and no cropping is applied, and - * the transform operations (rotate, c/a, vignetting correction) are performed using a faster less quality algorithm. - * The image you get with this listener is created to display on the monitor (monitor profile has been already applied). */ - class PreviewImageListener { - public: - virtual ~PreviewImageListener() {} - /** With this member function the staged processor notifies the listener that it allocated a new - * image to store the end result of the processing. It can be used in a shared manner. - * @param img is a pointer to the image - * @param scale describes the current scaling applied compared to the 100% size (preview scale) - * @param cp holds the coordinates of the current crop rectangle */ - virtual void setImage (IImage8* img, double scale, procparams::CropParams cp) {} - /** With this member function the staged processor notifies the listener that the image passed as parameter - * will be deleted, and no longer used to store the preview image. - * @param img the pointer to the image to be destroyed. The listener has to free the image! */ - virtual void delImage (IImage8* img) {} - /** With this member function the staged processor notifies the listener that the preview image has been updated. - * @param cp holds the coordinates of the current crop rectangle */ - virtual void imageReady (procparams::CropParams cp) {} - }; +public: + /** Returns the file name of the image. + * @return The file name of the image */ + virtual Glib::ustring getFileName () = 0; + /** Returns the embedded icc profile of the image. + * @return The handle of the embedded profile */ + virtual cmsHPROFILE getEmbeddedProfile () = 0; + /** Returns a class providing access to the exif and iptc metadata tags of the image. + * @return An instance of the ImageMetaData class */ + virtual const ImageMetaData* getMetaData () = 0; + /** This is a function used for internal purposes only. */ + virtual ImageSource* getImageSource () = 0; + /** This class has manual reference counting. You have to call this function each time to make a new reference to an instance. */ + virtual void increaseRef () {} + /** This class has manual reference counting. You have to call this function each time to remove a reference + * (the last one deletes the instance automatically). */ + virtual void decreaseRef () {} - /** When the detailed crop image is ready for display during staged processing (thus the changes have been updated), - * the staged processor notifies the listener class implementing a DetailedCropListener. - * It is important to note that the file passed to the listener can not be used in a shared manner, the class - * implementing this interface has to store a copy of it. */ - class DetailedCropListener { - public: - virtual ~DetailedCropListener() {} - /** With this member function the staged processor notifies the listener that the detailed crop image has been updated. - * @param img is a pointer to the detailed crop image */ - virtual void setDetailedCrop (IImage8* img, IImage8* imgtrue, procparams::ColorManagementParams cmp, - procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip) {} - virtual bool getWindow (int& cx, int& cy, int& cw, int& ch, int& skip) { return false; } - // virtual void setPosition (int x, int y, bool update=true) {} + virtual ~InitialImage () {} - }; + /** Loads an image into the memory. + * @param fname the name of the file + * @param isRaw shall be true if it is a raw file + * @param errorCode is a pointer to a variable that is set to nonzero if an error happened (output) + * @param pl is a pointer pointing to an object implementing a progress listener. It can be NULL, in this case progress is not reported. + * @return an object representing the loaded and pre-processed image */ + static InitialImage* load (const Glib::ustring& fname, bool isRaw, int* errorCode, ProgressListener* pl = NULL); +}; - /** This listener is used when the full size of the final image has been changed (e.g. rotated by 90 deg.) */ - class SizeListener { - public: - virtual ~SizeListener() {} - /** This member function is called when the size of the final image has been changed - * @param w is the width of the final image (without cropping) - * @param h is the height of the final image (without cropping) - * @param ow is the width of the final image (without resizing and cropping) - * @param oh is the height of the final image (without resizing and cropping) */ - virtual void sizeChanged (int w, int h, int ow, int oh) {} - }; +/** When the preview image is ready for display during staged processing (thus the changes have been updated), + * the staged processor notifies the listener class implementing a PreviewImageListener. + * It is important to note that the file passed to the listener can be used in a shared manner (copying it is not + * needed) as long as the mutex corresponding to the image is used every time the image is accessed. + * If the scale of the preview image is >1, no sharpening, no denoising and no cropping is applied, and + * the transform operations (rotate, c/a, vignetting correction) are performed using a faster less quality algorithm. + * The image you get with this listener is created to display on the monitor (monitor profile has been already applied). */ +class PreviewImageListener +{ +public: + virtual ~PreviewImageListener() {} + /** With this member function the staged processor notifies the listener that it allocated a new + * image to store the end result of the processing. It can be used in a shared manner. + * @param img is a pointer to the image + * @param scale describes the current scaling applied compared to the 100% size (preview scale) + * @param cp holds the coordinates of the current crop rectangle */ + virtual void setImage (IImage8* img, double scale, procparams::CropParams cp) {} + /** With this member function the staged processor notifies the listener that the image passed as parameter + * will be deleted, and no longer used to store the preview image. + * @param img the pointer to the image to be destroyed. The listener has to free the image! */ + virtual void delImage (IImage8* img) {} + /** With this member function the staged processor notifies the listener that the preview image has been updated. + * @param cp holds the coordinates of the current crop rectangle */ + virtual void imageReady (procparams::CropParams cp) {} +}; - /** This listener is used when the histogram of the final image has changed. */ - class HistogramListener { - public: - virtual ~HistogramListener() {} - /** This member function is called when the histogram of the final image has changed. - * @param histRed is the array of size 256 containing the histogram of the red channel - * @param histGreen is the array of size 256 containing the histogram of the green channel - * @param histBlue is the array of size 256 containing the histogram of the blue channel - * @param histLuma is the array of size 256 containing the histogram of the luminance channel - * other for curves backgrounds, histRAW is RAW without colors */ - virtual void histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve,LUTu & histLLCurve, */LUTu & histLCAM, LUTu & histCCAM, - LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw, LUTu & histChroma) {} - }; +/** When the detailed crop image is ready for display during staged processing (thus the changes have been updated), + * the staged processor notifies the listener class implementing a DetailedCropListener. + * It is important to note that the file passed to the listener can not be used in a shared manner, the class + * implementing this interface has to store a copy of it. */ +class DetailedCropListener +{ +public: + virtual ~DetailedCropListener() {} + /** With this member function the staged processor notifies the listener that the detailed crop image has been updated. + * @param img is a pointer to the detailed crop image */ + virtual void setDetailedCrop (IImage8* img, IImage8* imgtrue, procparams::ColorManagementParams cmp, + procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip) {} + virtual bool getWindow (int& cx, int& cy, int& cw, int& ch, int& skip) + { + return false; + } + // virtual void setPosition (int x, int y, bool update=true) {} - /** This listener is used when the auto exposure has been recomputed (e.g. when the clipping ratio changed). */ - class AutoExpListener { - public: - virtual ~AutoExpListener() {} - /** This member function is called when the auto exposure has been recomputed. - * @param brightness is the new brightness value (in logarithmic scale) - * @param bright is the new ... - * @param black is the new black level (measured in absolute pixel data) - * @param contrast is the new contrast values - * @param hlcompr is the new highlight recovery amount - * @param hlcomprthresh is the new threshold for hlcompr - * @param hlrecons set to true if HighLight Reconstruction is enabled */ - virtual void autoExpChanged (double brightness, int bright, int contrast, int black, int hlcompr, int hlcomprthresh, bool hlrecons) {} - }; +}; - class AutoCamListener { - public : - virtual ~AutoCamListener() {} - virtual void autoCamChanged (double ccam) {} - virtual void adapCamChanged (double cadap) {} - }; - - class AutoChromaListener { - public : - virtual ~AutoChromaListener() {} - virtual void chromaChanged (double autchroma, double autred, double autblue) {} - virtual void noiseChanged (double nresid, double highresid) {} - virtual void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) {} - - }; +/** This listener is used when the full size of the final image has been changed (e.g. rotated by 90 deg.) */ +class SizeListener +{ +public: + virtual ~SizeListener() {} + /** This member function is called when the size of the final image has been changed + * @param w is the width of the final image (without cropping) + * @param h is the height of the final image (without cropping) + * @param ow is the width of the final image (without resizing and cropping) + * @param oh is the height of the final image (without resizing and cropping) */ + virtual void sizeChanged (int w, int h, int ow, int oh) {} +}; - class AutoColorTonListener { - public : - virtual ~AutoColorTonListener() {} - virtual void autoColorTonChanged (int bwct, int satthres, int satprot) {} - }; - - class AutoBWListener { - public : - virtual ~AutoBWListener() {} - virtual void BWChanged (double redbw, double greenbw, double bluebw) {} - - }; +/** This listener is used when the histogram of the final image has changed. */ +class HistogramListener +{ +public: + virtual ~HistogramListener() {} + /** This member function is called when the histogram of the final image has changed. + * @param histRed is the array of size 256 containing the histogram of the red channel + * @param histGreen is the array of size 256 containing the histogram of the green channel + * @param histBlue is the array of size 256 containing the histogram of the blue channel + * @param histLuma is the array of size 256 containing the histogram of the luminance channel + * other for curves backgrounds, histRAW is RAW without colors */ + virtual void histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve,LUTu & histLLCurve, */LUTu & histLCAM, LUTu & histCCAM, + LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw, LUTu & histChroma) {} +}; - class WaveletListener { - public : - virtual ~WaveletListener() {} - virtual void wavChanged (double nlevel) {} - - }; - +/** This listener is used when the auto exposure has been recomputed (e.g. when the clipping ratio changed). */ +class AutoExpListener +{ +public: + virtual ~AutoExpListener() {} + /** This member function is called when the auto exposure has been recomputed. + * @param brightness is the new brightness value (in logarithmic scale) + * @param bright is the new ... + * @param black is the new black level (measured in absolute pixel data) + * @param contrast is the new contrast values + * @param hlcompr is the new highlight recovery amount + * @param hlcomprthresh is the new threshold for hlcompr + * @param hlrecons set to true if HighLight Reconstruction is enabled */ + virtual void autoExpChanged (double brightness, int bright, int contrast, int black, int hlcompr, int hlcomprthresh, bool hlrecons) {} +}; - /** This class represents a detailed part of the image (looking through a kind of window). - * It can be created and destroyed with the appropriate members of StagedImageProcessor. - * Several crops can be assigned to the same image. */ - class DetailedCrop { - public: - virtual ~DetailedCrop() {} - /** Sets the window defining the crop. */ - virtual void setWindow (int cx, int cy, int cw, int ch, int skip) {} +class AutoCamListener +{ +public : + virtual ~AutoCamListener() {} + virtual void autoCamChanged (double ccam) {} + virtual void adapCamChanged (double cadap) {} +}; - /** First try to update (threadless update). If it returns false, make a full update */ - virtual bool tryUpdate () { return false; } - /** Perform a full recalculation of the part of the image corresponding to the crop. */ - virtual void fullUpdate () {} - /** Sets the listener of the crop. */ - virtual void setListener (DetailedCropListener* il) {} - /** Destroys the crop. */ - virtual void destroy () {} - }; +class AutoChromaListener +{ +public : + virtual ~AutoChromaListener() {} + virtual void chromaChanged (double autchroma, double autred, double autblue) {} + virtual void noiseChanged (double nresid, double highresid) {} + virtual void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) {} - /** This is a staged, cached image processing manager with partial image update support. */ - class StagedImageProcessor { +}; - public: - /** Returns the inital image corresponding to the image processor. - * @return the inital image corresponding to the image processor */ - virtual InitialImage* getInitialImage () =0; - /** Returns the current processing parameters. - * @param dst is the location where the image processing parameters are copied (it is assumed that the memory is allocated by the caller) */ - virtual void getParams (procparams::ProcParams* dst) =0; - /** An essential member function. Call this when a setting has been changed. This function returns a pointer to the - * processing parameters, that you have to update to reflect the changed situation. When ready, call the paramsUpdateReady - * function to start the image update. - * @param change is the ID of the changed setting */ - virtual procparams::ProcParams* beginUpdateParams () =0; - /** An essential member function. This indicates that you are ready with the update of the processing parameters you got - * with the beginUpdateParams call, so the image can be updated. This function returns immediately. - * The image update starts immediately in the background. If it is ready, the result is passed to a PreviewImageListener - * and to a DetailedCropListener (if enabled). */ - virtual void endUpdateParams (ProcEvent change) =0; - virtual void endUpdateParams (int changeFlags) =0; - // Starts a minimal update - virtual void startProcessing(int changeCode) =0; - /** Stops image processing. When it returns, the image processing is already stopped. */ - virtual void stopProcessing () =0; - /** Sets the scale of the preview image. The larger the number is, the faster the image updates are (typical values are 4-5). - * @param scale is the scale of the preview image */ - virtual void setPreviewScale (int scale) =0; - /** Returns the scale of the preview image. - * @return the current scale of the preview image */ - virtual int getPreviewScale () =0; - /** Returns the full width of the resulting image (in 1:1 scale). - * @return the width of the final image */ - virtual int getFullWidth () =0; - /** Returns the full height of the resulting image (in 1:1 scale). - * @return the height of the final image */ - virtual int getFullHeight () =0; - /** Returns the width of the preview image. - * @return the width of the preview image */ - virtual int getPreviewWidth () =0; - /** Returns the height of the preview image. - * @return the height of the preview image */ - virtual int getPreviewHeight () =0; +class AutoColorTonListener +{ +public : + virtual ~AutoColorTonListener() {} + virtual void autoColorTonChanged (int bwct, int satthres, int satprot) {} +}; - virtual bool updateTryLock() = 0; +class AutoBWListener +{ +public : + virtual ~AutoBWListener() {} + virtual void BWChanged (double redbw, double greenbw, double bluebw) {} - virtual void updateUnLock() = 0; +}; - /** Creates and returns a Crop instance that acts as a window on the image - * @param editDataProvider pointer to the EditDataProvider that communicates with the EditSubscriber - * @return a pointer to the Crop object that handles the image data trough its own pipeline */ - virtual DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) =0; +class WaveletListener +{ +public : + virtual ~WaveletListener() {} + virtual void wavChanged (double nlevel) {} - virtual bool getAutoWB (double& temp, double& green, double equal) =0; - virtual void getCamWB (double& temp, double& green) =0; - virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) =0; - virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) =0; - - virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) =0; - - virtual void setProgressListener (ProgressListener* l) =0; - virtual void setSizeListener (SizeListener* l) =0; - virtual void delSizeListener (SizeListener* l) =0; - virtual void setAutoExpListener (AutoExpListener* l) =0; - virtual void setHistogramListener (HistogramListener *l) =0; - virtual void setPreviewImageListener (PreviewImageListener* l) =0; - virtual void setAutoCamListener (AutoCamListener* l) =0; - virtual void setAutoBWListener (AutoBWListener* l) =0; - virtual void setAutoColorTonListener (AutoColorTonListener* l) =0; - virtual void setAutoChromaListener (AutoChromaListener* l) =0; - virtual void setWaveletListener (WaveletListener* l) =0; - - virtual ~StagedImageProcessor () {} - - /** Returns a staged, cached image processing manager supporting partial updates - * @param initialImage is a loaded and pre-processed initial image - * @return the staged image processing manager */ - static StagedImageProcessor* create (InitialImage* initialImage); - static void destroy (StagedImageProcessor* sip); - }; +}; -/** +/** This class represents a detailed part of the image (looking through a kind of window). + * It can be created and destroyed with the appropriate members of StagedImageProcessor. + * Several crops can be assigned to the same image. */ +class DetailedCrop +{ +public: + virtual ~DetailedCrop() {} + /** Sets the window defining the crop. */ + virtual void setWindow (int cx, int cy, int cw, int ch, int skip) {} + + /** First try to update (threadless update). If it returns false, make a full update */ + virtual bool tryUpdate () + { + return false; + } + /** Perform a full recalculation of the part of the image corresponding to the crop. */ + virtual void fullUpdate () {} + /** Sets the listener of the crop. */ + virtual void setListener (DetailedCropListener* il) {} + /** Destroys the crop. */ + virtual void destroy () {} +}; + +/** This is a staged, cached image processing manager with partial image update support. */ +class StagedImageProcessor +{ + +public: + /** Returns the inital image corresponding to the image processor. + * @return the inital image corresponding to the image processor */ + virtual InitialImage* getInitialImage () = 0; + /** Returns the current processing parameters. + * @param dst is the location where the image processing parameters are copied (it is assumed that the memory is allocated by the caller) */ + virtual void getParams (procparams::ProcParams* dst) = 0; + /** An essential member function. Call this when a setting has been changed. This function returns a pointer to the + * processing parameters, that you have to update to reflect the changed situation. When ready, call the paramsUpdateReady + * function to start the image update. + * @param change is the ID of the changed setting */ + virtual procparams::ProcParams* beginUpdateParams () = 0; + /** An essential member function. This indicates that you are ready with the update of the processing parameters you got + * with the beginUpdateParams call, so the image can be updated. This function returns immediately. + * The image update starts immediately in the background. If it is ready, the result is passed to a PreviewImageListener + * and to a DetailedCropListener (if enabled). */ + virtual void endUpdateParams (ProcEvent change) = 0; + virtual void endUpdateParams (int changeFlags) = 0; + // Starts a minimal update + virtual void startProcessing(int changeCode) = 0; + /** Stops image processing. When it returns, the image processing is already stopped. */ + virtual void stopProcessing () = 0; + /** Sets the scale of the preview image. The larger the number is, the faster the image updates are (typical values are 4-5). + * @param scale is the scale of the preview image */ + virtual void setPreviewScale (int scale) = 0; + /** Returns the scale of the preview image. + * @return the current scale of the preview image */ + virtual int getPreviewScale () = 0; + /** Returns the full width of the resulting image (in 1:1 scale). + * @return the width of the final image */ + virtual int getFullWidth () = 0; + /** Returns the full height of the resulting image (in 1:1 scale). + * @return the height of the final image */ + virtual int getFullHeight () = 0; + /** Returns the width of the preview image. + * @return the width of the preview image */ + virtual int getPreviewWidth () = 0; + /** Returns the height of the preview image. + * @return the height of the preview image */ + virtual int getPreviewHeight () = 0; + + virtual bool updateTryLock() = 0; + + virtual void updateUnLock() = 0; + + /** Creates and returns a Crop instance that acts as a window on the image + * @param editDataProvider pointer to the EditDataProvider that communicates with the EditSubscriber + * @return a pointer to the Crop object that handles the image data trough its own pipeline */ + virtual DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) = 0; + + virtual bool getAutoWB (double& temp, double& green, double equal) = 0; + virtual void getCamWB (double& temp, double& green) = 0; + virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0; + virtual void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) = 0; + + virtual void saveInputICCReference (const Glib::ustring& fname, bool apply_wb) = 0; + + virtual void setProgressListener (ProgressListener* l) = 0; + virtual void setSizeListener (SizeListener* l) = 0; + virtual void delSizeListener (SizeListener* l) = 0; + virtual void setAutoExpListener (AutoExpListener* l) = 0; + virtual void setHistogramListener (HistogramListener *l) = 0; + virtual void setPreviewImageListener (PreviewImageListener* l) = 0; + virtual void setAutoCamListener (AutoCamListener* l) = 0; + virtual void setAutoBWListener (AutoBWListener* l) = 0; + virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0; + virtual void setAutoChromaListener (AutoChromaListener* l) = 0; + virtual void setWaveletListener (WaveletListener* l) = 0; + + virtual ~StagedImageProcessor () {} + + /** Returns a staged, cached image processing manager supporting partial updates + * @param initialImage is a loaded and pre-processed initial image + * @return the staged image processing manager */ + static StagedImageProcessor* create (InitialImage* initialImage); + static void destroy (StagedImageProcessor* sip); +}; + + +/** * @brief Initializes the RT engine * @param s is a struct of basic settings * @param baseDir base directory of RT's installation dir * @param userSettingsDir RT's base directory in the user's settings dir */ - int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir); +int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir); /** Cleanup the RT engine (static variables) */ - void cleanup (); +void cleanup (); /** Returns the available working profile names * @return a vector of the available working profile names */ - std::vector getWorkingProfiles (); +std::vector getWorkingProfiles (); /** Returns the available output gammas * @return a vector of the available gamma names */ - std::vector getGamma (); +std::vector getGamma (); - /** This class holds all the necessary informations to accomplish the full processing of the image */ - class ProcessingJob { +/** This class holds all the necessary informations to accomplish the full processing of the image */ +class ProcessingJob +{ - public: +public: /** Creates a processing job from a file name. This function always succeeds. It only stores the data into the ProcessingJob class, it does not load - * the image thus it returns immediately. + * the image thus it returns immediately. * @param fname the name of the file * @param isRaw shall be true if it is a raw file * @param pparams is a struct containing the processing parameters * @return an object containing the data above. It can be passed to the functions that do the actual image processing. */ - static ProcessingJob* create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams); - + static ProcessingJob* create (const Glib::ustring& fname, bool isRaw, const procparams::ProcParams& pparams); + /** Creates a processing job from a file name. This function always succeeds. It only stores the data into the ProcessingJob class, it does not load * the image thus it returns immediately. This function increases the reference count of the initialImage. If you decide not the process the image you * have to cancel it by calling the member function void cancel(). If the image is processed the reference count of initialImage is decreased automatically, thus the ProcessingJob * instance gets invalid. You can not use a ProcessingJob instance to process an image twice. * @param initialImage is a loaded and pre-processed initial image * @param pparams is a struct containing the processing parameters - * @return an object containing the data above. It can be passed to the functions that do the actual image processing. */ - static ProcessingJob* create (InitialImage* initialImage, const procparams::ProcParams& pparams); + * @return an object containing the data above. It can be passed to the functions that do the actual image processing. */ + static ProcessingJob* create (InitialImage* initialImage, const procparams::ProcParams& pparams); /** Cancels and destroys a processing job. The reference count of the corresponding initialImage (if any) is decreased. After the call of this function the ProcessingJob instance - * gets invalid, you must not use it any more. Dont call this function while the job is being processed. + * gets invalid, you must not use it any more. Dont call this function while the job is being processed. * @param job is the job to destroy */ - static void destroy (ProcessingJob* job); - }; + static void destroy (ProcessingJob* job); +}; /** This function performs all the image processinf steps corresponding to the given ProcessingJob. It returns when it is ready, so it can be slow. * The ProcessingJob passed becomes invalid, you can not use it any more. - * @param job the ProcessingJob to cancel. - * @param errorCode is the error code if an error occured (e.g. the input image could not be loaded etc.) + * @param job the ProcessingJob to cancel. + * @param errorCode is the error code if an error occured (e.g. the input image could not be loaded etc.) * @param pl is an optional ProgressListener if you want to keep track of the progress * @param tunnelMetaData tunnels IPTC and XMP to output without change - * @return the resulting image, with the output profile applied, exif and iptc data set. You have to save it or you can access the pixel data directly. */ - IImage16* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = NULL, bool tunnelMetaData=false, bool flush = false); + * @return the resulting image, with the output profile applied, exif and iptc data set. You have to save it or you can access the pixel data directly. */ +IImage16* processImage (ProcessingJob* job, int& errorCode, ProgressListener* pl = NULL, bool tunnelMetaData = false, bool flush = false); /** This class is used to control the batch processing. The class implementing this interface will be called when the full processing of an * image is ready and the next job to process is needed. */ - class BatchProcessingListener : public ProgressListener { - public: - /** This function is called when an image gets ready during the batch processing. It has to return with the next job, or with NULL if - * there is no jobs left. - * @param img is the result of the last ProcessingJob - * @return the next ProcessingJob to process */ - virtual ProcessingJob* imageReady (IImage16* img) =0; - virtual void error(Glib::ustring message) =0; - }; +class BatchProcessingListener : public ProgressListener +{ +public: + /** This function is called when an image gets ready during the batch processing. It has to return with the next job, or with NULL if + * there is no jobs left. + * @param img is the result of the last ProcessingJob + * @return the next ProcessingJob to process */ + virtual ProcessingJob* imageReady (IImage16* img) = 0; + virtual void error(Glib::ustring message) = 0; +}; /** This function performs all the image processinf steps corresponding to the given ProcessingJob. It runs in the background, thus it returns immediately, - * When it finishes, it calls the BatchProcessingListener with the resulting image and asks for the next job. It the listener gives a new job, it goes on + * When it finishes, it calls the BatchProcessingListener with the resulting image and asks for the next job. It the listener gives a new job, it goes on * with processing. If no new job is given, it finishes. * The ProcessingJob passed becomes invalid, you can not use it any more. - * @param job the ProcessingJob to cancel. + * @param job the ProcessingJob to cancel. * @param bpl is the BatchProcessingListener that is called when the image is ready or the next job is needed. It also acts as a ProgressListener. - * @param tunnelMetaData tunnels IPTC and XMP to output without change */ - void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData); + * @param tunnelMetaData tunnels IPTC and XMP to output without change */ +void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData); - extern MyMutex* lcmsMutex; +extern MyMutex* lcmsMutex; } #endif diff --git a/rtengine/rtetest.cc b/rtengine/rtetest.cc index 4c3046685..5d2dbfddc 100644 --- a/rtengine/rtetest.cc +++ b/rtengine/rtetest.cc @@ -7,7 +7,7 @@ * 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 @@ -17,24 +17,28 @@ * along with RawTherapee. If not, see . */ #include "rtengine.h" -#include +#include //#include #include -class PListener : public rtengine::ProgressListener { - - public: - void setProgressStr (Glib::ustring str) { - std::cout << str << std::endl; - } - void setProgress (double p) { - std::cout << p << std::endl; - } +class PListener : public rtengine::ProgressListener +{ + +public: + void setProgressStr (Glib::ustring str) + { + std::cout << str << std::endl; + } + void setProgress (double p) + { + std::cout << p << std::endl; + } }; -int main (int argc, char* argv[]) { +int main (int argc, char* argv[]) +{ - if (argc<4) { + if (argc < 4) { std::cout << "Usage: rtcmd " << std::endl; exit(1); } @@ -47,14 +51,17 @@ int main (int argc, char* argv[]) { s.monitorProfile = ""; Glib::thread_init (); - rtengine::init (s,""); + rtengine::init (s, ""); PListener pl; rtengine::InitialImage* ii; int errorCode; ii = rtengine::InitialImage::load (argv[1], true, errorCode, &pl); - if (!ii) + + if (!ii) { ii = rtengine::InitialImage::load (argv[1], false, errorCode, &pl); + } + if (!ii) { std::cout << "Input file not supported." << std::endl; exit(2); diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 49bf12d9b..5811d01f5 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -7,7 +7,7 @@ * 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 @@ -24,7 +24,7 @@ #include "curves.h" #include #include "improcfun.h" -#include "colortemp.h" +#include "colortemp.h" #include "mytime.h" #include "utils.h" #include "iccstore.h" @@ -44,27 +44,31 @@ extern Options options; -namespace rtengine { +namespace rtengine +{ using namespace procparams; -Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode) { +Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode) +{ StdImageSource imgSrc; + if (imgSrc.load(fname)) { return NULL; } ImageIO* img = imgSrc.getImageIO(); - + Thumbnail* tpp = new Thumbnail (); unsigned char* data; img->getEmbeddedProfileData (tpp->embProfileLength, data); + if (data && tpp->embProfileLength) { tpp->embProfileData = new unsigned char [tpp->embProfileLength]; memcpy (tpp->embProfileData, data, tpp->embProfileLength); } - + tpp->scaleForSave = 8192; tpp->defGain = 1.0; tpp->gammaCorrected = false; @@ -79,22 +83,22 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, w = img->width; h = img->height; tpp->scale = 1.; - } - else { - if (fixwh==1) { + } else { + if (fixwh == 1) { w = h * img->width / img->height; tpp->scale = (double)img->height / h; - } - else { + } else { h = w * img->height / img->width; tpp->scale = (double)img->width / w; } } + // bilinear interpolation if (tpp->thumbImg) { delete tpp->thumbImg; tpp->thumbImg = NULL; } + if (inspectorMode) { // we want an Image8 if (img->getType() == rtengine::sImage8) { @@ -103,19 +107,17 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, Image8 *thImg = new Image8 (w, h); srcImg->copyData(thImg); tpp->thumbImg = thImg; - } - else { + } else { // copy the image with a conversion tpp->thumbImg = resizeTo(w, h, TI_Bilinear, img); } - } - else { + } else { // we want the same image type than the source file tpp->thumbImg = resizeToSameType(w, h, TI_Bilinear, img); // histogram computation tpp->aeHistCompression = 3; - tpp->aeHistogram(65536>>tpp->aeHistCompression); + tpp->aeHistogram(65536 >> tpp->aeHistCompression); double avg_r = 0; double avg_g = 0; @@ -125,25 +127,22 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, if (img->getType() == rtengine::sImage8) { Image8 *image = static_cast(img); image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression); - } - else if (img->getType() == sImage16) { + } else if (img->getType() == sImage16) { Image16 *image = static_cast(img); image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression); - } - else if (img->getType() == sImagefloat) { + } else if (img->getType() == sImagefloat) { Imagefloat *image = static_cast(img); image->computeHistogramAutoWB(avg_r, avg_g, avg_b, n, tpp->aeHistogram, tpp->aeHistCompression); - } - else { + } else { printf("loadFromImage: Unsupported image type \"%s\"!\n", img->getType()); } - if (n>0) { + if (n > 0) { ColorTemp cTemp; - tpp->redAWBMul = avg_r/double(n); - tpp->greenAWBMul = avg_g/double(n); - tpp->blueAWBMul = avg_b/double(n); + tpp->redAWBMul = avg_r / double(n); + tpp->greenAWBMul = avg_g / double(n); + tpp->blueAWBMul = avg_b / double(n); tpp->wbEqual = wbEq; cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen); @@ -157,10 +156,10 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode) { - RawImage *ri= new RawImage(fname); - int r = ri->loadRaw(false,false); - if( r ) - { + RawImage *ri = new RawImage(fname); + int r = ri->loadRaw(false, false); + + if( r ) { delete ri; return NULL; } @@ -178,23 +177,19 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL int err = 1; // see if it is something we support - if ( ri->is_supportedThumb() ) - { - const char* data((const char*)fdata(ri->get_thumbOffset(),ri->get_file())); - if ( (unsigned char)data[1] == 0xd8 ) - { - err = img->loadJPEGFromMemory(data,ri->get_thumbLength()); - } - else - { - err = img->loadPPMFromMemory(data,ri->get_thumbWidth(),ri->get_thumbHeight(),ri->get_thumbSwap(),ri->get_thumbBPS()); + if ( ri->is_supportedThumb() ) { + const char* data((const char*)fdata(ri->get_thumbOffset(), ri->get_file())); + + if ( (unsigned char)data[1] == 0xd8 ) { + err = img->loadJPEGFromMemory(data, ri->get_thumbLength()); + } else { + err = img->loadPPMFromMemory(data, ri->get_thumbWidth(), ri->get_thumbHeight(), ri->get_thumbSwap(), ri->get_thumbBPS()); } } // did we succeed? - if ( err ) - { - printf("Could not extract thumb from %s\n",fname.data()); + if ( err ) { + printf("Could not extract thumb from %s\n", fname.data()); delete img; delete ri; return NULL; @@ -213,13 +208,11 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL w = img->width; h = img->height; tpp->scale = 1.; - } - else { - if (fixwh==1) { + } else { + if (fixwh == 1) { w = h * img->width / img->height; tpp->scale = (double)img->height / h; - } - else { + } else { h = w * img->height / img->width; tpp->scale = (double)img->width / w; } @@ -229,18 +222,22 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL delete tpp->thumbImg; tpp->thumbImg = NULL; } + if (inspectorMode) { tpp->thumbImg = img; - } - else { + } else { tpp->thumbImg = resizeTo(w, h, TI_Nearest, img); delete img; } if (rotate && ri->get_rotateDegree() > 0) { std::string fname = ri->get_filename(); - std::string suffix = fname.length() > 4 ? fname.substr(fname.length()-3) : ""; - for (int i = 0; i < suffix.length(); i++) suffix[i] = std::tolower(suffix[i]); + std::string suffix = fname.length() > 4 ? fname.substr(fname.length() - 3) : ""; + + for (int i = 0; i < suffix.length(); i++) { + suffix[i] = std::tolower(suffix[i]); + } + // Leaf .mos, Mamiya .mef and Phase One .iiq files have thumbnails already rotated. if (suffix != "mos" && suffix != "mef" && suffix != "iiq") { tpp->thumbImg->rotate(ri->get_rotateDegree()); @@ -250,8 +247,9 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL } } - if (!inspectorMode) + if (!inspectorMode) { tpp->init (); + } delete ri; @@ -259,378 +257,464 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL } #define FISRED(filter,row,col) \ - ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==0 || !filter) + ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==0 || !filter) #define FISGREEN(filter,row,col) \ - ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter) + ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter) #define FISBLUE(filter,row,col) \ - ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==2 || !filter) + ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==2 || !filter) RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname) { - RawMetaDataLocation rml; - rml.exifBase = -1; - rml.ciffBase = -1; - rml.ciffLength = -1; + RawMetaDataLocation rml; + rml.exifBase = -1; + rml.ciffBase = -1; + rml.ciffLength = -1; - RawImage ri(fname); - int r = ri.loadRaw(false); - if( !r ){ - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - } - return rml; + RawImage ri(fname); + int r = ri.loadRaw(false); + + if( !r ) { + rml.exifBase = ri.get_exifBase(); + rml.ciffBase = ri.get_ciffBase(); + rml.ciffLength = ri.get_ciffLen(); + } + + return rml; } Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate) { - RawImage *ri= new RawImage (fname); - int r = ri->loadRaw(1,0); - if( r ){ - delete ri; - return NULL; - } - int width = ri->get_width(); - int height = ri->get_height(); - rtengine::Thumbnail* tpp = new rtengine::Thumbnail; + RawImage *ri = new RawImage (fname); + int r = ri->loadRaw(1, 0); - tpp->isRaw = true; - tpp->embProfile = NULL; - tpp->embProfileData = NULL; - tpp->embProfileLength = ri->get_profileLen(); - if (ri->get_profileLen()) - tpp->embProfile = cmsOpenProfileFromMem(ri->get_profile(), - ri->get_profileLen()); //\ TODO check if mutex is needed + if( r ) { + delete ri; + return NULL; + } - tpp->redMultiplier = ri->get_pre_mul(0); - tpp->greenMultiplier = ri->get_pre_mul(1); - tpp->blueMultiplier = ri->get_pre_mul(2); + int width = ri->get_width(); + int height = ri->get_height(); + rtengine::Thumbnail* tpp = new rtengine::Thumbnail; - ri->scale_colors(); - ri->pre_interpolate(); + tpp->isRaw = true; + tpp->embProfile = NULL; + tpp->embProfileData = NULL; + tpp->embProfileLength = ri->get_profileLen(); - rml.exifBase = ri->get_exifBase(); - rml.ciffBase = ri->get_ciffBase(); - rml.ciffLength = ri->get_ciffLen(); + if (ri->get_profileLen()) + tpp->embProfile = cmsOpenProfileFromMem(ri->get_profile(), + ri->get_profileLen()); //\ TODO check if mutex is needed - tpp->camwbRed = tpp->redMultiplier / ri->get_pre_mul(0); - tpp->camwbGreen = tpp->greenMultiplier / ri->get_pre_mul(1); - tpp->camwbBlue = tpp->blueMultiplier / ri->get_pre_mul(2); - tpp->defGain= 1.0/ min(ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2)); - tpp->gammaCorrected = true; + tpp->redMultiplier = ri->get_pre_mul(0); + tpp->greenMultiplier = ri->get_pre_mul(1); + tpp->blueMultiplier = ri->get_pre_mul(2); - unsigned filter = ri->get_filters(); - int firstgreen = 1; - // locate first green location in the first row - if(ri->getSensorType()==ST_BAYER) - while (!FISGREEN(filter,1,firstgreen)) - firstgreen++; + ri->scale_colors(); + ri->pre_interpolate(); - int skip = 1; - if (ri->get_FujiWidth() != 0){ - if (fixwh == 1) // fix height, scale width - skip = ((ri->get_height() - ri->get_FujiWidth()) / sqrt(0.5) - firstgreen - 1) / h; - else - skip = (ri->get_FujiWidth()/sqrt(0.5) - firstgreen - 1) / w; - }else{ - if (fixwh == 1) // fix height, scale width - skip = (ri->get_height() - firstgreen - 1) / h; - else - skip = (ri->get_width() - firstgreen - 1) / w; - } - if (skip % 2) - skip--; - if (skip < 1) - skip = 1; + rml.exifBase = ri->get_exifBase(); + rml.ciffBase = ri->get_ciffBase(); + rml.ciffLength = ri->get_ciffLen(); - int hskip = skip, vskip = skip; - if (!ri->get_model().compare("D1X")) - hskip *= 2; + tpp->camwbRed = tpp->redMultiplier / ri->get_pre_mul(0); + tpp->camwbGreen = tpp->greenMultiplier / ri->get_pre_mul(1); + tpp->camwbBlue = tpp->blueMultiplier / ri->get_pre_mul(2); + tpp->defGain = 1.0 / min(ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2)); + tpp->gammaCorrected = true; - int rofs = 0; - int tmpw = (width - 2) / hskip; - int tmph = (height - 2) / vskip; + unsigned filter = ri->get_filters(); + int firstgreen = 1; - DCraw::dcrawImage_t image = ri->get_image(); + // locate first green location in the first row + if(ri->getSensorType() == ST_BAYER) + while (!FISGREEN(filter, 1, firstgreen)) { + firstgreen++; + } - Imagefloat* tmpImg = new Imagefloat(tmpw, tmph); - if (ri->getSensorType()==ST_BAYER) { - // demosaicing! (sort of) - for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { - rofs = row * width; - for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col+= hskip, x++) { - int ofs = rofs + col; - int g = image[ofs][1]; - int r, b; - if (FISRED(filter,row,col+1)) { - r = (image[ofs + 1 ][0] + image[ofs - 1 ][0]) >> 1; - b = (image[ofs + width][2] + image[ofs - width][2]) >> 1; - } else { - b = (image[ofs + 1 ][2] + image[ofs - 1 ][2]) >> 1; - r = (image[ofs + width][0] + image[ofs - width][0]) >> 1; - } - tmpImg->r(y,x) = r; - tmpImg->g(y,x) = g; - tmpImg->b(y,x) = b; - } - } - } else if (ri->get_colors() == 1) { - for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { - rofs = row * width; - for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col - += hskip, x++) { - int ofs = rofs + col; - tmpImg->r(y,x) = tmpImg->g(y,x) = tmpImg->b(y,x) = image[ofs][0]; - } - } - } else { - if(ri->getSensorType()==ST_FUJI_XTRANS) { - for( int row=1, y = 0; row < height-1 && y < tmph; row+=vskip, y++) { - rofs = row * width; - for( int col=1, x = 0; col < width-1 && x < tmpw; col+=hskip, x++ ) { - int ofs = rofs + col; - float sum[3] = {}; - int c; - for(int v=-1;v<=1;v++) { - for(int h=-1;h<=1;h++) { - c = ri->XTRANSFC(row+v,col+h); - sum[c] += image[ofs + v*width + h][c]; - } - } - c = ri->XTRANSFC(row,col); + int skip = 1; - switch (c) { - case 0: tmpImg->r(y,x) = image[ofs][0]; tmpImg->g(y,x) = sum[1] / 5.f; tmpImg->b(y,x) = sum[2] / 3.f; break; - case 1: tmpImg->r(y,x) = sum[0] / 2.f; tmpImg->g(y,x) = image[ofs][1]; tmpImg->b(y,x) = sum[2] / 2.f; break; - case 2: tmpImg->r(y,x) = sum[0] / 3.f; tmpImg->g(y,x) = sum[1] / 5.f; tmpImg->b(y,x) = image[ofs][2]; break; - } - } - } - } else { - int iwidth = ri->get_iwidth(); - int iheight = ri->get_iheight(); - int left_margin = ri->get_leftmargin(); - firstgreen += left_margin; - int top_margin = ri->get_topmargin(); - for (int row = 1 + top_margin, y = 0; row < iheight + top_margin - 1 && y < tmph; row += vskip, y++) { - rofs = row * iwidth; - for (int col = firstgreen, x = 0; col < iwidth + left_margin - 1 && x < tmpw; col += hskip, x++) { - int ofs = rofs + col; - tmpImg->r(y,x) = image[ofs][0]; - tmpImg->g(y,x) = image[ofs][1]; - tmpImg->b(y,x) = image[ofs][2]; - } - } - } - } + if (ri->get_FujiWidth() != 0) { + if (fixwh == 1) { // fix height, scale width + skip = ((ri->get_height() - ri->get_FujiWidth()) / sqrt(0.5) - firstgreen - 1) / h; + } else { + skip = (ri->get_FujiWidth() / sqrt(0.5) - firstgreen - 1) / w; + } + } else { + if (fixwh == 1) { // fix height, scale width + skip = (ri->get_height() - firstgreen - 1) / h; + } else { + skip = (ri->get_width() - firstgreen - 1) / w; + } + } - if (ri->get_FujiWidth() != 0) { - int fw = ri->get_FujiWidth() / hskip; - double step = sqrt(0.5); - int wide = fw / step; - int high = (tmph - fw) / step; - Imagefloat* fImg = new Imagefloat(wide, high); - float r, c; + if (skip % 2) { + skip--; + } - for (int row = 0; row < high; row++) - for (int col = 0; col < wide; col++) { - unsigned ur = r = fw + (row - col) * step; - unsigned uc = c = (row + col) * step; - if (ur > tmph - 2 || uc > tmpw - 2) - continue; - double fr = r - ur; - double fc = c - uc; - fImg->r(row,col) = (tmpImg->r(ur,uc)*(1-fc) + tmpImg->r(ur,uc + 1)*fc) * (1-fr) + (tmpImg->r(ur + 1,uc)*(1-fc) + tmpImg->r(ur + 1,uc + 1)*fc) * fr; - fImg->g(row,col) = (tmpImg->g(ur,uc)*(1-fc) + tmpImg->g(ur,uc + 1)*fc) * (1-fr) + (tmpImg->g(ur + 1,uc)*(1-fc) + tmpImg->g(ur + 1,uc + 1)*fc) * fr; - fImg->b(row,col) = (tmpImg->b(ur,uc)*(1-fc) + tmpImg->b(ur,uc + 1)*fc) * (1-fr) + (tmpImg->b(ur + 1,uc)*(1-fc) + tmpImg->b(ur + 1,uc + 1)*fc) * fr; - } - delete tmpImg; - tmpImg = fImg; - tmpw = wide; - tmph = high; - } + if (skip < 1) { + skip = 1; + } - if (fixwh == 1) // fix height, scale width - w = tmpw * h / tmph; - else - h = tmph * w / tmpw; - - if (tpp->thumbImg) delete tpp->thumbImg; tpp->thumbImg = NULL; + int hskip = skip, vskip = skip; + + if (!ri->get_model().compare("D1X")) { + hskip *= 2; + } + + int rofs = 0; + int tmpw = (width - 2) / hskip; + int tmph = (height - 2) / vskip; + + DCraw::dcrawImage_t image = ri->get_image(); + + Imagefloat* tmpImg = new Imagefloat(tmpw, tmph); + + if (ri->getSensorType() == ST_BAYER) { + // demosaicing! (sort of) + for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { + rofs = row * width; + + for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col += hskip, x++) { + int ofs = rofs + col; + int g = image[ofs][1]; + int r, b; + + if (FISRED(filter, row, col + 1)) { + r = (image[ofs + 1 ][0] + image[ofs - 1 ][0]) >> 1; + b = (image[ofs + width][2] + image[ofs - width][2]) >> 1; + } else { + b = (image[ofs + 1 ][2] + image[ofs - 1 ][2]) >> 1; + r = (image[ofs + width][0] + image[ofs - width][0]) >> 1; + } + + tmpImg->r(y, x) = r; + tmpImg->g(y, x) = g; + tmpImg->b(y, x) = b; + } + } + } else if (ri->get_colors() == 1) { + for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { + rofs = row * width; + + for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col + += hskip, x++) { + int ofs = rofs + col; + tmpImg->r(y, x) = tmpImg->g(y, x) = tmpImg->b(y, x) = image[ofs][0]; + } + } + } else { + if(ri->getSensorType() == ST_FUJI_XTRANS) { + for( int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) { + rofs = row * width; + + for( int col = 1, x = 0; col < width - 1 && x < tmpw; col += hskip, x++ ) { + int ofs = rofs + col; + float sum[3] = {}; + int c; + + for(int v = -1; v <= 1; v++) { + for(int h = -1; h <= 1; h++) { + c = ri->XTRANSFC(row + v, col + h); + sum[c] += image[ofs + v * width + h][c]; + } + } + + c = ri->XTRANSFC(row, col); + + switch (c) { + case 0: + tmpImg->r(y, x) = image[ofs][0]; + tmpImg->g(y, x) = sum[1] / 5.f; + tmpImg->b(y, x) = sum[2] / 3.f; + break; + + case 1: + tmpImg->r(y, x) = sum[0] / 2.f; + tmpImg->g(y, x) = image[ofs][1]; + tmpImg->b(y, x) = sum[2] / 2.f; + break; + + case 2: + tmpImg->r(y, x) = sum[0] / 3.f; + tmpImg->g(y, x) = sum[1] / 5.f; + tmpImg->b(y, x) = image[ofs][2]; + break; + } + } + } + } else { + int iwidth = ri->get_iwidth(); + int iheight = ri->get_iheight(); + int left_margin = ri->get_leftmargin(); + firstgreen += left_margin; + int top_margin = ri->get_topmargin(); + + for (int row = 1 + top_margin, y = 0; row < iheight + top_margin - 1 && y < tmph; row += vskip, y++) { + rofs = row * iwidth; + + for (int col = firstgreen, x = 0; col < iwidth + left_margin - 1 && x < tmpw; col += hskip, x++) { + int ofs = rofs + col; + tmpImg->r(y, x) = image[ofs][0]; + tmpImg->g(y, x) = image[ofs][1]; + tmpImg->b(y, x) = image[ofs][2]; + } + } + } + } + + if (ri->get_FujiWidth() != 0) { + int fw = ri->get_FujiWidth() / hskip; + double step = sqrt(0.5); + int wide = fw / step; + int high = (tmph - fw) / step; + Imagefloat* fImg = new Imagefloat(wide, high); + float r, c; + + for (int row = 0; row < high; row++) + for (int col = 0; col < wide; col++) { + unsigned ur = r = fw + (row - col) * step; + unsigned uc = c = (row + col) * step; + + if (ur > tmph - 2 || uc > tmpw - 2) { + continue; + } + + double fr = r - ur; + double fc = c - uc; + fImg->r(row, col) = (tmpImg->r(ur, uc) * (1 - fc) + tmpImg->r(ur, uc + 1) * fc) * (1 - fr) + (tmpImg->r(ur + 1, uc) * (1 - fc) + tmpImg->r(ur + 1, uc + 1) * fc) * fr; + fImg->g(row, col) = (tmpImg->g(ur, uc) * (1 - fc) + tmpImg->g(ur, uc + 1) * fc) * (1 - fr) + (tmpImg->g(ur + 1, uc) * (1 - fc) + tmpImg->g(ur + 1, uc + 1) * fc) * fr; + fImg->b(row, col) = (tmpImg->b(ur, uc) * (1 - fc) + tmpImg->b(ur, uc + 1) * fc) * (1 - fr) + (tmpImg->b(ur + 1, uc) * (1 - fc) + tmpImg->b(ur + 1, uc + 1) * fc) * fr; + } + + delete tmpImg; + tmpImg = fImg; + tmpw = wide; + tmph = high; + } + + if (fixwh == 1) { // fix height, scale width + w = tmpw * h / tmph; + } else { + h = tmph * w / tmpw; + } + + if (tpp->thumbImg) { + delete tpp->thumbImg; + } + + tpp->thumbImg = NULL; tpp->thumbImg = resizeTo(w, h, TI_Bilinear, tmpImg); - delete tmpImg; + delete tmpImg; - if (ri->get_FujiWidth() != 0) - tpp->scale = (double) (height - ri->get_FujiWidth()) / sqrt(0.5) / h; - else - tpp->scale = (double) height / h; + if (ri->get_FujiWidth() != 0) { + tpp->scale = (double) (height - ri->get_FujiWidth()) / sqrt(0.5) / h; + } else { + tpp->scale = (double) height / h; + } - // generate histogram for auto exposure - tpp->aeHistCompression = 3; - tpp->aeHistogram(65536 >> tpp->aeHistCompression); - tpp->aeHistogram.clear(); - int radd = 4; - int gadd = 4; - int badd = 4; - if (!filter) - radd = gadd = badd = 1; - for (int i = 8; i < height - 8; i++) { - int start, end; - if (ri->get_FujiWidth() != 0) { - int fw = ri->get_FujiWidth(); - start = ABS(fw-i) + 8; - end = min(height + width-fw-i, fw+i) - 8; - } else { - start = 8; - end = width - 8; - } - if (ri->get_colors() == 1) { - for (int j = start; j < end; j++) { - tpp->aeHistogram[((int)(image[i* width+j][0]))>>tpp->aeHistCompression]+=radd; - tpp->aeHistogram[((int)(image[i* width+j][0]))>>tpp->aeHistCompression]+=gadd; - tpp->aeHistogram[((int)(image[i* width+j][0]))>>tpp->aeHistCompression]+=badd; - } - } else if(ri->getSensorType()==ST_BAYER) { - for (int j = start; j < end; j++) - if (FISGREEN(filter,i,j)) - tpp->aeHistogram[((int)(tpp->camwbGreen*image[i* width+j][1]))>>tpp->aeHistCompression]+=gadd; - else if (FISRED(filter,i,j)) - tpp->aeHistogram[((int)(tpp->camwbRed * image[i* width+j][0]))>>tpp->aeHistCompression]+=radd; - else if (FISBLUE(filter,i,j)) - tpp->aeHistogram[((int)(tpp->camwbBlue *image[i* width+j][2]))>>tpp->aeHistCompression]+=badd; - } else if(ri->getSensorType()==ST_FUJI_XTRANS) { - for (int j = start; j < end; j++) - if (ri->ISXTRANSGREEN(i,j)) - tpp->aeHistogram[((int)(tpp->camwbGreen*image[i* width+j][1]))>>tpp->aeHistCompression]+=gadd; - else if (ri->ISXTRANSRED(i,j)) - tpp->aeHistogram[((int)(tpp->camwbRed * image[i* width+j][0]))>>tpp->aeHistCompression]+=radd; - else if (ri->ISXTRANSBLUE(i,j)) - tpp->aeHistogram[((int)(tpp->camwbBlue *image[i* width+j][2]))>>tpp->aeHistCompression]+=badd; - } else /* if(ri->getSensorType()==ST_FOVEON) */{ - for (int j = start; j < end; j++) { - tpp->aeHistogram[((int)(image[i* width+j][0]*2.f))>>tpp->aeHistCompression]+=radd; - tpp->aeHistogram[((int)(image[i* width+j][1]))>>tpp->aeHistCompression]+=gadd; - tpp->aeHistogram[((int)(image[i* width+j][2]*0.5f))>>tpp->aeHistCompression]+=badd; - } - } - } + // generate histogram for auto exposure + tpp->aeHistCompression = 3; + tpp->aeHistogram(65536 >> tpp->aeHistCompression); + tpp->aeHistogram.clear(); + int radd = 4; + int gadd = 4; + int badd = 4; - // generate autoWB - double avg_r = 0; - double avg_g = 0; - double avg_b = 0; - const float eps=1e-5; //tolerance to avoid dividing by zero + if (!filter) { + radd = gadd = badd = 1; + } - float rn = eps, gn = eps, bn = eps; + for (int i = 8; i < height - 8; i++) { + int start, end; - for (int i = 32; i < height - 32; i++) { - int start, end; - if (ri->get_FujiWidth() != 0) { - int fw = ri->get_FujiWidth(); - start = ABS(fw-i) + 32; - end = min(height + width-fw-i, fw+i) - 32; - } else { - start = 32; - end = width - 32; - } - if(ri->getSensorType()==ST_BAYER) { - for (int j = start; j < end; j++) { - if (!filter) { - double d = tpp->defGain * image[i * width + j][0]; - if (d > 64000.) - continue; - avg_g += d; avg_r += d; avg_b += d; - rn++; gn++; bn++; - } else if (FISGREEN(filter,i,j)) { - double d = tpp->defGain * image[i * width + j][1]; - if (d > 64000.) - continue; - avg_g += d; - gn++; - } - else if (FISRED(filter,i,j)) { - double d = tpp->defGain * image[i * width + j][0]; - if (d > 64000.) - continue; - avg_r += d; - rn++; - } - else if (FISBLUE(filter,i,j)) { - double d = tpp->defGain * image[i * width + j][2]; - if (d > 64000.) - continue; - avg_b += d; - bn++; - } - } - } else if(ri->getSensorType()==ST_FUJI_XTRANS) { - for (int j = start; j < end; j++) { - if (ri->ISXTRANSGREEN(i,j)) { - double d = tpp->defGain * image[i * width + j][1]; - if (d > 64000.) - continue; - avg_g += d; - gn++; - } - else if (ri->ISXTRANSRED(i,j)) { - double d = tpp->defGain * image[i * width + j][0]; - if (d > 64000.) - continue; - avg_r += d; - rn++; - } - else if (ri->ISXTRANSBLUE(i,j)) { - double d = tpp->defGain * image[i * width + j][2]; - if (d > 64000.) - continue; - avg_b += d; - bn++; - } - } - } else /* if(ri->getSensorType()==ST_FOVEON) */ { - for (int j = start; j < end; j++) { - double d = tpp->defGain * image[i * width + j][0]; - if (d <= 64000.) { - avg_r += d; - rn++; - } - d = tpp->defGain * image[i * width + j][1]; - if (d <= 64000.) { - avg_g += d; - gn++; - } - d = tpp->defGain * image[i * width + j][2]; - if (d <= 64000.) { - avg_b += d; - bn++; - } - } - } - } + if (ri->get_FujiWidth() != 0) { + int fw = ri->get_FujiWidth(); + start = ABS(fw - i) + 8; + end = min(height + width - fw - i, fw + i) - 8; + } else { + start = 8; + end = width - 8; + } - double reds = avg_r / rn * tpp->camwbRed; - double greens = avg_g / gn * tpp->camwbGreen; - double blues = avg_b / bn * tpp->camwbBlue; + if (ri->get_colors() == 1) { + for (int j = start; j < end; j++) { + tpp->aeHistogram[((int)(image[i * width + j][0])) >> tpp->aeHistCompression] += radd; + tpp->aeHistogram[((int)(image[i * width + j][0])) >> tpp->aeHistCompression] += gadd; + tpp->aeHistogram[((int)(image[i * width + j][0])) >> tpp->aeHistCompression] += badd; + } + } else if(ri->getSensorType() == ST_BAYER) { + for (int j = start; j < end; j++) + if (FISGREEN(filter, i, j)) { + tpp->aeHistogram[((int)(tpp->camwbGreen * image[i * width + j][1])) >> tpp->aeHistCompression] += gadd; + } else if (FISRED(filter, i, j)) { + tpp->aeHistogram[((int)(tpp->camwbRed * image[i * width + j][0])) >> tpp->aeHistCompression] += radd; + } else if (FISBLUE(filter, i, j)) { + tpp->aeHistogram[((int)(tpp->camwbBlue * image[i * width + j][2])) >> tpp->aeHistCompression] += badd; + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + for (int j = start; j < end; j++) + if (ri->ISXTRANSGREEN(i, j)) { + tpp->aeHistogram[((int)(tpp->camwbGreen * image[i * width + j][1])) >> tpp->aeHistCompression] += gadd; + } else if (ri->ISXTRANSRED(i, j)) { + tpp->aeHistogram[((int)(tpp->camwbRed * image[i * width + j][0])) >> tpp->aeHistCompression] += radd; + } else if (ri->ISXTRANSBLUE(i, j)) { + tpp->aeHistogram[((int)(tpp->camwbBlue * image[i * width + j][2])) >> tpp->aeHistCompression] += badd; + } + } else { /* if(ri->getSensorType()==ST_FOVEON) */ + for (int j = start; j < end; j++) { + tpp->aeHistogram[((int)(image[i * width + j][0] * 2.f)) >> tpp->aeHistCompression] += radd; + tpp->aeHistogram[((int)(image[i * width + j][1])) >> tpp->aeHistCompression] += gadd; + tpp->aeHistogram[((int)(image[i * width + j][2] * 0.5f)) >> tpp->aeHistCompression] += badd; + } + } + } - tpp->redAWBMul = ri->get_rgb_cam(0, 0) * reds + ri->get_rgb_cam(0, 1) * greens + ri->get_rgb_cam(0, 2) * blues; - tpp->greenAWBMul = ri->get_rgb_cam(1, 0) * reds + ri->get_rgb_cam(1, 1) * greens + ri->get_rgb_cam(1, 2) * blues; - tpp->blueAWBMul = ri->get_rgb_cam(2, 0) * reds + ri->get_rgb_cam(2, 1) * greens + ri->get_rgb_cam(2, 2) * blues; - tpp->wbEqual = wbEq; + // generate autoWB + double avg_r = 0; + double avg_g = 0; + double avg_b = 0; + const float eps = 1e-5; //tolerance to avoid dividing by zero - ColorTemp cTemp; - cTemp.mul2temp(tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen); + float rn = eps, gn = eps, bn = eps; - if (rotate && ri->get_rotateDegree() > 0) { - tpp->thumbImg->rotate(ri->get_rotateDegree()); - } + for (int i = 32; i < height - 32; i++) { + int start, end; - for (int a = 0; a < 3; a++) - for (int b = 0; b < 3; b++) - tpp->colorMatrix[a][b] = ri->get_rgb_cam(a, b); + if (ri->get_FujiWidth() != 0) { + int fw = ri->get_FujiWidth(); + start = ABS(fw - i) + 32; + end = min(height + width - fw - i, fw + i) - 32; + } else { + start = 32; + end = width - 32; + } - tpp->init(); - delete ri; - return tpp; + if(ri->getSensorType() == ST_BAYER) { + for (int j = start; j < end; j++) { + if (!filter) { + double d = tpp->defGain * image[i * width + j][0]; + + if (d > 64000.) { + continue; + } + + avg_g += d; + avg_r += d; + avg_b += d; + rn++; + gn++; + bn++; + } else if (FISGREEN(filter, i, j)) { + double d = tpp->defGain * image[i * width + j][1]; + + if (d > 64000.) { + continue; + } + + avg_g += d; + gn++; + } else if (FISRED(filter, i, j)) { + double d = tpp->defGain * image[i * width + j][0]; + + if (d > 64000.) { + continue; + } + + avg_r += d; + rn++; + } else if (FISBLUE(filter, i, j)) { + double d = tpp->defGain * image[i * width + j][2]; + + if (d > 64000.) { + continue; + } + + avg_b += d; + bn++; + } + } + } else if(ri->getSensorType() == ST_FUJI_XTRANS) { + for (int j = start; j < end; j++) { + if (ri->ISXTRANSGREEN(i, j)) { + double d = tpp->defGain * image[i * width + j][1]; + + if (d > 64000.) { + continue; + } + + avg_g += d; + gn++; + } else if (ri->ISXTRANSRED(i, j)) { + double d = tpp->defGain * image[i * width + j][0]; + + if (d > 64000.) { + continue; + } + + avg_r += d; + rn++; + } else if (ri->ISXTRANSBLUE(i, j)) { + double d = tpp->defGain * image[i * width + j][2]; + + if (d > 64000.) { + continue; + } + + avg_b += d; + bn++; + } + } + } else { /* if(ri->getSensorType()==ST_FOVEON) */ + for (int j = start; j < end; j++) { + double d = tpp->defGain * image[i * width + j][0]; + + if (d <= 64000.) { + avg_r += d; + rn++; + } + + d = tpp->defGain * image[i * width + j][1]; + + if (d <= 64000.) { + avg_g += d; + gn++; + } + + d = tpp->defGain * image[i * width + j][2]; + + if (d <= 64000.) { + avg_b += d; + bn++; + } + } + } + } + + double reds = avg_r / rn * tpp->camwbRed; + double greens = avg_g / gn * tpp->camwbGreen; + double blues = avg_b / bn * tpp->camwbBlue; + + tpp->redAWBMul = ri->get_rgb_cam(0, 0) * reds + ri->get_rgb_cam(0, 1) * greens + ri->get_rgb_cam(0, 2) * blues; + tpp->greenAWBMul = ri->get_rgb_cam(1, 0) * reds + ri->get_rgb_cam(1, 1) * greens + ri->get_rgb_cam(1, 2) * blues; + tpp->blueAWBMul = ri->get_rgb_cam(2, 0) * reds + ri->get_rgb_cam(2, 1) * greens + ri->get_rgb_cam(2, 2) * blues; + tpp->wbEqual = wbEq; + + ColorTemp cTemp; + cTemp.mul2temp(tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen); + + if (rotate && ri->get_rotateDegree() > 0) { + tpp->thumbImg->rotate(ri->get_rotateDegree()); + } + + for (int a = 0; a < 3; a++) + for (int b = 0; b < 3; b++) { + tpp->colorMatrix[a][b] = ri->get_rgb_cam(a, b); + } + + tpp->init(); + delete ri; + return tpp; } #undef FISRED #undef FISGREEN @@ -640,29 +724,39 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati unsigned short *Thumbnail::igammatab = 0; unsigned char *Thumbnail::gammatab = 0; -void Thumbnail::initGamma () { +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)); + + 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 () { +void Thumbnail::cleanupGamma () +{ delete [] igammatab; delete [] gammatab; } -void Thumbnail::init () { +void Thumbnail::init () +{ RawImageSource::inverse33 (colorMatrix, iColorMatrix); - //colorMatrix is rgb_cam + //colorMatrix is rgb_cam memset (cam2xyz, 0, sizeof(cam2xyz)); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) - for (int k=0; k<3; k++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) { cam2xyz[i][j] += xyz_sRGB[i][k] * colorMatrix[k][j]; + } + camProfile = iccStore->createFromMatrix (cam2xyz, false, "Camera"); } @@ -676,106 +770,123 @@ Thumbnail::Thumbnail () : defGain(1.0), scaleForSave(8192), gammaCorrected(false), - aeHistCompression(3) { + aeHistCompression(3) +{ } -Thumbnail::~Thumbnail () { +Thumbnail::~Thumbnail () +{ delete thumbImg; //delete [] aeHistogram; delete [] embProfileData; - if (embProfile) + + if (embProfile) { cmsCloseProfile(embProfile); - if (camProfile) + } + + if (camProfile) { cmsCloseProfile(camProfile); + } } // Simple processing of RAW internal JPGs -IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int rheight, rtengine::TypeInterpolation interp, double& myscale) { +IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int rheight, rtengine::TypeInterpolation interp, double& myscale) +{ int rwidth; - if (params.coarse.rotate==90 || params.coarse.rotate==270) { + + if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { rwidth = rheight; rheight = thumbImg->height * rwidth / thumbImg->width; - } - else + } else { rwidth = thumbImg->width * rheight / thumbImg->height; + } Image8* baseImg = resizeTo(rwidth, rheight, interp, thumbImg); - if (params.coarse.rotate) + if (params.coarse.rotate) { baseImg->rotate (params.coarse.rotate); + } - if (params.coarse.hflip) + if (params.coarse.hflip) { baseImg->hflip (); + } - if (params.coarse.vflip) + if (params.coarse.vflip) { baseImg->vflip (); + } + return baseImg; } // Full thumbnail processing, second stage if complete profile exists -IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName, - double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso,std::string expcomp_, double& myscale) { +IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName, + double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& myscale) +{ // check if the WB's equalizer value has changed - if (wbEqual < (params.wb.equal-5e-4) || wbEqual > (params.wb.equal+5e-4)) { + if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4)) { wbEqual = params.wb.equal; // recompute the autoWB ColorTemp cTemp; cTemp.mul2temp (redAWBMul, greenAWBMul, blueAWBMul, wbEqual, autoWBTemp, autoWBGreen); } + // compute WB multipliers - ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal,params.wb.method); - if (params.wb.method=="Camera") { + ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); + + if (params.wb.method == "Camera") { //recall colorMatrix is rgb_cam - double cam_r = colorMatrix[0][0]*camwbRed + colorMatrix[0][1]*camwbGreen + colorMatrix[0][2]*camwbBlue; - double cam_g = colorMatrix[1][0]*camwbRed + colorMatrix[1][1]*camwbGreen + colorMatrix[1][2]*camwbBlue; - double cam_b = colorMatrix[2][0]*camwbRed + colorMatrix[2][1]*camwbGreen + colorMatrix[2][2]*camwbBlue; + double cam_r = colorMatrix[0][0] * camwbRed + colorMatrix[0][1] * camwbGreen + colorMatrix[0][2] * camwbBlue; + double cam_g = colorMatrix[1][0] * camwbRed + colorMatrix[1][1] * camwbGreen + colorMatrix[1][2] * camwbBlue; + double cam_b = colorMatrix[2][0] * camwbRed + colorMatrix[2][1] * camwbGreen + colorMatrix[2][2] * camwbBlue; currWB = ColorTemp (cam_r, cam_g, cam_b, params.wb.equal); - } - else if (params.wb.method=="Auto") + } else if (params.wb.method == "Auto") { currWB = ColorTemp (autoWBTemp, autoWBGreen, wbEqual, "Custom"); + } + double r, g, b; currWB.getMultipliers (r, g, b); //iColorMatrix is cam_rgb - double rm = iColorMatrix[0][0]*r + iColorMatrix[0][1]*g + iColorMatrix[0][2]*b; - double gm = iColorMatrix[1][0]*r + iColorMatrix[1][1]*g + iColorMatrix[1][2]*b; - double bm = iColorMatrix[2][0]*r + iColorMatrix[2][1]*g + iColorMatrix[2][2]*b; + double rm = iColorMatrix[0][0] * r + iColorMatrix[0][1] * g + iColorMatrix[0][2] * b; + double gm = iColorMatrix[1][0] * r + iColorMatrix[1][1] * g + iColorMatrix[1][2] * b; + double bm = iColorMatrix[2][0] * r + iColorMatrix[2][1] * g + iColorMatrix[2][2] * b; rm = camwbRed / rm; gm = camwbGreen / gm; bm = camwbBlue / bm; - double mul_lum = 0.299*rm + 0.587*gm + 0.114*bm; + double mul_lum = 0.299 * rm + 0.587 * gm + 0.114 * bm; double logDefGain = log(defGain) / log(2.0); int rmi, gmi, bmi; // Since HL recovery is not rendered in thumbs // if (!isRaw || !params.toneCurve.hrenabled) { - logDefGain = 0.0; - rmi = 1024.0 * rm * defGain / mul_lum; - gmi = 1024.0 * gm * defGain / mul_lum; - bmi = 1024.0 * bm * defGain / mul_lum; -/* } - else { - rmi = 1024.0 * rm / mul_lum; - gmi = 1024.0 * gm / mul_lum; - bmi = 1024.0 * bm / mul_lum; - }*/ + logDefGain = 0.0; + rmi = 1024.0 * rm * defGain / mul_lum; + gmi = 1024.0 * gm * defGain / mul_lum; + bmi = 1024.0 * bm * defGain / mul_lum; + /* } + else { + rmi = 1024.0 * rm / mul_lum; + gmi = 1024.0 * gm / mul_lum; + bmi = 1024.0 * bm / mul_lum; + }*/ // The RAW exposure is not reflected since it's done in preprocessing. If we only have e.g. the chached thumb, // that is already preprocessed. So we simulate the effect here roughly my modifying the exposure accordingly - if (isRaw && fabs(1.0-params.raw.expos)>0.001) { - rmi*=params.raw.expos; - gmi*=params.raw.expos; - bmi*=params.raw.expos; + if (isRaw && fabs(1.0 - params.raw.expos) > 0.001) { + rmi *= params.raw.expos; + gmi *= params.raw.expos; + bmi *= params.raw.expos; } // resize to requested width and perform coarse transformation int rwidth; - if (params.coarse.rotate==90 || params.coarse.rotate==270) { + + if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { rwidth = rheight; rheight = int(size_t(thumbImg->height) * size_t(rwidth) / size_t(thumbImg->width)); - } - else + } else { rwidth = int(size_t(thumbImg->width) * size_t(rheight) / size_t(thumbImg->height)); + } Imagefloat* baseImg = resizeTo(rwidth, rheight, interp, thumbImg); @@ -785,46 +896,49 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei rheight = baseImg->height; } - if (params.coarse.hflip) + if (params.coarse.hflip) { baseImg->hflip (); + } - if (params.coarse.vflip) + if (params.coarse.vflip) { baseImg->vflip (); + } // apply white balance and raw white point (simulated) int val; unsigned short val_; - for (int i=0; iconvertTo(baseImg->r(i,j), val_); - val = static_cast(val_)*rmi>>10; - baseImg->r(i,j) = CLIP(val); + for (int i = 0; i < rheight; i++) + for (int j = 0; j < rwidth; j++) { - baseImg->convertTo(baseImg->g(i,j), val_); - val = static_cast(val_)*gmi>>10; - baseImg->g(i,j) = CLIP(val); + baseImg->convertTo(baseImg->r(i, j), val_); + val = static_cast(val_) * rmi >> 10; + baseImg->r(i, j) = CLIP(val); - baseImg->convertTo(baseImg->b(i,j), val_); - val = static_cast(val_)*bmi>>10; - baseImg->b(i,j) = CLIP(val); + baseImg->convertTo(baseImg->g(i, j), val_); + val = static_cast(val_) * gmi >> 10; + baseImg->g(i, j) = CLIP(val); + + baseImg->convertTo(baseImg->b(i, j), val_); + val = static_cast(val_) * bmi >> 10; + baseImg->b(i, j) = CLIP(val); } -/* - // apply highlight recovery, if needed -- CURRENTLY BROKEN DUE TO INCOMPATIBLE DATA TYPES, BUT HL RECOVERY AREN'T COMPUTED FOR THUMBNAILS ANYWAY... - if (isRaw && params.toneCurve.hrenabled) { - int maxval = 65535 / defGain; - if (params.toneCurve.method=="Luminance" || params.toneCurve.method=="Color") - for (int i=0; ir[i], baseImg->g[i], baseImg->b[i], baseImg->r[i], baseImg->g[i], baseImg->b[i], rwidth, maxval); - else if (params.toneCurve.method=="CIELab blending") { - double icamToD50[3][3]; - RawImageSource::inverse33 (cam2xyz, icamToD50); - for (int i=0; ir[i], baseImg->g[i], baseImg->b[i], baseImg->r[i], baseImg->g[i], baseImg->b[i], rwidth, maxval, cam2xyz, icamToD50); + /* + // apply highlight recovery, if needed -- CURRENTLY BROKEN DUE TO INCOMPATIBLE DATA TYPES, BUT HL RECOVERY AREN'T COMPUTED FOR THUMBNAILS ANYWAY... + if (isRaw && params.toneCurve.hrenabled) { + int maxval = 65535 / defGain; + if (params.toneCurve.method=="Luminance" || params.toneCurve.method=="Color") + for (int i=0; ir[i], baseImg->g[i], baseImg->b[i], baseImg->r[i], baseImg->g[i], baseImg->b[i], rwidth, maxval); + else if (params.toneCurve.method=="CIELab blending") { + double icamToD50[3][3]; + RawImageSource::inverse33 (cam2xyz, icamToD50); + for (int i=0; ir[i], baseImg->g[i], baseImg->b[i], baseImg->r[i], baseImg->g[i], baseImg->b[i], rwidth, maxval, cam2xyz, icamToD50); + } } - } -*/ + */ // if luma denoise has to be done for thumbnails, it should be right here @@ -838,15 +952,15 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei int fw = baseImg->width; int fh = baseImg->height; - //ColorTemp::CAT02 (baseImg, ¶ms) ;//perhaps not good! + //ColorTemp::CAT02 (baseImg, ¶ms) ;//perhaps not good! ImProcFunctions ipf (¶ms, false); - ipf.setScale (sqrt(double(fw*fw+fh*fh))/sqrt(double(thumbImg->width*thumbImg->width+thumbImg->height*thumbImg->height))*scale); + ipf.setScale (sqrt(double(fw * fw + fh * fh)) / sqrt(double(thumbImg->width * thumbImg->width + thumbImg->height * thumbImg->height))*scale); LUTu hist16 (65536); LUTu hist16C (65536); - double gamma = isRaw ? Color::sRGBGamma : 0; // usually in ImageSource, but we don't have that here + double gamma = isRaw ? Color::sRGBGamma : 0; // usually in ImageSource, but we don't have that here ipf.firstAnalysis (baseImg, ¶ms, hist16); // perform transform @@ -856,222 +970,246 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei int origFH; double tscale; getDimensions(origFW, origFH, tscale); - ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW*tscale+0.5, origFH*tscale+0.5, focalLen, focalLen35mm, focusDist, 0, true); // Raw rotate degree not detectable here + ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, focalLen, focalLen35mm, focusDist, 0, true); // Raw rotate degree not detectable here delete baseImg; baseImg = trImg; } - + // update blurmap SHMap* shmap = NULL; + if (params.sh.enabled) { shmap = new SHMap (fw, fh, false); - double radius = sqrt (double(fw*fw+fh*fh)) / 2.0; + double radius = sqrt (double(fw * fw + fh * fh)) / 2.0; double shradius = params.sh.radius; - if (!params.sh.hq) shradius *= radius / 1800.0; + + if (!params.sh.hq) { + shradius *= radius / 1800.0; + } + shmap->update (baseImg, shradius, ipf.lumimul, params.sh.hq, 16); } - + // RGB processing - double expcomp = params.toneCurve.expcomp; - int bright = params.toneCurve.brightness; - int contr = params.toneCurve.contrast; - int black = params.toneCurve.black; - int hlcompr = params.toneCurve.hlcompr; - int hlcomprthresh = params.toneCurve.hlcomprthresh; - + double expcomp = params.toneCurve.expcomp; + int bright = params.toneCurve.brightness; + int contr = params.toneCurve.contrast; + int black = params.toneCurve.black; + int hlcompr = params.toneCurve.hlcompr; + int hlcomprthresh = params.toneCurve.hlcomprthresh; + if (params.toneCurve.autoexp && aeHistogram) { - ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); - //ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr); + ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); + //ipf.getAutoExp (aeHistogram, aeHistCompression, logDefGain, params.toneCurve.clip, params.toneCurve.expcomp, params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr); } - LUTf curve1 (65536); - LUTf curve2 (65536); - LUTf curve (65536); - LUTf satcurve (65536); - LUTf lhskcurve (65536); - LUTf clcurve (65536); - LUTf clToningcurve (65536); - LUTf cl2Toningcurve (65536); - - LUTf rCurve (65536); - LUTf gCurve (65536); - LUTf bCurve (65536); + LUTf curve1 (65536); + LUTf curve2 (65536); + LUTf curve (65536); + LUTf satcurve (65536); + LUTf lhskcurve (65536); + LUTf clcurve (65536); + LUTf clToningcurve (65536); + LUTf cl2Toningcurve (65536); - LUTu dummy; + LUTf rCurve (65536); + LUTf gCurve (65536); + LUTf bCurve (65536); + + LUTu dummy; + + ToneCurve customToneCurve1, customToneCurve2; + ColorGradientCurve ctColorCurve; + OpacityCurve ctOpacityCurve; + // NoisCurve dnNoisCurve; - ToneCurve customToneCurve1, customToneCurve2; - ColorGradientCurve ctColorCurve; - OpacityCurve ctOpacityCurve; - // NoisCurve dnNoisCurve; - ColorAppearance customColCurve1; ColorAppearance customColCurve2; ColorAppearance customColCurve3; - ToneCurve customToneCurvebw1; - ToneCurve customToneCurvebw2; + ToneCurve customToneCurvebw1; + ToneCurve customToneCurvebw2; - CurveFactory::complexCurve (expcomp, black/65535.0, hlcompr, hlcomprthresh, - params.toneCurve.shcompr, bright, contr, - params.toneCurve.curveMode, params.toneCurve.curve, - params.toneCurve.curveMode2, params.toneCurve.curve2, - hist16, dummy, curve1, curve2, curve, dummy, customToneCurve1, customToneCurve2, 16); - - CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 16); - CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 16); - CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 16); + CurveFactory::complexCurve (expcomp, black / 65535.0, hlcompr, hlcomprthresh, + params.toneCurve.shcompr, bright, contr, + params.toneCurve.curveMode, params.toneCurve.curve, + params.toneCurve.curveMode2, params.toneCurve.curve2, + hist16, dummy, curve1, curve2, curve, dummy, customToneCurve1, customToneCurve2, 16); - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); - double wp[3][3] = { - {wprof[0][0],wprof[0][1],wprof[0][2]}, - {wprof[1][0],wprof[1][1],wprof[1][2]}, - {wprof[2][0],wprof[2][1],wprof[2][2]}}; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; - bool opautili=false; - params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); - //params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoisutili); + CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 16); + CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 16); + CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 16); + + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + double wp[3][3] = { + {wprof[0][0], wprof[0][1], wprof[0][2]}, + {wprof[1][0], wprof[1][1], wprof[1][2]}, + {wprof[2][0], wprof[2][1], wprof[2][2]} + }; + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; + bool opautili = false; + params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); + //params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoisutili); + + bool clctoningutili = false; + bool llctoningutili = false; + CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, scale == 1 ? 1 : 16); + CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, scale == 1 ? 1 : 16); - bool clctoningutili=false; - bool llctoningutili=false; - CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve,scale==1 ? 1 : 16); - CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, scale==1 ? 1 : 16); - CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 16); - - double rrm, ggm, bbm; + + double rrm, ggm, bbm; float autor, autog, autob; - float satLimit = float(params.colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; - float satLimitOpacity = 1.f-(float(params.colorToning.saturatedOpacity)/100.f); - - if(params.colorToning.enabled && params.colorToning.autosat){//for colortoning evaluation of saturation settings - float moyS=0.f; - float eqty=0.f; - ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation - //printf("moy=%f ET=%f\n", moyS,eqty); - float satp=((moyS+1.5f*eqty)-0.3f)/0.7f;//1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale - if(satp >= 0.92f) satp=0.92f;//avoid values too high (out of gamut) - if(satp <= 0.15f) satp=0.15f;//avoid too low values - - satLimit= 100.f*satp; - - satLimitOpacity= 100.f*(moyS-0.85f*eqty);//-0.85 sigma==>20% pixels with low saturation - } - + float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; + float satLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f); + + if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + float moyS = 0.f; + float eqty = 0.f; + ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation + //printf("moy=%f ET=%f\n", moyS,eqty); + float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale + + if(satp >= 0.92f) { + satp = 0.92f; //avoid values too high (out of gamut) + } + + if(satp <= 0.15f) { + satp = 0.15f; //avoid too low values + } + + satLimit = 100.f * satp; + + satLimitOpacity = 100.f * (moyS - 0.85f * eqty); //-0.85 sigma==>20% pixels with low saturation + } + autor = autog = autob = -9000.f; // This will ask to compute the "auto" values for the B&W tool - LabImage* labView = new LabImage (fw,fh); - DCPProfile *dcpProf = NULL; - if (isRaw) { - cmsHPROFILE dummy; - RawImageSource::findInputProfile(params.icm.input, NULL, camName, &dcpProf, dummy); - if (dcpProf != NULL) { - dcpProf->setStep2ApplyState(params.icm.working, params.icm.toneCurve, params.icm.applyLookTable, params.icm.applyBaselineExposureOffset); - } + LabImage* labView = new LabImage (fw, fh); + DCPProfile *dcpProf = NULL; + + if (isRaw) { + cmsHPROFILE dummy; + RawImageSource::findInputProfile(params.icm.input, NULL, camName, &dcpProf, dummy); + + if (dcpProf != NULL) { + dcpProf->setStep2ApplyState(params.icm.working, params.icm.toneCurve, params.icm.applyLookTable, params.icm.applyBaselineExposureOffset); } - ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit ,satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2,rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf); + } + + ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf); // freeing up some memory customToneCurve1.Reset(); customToneCurve2.Reset(); ctColorCurve.Reset(); ctOpacityCurve.Reset(); - // dnNoisCurve.Reset(); +// dnNoisCurve.Reset(); customToneCurvebw1.Reset(); customToneCurvebw2.Reset(); - if (shmap) + if (shmap) { delete shmap; + } // luminance histogram update - hist16.clear();hist16C.clear(); - for (int i=0; iL[i][j])))]++; hist16C[CLIP((int)sqrt(labView->a[i][j]*labView->a[i][j] + labView->b[i][j]*labView->b[i][j]))]++; } + // luminance processing -// ipf.EPDToneMap(labView,0,6); - - bool utili=false; - bool autili=false; - bool butili=false; - bool ccutili=false; - bool cclutili=false; - bool clcutili=false; - +// ipf.EPDToneMap(labView,0,6); + + bool utili = false; + bool autili = false; + bool butili = false; + bool ccutili = false; + bool cclutili = false; + bool clcutili = false; + CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, - hist16, hist16, curve, dummy, 16, utili); - - CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, hist16C, dummy, 16); - - CurveFactory::complexsgnCurve (1.f, autili, butili, ccutili, cclutili,params.labCurve.chromaticity, params.labCurve.rstprotection, - params.labCurve.acurve, params.labCurve.bcurve,params.labCurve.cccurve,params.labCurve.lccurve, curve1, curve2, satcurve,lhskcurve, - hist16C, hist16C, dummy, dummy, - 16); + hist16, hist16, curve, dummy, 16, utili); + + CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, hist16C, dummy, 16); + + CurveFactory::complexsgnCurve (1.f, autili, butili, ccutili, cclutili, params.labCurve.chromaticity, params.labCurve.rstprotection, + params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve, params.labCurve.lccurve, curve1, curve2, satcurve, lhskcurve, + hist16C, hist16C, dummy, dummy, + 16); //ipf.luminanceCurve (labView, labView, curve); - - ipf.chromiLuminanceCurve (NULL, 1,labView, labView, curve1, curve2, satcurve,lhskcurve, clcurve, curve, utili, autili, butili, ccutili,cclutili, clcutili, dummy, dummy, dummy, dummy); - - ipf.vibrance(labView); - if((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) ipf.EPDToneMap(labView,5,6); + ipf.chromiLuminanceCurve (NULL, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, curve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); - //if(!params.colorappearance.enabled){ipf.EPDToneMap(labView,5,6);} - - CurveFactory::curveLightBrightColor ( - params.colorappearance.curveMode, params.colorappearance.curve, - params.colorappearance.curveMode2, params.colorappearance.curve2, - params.colorappearance.curveMode3, params.colorappearance.curve3, - hist16, hist16, dummy, - hist16C, dummy, - customColCurve1, - customColCurve2, - customColCurve3, - 16); + ipf.vibrance(labView); - if(params.colorappearance.enabled){ - int begh = 0, endh = labView->H; - bool execsharp=false; - float d; - float fnum = fnumber;// F number - float fiso = iso;// ISO - float fspeed = shutter;//speed - char * writ = new char[expcomp_.size() + 1];//convert expcomp_ to char - std::copy(expcomp_.begin(), expcomp_.end(), writ); - writ[expcomp_.size()] = '\0'; - float fcomp = atof(writ); //compensation + - - delete[] writ; - float adap; - if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) - //if no exif data or wrong - adap=2000.f; - else { - float E_V = fcomp + log2 ((fnum*fnum) / fspeed / (fiso/100.f)); - float expo2= params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV - E_V += expo2; - float expo1;//exposure raw white point - expo1=log2(params.raw.expos);//log2 ==>linear to EV - E_V += expo1; - adap= powf(2.f, E_V-3.f);//cd / m2 - //end calculation adaptation scene luminosity - } + if((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) { + ipf.EPDToneMap(labView, 5, 6); + } + + //if(!params.colorappearance.enabled){ipf.EPDToneMap(labView,5,6);} + + CurveFactory::curveLightBrightColor ( + params.colorappearance.curveMode, params.colorappearance.curve, + params.colorappearance.curveMode2, params.colorappearance.curve2, + params.colorappearance.curveMode3, params.colorappearance.curve3, + hist16, hist16, dummy, + hist16C, dummy, + customColCurve1, + customColCurve2, + customColCurve3, + 16); + + if(params.colorappearance.enabled) { + int begh = 0, endh = labView->H; + bool execsharp = false; + float d; + float fnum = fnumber;// F number + float fiso = iso;// ISO + float fspeed = shutter;//speed + char * writ = new char[expcomp_.size() + 1];//convert expcomp_ to char + std::copy(expcomp_.begin(), expcomp_.end(), writ); + writ[expcomp_.size()] = '\0'; + float fcomp = atof(writ); //compensation + - + delete[] writ; + float adap; + + if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) + //if no exif data or wrong + { + adap = 2000.f; + } else { + float E_V = fcomp + log2 ((fnum * fnum) / fspeed / (fiso / 100.f)); + float expo2 = params.toneCurve.expcomp; // exposure compensation in tonecurve ==> direct EV + E_V += expo2; + float expo1;//exposure raw white point + expo1 = log2(params.raw.expos); //log2 ==>linear to EV + E_V += expo1; + adap = powf(2.f, E_V - 3.f); //cd / m2 + //end calculation adaptation scene luminosity + } + + LUTf CAMBrightCurveJ; + LUTf CAMBrightCurveQ; + float CAMMean; + int sk; + int scale; + sk = 16; + int rtt = 0; + CieImage* cieView = new CieImage (fw, fh); + ipf.ciecam_02float (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 6, execsharp, d, sk, rtt); + delete cieView; + } - LUTf CAMBrightCurveJ; - LUTf CAMBrightCurveQ; - float CAMMean; - int sk; - int scale; - sk=16; - int rtt=0; - CieImage* cieView = new CieImage (fw,fh); - ipf.ciecam_02float (cieView, adap, begh, endh, 1, 2, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 6, execsharp, d, sk, rtt); - delete cieView; - } // color processing //ipf.colorCurve (labView, labView); @@ -1080,64 +1218,77 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei ipf.lab2monitorRgb (labView, readyImg); delete labView; delete baseImg; + // calculate scale - if (params.coarse.rotate==90 || params.coarse.rotate==270) + if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { myscale = scale * thumbImg->width / fh; - else + } else { myscale = scale * thumbImg->height / fh; + } myscale = 1.0 / myscale; -/* // apply crop - if (params.crop.enabled) { - int ix = 0; - for (int i=0; i(params.crop.y+params.crop.h)/myscale || j(params.crop.x+params.crop.w)/myscale) { - readyImg->data[ix++] /= 3; - readyImg->data[ix++] /= 3; - readyImg->data[ix++] /= 3; - } - else - ix += 3; - }*/ + /* // apply crop + if (params.crop.enabled) { + int ix = 0; + for (int i=0; i(params.crop.y+params.crop.h)/myscale || j(params.crop.x+params.crop.w)/myscale) { + readyImg->data[ix++] /= 3; + readyImg->data[ix++] /= 3; + readyImg->data[ix++] /= 3; + } + else + ix += 3; + }*/ return readyImg; } -int Thumbnail::getImageWidth (const procparams::ProcParams& params, int rheight, float &ratio) { - if (thumbImg==NULL) return 0; // Can happen if thumb is just building and GUI comes in with resize wishes +int Thumbnail::getImageWidth (const procparams::ProcParams& params, int rheight, float &ratio) +{ + if (thumbImg == NULL) { + return 0; // Can happen if thumb is just building and GUI comes in with resize wishes + } int rwidth; - if (params.coarse.rotate==90 || params.coarse.rotate==270) { - ratio = (float)(thumbImg->height) / (float)(thumbImg->width); - } - else { - ratio = (float)(thumbImg->width) / (float)(thumbImg->height); + + if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { + ratio = (float)(thumbImg->height) / (float)(thumbImg->width); + } else { + ratio = (float)(thumbImg->width) / (float)(thumbImg->height); } + rwidth = (int)(ratio * (float)rheight); return rwidth; } -void Thumbnail::getDimensions (int& w, int& h, double& scaleFac) { +void Thumbnail::getDimensions (int& w, int& h, double& scaleFac) +{ if (thumbImg) { - w=thumbImg->width; h=thumbImg->height; scaleFac=scale; + w = thumbImg->width; + h = thumbImg->height; + scaleFac = scale; } else { - w=0; h=0; scale=1; + w = 0; + h = 0; + scale = 1; } } -void Thumbnail::getCamWB (double& temp, double& green) { +void Thumbnail::getCamWB (double& temp, double& green) +{ - double cam_r = colorMatrix[0][0]*camwbRed + colorMatrix[0][1]*camwbGreen + colorMatrix[0][2]*camwbBlue; - double cam_g = colorMatrix[1][0]*camwbRed + colorMatrix[1][1]*camwbGreen + colorMatrix[1][2]*camwbBlue; - double cam_b = colorMatrix[2][0]*camwbRed + colorMatrix[2][1]*camwbGreen + colorMatrix[2][2]*camwbBlue; + double cam_r = colorMatrix[0][0] * camwbRed + colorMatrix[0][1] * camwbGreen + colorMatrix[0][2] * camwbBlue; + double cam_g = colorMatrix[1][0] * camwbRed + colorMatrix[1][1] * camwbGreen + colorMatrix[1][2] * camwbBlue; + double cam_b = colorMatrix[2][0] * camwbRed + colorMatrix[2][1] * camwbGreen + colorMatrix[2][2] * camwbBlue; ColorTemp currWB = ColorTemp (cam_r, cam_g, cam_b, 1.0); // we do not take the equalizer into account here, because we want camera's WB temp = currWB.getTemp (); green = currWB.getGreen (); } -void Thumbnail::getAutoWB (double& temp, double& green, double equal) { +void Thumbnail::getAutoWB (double& temp, double& green, double equal) +{ if (equal != wbEqual) { // compute the values depending on equal @@ -1146,37 +1297,45 @@ void Thumbnail::getAutoWB (double& temp, double& green, double equal) { // compute autoWBTemp and autoWBGreen cTemp.mul2temp(redAWBMul, greenAWBMul, blueAWBMul, wbEqual, autoWBTemp, autoWBGreen); } + temp = autoWBTemp; green = autoWBGreen; } -void Thumbnail::getAutoWBMultipliers (double& rm, double& gm, double& bm) { +void Thumbnail::getAutoWBMultipliers (double& rm, double& gm, double& bm) +{ rm = redAWBMul; gm = greenAWBMul; bm = blueAWBMul; } -void Thumbnail::applyAutoExp (procparams::ProcParams& params) { +void Thumbnail::applyAutoExp (procparams::ProcParams& params) +{ if (params.toneCurve.autoexp && aeHistogram) { ImProcFunctions ipf (¶ms, false); - ipf.getAutoExp (aeHistogram, aeHistCompression, log(defGain)/log(2.0), params.toneCurve.clip, params.toneCurve.expcomp, - params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); + ipf.getAutoExp (aeHistogram, aeHistCompression, log(defGain) / log(2.0), params.toneCurve.clip, params.toneCurve.expcomp, + params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); } } -void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp, int rect, double& rtemp, double& rgreen) { +void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp, int rect, double& rtemp, double& rgreen) +{ std::vector points, red, green, blue; - for (int i=yp-rect; i<=yp+rect; i++) - for (int j=xp-rect; j<=xp+rect; j++) + + for (int i = yp - rect; i <= yp + rect; i++) + for (int j = xp - rect; j <= xp + rect; j++) { points.push_back (Coord2D (j, i)); + } int fw = thumbImg->width, fh = thumbImg->height; - if (params.coarse.rotate==90 || params.coarse.rotate==270) { + + if (params.coarse.rotate == 90 || params.coarse.rotate == 270) { fw = thumbImg->height; fh = thumbImg->width; } + ImProcFunctions ipf (¶ms, false); ipf.transCoord (fw, fh, points, red, green, blue); int tr = getCoarseBitMask(params.coarse); @@ -1184,86 +1343,91 @@ void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp, double reds = 0, greens = 0, blues = 0; int rn = 0, gn = 0, bn = 0; thumbImg->getSpotWBData(reds, greens, blues, rn, gn, bn, red, green, blue, tr); - reds = reds/rn * camwbRed; - greens = greens/gn * camwbGreen; - blues = blues/bn * camwbBlue; + reds = reds / rn * camwbRed; + greens = greens / gn * camwbGreen; + blues = blues / bn * camwbBlue; - double rm = colorMatrix[0][0]*reds + colorMatrix[0][1]*greens + colorMatrix[0][2]*blues; - double gm = colorMatrix[1][0]*reds + colorMatrix[1][1]*greens + colorMatrix[1][2]*blues; - double bm = colorMatrix[2][0]*reds + colorMatrix[2][1]*greens + colorMatrix[2][2]*blues; + double rm = colorMatrix[0][0] * reds + colorMatrix[0][1] * greens + colorMatrix[0][2] * blues; + double gm = colorMatrix[1][0] * reds + colorMatrix[1][1] * greens + colorMatrix[1][2] * blues; + double bm = colorMatrix[2][0] * reds + colorMatrix[2][1] * greens + colorMatrix[2][2] * blues; ColorTemp ct (rm, gm, bm, params.wb.equal); rtemp = ct.getTemp (); rgreen = ct.getGreen (); } -void Thumbnail::transformPixel (int x, int y, int tran, int& tx, int& ty) { - +void Thumbnail::transformPixel (int x, int y, int tran, int& tx, int& ty) +{ + int W = thumbImg->width; int H = thumbImg->height; - int sw = W, sh = H; + int sw = W, sh = H; + if ((tran & TR_ROT) == TR_R90 || (tran & TR_ROT) == TR_R270) { sw = H; sh = W; } int ppx = x, ppy = y; - if (tran & TR_HFLIP) + + if (tran & TR_HFLIP) { ppx = sw - 1 - x ; - if (tran & TR_VFLIP) + } + + if (tran & TR_VFLIP) { ppy = sh - 1 - y; - + } + tx = ppx; ty = ppy; - + if ((tran & TR_ROT) == TR_R180) { tx = W - 1 - ppx; ty = H - 1 - ppy; - } - else if ((tran & TR_ROT) == TR_R90) { + } else if ((tran & TR_ROT) == TR_R90) { tx = ppy; ty = H - 1 - ppx; - } - else if ((tran & TR_ROT) == TR_R270) { + } else if ((tran & TR_ROT) == TR_R270) { tx = W - 1 - ppy; ty = ppx; } - tx/=scale; - ty/=scale; + + tx /= scale; + ty /= scale; } -unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) { - if (!thumbImg) +unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) +{ + if (!thumbImg) { return NULL; + } - if (thumbImg->widthwidth < trim_width) { return NULL; - + } + // to utilize the 8 bit color range of the thumbnail we brighten it and apply gamma correction - unsigned char* tmpdata = new unsigned char[thumbImg->height*trim_width]; - int ix = 0,max; + unsigned char* tmpdata = new unsigned char[thumbImg->height * trim_width]; + int ix = 0, max; if (gammaCorrected) { // if it's gamma correct (usually a RAW), we have the problem that there is a lot noise etc. that makes the maximum way too high. // Strategy is limit a certain percent of pixels so the overall picture quality when scaling to 8 bit is way better - const double BurnOffPct=0.03; // *100 = percent pixels that may be clipped + const double BurnOffPct = 0.03; // *100 = percent pixels that may be clipped // Calc the histogram unsigned int* hist16 = new unsigned int [65536]; - memset(hist16,0,sizeof(int)*65536); + memset(hist16, 0, sizeof(int) * 65536); if (thumbImg->getType() == sImage8) { Image8 *image = static_cast(thumbImg); image->calcGrayscaleHist(hist16); - } - else if (thumbImg->getType() == sImage16) { + } else if (thumbImg->getType() == sImage16) { Image16 *image = static_cast(thumbImg); image->calcGrayscaleHist(hist16); - } - else if (thumbImg->getType() == sImagefloat) { + } else if (thumbImg->getType() == sImagefloat) { Imagefloat *image = static_cast(thumbImg); image->calcGrayscaleHist(hist16); - } - else { + } else { printf("getGrayscaleHistEQ #1: Unsupported image type \"%s\"!\n", thumbImg->getType()); } @@ -1271,146 +1435,182 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) { unsigned long cutoff = thumbImg->height * thumbImg->height * 4 * BurnOffPct; int max_; - unsigned long sum=0; - for (max_=65535; max_>16384 && sum 16384 && sum < cutoff; max_--) { + sum += hist16[max_]; + } delete[] hist16; - scaleForSave = 65535*8192 / max_; + scaleForSave = 65535 * 8192 / max_; // Correction and gamma to 8 Bit if (thumbImg->getType() == sImage8) { Image8 *image = static_cast(thumbImg); - for (int i=0; iheight; i++) - for (int j=(thumbImg->width-trim_width)/2; jwidth-trim_width)/2; j++) { + + for (int i = 0; i < thumbImg->height; i++) + for (int j = (thumbImg->width - trim_width) / 2; j < trim_width + (thumbImg->width - trim_width) / 2; j++) { unsigned short r_, g_, b_; - 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]; - tmpdata[ix++] = (r*19595+g*38469+b*7472) >> 16; + 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]; + tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } - } - else if (thumbImg->getType() == sImage16) { + } else if (thumbImg->getType() == sImage16) { Image16 *image = static_cast(thumbImg); - for (int i=0; iheight; i++) - for (int j=(thumbImg->width-trim_width)/2; jwidth-trim_width)/2; j++) { + + for (int i = 0; i < thumbImg->height; i++) + for (int j = (thumbImg->width - trim_width) / 2; j < trim_width + (thumbImg->width - trim_width) / 2; j++) { unsigned short r_, g_, b_; - 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]; - tmpdata[ix++] = (r*19595+g*38469+b*7472) >> 16; + 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]; + tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } - } - else if (thumbImg->getType() == sImagefloat) { + } else if (thumbImg->getType() == sImagefloat) { Imagefloat *image = static_cast(thumbImg); - for (int i=0; iheight; i++) - for (int j=(thumbImg->width-trim_width)/2; jwidth-trim_width)/2; j++) { + + for (int i = 0; i < thumbImg->height; i++) + for (int j = (thumbImg->width - trim_width) / 2; j < trim_width + (thumbImg->width - trim_width) / 2; j++) { unsigned short r_, g_, b_; - 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]; - tmpdata[ix++] = (r*19595+g*38469+b*7472) >> 16; + 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]; + tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } - } - else { + } else { // If it's not gamma corrected (usually a JPG) we take the normal maximum - max=0; + max = 0; if (thumbImg->getType() == sImage8) { Image8 *image = static_cast(thumbImg); - unsigned char max_=0; + unsigned char max_ = 0; - for (int row=0; rowheight; row++) - for (int col=0; colwidth; col++) { - if (image->r(row,col)>max_) max_ = image->r(row,col); - if (image->g(row,col)>max_) max_ = image->g(row,col); - if (image->b(row,col)>max_) max_ = image->b(row,col); + for (int row = 0; row < image->height; row++) + for (int col = 0; col < image->width; col++) { + if (image->r(row, col) > max_) { + max_ = image->r(row, col); + } + + if (image->g(row, col) > max_) { + max_ = image->g(row, col); + } + + if (image->b(row, col) > max_) { + max_ = image->b(row, col); + } } + image->convertTo(max_, max); - if (max < 16384) max = 16384; - scaleForSave = 65535*8192 / max; + if (max < 16384) { + max = 16384; + } + + scaleForSave = 65535 * 8192 / max; // Correction and gamma to 8 Bit - for (int i=0; iheight; i++) - for (int j=(image->width-trim_width)/2; jwidth-trim_width)/2; j++) { + for (int i = 0; i < image->height; i++) + for (int j = (image->width - trim_width) / 2; j < trim_width + (image->width - trim_width) / 2; j++) { unsigned short rtmp, gtmp, btmp; - image->convertTo(image->r(i,j), rtmp); - image->convertTo(image->g(i,j), gtmp); - image->convertTo(image->b(i,j), btmp); + image->convertTo(image->r(i, j), rtmp); + image->convertTo(image->g(i, j), gtmp); + image->convertTo(image->b(i, j), btmp); int r = rtmp * scaleForSave >> 21; int g = gtmp * scaleForSave >> 21; int b = btmp * scaleForSave >> 21; - tmpdata[ix++] = (r*19595+g*38469+b*7472)>>16; + tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } - } - else if (thumbImg->getType() == sImage16) { + } else if (thumbImg->getType() == sImage16) { Image16 *image = static_cast(thumbImg); - unsigned short max_=0; + unsigned short max_ = 0; - for (int row=0; rowheight; row++) - for (int col=0; colwidth; col++) { - if (image->r(row,col)>max_) max_ = image->r(row,col); - if (image->g(row,col)>max_) max_ = image->g(row,col); - if (image->b(row,col)>max_) max_ = image->b(row,col); + for (int row = 0; row < image->height; row++) + for (int col = 0; col < image->width; col++) { + if (image->r(row, col) > max_) { + max_ = image->r(row, col); + } + + if (image->g(row, col) > max_) { + max_ = image->g(row, col); + } + + if (image->b(row, col) > max_) { + max_ = image->b(row, col); + } } + image->convertTo(max_, max); - if (max < 16384) max = 16384; - scaleForSave = 65535*8192 / max; + if (max < 16384) { + max = 16384; + } + + scaleForSave = 65535 * 8192 / max; // Correction and gamma to 8 Bit - for (int i=0; iheight; i++) - for (int j=(image->width-trim_width)/2; jwidth-trim_width)/2; j++) { + for (int i = 0; i < image->height; i++) + for (int j = (image->width - trim_width) / 2; j < trim_width + (image->width - trim_width) / 2; j++) { unsigned short rtmp, gtmp, btmp; - image->convertTo(image->r(i,j), rtmp); - image->convertTo(image->g(i,j), gtmp); - image->convertTo(image->b(i,j), btmp); + image->convertTo(image->r(i, j), rtmp); + image->convertTo(image->g(i, j), gtmp); + image->convertTo(image->b(i, j), btmp); int r = rtmp * scaleForSave >> 21; int g = gtmp * scaleForSave >> 21; int b = btmp * scaleForSave >> 21; - tmpdata[ix++] = (r*19595+g*38469+b*7472)>>16; + tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } - } - else if (thumbImg->getType() == sImagefloat) { + } else if (thumbImg->getType() == sImagefloat) { Imagefloat *image = static_cast(thumbImg); - float max_=0.f; + float max_ = 0.f; - for (int row=0; rowheight; row++) - for (int col=0; colwidth; col++) { - if (image->r(row,col)>max_) max_ = image->r(row,col); - if (image->g(row,col)>max_) max_ = image->g(row,col); - if (image->b(row,col)>max_) max_ = image->b(row,col); + for (int row = 0; row < image->height; row++) + for (int col = 0; col < image->width; col++) { + if (image->r(row, col) > max_) { + max_ = image->r(row, col); + } + + if (image->g(row, col) > max_) { + max_ = image->g(row, col); + } + + if (image->b(row, col) > max_) { + max_ = image->b(row, col); + } } + image->convertTo(max_, max); - if (max < 16384) max = 16384; - scaleForSave = 65535*8192 / max; + if (max < 16384) { + max = 16384; + } + + scaleForSave = 65535 * 8192 / max; // Correction and gamma to 8 Bit - for (int i=0; iheight; i++) - for (int j=(image->width-trim_width)/2; jwidth-trim_width)/2; j++) { + for (int i = 0; i < image->height; i++) + for (int j = (image->width - trim_width) / 2; j < trim_width + (image->width - trim_width) / 2; j++) { unsigned short rtmp, gtmp, btmp; - image->convertTo(image->r(i,j), rtmp); - image->convertTo(image->g(i,j), gtmp); - image->convertTo(image->b(i,j), btmp); + image->convertTo(image->r(i, j), rtmp); + image->convertTo(image->g(i, j), gtmp); + image->convertTo(image->b(i, j), btmp); int r = rtmp * scaleForSave >> 21; int g = gtmp * scaleForSave >> 21; int b = btmp * scaleForSave >> 21; - tmpdata[ix++] = (r*19595+g*38469+b*7472)>>16; + tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } - } - else { + } else { printf("getGrayscaleHistEQ #2: Unsupported image type \"%s\"!\n", thumbImg->getType()); } } @@ -1418,38 +1618,46 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) { // histogram equalization unsigned int hist[256] = {0}; - for (int i=0; i0 && cdf_min==-1) { - cdf_min=cdf; + int cdf = 0, cdf_min = -1; + + for (int i = 0; i < 256; i++) { + cdf += hist[i]; + + if (cdf > 0 && cdf_min == -1) { + cdf_min = cdf; } - if (cdf_min!=-1) { - hist[i] = (cdf-cdf_min)*255/((thumbImg->height*trim_width)-cdf_min); + + if (cdf_min != -1) { + hist[i] = (cdf - cdf_min) * 255 / ((thumbImg->height * trim_width) - cdf_min); } } - for (int i=0; igetType(), sizeof (char), strlen(thumbImg->getType()), f); fputc ('\n', f); guint32 w = guint32(thumbImg->width); @@ -1460,12 +1668,10 @@ bool Thumbnail::writeImage (const Glib::ustring& fname, int format) { if (thumbImg->getType() == sImage8) { Image8 *image = static_cast(thumbImg); image->writeData(f); - } - else if (thumbImg->getType() == sImage16) { + } else if (thumbImg->getType() == sImage16) { Image16 *image = static_cast(thumbImg); image->writeData(f); - } - else if (thumbImg->getType() == sImagefloat) { + } else if (thumbImg->getType() == sImagefloat) { Imagefloat *image = static_cast(thumbImg); image->writeData(f); } @@ -1475,119 +1681,172 @@ bool Thumbnail::writeImage (const Glib::ustring& fname, int format) { return true; } -bool Thumbnail::readImage (const Glib::ustring& fname) { - +bool Thumbnail::readImage (const Glib::ustring& fname) +{ + if (thumbImg) { delete thumbImg; thumbImg = NULL; } - Glib::ustring fullFName = fname+".rtti"; + Glib::ustring fullFName = fname + ".rtti"; - if (!safe_file_test (fullFName, Glib::FILE_TEST_EXISTS)) + if (!safe_file_test (fullFName, Glib::FILE_TEST_EXISTS)) { return false; + } FILE* f = safe_g_fopen (fullFName, "rb"); - if (!f) + + if (!f) { return false; + } char imgType[31]; // 30 -> arbitrary size, but should be enough for all image type's name fgets(imgType, 30, f); - imgType[strlen(imgType)-1] = '\0'; // imgType has a \n trailing character, so we overwrite it by the \0 char + imgType[strlen(imgType) - 1] = '\0'; // imgType has a \n trailing character, so we overwrite it by the \0 char guint32 width, height; fread (&width, 1, sizeof (guint32), f); fread (&height, 1, sizeof (guint32), f); bool success = false; + if (!strcmp(imgType, sImage8)) { Image8 *image = new Image8(width, height); image->readData(f); thumbImg = image; success = true; - } - else if (!strcmp(imgType, sImage16)) { + } else if (!strcmp(imgType, sImage16)) { Image16 *image = new Image16(width, height); image->readData(f); thumbImg = image; success = true; - } - else if (!strcmp(imgType, sImagefloat)) { + } else if (!strcmp(imgType, sImagefloat)) { Imagefloat *image = new Imagefloat(width, height); image->readData(f); thumbImg = image; success = true; - } - else { + } else { printf("readImage: Unsupported image type \"%s\"!\n", imgType); } + fclose(f); return success; } -bool Thumbnail::readData (const Glib::ustring& fname) { +bool Thumbnail::readData (const Glib::ustring& fname) +{ setlocale(LC_NUMERIC, "C"); // to set decimal point to "." SafeKeyFile keyFile; - + try { MyMutex::MyLock thmbLock(thumbMutex); - if (!keyFile.load_from_file (fname)) - return false; - if (keyFile.has_group ("LiveThumbData")) { - if (keyFile.has_key ("LiveThumbData", "CamWBRed")) camwbRed = keyFile.get_double ("LiveThumbData", "CamWBRed"); - if (keyFile.has_key ("LiveThumbData", "CamWBGreen")) camwbGreen = keyFile.get_double ("LiveThumbData", "CamWBGreen"); - if (keyFile.has_key ("LiveThumbData", "CamWBBlue")) camwbBlue = keyFile.get_double ("LiveThumbData", "CamWBBlue"); - if (keyFile.has_key ("LiveThumbData", "RedAWBMul")) redAWBMul = keyFile.get_double ("LiveThumbData", "RedAWBMul"); - if (keyFile.has_key ("LiveThumbData", "GreenAWBMul")) greenAWBMul = keyFile.get_double ("LiveThumbData", "GreenAWBMul"); - if (keyFile.has_key ("LiveThumbData", "BlueAWBMul")) blueAWBMul = keyFile.get_double ("LiveThumbData", "BlueAWBMul"); - if (keyFile.has_key ("LiveThumbData", "AEHistCompression")) aeHistCompression = keyFile.get_integer ("LiveThumbData", "AEHistCompression"); - if (keyFile.has_key ("LiveThumbData", "RedMultiplier")) redMultiplier = keyFile.get_double ("LiveThumbData", "RedMultiplier"); - if (keyFile.has_key ("LiveThumbData", "GreenMultiplier")) greenMultiplier = keyFile.get_double ("LiveThumbData", "GreenMultiplier"); - if (keyFile.has_key ("LiveThumbData", "BlueMultiplier")) blueMultiplier = keyFile.get_double ("LiveThumbData", "BlueMultiplier"); - if (keyFile.has_key ("LiveThumbData", "Scale")) scale = keyFile.get_double ("LiveThumbData", "Scale"); - if (keyFile.has_key ("LiveThumbData", "DefaultGain")) defGain = keyFile.get_double ("LiveThumbData", "DefaultGain"); - if (keyFile.has_key ("LiveThumbData", "ScaleForSave")) scaleForSave = keyFile.get_integer ("LiveThumbData", "ScaleForSave"); - if (keyFile.has_key ("LiveThumbData", "GammaCorrected")) gammaCorrected = keyFile.get_boolean ("LiveThumbData", "GammaCorrected"); + if (!keyFile.load_from_file (fname)) { + return false; + } + + if (keyFile.has_group ("LiveThumbData")) { + if (keyFile.has_key ("LiveThumbData", "CamWBRed")) { + camwbRed = keyFile.get_double ("LiveThumbData", "CamWBRed"); + } + + if (keyFile.has_key ("LiveThumbData", "CamWBGreen")) { + camwbGreen = keyFile.get_double ("LiveThumbData", "CamWBGreen"); + } + + if (keyFile.has_key ("LiveThumbData", "CamWBBlue")) { + camwbBlue = keyFile.get_double ("LiveThumbData", "CamWBBlue"); + } + + if (keyFile.has_key ("LiveThumbData", "RedAWBMul")) { + redAWBMul = keyFile.get_double ("LiveThumbData", "RedAWBMul"); + } + + if (keyFile.has_key ("LiveThumbData", "GreenAWBMul")) { + greenAWBMul = keyFile.get_double ("LiveThumbData", "GreenAWBMul"); + } + + if (keyFile.has_key ("LiveThumbData", "BlueAWBMul")) { + blueAWBMul = keyFile.get_double ("LiveThumbData", "BlueAWBMul"); + } + + if (keyFile.has_key ("LiveThumbData", "AEHistCompression")) { + aeHistCompression = keyFile.get_integer ("LiveThumbData", "AEHistCompression"); + } + + if (keyFile.has_key ("LiveThumbData", "RedMultiplier")) { + redMultiplier = keyFile.get_double ("LiveThumbData", "RedMultiplier"); + } + + if (keyFile.has_key ("LiveThumbData", "GreenMultiplier")) { + greenMultiplier = keyFile.get_double ("LiveThumbData", "GreenMultiplier"); + } + + if (keyFile.has_key ("LiveThumbData", "BlueMultiplier")) { + blueMultiplier = keyFile.get_double ("LiveThumbData", "BlueMultiplier"); + } + + if (keyFile.has_key ("LiveThumbData", "Scale")) { + scale = keyFile.get_double ("LiveThumbData", "Scale"); + } + + if (keyFile.has_key ("LiveThumbData", "DefaultGain")) { + defGain = keyFile.get_double ("LiveThumbData", "DefaultGain"); + } + + if (keyFile.has_key ("LiveThumbData", "ScaleForSave")) { + scaleForSave = keyFile.get_integer ("LiveThumbData", "ScaleForSave"); + } + + if (keyFile.has_key ("LiveThumbData", "GammaCorrected")) { + gammaCorrected = keyFile.get_boolean ("LiveThumbData", "GammaCorrected"); + } + if (keyFile.has_key ("LiveThumbData", "ColorMatrix")) { std::vector cm = keyFile.get_double_list ("LiveThumbData", "ColorMatrix"); int ix = 0; - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { colorMatrix[i][j] = cm[ix++]; + } } } + return true; - } - catch (Glib::Error &err) { - if (options.rtSettings.verbose) + } catch (Glib::Error &err) { + if (options.rtSettings.verbose) { printf("Thumbnail::readData / 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) + } + } catch (...) { + if (options.rtSettings.verbose) { printf("Thumbnail::readData / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); + } } return false; } -bool Thumbnail::writeData (const Glib::ustring& fname) { +bool Thumbnail::writeData (const Glib::ustring& fname) +{ SafeKeyFile keyFile; MyMutex::MyLock thmbLock(thumbMutex); try { - if( safe_file_test(fname,Glib::FILE_TEST_EXISTS) ) + if( safe_file_test(fname, Glib::FILE_TEST_EXISTS) ) { keyFile.load_from_file (fname); - } - catch (Glib::Error &err) { - if (options.rtSettings.verbose) + } + } 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()); - } - catch (...) { - if (options.rtSettings.verbose) + } + } catch (...) { + if (options.rtSettings.verbose) { printf("Thumbnail::writeData / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); + } } keyFile.set_double ("LiveThumbData", "CamWBRed", camwbRed); @@ -1608,27 +1867,31 @@ bool Thumbnail::writeData (const Glib::ustring& fname) { keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm); FILE *f = safe_g_fopen (fname, "wt"); + if (!f) { - if (options.rtSettings.verbose) + if (options.rtSettings.verbose) { printf("Thumbnail::writeData / Error: unable to open file \"%s\" with write access!\n", fname.c_str()); + } + return false; - } - else { + } else { fprintf (f, "%s", keyFile.to_data().c_str()); fclose (f); } + return true; } -bool Thumbnail::readEmbProfile (const Glib::ustring& fname) { +bool Thumbnail::readEmbProfile (const Glib::ustring& fname) +{ FILE* f = safe_g_fopen (fname, "rb"); + if (!f) { embProfileData = NULL; embProfile = NULL; embProfileLength = 0; - } - else { + } else { fseek (f, 0, SEEK_END); embProfileLength = ftell (f); fseek (f, 0, SEEK_SET); @@ -1638,54 +1901,66 @@ bool Thumbnail::readEmbProfile (const Glib::ustring& fname) { embProfile = cmsOpenProfileFromMem (embProfileData, embProfileLength); return true; } + return false; } -bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) { - +bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) +{ + if (embProfileData) { FILE* f = safe_g_fopen(fname, "wb"); + if (f) { fwrite (embProfileData, 1, embProfileLength, f); fclose (f); return true; } } + return false; } -bool Thumbnail::readAEHistogram (const Glib::ustring& fname) { +bool Thumbnail::readAEHistogram (const Glib::ustring& fname) +{ FILE* f = safe_g_fopen (fname, "rb"); - if (!f) + + if (!f) { aeHistogram(0); - else { - aeHistogram(65536>>aeHistCompression); - fread (&aeHistogram[0], 1, (65536>>aeHistCompression)*sizeof(aeHistogram[0]), f); + } else { + aeHistogram(65536 >> aeHistCompression); + fread (&aeHistogram[0], 1, (65536 >> aeHistCompression)*sizeof(aeHistogram[0]), f); fclose (f); return true; } + return false; } -bool Thumbnail::writeAEHistogram (const Glib::ustring& fname) { +bool Thumbnail::writeAEHistogram (const Glib::ustring& fname) +{ if (aeHistogram) { FILE* f = safe_g_fopen (fname, "wb"); + if (f) { - fwrite (&aeHistogram[0], 1, (65536>>aeHistCompression)*sizeof(aeHistogram[0]), f); + fwrite (&aeHistogram[0], 1, (65536 >> aeHistCompression)*sizeof(aeHistogram[0]), f); fclose (f); return true; } } + return false; } -unsigned char* Thumbnail::getImage8Data() { - if (thumbImg && thumbImg->getType()==rtengine::sImage8) { +unsigned char* Thumbnail::getImage8Data() +{ + if (thumbImg && thumbImg->getType() == rtengine::sImage8) { Image8* img8 = static_cast(thumbImg); return img8->data; } + return NULL; } diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 393241eb7..dd9d8e9ca 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -7,7 +7,7 @@ * 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 @@ -28,130 +28,133 @@ #include "imagefloat.h" #include "../rtgui/threadutils.h" -namespace rtengine { +namespace rtengine +{ - class Thumbnail { +class Thumbnail +{ - MyMutex thumbMutex; + MyMutex thumbMutex; - cmsHPROFILE camProfile; - double iColorMatrix[3][3]; - double cam2xyz[3][3]; + cmsHPROFILE camProfile; + double iColorMatrix[3][3]; + double cam2xyz[3][3]; - void transformPixel (int x, int y, int tran, int& tx, int& ty); + void transformPixel (int x, int y, int tran, int& tx, int& ty); - static unsigned short *igammatab; - static unsigned char *gammatab; + static unsigned short *igammatab; + static unsigned char *gammatab; - ImageIO* thumbImg; - double camwbRed; - double camwbGreen; - double camwbBlue; - double redAWBMul, greenAWBMul, blueAWBMul; // multipliers for auto WB - double autoWBTemp, autoWBGreen, wbEqual; // autoWBTemp and autoWBGreen are updated each time autoWB is requested and if wbEqual has been modified - LUTu aeHistogram; - int aeHistCompression; - int embProfileLength; - unsigned char* embProfileData; - cmsHPROFILE embProfile; - double redMultiplier; - double greenMultiplier; - double blueMultiplier; - double scale; - double defGain; - int scaleForSave; - bool gammaCorrected; - double colorMatrix[3][3]; + ImageIO* thumbImg; + double camwbRed; + double camwbGreen; + double camwbBlue; + double redAWBMul, greenAWBMul, blueAWBMul; // multipliers for auto WB + double autoWBTemp, autoWBGreen, wbEqual; // autoWBTemp and autoWBGreen are updated each time autoWB is requested and if wbEqual has been modified + LUTu aeHistogram; + int aeHistCompression; + int embProfileLength; + unsigned char* embProfileData; + cmsHPROFILE embProfile; + double redMultiplier; + double greenMultiplier; + double blueMultiplier; + double scale; + double defGain; + int scaleForSave; + bool gammaCorrected; + double colorMatrix[3][3]; - public: +public: - bool isRaw; - - ~Thumbnail (); - Thumbnail (); - - static void initGamma (); - static void cleanupGamma (); - void init (); - - IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, - double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& scale); - IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale); - int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio); - void getDimensions (int& w, int& h, double& scaleFac); - - static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode=false); - static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate); - static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode=false); - static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname); - - void getCamWB (double& temp, double& green); - void getAutoWB (double& temp, double& green, double equal); - void getAutoWBMultipliers (double& rm, double& gm, double& bm); - void getSpotWB (const procparams::ProcParams& params, int x, int y, int rect, double& temp, double& green); - void applyAutoExp (procparams::ProcParams& pparams); - - unsigned char* getGrayscaleHistEQ (int trim_width); - bool writeImage (const Glib::ustring& fname, int format); - bool readImage (const Glib::ustring& fname); - - bool readData (const Glib::ustring& fname); - bool writeData (const Glib::ustring& fname); - - bool readEmbProfile (const Glib::ustring& fname); - bool writeEmbProfile (const Glib::ustring& fname); + bool isRaw; - bool readAEHistogram (const Glib::ustring& fname); - bool writeAEHistogram (const Glib::ustring& fname); + ~Thumbnail (); + Thumbnail (); - unsigned char* getImage8Data(); // accessor to the 8bit image if it is one, which should be the case for the "Inspector" mode. + static void initGamma (); + static void cleanupGamma (); + void init (); - // Hombre: ... let's hope that proper template can make this cleaner + IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, + double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& scale); + IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale); + int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio); + void getDimensions (int& w, int& h, double& scaleFac); - static ImageIO* resizeToSameType(int nw, int nh, TypeInterpolation interp, ImageIO* srcImg) { - ImageIO* imgPtr; - if (srcImg->getType() == sImage8) { - Image8* castedSrcImg = static_cast(srcImg); - Image8* img8 = new Image8 (nw, nh); - castedSrcImg->resizeImgTo(nw, nh, interp, img8); - imgPtr = img8; - } - else if (srcImg->getType() == sImage16) { - Image16* castedSrcImg = static_cast(srcImg); - Image16* img16 = new Image16 (nw, nh); - castedSrcImg->resizeImgTo(nw, nh, interp, img16); - imgPtr = img16; - } - else if (srcImg->getType() == sImagefloat) { - Imagefloat* castedSrcImg = static_cast(srcImg); - Imagefloat* imgfloat = new Imagefloat (nw, nh); - castedSrcImg->resizeImgTo(nw, nh, interp, imgfloat); - imgPtr = imgfloat; - } - return imgPtr; - } + static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false); + static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate); + static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false); + static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname); - template - static IC* resizeTo(int nw, int nh, TypeInterpolation interp, ImageIO* srcImg) { + void getCamWB (double& temp, double& green); + void getAutoWB (double& temp, double& green, double equal); + void getAutoWBMultipliers (double& rm, double& gm, double& bm); + void getSpotWB (const procparams::ProcParams& params, int x, int y, int rect, double& temp, double& green); + void applyAutoExp (procparams::ProcParams& pparams); - IC* imgPtr = new IC (nw, nh); + unsigned char* getGrayscaleHistEQ (int trim_width); + bool writeImage (const Glib::ustring& fname, int format); + bool readImage (const Glib::ustring& fname); - // Hombre: ... let's hope that proper template can make this cleaner + bool readData (const Glib::ustring& fname); + bool writeData (const Glib::ustring& fname); - if (srcImg->getType() == sImage8) { - Image8* castedSrcImg = static_cast(srcImg); - castedSrcImg->resizeImgTo<>(nw, nh, interp, imgPtr); - } - else if (srcImg->getType() == sImage16) { - Image16* castedSrcImg = static_cast(srcImg); - castedSrcImg->resizeImgTo<>(nw, nh, interp, imgPtr); - } - else if (srcImg->getType() == sImagefloat) { - Imagefloat* castedSrcImg = static_cast(srcImg); - castedSrcImg->resizeImgTo<>(nw, nh, interp, imgPtr); - } - return imgPtr; - }; + bool readEmbProfile (const Glib::ustring& fname); + bool writeEmbProfile (const Glib::ustring& fname); + + bool readAEHistogram (const Glib::ustring& fname); + bool writeAEHistogram (const Glib::ustring& fname); + + unsigned char* getImage8Data(); // accessor to the 8bit image if it is one, which should be the case for the "Inspector" mode. + + // Hombre: ... let's hope that proper template can make this cleaner + + static ImageIO* resizeToSameType(int nw, int nh, TypeInterpolation interp, ImageIO* srcImg) + { + ImageIO* imgPtr; + + if (srcImg->getType() == sImage8) { + Image8* castedSrcImg = static_cast(srcImg); + Image8* img8 = new Image8 (nw, nh); + castedSrcImg->resizeImgTo(nw, nh, interp, img8); + imgPtr = img8; + } else if (srcImg->getType() == sImage16) { + Image16* castedSrcImg = static_cast(srcImg); + Image16* img16 = new Image16 (nw, nh); + castedSrcImg->resizeImgTo(nw, nh, interp, img16); + imgPtr = img16; + } else if (srcImg->getType() == sImagefloat) { + Imagefloat* castedSrcImg = static_cast(srcImg); + Imagefloat* imgfloat = new Imagefloat (nw, nh); + castedSrcImg->resizeImgTo(nw, nh, interp, imgfloat); + imgPtr = imgfloat; + } + + return imgPtr; + } + + template + static IC* resizeTo(int nw, int nh, TypeInterpolation interp, ImageIO* srcImg) + { + + IC* imgPtr = new IC (nw, nh); + + // Hombre: ... let's hope that proper template can make this cleaner + + if (srcImg->getType() == sImage8) { + Image8* castedSrcImg = static_cast(srcImg); + castedSrcImg->resizeImgTo<>(nw, nh, interp, imgPtr); + } else if (srcImg->getType() == sImage16) { + Image16* castedSrcImg = static_cast(srcImg); + castedSrcImg->resizeImgTo<>(nw, nh, interp, imgPtr); + } else if (srcImg->getType() == sImagefloat) { + Imagefloat* castedSrcImg = static_cast(srcImg); + castedSrcImg->resizeImgTo<>(nw, nh, interp, imgPtr); + } + + return imgPtr; + }; }; } diff --git a/rtengine/safegtk.cc b/rtengine/safegtk.cc index d0931f4a1..a1e45b998 100644 --- a/rtengine/safegtk.cc +++ b/rtengine/safegtk.cc @@ -9,7 +9,7 @@ * 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 @@ -40,101 +40,114 @@ 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; + 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; + 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; + Glib::RefPtr info; #ifdef GLIBMM_EXCEPTIONS_ENABLED - try { info = file->query_info(); }catch (...) { } + + try { + info = file->query_info(); + } catch (...) { } + #else - std::auto_ptr error; - info = file->query_info("*", Gio::FILE_QUERY_INFO_NONE, error); + std::auto_ptr error; + info = file->query_info("*", Gio::FILE_QUERY_INFO_NONE, error); #endif - return info; + return info; } Glib::RefPtr safe_next_file (Glib::RefPtr &dirList) { - Glib::RefPtr info; + Glib::RefPtr info; #ifdef GLIBMM_EXCEPTIONS_ENABLED - 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); + 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); + #else - bool retry; - Glib::ustring last_error = ""; - do { - retry = false; - std::auto_ptr error; - Glib::RefPtr cancellable; - info = dirList->next_file(cancellable, error); - if (!info && error.get()) { - printf ("%s\n", error.what().c_str()); - retry = (error.what() != last_error); - last_error = error.what(); - } - } while (retry); + bool retry; + Glib::ustring last_error = ""; + + do { + retry = false; + std::auto_ptr error; + Glib::RefPtr cancellable; + info = dirList->next_file(cancellable, error); + + if (!info && error.get()) { + printf ("%s\n", error.what().c_str()); + retry = (error.what() != last_error); + last_error = error.what(); + } + } while (retry); + #endif - return info; + return info; } #ifdef GLIBMM_EXCEPTIONS_ENABLED # define SAFE_ENUMERATOR_CODE_START \ - do{try { if ((dirList = dir->enumerate_children ())) \ - for (Glib::RefPtr info = safe_next_file(dirList); info; info = safe_next_file(dirList)) { - + do{try { if ((dirList = dir->enumerate_children ())) \ + 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) + }} catch (Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); }}while(0) #else # define SAFE_ENUMERATOR_CODE_START \ - do{std::auto_ptr error; Glib::RefPtr cancellable; \ - if ((dirList = dir->enumerate_children (cancellable, "*", Gio::FILE_QUERY_INFO_NONE, error))) \ - for (Glib::RefPtr info = safe_next_file(dirList); info; info = safe_next_file(dirList)) { - -# define SAFE_ENUMERATOR_CODE_END } if (error.get()) printf ("%s\n", error->what().c_str());}while (0) + do{std::auto_ptr error; Glib::RefPtr cancellable; \ + if ((dirList = dir->enumerate_children (cancellable, "*", Gio::FILE_QUERY_INFO_NONE, error))) \ + for (Glib::RefPtr info = safe_next_file(dirList); info; info = safe_next_file(dirList)) { + +# define SAFE_ENUMERATOR_CODE_END } if (error.get()) printf ("%s\n", error->what().c_str());}while (0) #endif #ifdef WIN32 @@ -142,31 +155,31 @@ Glib::RefPtr safe_next_file (Glib::RefPtr &d // High speed Windows version void safe_build_file_list (Glib::RefPtr &dir, std::vector &flist) { - Glib::ustring fullPath=dir->get_path() + Glib::ustring("\\*"); + Glib::ustring fullPath = dir->get_path() + Glib::ustring("\\*"); - DWORD dwVersion=GetVersion(); - bool win7Plus=(LOBYTE(LOWORD(dwVersion))>6) || ((LOBYTE(LOWORD(dwVersion))==6) && HIBYTE(LOWORD(dwVersion))>=1); // 6.1 or better + DWORD dwVersion = GetVersion(); + bool win7Plus = (LOBYTE(LOWORD(dwVersion)) > 6) || ((LOBYTE(LOWORD(dwVersion)) == 6) && HIBYTE(LOWORD(dwVersion)) >= 1); // 6.1 or better wchar_t *wDirName = (wchar_t*)g_utf8_to_utf16 (fullPath.c_str(), -1, NULL, NULL, NULL); WIN32_FIND_DATAW fi; - HANDLE hFF=FindFirstFileExW(wDirName, - //win7Plus ? FindExInfoBasic : // TODO: Add if MinGW is updated, makes it even faster - FindExInfoStandard,&fi, - FindExSearchNameMatch,NULL, - win7Plus ? 2 : 0); // Win7 large fetch + HANDLE hFF = FindFirstFileExW(wDirName, + //win7Plus ? FindExInfoBasic : // TODO: Add if MinGW is updated, makes it even faster + FindExInfoStandard, &fi, + FindExSearchNameMatch, NULL, + win7Plus ? 2 : 0); // Win7 large fetch if (hFF != INVALID_HANDLE_VALUE) { do { SYSTEMTIME stUTC; FileTimeToSystemTime(&fi.ftLastWriteTime, &stUTC); char time[64]; - sprintf(time,"%d-%02d-%02dT%02d:%02d:%02dZ",stUTC.wYear,stUTC.wMonth,stUTC.wDay,stUTC.wHour,stUTC.wMinute,stUTC.wSecond); + sprintf(time, "%d-%02d-%02dT%02d:%02d:%02dZ", stUTC.wYear, stUTC.wMonth, stUTC.wDay, stUTC.wHour, stUTC.wMinute, stUTC.wSecond); Glib::TimeVal timeVal; timeVal.assign_from_iso8601(Glib::ustring(time)); char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8,0,(WCHAR*)fi.cFileName,-1,pathA,MAX_PATH,0,0); + WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)fi.cFileName, -1, pathA, MAX_PATH, 0, 0); flist.push_back (FileMTimeInfo (removeExtension(Glib::ustring(pathA)), timeVal)); } while (FindNextFileW(hFF, &fi)); @@ -181,12 +194,13 @@ void safe_build_file_list (Glib::RefPtr &dir, std::vector &dir, std::vector &flist) { - Glib::RefPtr dirList; - if (dir) { - SAFE_ENUMERATOR_CODE_START - flist.push_back (FileMTimeInfo (removeExtension(info->get_name()), info->modification_time())); - SAFE_ENUMERATOR_CODE_END; - } + Glib::RefPtr dirList; + + if (dir) { + SAFE_ENUMERATOR_CODE_START + flist.push_back (FileMTimeInfo (removeExtension(info->get_name()), info->modification_time())); + SAFE_ENUMERATOR_CODE_END; + } } #endif /* @@ -194,57 +208,65 @@ void safe_build_file_list (Glib::RefPtr &dir, std::vector &dir, std::vector &names, const Glib::ustring &directory, const std::vector *extensions) { - Glib::RefPtr dirList; + Glib::RefPtr dirList; - if (dir) { - if (!extensions) { - SAFE_ENUMERATOR_CODE_START - 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; isize(); i++) - lcExtensions.push_back ((*extensions)[i].lowercase()); + if (dir) { + if (!extensions) { + SAFE_ENUMERATOR_CODE_START + 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; - SAFE_ENUMERATOR_CODE_START - // convert the current filename to lowercase in a new ustring - Glib::ustring fname = Glib::ustring(info->get_name()).lowercase(); + for (unsigned int i = 0; i < extensions->size(); i++) { + lcExtensions.push_back ((*extensions)[i].lowercase()); + } - size_t pos = fname.find_last_of('.'); - if (pos < (fname.length()-1)) { - // there is an extension to the filename + SAFE_ENUMERATOR_CODE_START + // convert the current filename to lowercase in a new ustring + Glib::ustring fname = Glib::ustring(info->get_name()).lowercase(); - Glib::ustring lcFileExt = fname.substr(pos+1).lowercase(); + size_t pos = fname.find_last_of('.'); - // look out if it has one of the retained extensions - for (size_t i=0; iget_name())); - break; - } - } - } - SAFE_ENUMERATOR_CODE_END; - } - } + 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; + Glib::RefPtr dirList; - SAFE_ENUMERATOR_CODE_START - if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden)) - subDirs.push_back (info->get_name()); - SAFE_ENUMERATOR_CODE_END; - } + 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 + + if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden)) { + subDirs.push_back (info->get_name()); + } + + SAFE_ENUMERATOR_CODE_END; + } } /* @@ -253,246 +275,284 @@ void safe_build_subdir_list (Glib::RefPtr &dir, std::vector error; - utf8_str = locale_to_utf8(src, error); - if (error.get()) - utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1","?", error); - } + { + std::auto_ptr error; + utf8_str = locale_to_utf8(src, error); + + if (error.get()) { + utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1", "?", error); + } + } #endif //GLIBMM_EXCEPTIONS_ENABLED #else - utf8_str = Glib::filename_to_utf8(src); + utf8_str = Glib::filename_to_utf8(src); #endif - return utf8_str; + return utf8_str; } Glib::ustring safe_locale_to_utf8 (const std::string& src) { - Glib::ustring utf8_str; + Glib::ustring utf8_str; #ifdef GLIBMM_EXCEPTIONS_ENABLED - 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","?"); - } + + 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 - { - std::auto_ptr error; - utf8_str = locale_to_utf8(src, error); - if (error.get()) - utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1","?", error); - } + { + std::auto_ptr error; + utf8_str = locale_to_utf8(src, error); + + if (error.get()) { + utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1", "?", error); + } + } #endif //GLIBMM_EXCEPTIONS_ENABLED - return utf8_str; + return utf8_str; } std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str) { - std::string str; + std::string str; #ifdef GLIBMM_EXCEPTIONS_ENABLED - try { - str = Glib::locale_from_utf8(utf8_str); - } - catch (const Glib::Error& e) { - //str = Glib::convert_with_fallback(utf8_str, "ISO-8859-1", "UTF-8", "?"); - } + + try { + str = Glib::locale_from_utf8(utf8_str); + } catch (const Glib::Error& e) { + //str = Glib::convert_with_fallback(utf8_str, "ISO-8859-1", "UTF-8", "?"); + } + #else - { - std::auto_ptr error; - str = Glib::locale_from_utf8(utf8_str, error); - /*if (error.get()) - {str = Glib::convert_with_fallback(utf8_str, "ISO-8859-1", "UTF-8", "?", error);}*/ - } + { + std::auto_ptr error; + str = Glib::locale_from_utf8(utf8_str, error); + /*if (error.get()) + {str = Glib::convert_with_fallback(utf8_str, "ISO-8859-1", "UTF-8", "?", error);}*/ + } #endif //GLIBMM_EXCEPTIONS_ENABLED - return str; + return str; } bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8) { - std::string cmd; - bool success = false; + std::string cmd; + bool success = false; #ifdef GLIBMM_EXCEPTIONS_ENABLED - 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()); - } + + 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()); + } + #else - std::auto_ptr error; - cmd = Glib::filename_from_utf8(cmd_utf8, error); - if (!error.get()) { - printf ("command line: %s\n", cmd.c_str()); - Glib::spawn_command_line_async (cmd, error); - } - if (error.get()) - printf ("%s\n", error->what().c_str()); - else - success = true; + std::auto_ptr error; + cmd = Glib::filename_from_utf8(cmd_utf8, error); + + if (!error.get()) { + printf ("command line: %s\n", cmd.c_str()); + Glib::spawn_command_line_async (cmd, error); + } + + if (error.get()) { + printf ("%s\n", error->what().c_str()); + } else { + success = true; + } + #endif - return success; + 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()); + int exitStatus = -1; - // 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); + 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; +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); + // 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"); + } - if (hFile==INVALID_HANDLE_VALUE) - f=NULL; - else - f=_fdopen( _open_osfhandle((intptr_t)hFile, 0) , "wb"); #else - f = safe_g_fopen(fname, "wb"); + f = safe_g_fopen(fname, "wb"); #endif - return f; + return f; } // Covers old UNIX ::open, which expects ANSI instead of UTF8 on Windows -int safe_open_ReadOnly(const char *fname) { - int fd=-1; +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); + // 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); + } - // 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); + fd = ::open(fname, O_RDONLY); #endif - return fd; + return fd; } -FILE * safe_g_fopen(const Glib::ustring& src,const gchar *mode) +FILE * safe_g_fopen(const Glib::ustring& src, const gchar *mode) { - return g_fopen(src.c_str(),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); + return Glib::file_test (filename, test); } int safe_g_remove(const Glib::ustring& filename) { - return ::g_remove(filename.c_str()); + 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()); + 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); + return ::g_mkdir_with_parents(dirName.c_str(), mode); } -Glib::ustring safe_get_user_picture_dir() { - #ifdef WIN32 +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:\\"); + WCHAR pathW[MAX_PATH] = {0}; - #else + 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 +#endif } -Glib::ustring safe_get_user_home_dir() { - #ifdef WIN32 +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:\\"); + WCHAR pathW[MAX_PATH] = {0}; - #else + 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 +#endif } #ifdef WIN32 -Glib::ustring safe_get_user_profile_dir() { - WCHAR pathW[MAX_PATH]={0}; - if (SHGetSpecialFolderPathW(NULL,pathW,CSIDL_PROFILE,false)) { +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); + WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); return Glib::ustring(pathA); - } else return Glib::ustring("C:\\"); + } else { + return Glib::ustring("C:\\"); + } } #endif -Glib::ustring safe_get_user_desktop_dir() { - #ifdef WIN32 +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:\\"); + WCHAR pathW[MAX_PATH] = {0}; - #else + 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 +#endif } #ifdef WIN32 @@ -501,7 +561,8 @@ Glib::ustring safe_get_user_desktop_dir() { * * Warning: this function is a workaround for Windows platform, and not necessarily bullet proof */ -bool safe_is_shortcut_dir (const Glib::ustring& path) { +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 index 599a2e06d..f29c18d0b 100644 --- a/rtengine/safegtk.h +++ b/rtengine/safegtk.h @@ -8,19 +8,23 @@ Glib::RefPtr safe_create_from_file(const Glib::ustring& filename); Cairo::RefPtr safe_create_from_png(const Glib::ustring& filename); -class FileMTimeInfo { +class FileMTimeInfo +{ - public: - Glib::ustring fname; - Glib::TimeVal mtime; - - FileMTimeInfo (Glib::ustring name, Glib::TimeVal mtime) : fname(name), mtime(mtime) {} - bool operator<(const FileMTimeInfo& other) const { return mtime safe_query_file_info (Glib::RefPtr &file); void safe_build_file_list (Glib::RefPtr &dir, std::vector &flist); -void safe_build_file_list (Glib::RefPtr &dir, std::vector &names, const Glib::ustring &directory = "", const std::vector *extensions=NULL); +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); @@ -31,7 +35,7 @@ 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(const Glib::ustring& src, const gchar *mode); FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname); int safe_open_ReadOnly(const char *fname); diff --git a/rtengine/safekeyfile.h b/rtengine/safekeyfile.h index 8e2148ed7..8a934240e 100644 --- a/rtengine/safekeyfile.h +++ b/rtengine/safekeyfile.h @@ -2,108 +2,109 @@ #define SAFE_KEY_FILE_H_INCLUDED #include -namespace rtengine { - +namespace rtengine +{ + class SafeKeyFile : public Glib::KeyFile { - public : - +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) + 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) + 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);} + { 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); + { 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); + 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 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); + typedef std::vector DoubleArrayType; - 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; i 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; } - return tempdouble; - } -*/ + */ + typedef std::vector StringArrayType; - StringArrayType get_keys(const Glib::ustring& group_name) const - SAFE_KEY_FILE_METHOD_NOINIT(get_keys(group_name), get_keys(group_name,error), 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; ir(i,j),0.f) + lumi[1]*std::max(img->g(i,j),0.f) + lumi[2]*std::max(img->b(i,j),0.f); - } - + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + luminance[i][j] = lumi[0] * std::max(img->r(i, j), 0.f) + lumi[1] * std::max(img->g(i, j), 0.f) + lumi[2] * std::max(img->b(i, j), 0.f); + } + } -void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int skip) { +void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int skip) +{ if (!hq) { - fillLuminance( img, map, lumi); + fillLuminance( img, map, lumi); #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ - AlignedBufferMP* pBuffer = new AlignedBufferMP (max(W,H)); - gaussHorizontal (map, map, *pBuffer, W, H, radius); - gaussVertical (map, map, *pBuffer, W, H, radius); - delete pBuffer; -} + { + AlignedBufferMP* pBuffer = new AlignedBufferMP (max(W, H)); + gaussHorizontal (map, map, *pBuffer, W, H, radius); + gaussVertical (map, map, *pBuffer, W, H, radius); + delete pBuffer; + } } else { - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //experimental dirpyr shmap + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //experimental dirpyr shmap - float thresh = (100.f*radius);//1000; + float thresh = (100.f * radius); //1000; - // set up range function - // calculate size of Lookup table. That's possible because from a value k for all i>=k rangefn[i] will be exp(-10) - // So we use this fact and the automatic clip of lut to reduce the size of lut and the number of calculations to fill the lut - // In past this lut had only integer precision with rangefn[i] = 0 for all i>=k - // We set the last element to a small epsilon 1e-15 instead of zero to avoid divisions by zero - const int lutSize = thresh * sqrtf(10.f) + 1; - thresh *= thresh; - LUTf rangefn(lutSize); - for (int i=0; i(i)*i) / thresh ));//*intfactor; - } - rangefn[lutSize-1] = 1e-15f; - - // We need one temporary buffer - float ** buffer = allocArray (W, H); - - // the final result has to be in map - // for an even number of levels that means: map => buffer, buffer => map - // for an odd number of levels that means: buffer => map, map => buffer, buffer => map - // so let's calculate the number of levels first - // There are at least two levels - int numLevels=2; - int scale=2; - while (skip*scale<16) { - scale *= 2; - numLevels++; - } + // set up range function + // calculate size of Lookup table. That's possible because from a value k for all i>=k rangefn[i] will be exp(-10) + // So we use this fact and the automatic clip of lut to reduce the size of lut and the number of calculations to fill the lut + // In past this lut had only integer precision with rangefn[i] = 0 for all i>=k + // We set the last element to a small epsilon 1e-15 instead of zero to avoid divisions by zero + const int lutSize = thresh * sqrtf(10.f) + 1; + thresh *= thresh; + LUTf rangefn(lutSize); - float ** dirpyrlo[2]; - if(numLevels&1) { // odd number of levels, start with buffer - dirpyrlo[0] = buffer; - dirpyrlo[1] = map; - } else { // even number of levels, start with map - dirpyrlo[0] = map; - dirpyrlo[1] = buffer; - } + for (int i = 0; i < lutSize - 1; i++) { + rangefn[i] = xexpf(-min(10.f, (static_cast(i) * i) / thresh )); //*intfactor; + } - fillLuminance( img, dirpyrlo[0], lumi); + rangefn[lutSize - 1] = 1e-15f; - scale = 1; - int level=0; - int indx=0; - dirpyr_shmap(dirpyrlo[indx], dirpyrlo[1-indx], W, H, rangefn, level, scale ); - scale *= 2; - level ++; - indx = 1-indx; - while (skip*scale<16) { - dirpyr_shmap(dirpyrlo[indx], dirpyrlo[1-indx], W, H, rangefn, level, scale ); - scale *= 2; - level ++; - indx = 1-indx; - } + // We need one temporary buffer + float ** buffer = allocArray (W, H); - dirpyr_shmap(dirpyrlo[indx], dirpyrlo[1-indx], W, H, rangefn, level, scale ); + // the final result has to be in map + // for an even number of levels that means: map => buffer, buffer => map + // for an odd number of levels that means: buffer => map, map => buffer, buffer => map + // so let's calculate the number of levels first + // There are at least two levels + int numLevels = 2; + int scale = 2; - freeArray(buffer, H); + while (skip * scale < 16) { + scale *= 2; + numLevels++; + } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/* - // anti-alias filtering the result -#ifdef _OPENMP -#pragma omp for -#endif - for (int i=0; i0 && j>0 && i(buffer, H); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + /* + // anti-alias filtering the result + #ifdef _OPENMP + #pragma omp for + #endif + for (int i=0; i0 && j>0 && i _max_f) - _max_f = _val; - _avg += _val; + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + _val = map[i][j]; + + if (_val < _min_f) { + _min_f = _val; + } + + if (_val > _max_f) { + _max_f = _val; + } + + _avg += _val; + } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + if(_min_f < min_f ) { + min_f = _min_f; + } + + if(_max_f > max_f ) { + max_f = _max_f; + } } -#ifdef _OPENMP -#pragma omp critical -#endif -{ - if(_min_f < min_f ) - min_f = _min_f; - if(_max_f > max_f ) - max_f = _max_f; -} -} - _avg /= ((H)*(W)); + } + _avg /= ((H) * (W)); avg = _avg; } -void SHMap::forceStat (float max_, float min_, float avg_) { +void SHMap::forceStat (float max_, float min_, float avg_) +{ max_f = max_; min_f = min_; @@ -197,192 +223,228 @@ void SHMap::forceStat (float max_, float min_, float avg_) { SSEFUNCTION void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, LUTf & rangefn, int level, int scale) { - //scale is spacing of directional averaging weights + //scale is spacing of directional averaging weights - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // calculate weights, compute directionally weighted average + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // calculate weights, compute directionally weighted average - int scalewin, halfwin; + int scalewin, halfwin; - if(level < 2) { - halfwin = 1; - scalewin = halfwin*scale; + if(level < 2) { + halfwin = 1; + scalewin = halfwin * scale; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #if defined( __SSE2__ ) && defined( __x86_64__ ) - __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; + __m128 dirwtv, valv, normv, dftemp1v, dftemp2v; #endif // __SSE2__ - int j; + int j; #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - for(int i = 0; i < height; i++) { - float dirwt; - for(j = 0; j < scalewin; j++) { - float val=0.f; - float norm=0.f; - for(int inbr=max(i-scalewin,i%scale); inbr<=min(i+scalewin, height-1); inbr+=scale) { - for (int jnbr=j%scale; jnbr<=j+scalewin; jnbr+=scale) { - dirwt = ( rangefn[abs(data_fine[inbr][jnbr]-data_fine[i][j])] ); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j] = val/norm; // low pass filter - } + + for(int i = 0; i < height; i++) { + float dirwt; + + for(j = 0; j < scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(i - scalewin, i % scale); inbr <= min(i + scalewin, height - 1); inbr += scale) { + for (int jnbr = j % scale; jnbr <= j + scalewin; jnbr += scale) { + dirwt = ( rangefn[abs(data_fine[inbr][jnbr] - data_fine[i][j])] ); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; // low pass filter + } + #if defined( __SSE2__ ) && defined( __x86_64__ ) - int inbrMin = max(i-scalewin,i%scale); - for(; j < (width-scalewin)-3; j+=4) { - valv= _mm_setzero_ps(); - normv= _mm_setzero_ps(); - dftemp1v = LVFU(data_fine[i][j]); - for(int inbr=inbrMin; inbr<=min(i+scalewin, height-1); inbr+=scale) { - for (int jnbr=j-scalewin; jnbr<=j+scalewin; jnbr+=scale) { - dftemp2v = LVFU(data_fine[inbr][jnbr]); - dirwtv = ( rangefn[_mm_cvttps_epi32(vabsf(dftemp2v-dftemp1v))] ); - valv += dirwtv*dftemp2v; - normv += dirwtv; - } - } - _mm_storeu_ps( &data_coarse[i][j], valv/normv); - } - for(; j < width-scalewin; j++) { - float val=0.f; - float norm=0.f; - for(int inbr=inbrMin; inbr<=min(i+scalewin, height-1); inbr+=scale) { - for (int jnbr=j-scalewin; jnbr<=j+scalewin; jnbr+=scale) { - dirwt = ( rangefn[abs(data_fine[inbr][jnbr]-data_fine[i][j])] ); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j] = val/norm; // low pass filter - } + int inbrMin = max(i - scalewin, i % scale); + + for(; j < (width - scalewin) - 3; j += 4) { + valv = _mm_setzero_ps(); + normv = _mm_setzero_ps(); + dftemp1v = LVFU(data_fine[i][j]); + + for(int inbr = inbrMin; inbr <= min(i + scalewin, height - 1); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { + dftemp2v = LVFU(data_fine[inbr][jnbr]); + dirwtv = ( rangefn[_mm_cvttps_epi32(vabsf(dftemp2v - dftemp1v))] ); + valv += dirwtv * dftemp2v; + normv += dirwtv; + } + } + + _mm_storeu_ps( &data_coarse[i][j], valv / normv); + } + + for(; j < width - scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = inbrMin; inbr <= min(i + scalewin, height - 1); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { + dirwt = ( rangefn[abs(data_fine[inbr][jnbr] - data_fine[i][j])] ); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; // low pass filter + } #else - for(; j < width-scalewin; j++) { - float val=0.f; - float norm=0.f; - for(int inbr=max(i-scalewin,i%scale); inbr<=min(i+scalewin, height-1); inbr+=scale) { - for (int jnbr=j-scalewin; jnbr<=j+scalewin; jnbr+=scale) { - dirwt = ( rangefn[abs(data_fine[inbr][jnbr]-data_fine[i][j])] ); - val += dirwt*data_fine[inbr][jnbr]; - norm += dirwt; - } - } - data_coarse[i][j] = val/norm; // low pass filter - } + + for(; j < width - scalewin; j++) { + float val = 0.f; + float norm = 0.f; + + for(int inbr = max(i - scalewin, i % scale); inbr <= min(i + scalewin, height - 1); inbr += scale) { + for (int jnbr = j - scalewin; jnbr <= j + scalewin; jnbr += scale) { + dirwt = ( rangefn[abs(data_fine[inbr][jnbr] - data_fine[i][j])] ); + val += dirwt * data_fine[inbr][jnbr]; + norm += dirwt; + } + } + + data_coarse[i][j] = val / norm; // low pass filter + } + #endif - for(; j < width; j++) { - float val=0.f; - float norm=0.f; - for(int inbr=max(i-scalewin,i%scale); inbr<=min(i+scalewin, height-1); inbr+=scale) { - for (int jnbr=j-scalewin; jnbrinitialImage; + if (!ii) { ii = InitialImage::load (job->fname, job->isRaw, &errorCode); + if (errorCode) { delete job; return NULL; } } + procparams::ProcParams& params = job->pparams; // acquire image from imagesource @@ -63,25 +68,26 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p imgsrc->getFullSize (fw, fh, tr); // check the crop params - if (params.crop.x > fw || params.crop.y > fh) { - // the crop is completely out of the image, so we disable the crop - params.crop.enabled = false; - // and we set the values to the defaults - params.crop.x = 0; - params.crop.y = 0; - params.crop.w = fw; - params.crop.h = fh; - } - else { - if ((params.crop.x + params.crop.w) > fw) { - // crop overflow in the width dimension ; we trim it - params.crop.w = fw-params.crop.x; - } - if ((params.crop.y + params.crop.h) > fh) { - // crop overflow in the height dimension ; we trim it - params.crop.h = fh-params.crop.y; - } - } + if (params.crop.x > fw || params.crop.y > fh) { + // the crop is completely out of the image, so we disable the crop + params.crop.enabled = false; + // and we set the values to the defaults + params.crop.x = 0; + params.crop.y = 0; + params.crop.w = fw; + params.crop.h = fh; + } else { + if ((params.crop.x + params.crop.w) > fw) { + // crop overflow in the width dimension ; we trim it + params.crop.w = fw - params.crop.x; + } + + if ((params.crop.y + params.crop.h) > fh) { + // crop overflow in the height dimension ; we trim it + params.crop.h = fh - params.crop.y; + } + } + // MyTime t1,t2; // t1.set(); @@ -93,473 +99,610 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if (params.toneCurve.autoexp) {// this enabled HLRecovery LUTu histRedRaw(256), histGreenRaw(256), histBlueRaw(256); imgsrc->getRAWHistogram(histRedRaw, histGreenRaw, histBlueRaw); + if (ToneCurveParams::HLReconstructionNecessary(histRedRaw, histGreenRaw, histBlueRaw) && !params.toneCurve.hrenabled) { - params.toneCurve.hrenabled=true; + params.toneCurve.hrenabled = true; // WARNING: Highlight Reconstruction is being forced 'on', should we force a method here too? } } - if (pl) pl->setProgress (0.20); + if (pl) { + pl->setProgress (0.20); + } + imgsrc->demosaic( params.raw); - if (pl) pl->setProgress (0.30); + + if (pl) { + pl->setProgress (0.30); + } + imgsrc->HLRecovery_Global( params.toneCurve ); - if (pl) pl->setProgress (0.40); - // set the color temperature + + if (pl) { + pl->setProgress (0.40); + } + + // set the color temperature ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); - if (params.wb.method=="Camera") + + if (params.wb.method == "Camera") { currWB = imgsrc->getWB (); - else if (params.wb.method=="Auto") { + } else if (params.wb.method == "Auto") { double rm, gm, bm; imgsrc->getAutoWBMultipliers(rm, gm, bm); currWB.update(rm, gm, bm, params.wb.equal); } - - NoiseCurve noiseLCurve; - NoiseCurve noiseCCurve; - Imagefloat *calclum = NULL ; + + NoiseCurve noiseLCurve; + NoiseCurve noiseCCurve; + Imagefloat *calclum = NULL ; params.dirpyrDenoise.getCurves(noiseLCurve, noiseCCurve); - float autoNR = (float) settings->nrauto;// - float autoNRmax = (float) settings->nrautomax;// - int tilesize; - int overlap; - if(settings->leveldnti ==0) { - tilesize = 1024; - overlap = 128; - } - if(settings->leveldnti ==1) { - tilesize = 768; - overlap = 96; - } - - // const int tilesize = 768; - // const int overlap = 96; - int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - ipf.Tile_calc (tilesize, overlap, 2, fw, fh, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); - int nbtl=numtiles_W*numtiles_H; - if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) nbtl=9; - float *ch_M = new float [nbtl];//allocate memory - float *max_r = new float [nbtl]; - float *max_b = new float [nbtl]; - float *min_b = new float [9]; - float *min_r = new float [9]; - float *lumL = new float [nbtl]; - float *chromC = new float [nbtl]; - float *ry = new float [nbtl]; - float *sk = new float [nbtl]; - float *pcsk = new float [nbtl]; - float *Max_R_ =new float [nbtl]; - float *Max_B_ = new float [nbtl]; - // printf("expert=%d\n",settings->leveldnautsimpl); - if(settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="PON") { - MyTime t1pone,t2pone; - t1pone.set(); - int crW,crH; - if(settings->leveldnv ==0) {crW=100;crH=100;} - if(settings->leveldnv ==1) {crW=250;crH=250;} - if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} - // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview - if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} - - float lowdenoise=1.f; - int levaut=settings->leveldnaut; - if(levaut==1) //Standard - lowdenoise=0.7f; - - // int crW=tileWskip-10;//crop noise width - // int crH=tileHskip-10;//crop noise height -// Imagefloat *origCropPart;//init auto noise -// origCropPart = new Imagefloat (crW, crH);//allocate memory - if (params.dirpyrDenoise.enabled) {//evaluate Noise - LUTf gamcurve(65536,0); - float gam, gamthresh, gamslope; - ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); - #pragma omp parallel - { - Imagefloat *origCropPart;//init auto noise - origCropPart = new Imagefloat (crW, crH);//allocate memory - Imagefloat *provicalc = new Imagefloat ((crW+1)/2, (crH+1)/2);//for denoise curves - int skipP=1; - #pragma omp for schedule(dynamic) collapse(2) nowait - for(int wcr=0;wcrgetImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); + float autoNR = (float) settings->nrauto;// + float autoNRmax = (float) settings->nrautomax;// + int tilesize; + int overlap; - // we only need image reduced to 1/4 here - for(int ii=0;iir(ii>>1,jj>>1) = origCropPart->r(ii,jj); - provicalc->g(ii>>1,jj>>1) = origCropPart->g(ii,jj); - provicalc->b(ii>>1,jj>>1) = origCropPart->b(ii,jj); - } - } - imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve - float maxr=0.f; - float maxb=0.f; - float pondcorrec=1.0f; - float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; - int Nb; - chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;chromina=0.f; sigma=0.f; - ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); - float multip=1.f; - float adjustr=1.f; - if (params.icm.working=="ProPhoto") {adjustr =1.f;}// - else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} - else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} - - if(!imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good fot gamma=1 - float maxmax=max(maxredaut,maxblueaut); - float delta; - int mode=2; - int lissage=settings->leveldnliss; - ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc); + if(settings->leveldnti == 0) { + tilesize = 1024; + overlap = 128; + } - // printf("PROCESS cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f sigL=%f\n",chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema, sigma_L); - if(maxredaut > maxblueaut) { - maxr=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - if(minblueaut <= minredaut && minblueaut < chaut) maxb=(-chaut+minblueaut)/(autoNRmax*multip*adjustr*lowdenoise); - } - else { - maxb=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - if(minredaut <= minblueaut && minredaut < chaut) maxr=(-chaut+minredaut)/(autoNRmax*multip*adjustr*lowdenoise); - }//maxb mxr - empirical evaluation red / blue - - ch_M[hcr*numtiles_W + wcr]=pondcorrec*chaut/(autoNR*multip*adjustr*lowdenoise); - max_r[hcr*numtiles_W + wcr]=pondcorrec*maxr; - max_b[hcr*numtiles_W + wcr]=pondcorrec*maxb; - lumL[hcr*numtiles_W + wcr]=lumema; - chromC[hcr*numtiles_W + wcr]=chromina; - ry[hcr*numtiles_W + wcr]=redyel; - sk[hcr*numtiles_W + wcr]=skinc; - pcsk[hcr*numtiles_W + wcr]=nsknc; - - } - } - - delete provicalc; - delete origCropPart; - } + if(settings->leveldnti == 1) { + tilesize = 768; + overlap = 96; + } - int liss=settings->leveldnliss;//smooth result around mean + // const int tilesize = 768; + // const int overlap = 96; + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + ipf.Tile_calc (tilesize, overlap, 2, fw, fh, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + int nbtl = numtiles_W * numtiles_H; - if(liss==2 || liss==3){ - // I smooth only mean and not delta (max) - float nchm=0.f; - float koef=0.4f;//between 0.1 to 0.9 - if(liss==3) koef=0.0f;//quasi auto for mean Ch - for(int wcr=0;wcrMaxR) MaxR=Max_R_[k]; - if(max_b[k]>MaxB) MaxB=Max_B_[k]; - - } - MaxBMoy/=nbtl; - MaxRMoy/=nbtl; - - for(int k=0;k MaxB) { - max_r[k]=MaxRMoy + (MaxR-MaxRMoy)*0.66f;//#std Dev - //max_b[k]=MinB; - max_b[k]=MaxBMoy + (MaxB-MaxBMoy)*0.66f; - - } - else { - max_b[k]=MaxBMoy + (MaxB-MaxBMoy)*0.66f; - //max_r[k]=MinR; - max_r[k]=MaxRMoy + (MaxR-MaxRMoy)*0.66f; + if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { + nbtl = 9; + } + + float *ch_M = new float [nbtl];//allocate memory + float *max_r = new float [nbtl]; + float *max_b = new float [nbtl]; + float *min_b = new float [9]; + float *min_r = new float [9]; + float *lumL = new float [nbtl]; + float *chromC = new float [nbtl]; + float *ry = new float [nbtl]; + float *sk = new float [nbtl]; + float *pcsk = new float [nbtl]; + float *Max_R_ = new float [nbtl]; + float *Max_B_ = new float [nbtl]; + + // printf("expert=%d\n",settings->leveldnautsimpl); + if(settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PON") { + MyTime t1pone, t2pone; + t1pone.set(); + int crW, crH; + + if(settings->leveldnv == 0) { + crW = 100; + crH = 100; + } + + if(settings->leveldnv == 1) { + crW = 250; + crH = 250; + } + + if(settings->leveldnv == 2) { + crW = int(tileWskip / 2); + crH = int(tileHskip / 2); + } + + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv == 3) { + crW = tileWskip - 10; + crH = tileHskip - 10; + } + + float lowdenoise = 1.f; + int levaut = settings->leveldnaut; + + if(levaut == 1) { //Standard + lowdenoise = 0.7f; + } + + // int crW=tileWskip-10;//crop noise width + // int crH=tileHskip-10;//crop noise height +// Imagefloat *origCropPart;//init auto noise +// origCropPart = new Imagefloat (crW, crH);//allocate memory + if (params.dirpyrDenoise.enabled) {//evaluate Noise + LUTf gamcurve(65536, 0); + float gam, gamthresh, gamslope; + ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + #pragma omp parallel + { + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves + int skipP = 1; + #pragma omp for schedule(dynamic) collapse(2) nowait + + for(int wcr = 0; wcr < numtiles_W; wcr++) { + for(int hcr = 0; hcr < numtiles_H; hcr++) { + int beg_tileW = wcr * tileWskip + tileWskip / 2.f - crW / 2.f; + int beg_tileH = hcr * tileHskip + tileHskip / 2.f - crH / 2.f; + PreviewProps ppP (beg_tileW , beg_tileH, crW, crH, skipP); + imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); + + // we only need image reduced to 1/4 here + for(int ii = 0; ii < crH; ii += 2) { + for(int jj = 0; jj < crW; jj += 2) { + provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj); + provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj); + provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj); + } + } + + imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve + float maxr = 0.f; + float maxb = 0.f; + float pondcorrec = 1.0f; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + int Nb; + chaut = 0.f; + redaut = 0.f; + blueaut = 0.f; + maxredaut = 0.f; + maxblueaut = 0.f; + chromina = 0.f; + sigma = 0.f; + ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + float multip = 1.f; + float adjustr = 1.f; + + if (params.icm.working == "ProPhoto") { + adjustr = 1.f; // + } else if (params.icm.working == "Adobe RGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "sRGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "WideGamut") { + adjustr = 1.f / 1.1f; + } else if (params.icm.working == "Beta RGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BestRGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BruceRGB") { + adjustr = 1.f / 1.2f; + } + + if(!imgsrc->isRAW()) { + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + } + + float maxmax = max(maxredaut, maxblueaut); + float delta; + int mode = 2; + int lissage = settings->leveldnliss; + ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc); + + // printf("PROCESS cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f sigL=%f\n",chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema, sigma_L); + if(maxredaut > maxblueaut) { + maxr = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + + if(minblueaut <= minredaut && minblueaut < chaut) { + maxb = (-chaut + minblueaut) / (autoNRmax * multip * adjustr * lowdenoise); + } + } else { + maxb = (delta) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + + if(minredaut <= minblueaut && minredaut < chaut) { + maxr = (-chaut + minredaut) / (autoNRmax * multip * adjustr * lowdenoise); + } + }//maxb mxr - empirical evaluation red / blue + + ch_M[hcr * numtiles_W + wcr] = pondcorrec * chaut / (autoNR * multip * adjustr * lowdenoise); + max_r[hcr * numtiles_W + wcr] = pondcorrec * maxr; + max_b[hcr * numtiles_W + wcr] = pondcorrec * maxb; + lumL[hcr * numtiles_W + wcr] = lumema; + chromC[hcr * numtiles_W + wcr] = chromina; + ry[hcr * numtiles_W + wcr] = redyel; + sk[hcr * numtiles_W + wcr] = skinc; + pcsk[hcr * numtiles_W + wcr] = nsknc; + + } + } + + delete provicalc; + delete origCropPart; + } + + int liss = settings->leveldnliss; //smooth result around mean + + if(liss == 2 || liss == 3) { + // I smooth only mean and not delta (max) + float nchm = 0.f; + float koef = 0.4f; //between 0.1 to 0.9 + + if(liss == 3) { + koef = 0.0f; //quasi auto for mean Ch + } + + for(int wcr = 0; wcr < numtiles_W; wcr++) { + for(int hcr = 0; hcr < numtiles_H; hcr++) { + nchm += ch_M[hcr * numtiles_W + wcr]; + } + } + + nchm /= (numtiles_H * numtiles_W); + + for(int wcr = 0; wcr < numtiles_W; wcr++) { + for(int hcr = 0; hcr < numtiles_H; hcr++) { + ch_M[hcr * numtiles_W + wcr] = nchm + (ch_M[hcr * numtiles_W + wcr] - nchm) * koef; + } + } + } + + if(liss == 3) { //same as auto but with much cells + float MaxR = 0.f; + float MaxB = 0.f; + float MaxRMoy = 0.f; + float MaxBMoy = 0.f; + + for(int k = 0; k < nbtl; k++) { + MaxBMoy += max_b[k]; + MaxRMoy += max_r[k]; + + if(max_r[k] > MaxR) { + MaxR = Max_R_[k]; + } + + if(max_b[k] > MaxB) { + MaxB = Max_B_[k]; + } + + } + + MaxBMoy /= nbtl; + MaxRMoy /= nbtl; + + for(int k = 0; k < nbtl; k++) { + if(MaxR > MaxB) { + max_r[k] = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev + //max_b[k]=MinB; + max_b[k] = MaxBMoy + (MaxB - MaxBMoy) * 0.66f; + + } else { + max_b[k] = MaxBMoy + (MaxB - MaxBMoy) * 0.66f; + //max_r[k]=MinR; + max_r[k] = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; + + } + } + } + + if (settings->verbose) { + t2pone.set(); + printf("Info denoise ponderated performed in %d usec:\n", t2pone.etime(t1pone)); + } + + } + } + + + if((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { + MyTime t1aue, t2aue; + t1aue.set(); + int crW, crH; + + if(settings->leveldnv == 0) { + crW = 100; + crH = 100; + } + + if(settings->leveldnv == 1) { + crW = 250; + crH = 250; + } + + if(settings->leveldnv == 2) { + crW = int(tileWskip / 2); + crH = int(tileHskip / 2); + } + + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv == 3) { + crW = tileWskip - 10; + crH = tileHskip - 10; + } + + float lowdenoise = 1.f; + int levaut = settings->leveldnaut; + + if(levaut == 1) { //Standard + lowdenoise = 0.7f; + } + + if (params.dirpyrDenoise.enabled) {//evaluate Noise + LUTf gamcurve(65536, 0); + float gam, gamthresh, gamslope; + ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + int Nb[9]; + int coordW[3];//coordonate of part of image to mesure noise + int coordH[3]; + int begW = 50; + int begH = 50; + coordW[0] = begW; + coordW[1] = fw / 2 - crW / 2; + coordW[2] = fw - crW - begW; + coordH[0] = begH; + coordH[1] = fh / 2 - crH / 2; + coordH[2] = fh - crH - begH; + #pragma omp parallel + { + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + Imagefloat *provicalc = new Imagefloat ((crW + 1) / 2, (crH + 1) / 2); //for denoise curves + + #pragma omp for schedule(dynamic) collapse(2) nowait + + for(int wcr = 0; wcr <= 2; wcr++) { + for(int hcr = 0; hcr <= 2; hcr++) { + PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1); + imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw); + + // we only need image reduced to 1/4 here + for(int ii = 0; ii < crH; ii += 2) { + for(int jj = 0; jj < crW; jj += 2) { + provicalc->r(ii >> 1, jj >> 1) = origCropPart->r(ii, jj); + provicalc->g(ii >> 1, jj >> 1) = origCropPart->g(ii, jj); + provicalc->b(ii >> 1, jj >> 1) = origCropPart->b(ii, jj); + } + } + + imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve + int nb = 0; + float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, nresi = 0.f, highresi = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f; + ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + Nb[hcr * 3 + wcr] = nb; + ch_M[hcr * 3 + wcr] = chaut; + max_r[hcr * 3 + wcr] = maxredaut; + max_b[hcr * 3 + wcr] = maxblueaut; + min_r[hcr * 3 + wcr] = minredaut; + min_b[hcr * 3 + wcr] = minblueaut; + lumL[hcr * 3 + wcr] = lumema; + chromC[hcr * 3 + wcr] = chromina; + ry[hcr * 3 + wcr] = redyel; + sk[hcr * 3 + wcr] = skinc; + pcsk[hcr * 3 + wcr] = nsknc; + } + } + + delete provicalc; + delete origCropPart; + } + float chM = 0.f; + float MaxR = 0.f; + float MaxB = 0.f; + float MinR = 100000000.f; + float MinB = 100000000.f; + float maxr = 0.f; + float maxb = 0.f; + float multip = 1.f; + float adjustr = 1.f; + float Max_R[9] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float Max_B[9] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float Min_R[9]; + float Min_B[9]; + float MaxRMoy = 0.f; + float MaxBMoy = 0.f; + float MinRMoy = 0.f; + float MinBMoy = 0.f; + + if (params.icm.working == "ProPhoto") { + adjustr = 1.f; + } else if (params.icm.working == "Adobe RGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "sRGB") { + adjustr = 1.f / 1.3f; + } else if (params.icm.working == "WideGamut") { + adjustr = 1.f / 1.1f; + } else if (params.icm.working == "Beta RGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BestRGB") { + adjustr = 1.f / 1.2f; + } else if (params.icm.working == "BruceRGB") { + adjustr = 1.f / 1.2f; + } + + if(!imgsrc->isRAW()) { + multip = 2.f; //take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + } + + float delta[9]; + int mode = 1; + int lissage = settings->leveldnliss; + + for(int k = 0; k < 9; k++) { + float maxmax = max(max_r[k], max_b[k]); + ipf.calcautodn_info (ch_M[k], delta[k], Nb[k], levaut, maxmax, lumL[k], chromC[k], mode, lissage, ry[k], sk[k], pcsk[k] ); + // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]); + } + + for(int k = 0; k < 9; k++) { + if(max_r[k] > max_b[k]) { + //printf("R delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise); + Max_R[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + Min_B[k] = -(ch_M[k] - min_b[k]) / (autoNRmax * multip * adjustr * lowdenoise); + Max_B[k] = 0.f; + Min_R[k] = 0.f; + } else { + //printf("B delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise); + Max_B[k] = (delta[k]) / ((autoNRmax * multip * adjustr * lowdenoise) / 2.f); + Min_R[k] = - (ch_M[k] - min_r[k]) / (autoNRmax * multip * adjustr * lowdenoise); + Min_B[k] = 0.f; + Max_R[k] = 0.f; + } + } + + for(int k = 0; k < 9; k++) { + // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]); + chM += ch_M[k]; + MaxBMoy += Max_B[k]; + MaxRMoy += Max_R[k]; + MinRMoy += Min_R[k]; + MinBMoy += Min_B[k]; + + if(Max_R[k] > MaxR) { + MaxR = Max_R[k]; + } + + if(Max_B[k] > MaxB) { + MaxB = Max_B[k]; + } + + if(Min_R[k] < MinR) { + MinR = Min_R[k]; + } + + if(Min_B[k] < MinB) { + MinB = Min_B[k]; + } + + } + + chM /= 9; + MaxBMoy /= 9; + MaxRMoy /= 9; + MinBMoy /= 9; + MinRMoy /= 9; + + if(MaxR > MaxB) { + maxr = MaxRMoy + (MaxR - MaxRMoy) * 0.66f; //#std Dev + // maxb=MinB; + maxb = MinBMoy + (MinB - MinBMoy) * 0.66f; + + } else { + maxb = MaxBMoy + (MaxB - MaxBMoy) * 0.66f; + // maxr=MinR; + maxr = MinRMoy + (MinR - MinRMoy) * 0.66f; + + } + +// printf("SIMPL cha=%f red=%f bl=%f \n",chM,maxr,maxb); + + params.dirpyrDenoise.chroma = chM / (autoNR * multip * adjustr); + params.dirpyrDenoise.redchro = maxr; + params.dirpyrDenoise.bluechro = maxb; + } + + if (settings->verbose) { + t2aue.set(); + printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue)); + } + + //end evaluate noise + } - } - } - } - - if (settings->verbose) { - t2pone.set(); - printf("Info denoise ponderated performed in %d usec:\n", t2pone.etime(t1pone)); - } - - } - } - - if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) { - MyTime t1aue,t2aue; - t1aue.set(); - int crW,crH; - if(settings->leveldnv ==0) {crW=100;crH=100;} - if(settings->leveldnv ==1) {crW=250;crH=250;} - if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} - // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview - if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} - - float lowdenoise=1.f; - int levaut=settings->leveldnaut; - if(levaut==1) //Standard - lowdenoise=0.7f; - - if (params.dirpyrDenoise.enabled) {//evaluate Noise - LUTf gamcurve(65536,0); - float gam, gamthresh, gamslope; - ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); - int Nb[9]; - int coordW[3];//coordonate of part of image to mesure noise - int coordH[3]; - int begW=50; - int begH=50; - coordW[0]=begW;coordW[1]=fw/2-crW/2;coordW[2]=fw-crW-begW; - coordH[0]=begH;coordH[1]=fh/2-crH/2;coordH[2]=fh-crH-begH; - #pragma omp parallel - { - Imagefloat *origCropPart;//init auto noise - origCropPart = new Imagefloat (crW, crH);//allocate memory - Imagefloat *provicalc = new Imagefloat ((crW+1)/2, (crH+1)/2);//for denoise curves - #pragma omp for schedule(dynamic) collapse(2) nowait - for(int wcr=0;wcr<=2;wcr++) { - for(int hcr=0;hcr<=2;hcr++) { - PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1); - imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw); - // we only need image reduced to 1/4 here - for(int ii=0;iir(ii>>1,jj>>1) = origCropPart->r(ii,jj); - provicalc->g(ii>>1,jj>>1) = origCropPart->g(ii,jj); - provicalc->b(ii>>1,jj>>1) = origCropPart->b(ii,jj); - } - } - imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve - int nb = 0; - float chaut=0.f, redaut=0.f, blueaut=0.f, maxredaut=0.f, maxblueaut=0.f, minredaut=0.f, minblueaut=0.f, nresi=0.f, highresi=0.f, chromina=0.f, sigma=0.f, lumema=0.f, sigma_L=0.f, redyel=0.f, skinc=0.f, nsknc=0.f; - ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); - Nb[hcr*3 + wcr] = nb; - ch_M[hcr*3 + wcr] = chaut; - max_r[hcr*3 + wcr] = maxredaut; - max_b[hcr*3 + wcr] = maxblueaut; - min_r[hcr*3 + wcr] = minredaut; - min_b[hcr*3 + wcr] = minblueaut; - lumL[hcr*3 + wcr] = lumema; - chromC[hcr*3 + wcr] = chromina; - ry[hcr*3 + wcr] = redyel; - sk[hcr*3 + wcr] = skinc; - pcsk[hcr*3 + wcr] = nsknc; - } - } - delete provicalc; - delete origCropPart; - } - float chM=0.f; - float MaxR=0.f; - float MaxB=0.f; - float MinR=100000000.f; - float MinB=100000000.f; - float maxr=0.f; - float maxb=0.f; - float multip=1.f; - float adjustr=1.f; - float Max_R[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; - float Max_B[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; - float Min_R[9]; - float Min_B[9]; - float MaxRMoy=0.f; - float MaxBMoy=0.f; - float MinRMoy=0.f; - float MinBMoy=0.f; - - if (params.icm.working=="ProPhoto") {adjustr =1.f;} - else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} - else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} - else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} - else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} - - if(!imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good fot gamma=1 - float delta[9]; - int mode=1; - int lissage=settings->leveldnliss; - for(int k=0;k<9;k++) { - float maxmax = max(max_r[k],max_b[k]); - ipf.calcautodn_info (ch_M[k], delta[k], Nb[k], levaut, maxmax, lumL[k], chromC[k], mode, lissage, ry[k], sk[k], pcsk[k] ); - // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]); - } - for(int k=0;k<9;k++) { - if(max_r[k] > max_b[k]) { - //printf("R delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise); - Max_R[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - Min_B[k]= -(ch_M[k]-min_b[k])/(autoNRmax*multip*adjustr*lowdenoise); - Max_B[k]=0.f; - Min_R[k]=0.f; - } - else { - //printf("B delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise); - Max_B[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); - Min_R[k]=- (ch_M[k]-min_r[k]) / (autoNRmax*multip*adjustr*lowdenoise); - Min_B[k]=0.f; - Max_R[k]=0.f; - } - } - - for(int k=0;k<9;k++) { - // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]); - chM+=ch_M[k]; - MaxBMoy+=Max_B[k]; - MaxRMoy+=Max_R[k]; - MinRMoy+=Min_R[k]; - MinBMoy+=Min_B[k]; - if(Max_R[k]>MaxR) MaxR=Max_R[k]; - if(Max_B[k]>MaxB) MaxB=Max_B[k]; - if(Min_R[k] MaxB) { - maxr=MaxRMoy + (MaxR-MaxRMoy)*0.66f;//#std Dev - // maxb=MinB; - maxb=MinBMoy + (MinB-MinBMoy)*0.66f; - - } - else { - maxb=MaxBMoy + (MaxB-MaxBMoy)*0.66f; - // maxr=MinR; - maxr=MinRMoy + (MinR-MinRMoy)*0.66f; - - } - -// printf("SIMPL cha=%f red=%f bl=%f \n",chM,maxr,maxb); - params.dirpyrDenoise.chroma=chM/(autoNR*multip*adjustr); - params.dirpyrDenoise.redchro=maxr; - params.dirpyrDenoise.bluechro=maxb; - } - if (settings->verbose) { - t2aue.set(); - printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue)); - } - - //end evaluate noise - } - - - - - Imagefloat* baseImg = new Imagefloat (fw, fh); imgsrc->getImage (currWB, tr, baseImg, pp, params.toneCurve, params.icm, params.raw); - if (pl) pl->setProgress (0.45); -// LUTf Noisecurve (65536,0); + if (pl) { + pl->setProgress (0.45); + } + +// LUTf Noisecurve (65536,0); //!!!// auto exposure!!! double expcomp = params.toneCurve.expcomp; - int bright = params.toneCurve.brightness; - int contr = params.toneCurve.contrast; - int black = params.toneCurve.black; - int hlcompr = params.toneCurve.hlcompr; - int hlcomprthresh = params.toneCurve.hlcomprthresh; + int bright = params.toneCurve.brightness; + int contr = params.toneCurve.contrast; + int black = params.toneCurve.black; + int hlcompr = params.toneCurve.hlcompr; + int hlcomprthresh = params.toneCurve.hlcomprthresh; if (params.toneCurve.autoexp) { - LUTu aehist; int aehistcompr; - imgsrc->getAutoExpHistogram (aehist, aehistcompr); - ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, expcomp, bright, contr, black, hlcompr,hlcomprthresh); + LUTu aehist; + int aehistcompr; + imgsrc->getAutoExpHistogram (aehist, aehistcompr); + ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); } // at this stage, we can flush the raw data to free up quite an important amount of memory // commented out because it makes the application crash when batch processing... // TODO: find a better place to flush rawData and rawRGB if(flush) { - imgsrc->flushRawData(); - imgsrc->flushRGB(); + imgsrc->flushRawData(); + imgsrc->flushRGB(); } // perform luma/chroma denoise -// CieImage *cieView; -// NoisCurve noiseLCurve; +// CieImage *cieView; +// NoisCurve noiseLCurve; // bool lldenoiseutili=false; -// Imagefloat *calclum ; +// Imagefloat *calclum ; // params.dirpyrDenoise.getCurves(noiseLCurve, lldenoiseutili); -// if (params.dirpyrDenoise.enabled && lldenoiseutili) { +// if (params.dirpyrDenoise.enabled && lldenoiseutili) { - DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; // make a copy because we cheat here + DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; // make a copy because we cheat here + + if(denoiseParams.Lmethod == "CUR") { + if(noiseLCurve) { + denoiseParams.luma = 0.5f; + } else { + denoiseParams.luma = 0.0f; + } + } else if(denoiseParams.Lmethod == "SLI") { + noiseLCurve.Reset(); + } + + if (denoiseParams.enabled && (noiseLCurve || noiseCCurve )) { + // we only need image reduced to 1/4 here + calclum = new Imagefloat ((fw + 1) / 2, (fh + 1) / 2); //for luminance denoise curve + #pragma omp parallel for + + for(int ii = 0; ii < fh; ii += 2) { + for(int jj = 0; jj < fw; jj += 2) { + calclum->r(ii >> 1, jj >> 1) = baseImg->r(ii, jj); + calclum->g(ii >> 1, jj >> 1) = baseImg->g(ii, jj); + calclum->b(ii >> 1, jj >> 1) = baseImg->b(ii, jj); + } + } + + imgsrc->convertColorSpace(calclum, params.icm, currWB); + } - if(denoiseParams.Lmethod == "CUR") { - if(noiseLCurve) - denoiseParams.luma = 0.5f; - else - denoiseParams.luma = 0.0f; - } else if(denoiseParams.Lmethod=="SLI") - noiseLCurve.Reset(); - if (denoiseParams.enabled && (noiseLCurve || noiseCCurve )) { - // we only need image reduced to 1/4 here - calclum = new Imagefloat ((fw+1)/2, (fh+1)/2);//for luminance denoise curve -#pragma omp parallel for - for(int ii=0;iir(ii>>1,jj>>1) = baseImg->r(ii,jj); - calclum->g(ii>>1,jj>>1) = baseImg->g(ii,jj); - calclum->b(ii>>1,jj>>1) = baseImg->b(ii,jj); - } - } - imgsrc->convertColorSpace(calclum, params.icm, currWB); - } if (denoiseParams.enabled) { - // CurveFactory::denoiseLL(lldenoiseutili, denoiseParams.lcurve, Noisecurve,1); - //denoiseParams.getCurves(noiseLCurve); -// ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), denoiseParams, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, lldenoiseutili); - float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi; - int kall=2; - ipf.RGB_denoise(kall, baseImg, baseImg, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); - - } - // delete calclum; - delete [] ch_M; - delete [] max_r; - delete [] max_b; - delete [] min_r; - delete [] min_b; - delete [] lumL; - delete [] chromC; - delete [] ry; - delete [] sk; - delete [] pcsk; + // CurveFactory::denoiseLL(lldenoiseutili, denoiseParams.lcurve, Noisecurve,1); + //denoiseParams.getCurves(noiseLCurve); +// ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), denoiseParams, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, lldenoiseutili); + float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi; + int kall = 2; + ipf.RGB_denoise(kall, baseImg, baseImg, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), denoiseParams, imgsrc->getDirPyrDenoiseExpComp(), noiseLCurve, noiseCCurve, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); + + } + +// delete calclum; + delete [] ch_M; + delete [] max_r; + delete [] max_b; + delete [] min_r; + delete [] min_b; + delete [] lumL; + delete [] chromC; + delete [] ry; + delete [] sk; + delete [] pcsk; delete [] Max_R_; delete [] Max_B_; - + imgsrc->convertColorSpace(baseImg, params.icm, currWB); // perform first analysis LUTu hist16 (65536); LUTu hist16C (65536); - + ipf.firstAnalysis (baseImg, ¶ms, hist16); // perform transform (excepted resizing) @@ -573,107 +716,123 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p // update blurmap SHMap* shmap = NULL; + if (params.sh.enabled) { shmap = new SHMap (fw, fh, true); - double radius = sqrt (double(fw*fw+fh*fh)) / 2.0; - double shradius = params.sh.radius; - if (!params.sh.hq) shradius *= radius / 1800.0; - shmap->update (baseImg, shradius, ipf.lumimul, params.sh.hq, 1); + double radius = sqrt (double(fw * fw + fh * fh)) / 2.0; + double shradius = params.sh.radius; + + if (!params.sh.hq) { + shradius *= radius / 1800.0; + } + + shmap->update (baseImg, shradius, ipf.lumimul, params.sh.hq, 1); } + // RGB processing LUTf curve1 (65536); LUTf curve2 (65536); - LUTf curve (65536,0); - LUTf satcurve (65536,0); - LUTf lhskcurve (65536,0); - LUTf lumacurve(65536,0); - LUTf clcurve (65536,0); - LUTf clToningcurve (65536,0); - LUTf cl2Toningcurve (65536,0); - LUTf wavclCurve (65536,0); + LUTf curve (65536, 0); + LUTf satcurve (65536, 0); + LUTf lhskcurve (65536, 0); + LUTf lumacurve(65536, 0); + LUTf clcurve (65536, 0); + LUTf clToningcurve (65536, 0); + LUTf cl2Toningcurve (65536, 0); + LUTf wavclCurve (65536, 0); - LUTf rCurve (65536,0); - LUTf gCurve (65536,0); - LUTf bCurve (65536,0); - LUTu dummy; + LUTf rCurve (65536, 0); + LUTf gCurve (65536, 0); + LUTf bCurve (65536, 0); + LUTu dummy; - ToneCurve customToneCurve1, customToneCurve2; - ColorGradientCurve ctColorCurve; - OpacityCurve ctOpacityCurve; - ColorAppearance customColCurve1, customColCurve2,customColCurve3 ; - ToneCurve customToneCurvebw1; - ToneCurve customToneCurvebw2; - //if(params.blackwhite.enabled) params.toneCurve.hrenabled=false; + ToneCurve customToneCurve1, customToneCurve2; + ColorGradientCurve ctColorCurve; + OpacityCurve ctOpacityCurve; + ColorAppearance customColCurve1, customColCurve2, customColCurve3 ; + ToneCurve customToneCurvebw1; + ToneCurve customToneCurvebw2; + //if(params.blackwhite.enabled) params.toneCurve.hrenabled=false; - CurveFactory::complexCurve (expcomp, black/65535.0, hlcompr, hlcomprthresh, params.toneCurve.shcompr, bright, contr, - params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2, - hist16, dummy, curve1, curve2, curve, dummy, customToneCurve1, customToneCurve2 ); + CurveFactory::complexCurve (expcomp, black / 65535.0, hlcompr, hlcomprthresh, params.toneCurve.shcompr, bright, contr, + params.toneCurve.curveMode, params.toneCurve.curve, params.toneCurve.curveMode2, params.toneCurve.curve2, + hist16, dummy, curve1, curve2, curve, dummy, customToneCurve1, customToneCurve2 ); - CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 1); - CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 1); - CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 1); + CurveFactory::RGBCurve (params.rgbCurves.rcurve, rCurve, 1); + CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, 1); + CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, 1); - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); - double wp[3][3] = { - {wprof[0][0],wprof[0][1],wprof[0][2]}, - {wprof[1][0],wprof[1][1],wprof[1][2]}, - {wprof[2][0],wprof[2][1],wprof[2][2]}}; - double wip[3][3] = { - {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, - {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, - {wiprof[2][0],wiprof[2][1],wiprof[2][2]} - }; - bool opautili=false; - params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); + double wp[3][3] = { + {wprof[0][0], wprof[0][1], wprof[0][2]}, + {wprof[1][0], wprof[1][1], wprof[1][2]}, + {wprof[2][0], wprof[2][1], wprof[2][2]} + }; + double wip[3][3] = { + {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, + {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, + {wiprof[2][0], wiprof[2][1], wiprof[2][2]} + }; + bool opautili = false; + params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip, opautili); - bool clctoningutili=false; - CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, 1); - bool llctoningutili=false; - CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, 1); + bool clctoningutili = false; + CurveFactory::curveToningCL(clctoningutili, params.colorToning.clcurve, clToningcurve, 1); + bool llctoningutili = false; + CurveFactory::curveToningLL(llctoningutili, params.colorToning.cl2curve, cl2Toningcurve, 1); - LabImage* labView = new LabImage (fw,fh); + LabImage* labView = new LabImage (fw, fh); - CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 1); - double rrm, ggm, bbm; + CurveFactory::curveBW (params.blackwhite.beforeCurve, params.blackwhite.afterCurve, hist16, dummy, customToneCurvebw1, customToneCurvebw2, 1); + double rrm, ggm, bbm; float autor, autog, autob; - float satLimit = float(params.colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; - float satLimitOpacity = 1.f-(float(params.colorToning.saturatedOpacity)/100.f); - - if(params.colorToning.enabled && params.colorToning.autosat){//for colortoning evaluation of saturation settings - float moyS=0.f; - float eqty=0.f; - ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation - //printf("moy=%f ET=%f\n", moyS,eqty); - float satp=((moyS+1.5f*eqty)-0.3f)/0.7f;//1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale - if(satp >= 0.92f) satp=0.92f;//avoid values too high (out of gamut) - if(satp <= 0.15f) satp=0.15f;//avoid too low values - - satLimit= 100.f*satp; - - satLimitOpacity= 100.f*(moyS-0.85f*eqty);//-0.85 sigma==>20% pixels with low saturation - } - + float satLimit = float(params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; + float satLimitOpacity = 1.f - (float(params.colorToning.saturatedOpacity) / 100.f); + + if(params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + float moyS = 0.f; + float eqty = 0.f; + ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation + //printf("moy=%f ET=%f\n", moyS,eqty); + float satp = ((moyS + 1.5f * eqty) - 0.3f) / 0.7f; //1.5 sigma ==> 93% pixels with high saturation -0.3 / 0.7 convert to Hombre scale + + if(satp >= 0.92f) { + satp = 0.92f; //avoid values too high (out of gamut) + } + + if(satp <= 0.15f) { + satp = 0.15f; //avoid too low values + } + + satLimit = 100.f * satp; + + satLimitOpacity = 100.f * (moyS - 0.85f * eqty); //-0.85 sigma==>20% pixels with low saturation + } + autor = -9000.f; // This will ask to compute the "auto" values for the B&W tool (have to be inferior to -5000) DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB); - ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit ,satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve,customToneCurve1, customToneCurve2,customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf); - if (settings->verbose) - printf("Output image / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", autor, autog, autob); + ipf.rgbProc (baseImg, labView, NULL, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf); - // if clut was used and size of clut cache == 1 we free the memory used by the clutstore (default clut cache size = 1 for 32 bit OS) - if ( params.filmSimulation.enabled && !params.filmSimulation.clutFilename.empty() && options.clutCacheSize == 1) - clutStore.clearCache(); + if (settings->verbose) { + printf("Output image / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", autor, autog, autob); + } + + // if clut was used and size of clut cache == 1 we free the memory used by the clutstore (default clut cache size = 1 for 32 bit OS) + if ( params.filmSimulation.enabled && !params.filmSimulation.clutFilename.empty() && options.clutCacheSize == 1) { + clutStore.clearCache(); + } // freeing up some memory customToneCurve1.Reset(); customToneCurve2.Reset(); ctColorCurve.Reset(); ctOpacityCurve.Reset(); - noiseLCurve.Reset(); - noiseCCurve.Reset(); + noiseLCurve.Reset(); + noiseCCurve.Reset(); customToneCurvebw1.Reset(); customToneCurvebw2.Reset(); @@ -681,223 +840,283 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p delete baseImg; baseImg = NULL; - if (shmap) - delete shmap; + if (shmap) { + delete shmap; + } + shmap = NULL; - if (pl) + if (pl) { pl->setProgress (0.5); + } - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // start tile processing...??? + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // start tile processing...??? + + hist16.clear(); + hist16C.clear(); + + if(params.labCurve.contrast != 0) { //only use hist16 for contrast - hist16.clear(); hist16C.clear(); - if(params.labCurve.contrast !=0) {//only use hist16 for contrast - #ifdef _OPENMP -#pragma omp parallel shared(hist16,labView, fh, fw) + #pragma omp parallel shared(hist16,labView, fh, fw) #endif -{ - LUTu hist16thr (65536); // one temporary lookup table per thread - hist16thr.clear(); + { + LUTu hist16thr (65536); // one temporary lookup table per thread + hist16thr.clear(); #ifdef _OPENMP -#pragma omp for schedule(static) nowait + #pragma omp for schedule(static) nowait #endif - for (int i=0; iL[i][j])))]++; + + for (int i = 0; i < fh; i++) + for (int j = 0; j < fw; j++) + { + hist16thr[CLIP((int)((labView->L[i][j])))]++; + } + + #pragma omp critical + { + for(int i = 0; i < 65536; i++) + { + hist16[i] += hist16thr[i]; + } + } } -#pragma omp critical -{ - for(int i=0;i<65536;i++) - hist16[i] += hist16thr[i]; -} -} - - - } - bool utili=false; - bool autili=false; - bool butili=false; - bool ccutili=false; - bool cclutili=false; - bool clcutili=false; - CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve,hist16, hist16, lumacurve, dummy, 1, utili); - CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, hist16C, dummy, 1); + } - CurveFactory::complexsgnCurve (1.f, autili, butili, ccutili, cclutili, params.labCurve.chromaticity, params.labCurve.rstprotection, - params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve,params.labCurve.lccurve,curve1, curve2, satcurve,lhskcurve, - hist16C, hist16C, dummy,dummy, - 1); + bool utili = false; + bool autili = false; + bool butili = false; + bool ccutili = false; + bool cclutili = false; + bool clcutili = false; - ipf.chromiLuminanceCurve (NULL, 1,labView, labView, curve1, curve2, satcurve,lhskcurve,clcurve, lumacurve, utili, autili, butili, ccutili,cclutili, clcutili, dummy, dummy, dummy, dummy); - - if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled))ipf.EPDToneMap(labView,5,1); - + CurveFactory::complexLCurve (params.labCurve.brightness, params.labCurve.contrast, params.labCurve.lcurve, hist16, hist16, lumacurve, dummy, 1, utili); + CurveFactory::curveCL(clcutili, params.labCurve.clcurve, clcurve, hist16C, dummy, 1); - ipf.vibrance(labView); + CurveFactory::complexsgnCurve (1.f, autili, butili, ccutili, cclutili, params.labCurve.chromaticity, params.labCurve.rstprotection, + params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve, params.labCurve.lccurve, curve1, curve2, satcurve, lhskcurve, + hist16C, hist16C, dummy, dummy, + 1); - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ipf.impulsedenoise (labView); - // for all treatments Defringe, Sharpening, Contrast detail ,Microcontrast they are activated if "CIECAM" function are disabled + ipf.chromiLuminanceCurve (NULL, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); + + if((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) { + ipf.EPDToneMap(labView, 5, 1); + } + + + ipf.vibrance(labView); + + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { + ipf.impulsedenoise (labView); + } + + // for all treatments Defringe, Sharpening, Contrast detail ,Microcontrast they are activated if "CIECAM" function are disabled + + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { + ipf.defringe (labView); + } + + if (params.sharpenEdge.enabled) { + ipf.MLsharpen(labView); + } + + if (params.sharpenMicro.enabled) { + if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { + ipf.MLmicrocontrast (labView); //!params.colorappearance.sharpcie + } + } + + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ipf.defringe (labView); - - if (params.sharpenEdge.enabled) { - ipf.MLsharpen(labView); - } - if (params.sharpenMicro.enabled) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ipf.MLmicrocontrast (labView);//!params.colorappearance.sharpcie - } - - if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { - float **buffer = new float*[fh]; - for (int i=0; iautocielab) || !params.colorappearance.enabled) ipf.dirpyrequalizer (labView, 1);//TODO: this is the luminance tonecurve, not the RGB one - int kall=2; - bool wavcontlutili=false; - - CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1); - - if((params.wavelet.enabled)) ipf.ip_wavelet(labView, labView, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, 1); - wavCLVCurve.Reset(); - //Colorappearance and tone-mapping associated - - int f_w=1,f_h=1; - int begh = 0, endh = fh; - if(params.colorappearance.tonecie || params.colorappearance.enabled){f_w=fw;f_h=fh;} - CieImage *cieView = new CieImage (f_w,(f_h)); - begh=0; - endh=fh; - CurveFactory::curveLightBrightColor ( - params.colorappearance.curveMode, params.colorappearance.curve, - params.colorappearance.curveMode2, params.colorappearance.curve2, - params.colorappearance.curveMode3, params.colorappearance.curve3, - hist16, hist16,dummy, - hist16C, dummy, - customColCurve1, - customColCurve2, - customColCurve3, - 1); - if(params.colorappearance.enabled){ - double adap; - float fnum = imgsrc->getMetaData()->getFNumber ();// F number - float fiso = imgsrc->getMetaData()->getISOSpeed () ;// ISO - float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed - float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + - - if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { - adap=2000.; - }//if no exif data or wrong - else { - float E_V = fcomp + log2 ((fnum*fnum) / fspeed / (fiso/100.f)); - E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV - E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV - adap = powf(2.f, E_V-3.f);//cd / m2 - } - LUTf CAMBrightCurveJ; - LUTf CAMBrightCurveQ; - float CAMMean; - if (params.sharpening.enabled) { - float d; - double dd; + params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL ); - int sk=1; - if(settings->ciecamfloat) ipf.ciecam_02float (cieView, float(adap), begh, endh,1,2, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, sk, 1); - else ipf.ciecam_02 (cieView, adap, begh, endh,1,2, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1); - } - else { - float d; + // 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 + } + + int kall = 2; + bool wavcontlutili = false; + + CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1); + + if((params.wavelet.enabled)) { + ipf.ip_wavelet(labView, labView, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, 1); + } + + wavCLVCurve.Reset(); + + //Colorappearance and tone-mapping associated + + int f_w = 1, f_h = 1; + int begh = 0, endh = fh; + + if(params.colorappearance.tonecie || params.colorappearance.enabled) { + f_w = fw; + f_h = fh; + } + + CieImage *cieView = new CieImage (f_w, (f_h)); + begh = 0; + endh = fh; + CurveFactory::curveLightBrightColor ( + params.colorappearance.curveMode, params.colorappearance.curve, + params.colorappearance.curveMode2, params.colorappearance.curve2, + params.colorappearance.curveMode3, params.colorappearance.curve3, + hist16, hist16, dummy, + hist16C, dummy, + customColCurve1, + customColCurve2, + customColCurve3, + 1); + + if(params.colorappearance.enabled) { + double adap; + float fnum = imgsrc->getMetaData()->getFNumber ();// F number + float fiso = imgsrc->getMetaData()->getISOSpeed () ;// ISO + float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed + float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + - + + if(fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { + adap = 2000.; + }//if no exif data or wrong + else { + float E_V = fcomp + log2 ((fnum * fnum) / fspeed / (fiso / 100.f)); + E_V += params.toneCurve.expcomp;// exposure compensation in tonecurve ==> direct EV + E_V += log2(params.raw.expos);// exposure raw white point ; log2 ==> linear to EV + adap = powf(2.f, E_V - 3.f); //cd / m2 + } + + LUTf CAMBrightCurveJ; + LUTf CAMBrightCurveQ; + float CAMMean; + + if (params.sharpening.enabled) { + float d; + double dd; + + int sk = 1; + + if(settings->ciecamfloat) { + ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, sk, 1); + } else { + ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1); + } + } else { + float d; + + double dd; + int sk = 1; + + if(settings->ciecamfloat) { + ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, sk, 1); + } else { + ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1); + } + } + } - double dd; - int sk=1; - if(settings->ciecamfloat) ipf.ciecam_02float (cieView, float(adap), begh, endh,1,2, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, sk, 1); - else ipf.ciecam_02 (cieView, adap, begh, endh,1, 2, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1); - } - } delete cieView; cieView = NULL; - - - - // end tile processing...??? - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if (pl) pl->setProgress (0.60); + + + // end tile processing...??? + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if (pl) { + pl->setProgress (0.60); + } int imw, imh; double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh); - bool labResize = params.resize.enabled && params.resize.method != "Nearest" && tmpScale != 1.0; + bool labResize = params.resize.enabled && params.resize.method != "Nearest" && tmpScale != 1.0; LabImage *tmplab; // crop and convert to rgb16 int cx = 0, cy = 0, cw = labView->W, ch = labView->H; + if (params.crop.enabled) { cx = params.crop.x; cy = params.crop.y; cw = params.crop.w; ch = params.crop.h; + if(labResize) { // crop lab data - tmplab = new LabImage(cw,ch); - for(int row = 0;rowL[row][col] = labView->L[row+cy][col+cx]; - tmplab->a[row][col] = labView->a[row+cy][col+cx]; - tmplab->b[row][col] = labView->b[row+cy][col+cx]; - } - } - delete labView; - labView = tmplab; - cx = 0; - cy = 0; + tmplab = new LabImage(cw, ch); + + for(int row = 0; row < ch; row++) { + for(int col = 0; col < cw; col++) { + tmplab->L[row][col] = labView->L[row + cy][col + cx]; + tmplab->a[row][col] = labView->a[row + cy][col + cx]; + tmplab->b[row][col] = labView->b[row + cy][col + cx]; + } + } + + delete labView; + labView = tmplab; + cx = 0; + cy = 0; } } if (labResize) { // resize lab data // resize image - tmplab = new LabImage(imw,imh); + tmplab = new LabImage(imw, imh); ipf.Lanczos (labView, tmplab, tmpScale); delete labView; labView = tmplab; - cw = labView->W; - ch = labView->H; - if(params.prsharpening.enabled) { - for(int i=0;iW; + ch = labView->H; + + if(params.prsharpening.enabled) { + for(int i = 0; i < ch; i++) + for(int j = 0; j < cw; j++) { labView->L[i][j] = labView->L[i][j] < 0.f ? 0.f : labView->L[i][j]; + } float **buffer = new float*[ch]; - for (int i=0; i opnames = iccStore->getOutputProfiles (); + //test if files are in system - for (int j=0; j<9; j++) { + for (int j = 0; j < 9; j++) { // one can modify "option" [Color Management] to adapt the profile's name if they are different for windows, MacOS, Linux ?? // some of them are actually provided by RT, thanks to Jacques Desmis - if (j==0) chpro=options.rtSettings.prophoto; - else if(j==1) chpro=options.rtSettings.adobe; - else if(j==2) chpro=options.rtSettings.widegamut; - else if(j==3) chpro=options.rtSettings.beta; - else if(j==4) chpro=options.rtSettings.best; - else if(j==5) chpro=options.rtSettings.bruce; - else if(j==6) chpro=options.rtSettings.srgb; - else if(j==7) chpro=options.rtSettings.srgb10;//gamma 1.0 - else if(j==8) chpro=options.rtSettings.prophoto10;//gamma 1.0 - - for (unsigned int i=0; iverbose) { + printf("Missing file: %s\n", chpro.c_str()); } - if (!present_space[j] && settings->verbose) printf("Missing file: %s\n", chpro.c_str()); } - if (params.icm.freegamma && params.icm.gampos < 1.35) pro=true; //select profil with gammaTRC modified : - else if (params.icm.gamma=="linear_g1.0" || (params.icm.gamma=="High_g1.3_s3.35")) pro=true;//pro=0 RT_sRGB || Prophoto + + if (params.icm.freegamma && params.icm.gampos < 1.35) { + pro = true; //select profil with gammaTRC modified : + } else if (params.icm.gamma == "linear_g1.0" || (params.icm.gamma == "High_g1.3_s3.35")) { + pro = true; //pro=0 RT_sRGB || Prophoto + } // Check that output profiles exist, otherwise use LCMS2 // Use the icc/icm profiles associated to possible working profiles, set in "options" - if (params.icm.working=="ProPhoto" && present_space[0] && !pro) outProfile=options.rtSettings.prophoto; - else if (params.icm.working=="Adobe RGB" && present_space[1] ) outProfile=options.rtSettings.adobe; - else if (params.icm.working=="WideGamut" && present_space[2] ) outProfile=options.rtSettings.widegamut; - else if (params.icm.working=="Beta RGB" && present_space[3] ) outProfile=options.rtSettings.beta; - else if (params.icm.working=="BestRGB" && present_space[4] ) outProfile=options.rtSettings.best; - else if (params.icm.working=="BruceRGB" && present_space[5] ) outProfile=options.rtSettings.bruce; - else if (params.icm.working=="sRGB" && present_space[6] && !pro) outProfile=options.rtSettings.srgb; - else if (params.icm.working=="sRGB" && present_space[7] && pro) outProfile=options.rtSettings.srgb10; - else if (params.icm.working=="ProPhoto" && present_space[8] && pro) outProfile=options.rtSettings.prophoto10; - else { + if (params.icm.working == "ProPhoto" && present_space[0] && !pro) { + outProfile = options.rtSettings.prophoto; + } else if (params.icm.working == "Adobe RGB" && present_space[1] ) { + outProfile = options.rtSettings.adobe; + } else if (params.icm.working == "WideGamut" && present_space[2] ) { + outProfile = options.rtSettings.widegamut; + } else if (params.icm.working == "Beta RGB" && present_space[3] ) { + outProfile = options.rtSettings.beta; + } else if (params.icm.working == "BestRGB" && present_space[4] ) { + outProfile = options.rtSettings.best; + } else if (params.icm.working == "BruceRGB" && present_space[5] ) { + outProfile = options.rtSettings.bruce; + } else if (params.icm.working == "sRGB" && present_space[6] && !pro) { + outProfile = options.rtSettings.srgb; + } else if (params.icm.working == "sRGB" && present_space[7] && pro) { + outProfile = options.rtSettings.srgb10; + } else if (params.icm.working == "ProPhoto" && present_space[8] && pro) { + outProfile = options.rtSettings.prophoto10; + } else { // Should not occurs - if (settings->verbose) printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", params.icm.working.c_str() ); - useLCMS=true; + if (settings->verbose) { + printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", params.icm.working.c_str() ); + } + + useLCMS = true; } //begin adaptation rTRC gTRC bTRC //"jprof" profile has the same characteristics than RGB values, but TRC are adapted... for applying profile if (!useLCMS) { - if (settings->verbose) printf("Output Gamma - profile: \"%s\"\n", outProfile.c_str() ); //c_str() + if (settings->verbose) { + printf("Output Gamma - profile: \"%s\"\n", outProfile.c_str() ); //c_str() + } + jprof = iccStore->getProfile(outProfile); //get output profile + if (jprof == NULL) { useLCMS = true; - if (settings->verbose) printf("\"%s\" ICC output profile not found!\n", outProfile.c_str()); - } - else { + + if (settings->verbose) { + printf("\"%s\" ICC output profile not found!\n", outProfile.c_str()); + } + } else { Parameters[0] = ga0; Parameters[1] = ga1; Parameters[2] = ga2; @@ -978,110 +1236,124 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p Parameters[5] = ga5; Parameters[6] = ga6; // 7 parameters for smoother curves - //change desc Tag , to "free gamma", or "BT709", etc. - cmsContext ContextID = cmsGetProfileContextID(jprof);//modification TAG - DescriptionMLU = cmsMLUalloc(ContextID, 1); - CopyrightMLU = cmsMLUalloc(ContextID, 1);//for ICC - DmndMLU=cmsMLUalloc(ContextID, 1);//for ICC - DmddMLU=cmsMLUalloc(ContextID, 1);// for ICC + //change desc Tag , to "free gamma", or "BT709", etc. + cmsContext ContextID = cmsGetProfileContextID(jprof);//modification TAG + DescriptionMLU = cmsMLUalloc(ContextID, 1); + CopyrightMLU = cmsMLUalloc(ContextID, 1);//for ICC + DmndMLU = cmsMLUalloc(ContextID, 1); //for ICC + DmddMLU = cmsMLUalloc(ContextID, 1); // for ICC - // instruction with //ICC are used for generate icc profile - if (DescriptionMLU == NULL) printf("Description error\n"); - cmsMLUsetWide(CopyrightMLU, "en", "US", L"General Public License - AdobeRGB compatible") ;//adapt to profil - cmsMLUsetWide(DmndMLU, "en", "US", L"RawTherapee") ; - cmsMLUsetWide(DmddMLU, "en", "US", L"RTMedium") ; //adapt to profil - //display Tag desc with : selection of gamma and Primaries - if (!params.icm.freegamma) { - std::wstring gammaStr; - if(params.icm.gamma=="High_g1.3_s3.35") { - gammaStr = std::wstring(L"GammaTRC: High g=1.3 s=3.35"); - } - else if (params.icm.gamma=="Low_g2.6_s6.9") { - gammaStr = std::wstring(L"GammaTRC: Low g=2.6 s=6.9"); - } - else if (params.icm.gamma=="sRGB_g2.4_s12.92") { - gammaStr = std::wstring(L"GammaTRC: sRGB g=2.4 s=12.92"); - } - else if (params.icm.gamma== "BT709_g2.2_s4.5") { - gammaStr = std::wstring(L"GammaTRC: BT709 g=2.2 s=4.5"); - } - else if (params.icm.gamma== "linear_g1.0") { - gammaStr = std::wstring(L"GammaTRC: Linear g=1.0"); - } - else if (params.icm.gamma== "standard_g2.2") { - gammaStr = std::wstring(L"GammaTRC: g=2.2"); - } - else if (params.icm.gamma== "standard_g1.8") { - gammaStr = std::wstring(L"GammaTRC: g=1.8"); - } - cmsMLUsetWide(DescriptionMLU, "en", "US", gammaStr.c_str()); + // instruction with //ICC are used for generate icc profile + if (DescriptionMLU == NULL) { + printf("Description error\n"); + } - //for elaboration ICC profiles - // else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Medium gamma sRGB(AdobeRGB compatible)"); - // else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma BT709(IEC61966 equivalent)"); - // else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma sRGB(IEC61966 equivalent)"); - // else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma Linear1.0(IEC61966 equivalent)"); - //else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma BT709(Prophoto compatible)"); - // else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma sRGB(Prophoto compatible)"); - // else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma Linear1.0(Prophoto compatible)"); - } - else { - // create description with gamma + slope + primaries - std::wostringstream gammaWs; - gammaWs.precision(2); - gammaWs<<"Manual GammaTRC: g="<<(float)params.icm.gampos<<" s="<<(float)params.icm.slpos; - cmsMLUsetWide(DescriptionMLU, "en", "US", gammaWs.str().c_str()); - } + cmsMLUsetWide(CopyrightMLU, "en", "US", L"General Public License - AdobeRGB compatible") ;//adapt to profil + cmsMLUsetWide(DmndMLU, "en", "US", L"RawTherapee") ; + cmsMLUsetWide(DmddMLU, "en", "US", L"RTMedium") ; //adapt to profil + + //display Tag desc with : selection of gamma and Primaries + if (!params.icm.freegamma) { + std::wstring gammaStr; + + if(params.icm.gamma == "High_g1.3_s3.35") { + gammaStr = std::wstring(L"GammaTRC: High g=1.3 s=3.35"); + } else if (params.icm.gamma == "Low_g2.6_s6.9") { + gammaStr = std::wstring(L"GammaTRC: Low g=2.6 s=6.9"); + } else if (params.icm.gamma == "sRGB_g2.4_s12.92") { + gammaStr = std::wstring(L"GammaTRC: sRGB g=2.4 s=12.92"); + } else if (params.icm.gamma == "BT709_g2.2_s4.5") { + gammaStr = std::wstring(L"GammaTRC: BT709 g=2.2 s=4.5"); + } else if (params.icm.gamma == "linear_g1.0") { + gammaStr = std::wstring(L"GammaTRC: Linear g=1.0"); + } else if (params.icm.gamma == "standard_g2.2") { + gammaStr = std::wstring(L"GammaTRC: g=2.2"); + } else if (params.icm.gamma == "standard_g1.8") { + gammaStr = std::wstring(L"GammaTRC: g=1.8"); + } + + cmsMLUsetWide(DescriptionMLU, "en", "US", gammaStr.c_str()); + + //for elaboration ICC profiles + // else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Medium gamma sRGB(AdobeRGB compatible)"); + // else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma BT709(IEC61966 equivalent)"); + // else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma sRGB(IEC61966 equivalent)"); + // else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma Linear1.0(IEC61966 equivalent)"); + //else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma BT709(Prophoto compatible)"); + // else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma sRGB(Prophoto compatible)"); + // else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma Linear1.0(Prophoto compatible)"); + } else { + // create description with gamma + slope + primaries + std::wostringstream gammaWs; + gammaWs.precision(2); + gammaWs << "Manual GammaTRC: g=" << (float)params.icm.gampos << " s=" << (float)params.icm.slpos; + cmsMLUsetWide(DescriptionMLU, "en", "US", gammaWs.str().c_str()); + } + + cmsWriteTag(jprof, cmsSigProfileDescriptionTag, DescriptionMLU);//desc changed + // cmsWriteTag(jprof, cmsSigCopyrightTag, CopyrightMLU); + // cmsWriteTag(jprof, cmsSigDeviceMfgDescTag, DmndMLU); + // cmsWriteTag(jprof, cmsSigDeviceModelDescTag, DmddMLU); - cmsWriteTag(jprof, cmsSigProfileDescriptionTag, DescriptionMLU);//desc changed - // cmsWriteTag(jprof, cmsSigCopyrightTag, CopyrightMLU); - // cmsWriteTag(jprof, cmsSigDeviceMfgDescTag, DmndMLU); - // cmsWriteTag(jprof, cmsSigDeviceModelDescTag, DmddMLU); - // Calculate output profile's rTRC bTRC gTRC GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, 5, Parameters); cmsWriteTag(jprof, cmsSigGreenTRCTag, (void*)GammaTRC[1] ); cmsWriteTag(jprof, cmsSigRedTRCTag, (void*)GammaTRC[0] ); cmsWriteTag(jprof, cmsSigBlueTRCTag, (void*)GammaTRC[2] ); - //for generation ICC profiles : here Prophoto ==> Large - // if(params.icm.gamma== "BT709_g2.2_s4.5") cmsSaveProfileToFile(jprof, "RT_sRGB_gBT709.icm"); - // else if (params.icm.gamma== "sRGB_g2.4_s12.92") cmsSaveProfileToFile(jprof, "RT_Medium_gsRGB.icc"); - // else if (params.icm.gamma== "linear_g1.0") cmsSaveProfileToFile(jprof, "RT_Large_g10.icc"); - - + //for generation ICC profiles : here Prophoto ==> Large + // if(params.icm.gamma== "BT709_g2.2_s4.5") cmsSaveProfileToFile(jprof, "RT_sRGB_gBT709.icm"); + // else if (params.icm.gamma== "sRGB_g2.4_s12.92") cmsSaveProfileToFile(jprof, "RT_Medium_gsRGB.icc"); + // else if (params.icm.gamma== "linear_g1.0") cmsSaveProfileToFile(jprof, "RT_Large_g10.icc"); + + } } - if (GammaTRC[0]) cmsFreeToneCurve(GammaTRC[0]); - } - else { + + if (GammaTRC[0]) { + cmsFreeToneCurve(GammaTRC[0]); + } + } else { // if Default gamma mode: we use the profile selected in the "Output profile" combobox; // gamma come from the selected profile, otherwise it comes from "Free gamma" tool // readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.blackwhite.enabled); - bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled ; - if(autili || butili ) bwonly = false; + bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled ; + + if(autili || butili ) { + bwonly = false; + } + readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, bwonly); - if (settings->verbose) printf("Output profile_: \"%s\"\n", params.icm.output.c_str()); + + if (settings->verbose) { + printf("Output profile_: \"%s\"\n", params.icm.output.c_str()); + } } delete labView; labView = NULL; - - - - if(!autili && !butili ) { - if(params.blackwhite.enabled && !params.colorToning.enabled ) {//force BW r=g=b - if (settings->verbose) printf("Force BW\n"); - for (int ccw=0;ccwr(cch,ccw)=readyImg->g(cch,ccw); - readyImg->b(cch,ccw)=readyImg->g(cch,ccw); - } - } - } - } - if (pl) pl->setProgress (0.70); + + + + if(!autili && !butili ) { + if(params.blackwhite.enabled && !params.colorToning.enabled ) {//force BW r=g=b + if (settings->verbose) { + printf("Force BW\n"); + } + + for (int ccw = 0; ccw < cw; ccw++) { + for (int cch = 0; cch < ch; cch++) { + readyImg->r(cch, ccw) = readyImg->g(cch, ccw); + readyImg->b(cch, ccw) = readyImg->g(cch, ccw); + } + } + } + } + + if (pl) { + pl->setProgress (0.70); + } if (tmpScale != 1.0 && params.resize.method == "Nearest") { // resize rgb data (gamma applied) Image16* tempImage = new Image16 (imw, imh); @@ -1090,10 +1362,11 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p readyImg = tempImage; } - if (tunnelMetaData) + if (tunnelMetaData) { readyImg->setMetadata (ii->getMetaData()->getExifData ()); - else + } else { readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); + } // Setting the output curve to readyImg @@ -1103,66 +1376,78 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p ProfileContent pc(jprof); readyImg->setOutputProfile (pc.data, pc.length); } - } - else { + } else { // use RT_sRGB.icm profile if present, otherwise use LCMS2 profile generate by lab2rgb16b Glib::ustring outputProfile; - if (params.icm.output!="" && params.icm.output!=ColorManagementParams::NoICMString) { + + if (params.icm.output != "" && params.icm.output != ColorManagementParams::NoICMString) { outputProfile = params.icm.output; /* if we'd wanted the RT_sRGB profile we would have selected it - else { + else { // use RT_sRGB.icm profile if present, otherwise use LCMS2 profile generate by lab2rgb16b if (settings->verbose) printf("No output profiles set ; looking for the default sRGB profile (\"%s\")...\n", options.rtSettings.srgb.c_str()); outputProfile = options.rtSettings.srgb; }*/ - // if iccStore->getProfile send back an object, then iccStore->getContent will do too - cmsHPROFILE jprof = iccStore->getProfile(outputProfile); //get outProfile - if (jprof == NULL) { - if (settings->verbose) printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", outputProfile.c_str()); - } - else { - if (settings->verbose) printf("Using \"%s\" output profile\n", outputProfile.c_str()); - ProfileContent pc = iccStore->getContent (outputProfile); - readyImg->setOutputProfile (pc.data, pc.length); - } + // if iccStore->getProfile send back an object, then iccStore->getContent will do too + cmsHPROFILE jprof = iccStore->getProfile(outputProfile); //get outProfile + + if (jprof == NULL) { + if (settings->verbose) { + printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", outputProfile.c_str()); + } + } else { + if (settings->verbose) { + printf("Using \"%s\" output profile\n", outputProfile.c_str()); + } + + ProfileContent pc = iccStore->getContent (outputProfile); + readyImg->setOutputProfile (pc.data, pc.length); + } } else { // No ICM - readyImg->setOutputProfile (NULL,0); + readyImg->setOutputProfile (NULL, 0); } } + // t2.set(); // if( settings->verbose ) // printf("Total:- %d usec\n", t2.etime(t1)); - if (!job->initialImage) + if (!job->initialImage) { ii->decreaseRef (); + } delete job; - if (pl) + + if (pl) { pl->setProgress (0.75); -/* curve1.reset();curve2.reset(); - curve.reset(); - satcurve.reset(); - lhskcurve.reset(); - - rCurve.reset(); - gCurve.reset(); - bCurve.reset(); - hist16.reset(); - hist16C.reset(); -*/ + } + + /* curve1.reset();curve2.reset(); + curve.reset(); + satcurve.reset(); + lhskcurve.reset(); + + rCurve.reset(); + gCurve.reset(); + bCurve.reset(); + hist16.reset(); + hist16C.reset(); + */ return readyImg; } -void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) { +void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) +{ ProcessingJob* currentJob = job; - + while (currentJob) { int errorCode; IImage16* img = processImage (currentJob, errorCode, bpl, tunnelMetaData, true); + if (errorCode) { bpl->error (M("MAIN_MSG_CANNOTLOAD")); currentJob = NULL; @@ -1177,16 +1462,18 @@ void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl, bo } } -void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) { +void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl, bool tunnelMetaData) +{ if (bpl) #if __GNUC__ == 4 && __GNUC_MINOR__ == 8 && defined( WIN32 ) && defined(__x86_64__) - // See Issue 2384 "Very bad response time on win7/64 using gcc 4.8 when queue is running" + // See Issue 2384 "Very bad response time on win7/64 using gcc 4.8 when queue is running" Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl, tunnelMetaData), 0, true, true, Glib::THREAD_PRIORITY_NORMAL); + #else Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl, tunnelMetaData), 0, true, true, Glib::THREAD_PRIORITY_LOW); #endif - + } } diff --git a/rtengine/simpleprocess.h b/rtengine/simpleprocess.h index fb5a24ff6..d6efe802d 100644 --- a/rtengine/simpleprocess.h +++ b/rtengine/simpleprocess.h @@ -1,4 +1,4 @@ -/* +/* * File: simpleprocess.h * Author: askv * @@ -6,21 +6,22 @@ */ #ifndef SIMPLEPROCESS_H -#define SIMPLEPROCESS_H +#define SIMPLEPROCESS_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif - -#ifdef __cplusplus + +#ifdef __cplusplus } #endif -namespace rtengine { +namespace rtengine +{ extern Glib::Thread *batchThread; } -#endif /* SIMPLEPROCESS_H */ +#endif /* SIMPLEPROCESS_H */ diff --git a/rtengine/sleef.h b/rtengine/sleef.h index ab42eda40..101a4faff 100644 --- a/rtengine/sleef.h +++ b/rtengine/sleef.h @@ -1,9 +1,9 @@ typedef struct { - double x, y; + double x, y; } double2; typedef struct { - float x, y; + float x, y; } float2; double xsin(double d); diff --git a/rtengine/sleefsseavx.h b/rtengine/sleefsseavx.h index 2058c3749..8fe20c54b 100644 --- a/rtengine/sleefsseavx.h +++ b/rtengine/sleefsseavx.h @@ -12,14 +12,32 @@ typedef __m128 vfloat; typedef __m128i vint2; typedef __m128i vmask; -static vdouble vloadu(double *p) { return _mm_loadu_pd(p); } -static void vstoreu(double *p, vdouble v) { _mm_storeu_pd(p, v); } +static vdouble vloadu(double *p) +{ + return _mm_loadu_pd(p); +} +static void vstoreu(double *p, vdouble v) +{ + _mm_storeu_pd(p, v); +} -static vfloat vloaduf(float *p) { return _mm_loadu_ps(p); } -static void vstoreuf(float *p, vfloat v) { _mm_storeu_ps(p, v); } +static vfloat vloaduf(float *p) +{ + return _mm_loadu_ps(p); +} +static void vstoreuf(float *p, vfloat v) +{ + _mm_storeu_ps(p, v); +} -static vint2 vloadui2(int32_t *p) { return (vint2)_mm_loadu_si128((__m128i *)p); } -static void vstoreui2(int32_t *p, vint2 v) { _mm_storeu_si128((__m128i *)p, (__m128i)v); } +static vint2 vloadui2(int32_t *p) +{ + return (vint2)_mm_loadu_si128((__m128i *)p); +} +static void vstoreui2(int32_t *p, vint2 v) +{ + _mm_storeu_si128((__m128i *)p, (__m128i)v); +} #endif #ifdef ENABLE_AVX @@ -32,30 +50,44 @@ typedef __m128i vint; typedef __m256 vfloat; typedef struct { - vint x, y; + vint x, y; } vint2; -static vdouble vloadu(double *p) { return _mm256_loadu_pd(p); } -static void vstoreu(double *p, vdouble v) { return _mm256_storeu_pd(p, v); } - -static vfloat vloaduf(float *p) { return _mm256_loadu_ps(p); } -static void vstoreuf(float *p, vfloat v) { return _mm256_storeu_ps(p, v); } - -static vint2 vloadui2(int32_t *p) { - vint2 r; - r.x = _mm_loadu_si128((__m128i *) p ); - r.y = _mm_loadu_si128((__m128i *)(p + 4)); - return r; +static vdouble vloadu(double *p) +{ + return _mm256_loadu_pd(p); +} +static void vstoreu(double *p, vdouble v) +{ + return _mm256_storeu_pd(p, v); } -static void vstoreui2(int32_t *p, vint2 v) { - _mm_storeu_si128((__m128i *) p , v.x); - _mm_storeu_si128((__m128i *)(p + 4), v.y); +static vfloat vloaduf(float *p) +{ + return _mm256_loadu_ps(p); +} +static void vstoreuf(float *p, vfloat v) +{ + return _mm256_storeu_ps(p, v); +} + +static vint2 vloadui2(int32_t *p) +{ + vint2 r; + r.x = _mm_loadu_si128((__m128i *) p ); + r.y = _mm_loadu_si128((__m128i *)(p + 4)); + return r; +} + +static void vstoreui2(int32_t *p, vint2 v) +{ + _mm_storeu_si128((__m128i *) p , v.x); + _mm_storeu_si128((__m128i *)(p + 4), v.y); } #endif typedef struct { - vdouble x, y; + vdouble x, y; } vdouble2; vdouble xldexp(vdouble x, vint q); @@ -91,7 +123,7 @@ vdouble xlog1p(vdouble a); // typedef struct { - vfloat x, y; + vfloat x, y; } vfloat2; vfloat xsinf(vfloat d); diff --git a/rtengine/slicer.cc b/rtengine/slicer.cc index c4a5d09e1..72a42e07e 100644 --- a/rtengine/slicer.cc +++ b/rtengine/slicer.cc @@ -30,109 +30,123 @@ using namespace std; // If no parameter set, everything = 0 -> process all the image -Block::Block() { - posX = 0; - posY = 0; - width = 0; - height = 0; +Block::Block() +{ + posX = 0; + posY = 0; + width = 0; + height = 0; } -Block::Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - posX = x; - posY = y; - width = w; - height = h; +Block::Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h) +{ + posX = x; + posY = y; + width = w; + height = h; } /* * Slice a sub-region to process in blocks who's size is given by the number of processor * and the number of pixel per block (and hence the memory footprint) */ -Slicer::Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels ) { - // If the sub-region has a portrait shape, X and Y coordinates are swapped for better result - // It will be swapped back when sending back the block coordinates - region.width = !(subRegion->width) ? imageWidth : subRegion->width; - region.height = !(subRegion->height) ? imageHeight : subRegion->height; // Assuming that the sub-region is under posY - if (region.width < region.height) { - region.width = !(subRegion->height) ? imageHeight : subRegion->height; - region.height = !(subRegion->width) ? imageWidth : subRegion->width; // Assuming that the sub-region is under posY - portrait = true; - imWidth = imageHeight; - imHeight = imageWidth; - region.posX = subRegion->posY; - region.posY = subRegion->posX; - } - else { - portrait = false; - imWidth = imageWidth; - imHeight = imageHeight; - region.posX = subRegion->posX; - region.posY = subRegion->posY; - } - double subRegionRatio = (double)(region.width) / (double)(region.height); +Slicer::Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels ) +{ + // If the sub-region has a portrait shape, X and Y coordinates are swapped for better result + // It will be swapped back when sending back the block coordinates + region.width = !(subRegion->width) ? imageWidth : subRegion->width; + region.height = !(subRegion->height) ? imageHeight : subRegion->height; // Assuming that the sub-region is under posY - //total number of core/processor + if (region.width < region.height) { + region.width = !(subRegion->height) ? imageHeight : subRegion->height; + region.height = !(subRegion->width) ? imageWidth : subRegion->width; // Assuming that the sub-region is under posY + portrait = true; + imWidth = imageHeight; + imHeight = imageWidth; + region.posX = subRegion->posY; + region.posY = subRegion->posX; + } else { + portrait = false; + imWidth = imageWidth; + imHeight = imageHeight; + region.posX = subRegion->posX; + region.posY = subRegion->posY; + } + + double subRegionRatio = (double)(region.width) / (double)(region.height); + + //total number of core/processor #ifdef _OPENMP - unsigned int procNumber = omp_get_num_procs(); + unsigned int procNumber = omp_get_num_procs(); #else - unsigned int procNumber = 1; + unsigned int procNumber = 1; #endif - //calculate the number of block - blockNumber = (double(region.width*region.height) / (double)pixels); - blockNumber = int((rtengine::max(blockNumber, 1U) + (double)procNumber/2.)/procNumber)*procNumber; - vBlockNumber = (unsigned int)(sqrt((double)blockNumber / subRegionRatio)+0.5); - vBlockNumber = CLAMP(vBlockNumber, 1, blockNumber); - hBlockNumber = (double)blockNumber / (double)vBlockNumber; - blockWidth = 1.0 / hBlockNumber; + //calculate the number of block + blockNumber = (double(region.width * region.height) / (double)pixels); + blockNumber = int((rtengine::max(blockNumber, 1U) + (double)procNumber / 2.) / procNumber) * procNumber; + vBlockNumber = (unsigned int)(sqrt((double)blockNumber / subRegionRatio) + 0.5); + vBlockNumber = CLAMP(vBlockNumber, 1, blockNumber); + hBlockNumber = (double)blockNumber / (double)vBlockNumber; + blockWidth = 1.0 / hBlockNumber; - double maxPixelNumberX = (double)region.height / (double)vBlockNumber; - double maxPixelNumberY = (double)region.width / (double)((unsigned int)hBlockNumber); - if (maxPixelNumberX - (double)((unsigned int)maxPixelNumberX) != 0.) maxPixelNumberX += 1.; - if (maxPixelNumberY - (double)((unsigned int)maxPixelNumberY) != 0.) maxPixelNumberY += 1.; - maxPixelNumber = (unsigned int)maxPixelNumberX * (unsigned int)maxPixelNumberY; + double maxPixelNumberX = (double)region.height / (double)vBlockNumber; + double maxPixelNumberY = (double)region.width / (double)((unsigned int)hBlockNumber); + + if (maxPixelNumberX - (double)((unsigned int)maxPixelNumberX) != 0.) { + maxPixelNumberX += 1.; + } + + if (maxPixelNumberY - (double)((unsigned int)maxPixelNumberY) != 0.) { + maxPixelNumberY += 1.; + } + + maxPixelNumber = (unsigned int)maxPixelNumberX * (unsigned int)maxPixelNumberY; } // return the absolute position and size of the requested block -void Slicer::get_block(unsigned int numBlock, Block *block) { - double roundingTradeOff = (hBlockNumber - (double)((int)hBlockNumber)) == 0.5 ? 2.1 : 2.0; - unsigned int alreadyCompletedLineNbr = (unsigned int)((double)(numBlock) * blockWidth + (blockWidth/roundingTradeOff)); +void Slicer::get_block(unsigned int numBlock, Block *block) +{ + double roundingTradeOff = (hBlockNumber - (double)((int)hBlockNumber)) == 0.5 ? 2.1 : 2.0; + unsigned int alreadyCompletedLineNbr = (unsigned int)((double)(numBlock) * blockWidth + (blockWidth / roundingTradeOff)); - unsigned int prevLineEnd = (unsigned int)((double)alreadyCompletedLineNbr * hBlockNumber + 0.5); - unsigned int myLineEnd = (unsigned int)((double)(alreadyCompletedLineNbr+1) * hBlockNumber + 0.5); + unsigned int prevLineEnd = (unsigned int)((double)alreadyCompletedLineNbr * hBlockNumber + 0.5); + unsigned int myLineEnd = (unsigned int)((double)(alreadyCompletedLineNbr + 1) * hBlockNumber + 0.5); - unsigned int nbrCellsOnMyLine = myLineEnd - prevLineEnd; - unsigned int cellOnMyLine = numBlock - prevLineEnd; + unsigned int nbrCellsOnMyLine = myLineEnd - prevLineEnd; + unsigned int cellOnMyLine = numBlock - prevLineEnd; - unsigned int blockStart = (unsigned int)(((double)region.width / (double)nbrCellsOnMyLine)*(double)(cellOnMyLine)); - unsigned int blockEnd = (unsigned int)(((double)region.width / (double)nbrCellsOnMyLine)*(double)(cellOnMyLine+1)); - block->width = blockEnd - blockStart; - block->posX = region.posX + blockStart; - if (cellOnMyLine == (nbrCellsOnMyLine-1)) { - // We make sure that the last block of the row take the rest of the remaining X space - block->width = region.posX + region.width - block->posX; - } + unsigned int blockStart = (unsigned int)(((double)region.width / (double)nbrCellsOnMyLine) * (double)(cellOnMyLine)); + unsigned int blockEnd = (unsigned int)(((double)region.width / (double)nbrCellsOnMyLine) * (double)(cellOnMyLine + 1)); + block->width = blockEnd - blockStart; + block->posX = region.posX + blockStart; - blockStart = (unsigned int)(((double)region.height / (double)vBlockNumber)*(double)(alreadyCompletedLineNbr)); - blockEnd = (unsigned int)(((double)region.height / (double)vBlockNumber)*(double)(alreadyCompletedLineNbr+1)); - block->height = blockEnd - blockStart; - block->posY = region.posY + blockStart; - if (alreadyCompletedLineNbr == (vBlockNumber-1)) { - block->height = region.posY + region.height - block->posY; - } + if (cellOnMyLine == (nbrCellsOnMyLine - 1)) { + // We make sure that the last block of the row take the rest of the remaining X space + block->width = region.posX + region.width - block->posX; + } - if (portrait) { - // we swap back the X/Y coordinates - unsigned int temp; + blockStart = (unsigned int)(((double)region.height / (double)vBlockNumber) * (double)(alreadyCompletedLineNbr)); + blockEnd = (unsigned int)(((double)region.height / (double)vBlockNumber) * (double)(alreadyCompletedLineNbr + 1)); + block->height = blockEnd - blockStart; + block->posY = region.posY + blockStart; - temp = block->posX; - block->posX = block->posY; - block->posY = temp; + if (alreadyCompletedLineNbr == (vBlockNumber - 1)) { + block->height = region.posY + region.height - block->posY; + } - temp = block->width; - block->width = block->height; - block->height = temp; + if (portrait) { + // we swap back the X/Y coordinates + unsigned int temp; - } + temp = block->posX; + block->posX = block->posY; + block->posY = temp; + + temp = block->width; + block->width = block->height; + block->height = temp; + + } } diff --git a/rtengine/slicer.h b/rtengine/slicer.h index 5cf24ddd0..06e1522cd 100644 --- a/rtengine/slicer.h +++ b/rtengine/slicer.h @@ -21,19 +21,20 @@ //The image is divided in blocks even on single processor machine, mainly to decrease memory consumption //maximum number of pixel per block -#define PIXELS_PER_BLOCK 250000 +#define PIXELS_PER_BLOCK 250000 /* * Used to specify a subregion of an image and to specify a cell in this subregion */ -class Block { - public: - unsigned int posX; - unsigned int posY; - unsigned int width; // If 0, use the full width of the image - unsigned int height; // If 0, use the full height of the image - Block(); - Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h); +class Block +{ +public: + unsigned int posX; + unsigned int posY; + unsigned int width; // If 0, use the full width of the image + unsigned int height; // If 0, use the full height of the image + Block(); + Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h); }; /* @@ -41,21 +42,22 @@ class Block { * processor, and tries to create blocks as square as possible. There can be a different number of block on * each line, and the pixel per block requested may be oversized by very few percents. */ -class Slicer { - protected: - bool portrait; // Orientation of the sub-region - unsigned int imWidth; // Image width - unsigned int imHeight; // Image height - Block region; // Sub-region to process - double hBlockNumber; // Horizontal number of block for the sub-region - unsigned int vBlockNumber; // Vertical number of block for the sub-region - double blockWidth; +class Slicer +{ +protected: + bool portrait; // Orientation of the sub-region + unsigned int imWidth; // Image width + unsigned int imHeight; // Image height + Block region; // Sub-region to process + double hBlockNumber; // Horizontal number of block for the sub-region + unsigned int vBlockNumber; // Vertical number of block for the sub-region + double blockWidth; - public: - unsigned int blockNumber; // number of block for the sub-region - unsigned int maxPixelNumber; // number of pixel of the biggest block (for memory allocation purpose) - Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels); - void get_block(unsigned int blockId, Block *block); +public: + unsigned int blockNumber; // number of block for the sub-region + unsigned int maxPixelNumber; // number of pixel of the biggest block (for memory allocation purpose) + Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels); + void get_block(unsigned int blockId, Block *block); }; #endif diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index fe326a8e8..1604c9c6d 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -7,7 +7,7 @@ * 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 @@ -25,25 +25,34 @@ #undef THREAD_PRIORITY_NORMAL -namespace rtengine { +namespace rtengine +{ extern const Settings* settings; -template void freeArray (T** a, int H) { - for (int i=0; i void freeArray (T** a, int H) +{ + for (int i = 0; i < H; i++) { + delete [] a[i]; + } + + delete [] a; } -template T** allocArray (int W, int H) { +template T** allocArray (int W, int H) +{ T** t = new T*[H]; - for (int i=0; igetH()/HR_SCALE; + + if (hrmap[0] != NULL) { + int dh = img->getH() / HR_SCALE; freeArray(hrmap[0], dh); freeArray(hrmap[1], dh); freeArray(hrmap[2], dh); } - if (needhr) + if (needhr) { freeArray(needhr, img->getH()); + } - if (img) delete img; + if (img) { + delete img; + } } -void StdImageSource::getSampleFormat (Glib::ustring &fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) { +void StdImageSource::getSampleFormat (Glib::ustring &fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) +{ sFormat = IIOSF_UNKNOWN; sArrangement = IIOSA_UNKNOWN; size_t lastdot = fname.find_last_of ('.'); + if( Glib::ustring::npos == lastdot ) { return; } + if (!fname.casefold().compare (lastdot, 4, ".jpg") || - !fname.casefold().compare (lastdot, 5, ".jpeg")) - { + !fname.casefold().compare (lastdot, 5, ".jpeg")) { // For now, png and jpeg files are converted to unsigned short by the loader itself, // but there should be functions that read the sample format first, like the TIFF case below sFormat = IIOSF_UNSIGNED_CHAR; sArrangement = IIOSA_CHUNKY; return; - } - else if (!fname.casefold().compare (lastdot, 4, ".png")) { + } else if (!fname.casefold().compare (lastdot, 4, ".png")) { int result = ImageIO::getPNGSampleFormat (fname, sFormat, sArrangement); - if (result == IMIO_SUCCESS) + + if (result == IMIO_SUCCESS) { return; - } - else if (!fname.casefold().compare (lastdot, 4, ".tif") || - !fname.casefold().compare (lastdot, 5, ".tiff")) - { + } + } else if (!fname.casefold().compare (lastdot, 4, ".tif") || + !fname.casefold().compare (lastdot, 5, ".tiff")) { int result = ImageIO::getTIFFSampleFormat (fname, sFormat, sArrangement); - if (result == IMIO_SUCCESS) + + if (result == IMIO_SUCCESS) { return; + } } + return; } @@ -108,7 +125,8 @@ void StdImageSource::getSampleFormat (Glib::ustring &fname, IIOSampleFormat &sFo * and RT's image data type (Image8, Image16 and Imagefloat), then it will * load the image into it */ -int StdImageSource::load (Glib::ustring fname, bool batch) { +int StdImageSource::load (Glib::ustring fname, bool batch) +{ fileName = fname; @@ -121,26 +139,26 @@ int StdImageSource::load (Glib::ustring fname, bool batch) { // Then create the appropriate object switch (sFormat) { - case (IIOSF_UNSIGNED_CHAR): - { + case (IIOSF_UNSIGNED_CHAR): { Image8 *img_8 = new Image8 (); img = img_8; break; - } - case (IIOSF_UNSIGNED_SHORT): - { + } + + case (IIOSF_UNSIGNED_SHORT): { Image16 *img_16 = new Image16 (); img = img_16; break; - } + } + case (IIOSF_LOGLUV24): case (IIOSF_LOGLUV32): - case (IIOSF_FLOAT): - { + case (IIOSF_FLOAT): { Imagefloat *img_float = new Imagefloat (); img = img_float; break; - } + } + default: return IMIO_FILETYPENOTSUPPORTED; } @@ -157,6 +175,7 @@ int StdImageSource::load (Glib::ustring fname, bool batch) { // And load the image! int error = img->load (fname); + if (error) { delete img; img = NULL; @@ -165,18 +184,19 @@ int StdImageSource::load (Glib::ustring fname, bool batch) { embProfile = img->getEmbeddedProfile (); - idata = new ImageData (fname); + idata = new ImageData (fname); + if (idata->hasExif()) { int deg = 0; - if (idata->getOrientation()=="Rotate 90 CW") { + + if (idata->getOrientation() == "Rotate 90 CW") { deg = 90; - } - else if (idata->getOrientation()=="Rotate 180") { + } else if (idata->getOrientation() == "Rotate 180") { deg = 180; - } - else if (idata->getOrientation()=="Rotate 270 CW") { + } else if (idata->getOrientation() == "Rotate 270 CW") { deg = 270; } + if (deg) { img->rotate(deg); } @@ -187,13 +207,14 @@ int StdImageSource::load (Glib::ustring fname, bool batch) { plistener->setProgress (1.0); } - wb = ColorTemp (1.0,1.0,1.0,1.0); + wb = ColorTemp (1.0, 1.0, 1.0, 1.0); //this is probably a mistake if embedded profile is not D65 return 0; } -void StdImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp,ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw) { +void StdImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw) +{ // the code will use OpenMP as of now. @@ -204,40 +225,49 @@ void StdImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre // 2. it's more optimized like this // Flip if needed - if (tran & TR_HFLIP) + if (tran & TR_HFLIP) { image->hflip(); - if (tran & TR_VFLIP) + } + + if (tran & TR_VFLIP) { image->vflip(); + } } -void StdImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb) { +void StdImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb) +{ colorSpaceConversion (image, cmp, embProfile, img->getSampleFormat()); } -void StdImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat) { +void StdImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat) +{ bool skipTransform = false; cmsHPROFILE in = NULL; cmsHPROFILE out = iccStore->workingSpace (cmp.working); - if (cmp.input=="(embedded)" || cmp.input=="" || cmp.input=="(camera)" || cmp.input=="(cameraICC)") { - if (embedded) + + if (cmp.input == "(embedded)" || cmp.input == "" || cmp.input == "(camera)" || cmp.input == "(cameraICC)") { + if (embedded) { in = embedded; - else { - if (sampleFormat & (IIOSF_LOGLUV24|IIOSF_LOGLUV32|IIOSF_FLOAT)) + } else { + if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT)) { skipTransform = true; - else + } else { in = iccStore->getsRGBProfile (); + } } } else { - if (cmp.input!="(none)") { + if (cmp.input != "(none)") { in = iccStore->getProfile (cmp.input); - if (in==NULL && embedded) + + if (in == NULL && embedded) { in = embedded; - else if (in==NULL) { - if (sampleFormat & (IIOSF_LOGLUV24|IIOSF_LOGLUV32|IIOSF_FLOAT)) + } else if (in == NULL) { + if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT)) { skipTransform = true; - else + } else { in = iccStore->getsRGBProfile (); + } } } } @@ -246,11 +276,13 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams if(in == embedded && cmsGetColorSpace(in) != cmsSigRgbData) { // if embedded profile is not an RGB profile, use sRGB printf("embedded profile is not an RGB profile, using sRGB as input profile\n"); in = iccStore->getsRGBProfile (); - } + } + lcmsMutex->lock (); cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_FLT, out, TYPE_RGB_FLT, settings->colorimetricIntent, - cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); lcmsMutex->unlock (); + if(hTransform) { // Convert to the [0.0 ; 1.0] range im->normalizeFloatTo1(); @@ -262,43 +294,46 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams cmsDeleteTransform(hTransform); } else { - printf("Could not convert from %s to %s\n",in == embedded ? "embedded profile" : cmp.input.data(),cmp.working.data()); + printf("Could not convert from %s to %s\n", in == embedded ? "embedded profile" : cmp.input.data(), cmp.working.data()); } } } -void StdImageSource::getFullSize (int& w, int& h, int tr) { +void StdImageSource::getFullSize (int& w, int& h, int tr) +{ w = img->width; h = img->height; + if ((tr & TR_ROT) == TR_R90 || (tr & TR_ROT) == TR_R270) { w = img->height; h = img->width; } } -void StdImageSource::getSize (int tran, PreviewProps pp, int& w, int& h) { +void StdImageSource::getSize (int tran, PreviewProps pp, int& w, int& h) +{ w = pp.w / pp.skip + (pp.w % pp.skip > 0); h = pp.h / pp.skip + (pp.h % pp.skip > 0); } -void StdImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) { +void StdImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) +{ if (img->getType() == sImage8) { Image8 *img_ = static_cast(img); img_->computeAutoHistogram(histogram, histcompr); - } - else if (img->getType() == sImage16) { + } else if (img->getType() == sImage16) { Image16 *img_ = static_cast(img); img_->computeAutoHistogram(histogram, histcompr); - } - else if (img->getType() == sImagefloat) { + } else if (img->getType() == sImagefloat) { Imagefloat *img_ = static_cast(img); img_->computeAutoHistogram(histogram, histcompr); } } -void StdImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) { +void StdImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) +{ if (redAWBMul != -1.) { rm = redAWBMul; gm = greenAWBMul; @@ -313,16 +348,19 @@ void StdImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm) { blueAWBMul = bm; } -ColorTemp StdImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector& blue, int tran, double equal) { +ColorTemp StdImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector& blue, int tran, double equal) +{ int rn, gn, bn; double reds, greens, blues; img->getSpotWBData(reds, greens, blues, rn, gn, bn, red, green, blue, tran); double img_r, img_g, img_b; wb.getMultipliers (img_r, img_g, img_b); - if( settings->verbose ) - printf ("AVG: %g %g %g\n", reds/rn, greens/gn, blues/bn); - return ColorTemp (reds/rn*img_r, greens/gn*img_g, blues/bn*img_b, equal); + if( settings->verbose ) { + printf ("AVG: %g %g %g\n", reds / rn, greens / gn, blues / bn); + } + + return ColorTemp (reds / rn * img_r, greens / gn * img_g, blues / bn * img_b, equal); } } diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index ed14ebba8..3848fe5e9 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -7,7 +7,7 @@ * 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 @@ -21,55 +21,93 @@ #include "imagesource.h" -namespace rtengine { +namespace rtengine +{ -class StdImageSource : public ImageSource { +class StdImageSource : public ImageSource +{ - protected: - ImageIO* img; - ColorTemp wb; - ProgressListener* plistener; - bool full; - float** hrmap[3]; - char** needhr; - int max[3]; - bool rgbSourceModified; +protected: + ImageIO* img; + ColorTemp wb; + ProgressListener* plistener; + bool full; + float** hrmap[3]; + char** needhr; + int max[3]; + bool rgbSourceModified; - //void transformPixel (int x, int y, int tran, int& tx, int& ty); - void getSampleFormat (Glib::ustring &fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement); + //void transformPixel (int x, int y, int tran, int& tx, int& ty); + void getSampleFormat (Glib::ustring &fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement); - public: - StdImageSource (); - ~StdImageSource (); +public: + StdImageSource (); + ~StdImageSource (); - int load (Glib::ustring fname, bool batch = false); - void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw); - ColorTemp getWB () { return wb; } - void getAutoWBMultipliers (double &rm, double &gm, double &bm); - ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal); + int load (Glib::ustring fname, bool batch = false); + void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw); + ColorTemp getWB () + { + return wb; + } + void getAutoWBMultipliers (double &rm, double &gm, double &bm); + ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal); - bool isWBProviderReady () { return true; }; + bool isWBProviderReady () + { + return true; + }; - void getAutoExpHistogram (LUTu &histogram, int& histcompr); + void getAutoExpHistogram (LUTu &histogram, int& histcompr); - double getDefGain () { return 0.0; } + double getDefGain () + { + return 0.0; + } - void getFullSize (int& w, int& h, int tr = TR_NONE); - void getSize (int tran, PreviewProps pp, int& w, int& h); + void getFullSize (int& w, int& h, int tr = TR_NONE); + void getSize (int tran, PreviewProps pp, int& w, int& h); - ImageData* getImageData () { return idata; } - ImageIO* getImageIO () { return img; } - ImageMatrices* getImageMatrices () { return (ImageMatrices*)NULL; } - bool isRAW() const { return false; } + ImageData* getImageData () + { + return idata; + } + ImageIO* getImageIO () + { + return img; + } + ImageMatrices* getImageMatrices () + { + return (ImageMatrices*)NULL; + } + bool isRAW() const + { + return false; + } - void setProgressListener (ProgressListener* pl) { plistener = pl; } + void setProgressListener (ProgressListener* pl) + { + plistener = pl; + } - void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h) - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); - //static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded); + void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h) + static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); + //static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded); - static inline double intpow (double a, int b) { double r = 1.0; for (int i=0; i=sh) sy = sh-1; - double dy = (double)i*sh/dh - sy; - int ny = sy+1; - if (ny>=sh) ny = sy; - int or1 = 3*sw*sy; - int or2 = 3*sw*ny; - for (int j=0; j=sw) sx = sw; - double dx = (double)j*sw/dw - sx; - int nx = sx+1; - if (nx>=sw) nx = sx; - int ofs11 = or1 + 3*sx; - int ofs12 = or1 + 3*nx; - int ofs21 = or2 + 3*sx; - int ofs22 = or2 + 3*nx; - unsigned int val = src[ofs11]*(1-dx)*(1-dy) + src[ofs12]*dx*(1-dy) + src[ofs21]*(1-dx)*dy + src[ofs22]*dx*dy; + + for (int i = 0; i < dh; i++) { + int sy = i * sh / dh; + + if (sy >= sh) { + sy = sh - 1; + } + + double dy = (double)i * sh / dh - sy; + int ny = sy + 1; + + if (ny >= sh) { + ny = sy; + } + + int or1 = 3 * sw * sy; + int or2 = 3 * sw * ny; + + for (int j = 0; j < dw; j++) { + int sx = j * sw / dw; + + if (sx >= sw) { + sx = sw; + } + + double dx = (double)j * sw / dw - sx; + int nx = sx + 1; + + if (nx >= sw) { + nx = sx; + } + + int ofs11 = or1 + 3 * sx; + int ofs12 = or1 + 3 * nx; + int ofs21 = or2 + 3 * sx; + int ofs22 = or2 + 3 * nx; + unsigned int val = src[ofs11] * (1 - dx) * (1 - dy) + src[ofs12] * dx * (1 - dy) + src[ofs21] * (1 - dx) * dy + src[ofs22] * dx * dy; dst[ix++] = val; - ofs11++; ofs12++; ofs21++; ofs22++; - val = src[ofs11]*(1-dx)*(1-dy) + src[ofs12]*dx*(1-dy) + src[ofs21]*(1-dx)*dy + src[ofs22]*dx*dy; + ofs11++; + ofs12++; + ofs21++; + ofs22++; + val = src[ofs11] * (1 - dx) * (1 - dy) + src[ofs12] * dx * (1 - dy) + src[ofs21] * (1 - dx) * dy + src[ofs22] * dx * dy; dst[ix++] = val; - ofs11++; ofs12++; ofs21++; ofs22++; - val = src[ofs11]*(1-dx)*(1-dy) + src[ofs12]*dx*(1-dy) + src[ofs21]*(1-dx)*dy + src[ofs22]*dx*dy; + ofs11++; + ofs12++; + ofs21++; + ofs22++; + val = src[ofs11] * (1 - dx) * (1 - dy) + src[ofs12] * dx * (1 - dy) + src[ofs21] * (1 - dx) * dy + src[ofs22] * dx * dy; dst[ix++] = val; } } } -void nearestInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) { +void nearestInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) +{ int ix = 0; - for (int i=0; itoInt(); - if( n==0 ) return "OFF"; - else if( n == 1) return "ON"; - else return "undef"; + int n = t->toInt(); + + if( n == 0 ) { + return "OFF"; + } else if( n == 1) { + return "ON"; + } else { + return "undef"; + } } }; CAOnOffInterpreter caOnOffInterpreter; -class CAIntSerNumInterpreter : public Interpreter { - public: - CAIntSerNumInterpreter () {} - virtual std::string toString (Tag* t) { return ""; } +class CAIntSerNumInterpreter : public Interpreter +{ +public: + CAIntSerNumInterpreter () {} + virtual std::string toString (Tag* t) + { + return ""; + } }; CAIntSerNumInterpreter caIntSerNumInterpreter; -class CAApertureInterpreter : public Interpreter { - public: - CAApertureInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - double v = pow(2.0, t->toDouble()/64.0); - if( v<0. || v> 1000.) return "undef"; - sprintf (buffer, "%.1f",v ); - return buffer; +class CAApertureInterpreter : public Interpreter +{ +public: + CAApertureInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + double v = pow(2.0, t->toDouble() / 64.0); + + if( v < 0. || v > 1000.) { + return "undef"; } + + sprintf (buffer, "%.1f", v ); + return buffer; + } }; CAApertureInterpreter caApertureInterpreter; -class CAMacroModeInterpreter : public ChoiceInterpreter { +class CAMacroModeInterpreter : public ChoiceInterpreter +{ public: - CAMacroModeInterpreter(){ + CAMacroModeInterpreter() + { choices[1] = "Macro"; choices[2] = "Normal"; - } + } }; CAMacroModeInterpreter caMacroModeInterpreter; -class CASelfTimerInterpreter : public Interpreter { +class CASelfTimerInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - int sec = t->toInt(0,SHORT); - if( !sec ) return "OFF"; - char buffer[32]; - sprintf (buffer, "%.1fs %s", sec/10., sec&0x4000?",Custom":""); + virtual std::string toString (Tag* t) + { + int sec = t->toInt(0, SHORT); + + if( !sec ) { + return "OFF"; + } + + char buffer[32]; + sprintf (buffer, "%.1fs %s", sec / 10., sec & 0x4000 ? ",Custom" : ""); return buffer; } }; CASelfTimerInterpreter caSelfTimerInterpreter; -class CAQualityInterpreter : public ChoiceInterpreter { +class CAQualityInterpreter : public ChoiceInterpreter +{ public: - CAQualityInterpreter(){ + CAQualityInterpreter() + { choices[1] = "Economy"; choices[2] = "Normal"; choices[3] = "Fine"; choices[4] = "RAW"; choices[5] = "Superfine"; - } + } }; CAQualityInterpreter caQualityInterpreter; -class CAFlashModeInterpreter : public ChoiceInterpreter { +class CAFlashModeInterpreter : public ChoiceInterpreter +{ public: - CAFlashModeInterpreter(){ + CAFlashModeInterpreter() + { choices[0] = "Off"; choices[1] = "Auto"; choices[2] = "On"; @@ -104,27 +133,31 @@ public: choices[4] = "Slow-sync"; choices[5] = "Red-eye reduction (Auto)"; choices[6] = "Red-eye reduction (On)"; - choices[16]= "External flash"; - } + choices[16] = "External flash"; + } }; CAFlashModeInterpreter caFlashModeInterpreter; -class CAContinuousDriveInterpreter : public ChoiceInterpreter { +class CAContinuousDriveInterpreter : public ChoiceInterpreter +{ public: - CAContinuousDriveInterpreter(){ + CAContinuousDriveInterpreter() + { choices[0] = "Single"; choices[1] = "Continuous"; choices[2] = "Movie"; choices[3] = "Continuous, Speed Priority"; choices[4] = "Continuous, Low"; choices[5] = "Continuous, High"; - } + } }; CAContinuousDriveInterpreter caContinuousDriveInterpreter; -class CAFocusModeInterpreter : public ChoiceInterpreter { +class CAFocusModeInterpreter : public ChoiceInterpreter +{ public: - CAFocusModeInterpreter(){ + CAFocusModeInterpreter() + { choices[0] = "One-shot AF"; choices[1] = "AI Servo AF"; choices[2] = "AI Focus AF"; @@ -133,13 +166,15 @@ public: choices[5] = "Continuous"; choices[6] = "Manual Focus"; choices[16] = "Pan Focus"; - } + } }; CAFocusModeInterpreter caFocusModeInterpreter; -class CARecordModeInterpreter : public ChoiceInterpreter { +class CARecordModeInterpreter : public ChoiceInterpreter +{ public: - CARecordModeInterpreter(){ + CARecordModeInterpreter() + { choices[1] = "JPEG"; choices[2] = "CRW+THM"; choices[3] = "AVI+THM"; @@ -148,13 +183,15 @@ public: choices[6] = "CR2"; choices[7] = "CR2+JPEG"; choices[9] = "Video"; - } + } }; CARecordModeInterpreter caRecordModeInterpreter; -class CAImageSizeInterpreter : public ChoiceInterpreter { +class CAImageSizeInterpreter : public ChoiceInterpreter +{ public: - CAImageSizeInterpreter (){ + CAImageSizeInterpreter () + { choices[0] = "Large"; choices[1] = "Medium"; choices[2] = "Small"; @@ -169,13 +206,15 @@ public: choices[130] = "Small Movie"; choices[137] = "1280x720 Movie"; choices[142] = "1920x1080 Movie"; - } + } }; CAImageSizeInterpreter caImageSizeInterpreter; -class CAEasyModeInterpreter : public ChoiceInterpreter { +class CAEasyModeInterpreter : public ChoiceInterpreter +{ public: - CAEasyModeInterpreter (){ + CAEasyModeInterpreter () + { choices[0] = "Full auto "; choices[1] = "Manual "; choices[2] = "Landscape "; @@ -214,38 +253,44 @@ public: choices[43] = "Poster"; choices[47] = "Fisheye"; choices[48] = "Miniature"; - choices[261]= "Sunset"; - } + choices[261] = "Sunset"; + } }; CAEasyModeInterpreter caEasyModeInterpreter; -class CADigitalZoomInterpreter : public ChoiceInterpreter { +class CADigitalZoomInterpreter : public ChoiceInterpreter +{ public: - CADigitalZoomInterpreter(){ + CADigitalZoomInterpreter() + { choices[0] = "None"; choices[1] = "2x"; choices[2] = "4x"; choices[3] = "Other"; - } + } }; CADigitalZoomInterpreter caDigitalZoomInterpreter; -class CAMeteringModeInterpreter : public ChoiceInterpreter { +class CAMeteringModeInterpreter : public ChoiceInterpreter +{ public: - CAMeteringModeInterpreter(){ + CAMeteringModeInterpreter() + { choices[0] = "Default"; choices[1] = "Spot"; choices[2] = "Average"; choices[3] = "Evaluative"; choices[4] = "Partial"; choices[5] = "Center-weighted averaging"; - } + } }; CAMeteringModeInterpreter caMeteringModeInterpreter; -class CAFocusRangeInterpreter : public ChoiceInterpreter { +class CAFocusRangeInterpreter : public ChoiceInterpreter +{ public: - CAFocusRangeInterpreter(){ + CAFocusRangeInterpreter() + { choices[0] = "Manual"; choices[1] = "Auto"; choices[2] = "Not Known"; @@ -257,13 +302,15 @@ public: choices[8] = "Pan Focus"; choices[9] = "Super Macro"; choices[10] = "Infinity"; - } + } }; CAFocusRangeInterpreter caFocusRangeInterpreter; -class CAAFPointInterpreter : public ChoiceInterpreter { +class CAAFPointInterpreter : public ChoiceInterpreter +{ public: - CAAFPointInterpreter(){ + CAAFPointInterpreter() + { choices[0x2005] = "Manual AF point selection "; choices[0x3000] = "None (MF)"; choices[0x3001] = "Auto AF point selection "; @@ -272,13 +319,15 @@ public: choices[0x3004] = "Left "; choices[0x4001] = "Auto AF point selection "; choices[0x4006] = "Face Detect"; - } + } }; CAAFPointInterpreter caAFPointInterpreter; -class CAExposureModeInterpreter : public ChoiceInterpreter { +class CAExposureModeInterpreter : public ChoiceInterpreter +{ public: - CAExposureModeInterpreter(){ + CAExposureModeInterpreter() + { choices[0] = "Easy"; choices[1] = "Program AE"; choices[2] = "Shutter speed priority AE"; @@ -287,75 +336,115 @@ public: choices[5] = "Depth-of-field AE"; choices[6] = "M-Dep"; choices[7] = "Bulb"; - } + } }; CAExposureModeInterpreter caExposureModeInterpreter; -class CAFlashBitsInterpreter : public Interpreter { +class CAFlashBitsInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - std::ostringstream s; - unsigned bits = t->toInt(0,SHORT); - if( bits & 0x0001 ) s << "Manual "; - if( bits & 0x0002 ) s << "TTL "; - if( bits & 0x0004 ) s << "A-TTL "; - if( bits & 0x0008 ) s << "E-TTL "; - if( bits & 0x0010 ) s << "FP sync enabled "; - if( bits & 0x0080 ) s << "2nd curtain "; - if( bits & 0x0800 ) s << "FP sync used "; - if( bits & 0x2000 ) s << "Built-in "; - if( bits & 0x4000 ) s << "External "; + virtual std::string toString (Tag* t) + { + std::ostringstream s; + unsigned bits = t->toInt(0, SHORT); + + if( bits & 0x0001 ) { + s << "Manual "; + } + + if( bits & 0x0002 ) { + s << "TTL "; + } + + if( bits & 0x0004 ) { + s << "A-TTL "; + } + + if( bits & 0x0008 ) { + s << "E-TTL "; + } + + if( bits & 0x0010 ) { + s << "FP sync enabled "; + } + + if( bits & 0x0080 ) { + s << "2nd curtain "; + } + + if( bits & 0x0800 ) { + s << "FP sync used "; + } + + if( bits & 0x2000 ) { + s << "Built-in "; + } + + if( bits & 0x4000 ) { + s << "External "; + } + return s.str(); } }; CAFlashBitsInterpreter caFlashBitsInterpreter; -class CAFocusContinuousInterpreter : public ChoiceInterpreter { +class CAFocusContinuousInterpreter : public ChoiceInterpreter +{ public: - CAFocusContinuousInterpreter(){ + CAFocusContinuousInterpreter() + { choices[0] = "Single"; choices[1] = "Continuous"; choices[8] = "Manual"; - } + } }; CAFocusContinuousInterpreter caFocusContinuousInterpreter; -class CAAESettingsInterpreter : public ChoiceInterpreter { +class CAAESettingsInterpreter : public ChoiceInterpreter +{ public: - CAAESettingsInterpreter(){ + CAAESettingsInterpreter() + { choices[0] = "Normal AE"; choices[1] = "Exposure Compensation"; choices[2] = "AE Lock"; choices[3] = "AE Lock + Exposure Comp."; choices[4] = "No AE"; - } + } }; CAAESettingsInterpreter caAESettingsInterpreter; -class CAStabilizationInterpreter : public ChoiceInterpreter { +class CAStabilizationInterpreter : public ChoiceInterpreter +{ public: - CAStabilizationInterpreter(){ + CAStabilizationInterpreter() + { choices[0] = "Off"; choices[1] = "On"; choices[2] = "On, Shot Only"; choices[3] = "On, Panning"; choices[4] = "On, Video"; - } + } }; CAStabilizationInterpreter caStabilizationInterpreter; -class CASpotMeteringInterpreter : public ChoiceInterpreter { +class CASpotMeteringInterpreter : public ChoiceInterpreter +{ public: - CASpotMeteringInterpreter(){ + CASpotMeteringInterpreter() + { choices[0] = "Center"; choices[1] = "AF Point"; - } + } }; CASpotMeteringInterpreter caSpotMeteringInterpreter; -class CAPhotoEffectInterpreter : public ChoiceInterpreter { +class CAPhotoEffectInterpreter : public ChoiceInterpreter +{ public: - CAPhotoEffectInterpreter(){ + CAPhotoEffectInterpreter() + { choices[0] = "Off"; choices[1] = "Vivid"; choices[2] = "Neutral"; @@ -364,518 +453,591 @@ public: choices[5] = "B&W"; choices[6] = "Custom"; choices[100] = "My Color Data"; - } + } }; CAPhotoEffectInterpreter caPhotoEffectInterpreter; -class CAManualFlashInterpreter : public ChoiceInterpreter { +class CAManualFlashInterpreter : public ChoiceInterpreter +{ public: - CAManualFlashInterpreter(){ + CAManualFlashInterpreter() + { choices[0] = "N/A"; choices[0x500] = "Full"; choices[0x502] = "Medium"; choices[0x504] = "Low"; choices[0x7fff] = "N/A"; - } + } }; CAManualFlashInterpreter caManualFlashInterpreter; -class CARAWQualityInterpreter : public ChoiceInterpreter { +class CARAWQualityInterpreter : public ChoiceInterpreter +{ public: - CARAWQualityInterpreter(){ + CARAWQualityInterpreter() + { choices[0] = "N/A"; choices[1] = "sRAW1 (mRAW)"; choices[2] = "sRAW2 (sRAW)"; - } + } }; CARAWQualityInterpreter caRAWQualityInterpreter; -class CAFocalInterpreter : public Interpreter { +class CAFocalInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - Tag *unitTag = t->getParent()->getRoot()->findTag("FocalUnits"); - double v = unitTag?unitTag->toDouble():1.; - v = (v>0. ? t->toDouble()/v : t->toDouble()); - if( v <0. || v>1000000.) return "undef"; - char buffer[32]; + virtual std::string toString (Tag* t) + { + Tag *unitTag = t->getParent()->getRoot()->findTag("FocalUnits"); + double v = unitTag ? unitTag->toDouble() : 1.; + v = (v > 0. ? t->toDouble() / v : t->toDouble()); + + if( v < 0. || v > 1000000.) { + return "undef"; + } + + char buffer[32]; sprintf (buffer, "%.1f", v ); return buffer; } }; CAFocalInterpreter caFocalInterpreter; -class CALensInterpreter : public IntLensInterpreter< int > { - public: - CALensInterpreter () { // From EXIFTOOL database 'Canon.pm' V3.19 - choices.insert(p_t(1, "Canon EF 50mm f/1.8")); - choices.insert(p_t(2, "Canon EF 28mm f/2.8")); - choices.insert(p_t(3, "Canon EF 135mm f/2.8 Soft")); - choices.insert(p_t(4, "Canon EF 35-105mm f/3.5-4.5")); - choices.insert(p_t(4, "Sigma UC Zoom 35-135mm f/4-5.6")); - choices.insert(p_t(5, "Canon EF 35-70mm f/3.5-4.5")); - choices.insert(p_t(6, "Canon EF 28-70mm f/3.5-4.5")); - choices.insert(p_t(6, "Sigma 18-50mm f/3.5-5.6 DC")); - choices.insert(p_t(6, "Sigma 18-125mm f/3.5-5.6 DC IF ASP")); - choices.insert(p_t(6, "Tokina AF 193-2 19-35mm f/3.5-4.5")); - choices.insert(p_t(6, "Sigma 28-80mm f/3.5-5.6 II Macro")); - choices.insert(p_t(7, "Canon EF 100-300mm f/5.6L")); - choices.insert(p_t(8, "Canon EF 100-300mm f/5.6")); - choices.insert(p_t(8, "Sigma 70-300mm f/4-5.6 [APO] DG Macro")); - choices.insert(p_t(8, "Tokina AT-X 242 AF 24-200mm f/3.5-5.6")); - choices.insert(p_t(9, "Canon EF 70-210mm f/4")); - choices.insert(p_t(9, "Sigma 55-200mm f/4-5.6 DC")); - choices.insert(p_t(10, "Canon EF 50mm f/2.5 Macro")); - choices.insert(p_t(10, "Sigma 50mm f/2.8 EX")); - choices.insert(p_t(10, "Sigma 28mm f/1.8")); - choices.insert(p_t(10, "Sigma 105mm f/2.8 Macro EX")); - choices.insert(p_t(10, "Sigma 70mm f/2.8 EX DG Macro EF")); - choices.insert(p_t(11, "Canon EF 35mm f/2")); - choices.insert(p_t(13, "Canon EF 15mm f/2.8 Fisheye")); - choices.insert(p_t(14, "Canon EF 50-200mm f/3.5-4.5L")); - choices.insert(p_t(15, "Canon EF 50-200mm f/3.5-4.5")); - choices.insert(p_t(16, "Canon EF 35-135mm f/3.5-4.5")); - choices.insert(p_t(17, "Canon EF 35-70mm f/3.5-4.5A")); - choices.insert(p_t(18, "Canon EF 28-70mm f/3.5-4.5")); - choices.insert(p_t(20, "Canon EF 100-200mm f/4.5A")); - choices.insert(p_t(21, "Canon EF 80-200mm f/2.8L")); - choices.insert(p_t(22, "Canon EF 20-35mm f/2.8L")); - choices.insert(p_t(22, "Tokina AT-X 280 AF Pro 28-80mm f/2.8 Aspherical")); - choices.insert(p_t(23, "Canon EF 35-105mm f/3.5-4.5")); - choices.insert(p_t(24, "Canon EF 35-80mm f/4-5.6 Power Zoom")); - choices.insert(p_t(25, "Canon EF 35-80mm f/4-5.6 Power Zoom")); - choices.insert(p_t(26, "Canon EF 100mm f/2.8 Macro")); - choices.insert(p_t(26, "Cosina 100mm f/3.5 Macro AF")); - choices.insert(p_t(26, "Tamron SP AF 90mm f/2.8 Di Macro")); - choices.insert(p_t(26, "Tamron SP AF 180mm f/3.5 Di Macro")); - choices.insert(p_t(26, "Carl Zeiss Planar T* 50mm f/1.4")); - choices.insert(p_t(27, "Canon EF 35-80mm f/4-5.6")); - choices.insert(p_t(28, "Canon EF 80-200mm f/4.5-5.6")); - choices.insert(p_t(28, "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical IF Macro")); - choices.insert(p_t(28, "Tamron SP AF 28-105mm f/2.8 LD Aspherical IF")); - choices.insert(p_t(28, "Tamron AF 28-200mm f/3.8-5.6 Aspherical")); - choices.insert(p_t(28, "Tamron AF 70-300mm f/4.5-5.6 Di LD 1:2 Macro Zoom")); - choices.insert(p_t(29, "Canon EF 50mm f/1.8 II")); - choices.insert(p_t(30, "Canon EF 35-105mm f/4.5-5.6")); - choices.insert(p_t(31, "Canon EF 75-300mm f/4-5.6")); - choices.insert(p_t(31, "Tamron SP AF 300mm f/2.8 LD IF")); - choices.insert(p_t(32, "Canon EF 24mm f/2.8")); - choices.insert(p_t(32, "Sigma 15mm f/2.8 EX Fisheye")); - choices.insert(p_t(33, "Voigtlander or Carl Zeiss Lens")); - choices.insert(p_t(33, "Voigtlander Ultron 40mm f/2 SLII Aspherical")); - choices.insert(p_t(33, "Carl Zeiss Distagon T* 15mm f/2.8 ZE")); - choices.insert(p_t(33, "Carl Zeiss Distagon T* 18mm f/3.5 ZE")); - choices.insert(p_t(33, "Carl Zeiss Distagon T* 21mm f/2.8 ZE")); - choices.insert(p_t(33, "Carl Zeiss Distagon T* 28mm f/2 ZE")); - choices.insert(p_t(33, "Carl Zeiss Distagon T* 35mm f/2 ZE")); - choices.insert(p_t(35, "Canon EF 35-80mm f/4-5.6")); - choices.insert(p_t(36, "Canon EF 38-76mm f/4.5-5.6")); - choices.insert(p_t(37, "Canon EF 35-80mm f/4-5.6")); - choices.insert(p_t(37, "Tamron 70-200mm f/2.8 Di LD IF Macro")); - choices.insert(p_t(37, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical IF Macro (A20)")); - choices.insert(p_t(37, "Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical IF")); - choices.insert(p_t(37, "Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical IF Macro")); - choices.insert(p_t(38, "Canon EF 80-200mm f/4.5-5.6")); - choices.insert(p_t(39, "Canon EF 75-300mm f/4-5.6")); - choices.insert(p_t(40, "Canon EF 28-80mm f/3.5-5.6")); - choices.insert(p_t(41, "Canon EF 28-90mm f/4-5.6")); - choices.insert(p_t(42, "Canon EF 28-200mm f/3.5-5.6")); - choices.insert(p_t(42, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical IF Macro (A20)")); - choices.insert(p_t(43, "Canon EF 28-105mm f/4-5.6")); - choices.insert(p_t(44, "Canon EF 90-300mm f/4.5-5.6")); - choices.insert(p_t(45, "Canon EF-S 18-55mm f/3.5-5.6 II")); - choices.insert(p_t(46, "Canon EF 28-90mm f/4-5.6")); - choices.insert(p_t(48, "Canon EF-S 18-55mm f/3.5-5.6 IS")); - choices.insert(p_t(49, "Canon EF-S 55-250mm f/4-5.6 IS")); - choices.insert(p_t(50, "Canon EF-S 18-200mm f/3.5-5.6 IS")); - choices.insert(p_t(51, "Canon EF-S 18-135mm f/3.5-5.6 IS")); - choices.insert(p_t(52, "Canon EF-S 18-55mm f/3.5-5.6 IS II")); - choices.insert(p_t(53, "Canon EF-S 18-55mm f/3.5-5.6 III")); - choices.insert(p_t(54, "Canon EF-S 55-250mm f/4-5.6 IS II")); - choices.insert(p_t(94, "Canon TS-E 17mm f/4L")); - choices.insert(p_t(95, "Canon TS-E 24mm f/3.5 L II")); - choices.insert(p_t(124, "Canon MP-E 65mm f/2.8 1-5x Macro Photo")); - choices.insert(p_t(125, "Canon TS-E 24mm f/3.5L")); - choices.insert(p_t(126, "Canon TS-E 45mm f/2.8")); - choices.insert(p_t(127, "Canon TS-E 90mm f/2.8")); - choices.insert(p_t(129, "Canon EF 300mm f/2.8L")); - choices.insert(p_t(130, "Canon EF 50mm f/1.0L")); - choices.insert(p_t(131, "Canon EF 28-80mm f/2.8-4L")); - choices.insert(p_t(131, "Sigma 8mm f/3.5 EX DG Circular Fisheye")); - choices.insert(p_t(131, "Sigma 17-35mm f/2.8-4 EX DG Aspherical HSM")); - choices.insert(p_t(131, "Sigma 17-70mm f/2.8-4.5 DC Macro")); - choices.insert(p_t(131, "Sigma APO 50-150mm f/2.8 EX DC HSM II")); - choices.insert(p_t(131, "Sigma APO 120-300mm f/2.8 EX DG HSM")); - choices.insert(p_t(131, "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye")); - choices.insert(p_t(131, "Sigma 70-200mm f/2.8 APO EX HSM")); - choices.insert(p_t(132, "Canon EF 1200mm f/5.6L")); - choices.insert(p_t(134, "Canon EF 600mm f/4L IS")); - choices.insert(p_t(135, "Canon EF 200mm f/1.8L")); - choices.insert(p_t(136, "Canon EF 300mm f/2.8L")); - choices.insert(p_t(137, "Canon EF 85mm f/1.2L")); - choices.insert(p_t(137, "Sigma 18-50mm f/2.8-4.5 DC OS HSM")); - choices.insert(p_t(137, "Sigma 50-200mm f/4-5.6 DC OS HSM")); - choices.insert(p_t(137, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); - choices.insert(p_t(137, "Sigma 24-70mm f/2.8 IF EX DG HSM")); - choices.insert(p_t(137, "Sigma 18-125mm f/3.8-5.6 DC OS HSM")); - choices.insert(p_t(137, "Sigma 17-70mm f/2.8-4 DC Macro OS HSM")); - choices.insert(p_t(137, "Sigma 17-50mm f/2.8 OS HSM")); - choices.insert(p_t(137, "Sigma 18-200mm f/3.5-6.3 II DC OS HSM")); - choices.insert(p_t(137, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD")); - choices.insert(p_t(137, "Sigma 8-16mm f/4.5-5.6 DC HSM")); - choices.insert(p_t(137, "Tamron SP 17-50mm f/2.8 XR Di II VC")); - choices.insert(p_t(137, "Tamron SP 60mm f/2 Macro Di II")); - choices.insert(p_t(137, "Sigma 10-20mm f/3.5 EX DC HSM")); - choices.insert(p_t(137, "Tamron SP 24-70mm f/2.8 Di VC USD")); - choices.insert(p_t(138, "Canon EF 28-80mm f/2.8-4L")); - choices.insert(p_t(139, "Canon EF 400mm f/2.8L")); - choices.insert(p_t(140, "Canon EF 500mm f/4.5L")); - choices.insert(p_t(141, "Canon EF 500mm f/4.5L")); - choices.insert(p_t(142, "Canon EF 300mm f/2.8L IS")); - choices.insert(p_t(143, "Canon EF 500mm f/4L IS")); - choices.insert(p_t(144, "Canon EF 35-135mm f/4-5.6 USM")); - choices.insert(p_t(145, "Canon EF 100-300mm f/4.5-5.6 USM")); - choices.insert(p_t(146, "Canon EF 70-210mm f/3.5-4.5 USM")); - choices.insert(p_t(147, "Canon EF 35-135mm f/4-5.6 USM")); - choices.insert(p_t(148, "Canon EF 28-80mm f/3.5-5.6 USM")); - choices.insert(p_t(149, "Canon EF 100mm f/2 USM")); - choices.insert(p_t(150, "Canon EF 14mm f/2.8L")); - choices.insert(p_t(150, "Sigma 20mm f/1.8 EX")); - choices.insert(p_t(150, "Sigma 24mm f/1.8 DG Macro EX")); - choices.insert(p_t(150, "Sigma 30mm f/1.4 DC HSM")); - choices.insert(p_t(151, "Canon EF 200mm f/2.8L")); - choices.insert(p_t(152, "Canon EF 300mm f/4L IS")); - choices.insert(p_t(152, "Sigma 12-24mm f/4.5-5.6 EX DG Aspherical HSM")); - choices.insert(p_t(152, "Sigma 14mm f/2.8 EX Aspherical HSM")); - choices.insert(p_t(152, "Sigma 10-20mm f/4-5.6")); - choices.insert(p_t(152, "Sigma 100-300mm f/4")); - choices.insert(p_t(153, "Canon EF 35-350mm f/3.5-5.6L")); - choices.insert(p_t(153, "Sigma 50-500mm f/4-6.3 APO HSM EX")); - choices.insert(p_t(153, "Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical IF Macro")); - choices.insert(p_t(153, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical IF Macro (A14)")); - choices.insert(p_t(153, "Tamron 18-250mm f/3.5-6.3 Di II LD Aspherical IF Macro")); - choices.insert(p_t(154, "Canon EF 20mm f/2.8 USM")); - choices.insert(p_t(155, "Canon EF 85mm f/1.8 USM")); - choices.insert(p_t(156, "Canon EF 28-105mm f/3.5-4.5 USM")); - choices.insert(p_t(156, "Tamron SP 70-300mm f/4-5.6 Di VC USD")); - choices.insert(p_t(160, "Canon EF 20-35mm f/3.5-4.5 USM")); - choices.insert(p_t(160, "Tamron AF 19-35mm f/3.5-4.5")); - choices.insert(p_t(160, "Tokina AT-X 124 AF Pro DX 12-24mm f/4")); - choices.insert(p_t(160, "Tokina AT-X 107 AF DX 10-17mm f/3.5-4.5 Fisheye")); - choices.insert(p_t(160, "Tokina AT-X 116 AF Pro DX 11-16mm f/2.8")); - choices.insert(p_t(161, "Canon EF 28-70mm f/2.8L")); - choices.insert(p_t(161, "Sigma 24-70mm f/2.8 EX")); - choices.insert(p_t(161, "Sigma 28-70mm f/2.8 EX")); - choices.insert(p_t(161, "Tamron AF 17-50mm f/2.8 Di-II LD Aspherical")); - choices.insert(p_t(161, "Tamron 90mm f/2.8")); - choices.insert(p_t(161, "Sigma 24-60mm f/2.8 EX DG")); - choices.insert(p_t(162, "Canon EF 200mm f/2.8L")); - choices.insert(p_t(163, "Canon EF 300mm f/4L")); - choices.insert(p_t(164, "Canon EF 400mm f/5.6L")); - choices.insert(p_t(165, "Canon EF 70-200mm f/2.8 L")); - choices.insert(p_t(166, "Canon EF 70-200mm f/2.8 L + x1.4")); - choices.insert(p_t(167, "Canon EF 70-200mm f/2.8 L + x2")); - choices.insert(p_t(168, "Canon EF 28mm f/1.8 USM")); - choices.insert(p_t(169, "Canon EF 17-35mm f/2.8L")); - choices.insert(p_t(169, "Sigma 18-200mm f/3.5-6.3 DC OS")); - choices.insert(p_t(169, "Sigma 15-30mm f/3.5-4.5 EX DG Aspherical")); - choices.insert(p_t(169, "Sigma 18-50mm f/2.8 Macro")); - choices.insert(p_t(169, "Sigma 30mm f/1.4 EX DC HSM")); - choices.insert(p_t(169, "Sigma 50mm f/1.4 EX DG HSM")); - choices.insert(p_t(169, "Sigma 85mm f/1.4 EX DG HSM")); - choices.insert(p_t(169, "Sigma 35mm f/1.4 DG HSM")); - choices.insert(p_t(170, "Canon EF 200mm f/2.8L II")); - choices.insert(p_t(171, "Canon EF 300mm f/4L")); - choices.insert(p_t(172, "Canon EF 400mm f/5.6L")); - choices.insert(p_t(173, "Canon EF 180mm f/3.5L Macro")); - choices.insert(p_t(173, "Sigma 180mm f/3.5 EX HSM Macro")); - choices.insert(p_t(173, "Sigma APO 150mm f/2.8 EX DG HSM Macro")); - choices.insert(p_t(174, "Canon EF 135mm f/2L")); - choices.insert(p_t(174, "Sigma 70-200mm f/2.8 EX DG APO OS HSM")); - choices.insert(p_t(174, "Sigma 50-500mm f/4.5-6.3 APO DG OS HSM")); - choices.insert(p_t(175, "Canon EF 400mm f/2.8L")); - choices.insert(p_t(176, "Canon EF 24-85mm f/3.5-4.5 USM")); - choices.insert(p_t(177, "Canon EF 300mm f/4L IS")); - choices.insert(p_t(178, "Canon EF 28-135mm f/3.5-5.6 IS")); - choices.insert(p_t(179, "Canon EF 24mm f/1.4L")); - choices.insert(p_t(180, "Canon EF 35mm f/1.4L")); - choices.insert(p_t(181, "Canon EF 100-400mm f/4.5-5.6L IS + x1.4")); - choices.insert(p_t(182, "Canon EF 100-400mm f/4.5-5.6L IS + x2")); - choices.insert(p_t(183, "Canon EF 100-400mm f/4.5-5.6L IS")); - choices.insert(p_t(183, "Sigma 150mm f/2.8 EX DG OS HSM APO Macro")); - choices.insert(p_t(183, "Sigma 105mm f/2.8 EX DG OS HSM Macro")); - choices.insert(p_t(184, "Canon EF 400mm f/2.8L + x2")); - choices.insert(p_t(185, "Canon EF 600mm f/4L IS")); - choices.insert(p_t(186, "Canon EF 70-200mm f/4L")); - choices.insert(p_t(187, "Canon EF 70-200mm f/4L + 1.4x")); - choices.insert(p_t(188, "Canon EF 70-200mm f/4L + 2x")); - choices.insert(p_t(189, "Canon EF 70-200mm f/4L + 2.8x")); - choices.insert(p_t(190, "Canon EF 100mm f/2.8 Macro")); - choices.insert(p_t(191, "Canon EF 400mm f/4 DO IS")); - choices.insert(p_t(193, "Canon EF 35-80mm f/4-5.6 USM")); - choices.insert(p_t(194, "Canon EF 80-200mm f/4.5-5.6 USM")); - choices.insert(p_t(195, "Canon EF 35-105mm f/4.5-5.6 USM")); - choices.insert(p_t(196, "Canon EF 75-300mm f/4-5.6 USM")); - choices.insert(p_t(197, "Canon EF 75-300mm f/4-5.6 IS USM")); - choices.insert(p_t(198, "Canon EF 50mm f/1.4 USM")); - choices.insert(p_t(199, "Canon EF 28-80mm f/3.5-5.6 USM")); - choices.insert(p_t(200, "Canon EF 75-300mm f/4-5.6 USM")); - choices.insert(p_t(201, "Canon EF 28-80mm f/3.5-5.6 USM")); - choices.insert(p_t(202, "Canon EF 28-80mm f/3.5-5.6 USM IV")); - choices.insert(p_t(208, "Canon EF 22-55mm f/4-5.6 USM")); - choices.insert(p_t(209, "Canon EF 55-200mm f/4.5-5.6")); - choices.insert(p_t(210, "Canon EF 28-90mm f/4-5.6 USM")); - choices.insert(p_t(211, "Canon EF 28-200mm f/3.5-5.6 USM")); - choices.insert(p_t(212, "Canon EF 28-105mm f/4-5.6 USM")); - choices.insert(p_t(213, "Canon EF 90-300mm f/4.5-5.6 USM")); - choices.insert(p_t(214, "Canon EF-S 18-55mm f/3.5-5.6 USM")); - choices.insert(p_t(215, "Canon EF 55-200mm f/4.5-5.6 II USM")); - choices.insert(p_t(224, "Canon EF 70-200mm f/2.8L IS")); - choices.insert(p_t(225, "Canon EF 70-200mm f/2.8L IS + x1.4")); - choices.insert(p_t(226, "Canon EF 70-200mm f/2.8L IS + x2")); - choices.insert(p_t(227, "Canon EF 70-200mm f/2.8L IS + x2.8")); - choices.insert(p_t(228, "Canon EF 28-105mm f/3.5-4.5 USM")); - choices.insert(p_t(229, "Canon EF 16-35mm f/2.8L")); - choices.insert(p_t(230, "Canon EF 24-70mm f/2.8L")); - choices.insert(p_t(231, "Canon EF 17-40mm f/4L")); - choices.insert(p_t(232, "Canon EF 70-300mm f/4.5-5.6 DO IS USM")); - choices.insert(p_t(233, "Canon EF 28-300mm f/3.5-5.6L IS")); - choices.insert(p_t(234, "Canon EF-S 17-85mm f4-5.6 IS USM")); - choices.insert(p_t(235, "Canon EF-S 10-22mm f/3.5-4.5 USM")); - choices.insert(p_t(236, "Canon EF-S 60mm f/2.8 Macro USM")); - choices.insert(p_t(237, "Canon EF 24-105mm f/4L IS")); - choices.insert(p_t(238, "Canon EF 70-300mm f/4-5.6 IS USM")); - choices.insert(p_t(239, "Canon EF 85mm f/1.2L II")); - choices.insert(p_t(240, "Canon EF-S 17-55mm f/2.8 IS USM")); - choices.insert(p_t(241, "Canon EF 50mm f/1.2L")); - choices.insert(p_t(242, "Canon EF 70-200mm f/4L IS")); - choices.insert(p_t(243, "Canon EF 70-200mm f/4L IS + 1.4x")); - choices.insert(p_t(244, "Canon EF 70-200mm f/4L IS + 2x")); - choices.insert(p_t(245, "Canon EF 70-200mm f/4L IS + 2.8x")); - choices.insert(p_t(246, "Canon EF 16-35mm f/2.8L II")); - choices.insert(p_t(247, "Canon EF 14mm f/2.8L II USM")); - choices.insert(p_t(248, "Canon EF 200mm f/2L IS")); - choices.insert(p_t(249, "Canon EF 800mm f/5.6L IS")); - choices.insert(p_t(250, "Canon EF 24mm f/1.4L II")); - choices.insert(p_t(251, "Canon EF 70-200mm f/2.8L IS II USM")); - choices.insert(p_t(252, "Canon EF 70-200mm f/2.8L IS II USM + x1.4")); - choices.insert(p_t(253, "Canon EF 70-200mm f/2.8L IS II USM + x2")); - choices.insert(p_t(254, "Canon EF 100mm f/2.8L Macro IS USM")); - choices.insert(p_t(488, "Canon EF-S 15-85mm f/3.5-5.6 IS USM")); - choices.insert(p_t(489, "Canon EF 70-300mm f/4-5.6L IS USM")); - choices.insert(p_t(490, "Canon EF 8-15mm f/4L USM")); - choices.insert(p_t(491, "Canon EF 300mm f/2.8L IS II USM")); - choices.insert(p_t(492, "Canon EF 400mm f/2.8L IS II USM")); - choices.insert(p_t(493, "Canon EF 24-105mm f/4L IS USM")); - choices.insert(p_t(494, "Canon EF 600mm f/4.0L IS II USM")); - choices.insert(p_t(495, "Canon EF 24-70mm f/2.8L II USM")); - choices.insert(p_t(496, "Canon EF 200-400mm f/4L IS USM")); - choices.insert(p_t(502, "Canon EF 28mm f/2.8 IS USM")); - choices.insert(p_t(503, "Canon EF 24mm f/2.8 IS USM")); - choices.insert(p_t(504, "Canon EF 24-70mm f/4L IS USM")); - choices.insert(p_t(505, "Canon EF 35mm f/2 IS USM")); - choices.insert(p_t(4142, "Canon EF-S 18-135mm f/3.5-5.6 IS STM")); - choices.insert(p_t(4143, "Canon EF-M 18-55mm f/3.5-5.6 IS STM")); - choices.insert(p_t(4144, "Canon EF 40mm f/2.8 STM")); - choices.insert(p_t(4145, "Canon EF-M 22mm f/2 STM")); - choices.insert(p_t(4146, "Canon EF-S 18-55mm f/3.5-5.6 IS STM")); - choices.insert(p_t(4147, "Canon EF-M 11-22mm f/4-5.6 IS STM")); +class CALensInterpreter : public IntLensInterpreter< int > +{ +public: + CALensInterpreter () // From EXIFTOOL database 'Canon.pm' V3.19 + { + choices.insert(p_t(1, "Canon EF 50mm f/1.8")); + choices.insert(p_t(2, "Canon EF 28mm f/2.8")); + choices.insert(p_t(3, "Canon EF 135mm f/2.8 Soft")); + choices.insert(p_t(4, "Canon EF 35-105mm f/3.5-4.5")); + choices.insert(p_t(4, "Sigma UC Zoom 35-135mm f/4-5.6")); + choices.insert(p_t(5, "Canon EF 35-70mm f/3.5-4.5")); + choices.insert(p_t(6, "Canon EF 28-70mm f/3.5-4.5")); + choices.insert(p_t(6, "Sigma 18-50mm f/3.5-5.6 DC")); + choices.insert(p_t(6, "Sigma 18-125mm f/3.5-5.6 DC IF ASP")); + choices.insert(p_t(6, "Tokina AF 193-2 19-35mm f/3.5-4.5")); + choices.insert(p_t(6, "Sigma 28-80mm f/3.5-5.6 II Macro")); + choices.insert(p_t(7, "Canon EF 100-300mm f/5.6L")); + choices.insert(p_t(8, "Canon EF 100-300mm f/5.6")); + choices.insert(p_t(8, "Sigma 70-300mm f/4-5.6 [APO] DG Macro")); + choices.insert(p_t(8, "Tokina AT-X 242 AF 24-200mm f/3.5-5.6")); + choices.insert(p_t(9, "Canon EF 70-210mm f/4")); + choices.insert(p_t(9, "Sigma 55-200mm f/4-5.6 DC")); + choices.insert(p_t(10, "Canon EF 50mm f/2.5 Macro")); + choices.insert(p_t(10, "Sigma 50mm f/2.8 EX")); + choices.insert(p_t(10, "Sigma 28mm f/1.8")); + choices.insert(p_t(10, "Sigma 105mm f/2.8 Macro EX")); + choices.insert(p_t(10, "Sigma 70mm f/2.8 EX DG Macro EF")); + choices.insert(p_t(11, "Canon EF 35mm f/2")); + choices.insert(p_t(13, "Canon EF 15mm f/2.8 Fisheye")); + choices.insert(p_t(14, "Canon EF 50-200mm f/3.5-4.5L")); + choices.insert(p_t(15, "Canon EF 50-200mm f/3.5-4.5")); + choices.insert(p_t(16, "Canon EF 35-135mm f/3.5-4.5")); + choices.insert(p_t(17, "Canon EF 35-70mm f/3.5-4.5A")); + choices.insert(p_t(18, "Canon EF 28-70mm f/3.5-4.5")); + choices.insert(p_t(20, "Canon EF 100-200mm f/4.5A")); + choices.insert(p_t(21, "Canon EF 80-200mm f/2.8L")); + choices.insert(p_t(22, "Canon EF 20-35mm f/2.8L")); + choices.insert(p_t(22, "Tokina AT-X 280 AF Pro 28-80mm f/2.8 Aspherical")); + choices.insert(p_t(23, "Canon EF 35-105mm f/3.5-4.5")); + choices.insert(p_t(24, "Canon EF 35-80mm f/4-5.6 Power Zoom")); + choices.insert(p_t(25, "Canon EF 35-80mm f/4-5.6 Power Zoom")); + choices.insert(p_t(26, "Canon EF 100mm f/2.8 Macro")); + choices.insert(p_t(26, "Cosina 100mm f/3.5 Macro AF")); + choices.insert(p_t(26, "Tamron SP AF 90mm f/2.8 Di Macro")); + choices.insert(p_t(26, "Tamron SP AF 180mm f/3.5 Di Macro")); + choices.insert(p_t(26, "Carl Zeiss Planar T* 50mm f/1.4")); + choices.insert(p_t(27, "Canon EF 35-80mm f/4-5.6")); + choices.insert(p_t(28, "Canon EF 80-200mm f/4.5-5.6")); + choices.insert(p_t(28, "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical IF Macro")); + choices.insert(p_t(28, "Tamron SP AF 28-105mm f/2.8 LD Aspherical IF")); + choices.insert(p_t(28, "Tamron AF 28-200mm f/3.8-5.6 Aspherical")); + choices.insert(p_t(28, "Tamron AF 70-300mm f/4.5-5.6 Di LD 1:2 Macro Zoom")); + choices.insert(p_t(29, "Canon EF 50mm f/1.8 II")); + choices.insert(p_t(30, "Canon EF 35-105mm f/4.5-5.6")); + choices.insert(p_t(31, "Canon EF 75-300mm f/4-5.6")); + choices.insert(p_t(31, "Tamron SP AF 300mm f/2.8 LD IF")); + choices.insert(p_t(32, "Canon EF 24mm f/2.8")); + choices.insert(p_t(32, "Sigma 15mm f/2.8 EX Fisheye")); + choices.insert(p_t(33, "Voigtlander or Carl Zeiss Lens")); + choices.insert(p_t(33, "Voigtlander Ultron 40mm f/2 SLII Aspherical")); + choices.insert(p_t(33, "Carl Zeiss Distagon T* 15mm f/2.8 ZE")); + choices.insert(p_t(33, "Carl Zeiss Distagon T* 18mm f/3.5 ZE")); + choices.insert(p_t(33, "Carl Zeiss Distagon T* 21mm f/2.8 ZE")); + choices.insert(p_t(33, "Carl Zeiss Distagon T* 28mm f/2 ZE")); + choices.insert(p_t(33, "Carl Zeiss Distagon T* 35mm f/2 ZE")); + choices.insert(p_t(35, "Canon EF 35-80mm f/4-5.6")); + choices.insert(p_t(36, "Canon EF 38-76mm f/4.5-5.6")); + choices.insert(p_t(37, "Canon EF 35-80mm f/4-5.6")); + choices.insert(p_t(37, "Tamron 70-200mm f/2.8 Di LD IF Macro")); + choices.insert(p_t(37, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical IF Macro (A20)")); + choices.insert(p_t(37, "Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical IF")); + choices.insert(p_t(37, "Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical IF Macro")); + choices.insert(p_t(38, "Canon EF 80-200mm f/4.5-5.6")); + choices.insert(p_t(39, "Canon EF 75-300mm f/4-5.6")); + choices.insert(p_t(40, "Canon EF 28-80mm f/3.5-5.6")); + choices.insert(p_t(41, "Canon EF 28-90mm f/4-5.6")); + choices.insert(p_t(42, "Canon EF 28-200mm f/3.5-5.6")); + choices.insert(p_t(42, "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical IF Macro (A20)")); + choices.insert(p_t(43, "Canon EF 28-105mm f/4-5.6")); + choices.insert(p_t(44, "Canon EF 90-300mm f/4.5-5.6")); + choices.insert(p_t(45, "Canon EF-S 18-55mm f/3.5-5.6 II")); + choices.insert(p_t(46, "Canon EF 28-90mm f/4-5.6")); + choices.insert(p_t(48, "Canon EF-S 18-55mm f/3.5-5.6 IS")); + choices.insert(p_t(49, "Canon EF-S 55-250mm f/4-5.6 IS")); + choices.insert(p_t(50, "Canon EF-S 18-200mm f/3.5-5.6 IS")); + choices.insert(p_t(51, "Canon EF-S 18-135mm f/3.5-5.6 IS")); + choices.insert(p_t(52, "Canon EF-S 18-55mm f/3.5-5.6 IS II")); + choices.insert(p_t(53, "Canon EF-S 18-55mm f/3.5-5.6 III")); + choices.insert(p_t(54, "Canon EF-S 55-250mm f/4-5.6 IS II")); + choices.insert(p_t(94, "Canon TS-E 17mm f/4L")); + choices.insert(p_t(95, "Canon TS-E 24mm f/3.5 L II")); + choices.insert(p_t(124, "Canon MP-E 65mm f/2.8 1-5x Macro Photo")); + choices.insert(p_t(125, "Canon TS-E 24mm f/3.5L")); + choices.insert(p_t(126, "Canon TS-E 45mm f/2.8")); + choices.insert(p_t(127, "Canon TS-E 90mm f/2.8")); + choices.insert(p_t(129, "Canon EF 300mm f/2.8L")); + choices.insert(p_t(130, "Canon EF 50mm f/1.0L")); + choices.insert(p_t(131, "Canon EF 28-80mm f/2.8-4L")); + choices.insert(p_t(131, "Sigma 8mm f/3.5 EX DG Circular Fisheye")); + choices.insert(p_t(131, "Sigma 17-35mm f/2.8-4 EX DG Aspherical HSM")); + choices.insert(p_t(131, "Sigma 17-70mm f/2.8-4.5 DC Macro")); + choices.insert(p_t(131, "Sigma APO 50-150mm f/2.8 EX DC HSM II")); + choices.insert(p_t(131, "Sigma APO 120-300mm f/2.8 EX DG HSM")); + choices.insert(p_t(131, "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye")); + choices.insert(p_t(131, "Sigma 70-200mm f/2.8 APO EX HSM")); + choices.insert(p_t(132, "Canon EF 1200mm f/5.6L")); + choices.insert(p_t(134, "Canon EF 600mm f/4L IS")); + choices.insert(p_t(135, "Canon EF 200mm f/1.8L")); + choices.insert(p_t(136, "Canon EF 300mm f/2.8L")); + choices.insert(p_t(137, "Canon EF 85mm f/1.2L")); + choices.insert(p_t(137, "Sigma 18-50mm f/2.8-4.5 DC OS HSM")); + choices.insert(p_t(137, "Sigma 50-200mm f/4-5.6 DC OS HSM")); + choices.insert(p_t(137, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); + choices.insert(p_t(137, "Sigma 24-70mm f/2.8 IF EX DG HSM")); + choices.insert(p_t(137, "Sigma 18-125mm f/3.8-5.6 DC OS HSM")); + choices.insert(p_t(137, "Sigma 17-70mm f/2.8-4 DC Macro OS HSM")); + choices.insert(p_t(137, "Sigma 17-50mm f/2.8 OS HSM")); + choices.insert(p_t(137, "Sigma 18-200mm f/3.5-6.3 II DC OS HSM")); + choices.insert(p_t(137, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD")); + choices.insert(p_t(137, "Sigma 8-16mm f/4.5-5.6 DC HSM")); + choices.insert(p_t(137, "Tamron SP 17-50mm f/2.8 XR Di II VC")); + choices.insert(p_t(137, "Tamron SP 60mm f/2 Macro Di II")); + choices.insert(p_t(137, "Sigma 10-20mm f/3.5 EX DC HSM")); + choices.insert(p_t(137, "Tamron SP 24-70mm f/2.8 Di VC USD")); + choices.insert(p_t(138, "Canon EF 28-80mm f/2.8-4L")); + choices.insert(p_t(139, "Canon EF 400mm f/2.8L")); + choices.insert(p_t(140, "Canon EF 500mm f/4.5L")); + choices.insert(p_t(141, "Canon EF 500mm f/4.5L")); + choices.insert(p_t(142, "Canon EF 300mm f/2.8L IS")); + choices.insert(p_t(143, "Canon EF 500mm f/4L IS")); + choices.insert(p_t(144, "Canon EF 35-135mm f/4-5.6 USM")); + choices.insert(p_t(145, "Canon EF 100-300mm f/4.5-5.6 USM")); + choices.insert(p_t(146, "Canon EF 70-210mm f/3.5-4.5 USM")); + choices.insert(p_t(147, "Canon EF 35-135mm f/4-5.6 USM")); + choices.insert(p_t(148, "Canon EF 28-80mm f/3.5-5.6 USM")); + choices.insert(p_t(149, "Canon EF 100mm f/2 USM")); + choices.insert(p_t(150, "Canon EF 14mm f/2.8L")); + choices.insert(p_t(150, "Sigma 20mm f/1.8 EX")); + choices.insert(p_t(150, "Sigma 24mm f/1.8 DG Macro EX")); + choices.insert(p_t(150, "Sigma 30mm f/1.4 DC HSM")); + choices.insert(p_t(151, "Canon EF 200mm f/2.8L")); + choices.insert(p_t(152, "Canon EF 300mm f/4L IS")); + choices.insert(p_t(152, "Sigma 12-24mm f/4.5-5.6 EX DG Aspherical HSM")); + choices.insert(p_t(152, "Sigma 14mm f/2.8 EX Aspherical HSM")); + choices.insert(p_t(152, "Sigma 10-20mm f/4-5.6")); + choices.insert(p_t(152, "Sigma 100-300mm f/4")); + choices.insert(p_t(153, "Canon EF 35-350mm f/3.5-5.6L")); + choices.insert(p_t(153, "Sigma 50-500mm f/4-6.3 APO HSM EX")); + choices.insert(p_t(153, "Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical IF Macro")); + choices.insert(p_t(153, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical IF Macro (A14)")); + choices.insert(p_t(153, "Tamron 18-250mm f/3.5-6.3 Di II LD Aspherical IF Macro")); + choices.insert(p_t(154, "Canon EF 20mm f/2.8 USM")); + choices.insert(p_t(155, "Canon EF 85mm f/1.8 USM")); + choices.insert(p_t(156, "Canon EF 28-105mm f/3.5-4.5 USM")); + choices.insert(p_t(156, "Tamron SP 70-300mm f/4-5.6 Di VC USD")); + choices.insert(p_t(160, "Canon EF 20-35mm f/3.5-4.5 USM")); + choices.insert(p_t(160, "Tamron AF 19-35mm f/3.5-4.5")); + choices.insert(p_t(160, "Tokina AT-X 124 AF Pro DX 12-24mm f/4")); + choices.insert(p_t(160, "Tokina AT-X 107 AF DX 10-17mm f/3.5-4.5 Fisheye")); + choices.insert(p_t(160, "Tokina AT-X 116 AF Pro DX 11-16mm f/2.8")); + choices.insert(p_t(161, "Canon EF 28-70mm f/2.8L")); + choices.insert(p_t(161, "Sigma 24-70mm f/2.8 EX")); + choices.insert(p_t(161, "Sigma 28-70mm f/2.8 EX")); + choices.insert(p_t(161, "Tamron AF 17-50mm f/2.8 Di-II LD Aspherical")); + choices.insert(p_t(161, "Tamron 90mm f/2.8")); + choices.insert(p_t(161, "Sigma 24-60mm f/2.8 EX DG")); + choices.insert(p_t(162, "Canon EF 200mm f/2.8L")); + choices.insert(p_t(163, "Canon EF 300mm f/4L")); + choices.insert(p_t(164, "Canon EF 400mm f/5.6L")); + choices.insert(p_t(165, "Canon EF 70-200mm f/2.8 L")); + choices.insert(p_t(166, "Canon EF 70-200mm f/2.8 L + x1.4")); + choices.insert(p_t(167, "Canon EF 70-200mm f/2.8 L + x2")); + choices.insert(p_t(168, "Canon EF 28mm f/1.8 USM")); + choices.insert(p_t(169, "Canon EF 17-35mm f/2.8L")); + choices.insert(p_t(169, "Sigma 18-200mm f/3.5-6.3 DC OS")); + choices.insert(p_t(169, "Sigma 15-30mm f/3.5-4.5 EX DG Aspherical")); + choices.insert(p_t(169, "Sigma 18-50mm f/2.8 Macro")); + choices.insert(p_t(169, "Sigma 30mm f/1.4 EX DC HSM")); + choices.insert(p_t(169, "Sigma 50mm f/1.4 EX DG HSM")); + choices.insert(p_t(169, "Sigma 85mm f/1.4 EX DG HSM")); + choices.insert(p_t(169, "Sigma 35mm f/1.4 DG HSM")); + choices.insert(p_t(170, "Canon EF 200mm f/2.8L II")); + choices.insert(p_t(171, "Canon EF 300mm f/4L")); + choices.insert(p_t(172, "Canon EF 400mm f/5.6L")); + choices.insert(p_t(173, "Canon EF 180mm f/3.5L Macro")); + choices.insert(p_t(173, "Sigma 180mm f/3.5 EX HSM Macro")); + choices.insert(p_t(173, "Sigma APO 150mm f/2.8 EX DG HSM Macro")); + choices.insert(p_t(174, "Canon EF 135mm f/2L")); + choices.insert(p_t(174, "Sigma 70-200mm f/2.8 EX DG APO OS HSM")); + choices.insert(p_t(174, "Sigma 50-500mm f/4.5-6.3 APO DG OS HSM")); + choices.insert(p_t(175, "Canon EF 400mm f/2.8L")); + choices.insert(p_t(176, "Canon EF 24-85mm f/3.5-4.5 USM")); + choices.insert(p_t(177, "Canon EF 300mm f/4L IS")); + choices.insert(p_t(178, "Canon EF 28-135mm f/3.5-5.6 IS")); + choices.insert(p_t(179, "Canon EF 24mm f/1.4L")); + choices.insert(p_t(180, "Canon EF 35mm f/1.4L")); + choices.insert(p_t(181, "Canon EF 100-400mm f/4.5-5.6L IS + x1.4")); + choices.insert(p_t(182, "Canon EF 100-400mm f/4.5-5.6L IS + x2")); + choices.insert(p_t(183, "Canon EF 100-400mm f/4.5-5.6L IS")); + choices.insert(p_t(183, "Sigma 150mm f/2.8 EX DG OS HSM APO Macro")); + choices.insert(p_t(183, "Sigma 105mm f/2.8 EX DG OS HSM Macro")); + choices.insert(p_t(184, "Canon EF 400mm f/2.8L + x2")); + choices.insert(p_t(185, "Canon EF 600mm f/4L IS")); + choices.insert(p_t(186, "Canon EF 70-200mm f/4L")); + choices.insert(p_t(187, "Canon EF 70-200mm f/4L + 1.4x")); + choices.insert(p_t(188, "Canon EF 70-200mm f/4L + 2x")); + choices.insert(p_t(189, "Canon EF 70-200mm f/4L + 2.8x")); + choices.insert(p_t(190, "Canon EF 100mm f/2.8 Macro")); + choices.insert(p_t(191, "Canon EF 400mm f/4 DO IS")); + choices.insert(p_t(193, "Canon EF 35-80mm f/4-5.6 USM")); + choices.insert(p_t(194, "Canon EF 80-200mm f/4.5-5.6 USM")); + choices.insert(p_t(195, "Canon EF 35-105mm f/4.5-5.6 USM")); + choices.insert(p_t(196, "Canon EF 75-300mm f/4-5.6 USM")); + choices.insert(p_t(197, "Canon EF 75-300mm f/4-5.6 IS USM")); + choices.insert(p_t(198, "Canon EF 50mm f/1.4 USM")); + choices.insert(p_t(199, "Canon EF 28-80mm f/3.5-5.6 USM")); + choices.insert(p_t(200, "Canon EF 75-300mm f/4-5.6 USM")); + choices.insert(p_t(201, "Canon EF 28-80mm f/3.5-5.6 USM")); + choices.insert(p_t(202, "Canon EF 28-80mm f/3.5-5.6 USM IV")); + choices.insert(p_t(208, "Canon EF 22-55mm f/4-5.6 USM")); + choices.insert(p_t(209, "Canon EF 55-200mm f/4.5-5.6")); + choices.insert(p_t(210, "Canon EF 28-90mm f/4-5.6 USM")); + choices.insert(p_t(211, "Canon EF 28-200mm f/3.5-5.6 USM")); + choices.insert(p_t(212, "Canon EF 28-105mm f/4-5.6 USM")); + choices.insert(p_t(213, "Canon EF 90-300mm f/4.5-5.6 USM")); + choices.insert(p_t(214, "Canon EF-S 18-55mm f/3.5-5.6 USM")); + choices.insert(p_t(215, "Canon EF 55-200mm f/4.5-5.6 II USM")); + choices.insert(p_t(224, "Canon EF 70-200mm f/2.8L IS")); + choices.insert(p_t(225, "Canon EF 70-200mm f/2.8L IS + x1.4")); + choices.insert(p_t(226, "Canon EF 70-200mm f/2.8L IS + x2")); + choices.insert(p_t(227, "Canon EF 70-200mm f/2.8L IS + x2.8")); + choices.insert(p_t(228, "Canon EF 28-105mm f/3.5-4.5 USM")); + choices.insert(p_t(229, "Canon EF 16-35mm f/2.8L")); + choices.insert(p_t(230, "Canon EF 24-70mm f/2.8L")); + choices.insert(p_t(231, "Canon EF 17-40mm f/4L")); + choices.insert(p_t(232, "Canon EF 70-300mm f/4.5-5.6 DO IS USM")); + choices.insert(p_t(233, "Canon EF 28-300mm f/3.5-5.6L IS")); + choices.insert(p_t(234, "Canon EF-S 17-85mm f4-5.6 IS USM")); + choices.insert(p_t(235, "Canon EF-S 10-22mm f/3.5-4.5 USM")); + choices.insert(p_t(236, "Canon EF-S 60mm f/2.8 Macro USM")); + choices.insert(p_t(237, "Canon EF 24-105mm f/4L IS")); + choices.insert(p_t(238, "Canon EF 70-300mm f/4-5.6 IS USM")); + choices.insert(p_t(239, "Canon EF 85mm f/1.2L II")); + choices.insert(p_t(240, "Canon EF-S 17-55mm f/2.8 IS USM")); + choices.insert(p_t(241, "Canon EF 50mm f/1.2L")); + choices.insert(p_t(242, "Canon EF 70-200mm f/4L IS")); + choices.insert(p_t(243, "Canon EF 70-200mm f/4L IS + 1.4x")); + choices.insert(p_t(244, "Canon EF 70-200mm f/4L IS + 2x")); + choices.insert(p_t(245, "Canon EF 70-200mm f/4L IS + 2.8x")); + choices.insert(p_t(246, "Canon EF 16-35mm f/2.8L II")); + choices.insert(p_t(247, "Canon EF 14mm f/2.8L II USM")); + choices.insert(p_t(248, "Canon EF 200mm f/2L IS")); + choices.insert(p_t(249, "Canon EF 800mm f/5.6L IS")); + choices.insert(p_t(250, "Canon EF 24mm f/1.4L II")); + choices.insert(p_t(251, "Canon EF 70-200mm f/2.8L IS II USM")); + choices.insert(p_t(252, "Canon EF 70-200mm f/2.8L IS II USM + x1.4")); + choices.insert(p_t(253, "Canon EF 70-200mm f/2.8L IS II USM + x2")); + choices.insert(p_t(254, "Canon EF 100mm f/2.8L Macro IS USM")); + choices.insert(p_t(488, "Canon EF-S 15-85mm f/3.5-5.6 IS USM")); + choices.insert(p_t(489, "Canon EF 70-300mm f/4-5.6L IS USM")); + choices.insert(p_t(490, "Canon EF 8-15mm f/4L USM")); + choices.insert(p_t(491, "Canon EF 300mm f/2.8L IS II USM")); + choices.insert(p_t(492, "Canon EF 400mm f/2.8L IS II USM")); + choices.insert(p_t(493, "Canon EF 24-105mm f/4L IS USM")); + choices.insert(p_t(494, "Canon EF 600mm f/4.0L IS II USM")); + choices.insert(p_t(495, "Canon EF 24-70mm f/2.8L II USM")); + choices.insert(p_t(496, "Canon EF 200-400mm f/4L IS USM")); + choices.insert(p_t(502, "Canon EF 28mm f/2.8 IS USM")); + choices.insert(p_t(503, "Canon EF 24mm f/2.8 IS USM")); + choices.insert(p_t(504, "Canon EF 24-70mm f/4L IS USM")); + choices.insert(p_t(505, "Canon EF 35mm f/2 IS USM")); + choices.insert(p_t(4142, "Canon EF-S 18-135mm f/3.5-5.6 IS STM")); + choices.insert(p_t(4143, "Canon EF-M 18-55mm f/3.5-5.6 IS STM")); + choices.insert(p_t(4144, "Canon EF 40mm f/2.8 STM")); + choices.insert(p_t(4145, "Canon EF-M 22mm f/2 STM")); + choices.insert(p_t(4146, "Canon EF-S 18-55mm f/3.5-5.6 IS STM")); + choices.insert(p_t(4147, "Canon EF-M 11-22mm f/4-5.6 IS STM")); + } + + virtual std::string toString (Tag* t) + { + int lensID = t->toInt(); + + it_t r; + size_t nFound = choices.count( lensID ); + + if(1 == nFound) { + r = choices.find ( lensID ); + return r->second; } - virtual std::string toString (Tag* t) - { - int lensID = t->toInt(); + Tag *apertureTag = t->getParent()->getRoot()->findTag("MaxAperture"); + Tag *focalLengthTag = t->getParent()->getRoot()->findTag("FocalLength"); + Tag *focalLengthMaxTag = t->getParent()->getRoot()->findTag("LongFocal"); + Tag *focalLengthMinTag = t->getParent()->getRoot()->findTag("ShortFocal"); + Tag *unitTag = t->getParent()->getRoot()->findTag("FocalUnits"); + double maxApertureAtFocal = 0.; + double focalLength = 0.; + double focalLengthMin = 0.; + double focalLengthMax = 0.; - it_t r; - size_t nFound = choices.count( lensID ); - if(1 == nFound) { - r = choices.find ( lensID ); - return r->second; - } + if( apertureTag ) { + maxApertureAtFocal = pow(2.0, apertureTag->toDouble() / 64.0); + } - Tag *apertureTag = t->getParent()->getRoot()->findTag("MaxAperture"); - Tag *focalLengthTag = t->getParent()->getRoot()->findTag("FocalLength"); - Tag *focalLengthMaxTag = t->getParent()->getRoot()->findTag("LongFocal"); - Tag *focalLengthMinTag = t->getParent()->getRoot()->findTag("ShortFocal"); - Tag *unitTag = t->getParent()->getRoot()->findTag("FocalUnits"); - double maxApertureAtFocal = 0.; - double focalLength = 0.; - double focalLengthMin = 0.; - double focalLengthMax = 0.; - if( apertureTag ) - maxApertureAtFocal = pow(2.0, apertureTag->toDouble()/64.0); - if( unitTag ){ - double unit = unitTag->toDouble(); - if( unit==0. ) - unit=1; - if( focalLengthTag ) - focalLength = focalLengthTag->toDouble(); - if( focalLengthMinTag ) - focalLengthMin = focalLengthMinTag->toDouble()/unit; - if( focalLengthMaxTag ) - focalLengthMax = focalLengthMaxTag->toDouble()/unit; - } - - std::ostringstream s; - s << "Unknown "; - if (focalLengthMin > 0.) - s << focalLengthMin; - if (focalLengthMax > 0. && focalLengthMax != focalLengthMin) - s << "-" << focalLengthMax; - if (focalLengthMin > 0.) - s << "mm"; - - s << " (" << lensID << ")"; - if (0 == nFound) { - return s.str(); - } - double deltaMin = 1000.; - - std::string bestMatch(s.str()); - std::ostringstream candidates; - for (r = choices.lower_bound(lensID); r != choices.upper_bound(lensID); r++) { - double a1,a2,f1,f2,lensAperture,dif; - - if( !extractLensInfo( r->second ,f1,f2,a1,a2) ) - continue; - if( f1 == 0. || a1 == 0.) - continue; - - if( focalLength < f1 - .5 || focalLength > f2 + 0.5 ) - continue; - if( focalLengthMin>0. && fabs(f1-focalLengthMin) > 0.5 ) - continue; - if( focalLengthMax>0. && fabs(f2-focalLengthMax) > 0.5 ) - continue; - if( maxApertureAtFocal > 0.1){ - if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 +0.15) - continue; - - if( a1 == a2 || f1 == f2) - lensAperture = a1; - else - lensAperture = exp( log(a1)+(log(a2)-log(a1))/(log(f2)-log(f1))*(log(focalLength)-log(f1)) ); - - dif = abs(lensAperture - maxApertureAtFocal); - } else - dif = 0; - - if( dif < deltaMin ){ - deltaMin = dif; - bestMatch = r->second; - } - if( dif < 0.15){ - if( candidates.tellp() ) - candidates << "\n or " << r->second; - else - candidates << r->second; - } + if( unitTag ) { + double unit = unitTag->toDouble(); + if( unit == 0. ) { + unit = 1; + } + + if( focalLengthTag ) { + focalLength = focalLengthTag->toDouble(); + } + + if( focalLengthMinTag ) { + focalLengthMin = focalLengthMinTag->toDouble() / unit; + } + + if( focalLengthMaxTag ) { + focalLengthMax = focalLengthMaxTag->toDouble() / unit; } - if( !candidates.tellp() ) - return bestMatch; - else - return candidates.str(); } + + std::ostringstream s; + s << "Unknown "; + + if (focalLengthMin > 0.) { + s << focalLengthMin; + } + + if (focalLengthMax > 0. && focalLengthMax != focalLengthMin) { + s << "-" << focalLengthMax; + } + + if (focalLengthMin > 0.) { + s << "mm"; + } + + s << " (" << lensID << ")"; + + if (0 == nFound) { + return s.str(); + } + + double deltaMin = 1000.; + + std::string bestMatch(s.str()); + std::ostringstream candidates; + + for (r = choices.lower_bound(lensID); r != choices.upper_bound(lensID); r++) { + double a1, a2, f1, f2, lensAperture, dif; + + if( !extractLensInfo( r->second , f1, f2, a1, a2) ) { + continue; + } + + if( f1 == 0. || a1 == 0.) { + continue; + } + + if( focalLength < f1 - .5 || focalLength > f2 + 0.5 ) { + continue; + } + + if( focalLengthMin > 0. && fabs(f1 - focalLengthMin) > 0.5 ) { + continue; + } + + if( focalLengthMax > 0. && fabs(f2 - focalLengthMax) > 0.5 ) { + continue; + } + + if( maxApertureAtFocal > 0.1) { + if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 + 0.15) { + continue; + } + + if( a1 == a2 || f1 == f2) { + lensAperture = a1; + } else { + lensAperture = exp( log(a1) + (log(a2) - log(a1)) / (log(f2) - log(f1)) * (log(focalLength) - log(f1)) ); + } + + dif = abs(lensAperture - maxApertureAtFocal); + } else { + dif = 0; + } + + if( dif < deltaMin ) { + deltaMin = dif; + bestMatch = r->second; + } + + if( dif < 0.15) { + if( candidates.tellp() ) { + candidates << "\n or " << r->second; + } else { + candidates << r->second; + } + } + + } + + if( !candidates.tellp() ) { + return bestMatch; + } else { + return candidates.str(); + } + } }; CALensInterpreter caLensInterpreter; -class CAFocalTypeInterpreter : public ChoiceInterpreter { +class CAFocalTypeInterpreter : public ChoiceInterpreter +{ public: - CAFocalTypeInterpreter(){ - choices[0] = "undef"; - choices[1] = "Fixed"; - choices[2] = "Zoom"; - } + CAFocalTypeInterpreter() + { + choices[0] = "undef"; + choices[1] = "Fixed"; + choices[2] = "Zoom"; + } }; CAFocalTypeInterpreter caFocalTypeInterpreter; -class CAFocalPlaneInterpreter : public Interpreter { +class CAFocalPlaneInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - int val = t->toInt(); - if( val <40 ) return "undef"; - char buffer[1024]; - sprintf (buffer, "%.2fmm", val *25.4 / 1000); + virtual std::string toString (Tag* t) + { + int val = t->toInt(); + + if( val < 40 ) { + return "undef"; + } + + char buffer[1024]; + sprintf (buffer, "%.2fmm", val * 25.4 / 1000); return buffer; - } + } }; CAFocalPlaneInterpreter caFocalPlaneInterpreter; -class CAExposureTimeInterpreter : public Interpreter { +class CAExposureTimeInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - char buffer[1024]; - double d = pow (2, - t->toInt()/32.0); + virtual std::string toString (Tag* t) + { + char buffer[1024]; + double d = pow (2, - t->toInt() / 32.0); sprintf (buffer, "%.3f", d); return buffer; - } + } }; CAExposureTimeInterpreter caExposureTimeInterpreter; -class CAEVInterpreter : public Interpreter { - virtual std::string toString (Tag* t) { - char buffer[1024]; - sprintf (buffer, "%.1f", t->toDouble()/32.0 ); +class CAEVInterpreter : public Interpreter +{ + virtual std::string toString (Tag* t) + { + char buffer[1024]; + sprintf (buffer, "%.1f", t->toDouble() / 32.0 ); return buffer; - } + } }; CAEVInterpreter caEVInterpreter; -class CABaseISOInterpreter : public Interpreter { +class CABaseISOInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - char buffer[32]; - int a = t->toInt(); - sprintf (buffer, "%d", a); - return buffer; + virtual std::string toString (Tag* t) + { + char buffer[32]; + int a = t->toInt(); + sprintf (buffer, "%d", a); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = Interpreter::toInt(t, ofs); + + if(a > 1) { + double i = pow(2., double(a) / 32. - 4.) * 50.; + return i; + } else { + return 0.; } - virtual double toDouble (Tag* t, int ofs){ - int a = Interpreter::toInt(t, ofs); - if(a>1) { - double i = pow(2., double(a)/32. - 4.) * 50.; - return i; - } - else - return 0.; - } - virtual int toInt (Tag* t, int ofs, TagType astype){ - int a = Interpreter::toInt(t, ofs, astype); - if(a>1) { - int i = int(double(powf(2.f, float(a)/32.f - 4.f)) * 50.f +0.5f); - return i; - } - else - return 0; + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + int a = Interpreter::toInt(t, ofs, astype); + + if(a > 1) { + int i = int(double(powf(2.f, float(a) / 32.f - 4.f)) * 50.f + 0.5f); + return i; + } else { + return 0; } + } }; CABaseISOInterpreter caBaseISOInterpreter; -class CAToneCurveInterpreter : public ChoiceInterpreter { +class CAToneCurveInterpreter : public ChoiceInterpreter +{ public: - CAToneCurveInterpreter(){ + CAToneCurveInterpreter() + { choices[0] = "Standard"; choices[1] = "Manual"; choices[2] = "Custom"; - } + } }; CAToneCurveInterpreter caToneCurveInterpreter; -class CASharpnessFrequencyInterpreter : public ChoiceInterpreter { +class CASharpnessFrequencyInterpreter : public ChoiceInterpreter +{ public: - CASharpnessFrequencyInterpreter(){ + CASharpnessFrequencyInterpreter() + { choices[0] = "N/A"; choices[1] = "Lowest"; choices[2] = "Low"; choices[3] = "Standard"; choices[4] = "High"; choices[5] = "Highest"; - } + } }; CASharpnessFrequencyInterpreter caSharpnessFrequencyInterpreter; -class CAWhiteBalanceInterpreter : public ChoiceInterpreter { +class CAWhiteBalanceInterpreter : public ChoiceInterpreter +{ public: - CAWhiteBalanceInterpreter(){ + CAWhiteBalanceInterpreter() + { choices[0] = "Auto"; choices[1] = "Daylight"; choices[2] = "Cloudy"; @@ -893,13 +1055,15 @@ public: choices[15] = "Custom 1"; choices[16] = "Custom 2"; choices[17] = "Underwater"; - } + } }; CAWhiteBalanceInterpreter caWhiteBalanceInterpreter; -class CAPictureStyleInterpreter : public ChoiceInterpreter { +class CAPictureStyleInterpreter : public ChoiceInterpreter +{ public: - CAPictureStyleInterpreter(){ + CAPictureStyleInterpreter() + { choices[0] = "None"; choices[1] = "Standard "; choices[2] = "Set 1"; @@ -917,36 +1081,46 @@ public: choices[0x84] = "Neutral"; choices[0x85] = "Faithful"; choices[0x86] = "Monochrome"; - } + } }; CAPictureStyleInterpreter caPictureStyleInterpreter; -class CASlowShutterInterpreter : public ChoiceInterpreter { +class CASlowShutterInterpreter : public ChoiceInterpreter +{ public: - CASlowShutterInterpreter(){ + CASlowShutterInterpreter() + { choices[0] = "Off"; choices[1] = "Night Scene"; choices[2] = "On"; choices[3] = "None"; - } + } }; CASlowShutterInterpreter caSlowShutterInterpreter; -class CAFlashGuideNumberInterpreter : public Interpreter{ +class CAFlashGuideNumberInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - int n= t->toInt(); - if( n==-1) return "undef"; - char buffer[32]; - sprintf (buffer, "%.0f", n/32. ); + virtual std::string toString (Tag* t) + { + int n = t->toInt(); + + if( n == -1) { + return "undef"; + } + + char buffer[32]; + sprintf (buffer, "%.0f", n / 32. ); return buffer; - } + } }; CAFlashGuideNumberInterpreter caFlashGuideNumberInterpreter; -class CAAFPointsInFocusInterpreter : public ChoiceInterpreter { +class CAAFPointsInFocusInterpreter : public ChoiceInterpreter +{ public: - CAAFPointsInFocusInterpreter(){ + CAAFPointsInFocusInterpreter() + { choices[0x3000] = "None (MF)"; choices[0x3001] = "Right"; choices[0x3002] = "Center"; @@ -955,102 +1129,120 @@ public: choices[0x3005] = "Left+Right"; choices[0x3006] = "Left+Center"; choices[0x3007] = "All"; - } + } }; CAAFPointsInFocusInterpreter caAFPointsInFocusInterpreter; -class CAAutoExposureBracketingInterpreter : public ChoiceInterpreter { +class CAAutoExposureBracketingInterpreter : public ChoiceInterpreter +{ public: - CAAutoExposureBracketingInterpreter(){ + CAAutoExposureBracketingInterpreter() + { choices[-1] = "On "; choices[0] = "Off "; choices[1] = "On (shot 1)"; choices[2] = "On (shot 2)"; choices[3] = "On (shot 3)"; - } + } }; CAAutoExposureBracketingInterpreter caAutoExposureBracketingInterpreter; -class CAControModeInterpreter : public ChoiceInterpreter { +class CAControModeInterpreter : public ChoiceInterpreter +{ public: - CAControModeInterpreter(){ + CAControModeInterpreter() + { choices[0] = "n/a"; choices[1] = "Camera Local Control"; choices[3] = "Computer Remote Control"; - } + } }; CAControModeInterpreter caControModeInterpreter; -class CAFocusDistanceInterpreter : public Interpreter { +class CAFocusDistanceInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - char buffer[1024]; - sprintf (buffer, "%.2f", t->toDouble()/100 ); + virtual std::string toString (Tag* t) + { + char buffer[1024]; + sprintf (buffer, "%.2f", t->toDouble() / 100 ); return buffer; - } + } }; CAFocusDistanceInterpreter caFocusDistanceInterpreter; -class CAMeasuredEVInterpreter : public Interpreter { +class CAMeasuredEVInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - char buffer[1024]; - sprintf (buffer, "%.1f", t->toDouble()/8 - 6 ); + virtual std::string toString (Tag* t) + { + char buffer[1024]; + sprintf (buffer, "%.1f", t->toDouble() / 8 - 6 ); return buffer; - } + } }; CAMeasuredEVInterpreter caMeasuredEVInterpreter; -class CACameraTypeInterpreter : public ChoiceInterpreter { +class CACameraTypeInterpreter : public ChoiceInterpreter +{ public: - CACameraTypeInterpreter(){ - choices[248] = "EOS High-end"; - choices[250] = "Compact"; - choices[252] = "EOS Mid-end"; - choices[255] = "DV Camera"; - } + CACameraTypeInterpreter() + { + choices[248] = "EOS High-end"; + choices[250] = "Compact"; + choices[252] = "EOS Mid-end"; + choices[255] = "DV Camera"; + } }; CACameraTypeInterpreter caCameraTypeInterpreter; -class CAAutoRotateInterpreter : public ChoiceInterpreter { +class CAAutoRotateInterpreter : public ChoiceInterpreter +{ public: - CAAutoRotateInterpreter(){ + CAAutoRotateInterpreter() + { choices[-1] = "Rotated by Software"; choices[0] = "None"; choices[1] = "Rotate 90 CW"; choices[2] = "Rotate 180"; choices[3] = "Rotate 270 CW"; - } + } }; CAAutoRotateInterpreter caAutoRotateInterpreter; -class CABracketModeInterpreter : public ChoiceInterpreter { +class CABracketModeInterpreter : public ChoiceInterpreter +{ public: - CABracketModeInterpreter(){ + CABracketModeInterpreter() + { choices[0] = "Off"; choices[1] = "AEB"; choices[2] = "FEB"; choices[3] = "ISO"; choices[4] = "WB"; - } + } }; CABracketModeInterpreter caBracketModeInterpreter; -class CARAWJpegQualityInterpreter : public ChoiceInterpreter { +class CARAWJpegQualityInterpreter : public ChoiceInterpreter +{ public: - CARAWJpegQualityInterpreter(){ + CARAWJpegQualityInterpreter() + { choices[1] = "Economy"; choices[2] = "Normal"; choices[3] = "Fine"; choices[4] = "RAW"; choices[5] = "Superfine"; - } + } }; CARAWJpegQualityInterpreter caRAWJpegQualityInterpreter; -class CAJpegSizeInterpreter : public ChoiceInterpreter { +class CAJpegSizeInterpreter : public ChoiceInterpreter +{ public: - CAJpegSizeInterpreter(){ + CAJpegSizeInterpreter() + { choices[0] = "Large"; choices[1] = "Medium"; choices[2] = "Small"; @@ -1059,476 +1251,491 @@ public: choices[7] = "Medium 3"; choices[8] = "Postcard"; choices[9] = "Widescreen"; - } + } }; CAJpegSizeInterpreter caJpegSizeInterpreter; -class CAWBBracketModeInterpreter : public ChoiceInterpreter { +class CAWBBracketModeInterpreter : public ChoiceInterpreter +{ public: - CAWBBracketModeInterpreter(){ - choices[0] = "Off"; - choices[1] = "Shift AB"; - choices[2] = "shift GM"; - } + CAWBBracketModeInterpreter() + { + choices[0] = "Off"; + choices[1] = "Shift AB"; + choices[2] = "shift GM"; + } }; CAWBBracketModeInterpreter caWBBracketModeInterpreter; -class CAFilterEffectInterpreter : public ChoiceInterpreter { +class CAFilterEffectInterpreter : public ChoiceInterpreter +{ public: - CAFilterEffectInterpreter(){ + CAFilterEffectInterpreter() + { choices[0] = "None"; choices[1] = "Yellow"; choices[2] = "Orange"; choices[3] = "Red"; choices[4] = "Green"; - } + } }; CAFilterEffectInterpreter caFilterEffectInterpreter; -class CAToningEffectInterpreter : public ChoiceInterpreter { +class CAToningEffectInterpreter : public ChoiceInterpreter +{ public: - CAToningEffectInterpreter(){ + CAToningEffectInterpreter() + { choices[0] = "None"; choices[1] = "Sepia"; choices[2] = "Blue"; choices[3] = "Purple"; choices[4] = "Green"; - } + } }; CAToningEffectInterpreter caToningEffectInterpreter; -class CAFileNumberInterpreter : public Interpreter { +class CAFileNumberInterpreter : public Interpreter +{ public: - virtual std::string toString (Tag* t) { - unsigned long val = t->toInt(0,LONG); - char buffer[32]; - sprintf (buffer, "%ld", ((val&0xffc0)>>6)*10000+((val>>16)&0xff)+((val&0x3f)<<8) ); + virtual std::string toString (Tag* t) + { + unsigned long val = t->toInt(0, LONG); + char buffer[32]; + sprintf (buffer, "%ld", ((val & 0xffc0) >> 6) * 10000 + ((val >> 16) & 0xff) + ((val & 0x3f) << 8) ); return buffer; - } + } }; CAFileNumberInterpreter caFileNumberInterpreter; -class CAModelIDInterpreter : public ChoiceInterpreter { - public: - CAModelIDInterpreter () { - choices[0x1010000] = "PowerShot A30"; - choices[0x1040000] = "PowerShot S300 / Digital IXUS 300 / IXY Digital 300"; - choices[0x1060000] = "PowerShot A20"; - choices[0x1080000] = "PowerShot A10"; - choices[0x1090000] = "PowerShot S110 / Digital IXUS v / IXY Digital 200"; - choices[0x1100000] = "PowerShot G2"; - choices[0x1110000] = "PowerShot S40"; - choices[0x1120000] = "PowerShot S30"; - choices[0x1130000] = "PowerShot A40"; - choices[0x1140000] = "EOS D30"; - choices[0x1150000] = "PowerShot A100"; - choices[0x1160000] = "PowerShot S200 / Digital IXUS v2 / IXY Digital 200a"; - choices[0x1170000] = "PowerShot A200"; - choices[0x1180000] = "PowerShot S330 / Digital IXUS 330 / IXY Digital 300a"; - choices[0x1190000] = "PowerShot G3"; - choices[0x1210000] = "PowerShot S45"; - choices[0x1230000] = "PowerShot SD100 / Digital IXUS II / IXY Digital 30"; - choices[0x1240000] = "PowerShot S230 / Digital IXUS v3 / IXY Digital 320"; - choices[0x1250000] = "PowerShot A70"; - choices[0x1260000] = "PowerShot A60"; - choices[0x1270000] = "PowerShot S400 / Digital IXUS 400 / IXY Digital 400"; - choices[0x1290000] = "PowerShot G5"; - choices[0x1300000] = "PowerShot A300"; - choices[0x1310000] = "PowerShot S50"; - choices[0x1340000] = "PowerShot A80"; - choices[0x1350000] = "PowerShot SD10 / Digital IXUS i / IXY Digital L"; - choices[0x1360000] = "PowerShot S1 IS"; - choices[0x1370000] = "PowerShot Pro1"; - choices[0x1380000] = "PowerShot S70"; - choices[0x1390000] = "PowerShot S60"; - choices[0x1400000] = "PowerShot G6"; - choices[0x1410000] = "PowerShot S500 / Digital IXUS 500 / IXY Digital 500"; - choices[0x1420000] = "PowerShot A75"; - choices[0x1440000] = "PowerShot SD110 / Digital IXUS IIs / IXY Digital 30a"; - choices[0x1450000] = "PowerShot A400"; - choices[0x1470000] = "PowerShot A310"; - choices[0x1490000] = "PowerShot A85"; - choices[0x1520000] = "PowerShot S410 / Digital IXUS 430 / IXY Digital 450"; - choices[0x1530000] = "PowerShot A95"; - choices[0x1540000] = "PowerShot SD300 / Digital IXUS 40 / IXY Digital 50"; - choices[0x1550000] = "PowerShot SD200 / Digital IXUS 30 / IXY Digital 40"; - choices[0x1560000] = "PowerShot A520"; - choices[0x1570000] = "PowerShot A510"; - choices[0x1590000] = "PowerShot SD20 / Digital IXUS i5 / IXY Digital L2"; - choices[0x1640000] = "PowerShot S2 IS"; - choices[0x1650000] = "PowerShot SD430 / IXUS Wireless / IXY Wireless"; - choices[0x1660000] = "PowerShot SD500 / Digital IXUS 700 / IXY Digital 600"; - choices[0x1668000] = "EOS D60"; - choices[0x1700000] = "PowerShot SD30 / Digital IXUS i zoom / IXY Digital L3"; - choices[0x1740000] = "PowerShot A430"; - choices[0x1750000] = "PowerShot A410"; - choices[0x1760000] = "PowerShot S80"; - choices[0x1780000] = "PowerShot A620"; - choices[0x1790000] = "PowerShot A610"; - choices[0x1800000] = "PowerShot SD630 / Digital IXUS 65 / IXY Digital 80"; - choices[0x1810000] = "PowerShot SD450 / Digital IXUS 55 / IXY Digital 60"; - choices[0x1820000] = "PowerShot TX1"; - choices[0x1870000] = "PowerShot SD400 / Digital IXUS 50 / IXY Digital 55"; - choices[0x1880000] = "PowerShot A420"; - choices[0x1890000] = "PowerShot SD900 / Digital IXUS 900 Ti / IXY Digital 1000"; - choices[0x1900000] = "PowerShot SD550 / Digital IXUS 750 / IXY Digital 700"; - choices[0x1920000] = "PowerShot A700"; - choices[0x1940000] = "PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS"; - choices[0x1950000] = "PowerShot S3 IS"; - choices[0x1960000] = "PowerShot A540"; - choices[0x1970000] = "PowerShot SD600 / Digital IXUS 60 / IXY Digital 70"; - choices[0x1980000] = "PowerShot G7"; - choices[0x1990000] = "PowerShot A530"; - choices[0x2000000] = "PowerShot SD800 IS / Digital IXUS 850 IS / IXY Digital 900 IS"; - choices[0x2010000] = "PowerShot SD40 / Digital IXUS i7 / IXY Digital L4"; - choices[0x2020000] = "PowerShot A710 IS"; - choices[0x2030000] = "PowerShot A640"; - choices[0x2040000] = "PowerShot A630"; - choices[0x2090000] = "PowerShot S5 IS"; - choices[0x2100000] = "PowerShot A460"; - choices[0x2120000] = "PowerShot SD850 IS / Digital IXUS 950 IS / IXY Digital 810 IS"; - choices[0x2130000] = "PowerShot A570 IS"; - choices[0x2140000] = "PowerShot A560"; - choices[0x2150000] = "PowerShot SD750 / Digital IXUS 75 / IXY Digital 90"; - choices[0x2160000] = "PowerShot SD1000 / Digital IXUS 70 / IXY Digital 10"; - choices[0x2180000] = "PowerShot A550"; - choices[0x2190000] = "PowerShot A450"; - choices[0x2230000] = "PowerShot G9"; - choices[0x2240000] = "PowerShot A650 IS"; - choices[0x2260000] = "PowerShot A720 IS"; - choices[0x2290000] = "PowerShot SX100 IS"; - choices[0x2300000] = "PowerShot SD950 IS / Digital IXUS 960 IS / IXY Digital 2000 IS"; - choices[0x2310000] = "PowerShot SD870 IS / Digital IXUS 860 IS / IXY Digital 910 IS"; - choices[0x2320000] = "PowerShot SD890 IS / Digital IXUS 970 IS / IXY Digital 820 IS"; - choices[0x2360000] = "PowerShot SD790 IS / Digital IXUS 90 IS / IXY Digital 95 IS"; - choices[0x2370000] = "PowerShot SD770 IS / Digital IXUS 85 IS / IXY Digital 25 IS"; - choices[0x2380000] = "PowerShot A590 IS"; - choices[0x2390000] = "PowerShot A580"; - choices[0x2420000] = "PowerShot A470"; - choices[0x2430000] = "PowerShot SD1100 IS / Digital IXUS 80 IS / IXY Digital 20 IS"; - choices[0x2460000] = "PowerShot SX1 IS"; - choices[0x2470000] = "PowerShot SX10 IS"; - choices[0x2480000] = "PowerShot A1000 IS"; - choices[0x2490000] = "PowerShot G10"; - choices[0x2510000] = "PowerShot A2000 IS"; - choices[0x2520000] = "PowerShot SX110 IS"; - choices[0x2530000] = "PowerShot SD990 IS / Digital IXUS 980 IS / IXY Digital 3000 IS"; - choices[0x2540000] = "PowerShot SD880 IS / Digital IXUS 870 IS / IXY Digital 920 IS"; - choices[0x2550000] = "PowerShot E1"; - choices[0x2560000] = "PowerShot D10"; - choices[0x2570000] = "PowerShot SD960 IS / Digital IXUS 110 IS / IXY Digital 510 IS"; - choices[0x2580000] = "PowerShot A2100 IS"; - choices[0x2590000] = "PowerShot A480"; - choices[0x2600000] = "PowerShot SX200 IS"; - choices[0x2610000] = "PowerShot SD970 IS / Digital IXUS 990 IS / IXY Digital 830 IS"; - choices[0x2620000] = "PowerShot SD780 IS / Digital IXUS 100 IS / IXY Digital 210 IS"; - choices[0x2630000] = "PowerShot A1100 IS"; - choices[0x2640000] = "PowerShot SD1200 IS / Digital IXUS 95 IS / IXY Digital 110 IS"; - choices[0x2700000] = "PowerShot G11"; - choices[0x2710000] = "PowerShot SX120 IS"; - choices[0x2720000] = "PowerShot S90"; - choices[0x2750000] = "PowerShot SX20 IS"; - choices[0x2760000] = "PowerShot SD980 IS / Digital IXUS 200 IS / IXY Digital 930 IS"; - choices[0x2770000] = "PowerShot SD940 IS / Digital IXUS 120 IS / IXY Digital 220 IS"; - choices[0x2800000] = "PowerShot A495"; - choices[0x2810000] = "PowerShot A490"; - choices[0x2820000] = "PowerShot A3100 IS"; - choices[0x2830000] = "PowerShot A3000 IS"; - choices[0x2840000] = "PowerShot SD1400 IS / IXUS 130 / IXY 400F"; - choices[0x2850000] = "PowerShot SD1300 IS / IXUS 105 / IXY 200F"; - choices[0x2860000] = "PowerShot SD3500 IS / IXUS 210 / IXY 10S"; - choices[0x2870000] = "PowerShot SX210 IS"; - choices[0x2880000] = "PowerShot SD4000 IS / IXUS 300 HS / IXY 30S"; - choices[0x2890000] = "PowerShot SD4500 IS / IXUS 1000 HS / IXY 50S"; - choices[0x2920000] = "PowerShot G12"; - choices[0x2930000] = "PowerShot SX30 IS"; - choices[0x2940000] = "PowerShot SX130 IS"; - choices[0x2950000] = "PowerShot S95"; - choices[0x3010000] = "PowerShot Pro90 IS"; - choices[0x3340000] = "PowerShot SX50 HS"; - choices[0x3360000] = "PowerShot S110"; - choices[0x3540000] = "PowerShot G16"; - choices[0x3550000] = "PowerShot S120"; - choices[0x4040000] = "PowerShot G1"; - choices[0x6040000] = "PowerShot S100 / Digital IXUS / IXY Digital"; - choices[0x4007d673] = "DC19 / DC21 / DC22"; - choices[0x4007d674] = "XH A1"; - choices[0x4007d675] = "HV10"; - choices[0x4007d676] = "MD130 / MD140 / MD150 / MD160"; - choices[0x4007d777] = "iVIS DC50"; - choices[0x4007d778] = "iVIS HV20"; - choices[0x4007d779] = "DC211"; - choices[0x4007d77a] = "HG10"; - choices[0x4007d77b] = "iVIS HR10"; - choices[0x4007d878] = "HV30"; - choices[0x4007d87e] = "DC301 / DC310 / DC311 / DC320 / DC330"; - choices[0x4007d87f] = "FS100"; - choices[0x4007d880] = "iVIS HF10"; - choices[0x4007d882] = "HG20 / HG21 / VIXIA HG21"; - choices[0x4007d925] = "LEGRIA HF21"; - choices[0x4007d978] = "LEGRIA HV40"; - choices[0x4007d987] = "DC410 / DC420"; - choices[0x4007d988] = "LEGRIA FS19 / FS20 / FS21 / FS22 / FS200"; - choices[0x4007d989] = "LEGRIA HF20 / HF200"; - choices[0x4007d98a] = "VIXIA HF S10 / S100"; - choices[0x4007da8e] = "LEGRIA HF R16 / R17 / R106"; - choices[0x4007da90] = "LEGRIA HF S21 / VIXIA HF S200"; - choices[0x4007da92] = "LEGRIA FS36 / FS305 / FS306 / FS307"; - choices[0x80000001] = "EOS-1D"; - choices[0x80000167] = "EOS-1DS"; - choices[0x80000168] = "EOS 10D"; - choices[0x80000169] = "EOS-1D Mark III"; - choices[0x80000170] = "EOS Digital Rebel / 300D / Kiss Digital"; - choices[0x80000174] = "EOS-1D Mark II"; - choices[0x80000175] = "EOS 20D"; - choices[0x80000176] = "EOS Digital Rebel XSi / 450D / Kiss X2"; - choices[0x80000188] = "EOS-1Ds Mark II"; - choices[0x80000189] = "EOS Digital Rebel XT / 350D / Kiss Digital N"; - choices[0x80000190] = "EOS 40D"; - choices[0x80000213] = "EOS 5D"; - choices[0x80000215] = "EOS-1Ds Mark III"; - choices[0x80000218] = "EOS 5D Mark II"; - choices[0x80000232] = "EOS-1D Mark II N"; - choices[0x80000234] = "EOS 30D"; - choices[0x80000236] = "EOS Digital Rebel XTi / 400D / Kiss Digital X"; - choices[0x80000250] = "EOS 7D"; - choices[0x80000252] = "EOS Rebel T1i / 500D / Kiss X3"; - choices[0x80000254] = "EOS Rebel XS / 1000D / Kiss F"; - choices[0x80000261] = "EOS 50D"; - choices[0x80000270] = "EOS Rebel T2i / 550D / Kiss X4"; - choices[0x80000281] = "EOS-1D Mark IV"; - choices[0x80000285] = "EOS 5D Mark III"; - choices[0x80000286] = "EOS 600D"; - choices[0x80000287] = "EOS 60D"; - choices[0x80000325] = "EOS 70D"; - } +class CAModelIDInterpreter : public ChoiceInterpreter +{ +public: + CAModelIDInterpreter () + { + choices[0x1010000] = "PowerShot A30"; + choices[0x1040000] = "PowerShot S300 / Digital IXUS 300 / IXY Digital 300"; + choices[0x1060000] = "PowerShot A20"; + choices[0x1080000] = "PowerShot A10"; + choices[0x1090000] = "PowerShot S110 / Digital IXUS v / IXY Digital 200"; + choices[0x1100000] = "PowerShot G2"; + choices[0x1110000] = "PowerShot S40"; + choices[0x1120000] = "PowerShot S30"; + choices[0x1130000] = "PowerShot A40"; + choices[0x1140000] = "EOS D30"; + choices[0x1150000] = "PowerShot A100"; + choices[0x1160000] = "PowerShot S200 / Digital IXUS v2 / IXY Digital 200a"; + choices[0x1170000] = "PowerShot A200"; + choices[0x1180000] = "PowerShot S330 / Digital IXUS 330 / IXY Digital 300a"; + choices[0x1190000] = "PowerShot G3"; + choices[0x1210000] = "PowerShot S45"; + choices[0x1230000] = "PowerShot SD100 / Digital IXUS II / IXY Digital 30"; + choices[0x1240000] = "PowerShot S230 / Digital IXUS v3 / IXY Digital 320"; + choices[0x1250000] = "PowerShot A70"; + choices[0x1260000] = "PowerShot A60"; + choices[0x1270000] = "PowerShot S400 / Digital IXUS 400 / IXY Digital 400"; + choices[0x1290000] = "PowerShot G5"; + choices[0x1300000] = "PowerShot A300"; + choices[0x1310000] = "PowerShot S50"; + choices[0x1340000] = "PowerShot A80"; + choices[0x1350000] = "PowerShot SD10 / Digital IXUS i / IXY Digital L"; + choices[0x1360000] = "PowerShot S1 IS"; + choices[0x1370000] = "PowerShot Pro1"; + choices[0x1380000] = "PowerShot S70"; + choices[0x1390000] = "PowerShot S60"; + choices[0x1400000] = "PowerShot G6"; + choices[0x1410000] = "PowerShot S500 / Digital IXUS 500 / IXY Digital 500"; + choices[0x1420000] = "PowerShot A75"; + choices[0x1440000] = "PowerShot SD110 / Digital IXUS IIs / IXY Digital 30a"; + choices[0x1450000] = "PowerShot A400"; + choices[0x1470000] = "PowerShot A310"; + choices[0x1490000] = "PowerShot A85"; + choices[0x1520000] = "PowerShot S410 / Digital IXUS 430 / IXY Digital 450"; + choices[0x1530000] = "PowerShot A95"; + choices[0x1540000] = "PowerShot SD300 / Digital IXUS 40 / IXY Digital 50"; + choices[0x1550000] = "PowerShot SD200 / Digital IXUS 30 / IXY Digital 40"; + choices[0x1560000] = "PowerShot A520"; + choices[0x1570000] = "PowerShot A510"; + choices[0x1590000] = "PowerShot SD20 / Digital IXUS i5 / IXY Digital L2"; + choices[0x1640000] = "PowerShot S2 IS"; + choices[0x1650000] = "PowerShot SD430 / IXUS Wireless / IXY Wireless"; + choices[0x1660000] = "PowerShot SD500 / Digital IXUS 700 / IXY Digital 600"; + choices[0x1668000] = "EOS D60"; + choices[0x1700000] = "PowerShot SD30 / Digital IXUS i zoom / IXY Digital L3"; + choices[0x1740000] = "PowerShot A430"; + choices[0x1750000] = "PowerShot A410"; + choices[0x1760000] = "PowerShot S80"; + choices[0x1780000] = "PowerShot A620"; + choices[0x1790000] = "PowerShot A610"; + choices[0x1800000] = "PowerShot SD630 / Digital IXUS 65 / IXY Digital 80"; + choices[0x1810000] = "PowerShot SD450 / Digital IXUS 55 / IXY Digital 60"; + choices[0x1820000] = "PowerShot TX1"; + choices[0x1870000] = "PowerShot SD400 / Digital IXUS 50 / IXY Digital 55"; + choices[0x1880000] = "PowerShot A420"; + choices[0x1890000] = "PowerShot SD900 / Digital IXUS 900 Ti / IXY Digital 1000"; + choices[0x1900000] = "PowerShot SD550 / Digital IXUS 750 / IXY Digital 700"; + choices[0x1920000] = "PowerShot A700"; + choices[0x1940000] = "PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS"; + choices[0x1950000] = "PowerShot S3 IS"; + choices[0x1960000] = "PowerShot A540"; + choices[0x1970000] = "PowerShot SD600 / Digital IXUS 60 / IXY Digital 70"; + choices[0x1980000] = "PowerShot G7"; + choices[0x1990000] = "PowerShot A530"; + choices[0x2000000] = "PowerShot SD800 IS / Digital IXUS 850 IS / IXY Digital 900 IS"; + choices[0x2010000] = "PowerShot SD40 / Digital IXUS i7 / IXY Digital L4"; + choices[0x2020000] = "PowerShot A710 IS"; + choices[0x2030000] = "PowerShot A640"; + choices[0x2040000] = "PowerShot A630"; + choices[0x2090000] = "PowerShot S5 IS"; + choices[0x2100000] = "PowerShot A460"; + choices[0x2120000] = "PowerShot SD850 IS / Digital IXUS 950 IS / IXY Digital 810 IS"; + choices[0x2130000] = "PowerShot A570 IS"; + choices[0x2140000] = "PowerShot A560"; + choices[0x2150000] = "PowerShot SD750 / Digital IXUS 75 / IXY Digital 90"; + choices[0x2160000] = "PowerShot SD1000 / Digital IXUS 70 / IXY Digital 10"; + choices[0x2180000] = "PowerShot A550"; + choices[0x2190000] = "PowerShot A450"; + choices[0x2230000] = "PowerShot G9"; + choices[0x2240000] = "PowerShot A650 IS"; + choices[0x2260000] = "PowerShot A720 IS"; + choices[0x2290000] = "PowerShot SX100 IS"; + choices[0x2300000] = "PowerShot SD950 IS / Digital IXUS 960 IS / IXY Digital 2000 IS"; + choices[0x2310000] = "PowerShot SD870 IS / Digital IXUS 860 IS / IXY Digital 910 IS"; + choices[0x2320000] = "PowerShot SD890 IS / Digital IXUS 970 IS / IXY Digital 820 IS"; + choices[0x2360000] = "PowerShot SD790 IS / Digital IXUS 90 IS / IXY Digital 95 IS"; + choices[0x2370000] = "PowerShot SD770 IS / Digital IXUS 85 IS / IXY Digital 25 IS"; + choices[0x2380000] = "PowerShot A590 IS"; + choices[0x2390000] = "PowerShot A580"; + choices[0x2420000] = "PowerShot A470"; + choices[0x2430000] = "PowerShot SD1100 IS / Digital IXUS 80 IS / IXY Digital 20 IS"; + choices[0x2460000] = "PowerShot SX1 IS"; + choices[0x2470000] = "PowerShot SX10 IS"; + choices[0x2480000] = "PowerShot A1000 IS"; + choices[0x2490000] = "PowerShot G10"; + choices[0x2510000] = "PowerShot A2000 IS"; + choices[0x2520000] = "PowerShot SX110 IS"; + choices[0x2530000] = "PowerShot SD990 IS / Digital IXUS 980 IS / IXY Digital 3000 IS"; + choices[0x2540000] = "PowerShot SD880 IS / Digital IXUS 870 IS / IXY Digital 920 IS"; + choices[0x2550000] = "PowerShot E1"; + choices[0x2560000] = "PowerShot D10"; + choices[0x2570000] = "PowerShot SD960 IS / Digital IXUS 110 IS / IXY Digital 510 IS"; + choices[0x2580000] = "PowerShot A2100 IS"; + choices[0x2590000] = "PowerShot A480"; + choices[0x2600000] = "PowerShot SX200 IS"; + choices[0x2610000] = "PowerShot SD970 IS / Digital IXUS 990 IS / IXY Digital 830 IS"; + choices[0x2620000] = "PowerShot SD780 IS / Digital IXUS 100 IS / IXY Digital 210 IS"; + choices[0x2630000] = "PowerShot A1100 IS"; + choices[0x2640000] = "PowerShot SD1200 IS / Digital IXUS 95 IS / IXY Digital 110 IS"; + choices[0x2700000] = "PowerShot G11"; + choices[0x2710000] = "PowerShot SX120 IS"; + choices[0x2720000] = "PowerShot S90"; + choices[0x2750000] = "PowerShot SX20 IS"; + choices[0x2760000] = "PowerShot SD980 IS / Digital IXUS 200 IS / IXY Digital 930 IS"; + choices[0x2770000] = "PowerShot SD940 IS / Digital IXUS 120 IS / IXY Digital 220 IS"; + choices[0x2800000] = "PowerShot A495"; + choices[0x2810000] = "PowerShot A490"; + choices[0x2820000] = "PowerShot A3100 IS"; + choices[0x2830000] = "PowerShot A3000 IS"; + choices[0x2840000] = "PowerShot SD1400 IS / IXUS 130 / IXY 400F"; + choices[0x2850000] = "PowerShot SD1300 IS / IXUS 105 / IXY 200F"; + choices[0x2860000] = "PowerShot SD3500 IS / IXUS 210 / IXY 10S"; + choices[0x2870000] = "PowerShot SX210 IS"; + choices[0x2880000] = "PowerShot SD4000 IS / IXUS 300 HS / IXY 30S"; + choices[0x2890000] = "PowerShot SD4500 IS / IXUS 1000 HS / IXY 50S"; + choices[0x2920000] = "PowerShot G12"; + choices[0x2930000] = "PowerShot SX30 IS"; + choices[0x2940000] = "PowerShot SX130 IS"; + choices[0x2950000] = "PowerShot S95"; + choices[0x3010000] = "PowerShot Pro90 IS"; + choices[0x3340000] = "PowerShot SX50 HS"; + choices[0x3360000] = "PowerShot S110"; + choices[0x3540000] = "PowerShot G16"; + choices[0x3550000] = "PowerShot S120"; + choices[0x4040000] = "PowerShot G1"; + choices[0x6040000] = "PowerShot S100 / Digital IXUS / IXY Digital"; + choices[0x4007d673] = "DC19 / DC21 / DC22"; + choices[0x4007d674] = "XH A1"; + choices[0x4007d675] = "HV10"; + choices[0x4007d676] = "MD130 / MD140 / MD150 / MD160"; + choices[0x4007d777] = "iVIS DC50"; + choices[0x4007d778] = "iVIS HV20"; + choices[0x4007d779] = "DC211"; + choices[0x4007d77a] = "HG10"; + choices[0x4007d77b] = "iVIS HR10"; + choices[0x4007d878] = "HV30"; + choices[0x4007d87e] = "DC301 / DC310 / DC311 / DC320 / DC330"; + choices[0x4007d87f] = "FS100"; + choices[0x4007d880] = "iVIS HF10"; + choices[0x4007d882] = "HG20 / HG21 / VIXIA HG21"; + choices[0x4007d925] = "LEGRIA HF21"; + choices[0x4007d978] = "LEGRIA HV40"; + choices[0x4007d987] = "DC410 / DC420"; + choices[0x4007d988] = "LEGRIA FS19 / FS20 / FS21 / FS22 / FS200"; + choices[0x4007d989] = "LEGRIA HF20 / HF200"; + choices[0x4007d98a] = "VIXIA HF S10 / S100"; + choices[0x4007da8e] = "LEGRIA HF R16 / R17 / R106"; + choices[0x4007da90] = "LEGRIA HF S21 / VIXIA HF S200"; + choices[0x4007da92] = "LEGRIA FS36 / FS305 / FS306 / FS307"; + choices[0x80000001] = "EOS-1D"; + choices[0x80000167] = "EOS-1DS"; + choices[0x80000168] = "EOS 10D"; + choices[0x80000169] = "EOS-1D Mark III"; + choices[0x80000170] = "EOS Digital Rebel / 300D / Kiss Digital"; + choices[0x80000174] = "EOS-1D Mark II"; + choices[0x80000175] = "EOS 20D"; + choices[0x80000176] = "EOS Digital Rebel XSi / 450D / Kiss X2"; + choices[0x80000188] = "EOS-1Ds Mark II"; + choices[0x80000189] = "EOS Digital Rebel XT / 350D / Kiss Digital N"; + choices[0x80000190] = "EOS 40D"; + choices[0x80000213] = "EOS 5D"; + choices[0x80000215] = "EOS-1Ds Mark III"; + choices[0x80000218] = "EOS 5D Mark II"; + choices[0x80000232] = "EOS-1D Mark II N"; + choices[0x80000234] = "EOS 30D"; + choices[0x80000236] = "EOS Digital Rebel XTi / 400D / Kiss Digital X"; + choices[0x80000250] = "EOS 7D"; + choices[0x80000252] = "EOS Rebel T1i / 500D / Kiss X3"; + choices[0x80000254] = "EOS Rebel XS / 1000D / Kiss F"; + choices[0x80000261] = "EOS 50D"; + choices[0x80000270] = "EOS Rebel T2i / 550D / Kiss X4"; + choices[0x80000281] = "EOS-1D Mark IV"; + choices[0x80000285] = "EOS 5D Mark III"; + choices[0x80000286] = "EOS 600D"; + choices[0x80000287] = "EOS 60D"; + choices[0x80000325] = "EOS 70D"; + } }; CAModelIDInterpreter caModelIDInterpreter; -class CAPanoramaDirectionInterpreter : public ChoiceInterpreter { +class CAPanoramaDirectionInterpreter : public ChoiceInterpreter +{ public: - CAPanoramaDirectionInterpreter(){ - choices[0] = "Left to Right"; - choices[1] = "Right to Left"; - choices[2] = "Bottom to Top"; - choices[3] = "Top to Bottom"; - choices[4] = "2x2 Matrix (Clockwise)"; - } + CAPanoramaDirectionInterpreter() + { + choices[0] = "Left to Right"; + choices[1] = "Right to Left"; + choices[2] = "Bottom to Top"; + choices[3] = "Top to Bottom"; + choices[4] = "2x2 Matrix (Clockwise)"; + } }; CAPanoramaDirectionInterpreter caPanoramaDirectionInterpreter; -class CAAspectRatioInterpreter : public ChoiceInterpreter { +class CAAspectRatioInterpreter : public ChoiceInterpreter +{ public: - CAAspectRatioInterpreter(){ - choices[0] = "3:2"; - choices[1] = "1:1"; - choices[2] = "4:3"; - choices[7] = "16:9"; - } + CAAspectRatioInterpreter() + { + choices[0] = "3:2"; + choices[1] = "1:1"; + choices[2] = "4:3"; + choices[7] = "16:9"; + } }; CAAspectRatioInterpreter caAspectRatioInterpreter; const TagAttrib canonCameraSettingsAttribs[] = { - {0, AC_WRITE, 0, 0, 1, AUTO, "MacroMode", &caMacroModeInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "SelfTimer", &caSelfTimerInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "Quality", &caQualityInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "CanonFlashMode", &caFlashModeInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "ContinuousDrive", &caContinuousDriveInterpreter}, - {0, AC_WRITE, 0, 0, 7, AUTO, "FocusMode", &caFocusModeInterpreter}, - {0, AC_WRITE, 0, 0, 9, AUTO, "RecordMode", &caRecordModeInterpreter}, - {0, AC_WRITE, 0, 0, 10, AUTO, "CanonImageSize", &caImageSizeInterpreter}, - {0, AC_WRITE, 0, 0, 11, AUTO, "EasyMode", &caEasyModeInterpreter}, - {0, AC_WRITE, 0, 0, 12, AUTO, "DigitalZoom", &caDigitalZoomInterpreter}, - {0, AC_WRITE, 0, 0, 13, AUTO, "Contrast", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 14, AUTO, "Saturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 15, AUTO, "Sharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 16, AUTO, "CameraISO", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 17, AUTO, "MeteringMode", &caMeteringModeInterpreter}, - {0, AC_WRITE, 0, 0, 18, AUTO, "FocusRange", &caFocusRangeInterpreter}, - {0, AC_WRITE, 0, 0, 19, AUTO, "AFPoint", &caAFPointInterpreter}, - {0, AC_WRITE, 0, 0, 20, AUTO, "CanonExposureMode", &caExposureModeInterpreter}, - {0, AC_WRITE, 0, 0, 22, AUTO, "LensID", &caLensInterpreter}, - {0, AC_WRITE, 0, 0, 23, AUTO, "LongFocal", &caFocalInterpreter}, - {0, AC_WRITE, 0, 0, 24, AUTO, "ShortFocal", &caFocalInterpreter}, - {0, AC_WRITE, 0, 0, 25, AUTO, "FocalUnits", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 26, AUTO, "MaxAperture", &caApertureInterpreter}, - {0, AC_WRITE, 0, 0, 27, AUTO, "MinAperture", &caApertureInterpreter}, - {0, AC_WRITE, 0, 0, 28, AUTO, "FlashActivity", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 29, AUTO, "FlashBits", &caFlashBitsInterpreter}, - {0, AC_WRITE, 0, 0, 32, AUTO, "FocusContinuous", &caFocusContinuousInterpreter}, - {0, AC_WRITE, 0, 0, 33, AUTO, "AESetting", &caAESettingsInterpreter}, - {0, AC_WRITE, 0, 0, 34, AUTO, "ImageStabilization", &caStabilizationInterpreter}, - {0, AC_WRITE, 0, 0, 35, AUTO, "DisplayAperture", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 36, AUTO, "ZoomSourceWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 37, AUTO, "ZoomTargetWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 39, AUTO, "SpotMeteringMode", &caSpotMeteringInterpreter}, - {0, AC_WRITE, 0, 0, 40, AUTO, "PhotoEffect", &caPhotoEffectInterpreter}, - {0, AC_WRITE, 0, 0, 41, AUTO, "ManualFlashOutput", &caManualFlashInterpreter}, - {0, AC_WRITE, 0, 0, 42, AUTO, "ColorTone", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 46, AUTO, "SRAWQuality", &caRAWQualityInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} + {0, AC_WRITE, 0, 0, 1, AUTO, "MacroMode", &caMacroModeInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "SelfTimer", &caSelfTimerInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "Quality", &caQualityInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "CanonFlashMode", &caFlashModeInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "ContinuousDrive", &caContinuousDriveInterpreter}, + {0, AC_WRITE, 0, 0, 7, AUTO, "FocusMode", &caFocusModeInterpreter}, + {0, AC_WRITE, 0, 0, 9, AUTO, "RecordMode", &caRecordModeInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "CanonImageSize", &caImageSizeInterpreter}, + {0, AC_WRITE, 0, 0, 11, AUTO, "EasyMode", &caEasyModeInterpreter}, + {0, AC_WRITE, 0, 0, 12, AUTO, "DigitalZoom", &caDigitalZoomInterpreter}, + {0, AC_WRITE, 0, 0, 13, AUTO, "Contrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 14, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 15, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 16, AUTO, "CameraISO", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 17, AUTO, "MeteringMode", &caMeteringModeInterpreter}, + {0, AC_WRITE, 0, 0, 18, AUTO, "FocusRange", &caFocusRangeInterpreter}, + {0, AC_WRITE, 0, 0, 19, AUTO, "AFPoint", &caAFPointInterpreter}, + {0, AC_WRITE, 0, 0, 20, AUTO, "CanonExposureMode", &caExposureModeInterpreter}, + {0, AC_WRITE, 0, 0, 22, AUTO, "LensID", &caLensInterpreter}, + {0, AC_WRITE, 0, 0, 23, AUTO, "LongFocal", &caFocalInterpreter}, + {0, AC_WRITE, 0, 0, 24, AUTO, "ShortFocal", &caFocalInterpreter}, + {0, AC_WRITE, 0, 0, 25, AUTO, "FocalUnits", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 26, AUTO, "MaxAperture", &caApertureInterpreter}, + {0, AC_WRITE, 0, 0, 27, AUTO, "MinAperture", &caApertureInterpreter}, + {0, AC_WRITE, 0, 0, 28, AUTO, "FlashActivity", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 29, AUTO, "FlashBits", &caFlashBitsInterpreter}, + {0, AC_WRITE, 0, 0, 32, AUTO, "FocusContinuous", &caFocusContinuousInterpreter}, + {0, AC_WRITE, 0, 0, 33, AUTO, "AESetting", &caAESettingsInterpreter}, + {0, AC_WRITE, 0, 0, 34, AUTO, "ImageStabilization", &caStabilizationInterpreter}, + {0, AC_WRITE, 0, 0, 35, AUTO, "DisplayAperture", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 36, AUTO, "ZoomSourceWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 37, AUTO, "ZoomTargetWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 39, AUTO, "SpotMeteringMode", &caSpotMeteringInterpreter}, + {0, AC_WRITE, 0, 0, 40, AUTO, "PhotoEffect", &caPhotoEffectInterpreter}, + {0, AC_WRITE, 0, 0, 41, AUTO, "ManualFlashOutput", &caManualFlashInterpreter}, + {0, AC_WRITE, 0, 0, 42, AUTO, "ColorTone", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 46, AUTO, "SRAWQuality", &caRAWQualityInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} }; const TagAttrib canonFocalLengthAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "FocalType", &caFocalTypeInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "FocalLength", &caFocalInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "FocalPlaneXSize", &caFocalPlaneInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "FocalPlaneYSize", &caFocalPlaneInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} + {0, AC_WRITE, 0, 0, 0, AUTO, "FocalType", &caFocalTypeInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "FocalLength", &caFocalInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "FocalPlaneXSize", &caFocalPlaneInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "FocalPlaneYSize", &caFocalPlaneInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} }; const TagAttrib canonShotInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 1, AUTO, "AutoISO", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "BaseISO" ,&caBaseISOInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "MeasuredEV", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "TargetAperture", &caApertureInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "TargetExposureTime",&caExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 6, AUTO, "ExposureCompensation",&caEVInterpreter}, - {0, AC_WRITE, 0, 0, 7, AUTO, "WhiteBalance",&caWhiteBalanceInterpreter}, - {0, AC_WRITE, 0, 0, 8, AUTO, "SlowShutter",&caSlowShutterInterpreter}, - {0, AC_WRITE, 0, 0, 9, AUTO, "SequenceNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0,10, AUTO, "OpticalZoomCode", &stdInterpreter}, - {0, AC_WRITE, 0, 0,13, AUTO, "FlashGuideNumber" , &caFlashGuideNumberInterpreter}, - {0, AC_WRITE, 0, 0,14, AUTO, "AFPointsInFocus", &caAFPointsInFocusInterpreter}, - {0, AC_WRITE, 0, 0,15, AUTO, "FlashExposureComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0,16, AUTO, "AutoExposureBracketing",&caAutoExposureBracketingInterpreter}, - {0, AC_WRITE, 0, 0,17, AUTO, "AEBBracketValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0,18, AUTO, "ControlMode", &caControModeInterpreter}, - {0, AC_WRITE, 0, 0,19, AUTO, "FocusDistanceUpper", &caFocusDistanceInterpreter}, - {0, AC_WRITE, 0, 0,20, AUTO, "FocusDistanceLower", &caFocusDistanceInterpreter}, - {0, AC_WRITE, 0, 0,21, AUTO, "FNumber" ,&caApertureInterpreter}, - {0, AC_WRITE, 0, 0,22, AUTO, "ExposureTime",&caExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0,24, AUTO, "BulbDuration", &stdInterpreter}, - {0, AC_WRITE, 0, 0,24, AUTO, "MeasuredEV2", &caMeasuredEVInterpreter}, - {0, AC_WRITE, 0, 0,26, AUTO, "CameraType", &caCameraTypeInterpreter}, - {0, AC_WRITE, 0, 0,27, AUTO, "AutoRotate",&caAutoRotateInterpreter}, - {0, AC_WRITE, 0, 0,28, AUTO, "NDFilter",&caOnOffInterpreter}, - {0, AC_WRITE, 0, 0,29, AUTO, "Self-timer2", &stdInterpreter}, - {0, AC_WRITE, 0, 0,33, AUTO, "FlashOutput", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 1, AUTO, "AutoISO", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "BaseISO" , &caBaseISOInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "MeasuredEV", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "TargetAperture", &caApertureInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "TargetExposureTime", &caExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 6, AUTO, "ExposureCompensation", &caEVInterpreter}, + {0, AC_WRITE, 0, 0, 7, AUTO, "WhiteBalance", &caWhiteBalanceInterpreter}, + {0, AC_WRITE, 0, 0, 8, AUTO, "SlowShutter", &caSlowShutterInterpreter}, + {0, AC_WRITE, 0, 0, 9, AUTO, "SequenceNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "OpticalZoomCode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 13, AUTO, "FlashGuideNumber" , &caFlashGuideNumberInterpreter}, + {0, AC_WRITE, 0, 0, 14, AUTO, "AFPointsInFocus", &caAFPointsInFocusInterpreter}, + {0, AC_WRITE, 0, 0, 15, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 16, AUTO, "AutoExposureBracketing", &caAutoExposureBracketingInterpreter}, + {0, AC_WRITE, 0, 0, 17, AUTO, "AEBBracketValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 18, AUTO, "ControlMode", &caControModeInterpreter}, + {0, AC_WRITE, 0, 0, 19, AUTO, "FocusDistanceUpper", &caFocusDistanceInterpreter}, + {0, AC_WRITE, 0, 0, 20, AUTO, "FocusDistanceLower", &caFocusDistanceInterpreter}, + {0, AC_WRITE, 0, 0, 21, AUTO, "FNumber" , &caApertureInterpreter}, + {0, AC_WRITE, 0, 0, 22, AUTO, "ExposureTime", &caExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 24, AUTO, "BulbDuration", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 24, AUTO, "MeasuredEV2", &caMeasuredEVInterpreter}, + {0, AC_WRITE, 0, 0, 26, AUTO, "CameraType", &caCameraTypeInterpreter}, + {0, AC_WRITE, 0, 0, 27, AUTO, "AutoRotate", &caAutoRotateInterpreter}, + {0, AC_WRITE, 0, 0, 28, AUTO, "NDFilter", &caOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 29, AUTO, "Self-timer2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 33, AUTO, "FlashOutput", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, }; const TagAttrib canonFileInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 1, AUTO, "FileNumber", &caFileNumberInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "BracketMode", &caBracketModeInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "BracketValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "BracketShotNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 6, AUTO, "RawJpgQuality",&caRAWJpegQualityInterpreter}, - {0, AC_WRITE, 0, 0, 7, AUTO, "RawJpgSize",&caJpegSizeInterpreter}, - {0, AC_WRITE, 0, 0, 8, AUTO, "NoiseReduction",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 9, AUTO, "WBBracketMode" ,&caWBBracketModeInterpreter}, - {0, AC_WRITE, 0, 0,12, AUTO, "WBBracketValueAB", &stdInterpreter}, - {0, AC_WRITE, 0, 0,13, AUTO, "WBBracketValueGM", &stdInterpreter}, - {0, AC_WRITE, 0, 0,14, AUTO, "FilterEffect" ,&caFilterEffectInterpreter}, - {0, AC_WRITE, 0, 0,15, AUTO, "ToningEffect" ,&caToningEffectInterpreter}, - {0, AC_WRITE, 0, 0,19, AUTO, "LiveViewShooting" ,&caOnOffInterpreter}, - {0, AC_WRITE, 0, 0,25, AUTO, "FlashExposureLock" ,&caOnOffInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 1, AUTO, "FileNumber", &caFileNumberInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "BracketMode", &caBracketModeInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "BracketValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "BracketShotNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 6, AUTO, "RawJpgQuality", &caRAWJpegQualityInterpreter}, + {0, AC_WRITE, 0, 0, 7, AUTO, "RawJpgSize", &caJpegSizeInterpreter}, + {0, AC_WRITE, 0, 0, 8, AUTO, "NoiseReduction", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 9, AUTO, "WBBracketMode" , &caWBBracketModeInterpreter}, + {0, AC_WRITE, 0, 0, 12, AUTO, "WBBracketValueAB", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 13, AUTO, "WBBracketValueGM", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 14, AUTO, "FilterEffect" , &caFilterEffectInterpreter}, + {0, AC_WRITE, 0, 0, 15, AUTO, "ToningEffect" , &caToningEffectInterpreter}, + {0, AC_WRITE, 0, 0, 19, AUTO, "LiveViewShooting" , &caOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 25, AUTO, "FlashExposureLock" , &caOnOffInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, }; const TagAttrib canonProcessingInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 1, AUTO, "ToneCurve", &caToneCurveInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "Sharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "SharpnessFrequency", &caSharpnessFrequencyInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "SensorRedLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "SensorBlueLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 6, AUTO, "WhiteBalanceRed", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 7, AUTO, "WhiteBalanceBlue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 8, AUTO, "WhiteBalance", &caWhiteBalanceInterpreter}, - {0, AC_WRITE, 0, 0, 9, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0,10, AUTO, "PictureStyle", &caPictureStyleInterpreter}, - {0, AC_WRITE, 0, 0,11, AUTO, "DigitalGain", &stdInterpreter}, - {0, AC_WRITE, 0, 0,12, AUTO, "WBShiftAB", &stdInterpreter}, - {0, AC_WRITE, 0, 0,13, AUTO, "WBShiftGM", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ToneCurve", &caToneCurveInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "SharpnessFrequency", &caSharpnessFrequencyInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "SensorRedLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "SensorBlueLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 6, AUTO, "WhiteBalanceRed", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 7, AUTO, "WhiteBalanceBlue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 8, AUTO, "WhiteBalance", &caWhiteBalanceInterpreter}, + {0, AC_WRITE, 0, 0, 9, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "PictureStyle", &caPictureStyleInterpreter}, + {0, AC_WRITE, 0, 0, 11, AUTO, "DigitalGain", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 12, AUTO, "WBShiftAB", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 13, AUTO, "WBShiftGM", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, }; const TagAttrib canonPanoramaInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 2, AUTO, "PanoramaFrameNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "PanoramaDirection", &caPanoramaDirectionInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 2, AUTO, "PanoramaFrameNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "PanoramaDirection", &caPanoramaDirectionInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, }; const TagAttrib canonCropInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "CropLeftMargin", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "CropRightMargin", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "CropTopMargin", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "CropBottomMargin", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 0, AUTO, "CropLeftMargin", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "CropRightMargin", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "CropTopMargin", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "CropBottomMargin", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, }; const TagAttrib canonAspectInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "AspectRatio", &caAspectRatioInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "CroppedImageWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "CroppedImageHeight", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 0, AUTO, "AspectRatio", &caAspectRatioInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "CroppedImageWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "CroppedImageHeight", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}, }; const TagAttrib canonMicroAdjustAttrib[] = { - {0, AC_WRITE, 0, 0, 1, AUTO, "AFMicroAdjActive", &caOnOffInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 2, AUTO, "", NULL}, + {0, AC_WRITE, 0, 0, 1, AUTO, "AFMicroAdjActive", &caOnOffInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 2, AUTO, "", NULL}, }; const TagAttrib canonAttribs[] = { - {0, AC_WRITE, 0, canonCameraSettingsAttribs, 0x0001, AUTO, "CanonCameraSettings", &stdInterpreter}, - {0, AC_WRITE, 0, canonFocalLengthAttribs, 0x0002, AUTO, "CanonFocalLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0003, AUTO, "CanonFlashInfo", &stdInterpreter}, - {0, AC_WRITE, 0, canonShotInfoAttribs, 0x0004, AUTO, "CanonShotInfo", &stdInterpreter}, - {0, AC_WRITE, 0, canonPanoramaInfoAttribs, 0x0005, AUTO, "CanonPanorama", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0006, AUTO, "CanonImageType", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0007, AUTO, "CanonFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0008, AUTO, "FileNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0009, AUTO, "OwnerName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000a, AUTO, "ColorInfoD30", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000c, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000d, AUTO, "CanonCameraInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000e, AUTO, "CanonFileLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000f, AUTO, "CustomFunctions", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0010, AUTO, "CanonModelID", &caModelIDInterpreter}, - {0, AC_WRITE, 0, 0, 0x0012, AUTO, "CanonAFInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0015, AUTO, "SerialNumberFormat", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001c, AUTO, "DateStampMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001d, AUTO, "MyColors", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001e, AUTO, "FirmwareRevision", &stdInterpreter}, - {0, AC_NEW, 0, 0, 0x0024, AUTO, "FaceDetect1", &stdInterpreter}, - {0, AC_NEW, 0, 0, 0x0025, AUTO, "FaceDetect2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0026, AUTO, "CanonAFInfo2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0083, AUTO, "OriginalDecisionData", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0090, AUTO, "CustomFunctions1D", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0091, AUTO, "PersonalFunctions", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0092, AUTO, "PersonalFunctionValues", &stdInterpreter}, - {0, AC_WRITE, 0, canonFileInfoAttribs, 0x0093, AUTO, "CanonFileInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0094, AUTO, "AFPointsInFocus1D", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0095, AUTO, "LensType", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0096, AUTO, "InternalSerialNumber", &caIntSerNumInterpreter}, - {0, AC_WRITE, 0, 0, 0x0097, AUTO, "DustRemovalData", &stdInterpreter}, - {0, AC_WRITE, 0, canonCropInfoAttribs, 0x0098, AUTO, "CropInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0099, AUTO, "CustomFunctions2", &stdInterpreter}, - {0, AC_WRITE, 0, canonAspectInfoAttribs, 0x009a, AUTO, "AspectInfo", &stdInterpreter}, - {0, AC_WRITE, 0, canonProcessingInfoAttribs, 0x00a0, AUTO, "ProcessingInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a1, AUTO, "ToneCurveTable", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a2, AUTO, "SharpnessTable", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a3, AUTO, "SharpnessFreqTable", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a4, AUTO, "WhiteBalanceTable", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a9, AUTO, "ColorBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00aa, AUTO, "MeasuredColor", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00ae, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_NEW , 0, 0, 0x00b0, AUTO, "CanonFlags", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00b1, AUTO, "ModifiedInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00b2, AUTO, "ToneCurveMatching", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00b3, AUTO, "WhiteBalanceMatching", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00b4, AUTO, "ColorSpace", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x00b6, AUTO, "PreviewImageInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00d0, AUTO, "VRDOffset", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00e0, AUTO, "SensorInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x4001, AUTO, "ColorBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x4002, AUTO, "UnknownBlock1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x4003, AUTO, "ColorInfo", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x4005, AUTO, "UnknownBlock2", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x4008, AUTO, "BlackLevel", &stdInterpreter}, - {1, AC_WRITE, 0, canonMicroAdjustAttrib, 0x4013, AUTO, "AFMicroAdj", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, canonCameraSettingsAttribs, 0x0001, AUTO, "CanonCameraSettings", &stdInterpreter}, + {0, AC_WRITE, 0, canonFocalLengthAttribs, 0x0002, AUTO, "CanonFocalLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0003, AUTO, "CanonFlashInfo", &stdInterpreter}, + {0, AC_WRITE, 0, canonShotInfoAttribs, 0x0004, AUTO, "CanonShotInfo", &stdInterpreter}, + {0, AC_WRITE, 0, canonPanoramaInfoAttribs, 0x0005, AUTO, "CanonPanorama", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0006, AUTO, "CanonImageType", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0007, AUTO, "CanonFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0008, AUTO, "FileNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0009, AUTO, "OwnerName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000a, AUTO, "ColorInfoD30", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000c, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000d, AUTO, "CanonCameraInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000e, AUTO, "CanonFileLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000f, AUTO, "CustomFunctions", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0010, AUTO, "CanonModelID", &caModelIDInterpreter}, + {0, AC_WRITE, 0, 0, 0x0012, AUTO, "CanonAFInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0015, AUTO, "SerialNumberFormat", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001c, AUTO, "DateStampMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001d, AUTO, "MyColors", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001e, AUTO, "FirmwareRevision", &stdInterpreter}, + {0, AC_NEW, 0, 0, 0x0024, AUTO, "FaceDetect1", &stdInterpreter}, + {0, AC_NEW, 0, 0, 0x0025, AUTO, "FaceDetect2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0026, AUTO, "CanonAFInfo2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0083, AUTO, "OriginalDecisionData", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0090, AUTO, "CustomFunctions1D", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0091, AUTO, "PersonalFunctions", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0092, AUTO, "PersonalFunctionValues", &stdInterpreter}, + {0, AC_WRITE, 0, canonFileInfoAttribs, 0x0093, AUTO, "CanonFileInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0094, AUTO, "AFPointsInFocus1D", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0095, AUTO, "LensType", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0096, AUTO, "InternalSerialNumber", &caIntSerNumInterpreter}, + {0, AC_WRITE, 0, 0, 0x0097, AUTO, "DustRemovalData", &stdInterpreter}, + {0, AC_WRITE, 0, canonCropInfoAttribs, 0x0098, AUTO, "CropInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0099, AUTO, "CustomFunctions2", &stdInterpreter}, + {0, AC_WRITE, 0, canonAspectInfoAttribs, 0x009a, AUTO, "AspectInfo", &stdInterpreter}, + {0, AC_WRITE, 0, canonProcessingInfoAttribs, 0x00a0, AUTO, "ProcessingInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a1, AUTO, "ToneCurveTable", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a2, AUTO, "SharpnessTable", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a3, AUTO, "SharpnessFreqTable", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a4, AUTO, "WhiteBalanceTable", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a9, AUTO, "ColorBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00aa, AUTO, "MeasuredColor", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00ae, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_NEW , 0, 0, 0x00b0, AUTO, "CanonFlags", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00b1, AUTO, "ModifiedInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00b2, AUTO, "ToneCurveMatching", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00b3, AUTO, "WhiteBalanceMatching", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00b4, AUTO, "ColorSpace", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x00b6, AUTO, "PreviewImageInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00d0, AUTO, "VRDOffset", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00e0, AUTO, "SensorInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x4001, AUTO, "ColorBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x4002, AUTO, "UnknownBlock1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x4003, AUTO, "ColorInfo", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x4005, AUTO, "UnknownBlock2", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x4008, AUTO, "BlackLevel", &stdInterpreter}, + {1, AC_WRITE, 0, canonMicroAdjustAttrib, 0x4013, AUTO, "AFMicroAdj", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; } #endif diff --git a/rtexif/fujiattribs.cc b/rtexif/fujiattribs.cc index 717c5018e..456559175 100644 --- a/rtexif/fujiattribs.cc +++ b/rtexif/fujiattribs.cc @@ -7,7 +7,7 @@ * 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 @@ -21,240 +21,270 @@ #include "rtexif.h" -namespace rtexif { +namespace rtexif +{ -class FAOnOffInterpreter : public ChoiceInterpreter { - public: - FAOnOffInterpreter () { - choices[0] = "Off"; - choices[1] = "On"; - } +class FAOnOffInterpreter : public ChoiceInterpreter +{ +public: + FAOnOffInterpreter () + { + choices[0] = "Off"; + choices[1] = "On"; + } }; FAOnOffInterpreter faOnOffInterpreter; -class FASharpnessInterpreter : public ChoiceInterpreter { - public: - FASharpnessInterpreter () { - choices[1] = "Soft"; - choices[2] = "Soft2"; - choices[3] = "Normal"; - choices[4] = "Hard"; - choices[5] = "Hard2"; - choices[0x82] = "Medium Soft"; - choices[0x84] = "Medium Hard"; - choices[0x8000] = "Film Simulation"; - choices[0xffff] = "n/a"; - } +class FASharpnessInterpreter : public ChoiceInterpreter +{ +public: + FASharpnessInterpreter () + { + choices[1] = "Soft"; + choices[2] = "Soft2"; + choices[3] = "Normal"; + choices[4] = "Hard"; + choices[5] = "Hard2"; + choices[0x82] = "Medium Soft"; + choices[0x84] = "Medium Hard"; + choices[0x8000] = "Film Simulation"; + choices[0xffff] = "n/a"; + } }; FASharpnessInterpreter faSharpnessInterpreter; -class FAWhiteBalanceInterpreter : public ChoiceInterpreter { - public: - FAWhiteBalanceInterpreter () { - choices[0] = "Auto"; - choices[0x100] = "Daylight"; - choices[0x200] = "Cloudy"; - choices[0x300] = "Daylight Fluorescent"; - choices[0x301] = "Day White Fluorescent"; - choices[0x302] = "White Fluorescent"; - choices[0x303] = "Warm White Fluorescent"; - choices[0x304] = "Living Room Warm White Fluorescent"; - choices[0x400] = "Incandescent"; - choices[0x500] = "Flash"; - choices[0xf00] = "Custom"; - choices[0xf01] = "Custom2"; - choices[0xf02] = "Custom3"; - choices[0xf03] = "Custom4"; - choices[0xf04] = "Custom5"; - choices[0xff0] = "Kelvin"; - } +class FAWhiteBalanceInterpreter : public ChoiceInterpreter +{ +public: + FAWhiteBalanceInterpreter () + { + choices[0] = "Auto"; + choices[0x100] = "Daylight"; + choices[0x200] = "Cloudy"; + choices[0x300] = "Daylight Fluorescent"; + choices[0x301] = "Day White Fluorescent"; + choices[0x302] = "White Fluorescent"; + choices[0x303] = "Warm White Fluorescent"; + choices[0x304] = "Living Room Warm White Fluorescent"; + choices[0x400] = "Incandescent"; + choices[0x500] = "Flash"; + choices[0xf00] = "Custom"; + choices[0xf01] = "Custom2"; + choices[0xf02] = "Custom3"; + choices[0xf03] = "Custom4"; + choices[0xf04] = "Custom5"; + choices[0xff0] = "Kelvin"; + } }; FAWhiteBalanceInterpreter faWhiteBalanceInterpreter; -class FASaturationInterpreter : public ChoiceInterpreter { - public: - FASaturationInterpreter () { - choices[0] = "Normal"; - choices[0x80] = "Medium High"; - choices[0x100] = "High"; - choices[0x180] = "Medium Low"; - choices[0x200] = "Low"; - choices[0x300] = "None (B&W)"; - choices[0x8000] = "Film Simulation"; - } +class FASaturationInterpreter : public ChoiceInterpreter +{ +public: + FASaturationInterpreter () + { + choices[0] = "Normal"; + choices[0x80] = "Medium High"; + choices[0x100] = "High"; + choices[0x180] = "Medium Low"; + choices[0x200] = "Low"; + choices[0x300] = "None (B&W)"; + choices[0x8000] = "Film Simulation"; + } }; FASaturationInterpreter faSaturationInterpreter; -class FAContrastInterpreter : public ChoiceInterpreter { - public: - FAContrastInterpreter () { - choices[0] = "Normal"; - choices[0x80] = "Medium High"; - choices[0x100] = "High"; - choices[0x180] = "Medium Low"; - choices[0x200] = "Low"; - choices[0x8000] = "Film Simulation"; - } +class FAContrastInterpreter : public ChoiceInterpreter +{ +public: + FAContrastInterpreter () + { + choices[0] = "Normal"; + choices[0x80] = "Medium High"; + choices[0x100] = "High"; + choices[0x180] = "Medium Low"; + choices[0x200] = "Low"; + choices[0x8000] = "Film Simulation"; + } }; FAContrastInterpreter faContrastInterpreter; -class FAContrast2Interpreter : public ChoiceInterpreter { - public: - FAContrast2Interpreter () { - choices[0] = "Normal"; - choices[0x100] = "High"; - choices[0x300] = "Low"; - } +class FAContrast2Interpreter : public ChoiceInterpreter +{ +public: + FAContrast2Interpreter () + { + choices[0] = "Normal"; + choices[0x100] = "High"; + choices[0x300] = "Low"; + } }; FAContrast2Interpreter faContrast2Interpreter; -class FANoiseReductionInterpreter : public ChoiceInterpreter { - public: - FANoiseReductionInterpreter () { - choices[0x40] = "Low"; - choices[0x80] = "Normal"; - } +class FANoiseReductionInterpreter : public ChoiceInterpreter +{ +public: + FANoiseReductionInterpreter () + { + choices[0x40] = "Low"; + choices[0x80] = "Normal"; + } }; FANoiseReductionInterpreter faNoiseReductionInterpreter; -class FAFlashInterpreter : public ChoiceInterpreter { - public: - FAFlashInterpreter () { - choices[0] = "Auto"; - choices[1] = "On"; - choices[2] = "Off"; - choices[3] = "Red-eye reduction"; - choices[4] = "External"; - } +class FAFlashInterpreter : public ChoiceInterpreter +{ +public: + FAFlashInterpreter () + { + choices[0] = "Auto"; + choices[1] = "On"; + choices[2] = "Off"; + choices[3] = "Red-eye reduction"; + choices[4] = "External"; + } }; FAFlashInterpreter faFlashInterpreter; -class FAFocusModeInterpreter : public ChoiceInterpreter { - public: - FAFocusModeInterpreter () { - choices[0] = "Auto"; - choices[1] = "Manual"; - } +class FAFocusModeInterpreter : public ChoiceInterpreter +{ +public: + FAFocusModeInterpreter () + { + choices[0] = "Auto"; + choices[1] = "Manual"; + } }; FAFocusModeInterpreter faFocusModeInterpreter; -class FAColorModeInterpreter : public ChoiceInterpreter { - public: - FAColorModeInterpreter () { - choices[0] = "Standard"; - choices[0x10] = "Chrome"; - choices[0x30] = "B & W"; - } +class FAColorModeInterpreter : public ChoiceInterpreter +{ +public: + FAColorModeInterpreter () + { + choices[0] = "Standard"; + choices[0x10] = "Chrome"; + choices[0x30] = "B & W"; + } }; FAColorModeInterpreter faColorModeInterpreter; -class FADynamicRangeInterpreter : public ChoiceInterpreter { - public: - FADynamicRangeInterpreter () { - choices[1] = "Standard"; - choices[3] = "Wide"; - } +class FADynamicRangeInterpreter : public ChoiceInterpreter +{ +public: + FADynamicRangeInterpreter () + { + choices[1] = "Standard"; + choices[3] = "Wide"; + } }; FADynamicRangeInterpreter faDynamicRangeInterpreter; -class FAFilmModeInterpreter : public ChoiceInterpreter { - public: - FAFilmModeInterpreter () { - choices[0] = "F0/Standard"; - choices[0x100] = "F1/Studio Portrait"; - choices[0x110] = "F1a/Studio Portrait Enhanced Saturation"; - choices[0x120] = "F1b/Studio Portrait Smooth Skin Tone"; - choices[0x130] = "F1c/Studio Portrait Increased Sharpness "; - choices[0x200] = "F2/Fujichrome"; - choices[0x300] = "F3/Studio Portrait Ex"; - choices[0x400] = "F4/Velvia"; - } +class FAFilmModeInterpreter : public ChoiceInterpreter +{ +public: + FAFilmModeInterpreter () + { + choices[0] = "F0/Standard"; + choices[0x100] = "F1/Studio Portrait"; + choices[0x110] = "F1a/Studio Portrait Enhanced Saturation"; + choices[0x120] = "F1b/Studio Portrait Smooth Skin Tone"; + choices[0x130] = "F1c/Studio Portrait Increased Sharpness "; + choices[0x200] = "F2/Fujichrome"; + choices[0x300] = "F3/Studio Portrait Ex"; + choices[0x400] = "F4/Velvia"; + } }; FAFilmModeInterpreter faFilmModeInterpreter; -class FADRSettingInterpreter : public ChoiceInterpreter { - public: - FADRSettingInterpreter () { - choices[0] = "Auto (100-400%)"; - choices[0x1] = "RAW"; - choices[0x100] = "Standard (100%)"; - choices[0x200] = "Wide1 (230%)"; - choices[0x201] = "Wide2 (400%)"; - choices[0x8000] = "Film Simulation"; - } +class FADRSettingInterpreter : public ChoiceInterpreter +{ +public: + FADRSettingInterpreter () + { + choices[0] = "Auto (100-400%)"; + choices[0x1] = "RAW"; + choices[0x100] = "Standard (100%)"; + choices[0x200] = "Wide1 (230%)"; + choices[0x201] = "Wide2 (400%)"; + choices[0x8000] = "Film Simulation"; + } }; FADRSettingInterpreter faDRSettingInterpreter; -class FAPictureModeInterpreter : public ChoiceInterpreter { - public: - FAPictureModeInterpreter () { - choices[0] = "Auto"; - choices[1] = "Portrait"; - choices[2] = "Landscape"; - choices[3] = "Macro"; - choices[4] = "Sports"; - choices[5] = "Night Scene"; - choices[6] = "Program AE"; - choices[7] = "Natural Light"; - choices[8] = "Anti-blur"; - choices[9] = "Beach & Snow"; - choices[10] = "Sunset"; - choices[11] = "Museum"; - choices[12] = "Party"; - choices[13] = "Flower"; - choices[14] = "Text"; - choices[15] = "Natural Light & Flash"; - choices[16] = "Beach"; - choices[17] = "Fireworks"; - choices[18] = "Underwater"; - choices[0x100] = "Aperture-priority AE"; - choices[0x200] = "Shutter speed priority AE"; - choices[0x300] = "Manual"; - } +class FAPictureModeInterpreter : public ChoiceInterpreter +{ +public: + FAPictureModeInterpreter () + { + choices[0] = "Auto"; + choices[1] = "Portrait"; + choices[2] = "Landscape"; + choices[3] = "Macro"; + choices[4] = "Sports"; + choices[5] = "Night Scene"; + choices[6] = "Program AE"; + choices[7] = "Natural Light"; + choices[8] = "Anti-blur"; + choices[9] = "Beach & Snow"; + choices[10] = "Sunset"; + choices[11] = "Museum"; + choices[12] = "Party"; + choices[13] = "Flower"; + choices[14] = "Text"; + choices[15] = "Natural Light & Flash"; + choices[16] = "Beach"; + choices[17] = "Fireworks"; + choices[18] = "Underwater"; + choices[0x100] = "Aperture-priority AE"; + choices[0x200] = "Shutter speed priority AE"; + choices[0x300] = "Manual"; + } }; FAPictureModeInterpreter faPictureModeInterpreter; const TagAttrib fujiAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "Version", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0010, AUTO, "InternalSerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1000, AUTO, "Quality", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1001, AUTO, "Sharpness", &faSharpnessInterpreter}, - {0, AC_WRITE, 0, 0, 0x1002, AUTO, "WhiteBalance", &faWhiteBalanceInterpreter}, - {0, AC_WRITE, 0, 0, 0x1003, AUTO, "Saturation", &faSaturationInterpreter}, - {0, AC_WRITE, 0, 0, 0x1004, AUTO, "Contrast", &faContrastInterpreter}, - {0, AC_WRITE, 0, 0, 0x1005, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1006, AUTO, "Contrast2", &faContrast2Interpreter}, - {0, AC_WRITE, 0, 0, 0x100a, AUTO, "WhiteBalanceFineTune", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100b, AUTO, "NoiseReduction", &faNoiseReductionInterpreter}, - {0, AC_WRITE, 0, 0, 0x1010, AUTO, "FujiFlashMode", &faFlashInterpreter}, - {0, AC_WRITE, 0, 0, 0x1011, AUTO, "FlashExposureComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1020, AUTO, "Macro", &faOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1021, AUTO, "FocusMode", &faFocusModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x1023, AUTO, "FocusPixel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1030, AUTO, "SlowSync", &faOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1031, AUTO, "PictureMode", &faPictureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x1100, AUTO, "AutoBracketing", &faOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1101, AUTO, "SequenceNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1210, AUTO, "ColorMode", &faColorModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x1300, AUTO, "BlurWarning", &faOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1301, AUTO, "FocusWarning", &faOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1302, AUTO, "ExposureWarning", &faOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1400, AUTO, "DynamicRange", &faDynamicRangeInterpreter}, - {0, AC_WRITE, 0, 0, 0x1401, AUTO, "FilmMode", &faFilmModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x1402, AUTO, "DynamicRangeSetting", &faDRSettingInterpreter}, - {0, AC_WRITE, 0, 0, 0x1403, AUTO, "DevelopmentDynamicRange", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1404, AUTO, "MinFocalLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1405, AUTO, "MaxFocalLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1406, AUTO, "MaxApertureAtMinFocal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1407, AUTO, "MaxApertureAtMaxFocal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x140b, AUTO, "AutoDynamicRange", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x4100, AUTO, "FacesDetected", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x8000, AUTO, "FileSource", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x8002, AUTO, "OrderNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x8003, AUTO, "FrameNumber", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "Version", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0010, AUTO, "InternalSerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1000, AUTO, "Quality", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1001, AUTO, "Sharpness", &faSharpnessInterpreter}, + {0, AC_WRITE, 0, 0, 0x1002, AUTO, "WhiteBalance", &faWhiteBalanceInterpreter}, + {0, AC_WRITE, 0, 0, 0x1003, AUTO, "Saturation", &faSaturationInterpreter}, + {0, AC_WRITE, 0, 0, 0x1004, AUTO, "Contrast", &faContrastInterpreter}, + {0, AC_WRITE, 0, 0, 0x1005, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1006, AUTO, "Contrast2", &faContrast2Interpreter}, + {0, AC_WRITE, 0, 0, 0x100a, AUTO, "WhiteBalanceFineTune", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100b, AUTO, "NoiseReduction", &faNoiseReductionInterpreter}, + {0, AC_WRITE, 0, 0, 0x1010, AUTO, "FujiFlashMode", &faFlashInterpreter}, + {0, AC_WRITE, 0, 0, 0x1011, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1020, AUTO, "Macro", &faOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1021, AUTO, "FocusMode", &faFocusModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x1023, AUTO, "FocusPixel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1030, AUTO, "SlowSync", &faOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1031, AUTO, "PictureMode", &faPictureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x1100, AUTO, "AutoBracketing", &faOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1101, AUTO, "SequenceNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1210, AUTO, "ColorMode", &faColorModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x1300, AUTO, "BlurWarning", &faOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1301, AUTO, "FocusWarning", &faOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1302, AUTO, "ExposureWarning", &faOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1400, AUTO, "DynamicRange", &faDynamicRangeInterpreter}, + {0, AC_WRITE, 0, 0, 0x1401, AUTO, "FilmMode", &faFilmModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x1402, AUTO, "DynamicRangeSetting", &faDRSettingInterpreter}, + {0, AC_WRITE, 0, 0, 0x1403, AUTO, "DevelopmentDynamicRange", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1404, AUTO, "MinFocalLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1405, AUTO, "MaxFocalLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1406, AUTO, "MaxApertureAtMinFocal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1407, AUTO, "MaxApertureAtMaxFocal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x140b, AUTO, "AutoDynamicRange", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x4100, AUTO, "FacesDetected", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x8000, AUTO, "FileSource", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x8002, AUTO, "OrderNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x8003, AUTO, "FrameNumber", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; } #endif diff --git a/rtexif/kodakattribs.cc b/rtexif/kodakattribs.cc index d05f8c4bb..678dae114 100644 --- a/rtexif/kodakattribs.cc +++ b/rtexif/kodakattribs.cc @@ -7,130 +7,160 @@ #include #include "rtexif.h" -namespace rtexif { +namespace rtexif +{ void parseKodakIfdTextualInfo(Tag *textualInfo, Tag* exif_) { - // parse TextualInfo and copy values into corresponding standard Exif - if (textualInfo->getType() != ASCII) { - return; - } - TagDirectory *exif = exif_->getDirectory(); - char *value = (char *)textualInfo->getValue(); - int valuesize = textualInfo->getValueSize(); + // parse TextualInfo and copy values into corresponding standard Exif + if (textualInfo->getType() != ASCII) { + return; + } - char *p = value; - char *pc, *plf; - while ((pc = strchr(p, ':')) != NULL && (plf = strchr(pc, '\n')) != NULL) { - while (*p == ' ') p++; - size_t len = pc - p; - while (len > 1 && p[len-1] == ' ') len--; - std::string key = std::string(p, len); - ++pc; while (*pc == ' ') pc++; - len = plf - pc; - while (len > 1 && pc[len-1] == ' ') len--; - std::string val = std::string(pc, len); - p = ++plf; + TagDirectory *exif = exif_->getDirectory(); + char *value = (char *)textualInfo->getValue(); + int valuesize = textualInfo->getValueSize(); - // we pick out a few select tags here - Tag *t; - if (key == "Lens") { - // Proback645 may have "Lens" but not "Focal Length" - float flen = atof(val.c_str()); - if (flen != 0.0) { - t = new Tag(exif, lookupAttrib(exifAttribs,"FocalLength")); - t->initRational(flen*32, 32); - exif->replaceTag(t); - } - } else if (key == "Focal Length") { - float flen = atof(val.c_str()); - if (flen != 0.0) { - t = new Tag(exif, lookupAttrib(exifAttribs,"FocalLength")); - t->initRational(flen*32, 32); - exif->replaceTag(t); - } - } else if (key == "Aperture") { - float aperture = atof(&val.c_str()[1]); - if (aperture != 0.0) { - t = new Tag(exif, lookupAttrib(exifAttribs,"FNumber")); - t->initRational((int)(aperture*10), 10); - exif->replaceTag(t); - } - } else if (key == "Exposure Bias" || key == "Compensation") { - float bias = 0.0; - if (val != "Off") { - bias = atof(val.c_str()); - } - t = new Tag (exif, lookupAttrib(exifAttribs,"ExposureBiasValue")); - t->initRational ((int)(bias*1000), 1000); - exif->replaceTag(t); - } else if (key == "ISO Speed") { - t = new Tag (exif, lookupAttrib(exifAttribs,"ISOSpeedRatings")); - t->initInt(atoi(val.c_str()), SHORT); - exif->replaceTag(t); - } else if (key == "Shutter") { - const char *p1 = strchr(val.c_str(), '/'); - int a, b; - if (p1 == NULL) { - a = atoi(val.c_str()); - b = 1; - } else { - a = atoi(val.c_str()); - b = atoi(&p1[1]); - } - t = new Tag (exif, lookupAttrib(exifAttribs,"ExposureTime")); - t->initRational(a, b); - exif->replaceTag(t); + char *p = value; + char *pc, *plf; - float ssv = -log2((float)a/(float)b); // convert to APEX value - t = new Tag (exif, lookupAttrib(exifAttribs,"ShutterSpeedValue")); - t->initRational(1000000 * ssv, 1000000); - exif->replaceTag(t); - } else if (key == "Flash Fired") { - t = new Tag (exif, lookupAttrib(exifAttribs,"Flash")); - if (val == "No") { - t->initInt(0, SHORT); - } else { - // not sure if "Flash Fired" is only yes/no, only seen "No" in test pictures - t->initInt(1, SHORT); - } - exif->replaceTag(t); - } else if (key == "White balance") { // yes should be small 'b' int 'balance'. - t = new Tag (exif, lookupAttrib(exifAttribs,"Flash")); - t->initInt((val == "Auto") ? 0 : 1, SHORT); - exif->replaceTag(t); - } - } + while ((pc = strchr(p, ':')) != NULL && (plf = strchr(pc, '\n')) != NULL) { + while (*p == ' ') { + p++; + } + + size_t len = pc - p; + + while (len > 1 && p[len - 1] == ' ') { + len--; + } + + std::string key = std::string(p, len); + ++pc; + + while (*pc == ' ') { + pc++; + } + + len = plf - pc; + + while (len > 1 && pc[len - 1] == ' ') { + len--; + } + + std::string val = std::string(pc, len); + p = ++plf; + + // we pick out a few select tags here + Tag *t; + + if (key == "Lens") { + // Proback645 may have "Lens" but not "Focal Length" + float flen = atof(val.c_str()); + + if (flen != 0.0) { + t = new Tag(exif, lookupAttrib(exifAttribs, "FocalLength")); + t->initRational(flen * 32, 32); + exif->replaceTag(t); + } + } else if (key == "Focal Length") { + float flen = atof(val.c_str()); + + if (flen != 0.0) { + t = new Tag(exif, lookupAttrib(exifAttribs, "FocalLength")); + t->initRational(flen * 32, 32); + exif->replaceTag(t); + } + } else if (key == "Aperture") { + float aperture = atof(&val.c_str()[1]); + + if (aperture != 0.0) { + t = new Tag(exif, lookupAttrib(exifAttribs, "FNumber")); + t->initRational((int)(aperture * 10), 10); + exif->replaceTag(t); + } + } else if (key == "Exposure Bias" || key == "Compensation") { + float bias = 0.0; + + if (val != "Off") { + bias = atof(val.c_str()); + } + + t = new Tag (exif, lookupAttrib(exifAttribs, "ExposureBiasValue")); + t->initRational ((int)(bias * 1000), 1000); + exif->replaceTag(t); + } else if (key == "ISO Speed") { + t = new Tag (exif, lookupAttrib(exifAttribs, "ISOSpeedRatings")); + t->initInt(atoi(val.c_str()), SHORT); + exif->replaceTag(t); + } else if (key == "Shutter") { + const char *p1 = strchr(val.c_str(), '/'); + int a, b; + + if (p1 == NULL) { + a = atoi(val.c_str()); + b = 1; + } else { + a = atoi(val.c_str()); + b = atoi(&p1[1]); + } + + t = new Tag (exif, lookupAttrib(exifAttribs, "ExposureTime")); + t->initRational(a, b); + exif->replaceTag(t); + + float ssv = -log2((float)a / (float)b); // convert to APEX value + t = new Tag (exif, lookupAttrib(exifAttribs, "ShutterSpeedValue")); + t->initRational(1000000 * ssv, 1000000); + exif->replaceTag(t); + } else if (key == "Flash Fired") { + t = new Tag (exif, lookupAttrib(exifAttribs, "Flash")); + + if (val == "No") { + t->initInt(0, SHORT); + } else { + // not sure if "Flash Fired" is only yes/no, only seen "No" in test pictures + t->initInt(1, SHORT); + } + + exif->replaceTag(t); + } else if (key == "White balance") { // yes should be small 'b' int 'balance'. + t = new Tag (exif, lookupAttrib(exifAttribs, "Flash")); + t->initInt((val == "Auto") ? 0 : 1, SHORT); + exif->replaceTag(t); + } + } } // table not complete, not all proprietary Kodak tags are known const TagAttrib kodakIfdAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0001, AUTO, "UnknownEV?", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0003, AUTO, "ExposureValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03e9, AUTO, "OriginalFileName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03eb, AUTO, "SensorLeftBorder", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03ec, AUTO, "SensorTopBorder", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03ed, AUTO, "SensorImageWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03ee, AUTO, "SensorImageHeight", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03f1, AUTO, "TextualInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03fc, AUTO, "WhiteBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03fd, AUTO, "Processing", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0401, AUTO, "Time", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0414, AUTO, "NCDFileInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0846, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0852, AUTO, "WB_RGBMul0", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0853, AUTO, "WB_RGBMul1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0854, AUTO, "WB_RGBMul2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0855, AUTO, "WB_RGBMul3", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x085c, AUTO, "WB_RGBCoeffs0", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x085d, AUTO, "WB_RGBCoeffs1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x085e, AUTO, "WB_RGBCoeffs2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x085f, AUTO, "WB_RGBCoeffs3", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0ce5, AUTO, "FirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1391, AUTO, "ToneCurveFileName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1784, AUTO, "ISO", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL }}; + {0, AC_WRITE, 0, 0, 0x0001, AUTO, "UnknownEV?", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0003, AUTO, "ExposureValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03e9, AUTO, "OriginalFileName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03eb, AUTO, "SensorLeftBorder", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03ec, AUTO, "SensorTopBorder", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03ed, AUTO, "SensorImageWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03ee, AUTO, "SensorImageHeight", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03f1, AUTO, "TextualInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03fc, AUTO, "WhiteBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03fd, AUTO, "Processing", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0401, AUTO, "Time", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0414, AUTO, "NCDFileInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0846, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0852, AUTO, "WB_RGBMul0", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0853, AUTO, "WB_RGBMul1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0854, AUTO, "WB_RGBMul2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0855, AUTO, "WB_RGBMul3", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x085c, AUTO, "WB_RGBCoeffs0", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x085d, AUTO, "WB_RGBCoeffs1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x085e, AUTO, "WB_RGBCoeffs2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x085f, AUTO, "WB_RGBCoeffs3", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0ce5, AUTO, "FirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1391, AUTO, "ToneCurveFileName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1784, AUTO, "ISO", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL } +}; } #endif diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc index 1c92587b4..dbf7796b7 100644 --- a/rtexif/nikonattribs.cc +++ b/rtexif/nikonattribs.cc @@ -28,907 +28,1090 @@ using namespace std; -namespace rtexif { +namespace rtexif +{ -class NAISOInterpreter : public Interpreter { - public: - NAISOInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - sprintf (buffer, "%d", t->toInt(2)); - return buffer; - } +class NAISOInterpreter : public Interpreter +{ +public: + NAISOInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + sprintf (buffer, "%d", t->toInt(2)); + return buffer; + } }; NAISOInterpreter naISOInterpreter; -class NAISOInfoISOInterpreter : public Interpreter { - public: - NAISOInfoISOInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - int a = t->toInt(); - sprintf (buffer, "%d", a); - return buffer; +class NAISOInfoISOInterpreter : public Interpreter +{ +public: + NAISOInfoISOInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + int a = t->toInt(); + sprintf (buffer, "%d", a); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->getValue()[ofs]; + + if(a > 1) { + double i = pow(2., double(a) / 12. - 5.) * 100.; + return i; + } else { + return 0.; } - virtual double toDouble (Tag* t, int ofs){ - int a = t->getValue()[ofs]; - if(a>1) { - double i = pow(2., double(a)/12. - 5.) * 100.; - return i; - } - else - return 0.; - } - virtual int toInt (Tag* t, int ofs, TagType astype){ - int a = t->getValue()[ofs]; - if(a>1) { - int i = int(double(powf(2.f, float(a)/12.f - 5.f)) * 100.f +0.5f); - return i; - } - else - return 0; + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + int a = t->getValue()[ofs]; + + if(a > 1) { + int i = int(double(powf(2.f, float(a) / 12.f - 5.f)) * 100.f + 0.5f); + return i; + } else { + return 0; } + } }; NAISOInfoISOInterpreter naISOInfoISOInterpreter; -class NAISOExpansionInterpreter : public Interpreter { - public: - NAISOExpansionInterpreter () {} - virtual std::string toString (Tag* t) { - int a = t->toInt(); - // unclear if this interpretation is correct! - switch (a) { - case 0x0: return "Off"; - case 0x101: return "Hi 0.3"; - case 0x102: return "Hi 0.5"; - case 0x103: return "Hi 0.7"; - case 0x104: return "Hi 1.0"; - case 0x105: return "Hi 1.3"; - case 0x106: return "Hi 1.5"; - case 0x107: return "Hi 1.7"; - case 0x108: return "Hi 2.0"; - case 0x201: return "Lo 0.3"; - case 0x202: return "Lo 0.5"; - case 0x203: return "Lo 0.7"; - case 0x204: return "Lo 1.0"; - default: { char buffer[32]; sprintf(buffer, "0x%04X", a); return buffer; } - } +class NAISOExpansionInterpreter : public Interpreter +{ +public: + NAISOExpansionInterpreter () {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(); + + // unclear if this interpretation is correct! + switch (a) { + case 0x0: + return "Off"; + + case 0x101: + return "Hi 0.3"; + + case 0x102: + return "Hi 0.5"; + + case 0x103: + return "Hi 0.7"; + + case 0x104: + return "Hi 1.0"; + + case 0x105: + return "Hi 1.3"; + + case 0x106: + return "Hi 1.5"; + + case 0x107: + return "Hi 1.7"; + + case 0x108: + return "Hi 2.0"; + + case 0x201: + return "Lo 0.3"; + + case 0x202: + return "Lo 0.5"; + + case 0x203: + return "Lo 0.7"; + + case 0x204: + return "Lo 1.0"; + + default: { + char buffer[32]; + sprintf(buffer, "0x%04X", a); + return buffer; } + } + } }; NAISOExpansionInterpreter naISOExpansionInterpreter; -class NALensTypeInterpreter : public Interpreter { - public: - NALensTypeInterpreter () {} - virtual std::string toString (Tag* t) { - int a = t->toInt(); - std::ostringstream str; - str << "MF = " << (a&1 ? "Yes" : "No") << std::endl; - str << "D = " << (a&2 ? "Yes" : "No") << std::endl; - str << "G = " << (a&4 ? "Yes" : "No") << std::endl; - str << "VR = " << (a&8 ? "Yes" : "No"); - return str.str(); - } +class NALensTypeInterpreter : public Interpreter +{ +public: + NALensTypeInterpreter () {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(); + std::ostringstream str; + str << "MF = " << (a & 1 ? "Yes" : "No") << std::endl; + str << "D = " << (a & 2 ? "Yes" : "No") << std::endl; + str << "G = " << (a & 4 ? "Yes" : "No") << std::endl; + str << "VR = " << (a & 8 ? "Yes" : "No"); + return str.str(); + } }; NALensTypeInterpreter naLensTypeInterpreter; -class NAFlashModeInterpreter : public ChoiceInterpreter { - public: - NAFlashModeInterpreter () { - choices[0] = "Did Not Fire"; - choices[1] = "Fired, Manual"; - choices[7] = "Fired, External"; - choices[8] = "Fired, Commander Mode"; - choices[9] = "Fired, TTL Mode"; - } +class NAFlashModeInterpreter : public ChoiceInterpreter +{ +public: + NAFlashModeInterpreter () + { + choices[0] = "Did Not Fire"; + choices[1] = "Fired, Manual"; + choices[7] = "Fired, External"; + choices[8] = "Fired, Commander Mode"; + choices[9] = "Fired, TTL Mode"; + } }; NAFlashModeInterpreter naFlashModeInterpreter; -class NAHiISONRInterpreter : public ChoiceInterpreter { - public: - NAHiISONRInterpreter () { - choices[0] = "Off"; - choices[1] = "Minimal"; - choices[2] = "Low"; - choices[4] = "Normal"; - choices[6] = "High"; - } +class NAHiISONRInterpreter : public ChoiceInterpreter +{ +public: + NAHiISONRInterpreter () + { + choices[0] = "Off"; + choices[1] = "Minimal"; + choices[2] = "Low"; + choices[4] = "Normal"; + choices[6] = "High"; + } }; NAHiISONRInterpreter naHiISONRInterpreter; -class NAShootingModeInterpreter : public Interpreter { - public: - NAShootingModeInterpreter () {} - virtual std::string toString (Tag* t) { - int a = t->toInt(); - std::ostringstream str; - str << "Continuous = " << (a&1 ? "Yes" : "No") << std::endl; - str << "Delay = " << (a&2 ? "Yes" : "No") << std::endl; - str << "PC Control = " << (a&4 ? "Yes" : "No") << std::endl; - str << "White-Balance Bracketing = " << (a&8 ? "Yes" : "No") << std::endl; - str << "Exposure Bracketing = " << (a&16 ? "Yes" : "No") << std::endl; - str << "Auto ISO = " << (a&32 ? "Yes" : "No") << std::endl; - str << "IR Control = " << (a&64 ? "Yes" : "No"); - return str.str(); - } +class NAShootingModeInterpreter : public Interpreter +{ +public: + NAShootingModeInterpreter () {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(); + std::ostringstream str; + str << "Continuous = " << (a & 1 ? "Yes" : "No") << std::endl; + str << "Delay = " << (a & 2 ? "Yes" : "No") << std::endl; + str << "PC Control = " << (a & 4 ? "Yes" : "No") << std::endl; + str << "White-Balance Bracketing = " << (a & 8 ? "Yes" : "No") << std::endl; + str << "Exposure Bracketing = " << (a & 16 ? "Yes" : "No") << std::endl; + str << "Auto ISO = " << (a & 32 ? "Yes" : "No") << std::endl; + str << "IR Control = " << (a & 64 ? "Yes" : "No"); + return str.str(); + } }; NAShootingModeInterpreter naShootingModeInterpreter; -class NAAFInfoInterpreter : public Interpreter { - std::map amchoices; - std::map afpchoices; - public: - NAAFInfoInterpreter () { - amchoices[0] = "Single Area"; - amchoices[1] = "Dynamic Area"; - amchoices[2] = "Dynamic Area, Closest Subject"; - amchoices[3] = "Group Dynamic"; - amchoices[4] = "Single Area (wide)"; - amchoices[5] = "Dynamic Area (wide)"; - afpchoices[0] = "Center"; - afpchoices[1] = "Top"; - afpchoices[2] = "Bottom"; - afpchoices[3] = "Left"; - afpchoices[4] = "Right"; - afpchoices[5] = "Upper-left"; - afpchoices[6] = "Upper-right"; - afpchoices[7] = "Lower-left"; - afpchoices[8] = "Lower-right"; - afpchoices[9] = "Far Left"; - afpchoices[10] = "Far Right"; - } - virtual std::string toString (Tag* t) { - int am = t->toInt (0, BYTE); - int afp = t->toInt (1, BYTE); - int aff = t->toInt (2, SHORT); - std::ostringstream str; - str << "AFAreaMode = " << amchoices[am] << std::endl; - str << "AFAreaMode = " << afpchoices[afp] << std::endl; +class NAAFInfoInterpreter : public Interpreter +{ + std::map amchoices; + std::map afpchoices; +public: + NAAFInfoInterpreter () + { + amchoices[0] = "Single Area"; + amchoices[1] = "Dynamic Area"; + amchoices[2] = "Dynamic Area, Closest Subject"; + amchoices[3] = "Group Dynamic"; + amchoices[4] = "Single Area (wide)"; + amchoices[5] = "Dynamic Area (wide)"; + afpchoices[0] = "Center"; + afpchoices[1] = "Top"; + afpchoices[2] = "Bottom"; + afpchoices[3] = "Left"; + afpchoices[4] = "Right"; + afpchoices[5] = "Upper-left"; + afpchoices[6] = "Upper-right"; + afpchoices[7] = "Lower-left"; + afpchoices[8] = "Lower-right"; + afpchoices[9] = "Far Left"; + afpchoices[10] = "Far Right"; + } + virtual std::string toString (Tag* t) + { + int am = t->toInt (0, BYTE); + int afp = t->toInt (1, BYTE); + int aff = t->toInt (2, SHORT); + std::ostringstream str; + str << "AFAreaMode = " << amchoices[am] << std::endl; + str << "AFAreaMode = " << afpchoices[afp] << std::endl; - std::ostringstream af; - if (aff&1) - if (af.str()=="") af << "Center"; - else af << ", Center"; - else if (aff&2) - if (af.str()=="") af << "Top"; - else af << ", Top"; - else if (aff&4) - if (af.str()=="") af << "Bottom"; - else af << ", Bottom"; - else if (aff&8) - if (af.str()=="") af << "Left"; - else af << ", Left"; - else if (aff&16) - if (af.str()=="") af << "Right"; - else af << ", Right"; - else if (aff&32) - if (af.str()=="") af << "Upper-left"; - else af << ", Upper-left"; - else if (aff&64) - if (af.str()=="") af << "Upper-right"; - else af << ", Upper-right"; - else if (aff&128) - if (af.str()=="") af << " Lower-left"; - else af << ", Lower-left"; - else if (aff&256) - if (af.str()=="") af << "Lower-right"; - else af << ", Lower-right"; - else if (aff&512) - if (af.str()=="") af << "Far Left"; - else af << ", Far Left"; - else if (aff&1024) { - if (af.str()=="") af << "Far Right"; - else af << ", Far Right"; + std::ostringstream af; + + if (aff & 1) + if (af.str() == "") { + af << "Center"; + } else { + af << ", Center"; + } + else if (aff & 2) + if (af.str() == "") { + af << "Top"; + } else { + af << ", Top"; + } + else if (aff & 4) + if (af.str() == "") { + af << "Bottom"; + } else { + af << ", Bottom"; + } + else if (aff & 8) + if (af.str() == "") { + af << "Left"; + } else { + af << ", Left"; + } + else if (aff & 16) + if (af.str() == "") { + af << "Right"; + } else { + af << ", Right"; + } + else if (aff & 32) + if (af.str() == "") { + af << "Upper-left"; + } else { + af << ", Upper-left"; + } + else if (aff & 64) + if (af.str() == "") { + af << "Upper-right"; + } else { + af << ", Upper-right"; + } + else if (aff & 128) + if (af.str() == "") { + af << " Lower-left"; + } else { + af << ", Lower-left"; + } + else if (aff & 256) + if (af.str() == "") { + af << "Lower-right"; + } else { + af << ", Lower-right"; + } + else if (aff & 512) + if (af.str() == "") { + af << "Far Left"; + } else { + af << ", Far Left"; + } + else if (aff & 1024) { + if (af.str() == "") { + af << "Far Right"; + } else { + af << ", Far Right"; } - - str << "AFPointsInFocus = " << af.str(); - return str.str(); } + + str << "AFPointsInFocus = " << af.str(); + return str.str(); + } }; NAAFInfoInterpreter naAFInfoInterpreter; -class NALensDataInterpreter : public Interpreter { - std::map lenses; - public: - NALensDataInterpreter () { // From EXIFTOOL database 'Nikon.pm' V2.80 -/* The key is a composite string made of 8 HEX bytes - * LensIDNumber LensFStops MinFocalLength MaxFocalLength MaxApertureAtMinFocal MaxApertureAtMaxFocal MCUVersion and LensType */ - lenses["00 00 00 00 00 00 00 01"] = "Manual Lens No CPU"; - lenses["00 00 00 00 00 00 E1 12"] = "TC-17E II"; - lenses["00 00 00 00 00 00 F1 0C"] = "TC-14E [II] or Sigma APO Tele Converter 1.4x EX DG or Kenko Teleplus PRO 300 DG 1.4x"; - lenses["00 00 00 00 00 00 F2 18"] = "TC-20E [II] or Sigma APO Tele Converter 2x EX DG or Kenko Teleplus PRO 300 DG 2.0x"; - lenses["00 00 48 48 53 53 00 01"] = "Loreo 40mm f/11-22 3D Lens in a Cap 9005"; - lenses["00 36 1C 2D 34 3C 00 06"] = "Tamron SP AF 11-18mm f/4.5-5.6 Di II LD Aspherical (IF)"; - lenses["00 3C 1F 37 30 30 00 06"] = "Tokina AT-X 124 PRO DX AF 12-24mm f/4"; - lenses["00 3E 80 A0 38 3F 00 02"] = "Tamron SP AF 200-500mm f/5-6.3 Di LD (IF)"; - lenses["00 3F 2D 80 2B 40 00 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF)"; - lenses["00 3F 2D 80 2C 40 00 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro"; - lenses["00 3F 80 A0 38 3F 00 02"] = "Tamron SP AF 200-500mm f/5-6.3 Di"; - lenses["00 40 11 11 2C 2C 00 00"] = "Samyang 8mm f/3.5 Fish-Eye"; - lenses["00 40 18 2B 2C 34 00 06"] = "Tokina AT-X 107 DX Fish-Eye AF 10-17mm f/3.5-4.5"; - lenses["00 40 2A 72 2C 3C 00 06"] = "Tokina AT-X 16.5-135 DX AF 16.5-135mm f/3.5-5.6"; - lenses["00 40 2B 2B 2C 2C 00 02"] = "Tokina AT-X 17 PRO AF 17mm f/3.5"; - lenses["00 40 2D 2D 2C 2C 00 00"] = "Carl Zeiss Distagon T* 18mm f/3.5 ZF.2"; - lenses["00 40 2D 80 2C 40 00 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)"; - lenses["00 40 2D 88 2C 40 00 06"] = "Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18NII)"; - lenses["00 40 2D 88 2C 40 62 06"] = "Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18)"; - lenses["00 40 31 31 2C 2C 00 00"] = "Voigtlander Color Skopar 20mm f/3.5 SLII Aspherical"; - lenses["00 40 37 80 2C 3C 00 02"] = "Tokina AT-X 242 AF 24-200mm f/3.5-5.6"; - lenses["00 40 64 64 2C 2C 00 00"] = "Voigtlander APO-Lanthar 90mm f/3.5 SLII Close Focus"; - lenses["00 44 60 98 34 3C 00 02"] = "Tokina AT-X 840D 80-400mm f/4.5-5.6"; - lenses["00 47 10 10 24 24 00 00"] = "Fisheye Nikkor 8mm f/2.8 AiS"; - lenses["00 47 25 25 24 24 00 02"] = "Tamron SP AF 14mm f/2.8 Aspherical (IF) (69E)"; - lenses["00 47 44 44 24 24 00 06"] = "Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro)"; - lenses["00 47 53 80 30 3C 00 06"] = "Tamron AF 55-200mm f/4-5.6 Di II LD"; - lenses["00 48 1C 29 24 24 00 06"] = "Tokina AT-X 116 PRO DX AF 11-16mm f/2.8"; - lenses["00 48 29 3C 24 24 00 06"] = "Tokina AT-X 16-28 PRO FX AF 16-28mm f/2.8"; - lenses["00 48 29 50 24 24 00 06"] = "Tokina AT-X 165 PRO DX AF 16-50mm f/2.8"; - lenses["00 48 32 32 24 24 00 00"] = "Carl Zeiss Distagon T* 21mm f/2.8 ZF.2"; - lenses["00 48 3C 60 24 24 00 02"] = "Tokina AT-X 280 PRO AF 28-80mm f/2.8 Aspherical"; - lenses["00 48 3C 6A 24 24 00 02"] = "Tamron SP AF 28-105mm f/2.8"; - lenses["00 48 50 50 18 18 00 00"] = "Nikkor H 50mm f/2"; - lenses["00 48 50 72 24 24 00 06"] = "Tokina AT-X 535 PRO DX AF 50-135mm f/2.8"; - lenses["00 48 5C 8E 30 3C 00 06"] = "Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17)"; - lenses["00 48 68 68 24 24 00 00"] = "Series E 100mm f/2.8"; - lenses["00 48 80 80 30 30 00 00"] = "Nikkor 200mm f/4 AiS"; - lenses["00 49 30 48 22 2B 00 02"] = "Tamron SP AF 20-40mm f/2.7-3.5"; - lenses["00 4C 6A 6A 20 20 00 00"] = "Nikkor 105mm f/2.5 AiS"; - lenses["00 4C 7C 7C 2C 2C 00 02"] = "Tamron SP AF 180mm f/3.5 Di Model (B01)"; - lenses["00 53 2B 50 24 24 00 06"] = "Tamron SP AF 17-50mm f/2.8 (A16)"; - lenses["00 54 2B 50 24 24 00 06"] = "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)"; - lenses["00 54 3C 3C 18 18 00 00"] = "Carl Zeiss Distagon T* 28mm f/2 ZF.2"; - lenses["00 54 44 44 0C 0C 00 00"] = "Nikkor 35mm f/1.4 AiS"; - lenses["00 54 44 44 18 18 00 00"] = "Carl Zeiss Distagon T* 35mm f/2 ZF.2"; - lenses["00 54 48 48 18 18 00 00"] = "Voigtlander Ultron 40mm f/2 SLII Aspherical"; - lenses["00 54 50 50 0C 0C 00 00"] = "Carl Zeiss Planar T* 50mm f/1.4 ZF.2"; - lenses["00 54 50 50 18 18 00 00"] = "Carl Zeiss Makro-Planar T* 50mm f/2 ZF.2"; - lenses["00 54 55 55 0C 0C 00 00"] = "Voigtlander Nokton 58mm f/1.4 SLII"; - lenses["00 54 56 56 30 30 00 00"] = "Coastal Optical Systems 60mm f/4 UV-VIS-IR Macro Apo"; - lenses["00 54 62 62 0C 0C 00 00"] = "Carl Zeiss Planar T* 85mm f/1.4 ZF.2"; - lenses["00 54 68 68 18 18 00 00"] = "Carl Zeiss Makro-Planar T* 100mm f/2 ZF.2"; - lenses["00 54 68 68 24 24 00 02"] = "Tokina AT-X M100 PRO D 100mm f/2.8 Macro"; - lenses["00 54 8E 8E 24 24 00 02"] = "Tokina AT-X 300 PRO AF 300mm f/2.8"; - lenses["00 58 64 64 20 20 00 00"] = "Soligor C/D Macro MC 90mm f/2.5"; - lenses["01 00 00 00 00 00 02 00"] = "AF Teleconverter TC-16A 1.6x"; - lenses["01 00 00 00 00 00 08 00"] = "AF Teleconverter TC-16A 1.6x"; - lenses["01 58 50 50 14 14 02 00"] = "AF Nikkor 50mm f/1.8"; - lenses["02 2F 98 98 3D 3D 02 00"] = "Sigma APO 400mm f/5.6"; - lenses["02 34 A0 A0 44 44 02 00"] = "Sigma APO 500mm f/7.2"; - lenses["02 37 5E 8E 35 3D 02 00"] = "Sigma APO 75-300mm f/4.5-5.6"; - lenses["02 37 A0 A0 34 34 02 00"] = "Sigma APO 500mm f/4.5"; - lenses["02 3A 5E 8E 32 3D 02 00"] = "Sigma 75-300mm f/4-5.6"; - lenses["02 3B 44 61 30 3D 02 00"] = "Sigma 35-80mm f/4-5.6"; - lenses["02 3C B0 B0 3C 3C 02 00"] = "Sigma APO 800mm f/5.6"; - lenses["02 3F 24 24 2C 2C 02 00"] = "Sigma 14mm f/3.5"; - lenses["02 3F 3C 5C 2D 35 02 00"] = "Sigma 28-70mm f/3.5-4.5 UC"; - lenses["02 40 44 5C 2C 34 02 00"] = "Exakta AF 35-70mm f/3.5-4.5 MC"; - lenses["02 40 44 73 2B 36 02 00"] = "Sigma 35-135mm f/3.5-4.5 a"; - lenses["02 42 44 5C 2A 34 02 00"] = "AF Zoom-Nikkor 35-70mm f/3.3-4.5"; - lenses["02 42 44 5C 2A 34 08 00"] = "AF Zoom-Nikkor 35-70mm f/3.3-4.5"; - lenses["02 46 37 37 25 25 02 00"] = "Sigma 24mm f/2.8 Super Wide II Macro"; - lenses["02 46 3C 5C 25 25 02 00"] = "Sigma 28-70mm f/2.8"; - lenses["02 46 5C 82 25 25 02 00"] = "Sigma 70-210mm f/2.8 APO"; - lenses["02 48 50 50 24 24 02 00"] = "Sigma 50mm f/2.8 Macro"; - lenses["02 48 65 65 24 24 02 00"] = "Sigma 90mm f/2.8 Macro"; - lenses["03 43 5C 81 35 35 02 00"] = "Soligor AF C/D Zoom UMCS 70-210mm f/4.5"; - lenses["03 48 5C 81 30 30 02 00"] = "AF Zoom-Nikkor 70-210mm f/4"; - lenses["04 48 3C 3C 24 24 03 00"] = "AF Nikkor 28mm f/2.8"; - lenses["05 54 50 50 0C 0C 04 00"] = "AF Nikkor 50mm f/1.4"; - lenses["06 3F 68 68 2C 2C 06 00"] = "Cosina AF 100mm f/3.5 Macro"; - lenses["06 54 53 53 24 24 06 00"] = "AF Micro-Nikkor 55mm f/2.8"; - lenses["07 36 3D 5F 2C 3C 03 00"] = "Cosina AF Zoom 28-80mm f/3.5-5.6 MC Macro"; - lenses["07 3E 30 43 2D 35 03 00"] = "Soligor AF Zoom 19-35mm f/3.5-4.5 MC"; - lenses["07 40 2F 44 2C 34 03 02"] = "Tamron AF 19-35mm f/3.5-4.5 (A10)"; - lenses["07 40 30 45 2D 35 03 02"] = "Tamron AF 19-35mm f/3.5-4.5 (A10)"; - lenses["07 40 3C 5C 2C 35 03 00"] = "Tokina AF 270 II (AF 28-70mm f/3.5-4.5)"; - lenses["07 40 3C 62 2C 34 03 00"] = "AF Zoom-Nikkor 28-85mm f/3.5-4.5"; - lenses["07 46 2B 44 24 30 03 02"] = "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF) (A05)"; - lenses["07 46 3D 6A 25 2F 03 00"] = "Cosina AF Zoom 28-105mm f/2.8-3.8 MC"; - lenses["07 47 3C 5C 25 35 03 00"] = "Tokina AF 287 SD AF 28-70mm f/2.8-4.5"; - lenses["07 48 3C 5C 24 24 03 00"] = "Tokina AT-X 287 AF 28-70mm f/2.8"; - lenses["08 40 44 6A 2C 34 04 00"] = "AF Zoom-Nikkor 35-105mm f/3.5-4.5"; - lenses["09 48 37 37 24 24 04 00"] = "AF Nikkor 24mm f/2.8"; - lenses["0A 48 8E 8E 24 24 03 00"] = "AF Nikkor 300mm f/2.8 IF-ED"; - lenses["0A 48 8E 8E 24 24 05 00"] = "AF Nikkor 300mm f/2.8 IF-ED N"; - lenses["0B 3E 3D 7F 2F 3D 0E 00"] = "Tamron AF 28-200mm f/3.8-5.6 (71D)"; - lenses["0B 3E 3D 7F 2F 3D 0E 02"] = "Tamron AF 28-200mm f/3.8-5.6D (171D)"; - lenses["0B 48 7C 7C 24 24 05 00"] = "AF Nikkor 180mm f/2.8 IF-ED"; - lenses["0D 40 44 72 2C 34 07 00"] = "AF Zoom-Nikkor 35-135mm f/3.5-4.5"; - lenses["0E 48 5C 81 30 30 05 00"] = "AF Zoom-Nikkor 70-210mm f/4"; - lenses["0E 4A 31 48 23 2D 0E 02"] = "Tamron SP AF 20-40mm f/2.7-3.5 (166D)"; - lenses["0F 58 50 50 14 14 05 00"] = "AF Nikkor 50mm f/1.8 N"; - lenses["10 3D 3C 60 2C 3C D2 02"] = "Tamron AF 28-80mm f/3.5-5.6 Aspherical (177D)"; - lenses["10 48 8E 8E 30 30 08 00"] = "AF Nikkor 300mm f/4 IF-ED"; - lenses["11 48 44 5C 24 24 08 00"] = "AF Zoom-Nikkor 35-70mm f/2.8"; - lenses["12 36 5C 81 35 3D 09 00"] = "Cosina AF Zoom 70-210mm f/4.5-5.6 MC Macro"; - lenses["12 36 69 97 35 42 09 00"] = "Soligor AF Zoom 100-400mm f/4.5-6.7 MC"; - lenses["12 39 5C 8E 34 3D 08 02"] = "Cosina AF Zoom 70-300mm f/4.5-5.6 MC Macro"; - lenses["12 3B 68 8D 3D 43 09 02"] = "Cosina AF Zoom 100-300mm f/5.6-6.7 MC Macro"; - lenses["12 3B 98 98 3D 3D 09 00"] = "Tokina AT-X 400 SD AF 400mm f/5.6"; - lenses["12 3D 3C 80 2E 3C DF 02"] = "Tamron AF 28-200mm f/3.8-5.6 AF Aspherical LD (IF) (271D)"; - lenses["12 44 5E 8E 34 3C 09 00"] = "Tokina 730 AF 75-300mm f/4.5-5.6"; - lenses["12 48 5C 81 30 3C 09 00"] = "AF Nikkor 70-210mm f/4-5.6"; - lenses["12 4A 5C 81 31 3D 09 00"] = "Soligor AF C/D Auto Zoom+Macro 70-210mm f/4-5.6 UMCS"; - lenses["13 42 37 50 2A 34 0B 00"] = "AF Zoom-Nikkor 24-50mm f/3.3-4.5"; - lenses["14 48 60 80 24 24 0B 00"] = "AF Zoom-Nikkor 80-200mm f/2.8 ED"; - lenses["14 48 68 8E 30 30 0B 00"] = "Tokina AT-X 340 AF II 100-300mm f/4"; - lenses["14 54 60 80 24 24 0B 00"] = "Tokina AT-X 828 AF 80-200mm f/2.8"; - lenses["15 4C 62 62 14 14 0C 00"] = "AF Nikkor 85mm f/1.8"; - lenses["17 3C A0 A0 30 30 0F 00"] = "Nikkor 500mm f/4 P ED IF"; - lenses["17 3C A0 A0 30 30 11 00"] = "Nikkor 500mm f/4 P ED IF"; - lenses["18 40 44 72 2C 34 0E 00"] = "AF Zoom-Nikkor 35-135mm f/3.5-4.5 N"; - lenses["1A 54 44 44 18 18 11 00"] = "AF Nikkor 35mm f/2"; - lenses["1B 44 5E 8E 34 3C 10 00"] = "AF Zoom-Nikkor 75-300mm f/4.5-5.6"; - lenses["1C 48 30 30 24 24 12 00"] = "AF Nikkor 20mm f/2.8"; - lenses["1D 42 44 5C 2A 34 12 00"] = "AF Zoom-Nikkor 35-70mm f/3.3-4.5 N"; - lenses["1E 54 56 56 24 24 13 00"] = "AF Micro-Nikkor 60mm f/2.8"; - lenses["1E 5D 64 64 20 20 13 00"] = "Tamron SP AF 90mm f/2.5 (52E)"; - lenses["1F 54 6A 6A 24 24 14 00"] = "AF Micro-Nikkor 105mm f/2.8"; - lenses["20 3C 80 98 3D 3D 1E 02"] = "Tamron AF 200-400mm f/5.6 LD IF (75D)"; - lenses["20 48 60 80 24 24 15 00"] = "AF Zoom-Nikkor 80-200mm f/2.8 ED"; - lenses["20 5A 64 64 20 20 14 00"] = "Tamron SP AF 90mm f/2.5 Macro (152E)"; - lenses["21 40 3C 5C 2C 34 16 00"] = "AF Zoom-Nikkor 28-70mm f/3.5-4.5"; - lenses["21 56 8E 8E 24 24 14 00"] = "Tamron SP AF 300mm f/2.8 LD-IF (60E)"; - lenses["22 48 72 72 18 18 16 00"] = "AF DC-Nikkor 135mm f/2"; - lenses["22 53 64 64 24 24 E0 02"] = "Tamron SP AF 90mm f/2.8 Macro 1:1 (72E)"; - lenses["23 30 BE CA 3C 48 17 00"] = "Zoom-Nikkor 1200-1700mm f/5.6-8 P ED IF"; - lenses["24 44 60 98 34 3C 1A 02"] = "Tokina AT-X 840 AF II 80-400mm f/4.5-5.6"; - lenses["24 48 60 80 24 24 1A 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; - lenses["24 54 60 80 24 24 1A 02"] = "Tokina AT-X 828 AF PRO 80-200mm f/2.8"; - lenses["25 44 44 8E 34 42 1B 02"] = "Tokina AF 353 (AF 35-300mm f/4.5-6.7)"; - lenses["25 48 3C 5C 24 24 1B 02"] = "Tokina AT-X 270 AF PRO II 28-70mm f/2.6-2.8"; - lenses["25 48 3C 5C 24 24 1B 02"] = "Tokina AT-X 287 AF PRO SV 28-70mm f/2.8"; - lenses["25 48 44 5C 24 24 1B 02"] = "AF Zoom-Nikkor 35-70mm f/2.8D"; - lenses["25 48 44 5C 24 24 52 02"] = "AF Zoom-Nikkor 35-70mm f/2.8D"; - lenses["26 3C 54 80 30 3C 1C 06"] = "Sigma 55-200mm f/4-5.6 DC"; - lenses["26 3C 5C 82 30 3C 1C 02"] = "Sigma 70-210mm f/4-5.6 UC-II"; - lenses["26 3C 5C 8E 30 3C 1C 02"] = "Sigma 70-300mm f/4-5.6 DG Macro"; - lenses["26 3C 98 98 3C 3C 1C 02"] = "Sigma APO Tele Macro 400mm f/5.6"; - lenses["26 3D 3C 80 2F 3D 1C 02"] = "Sigma 28-300mm f/3.8-5.6 Aspherical"; - lenses["26 3E 3C 6A 2E 3C 1C 02"] = "Sigma 28-105mm f/3.8-5.6 UC-III Aspherical IF"; - lenses["26 40 27 3F 2C 34 1C 02"] = "Sigma 15-30mm f/3.5-4.5 EX Aspherical DG DF"; - lenses["26 40 2D 44 2B 34 1C 02"] = "Sigma 18-35mm f/3.5-4.5 Aspherical"; - lenses["26 40 2D 50 2C 3C 1C 06"] = "Sigma 18-50mm f/3.5-5.6 DC"; - lenses["26 40 2D 70 2B 3C 1C 06"] = "Sigma 18-125mm f/3.5-5.6 DC"; - lenses["26 40 2D 80 2C 40 1C 06"] = "Sigma 18-200mm f/3.5-6.3 DC"; - lenses["26 40 37 5C 2C 3C 1C 02"] = "Sigma 24-70mm f/3.5-5.6 Aspherical HF"; - lenses["26 40 3C 5C 2C 34 1C 02"] = "AF Zoom-Nikkor 28-70mm f/3.5-4.5D"; - lenses["26 40 3C 60 2C 3C 1C 02"] = "Sigma 28-80mm f/3.5-5.6 Mini Zoom Macro II Aspherical"; - lenses["26 40 3C 65 2C 3C 1C 02"] = "Sigma 28-90mm f/3.5-5.6 Macro"; - lenses["26 40 3C 80 2B 3C 1C 02"] = "Sigma 28-200mm f/3.5-5.6 Compact Aspherical Hyperzoom Macro"; - lenses["26 40 3C 80 2C 3C 1C 02"] = "Sigma 28-200mm f/3.5-5.6 Compact Aspherical Hyperzoom Macro"; - lenses["26 40 3C 8E 2C 40 1C 02"] = "Sigma 28-300mm f/3.5-6.3 Macro"; - lenses["26 40 7B A0 34 40 1C 02"] = "Sigma APO 170-500mm f/5-6.3 Aspherical RF"; - lenses["26 41 3C 8E 2C 40 1C 02"] = "Sigma 28-300mm f/3.5-6.3 DG Macro"; - lenses["26 44 73 98 34 3C 1C 02"] = "Sigma 135-400mm f/4.5-5.6 APO Aspherical"; - lenses["26 48 11 11 30 30 1C 02"] = "Sigma 8mm f/4 EX Circular Fisheye"; - lenses["26 48 27 27 24 24 1C 02"] = "Sigma 15mm f/2.8 EX Diagonal Fish-Eye"; - lenses["26 48 2D 50 24 24 1C 06"] = "Sigma 18-50mm f/2.8 EX DC"; - lenses["26 48 31 49 24 24 1C 02"] = "Sigma 20-40mm f/2.8"; - lenses["26 48 37 56 24 24 1C 02"] = "Sigma 24-60mm f/2.8 EX DG"; - lenses["26 48 3C 5C 24 24 1C 06"] = "Sigma 28-70mm f/2.8 EX DG"; - lenses["26 48 3C 5C 24 30 1C 02"] = "Sigma 28-70mm f/2.8-4 DG High Speed Zoom"; - lenses["26 48 3C 6A 24 30 1C 02"] = "Sigma 28-105mm f/2.8-4 Aspherical"; - lenses["26 48 8E 8E 30 30 1C 02"] = "Sigma APO Tele Macro 300mm f/4"; - lenses["26 54 2B 44 24 30 1C 02"] = "Sigma 17-35mm f/2.8-4 EX Aspherical"; - lenses["26 54 37 5C 24 24 1C 02"] = "Sigma 24-70mm f/2.8 EX DG Macro"; - lenses["26 54 37 73 24 34 1C 02"] = "Sigma 24-135mm f/2.8-4.5"; - lenses["26 54 3C 5C 24 24 1C 02"] = "Sigma 28-70mm f/2.8 EX"; - lenses["26 58 31 31 14 14 1C 02"] = "Sigma 20mm f/1.8 EX Aspherical DG DF RF"; - lenses["26 58 37 37 14 14 1C 02"] = "Sigma 24mm f/1.8 EX Aspherical DG DF MACRO"; - lenses["26 58 3C 3C 14 14 1C 02"] = "Sigma 28mm f/1.8 EX DG DF"; - lenses["27 48 8E 8E 24 24 1D 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED"; - lenses["27 48 8E 8E 24 24 E1 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-17E"; - lenses["27 48 8E 8E 24 24 F1 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-14E"; - lenses["27 48 8E 8E 24 24 F2 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-20E"; - lenses["27 48 8E 8E 30 30 1D 02"] = "Tokina AT-X 304 AF 300mm f/4"; - lenses["27 54 8E 8E 24 24 1D 02"] = "Tamron SP AF 300mm f/2.8 LD-IF (360E)"; - lenses["28 3C A6 A6 30 30 1D 02"] = "AF-I Nikkor 600mm f/4D IF-ED"; - lenses["28 3C A6 A6 30 30 E1 02"] = "AF-I Nikkor 600mm f/4D IF-ED + TC-17E"; - lenses["28 3C A6 A6 30 30 F1 02"] = "AF-I Nikkor 600mm f/4D IF-ED + TC-14E"; - lenses["28 3C A6 A6 30 30 F2 02"] = "AF-I Nikkor 600mm f/4D IF-ED + TC-20E"; - lenses["2A 54 3C 3C 0C 0C 26 02"] = "AF Nikkor 28mm f/1.4D"; - lenses["2B 3C 44 60 30 3C 1F 02"] = "AF Zoom-Nikkor 35-80mm f/4-5.6D"; - lenses["2C 48 6A 6A 18 18 27 02"] = "AF DC-Nikkor 105mm f/2D"; - lenses["2D 48 80 80 30 30 21 02"] = "AF Micro-Nikkor 200mm f/4D IF-ED"; - lenses["2E 48 5C 82 30 3C 22 02"] = "AF Nikkor 70-210mm f/4-5.6D"; - lenses["2E 48 5C 82 30 3C 28 02"] = "AF Nikkor 70-210mm f/4-5.6D"; - lenses["2F 40 30 44 2C 34 29 02"] = "Tokina AF 235 II 20-35mm f/3.5-4.5"; - lenses["2F 40 30 44 2C 34 29 02"] = "Tokina AF 193 19-35mm f/3.5-4.5"; - lenses["2F 48 30 44 24 24 29 02"] = "AF Zoom-Nikkor 20-35mm f/2.8D IF"; - lenses["2F 48 30 44 24 24 29 02"] = "Tokina AT-X 235 AF PRO (AF 20-35mm f/2.8)"; - lenses["30 48 98 98 24 24 24 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED"; - lenses["30 48 98 98 24 24 E1 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-17E"; - lenses["30 48 98 98 24 24 F1 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-14E"; - lenses["30 48 98 98 24 24 F2 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-20E"; - lenses["31 54 56 56 24 24 25 02"] = "AF Micro-Nikkor 60mm f/2.8D"; - lenses["32 53 64 64 24 24 35 02"] = "Tamron SP AF 90mm f/2.8 Di Macro 1:1 (172E/272E)"; - lenses["32 54 50 50 24 24 35 02"] = "Sigma 50mm f/2.8 EX DG Macro"; - lenses["32 54 6A 6A 24 24 35 02"] = "AF Micro-Nikkor 105mm f/2.8D"; - lenses["32 54 6A 6A 24 24 35 02"] = "Sigma 105mm f/2.8 EX DG Macro"; - lenses["33 48 2D 2D 24 24 31 02"] = "AF Nikkor 18mm f/2.8D"; - lenses["33 54 3C 5E 24 24 62 02"] = "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09)"; - lenses["34 48 29 29 24 24 32 02"] = "AF Fisheye Nikkor 16mm f/2.8D"; - lenses["35 3C A0 A0 30 30 33 02"] = "AF-I Nikkor 500mm f/4D IF-ED"; - lenses["35 3C A0 A0 30 30 E1 02"] = "AF-I Nikkor 500mm f/4D IF-ED + TC-17E"; - lenses["35 3C A0 A0 30 30 F1 02"] = "AF-I Nikkor 500mm f/4D IF-ED + TC-14E"; - lenses["35 3C A0 A0 30 30 F2 02"] = "AF-I Nikkor 500mm f/4D IF-ED + TC-20E"; - lenses["36 48 37 37 24 24 34 02"] = "AF Nikkor 24mm f/2.8D"; - lenses["37 48 30 30 24 24 36 02"] = "AF Nikkor 20mm f/2.8D"; - lenses["38 4C 62 62 14 14 37 02"] = "AF Nikkor 85mm f/1.8D"; - lenses["3A 40 3C 5C 2C 34 39 02"] = "AF Zoom-Nikkor 28-70mm f/3.5-4.5D"; - lenses["3B 48 44 5C 24 24 3A 02"] = "AF Zoom-Nikkor 35-70mm f/2.8D N"; - lenses["3C 48 60 80 24 24 3B 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; - lenses["3D 3C 44 60 30 3C 3E 02"] = "AF Zoom-Nikkor 35-80mm f/4-5.6D"; - lenses["3E 48 3C 3C 24 24 3D 02"] = "AF Nikkor 28mm f/2.8D"; - lenses["3F 40 44 6A 2C 34 45 02"] = "AF Zoom-Nikkor 35-105mm f/3.5-4.5D"; - lenses["41 48 7C 7C 24 24 43 02"] = "AF Nikkor 180mm f/2.8D IF-ED"; - lenses["42 54 44 44 18 18 44 02"] = "AF Nikkor 35mm f/2D"; - lenses["43 54 50 50 0C 0C 46 02"] = "AF Nikkor 50mm f/1.4D"; - lenses["44 44 60 80 34 3C 47 02"] = "AF Zoom-Nikkor 80-200mm f/4.5-5.6D"; - lenses["45 3D 3C 60 2C 3C 48 02"] = "Tamron AF 28-80mm f/3.5-5.6 Aspherical (177D)"; - lenses["45 40 3C 60 2C 3C 48 02"] = "AF Zoom-Nikkor 28-80mm f/3.5-5.6D"; - lenses["45 41 37 72 2C 3C 48 02"] = "Tamron SP AF 24-135mm f/3.5-5.6 AD Aspherical (IF) Macro (190D)"; - lenses["46 3C 44 60 30 3C 49 02"] = "AF Zoom-Nikkor 35-80mm f/4-5.6D N"; - lenses["47 42 37 50 2A 34 4A 02"] = "AF Zoom-Nikkor 24-50mm f/3.3-4.5D"; - lenses["48 38 1F 37 34 3C 4B 06"] = "Sigma 12-24mm f/4.5-5.6 EX Aspherical DG HSM"; - lenses["48 3C 19 31 30 3C 4B 06"] = "Sigma 10-20mm f/4-5.6 EX DC HSM"; - lenses["48 3C 50 A0 30 40 4B 02"] = "Sigma 50-500mm f/4-6.3 EX APO RF HSM"; - lenses["48 3C 8E B0 3C 3C 4B 02"] = "Sigma APO 300-800mm f/5.6 EX DG HSM"; - lenses["48 3C B0 B0 3C 3C 4B 02"] = "Sigma APO 800mm f/5.6 EX HSM"; - lenses["48 44 A0 A0 34 34 4B 02"] = "Sigma APO 500mm f/4.5 EX HSM"; - lenses["48 48 24 24 24 24 4B 02"] = "Sigma 14mm f/2.8 EX Aspherical HSM"; - lenses["48 48 2B 44 24 30 4B 06"] = "Sigma 17-35mm f/2.8-4 EX DG Aspherical HSM"; - lenses["48 48 68 8E 30 30 4B 02"] = "Sigma 100-300mm f/4 EX IF HSM"; - lenses["48 48 76 76 24 24 4B 06"] = "Sigma 150mm f/2.8 EX DG APO Macro HSM"; - lenses["48 48 8E 8E 24 24 4B 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED"; - lenses["48 48 8E 8E 24 24 E1 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-17E"; - lenses["48 48 8E 8E 24 24 F1 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-14E"; - lenses["48 48 8E 8E 24 24 F2 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-20E"; - lenses["48 4C 7C 7C 2C 2C 4B 02"] = "Sigma 180mm f/3.5 EX DG Macro"; - lenses["48 4C 7D 7D 2C 2C 4B 02"] = "Sigma APO Macro 180mm f/3.5 EX DG HSM"; - lenses["48 54 3E 3E 0C 0C 4B 06"] = "Sigma 30mm f/1.4 EX DC HSM"; - lenses["48 54 5C 80 24 24 4B 02"] = "Sigma 70-200mm f/2.8 EX APO IF HSM"; - lenses["48 54 6F 8E 24 24 4B 02"] = "Sigma APO 120-300mm f/2.8 EX DG HSM"; - lenses["48 54 8E 8E 24 24 4B 02"] = "Sigma APO 300mm f/2.8 EX DG HSM"; - lenses["49 3C A6 A6 30 30 4C 02"] = "AF-S Nikkor 600mm f/4D IF-ED"; - lenses["49 3C A6 A6 30 30 E1 02"] = "AF-S Nikkor 600mm f/4D IF-ED + TC-17E"; - lenses["49 3C A6 A6 30 30 F1 02"] = "AF-S Nikkor 600mm f/4D IF-ED + TC-14E"; - lenses["49 3C A6 A6 30 30 F2 02"] = "AF-S Nikkor 600mm f/4D IF-ED + TC-20E"; - lenses["4A 40 11 11 2C 0C 4D 02"] = "Samyang 8mm f/3.5 Fish-Eye CS"; - lenses["4A 48 24 24 24 0C 4D 02"] = "Samyang AE 14mm f/2.8 ED AS IF UMC"; - lenses["4A 54 62 62 0C 0C 4D 02"] = "AF Nikkor 85mm f/1.4D IF"; - lenses["4A 60 44 44 0C 0C 4D 02"] = "Samyang 35mm f/1.4 AS UMC"; - lenses["4A 60 62 62 0C 0C 4D 02"] = "Samyang AE 85mm f/1.4 AS IF UMC"; - lenses["4B 3C A0 A0 30 30 4E 02"] = "AF-S Nikkor 500mm f/4D IF-ED"; - lenses["4B 3C A0 A0 30 30 E1 02"] = "AF-S Nikkor 500mm f/4D IF-ED + TC-17E"; - lenses["4B 3C A0 A0 30 30 F1 02"] = "AF-S Nikkor 500mm f/4D IF-ED + TC-14E"; - lenses["4B 3C A0 A0 30 30 F2 02"] = "AF-S Nikkor 500mm f/4D IF-ED + TC-20E"; - lenses["4C 40 37 6E 2C 3C 4F 02"] = "AF Zoom-Nikkor 24-120mm f/3.5-5.6D IF"; - lenses["4D 40 3C 80 2C 3C 62 02"] = "AF Zoom-Nikkor 28-200mm f/3.5-5.6D IF"; - lenses["4D 41 3C 8E 2B 40 62 02"] = "Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical (IF) (A061)"; - lenses["4D 41 3C 8E 2C 40 62 02"] = "Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical (IF) (185D)"; - lenses["4E 48 72 72 18 18 51 02"] = "AF DC-Nikkor 135mm f/2D"; - lenses["4F 40 37 5C 2C 3C 53 06"] = "IX-Nikkor 24-70mm f/3.5-5.6"; - lenses["50 48 56 7C 30 3C 54 06"] = "IX-Nikkor 60-180mm f/4-5.6"; - lenses["53 48 60 80 24 24 57 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; - lenses["53 48 60 80 24 24 60 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; - lenses["54 44 5C 7C 34 3C 58 02"] = "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED"; - lenses["54 44 5C 7C 34 3C 61 02"] = "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED"; - lenses["56 3C 5C 8E 30 3C 1C 02"] = "Sigma 70-300mm f/4-5.6 APO Macro Super II"; - lenses["56 48 5C 8E 30 3C 5A 02"] = "AF Zoom-Nikkor 70-300mm f/4-5.6D ED"; - lenses["59 48 98 98 24 24 5D 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED"; - lenses["59 48 98 98 24 24 E1 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-17E"; - lenses["59 48 98 98 24 24 F1 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-14E"; - lenses["59 48 98 98 24 24 F2 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-20E"; - lenses["5A 3C 3E 56 30 3C 5E 06"] = "IX-Nikkor 30-60mm f/4-5.6"; - lenses["5B 44 56 7C 34 3C 5F 06"] = "IX-Nikkor 60-180mm f/4.5-5.6"; - lenses["5D 48 3C 5C 24 24 63 02"] = "AF-S Zoom-Nikkor 28-70mm f/2.8D IF-ED"; - lenses["5E 48 60 80 24 24 64 02"] = "AF-S Zoom-Nikkor 80-200mm f/2.8D IF-ED"; - lenses["5F 40 3C 6A 2C 34 65 02"] = "AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF"; - lenses["60 40 3C 60 2C 3C 66 02"] = "AF Zoom-Nikkor 28-80mm f/3.5-5.6D"; - lenses["61 44 5E 86 34 3C 67 02"] = "AF Zoom-Nikkor 75-240mm f/4.5-5.6D"; - lenses["63 48 2B 44 24 24 68 02"] = "AF-S Nikkor 17-35mm f/2.8D IF-ED"; - lenses["64 00 62 62 24 24 6A 02"] = "PC Micro-Nikkor 85mm f/2.8D"; - lenses["65 44 60 98 34 3C 6B 0A"] = "AF VR Zoom-Nikkor 80-400mm f/4.5-5.6D ED"; - lenses["66 40 2D 44 2C 34 6C 02"] = "AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED"; - lenses["67 48 37 62 24 30 6D 02"] = "AF Zoom-Nikkor 24-85mm f/2.8-4D IF"; - lenses["67 54 37 5C 24 24 1C 02"] = "Sigma 24-70mm f/2.8 EX DG Macro"; - lenses["68 42 3C 60 2A 3C 6E 06"] = "AF Zoom-Nikkor 28-80mm f/3.3-5.6G"; - lenses["69 47 5C 8E 30 3C 00 02"] = "Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17N)"; - lenses["69 48 5C 8E 30 3C 6F 02"] = "Tamron AF 70-300mm f/4-5.6 LD Macro 1:2 (772D)"; - lenses["69 48 5C 8E 30 3C 6F 06"] = "AF Zoom-Nikkor 70-300mm f/4-5.6G"; - lenses["6A 48 8E 8E 30 30 70 02"] = "AF-S Nikkor 300mm f/4D IF-ED"; - lenses["6B 48 24 24 24 24 71 02"] = "AF Nikkor ED 14mm f/2.8D"; - lenses["6D 48 8E 8E 24 24 73 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED II"; - lenses["6E 48 98 98 24 24 74 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED II"; - lenses["6F 3C A0 A0 30 30 75 02"] = "AF-S Nikkor 500mm f/4D IF-ED II"; - lenses["70 3C A6 A6 30 30 76 02"] = "AF-S Nikkor 600mm f/4D IF-ED II"; - lenses["72 48 4C 4C 24 24 77 00"] = "Nikkor 45mm f/2.8 P"; - lenses["74 40 37 62 2C 34 78 06"] = "AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED"; - lenses["75 40 3C 68 2C 3C 79 06"] = "AF Zoom-Nikkor 28-100mm f/3.5-5.6G"; - lenses["76 58 50 50 14 14 7A 02"] = "AF Nikkor 50mm f/1.8D"; - lenses["77 44 61 98 34 3C 7B 0E"] = "Sigma 80-400mm f/4.5-5.6 EX OS"; - lenses["77 48 5C 80 24 24 7B 0E"] = "AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED"; - lenses["78 40 37 6E 2C 3C 7C 0E"] = "AF-S VR Zoom-Nikkor 24-120mm f/3.5-5.6G IF-ED"; - lenses["79 40 11 11 2C 2C 1C 06"] = "Sigma 8mm f/3.5 EX Circular Fisheye"; - lenses["79 40 3C 80 2C 3C 7F 06"] = "AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED"; - lenses["79 48 5C 5C 24 24 1C 06"] = "Sigma 70mm f/2.8 EX DG Macro"; - lenses["7A 3B 53 80 30 3C 4B 06"] = "Sigma 55-200mm f/4-5.6 DC HSM"; - lenses["7A 3C 1F 37 30 30 7E 06"] = "AF-S DX Zoom-Nikkor 12-24mm f/4G IF-ED"; - lenses["7A 3C 1F 37 30 30 7E 06"] = "Tokina AT-X 124 AF PRO DX II (AF 12-24mm f/4)"; - lenses["7A 40 2D 50 2C 3C 4B 06"] = "Sigma 18-50mm f/3.5-5.6 DC HSM"; - lenses["7A 40 2D 80 2C 40 4B 0E"] = "Sigma 18-200mm f/3.5-6.3 DC OS HSM"; - lenses["7A 47 2B 5C 24 34 4B 06"] = "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF HSM"; - lenses["7A 47 50 76 24 24 4B 06"] = "Sigma 50-150mm f/2.8 EX APO DC HSM"; - lenses["7A 48 2B 5C 24 34 4B 06"] = "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF HSM"; - lenses["7A 48 2D 50 24 24 4B 06"] = "Sigma 18-50mm f/2.8 EX DC Macro"; - lenses["7A 48 5C 80 24 24 4B 06"] = "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"; - lenses["7A 54 6E 8E 24 24 4B 02"] = "Sigma APO 120-300mm f/2.8 EX DG HSM"; - lenses["7B 48 80 98 30 30 80 0E"] = "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED"; - lenses["7D 48 2B 53 24 24 82 06"] = "AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED"; - lenses["7F 40 2D 5C 2C 34 84 06"] = "AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED"; - lenses["7F 48 2B 5C 24 34 1C 06"] = "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF"; - lenses["7F 48 2D 50 24 24 1C 06"] = "Sigma 18-50mm f/2.8 EX DC Macro"; - lenses["80 48 1A 1A 24 24 85 06"] = "AF DX Fisheye-Nikkor 10.5mm f/2.8G ED"; - lenses["81 54 80 80 18 18 86 0E"] = "AF-S VR Nikkor 200mm f/2G IF-ED"; - lenses["82 48 8E 8E 24 24 87 0E"] = "AF-S VR Nikkor 300mm f/2.8G IF-ED"; - lenses["83 00 B0 B0 5A 5A 88 04"] = "FSA-L2 EDG 65 800mm f/13 G"; - lenses["89 3C 53 80 30 3C 8B 06"] = "AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED"; - lenses["8A 54 6A 6A 24 24 8C 0E"] = "AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED"; - lenses["8B 40 2D 80 2C 3C 8D 0E"] = "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED"; - lenses["8B 40 2D 80 2C 3C FD 0E"] = "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED [II]"; - lenses["8C 40 2D 53 2C 3C 8E 06"] = "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED"; - lenses["8D 44 5C 8E 34 3C 8F 0E"] = "AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED"; - lenses["8E 3C 2B 5C 24 30 4B 0E"] = "Sigma 17-70mm f/2.8-4 DC Macro OS HSM Contemporary"; - lenses["8F 40 2D 72 2C 3C 91 06"] = "AF-S DX Zoom-Nikkor 18-135mm f/3.5-5.6G IF-ED"; - lenses["90 3B 53 80 30 3C 92 0E"] = "AF-S DX VR Zoom-Nikkor 55-200mm f/4-5.6G IF-ED"; - lenses["91 54 44 44 0C 0C 4B 06"] = "Sigma 35mm f/1.4 DG HSM | A"; - lenses["92 2C 2D 88 2C 40 4B 0E"] = "Sigma 18-250mm f/3.5-6.3 DC Macro OS HSM"; - lenses["92 48 24 37 24 24 94 06"] = "AF-S Zoom-Nikkor 14-24mm f/2.8G ED"; - lenses["93 48 37 5C 24 24 95 06"] = "AF-S Zoom-Nikkor 24-70mm f/2.8G ED"; - lenses["94 40 2D 53 2C 3C 96 06"] = "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED II"; - lenses["95 00 37 37 2C 2C 97 06"] = "PC-E Nikkor 24mm f/3.5D ED"; - lenses["95 4C 37 37 2C 2C 97 02"] = "PC-E Nikkor 24mm f/3.5D ED"; - lenses["96 38 1F 37 34 3C 4B 06"] = "Sigma 12-24mm f/4.5-5.6 II DG HSM"; - lenses["96 48 98 98 24 24 98 0E"] = "AF-S VR Nikkor 400mm f/2.8G ED"; - lenses["97 3C A0 A0 30 30 99 0E"] = "AF-S VR Nikkor 500mm f/4G ED"; - lenses["98 3C A6 A6 30 30 9A 0E"] = "AF-S VR Nikkor 600mm f/4G ED"; - lenses["99 40 29 62 2C 3C 9B 0E"] = "AF-S DX VR Zoom-Nikkor 16-85mm f/3.5-5.6G ED"; - lenses["9A 40 2D 53 2C 3C 9C 0E"] = "AF-S DX VR Zoom-Nikkor 18-55mm f/3.5-5.6G"; - lenses["9B 00 4C 4C 24 24 9D 06"] = "PC-E Micro Nikkor 45mm f/2.8D ED"; - lenses["9B 54 4C 4C 24 24 9D 02"] = "PC-E Micro Nikkor 45mm f/2.8D ED"; - lenses["9B 54 62 62 0C 0C 4B 06"] = "Sigma 85mm f/1.4 EX DG HSM"; - lenses["9C 48 5C 80 24 24 4B 0E"] = "Sigma 70-200mm f/2.8 EX DG OS HSM"; - lenses["9C 54 56 56 24 24 9E 06"] = "AF-S Micro Nikkor 60mm f/2.8G ED"; - lenses["9D 00 62 62 24 24 9F 06"] = "PC-E Micro Nikkor 85mm f/2.8D"; - lenses["9D 48 2B 50 24 24 4B 0E"] = "Sigma 17-50mm f/2.8 EX DC OS HSM"; - lenses["9D 54 62 62 24 24 9F 02"] = "PC-E Micro Nikkor 85mm f/2.8D"; - lenses["9E 38 11 29 34 3C 4B 06"] = "Sigma 8-16mm f/4.5-5.6 DC HSM"; - lenses["9E 40 2D 6A 2C 3C A0 0E"] = "AF-S DX VR Zoom-Nikkor 18-105mm f/3.5-5.6G ED"; - lenses["9F 37 50 A0 34 40 4B 0E"] = "Sigma 50-500mm f/4.5-6.3 DG OS HSM"; - lenses["9F 58 44 44 14 14 A1 06"] = "AF-S DX Nikkor 35mm f/1.8G"; - lenses["A0 48 2A 5C 24 30 4B 0E"] = "Sigma 17-70mm f/2.8-4 DC Macro OS HSM"; - lenses["26 40 2D 44 2B 34 1C 02"] = "Sigma 18-35mm f/3.5-4.5 Aspherical"; - lenses["8B 4C 2D 44 14 14 4B 06"] = "Sigma 18-35mm f/1.8 DC HSM"; - lenses["A0 54 50 50 0C 0C A2 06"] = "AF-S Nikkor 50mm f/1.4G"; - lenses["A1 40 18 37 2C 34 A3 06"] = "AF-S DX Nikkor 10-24mm f/3.5-4.5G ED"; - lenses["A1 41 19 31 2C 2C 4B 06"] = "Sigma 10-20mm f/3.5 EX DC HSM"; - lenses["A2 48 5C 80 24 24 A4 0E"] = "AF-S Nikkor 70-200mm f/2.8G ED VR II"; - lenses["A3 3C 29 44 30 30 A5 0E"] = "AF-S Nikkor 16-35mm f/4G ED VR"; - lenses["A3 3C 5C 8E 30 3C 4B 0E"] = "Sigma 70-300mm f/4-5.6 DG OS"; - lenses["A4 47 2D 50 24 34 4B 0E"] = "Sigma 18-50mm f/2.8-4.5 DC OS HSM"; - lenses["A4 54 37 37 0C 0C A6 06"] = "AF-S Nikkor 24mm f/1.4G ED"; - lenses["A5 40 2D 88 2C 40 4B 0E"] = "Sigma 18-250mm f/3.5-6.3 DC OS HSM"; - lenses["A5 40 3C 8E 2C 3C A7 0E"] = "AF-S Nikkor 28-300mm f/3.5-5.6G ED VR"; - lenses["A6 48 37 5C 24 24 4B 06"] = "Sigma 24-70mm f/2.8 IF EX DG HSM"; - lenses["A6 48 8E 8E 24 24 A8 0E"] = "AF-S VR Nikkor 300mm f/2.8G IF-ED II"; - lenses["A7 49 80 A0 24 24 4B 06"] = "Sigma APO 200-500mm f/2.8 EX DG"; - lenses["A7 4B 62 62 2C 2C A9 0E"] = "AF-S DX Micro Nikkor 85mm f/3.5G ED VR"; - lenses["A8 48 80 98 30 30 AA 0E"] = "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED II"; - lenses["A9 54 80 80 18 18 AB 0E"] = "AF-S Nikkor 200mm f/2G ED VR II"; - lenses["AA 3C 37 6E 30 30 AC 0E"] = "AF-S Nikkor 24-120mm f/4G ED VR"; - lenses["AC 38 53 8E 34 3C AE 0E"] = "AF-S DX VR Nikkor 55-300mm f/4.5-5.6G ED"; - lenses["AD 3C 2D 8E 2C 3C AF 0E"] = "AF-S DX Nikkor 18-300mm 3.5-5.6G ED VR"; - lenses["AE 54 62 62 0C 0C B0 06"] = "AF-S Nikkor 85mm f/1.4G"; - lenses["AF 54 44 44 0C 0C B1 06"] = "AF-S Nikkor 35mm f/1.4G"; - lenses["B0 4C 50 50 14 14 B2 06"] = "AF-S Nikkor 50mm f/1.8G"; - lenses["B1 48 48 48 24 24 B3 06"] = "AF-S DX Micro Nikkor 40mm f/2.8G"; - lenses["B2 48 5C 80 30 30 B4 0E"] = "AF-S Nikkor 70-200mm f/4G ED VR"; - lenses["B3 4C 62 62 14 14 B5 06"] = "AF-S Nikkor 85mm f/1.8G"; - lenses["B4 40 37 62 2C 34 B6 0E"] = "AF-S VR Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED"; - lenses["B5 4C 3C 3C 14 14 B7 06"] = "AF-S Nikkor 28mm f/1.8G"; - lenses["B6 48 37 56 24 24 1C 02"] = "Sigma 24-60mm f/2.8 EX DG"; - lenses["B7 44 60 98 34 3C B9 0E"] = "AF-S Nikkor 80-400mm f/4.5-5.6G ED VR"; - lenses["B8 40 2D 44 2C 34 BA 06"] = "AF-S Nikkor 18-35mm f/3.5-4.5G ED"; - lenses["CD 3D 2D 70 2E 3C 4B 0E"] = "Sigma 18-125mm f/3.8-5.6 DC OS HSM"; - lenses["CE 34 76 A0 38 40 4B 0E"] = "Sigma 150-500mm f/5-6.3 DG OS APO HSM"; - lenses["CF 38 6E 98 34 3C 4B 0E"] = "Sigma APO 120-400mm f/4.5-5.6 DG OS HSM"; - lenses["DC 48 19 19 24 24 4B 06"] = "Sigma 10mm f/2.8 EX DC HSM Fisheye"; - lenses["DE 54 50 50 0C 0C 4B 06"] = "Sigma 50mm f/1.4 EX DG HSM"; - lenses["D8 48 5C 5C 24 24 1C 06"] = "Sigma 70mm f/2.8 EX DG Macro"; - lenses["E0 3C 5C 8E 30 3C 4B 06"] = "Sigma 70-300mm f/4-5.6 APO DG Macro HSM"; - lenses["E1 58 37 37 14 14 1C 02"] = "Sigma 24mm f/1.8 EX DG Aspherical Macro"; - lenses["E3 54 50 50 24 24 35 02"] = "Sigma 50mm f/2.8 EX DG Macro"; - lenses["E5 54 6A 6A 24 24 35 02"] = "Sigma 105mm f/2.8 EX DG Macro"; - lenses["E6 41 3C 8E 2C 40 1C 02"] = "Sigma 28-300mm f/3.5-6.3 DG Macro"; - lenses["E9 54 37 5C 24 24 1C 02"] = "Sigma 24-70mm f/2.8 EX DG Macro"; - lenses["ED 40 2D 80 2C 40 4B 0E"] = "Sigma 18-200mm f/3.5-6.3 DC OS HSM"; - lenses["EE 48 5C 80 24 24 4B 06"] = "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"; - lenses["F0 38 1F 37 34 3C 4B 06"] = "Sigma 12-24mm f/4.5-5.6 EX DG Aspherical HSM"; - lenses["F0 3F 2D 8A 2C 40 DF 0E"] = "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)"; - lenses["F1 44 A0 A0 34 34 4B 02"] = "Sigma APO 500mm f/4.5 EX DG HSM"; - lenses["F1 47 5C 8E 30 3C DF 0E"] = "Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)"; - lenses["F3 48 68 8E 30 30 4B 02"] = "Sigma APO 100-300mm f/4 EX IF HSM"; - lenses["F3 54 2B 50 24 24 84 0E"] = "Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)"; - lenses["F4 54 56 56 18 18 84 06"] = "Tamron SP AF 60mm f/2.0 Di II Macro 1:1 (G005)"; - lenses["F5 40 2C 8A 2C 40 40 0E"] = "Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical (IF) Macro (B003)"; - lenses["F5 48 76 76 24 24 4B 06"] = "Sigma 150mm f/2.8 EX DG APO Macro HSM"; - lenses["F6 3F 18 37 2C 34 84 06"] = "Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) (B001)"; - lenses["F6 48 2D 50 24 24 4B 06"] = "Sigma 18-50mm f/2.8 EX DC Macro"; - lenses["F7 53 5C 80 24 24 40 06"] = "Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)"; - lenses["F7 53 5C 80 24 24 84 06"] = "Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)"; - lenses["F8 54 3E 3E 0C 0C 4B 06"] = "Sigma 30mm f/1.4 EX DC HSM"; - lenses["F8 54 64 64 24 24 DF 06"] = "Tamron SP AF 90mm f/2.8 Di Macro 1:1 (272NII)"; - lenses["F8 55 64 64 24 24 84 06"] = "Tamron SP AF 90mm f/2.8 Di Macro 1:1 (272NII)"; - lenses["F9 3C 19 31 30 3C 4B 06"] = "Sigma 10-20mm f/4-5.6 EX DC HSM"; - lenses["F9 40 3C 8E 2C 40 40 0E"] = "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical (IF) Macro (A20)"; - lenses["FA 54 3C 5E 24 24 84 06"] = "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09NII)"; - lenses["FA 54 3C 5E 24 24 DF 06"] = "Tamron SP AF 28-75mm f//2.8 XR Di LD Aspherical (IF) Macro (A09NII)"; - lenses["FA 54 6E 8E 24 24 4B 02"] = "Sigma APO 120-300mm f/2.8 EX DG HSM"; - lenses["FB 54 2B 50 24 24 84 06"] = "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)"; - lenses["FB 54 8E 8E 24 24 4B 02"] = "Sigma APO 300mm f/2.8 EX DG HSM"; - lenses["FC 40 2D 80 2C 40 DF 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)"; - lenses["FD 47 50 76 24 24 4B 06"] = "Sigma 50-150mm f/2.8 EX APO DC HSM II"; - lenses["FE 47 00 00 24 24 4B 06"] = "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye"; - lenses["FE 48 37 5C 24 24 DF 0E"] = "Tamron SP 24-70mm f/2.8 Di VC USD"; - lenses["FE 53 5C 80 24 24 84 06"] = "Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)"; - lenses["FE 54 5C 80 24 24 DF 0E"] = "Tamron SP AF 70-200mm f//2.8 Di VC USD (A009)"; - lenses["FE 54 64 64 24 24 DF 0E"] = "Tamron SP 90mm f/2.8 Di VC USD Macro 1:1"; +class NALensDataInterpreter : public Interpreter +{ + std::map lenses; +public: + NALensDataInterpreter () // From EXIFTOOL database 'Nikon.pm' V2.80 + { + /* The key is a composite string made of 8 HEX bytes + * LensIDNumber LensFStops MinFocalLength MaxFocalLength MaxApertureAtMinFocal MaxApertureAtMaxFocal MCUVersion and LensType */ + lenses["00 00 00 00 00 00 00 01"] = "Manual Lens No CPU"; + lenses["00 00 00 00 00 00 E1 12"] = "TC-17E II"; + lenses["00 00 00 00 00 00 F1 0C"] = "TC-14E [II] or Sigma APO Tele Converter 1.4x EX DG or Kenko Teleplus PRO 300 DG 1.4x"; + lenses["00 00 00 00 00 00 F2 18"] = "TC-20E [II] or Sigma APO Tele Converter 2x EX DG or Kenko Teleplus PRO 300 DG 2.0x"; + lenses["00 00 48 48 53 53 00 01"] = "Loreo 40mm f/11-22 3D Lens in a Cap 9005"; + lenses["00 36 1C 2D 34 3C 00 06"] = "Tamron SP AF 11-18mm f/4.5-5.6 Di II LD Aspherical (IF)"; + lenses["00 3C 1F 37 30 30 00 06"] = "Tokina AT-X 124 PRO DX AF 12-24mm f/4"; + lenses["00 3E 80 A0 38 3F 00 02"] = "Tamron SP AF 200-500mm f/5-6.3 Di LD (IF)"; + lenses["00 3F 2D 80 2B 40 00 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF)"; + lenses["00 3F 2D 80 2C 40 00 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro"; + lenses["00 3F 80 A0 38 3F 00 02"] = "Tamron SP AF 200-500mm f/5-6.3 Di"; + lenses["00 40 11 11 2C 2C 00 00"] = "Samyang 8mm f/3.5 Fish-Eye"; + lenses["00 40 18 2B 2C 34 00 06"] = "Tokina AT-X 107 DX Fish-Eye AF 10-17mm f/3.5-4.5"; + lenses["00 40 2A 72 2C 3C 00 06"] = "Tokina AT-X 16.5-135 DX AF 16.5-135mm f/3.5-5.6"; + lenses["00 40 2B 2B 2C 2C 00 02"] = "Tokina AT-X 17 PRO AF 17mm f/3.5"; + lenses["00 40 2D 2D 2C 2C 00 00"] = "Carl Zeiss Distagon T* 18mm f/3.5 ZF.2"; + lenses["00 40 2D 80 2C 40 00 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)"; + lenses["00 40 2D 88 2C 40 00 06"] = "Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18NII)"; + lenses["00 40 2D 88 2C 40 62 06"] = "Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical (IF) Macro (A18)"; + lenses["00 40 31 31 2C 2C 00 00"] = "Voigtlander Color Skopar 20mm f/3.5 SLII Aspherical"; + lenses["00 40 37 80 2C 3C 00 02"] = "Tokina AT-X 242 AF 24-200mm f/3.5-5.6"; + lenses["00 40 64 64 2C 2C 00 00"] = "Voigtlander APO-Lanthar 90mm f/3.5 SLII Close Focus"; + lenses["00 44 60 98 34 3C 00 02"] = "Tokina AT-X 840D 80-400mm f/4.5-5.6"; + lenses["00 47 10 10 24 24 00 00"] = "Fisheye Nikkor 8mm f/2.8 AiS"; + lenses["00 47 25 25 24 24 00 02"] = "Tamron SP AF 14mm f/2.8 Aspherical (IF) (69E)"; + lenses["00 47 44 44 24 24 00 06"] = "Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro)"; + lenses["00 47 53 80 30 3C 00 06"] = "Tamron AF 55-200mm f/4-5.6 Di II LD"; + lenses["00 48 1C 29 24 24 00 06"] = "Tokina AT-X 116 PRO DX AF 11-16mm f/2.8"; + lenses["00 48 29 3C 24 24 00 06"] = "Tokina AT-X 16-28 PRO FX AF 16-28mm f/2.8"; + lenses["00 48 29 50 24 24 00 06"] = "Tokina AT-X 165 PRO DX AF 16-50mm f/2.8"; + lenses["00 48 32 32 24 24 00 00"] = "Carl Zeiss Distagon T* 21mm f/2.8 ZF.2"; + lenses["00 48 3C 60 24 24 00 02"] = "Tokina AT-X 280 PRO AF 28-80mm f/2.8 Aspherical"; + lenses["00 48 3C 6A 24 24 00 02"] = "Tamron SP AF 28-105mm f/2.8"; + lenses["00 48 50 50 18 18 00 00"] = "Nikkor H 50mm f/2"; + lenses["00 48 50 72 24 24 00 06"] = "Tokina AT-X 535 PRO DX AF 50-135mm f/2.8"; + lenses["00 48 5C 8E 30 3C 00 06"] = "Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17)"; + lenses["00 48 68 68 24 24 00 00"] = "Series E 100mm f/2.8"; + lenses["00 48 80 80 30 30 00 00"] = "Nikkor 200mm f/4 AiS"; + lenses["00 49 30 48 22 2B 00 02"] = "Tamron SP AF 20-40mm f/2.7-3.5"; + lenses["00 4C 6A 6A 20 20 00 00"] = "Nikkor 105mm f/2.5 AiS"; + lenses["00 4C 7C 7C 2C 2C 00 02"] = "Tamron SP AF 180mm f/3.5 Di Model (B01)"; + lenses["00 53 2B 50 24 24 00 06"] = "Tamron SP AF 17-50mm f/2.8 (A16)"; + lenses["00 54 2B 50 24 24 00 06"] = "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)"; + lenses["00 54 3C 3C 18 18 00 00"] = "Carl Zeiss Distagon T* 28mm f/2 ZF.2"; + lenses["00 54 44 44 0C 0C 00 00"] = "Nikkor 35mm f/1.4 AiS"; + lenses["00 54 44 44 18 18 00 00"] = "Carl Zeiss Distagon T* 35mm f/2 ZF.2"; + lenses["00 54 48 48 18 18 00 00"] = "Voigtlander Ultron 40mm f/2 SLII Aspherical"; + lenses["00 54 50 50 0C 0C 00 00"] = "Carl Zeiss Planar T* 50mm f/1.4 ZF.2"; + lenses["00 54 50 50 18 18 00 00"] = "Carl Zeiss Makro-Planar T* 50mm f/2 ZF.2"; + lenses["00 54 55 55 0C 0C 00 00"] = "Voigtlander Nokton 58mm f/1.4 SLII"; + lenses["00 54 56 56 30 30 00 00"] = "Coastal Optical Systems 60mm f/4 UV-VIS-IR Macro Apo"; + lenses["00 54 62 62 0C 0C 00 00"] = "Carl Zeiss Planar T* 85mm f/1.4 ZF.2"; + lenses["00 54 68 68 18 18 00 00"] = "Carl Zeiss Makro-Planar T* 100mm f/2 ZF.2"; + lenses["00 54 68 68 24 24 00 02"] = "Tokina AT-X M100 PRO D 100mm f/2.8 Macro"; + lenses["00 54 8E 8E 24 24 00 02"] = "Tokina AT-X 300 PRO AF 300mm f/2.8"; + lenses["00 58 64 64 20 20 00 00"] = "Soligor C/D Macro MC 90mm f/2.5"; + lenses["01 00 00 00 00 00 02 00"] = "AF Teleconverter TC-16A 1.6x"; + lenses["01 00 00 00 00 00 08 00"] = "AF Teleconverter TC-16A 1.6x"; + lenses["01 58 50 50 14 14 02 00"] = "AF Nikkor 50mm f/1.8"; + lenses["02 2F 98 98 3D 3D 02 00"] = "Sigma APO 400mm f/5.6"; + lenses["02 34 A0 A0 44 44 02 00"] = "Sigma APO 500mm f/7.2"; + lenses["02 37 5E 8E 35 3D 02 00"] = "Sigma APO 75-300mm f/4.5-5.6"; + lenses["02 37 A0 A0 34 34 02 00"] = "Sigma APO 500mm f/4.5"; + lenses["02 3A 5E 8E 32 3D 02 00"] = "Sigma 75-300mm f/4-5.6"; + lenses["02 3B 44 61 30 3D 02 00"] = "Sigma 35-80mm f/4-5.6"; + lenses["02 3C B0 B0 3C 3C 02 00"] = "Sigma APO 800mm f/5.6"; + lenses["02 3F 24 24 2C 2C 02 00"] = "Sigma 14mm f/3.5"; + lenses["02 3F 3C 5C 2D 35 02 00"] = "Sigma 28-70mm f/3.5-4.5 UC"; + lenses["02 40 44 5C 2C 34 02 00"] = "Exakta AF 35-70mm f/3.5-4.5 MC"; + lenses["02 40 44 73 2B 36 02 00"] = "Sigma 35-135mm f/3.5-4.5 a"; + lenses["02 42 44 5C 2A 34 02 00"] = "AF Zoom-Nikkor 35-70mm f/3.3-4.5"; + lenses["02 42 44 5C 2A 34 08 00"] = "AF Zoom-Nikkor 35-70mm f/3.3-4.5"; + lenses["02 46 37 37 25 25 02 00"] = "Sigma 24mm f/2.8 Super Wide II Macro"; + lenses["02 46 3C 5C 25 25 02 00"] = "Sigma 28-70mm f/2.8"; + lenses["02 46 5C 82 25 25 02 00"] = "Sigma 70-210mm f/2.8 APO"; + lenses["02 48 50 50 24 24 02 00"] = "Sigma 50mm f/2.8 Macro"; + lenses["02 48 65 65 24 24 02 00"] = "Sigma 90mm f/2.8 Macro"; + lenses["03 43 5C 81 35 35 02 00"] = "Soligor AF C/D Zoom UMCS 70-210mm f/4.5"; + lenses["03 48 5C 81 30 30 02 00"] = "AF Zoom-Nikkor 70-210mm f/4"; + lenses["04 48 3C 3C 24 24 03 00"] = "AF Nikkor 28mm f/2.8"; + lenses["05 54 50 50 0C 0C 04 00"] = "AF Nikkor 50mm f/1.4"; + lenses["06 3F 68 68 2C 2C 06 00"] = "Cosina AF 100mm f/3.5 Macro"; + lenses["06 54 53 53 24 24 06 00"] = "AF Micro-Nikkor 55mm f/2.8"; + lenses["07 36 3D 5F 2C 3C 03 00"] = "Cosina AF Zoom 28-80mm f/3.5-5.6 MC Macro"; + lenses["07 3E 30 43 2D 35 03 00"] = "Soligor AF Zoom 19-35mm f/3.5-4.5 MC"; + lenses["07 40 2F 44 2C 34 03 02"] = "Tamron AF 19-35mm f/3.5-4.5 (A10)"; + lenses["07 40 30 45 2D 35 03 02"] = "Tamron AF 19-35mm f/3.5-4.5 (A10)"; + lenses["07 40 3C 5C 2C 35 03 00"] = "Tokina AF 270 II (AF 28-70mm f/3.5-4.5)"; + lenses["07 40 3C 62 2C 34 03 00"] = "AF Zoom-Nikkor 28-85mm f/3.5-4.5"; + lenses["07 46 2B 44 24 30 03 02"] = "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical (IF) (A05)"; + lenses["07 46 3D 6A 25 2F 03 00"] = "Cosina AF Zoom 28-105mm f/2.8-3.8 MC"; + lenses["07 47 3C 5C 25 35 03 00"] = "Tokina AF 287 SD AF 28-70mm f/2.8-4.5"; + lenses["07 48 3C 5C 24 24 03 00"] = "Tokina AT-X 287 AF 28-70mm f/2.8"; + lenses["08 40 44 6A 2C 34 04 00"] = "AF Zoom-Nikkor 35-105mm f/3.5-4.5"; + lenses["09 48 37 37 24 24 04 00"] = "AF Nikkor 24mm f/2.8"; + lenses["0A 48 8E 8E 24 24 03 00"] = "AF Nikkor 300mm f/2.8 IF-ED"; + lenses["0A 48 8E 8E 24 24 05 00"] = "AF Nikkor 300mm f/2.8 IF-ED N"; + lenses["0B 3E 3D 7F 2F 3D 0E 00"] = "Tamron AF 28-200mm f/3.8-5.6 (71D)"; + lenses["0B 3E 3D 7F 2F 3D 0E 02"] = "Tamron AF 28-200mm f/3.8-5.6D (171D)"; + lenses["0B 48 7C 7C 24 24 05 00"] = "AF Nikkor 180mm f/2.8 IF-ED"; + lenses["0D 40 44 72 2C 34 07 00"] = "AF Zoom-Nikkor 35-135mm f/3.5-4.5"; + lenses["0E 48 5C 81 30 30 05 00"] = "AF Zoom-Nikkor 70-210mm f/4"; + lenses["0E 4A 31 48 23 2D 0E 02"] = "Tamron SP AF 20-40mm f/2.7-3.5 (166D)"; + lenses["0F 58 50 50 14 14 05 00"] = "AF Nikkor 50mm f/1.8 N"; + lenses["10 3D 3C 60 2C 3C D2 02"] = "Tamron AF 28-80mm f/3.5-5.6 Aspherical (177D)"; + lenses["10 48 8E 8E 30 30 08 00"] = "AF Nikkor 300mm f/4 IF-ED"; + lenses["11 48 44 5C 24 24 08 00"] = "AF Zoom-Nikkor 35-70mm f/2.8"; + lenses["12 36 5C 81 35 3D 09 00"] = "Cosina AF Zoom 70-210mm f/4.5-5.6 MC Macro"; + lenses["12 36 69 97 35 42 09 00"] = "Soligor AF Zoom 100-400mm f/4.5-6.7 MC"; + lenses["12 39 5C 8E 34 3D 08 02"] = "Cosina AF Zoom 70-300mm f/4.5-5.6 MC Macro"; + lenses["12 3B 68 8D 3D 43 09 02"] = "Cosina AF Zoom 100-300mm f/5.6-6.7 MC Macro"; + lenses["12 3B 98 98 3D 3D 09 00"] = "Tokina AT-X 400 SD AF 400mm f/5.6"; + lenses["12 3D 3C 80 2E 3C DF 02"] = "Tamron AF 28-200mm f/3.8-5.6 AF Aspherical LD (IF) (271D)"; + lenses["12 44 5E 8E 34 3C 09 00"] = "Tokina 730 AF 75-300mm f/4.5-5.6"; + lenses["12 48 5C 81 30 3C 09 00"] = "AF Nikkor 70-210mm f/4-5.6"; + lenses["12 4A 5C 81 31 3D 09 00"] = "Soligor AF C/D Auto Zoom+Macro 70-210mm f/4-5.6 UMCS"; + lenses["13 42 37 50 2A 34 0B 00"] = "AF Zoom-Nikkor 24-50mm f/3.3-4.5"; + lenses["14 48 60 80 24 24 0B 00"] = "AF Zoom-Nikkor 80-200mm f/2.8 ED"; + lenses["14 48 68 8E 30 30 0B 00"] = "Tokina AT-X 340 AF II 100-300mm f/4"; + lenses["14 54 60 80 24 24 0B 00"] = "Tokina AT-X 828 AF 80-200mm f/2.8"; + lenses["15 4C 62 62 14 14 0C 00"] = "AF Nikkor 85mm f/1.8"; + lenses["17 3C A0 A0 30 30 0F 00"] = "Nikkor 500mm f/4 P ED IF"; + lenses["17 3C A0 A0 30 30 11 00"] = "Nikkor 500mm f/4 P ED IF"; + lenses["18 40 44 72 2C 34 0E 00"] = "AF Zoom-Nikkor 35-135mm f/3.5-4.5 N"; + lenses["1A 54 44 44 18 18 11 00"] = "AF Nikkor 35mm f/2"; + lenses["1B 44 5E 8E 34 3C 10 00"] = "AF Zoom-Nikkor 75-300mm f/4.5-5.6"; + lenses["1C 48 30 30 24 24 12 00"] = "AF Nikkor 20mm f/2.8"; + lenses["1D 42 44 5C 2A 34 12 00"] = "AF Zoom-Nikkor 35-70mm f/3.3-4.5 N"; + lenses["1E 54 56 56 24 24 13 00"] = "AF Micro-Nikkor 60mm f/2.8"; + lenses["1E 5D 64 64 20 20 13 00"] = "Tamron SP AF 90mm f/2.5 (52E)"; + lenses["1F 54 6A 6A 24 24 14 00"] = "AF Micro-Nikkor 105mm f/2.8"; + lenses["20 3C 80 98 3D 3D 1E 02"] = "Tamron AF 200-400mm f/5.6 LD IF (75D)"; + lenses["20 48 60 80 24 24 15 00"] = "AF Zoom-Nikkor 80-200mm f/2.8 ED"; + lenses["20 5A 64 64 20 20 14 00"] = "Tamron SP AF 90mm f/2.5 Macro (152E)"; + lenses["21 40 3C 5C 2C 34 16 00"] = "AF Zoom-Nikkor 28-70mm f/3.5-4.5"; + lenses["21 56 8E 8E 24 24 14 00"] = "Tamron SP AF 300mm f/2.8 LD-IF (60E)"; + lenses["22 48 72 72 18 18 16 00"] = "AF DC-Nikkor 135mm f/2"; + lenses["22 53 64 64 24 24 E0 02"] = "Tamron SP AF 90mm f/2.8 Macro 1:1 (72E)"; + lenses["23 30 BE CA 3C 48 17 00"] = "Zoom-Nikkor 1200-1700mm f/5.6-8 P ED IF"; + lenses["24 44 60 98 34 3C 1A 02"] = "Tokina AT-X 840 AF II 80-400mm f/4.5-5.6"; + lenses["24 48 60 80 24 24 1A 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; + lenses["24 54 60 80 24 24 1A 02"] = "Tokina AT-X 828 AF PRO 80-200mm f/2.8"; + lenses["25 44 44 8E 34 42 1B 02"] = "Tokina AF 353 (AF 35-300mm f/4.5-6.7)"; + lenses["25 48 3C 5C 24 24 1B 02"] = "Tokina AT-X 270 AF PRO II 28-70mm f/2.6-2.8"; + lenses["25 48 3C 5C 24 24 1B 02"] = "Tokina AT-X 287 AF PRO SV 28-70mm f/2.8"; + lenses["25 48 44 5C 24 24 1B 02"] = "AF Zoom-Nikkor 35-70mm f/2.8D"; + lenses["25 48 44 5C 24 24 52 02"] = "AF Zoom-Nikkor 35-70mm f/2.8D"; + lenses["26 3C 54 80 30 3C 1C 06"] = "Sigma 55-200mm f/4-5.6 DC"; + lenses["26 3C 5C 82 30 3C 1C 02"] = "Sigma 70-210mm f/4-5.6 UC-II"; + lenses["26 3C 5C 8E 30 3C 1C 02"] = "Sigma 70-300mm f/4-5.6 DG Macro"; + lenses["26 3C 98 98 3C 3C 1C 02"] = "Sigma APO Tele Macro 400mm f/5.6"; + lenses["26 3D 3C 80 2F 3D 1C 02"] = "Sigma 28-300mm f/3.8-5.6 Aspherical"; + lenses["26 3E 3C 6A 2E 3C 1C 02"] = "Sigma 28-105mm f/3.8-5.6 UC-III Aspherical IF"; + lenses["26 40 27 3F 2C 34 1C 02"] = "Sigma 15-30mm f/3.5-4.5 EX Aspherical DG DF"; + lenses["26 40 2D 44 2B 34 1C 02"] = "Sigma 18-35mm f/3.5-4.5 Aspherical"; + lenses["26 40 2D 50 2C 3C 1C 06"] = "Sigma 18-50mm f/3.5-5.6 DC"; + lenses["26 40 2D 70 2B 3C 1C 06"] = "Sigma 18-125mm f/3.5-5.6 DC"; + lenses["26 40 2D 80 2C 40 1C 06"] = "Sigma 18-200mm f/3.5-6.3 DC"; + lenses["26 40 37 5C 2C 3C 1C 02"] = "Sigma 24-70mm f/3.5-5.6 Aspherical HF"; + lenses["26 40 3C 5C 2C 34 1C 02"] = "AF Zoom-Nikkor 28-70mm f/3.5-4.5D"; + lenses["26 40 3C 60 2C 3C 1C 02"] = "Sigma 28-80mm f/3.5-5.6 Mini Zoom Macro II Aspherical"; + lenses["26 40 3C 65 2C 3C 1C 02"] = "Sigma 28-90mm f/3.5-5.6 Macro"; + lenses["26 40 3C 80 2B 3C 1C 02"] = "Sigma 28-200mm f/3.5-5.6 Compact Aspherical Hyperzoom Macro"; + lenses["26 40 3C 80 2C 3C 1C 02"] = "Sigma 28-200mm f/3.5-5.6 Compact Aspherical Hyperzoom Macro"; + lenses["26 40 3C 8E 2C 40 1C 02"] = "Sigma 28-300mm f/3.5-6.3 Macro"; + lenses["26 40 7B A0 34 40 1C 02"] = "Sigma APO 170-500mm f/5-6.3 Aspherical RF"; + lenses["26 41 3C 8E 2C 40 1C 02"] = "Sigma 28-300mm f/3.5-6.3 DG Macro"; + lenses["26 44 73 98 34 3C 1C 02"] = "Sigma 135-400mm f/4.5-5.6 APO Aspherical"; + lenses["26 48 11 11 30 30 1C 02"] = "Sigma 8mm f/4 EX Circular Fisheye"; + lenses["26 48 27 27 24 24 1C 02"] = "Sigma 15mm f/2.8 EX Diagonal Fish-Eye"; + lenses["26 48 2D 50 24 24 1C 06"] = "Sigma 18-50mm f/2.8 EX DC"; + lenses["26 48 31 49 24 24 1C 02"] = "Sigma 20-40mm f/2.8"; + lenses["26 48 37 56 24 24 1C 02"] = "Sigma 24-60mm f/2.8 EX DG"; + lenses["26 48 3C 5C 24 24 1C 06"] = "Sigma 28-70mm f/2.8 EX DG"; + lenses["26 48 3C 5C 24 30 1C 02"] = "Sigma 28-70mm f/2.8-4 DG High Speed Zoom"; + lenses["26 48 3C 6A 24 30 1C 02"] = "Sigma 28-105mm f/2.8-4 Aspherical"; + lenses["26 48 8E 8E 30 30 1C 02"] = "Sigma APO Tele Macro 300mm f/4"; + lenses["26 54 2B 44 24 30 1C 02"] = "Sigma 17-35mm f/2.8-4 EX Aspherical"; + lenses["26 54 37 5C 24 24 1C 02"] = "Sigma 24-70mm f/2.8 EX DG Macro"; + lenses["26 54 37 73 24 34 1C 02"] = "Sigma 24-135mm f/2.8-4.5"; + lenses["26 54 3C 5C 24 24 1C 02"] = "Sigma 28-70mm f/2.8 EX"; + lenses["26 58 31 31 14 14 1C 02"] = "Sigma 20mm f/1.8 EX Aspherical DG DF RF"; + lenses["26 58 37 37 14 14 1C 02"] = "Sigma 24mm f/1.8 EX Aspherical DG DF MACRO"; + lenses["26 58 3C 3C 14 14 1C 02"] = "Sigma 28mm f/1.8 EX DG DF"; + lenses["27 48 8E 8E 24 24 1D 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED"; + lenses["27 48 8E 8E 24 24 E1 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-17E"; + lenses["27 48 8E 8E 24 24 F1 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-14E"; + lenses["27 48 8E 8E 24 24 F2 02"] = "AF-I Nikkor 300mm f/2.8D IF-ED + TC-20E"; + lenses["27 48 8E 8E 30 30 1D 02"] = "Tokina AT-X 304 AF 300mm f/4"; + lenses["27 54 8E 8E 24 24 1D 02"] = "Tamron SP AF 300mm f/2.8 LD-IF (360E)"; + lenses["28 3C A6 A6 30 30 1D 02"] = "AF-I Nikkor 600mm f/4D IF-ED"; + lenses["28 3C A6 A6 30 30 E1 02"] = "AF-I Nikkor 600mm f/4D IF-ED + TC-17E"; + lenses["28 3C A6 A6 30 30 F1 02"] = "AF-I Nikkor 600mm f/4D IF-ED + TC-14E"; + lenses["28 3C A6 A6 30 30 F2 02"] = "AF-I Nikkor 600mm f/4D IF-ED + TC-20E"; + lenses["2A 54 3C 3C 0C 0C 26 02"] = "AF Nikkor 28mm f/1.4D"; + lenses["2B 3C 44 60 30 3C 1F 02"] = "AF Zoom-Nikkor 35-80mm f/4-5.6D"; + lenses["2C 48 6A 6A 18 18 27 02"] = "AF DC-Nikkor 105mm f/2D"; + lenses["2D 48 80 80 30 30 21 02"] = "AF Micro-Nikkor 200mm f/4D IF-ED"; + lenses["2E 48 5C 82 30 3C 22 02"] = "AF Nikkor 70-210mm f/4-5.6D"; + lenses["2E 48 5C 82 30 3C 28 02"] = "AF Nikkor 70-210mm f/4-5.6D"; + lenses["2F 40 30 44 2C 34 29 02"] = "Tokina AF 235 II 20-35mm f/3.5-4.5"; + lenses["2F 40 30 44 2C 34 29 02"] = "Tokina AF 193 19-35mm f/3.5-4.5"; + lenses["2F 48 30 44 24 24 29 02"] = "AF Zoom-Nikkor 20-35mm f/2.8D IF"; + lenses["2F 48 30 44 24 24 29 02"] = "Tokina AT-X 235 AF PRO (AF 20-35mm f/2.8)"; + lenses["30 48 98 98 24 24 24 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED"; + lenses["30 48 98 98 24 24 E1 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-17E"; + lenses["30 48 98 98 24 24 F1 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-14E"; + lenses["30 48 98 98 24 24 F2 02"] = "AF-I Nikkor 400mm f/2.8D IF-ED + TC-20E"; + lenses["31 54 56 56 24 24 25 02"] = "AF Micro-Nikkor 60mm f/2.8D"; + lenses["32 53 64 64 24 24 35 02"] = "Tamron SP AF 90mm f/2.8 Di Macro 1:1 (172E/272E)"; + lenses["32 54 50 50 24 24 35 02"] = "Sigma 50mm f/2.8 EX DG Macro"; + lenses["32 54 6A 6A 24 24 35 02"] = "AF Micro-Nikkor 105mm f/2.8D"; + lenses["32 54 6A 6A 24 24 35 02"] = "Sigma 105mm f/2.8 EX DG Macro"; + lenses["33 48 2D 2D 24 24 31 02"] = "AF Nikkor 18mm f/2.8D"; + lenses["33 54 3C 5E 24 24 62 02"] = "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09)"; + lenses["34 48 29 29 24 24 32 02"] = "AF Fisheye Nikkor 16mm f/2.8D"; + lenses["35 3C A0 A0 30 30 33 02"] = "AF-I Nikkor 500mm f/4D IF-ED"; + lenses["35 3C A0 A0 30 30 E1 02"] = "AF-I Nikkor 500mm f/4D IF-ED + TC-17E"; + lenses["35 3C A0 A0 30 30 F1 02"] = "AF-I Nikkor 500mm f/4D IF-ED + TC-14E"; + lenses["35 3C A0 A0 30 30 F2 02"] = "AF-I Nikkor 500mm f/4D IF-ED + TC-20E"; + lenses["36 48 37 37 24 24 34 02"] = "AF Nikkor 24mm f/2.8D"; + lenses["37 48 30 30 24 24 36 02"] = "AF Nikkor 20mm f/2.8D"; + lenses["38 4C 62 62 14 14 37 02"] = "AF Nikkor 85mm f/1.8D"; + lenses["3A 40 3C 5C 2C 34 39 02"] = "AF Zoom-Nikkor 28-70mm f/3.5-4.5D"; + lenses["3B 48 44 5C 24 24 3A 02"] = "AF Zoom-Nikkor 35-70mm f/2.8D N"; + lenses["3C 48 60 80 24 24 3B 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; + lenses["3D 3C 44 60 30 3C 3E 02"] = "AF Zoom-Nikkor 35-80mm f/4-5.6D"; + lenses["3E 48 3C 3C 24 24 3D 02"] = "AF Nikkor 28mm f/2.8D"; + lenses["3F 40 44 6A 2C 34 45 02"] = "AF Zoom-Nikkor 35-105mm f/3.5-4.5D"; + lenses["41 48 7C 7C 24 24 43 02"] = "AF Nikkor 180mm f/2.8D IF-ED"; + lenses["42 54 44 44 18 18 44 02"] = "AF Nikkor 35mm f/2D"; + lenses["43 54 50 50 0C 0C 46 02"] = "AF Nikkor 50mm f/1.4D"; + lenses["44 44 60 80 34 3C 47 02"] = "AF Zoom-Nikkor 80-200mm f/4.5-5.6D"; + lenses["45 3D 3C 60 2C 3C 48 02"] = "Tamron AF 28-80mm f/3.5-5.6 Aspherical (177D)"; + lenses["45 40 3C 60 2C 3C 48 02"] = "AF Zoom-Nikkor 28-80mm f/3.5-5.6D"; + lenses["45 41 37 72 2C 3C 48 02"] = "Tamron SP AF 24-135mm f/3.5-5.6 AD Aspherical (IF) Macro (190D)"; + lenses["46 3C 44 60 30 3C 49 02"] = "AF Zoom-Nikkor 35-80mm f/4-5.6D N"; + lenses["47 42 37 50 2A 34 4A 02"] = "AF Zoom-Nikkor 24-50mm f/3.3-4.5D"; + lenses["48 38 1F 37 34 3C 4B 06"] = "Sigma 12-24mm f/4.5-5.6 EX Aspherical DG HSM"; + lenses["48 3C 19 31 30 3C 4B 06"] = "Sigma 10-20mm f/4-5.6 EX DC HSM"; + lenses["48 3C 50 A0 30 40 4B 02"] = "Sigma 50-500mm f/4-6.3 EX APO RF HSM"; + lenses["48 3C 8E B0 3C 3C 4B 02"] = "Sigma APO 300-800mm f/5.6 EX DG HSM"; + lenses["48 3C B0 B0 3C 3C 4B 02"] = "Sigma APO 800mm f/5.6 EX HSM"; + lenses["48 44 A0 A0 34 34 4B 02"] = "Sigma APO 500mm f/4.5 EX HSM"; + lenses["48 48 24 24 24 24 4B 02"] = "Sigma 14mm f/2.8 EX Aspherical HSM"; + lenses["48 48 2B 44 24 30 4B 06"] = "Sigma 17-35mm f/2.8-4 EX DG Aspherical HSM"; + lenses["48 48 68 8E 30 30 4B 02"] = "Sigma 100-300mm f/4 EX IF HSM"; + lenses["48 48 76 76 24 24 4B 06"] = "Sigma 150mm f/2.8 EX DG APO Macro HSM"; + lenses["48 48 8E 8E 24 24 4B 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED"; + lenses["48 48 8E 8E 24 24 E1 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-17E"; + lenses["48 48 8E 8E 24 24 F1 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-14E"; + lenses["48 48 8E 8E 24 24 F2 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED + TC-20E"; + lenses["48 4C 7C 7C 2C 2C 4B 02"] = "Sigma 180mm f/3.5 EX DG Macro"; + lenses["48 4C 7D 7D 2C 2C 4B 02"] = "Sigma APO Macro 180mm f/3.5 EX DG HSM"; + lenses["48 54 3E 3E 0C 0C 4B 06"] = "Sigma 30mm f/1.4 EX DC HSM"; + lenses["48 54 5C 80 24 24 4B 02"] = "Sigma 70-200mm f/2.8 EX APO IF HSM"; + lenses["48 54 6F 8E 24 24 4B 02"] = "Sigma APO 120-300mm f/2.8 EX DG HSM"; + lenses["48 54 8E 8E 24 24 4B 02"] = "Sigma APO 300mm f/2.8 EX DG HSM"; + lenses["49 3C A6 A6 30 30 4C 02"] = "AF-S Nikkor 600mm f/4D IF-ED"; + lenses["49 3C A6 A6 30 30 E1 02"] = "AF-S Nikkor 600mm f/4D IF-ED + TC-17E"; + lenses["49 3C A6 A6 30 30 F1 02"] = "AF-S Nikkor 600mm f/4D IF-ED + TC-14E"; + lenses["49 3C A6 A6 30 30 F2 02"] = "AF-S Nikkor 600mm f/4D IF-ED + TC-20E"; + lenses["4A 40 11 11 2C 0C 4D 02"] = "Samyang 8mm f/3.5 Fish-Eye CS"; + lenses["4A 48 24 24 24 0C 4D 02"] = "Samyang AE 14mm f/2.8 ED AS IF UMC"; + lenses["4A 54 62 62 0C 0C 4D 02"] = "AF Nikkor 85mm f/1.4D IF"; + lenses["4A 60 44 44 0C 0C 4D 02"] = "Samyang 35mm f/1.4 AS UMC"; + lenses["4A 60 62 62 0C 0C 4D 02"] = "Samyang AE 85mm f/1.4 AS IF UMC"; + lenses["4B 3C A0 A0 30 30 4E 02"] = "AF-S Nikkor 500mm f/4D IF-ED"; + lenses["4B 3C A0 A0 30 30 E1 02"] = "AF-S Nikkor 500mm f/4D IF-ED + TC-17E"; + lenses["4B 3C A0 A0 30 30 F1 02"] = "AF-S Nikkor 500mm f/4D IF-ED + TC-14E"; + lenses["4B 3C A0 A0 30 30 F2 02"] = "AF-S Nikkor 500mm f/4D IF-ED + TC-20E"; + lenses["4C 40 37 6E 2C 3C 4F 02"] = "AF Zoom-Nikkor 24-120mm f/3.5-5.6D IF"; + lenses["4D 40 3C 80 2C 3C 62 02"] = "AF Zoom-Nikkor 28-200mm f/3.5-5.6D IF"; + lenses["4D 41 3C 8E 2B 40 62 02"] = "Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical (IF) (A061)"; + lenses["4D 41 3C 8E 2C 40 62 02"] = "Tamron AF 28-300mm f/3.5-6.3 XR LD Aspherical (IF) (185D)"; + lenses["4E 48 72 72 18 18 51 02"] = "AF DC-Nikkor 135mm f/2D"; + lenses["4F 40 37 5C 2C 3C 53 06"] = "IX-Nikkor 24-70mm f/3.5-5.6"; + lenses["50 48 56 7C 30 3C 54 06"] = "IX-Nikkor 60-180mm f/4-5.6"; + lenses["53 48 60 80 24 24 57 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; + lenses["53 48 60 80 24 24 60 02"] = "AF Zoom-Nikkor 80-200mm f/2.8D ED"; + lenses["54 44 5C 7C 34 3C 58 02"] = "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED"; + lenses["54 44 5C 7C 34 3C 61 02"] = "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED"; + lenses["56 3C 5C 8E 30 3C 1C 02"] = "Sigma 70-300mm f/4-5.6 APO Macro Super II"; + lenses["56 48 5C 8E 30 3C 5A 02"] = "AF Zoom-Nikkor 70-300mm f/4-5.6D ED"; + lenses["59 48 98 98 24 24 5D 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED"; + lenses["59 48 98 98 24 24 E1 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-17E"; + lenses["59 48 98 98 24 24 F1 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-14E"; + lenses["59 48 98 98 24 24 F2 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED + TC-20E"; + lenses["5A 3C 3E 56 30 3C 5E 06"] = "IX-Nikkor 30-60mm f/4-5.6"; + lenses["5B 44 56 7C 34 3C 5F 06"] = "IX-Nikkor 60-180mm f/4.5-5.6"; + lenses["5D 48 3C 5C 24 24 63 02"] = "AF-S Zoom-Nikkor 28-70mm f/2.8D IF-ED"; + lenses["5E 48 60 80 24 24 64 02"] = "AF-S Zoom-Nikkor 80-200mm f/2.8D IF-ED"; + lenses["5F 40 3C 6A 2C 34 65 02"] = "AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF"; + lenses["60 40 3C 60 2C 3C 66 02"] = "AF Zoom-Nikkor 28-80mm f/3.5-5.6D"; + lenses["61 44 5E 86 34 3C 67 02"] = "AF Zoom-Nikkor 75-240mm f/4.5-5.6D"; + lenses["63 48 2B 44 24 24 68 02"] = "AF-S Nikkor 17-35mm f/2.8D IF-ED"; + lenses["64 00 62 62 24 24 6A 02"] = "PC Micro-Nikkor 85mm f/2.8D"; + lenses["65 44 60 98 34 3C 6B 0A"] = "AF VR Zoom-Nikkor 80-400mm f/4.5-5.6D ED"; + lenses["66 40 2D 44 2C 34 6C 02"] = "AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED"; + lenses["67 48 37 62 24 30 6D 02"] = "AF Zoom-Nikkor 24-85mm f/2.8-4D IF"; + lenses["67 54 37 5C 24 24 1C 02"] = "Sigma 24-70mm f/2.8 EX DG Macro"; + lenses["68 42 3C 60 2A 3C 6E 06"] = "AF Zoom-Nikkor 28-80mm f/3.3-5.6G"; + lenses["69 47 5C 8E 30 3C 00 02"] = "Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2 (A17N)"; + lenses["69 48 5C 8E 30 3C 6F 02"] = "Tamron AF 70-300mm f/4-5.6 LD Macro 1:2 (772D)"; + lenses["69 48 5C 8E 30 3C 6F 06"] = "AF Zoom-Nikkor 70-300mm f/4-5.6G"; + lenses["6A 48 8E 8E 30 30 70 02"] = "AF-S Nikkor 300mm f/4D IF-ED"; + lenses["6B 48 24 24 24 24 71 02"] = "AF Nikkor ED 14mm f/2.8D"; + lenses["6D 48 8E 8E 24 24 73 02"] = "AF-S Nikkor 300mm f/2.8D IF-ED II"; + lenses["6E 48 98 98 24 24 74 02"] = "AF-S Nikkor 400mm f/2.8D IF-ED II"; + lenses["6F 3C A0 A0 30 30 75 02"] = "AF-S Nikkor 500mm f/4D IF-ED II"; + lenses["70 3C A6 A6 30 30 76 02"] = "AF-S Nikkor 600mm f/4D IF-ED II"; + lenses["72 48 4C 4C 24 24 77 00"] = "Nikkor 45mm f/2.8 P"; + lenses["74 40 37 62 2C 34 78 06"] = "AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED"; + lenses["75 40 3C 68 2C 3C 79 06"] = "AF Zoom-Nikkor 28-100mm f/3.5-5.6G"; + lenses["76 58 50 50 14 14 7A 02"] = "AF Nikkor 50mm f/1.8D"; + lenses["77 44 61 98 34 3C 7B 0E"] = "Sigma 80-400mm f/4.5-5.6 EX OS"; + lenses["77 48 5C 80 24 24 7B 0E"] = "AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED"; + lenses["78 40 37 6E 2C 3C 7C 0E"] = "AF-S VR Zoom-Nikkor 24-120mm f/3.5-5.6G IF-ED"; + lenses["79 40 11 11 2C 2C 1C 06"] = "Sigma 8mm f/3.5 EX Circular Fisheye"; + lenses["79 40 3C 80 2C 3C 7F 06"] = "AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED"; + lenses["79 48 5C 5C 24 24 1C 06"] = "Sigma 70mm f/2.8 EX DG Macro"; + lenses["7A 3B 53 80 30 3C 4B 06"] = "Sigma 55-200mm f/4-5.6 DC HSM"; + lenses["7A 3C 1F 37 30 30 7E 06"] = "AF-S DX Zoom-Nikkor 12-24mm f/4G IF-ED"; + lenses["7A 3C 1F 37 30 30 7E 06"] = "Tokina AT-X 124 AF PRO DX II (AF 12-24mm f/4)"; + lenses["7A 40 2D 50 2C 3C 4B 06"] = "Sigma 18-50mm f/3.5-5.6 DC HSM"; + lenses["7A 40 2D 80 2C 40 4B 0E"] = "Sigma 18-200mm f/3.5-6.3 DC OS HSM"; + lenses["7A 47 2B 5C 24 34 4B 06"] = "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF HSM"; + lenses["7A 47 50 76 24 24 4B 06"] = "Sigma 50-150mm f/2.8 EX APO DC HSM"; + lenses["7A 48 2B 5C 24 34 4B 06"] = "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF HSM"; + lenses["7A 48 2D 50 24 24 4B 06"] = "Sigma 18-50mm f/2.8 EX DC Macro"; + lenses["7A 48 5C 80 24 24 4B 06"] = "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"; + lenses["7A 54 6E 8E 24 24 4B 02"] = "Sigma APO 120-300mm f/2.8 EX DG HSM"; + lenses["7B 48 80 98 30 30 80 0E"] = "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED"; + lenses["7D 48 2B 53 24 24 82 06"] = "AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED"; + lenses["7F 40 2D 5C 2C 34 84 06"] = "AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED"; + lenses["7F 48 2B 5C 24 34 1C 06"] = "Sigma 17-70mm f/2.8-4.5 DC Macro Asp. IF"; + lenses["7F 48 2D 50 24 24 1C 06"] = "Sigma 18-50mm f/2.8 EX DC Macro"; + lenses["80 48 1A 1A 24 24 85 06"] = "AF DX Fisheye-Nikkor 10.5mm f/2.8G ED"; + lenses["81 54 80 80 18 18 86 0E"] = "AF-S VR Nikkor 200mm f/2G IF-ED"; + lenses["82 48 8E 8E 24 24 87 0E"] = "AF-S VR Nikkor 300mm f/2.8G IF-ED"; + lenses["83 00 B0 B0 5A 5A 88 04"] = "FSA-L2 EDG 65 800mm f/13 G"; + lenses["89 3C 53 80 30 3C 8B 06"] = "AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED"; + lenses["8A 54 6A 6A 24 24 8C 0E"] = "AF-S VR Micro-Nikkor 105mm f/2.8G IF-ED"; + lenses["8B 40 2D 80 2C 3C 8D 0E"] = "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED"; + lenses["8B 40 2D 80 2C 3C FD 0E"] = "AF-S DX VR Zoom-Nikkor 18-200mm f/3.5-5.6G IF-ED [II]"; + lenses["8C 40 2D 53 2C 3C 8E 06"] = "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED"; + lenses["8D 44 5C 8E 34 3C 8F 0E"] = "AF-S VR Zoom-Nikkor 70-300mm f/4.5-5.6G IF-ED"; + lenses["8E 3C 2B 5C 24 30 4B 0E"] = "Sigma 17-70mm f/2.8-4 DC Macro OS HSM Contemporary"; + lenses["8F 40 2D 72 2C 3C 91 06"] = "AF-S DX Zoom-Nikkor 18-135mm f/3.5-5.6G IF-ED"; + lenses["90 3B 53 80 30 3C 92 0E"] = "AF-S DX VR Zoom-Nikkor 55-200mm f/4-5.6G IF-ED"; + lenses["91 54 44 44 0C 0C 4B 06"] = "Sigma 35mm f/1.4 DG HSM | A"; + lenses["92 2C 2D 88 2C 40 4B 0E"] = "Sigma 18-250mm f/3.5-6.3 DC Macro OS HSM"; + lenses["92 48 24 37 24 24 94 06"] = "AF-S Zoom-Nikkor 14-24mm f/2.8G ED"; + lenses["93 48 37 5C 24 24 95 06"] = "AF-S Zoom-Nikkor 24-70mm f/2.8G ED"; + lenses["94 40 2D 53 2C 3C 96 06"] = "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED II"; + lenses["95 00 37 37 2C 2C 97 06"] = "PC-E Nikkor 24mm f/3.5D ED"; + lenses["95 4C 37 37 2C 2C 97 02"] = "PC-E Nikkor 24mm f/3.5D ED"; + lenses["96 38 1F 37 34 3C 4B 06"] = "Sigma 12-24mm f/4.5-5.6 II DG HSM"; + lenses["96 48 98 98 24 24 98 0E"] = "AF-S VR Nikkor 400mm f/2.8G ED"; + lenses["97 3C A0 A0 30 30 99 0E"] = "AF-S VR Nikkor 500mm f/4G ED"; + lenses["98 3C A6 A6 30 30 9A 0E"] = "AF-S VR Nikkor 600mm f/4G ED"; + lenses["99 40 29 62 2C 3C 9B 0E"] = "AF-S DX VR Zoom-Nikkor 16-85mm f/3.5-5.6G ED"; + lenses["9A 40 2D 53 2C 3C 9C 0E"] = "AF-S DX VR Zoom-Nikkor 18-55mm f/3.5-5.6G"; + lenses["9B 00 4C 4C 24 24 9D 06"] = "PC-E Micro Nikkor 45mm f/2.8D ED"; + lenses["9B 54 4C 4C 24 24 9D 02"] = "PC-E Micro Nikkor 45mm f/2.8D ED"; + lenses["9B 54 62 62 0C 0C 4B 06"] = "Sigma 85mm f/1.4 EX DG HSM"; + lenses["9C 48 5C 80 24 24 4B 0E"] = "Sigma 70-200mm f/2.8 EX DG OS HSM"; + lenses["9C 54 56 56 24 24 9E 06"] = "AF-S Micro Nikkor 60mm f/2.8G ED"; + lenses["9D 00 62 62 24 24 9F 06"] = "PC-E Micro Nikkor 85mm f/2.8D"; + lenses["9D 48 2B 50 24 24 4B 0E"] = "Sigma 17-50mm f/2.8 EX DC OS HSM"; + lenses["9D 54 62 62 24 24 9F 02"] = "PC-E Micro Nikkor 85mm f/2.8D"; + lenses["9E 38 11 29 34 3C 4B 06"] = "Sigma 8-16mm f/4.5-5.6 DC HSM"; + lenses["9E 40 2D 6A 2C 3C A0 0E"] = "AF-S DX VR Zoom-Nikkor 18-105mm f/3.5-5.6G ED"; + lenses["9F 37 50 A0 34 40 4B 0E"] = "Sigma 50-500mm f/4.5-6.3 DG OS HSM"; + lenses["9F 58 44 44 14 14 A1 06"] = "AF-S DX Nikkor 35mm f/1.8G"; + lenses["A0 48 2A 5C 24 30 4B 0E"] = "Sigma 17-70mm f/2.8-4 DC Macro OS HSM"; + lenses["26 40 2D 44 2B 34 1C 02"] = "Sigma 18-35mm f/3.5-4.5 Aspherical"; + lenses["8B 4C 2D 44 14 14 4B 06"] = "Sigma 18-35mm f/1.8 DC HSM"; + lenses["A0 54 50 50 0C 0C A2 06"] = "AF-S Nikkor 50mm f/1.4G"; + lenses["A1 40 18 37 2C 34 A3 06"] = "AF-S DX Nikkor 10-24mm f/3.5-4.5G ED"; + lenses["A1 41 19 31 2C 2C 4B 06"] = "Sigma 10-20mm f/3.5 EX DC HSM"; + lenses["A2 48 5C 80 24 24 A4 0E"] = "AF-S Nikkor 70-200mm f/2.8G ED VR II"; + lenses["A3 3C 29 44 30 30 A5 0E"] = "AF-S Nikkor 16-35mm f/4G ED VR"; + lenses["A3 3C 5C 8E 30 3C 4B 0E"] = "Sigma 70-300mm f/4-5.6 DG OS"; + lenses["A4 47 2D 50 24 34 4B 0E"] = "Sigma 18-50mm f/2.8-4.5 DC OS HSM"; + lenses["A4 54 37 37 0C 0C A6 06"] = "AF-S Nikkor 24mm f/1.4G ED"; + lenses["A5 40 2D 88 2C 40 4B 0E"] = "Sigma 18-250mm f/3.5-6.3 DC OS HSM"; + lenses["A5 40 3C 8E 2C 3C A7 0E"] = "AF-S Nikkor 28-300mm f/3.5-5.6G ED VR"; + lenses["A6 48 37 5C 24 24 4B 06"] = "Sigma 24-70mm f/2.8 IF EX DG HSM"; + lenses["A6 48 8E 8E 24 24 A8 0E"] = "AF-S VR Nikkor 300mm f/2.8G IF-ED II"; + lenses["A7 49 80 A0 24 24 4B 06"] = "Sigma APO 200-500mm f/2.8 EX DG"; + lenses["A7 4B 62 62 2C 2C A9 0E"] = "AF-S DX Micro Nikkor 85mm f/3.5G ED VR"; + lenses["A8 48 80 98 30 30 AA 0E"] = "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED II"; + lenses["A9 54 80 80 18 18 AB 0E"] = "AF-S Nikkor 200mm f/2G ED VR II"; + lenses["AA 3C 37 6E 30 30 AC 0E"] = "AF-S Nikkor 24-120mm f/4G ED VR"; + lenses["AC 38 53 8E 34 3C AE 0E"] = "AF-S DX VR Nikkor 55-300mm f/4.5-5.6G ED"; + lenses["AD 3C 2D 8E 2C 3C AF 0E"] = "AF-S DX Nikkor 18-300mm 3.5-5.6G ED VR"; + lenses["AE 54 62 62 0C 0C B0 06"] = "AF-S Nikkor 85mm f/1.4G"; + lenses["AF 54 44 44 0C 0C B1 06"] = "AF-S Nikkor 35mm f/1.4G"; + lenses["B0 4C 50 50 14 14 B2 06"] = "AF-S Nikkor 50mm f/1.8G"; + lenses["B1 48 48 48 24 24 B3 06"] = "AF-S DX Micro Nikkor 40mm f/2.8G"; + lenses["B2 48 5C 80 30 30 B4 0E"] = "AF-S Nikkor 70-200mm f/4G ED VR"; + lenses["B3 4C 62 62 14 14 B5 06"] = "AF-S Nikkor 85mm f/1.8G"; + lenses["B4 40 37 62 2C 34 B6 0E"] = "AF-S VR Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED"; + lenses["B5 4C 3C 3C 14 14 B7 06"] = "AF-S Nikkor 28mm f/1.8G"; + lenses["B6 48 37 56 24 24 1C 02"] = "Sigma 24-60mm f/2.8 EX DG"; + lenses["B7 44 60 98 34 3C B9 0E"] = "AF-S Nikkor 80-400mm f/4.5-5.6G ED VR"; + lenses["B8 40 2D 44 2C 34 BA 06"] = "AF-S Nikkor 18-35mm f/3.5-4.5G ED"; + lenses["CD 3D 2D 70 2E 3C 4B 0E"] = "Sigma 18-125mm f/3.8-5.6 DC OS HSM"; + lenses["CE 34 76 A0 38 40 4B 0E"] = "Sigma 150-500mm f/5-6.3 DG OS APO HSM"; + lenses["CF 38 6E 98 34 3C 4B 0E"] = "Sigma APO 120-400mm f/4.5-5.6 DG OS HSM"; + lenses["DC 48 19 19 24 24 4B 06"] = "Sigma 10mm f/2.8 EX DC HSM Fisheye"; + lenses["DE 54 50 50 0C 0C 4B 06"] = "Sigma 50mm f/1.4 EX DG HSM"; + lenses["D8 48 5C 5C 24 24 1C 06"] = "Sigma 70mm f/2.8 EX DG Macro"; + lenses["E0 3C 5C 8E 30 3C 4B 06"] = "Sigma 70-300mm f/4-5.6 APO DG Macro HSM"; + lenses["E1 58 37 37 14 14 1C 02"] = "Sigma 24mm f/1.8 EX DG Aspherical Macro"; + lenses["E3 54 50 50 24 24 35 02"] = "Sigma 50mm f/2.8 EX DG Macro"; + lenses["E5 54 6A 6A 24 24 35 02"] = "Sigma 105mm f/2.8 EX DG Macro"; + lenses["E6 41 3C 8E 2C 40 1C 02"] = "Sigma 28-300mm f/3.5-6.3 DG Macro"; + lenses["E9 54 37 5C 24 24 1C 02"] = "Sigma 24-70mm f/2.8 EX DG Macro"; + lenses["ED 40 2D 80 2C 40 4B 0E"] = "Sigma 18-200mm f/3.5-6.3 DC OS HSM"; + lenses["EE 48 5C 80 24 24 4B 06"] = "Sigma 70-200mm f/2.8 EX APO DG Macro HSM II"; + lenses["F0 38 1F 37 34 3C 4B 06"] = "Sigma 12-24mm f/4.5-5.6 EX DG Aspherical HSM"; + lenses["F0 3F 2D 8A 2C 40 DF 0E"] = "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)"; + lenses["F1 44 A0 A0 34 34 4B 02"] = "Sigma APO 500mm f/4.5 EX DG HSM"; + lenses["F1 47 5C 8E 30 3C DF 0E"] = "Tamron SP 70-300mm f/4-5.6 Di VC USD (A005)"; + lenses["F3 48 68 8E 30 30 4B 02"] = "Sigma APO 100-300mm f/4 EX IF HSM"; + lenses["F3 54 2B 50 24 24 84 0E"] = "Tamron SP AF 17-50mm f/2.8 XR Di II VC LD Aspherical (IF) (B005)"; + lenses["F4 54 56 56 18 18 84 06"] = "Tamron SP AF 60mm f/2.0 Di II Macro 1:1 (G005)"; + lenses["F5 40 2C 8A 2C 40 40 0E"] = "Tamron AF 18-270mm f/3.5-6.3 Di II VC LD Aspherical (IF) Macro (B003)"; + lenses["F5 48 76 76 24 24 4B 06"] = "Sigma 150mm f/2.8 EX DG APO Macro HSM"; + lenses["F6 3F 18 37 2C 34 84 06"] = "Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical (IF) (B001)"; + lenses["F6 48 2D 50 24 24 4B 06"] = "Sigma 18-50mm f/2.8 EX DC Macro"; + lenses["F7 53 5C 80 24 24 40 06"] = "Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)"; + lenses["F7 53 5C 80 24 24 84 06"] = "Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)"; + lenses["F8 54 3E 3E 0C 0C 4B 06"] = "Sigma 30mm f/1.4 EX DC HSM"; + lenses["F8 54 64 64 24 24 DF 06"] = "Tamron SP AF 90mm f/2.8 Di Macro 1:1 (272NII)"; + lenses["F8 55 64 64 24 24 84 06"] = "Tamron SP AF 90mm f/2.8 Di Macro 1:1 (272NII)"; + lenses["F9 3C 19 31 30 3C 4B 06"] = "Sigma 10-20mm f/4-5.6 EX DC HSM"; + lenses["F9 40 3C 8E 2C 40 40 0E"] = "Tamron AF 28-300mm f/3.5-6.3 XR Di VC LD Aspherical (IF) Macro (A20)"; + lenses["FA 54 3C 5E 24 24 84 06"] = "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical (IF) Macro (A09NII)"; + lenses["FA 54 3C 5E 24 24 DF 06"] = "Tamron SP AF 28-75mm f//2.8 XR Di LD Aspherical (IF) Macro (A09NII)"; + lenses["FA 54 6E 8E 24 24 4B 02"] = "Sigma APO 120-300mm f/2.8 EX DG HSM"; + lenses["FB 54 2B 50 24 24 84 06"] = "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical (IF) (A16NII)"; + lenses["FB 54 8E 8E 24 24 4B 02"] = "Sigma APO 300mm f/2.8 EX DG HSM"; + lenses["FC 40 2D 80 2C 40 DF 06"] = "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF) Macro (A14NII)"; + lenses["FD 47 50 76 24 24 4B 06"] = "Sigma 50-150mm f/2.8 EX APO DC HSM II"; + lenses["FE 47 00 00 24 24 4B 06"] = "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye"; + lenses["FE 48 37 5C 24 24 DF 0E"] = "Tamron SP 24-70mm f/2.8 Di VC USD"; + lenses["FE 53 5C 80 24 24 84 06"] = "Tamron SP AF 70-200mm f/2.8 Di LD (IF) Macro (A001)"; + lenses["FE 54 5C 80 24 24 DF 0E"] = "Tamron SP AF 70-200mm f//2.8 Di VC USD (A009)"; + lenses["FE 54 64 64 24 24 DF 0E"] = "Tamron SP 90mm f/2.8 Di VC USD Macro 1:1"; + } + virtual std::string toString (Tag* t) + { + + static const unsigned char xlat[2][256] = { + { + 0xc1, 0xbf, 0x6d, 0x0d, 0x59, 0xc5, 0x13, 0x9d, 0x83, 0x61, 0x6b, 0x4f, 0xc7, 0x7f, 0x3d, 0x3d, + 0x53, 0x59, 0xe3, 0xc7, 0xe9, 0x2f, 0x95, 0xa7, 0x95, 0x1f, 0xdf, 0x7f, 0x2b, 0x29, 0xc7, 0x0d, + 0xdf, 0x07, 0xef, 0x71, 0x89, 0x3d, 0x13, 0x3d, 0x3b, 0x13, 0xfb, 0x0d, 0x89, 0xc1, 0x65, 0x1f, + 0xb3, 0x0d, 0x6b, 0x29, 0xe3, 0xfb, 0xef, 0xa3, 0x6b, 0x47, 0x7f, 0x95, 0x35, 0xa7, 0x47, 0x4f, + 0xc7, 0xf1, 0x59, 0x95, 0x35, 0x11, 0x29, 0x61, 0xf1, 0x3d, 0xb3, 0x2b, 0x0d, 0x43, 0x89, 0xc1, + 0x9d, 0x9d, 0x89, 0x65, 0xf1, 0xe9, 0xdf, 0xbf, 0x3d, 0x7f, 0x53, 0x97, 0xe5, 0xe9, 0x95, 0x17, + 0x1d, 0x3d, 0x8b, 0xfb, 0xc7, 0xe3, 0x67, 0xa7, 0x07, 0xf1, 0x71, 0xa7, 0x53, 0xb5, 0x29, 0x89, + 0xe5, 0x2b, 0xa7, 0x17, 0x29, 0xe9, 0x4f, 0xc5, 0x65, 0x6d, 0x6b, 0xef, 0x0d, 0x89, 0x49, 0x2f, + 0xb3, 0x43, 0x53, 0x65, 0x1d, 0x49, 0xa3, 0x13, 0x89, 0x59, 0xef, 0x6b, 0xef, 0x65, 0x1d, 0x0b, + 0x59, 0x13, 0xe3, 0x4f, 0x9d, 0xb3, 0x29, 0x43, 0x2b, 0x07, 0x1d, 0x95, 0x59, 0x59, 0x47, 0xfb, + 0xe5, 0xe9, 0x61, 0x47, 0x2f, 0x35, 0x7f, 0x17, 0x7f, 0xef, 0x7f, 0x95, 0x95, 0x71, 0xd3, 0xa3, + 0x0b, 0x71, 0xa3, 0xad, 0x0b, 0x3b, 0xb5, 0xfb, 0xa3, 0xbf, 0x4f, 0x83, 0x1d, 0xad, 0xe9, 0x2f, + 0x71, 0x65, 0xa3, 0xe5, 0x07, 0x35, 0x3d, 0x0d, 0xb5, 0xe9, 0xe5, 0x47, 0x3b, 0x9d, 0xef, 0x35, + 0xa3, 0xbf, 0xb3, 0xdf, 0x53, 0xd3, 0x97, 0x53, 0x49, 0x71, 0x07, 0x35, 0x61, 0x71, 0x2f, 0x43, + 0x2f, 0x11, 0xdf, 0x17, 0x97, 0xfb, 0x95, 0x3b, 0x7f, 0x6b, 0xd3, 0x25, 0xbf, 0xad, 0xc7, 0xc5, + 0xc5, 0xb5, 0x8b, 0xef, 0x2f, 0xd3, 0x07, 0x6b, 0x25, 0x49, 0x95, 0x25, 0x49, 0x6d, 0x71, 0xc7 + }, + { + 0xa7, 0xbc, 0xc9, 0xad, 0x91, 0xdf, 0x85, 0xe5, 0xd4, 0x78, 0xd5, 0x17, 0x46, 0x7c, 0x29, 0x4c, + 0x4d, 0x03, 0xe9, 0x25, 0x68, 0x11, 0x86, 0xb3, 0xbd, 0xf7, 0x6f, 0x61, 0x22, 0xa2, 0x26, 0x34, + 0x2a, 0xbe, 0x1e, 0x46, 0x14, 0x68, 0x9d, 0x44, 0x18, 0xc2, 0x40, 0xf4, 0x7e, 0x5f, 0x1b, 0xad, + 0x0b, 0x94, 0xb6, 0x67, 0xb4, 0x0b, 0xe1, 0xea, 0x95, 0x9c, 0x66, 0xdc, 0xe7, 0x5d, 0x6c, 0x05, + 0xda, 0xd5, 0xdf, 0x7a, 0xef, 0xf6, 0xdb, 0x1f, 0x82, 0x4c, 0xc0, 0x68, 0x47, 0xa1, 0xbd, 0xee, + 0x39, 0x50, 0x56, 0x4a, 0xdd, 0xdf, 0xa5, 0xf8, 0xc6, 0xda, 0xca, 0x90, 0xca, 0x01, 0x42, 0x9d, + 0x8b, 0x0c, 0x73, 0x43, 0x75, 0x05, 0x94, 0xde, 0x24, 0xb3, 0x80, 0x34, 0xe5, 0x2c, 0xdc, 0x9b, + 0x3f, 0xca, 0x33, 0x45, 0xd0, 0xdb, 0x5f, 0xf5, 0x52, 0xc3, 0x21, 0xda, 0xe2, 0x22, 0x72, 0x6b, + 0x3e, 0xd0, 0x5b, 0xa8, 0x87, 0x8c, 0x06, 0x5d, 0x0f, 0xdd, 0x09, 0x19, 0x93, 0xd0, 0xb9, 0xfc, + 0x8b, 0x0f, 0x84, 0x60, 0x33, 0x1c, 0x9b, 0x45, 0xf1, 0xf0, 0xa3, 0x94, 0x3a, 0x12, 0x77, 0x33, + 0x4d, 0x44, 0x78, 0x28, 0x3c, 0x9e, 0xfd, 0x65, 0x57, 0x16, 0x94, 0x6b, 0xfb, 0x59, 0xd0, 0xc8, + 0x22, 0x36, 0xdb, 0xd2, 0x63, 0x98, 0x43, 0xa1, 0x04, 0x87, 0x86, 0xf7, 0xa6, 0x26, 0xbb, 0xd6, + 0x59, 0x4d, 0xbf, 0x6a, 0x2e, 0xaa, 0x2b, 0xef, 0xe6, 0x78, 0xb6, 0x4e, 0xe0, 0x2f, 0xdc, 0x7c, + 0xbe, 0x57, 0x19, 0x32, 0x7e, 0x2a, 0xd0, 0xb8, 0xba, 0x29, 0x00, 0x3c, 0x52, 0x7d, 0xa8, 0x49, + 0x3b, 0x2d, 0xeb, 0x25, 0x49, 0xfa, 0xa3, 0xaa, 0x39, 0xa7, 0xc5, 0xa7, 0x50, 0x11, 0x36, 0xfb, + 0xc6, 0x67, 0x4a, 0xf5, 0xa5, 0x12, 0x65, 0x7e, 0xb0, 0xdf, 0xaf, 0x4e, 0xb3, 0x61, 0x7f, 0x2f + } + }; + + int ver = (t->toInt (0, BYTE) - '0') * 1000 + (t->toInt (1, BYTE) - '0') * 100 + (t->toInt (2, BYTE) - '0') * 10 + (t->toInt (3, BYTE) - '0'); + + std::ostringstream ld; + ld << "Version = " << ver << std::endl; + + int lenstype = t->getParent()->getTag(0x0083)->toInt(0, BYTE); + + std::ostringstream lid; + lid.setf (std::ios_base::hex, std::ios_base::basefield); + lid.setf (std::ios_base::uppercase); + + Tag *modelTag = t->getParent()->getRoot()->findTag("Model"); + std::string model( modelTag ? modelTag->valueToString() : ""); + int lidoffs = 7; + bool d100 = false; + + if (model.substr(0, 10) == "NIKON D100" || model.substr(0, 9) == "NIKON D1X") { + lidoffs = 0; + d100 = true; + } else if( ver < 204) { + lidoffs = 7; + d100 = false; + } else { + lidoffs = 8; + d100 = false; } - virtual std::string toString (Tag* t) { - static const unsigned char xlat[2][256] = { - { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d, - 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d, - 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f, - 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f, - 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1, - 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17, - 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89, - 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f, - 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b, - 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb, - 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3, - 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f, - 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35, - 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43, - 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5, - 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 }, - { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c, - 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34, - 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad, - 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05, - 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee, - 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d, - 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b, - 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b, - 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc, - 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33, - 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8, - 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6, - 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c, - 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49, - 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb, - 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } }; + unsigned char buffer[16]; - int ver = (t->toInt (0, BYTE) - '0') * 1000 + (t->toInt (1, BYTE) - '0') * 100 + (t->toInt (2, BYTE) - '0') * 10 + (t->toInt (3, BYTE) - '0'); - - std::ostringstream ld; - ld << "Version = " << ver << std::endl; - - int lenstype = t->getParent()->getTag(0x0083)->toInt(0,BYTE); - - std::ostringstream lid; - lid.setf (std::ios_base::hex, std::ios_base::basefield); - lid.setf (std::ios_base::uppercase); - - Tag *modelTag = t->getParent()->getRoot()->findTag("Model"); - std::string model( modelTag? modelTag->valueToString():""); - int lidoffs = 7; - bool d100 = false; - if (model.substr(0,10)=="NIKON D100" || model.substr(0,9)=="NIKON D1X") { - lidoffs = 0; - d100 = true; - }else if( ver<204){ - lidoffs = 7; - d100 = false; - }else{ - lidoffs = 8; - d100 = false; - } - - unsigned char buffer[16]; - if (d100) - memcpy (buffer, t->getValue()+6, 7); - else - memcpy (buffer, t->getValue()+4, 16); - - if (ver>=201) { - const unsigned char* serval = t->getParent()->getTag(0x001d)->getValue (); - int serial = 0; - for (int i=0; serval[i]; i++) - serial = serial*10 + (isdigit(serval[i]) ? serval[i] - '0' : serval[i] % 10); - const unsigned char* scval = t->getParent()->getTag(0x00a7)->getValue (); - int key = 0; - for (int i=0; i<4; i++) - key ^= scval[i]; - - unsigned char ci = xlat[0][serial & 0xff]; - unsigned char cj = xlat[1][key]; - unsigned char ck = 0x60; - for (int i=0; i < 16; i++) - buffer[i] ^= (cj += ci * ck++); - } - - std::string EffectiveMaxApertureString = ""; - if (!d100) { - int EffectiveMaxApertureValue; - if( ver<204 ){ - ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl; - ld << "AFAperture = " << (int) buffer[1] << std::endl; - ld << "FocusPosition = " << (int) buffer[4] << std::endl; - ld << "FocusDistance = " << (int) buffer[5] << std::endl; - ld << "FocalLength = " << (int) buffer[6] << std::endl; - EffectiveMaxApertureValue = (int) buffer[14]; - }else{ - ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl; - ld << "AFAperture = " << (int) buffer[1] << std::endl; - ld << "FocusPosition = " << (int) buffer[4] << std::endl; - ld << "FocusDistance = " << (int) buffer[6] << std::endl; - ld << "FocalLength = " << (int) buffer[7] << std::endl; - EffectiveMaxApertureValue = (int) buffer[15]; - } - switch (EffectiveMaxApertureValue) { - case 0x8: EffectiveMaxApertureString = "1.2";break; - case 0xc: EffectiveMaxApertureString = "1.4";break; - case 0x14: EffectiveMaxApertureString = "1.8";break; - case 0x18: EffectiveMaxApertureString = "2.0";break; - case 0x20: EffectiveMaxApertureString = "2.5";break; - case 0x24: EffectiveMaxApertureString = "2.8";break; - case 0x2a: EffectiveMaxApertureString = "3.3";break; - case 0x2c: EffectiveMaxApertureString = "3.5";break; - case 0x30: EffectiveMaxApertureString = "4.0";break; - case 0x34: EffectiveMaxApertureString = "4.5";break; - case 0x38: EffectiveMaxApertureString = "5.0";break; - case 0x3c: EffectiveMaxApertureString = "5.6";break; - case 0x40: EffectiveMaxApertureString = "6.3";break; - case 0x44: EffectiveMaxApertureString = "7.1";break; - case 0x48: EffectiveMaxApertureString = "8.0";break; - case 0x4e: EffectiveMaxApertureString = "9.5";break; - case 0x54: EffectiveMaxApertureString = "11.0";break; - case 0x5a: EffectiveMaxApertureString = "13.0";break; - case 0x5e: EffectiveMaxApertureString = "15.0";break; - case 0x60: EffectiveMaxApertureString = "16.0";break; - case 0x66: EffectiveMaxApertureString = "19.0";break; - case 0x6c: EffectiveMaxApertureString = "22.0";break; - default : EffectiveMaxApertureString = ""; - } - ld << "EffectiveMaxAperture = " << EffectiveMaxApertureString << std::endl; - } - - for (int i=0; i<7; i++) - lid << std::setw(2) << std::setfill('0') << (int)buffer[lidoffs+i] << ' '; - lid << std::setw(2) << std::setfill('0') << lenstype; - - std::map::iterator r = lenses.find (lid.str()); - if (r!=lenses.end()){ - if(r==lenses.begin() && EffectiveMaxApertureString != "") // first entry is for unchipped lenses - ld << "Lens = Unknown $FL$mm f/" << EffectiveMaxApertureString; - else - ld << "Lens = " << r->second; - } - else - ld << "Lens = Unknown, ID=" << lid.str(); - - return ld.str(); + if (d100) { + memcpy (buffer, t->getValue() + 6, 7); + } else { + memcpy (buffer, t->getValue() + 4, 16); } + if (ver >= 201) { + const unsigned char* serval = t->getParent()->getTag(0x001d)->getValue (); + int serial = 0; + + for (int i = 0; serval[i]; i++) { + serial = serial * 10 + (isdigit(serval[i]) ? serval[i] - '0' : serval[i] % 10); + } + + const unsigned char* scval = t->getParent()->getTag(0x00a7)->getValue (); + int key = 0; + + for (int i = 0; i < 4; i++) { + key ^= scval[i]; + } + + unsigned char ci = xlat[0][serial & 0xff]; + unsigned char cj = xlat[1][key]; + unsigned char ck = 0x60; + + for (int i = 0; i < 16; i++) { + buffer[i] ^= (cj += ci * ck++); + } + } + + std::string EffectiveMaxApertureString = ""; + + if (!d100) { + int EffectiveMaxApertureValue; + + if( ver < 204 ) { + ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl; + ld << "AFAperture = " << (int) buffer[1] << std::endl; + ld << "FocusPosition = " << (int) buffer[4] << std::endl; + ld << "FocusDistance = " << (int) buffer[5] << std::endl; + ld << "FocalLength = " << (int) buffer[6] << std::endl; + EffectiveMaxApertureValue = (int) buffer[14]; + } else { + ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl; + ld << "AFAperture = " << (int) buffer[1] << std::endl; + ld << "FocusPosition = " << (int) buffer[4] << std::endl; + ld << "FocusDistance = " << (int) buffer[6] << std::endl; + ld << "FocalLength = " << (int) buffer[7] << std::endl; + EffectiveMaxApertureValue = (int) buffer[15]; + } + + switch (EffectiveMaxApertureValue) { + case 0x8: + EffectiveMaxApertureString = "1.2"; + break; + + case 0xc: + EffectiveMaxApertureString = "1.4"; + break; + + case 0x14: + EffectiveMaxApertureString = "1.8"; + break; + + case 0x18: + EffectiveMaxApertureString = "2.0"; + break; + + case 0x20: + EffectiveMaxApertureString = "2.5"; + break; + + case 0x24: + EffectiveMaxApertureString = "2.8"; + break; + + case 0x2a: + EffectiveMaxApertureString = "3.3"; + break; + + case 0x2c: + EffectiveMaxApertureString = "3.5"; + break; + + case 0x30: + EffectiveMaxApertureString = "4.0"; + break; + + case 0x34: + EffectiveMaxApertureString = "4.5"; + break; + + case 0x38: + EffectiveMaxApertureString = "5.0"; + break; + + case 0x3c: + EffectiveMaxApertureString = "5.6"; + break; + + case 0x40: + EffectiveMaxApertureString = "6.3"; + break; + + case 0x44: + EffectiveMaxApertureString = "7.1"; + break; + + case 0x48: + EffectiveMaxApertureString = "8.0"; + break; + + case 0x4e: + EffectiveMaxApertureString = "9.5"; + break; + + case 0x54: + EffectiveMaxApertureString = "11.0"; + break; + + case 0x5a: + EffectiveMaxApertureString = "13.0"; + break; + + case 0x5e: + EffectiveMaxApertureString = "15.0"; + break; + + case 0x60: + EffectiveMaxApertureString = "16.0"; + break; + + case 0x66: + EffectiveMaxApertureString = "19.0"; + break; + + case 0x6c: + EffectiveMaxApertureString = "22.0"; + break; + + default : + EffectiveMaxApertureString = ""; + } + + ld << "EffectiveMaxAperture = " << EffectiveMaxApertureString << std::endl; + } + + for (int i = 0; i < 7; i++) { + lid << std::setw(2) << std::setfill('0') << (int)buffer[lidoffs + i] << ' '; + } + + lid << std::setw(2) << std::setfill('0') << lenstype; + + std::map::iterator r = lenses.find (lid.str()); + + if (r != lenses.end()) { + if(r == lenses.begin() && EffectiveMaxApertureString != "") { // first entry is for unchipped lenses + ld << "Lens = Unknown $FL$mm f/" << EffectiveMaxApertureString; + } else { + ld << "Lens = " << r->second; + } + } else { + ld << "Lens = Unknown, ID=" << lid.str(); + } + + return ld.str(); + } + }; NALensDataInterpreter naLensDataInterpreter; const TagAttrib nikonISOInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "ISO", &naISOInfoISOInterpreter}, - {0, AC_WRITE, 0, 0, 0x0004, SHORT, "ISOExpansion", &naISOExpansionInterpreter}, - {0, AC_WRITE, 0, 0, 0x0006, AUTO, "ISO2", &naISOInfoISOInterpreter}, - {0, AC_WRITE, 0, 0, 0x000a, SHORT, "ISOExpansion2", &naISOExpansionInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "ISO", &naISOInfoISOInterpreter}, + {0, AC_WRITE, 0, 0, 0x0004, SHORT, "ISOExpansion", &naISOExpansionInterpreter}, + {0, AC_WRITE, 0, 0, 0x0006, AUTO, "ISO2", &naISOInfoISOInterpreter}, + {0, AC_WRITE, 0, 0, 0x000a, SHORT, "ISOExpansion2", &naISOExpansionInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib nikon2Attribs[] = { - {0, AC_WRITE, 0, 0, 0x0002, AUTO, "Unknown", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0003, AUTO, "Quality", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0004, AUTO, "ColorMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0005, AUTO, "ImageAdjustment", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0006, AUTO, "ISOSpeed", &naISOInterpreter}, - {0, AC_WRITE, 0, 0, 0x0007, AUTO, "WhiteBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0008, AUTO, "Focus", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0009, AUTO, "Unknown", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000a, AUTO, "DigitalZoom", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000b, AUTO, "AuxiliaryLens", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0f00, AUTO, "Unknown", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0002, AUTO, "Unknown", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0003, AUTO, "Quality", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0004, AUTO, "ColorMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0005, AUTO, "ImageAdjustment", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0006, AUTO, "ISOSpeed", &naISOInterpreter}, + {0, AC_WRITE, 0, 0, 0x0007, AUTO, "WhiteBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0008, AUTO, "Focus", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0009, AUTO, "Unknown", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000a, AUTO, "DigitalZoom", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000b, AUTO, "AuxiliaryLens", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0f00, AUTO, "Unknown", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib nikon3Attribs[] = { - {0, AC_WRITE, 0, 0, 0x0001, AUTO, "MakerNoteVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0002, AUTO, "ISOSpeed", &naISOInterpreter}, - {0, AC_WRITE, 0, 0, 0x0003, AUTO, "ColorMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0004, AUTO, "Quality", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0005, AUTO, "WhiteBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0006, AUTO, "Sharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0007, AUTO, "FocusMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0008, AUTO, "FlashSetting", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0009, AUTO, "FlashType", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000b, AUTO, "WhiteBalanceFineTune", &stdInterpreter}, - {0, AC_NEW, 0, 0, 0x000c, AUTO, "ColorBalance1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000d, AUTO, "ProgramShift", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000e, AUTO, "ExposureDifference", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000f, AUTO, "ISOSelection", &naISOInterpreter}, - {0, AC_WRITE, 0, 0, 0x0010, AUTO, "DataDump", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0011, AUTO, "NikonPreview", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0012, AUTO, "FlashExposureComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0013, AUTO, "ISOSetting", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0016, AUTO, "ImageBoundary", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0018, AUTO, "FlashExposureBracketValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0019, AUTO, "ExposureBracketValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001a, AUTO, "ImageProcessing", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001b, AUTO, "CropHiSpeed", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001d, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001e, AUTO, "ColorSpace", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0020, AUTO, "ImageAuthentication", &stdInterpreter}, - {0, AC_WRITE, 0, nikonISOInfoAttribs, 0x0025, AUTO, "ISOInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0080, AUTO, "ImageAdjustment", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0081, AUTO, "ToneComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0082, AUTO, "AuxiliaryLens", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0083, AUTO, "LensType", &naLensTypeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0084, AUTO, "Lens", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0085, AUTO, "ManualFocusDistance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0086, AUTO, "DigitalZoom", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0087, AUTO, "FlashMode", &naFlashModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0088, AUTO, "AFInfo", &naAFInfoInterpreter}, - {0, AC_WRITE, 0, 0, 0x0089, AUTO, "ShootingMode", &naShootingModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x008a, AUTO, "AutoBracketRelease", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x008b, AUTO, "LensFStops", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x008c, AUTO, "NEFCurve1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x008d, AUTO, "ColorHue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x008f, AUTO, "SceneMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0090, AUTO, "LightSource", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0091, AUTO, "ShotInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0092, AUTO, "HueAdjustment", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0094, AUTO, "Saturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0095, AUTO, "NoiseReduction", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0096, AUTO, "NEFCurve2", &stdInterpreter}, - {0, AC_NEW, 0, 0, 0x0097, AUTO, "ColorBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0098, AUTO, "LensData", &naLensDataInterpreter}, - {0, AC_WRITE, 0, 0, 0x0099, AUTO, "RawImageCenter", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x009a, AUTO, "SensorPixelSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a0, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a2, AUTO, "ImageDataSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a5, AUTO, "ImageCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a6, AUTO, "DeletedImageCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a7, AUTO, "ShutterCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00a9, AUTO, "ImageOptimization", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00aa, AUTO, "Saturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00ab, AUTO, "VariProgram", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00ac, AUTO, "ImageStabilization", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00ad, AUTO, "AFResponse", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00b0, AUTO, "MultiExposure", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x00b1, AUTO, "HighISONoiseReduction", &naHiISONRInterpreter}, - {0, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0x0e01, AUTO, "NikonCaptureData", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0x0e09, AUTO, "NikonCaptureVersion", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0x0e0e, AUTO, "NikonCaptureOffsets", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0x0e10, AUTO, "NikonScanIFD", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0001, AUTO, "MakerNoteVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0002, AUTO, "ISOSpeed", &naISOInterpreter}, + {0, AC_WRITE, 0, 0, 0x0003, AUTO, "ColorMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0004, AUTO, "Quality", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0005, AUTO, "WhiteBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0006, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0007, AUTO, "FocusMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0008, AUTO, "FlashSetting", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0009, AUTO, "FlashType", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000b, AUTO, "WhiteBalanceFineTune", &stdInterpreter}, + {0, AC_NEW, 0, 0, 0x000c, AUTO, "ColorBalance1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000d, AUTO, "ProgramShift", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000e, AUTO, "ExposureDifference", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000f, AUTO, "ISOSelection", &naISOInterpreter}, + {0, AC_WRITE, 0, 0, 0x0010, AUTO, "DataDump", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0011, AUTO, "NikonPreview", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0012, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0013, AUTO, "ISOSetting", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0016, AUTO, "ImageBoundary", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0018, AUTO, "FlashExposureBracketValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0019, AUTO, "ExposureBracketValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001a, AUTO, "ImageProcessing", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001b, AUTO, "CropHiSpeed", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001d, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001e, AUTO, "ColorSpace", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0020, AUTO, "ImageAuthentication", &stdInterpreter}, + {0, AC_WRITE, 0, nikonISOInfoAttribs, 0x0025, AUTO, "ISOInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0080, AUTO, "ImageAdjustment", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0081, AUTO, "ToneComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0082, AUTO, "AuxiliaryLens", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0083, AUTO, "LensType", &naLensTypeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0084, AUTO, "Lens", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0085, AUTO, "ManualFocusDistance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0086, AUTO, "DigitalZoom", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0087, AUTO, "FlashMode", &naFlashModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0088, AUTO, "AFInfo", &naAFInfoInterpreter}, + {0, AC_WRITE, 0, 0, 0x0089, AUTO, "ShootingMode", &naShootingModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x008a, AUTO, "AutoBracketRelease", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x008b, AUTO, "LensFStops", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x008c, AUTO, "NEFCurve1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x008d, AUTO, "ColorHue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x008f, AUTO, "SceneMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0090, AUTO, "LightSource", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0091, AUTO, "ShotInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0092, AUTO, "HueAdjustment", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0094, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0095, AUTO, "NoiseReduction", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0096, AUTO, "NEFCurve2", &stdInterpreter}, + {0, AC_NEW, 0, 0, 0x0097, AUTO, "ColorBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0098, AUTO, "LensData", &naLensDataInterpreter}, + {0, AC_WRITE, 0, 0, 0x0099, AUTO, "RawImageCenter", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x009a, AUTO, "SensorPixelSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a0, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a2, AUTO, "ImageDataSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a5, AUTO, "ImageCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a6, AUTO, "DeletedImageCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a7, AUTO, "ShutterCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00a9, AUTO, "ImageOptimization", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00aa, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00ab, AUTO, "VariProgram", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00ac, AUTO, "ImageStabilization", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00ad, AUTO, "AFResponse", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00b0, AUTO, "MultiExposure", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x00b1, AUTO, "HighISONoiseReduction", &naHiISONRInterpreter}, + {0, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0x0e01, AUTO, "NikonCaptureData", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0x0e09, AUTO, "NikonCaptureVersion", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0x0e0e, AUTO, "NikonCaptureOffsets", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0x0e10, AUTO, "NikonScanIFD", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; } #endif diff --git a/rtexif/olympusattribs.cc b/rtexif/olympusattribs.cc index d858b64f0..4e2e4e53f 100644 --- a/rtexif/olympusattribs.cc +++ b/rtexif/olympusattribs.cc @@ -7,7 +7,7 @@ * 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 @@ -26,711 +26,767 @@ #include "rtexif.h" -namespace rtexif { +namespace rtexif +{ -class OLOnOffInterpreter : public Interpreter { - public: - OLOnOffInterpreter () {} - virtual std::string toString (Tag* t) { - if (t->toInt()==0) - return "Off"; - else - return "On"; +class OLOnOffInterpreter : public Interpreter +{ +public: + OLOnOffInterpreter () {} + virtual std::string toString (Tag* t) + { + if (t->toInt() == 0) { + return "Off"; + } else { + return "On"; } + } }; OLOnOffInterpreter olOnOffInterpreter; -class OLYesNoInterpreter : public Interpreter { - public: - OLYesNoInterpreter () {} - virtual std::string toString (Tag* t) { - if (t->toInt()==0) - return "No"; - else - return "Yes"; +class OLYesNoInterpreter : public Interpreter +{ +public: + OLYesNoInterpreter () {} + virtual std::string toString (Tag* t) + { + if (t->toInt() == 0) { + return "No"; + } else { + return "Yes"; } + } }; -OLYesNoInterpreter olYesNoInterpreter; +OLYesNoInterpreter olYesNoInterpreter; -class OLApertureInterpreter : public Interpreter { - public: - OLApertureInterpreter () {} - virtual std::string toString (Tag* t) { - std::ostringstream str; - str.precision(2); - str << pow(2, t->toInt() / 512.0); - return str.str(); - } +class OLApertureInterpreter : public Interpreter +{ +public: + OLApertureInterpreter () {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + str.precision(2); + str << pow(2, t->toInt() / 512.0); + return str.str(); + } }; -OLApertureInterpreter olApertureInterpreter; +OLApertureInterpreter olApertureInterpreter; -class OLLensTypeInterpreter : public Interpreter { - std::map lenses; - public: - OLLensTypeInterpreter () { // From EXIFTOOL database 'Olympus.pm' V2.09 - // exadecimal bytes - lenses["00 01 00"] = "Zuiko Digital ED 50mm f/2 Macro"; - lenses["00 01 01"] = "Zuiko Digital 40-150mm f/3.5-4.5"; - lenses["00 01 10"] = "Zuiko Digital ED 14-42mm f/3.5-5.6"; - lenses["00 02 00"] = "Zuiko Digital ED 150mm f/2"; - lenses["00 02 10"] = "Zuiko Digital 17mm f/2.8 Pancake"; - lenses["00 03 00"] = "Zuiko Digital ED 300mm f/2.8"; - lenses["00 03 10"] = "Zuiko Digital ED 14-150mm f/4-5.6"; - lenses["00 04 10"] = "Zuiko Digital ED 9-18mm f/4-5.6"; - lenses["00 05 00"] = "Zuiko Digital 14-54mm f/2.8-3.5"; - lenses["00 05 01"] = "Zuiko Digital Pro ED 90-250mm f/2.8"; - lenses["00 05 10"] = "Zuiko Digital ED 14-42mm f/3.5-5.6 L"; - lenses["00 06 00"] = "Zuiko Digital ED 50-200mm f/2.8-3.5"; - lenses["00 06 01"] = "Zuiko Digital ED 8mm f/3.5 Fisheye"; - lenses["00 06 10"] = "Zuiko Digital ED 40-150mm f/4-5.6"; - lenses["00 07 00"] = "Zuiko Digital 11-22mm f/2.8-3.5"; - lenses["00 07 01"] = "Zuiko Digital 18-180mm f/3.5-6.3"; - lenses["00 07 10"] = "Zuiko Digital ED 12mm f/2"; - lenses["00 08 01"] = "Zuiko Digital 70-300mm f/4-5.6"; - lenses["00 08 10"] = "Zuiko Digital ED 75-300mm f/4.8-6.7"; - lenses["00 09 10"] = "Zuiko Digital 14-42mm f/3.5-5.6 II"; - lenses["00 10 01"] = "Kenko Tokina Reflex 300mm f/6.3 MF Macro"; - lenses["00 10 10"] = "Zuiko Digital ED 12-50mm f/3.5-6.3 EZ"; - lenses["00 11 10"] = "Zuiko Digital 45mm f/1.8"; - lenses["00 12 10"] = "Zuiko Digital ED 60mm f/2.8 Macro"; - lenses["00 13 10"] = "Zuiko Digital ED 14-42mm f/3.5-5.6 II R"; - lenses["00 14 10"] = "Zuiko Digital ED 40-150mm f/4-5.6 R"; - lenses["00 15 00"] = "Zuiko Digital ED 7-14mm f/4"; - lenses["00 15 10"] = "Zuiko Digital ED 75mm f/1.8"; - lenses["00 16 10"] = "Zuiko Digital 17mm f/1.8"; - lenses["00 17 00"] = "Zuiko Digital Pro ED 35-100mm f/2"; - lenses["00 18 00"] = "Zuiko Digital 14-45mm f/3.5-5.6"; - lenses["00 18 10"] = "Zuiko Digital ED 75-300mm f/4.8-6.7 II"; - lenses["00 19 10"] = "Zuiko Digital ED 12-40mm f/2.8 Pro"; - lenses["00 20 00"] = "Zuiko Digital 35mm f/3.5 Macro"; - lenses["00 22 00"] = "Zuiko Digital 17.5-45mm f/3.5-5.6"; - lenses["00 23 00"] = "Zuiko Digital ED 14-42mm f/3.5-5.6"; - lenses["00 24 00"] = "Zuiko Digital ED 40-150mm f/4-5.6"; - lenses["00 30 00"] = "Zuiko Digital ED 50-200mm f/2.8-3.5 SWD"; - lenses["00 31 00"] = "Zuiko Digital ED 12-60mm f/2.8-4 SWD"; - lenses["00 32 00"] = "Zuiko Digital ED 14-35mm f/2 SWD"; - lenses["00 33 00"] = "Zuiko Digital 25mm f/2.8"; - lenses["00 34 00"] = "Zuiko Digital ED 9-18mm f/4-5.6"; - lenses["00 35 00"] = "Zuiko Digital 14-54mm f/2.8-3.5 II"; - lenses["01 01 00"] = "Sigma 18-50mm f/3.5-5.6 DC"; - lenses["01 01 10"] = "Sigma 30mm f/2.8 EX DN"; - lenses["01 02 00"] = "Sigma 55-200mm f/4-5.6 DC"; - lenses["01 02 10"] = "Sigma 19mm f/2.8 EX DN"; - lenses["01 03 00"] = "Sigma 18-125mm f/3.5-5.6 DC"; - lenses["01 03 10"] = "Sigma 30mm f/2.8 DN | A"; - lenses["01 04 00"] = "Sigma 18-125mm f/3.5-5.6 DC"; - lenses["01 04 10"] = "Sigma 19mm f/2.8 DN | A"; - lenses["01 05 00"] = "Sigma 30mm f/1.4 EX DC HSM"; - lenses["01 05 10"] = "Sigma 60mm f/2.8 DN | A"; - lenses["01 06 00"] = "Sigma 50-500mm f/4-6.3 EX DG APO HSM RF"; - lenses["01 07 00"] = "Sigma 105mm f/2.8 EX DG Macro"; - lenses["01 08 00"] = "Sigma 150mm f/2.8 EX DG APO HSM Macro"; - lenses["01 09 00"] = "Sigma 18-50mm f/2.8 EX DC Macro"; - lenses["01 10 00"] = "Sigma 24mm f/1.8 EX DG Aspherical Macro"; - lenses["01 11 00"] = "Sigma 135-400mm f/4.5-5.6 DG APO"; - lenses["01 12 00"] = "Sigma 300-800mm f/5.6 EX DG APO HSM"; - lenses["01 13 00"] = "Sigma 30mm f/1.4 EX DC HSM"; - lenses["01 14 00"] = "Sigma 50-500mm f/4-6.3 EX DG APO HSM"; - lenses["01 15 00"] = "Sigma 10-20mm f/4-5.6 EX DC HSM"; - lenses["01 16 00"] = "Sigma 70-200mm f/2.8 II EX DG APO HSM Macro"; - lenses["01 17 00"] = "Sigma 50mm f/1.4 EX DG HSM"; - lenses["02 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph."; - lenses["02 01 10"] = "Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS"; - lenses["02 02 00"] = "Leica D Summilux 25mm f/1.4 Asph."; - lenses["02 02 10"] = "Lumix G Vario 45-200mm f/4-5.6 Mega OIS"; - lenses["02 03 00"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph. Mega OIS"; - lenses["02 03 01"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph."; - lenses["02 03 10"] = "Lumix G Vario HD 14-140mm f/4-5.8 Asph. Mega OIS"; - lenses["02 04 00"] = "Leica D Vario Elmar 14-150mm f/3.5-5.6"; - lenses["02 04 10"] = "Lumix G Vario 7-14mm f/4 Asph."; - lenses["02 05 10"] = "Lumix G 20mm f/1.7 Asph."; - lenses["02 06 10"] = "Leica DG Macro-Elmarit 45mm f/2.8 Asph. Mega OIS"; - lenses["02 07 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 Asph. Mega OIS"; - lenses["02 08 10"] = "Lumix G Fisheye 8mm f/3.5"; - lenses["02 09 10"] = "Lumix G Vario 100-300mm f/4-5.6 Mega OIS"; - lenses["02 10 10"] = "Lumix G 14mm f/2.5 Asph."; - lenses["02 11 10"] = "Lumix G 12.5mm f/12 3D"; - lenses["02 12 10"] = "Leica DG Summilux 25mm f/1.4 Asph."; - lenses["02 13 10"] = "Lumix G X Vario PZ 45-175mm f/4-5.6 Asph. Power OIS"; - lenses["02 14 10"] = "Lumix G X Vario PZ 14-42mm f/3.5-5.6 Asph. Power OIS"; - lenses["02 15 10"] = "Lumix G X Vario 12-35mm f/2.8 Asph. Power OIS"; - lenses["02 16 10"] = "Lumix G Vario 45-150mm f/4-5.6 Asph. Mega OIS"; - lenses["02 17 10"] = "Lumix G X Vario 35-100mm f/2.8 Power OIS"; - lenses["02 18 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 II Asph. Mega OIS"; - lenses["02 19 10"] = "Lumix G Vario 14-140mm f/3.5-5.6 Asph. Power OIS"; - lenses["03 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph."; - lenses["03 02 00"] = "Leica D Summilux 25mm f/1.4 Asph."; - } - virtual std::string toString (Tag* t) { - std::ostringstream lid; - lid.setf (std::ios_base::hex, std::ios_base::basefield); - lid.setf (std::ios_base::uppercase); - lid << std::setw(2) << std::setfill('0') << t->toInt(0)<< ' '; //maker - lid << std::setw(2) << std::setfill('0') << t->toInt(2)<< ' '; //model - lid << std::setw(2) << std::setfill('0') << t->toInt(3); // submodel +class OLLensTypeInterpreter : public Interpreter +{ + std::map lenses; +public: + OLLensTypeInterpreter () // From EXIFTOOL database 'Olympus.pm' V2.09 + { + // exadecimal bytes + lenses["00 01 00"] = "Zuiko Digital ED 50mm f/2 Macro"; + lenses["00 01 01"] = "Zuiko Digital 40-150mm f/3.5-4.5"; + lenses["00 01 10"] = "Zuiko Digital ED 14-42mm f/3.5-5.6"; + lenses["00 02 00"] = "Zuiko Digital ED 150mm f/2"; + lenses["00 02 10"] = "Zuiko Digital 17mm f/2.8 Pancake"; + lenses["00 03 00"] = "Zuiko Digital ED 300mm f/2.8"; + lenses["00 03 10"] = "Zuiko Digital ED 14-150mm f/4-5.6"; + lenses["00 04 10"] = "Zuiko Digital ED 9-18mm f/4-5.6"; + lenses["00 05 00"] = "Zuiko Digital 14-54mm f/2.8-3.5"; + lenses["00 05 01"] = "Zuiko Digital Pro ED 90-250mm f/2.8"; + lenses["00 05 10"] = "Zuiko Digital ED 14-42mm f/3.5-5.6 L"; + lenses["00 06 00"] = "Zuiko Digital ED 50-200mm f/2.8-3.5"; + lenses["00 06 01"] = "Zuiko Digital ED 8mm f/3.5 Fisheye"; + lenses["00 06 10"] = "Zuiko Digital ED 40-150mm f/4-5.6"; + lenses["00 07 00"] = "Zuiko Digital 11-22mm f/2.8-3.5"; + lenses["00 07 01"] = "Zuiko Digital 18-180mm f/3.5-6.3"; + lenses["00 07 10"] = "Zuiko Digital ED 12mm f/2"; + lenses["00 08 01"] = "Zuiko Digital 70-300mm f/4-5.6"; + lenses["00 08 10"] = "Zuiko Digital ED 75-300mm f/4.8-6.7"; + lenses["00 09 10"] = "Zuiko Digital 14-42mm f/3.5-5.6 II"; + lenses["00 10 01"] = "Kenko Tokina Reflex 300mm f/6.3 MF Macro"; + lenses["00 10 10"] = "Zuiko Digital ED 12-50mm f/3.5-6.3 EZ"; + lenses["00 11 10"] = "Zuiko Digital 45mm f/1.8"; + lenses["00 12 10"] = "Zuiko Digital ED 60mm f/2.8 Macro"; + lenses["00 13 10"] = "Zuiko Digital ED 14-42mm f/3.5-5.6 II R"; + lenses["00 14 10"] = "Zuiko Digital ED 40-150mm f/4-5.6 R"; + lenses["00 15 00"] = "Zuiko Digital ED 7-14mm f/4"; + lenses["00 15 10"] = "Zuiko Digital ED 75mm f/1.8"; + lenses["00 16 10"] = "Zuiko Digital 17mm f/1.8"; + lenses["00 17 00"] = "Zuiko Digital Pro ED 35-100mm f/2"; + lenses["00 18 00"] = "Zuiko Digital 14-45mm f/3.5-5.6"; + lenses["00 18 10"] = "Zuiko Digital ED 75-300mm f/4.8-6.7 II"; + lenses["00 19 10"] = "Zuiko Digital ED 12-40mm f/2.8 Pro"; + lenses["00 20 00"] = "Zuiko Digital 35mm f/3.5 Macro"; + lenses["00 22 00"] = "Zuiko Digital 17.5-45mm f/3.5-5.6"; + lenses["00 23 00"] = "Zuiko Digital ED 14-42mm f/3.5-5.6"; + lenses["00 24 00"] = "Zuiko Digital ED 40-150mm f/4-5.6"; + lenses["00 30 00"] = "Zuiko Digital ED 50-200mm f/2.8-3.5 SWD"; + lenses["00 31 00"] = "Zuiko Digital ED 12-60mm f/2.8-4 SWD"; + lenses["00 32 00"] = "Zuiko Digital ED 14-35mm f/2 SWD"; + lenses["00 33 00"] = "Zuiko Digital 25mm f/2.8"; + lenses["00 34 00"] = "Zuiko Digital ED 9-18mm f/4-5.6"; + lenses["00 35 00"] = "Zuiko Digital 14-54mm f/2.8-3.5 II"; + lenses["01 01 00"] = "Sigma 18-50mm f/3.5-5.6 DC"; + lenses["01 01 10"] = "Sigma 30mm f/2.8 EX DN"; + lenses["01 02 00"] = "Sigma 55-200mm f/4-5.6 DC"; + lenses["01 02 10"] = "Sigma 19mm f/2.8 EX DN"; + lenses["01 03 00"] = "Sigma 18-125mm f/3.5-5.6 DC"; + lenses["01 03 10"] = "Sigma 30mm f/2.8 DN | A"; + lenses["01 04 00"] = "Sigma 18-125mm f/3.5-5.6 DC"; + lenses["01 04 10"] = "Sigma 19mm f/2.8 DN | A"; + lenses["01 05 00"] = "Sigma 30mm f/1.4 EX DC HSM"; + lenses["01 05 10"] = "Sigma 60mm f/2.8 DN | A"; + lenses["01 06 00"] = "Sigma 50-500mm f/4-6.3 EX DG APO HSM RF"; + lenses["01 07 00"] = "Sigma 105mm f/2.8 EX DG Macro"; + lenses["01 08 00"] = "Sigma 150mm f/2.8 EX DG APO HSM Macro"; + lenses["01 09 00"] = "Sigma 18-50mm f/2.8 EX DC Macro"; + lenses["01 10 00"] = "Sigma 24mm f/1.8 EX DG Aspherical Macro"; + lenses["01 11 00"] = "Sigma 135-400mm f/4.5-5.6 DG APO"; + lenses["01 12 00"] = "Sigma 300-800mm f/5.6 EX DG APO HSM"; + lenses["01 13 00"] = "Sigma 30mm f/1.4 EX DC HSM"; + lenses["01 14 00"] = "Sigma 50-500mm f/4-6.3 EX DG APO HSM"; + lenses["01 15 00"] = "Sigma 10-20mm f/4-5.6 EX DC HSM"; + lenses["01 16 00"] = "Sigma 70-200mm f/2.8 II EX DG APO HSM Macro"; + lenses["01 17 00"] = "Sigma 50mm f/1.4 EX DG HSM"; + lenses["02 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph."; + lenses["02 01 10"] = "Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS"; + lenses["02 02 00"] = "Leica D Summilux 25mm f/1.4 Asph."; + lenses["02 02 10"] = "Lumix G Vario 45-200mm f/4-5.6 Mega OIS"; + lenses["02 03 00"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph. Mega OIS"; + lenses["02 03 01"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph."; + lenses["02 03 10"] = "Lumix G Vario HD 14-140mm f/4-5.8 Asph. Mega OIS"; + lenses["02 04 00"] = "Leica D Vario Elmar 14-150mm f/3.5-5.6"; + lenses["02 04 10"] = "Lumix G Vario 7-14mm f/4 Asph."; + lenses["02 05 10"] = "Lumix G 20mm f/1.7 Asph."; + lenses["02 06 10"] = "Leica DG Macro-Elmarit 45mm f/2.8 Asph. Mega OIS"; + lenses["02 07 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 Asph. Mega OIS"; + lenses["02 08 10"] = "Lumix G Fisheye 8mm f/3.5"; + lenses["02 09 10"] = "Lumix G Vario 100-300mm f/4-5.6 Mega OIS"; + lenses["02 10 10"] = "Lumix G 14mm f/2.5 Asph."; + lenses["02 11 10"] = "Lumix G 12.5mm f/12 3D"; + lenses["02 12 10"] = "Leica DG Summilux 25mm f/1.4 Asph."; + lenses["02 13 10"] = "Lumix G X Vario PZ 45-175mm f/4-5.6 Asph. Power OIS"; + lenses["02 14 10"] = "Lumix G X Vario PZ 14-42mm f/3.5-5.6 Asph. Power OIS"; + lenses["02 15 10"] = "Lumix G X Vario 12-35mm f/2.8 Asph. Power OIS"; + lenses["02 16 10"] = "Lumix G Vario 45-150mm f/4-5.6 Asph. Mega OIS"; + lenses["02 17 10"] = "Lumix G X Vario 35-100mm f/2.8 Power OIS"; + lenses["02 18 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 II Asph. Mega OIS"; + lenses["02 19 10"] = "Lumix G Vario 14-140mm f/3.5-5.6 Asph. Power OIS"; + lenses["03 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph."; + lenses["03 02 00"] = "Leica D Summilux 25mm f/1.4 Asph."; + } + virtual std::string toString (Tag* t) + { + std::ostringstream lid; + lid.setf (std::ios_base::hex, std::ios_base::basefield); + lid.setf (std::ios_base::uppercase); + lid << std::setw(2) << std::setfill('0') << t->toInt(0) << ' '; //maker + lid << std::setw(2) << std::setfill('0') << t->toInt(2) << ' '; //model + lid << std::setw(2) << std::setfill('0') << t->toInt(3); // submodel - std::map::iterator r = lenses.find (lid.str()); - if (r!=lenses.end()) - return r->second; - else - return "Unknown"; + std::map::iterator r = lenses.find (lid.str()); + + if (r != lenses.end()) { + return r->second; + } else { + return "Unknown"; } + } }; -OLLensTypeInterpreter olLensTypeInterpreter; +OLLensTypeInterpreter olLensTypeInterpreter; -class OLFlashTypeInterpreter : public ChoiceInterpreter { - public: - OLFlashTypeInterpreter () { - choices[0] = "None"; - choices[2] = "Simple E-System"; - choices[3] = "E-System"; - } +class OLFlashTypeInterpreter : public ChoiceInterpreter +{ +public: + OLFlashTypeInterpreter () + { + choices[0] = "None"; + choices[2] = "Simple E-System"; + choices[3] = "E-System"; + } }; OLFlashTypeInterpreter olFlashTypeInterpreter; -class OLExposureModeInterpreter : public ChoiceInterpreter { - public: - OLExposureModeInterpreter () { - choices[1] = "Manual"; - choices[2] = "Program"; - choices[3] = "Aperture-priority AE"; - choices[4] = "Shutter speed priority AE"; - choices[5] = "Program-shift"; - } +class OLExposureModeInterpreter : public ChoiceInterpreter +{ +public: + OLExposureModeInterpreter () + { + choices[1] = "Manual"; + choices[2] = "Program"; + choices[3] = "Aperture-priority AE"; + choices[4] = "Shutter speed priority AE"; + choices[5] = "Program-shift"; + } }; OLExposureModeInterpreter olExposureModeInterpreter; -class OLMeteringModeInterpreter : public ChoiceInterpreter { - public: - OLMeteringModeInterpreter () { - choices[2] = "Center-weighted average"; - choices[3] = "Spot"; - choices[5] = "ESP"; - choices[261] = "Pattern+AF"; - choices[515] = "Spot+Highlight control"; - choices[1027] = "Spot+Shadow control"; - } +class OLMeteringModeInterpreter : public ChoiceInterpreter +{ +public: + OLMeteringModeInterpreter () + { + choices[2] = "Center-weighted average"; + choices[3] = "Spot"; + choices[5] = "ESP"; + choices[261] = "Pattern+AF"; + choices[515] = "Spot+Highlight control"; + choices[1027] = "Spot+Shadow control"; + } }; OLMeteringModeInterpreter olMeteringModeInterpreter; -class OLFocusModeInterpreter : public ChoiceInterpreter { - public: - OLFocusModeInterpreter () { - choices[0] = "Single AF"; - choices[1] = "Sequential shooting AF"; - choices[2] = "Continuous AF"; - choices[3] = "Multi AF"; - choices[10] = "MF"; - } +class OLFocusModeInterpreter : public ChoiceInterpreter +{ +public: + OLFocusModeInterpreter () + { + choices[0] = "Single AF"; + choices[1] = "Sequential shooting AF"; + choices[2] = "Continuous AF"; + choices[3] = "Multi AF"; + choices[10] = "MF"; + } }; OLFocusModeInterpreter olFocusModeInterpreter; -class OLWhitebalance2Interpreter : public ChoiceInterpreter { - public: - OLWhitebalance2Interpreter () { - choices[0] = "Auto"; - choices[16] = "7500K (Fine Weather with Shade)"; - choices[17] = "6000K (Cloudy)"; - choices[18] = "5300K (Fine Weather)"; - choices[20] = "3000K (Tungsten light)"; - choices[21] = "3600K (Tungsten light-like)"; - choices[33] = "6600K (Daylight fluorescent)"; - choices[34] = "4500K (Neutral white fluorescent)"; - choices[35] = "4000K (Cool white fluorescent)"; - choices[48] = "3600K (Tungsten light-like)"; - choices[256] = "Custom WB 1"; - choices[257] = "Custom WB 2"; - choices[258] = "Custom WB 3"; - choices[259] = "Custom WB 4"; - choices[512] = "Custom WB 5400K"; - choices[513] = "Custom WB 2900K"; - choices[514] = "Custom WB 8000K"; - } +class OLWhitebalance2Interpreter : public ChoiceInterpreter +{ +public: + OLWhitebalance2Interpreter () + { + choices[0] = "Auto"; + choices[16] = "7500K (Fine Weather with Shade)"; + choices[17] = "6000K (Cloudy)"; + choices[18] = "5300K (Fine Weather)"; + choices[20] = "3000K (Tungsten light)"; + choices[21] = "3600K (Tungsten light-like)"; + choices[33] = "6600K (Daylight fluorescent)"; + choices[34] = "4500K (Neutral white fluorescent)"; + choices[35] = "4000K (Cool white fluorescent)"; + choices[48] = "3600K (Tungsten light-like)"; + choices[256] = "Custom WB 1"; + choices[257] = "Custom WB 2"; + choices[258] = "Custom WB 3"; + choices[259] = "Custom WB 4"; + choices[512] = "Custom WB 5400K"; + choices[513] = "Custom WB 2900K"; + choices[514] = "Custom WB 8000K"; + } }; OLWhitebalance2Interpreter olWhitebalance2Interpreter; -class OLSceneModeInterpreter : public ChoiceInterpreter { - public: - OLSceneModeInterpreter () { - choices[0] = "Standard"; - choices[6] = "Auto"; - choices[7] = "Sport"; - choices[8] = "Portrait"; - choices[9] = "Landscape+Portrait"; - choices[10] = "Landscape"; - choices[11] = "Night Scene"; - choices[12] = "Self Portrait"; - choices[13] = "Panorama"; - choices[14] = "2 in 1"; - choices[15] = "Movie"; - choices[16] = "Landscape+Portrait"; - choices[17] = "Night+Portrait"; - choices[18] = "Indoor"; - choices[19] = "Fireworks"; - choices[20] = "Sunset"; - choices[22] = "Macro"; - choices[23] = "Super Macro"; - choices[24] = "Food"; - choices[25] = "Documents"; - choices[26] = "Museum"; - choices[27] = "Shoot & Select"; - choices[28] = "Beach & Snow"; - choices[29] = "Self Protrait+Timer"; - choices[30] = "Candle"; - choices[31] = "Available Light"; - choices[32] = "Behind Glass"; - choices[33] = "My Mode"; - choices[34] = "Pet"; - choices[35] = "Underwater Wide1"; - choices[36] = "Underwater Macro"; - choices[37] = "Shoot & Select1"; - choices[38] = "Shoot & Select2"; - choices[39] = "High Key"; - choices[40] = "Digital Image Stabilization"; - choices[41] = "Auction"; - choices[42] = "Beach"; - choices[43] = "Snow"; - choices[44] = "Underwater Wide2"; - choices[45] = "Low Key"; - choices[46] = "Children"; - choices[47] = "Vivid"; - choices[48] = "Nature Macro"; - choices[49] = "Underwater Snapshot"; - choices[50] = "Shooting Guide"; - } +class OLSceneModeInterpreter : public ChoiceInterpreter +{ +public: + OLSceneModeInterpreter () + { + choices[0] = "Standard"; + choices[6] = "Auto"; + choices[7] = "Sport"; + choices[8] = "Portrait"; + choices[9] = "Landscape+Portrait"; + choices[10] = "Landscape"; + choices[11] = "Night Scene"; + choices[12] = "Self Portrait"; + choices[13] = "Panorama"; + choices[14] = "2 in 1"; + choices[15] = "Movie"; + choices[16] = "Landscape+Portrait"; + choices[17] = "Night+Portrait"; + choices[18] = "Indoor"; + choices[19] = "Fireworks"; + choices[20] = "Sunset"; + choices[22] = "Macro"; + choices[23] = "Super Macro"; + choices[24] = "Food"; + choices[25] = "Documents"; + choices[26] = "Museum"; + choices[27] = "Shoot & Select"; + choices[28] = "Beach & Snow"; + choices[29] = "Self Protrait+Timer"; + choices[30] = "Candle"; + choices[31] = "Available Light"; + choices[32] = "Behind Glass"; + choices[33] = "My Mode"; + choices[34] = "Pet"; + choices[35] = "Underwater Wide1"; + choices[36] = "Underwater Macro"; + choices[37] = "Shoot & Select1"; + choices[38] = "Shoot & Select2"; + choices[39] = "High Key"; + choices[40] = "Digital Image Stabilization"; + choices[41] = "Auction"; + choices[42] = "Beach"; + choices[43] = "Snow"; + choices[44] = "Underwater Wide2"; + choices[45] = "Low Key"; + choices[46] = "Children"; + choices[47] = "Vivid"; + choices[48] = "Nature Macro"; + choices[49] = "Underwater Snapshot"; + choices[50] = "Shooting Guide"; + } }; OLSceneModeInterpreter olSceneModeInterpreter; -class OLPictureModeBWFilterInterpreter : public ChoiceInterpreter { - public: - OLPictureModeBWFilterInterpreter () { - choices[0] = "n/a"; - choices[1] = "Neutral"; - choices[2] = "Yellow"; - choices[3] = "Orange"; - choices[4] = "Red"; - choices[5] = "Green"; - } +class OLPictureModeBWFilterInterpreter : public ChoiceInterpreter +{ +public: + OLPictureModeBWFilterInterpreter () + { + choices[0] = "n/a"; + choices[1] = "Neutral"; + choices[2] = "Yellow"; + choices[3] = "Orange"; + choices[4] = "Red"; + choices[5] = "Green"; + } }; OLPictureModeBWFilterInterpreter olPictureModeBWFilterInterpreter; -class OLPictureModeToneInterpreter : public ChoiceInterpreter { - public: - OLPictureModeToneInterpreter () { - choices[0] = "n/a"; - choices[1] = "Neutral"; - choices[2] = "Sepia"; - choices[3] = "Blue"; - choices[4] = "Purple"; - choices[5] = "Green"; - } +class OLPictureModeToneInterpreter : public ChoiceInterpreter +{ +public: + OLPictureModeToneInterpreter () + { + choices[0] = "n/a"; + choices[1] = "Neutral"; + choices[2] = "Sepia"; + choices[3] = "Blue"; + choices[4] = "Purple"; + choices[5] = "Green"; + } }; OLPictureModeToneInterpreter olPictureModeToneInterpreter; -class OLImageQuality2Interpreter : public ChoiceInterpreter { - public: - OLImageQuality2Interpreter () { - choices[1] = "SQ"; - choices[2] = "HQ"; - choices[3] = "SHQ"; - choices[4] = "RAW"; - } +class OLImageQuality2Interpreter : public ChoiceInterpreter +{ +public: + OLImageQuality2Interpreter () + { + choices[1] = "SQ"; + choices[2] = "HQ"; + choices[3] = "SHQ"; + choices[4] = "RAW"; + } }; OLImageQuality2Interpreter olImageQuality2Interpreter; -class OLDevEngineInterpreter : public ChoiceInterpreter { - public: - OLDevEngineInterpreter () { - choices[0] = "High Speed"; - choices[1] = "High Function"; - choices[2] = "Advanced High Speed"; - choices[3] = "Advanced High Function"; - } +class OLDevEngineInterpreter : public ChoiceInterpreter +{ +public: + OLDevEngineInterpreter () + { + choices[0] = "High Speed"; + choices[1] = "High Function"; + choices[2] = "Advanced High Speed"; + choices[3] = "Advanced High Function"; + } }; OLDevEngineInterpreter olDevEngineInterpreter; -class OLPictureModeInterpreter : public ChoiceInterpreter { - public: - OLPictureModeInterpreter () { - choices[1] = "Vivid"; - choices[2] = "Natural"; - choices[3] = "Muted"; - choices[4] = "Portrait"; - choices[256] = "Monotone"; - choices[512] = "Sepia"; - } +class OLPictureModeInterpreter : public ChoiceInterpreter +{ +public: + OLPictureModeInterpreter () + { + choices[1] = "Vivid"; + choices[2] = "Natural"; + choices[3] = "Muted"; + choices[4] = "Portrait"; + choices[256] = "Monotone"; + choices[512] = "Sepia"; + } }; OLPictureModeInterpreter olPictureModeInterpreter; -class OLColorSpaceInterpreter : public ChoiceInterpreter { - public: - OLColorSpaceInterpreter () { - choices[0] = "sRGB"; - choices[1] = "Adobe RGB"; - choices[2] = "Pro Photo RGB"; - } +class OLColorSpaceInterpreter : public ChoiceInterpreter +{ +public: + OLColorSpaceInterpreter () + { + choices[0] = "sRGB"; + choices[1] = "Adobe RGB"; + choices[2] = "Pro Photo RGB"; + } }; OLColorSpaceInterpreter olColorSpaceInterpreter; -class OLNoiseFilterInterpreter : public Interpreter { - public: - OLNoiseFilterInterpreter () {} - virtual std::string toString (Tag* t) { - int a = t->toInt (0); - int b = t->toInt (2); - int c = t->toInt (4); - if (a==-1 && b==-2 && c==1) - return "Low"; - else if (a==-2 && b==-2 && c==1) - return "Off"; - else if (a==0 && b==-2 && c==1) - return "Standard"; - else if (a==1 && b==-2 && c==1) - return "High"; - else return "Unknown"; +class OLNoiseFilterInterpreter : public Interpreter +{ +public: + OLNoiseFilterInterpreter () {} + virtual std::string toString (Tag* t) + { + int a = t->toInt (0); + int b = t->toInt (2); + int c = t->toInt (4); + + if (a == -1 && b == -2 && c == 1) { + return "Low"; + } else if (a == -2 && b == -2 && c == 1) { + return "Off"; + } else if (a == 0 && b == -2 && c == 1) { + return "Standard"; + } else if (a == 1 && b == -2 && c == 1) { + return "High"; + } else { + return "Unknown"; } + } }; OLNoiseFilterInterpreter olNoiseFilterInterpreter; -class OLFlashModeInterpreter : public Interpreter { - public: - OLFlashModeInterpreter () {} - virtual std::string toString (Tag* t) { - std::ostringstream str; - int a = t->toInt (); - str << "Flash Used = " << ((a&1) ? "Yes" : "No") << std::endl; - str << "Fill-in = " << ((a&2) ? "On" : "Off") << std::endl; - str << "Red-eye = " << ((a&4) ? "On" : "Off") << std::endl; - str << "Slow-sync = " << ((a&8) ? "On" : "Off") << std::endl; - str << "Forced On = " << ((a&16) ? "On" : "Off") << std::endl; - str << "2nd Curtain = " << ((a&32) ? "On" : "Off"); - return str.str(); - } +class OLFlashModeInterpreter : public Interpreter +{ +public: + OLFlashModeInterpreter () {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + int a = t->toInt (); + str << "Flash Used = " << ((a & 1) ? "Yes" : "No") << std::endl; + str << "Fill-in = " << ((a & 2) ? "On" : "Off") << std::endl; + str << "Red-eye = " << ((a & 4) ? "On" : "Off") << std::endl; + str << "Slow-sync = " << ((a & 8) ? "On" : "Off") << std::endl; + str << "Forced On = " << ((a & 16) ? "On" : "Off") << std::endl; + str << "2nd Curtain = " << ((a & 32) ? "On" : "Off"); + return str.str(); + } }; OLFlashModeInterpreter olFlashModeInterpreter; -class OLNoiseReductionInterpreter : public Interpreter { - public: - OLNoiseReductionInterpreter () {} - virtual std::string toString (Tag* t) { - std::ostringstream str; - int a = t->toInt (); - str << "Noise Reduction = " << ((a&1) ? "On" : "Off") << std::endl; - str << "Noise Filter = " << ((a&2) ? "On" : "Off") << std::endl; - str << "Noise Filter (ISO Boost) = " << ((a&4) ? "On" : "Off"); - return str.str(); - } +class OLNoiseReductionInterpreter : public Interpreter +{ +public: + OLNoiseReductionInterpreter () {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + int a = t->toInt (); + str << "Noise Reduction = " << ((a & 1) ? "On" : "Off") << std::endl; + str << "Noise Filter = " << ((a & 2) ? "On" : "Off") << std::endl; + str << "Noise Filter (ISO Boost) = " << ((a & 4) ? "On" : "Off"); + return str.str(); + } }; OLNoiseReductionInterpreter olNoiseReductionInterpreter; -class OLFlashModelInterpreter : public ChoiceInterpreter { - public: - OLFlashModelInterpreter () { - choices[0] = "None"; - choices[1] = "FL-20"; - choices[2] = "FL-50"; - choices[3] = "RF-11"; - choices[4] = "TF-22"; - choices[5] = "FL-36"; - choices[6] = "FL-50R"; - choices[7] = "FL-36R"; - } +class OLFlashModelInterpreter : public ChoiceInterpreter +{ +public: + OLFlashModelInterpreter () + { + choices[0] = "None"; + choices[1] = "FL-20"; + choices[2] = "FL-50"; + choices[3] = "RF-11"; + choices[4] = "TF-22"; + choices[5] = "FL-36"; + choices[6] = "FL-50R"; + choices[7] = "FL-36R"; + } }; OLFlashModelInterpreter olFlashModelInterpreter; const TagAttrib olyFocusInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "FocusInfoVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0209, AUTO, "AutoFocus", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0210, AUTO, "SceneDetect", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0211, AUTO, "SceneArea", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0212, AUTO, "SceneDetectData", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0300, AUTO, "ZoomStepCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0301, AUTO, "FocusStepCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0303, AUTO, "FocusStepInfinity", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0304, AUTO, "FocusStepNear", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0305, AUTO, "FocusDistance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0308, AUTO, "AFPoint", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1201, AUTO, "ExternalFlash", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1203, AUTO, "ExternalFlashGuideNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1204, AUTO, "ExternalFlashBounce", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1205, AUTO, "ExternalFlashZoom", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1208, AUTO, "InternalFlash", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1209, AUTO, "ManualFlash", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1500, AUTO, "SensorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1600, AUTO, "ImageStabilization", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "FocusInfoVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0209, AUTO, "AutoFocus", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0210, AUTO, "SceneDetect", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0211, AUTO, "SceneArea", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0212, AUTO, "SceneDetectData", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0300, AUTO, "ZoomStepCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0301, AUTO, "FocusStepCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0303, AUTO, "FocusStepInfinity", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0304, AUTO, "FocusStepNear", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0305, AUTO, "FocusDistance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0308, AUTO, "AFPoint", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1201, AUTO, "ExternalFlash", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1203, AUTO, "ExternalFlashGuideNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1204, AUTO, "ExternalFlashBounce", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1205, AUTO, "ExternalFlashZoom", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1208, AUTO, "InternalFlash", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1209, AUTO, "ManualFlash", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1500, AUTO, "SensorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1600, AUTO, "ImageStabilization", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib olyImageProcessingAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "ImageProcessingVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0100, AUTO, "WB_RBLevels", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0102, AUTO, "WB_RBLevels3000K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0103, AUTO, "WB_RBLevels3300K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "WB_RBLevels3600K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0105, AUTO, "WB_RBLevels3900K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0106, AUTO, "WB_RBLevels4000K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0107, AUTO, "WB_RBLevels4300K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0108, AUTO, "WB_RBLevels4500K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0109, AUTO, "WB_RBLevels4800K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010a, AUTO, "WB_RBLevels5300K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010b, AUTO, "WB_RBLevels6000K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010c, AUTO, "WB_RBLevels6600K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010d, AUTO, "WB_RBLevels7500K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010e, AUTO, "WB_RBLevelsCWB1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010f, AUTO, "WB_RBLevelsCWB2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0110, AUTO, "WB_RBLevelsCWB3", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0111, AUTO, "WB_RBLevelsCWB4", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0113, AUTO, "WB_GLevel3000K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0114, AUTO, "WB_GLevel3300K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0115, AUTO, "WB_GLevel3600K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0116, AUTO, "WB_GLevel3900K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0117, AUTO, "WB_GLevel4000K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0118, AUTO, "WB_GLevel4300K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0119, AUTO, "WB_GLevel4500K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x011a, AUTO, "WB_GLevel4800K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x011b, AUTO, "WB_GLevel5300K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x011c, AUTO, "WB_GLevel6000K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x011d, AUTO, "WB_GLevel6600K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x011e, AUTO, "WB_GLevel7500K", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x011f, AUTO, "WB_GLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0200, AUTO, "ColorMatrix", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0300, AUTO, "Enhancer", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0301, AUTO, "EnhancerValues", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0310, AUTO, "CoringFilter", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0311, AUTO, "CoringValues", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0600, AUTO, "BlackLevel2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0610, AUTO, "GainBase", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0611, AUTO, "ValidBits", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0612, AUTO, "CropLeft", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0613, AUTO, "CropTop", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0614, AUTO, "CropWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0615, AUTO, "CropHeight", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1010, AUTO, "NoiseReduction2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1011, AUTO, "DistortionCorrection2", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1012, AUTO, "ShadingCompensation2", &olOnOffInterpreter}, - {1, AC_WRITE, 0, 0, 0x1103, AUTO, "UnknownBlock", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1200, AUTO, "FaceDetect", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x1201, AUTO, "FaceDetectArea", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "ImageProcessingVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0100, AUTO, "WB_RBLevels", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0102, AUTO, "WB_RBLevels3000K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0103, AUTO, "WB_RBLevels3300K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "WB_RBLevels3600K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0105, AUTO, "WB_RBLevels3900K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0106, AUTO, "WB_RBLevels4000K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0107, AUTO, "WB_RBLevels4300K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0108, AUTO, "WB_RBLevels4500K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0109, AUTO, "WB_RBLevels4800K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010a, AUTO, "WB_RBLevels5300K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010b, AUTO, "WB_RBLevels6000K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010c, AUTO, "WB_RBLevels6600K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010d, AUTO, "WB_RBLevels7500K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010e, AUTO, "WB_RBLevelsCWB1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010f, AUTO, "WB_RBLevelsCWB2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0110, AUTO, "WB_RBLevelsCWB3", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0111, AUTO, "WB_RBLevelsCWB4", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0113, AUTO, "WB_GLevel3000K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0114, AUTO, "WB_GLevel3300K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0115, AUTO, "WB_GLevel3600K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0116, AUTO, "WB_GLevel3900K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0117, AUTO, "WB_GLevel4000K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0118, AUTO, "WB_GLevel4300K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0119, AUTO, "WB_GLevel4500K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x011a, AUTO, "WB_GLevel4800K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x011b, AUTO, "WB_GLevel5300K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x011c, AUTO, "WB_GLevel6000K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x011d, AUTO, "WB_GLevel6600K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x011e, AUTO, "WB_GLevel7500K", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x011f, AUTO, "WB_GLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0200, AUTO, "ColorMatrix", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0300, AUTO, "Enhancer", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0301, AUTO, "EnhancerValues", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0310, AUTO, "CoringFilter", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0311, AUTO, "CoringValues", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0600, AUTO, "BlackLevel2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0610, AUTO, "GainBase", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0611, AUTO, "ValidBits", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0612, AUTO, "CropLeft", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0613, AUTO, "CropTop", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0614, AUTO, "CropWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0615, AUTO, "CropHeight", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1010, AUTO, "NoiseReduction2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1011, AUTO, "DistortionCorrection2", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1012, AUTO, "ShadingCompensation2", &olOnOffInterpreter}, + {1, AC_WRITE, 0, 0, 0x1103, AUTO, "UnknownBlock", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1200, AUTO, "FaceDetect", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x1201, AUTO, "FaceDetectArea", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib olyRawDevelopmentAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "RawDevVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0101, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0102, AUTO, "RawDevWBFineAdjustment", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0103, AUTO, "RawDevGrayPoint", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "RawDevSaturationEmphasis", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0105, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0106, AUTO, "RawDevContrastValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0107, AUTO, "RawDevSharpnessValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0108, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter}, - {0, AC_WRITE, 0, 0, 0x0109, AUTO, "RawDevEngine", &olDevEngineInterpreter}, - {0, AC_WRITE, 0, 0, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter}, - {0, AC_WRITE, 0, 0, 0x010b, AUTO, "RawDevEditStatus", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010c, AUTO, "RawDevSettings", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "RawDevVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0101, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0102, AUTO, "RawDevWBFineAdjustment", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0103, AUTO, "RawDevGrayPoint", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "RawDevSaturationEmphasis", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0105, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0106, AUTO, "RawDevContrastValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0107, AUTO, "RawDevSharpnessValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0108, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter}, + {0, AC_WRITE, 0, 0, 0x0109, AUTO, "RawDevEngine", &olDevEngineInterpreter}, + {0, AC_WRITE, 0, 0, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter}, + {0, AC_WRITE, 0, 0, 0x010b, AUTO, "RawDevEditStatus", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010c, AUTO, "RawDevSettings", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib olyRawDevelopment2Attribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "RawDevVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0101, AUTO, "RawDevWhiteBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0102, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0103, AUTO, "RawDevWBFineAdjustment", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "RawDevGrayPoint", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0105, AUTO, "RawDevContrastValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0106, AUTO, "RawDevSharpnessValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0107, AUTO, "RawDevSaturationEmphasis", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0108, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0109, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter}, - {0, AC_WRITE, 0, 0, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter}, - {0, AC_WRITE, 0, 0, 0x010b, AUTO, "RawDevEngine", &olDevEngineInterpreter}, - {0, AC_WRITE, 0, 0, 0x010c, AUTO, "RawDevPictureMode", &olPictureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x010d, AUTO, "RawDevPMSaturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010e, AUTO, "RawDevPMContrast", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010f, AUTO, "RawDevPMSharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0110, AUTO, "RawDevPM_BWFilter", &olPictureModeBWFilterInterpreter}, - {0, AC_WRITE, 0, 0, 0x0111, AUTO, "RawDevPMPictureTone", &olPictureModeToneInterpreter}, - {0, AC_WRITE, 0, 0, 0x0112, AUTO, "RawDevGradation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0113, AUTO, "RawDevSaturation3", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0119, AUTO, "RawDevAutoGradation", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0120, AUTO, "RawDevPMNoiseFilter", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "RawDevVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0101, AUTO, "RawDevWhiteBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0102, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0103, AUTO, "RawDevWBFineAdjustment", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "RawDevGrayPoint", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0105, AUTO, "RawDevContrastValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0106, AUTO, "RawDevSharpnessValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0107, AUTO, "RawDevSaturationEmphasis", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0108, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0109, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter}, + {0, AC_WRITE, 0, 0, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter}, + {0, AC_WRITE, 0, 0, 0x010b, AUTO, "RawDevEngine", &olDevEngineInterpreter}, + {0, AC_WRITE, 0, 0, 0x010c, AUTO, "RawDevPictureMode", &olPictureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x010d, AUTO, "RawDevPMSaturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010e, AUTO, "RawDevPMContrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010f, AUTO, "RawDevPMSharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0110, AUTO, "RawDevPM_BWFilter", &olPictureModeBWFilterInterpreter}, + {0, AC_WRITE, 0, 0, 0x0111, AUTO, "RawDevPMPictureTone", &olPictureModeToneInterpreter}, + {0, AC_WRITE, 0, 0, 0x0112, AUTO, "RawDevGradation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0113, AUTO, "RawDevSaturation3", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0119, AUTO, "RawDevAutoGradation", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0120, AUTO, "RawDevPMNoiseFilter", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib olyCameraSettingsAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "CameraSettingsVersion", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0100, AUTO, "PreviewImageValid", &olYesNoInterpreter}, - {1, AC_WRITE, 0, 0, 0x0101, AUTO, "PreviewImageStart", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0102, AUTO, "PreviewImageLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0200, AUTO, "ExposureMode", &olExposureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0201, AUTO, "AELock", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0202, AUTO, "MeteringMode", &olMeteringModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0300, AUTO, "MacroMode", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0301, AUTO, "FocusMode", &olFocusModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0302, AUTO, "FocusProcess", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0303, AUTO, "AFSearch", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0304, AUTO, "AFAreas", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0400, AUTO, "FlashMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0401, AUTO, "FlashExposureComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0500, AUTO, "WhiteBalance2", &olWhitebalance2Interpreter}, - {0, AC_WRITE, 0, 0, 0x0501, AUTO, "WhiteBalanceTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0502, AUTO, "WhiteBalanceBracket", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0503, AUTO, "CustomSaturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0504, AUTO, "ModifiedSaturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0505, AUTO, "ContrastSetting", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0506, AUTO, "SharpnessSetting", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0507, AUTO, "ColorSpace", &olColorSpaceInterpreter}, - {0, AC_WRITE, 0, 0, 0x0509, AUTO, "SceneMode", &olSceneModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x050a, AUTO, "NoiseReduction", &olNoiseReductionInterpreter}, - {0, AC_WRITE, 0, 0, 0x050b, AUTO, "DistortionCorrection", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x050c, AUTO, "ShadingCompensation", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x050d, AUTO, "CompressionFactor", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x050f, AUTO, "Gradation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0520, AUTO, "PictureMode", &olPictureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0521, AUTO, "PictureModeSaturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0522, AUTO, "PictureModeHue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0523, AUTO, "PictureModeContrast", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0524, AUTO, "PictureModeSharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0525, AUTO, "PictureModeBWFilter", &olPictureModeBWFilterInterpreter}, - {0, AC_WRITE, 0, 0, 0x0526, AUTO, "PictureModeTone", &olPictureModeToneInterpreter}, - {0, AC_WRITE, 0, 0, 0x0527, AUTO, "NoiseFilter", &olNoiseFilterInterpreter}, - {0, AC_WRITE, 0, 0, 0x0600, AUTO, "DriveMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0601, AUTO, "PanoramaMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0603, AUTO, "ImageQuality2", &olImageQuality2Interpreter}, - {0, AC_WRITE, 0, 0, 0x0900, AUTO, "ManometerPressure", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0901, AUTO, "ManometerReading", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0902, AUTO, "ExtendedWBDetect", &olOnOffInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "CameraSettingsVersion", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0100, AUTO, "PreviewImageValid", &olYesNoInterpreter}, + {1, AC_WRITE, 0, 0, 0x0101, AUTO, "PreviewImageStart", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0102, AUTO, "PreviewImageLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0200, AUTO, "ExposureMode", &olExposureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0201, AUTO, "AELock", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0202, AUTO, "MeteringMode", &olMeteringModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0300, AUTO, "MacroMode", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0301, AUTO, "FocusMode", &olFocusModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0302, AUTO, "FocusProcess", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0303, AUTO, "AFSearch", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0304, AUTO, "AFAreas", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0400, AUTO, "FlashMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0401, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0500, AUTO, "WhiteBalance2", &olWhitebalance2Interpreter}, + {0, AC_WRITE, 0, 0, 0x0501, AUTO, "WhiteBalanceTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0502, AUTO, "WhiteBalanceBracket", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0503, AUTO, "CustomSaturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0504, AUTO, "ModifiedSaturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0505, AUTO, "ContrastSetting", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0506, AUTO, "SharpnessSetting", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0507, AUTO, "ColorSpace", &olColorSpaceInterpreter}, + {0, AC_WRITE, 0, 0, 0x0509, AUTO, "SceneMode", &olSceneModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x050a, AUTO, "NoiseReduction", &olNoiseReductionInterpreter}, + {0, AC_WRITE, 0, 0, 0x050b, AUTO, "DistortionCorrection", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x050c, AUTO, "ShadingCompensation", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x050d, AUTO, "CompressionFactor", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x050f, AUTO, "Gradation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0520, AUTO, "PictureMode", &olPictureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0521, AUTO, "PictureModeSaturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0522, AUTO, "PictureModeHue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0523, AUTO, "PictureModeContrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0524, AUTO, "PictureModeSharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0525, AUTO, "PictureModeBWFilter", &olPictureModeBWFilterInterpreter}, + {0, AC_WRITE, 0, 0, 0x0526, AUTO, "PictureModeTone", &olPictureModeToneInterpreter}, + {0, AC_WRITE, 0, 0, 0x0527, AUTO, "NoiseFilter", &olNoiseFilterInterpreter}, + {0, AC_WRITE, 0, 0, 0x0600, AUTO, "DriveMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0601, AUTO, "PanoramaMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0603, AUTO, "ImageQuality2", &olImageQuality2Interpreter}, + {0, AC_WRITE, 0, 0, 0x0900, AUTO, "ManometerPressure", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0901, AUTO, "ManometerReading", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0902, AUTO, "ExtendedWBDetect", &olOnOffInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib olyEquipmentAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "EquipmentVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0100, AUTO, "CameraType2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0101, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0102, AUTO, "InternalSerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0103, AUTO, "FocalPlaneDiagonal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0201, AUTO, "LensType", &olLensTypeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0202, AUTO, "LensSerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0204, AUTO, "LensFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0205, AUTO, "MaxApertureAtMinFocal", &olApertureInterpreter}, - {0, AC_WRITE, 0, 0, 0x0206, AUTO, "MaxApertureAtMaxFocal", &olApertureInterpreter}, - {0, AC_WRITE, 0, 0, 0x0207, AUTO, "MinFocalLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0208, AUTO, "MaxFocalLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020a, AUTO, "MaxApertureAtCurrentFocal", &olApertureInterpreter}, - {0, AC_WRITE, 0, 0, 0x020b, AUTO, "LensProperties", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0301, AUTO, "Extender", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0302, AUTO, "ExtenderSerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0303, AUTO, "ExtenderModel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0304, AUTO, "ExtenderFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1000, AUTO, "FlashType", &olFlashTypeInterpreter}, - {0, AC_WRITE, 0, 0, 0x1001, AUTO, "FlashModel", &olFlashModelInterpreter}, - {0, AC_WRITE, 0, 0, 0x1002, AUTO, "FlashFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1003, AUTO, "FlashSerialNumber", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "EquipmentVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0100, AUTO, "CameraType2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0101, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0102, AUTO, "InternalSerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0103, AUTO, "FocalPlaneDiagonal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0201, AUTO, "LensType", &olLensTypeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0202, AUTO, "LensSerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0204, AUTO, "LensFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0205, AUTO, "MaxApertureAtMinFocal", &olApertureInterpreter}, + {0, AC_WRITE, 0, 0, 0x0206, AUTO, "MaxApertureAtMaxFocal", &olApertureInterpreter}, + {0, AC_WRITE, 0, 0, 0x0207, AUTO, "MinFocalLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0208, AUTO, "MaxFocalLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020a, AUTO, "MaxApertureAtCurrentFocal", &olApertureInterpreter}, + {0, AC_WRITE, 0, 0, 0x020b, AUTO, "LensProperties", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0301, AUTO, "Extender", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0302, AUTO, "ExtenderSerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0303, AUTO, "ExtenderModel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0304, AUTO, "ExtenderFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1000, AUTO, "FlashType", &olFlashTypeInterpreter}, + {0, AC_WRITE, 0, 0, 0x1001, AUTO, "FlashModel", &olFlashModelInterpreter}, + {0, AC_WRITE, 0, 0, 0x1002, AUTO, "FlashFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1003, AUTO, "FlashSerialNumber", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib olympusAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0200, AUTO, "SpecialMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0201, AUTO, "Quality", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0202, AUTO, "Macro", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0203, AUTO, "BWMode", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0204, AUTO, "DigitalZoom", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0205, AUTO, "FocalPlaneDiagonal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0206, AUTO, "LensDistortionParams", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0207, AUTO, "CameraType", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0208, AUTO, "TextInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0209, AUTO, "CameraID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020b, AUTO, "EpsonImageWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020c, AUTO, "EpsonImageHeight", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020d, AUTO, "EpsonSoftware", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0280, AUTO, "PreviewImage", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0300, AUTO, "PreCaptureFrames", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0301, AUTO, "WhiteBoard", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0302, AUTO, "OneTouchWB", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0303, AUTO, "WhiteBalanceBracket", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0304, AUTO, "WhiteBalanceBias", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0403, AUTO, "SceneMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0404, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0405, AUTO, "Firmware", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0f00, AUTO, "DataDump", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0f01, AUTO, "DataDump2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1000, AUTO, "ShutterSpeedValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1001, AUTO, "ISOValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1002, AUTO, "ApertureValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1003, AUTO, "BrightnessValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1004, AUTO, "FlashMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1005, AUTO, "FlashDevice", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1006, AUTO, "ExposureCompensation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1007, AUTO, "SensorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1008, AUTO, "LensTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1009, AUTO, "LightCondition", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100a, AUTO, "FocusRange", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100b, AUTO, "FocusMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100c, AUTO, "ManualFocusDistance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100d, AUTO, "ZoomStepCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100e, AUTO, "FocusStepCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x100f, AUTO, "Sharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1010, AUTO, "FlashChargeLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1011, AUTO, "ColorMatrix", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1012, AUTO, "BlackLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1013, AUTO, "ColorTemperatureBG", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1014, AUTO, "ColorTemperatureRG", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1015, AUTO, "WBMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1017, AUTO, "RedBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1018, AUTO, "BlueBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1019, AUTO, "ColorMatrixNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x101a, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x101b, AUTO, "ExternalFlashAE1_0", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x101c, AUTO, "ExternalFlashAE2_0", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x101d, AUTO, "InternalFlashAE1_0", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x101e, AUTO, "InternalFlashAE2_0", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x101f, AUTO, "ExternalFlashAE1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1020, AUTO, "ExternalFlashAE2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1021, AUTO, "InternalFlashAE1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1022, AUTO, "InternalFlashAE2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1023, AUTO, "FlashExposureComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1024, AUTO, "InternalFlashTable", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1025, AUTO, "ExternalFlashGValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1026, AUTO, "ExternalFlashBounce", &olYesNoInterpreter}, - {0, AC_WRITE, 0, 0, 0x1027, AUTO, "ExternalFlashZoom", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1028, AUTO, "ExternalFlashMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1029, AUTO, "Contrast", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x102a, AUTO, "SharpnessFactor", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x102b, AUTO, "ColorControl", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x102c, AUTO, "ValidBits", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x102d, AUTO, "CoringFilter", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x102e, AUTO, "OlympusImageWidth", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x102f, AUTO, "OlympusImageHeight", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1030, AUTO, "SceneDetect", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1031, AUTO, "SceneArea", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1033, AUTO, "SceneDetectData", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1034, AUTO, "CompressionRatio", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x1035, AUTO, "PreviewImageValid", &olYesNoInterpreter}, - {1, AC_WRITE, 0, 0, 0x1036, AUTO, "PreviewImageStart", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x1037, AUTO, "PreviewImageLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1038, AUTO, "AFResult", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x1039, AUTO, "CCDScanMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x103a, AUTO, "NoiseReduction", &olOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x103b, AUTO, "InfinityLensStep", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x103c, AUTO, "NearLensStep", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x103d, AUTO, "LightValueCenter", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x103e, AUTO, "LightValuePeriphery", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x103f, AUTO, "FieldCount", &stdInterpreter}, - {0, AC_WRITE, 0, olyEquipmentAttribs, 0x2010, AUTO, "Equipment", &stdInterpreter}, - {0, AC_WRITE, 0, olyCameraSettingsAttribs, 0x2020, AUTO, "CameraSettings", &stdInterpreter}, - {0, AC_WRITE, 0, olyRawDevelopmentAttribs, 0x2030, AUTO, "RawDevelopment", &stdInterpreter}, - {0, AC_WRITE, 0, olyRawDevelopment2Attribs, 0x2031, AUTO, "RawDev2", &stdInterpreter}, - {0, AC_WRITE, 0, olyImageProcessingAttribs, 0x2040, AUTO, "ImageProcessing", &stdInterpreter}, - {0, AC_WRITE, 0, olyFocusInfoAttribs, 0x2050, AUTO, "FocusInfo", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2100, AUTO, "Olympus2100", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2300, AUTO, "Olympus2300", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2400, AUTO, "Olympus2400", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2500, AUTO, "Olympus2500", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2600, AUTO, "Olympus2600", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2700, AUTO, "Olympus2700", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2800, AUTO, "Olympus2800", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2900, AUTO, "Olympus2900", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x3000, AUTO, "RawInfo", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0200, AUTO, "SpecialMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0201, AUTO, "Quality", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0202, AUTO, "Macro", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0203, AUTO, "BWMode", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0204, AUTO, "DigitalZoom", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0205, AUTO, "FocalPlaneDiagonal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0206, AUTO, "LensDistortionParams", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0207, AUTO, "CameraType", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0208, AUTO, "TextInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0209, AUTO, "CameraID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020b, AUTO, "EpsonImageWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020c, AUTO, "EpsonImageHeight", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020d, AUTO, "EpsonSoftware", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0280, AUTO, "PreviewImage", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0300, AUTO, "PreCaptureFrames", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0301, AUTO, "WhiteBoard", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0302, AUTO, "OneTouchWB", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0303, AUTO, "WhiteBalanceBracket", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0304, AUTO, "WhiteBalanceBias", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0403, AUTO, "SceneMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0404, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0405, AUTO, "Firmware", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0f00, AUTO, "DataDump", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0f01, AUTO, "DataDump2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1000, AUTO, "ShutterSpeedValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1001, AUTO, "ISOValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1002, AUTO, "ApertureValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1003, AUTO, "BrightnessValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1004, AUTO, "FlashMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1005, AUTO, "FlashDevice", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1006, AUTO, "ExposureCompensation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1007, AUTO, "SensorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1008, AUTO, "LensTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1009, AUTO, "LightCondition", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100a, AUTO, "FocusRange", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100b, AUTO, "FocusMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100c, AUTO, "ManualFocusDistance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100d, AUTO, "ZoomStepCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100e, AUTO, "FocusStepCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x100f, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1010, AUTO, "FlashChargeLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1011, AUTO, "ColorMatrix", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1012, AUTO, "BlackLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1013, AUTO, "ColorTemperatureBG", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1014, AUTO, "ColorTemperatureRG", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1015, AUTO, "WBMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1017, AUTO, "RedBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1018, AUTO, "BlueBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1019, AUTO, "ColorMatrixNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x101a, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x101b, AUTO, "ExternalFlashAE1_0", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x101c, AUTO, "ExternalFlashAE2_0", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x101d, AUTO, "InternalFlashAE1_0", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x101e, AUTO, "InternalFlashAE2_0", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x101f, AUTO, "ExternalFlashAE1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1020, AUTO, "ExternalFlashAE2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1021, AUTO, "InternalFlashAE1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1022, AUTO, "InternalFlashAE2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1023, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1024, AUTO, "InternalFlashTable", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1025, AUTO, "ExternalFlashGValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1026, AUTO, "ExternalFlashBounce", &olYesNoInterpreter}, + {0, AC_WRITE, 0, 0, 0x1027, AUTO, "ExternalFlashZoom", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1028, AUTO, "ExternalFlashMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1029, AUTO, "Contrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x102a, AUTO, "SharpnessFactor", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x102b, AUTO, "ColorControl", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x102c, AUTO, "ValidBits", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x102d, AUTO, "CoringFilter", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x102e, AUTO, "OlympusImageWidth", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x102f, AUTO, "OlympusImageHeight", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1030, AUTO, "SceneDetect", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1031, AUTO, "SceneArea", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1033, AUTO, "SceneDetectData", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1034, AUTO, "CompressionRatio", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x1035, AUTO, "PreviewImageValid", &olYesNoInterpreter}, + {1, AC_WRITE, 0, 0, 0x1036, AUTO, "PreviewImageStart", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x1037, AUTO, "PreviewImageLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1038, AUTO, "AFResult", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x1039, AUTO, "CCDScanMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x103a, AUTO, "NoiseReduction", &olOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x103b, AUTO, "InfinityLensStep", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x103c, AUTO, "NearLensStep", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x103d, AUTO, "LightValueCenter", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x103e, AUTO, "LightValuePeriphery", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x103f, AUTO, "FieldCount", &stdInterpreter}, + {0, AC_WRITE, 0, olyEquipmentAttribs, 0x2010, AUTO, "Equipment", &stdInterpreter}, + {0, AC_WRITE, 0, olyCameraSettingsAttribs, 0x2020, AUTO, "CameraSettings", &stdInterpreter}, + {0, AC_WRITE, 0, olyRawDevelopmentAttribs, 0x2030, AUTO, "RawDevelopment", &stdInterpreter}, + {0, AC_WRITE, 0, olyRawDevelopment2Attribs, 0x2031, AUTO, "RawDev2", &stdInterpreter}, + {0, AC_WRITE, 0, olyImageProcessingAttribs, 0x2040, AUTO, "ImageProcessing", &stdInterpreter}, + {0, AC_WRITE, 0, olyFocusInfoAttribs, 0x2050, AUTO, "FocusInfo", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2100, AUTO, "Olympus2100", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2300, AUTO, "Olympus2300", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2400, AUTO, "Olympus2400", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2500, AUTO, "Olympus2500", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2600, AUTO, "Olympus2600", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2700, AUTO, "Olympus2700", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2800, AUTO, "Olympus2800", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2900, AUTO, "Olympus2900", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x3000, AUTO, "RawInfo", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; } #endif diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index 810d2634f..0a9be9c02 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -7,7 +7,7 @@ * 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 @@ -27,507 +27,557 @@ #include "rtexif.h" -namespace rtexif { +namespace rtexif +{ -class PAQualityInterpreter : public ChoiceInterpreter { - public: - PAQualityInterpreter () { - choices[0] = "Good"; - choices[1] = "Better"; - choices[2] = "Best"; - choices[3] = "TIFF"; - choices[4] = "RAW"; - choices[5] = "Premium"; - } +class PAQualityInterpreter : public ChoiceInterpreter +{ +public: + PAQualityInterpreter () + { + choices[0] = "Good"; + choices[1] = "Better"; + choices[2] = "Best"; + choices[3] = "TIFF"; + choices[4] = "RAW"; + choices[5] = "Premium"; + } }; PAQualityInterpreter paQualityInterpreter; -class PAOnOffInterpreter : public ChoiceInterpreter { - public: - PAOnOffInterpreter () { - choices[0] = "Off"; - choices[1] = "On"; - } +class PAOnOffInterpreter : public ChoiceInterpreter +{ +public: + PAOnOffInterpreter () + { + choices[0] = "Off"; + choices[1] = "On"; + } }; PAOnOffInterpreter paOnOffInterpreter; -class PAShakeReductionInterpreter : public ChoiceInterpreter { - public: - PAShakeReductionInterpreter () { - choices[ 0] = "Off"; - choices[ 1] = "On"; - choices[ 4] = "On (4)"; - choices[ 5] = "On but Disabled"; - choices[ 6] = "On (Video)"; - choices[ 7] = "On (7)"; - choices[ 15] = "On (15)"; - choices[ 39] = "On (mode 2)"; - choices[135] = "On (135)"; - choices[167] = "On (mode 1)"; - } +class PAShakeReductionInterpreter : public ChoiceInterpreter +{ +public: + PAShakeReductionInterpreter () + { + choices[ 0] = "Off"; + choices[ 1] = "On"; + choices[ 4] = "On (4)"; + choices[ 5] = "On but Disabled"; + choices[ 6] = "On (Video)"; + choices[ 7] = "On (7)"; + choices[ 15] = "On (15)"; + choices[ 39] = "On (mode 2)"; + choices[135] = "On (135)"; + choices[167] = "On (mode 1)"; + } }; PAShakeReductionInterpreter paShakeReductionInterpreter; -class PAShakeReduction2Interpreter : public ChoiceInterpreter { - public: - PAShakeReduction2Interpreter () { - choices[ 0] = "Off"; - choices[ 1] = "On"; - choices[ 4] = "Off (AA simulation off)"; - choices[ 5] = "On but Disabled"; - choices[ 6] = "On (Video)"; - choices[ 7] = "On (AA simulation off)"; - choices[12] = "Off (AA simulation type 1)"; - choices[15] = "On (AA simulation type 1)"; - choices[20] = "Off (AA simulation type 2)"; - choices[23] = "On (AA simulation type 2)"; - } +class PAShakeReduction2Interpreter : public ChoiceInterpreter +{ +public: + PAShakeReduction2Interpreter () + { + choices[ 0] = "Off"; + choices[ 1] = "On"; + choices[ 4] = "Off (AA simulation off)"; + choices[ 5] = "On but Disabled"; + choices[ 6] = "On (Video)"; + choices[ 7] = "On (AA simulation off)"; + choices[12] = "Off (AA simulation type 1)"; + choices[15] = "On (AA simulation type 1)"; + choices[20] = "Off (AA simulation type 2)"; + choices[23] = "On (AA simulation type 2)"; + } }; PAShakeReduction2Interpreter paShakeReduction2Interpreter; -class PAPictureModeInterpreter : public ChoiceInterpreter { - public: - PAPictureModeInterpreter () { - choices[0] = "Program"; - choices[1] = "Shutter Speed Priority"; - choices[2] = "Program AE"; - choices[3] = "Manual"; - choices[5] = "Portrait"; - choices[6] = "Landscape"; - choices[8] = "Sport"; - choices[9] = "Night Scene"; - choices[11] = "Soft"; - choices[12] = "Surf & Snow"; - choices[13] = "Candlelight"; - choices[14] = "Autumn"; - choices[15] = "Macro"; - choices[17] = "Fireworks"; - choices[18] = "Text"; - choices[19] = "Panorama"; - choices[20] = "3-D"; - choices[21] = "Black & White"; - choices[22] = "Sepia"; - choices[23] = "Red"; - choices[24] = "Pink"; - choices[25] = "Purple"; - choices[26] = "Blue"; - choices[27] = "Green"; - choices[28] = "Yellow"; - choices[30] = "Self Portrait"; - choices[31] = "Illustrations"; - choices[33] = "Digital Filter"; - choices[35] = "Night Scene Portrait"; - choices[37] = "Museum"; - choices[38] = "Food"; - choices[39] = "Underwater"; - choices[40] = "Green Mode"; - choices[49] = "Light Pet"; - choices[50] = "Dark Pet"; - choices[51] = "Medium Pet"; - choices[53] = "Underwater"; - choices[54] = "Candlelight"; - choices[55] = "Natural Skin Tone"; - choices[56] = "Synchro Sound Record"; - choices[58] = "Frame Composite"; - choices[59] = "Report"; - choices[60] = "Kids"; - choices[61] = "Blur Reduction"; - choices[65] = "Half-length Portrait"; - choices[221] = "P"; - choices[255] = "PICT"; - } +class PAPictureModeInterpreter : public ChoiceInterpreter +{ +public: + PAPictureModeInterpreter () + { + choices[0] = "Program"; + choices[1] = "Shutter Speed Priority"; + choices[2] = "Program AE"; + choices[3] = "Manual"; + choices[5] = "Portrait"; + choices[6] = "Landscape"; + choices[8] = "Sport"; + choices[9] = "Night Scene"; + choices[11] = "Soft"; + choices[12] = "Surf & Snow"; + choices[13] = "Candlelight"; + choices[14] = "Autumn"; + choices[15] = "Macro"; + choices[17] = "Fireworks"; + choices[18] = "Text"; + choices[19] = "Panorama"; + choices[20] = "3-D"; + choices[21] = "Black & White"; + choices[22] = "Sepia"; + choices[23] = "Red"; + choices[24] = "Pink"; + choices[25] = "Purple"; + choices[26] = "Blue"; + choices[27] = "Green"; + choices[28] = "Yellow"; + choices[30] = "Self Portrait"; + choices[31] = "Illustrations"; + choices[33] = "Digital Filter"; + choices[35] = "Night Scene Portrait"; + choices[37] = "Museum"; + choices[38] = "Food"; + choices[39] = "Underwater"; + choices[40] = "Green Mode"; + choices[49] = "Light Pet"; + choices[50] = "Dark Pet"; + choices[51] = "Medium Pet"; + choices[53] = "Underwater"; + choices[54] = "Candlelight"; + choices[55] = "Natural Skin Tone"; + choices[56] = "Synchro Sound Record"; + choices[58] = "Frame Composite"; + choices[59] = "Report"; + choices[60] = "Kids"; + choices[61] = "Blur Reduction"; + choices[65] = "Half-length Portrait"; + choices[221] = "P"; + choices[255] = "PICT"; + } }; PAPictureModeInterpreter paPictureModeInterpreter; -class PASceneModeInterpreter : public ChoiceInterpreter { - public: - PASceneModeInterpreter () { - choices[ 0] = "Off"; - choices[ 1] = "HDR"; - choices[ 4] = "Auto PICT"; - choices[ 5] = "Portrait"; - choices[ 6] = "Landscape"; - choices[ 7] = "Macro"; - choices[ 8] = "Sport"; - choices[ 9] = "Night Scene Portrait"; - choices[10] = "No Flash"; - choices[11] = "Night Scene"; - choices[12] = "Surf & Snow"; - choices[14] = "Sunset"; - choices[15] = "Kids"; - choices[16] = "Pet"; - choices[17] = "Candlelight"; - choices[18] = "Museum"; - choices[20] = "Food"; - choices[21] = "Stage Lighting"; - choices[22] = "Night Snap"; - choices[25] = "Night Scene HDR"; - choices[26] = "Blue Sky"; - choices[27] = "Forest"; - choices[29] = "Backlight Silhouette"; - } +class PASceneModeInterpreter : public ChoiceInterpreter +{ +public: + PASceneModeInterpreter () + { + choices[ 0] = "Off"; + choices[ 1] = "HDR"; + choices[ 4] = "Auto PICT"; + choices[ 5] = "Portrait"; + choices[ 6] = "Landscape"; + choices[ 7] = "Macro"; + choices[ 8] = "Sport"; + choices[ 9] = "Night Scene Portrait"; + choices[10] = "No Flash"; + choices[11] = "Night Scene"; + choices[12] = "Surf & Snow"; + choices[14] = "Sunset"; + choices[15] = "Kids"; + choices[16] = "Pet"; + choices[17] = "Candlelight"; + choices[18] = "Museum"; + choices[20] = "Food"; + choices[21] = "Stage Lighting"; + choices[22] = "Night Snap"; + choices[25] = "Night Scene HDR"; + choices[26] = "Blue Sky"; + choices[27] = "Forest"; + choices[29] = "Backlight Silhouette"; + } }; PASceneModeInterpreter paSceneModeInterpreter; -class PAAEProgramModeInterpreter : public ChoiceInterpreter { - public: - PAAEProgramModeInterpreter () { - choices[ 0] = "M, P or TAv"; - choices[ 1] = "Av, B or X"; - choices[ 2] = "Tv"; - choices[ 3] = "Sv or Green Mode"; - choices[ 8] = "Hi-speed Program"; - choices[ 11] = "Hi-speed Program (P-Shift)"; - choices[ 16] = "DOF Program"; - choices[ 19] = "DOF Program (P-Shift)"; - choices[ 24] = "MTF Program"; - choices[ 27] = "MTF Program (P-Shift)"; - choices[ 35] = "Standard"; - choices[ 43] = "Portrait"; - choices[ 51] = "Landscape"; - choices[ 59] = "Macro"; - choices[ 67] = "Sport"; - choices[ 75] = "Night Scene Portrait"; - choices[ 83] = "No Flash"; - choices[ 91] = "Night Scene"; - choices[ 99] = "Surf & Snow"; - choices[104] = "Night Snap"; - choices[107] = "Text"; - choices[115] = "Sunset"; - choices[123] = "Kids"; - choices[131] = "Pet"; - choices[139] = "Candlelight"; - choices[144] = "SCN"; - choices[147] = "Museum"; - choices[160] = "Program"; - choices[184] = "Shallow DOF Program"; - choices[216] = "HDR"; - } +class PAAEProgramModeInterpreter : public ChoiceInterpreter +{ +public: + PAAEProgramModeInterpreter () + { + choices[ 0] = "M, P or TAv"; + choices[ 1] = "Av, B or X"; + choices[ 2] = "Tv"; + choices[ 3] = "Sv or Green Mode"; + choices[ 8] = "Hi-speed Program"; + choices[ 11] = "Hi-speed Program (P-Shift)"; + choices[ 16] = "DOF Program"; + choices[ 19] = "DOF Program (P-Shift)"; + choices[ 24] = "MTF Program"; + choices[ 27] = "MTF Program (P-Shift)"; + choices[ 35] = "Standard"; + choices[ 43] = "Portrait"; + choices[ 51] = "Landscape"; + choices[ 59] = "Macro"; + choices[ 67] = "Sport"; + choices[ 75] = "Night Scene Portrait"; + choices[ 83] = "No Flash"; + choices[ 91] = "Night Scene"; + choices[ 99] = "Surf & Snow"; + choices[104] = "Night Snap"; + choices[107] = "Text"; + choices[115] = "Sunset"; + choices[123] = "Kids"; + choices[131] = "Pet"; + choices[139] = "Candlelight"; + choices[144] = "SCN"; + choices[147] = "Museum"; + choices[160] = "Program"; + choices[184] = "Shallow DOF Program"; + choices[216] = "HDR"; + } }; PAAEProgramModeInterpreter paAEProgramModeInterpreter; -class PAFlashModeInterpreter : public ChoiceInterpreter { - public: - PAFlashModeInterpreter () { - choices[0x0] = "Auto, Did not fire"; - choices[0x1] = "Off"; - choices[0x2] = "On, Did not fire"; - choices[0x3] = "Auto, Did not fire, Red-eye reduction"; - choices[0x100] = "Auto, Fired"; - choices[0x102] = "On"; - choices[0x103] = "Auto, Fired, Red-eye reduction"; - choices[0x104] = "On, Red-eye reduction"; - choices[0x105] = "On, Wireless (Master)"; - choices[0x106] = "On, Wireless (Control)"; - choices[0x108] = "On, Soft"; - choices[0x109] = "On, Slow-sync"; - choices[0x10a] = "On, Slow-sync, Red-eye reduction"; - choices[0x10b] = "On, Trailing-curtain Sync"; - } +class PAFlashModeInterpreter : public ChoiceInterpreter +{ +public: + PAFlashModeInterpreter () + { + choices[0x0] = "Auto, Did not fire"; + choices[0x1] = "Off"; + choices[0x2] = "On, Did not fire"; + choices[0x3] = "Auto, Did not fire, Red-eye reduction"; + choices[0x100] = "Auto, Fired"; + choices[0x102] = "On"; + choices[0x103] = "Auto, Fired, Red-eye reduction"; + choices[0x104] = "On, Red-eye reduction"; + choices[0x105] = "On, Wireless (Master)"; + choices[0x106] = "On, Wireless (Control)"; + choices[0x108] = "On, Soft"; + choices[0x109] = "On, Slow-sync"; + choices[0x10a] = "On, Slow-sync, Red-eye reduction"; + choices[0x10b] = "On, Trailing-curtain Sync"; + } }; PAFlashModeInterpreter paFlashModeInterpreter; -class PAFocusModeInterpreter : public ChoiceInterpreter { - public: - PAFocusModeInterpreter () { - choices[0] = "Normal"; - choices[1] = "Macro"; - choices[2] = "Infinity"; - choices[3] = "Manual"; - choices[4] = "Super Macro"; - choices[5] = "Pan Focus"; - choices[16] = "AF-S"; - choices[17] = "AF-C"; - choices[18] = "AF-A"; - } +class PAFocusModeInterpreter : public ChoiceInterpreter +{ +public: + PAFocusModeInterpreter () + { + choices[0] = "Normal"; + choices[1] = "Macro"; + choices[2] = "Infinity"; + choices[3] = "Manual"; + choices[4] = "Super Macro"; + choices[5] = "Pan Focus"; + choices[16] = "AF-S"; + choices[17] = "AF-C"; + choices[18] = "AF-A"; + } }; PAFocusModeInterpreter paFocusModeInterpreter; -class PAAFPointInterpreter : public ChoiceInterpreter { - public: - PAAFPointInterpreter () { - choices[1] = "Upper-left"; - choices[2] = "Top"; - choices[3] = "Upper-right"; - choices[4] = "Left"; - choices[5] = "Mid-left"; - choices[6] = "Center"; - choices[7] = "Mid-right"; - choices[8] = "Right"; - choices[9] = "Lower-left"; - choices[10] = "Bottom"; - choices[11] = "Lower-right"; - choices[65532] = "Face Recognition AF"; - choices[65533] = "Automatic Tracking AF"; - choices[65534] = "Fixed Center"; - choices[65535] = "Auto"; - } +class PAAFPointInterpreter : public ChoiceInterpreter +{ +public: + PAAFPointInterpreter () + { + choices[1] = "Upper-left"; + choices[2] = "Top"; + choices[3] = "Upper-right"; + choices[4] = "Left"; + choices[5] = "Mid-left"; + choices[6] = "Center"; + choices[7] = "Mid-right"; + choices[8] = "Right"; + choices[9] = "Lower-left"; + choices[10] = "Bottom"; + choices[11] = "Lower-right"; + choices[65532] = "Face Recognition AF"; + choices[65533] = "Automatic Tracking AF"; + choices[65534] = "Fixed Center"; + choices[65535] = "Auto"; + } }; PAAFPointInterpreter paAFPointInterpreter; -class PAAFFocusInterpreter : public ChoiceInterpreter { - public: - PAAFFocusInterpreter () { - choices[0x0] = "Fixed Center or Multiple"; - choices[0x1] = "Top-left"; - choices[0x2] = "Top-center"; - choices[0x3] = "Top-right"; - choices[0x4] = "Left"; - choices[0x5] = "Center"; - choices[0x6] = "Right"; - choices[0x7] = "Bottom-left"; - choices[0x8] = "Bottom-center"; - choices[0x9] = "Bottom-right"; - choices[0xffff] = "None"; - } +class PAAFFocusInterpreter : public ChoiceInterpreter +{ +public: + PAAFFocusInterpreter () + { + choices[0x0] = "Fixed Center or Multiple"; + choices[0x1] = "Top-left"; + choices[0x2] = "Top-center"; + choices[0x3] = "Top-right"; + choices[0x4] = "Left"; + choices[0x5] = "Center"; + choices[0x6] = "Right"; + choices[0x7] = "Bottom-left"; + choices[0x8] = "Bottom-center"; + choices[0x9] = "Bottom-right"; + choices[0xffff] = "None"; + } }; PAAFFocusInterpreter paAFFocusInterpreter; -class PAISOInterpreter : public ChoiceInterpreter { - public: - PAISOInterpreter () { - choices[3] = "50"; - choices[4] = "64"; - choices[5] = "80"; - choices[6] = "100"; - choices[7] = "125"; - choices[8] = "160"; - choices[9] = "200"; - choices[10] = "250"; - choices[11] = "320"; - choices[12] = "400"; - choices[13] = "500"; - choices[14] = "640"; - choices[15] = "800"; - choices[16] = "1000"; - choices[17] = "1250"; - choices[18] = "1600"; - choices[19] = "2000"; - choices[20] = "2500"; - choices[21] = "3200"; - choices[22] = "4000"; - choices[23] = "5000"; - choices[24] = "6400"; - choices[25] = "8000"; - choices[26] = "10000"; - choices[27] = "12800"; - choices[28] = "16000"; - choices[29] = "20000"; - choices[30] = "25600"; - choices[31] = "32000"; - choices[32] = "40000"; - choices[33] = "51200"; +class PAISOInterpreter : public ChoiceInterpreter +{ +public: + PAISOInterpreter () + { + choices[3] = "50"; + choices[4] = "64"; + choices[5] = "80"; + choices[6] = "100"; + choices[7] = "125"; + choices[8] = "160"; + choices[9] = "200"; + choices[10] = "250"; + choices[11] = "320"; + choices[12] = "400"; + choices[13] = "500"; + choices[14] = "640"; + choices[15] = "800"; + choices[16] = "1000"; + choices[17] = "1250"; + choices[18] = "1600"; + choices[19] = "2000"; + choices[20] = "2500"; + choices[21] = "3200"; + choices[22] = "4000"; + choices[23] = "5000"; + choices[24] = "6400"; + choices[25] = "8000"; + choices[26] = "10000"; + choices[27] = "12800"; + choices[28] = "16000"; + choices[29] = "20000"; + choices[30] = "25600"; + choices[31] = "32000"; + choices[32] = "40000"; + choices[33] = "51200"; - choices[50] = "50"; - choices[100] = "100"; - choices[200] = "200"; - /*choices[400] = "400"; - choices[800] = "800"; - choices[1600] = "1600"; - choices[3200] = "3200"; Moved to tail for sorting reasons */ + choices[50] = "50"; + choices[100] = "100"; + choices[200] = "200"; + /*choices[400] = "400"; + choices[800] = "800"; + choices[1600] = "1600"; + choices[3200] = "3200"; Moved to tail for sorting reasons */ - choices[258] = "50"; - choices[259] = "70"; - choices[260] = "100"; - choices[261] = "140"; - choices[262] = "200"; - choices[263] = "280"; - choices[264] = "400"; - choices[265] = "560"; - choices[266] = "800"; - choices[267] = "1100"; - choices[268] = "1600"; - choices[269] = "2200"; - choices[270] = "3200"; - choices[271] = "4500"; - choices[272] = "6400"; - choices[273] = "9000"; - choices[274] = "12800"; - choices[275] = "18000"; - choices[276] = "25600"; - choices[277] = "36000"; - choices[278] = "51200"; + choices[258] = "50"; + choices[259] = "70"; + choices[260] = "100"; + choices[261] = "140"; + choices[262] = "200"; + choices[263] = "280"; + choices[264] = "400"; + choices[265] = "560"; + choices[266] = "800"; + choices[267] = "1100"; + choices[268] = "1600"; + choices[269] = "2200"; + choices[270] = "3200"; + choices[271] = "4500"; + choices[272] = "6400"; + choices[273] = "9000"; + choices[274] = "12800"; + choices[275] = "18000"; + choices[276] = "25600"; + choices[277] = "36000"; + choices[278] = "51200"; - choices[400] = "400"; - choices[800] = "800"; - choices[1600] = "1600"; - choices[3200] = "3200"; + choices[400] = "400"; + choices[800] = "800"; + choices[1600] = "1600"; + choices[3200] = "3200"; - //choices[65534] = "Auto"; ?? - //choices[65535] = "Auto"; ?? - } + //choices[65534] = "Auto"; ?? + //choices[65535] = "Auto"; ?? + } }; PAISOInterpreter paISOInterpreter; -class PAFNumberInterpreter: public Interpreter { +class PAFNumberInterpreter: public Interpreter +{ public: PAFNumberInterpreter () {} - virtual std::string toString (Tag* t) { + virtual std::string toString (Tag* t) + { char buffer[32]; - double v = t->toDouble()/10; - if( v < 0. || v > 1000. ) return "undef"; + double v = t->toDouble() / 10; + + if( v < 0. || v > 1000. ) { + return "undef"; + } + sprintf (buffer, "%.1f", v ); return buffer; } }; PAFNumberInterpreter paFNumberInterpreter; -class PAMeteringModeInterpreter : public ChoiceInterpreter { - public: - PAMeteringModeInterpreter () { - choices[0] = "Multi-segment"; - choices[1] = "Center-weighted average"; - choices[2] = "Spot"; - } +class PAMeteringModeInterpreter : public ChoiceInterpreter +{ +public: + PAMeteringModeInterpreter () + { + choices[0] = "Multi-segment"; + choices[1] = "Center-weighted average"; + choices[2] = "Spot"; + } }; PAMeteringModeInterpreter paMeteringModeInterpreter; -class PAWhiteBalanceInterpreter : public ChoiceInterpreter { - public: - PAWhiteBalanceInterpreter () { - choices[0] = "Auto"; - choices[1] = "Daylight"; - choices[2] = "Shade"; - choices[3] = "Fluorescent"; - choices[4] = "Tungsten"; - choices[5] = "Manual"; - choices[6] = "Daylight Fluorescent"; - choices[7] = "Day White Fluorescent"; - choices[8] = "White Fluorescent"; - choices[9] = "Flash"; - choices[10] = "Cloudy"; - choices[11] = "Warm White Fluorescent"; - choices[14] = "Multi Auto"; - choices[15] = "Color Temperature Enhancement"; - choices[17] = "Kelvin"; - choices[65534] = "Unknown"; - choices[65535] = "User Selected"; - } +class PAWhiteBalanceInterpreter : public ChoiceInterpreter +{ +public: + PAWhiteBalanceInterpreter () + { + choices[0] = "Auto"; + choices[1] = "Daylight"; + choices[2] = "Shade"; + choices[3] = "Fluorescent"; + choices[4] = "Tungsten"; + choices[5] = "Manual"; + choices[6] = "Daylight Fluorescent"; + choices[7] = "Day White Fluorescent"; + choices[8] = "White Fluorescent"; + choices[9] = "Flash"; + choices[10] = "Cloudy"; + choices[11] = "Warm White Fluorescent"; + choices[14] = "Multi Auto"; + choices[15] = "Color Temperature Enhancement"; + choices[17] = "Kelvin"; + choices[65534] = "Unknown"; + choices[65535] = "User Selected"; + } }; PAWhiteBalanceInterpreter paWhiteBalanceInterpreter; -class PAWhiteBalanceModeInterpreter : public ChoiceInterpreter { - public: - PAWhiteBalanceModeInterpreter () { - choices[1] = "Auto (Daylight)"; - choices[2] = "Auto (Shade)"; - choices[3] = "Auto (Flash)"; - choices[4] = "Auto (Tungsten)"; - choices[6] = "Auto (DaylightFluorescent)"; - choices[7] = "Auto (DaywhiteFluorescent)"; - choices[8] = "Auto (WhiteFluorescent)"; - choices[10] = "Auto (Cloudy)"; - choices[65534] = "Preset (Fireworks?)"; - choices[65535] = "User-Selected"; - } +class PAWhiteBalanceModeInterpreter : public ChoiceInterpreter +{ +public: + PAWhiteBalanceModeInterpreter () + { + choices[1] = "Auto (Daylight)"; + choices[2] = "Auto (Shade)"; + choices[3] = "Auto (Flash)"; + choices[4] = "Auto (Tungsten)"; + choices[6] = "Auto (DaylightFluorescent)"; + choices[7] = "Auto (DaywhiteFluorescent)"; + choices[8] = "Auto (WhiteFluorescent)"; + choices[10] = "Auto (Cloudy)"; + choices[65534] = "Preset (Fireworks?)"; + choices[65535] = "User-Selected"; + } }; PAWhiteBalanceModeInterpreter paWhiteBalanceModeInterpreter; -class PASaturationInterpreter : public ChoiceInterpreter { - public: - PASaturationInterpreter () { - choices[0] = "Low"; - choices[1] = "Normal"; - choices[2] = "High"; - choices[3] = "Med Low"; - choices[4] = "Med High"; - choices[5] = "Very Low"; - choices[6] = "Very High"; - } +class PASaturationInterpreter : public ChoiceInterpreter +{ +public: + PASaturationInterpreter () + { + choices[0] = "Low"; + choices[1] = "Normal"; + choices[2] = "High"; + choices[3] = "Med Low"; + choices[4] = "Med High"; + choices[5] = "Very Low"; + choices[6] = "Very High"; + } }; PASaturationInterpreter paSaturationInterpreter; -class PAContrastInterpreter : public ChoiceInterpreter { - public: - PAContrastInterpreter () { - choices[0] = "Low"; - choices[1] = "Normal"; - choices[2] = "High"; - choices[3] = "Med Low"; - choices[4] = "Med High"; - choices[5] = "Very Low"; - choices[6] = "Very High"; - } +class PAContrastInterpreter : public ChoiceInterpreter +{ +public: + PAContrastInterpreter () + { + choices[0] = "Low"; + choices[1] = "Normal"; + choices[2] = "High"; + choices[3] = "Med Low"; + choices[4] = "Med High"; + choices[5] = "Very Low"; + choices[6] = "Very High"; + } }; PAContrastInterpreter paContrastInterpreter; -class PASharpnessInterpreter : public ChoiceInterpreter { - public: - PASharpnessInterpreter () { - choices[0] = "Soft"; - choices[1] = "Normal"; - choices[2] = "Hard"; - choices[3] = "Med Soft"; - choices[4] = "Med Hard"; - choices[5] = "Very Soft"; - choices[6] = "Very Hard"; - } +class PASharpnessInterpreter : public ChoiceInterpreter +{ +public: + PASharpnessInterpreter () + { + choices[0] = "Soft"; + choices[1] = "Normal"; + choices[2] = "Hard"; + choices[3] = "Med Soft"; + choices[4] = "Med Hard"; + choices[5] = "Very Soft"; + choices[6] = "Very Hard"; + } }; PASharpnessInterpreter paSharpnessInterpreter; -class PAPictureModeInterpreter2: public ChoiceInterpreter { +class PAPictureModeInterpreter2: public ChoiceInterpreter +{ public: - PAPictureModeInterpreter2(){ - choices[ 0] = "Program"; - choices[ 1] = "Hi-speed Program"; - choices[ 2] = "DOF Program"; - choices[ 3] = "MTF Program"; - choices[ 4] = "Standard"; - choices[ 5] = "Portrait"; - choices[ 6] = "Landscape"; - choices[ 7] = "Macro"; - choices[ 8] = "Sport "; - choices[ 9] = "Night Scene Portrait "; - choices[10] = "No Flash"; - choices[11] = "Night Scene"; - choices[12] = "Surf & Snow"; - choices[13] = "Text"; - choices[14] = "Sunset"; - choices[15] = "Kids"; - choices[16] = "Pet"; - choices[17] = "Candlelight"; - choices[18] = "Museum"; - choices[19] = "Food "; - choices[20] = "Stage Lighting"; - choices[21] = "Night Snap"; - choices[256+4] = "Auto PICT"; - choices[256+5] = "Auto PICT (Portrait)"; - choices[256+6] = "Auto PICT (Landscape)"; - choices[256+7] = "Auto PICT (Macro)"; - choices[256+8] = "Auto PICT (Sport)"; - choices[256+8] = "Auto PICT (Sport)"; - choices[512+0] = "Program (HyP)"; - choices[512+1] = "Hi-speed Program (HyP)"; - choices[512+2] = "DOF Program (HyP)"; - choices[512+3] = "MTF Program (HyP)"; - choices[3*256] = "Green Mode"; - choices[4*256] = "Shutter Speed Priority"; - choices[5*256] = "Aperture Priority"; - choices[6*256] = "Program Tv Shift"; - choices[7*256] = "Program Av Shift"; - choices[8*256] = "Manual"; - choices[9*256] = "Bulb"; - choices[10*256] = "Aperture Priority, Off-Auto-Aperture"; - choices[11*256] = "Manual, Off-Auto-Aperture"; - choices[12*256] = "Bulb, Off-Auto-Aperture"; - choices[13*256] = "Shutter & Aperture Priority AE"; - choices[15*256] = "Sensitivity Priority AE"; - choices[16*256] = "Flash X-Sync Speed AE"; - } - virtual std::string toString (Tag* t) { - int c = 256*t->toInt(0,BYTE) + t->toInt(1,BYTE); - std::map::iterator r = choices.find (c); - if (r!=choices.end()){ - std::ostringstream s; - s << r->second; - if( t->toInt(1,BYTE)==0 ) - s << "\n1/2 EV steps"; - else - s << "\n1/3 EV steps"; + PAPictureModeInterpreter2() + { + choices[ 0] = "Program"; + choices[ 1] = "Hi-speed Program"; + choices[ 2] = "DOF Program"; + choices[ 3] = "MTF Program"; + choices[ 4] = "Standard"; + choices[ 5] = "Portrait"; + choices[ 6] = "Landscape"; + choices[ 7] = "Macro"; + choices[ 8] = "Sport "; + choices[ 9] = "Night Scene Portrait "; + choices[10] = "No Flash"; + choices[11] = "Night Scene"; + choices[12] = "Surf & Snow"; + choices[13] = "Text"; + choices[14] = "Sunset"; + choices[15] = "Kids"; + choices[16] = "Pet"; + choices[17] = "Candlelight"; + choices[18] = "Museum"; + choices[19] = "Food "; + choices[20] = "Stage Lighting"; + choices[21] = "Night Snap"; + choices[256 + 4] = "Auto PICT"; + choices[256 + 5] = "Auto PICT (Portrait)"; + choices[256 + 6] = "Auto PICT (Landscape)"; + choices[256 + 7] = "Auto PICT (Macro)"; + choices[256 + 8] = "Auto PICT (Sport)"; + choices[256 + 8] = "Auto PICT (Sport)"; + choices[512 + 0] = "Program (HyP)"; + choices[512 + 1] = "Hi-speed Program (HyP)"; + choices[512 + 2] = "DOF Program (HyP)"; + choices[512 + 3] = "MTF Program (HyP)"; + choices[3 * 256] = "Green Mode"; + choices[4 * 256] = "Shutter Speed Priority"; + choices[5 * 256] = "Aperture Priority"; + choices[6 * 256] = "Program Tv Shift"; + choices[7 * 256] = "Program Av Shift"; + choices[8 * 256] = "Manual"; + choices[9 * 256] = "Bulb"; + choices[10 * 256] = "Aperture Priority, Off-Auto-Aperture"; + choices[11 * 256] = "Manual, Off-Auto-Aperture"; + choices[12 * 256] = "Bulb, Off-Auto-Aperture"; + choices[13 * 256] = "Shutter & Aperture Priority AE"; + choices[15 * 256] = "Sensitivity Priority AE"; + choices[16 * 256] = "Flash X-Sync Speed AE"; + } + virtual std::string toString (Tag* t) + { + int c = 256 * t->toInt(0, BYTE) + t->toInt(1, BYTE); + std::map::iterator r = choices.find (c); + + if (r != choices.end()) { + std::ostringstream s; + s << r->second; + + if( t->toInt(1, BYTE) == 0 ) { + s << "\n1/2 EV steps"; + } else { + s << "\n1/3 EV steps"; + } + return s.str(); - }else { - char buffer[1024]; + } else { + char buffer[1024]; t->toString (buffer); return std::string (buffer); } @@ -535,565 +585,621 @@ public: }; PAPictureModeInterpreter2 paPictureModeInterpreter2; -class PADriveModeInterpreter : public ChoiceInterpreter{ - std::map choices1; - std::map choices2; - std::map choices3; +class PADriveModeInterpreter : public ChoiceInterpreter +{ + std::map choices1; + std::map choices2; + std::map choices3; public: - PADriveModeInterpreter(){ - choices[0] = "Single-frame"; - choices[1] = "Continuous"; - choices[2] = "Continuous (Lo)"; - choices[3] = "Burst"; - choices[4] = "Continuous (Medium)"; - choices[255] = "Video"; - choices1[0] = "No Timer"; - choices1[1] = "Self-timer (12 s)"; - choices1[2] = "Self-timer (2 s)"; - choices1[15] = "Video"; - choices1[16] = "Mirror Lock-up"; - choices1[255] = "n/a"; - choices2[0] = "Shutter Button"; - choices2[1] = "Remote Control (3 s delay)"; - choices2[2] = "Remote Control"; - choices2[4] = "Remote Continuous Shooting"; - choices3[0] = "Single Exposure"; - choices3[1] = "Multiple Exposure"; - choices3[15] = "Interval Movie"; - choices3[16] = "HDR"; - choices3[32] = "HDR Strong 1"; - choices3[48] = "HDR Strong 2"; - choices3[64] = "HDR Strong 3"; - choices3[224] = "HDR Auto"; - choices3[255] = "Video"; - } - virtual std::string toString (Tag* t) { - std::map::iterator r = choices.find (t->toInt(0,BYTE)); - std::map::iterator r1 = choices1.find (t->toInt(1,BYTE)); - std::map::iterator r2 = choices2.find (t->toInt(2,BYTE)); - std::map::iterator r3 = choices3.find (t->toInt(3,BYTE)); + PADriveModeInterpreter() + { + choices[0] = "Single-frame"; + choices[1] = "Continuous"; + choices[2] = "Continuous (Lo)"; + choices[3] = "Burst"; + choices[4] = "Continuous (Medium)"; + choices[255] = "Video"; + choices1[0] = "No Timer"; + choices1[1] = "Self-timer (12 s)"; + choices1[2] = "Self-timer (2 s)"; + choices1[15] = "Video"; + choices1[16] = "Mirror Lock-up"; + choices1[255] = "n/a"; + choices2[0] = "Shutter Button"; + choices2[1] = "Remote Control (3 s delay)"; + choices2[2] = "Remote Control"; + choices2[4] = "Remote Continuous Shooting"; + choices3[0] = "Single Exposure"; + choices3[1] = "Multiple Exposure"; + choices3[15] = "Interval Movie"; + choices3[16] = "HDR"; + choices3[32] = "HDR Strong 1"; + choices3[48] = "HDR Strong 2"; + choices3[64] = "HDR Strong 3"; + choices3[224] = "HDR Auto"; + choices3[255] = "Video"; + } + virtual std::string toString (Tag* t) + { + std::map::iterator r = choices.find (t->toInt(0, BYTE)); + std::map::iterator r1 = choices1.find (t->toInt(1, BYTE)); + std::map::iterator r2 = choices2.find (t->toInt(2, BYTE)); + std::map::iterator r3 = choices3.find (t->toInt(3, BYTE)); std::ostringstream s; - s << ((r !=choices.end())? r->second : ""); - s << ((r1!=choices1.end())? r1->second : "")<<" "; - s << ((r2!=choices2.end())? r2->second : "")<<" "; - s << ((r3!=choices3.end())? r3->second : "")<<" "; + s << ((r != choices.end()) ? r->second : ""); + s << ((r1 != choices1.end()) ? r1->second : "") << " "; + s << ((r2 != choices2.end()) ? r2->second : "") << " "; + s << ((r3 != choices3.end()) ? r3->second : "") << " "; return s.str(); } }; PADriveModeInterpreter paDriveModeInterpreter; -class PAColorSpaceInterpreter: public ChoiceInterpreter{ +class PAColorSpaceInterpreter: public ChoiceInterpreter +{ public: - PAColorSpaceInterpreter(){ - choices[0] = "sRGB"; - choices[1] = "Adobe RGB"; - } + PAColorSpaceInterpreter() + { + choices[0] = "sRGB"; + choices[1] = "Adobe RGB"; + } }; PAColorSpaceInterpreter paColorSpaceInterpreter; -class PALensTypeInterpreter : public IntLensInterpreter< int > { - public: - PALensTypeInterpreter () { // From EXIFTOOL database 'Pentax.pm' V2.65 - choices.insert(p_t( 0+ 0, "M-42 or No Lens")); - choices.insert(p_t(256*1+ 0, "K,M Lens")); - choices.insert(p_t(256*2+ 0, "A Series Lens")); - choices.insert(p_t(256*3+ 0, "Sigma Lens")); - choices.insert(p_t(256*3+ 17, "smc PENTAX-FA SOFT 85mm f/2.8")); - choices.insert(p_t(256*3+ 18, "smc PENTAX-F 1.7X AF ADAPTER")); - choices.insert(p_t(256*3+ 19, "smc PENTAX-F 24-50mm f/4")); - choices.insert(p_t(256*3+ 20, "smc PENTAX-F 35-80mm f/4-5.6")); - choices.insert(p_t(256*3+ 21, "smc PENTAX-F 80-200mm f/4.7-5.6")); - choices.insert(p_t(256*3+ 22, "smc PENTAX-F FISH-EYE 17-28mm f/3.5-4.5")); - choices.insert(p_t(256*3+ 23, "smc PENTAX-F 100-300mm f/4.5-5.6")); - choices.insert(p_t(256*3+ 23, "Sigma AF 28-300mm f/3.5-5.6 DL IF")); - choices.insert(p_t(256*3+ 23, "Sigma AF 28-300mm f/3.5-6.3 DG IF Macro")); - choices.insert(p_t(256*3+ 24, "smc PENTAX-F 35-135mm f/3.5-4.5")); - choices.insert(p_t(256*3+ 25, "smc PENTAX-F 35-105mm f/4-5.6")); - choices.insert(p_t(256*3+ 25, "Sigma AF 28-300mm f/3.5-5.6 DL IF")); - choices.insert(p_t(256*3+ 25, "Sigma 55-200mm f/4-5.6 DC")); - choices.insert(p_t(256*3+ 25, "Sigma AF 28-300mm f/3.5-6.3 DG IF Macro")); - choices.insert(p_t(256*3+ 25, "Tokina 80-200mm f/2.8 ATX-Pro")); - choices.insert(p_t(256*3+ 26, "smc PENTAX-F* 250-600mm f/5.6 ED[IF]")); - choices.insert(p_t(256*3+ 27, "smc PENTAX-F 28-80mm f/3.5-4.5")); - choices.insert(p_t(256*3+ 27, "Tokina AT-X Pro AF 28-70mm f/2.6-2.8")); - choices.insert(p_t(256*3+ 28, "smc PENTAX-F 35-70mm f/3.5-4.5")); - choices.insert(p_t(256*3+ 28, "Tokina 19-35mm f/3.5-4.5 AF")); - choices.insert(p_t(256*3+ 28, "Tokina AT-X AF 400mm f/5.6")); - choices.insert(p_t(256*3+ 29, "PENTAX-F 28-80mm f/3.5-4.5")); - choices.insert(p_t(256*3+ 29, "Sigma AF 18-125mm f/3.5-5.6 DC")); - choices.insert(p_t(256*3+ 29, "Tokina AT-X PRO 28-70mm f/2.6-2.8")); - choices.insert(p_t(256*3+ 30, "PENTAX-F 70-200mm f/4-5.6")); - choices.insert(p_t(256*3+ 31, "smc PENTAX-F 70-210mm f/4-5.6")); - choices.insert(p_t(256*3+ 31, "Tokina AF 730 75-300mm f/4.5-5.6")); - choices.insert(p_t(256*3+ 31, "Takumar-F 70-210mm f/4-5.6")); - choices.insert(p_t(256*3+ 32, "smc PENTAX-F 50mm f/1.4")); - choices.insert(p_t(256*3+ 33, "smc PENTAX-F 50mm f/1.7")); - choices.insert(p_t(256*3+ 34, "smc PENTAX-F 135mm f/2.8 [IF]")); - choices.insert(p_t(256*3+ 35, "smc PENTAX-F 28mm f/2.8")); - choices.insert(p_t(256*3+ 36, "Sigma 20mm f/1.8 EX DG Aspherical RF")); - choices.insert(p_t(256*3+ 38, "smc PENTAX-F* 300mm f/4.5 ED[IF]")); - choices.insert(p_t(256*3+ 39, "smc PENTAX-F* 600mm f/4 ED[IF]")); - choices.insert(p_t(256*3+ 40, "smc PENTAX-F Macro 100mm f/2.8")); - choices.insert(p_t(256*3+ 41, "smc PENTAX-F Macro 50mm f/2.8")); - choices.insert(p_t(256*3+ 41, "Sigma 50mm f/2.8 Macro")); - choices.insert(p_t(256*3+ 44, "Sigma AF 10-20mm f/4-5.6 EX DC")); - choices.insert(p_t(256*3+ 44, "Sigma 12-24mm f/4.5-5.6 EX DG")); - choices.insert(p_t(256*3+ 44, "Sigma 17-70mm f/2.8-4.5 DC Macro")); - choices.insert(p_t(256*3+ 44, "Sigma 18-50mm f/3.5-5.6 DC")); - choices.insert(p_t(256*3+ 44, "Tamron 35-90mm f/4 AF")); - choices.insert(p_t(256*3+ 46, "Sigma APO 70-200mm f/2.8 EX")); - choices.insert(p_t(256*3+ 46, "Sigma EX APO 100-300mm f/4 IF")); - choices.insert(p_t(256*3+ 46, "Samsung/Schneider D-XENON 50-200mm f/4-5.6 ED")); - choices.insert(p_t(256*3+ 50, "smc PENTAX-FA 28-70mm f/4 AL")); - choices.insert(p_t(256*3+ 51, "Sigma 28mm f/1.8 EX DG Aspherical Macro")); - choices.insert(p_t(256*3+ 52, "smc PENTAX-FA 28-200mm f/3.8-5.6 AL[IF]")); - choices.insert(p_t(256*3+ 52, "Tamron AF LD 28-200mm f/3.8-5.6 [IF] Aspherical (171D)")); - choices.insert(p_t(256*3+ 53, "smc PENTAX-FA 28-80mm f/3.5-5.6 AL")); - choices.insert(p_t(256*3+ 247,"smc PENTAX-DA FISH-EYE 10-17mm f/3.5-4.5 ED[IF]")); - choices.insert(p_t(256*3+ 248,"smc PENTAX-DA 12-24mm f/4 ED AL[IF]")); - choices.insert(p_t(256*3+ 250,"smc PENTAX-DA 50-200mm f/4-5.6 ED")); - choices.insert(p_t(256*3+ 251,"smc PENTAX-DA 40mm f/2.8 Limited")); - choices.insert(p_t(256*3+ 252,"smc PENTAX-DA 18-55mm f/3.5-5.6 AL")); - choices.insert(p_t(256*3+ 253,"smc PENTAX-DA 14mm f/2.8 ED[IF]")); - choices.insert(p_t(256*3+ 254,"smc PENTAX-DA 16-45mm f/4 ED AL")); - choices.insert(p_t(256*3+ 255,"Sigma 18-200mm f/3.5-6.3 DC")); - choices.insert(p_t(256*3+ 255,"Sigma DL-II 35-80mm f/4-5.6")); - choices.insert(p_t(256*3+ 255,"Sigma DL Zoom 75-300mm f/4-5.6")); - choices.insert(p_t(256*3+ 255,"Sigma DF EX Aspherical 28-70mm f/2.8")); - choices.insert(p_t(256*3+ 255,"Sigma AF Tele 400mm f/5.6 Multi-coated")); - choices.insert(p_t(256*3+ 255,"Sigma 24-60mm f/2.8 EX DG")); - choices.insert(p_t(256*3+ 255,"Sigma 70-300mm f/4-5.6 Macro")); - choices.insert(p_t(256*3+ 255,"Sigma 55-200mm f/4-5.6 DC")); - choices.insert(p_t(256*3+ 255,"Sigma 18-50mm f/2.8 EX DC")); - choices.insert(p_t(256*4+ 1, "smc PENTAX-FA SOFT 28mm f/2.8")); - choices.insert(p_t(256*4+ 2, "smc PENTAX-FA 80-320mm f/4.5-5.6")); - choices.insert(p_t(256*4+ 3, "smc PENTAX-FA 43mm f/1.9 Limited")); - choices.insert(p_t(256*4+ 6, "smc PENTAX-FA 35-80mm f/4-5.6")); - choices.insert(p_t(256*4+ 12, "smc PENTAX-FA 50mm f/1.4")); - choices.insert(p_t(256*4+ 15, "smc PENTAX-FA 28-105mm f/4-5.6 [IF]")); - choices.insert(p_t(256*4+ 16, "Tamron AF 80-210mm f/4-5.6 (178D)")); - choices.insert(p_t(256*4+ 19, "Tamron SP AF 90mm f/2.8 (172E)")); - choices.insert(p_t(256*4+ 20, "smc PENTAX-FA 28-80mm f/3.5-5.6")); - choices.insert(p_t(256*4+ 21, "Cosina AF 100-300mm f/5.6-6.7")); - choices.insert(p_t(256*4+ 22, "Tokina 28-80mm f/3.5-5.6")); - choices.insert(p_t(256*4+ 23, "smc PENTAX-FA 20-35mm f/4 AL")); - choices.insert(p_t(256*4+ 24, "smc PENTAX-FA 77mm f/1.8 Limited")); - choices.insert(p_t(256*4+ 25, "Tamron SP AF 14mm f/2.8")); - choices.insert(p_t(256*4+ 26, "smc PENTAX-FA Macro 100mm f/3.5")); - choices.insert(p_t(256*4+ 26, "Cosina 100mm f/3.5 Macro")); - choices.insert(p_t(256*4+ 27, "Tamron AF 28-300mm f/3.5-6.3 LD Aspherical[IF] Macro (185D/285D)")); - choices.insert(p_t(256*4+ 28, "smc PENTAX-FA 35mm f/2 AL")); - choices.insert(p_t(256*4+ 29, "Tamron AF 28-200mm f/3.8-5.6 LD Super II Macro (371D)")); - choices.insert(p_t(256*4+ 34, "smc PENTAX-FA 24-90mm f/3.5-4.5 AL[IF]")); - choices.insert(p_t(256*4+ 35, "smc PENTAX-FA 100-300mm f/4.7-5.8")); - choices.insert(p_t(256*4+ 36, "Tamron AF70-300mm f/4-5.6 LD Macro")); - choices.insert(p_t(256*4+ 37, "Tamron SP AF 24-135mm f/3.5-5.6 AD AL (190D)")); - choices.insert(p_t(256*4+ 38, "smc PENTAX-FA 28-105mm f/3.2-4.5 AL[IF]")); - choices.insert(p_t(256*4+ 39, "smc PENTAX-FA 31mm f/1.8 AL Limited")); - choices.insert(p_t(256*4+ 41, "Tamron AF 28-200mm Super Zoom f/3.8-5.6 Aspherical XR [IF] Macro (A03)")); - choices.insert(p_t(256*4+ 43, "smc PENTAX-FA 28-90mm f/3.5-5.6")); - choices.insert(p_t(256*4+ 44, "smc PENTAX-FA J 75-300mm f/4.5-5.8 AL")); - choices.insert(p_t(256*4+ 45, "Tamron 28-300mm f/3.5-6.3 Ultra zoom XR")); - choices.insert(p_t(256*4+ 45, "Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical [IF] Macro")); - choices.insert(p_t(256*4+ 46, "smc PENTAX-FA J 28-80mm f/3.5-5.6 AL")); - choices.insert(p_t(256*4+ 47, "smc PENTAX-FA J 18-35mm f/4-5.6 AL")); - choices.insert(p_t(256*4+ 49, "Tamron SP AF 28-75mm f/2.8 XR Di (A09)")); - choices.insert(p_t(256*4+ 51, "smc PENTAX-D FA 50mm f/2.8 Macro")); - choices.insert(p_t(256*4+ 52, "smc PENTAX-D FA 100mm f/2.8 Macro")); - choices.insert(p_t(256*4+ 55, "Samsung/Schneider D-XENOGON 35mm f/2")); - choices.insert(p_t(256*4+ 56, "Samsung/Schneider D-XENON 100mm f/2.8 Macro")); - choices.insert(p_t(256*4+ 75, "Tamron SP AF 70-200mm f/2.8 Di LD [IF] Macro (A001)")); - choices.insert(p_t(256*4+ 214, "smc PENTAX-DA 35mm f/2.4 AL")); - choices.insert(p_t(256*4+ 229, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL II")); - choices.insert(p_t(256*4+ 230, "Tamron SP AF 17-50mm f/2.8 XR Di II")); - choices.insert(p_t(256*4+ 231, "smc PENTAX-DA 18-250mm f/3.5-6.3 ED AL [IF]")); - choices.insert(p_t(256*4+ 237, "Samsung/Schneider D-XENOGON 10-17mm f/3.5-4.5")); - choices.insert(p_t(256*4+ 239, "Samsung/Schneider D-XENON 12-24mm f/4 ED AL [IF]")); - choices.insert(p_t(256*4+ 242, "smc PENTAX-DA* 16-50mm f/2.8 ED AL [IF] SDM (SDM unused)")); - choices.insert(p_t(256*4+ 243, "smc PENTAX-DA 70mm f/2.4 Limited")); - choices.insert(p_t(256*4+ 244, "smc PENTAX-DA 21mm f/3.2 AL Limited")); - choices.insert(p_t(256*4+ 245, "Samsung/Schneider D-XENON 50-200mm f/4-5.6")); - choices.insert(p_t(256*4+ 246, "Samsung/Schneider D-XENON 18-55mm f/3.5-5.6")); - choices.insert(p_t(256*4+ 247, "smc PENTAX-DA 10-17mm f/3.5-4.5 ED [IF] Fisheye zoom")); - choices.insert(p_t(256*4+ 248, "smc PENTAX-DA 12-24mm f/4 ED AL [IF]")); - choices.insert(p_t(256*4+ 249, "Tamron 18-200mm f/3.5-6.3 XR DiII (A14)")); - choices.insert(p_t(256*4+ 250, "smc PENTAX-DA 50-200mm f/4-5.6 ED")); - choices.insert(p_t(256*4+ 251, "smc PENTAX-DA 40mm f/2.8 Limited")); - choices.insert(p_t(256*4+ 252, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL")); - choices.insert(p_t(256*4+ 253, "smc PENTAX-DA 14mm f/2.8 ED[IF]")); - choices.insert(p_t(256*4+ 254, "smc PENTAX-DA 16-45mm f/4 ED AL")); - choices.insert(p_t(256*5+ 1, "smc PENTAX-FA* 24mm f/2 AL[IF]")); - choices.insert(p_t(256*5+ 2, "smc PENTAX-FA 28mm f/2.8 AL")); - choices.insert(p_t(256*5+ 3, "smc PENTAX-FA 50mm f/1.7")); - choices.insert(p_t(256*5+ 4, "smc PENTAX-FA 50mm f/1.4")); - choices.insert(p_t(256*5+ 5, "smc PENTAX-FA* 600mm f/4 ED[IF]")); - choices.insert(p_t(256*5+ 6, "smc PENTAX-FA* 300mm f/4.5 ED[IF]")); - choices.insert(p_t(256*5+ 7, "smc PENTAX-FA 135mm f/2.8 [IF]")); - choices.insert(p_t(256*5+ 8, "smc PENTAX-FA Macro 50mm f/2.8")); - choices.insert(p_t(256*5+ 9, "smc PENTAX-FA Macro 100mm f/2.8")); - choices.insert(p_t(256*5+ 10, "smc PENTAX-FA* 85mm f/1.4 [IF]")); - choices.insert(p_t(256*5+ 11, "smc PENTAX-FA* 200mm f/2.8 ED[IF]")); - choices.insert(p_t(256*5+ 12, "smc PENTAX-FA 28-80mm f/3.5-4.7")); - choices.insert(p_t(256*5+ 13, "smc PENTAX-FA 70-200mm f/4-5.6")); - choices.insert(p_t(256*5+ 14, "smc PENTAX-FA* 250-600mm f/5.6 ED[IF]")); - choices.insert(p_t(256*5+ 15, "smc PENTAX-FA 28-105mm f/4-5.6")); - choices.insert(p_t(256*5+ 16, "smc PENTAX-FA 100-300mm f/4.5-5.6")); - choices.insert(p_t(256*5+ 98, "smc PENTAX-FA 100-300mm f/4.5-5.6")); - choices.insert(p_t(256*6+ 1, "smc PENTAX-FA* 85mm f/1.4 [IF]")); - choices.insert(p_t(256*6+ 2, "smc PENTAX-FA* 200mm f/2.8 ED[IF]")); - choices.insert(p_t(256*6+ 3, "smc PENTAX-FA* 300mm f/2.8 ED[IF]")); - choices.insert(p_t(256*6+ 4, "smc PENTAX-FA* 28-70mm f/2.8 AL")); - choices.insert(p_t(256*6+ 5, "smc PENTAX-FA* 80-200mm f/2.8 ED[IF]")); - choices.insert(p_t(256*6+ 6, "smc PENTAX-FA* 28-70mm f/2.8 AL")); - choices.insert(p_t(256*6+ 7, "smc PENTAX-FA* 80-200mm f/2.8 ED[IF]")); - choices.insert(p_t(256*6+ 8, "smc PENTAX-FA 28-70mm f/4 AL")); - choices.insert(p_t(256*6+ 9, "smc PENTAX-FA 20mm f/2.8")); - choices.insert(p_t(256*6+ 10, "smc PENTAX-FA* 400mm f/5.6 ED[IF]")); - choices.insert(p_t(256*6+ 13, "smc PENTAX-FA* 400mm f/5.6 ED[IF]")); - choices.insert(p_t(256*6+ 14, "smc PENTAX-FA* Macro 200mm f/4 ED[IF]")); - choices.insert(p_t(256*7+ 0, "smc PENTAX-DA 21mm f/3.2 AL Limited")); - choices.insert(p_t(256*7+ 58, "smc PENTAX-D FA Macro 100mm f/2.8 WR")); - choices.insert(p_t(256*7+ 75, "Tamron SP AF 70-200mm f/2.8 Di LD [IF] Macro (A001)")); - choices.insert(p_t(256*7+ 202, "smc PENTAX-DA L 18-55mm f/3.5-5.6 AL WR")); - choices.insert(p_t(256*7+ 204, "HD PENTAX-DA 15mm f/4 ED AL Limited")); - choices.insert(p_t(256*7+ 205, "HD PENTAX-DA 35mm f/2.8 Macro Limited")); - choices.insert(p_t(256*7+ 206, "HD PENTAX-DA 70mm f/2.4 Limited")); - choices.insert(p_t(256*7+ 207, "HD PENTAX-DA 21mm f/3.2 ED AL Limited")); - choices.insert(p_t(256*7+ 208, "HD PENTAX-DA 40mm f/2.8 Limited")); - choices.insert(p_t(256*7+ 212, "smc PENTAX-DA 50mm f/1.8")); - choices.insert(p_t(256*7+ 213, "smc PENTAX-DA 40mm f/2.8 XS")); - choices.insert(p_t(256*7+ 214, "smc PENTAX-DA 35mm f/2.4 AL")); - choices.insert(p_t(256*7+ 216, "smc PENTAX-DA L 55-300mm f/4-5.8 ED")); - choices.insert(p_t(256*7+ 217, "smc PENTAX-DA 50-200mm f/4-5.6 ED WR")); - choices.insert(p_t(256*7+ 218, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL WR")); - choices.insert(p_t(256*7+ 220, "Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical [IF]")); - choices.insert(p_t(256*7+ 221, "smc PENTAX-DA L 50-200mm f/4-5.6 ED")); - choices.insert(p_t(256*7+ 222, "smc PENTAX-DA L 18-55mm f/3.5-5.6")); - choices.insert(p_t(256*7+ 223, "Samsung/Schneider D-XENON 18-55mm f/3.5-5.6 II")); - choices.insert(p_t(256*7+ 224, "smc PENTAX-DA 15mm f/4 ED AL Limited")); - choices.insert(p_t(256*7+ 225, "Samsung/Schneider D-XENON 18-250mm f/3.5-6.3")); - choices.insert(p_t(256*7+ 226, "smc PENTAX-DA* 55mm f/1.4 SDM (SDM unused)")); - choices.insert(p_t(256*7+ 227, "smc PENTAX-DA* 60-250mm f/4 [IF] SDM (SDM unused)")); - choices.insert(p_t(256*7+ 228, "Samsung 16-45mm f/4 ED")); - choices.insert(p_t(256*7+ 229, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL II")); - choices.insert(p_t(256*7+ 230, "Tamron AF 17-50mm f/2.8 XR Di-II LD (Model A16)")); - choices.insert(p_t(256*7+ 231, "smc PENTAX-DA 18-250mm f/3.5-6.3 ED AL [IF]")); - choices.insert(p_t(256*7+ 233, "smc PENTAX-DA 35mm f/2.8 Macro Limited")); - choices.insert(p_t(256*7+ 234, "smc PENTAX-DA* 300mm f/4 ED [IF] SDM (SDM unused)")); - choices.insert(p_t(256*7+ 235, "smc PENTAX-DA* 200mm f/2.8 ED [IF] SDM (SDM unused)")); - choices.insert(p_t(256*7+ 236, "smc PENTAX-DA 55-300mm f/4-5.8 ED")); - choices.insert(p_t(256*7+ 238, "Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical [IF] Macro")); - choices.insert(p_t(256*7+ 241, "smc PENTAX-DA* 50-135mm f/2.8 ED [IF] SDM (SDM unused)")); - choices.insert(p_t(256*7+ 242, "smc PENTAX-DA* 16-50mm f/2.8 ED AL [IF] SDM (SDM unused)")); - choices.insert(p_t(256*7+ 243, "smc PENTAX-DA 70mm f/2.4 Limited")); - choices.insert(p_t(256*7+ 244, "smc PENTAX-DA 21mm f/3.2 AL Limited")); - choices.insert(p_t(256*8+ 3, "Sigma AF 18-125mm f/3.5-5.6 DC")); - choices.insert(p_t(256*8+ 4, "Sigma 50mm f/1.4 EX DG HSM")); - choices.insert(p_t(256*8+ 8, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); - choices.insert(p_t(256*8+ 11, "Sigma 10-20mm f/3.5 EX DC HSM")); - choices.insert(p_t(256*8+ 12, "Sigma 70-300mm f/4-5.6 DG OS")); - choices.insert(p_t(256*8+ 13, "Sigma 120-400mm f/4.5-5.6 APO DG OS HSM")); - choices.insert(p_t(256*8+ 14, "Sigma 17-70mm f/2.8-4.0 DC Macro OS HSM")); - choices.insert(p_t(256*8+ 15, "Sigma 150-500mm f/5-6.3 APO DG OS HSM")); - choices.insert(p_t(256*8+ 16, "Sigma 70-200mm f/2.8 EX DG Macro HSM II")); - choices.insert(p_t(256*8+ 17, "Sigma 50-500mm f/4.5-6.3 DG OS HSM")); - choices.insert(p_t(256*8+ 18, "Sigma 8-16mm f/4.5-5.6 DC HSM")); - choices.insert(p_t(256*8+ 21, "Sigma 17-50mm f/2.8 EX DC OS HSM")); - choices.insert(p_t(256*8+ 22, "Sigma 85mm f/1.4 EX DG HSM")); - choices.insert(p_t(256*8+ 23, "Sigma 70-200mm f/2.8 APO EX DG OS HSM")); - choices.insert(p_t(256*8+ 27, "Sigma 18-200mm f/3.5-6.3 II DC HSM")); - choices.insert(p_t(256*8+ 28, "Sigma 18-250mm f/3.5-6.3 DC Macro HSM")); - choices.insert(p_t(256*8+ 30, "Sigma 17-70mm f/2.8-4 DC Macro HSM | C")); // "| C" stands for "Contemporary" product line - choices.insert(p_t(256*8+ 210, "smc PENTAX-DA 18-270mm f/3.5-6.3 ED SDM")); - choices.insert(p_t(256*8+ 211, "HD PENTAX-DA 560mm f/5.6 ED AW")); - choices.insert(p_t(256*8+ 215, "smc PENTAX-DA 18-135mm f/3.5-5.6 ED AL [IF] DC WR")); - choices.insert(p_t(256*8+ 226, "smc PENTAX-DA* 55mm f/1.4 SDM")); - choices.insert(p_t(256*8+ 227, "smc PENTAX-DA* 60-250mm f/4 [IF] SDM")); - choices.insert(p_t(256*8+ 232, "smc PENTAX-DA 17-70mm f/4 AL [IF] SDM")); - choices.insert(p_t(256*8+ 234, "smc PENTAX-DA* 300mm f/4 ED [IF] SDM")); - choices.insert(p_t(256*8+ 235, "smc PENTAX-DA* 200mm f/2.8 ED [IF] SDM")); - choices.insert(p_t(256*8+ 241, "smc PENTAX-DA* 50-135mm f/2.8 ED [IF] SDM")); - choices.insert(p_t(256*8+ 242, "smc PENTAX-DA* 16-50mm f/2.8 ED AL [IF] SDM")); - choices.insert(p_t(256*8+ 255, "Sigma 70-200mm f/2.8 EX DG Macro HSM II")); - choices.insert(p_t(256*8+ 255, "Sigma 150-500mm f/5-6.3 DG APO [OS] HSM")); - choices.insert(p_t(256*8+ 255, "Sigma 50-150mm f/2.8 II APO EX DC HSM")); - choices.insert(p_t(256*8+ 255, "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye")); - choices.insert(p_t(256*8+ 255, "Sigma 50-200mm f/4-5.6 DC OS")); - choices.insert(p_t(256*8+ 255, "Sigma 24-70mm f/2.8 EX DG HSM")); - choices.insert(p_t(256*9+ 0, "645 Manual Lens")); - choices.insert(p_t(256*10+ 0, "645 A Series Lens")); - choices.insert(p_t(256*11+ 1, "smc PENTAX-FA 645 75mm f/2.8")); - choices.insert(p_t(256*11+ 2, "smc PENTAX-FA 645 45mm f/2.8")); - choices.insert(p_t(256*11+ 3, "smc PENTAX-FA* 645 300mm f/4 ED [IF]")); - choices.insert(p_t(256*11+ 4, "smc PENTAX-FA 645 45-85mm f/4.5")); - choices.insert(p_t(256*11+ 5, "smc PENTAX-FA 645 400mm f/5.6 ED [IF]")); - choices.insert(p_t(256*11+ 7, "smc PENTAX-FA 645 Macro 120mm f/4")); - choices.insert(p_t(256*11+ 8, "smc PENTAX-FA 645 80-160mm f/4.5")); - choices.insert(p_t(256*11+ 9, "smc PENTAX-FA 645 200mm f/4 [IF]")); - choices.insert(p_t(256*11+ 10, "smc PENTAX-FA 645 150mm f/2.8 [IF]")); - choices.insert(p_t(256*11+ 11, "smc PENTAX-FA 645 35mm f/3.5 AL [IF]")); - choices.insert(p_t(256*11+ 12, "smc PENTAX-FA 645 300mm f/5.6 ED [IF]")); - choices.insert(p_t(256*11+ 14, "smc PENTAX-FA 645 55-110mm f/5.6")); - choices.insert(p_t(256*11+ 16, "smc PENTAX-FA 645 33-55mm f/4.5 AL")); - choices.insert(p_t(256*11+ 17, "smc PENTAX-FA 645 150-300mm f/5.6 ED [IF]")); - choices.insert(p_t(256*13+ 18, "smc PENTAX-D FA 645 55mm f/2.8 AL [IF] SDM AW")); - choices.insert(p_t(256*13+ 19, "smc PENTAX-D FA 645 25mm f/4 AL [IF] SDM AW")); - choices.insert(p_t(256*13+ 20, "HD PENTAX-D FA 645 90mm f/2.8 ED AW SR")); - choices.insert(p_t(256*21+ 0, "Pentax Q Manual Lens")); - choices.insert(p_t(256*21+ 1, "01 Standard Prime 8.5mm f/1.9")); - choices.insert(p_t(256*21+ 2, "02 Standard Zoom 5-15mm f/2.8-4.5")); - choices.insert(p_t(256*21+ 6, "06 Telephoto Zoom 15-45mm f/2.8")); - choices.insert(p_t(256*21+ 7, "07 Mount Shield 11.5mm f/9")); - choices.insert(p_t(256*22+ 3, "03 Fish-eye 3.2mm f/5.6")); - choices.insert(p_t(256*22+ 4, "04 Toy Lens Wide 6.3mm f/7.1")); - choices.insert(p_t(256*22+ 5, "05 Toy Lens Telephoto 18mm f/8")); +class PALensTypeInterpreter : public IntLensInterpreter< int > +{ +public: + PALensTypeInterpreter () // From EXIFTOOL database 'Pentax.pm' V2.65 + { + choices.insert(p_t( 0 + 0, "M-42 or No Lens")); + choices.insert(p_t(256 * 1 + 0, "K,M Lens")); + choices.insert(p_t(256 * 2 + 0, "A Series Lens")); + choices.insert(p_t(256 * 3 + 0, "Sigma Lens")); + choices.insert(p_t(256 * 3 + 17, "smc PENTAX-FA SOFT 85mm f/2.8")); + choices.insert(p_t(256 * 3 + 18, "smc PENTAX-F 1.7X AF ADAPTER")); + choices.insert(p_t(256 * 3 + 19, "smc PENTAX-F 24-50mm f/4")); + choices.insert(p_t(256 * 3 + 20, "smc PENTAX-F 35-80mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 21, "smc PENTAX-F 80-200mm f/4.7-5.6")); + choices.insert(p_t(256 * 3 + 22, "smc PENTAX-F FISH-EYE 17-28mm f/3.5-4.5")); + choices.insert(p_t(256 * 3 + 23, "smc PENTAX-F 100-300mm f/4.5-5.6")); + choices.insert(p_t(256 * 3 + 23, "Sigma AF 28-300mm f/3.5-5.6 DL IF")); + choices.insert(p_t(256 * 3 + 23, "Sigma AF 28-300mm f/3.5-6.3 DG IF Macro")); + choices.insert(p_t(256 * 3 + 24, "smc PENTAX-F 35-135mm f/3.5-4.5")); + choices.insert(p_t(256 * 3 + 25, "smc PENTAX-F 35-105mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 25, "Sigma AF 28-300mm f/3.5-5.6 DL IF")); + choices.insert(p_t(256 * 3 + 25, "Sigma 55-200mm f/4-5.6 DC")); + choices.insert(p_t(256 * 3 + 25, "Sigma AF 28-300mm f/3.5-6.3 DG IF Macro")); + choices.insert(p_t(256 * 3 + 25, "Tokina 80-200mm f/2.8 ATX-Pro")); + choices.insert(p_t(256 * 3 + 26, "smc PENTAX-F* 250-600mm f/5.6 ED[IF]")); + choices.insert(p_t(256 * 3 + 27, "smc PENTAX-F 28-80mm f/3.5-4.5")); + choices.insert(p_t(256 * 3 + 27, "Tokina AT-X Pro AF 28-70mm f/2.6-2.8")); + choices.insert(p_t(256 * 3 + 28, "smc PENTAX-F 35-70mm f/3.5-4.5")); + choices.insert(p_t(256 * 3 + 28, "Tokina 19-35mm f/3.5-4.5 AF")); + choices.insert(p_t(256 * 3 + 28, "Tokina AT-X AF 400mm f/5.6")); + choices.insert(p_t(256 * 3 + 29, "PENTAX-F 28-80mm f/3.5-4.5")); + choices.insert(p_t(256 * 3 + 29, "Sigma AF 18-125mm f/3.5-5.6 DC")); + choices.insert(p_t(256 * 3 + 29, "Tokina AT-X PRO 28-70mm f/2.6-2.8")); + choices.insert(p_t(256 * 3 + 30, "PENTAX-F 70-200mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 31, "smc PENTAX-F 70-210mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 31, "Tokina AF 730 75-300mm f/4.5-5.6")); + choices.insert(p_t(256 * 3 + 31, "Takumar-F 70-210mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 32, "smc PENTAX-F 50mm f/1.4")); + choices.insert(p_t(256 * 3 + 33, "smc PENTAX-F 50mm f/1.7")); + choices.insert(p_t(256 * 3 + 34, "smc PENTAX-F 135mm f/2.8 [IF]")); + choices.insert(p_t(256 * 3 + 35, "smc PENTAX-F 28mm f/2.8")); + choices.insert(p_t(256 * 3 + 36, "Sigma 20mm f/1.8 EX DG Aspherical RF")); + choices.insert(p_t(256 * 3 + 38, "smc PENTAX-F* 300mm f/4.5 ED[IF]")); + choices.insert(p_t(256 * 3 + 39, "smc PENTAX-F* 600mm f/4 ED[IF]")); + choices.insert(p_t(256 * 3 + 40, "smc PENTAX-F Macro 100mm f/2.8")); + choices.insert(p_t(256 * 3 + 41, "smc PENTAX-F Macro 50mm f/2.8")); + choices.insert(p_t(256 * 3 + 41, "Sigma 50mm f/2.8 Macro")); + choices.insert(p_t(256 * 3 + 44, "Sigma AF 10-20mm f/4-5.6 EX DC")); + choices.insert(p_t(256 * 3 + 44, "Sigma 12-24mm f/4.5-5.6 EX DG")); + choices.insert(p_t(256 * 3 + 44, "Sigma 17-70mm f/2.8-4.5 DC Macro")); + choices.insert(p_t(256 * 3 + 44, "Sigma 18-50mm f/3.5-5.6 DC")); + choices.insert(p_t(256 * 3 + 44, "Tamron 35-90mm f/4 AF")); + choices.insert(p_t(256 * 3 + 46, "Sigma APO 70-200mm f/2.8 EX")); + choices.insert(p_t(256 * 3 + 46, "Sigma EX APO 100-300mm f/4 IF")); + choices.insert(p_t(256 * 3 + 46, "Samsung/Schneider D-XENON 50-200mm f/4-5.6 ED")); + choices.insert(p_t(256 * 3 + 50, "smc PENTAX-FA 28-70mm f/4 AL")); + choices.insert(p_t(256 * 3 + 51, "Sigma 28mm f/1.8 EX DG Aspherical Macro")); + choices.insert(p_t(256 * 3 + 52, "smc PENTAX-FA 28-200mm f/3.8-5.6 AL[IF]")); + choices.insert(p_t(256 * 3 + 52, "Tamron AF LD 28-200mm f/3.8-5.6 [IF] Aspherical (171D)")); + choices.insert(p_t(256 * 3 + 53, "smc PENTAX-FA 28-80mm f/3.5-5.6 AL")); + choices.insert(p_t(256 * 3 + 247, "smc PENTAX-DA FISH-EYE 10-17mm f/3.5-4.5 ED[IF]")); + choices.insert(p_t(256 * 3 + 248, "smc PENTAX-DA 12-24mm f/4 ED AL[IF]")); + choices.insert(p_t(256 * 3 + 250, "smc PENTAX-DA 50-200mm f/4-5.6 ED")); + choices.insert(p_t(256 * 3 + 251, "smc PENTAX-DA 40mm f/2.8 Limited")); + choices.insert(p_t(256 * 3 + 252, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL")); + choices.insert(p_t(256 * 3 + 253, "smc PENTAX-DA 14mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 3 + 254, "smc PENTAX-DA 16-45mm f/4 ED AL")); + choices.insert(p_t(256 * 3 + 255, "Sigma 18-200mm f/3.5-6.3 DC")); + choices.insert(p_t(256 * 3 + 255, "Sigma DL-II 35-80mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 255, "Sigma DL Zoom 75-300mm f/4-5.6")); + choices.insert(p_t(256 * 3 + 255, "Sigma DF EX Aspherical 28-70mm f/2.8")); + choices.insert(p_t(256 * 3 + 255, "Sigma AF Tele 400mm f/5.6 Multi-coated")); + choices.insert(p_t(256 * 3 + 255, "Sigma 24-60mm f/2.8 EX DG")); + choices.insert(p_t(256 * 3 + 255, "Sigma 70-300mm f/4-5.6 Macro")); + choices.insert(p_t(256 * 3 + 255, "Sigma 55-200mm f/4-5.6 DC")); + choices.insert(p_t(256 * 3 + 255, "Sigma 18-50mm f/2.8 EX DC")); + choices.insert(p_t(256 * 4 + 1, "smc PENTAX-FA SOFT 28mm f/2.8")); + choices.insert(p_t(256 * 4 + 2, "smc PENTAX-FA 80-320mm f/4.5-5.6")); + choices.insert(p_t(256 * 4 + 3, "smc PENTAX-FA 43mm f/1.9 Limited")); + choices.insert(p_t(256 * 4 + 6, "smc PENTAX-FA 35-80mm f/4-5.6")); + choices.insert(p_t(256 * 4 + 12, "smc PENTAX-FA 50mm f/1.4")); + choices.insert(p_t(256 * 4 + 15, "smc PENTAX-FA 28-105mm f/4-5.6 [IF]")); + choices.insert(p_t(256 * 4 + 16, "Tamron AF 80-210mm f/4-5.6 (178D)")); + choices.insert(p_t(256 * 4 + 19, "Tamron SP AF 90mm f/2.8 (172E)")); + choices.insert(p_t(256 * 4 + 20, "smc PENTAX-FA 28-80mm f/3.5-5.6")); + choices.insert(p_t(256 * 4 + 21, "Cosina AF 100-300mm f/5.6-6.7")); + choices.insert(p_t(256 * 4 + 22, "Tokina 28-80mm f/3.5-5.6")); + choices.insert(p_t(256 * 4 + 23, "smc PENTAX-FA 20-35mm f/4 AL")); + choices.insert(p_t(256 * 4 + 24, "smc PENTAX-FA 77mm f/1.8 Limited")); + choices.insert(p_t(256 * 4 + 25, "Tamron SP AF 14mm f/2.8")); + choices.insert(p_t(256 * 4 + 26, "smc PENTAX-FA Macro 100mm f/3.5")); + choices.insert(p_t(256 * 4 + 26, "Cosina 100mm f/3.5 Macro")); + choices.insert(p_t(256 * 4 + 27, "Tamron AF 28-300mm f/3.5-6.3 LD Aspherical[IF] Macro (185D/285D)")); + choices.insert(p_t(256 * 4 + 28, "smc PENTAX-FA 35mm f/2 AL")); + choices.insert(p_t(256 * 4 + 29, "Tamron AF 28-200mm f/3.8-5.6 LD Super II Macro (371D)")); + choices.insert(p_t(256 * 4 + 34, "smc PENTAX-FA 24-90mm f/3.5-4.5 AL[IF]")); + choices.insert(p_t(256 * 4 + 35, "smc PENTAX-FA 100-300mm f/4.7-5.8")); + choices.insert(p_t(256 * 4 + 36, "Tamron AF70-300mm f/4-5.6 LD Macro")); + choices.insert(p_t(256 * 4 + 37, "Tamron SP AF 24-135mm f/3.5-5.6 AD AL (190D)")); + choices.insert(p_t(256 * 4 + 38, "smc PENTAX-FA 28-105mm f/3.2-4.5 AL[IF]")); + choices.insert(p_t(256 * 4 + 39, "smc PENTAX-FA 31mm f/1.8 AL Limited")); + choices.insert(p_t(256 * 4 + 41, "Tamron AF 28-200mm Super Zoom f/3.8-5.6 Aspherical XR [IF] Macro (A03)")); + choices.insert(p_t(256 * 4 + 43, "smc PENTAX-FA 28-90mm f/3.5-5.6")); + choices.insert(p_t(256 * 4 + 44, "smc PENTAX-FA J 75-300mm f/4.5-5.8 AL")); + choices.insert(p_t(256 * 4 + 45, "Tamron 28-300mm f/3.5-6.3 Ultra zoom XR")); + choices.insert(p_t(256 * 4 + 45, "Tamron AF 28-300mm f/3.5-6.3 XR Di LD Aspherical [IF] Macro")); + choices.insert(p_t(256 * 4 + 46, "smc PENTAX-FA J 28-80mm f/3.5-5.6 AL")); + choices.insert(p_t(256 * 4 + 47, "smc PENTAX-FA J 18-35mm f/4-5.6 AL")); + choices.insert(p_t(256 * 4 + 49, "Tamron SP AF 28-75mm f/2.8 XR Di (A09)")); + choices.insert(p_t(256 * 4 + 51, "smc PENTAX-D FA 50mm f/2.8 Macro")); + choices.insert(p_t(256 * 4 + 52, "smc PENTAX-D FA 100mm f/2.8 Macro")); + choices.insert(p_t(256 * 4 + 55, "Samsung/Schneider D-XENOGON 35mm f/2")); + choices.insert(p_t(256 * 4 + 56, "Samsung/Schneider D-XENON 100mm f/2.8 Macro")); + choices.insert(p_t(256 * 4 + 75, "Tamron SP AF 70-200mm f/2.8 Di LD [IF] Macro (A001)")); + choices.insert(p_t(256 * 4 + 214, "smc PENTAX-DA 35mm f/2.4 AL")); + choices.insert(p_t(256 * 4 + 229, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL II")); + choices.insert(p_t(256 * 4 + 230, "Tamron SP AF 17-50mm f/2.8 XR Di II")); + choices.insert(p_t(256 * 4 + 231, "smc PENTAX-DA 18-250mm f/3.5-6.3 ED AL [IF]")); + choices.insert(p_t(256 * 4 + 237, "Samsung/Schneider D-XENOGON 10-17mm f/3.5-4.5")); + choices.insert(p_t(256 * 4 + 239, "Samsung/Schneider D-XENON 12-24mm f/4 ED AL [IF]")); + choices.insert(p_t(256 * 4 + 242, "smc PENTAX-DA* 16-50mm f/2.8 ED AL [IF] SDM (SDM unused)")); + choices.insert(p_t(256 * 4 + 243, "smc PENTAX-DA 70mm f/2.4 Limited")); + choices.insert(p_t(256 * 4 + 244, "smc PENTAX-DA 21mm f/3.2 AL Limited")); + choices.insert(p_t(256 * 4 + 245, "Samsung/Schneider D-XENON 50-200mm f/4-5.6")); + choices.insert(p_t(256 * 4 + 246, "Samsung/Schneider D-XENON 18-55mm f/3.5-5.6")); + choices.insert(p_t(256 * 4 + 247, "smc PENTAX-DA 10-17mm f/3.5-4.5 ED [IF] Fisheye zoom")); + choices.insert(p_t(256 * 4 + 248, "smc PENTAX-DA 12-24mm f/4 ED AL [IF]")); + choices.insert(p_t(256 * 4 + 249, "Tamron 18-200mm f/3.5-6.3 XR DiII (A14)")); + choices.insert(p_t(256 * 4 + 250, "smc PENTAX-DA 50-200mm f/4-5.6 ED")); + choices.insert(p_t(256 * 4 + 251, "smc PENTAX-DA 40mm f/2.8 Limited")); + choices.insert(p_t(256 * 4 + 252, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL")); + choices.insert(p_t(256 * 4 + 253, "smc PENTAX-DA 14mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 4 + 254, "smc PENTAX-DA 16-45mm f/4 ED AL")); + choices.insert(p_t(256 * 5 + 1, "smc PENTAX-FA* 24mm f/2 AL[IF]")); + choices.insert(p_t(256 * 5 + 2, "smc PENTAX-FA 28mm f/2.8 AL")); + choices.insert(p_t(256 * 5 + 3, "smc PENTAX-FA 50mm f/1.7")); + choices.insert(p_t(256 * 5 + 4, "smc PENTAX-FA 50mm f/1.4")); + choices.insert(p_t(256 * 5 + 5, "smc PENTAX-FA* 600mm f/4 ED[IF]")); + choices.insert(p_t(256 * 5 + 6, "smc PENTAX-FA* 300mm f/4.5 ED[IF]")); + choices.insert(p_t(256 * 5 + 7, "smc PENTAX-FA 135mm f/2.8 [IF]")); + choices.insert(p_t(256 * 5 + 8, "smc PENTAX-FA Macro 50mm f/2.8")); + choices.insert(p_t(256 * 5 + 9, "smc PENTAX-FA Macro 100mm f/2.8")); + choices.insert(p_t(256 * 5 + 10, "smc PENTAX-FA* 85mm f/1.4 [IF]")); + choices.insert(p_t(256 * 5 + 11, "smc PENTAX-FA* 200mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 5 + 12, "smc PENTAX-FA 28-80mm f/3.5-4.7")); + choices.insert(p_t(256 * 5 + 13, "smc PENTAX-FA 70-200mm f/4-5.6")); + choices.insert(p_t(256 * 5 + 14, "smc PENTAX-FA* 250-600mm f/5.6 ED[IF]")); + choices.insert(p_t(256 * 5 + 15, "smc PENTAX-FA 28-105mm f/4-5.6")); + choices.insert(p_t(256 * 5 + 16, "smc PENTAX-FA 100-300mm f/4.5-5.6")); + choices.insert(p_t(256 * 5 + 98, "smc PENTAX-FA 100-300mm f/4.5-5.6")); + choices.insert(p_t(256 * 6 + 1, "smc PENTAX-FA* 85mm f/1.4 [IF]")); + choices.insert(p_t(256 * 6 + 2, "smc PENTAX-FA* 200mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 6 + 3, "smc PENTAX-FA* 300mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 6 + 4, "smc PENTAX-FA* 28-70mm f/2.8 AL")); + choices.insert(p_t(256 * 6 + 5, "smc PENTAX-FA* 80-200mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 6 + 6, "smc PENTAX-FA* 28-70mm f/2.8 AL")); + choices.insert(p_t(256 * 6 + 7, "smc PENTAX-FA* 80-200mm f/2.8 ED[IF]")); + choices.insert(p_t(256 * 6 + 8, "smc PENTAX-FA 28-70mm f/4 AL")); + choices.insert(p_t(256 * 6 + 9, "smc PENTAX-FA 20mm f/2.8")); + choices.insert(p_t(256 * 6 + 10, "smc PENTAX-FA* 400mm f/5.6 ED[IF]")); + choices.insert(p_t(256 * 6 + 13, "smc PENTAX-FA* 400mm f/5.6 ED[IF]")); + choices.insert(p_t(256 * 6 + 14, "smc PENTAX-FA* Macro 200mm f/4 ED[IF]")); + choices.insert(p_t(256 * 7 + 0, "smc PENTAX-DA 21mm f/3.2 AL Limited")); + choices.insert(p_t(256 * 7 + 58, "smc PENTAX-D FA Macro 100mm f/2.8 WR")); + choices.insert(p_t(256 * 7 + 75, "Tamron SP AF 70-200mm f/2.8 Di LD [IF] Macro (A001)")); + choices.insert(p_t(256 * 7 + 202, "smc PENTAX-DA L 18-55mm f/3.5-5.6 AL WR")); + choices.insert(p_t(256 * 7 + 204, "HD PENTAX-DA 15mm f/4 ED AL Limited")); + choices.insert(p_t(256 * 7 + 205, "HD PENTAX-DA 35mm f/2.8 Macro Limited")); + choices.insert(p_t(256 * 7 + 206, "HD PENTAX-DA 70mm f/2.4 Limited")); + choices.insert(p_t(256 * 7 + 207, "HD PENTAX-DA 21mm f/3.2 ED AL Limited")); + choices.insert(p_t(256 * 7 + 208, "HD PENTAX-DA 40mm f/2.8 Limited")); + choices.insert(p_t(256 * 7 + 212, "smc PENTAX-DA 50mm f/1.8")); + choices.insert(p_t(256 * 7 + 213, "smc PENTAX-DA 40mm f/2.8 XS")); + choices.insert(p_t(256 * 7 + 214, "smc PENTAX-DA 35mm f/2.4 AL")); + choices.insert(p_t(256 * 7 + 216, "smc PENTAX-DA L 55-300mm f/4-5.8 ED")); + choices.insert(p_t(256 * 7 + 217, "smc PENTAX-DA 50-200mm f/4-5.6 ED WR")); + choices.insert(p_t(256 * 7 + 218, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL WR")); + choices.insert(p_t(256 * 7 + 220, "Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical [IF]")); + choices.insert(p_t(256 * 7 + 221, "smc PENTAX-DA L 50-200mm f/4-5.6 ED")); + choices.insert(p_t(256 * 7 + 222, "smc PENTAX-DA L 18-55mm f/3.5-5.6")); + choices.insert(p_t(256 * 7 + 223, "Samsung/Schneider D-XENON 18-55mm f/3.5-5.6 II")); + choices.insert(p_t(256 * 7 + 224, "smc PENTAX-DA 15mm f/4 ED AL Limited")); + choices.insert(p_t(256 * 7 + 225, "Samsung/Schneider D-XENON 18-250mm f/3.5-6.3")); + choices.insert(p_t(256 * 7 + 226, "smc PENTAX-DA* 55mm f/1.4 SDM (SDM unused)")); + choices.insert(p_t(256 * 7 + 227, "smc PENTAX-DA* 60-250mm f/4 [IF] SDM (SDM unused)")); + choices.insert(p_t(256 * 7 + 228, "Samsung 16-45mm f/4 ED")); + choices.insert(p_t(256 * 7 + 229, "smc PENTAX-DA 18-55mm f/3.5-5.6 AL II")); + choices.insert(p_t(256 * 7 + 230, "Tamron AF 17-50mm f/2.8 XR Di-II LD (Model A16)")); + choices.insert(p_t(256 * 7 + 231, "smc PENTAX-DA 18-250mm f/3.5-6.3 ED AL [IF]")); + choices.insert(p_t(256 * 7 + 233, "smc PENTAX-DA 35mm f/2.8 Macro Limited")); + choices.insert(p_t(256 * 7 + 234, "smc PENTAX-DA* 300mm f/4 ED [IF] SDM (SDM unused)")); + choices.insert(p_t(256 * 7 + 235, "smc PENTAX-DA* 200mm f/2.8 ED [IF] SDM (SDM unused)")); + choices.insert(p_t(256 * 7 + 236, "smc PENTAX-DA 55-300mm f/4-5.8 ED")); + choices.insert(p_t(256 * 7 + 238, "Tamron AF 18-250mm f/3.5-6.3 Di II LD Aspherical [IF] Macro")); + choices.insert(p_t(256 * 7 + 241, "smc PENTAX-DA* 50-135mm f/2.8 ED [IF] SDM (SDM unused)")); + choices.insert(p_t(256 * 7 + 242, "smc PENTAX-DA* 16-50mm f/2.8 ED AL [IF] SDM (SDM unused)")); + choices.insert(p_t(256 * 7 + 243, "smc PENTAX-DA 70mm f/2.4 Limited")); + choices.insert(p_t(256 * 7 + 244, "smc PENTAX-DA 21mm f/3.2 AL Limited")); + choices.insert(p_t(256 * 8 + 3, "Sigma AF 18-125mm f/3.5-5.6 DC")); + choices.insert(p_t(256 * 8 + 4, "Sigma 50mm f/1.4 EX DG HSM")); + choices.insert(p_t(256 * 8 + 8, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); + choices.insert(p_t(256 * 8 + 11, "Sigma 10-20mm f/3.5 EX DC HSM")); + choices.insert(p_t(256 * 8 + 12, "Sigma 70-300mm f/4-5.6 DG OS")); + choices.insert(p_t(256 * 8 + 13, "Sigma 120-400mm f/4.5-5.6 APO DG OS HSM")); + choices.insert(p_t(256 * 8 + 14, "Sigma 17-70mm f/2.8-4.0 DC Macro OS HSM")); + choices.insert(p_t(256 * 8 + 15, "Sigma 150-500mm f/5-6.3 APO DG OS HSM")); + choices.insert(p_t(256 * 8 + 16, "Sigma 70-200mm f/2.8 EX DG Macro HSM II")); + choices.insert(p_t(256 * 8 + 17, "Sigma 50-500mm f/4.5-6.3 DG OS HSM")); + choices.insert(p_t(256 * 8 + 18, "Sigma 8-16mm f/4.5-5.6 DC HSM")); + choices.insert(p_t(256 * 8 + 21, "Sigma 17-50mm f/2.8 EX DC OS HSM")); + choices.insert(p_t(256 * 8 + 22, "Sigma 85mm f/1.4 EX DG HSM")); + choices.insert(p_t(256 * 8 + 23, "Sigma 70-200mm f/2.8 APO EX DG OS HSM")); + choices.insert(p_t(256 * 8 + 27, "Sigma 18-200mm f/3.5-6.3 II DC HSM")); + choices.insert(p_t(256 * 8 + 28, "Sigma 18-250mm f/3.5-6.3 DC Macro HSM")); + choices.insert(p_t(256 * 8 + 30, "Sigma 17-70mm f/2.8-4 DC Macro HSM | C")); // "| C" stands for "Contemporary" product line + choices.insert(p_t(256 * 8 + 210, "smc PENTAX-DA 18-270mm f/3.5-6.3 ED SDM")); + choices.insert(p_t(256 * 8 + 211, "HD PENTAX-DA 560mm f/5.6 ED AW")); + choices.insert(p_t(256 * 8 + 215, "smc PENTAX-DA 18-135mm f/3.5-5.6 ED AL [IF] DC WR")); + choices.insert(p_t(256 * 8 + 226, "smc PENTAX-DA* 55mm f/1.4 SDM")); + choices.insert(p_t(256 * 8 + 227, "smc PENTAX-DA* 60-250mm f/4 [IF] SDM")); + choices.insert(p_t(256 * 8 + 232, "smc PENTAX-DA 17-70mm f/4 AL [IF] SDM")); + choices.insert(p_t(256 * 8 + 234, "smc PENTAX-DA* 300mm f/4 ED [IF] SDM")); + choices.insert(p_t(256 * 8 + 235, "smc PENTAX-DA* 200mm f/2.8 ED [IF] SDM")); + choices.insert(p_t(256 * 8 + 241, "smc PENTAX-DA* 50-135mm f/2.8 ED [IF] SDM")); + choices.insert(p_t(256 * 8 + 242, "smc PENTAX-DA* 16-50mm f/2.8 ED AL [IF] SDM")); + choices.insert(p_t(256 * 8 + 255, "Sigma 70-200mm f/2.8 EX DG Macro HSM II")); + choices.insert(p_t(256 * 8 + 255, "Sigma 150-500mm f/5-6.3 DG APO [OS] HSM")); + choices.insert(p_t(256 * 8 + 255, "Sigma 50-150mm f/2.8 II APO EX DC HSM")); + choices.insert(p_t(256 * 8 + 255, "Sigma 4.5mm f/2.8 EX DC HSM Circular Fisheye")); + choices.insert(p_t(256 * 8 + 255, "Sigma 50-200mm f/4-5.6 DC OS")); + choices.insert(p_t(256 * 8 + 255, "Sigma 24-70mm f/2.8 EX DG HSM")); + choices.insert(p_t(256 * 9 + 0, "645 Manual Lens")); + choices.insert(p_t(256 * 10 + 0, "645 A Series Lens")); + choices.insert(p_t(256 * 11 + 1, "smc PENTAX-FA 645 75mm f/2.8")); + choices.insert(p_t(256 * 11 + 2, "smc PENTAX-FA 645 45mm f/2.8")); + choices.insert(p_t(256 * 11 + 3, "smc PENTAX-FA* 645 300mm f/4 ED [IF]")); + choices.insert(p_t(256 * 11 + 4, "smc PENTAX-FA 645 45-85mm f/4.5")); + choices.insert(p_t(256 * 11 + 5, "smc PENTAX-FA 645 400mm f/5.6 ED [IF]")); + choices.insert(p_t(256 * 11 + 7, "smc PENTAX-FA 645 Macro 120mm f/4")); + choices.insert(p_t(256 * 11 + 8, "smc PENTAX-FA 645 80-160mm f/4.5")); + choices.insert(p_t(256 * 11 + 9, "smc PENTAX-FA 645 200mm f/4 [IF]")); + choices.insert(p_t(256 * 11 + 10, "smc PENTAX-FA 645 150mm f/2.8 [IF]")); + choices.insert(p_t(256 * 11 + 11, "smc PENTAX-FA 645 35mm f/3.5 AL [IF]")); + choices.insert(p_t(256 * 11 + 12, "smc PENTAX-FA 645 300mm f/5.6 ED [IF]")); + choices.insert(p_t(256 * 11 + 14, "smc PENTAX-FA 645 55-110mm f/5.6")); + choices.insert(p_t(256 * 11 + 16, "smc PENTAX-FA 645 33-55mm f/4.5 AL")); + choices.insert(p_t(256 * 11 + 17, "smc PENTAX-FA 645 150-300mm f/5.6 ED [IF]")); + choices.insert(p_t(256 * 13 + 18, "smc PENTAX-D FA 645 55mm f/2.8 AL [IF] SDM AW")); + choices.insert(p_t(256 * 13 + 19, "smc PENTAX-D FA 645 25mm f/4 AL [IF] SDM AW")); + choices.insert(p_t(256 * 13 + 20, "HD PENTAX-D FA 645 90mm f/2.8 ED AW SR")); + choices.insert(p_t(256 * 21 + 0, "Pentax Q Manual Lens")); + choices.insert(p_t(256 * 21 + 1, "01 Standard Prime 8.5mm f/1.9")); + choices.insert(p_t(256 * 21 + 2, "02 Standard Zoom 5-15mm f/2.8-4.5")); + choices.insert(p_t(256 * 21 + 6, "06 Telephoto Zoom 15-45mm f/2.8")); + choices.insert(p_t(256 * 21 + 7, "07 Mount Shield 11.5mm f/9")); + choices.insert(p_t(256 * 22 + 3, "03 Fish-eye 3.2mm f/5.6")); + choices.insert(p_t(256 * 22 + 4, "04 Toy Lens Wide 6.3mm f/7.1")); + choices.insert(p_t(256 * 22 + 5, "05 Toy Lens Telephoto 18mm f/8")); + } + virtual std::string toString (Tag* t) + { + double *liArray = NULL; + double maxApertureAtFocal = 0.; + double focalLength = 0.; + int lensID = 256 * t->toInt(0, BYTE) + t->toInt(1, BYTE); + TagDirectory *root = t->getParent()->getRoot(); + + if (root) { + + Tag *t1; + t1 = root->findTag("FocalLength"); // Should get tag 0x920A (rational64u) from the standard Exif tag list + + if( t1) { + focalLength = t1->toDouble(); // Focal Length + } + + t1 = root->findTag("MaxAperture"); + + if(t1) { + double maxAperture = t1->toDouble(); // MaxApertureValue at focal Length + + if (maxAperture != 0.) { + maxApertureAtFocal = maxAperture; + } else { + t1 = root->findTag("NominalMaxAperture"); + + if(t1) { + maxApertureAtFocal = t1->toDouble(); + } + } + } + + t1 = root->getTagP("LensInfo"); + + if(t1) { + liArray = t1->toDoubleArray(); + } + + // Focal length below 10mm are set to 0 by the camera in the standard Exif tag, so we'll look into the makernotes + // This value will have decimals, which reflects more precision... or imprecision, due to the packed form of this value, who knows? + if (focalLength == 0.) { + rtexif::TagDirectory* mnote = root->findTag("MakerNote")->getDirectory(); + rtexif::Tag* flt = mnote->getTagP("LensInfo/FocalLength"); + + if (flt) { + focalLength = flt->toDouble (); + } else if ((flt = mnote->getTagP ("FocalLength"))) { + focalLength = flt->toDouble(); + } + } } - virtual std::string toString (Tag* t) { - double *liArray = NULL; - double maxApertureAtFocal = 0.; - double focalLength = 0.; - int lensID = 256*t->toInt(0,BYTE) + t->toInt(1,BYTE); - TagDirectory *root=t->getParent()->getRoot(); - if (root){ - Tag *t1; - t1 = root->findTag("FocalLength"); // Should get tag 0x920A (rational64u) from the standard Exif tag list - if( t1) - focalLength = t1->toDouble(); // Focal Length + std::string retval = guess( lensID, focalLength, maxApertureAtFocal, liArray); - t1 = root->findTag("MaxAperture"); - if(t1){ - double maxAperture = t1->toDouble(); // MaxApertureValue at focal Length - if (maxAperture != 0.) - maxApertureAtFocal = maxAperture; - else { - t1 = root->findTag("NominalMaxAperture"); - if(t1) - maxApertureAtFocal = t1->toDouble(); - } - } - - t1 = root->getTagP("LensInfo"); - if(t1) - liArray = t1->toDoubleArray(); - - // Focal length below 10mm are set to 0 by the camera in the standard Exif tag, so we'll look into the makernotes - // This value will have decimals, which reflects more precision... or imprecision, due to the packed form of this value, who knows? - if (focalLength == 0.) { - rtexif::TagDirectory* mnote = root->findTag("MakerNote")->getDirectory(); - rtexif::Tag* flt=mnote->getTagP("LensInfo/FocalLength"); - if (flt) - focalLength = flt->toDouble (); - else if ((flt = mnote->getTagP ("FocalLength"))) - focalLength = flt->toDouble(); - } - } - std::string retval = guess( lensID, focalLength, maxApertureAtFocal, liArray); - if(liArray) - delete [] liArray; - return retval; + if(liArray) { + delete [] liArray; } + + return retval; + } }; PALensTypeInterpreter paLensTypeInterpreter; -class PASRResultInterpreter: public Interpreter { +class PASRResultInterpreter: public Interpreter +{ public: - PASRResultInterpreter(){ } - virtual std::string toString (Tag* t) { + PASRResultInterpreter() { } + virtual std::string toString (Tag* t) + { std::ostringstream str; - int b = t->toInt(0,BYTE); - if (!b) + int b = t->toInt(0, BYTE); + + if (!b) { str << "Not stabilized"; - else if (b & 1) + } else if (b & 1) { str << "Stabilized"; - else if (b & 64) - str << "Not Ready"; + } else if (b & 64) { + str << "Not Ready"; + } + return str.str(); - } + } }; PASRResultInterpreter paSRResultInterpreter; -class PAHighISONoiseInterpreter: public ChoiceInterpreter { +class PAHighISONoiseInterpreter: public ChoiceInterpreter +{ public: - PAHighISONoiseInterpreter(){ - choices[0] = "Off"; - choices[1] = "Weakest"; - choices[2] = "Weak"; - choices[3] = "Strong"; - } + PAHighISONoiseInterpreter() + { + choices[0] = "Off"; + choices[1] = "Weakest"; + choices[2] = "Weak"; + choices[3] = "Strong"; + } }; PAHighISONoiseInterpreter paHighISONoiseInterpreter; -class PAMonochromeFilterEffectInterpreter: public ChoiceInterpreter { +class PAMonochromeFilterEffectInterpreter: public ChoiceInterpreter +{ public: - PAMonochromeFilterEffectInterpreter(){ - choices[1] = "Green"; - choices[2] = "Yellow"; - choices[3] = "Orange"; - choices[4] = "Red"; - choices[5] = "Magenta"; - choices[6] = "Blue"; - choices[7] = "Cyan"; - choices[8] = "Infrared"; - choices[65535] = "None"; - } + PAMonochromeFilterEffectInterpreter() + { + choices[1] = "Green"; + choices[2] = "Yellow"; + choices[3] = "Orange"; + choices[4] = "Red"; + choices[5] = "Magenta"; + choices[6] = "Blue"; + choices[7] = "Cyan"; + choices[8] = "Infrared"; + choices[65535] = "None"; + } }; PAMonochromeFilterEffectInterpreter paMonochromeFilterEffectInterpreter; -class PAMonochromeToningInterpreter: public ChoiceInterpreter { +class PAMonochromeToningInterpreter: public ChoiceInterpreter +{ public: - PAMonochromeToningInterpreter(){ - choices[0] = "-4"; - choices[1] = "-3"; - choices[2] = "-2"; - choices[3] = "-1"; - choices[4] = "0"; - choices[5] = "1"; - choices[6] = "2"; - choices[7] = "3"; - choices[8] = "4"; - choices[65535] = "None"; - } + PAMonochromeToningInterpreter() + { + choices[0] = "-4"; + choices[1] = "-3"; + choices[2] = "-2"; + choices[3] = "-1"; + choices[4] = "0"; + choices[5] = "1"; + choices[6] = "2"; + choices[7] = "3"; + choices[8] = "4"; + choices[65535] = "None"; + } }; PAMonochromeToningInterpreter paMonochromeToningInterpreter; -class PAShadowCorrectionInterpreter: public ChoiceInterpreter { +class PAShadowCorrectionInterpreter: public ChoiceInterpreter +{ public: - PAShadowCorrectionInterpreter(){ - choices[ 0 ] = "Off"; - choices[ 1 ] = "On"; - choices[ 2 ] = "Auto 2"; - choices[ 1<<8 | 1 ] = "Weak"; - choices[ 1<<8 | 2 ] = "Normal"; - choices[ 1<<8 | 3 ] = "Strong"; - choices[ 2<<8 | 4 ] = "Auto"; - } + PAShadowCorrectionInterpreter() + { + choices[ 0 ] = "Off"; + choices[ 1 ] = "On"; + choices[ 2 ] = "Auto 2"; + choices[ 1 << 8 | 1 ] = "Weak"; + choices[ 1 << 8 | 2 ] = "Normal"; + choices[ 1 << 8 | 3 ] = "Strong"; + choices[ 2 << 8 | 4 ] = "Auto"; + } - virtual std::string toString (Tag* t) { - int idx = 0; - if (t->getCount() == 1) - idx = t->toInt(0,BYTE); - else if (t->getCount() == 2) - idx = t->toInt(0,BYTE) << 8 | t->toInt(1,BYTE); + virtual std::string toString (Tag* t) + { + int idx = 0; - std::map::iterator r = choices.find (idx); - std::ostringstream s; - s << ((r !=choices.end())? r->second : "n/a"); - return s.str(); - } + if (t->getCount() == 1) { + idx = t->toInt(0, BYTE); + } else if (t->getCount() == 2) { + idx = t->toInt(0, BYTE) << 8 | t->toInt(1, BYTE); + } + + std::map::iterator r = choices.find (idx); + std::ostringstream s; + s << ((r != choices.end()) ? r->second : "n/a"); + return s.str(); + } }; PAShadowCorrectionInterpreter paShadowCorrectionInterpreter; -class PAISOAutoParametersInterpreter: public ChoiceInterpreter { +class PAISOAutoParametersInterpreter: public ChoiceInterpreter +{ public: - PAISOAutoParametersInterpreter(){ - choices[1] = "Slow"; - choices[2] = "Standard"; - choices[3] = "Fast"; - } - virtual std::string toString (Tag* t) { - std::map::iterator r = choices.find (t->toInt(0,BYTE)); - std::ostringstream s; - s << ((r !=choices.end())? r->second : "n/a"); - return s.str(); - } + PAISOAutoParametersInterpreter() + { + choices[1] = "Slow"; + choices[2] = "Standard"; + choices[3] = "Fast"; + } + virtual std::string toString (Tag* t) + { + std::map::iterator r = choices.find (t->toInt(0, BYTE)); + std::ostringstream s; + s << ((r != choices.end()) ? r->second : "n/a"); + return s.str(); + } }; PAISOAutoParametersInterpreter paISOAutoParametersInterpreter; -class PABleachBypassToningInterpreter: public ChoiceInterpreter { +class PABleachBypassToningInterpreter: public ChoiceInterpreter +{ public: - PABleachBypassToningInterpreter(){ - choices[1] = "Green"; - choices[2] = "Yellow"; - choices[3] = "Orange"; - choices[4] = "Red"; - choices[5] = "Magenta"; - choices[6] = "Purple"; - choices[7] = "Blue"; - choices[8] = "Cyan"; - choices[65535] = "Off"; - } + PABleachBypassToningInterpreter() + { + choices[1] = "Green"; + choices[2] = "Yellow"; + choices[3] = "Orange"; + choices[4] = "Red"; + choices[5] = "Magenta"; + choices[6] = "Purple"; + choices[7] = "Blue"; + choices[8] = "Cyan"; + choices[65535] = "Off"; + } }; PABleachBypassToningInterpreter paBleachBypassToningInterpreter; -class PABlurControlInterpreter: public ChoiceInterpreter { +class PABlurControlInterpreter: public ChoiceInterpreter +{ public: - PABlurControlInterpreter(){ - choices[0] = "Off"; - choices[1] = "Low"; - choices[2] = "Medium"; - choices[3] = "High"; - } - virtual std::string toString (Tag* t) { - std::map::iterator r = choices.find (t->toInt(0,BYTE)); - std::ostringstream s; - s << ((r !=choices.end())? r->second : "n/a"); - return s.str(); - } + PABlurControlInterpreter() + { + choices[0] = "Off"; + choices[1] = "Low"; + choices[2] = "Medium"; + choices[3] = "High"; + } + virtual std::string toString (Tag* t) + { + std::map::iterator r = choices.find (t->toInt(0, BYTE)); + std::ostringstream s; + s << ((r != choices.end()) ? r->second : "n/a"); + return s.str(); + } }; PABlurControlInterpreter paBlurControlInterpreter; -class PAHDRInterpreter: public ChoiceInterpreter { - std::map choices1; - std::map choices2; +class PAHDRInterpreter: public ChoiceInterpreter +{ + std::map choices1; + std::map choices2; public: - PAHDRInterpreter(){ - choices[0] = "Off"; - choices[1] = "HDR Auto"; - choices[2] = "HDR 1"; - choices[3] = "HDR 2"; - choices[4] = "HDR 3"; + PAHDRInterpreter() + { + choices[0] = "Off"; + choices[1] = "HDR Auto"; + choices[2] = "HDR 1"; + choices[3] = "HDR 2"; + choices[4] = "HDR 3"; - choices1[0] = "Auto-align Off"; - choices1[1] = "Auto-align On"; + choices1[0] = "Auto-align Off"; + choices1[1] = "Auto-align On"; - choices2[0] = "n/a"; - choices2[1] = "1 EV"; - choices2[2] = "2 EV"; - choices2[4] = "3 EV"; - } - virtual std::string toString (Tag* t) { - std::map::iterator r = choices.find (t->toInt(0,BYTE)); - std::map::iterator r1 = choices1.find (t->toInt(1,BYTE)); - std::map::iterator r2 = choices2.find (t->toInt(2,BYTE)); - std::ostringstream s; - s << ((r !=choices.end() )? r->second : "") << std::endl; - s << ((r1!=choices1.end())? r1->second : "") << std::endl; - s << ((r2!=choices2.end())? r2->second : ""); - return s.str(); - } + choices2[0] = "n/a"; + choices2[1] = "1 EV"; + choices2[2] = "2 EV"; + choices2[4] = "3 EV"; + } + virtual std::string toString (Tag* t) + { + std::map::iterator r = choices.find (t->toInt(0, BYTE)); + std::map::iterator r1 = choices1.find (t->toInt(1, BYTE)); + std::map::iterator r2 = choices2.find (t->toInt(2, BYTE)); + std::ostringstream s; + s << ((r != choices.end() ) ? r->second : "") << std::endl; + s << ((r1 != choices1.end()) ? r1->second : "") << std::endl; + s << ((r2 != choices2.end()) ? r2->second : ""); + return s.str(); + } }; PAHDRInterpreter paHDRInterpreter; -class PACrossProcessInterpreter: public ChoiceInterpreter { +class PACrossProcessInterpreter: public ChoiceInterpreter +{ public: - PACrossProcessInterpreter(){ - choices[ 0] = "Off"; - choices[ 1] = "Randow"; - choices[ 2] = "Preset 1"; - choices[ 3] = "Preset 2"; - choices[ 4] = "Preset 3"; - choices[33] = "Favorite 1"; - choices[34] = "Favorite 2"; - choices[35] = "Favorite 3"; - } + PACrossProcessInterpreter() + { + choices[ 0] = "Off"; + choices[ 1] = "Randow"; + choices[ 2] = "Preset 1"; + choices[ 3] = "Preset 2"; + choices[ 4] = "Preset 3"; + choices[33] = "Favorite 1"; + choices[34] = "Favorite 2"; + choices[35] = "Favorite 3"; + } }; PACrossProcessInterpreter paCrossProcessInterpreter; -class PAPowerSourceInterpreter: public ChoiceInterpreter { +class PAPowerSourceInterpreter: public ChoiceInterpreter +{ public: - PAPowerSourceInterpreter(){ - choices[2] = "Body Battery"; - choices[3] = "Grip Battery "; - choices[4] = "External Power Supply"; - } + PAPowerSourceInterpreter() + { + choices[2] = "Body Battery"; + choices[3] = "Grip Battery "; + choices[4] = "External Power Supply"; + } }; PAPowerSourceInterpreter paPowerSourceInterpreter; -class PALensModelQInterpreter: public Interpreter { +class PALensModelQInterpreter: public Interpreter +{ public: - PALensModelQInterpreter(){} - virtual std::string toString (Tag* t){ + PALensModelQInterpreter() {} + virtual std::string toString (Tag* t) + { char buffer[31]; buffer[0] = 0; // return buffer; // TODO: how to get the string content!? @@ -1106,10 +1212,12 @@ public: }; PALensModelQInterpreter paLensModelQInterpreter; -class PALensInfoQInterpreter: public Interpreter { +class PALensInfoQInterpreter: public Interpreter +{ public: - PALensInfoQInterpreter(){} - virtual std::string toString (Tag* t){ + PALensInfoQInterpreter() {} + virtual std::string toString (Tag* t) + { char buffer[21]; buffer[0] = 0; return buffer; // TODO: how to get the string content!? @@ -1122,736 +1230,887 @@ public: }; PALensInfoQInterpreter paLensInfoQInterpreter; -class PAFlashExposureCompInterpreter: public Interpreter { +class PAFlashExposureCompInterpreter: public Interpreter +{ public: - PAFlashExposureCompInterpreter(){} - virtual std::string toString (Tag* t){ + PAFlashExposureCompInterpreter() {} + virtual std::string toString (Tag* t) + { int a; - if (t->getCount() == 1) a = t->toInt(0, SLONG) / 256; // int32u - else a = t->toInt(0, SBYTE) / 6; // int8u[2] + + if (t->getCount() == 1) { + a = t->toInt(0, SLONG) / 256; // int32u + } else { + a = t->toInt(0, SBYTE) / 6; // int8u[2] + } + char buffer[10]; sprintf (buffer, "%d", a ); return buffer; } - virtual double toDouble (Tag* t, int ofs){ + virtual double toDouble (Tag* t, int ofs) + { int a; - if (t->getCount() == 1) a = t->toInt(0, SLONG) / 256; // int32u - else a = t->toInt(0, SBYTE) / 6; // int8u[2] + + if (t->getCount() == 1) { + a = t->toInt(0, SLONG) / 256; // int32u + } else { + a = t->toInt(0, SBYTE) / 6; // int8u[2] + } + return double(a); } }; PAFlashExposureCompInterpreter paFlashExposureCompInterpreter; -class PAFocalLengthInterpreter: public Interpreter { +class PAFocalLengthInterpreter: public Interpreter +{ public: - PAFocalLengthInterpreter(){} - virtual std::string toString (Tag* t){ - double a = double(t->toInt(0,LONG)); - if(a>1.){ + PAFocalLengthInterpreter() {} + virtual std::string toString (Tag* t) + { + double a = double(t->toInt(0, LONG)); + + if(a > 1.) { char buffer[10]; - sprintf (buffer, "%.2f", a/100. ); + sprintf (buffer, "%.2f", a / 100. ); return buffer; - }else + } else { return "n/a"; + } } - virtual double toDouble (Tag* t, int ofs){ - double a = double(t->toInt(0,LONG)); - if(a>1.) - return a/100.; - else + virtual double toDouble (Tag* t, int ofs) + { + double a = double(t->toInt(0, LONG)); + + if(a > 1.) { + return a / 100.; + } else { return 0.; + } } }; PAFocalLengthInterpreter paFocalLengthInterpreter; -class PALensDataFocalLengthInterpreter: public Interpreter { +class PALensDataFocalLengthInterpreter: public Interpreter +{ public: - PALensDataFocalLengthInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,BYTE); - float b = float(10*int(a>>2)) * pow(4.f, float(int(a&0x03)-2)); - if(b>1.f){ + PALensDataFocalLengthInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, BYTE); + float b = float(10 * int(a >> 2)) * pow(4.f, float(int(a & 0x03) - 2)); + + if(b > 1.f) { char buffer[10]; sprintf (buffer, "%.2f", b ); return buffer; - }else + } else { return "n/a"; + } } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(ofs,BYTE); - float b = float(10*int(a>>2)) * pow(4.f, float(int(a&0x03)-2)); - if(b>1.f) + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(ofs, BYTE); + float b = float(10 * int(a >> 2)) * pow(4.f, float(int(a & 0x03) - 2)); + + if(b > 1.f) { return b; - else + } else { return 0.; + } } }; PALensDataFocalLengthInterpreter paLensDataFocalLengthInterpreter; -class PAISOfInterpreter: public Interpreter { - public: - PAISOfInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,BYTE); - char buffer[32]; - double v = 100.*exp(double(a-32)*log(2.)/8.); - sprintf (buffer, "%.1f", v ); - return buffer; - } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,BYTE); - return 100.*exp(double(a-32)*log(2.)/8.); - } +class PAISOfInterpreter: public Interpreter +{ +public: + PAISOfInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, BYTE); + char buffer[32]; + double v = 100.*exp(double(a - 32) * log(2.) / 8.); + sprintf (buffer, "%.1f", v ); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, BYTE); + return 100.*exp(double(a - 32) * log(2.) / 8.); + } }; PAISOfInterpreter paISOfInterpreter; -class PAMaxApertureInterpreter: public Interpreter { - public: - PAMaxApertureInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,BYTE); - a &= 0x7F; - if(a>1){ - char buffer[32]; - double v = pow(2.0, (a-1)/32.0); - if( v < 0. || v > 1000. ) return "undef"; - sprintf (buffer, "%.1f", v ); - return buffer; - }else - return "n/a"; - } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,BYTE); - a &= 0x7F; - if(a>1) - return pow(2.0, double(a-1)/32.0); - else - return 0.; - } +class PAMaxApertureInterpreter: public Interpreter +{ +public: + PAMaxApertureInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, BYTE); + a &= 0x7F; + + if(a > 1) { + char buffer[32]; + double v = pow(2.0, (a - 1) / 32.0); + + if( v < 0. || v > 1000. ) { + return "undef"; + } + + sprintf (buffer, "%.1f", v ); + return buffer; + } else { + return "n/a"; + } + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, BYTE); + a &= 0x7F; + + if(a > 1) { + return pow(2.0, double(a - 1) / 32.0); + } else { + return 0.; + } + } }; PAMaxApertureInterpreter paMaxApertureInterpreter; -class PAAEXvInterpreter: public Interpreter { - public: - PAAEXvInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,BYTE); - char buffer[32]; - double v = double(a-64)/8.; - sprintf (buffer, "%.1f", v ); - return buffer; - } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,BYTE); - return double(a-64)/8.; - } +class PAAEXvInterpreter: public Interpreter +{ +public: + PAAEXvInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, BYTE); + char buffer[32]; + double v = double(a - 64) / 8.; + sprintf (buffer, "%.1f", v ); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, BYTE); + return double(a - 64) / 8.; + } }; PAAEXvInterpreter paAEXvInterpreter; -class PAAEBXvInterpreter: public Interpreter { - public: - PAAEBXvInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,SBYTE); - char buffer[32]; - double v = double(a)/8.; - sprintf (buffer, "%.1f", v ); - return buffer; - } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,SBYTE); - return double(a)/8.; - } +class PAAEBXvInterpreter: public Interpreter +{ +public: + PAAEBXvInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, SBYTE); + char buffer[32]; + double v = double(a) / 8.; + sprintf (buffer, "%.1f", v ); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, SBYTE); + return double(a) / 8.; + } }; PAAEBXvInterpreter paAEBXvInterpreter; -class PAApertureInterpreter: public Interpreter { - public: - PAApertureInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,BYTE); - char buffer[32]; - double v = exp((double(a)-68.)*log(2.)/16.); - sprintf (buffer, "%.1f", v ); - return buffer; - } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,BYTE); - return exp((double(a)-68.)*log(2.)/16.); - } +class PAApertureInterpreter: public Interpreter +{ +public: + PAApertureInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, BYTE); + char buffer[32]; + double v = exp((double(a) - 68.) * log(2.) / 16.); + sprintf (buffer, "%.1f", v ); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, BYTE); + return exp((double(a) - 68.) * log(2.) / 16.); + } }; PAApertureInterpreter paApertureInterpreter; -class PAExposureTimeInterpreter: public Interpreter { - public: - PAExposureTimeInterpreter(){} - virtual std::string toString (Tag* t){ - int a = t->toInt(0,BYTE); - char buffer[32]; - double v = 24.*exp(-(double(a)-32.)*log(2.)/8.); - sprintf (buffer, "%.6f", v ); - return buffer; - } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,BYTE); - return 24.*exp(-(double(a)-32.)*log(2.)/8.); - } +class PAExposureTimeInterpreter: public Interpreter +{ +public: + PAExposureTimeInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(0, BYTE); + char buffer[32]; + double v = 24.*exp(-(double(a) - 32.) * log(2.) / 8.); + sprintf (buffer, "%.6f", v ); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, BYTE); + return 24.*exp(-(double(a) - 32.) * log(2.) / 8.); + } }; PAExposureTimeInterpreter paExposureTimeInterpreter; -class PANominalMinApertureInterpreter: public Interpreter { +class PANominalMinApertureInterpreter: public Interpreter +{ public: - PANominalMinApertureInterpreter(){} - virtual std::string toString (Tag* t){ - char buffer[32]; - int a = t->toInt(0,BYTE); - int mina = a & 0x0F; - sprintf (buffer, "%.1f", double(int(pow(2.0, double(mina+10)/4.0)+0.2))); - return buffer; + PANominalMinApertureInterpreter() {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + int a = t->toInt(0, BYTE); + int mina = a & 0x0F; + sprintf (buffer, "%.1f", double(int(pow(2.0, double(mina + 10) / 4.0) + 0.2))); + return buffer; } - virtual double toDouble (Tag* t, int ofs){ - int a = t->toInt(0,BYTE) & 0x0F; - return double(int(pow(2.0, double(a+10)/4.0)+0.2)); + virtual double toDouble (Tag* t, int ofs) + { + int a = t->toInt(0, BYTE) & 0x0F; + return double(int(pow(2.0, double(a + 10) / 4.0) + 0.2)); } }; PANominalMinApertureInterpreter paNominalMinApertureInterpreter; -class PANominalMaxApertureInterpreter: public Interpreter { +class PANominalMaxApertureInterpreter: public Interpreter +{ public: - PANominalMaxApertureInterpreter(){} - virtual std::string toString (Tag* t){ - char buffer[32]; - int a = t->toInt(0,BYTE); - int maxa = (a & 0xF0)>>4; - sprintf (buffer, "%.1f", double(int(pow(2.0, double(maxa)/4.0)+0.2)) ); - return buffer; + PANominalMaxApertureInterpreter() {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + int a = t->toInt(0, BYTE); + int maxa = (a & 0xF0) >> 4; + sprintf (buffer, "%.1f", double(int(pow(2.0, double(maxa) / 4.0) + 0.2)) ); + return buffer; } - virtual double toDouble (Tag* t, int ofs){ - int a = ( t->toInt(0,BYTE) & 0xF0)>>4; - return double(int(pow(2.0, double(a)/4.0)+0.2)); + virtual double toDouble (Tag* t, int ofs) + { + int a = ( t->toInt(0, BYTE) & 0xF0) >> 4; + return double(int(pow(2.0, double(a) / 4.0) + 0.2)); } }; PANominalMaxApertureInterpreter paNominalMaxApertureInterpreter; -class PAFlashStatusInterpreter: public ChoiceInterpreter { +class PAFlashStatusInterpreter: public ChoiceInterpreter +{ public: - PAFlashStatusInterpreter(){ - choices[0x0] = "Off"; - choices[0x2] = "External, Did not fire"; - choices[0x6] = "External, Fired"; - choices[0x9] = "Internal, Did not fire"; - choices[0xd] = "Internal, Fired"; - } + PAFlashStatusInterpreter() + { + choices[0x0] = "Off"; + choices[0x2] = "External, Did not fire"; + choices[0x6] = "External, Fired"; + choices[0x9] = "Internal, Did not fire"; + choices[0xd] = "Internal, Fired"; + } }; PAFlashStatusInterpreter paFlashStatusInterpreter; -class PAInternalFlashModeInterpreter: public ChoiceInterpreter { +class PAInternalFlashModeInterpreter: public ChoiceInterpreter +{ public: - PAInternalFlashModeInterpreter(){ - choices[0x0] = "n/a - Off-Auto-Aperture"; - choices[0x86] = "On, Wireless (Control)"; - choices[0x95] = "On, Wireless (Master)"; - choices[0xc0] = "On"; - choices[0xc1] = "On, Red-eye reduction"; - choices[0xc2] = "On, Auto"; - choices[0xc3] = "On, Auto, Red-eye reduction"; - choices[0xc8] = "On, Slow-sync"; - choices[0xc9] = "On, Slow-sync, Red-eye reduction"; - choices[0xca] = "On, Trailing-curtain Sync"; - choices[0xf0] = "Off, Normal"; - choices[0xf1] = "Off, Red-eye reduction"; - choices[0xf2] = "Off, Auto"; - choices[0xf3] = "Off, Auto, Red-eye reduction"; - choices[0xf4] = "Off, (Unknown 0xf4)"; - choices[0xf5] = "Off, Wireless (Master)"; - choices[0xf6] = "Off, Wireless (Control)"; - choices[0xf8] = "Off, Slow-sync"; - choices[0xf9] = "Off, Slow-sync, Red-eye reduction"; - choices[0xfa] = "Off, Trailing-curtain Sync"; - } + PAInternalFlashModeInterpreter() + { + choices[0x0] = "n/a - Off-Auto-Aperture"; + choices[0x86] = "On, Wireless (Control)"; + choices[0x95] = "On, Wireless (Master)"; + choices[0xc0] = "On"; + choices[0xc1] = "On, Red-eye reduction"; + choices[0xc2] = "On, Auto"; + choices[0xc3] = "On, Auto, Red-eye reduction"; + choices[0xc8] = "On, Slow-sync"; + choices[0xc9] = "On, Slow-sync, Red-eye reduction"; + choices[0xca] = "On, Trailing-curtain Sync"; + choices[0xf0] = "Off, Normal"; + choices[0xf1] = "Off, Red-eye reduction"; + choices[0xf2] = "Off, Auto"; + choices[0xf3] = "Off, Auto, Red-eye reduction"; + choices[0xf4] = "Off, (Unknown 0xf4)"; + choices[0xf5] = "Off, Wireless (Master)"; + choices[0xf6] = "Off, Wireless (Control)"; + choices[0xf8] = "Off, Slow-sync"; + choices[0xf9] = "Off, Slow-sync, Red-eye reduction"; + choices[0xfa] = "Off, Trailing-curtain Sync"; + } }; PAInternalFlashModeInterpreter paInternalFlashModeInterpreter; -class PAExternalFlashModeInterpreter: public ChoiceInterpreter { - public: - PAExternalFlashModeInterpreter(){ - choices[0x0 ]= "n/a - Off-Auto-Aperture"; - choices[0x3f] = "Off"; - choices[0x40] = "On, Auto"; - choices[0xbf] = "On, Flash Problem"; - choices[0xc0] = "On, Manual"; - choices[0xc4] = "On, P-TTL Auto"; - choices[0xc5] = "On, Contrast-control Sync"; - choices[0xc6] = "On, High-speed Sync"; - choices[0xcc] = "On, Wireless"; - choices[0xcd] = "On, Wireless, High-speed Sync"; - } +class PAExternalFlashModeInterpreter: public ChoiceInterpreter +{ +public: + PAExternalFlashModeInterpreter() + { + choices[0x0 ] = "n/a - Off-Auto-Aperture"; + choices[0x3f] = "Off"; + choices[0x40] = "On, Auto"; + choices[0xbf] = "On, Flash Problem"; + choices[0xc0] = "On, Manual"; + choices[0xc4] = "On, P-TTL Auto"; + choices[0xc5] = "On, Contrast-control Sync"; + choices[0xc6] = "On, High-speed Sync"; + choices[0xcc] = "On, Wireless"; + choices[0xcd] = "On, Wireless, High-speed Sync"; + } }; PAExternalFlashModeInterpreter paExternalFlashModeInterpreter; -class PAExternalFlashExposureCompInterpreter: public ChoiceInterpreter { - public: - PAExternalFlashExposureCompInterpreter(){ - choices[0] = "n/a"; - choices[144] = "n/a (Manual Mode)"; - choices[164] = "-3.0"; - choices[167] = "-2.5"; - choices[168] = "-2.0"; - choices[171] = "-1.5"; - choices[172] = "-1.0"; - choices[175] = "-0.5"; - choices[176] = "0"; - choices[179] = "+0.5"; - choices[180] = "+1.0"; - } +class PAExternalFlashExposureCompInterpreter: public ChoiceInterpreter +{ +public: + PAExternalFlashExposureCompInterpreter() + { + choices[0] = "n/a"; + choices[144] = "n/a (Manual Mode)"; + choices[164] = "-3.0"; + choices[167] = "-2.5"; + choices[168] = "-2.0"; + choices[171] = "-1.5"; + choices[172] = "-1.0"; + choices[175] = "-0.5"; + choices[176] = "0"; + choices[179] = "+0.5"; + choices[180] = "+1.0"; + } }; PAExternalFlashExposureCompInterpreter paExternalFlashExposureCompInterpreter; -class PAExternalFlashBounceInterpreter: public ChoiceInterpreter { - public: - PAExternalFlashBounceInterpreter(){ - choices[0] = "n/a"; - choices[16] = "Direct"; - choices[48] = "Bonce"; - } +class PAExternalFlashBounceInterpreter: public ChoiceInterpreter +{ +public: + PAExternalFlashBounceInterpreter() + { + choices[0] = "n/a"; + choices[16] = "Direct"; + choices[48] = "Bonce"; + } }; PAExternalFlashBounceInterpreter paExternalFlashBounceInterpreter; -class PAExternalFlashGNInterpreter: public Interpreter { - public: - PAExternalFlashGNInterpreter(){} - virtual std::string toString (Tag* t) { - char buffer[1024]; - int b = t->toInt(0,BYTE) & 0x1F; - sprintf (buffer, "%.0f", pow(2.,b/16.+4) ); - return buffer; - } +class PAExternalFlashGNInterpreter: public Interpreter +{ +public: + PAExternalFlashGNInterpreter() {} + virtual std::string toString (Tag* t) + { + char buffer[1024]; + int b = t->toInt(0, BYTE) & 0x1F; + sprintf (buffer, "%.0f", pow(2., b / 16. + 4) ); + return buffer; + } }; PAExternalFlashGNInterpreter paExternalFlashGNInterpreter; -class PAEVStepsInterpreter:public Interpreter { +class PAEVStepsInterpreter: public Interpreter +{ public: - PAEVStepsInterpreter(){} - virtual std::string toString (Tag* t) { - std::ostringstream str; - if( t->toInt(0,BYTE) & 0x20 ) - str << "1/3 EV steps"; - else - str << "1/2 EV steps"; - return str.str(); - } + PAEVStepsInterpreter() {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + + if( t->toInt(0, BYTE) & 0x20 ) { + str << "1/3 EV steps"; + } else { + str << "1/2 EV steps"; + } + + return str.str(); + } }; PAEVStepsInterpreter paEVStepsInterpreter; -class PAEDialinInterpreter:public Interpreter { +class PAEDialinInterpreter: public Interpreter +{ public: - PAEDialinInterpreter(){} - virtual std::string toString (Tag* t) { - std::ostringstream str; - if( t->toInt(0,BYTE) & 0x40 ) - str << "P Shift"; - else - str << "Tv or Av"; - return str.str(); - } + PAEDialinInterpreter() {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + + if( t->toInt(0, BYTE) & 0x40 ) { + str << "P Shift"; + } else { + str << "Tv or Av"; + } + + return str.str(); + } }; PAEDialinInterpreter paEDialinInterpreter; -class PAApertureRingUseInterpreter: public Interpreter { +class PAApertureRingUseInterpreter: public Interpreter +{ public: - PAApertureRingUseInterpreter(){} - virtual std::string toString (Tag* t) { - std::ostringstream str; - if( t->toInt(0,BYTE) & 0x80 ) - str << "Permitted"; - else - str << "Prohibited"; - return str.str(); - } + PAApertureRingUseInterpreter() {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + + if( t->toInt(0, BYTE) & 0x80 ) { + str << "Permitted"; + } else { + str << "Prohibited"; + } + + return str.str(); + } }; PAApertureRingUseInterpreter paApertureRingUseInterpreter; -class PAFlashOptionInterpreter: public ChoiceInterpreter { +class PAFlashOptionInterpreter: public ChoiceInterpreter +{ public: - PAFlashOptionInterpreter(){ - choices[0x0] = "Normal"; - choices[0x1] = "Red-eye reduction"; - choices[0x2] = "Auto"; - choices[0x3] = "Auto, Red-eye reduction"; - choices[0x5] = "Wireless (Master)"; - choices[0x6] = "Wireless (Control)"; - choices[0x8] = "Slow-sync"; - choices[0x9] = "Slow-sync, Red-eye reduction"; - choices[0xa] = "Trailing-curtain Sync"; - } - virtual std::string toString (Tag* t) { - std::map::iterator r = choices.find (t->toInt(0,BYTE) >>4); - if (r!=choices.end()) - return r->second; - else { - char buffer[1024]; - t->toString (buffer); - return std::string (buffer); - } - } + PAFlashOptionInterpreter() + { + choices[0x0] = "Normal"; + choices[0x1] = "Red-eye reduction"; + choices[0x2] = "Auto"; + choices[0x3] = "Auto, Red-eye reduction"; + choices[0x5] = "Wireless (Master)"; + choices[0x6] = "Wireless (Control)"; + choices[0x8] = "Slow-sync"; + choices[0x9] = "Slow-sync, Red-eye reduction"; + choices[0xa] = "Trailing-curtain Sync"; + } + virtual std::string toString (Tag* t) + { + std::map::iterator r = choices.find (t->toInt(0, BYTE) >> 4); + + if (r != choices.end()) { + return r->second; + } else { + char buffer[1024]; + t->toString (buffer); + return std::string (buffer); + } + } }; PAFlashOptionInterpreter paFlashOptionInterpreter; -class PAMeteringMode2Interpreter: public Interpreter { +class PAMeteringMode2Interpreter: public Interpreter +{ public: - PAMeteringMode2Interpreter(){} - virtual std::string toString (Tag* t) { - std::ostringstream str; - int v = (t->toInt(0,BYTE) & 0xF); - if(!v) - str << "Multi-segment"; - else if(v&1) - str << "Center-weighted average"; - else if(v&2) - str << "Spot"; - return str.str(); - } + PAMeteringMode2Interpreter() {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + int v = (t->toInt(0, BYTE) & 0xF); + + if(!v) { + str << "Multi-segment"; + } else if(v & 1) { + str << "Center-weighted average"; + } else if(v & 2) { + str << "Spot"; + } + + return str.str(); + } }; PAMeteringMode2Interpreter paMeteringMode2Interpreter; -class PAExposureBracketStepSizeInterpreter: public ChoiceInterpreter { +class PAExposureBracketStepSizeInterpreter: public ChoiceInterpreter +{ public: - PAExposureBracketStepSizeInterpreter(){ - choices[3] = "0.3"; - choices[4] = "0.5"; - choices[5] = "0.7"; - choices[8] = "1.0"; - choices[11] = "1.3"; - choices[12] = "1.5"; - choices[13] = "1.7"; - choices[16] = "2.0"; - } + PAExposureBracketStepSizeInterpreter() + { + choices[3] = "0.3"; + choices[4] = "0.5"; + choices[5] = "0.7"; + choices[8] = "1.0"; + choices[11] = "1.3"; + choices[12] = "1.5"; + choices[13] = "1.7"; + choices[16] = "2.0"; + } }; PAExposureBracketStepSizeInterpreter paExposureBracketStepSizeInterpreter; -class PAPictureMode2Interpreter: public ChoiceInterpreter { +class PAPictureMode2Interpreter: public ChoiceInterpreter +{ public: - PAPictureMode2Interpreter(){ - choices[0] = "Scene Mode"; - choices[1] = "Auto PICT"; - choices[2] = "Program AE"; - choices[3] = "Green Mode"; - choices[4] = "Shutter Speed Priority"; - choices[5] = "Aperture Priority"; - choices[6] = "Program Tv Shift"; - choices[7] = "Program Av Shift"; - choices[8] = "Manual"; - choices[9] = "Bulb"; - choices[10] = "Aperture Priority, Off-Auto-Aperture"; - choices[11] = "Manual, Off-Auto-Aperture"; - choices[12] = "Bulb, Off-Auto-Aperture"; - choices[13] = "Shutter & Aperture Priority AE"; - choices[15] = "Sensitivity Priority AE"; - choices[16] = "Flash X-Sync Speed AE"; - } + PAPictureMode2Interpreter() + { + choices[0] = "Scene Mode"; + choices[1] = "Auto PICT"; + choices[2] = "Program AE"; + choices[3] = "Green Mode"; + choices[4] = "Shutter Speed Priority"; + choices[5] = "Aperture Priority"; + choices[6] = "Program Tv Shift"; + choices[7] = "Program Av Shift"; + choices[8] = "Manual"; + choices[9] = "Bulb"; + choices[10] = "Aperture Priority, Off-Auto-Aperture"; + choices[11] = "Manual, Off-Auto-Aperture"; + choices[12] = "Bulb, Off-Auto-Aperture"; + choices[13] = "Shutter & Aperture Priority AE"; + choices[15] = "Sensitivity Priority AE"; + choices[16] = "Flash X-Sync Speed AE"; + } }; PAPictureMode2Interpreter paPictureMode2Interpreter; -class PAProgramLineInterpreter: public Interpreter { +class PAProgramLineInterpreter: public Interpreter +{ public: - PAProgramLineInterpreter(){} - virtual std::string toString (Tag* t) { - std::ostringstream str; - int c = t->toInt(0,BYTE); - switch(c & 0xf){ - case 0: str << "Manual";break; - case 1: str << "AF-S";break; - case 2: str << "AF-C";break; - case 3: str << "AF-A";break; - } - if( (c & 0xF0) == 0) str << ", Point Selection Auto"; - else if( c & 0x20 ) str << ", Fixed Center Point Selected"; - else if( c & 0x10 ) str << ", Point Selected"; - return str.str(); - } + PAProgramLineInterpreter() {} + virtual std::string toString (Tag* t) + { + std::ostringstream str; + int c = t->toInt(0, BYTE); + + switch(c & 0xf) { + case 0: + str << "Manual"; + break; + + case 1: + str << "AF-S"; + break; + + case 2: + str << "AF-C"; + break; + + case 3: + str << "AF-A"; + break; + } + + if( (c & 0xF0) == 0) { + str << ", Point Selection Auto"; + } else if( c & 0x20 ) { + str << ", Fixed Center Point Selected"; + } else if( c & 0x10 ) { + str << ", Point Selected"; + } + + return str.str(); + } }; PAProgramLineInterpreter paProgramLineInterpreter; -class PAAFModeInterpreter: public Interpreter { +class PAAFModeInterpreter: public Interpreter +{ public: - PAAFModeInterpreter(){} - virtual std::string toString (Tag* t) { - switch(t->toInt(0,BYTE) & 0x3){ - case 0: return "Normal"; - case 1: return "Hi Speed"; - case 2: return "Depth"; - case 3: return "MTF"; - } - return"Normal"; - } + PAAFModeInterpreter() {} + virtual std::string toString (Tag* t) + { + switch(t->toInt(0, BYTE) & 0x3) { + case 0: + return "Normal"; + + case 1: + return "Hi Speed"; + + case 2: + return "Depth"; + + case 3: + return "MTF"; + } + + return"Normal"; + } }; PAAFModeInterpreter paAFModeInterpreter; -class PAAFPointSelectedInterpreter: public Interpreter { +class PAAFPointSelectedInterpreter: public Interpreter +{ public: - PAAFPointSelectedInterpreter(){} - virtual std::string toString (Tag* t) { - const char *ps[]={"Upper-left","Top","Upper-right","Left","Mid-left","Center","Mid-right","Right","Lower-left","Bottom","Lower-right"}; - int c = t->toInt(0,SHORT); - if( !c ) - return "Auto"; - else{ - for( int iBit=0; iBit<11; iBit++) - if( c & (1<toInt(0, SHORT); + + if( !c ) { + return "Auto"; + } else { + for( int iBit = 0; iBit < 11; iBit++) + if( c & (1 << iBit) ) { + return ps[iBit]; + } + + return "n/a"; + } + } }; PAAFPointSelectedInterpreter paAFPointSelectedInterpreter; -class PADriveMode2Interpreter: public Interpreter { +class PADriveMode2Interpreter: public Interpreter +{ public: - PADriveMode2Interpreter(){} - virtual std::string toString (Tag* t) { - int c = t->toInt(0,BYTE); - if( !c ) - return "Single-frame"; - else if( c & 0x01) - return "Continuous"; - else if( c & 0x04) - return "Self-timer (12 s)"; - else if( c & 0x08) - return "Self-timer (2 s)"; - else if( c & 0x10 ) - return "Remote Control (3 s delay)"; - else if( c & 0x20) - return "Remote Control"; - else if( c & 0x40) - return "Exposure Bracket"; - else if( c & 0x80) - return "Multiple Exposure"; - else - return "Unknown"; - } + PADriveMode2Interpreter() {} + virtual std::string toString (Tag* t) + { + int c = t->toInt(0, BYTE); + + if( !c ) { + return "Single-frame"; + } else if( c & 0x01) { + return "Continuous"; + } else if( c & 0x04) { + return "Self-timer (12 s)"; + } else if( c & 0x08) { + return "Self-timer (2 s)"; + } else if( c & 0x10 ) { + return "Remote Control (3 s delay)"; + } else if( c & 0x20) { + return "Remote Control"; + } else if( c & 0x40) { + return "Exposure Bracket"; + } else if( c & 0x80) { + return "Multiple Exposure"; + } else { + return "Unknown"; + } + } }; PADriveMode2Interpreter paDriveMode2Interpreter; const TagAttrib pentaxAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "PentaxVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0001, AUTO, "PentaxModelType", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0002, AUTO, "PreviewImageSize", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0003, AUTO, "PreviewImageLength", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0004, AUTO, "PreviewImageStart", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0005, AUTO, "PentaxModelID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0006, AUTO, "Date", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0007, AUTO, "Time", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0008, AUTO, "Quality", &paQualityInterpreter}, - {0, AC_WRITE, 0, 0, 0x0009, AUTO, "PentaxImageSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000b, AUTO, "PictureMode", &paPictureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x000c, AUTO, "FlashMode", &paFlashModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x000d, AUTO, "FocusMode", &paFocusModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x000e, AUTO, "AFPointSelected", &paAFPointInterpreter}, - {0, AC_WRITE, 0, 0, 0x000f, AUTO, "AFPointsInFocus", &paAFFocusInterpreter}, - {0, AC_WRITE, 0, 0, 0x0010, AUTO, "FocusPosition", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0012, AUTO, "ExposureTime", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0013, AUTO, "FNumber", &paFNumberInterpreter}, - {0, AC_WRITE, 0, 0, 0x0014, AUTO, "ISO", &paISOInterpreter}, - {0, AC_WRITE, 0, 0, 0x0015, AUTO, "LightReading", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0016, AUTO, "ExposureCompensation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0017, AUTO, "MeteringMode", &paMeteringModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0018, AUTO, "AutoBracketing", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0019, AUTO, "WhiteBalance", &paWhiteBalanceInterpreter}, - {0, AC_WRITE, 0, 0, 0x001a, AUTO, "WhiteBalanceMode", &paWhiteBalanceModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x001b, AUTO, "BlueBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001c, AUTO, "RedBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001d, AUTO, "FocalLength", &paFocalLengthInterpreter}, - {0, AC_WRITE, 0, 0, 0x001e, AUTO, "DigitalZoom", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001f, AUTO, "Saturation", &paSaturationInterpreter}, - {0, AC_WRITE, 0, 0, 0x0020, AUTO, "Contrast", &paContrastInterpreter}, - {0, AC_WRITE, 0, 0, 0x0021, AUTO, "Sharpness", &paSharpnessInterpreter}, - {0, AC_WRITE, 0, 0, 0x0022, AUTO, "WorldTimeLocation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0023, AUTO, "HometownCity", &stdInterpreter}, - {0, AC_NEW, 0, 0, 0x0024, AUTO, "DestinationCity", &stdInterpreter}, - {0, AC_NEW, 0, 0, 0x0025, AUTO, "HometownDST", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0026, AUTO, "DestinationDST", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0027, AUTO, "DSPFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0028, AUTO, "CPUFirmwareVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0029, AUTO, "FrameNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x002d, AUTO, "EffectiveLV", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0032, AUTO, "ImageProcessing", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0033, AUTO, "PictureMode", &paPictureModeInterpreter2}, - {0, AC_WRITE, 0, 0, 0x0034, AUTO, "DriveMode", &paDriveModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0037, AUTO, "ColorSpace", &paColorSpaceInterpreter}, - {0, AC_WRITE, 0, 0, 0x0038, AUTO, "ImageAreaOffset", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0039, AUTO, "RawImageSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x003c, AUTO, "AFPointsInFocus", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x003e, AUTO, "PreviewImageBorders", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x003f, AUTO, "LensType", &paLensTypeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0040, AUTO, "SensitivityAdjust", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0041, AUTO, "ImageProcessingCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0047, AUTO, "CameraTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0048, AUTO, "AELock", &paOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0049, AUTO, "NoiseReduction", &paOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x004d, AUTO, "FlashExposureComp", &paFlashExposureCompInterpreter}, - {0, AC_WRITE, 0, 0, 0x004f, AUTO, "ImageTone", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0050, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxSRInfoAttribs, 0x005c, AUTO, "ShakeReductionInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x005d, AUTO, "ShutterCount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0069, AUTO, "DynamicRangeExpansion", &paOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0071, AUTO, "HighISONoiseReduction", &paHighISONoiseInterpreter}, - {0, AC_WRITE, 0, 0, 0x0072, AUTO, "AFAdjustment", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0073, AUTO, "MonochromeFilterEffect", &paMonochromeFilterEffectInterpreter}, - {0, AC_WRITE, 0, 0, 0x0074, AUTO, "MonochromeToning", &paMonochromeToningInterpreter}, - {0, AC_WRITE, 0, 0, 0x0076, AUTO, "FaceDetect", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0077, AUTO, "FaceDetectFrameSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0079, AUTO, "ShadowCorrection", &paShadowCorrectionInterpreter}, - {0, AC_WRITE, 0, 0, 0x007a, AUTO, "ISOAutoParameters", &paISOAutoParametersInterpreter}, - {0, AC_WRITE, 0, 0, 0x007b, AUTO, "CrossProcess", &paCrossProcessInterpreter}, - {0, AC_WRITE, 0, pentaxLensCorrAttribs, 0x007d, AUTO, "LensCorr", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x007f, AUTO, "BleachBypassToning", &paBleachBypassToningInterpreter}, - {0, AC_WRITE, 0, 0, 0x0082, AUTO, "BlurControl", &paBlurControlInterpreter}, - {0, AC_WRITE, 0, 0, 0x0085, AUTO, "HDR", &paHDRInterpreter}, - {0, AC_WRITE, 0, 0, 0x0088, AUTO, "NeutralDensityFilter", &paOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x008b, AUTO, "ISO", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0200, AUTO, "BlackPoint", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0201, AUTO, "WhitePoint", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0203, AUTO, "ColorMatrixA", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0204, AUTO, "ColorMatrixB", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxCameraSettingsAttribs, 0x0205, AUTO, "CameraSettings", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxAEInfoAttribs, 0x0206, AUTO, "AEInfo", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxLensDataAttribs, 0x0207, AUTO, "LensInfo", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxFlashInfoAttribs, 0x0208, AUTO, "FlashInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0209, AUTO, "AEMeteringSegments", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020a, AUTO, "FlashADump", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020b, AUTO, "FlashBDump", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020d, AUTO, "WB_RGGBLevelsDaylight", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020e, AUTO, "WB_RGGBLevelsShade", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x020f, AUTO, "WB_RGGBLevelsCloudy", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0210, AUTO, "WB_RGGBLevelsTungsten", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0211, AUTO, "WB_RGGBLevelsFluorescentD", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0212, AUTO, "WB_RGGBLevelsFluorescentN", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0213, AUTO, "WB_RGGBLevelsFluorescentW", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0214, AUTO, "WB_RGGBLevelsFlash", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxCameraInfoAttribs, 0x0215, AUTO, "CameraInfo", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxBatteryInfoAttribs, 0x0216, AUTO, "BatteryInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x021f, AUTO, "AFInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0222, AUTO, "ColorInfo", &stdInterpreter}, - {0, AC_WRITE, 0, pentaxLensInfoQAttribs, 0x0239, AUTO, "LensInfoQ", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03fe, AUTO, "DataDump", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x03ff, AUTO, "UnknownInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0402, AUTO, "ToneCurve", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0403, AUTO, "ToneCurves", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "PentaxVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0001, AUTO, "PentaxModelType", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0002, AUTO, "PreviewImageSize", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0003, AUTO, "PreviewImageLength", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0004, AUTO, "PreviewImageStart", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0005, AUTO, "PentaxModelID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0006, AUTO, "Date", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0007, AUTO, "Time", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0008, AUTO, "Quality", &paQualityInterpreter}, + {0, AC_WRITE, 0, 0, 0x0009, AUTO, "PentaxImageSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000b, AUTO, "PictureMode", &paPictureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x000c, AUTO, "FlashMode", &paFlashModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x000d, AUTO, "FocusMode", &paFocusModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x000e, AUTO, "AFPointSelected", &paAFPointInterpreter}, + {0, AC_WRITE, 0, 0, 0x000f, AUTO, "AFPointsInFocus", &paAFFocusInterpreter}, + {0, AC_WRITE, 0, 0, 0x0010, AUTO, "FocusPosition", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0012, AUTO, "ExposureTime", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0013, AUTO, "FNumber", &paFNumberInterpreter}, + {0, AC_WRITE, 0, 0, 0x0014, AUTO, "ISO", &paISOInterpreter}, + {0, AC_WRITE, 0, 0, 0x0015, AUTO, "LightReading", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0016, AUTO, "ExposureCompensation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0017, AUTO, "MeteringMode", &paMeteringModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0018, AUTO, "AutoBracketing", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0019, AUTO, "WhiteBalance", &paWhiteBalanceInterpreter}, + {0, AC_WRITE, 0, 0, 0x001a, AUTO, "WhiteBalanceMode", &paWhiteBalanceModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x001b, AUTO, "BlueBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001c, AUTO, "RedBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001d, AUTO, "FocalLength", &paFocalLengthInterpreter}, + {0, AC_WRITE, 0, 0, 0x001e, AUTO, "DigitalZoom", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001f, AUTO, "Saturation", &paSaturationInterpreter}, + {0, AC_WRITE, 0, 0, 0x0020, AUTO, "Contrast", &paContrastInterpreter}, + {0, AC_WRITE, 0, 0, 0x0021, AUTO, "Sharpness", &paSharpnessInterpreter}, + {0, AC_WRITE, 0, 0, 0x0022, AUTO, "WorldTimeLocation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0023, AUTO, "HometownCity", &stdInterpreter}, + {0, AC_NEW, 0, 0, 0x0024, AUTO, "DestinationCity", &stdInterpreter}, + {0, AC_NEW, 0, 0, 0x0025, AUTO, "HometownDST", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0026, AUTO, "DestinationDST", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0027, AUTO, "DSPFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0028, AUTO, "CPUFirmwareVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0029, AUTO, "FrameNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x002d, AUTO, "EffectiveLV", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0032, AUTO, "ImageProcessing", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0033, AUTO, "PictureMode", &paPictureModeInterpreter2}, + {0, AC_WRITE, 0, 0, 0x0034, AUTO, "DriveMode", &paDriveModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0037, AUTO, "ColorSpace", &paColorSpaceInterpreter}, + {0, AC_WRITE, 0, 0, 0x0038, AUTO, "ImageAreaOffset", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0039, AUTO, "RawImageSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x003c, AUTO, "AFPointsInFocus", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x003e, AUTO, "PreviewImageBorders", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x003f, AUTO, "LensType", &paLensTypeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0040, AUTO, "SensitivityAdjust", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0041, AUTO, "ImageProcessingCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0047, AUTO, "CameraTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0048, AUTO, "AELock", &paOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0049, AUTO, "NoiseReduction", &paOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x004d, AUTO, "FlashExposureComp", &paFlashExposureCompInterpreter}, + {0, AC_WRITE, 0, 0, 0x004f, AUTO, "ImageTone", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0050, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxSRInfoAttribs, 0x005c, AUTO, "ShakeReductionInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x005d, AUTO, "ShutterCount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0069, AUTO, "DynamicRangeExpansion", &paOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0071, AUTO, "HighISONoiseReduction", &paHighISONoiseInterpreter}, + {0, AC_WRITE, 0, 0, 0x0072, AUTO, "AFAdjustment", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0073, AUTO, "MonochromeFilterEffect", &paMonochromeFilterEffectInterpreter}, + {0, AC_WRITE, 0, 0, 0x0074, AUTO, "MonochromeToning", &paMonochromeToningInterpreter}, + {0, AC_WRITE, 0, 0, 0x0076, AUTO, "FaceDetect", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0077, AUTO, "FaceDetectFrameSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0079, AUTO, "ShadowCorrection", &paShadowCorrectionInterpreter}, + {0, AC_WRITE, 0, 0, 0x007a, AUTO, "ISOAutoParameters", &paISOAutoParametersInterpreter}, + {0, AC_WRITE, 0, 0, 0x007b, AUTO, "CrossProcess", &paCrossProcessInterpreter}, + {0, AC_WRITE, 0, pentaxLensCorrAttribs, 0x007d, AUTO, "LensCorr", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x007f, AUTO, "BleachBypassToning", &paBleachBypassToningInterpreter}, + {0, AC_WRITE, 0, 0, 0x0082, AUTO, "BlurControl", &paBlurControlInterpreter}, + {0, AC_WRITE, 0, 0, 0x0085, AUTO, "HDR", &paHDRInterpreter}, + {0, AC_WRITE, 0, 0, 0x0088, AUTO, "NeutralDensityFilter", &paOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x008b, AUTO, "ISO", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0200, AUTO, "BlackPoint", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0201, AUTO, "WhitePoint", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0203, AUTO, "ColorMatrixA", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0204, AUTO, "ColorMatrixB", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxCameraSettingsAttribs, 0x0205, AUTO, "CameraSettings", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxAEInfoAttribs, 0x0206, AUTO, "AEInfo", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxLensDataAttribs, 0x0207, AUTO, "LensInfo", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxFlashInfoAttribs, 0x0208, AUTO, "FlashInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0209, AUTO, "AEMeteringSegments", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020a, AUTO, "FlashADump", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020b, AUTO, "FlashBDump", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020d, AUTO, "WB_RGGBLevelsDaylight", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020e, AUTO, "WB_RGGBLevelsShade", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x020f, AUTO, "WB_RGGBLevelsCloudy", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0210, AUTO, "WB_RGGBLevelsTungsten", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0211, AUTO, "WB_RGGBLevelsFluorescentD", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0212, AUTO, "WB_RGGBLevelsFluorescentN", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0213, AUTO, "WB_RGGBLevelsFluorescentW", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0214, AUTO, "WB_RGGBLevelsFlash", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxCameraInfoAttribs, 0x0215, AUTO, "CameraInfo", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxBatteryInfoAttribs, 0x0216, AUTO, "BatteryInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x021f, AUTO, "AFInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0222, AUTO, "ColorInfo", &stdInterpreter}, + {0, AC_WRITE, 0, pentaxLensInfoQAttribs, 0x0239, AUTO, "LensInfoQ", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03fe, AUTO, "DataDump", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x03ff, AUTO, "UnknownInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0402, AUTO, "ToneCurve", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0403, AUTO, "ToneCurves", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxSRInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "SRResult", &paSRResultInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "ShakeReduction", &paShakeReductionInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "SRHalfPressTime", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "SRFocalLength", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "SRResult", &paSRResultInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ShakeReduction", &paShakeReductionInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "SRHalfPressTime", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "SRFocalLength", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxSRInfo2Attribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "SRResult", &paSRResultInterpreter}, // assuming it's the same interpreter, but that's not sure - {0, AC_WRITE, 0, 0, 1, AUTO, "ShakeReduction", &paShakeReduction2Interpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "SRResult", &paSRResultInterpreter}, // assuming it's the same interpreter, but that's not sure + {0, AC_WRITE, 0, 0, 1, AUTO, "ShakeReduction", &paShakeReduction2Interpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxLensDataAttribs[] = { - {0, AC_WRITE, 0, 0, 9, AUTO, "FocalLength", &paLensDataFocalLengthInterpreter}, - {0, AC_WRITE, 0, 0, 10, AUTO, "NominalMaxAperture", &paNominalMaxApertureInterpreter}, - {0, AC_WRITE, 0, 0, 10, AUTO, "NominalMinAperture", &paNominalMinApertureInterpreter}, - {0, AC_WRITE, 0, 0, 14, AUTO, "MaxAperture", &paMaxApertureInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 9, AUTO, "FocalLength", &paLensDataFocalLengthInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "NominalMaxAperture", &paNominalMaxApertureInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "NominalMinAperture", &paNominalMinApertureInterpreter}, + {0, AC_WRITE, 0, 0, 14, AUTO, "MaxAperture", &paMaxApertureInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxLensInfoQAttribs[] = { - {0, AC_WRITE, 0, 0, 12, AUTO, "LensModel", &paLensModelQInterpreter}, - {0, AC_WRITE, 0, 0, 42, AUTO, "LensInfo", &paLensInfoQInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 12, AUTO, "LensModel", &paLensModelQInterpreter}, + {0, AC_WRITE, 0, 0, 42, AUTO, "LensInfo", &paLensInfoQInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxLensCorrAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "DistortionCorrection", &paOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "ChromaticAberrationCorrection", &paOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "VignettingCorrection", &paOnOffInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "DistortionCorrection", &paOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ChromaticAberrationCorrection", &paOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "VignettingCorrection", &paOnOffInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxCameraSettingsAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "PictureMode2", &paPictureMode2Interpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "ProgramLine", &paProgramLineInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "EVSteps", &paEVStepsInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "E-DialinProgram", &paEDialinInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "ApertureRing", &paApertureRingUseInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "FlashOptions", &paFlashOptionInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "MeteringMode2", &paMeteringMode2Interpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "AFMode", &paAFModeInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "AFPointSelected2", &paAFPointSelectedInterpreter}, - {0, AC_WRITE, 0, 0, 7, AUTO, "DriveMode2", &paDriveMode2Interpreter}, - {0, AC_WRITE, 0, 0, 8, AUTO, "ExposureBracketStepSize", &paExposureBracketStepSizeInterpreter}, - {0, AC_WRITE, 0, 0, 9, AUTO, "BracketShotNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 10, AUTO, "WhiteBalanceSet", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "PictureMode2", &paPictureMode2Interpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ProgramLine", &paProgramLineInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "EVSteps", &paEVStepsInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "E-DialinProgram", &paEDialinInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ApertureRing", &paApertureRingUseInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "FlashOptions", &paFlashOptionInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "MeteringMode2", &paMeteringMode2Interpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "AFMode", &paAFModeInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "AFPointSelected2", &paAFPointSelectedInterpreter}, + {0, AC_WRITE, 0, 0, 7, AUTO, "DriveMode2", &paDriveMode2Interpreter}, + {0, AC_WRITE, 0, 0, 8, AUTO, "ExposureBracketStepSize", &paExposureBracketStepSizeInterpreter}, + {0, AC_WRITE, 0, 0, 9, AUTO, "BracketShotNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "WhiteBalanceSet", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxAEInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "AEExposureTime", &paExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "AEAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "AE_ISO", &paISOfInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "AEXv", &paAEXvInterpreter}, - {0, AC_WRITE, 0, 0, 4,SBYTE, "AEBXv", &paAEBXvInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "AEMinExposureTime", &paExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 6, AUTO, "AEProgramMode", &paAEProgramModeInterpreter}, - {0, AC_WRITE, 0, 0, 9, AUTO, "AEMaxAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 10, AUTO, "AEMaxAperture2", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 11, AUTO, "AEMinAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 12, AUTO, "AEMeteringMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 14,SBYTE, "FlashExposureCompSet", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "AEExposureTime", &paExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "AEAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "AE_ISO", &paISOfInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "AEXv", &paAEXvInterpreter}, + {0, AC_WRITE, 0, 0, 4, SBYTE, "AEBXv", &paAEBXvInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "AEMinExposureTime", &paExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 6, AUTO, "AEProgramMode", &paAEProgramModeInterpreter}, + {0, AC_WRITE, 0, 0, 9, AUTO, "AEMaxAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 10, AUTO, "AEMaxAperture2", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 11, AUTO, "AEMinAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 12, AUTO, "AEMeteringMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 14, SBYTE, "FlashExposureCompSet", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxAEInfo2Attribs[] = { - {0, AC_WRITE, 0, 0, 2, AUTO, "AEExposureTime", &paExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "AEAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "AE_ISO", &paISOfInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "AEXv", &paAEXvInterpreter}, - {0, AC_WRITE, 0, 0, 6,SBYTE, "AEBXv", &paAEBXvInterpreter}, - {0, AC_WRITE, 0, 0, 8,SBYTE, "AEError", &stdInterpreter}, - //{0, AC_WRITE, 0, 0, 11, AUTO, "AEApertureSteps", &}, - {0, AC_WRITE, 0, 0, 15, AUTO, "SceneMode", &paSceneModeInterpreter}, - {0, AC_WRITE, 0, 0, 16, AUTO, "AEMaxAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 17, AUTO, "AEMaxAperture2", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 18, AUTO, "AEMinAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 19, AUTO, "AEMinExposureTime", &paExposureTimeInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 2, AUTO, "AEExposureTime", &paExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "AEAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "AE_ISO", &paISOfInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "AEXv", &paAEXvInterpreter}, + {0, AC_WRITE, 0, 0, 6, SBYTE, "AEBXv", &paAEBXvInterpreter}, + {0, AC_WRITE, 0, 0, 8, SBYTE, "AEError", &stdInterpreter}, +//{0, AC_WRITE, 0, 0, 11, AUTO, "AEApertureSteps", &}, + {0, AC_WRITE, 0, 0, 15, AUTO, "SceneMode", &paSceneModeInterpreter}, + {0, AC_WRITE, 0, 0, 16, AUTO, "AEMaxAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 17, AUTO, "AEMaxAperture2", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 18, AUTO, "AEMinAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 19, AUTO, "AEMinExposureTime", &paExposureTimeInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxAEInfo3Attribs[] = { - {0, AC_WRITE, 0, 0, 16, AUTO, "AEExposureTime", &paExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 17, AUTO, "AEAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 18, AUTO, "AE_ISO", &paISOfInterpreter}, - {0, AC_WRITE, 0, 0, 28, AUTO, "AEMaxAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 29, AUTO, "AEMaxAperture2", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 30, AUTO, "AEMinAperture", &paApertureInterpreter}, - {0, AC_WRITE, 0, 0, 31, AUTO, "AEMinExposureTime", &paExposureTimeInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 16, AUTO, "AEExposureTime", &paExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 17, AUTO, "AEAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 18, AUTO, "AE_ISO", &paISOfInterpreter}, + {0, AC_WRITE, 0, 0, 28, AUTO, "AEMaxAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 29, AUTO, "AEMaxAperture2", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 30, AUTO, "AEMinAperture", &paApertureInterpreter}, + {0, AC_WRITE, 0, 0, 31, AUTO, "AEMinExposureTime", &paExposureTimeInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxFlashInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "FlashStatus", &paFlashStatusInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "InternalFlashMode", &paInternalFlashModeInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "ExternalFlashMode", &paExternalFlashModeInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "InternalFlashStrength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 24, AUTO, "ExternalFlashGuideNumber", &paExternalFlashGNInterpreter}, - {0, AC_WRITE, 0, 0, 25, AUTO, "ExternalFlashExposureComp", &paExternalFlashExposureCompInterpreter}, - {0, AC_WRITE, 0, 0, 26, AUTO, "ExternalFlashBounce", &paExternalFlashBounceInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "FlashStatus", &paFlashStatusInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "InternalFlashMode", &paInternalFlashModeInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "ExternalFlashMode", &paExternalFlashModeInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "InternalFlashStrength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 24, AUTO, "ExternalFlashGuideNumber", &paExternalFlashGNInterpreter}, + {0, AC_WRITE, 0, 0, 25, AUTO, "ExternalFlashExposureComp", &paExternalFlashExposureCompInterpreter}, + {0, AC_WRITE, 0, 0, 26, AUTO, "ExternalFlashBounce", &paExternalFlashBounceInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxBatteryInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "PowerSource", &paPowerSourceInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "BatteryStates", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "BatteryADBodyNoLoad", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "BatteryADBodyLoad", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "BatteryADGripNoLoad", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 5, AUTO, "BatteryADGripLoad", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "PowerSource", &paPowerSourceInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "BatteryStates", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "BatteryADBodyNoLoad", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "BatteryADBodyLoad", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "BatteryADGripNoLoad", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 5, AUTO, "BatteryADGripLoad", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib pentaxCameraInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 0, AUTO, "PentaxModelID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "ManufactureDate", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "ProductionCode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "InternalSerialNumber", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0, AUTO, "PentaxModelID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ManufactureDate", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "ProductionCode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "InternalSerialNumber", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; } #endif diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 9130b0ba9..e80467b5d 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -9,7 +9,7 @@ * 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 @@ -33,7 +33,8 @@ using namespace std; -namespace rtexif { +namespace rtexif +{ Interpreter stdInterpreter; @@ -43,140 +44,176 @@ Interpreter stdInterpreter; #define TAG_SUBFILETYPE 0x00fe -TagDirectory::TagDirectory () - : attribs(ifdAttribs), order(HOSTORDER), parent(NULL) {} +TagDirectory::TagDirectory () + : attribs(ifdAttribs), order(HOSTORDER), parent(NULL) {} -TagDirectory::TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border) +TagDirectory::TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border) : attribs(ta), order(border), parent(p) {} TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored) - : attribs(ta), order(border), parent(p) + : attribs(ta), order(border), parent(p) { - int numOfTags = get2 (f, order); - if (numOfTags<=0 || numOfTags>1000) // KodakIfd has lots of tags, thus 1000 as the limit - return; - - bool thumbdescr = false; - for (int i=0; igetType()==0) { - delete newTag; - continue; + if (numOfTags <= 0 || numOfTags > 1000) { // KodakIfd has lots of tags, thus 1000 as the limit + return; } - - if (skipIgnored) { - int id = newTag->getID(); - // detect and possibly ignore tags of directories belonging to the embedded thumbnail image - if (attribs==ifdAttribs && id==TAG_SUBFILETYPE && newTag->toInt()!=0) - thumbdescr = true; + bool thumbdescr = false; - const TagAttrib* attrib = getAttrib (id); + for (int i = 0; i < numOfTags; i++) { - if (!attrib || attrib->ignore==1 || (thumbdescr && attrib->ignore==2)) - delete newTag; - else - addTag (newTag); - } else addTag (newTag); - } -} - -TagDirectory::~TagDirectory () { + Tag* newTag = new Tag (this, f, base); - for (size_t i=0; igetType() == 0) { + delete newTag; + continue; + } + + if (skipIgnored) { + int id = newTag->getID(); + + // detect and possibly ignore tags of directories belonging to the embedded thumbnail image + if (attribs == ifdAttribs && id == TAG_SUBFILETYPE && newTag->toInt() != 0) { + thumbdescr = true; + } + + const TagAttrib* attrib = getAttrib (id); + + if (!attrib || attrib->ignore == 1 || (thumbdescr && attrib->ignore == 2)) { + delete newTag; + } else { + addTag (newTag); + } + } else { + addTag (newTag); + } + } } -class CompareTags { +TagDirectory::~TagDirectory () +{ + + for (size_t i = 0; i < tags.size(); i++) { + delete tags[i]; + } +} + +class CompareTags +{ public: - int operator() (Tag* const& a, Tag* const& b) const { + int operator() (Tag* const& a, Tag* const& b) const + { return a->getID() < b->getID(); } }; -void TagDirectory::sort () { +void TagDirectory::sort () +{ std::sort (tags.begin(), tags.end(), CompareTags()); - for (size_t i=0; iisDirectory()) - for (int j=0; tags[i]->getDirectory(j); j++) + for (int j = 0; tags[i]->getDirectory(j); j++) { tags[i]->getDirectory(j)->sort (); + } } TagDirectory* TagDirectory::getRoot() { - if(parent) return parent->getRoot(); - else return this; + if(parent) { + return parent->getRoot(); + } else { + return this; + } } -const TagAttrib* TagDirectory::getAttrib (int id) { +const TagAttrib* TagDirectory::getAttrib (int id) +{ if (attribs) - for (int i=0; attribs[i].ignore!=-1; i++) - if (attribs[i].ID==id) + for (int i = 0; attribs[i].ignore != -1; i++) + if (attribs[i].ID == id) { return &attribs[i]; + } return NULL; } -const TagAttrib* TagDirectory::getAttrib (const char* name) { +const TagAttrib* TagDirectory::getAttrib (const char* name) +{ if (attribs) - for (int i=0; attribs[i].ignore!=-1; i++) - if (!strcmp (attribs[i].name, name)) + for (int i = 0; attribs[i].ignore != -1; i++) + if (!strcmp (attribs[i].name, name)) { return &attribs[i]; + } return NULL; } -const TagAttrib* TagDirectory::getAttribP (const char* name) { +const TagAttrib* TagDirectory::getAttribP (const char* name) +{ - if (attribs) - for (int i=0; attribs[i].ignore!=-1; i++) { - // Yeah, self made comparison! - const char *n = name; - const char *a = attribs[i].name; - while (*n && *a && *n==*a) { n++; a++; }; - if (!*a && (!*n || *n=='/')) { - // we reached the end of the subpart of name and the end of attribs->name, so they match - if (*n=='/') { - Tag* tag = getTag (attribs[i].ID); - TagDirectory *tagDir; - if (attribs[i].subdirAttribs && tag && (tagDir=tag->getDirectory())) - return tagDir->getAttribP(n+1); - else - return NULL; - } - else - return &attribs[i]; - } - } - return NULL; -} + if (attribs) + for (int i = 0; attribs[i].ignore != -1; i++) { + // Yeah, self made comparison! + const char *n = name; + const char *a = attribs[i].name; -void TagDirectory::printAll (unsigned int level) const { + while (*n && *a && *n == *a) { + n++; + a++; + }; - // set the spacer prefix string - char prefixStr[level*4+1]; - unsigned int i; - for (i=0; iname, so they match + if (*n == '/') { + Tag* tag = getTag (attribs[i].ID); + TagDirectory *tagDir; - // recursively iterate over the tag list - for (size_t i=0; inameToString (); - if (tags[i]->isDirectory()) - for (int j=0; tags[i]->getDirectory(j); j++) { - printf ("%s+-- DIRECTORY %s[%d]:\n", prefixStr, name.c_str(), j); - tags[i]->getDirectory(j)->printAll (level+1); + if (attribs[i].subdirAttribs && tag && (tagDir = tag->getDirectory())) { + return tagDir->getAttribP(n + 1); + } else { + return NULL; + } + } else { + return &attribs[i]; + } + } } - else - std::string value = tags[i]->valueToString (); - } + + return NULL; +} + +void TagDirectory::printAll (unsigned int level) const +{ + + // set the spacer prefix string + char prefixStr[level * 4 + 1]; + unsigned int i; + + for (i = 0; i < level * 4; i++) { + prefixStr[i] = ' '; + } + + prefixStr[i] = '\0'; + + // recursively iterate over the tag list + for (size_t i = 0; i < tags.size(); i++) { + std::string name = tags[i]->nameToString (); + + if (tags[i]->isDirectory()) + for (int j = 0; tags[i]->getDirectory(j); j++) { + printf ("%s+-- DIRECTORY %s[%d]:\n", prefixStr, name.c_str(), j); + tags[i]->getDirectory(j)->printAll (level + 1); + } + else { + std::string value = tags[i]->valueToString (); + } + } } /** @brief Dump the TagDirectory and its sub-directories to the file 'fname' @@ -215,25 +252,31 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring { rtengine::SafeKeyFile *kf; - if (!keyFile) + + if (!keyFile) { kf = new rtengine::SafeKeyFile(); - else + } else { kf = keyFile; + } - if (!kf) + if (!kf) { return false; + } - if (!keyFile || tagDirName.empty()) + if (!keyFile || tagDirName.empty()) { tagDirName = "EXIF"; + } std::vector tagDirList; std::vector tagDirPaths; FILE *f = NULL; + if (!keyFile) { // open the file in write mode f = safe_g_fopen (commFName, "wt"); - if (f==NULL) { + + if (f == NULL) { printf("TagDirectory::keyFileDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str()); delete kf; return false; @@ -256,262 +299,340 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring kf->set_string ("Common Data", "Model", cfs->camModel); } - // recursively iterate over the tag list - for (size_t i=0; inameToString (); - if (tags[i]->isDirectory()) - for (int j=0; tags[i]->getDirectory(j); j++) { - // 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"); - } - else { - kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString()); - } - } + // recursively iterate over the tag list + for (size_t i = 0; i < tags.size(); i++) { + std::string tagName = tags[i]->nameToString (); - // dumping the sub-directories - for (size_t i=0; i< tagDirList.size(); i++) - tagDirList.at(i)->CPBDump(commFName, imageFName, profileFName, defaultPParams, cfs, flagMode, kf, tagDirPaths.at(i)); + if (tags[i]->isDirectory()) + for (int j = 0; tags[i]->getDirectory(j); j++) { + // 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"); + } + else { + kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString()); + } + } - if (!keyFile) { - fprintf (f, "%s", kf->to_data().c_str()); - fclose (f); - delete kf; - } + // dumping the sub-directories + for (size_t i = 0; i < tagDirList.size(); i++) { + tagDirList.at(i)->CPBDump(commFName, imageFName, profileFName, defaultPParams, cfs, flagMode, kf, tagDirPaths.at(i)); + } - return true; + if (!keyFile) { + fprintf (f, "%s", kf->to_data().c_str()); + fclose (f); + delete kf; + } + + return true; } -Glib::ustring TagDirectory::getDumpKey (int tagID, const Glib::ustring tagName) { +Glib::ustring TagDirectory::getDumpKey (int tagID, const Glib::ustring tagName) +{ Glib::ustring key; - if (options.CPBKeys == CPBKT_TID || options.CPBKeys == CPBKT_TID_NAME) + + if (options.CPBKeys == CPBKT_TID || options.CPBKeys == CPBKT_TID_NAME) { key = Glib::ustring(Glib::ustring::format(std::fixed, std::hex, std::setfill(L'0'), std::setw(4), tagID)); - if (options.CPBKeys == CPBKT_TID_NAME) + } + + if (options.CPBKeys == CPBKT_TID_NAME) { key += Glib::ustring("_"); - if (options.CPBKeys == CPBKT_TID_NAME || options.CPBKeys == CPBKT_NAME) + } + + if (options.CPBKeys == CPBKT_TID_NAME || options.CPBKeys == CPBKT_NAME) { key += Glib::ustring(tagName); + } + return key; } -void TagDirectory::addTag (Tag* tag) { +void TagDirectory::addTag (Tag* tag) +{ + + // look up if it already exists: + if (getTag (tag->getID())) { + delete tag; + } else { + tags.push_back (tag); + } +} + +void TagDirectory::addTagFront (Tag* tag) +{ + + // look up if it already exists: + if (getTag (tag->getID())) { + delete tag; + } else { + tags.insert (tags.begin(), tag); + } +} + +void TagDirectory::replaceTag (Tag* tag) +{ + + // look up if it already exists: + for (size_t i = 0; i < tags.size(); i++) + if (tags[i]->getID() == tag->getID()) { + delete tags[i]; + tags[i] = tag; + return; + } - // look up if it already exists: - if (getTag (tag->getID())) - delete tag; - else tags.push_back (tag); } -void TagDirectory::addTagFront (Tag* tag) { +Tag* TagDirectory::getTag (int ID) const +{ - // look up if it already exists: - if (getTag (tag->getID())) - delete tag; - else - tags.insert (tags.begin(), tag); -} - -void TagDirectory::replaceTag (Tag* tag) { - - // look up if it already exists: - for (size_t i=0; igetID()==tag->getID()) { - delete tags[i]; - tags[i] = tag; - return; - } - tags.push_back (tag); -} - -Tag* TagDirectory::getTag (int ID) const { - - for (size_t i=0; igetID()==ID) - return tags[i]; - return NULL; -} - -Tag* TagDirectory::getTag (const char* name) const { - - if (attribs) { - for (int i=0; attribs[i].ignore!=-1; i++) - if (!strcmp (attribs[i].name, name)) - return getTag (attribs[i].ID); - } - return NULL; -} - -Tag* TagDirectory::getTagP (const char* name) const { - - if (attribs) - for (int i=0; attribs[i].ignore!=-1; i++) { - // Yeah, self made comparison! - const char *n = name; - const char *a = attribs[i].name; - while (*n && *a && *n==*a) { n++; a++; }; - if (!*a && (!*n || *n=='/')) { - // we reached the end of the subpart of name and the end of attribs->name, so they match - if (*n=='/') { - Tag* tag = getTag (attribs[i].ID); - TagDirectory *tagDir; - if (attribs[i].subdirAttribs && tag && (tagDir=tag->getDirectory())) - return tagDir->getTagP(n+1); - else - return NULL; - } - else - return getTag (attribs[i].ID); - } - } - return NULL; -} - -Tag* TagDirectory::findTag (const char* name) const { - if (attribs) { - for (int i=0; attribs[i].ignore!=-1; i++) - if (!strcmp (attribs[i].name, name)){ - Tag* t= getTag (attribs[i].ID); - if(t) return t; - else break; + for (size_t i = 0; i < tags.size(); i++) + if (tags[i]->getID() == ID) { + return tags[i]; } - } - for (size_t i=0; iisDirectory()){ - TagDirectory *dir = tags[i]->getDirectory(); - Tag* t=dir->findTag(name); - if(t) return t; - } - return NULL; + + return NULL; +} + +Tag* TagDirectory::getTag (const char* name) const +{ + + if (attribs) { + for (int i = 0; attribs[i].ignore != -1; i++) + if (!strcmp (attribs[i].name, name)) { + return getTag (attribs[i].ID); + } + } + + return NULL; +} + +Tag* TagDirectory::getTagP (const char* name) const +{ + + if (attribs) + for (int i = 0; attribs[i].ignore != -1; i++) { + // Yeah, self made comparison! + const char *n = name; + const char *a = attribs[i].name; + + while (*n && *a && *n == *a) { + n++; + a++; + }; + + if (!*a && (!*n || *n == '/')) { + // we reached the end of the subpart of name and the end of attribs->name, so they match + if (*n == '/') { + Tag* tag = getTag (attribs[i].ID); + TagDirectory *tagDir; + + if (attribs[i].subdirAttribs && tag && (tagDir = tag->getDirectory())) { + return tagDir->getTagP(n + 1); + } else { + return NULL; + } + } else { + return getTag (attribs[i].ID); + } + } + } + + return NULL; +} + +Tag* TagDirectory::findTag (const char* name) const +{ + if (attribs) { + for (int i = 0; attribs[i].ignore != -1; i++) + if (!strcmp (attribs[i].name, name)) { + Tag* t = getTag (attribs[i].ID); + + if(t) { + return t; + } else { + break; + } + } + } + + for (size_t i = 0; i < tags.size(); i++) + if(tags[i]->isDirectory()) { + TagDirectory *dir = tags[i]->getDirectory(); + Tag* t = dir->findTag(name); + + if(t) { + return t; + } + } + + return NULL; } // Searches a simple value, as either attribute or element // only for simple values, not for entries with special chars or free text -bool TagDirectory::getXMPTagValue(const char* name, char* value) const { - *value=0; +bool TagDirectory::getXMPTagValue(const char* name, char* value) const +{ + *value = 0; + + if (!getTag("ApplicationNotes")) { + return false; + } - if (!getTag("ApplicationNotes")) return false; char *sXMP = (char*)getTag("ApplicationNotes")->getValue(); // Check for full word - char *pos=sXMP; + char *pos = sXMP; + + bool found = false; - bool found=false; do { - pos=strstr(pos,name); + pos = strstr(pos, name); + if (pos) { - char nextChar=*(pos+strlen(name)); - if (nextChar==' ' || nextChar=='>' || nextChar=='=') - found=true; - else - pos+=strlen(name); + char nextChar = *(pos + strlen(name)); + + if (nextChar == ' ' || nextChar == '>' || nextChar == '=') { + found = true; + } else { + pos += strlen(name); + } } } while (pos && !found); - if (!found) return false; - char *posTag =strchr(pos,'>'); - char *posAttr=strchr(pos,'"'); + if (!found) { + return false; + } - if (!posTag && !posAttr) return false; + char *posTag = strchr(pos, '>'); + char *posAttr = strchr(pos, '"'); - if (posTag && (!posAttr || posTaggetID()==ID) tags[i]->setKeep(true); +void TagDirectory::keepTag (int ID) +{ + for (size_t i = 0; i < tags.size(); i++) + if (tags[i]->getID() == ID) { + tags[i]->setKeep(true); + } } -int TagDirectory::calculateSize () { +int TagDirectory::calculateSize () +{ - int size = 2; // space to store the number of tags - for (size_t i=0; igetKeep()) - size += 12 + tags[i]->calculateSize (); - - size += 4; // next ifd pointer - return size; + int size = 2; // space to store the number of tags + + for (size_t i = 0; i < tags.size(); i++) + if (tags[i]->getKeep()) { + size += 12 + tags[i]->calculateSize (); + } + + size += 4; // next ifd pointer + return size; } - -TagDirectory* TagDirectory::clone (TagDirectory* parent) { - + +TagDirectory* TagDirectory::clone (TagDirectory* parent) +{ + TagDirectory* td = new TagDirectory (parent, attribs, order); - for (size_t i=0; itags.push_back (tags[i]->clone (td)); + } + return td; } -int TagDirectory::write (int start, unsigned char* buffer) { +int TagDirectory::write (int start, unsigned char* buffer) +{ int size = calculateSize (); int tagnum = 0; int nondirspace = 0; - for (size_t i=0; igetKeep()) { tagnum++; - if (!tags[i]->isDirectory()) + + if (!tags[i]->isDirectory()) { nondirspace += tags[i]->calculateSize(); + } } + int nextValOffs = start + 2 + tagnum * 12 + 4; int nextDirOffs = nextValOffs + nondirspace; int pos = start; - sset2 (tagnum, buffer+start, order); + sset2 (tagnum, buffer + start, order); pos += 2; int maxPos = start + size; - for (size_t i=0; igetKeep()) { - if (!tags[i]->isDirectory()) - nextValOffs = tags[i]->write (pos, nextValOffs, buffer); // pos: where to put the tag, dataoffset: the place where the value can be put. return: next data offset - else - nextDirOffs = tags[i]->write (pos, nextDirOffs, buffer); // pos: where to put the tag, dataoffset: the place where the value can be put. return: next data offset - + if (!tags[i]->isDirectory()) { + nextValOffs = tags[i]->write (pos, nextValOffs, buffer); // pos: where to put the tag, dataoffset: the place where the value can be put. return: next data offset + } else { + nextDirOffs = tags[i]->write (pos, nextDirOffs, buffer); // pos: where to put the tag, dataoffset: the place where the value can be put. return: next data offset + } + pos += 12; } } - sset4 (0, buffer+pos, order); + + sset4 (0, buffer + pos, order); return maxPos; } -void TagDirectory::applyChange (std::string name, std::string value) { +void TagDirectory::applyChange (std::string name, std::string value) +{ std::string::size_type dp = name.find_first_of ('.'); - std::string fseg = name.substr (0,dp); + std::string fseg = name.substr (0, dp); + // this is a final segment: apply change - if (dp==std::string::npos) { + if (dp == std::string::npos) { Tag* t = NULL; - for (size_t i=0; inameToString()==fseg) { + + for (size_t i = 0; i < tags.size(); i++) + if (tags[i]->nameToString() == fseg) { t = tags[i]; break; } - - if (value=="#keep" && t) + + if (value == "#keep" && t) { t->setKeep (true); - else if (value=="#delete" && t) + } else if (value == "#delete" && t) { t->setKeep (false); - else if (t && !t->isDirectory()) + } else if (t && !t->isDirectory()) { t->valueFromString (value); - else { + } else { const TagAttrib* attrib = NULL; - for (int i=0; attribs[i].ignore!=-1; i++) + + for (int i = 0; attribs[i].ignore != -1; i++) if (!strcmp (attribs[i].name, fseg.c_str())) { attrib = &attribs[i]; break; - } + } + if (attrib) { Tag* nt = new Tag (this, attrib); nt->initString (value.c_str()); @@ -523,113 +644,129 @@ void TagDirectory::applyChange (std::string name, std::string value) { else { // try to find it std::string::size_type dp1 = fseg.find_first_of ('['); - std::string basename = fseg.substr (0,dp1); + std::string basename = fseg.substr (0, dp1); Tag* t = NULL; int dirnum = -1; - for (size_t i=0; iisDirectory()) { - for (int j=0; tags[i]->getDirectory(j); j++) { + for (int j = 0; tags[i]->getDirectory(j); j++) { if (tags[i]->nameToString(j) == fseg) { t = tags[i]; dirnum = j; break; } } + if (!t && tags[i]->nameToString() == basename) { // found it, but that directory index does not exist t = tags[i]; dirnum = -1; } } - if (!t && value!="#keep" && value!="#delete") { + + if (!t && value != "#keep" && value != "#delete") { const TagAttrib* attrib = NULL; - for (int i=0; attribs[i].ignore!=-1; i++) + + for (int i = 0; attribs[i].ignore != -1; i++) if (!strcmp (attribs[i].name, fseg.c_str())) { attrib = &attribs[i]; break; - } + } + if (attrib && attrib->subdirAttribs) { t = new Tag (this, attrib); t->initSubDir (); addTag (t); } + dirnum = 0; } - if (t && dirnum>=0) - t->getDirectory(dirnum)->applyChange (name.substr (dp+1, std::string::npos), value); + + if (t && dirnum >= 0) { + t->getDirectory(dirnum)->applyChange (name.substr (dp + 1, std::string::npos), value); + } } } TagDirectoryTable::TagDirectoryTable () -:zeroOffset(0),valuesSize(0) + : zeroOffset(0), valuesSize(0) { } -TagDirectoryTable::TagDirectoryTable (TagDirectory* p, unsigned char *v,int memsize,int offs, TagType type, const TagAttrib* ta, ByteOrder border) -:TagDirectory(p,ta,border),zeroOffset(offs),valuesSize(memsize),defaultType( type ) +TagDirectoryTable::TagDirectoryTable (TagDirectory* p, unsigned char *v, int memsize, int offs, TagType type, const TagAttrib* ta, ByteOrder border) + : TagDirectory(p, ta, border), zeroOffset(offs), valuesSize(memsize), defaultType( type ) { values = new unsigned char[valuesSize]; - memcpy(values,v,valuesSize); + memcpy(values, v, valuesSize); // Security ; will avoid to read above the buffer limit if the RT's tagDirectoryTable is longer that what's in the file - int count = valuesSize/getTypeSize(type); + int count = valuesSize / getTypeSize(type); - for(const TagAttrib* tattr = ta; tattr->ignore != -1 && tattr->IDID*getTypeSize(type)), tattr->type == AUTO ? type : tattr->type); + for(const TagAttrib* tattr = ta; tattr->ignore != -1 && tattr->ID < count; ++tattr) { + Tag* newTag = new Tag (this, tattr, (values + zeroOffset + tattr->ID * getTypeSize(type)), tattr->type == AUTO ? type : tattr->type); tags.push_back(newTag); // Here we can insert more tag in the same offset because of bitfield meaning } } -TagDirectoryTable::TagDirectoryTable (TagDirectory* p, FILE* f, int memsize,int offs, TagType type, const TagAttrib* ta, ByteOrder border) -:TagDirectory(p,ta,border),zeroOffset(offs),valuesSize(memsize),defaultType( type ) +TagDirectoryTable::TagDirectoryTable (TagDirectory* p, FILE* f, int memsize, int offs, TagType type, const TagAttrib* ta, ByteOrder border) + : TagDirectory(p, ta, border), zeroOffset(offs), valuesSize(memsize), defaultType( type ) { values = new unsigned char[valuesSize]; fread (values, 1, valuesSize, f); // Security ; will avoid to read above the buffer limit if the RT's tagDirectoryTable is longer that what's in the file - int count = valuesSize/getTypeSize(type); + int count = valuesSize / getTypeSize(type); - for(const TagAttrib* tattr = ta; tattr->ignore != -1 && tattr->IDID*getTypeSize(type)), tattr->type == AUTO ? type : tattr->type); + for(const TagAttrib* tattr = ta; tattr->ignore != -1 && tattr->ID < count; ++tattr) { + Tag* newTag = new Tag (this, tattr, (values + zeroOffset + tattr->ID * getTypeSize(type)), tattr->type == AUTO ? type : tattr->type); tags.push_back(newTag); // Here we can insert more tag in the same offset because of bitfield meaning } } -TagDirectory* TagDirectoryTable::clone (TagDirectory* parent) { +TagDirectory* TagDirectoryTable::clone (TagDirectory* parent) +{ - TagDirectory* td = new TagDirectoryTable (parent,values,valuesSize,zeroOffset,defaultType, attribs, order); + TagDirectory* td = new TagDirectoryTable (parent, values, valuesSize, zeroOffset, defaultType, attribs, order); return td; } TagDirectoryTable::~TagDirectoryTable() { - if(values) + if(values) { delete [] values; + } } int TagDirectoryTable::calculateSize () { return valuesSize; } -int TagDirectoryTable::write (int start, unsigned char* buffer) { - if( values && valuesSize){ - memcpy(buffer+start,values,valuesSize); - return start+valuesSize; - }else +int TagDirectoryTable::write (int start, unsigned char* buffer) +{ + if( values && valuesSize) { + memcpy(buffer + start, values, valuesSize); + return start + valuesSize; + } else { return start; + } } //--------------- class Tag --------------------------------------------------- // this class represents a tag stored in the directory //----------------------------------------------------------------------------- -Tag::Tag (TagDirectory* p, FILE* f, int base) - : type(INVALID), count(0), value(NULL), allocOwnMemory(true), attrib(NULL), parent(p), directory(NULL) { +Tag::Tag (TagDirectory* p, FILE* f, int base) + : type(INVALID), count(0), value(NULL), allocOwnMemory(true), attrib(NULL), parent(p), directory(NULL) +{ ByteOrder order = getOrder(); tag = get2 (f, order); type = (TagType)get2 (f, order); count = get4 (f, order); - if (!count) count = 1; + + if (!count) { + count = 1; + } makerNoteKind = NOMK; keep = false; @@ -637,7 +774,7 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) // filter out invalid tags // note the large count is to be able to pass LeafData ASCII tag which can be up to almost 10 megabytes, // (only a small part of it will actually be parsed though) - if ((int)type<1 || (int)type>14 || count>10*1024*1024) { + if ((int)type < 1 || (int)type > 14 || count > 10 * 1024 * 1024) { type = INVALID; return; } @@ -648,234 +785,277 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) // load value field (possibly seek before) valuesize = count * getTypeSize(type); - if (valuesize > 4) + if (valuesize > 4) { fseek (f, get4(f, getOrder()) + base, SEEK_SET); + } attrib = parent->getAttrib (tag); - if (attrib && (attrib->action==AC_WRITE || attrib->action==AC_NEW)) + if (attrib && (attrib->action == AC_WRITE || attrib->action == AC_NEW)) { keep = true; + } - if( tag == 0xc634 ){ // DNGPrivateData + if( tag == 0xc634 ) { // DNGPrivateData int currPos = ftell(f); const int buffersize = 32; - char buffer[buffersize],*p=buffer; - while( fread (p, 1, 1, f ) && *p != 0 && p-buffergetRoot()->findTag("Make"); - std::string make( tmake ? tmake->valueToString():""); - int save = ftell(f); - int originalOffset = sget4( (unsigned char*)&buffer[10], ( make.find("SONY") != std::string::npos ) || ( make.find("Canon") != std::string::npos ) || ( make.find("OLYMPUS") != std::string::npos ) ?MOTOROLA:bom ); + char buffer[buffersize], *p = buffer; - if( !parseMakerNote(f, save - originalOffset , bom )) + while( fread (p, 1, 1, f ) && *p != 0 && p - buffer < buffersize - 1 ) { + p++; + } + + *p = 0; + + if( !strncmp(buffer, "Adobe", 5) ) { + fread (buffer, 1, 14, f ); + + if( !strncmp( buffer, "MakN", 4) ) { + ByteOrder bom = ((buffer[8] == 'M' && buffer[9] == 'M') ? MOTOROLA : INTEL) ; + Tag* tmake = parent->getRoot()->findTag("Make"); + std::string make( tmake ? tmake->valueToString() : ""); + int save = ftell(f); + int originalOffset = sget4( (unsigned char*)&buffer[10], ( make.find("SONY") != std::string::npos ) || ( make.find("Canon") != std::string::npos ) || ( make.find("OLYMPUS") != std::string::npos ) ? MOTOROLA : bom ); + + if( !parseMakerNote(f, save - originalOffset , bom )) { type = INVALID; + } } - }else if( !strncmp(buffer,"PENTAX",6) ){ + } else if( !strncmp(buffer, "PENTAX", 6) ) { makerNoteKind = HEADERIFD; fread (buffer, 1, 2, f); directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, currPos, pentaxAttribs, strncmp(buffer,"MM",2)? INTEL:MOTOROLA); + directory[0] = new TagDirectory (parent, f, currPos, pentaxAttribs, strncmp(buffer, "MM", 2) ? INTEL : MOTOROLA); directory[1] = NULL; - }else - /* SONY uses this tag to write hidden info and pointer to private encrypted tags - { - unsigned offset =sget4((unsigned char*)buffer, order); - fseek(f,offset,SEEK_SET); - makerNoteKind = TABLESUBDIR; - directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, base, sonyDNGMakerNote, order); - directory[1] = NULL; - fseek (f, save, SEEK_SET); - return; - }*/ - type = INVALID; + } else + /* SONY uses this tag to write hidden info and pointer to private encrypted tags + { + unsigned offset =sget4((unsigned char*)buffer, order); + fseek(f,offset,SEEK_SET); + makerNoteKind = TABLESUBDIR; + directory = new TagDirectory*[2]; + directory[0] = new TagDirectory (parent, f, base, sonyDNGMakerNote, order); + directory[1] = NULL; + fseek (f, save, SEEK_SET); + return; + }*/ + { + type = INVALID; + } } + // if this tag is the makernote, it needs special treatment (brand specific parsing) - if (tag==0x927C && attrib && !strcmp (attrib->name, "MakerNote") ) { - if( !parseMakerNote(f,base,order )){ + if (tag == 0x927C && attrib && !strcmp (attrib->name, "MakerNote") ) { + if( !parseMakerNote(f, base, order )) { type = INVALID; fseek (f, save, SEEK_SET); return; } + } else if (attrib && attrib->subdirAttribs) { + // Some subdirs are specific of maker and model + char make[128], model[128]; + make[0] = 0; + model[0] = 0; + Tag* tmake = parent->getRoot()->getTag ("Make"); + + if (tmake) { + tmake->toString (make); + } + + Tag* tmodel = parent->getRoot()->getTag ("Model"); + + if (tmodel) { + tmodel->toString (model); + } + + if (!strncmp(make, "SONY", 4)) { + switch( tag ) { + case 0x0010: + directory = new TagDirectory*[2]; + directory[1] = NULL; + + if (count == 15360) { + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , sonyCameraInfoAttribs, order); + } else { + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , sonyCameraInfo2Attribs, order); + } + + break; + + case 0x0114: + directory = new TagDirectory*[2]; + directory[1] = NULL; + + if (count == 280 || count == 364) { + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, SHORT , sonyCameraSettingsAttribs, MOTOROLA); + } else if (count == 332) { + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, SHORT , sonyCameraSettingsAttribs2, MOTOROLA); + } else if(count == 1536 || count == 2048) { + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , sonyCameraSettingsAttribs3, INTEL); + } else { + // Unknown CameraSettings + delete [] directory; + directory = NULL; + type = INVALID; + } + + makerNoteKind = directory ? TABLESUBDIR : NOMK; + break; + + case 0x9405: + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, SHORT , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + + default: + goto defsubdirs; + } + } else if ((!strncmp(make, "PENTAX", 6)) || (!strncmp(make, "RICOH", 5) && !strncmp(model, "PENTAX", 6))) { // Either the former Pentax brand or the RICOH brand + PENTAX model" + switch( tag ) { + case 0x007d: + case 0x0205: + case 0x0208: + case 0x0216: + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + + case 0x0215: + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, LONG , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + + case 0x005c: + directory = new TagDirectory*[2]; + directory[1] = NULL; + + if (count == 4) { // SRInfo + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , pentaxSRInfoAttribs, order); + } else if (count == 2) { // SRInfo2 + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , pentaxSRInfo2Attribs, order); + } else { + // Unknown SRInfo + delete [] directory; + directory = NULL; + type = INVALID; + } + + makerNoteKind = directory ? TABLESUBDIR : NOMK; + break; + + case 0x0206: + directory = new TagDirectory*[2]; + directory[1] = NULL; + + if (count == 21) { // AEInfo2 + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , pentaxAEInfo2Attribs, order); + } else if (count == 48) { // AEInfo3 + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , pentaxAEInfo3Attribs, order); + } else if (count <= 25) { // AEInfo + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , pentaxAEInfoAttribs, order); + } else { + // Unknown AEInfo + delete [] directory; + directory = NULL; + type = INVALID; + } + + makerNoteKind = directory ? TABLESUBDIR : NOMK; + break; + + case 0x0207: { + // There are 2 format pentaxLensDataAttribs + int offsetFirst = 4; // LensInfo2 + + if( strstr(model, "*ist") || strstr(model, "GX-1") || strstr(model, "K100D") || strstr(model, "K110D") ) { + offsetFirst = 3; // LensInfo + } else if( strstr(model, "645D") ) { + offsetFirst = 13; // LensInfo3 + } else if( strstr(model, "K-01") || strstr(model, "K-30") || strstr(model, "K-50")) { + offsetFirst = 15; // LensInfo5 + } else if( strstr(model, "K-5") || strstr(model, "K-r") ) { + offsetFirst = 12; // LensInfo4 + } else if(!strncmp(make, "RICOH", 5)) { // all PENTAX camera model produced under the RICOH era uses LensInfo5, for now... + offsetFirst = 15; // LensInfo5 too + } + + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, offsetFirst, BYTE , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + } + break; + + case 0x0239: + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + + default: + goto defsubdirs; + } + } else if (!strncmp(make, "Canon", 5)) { + switch( tag ) { + case 0x0001: + case 0x0002: + case 0x0004: + case 0x0005: + case 0x0093: + case 0x0098: + case 0x00a0: + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, SSHORT , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + + case 0x009a: + case 0x4013: + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, LONG , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + + default: + goto defsubdirs; + } + } else if (!strncmp(make, "NIKON", 5)) { + switch (tag) { + case 0x0025: { + directory = new TagDirectory*[2]; + directory[1] = NULL; + directory[0] = new TagDirectoryTable (parent, f, valuesize, 0, BYTE , attrib->subdirAttribs, order); + makerNoteKind = TABLESUBDIR; + break; + } + + default: + goto defsubdirs; + } + } else if(type == UNDEFINED) { + count = 1; + type = LONG; + directory = new TagDirectory*[2]; + directory[0] = new TagDirectory (parent, f, base, attrib->subdirAttribs, order); + directory[1] = NULL; + } else { + goto defsubdirs; + } + } else { + // read value + value = new unsigned char [valuesize + 1]; + fread (value, 1, valuesize, f); + value[valuesize] = '\0'; } - else if (attrib && attrib->subdirAttribs) { - // Some subdirs are specific of maker and model - char make[128], model[128]; - make[0]=0; - model[0]=0; - Tag* tmake = parent->getRoot()->getTag ("Make"); - if (tmake) tmake->toString (make); - Tag* tmodel = parent->getRoot()->getTag ("Model"); - if (tmodel) tmodel->toString (model); - if (!strncmp(make, "SONY", 4)) { - switch( tag ){ - case 0x0010: - directory = new TagDirectory*[2]; - directory[1] = NULL; - if (count == 15360) - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , sonyCameraInfoAttribs, order); - else - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , sonyCameraInfo2Attribs, order); - break; - case 0x0114: - directory = new TagDirectory*[2]; - directory[1] = NULL; - if (count == 280 || count == 364) - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,SHORT , sonyCameraSettingsAttribs, MOTOROLA); - else if (count == 332) - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,SHORT , sonyCameraSettingsAttribs2, MOTOROLA); - else if(count == 1536 || count == 2048) - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , sonyCameraSettingsAttribs3, INTEL); - else { - // Unknown CameraSettings - delete [] directory; - directory = NULL; - type = INVALID; - } - makerNoteKind = directory ? TABLESUBDIR : NOMK; - break; - case 0x9405: - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,SHORT , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - default: - goto defsubdirs; - } - }else if ((!strncmp(make, "PENTAX", 6)) || (!strncmp(make, "RICOH", 5) && !strncmp(model, "PENTAX", 6))) { // Either the former Pentax brand or the RICOH brand + PENTAX model" - switch( tag ){ - case 0x007d: - case 0x0205: - case 0x0208: - case 0x0216: - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - case 0x0215: - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,LONG , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - case 0x005c: - directory = new TagDirectory*[2]; - directory[1] = NULL; - if (count == 4) // SRInfo - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , pentaxSRInfoAttribs, order); - else if (count == 2) // SRInfo2 - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , pentaxSRInfo2Attribs, order); - else { - // Unknown SRInfo - delete [] directory; - directory = NULL; - type = INVALID; - } - makerNoteKind = directory ? TABLESUBDIR : NOMK; - break; - case 0x0206: - directory = new TagDirectory*[2]; - directory[1] = NULL; - if (count == 21) // AEInfo2 - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , pentaxAEInfo2Attribs, order); - else if (count == 48) // AEInfo3 - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , pentaxAEInfo3Attribs, order); - else if (count <= 25) // AEInfo - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , pentaxAEInfoAttribs, order); - else { - // Unknown AEInfo - delete [] directory; - directory = NULL; - type = INVALID; - } - makerNoteKind = directory ? TABLESUBDIR : NOMK; - break; - case 0x0207: - { // There are 2 format pentaxLensDataAttribs - int offsetFirst = 4; // LensInfo2 - if( strstr(model, "*ist") || strstr(model, "GX-1") || strstr(model, "K100D") || strstr(model, "K110D") ) - offsetFirst = 3; // LensInfo - else if( strstr(model, "645D") ) - offsetFirst = 13; // LensInfo3 - else if( strstr(model, "K-01") || strstr(model, "K-30") || strstr(model, "K-50")) - offsetFirst = 15; // LensInfo5 - else if( strstr(model, "K-5") || strstr(model, "K-r") ) - offsetFirst = 12; // LensInfo4 - else if(!strncmp(make, "RICOH", 5)) { // all PENTAX camera model produced under the RICOH era uses LensInfo5, for now... - offsetFirst = 15; // LensInfo5 too - } - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,offsetFirst,BYTE , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - } - break; - case 0x0239: - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - default: - goto defsubdirs; - } - }else if (!strncmp(make, "Canon", 5)) { - switch( tag ){ - case 0x0001: - case 0x0002: - case 0x0004: - case 0x0005: - case 0x0093: - case 0x0098: - case 0x00a0: - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,SSHORT , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - case 0x009a: - case 0x4013: - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,LONG , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - default: - goto defsubdirs; - } - }else if (!strncmp(make, "NIKON", 5)) { - switch (tag) { - case 0x0025: { - directory = new TagDirectory*[2]; - directory[1] = NULL; - directory[0] = new TagDirectoryTable (parent, f, valuesize,0,BYTE , attrib->subdirAttribs, order); - makerNoteKind = TABLESUBDIR; - break; - } - default: - goto defsubdirs; - } - }else if(type==UNDEFINED){ - count = 1; - type = LONG; - directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, base, attrib->subdirAttribs, order); - directory[1] = NULL; - }else - goto defsubdirs; - } - else { - // read value - value = new unsigned char [valuesize+1]; - fread (value, 1, valuesize, f); - value[valuesize] = '\0'; - } + // seek back to the saved position fseek (f, save, SEEK_SET); return; @@ -887,23 +1067,28 @@ defsubdirs: int pos = ftell (f); // count the number of valid subdirs int sdcount = count; - if (sdcount>0) { - if (parent->getAttribTable()==olympusAttribs) + + if (sdcount > 0) { + if (parent->getAttribTable() == olympusAttribs) { sdcount = 1; + } + // allocate space - directory = new TagDirectory*[sdcount+1]; + directory = new TagDirectory*[sdcount + 1]; + // load directories - for (size_t j=0,i=0; jsubdirAttribs, order); fseek (f, pos, SEEK_SET); } + // set the terminating NULL directory[sdcount] = NULL; - } - else + } else { type = INVALID; + } // seek back to the saved position fseek (f, save, SEEK_SET); @@ -915,18 +1100,18 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) { value = NULL; Tag* tmake = parent->getRoot()->findTag("Make"); - std::string make( tmake ? tmake->valueToString():""); + std::string make( tmake ? tmake->valueToString() : ""); Tag* tmodel = parent->getRoot()->findTag ("Model"); - std::string model( tmodel ? tmodel->valueToString():""); + std::string model( tmodel ? tmodel->valueToString() : ""); if ( make.find( "NIKON" ) != std::string::npos ) { - if ( model.find("NIKON E700")!= std::string::npos || - model.find("NIKON E800")!= std::string::npos || - model.find("NIKON E900")!= std::string::npos || - model.find("NIKON E900S")!= std::string::npos || - model.find("NIKON E910")!= std::string::npos || - model.find("NIKON E950")!= std::string::npos ) { + if ( model.find("NIKON E700") != std::string::npos || + model.find("NIKON E800") != std::string::npos || + model.find("NIKON E900") != std::string::npos || + model.find("NIKON E900S") != std::string::npos || + model.find("NIKON E910") != std::string::npos || + model.find("NIKON E950") != std::string::npos ) { makerNoteKind = HEADERIFD; valuesize = 8; value = new unsigned char[8]; @@ -934,8 +1119,8 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) directory = new TagDirectory*[2]; directory[0] = new TagDirectory (parent, f, base, nikon2Attribs, bom); directory[1] = NULL; - } else if ( model.find("NIKON E990")!= std::string::npos || - (model.find("NIKON D1")!= std::string::npos && model.size()>8 && model.at(8)!='0')) { + } else if ( model.find("NIKON E990") != std::string::npos || + (model.find("NIKON D1") != std::string::npos && model.size() > 8 && model.at(8) != '0')) { makerNoteKind = IFD; directory = new TagDirectory*[2]; directory[0] = new TagDirectory (parent, f, base, nikon3Attribs, bom); @@ -948,7 +1133,7 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) int basepos = ftell (f); fread (value, 1, 18, f); directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, basepos+10, nikon3Attribs, bom); + directory[0] = new TagDirectory (parent, f, basepos + 10, nikon3Attribs, bom); directory[1] = NULL; } } else if ( make.find( "Canon" ) != std::string::npos ) { @@ -970,7 +1155,7 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) value = new unsigned char[10]; fread (value, 1, 10, f); directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, ftell (f)-10, pentaxAttribs, bom); + directory[0] = new TagDirectory (parent, f, ftell (f) - 10, pentaxAttribs, bom); directory[1] = NULL; } else if ( make.find( "FUJIFILM" ) != std::string::npos ) { makerNoteKind = FUJI; @@ -978,7 +1163,7 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) value = new unsigned char[12]; fread (value, 1, 12, f); directory = new TagDirectory*[2]; - directory[0] = new TagDirectory (parent, f, ftell(f)-12, fujiAttribs, INTEL); + directory[0] = new TagDirectory (parent, f, ftell(f) - 12, fujiAttribs, INTEL); directory[1] = NULL; } else if ( make.find( "KONICA MINOLTA" ) != std::string::npos || make.find( "Minolta" ) != std::string::npos ) { makerNoteKind = IFD; @@ -989,12 +1174,14 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) valuesize = 12; value = new unsigned char[12]; fread (value, 1, 12, f); - if (!strncmp((char*)value, "SONY DSC", 8)) + + if (!strncmp((char*)value, "SONY DSC", 8)) { makerNoteKind = HEADERIFD; - else { + } else { makerNoteKind = IFD; fseek (f, -12, SEEK_CUR); } + directory = new TagDirectory*[2]; directory[0] = new TagDirectory (parent, f, base, sonyAttribs, bom ); directory[1] = NULL; @@ -1005,367 +1192,545 @@ bool Tag::parseMakerNote(FILE* f, int base, ByteOrder bom ) fread (value, 1, 8, f); directory = new TagDirectory*[2]; directory[1] = NULL; + if (!strncmp((char*)value, "OLYMPUS", 7)) { makerNoteKind = OLYMPUS2; - fread (value+8, 1, 4, f); + fread (value + 8, 1, 4, f); valuesize = 12; - directory[0] = new TagDirectory (parent, f, ftell(f)-12, olympusAttribs, value[8]=='I' ? INTEL : MOTOROLA); - } else + directory[0] = new TagDirectory (parent, f, ftell(f) - 12, olympusAttribs, value[8] == 'I' ? INTEL : MOTOROLA); + } else { directory[0] = new TagDirectory (parent, f, base, olympusAttribs, bom); - } else + } + } else { return false; + } + return true; } -Tag* Tag::clone (TagDirectory* parent) { +Tag* Tag::clone (TagDirectory* parent) +{ Tag* t = new Tag (parent, attrib); - + t->tag = tag; t->type = type; t->count = count; t->keep = keep; t->valuesize = valuesize; + if (value) { t->value = new unsigned char [valuesize]; memcpy (t->value, value, valuesize); - } - else + } else { value = NULL; + } + t->makerNoteKind = makerNoteKind; + if (directory) { int ds = 0; + for (; directory[ds]; ds++); - t->directory = new TagDirectory*[ds+1]; - for (int i=0; idirectory = new TagDirectory*[ds + 1]; + + for (int i = 0; i < ds; i++) { t->directory[i] = directory[i]->clone (parent); + } + t->directory[ds] = NULL; - } - else + } else { t->directory = NULL; + } + return t; } -Tag::~Tag () { +Tag::~Tag () +{ - // delete value - if (value && allocOwnMemory) - delete [] value; - - // if there are directories behind the tag, delete them - int i = 0; - if (directory) { - while (directory[i]) - delete directory[i++]; - delete [] directory; - } -} - -void Tag::setInt (int v, int ofs, TagType astype) { - - if (astype==SHORT) - sset2 (v, value+ofs, getOrder()); - else if (astype==RATIONAL) { - sset4 (v, value+ofs, getOrder()); - sset4 (1, value+ofs+4, getOrder()); - } - else - sset4 (v, value+ofs, getOrder()); -} - -void Tag::fromInt (int v) { - - if (type==SHORT) - sset2 (v, value, getOrder()); - else - sset4 (v, value, getOrder()); -} - -void Tag::fromString (const char* v, int size) { - - if( value && allocOwnMemory) + // delete value + if (value && allocOwnMemory) { delete [] value; - if (size<0) + } + + // if there are directories behind the tag, delete them + int i = 0; + + if (directory) { + while (directory[i]) { + delete directory[i++]; + } + + delete [] directory; + } +} + +void Tag::setInt (int v, int ofs, TagType astype) +{ + + if (astype == SHORT) { + sset2 (v, value + ofs, getOrder()); + } else if (astype == RATIONAL) { + sset4 (v, value + ofs, getOrder()); + sset4 (1, value + ofs + 4, getOrder()); + } else { + sset4 (v, value + ofs, getOrder()); + } +} + +void Tag::fromInt (int v) +{ + + if (type == SHORT) { + sset2 (v, value, getOrder()); + } else { + sset4 (v, value, getOrder()); + } +} + +void Tag::fromString (const char* v, int size) +{ + + if( value && allocOwnMemory) { + delete [] value; + } + + if (size < 0) { valuesize = strlen (v) + 1; - else + } else { valuesize = size; + } + count = valuesize; - if( allocOwnMemory ) - value = new unsigned char [valuesize]; + + if( allocOwnMemory ) { + value = new unsigned char [valuesize]; + } + memcpy ((char*)value, v, valuesize); } -int Tag::toInt (int ofs, TagType astype) { - if (attrib) - return attrib->interpreter->toInt(this, ofs, astype); +int Tag::toInt (int ofs, TagType astype) +{ + if (attrib) { + return attrib->interpreter->toInt(this, ofs, astype); + } - int a; - if (astype == INVALID) - astype = type; - switch (astype) { + int a; + + if (astype == INVALID) { + astype = type; + } + + switch (astype) { //case SBYTE: return (signed char)(value[ofs]); - case SBYTE: return int((reinterpret_cast(value))[ofs]); - case BYTE: return value[ofs]; - case ASCII: return 0; - case SSHORT:return (int)int2_to_signed(sget2 (value+ofs, getOrder())); - case SHORT: return (int)sget2 (value+ofs, getOrder()); + case SBYTE: + return int((reinterpret_cast(value))[ofs]); + + case BYTE: + return value[ofs]; + + case ASCII: + return 0; + + case SSHORT: + return (int)int2_to_signed(sget2 (value + ofs, getOrder())); + + case SHORT: + return (int)sget2 (value + ofs, getOrder()); + case SLONG: - case LONG: return (int)sget4 (value+ofs, getOrder()); - case SRATIONAL: - case RATIONAL: a = (int)sget4 (value+ofs+4, getOrder()); return a==0 ? 0 : (int)sget4 (value+ofs, getOrder()) / a; - case FLOAT: return (int)toDouble(ofs); - case UNDEFINED: return 0; - default: return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) - } - return 0; + case LONG: + return (int)sget4 (value + ofs, getOrder()); + + case SRATIONAL: + case RATIONAL: + a = (int)sget4 (value + ofs + 4, getOrder()); + return a == 0 ? 0 : (int)sget4 (value + ofs, getOrder()) / a; + + case FLOAT: + return (int)toDouble(ofs); + + case UNDEFINED: + return 0; + + default: + return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) + } + + return 0; } -double Tag::toDouble (int ofs) { - if (attrib) - return attrib->interpreter->toDouble(this, ofs); +double Tag::toDouble (int ofs) +{ + if (attrib) { + return attrib->interpreter->toDouble(this, ofs); + } - union IntFloat { uint32_t i; float f; } conv; + union IntFloat { + uint32_t i; + float f; + } conv; + + double ud, dd; + + switch (type) { + case SBYTE: + return (double)(int((reinterpret_cast(value))[ofs])); + + case BYTE: + return (double)((int)value[ofs]); + + case ASCII: + return 0.0; + + case SSHORT: + return (double)int2_to_signed(sget2 (value + ofs, getOrder())); + + case SHORT: + return (double)((int)sget2 (value + ofs, getOrder())); - double ud, dd; - switch (type) { - case SBYTE: return (double)(int((reinterpret_cast(value))[ofs])); - case BYTE: return (double)((int)value[ofs]); - case ASCII: return 0.0; - case SSHORT:return (double)int2_to_signed(sget2 (value+ofs, getOrder())); - case SHORT: return (double)((int)sget2 (value+ofs, getOrder())); case SLONG: - case LONG: return (double)((int)sget4 (value+ofs, getOrder())); + case LONG: + return (double)((int)sget4 (value + ofs, getOrder())); + case SRATIONAL: - case RATIONAL: ud = (int)sget4 (value+ofs, getOrder()); dd = (int)sget4 (value+ofs+4, getOrder()); return dd==0. ? 0. : (double)ud / (double)dd; + case RATIONAL: + ud = (int)sget4 (value + ofs, getOrder()); + dd = (int)sget4 (value + ofs + 4, getOrder()); + return dd == 0. ? 0. : (double)ud / (double)dd; + case FLOAT: - conv.i=sget4 (value+ofs, getOrder()); + conv.i = sget4 (value + ofs, getOrder()); return conv.f; // IEEE FLOATs are already C format, they just need a recast - case UNDEFINED: return 0.; - default: return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) - } - return 0.; + case UNDEFINED: + return 0.; + + default: + return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) + } + + return 0.; } /** * @brief Create an array of the elements */ -double *Tag::toDoubleArray(int ofs) { +double *Tag::toDoubleArray(int ofs) +{ double *values = new double[count]; - for (unsigned int i=0; i126) - isstring = false; - if (isstring) { - int j = 0; - for (i=0; i+ofs') - buffer[j++] = '\\'; - buffer[j++] = value[i+ofs]; - } - buffer[j++] = 0; - return; - } - } - else if (type==ASCII) { - sprintf (buffer, "%.64s", value+ofs); - return; - } - - size_t maxcount = 4; - if (count<4) - maxcount = count; - - strcpy (buffer, ""); - for (size_t i=0; i0) - strcat (buffer, ", "); - char* b = buffer + strlen(buffer); - switch (type) { - case UNDEFINED: - case BYTE: sprintf (b, "%d", value[i+ofs]); break; - case SSHORT: sprintf (b, "%d", toInt(2*i+ofs)); break; - case SHORT: sprintf (b, "%u", toInt(2*i+ofs)); break; - case SLONG: sprintf (b, "%ld", (long)toInt(4*i+ofs)); break; - case LONG: sprintf (b, "%lu", (unsigned long)toInt(4*i+ofs)); break; - case SRATIONAL: - case RATIONAL: sprintf (b, "%d/%d", (int)sget4 (value+8*i+ofs, getOrder()), (int)sget4 (value+8*i+ofs+4, getOrder())); break; - case FLOAT: sprintf (b, "%g", toDouble(8*i+ofs)); break; - default: break; + case BYTE: + num = (int)value[ofs]; + denom = 1; + break; + + case ASCII: + num = 0; + denom = 0; + break; + + case SSHORT: + case SHORT: + num = (int)sget2 (value + ofs, getOrder()); + denom = 1; + break; + + case SLONG: + case LONG: + num = (int)sget4 (value + ofs, getOrder()); + denom = 1; + break; + + case SRATIONAL: + case RATIONAL: + num = (int)sget4 (value + ofs, getOrder()); + denom = (int)sget4 (value + ofs + 4, getOrder()); + break; + + case FLOAT: + num = 0; + denom = 0; + break; + + case UNDEFINED: + num = 0; + denom = 0; + break; + + default: + num = 0; + denom = 0; + break; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) } - } - if (count > maxcount) - strcat (buffer, "..."); } -std::string Tag::nameToString (int i) { +void Tag::toString (char* buffer, int ofs) +{ + + if (type == UNDEFINED && !directory) { + bool isstring = true; + unsigned int i = 0; + + for (i = 0; i + ofs < count && i < 64 && value[i + ofs]; i++) + if (value[i + ofs] < 32 || value[i + ofs] > 126) { + isstring = false; + } + + if (isstring) { + int j = 0; + + for (i = 0; i + ofs < count && i < 64 && value[i + ofs]; i++) { + if (value[i + ofs] == '<' || value[i + ofs] == '>') { + buffer[j++] = '\\'; + } + + buffer[j++] = value[i + ofs]; + } + + buffer[j++] = 0; + return; + } + } else if (type == ASCII) { + sprintf (buffer, "%.64s", value + ofs); + return; + } + + size_t maxcount = 4; + + if (count < 4) { + maxcount = count; + } + + strcpy (buffer, ""); + + for (size_t i = 0; i < maxcount; i++) { + if (i > 0) { + strcat (buffer, ", "); + } + + char* b = buffer + strlen(buffer); + + switch (type) { + case UNDEFINED: + case BYTE: + sprintf (b, "%d", value[i + ofs]); + break; + + case SSHORT: + sprintf (b, "%d", toInt(2 * i + ofs)); + break; + + case SHORT: + sprintf (b, "%u", toInt(2 * i + ofs)); + break; + + case SLONG: + sprintf (b, "%ld", (long)toInt(4 * i + ofs)); + break; + + case LONG: + sprintf (b, "%lu", (unsigned long)toInt(4 * i + ofs)); + break; + + case SRATIONAL: + case RATIONAL: + sprintf (b, "%d/%d", (int)sget4 (value + 8 * i + ofs, getOrder()), (int)sget4 (value + 8 * i + ofs + 4, getOrder())); + break; + + case FLOAT: + sprintf (b, "%g", toDouble(8 * i + ofs)); + break; + + default: + break; + } + } + + if (count > maxcount) { + strcat (buffer, "..."); + } +} + +std::string Tag::nameToString (int i) +{ char buffer[1024]; - if (attrib) + + if (attrib) { strcpy (buffer, attrib->name); - else + } else { sprintf (buffer, "0x%x", tag); - if (i>0) - sprintf (buffer+strlen(buffer)-1, "[%d]", i); - return buffer; + } + + if (i > 0) { + sprintf (buffer + strlen(buffer) - 1, "[%d]", i); + } + + return buffer; } -std::string Tag::valueToString () { +std::string Tag::valueToString () +{ char buffer[1024]; - if (attrib && attrib->interpreter) + + if (attrib && attrib->interpreter) { return attrib->interpreter->toString (this); - else { + } else { toString (buffer); return buffer; } } -void Tag::valueFromString (const std::string& value) { +void Tag::valueFromString (const std::string& value) +{ - if (attrib && attrib->interpreter) + if (attrib && attrib->interpreter) { attrib->interpreter->fromString (this, value); + } } -int Tag::calculateSize () { +int Tag::calculateSize () +{ int size = 0; - + if (directory) { int j; - for (j=0; directory[j]; j++) + + for (j = 0; directory[j]; j++) { size += directory[j]->calculateSize (); - if (j>1) - size += 4*j; - } - else if (valuesize > 4) - size += valuesize + (valuesize%2); // we align tags to even byte positions - - if (makerNoteKind!=NOMK) - count = directory[0]->calculateSize () / getTypeSize(type); - - if (makerNoteKind==NIKON3 || makerNoteKind==OLYMPUS2 || makerNoteKind==FUJI) - size += valuesize; - else if (makerNoteKind==HEADERIFD) - size += valuesize; - return size; -} - -int Tag::write (int offs, int dataOffs, unsigned char* buffer) { - - if ((int)type==0 || offs>65500) - return dataOffs; - - sset2 (tag, buffer+offs, parent->getOrder()); - offs += 2; - unsigned short typ = type; - sset2 (typ, buffer+offs, parent->getOrder()); - offs += 2; - sset4 (count, buffer+offs, parent->getOrder()); - offs += 4; - if (!directory) { - if (valuesize>4) { - sset4 (dataOffs, buffer+offs, parent->getOrder()); - memcpy (buffer+dataOffs, value, valuesize); - if (valuesize%2) - buffer[dataOffs+valuesize] = 0; // zero padding required by the exif standard - return dataOffs + valuesize + (valuesize%2); - } - else { - memcpy (buffer+offs, value, valuesize); - return dataOffs; - } - } - else { - if (makerNoteKind==NIKON3) { - sset4 (dataOffs, buffer+offs, parent->getOrder()); - memcpy (buffer+dataOffs, value, 18); - dataOffs += 10; - dataOffs += directory[0]->write (8, buffer+dataOffs); - return dataOffs; - } - else if (makerNoteKind==OLYMPUS2 || makerNoteKind==FUJI) { - sset4 (dataOffs, buffer+offs, parent->getOrder()); - memcpy (buffer+dataOffs, value, valuesize); - dataOffs += valuesize + directory[0]->write (valuesize, buffer+dataOffs); - return dataOffs; - } - else if (makerNoteKind==HEADERIFD) { - sset4 (dataOffs, buffer+offs, parent->getOrder()); - memcpy (buffer+dataOffs, value, valuesize); - dataOffs += valuesize; - dataOffs += directory[0]->write (dataOffs, buffer); - return dataOffs; - } - else if( makerNoteKind==TABLESUBDIR){ - sset4 (dataOffs, buffer+offs, parent->getOrder()); - dataOffs = directory[0]->write (dataOffs, buffer); - return dataOffs; - } - else if (!directory[1]) { - sset4 (dataOffs, buffer+offs, parent->getOrder()); - return directory[0]->write (dataOffs, buffer); - } - else { - sset4 (dataOffs, buffer+offs, parent->getOrder()); - int linkOffs = dataOffs; - for (int i=0; directory[i]; i++) - dataOffs += 4; - for (int i=0; directory[i]; i++) { - sset4 (dataOffs, buffer+linkOffs, parent->getOrder()); - linkOffs += 4; - dataOffs = directory[i]->write (dataOffs, buffer); } + + if (j > 1) { + size += 4 * j; + } + } else if (valuesize > 4) { + size += valuesize + (valuesize % 2); // we align tags to even byte positions + } + + if (makerNoteKind != NOMK) { + count = directory[0]->calculateSize () / getTypeSize(type); + } + + if (makerNoteKind == NIKON3 || makerNoteKind == OLYMPUS2 || makerNoteKind == FUJI) { + size += valuesize; + } else if (makerNoteKind == HEADERIFD) { + size += valuesize; + } + + return size; +} + +int Tag::write (int offs, int dataOffs, unsigned char* buffer) +{ + + if ((int)type == 0 || offs > 65500) { return dataOffs; } - } + + sset2 (tag, buffer + offs, parent->getOrder()); + offs += 2; + unsigned short typ = type; + sset2 (typ, buffer + offs, parent->getOrder()); + offs += 2; + sset4 (count, buffer + offs, parent->getOrder()); + offs += 4; + + if (!directory) { + if (valuesize > 4) { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + memcpy (buffer + dataOffs, value, valuesize); + + if (valuesize % 2) { + buffer[dataOffs + valuesize] = 0; // zero padding required by the exif standard + } + + return dataOffs + valuesize + (valuesize % 2); + } else { + memcpy (buffer + offs, value, valuesize); + return dataOffs; + } + } else { + if (makerNoteKind == NIKON3) { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + memcpy (buffer + dataOffs, value, 18); + dataOffs += 10; + dataOffs += directory[0]->write (8, buffer + dataOffs); + return dataOffs; + } else if (makerNoteKind == OLYMPUS2 || makerNoteKind == FUJI) { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + memcpy (buffer + dataOffs, value, valuesize); + dataOffs += valuesize + directory[0]->write (valuesize, buffer + dataOffs); + return dataOffs; + } else if (makerNoteKind == HEADERIFD) { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + memcpy (buffer + dataOffs, value, valuesize); + dataOffs += valuesize; + dataOffs += directory[0]->write (dataOffs, buffer); + return dataOffs; + } else if( makerNoteKind == TABLESUBDIR) { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + dataOffs = directory[0]->write (dataOffs, buffer); + return dataOffs; + } else if (!directory[1]) { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + return directory[0]->write (dataOffs, buffer); + } else { + sset4 (dataOffs, buffer + offs, parent->getOrder()); + int linkOffs = dataOffs; + + for (int i = 0; directory[i]; i++) { + dataOffs += 4; + } + + for (int i = 0; directory[i]; i++) { + sset4 (dataOffs, buffer + linkOffs, parent->getOrder()); + linkOffs += 4; + dataOffs = directory[i]->write (dataOffs, buffer); + } + + return dataOffs; + } + } } Tag::Tag (TagDirectory* p, const TagAttrib* attr) - : tag(attr ? attr->ID : -1), type(INVALID), count(0), value(NULL), valuesize(0), keep(true), allocOwnMemory(true), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) { + : tag(attr ? attr->ID : -1), type(INVALID), count(0), value(NULL), valuesize(0), keep(true), allocOwnMemory(true), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) +{ } -Tag::Tag (TagDirectory* p, const TagAttrib* attr, int data, TagType t) - : tag(attr ? attr->ID : -1), type(t), count(1), value(NULL), valuesize(0), keep(true), allocOwnMemory(true), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) { +Tag::Tag (TagDirectory* p, const TagAttrib* attr, int data, TagType t) + : tag(attr ? attr->ID : -1), type(t), count(1), value(NULL), valuesize(0), keep(true), allocOwnMemory(true), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) +{ initInt (data, t); } Tag::Tag (TagDirectory* p, const TagAttrib* attr, unsigned char *data, TagType t) - : tag(attr ? attr->ID : -1), type(t), count(1), value(NULL), valuesize(0), keep(true), allocOwnMemory(false), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) { + : tag(attr ? attr->ID : -1), type(t), count(1), value(NULL), valuesize(0), keep(true), allocOwnMemory(false), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) +{ initType (data, t); } -Tag::Tag (TagDirectory* p, const TagAttrib* attr, const char* text) - : tag(attr ? attr->ID : -1), type(ASCII), count(1), value(NULL), valuesize(0), keep(true), allocOwnMemory(true), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) { +Tag::Tag (TagDirectory* p, const TagAttrib* attr, const char* text) + : tag(attr ? attr->ID : -1), type(ASCII), count(1), value(NULL), valuesize(0), keep(true), allocOwnMemory(true), attrib(attr), parent(p), directory(NULL), makerNoteKind (NOMK) +{ initString (text); } @@ -1373,41 +1738,48 @@ Tag::Tag (TagDirectory* p, const TagAttrib* attr, const char* text) void Tag::initType (unsigned char *data, TagType type) { valuesize = getTypeSize(type); - if( allocOwnMemory ){ - value = new unsigned char[valuesize]; - memcpy ((char*)value, data, valuesize); - }else + + if( allocOwnMemory ) { + value = new unsigned char[valuesize]; + memcpy ((char*)value, data, valuesize); + } else { value = data; + } } -void Tag::initInt (int data, TagType t, int cnt) { - +void Tag::initInt (int data, TagType t, int cnt) +{ + type = t; - if (t==LONG) + + if (t == LONG) { valuesize = 4; - else if (t==SHORT) + } else if (t == SHORT) { valuesize = 2; - else if (t==BYTE) + } else if (t == BYTE) { valuesize = 1; - else if (t==RATIONAL) + } else if (t == RATIONAL) { valuesize = 8; + } count = cnt; valuesize *= count; value = new unsigned char[valuesize]; setInt (data, 0, t); } - -void Tag::initString (const char* text) { + +void Tag::initString (const char* text) +{ type = ASCII; - count = strlen(text)+1; + count = strlen(text) + 1; valuesize = count; value = new unsigned char[valuesize]; strcpy ((char*)value, text); } -void Tag::initSubDir () { +void Tag::initSubDir () +{ type = LONG; valuesize = 4; count = 1; @@ -1418,7 +1790,8 @@ void Tag::initSubDir () { directory[1] = NULL; } -void Tag::initSubDir (TagDirectory* dir) { +void Tag::initSubDir (TagDirectory* dir) +{ type = LONG; valuesize = 4; count = 1; @@ -1429,7 +1802,8 @@ void Tag::initSubDir (TagDirectory* dir) { directory[1] = NULL; } -void Tag::initMakerNote (MNKind mnk, const TagAttrib* ta) { +void Tag::initMakerNote (MNKind mnk, const TagAttrib* ta) +{ type = UNDEFINED; valuesize = 4; count = 1; @@ -1441,22 +1815,25 @@ void Tag::initMakerNote (MNKind mnk, const TagAttrib* ta) { makerNoteKind = mnk; } -void Tag::initUndefArray (const char* data, int len) { +void Tag::initUndefArray (const char* data, int len) +{ type = UNDEFINED; count = valuesize = len; value = new unsigned char[valuesize]; memcpy (value, data, len); } -void Tag::initLongArray (const char* data, int len) { +void Tag::initLongArray (const char* data, int len) +{ type = LONG; - count = (len+3)/4; + count = (len + 3) / 4; valuesize = count * 4; value = new unsigned char[valuesize]; memcpy (value, data, len); } -void Tag::initRational (int num, int den) { +void Tag::initRational (int num, int den) +{ count = 1; valuesize = 8; value = new unsigned char[8]; @@ -1470,21 +1847,25 @@ void Tag::initRational (int num, int den) { //----------------------------------------------------------------------------- -const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field) { +const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field) +{ - for (int i=0; dir[i].ignore!=-1; i++) - if (!strcmp (dir[i].name, field)) + for (int i = 0; dir[i].ignore != -1; i++) + if (!strcmp (dir[i].name, field)) { return &dir[i]; + } + return 0; } -TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) { +TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) +{ TagDirectory* root = new TagDirectory (NULL, ifdAttribs, INTEL); - Tag* exif = new Tag (root, lookupAttrib(ifdAttribs,"Exif")); + Tag* exif = new Tag (root, lookupAttrib(ifdAttribs, "Exif")); exif->initSubDir (); - Tag* mn = new Tag (exif->getDirectory(), lookupAttrib(exifAttribs,"MakerNote")); + Tag* mn = new Tag (exif->getDirectory(), lookupAttrib(exifAttribs, "MakerNote")); mn->initMakerNote (IFD, canonAttribs); root->addTag (exif); exif->getDirectory()->addTag (mn); @@ -1493,7 +1874,8 @@ TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) { return root; } -Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name) { +Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name) +{ int s = ftell (f); char* data = new char [len]; fread (data, len, 1, f); @@ -1505,196 +1887,284 @@ Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const cha return cs; } -void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) { +void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) +{ - char buffer[1024]; - Tag* t; + char buffer[1024]; + Tag* t; - fseek (f, base+length-4, SEEK_SET); + fseek (f, base + length - 4, SEEK_SET); - int dirStart = get4 (f, INTEL) + base; - fseek (f, dirStart, SEEK_SET); + int dirStart = get4 (f, INTEL) + base; + fseek (f, dirStart, SEEK_SET); - int numOfTags = get2 (f, INTEL); + int numOfTags = get2 (f, INTEL); - if (numOfTags > 100) return; - - float exptime, shutter, aperture, fnumber, ev; - exptime = fnumber = shutter = aperture = ev = -1000.f; - int focal_len, iso; - focal_len = iso = -1; - - TagDirectory* exif = root->getTag("Exif")->getDirectory(); - - time_t timestamp = time (NULL); - - for (int i=0; i> 8) + 8) | 8) == 0x38) - parseCIFF (f, ftell(f), len, root); // Parse a sub-table - - if (type == 0x0810) { - fread (buffer, 64, 1, f); - t = new Tag (root, lookupAttrib(ifdAttribs,"Artist")); - t->initString (buffer); - root->addTag (t); + if (numOfTags > 100) { + return; } - if (type == 0x080a) { - fread (buffer, 64, 1, f); - t = new Tag (root, lookupAttrib(ifdAttribs,"Make")); - t->initString (buffer); - root->addTag (t); - fseek (f, strlen(buffer) - 63, SEEK_CUR); - fread (buffer, 64, 1, f); - t = new Tag (root, lookupAttrib(ifdAttribs,"Model")); - t->initString (buffer); - root->addTag (t); - } - if (type == 0x1818) { - ev = int_to_float(get4(f, INTEL)); - shutter = int_to_float(get4(f, INTEL)); - exptime = pow (2, -shutter); - aperture = int_to_float(get4(f, INTEL)); - fnumber = pow (2, aperture/2); - - } - if (type == 0x102d) { - Tag* t = saveCIFFMNTag (f, root, len, "CanonCameraSettings"); - int mm = t->toInt (34, SHORT); - Tag* nt = new Tag (exif, lookupAttrib(exifAttribs,"MeteringMode")); - switch (mm) { - case 0: nt->initInt (5, SHORT); break; - case 1: nt->initInt (3, SHORT); break; - case 2: nt->initInt (1, SHORT); break; - case 3: nt->initInt (5, SHORT); break; - case 4: nt->initInt (6, SHORT); break; - case 5: nt->initInt (2, SHORT); break; + + float exptime, shutter, aperture, fnumber, ev; + exptime = fnumber = shutter = aperture = ev = -1000.f; + int focal_len, iso; + focal_len = iso = -1; + + TagDirectory* exif = root->getTag("Exif")->getDirectory(); + + time_t timestamp = time (NULL); + + for (int i = 0; i < numOfTags; i++) { + + int type = get2 (f, INTEL); + int len = get4 (f, INTEL); + int nextPos = ftell (f) + 4; + + // seek to the location of the value + fseek (f, base + get4 (f, INTEL), SEEK_SET); + + if ((((type >> 8) + 8) | 8) == 0x38) { + parseCIFF (f, ftell(f), len, root); // Parse a sub-table + } + + if (type == 0x0810) { + fread (buffer, 64, 1, f); + t = new Tag (root, lookupAttrib(ifdAttribs, "Artist")); + t->initString (buffer); + root->addTag (t); + } + + if (type == 0x080a) { + fread (buffer, 64, 1, f); + t = new Tag (root, lookupAttrib(ifdAttribs, "Make")); + t->initString (buffer); + root->addTag (t); + fseek (f, strlen(buffer) - 63, SEEK_CUR); + fread (buffer, 64, 1, f); + t = new Tag (root, lookupAttrib(ifdAttribs, "Model")); + t->initString (buffer); + root->addTag (t); + } + + if (type == 0x1818) { + ev = int_to_float(get4(f, INTEL)); + shutter = int_to_float(get4(f, INTEL)); + exptime = pow (2, -shutter); + aperture = int_to_float(get4(f, INTEL)); + fnumber = pow (2, aperture / 2); + + } + + if (type == 0x102d) { + Tag* t = saveCIFFMNTag (f, root, len, "CanonCameraSettings"); + int mm = t->toInt (34, SHORT); + Tag* nt = new Tag (exif, lookupAttrib(exifAttribs, "MeteringMode")); + + switch (mm) { + case 0: + nt->initInt (5, SHORT); + break; + + case 1: + nt->initInt (3, SHORT); + break; + + case 2: + nt->initInt (1, SHORT); + break; + + case 3: + nt->initInt (5, SHORT); + break; + + case 4: + nt->initInt (6, SHORT); + break; + + case 5: + nt->initInt (2, SHORT); + break; + } + + exif->addTag (nt); + nt = new Tag (exif, lookupAttrib(exifAttribs, "MaxApertureValue")); + nt->initRational (t->toInt(52, SHORT), 32); + exif->addTag (nt); + int em = t->toInt(40, SHORT); + nt = new Tag (exif, lookupAttrib(exifAttribs, "ExposureProgram")); + + switch (em) { + case 0: + nt->initInt (2, SHORT); + break; + + case 1: + nt->initInt (2, SHORT); + break; + + case 2: + nt->initInt (4, SHORT); + break; + + case 3: + nt->initInt (3, SHORT); + break; + + case 4: + nt->initInt (1, SHORT); + break; + + default: + nt->initInt (0, SHORT); + break; + } + + exif->addTag (nt); + nt = new Tag (exif, lookupAttrib(exifAttribs, "Flash")); + + if (t->toInt(8, SHORT) == 0) { + nt->initInt (0, SHORT); + } else { + nt->initInt (1, SHORT); + } + + exif->addTag (nt); + nt = new Tag (exif, lookupAttrib(exifAttribs, "MaxApertureValue")); + nt->initRational (t->toInt(52, SHORT), 32); + exif->addTag (nt); + } + + if (type == 0x1029) { + saveCIFFMNTag (f, root, len, "CanonFocalLength"); + } + + if (type == 0x1031) { + saveCIFFMNTag (f, root, len, "SensorInfo"); + } + + if (type == 0x1033) { + saveCIFFMNTag (f, root, len, "CustomFunctions"); + } + + if (type == 0x1038) { + saveCIFFMNTag (f, root, len, "CanonAFInfo"); + } + + if (type == 0x1093) { + saveCIFFMNTag (f, root, len, "CanonFileInfo"); + } + + if (type == 0x10a9) { + saveCIFFMNTag (f, root, len, "ColorBalance"); + } + + if (type == 0x102a) { + saveCIFFMNTag (f, root, len, "CanonShotInfo"); + + iso = pow (2, (get4(f, INTEL), get2(f, INTEL)) / 32.0 - 4) * 50; + aperture = (get2(f, INTEL), (short)get2(f, INTEL)) / 32.0f; + fnumber = pow (2, aperture / 2); + shutter = ((short)get2(f, INTEL)) / 32.0f; + ev = ((short)get2(f, INTEL)) / 32.0f; + fseek (f, 34, SEEK_CUR); + + if (shutter > 1e6) { + shutter = get2 (f, INTEL) / 10.0f; + } + + exptime = pow (2, -shutter); + } + + if (type == 0x5029) { + focal_len = len >> 16; + + if ((len & 0xffff) == 2) { + focal_len /= 32; + } } - exif->addTag (nt); - nt = new Tag (exif, lookupAttrib(exifAttribs,"MaxApertureValue")); - nt->initRational (t->toInt(52,SHORT), 32); - exif->addTag (nt); - int em = t->toInt(40,SHORT); - nt = new Tag (exif, lookupAttrib(exifAttribs,"ExposureProgram")); - switch (em) { - case 0: nt->initInt (2, SHORT); break; - case 1: nt->initInt (2, SHORT); break; - case 2: nt->initInt (4, SHORT); break; - case 3: nt->initInt (3, SHORT); break; - case 4: nt->initInt (1, SHORT); break; - default: nt->initInt (0, SHORT); break; - } - exif->addTag (nt); - nt = new Tag (exif, lookupAttrib(exifAttribs,"Flash")); - if (t->toInt(8,SHORT)==0) - nt->initInt (0, SHORT); - else - nt->initInt (1, SHORT); - exif->addTag (nt); - nt = new Tag (exif, lookupAttrib(exifAttribs,"MaxApertureValue")); - nt->initRational (t->toInt(52,SHORT), 32); - exif->addTag (nt); - } - if (type == 0x1029) - saveCIFFMNTag (f, root, len, "CanonFocalLength"); - if (type == 0x1031) - saveCIFFMNTag (f, root, len, "SensorInfo"); - if (type == 0x1033) - saveCIFFMNTag (f, root, len, "CustomFunctions"); - if (type == 0x1038) - saveCIFFMNTag (f, root, len, "CanonAFInfo"); - if (type == 0x1093) - saveCIFFMNTag (f, root, len, "CanonFileInfo"); - if (type == 0x10a9) - saveCIFFMNTag (f, root, len, "ColorBalance"); - if (type == 0x102a) { - saveCIFFMNTag (f, root, len, "CanonShotInfo"); - iso = pow (2, (get4(f, INTEL),get2(f, INTEL))/32.0 - 4) * 50; - aperture = (get2(f, INTEL),(short)get2(f, INTEL))/32.0f; - fnumber = pow (2, aperture/2); - shutter = ((short)get2(f, INTEL))/32.0f; - ev = ((short)get2(f, INTEL))/32.0f; - fseek (f, 34, SEEK_CUR); - if (shutter > 1e6) shutter = get2 (f, INTEL) / 10.0f; - exptime = pow (2,-shutter); - } - if (type == 0x5029) { - focal_len = len >> 16; - if ((len & 0xffff) == 2) focal_len /= 32; - } // if (type == 0x5813) flash_used = int_to_float(len); - if (type == 0x580e) timestamp = len; - if (type == 0x180e) timestamp = get4 (f, INTEL); - if ((type | 0x4000) == 0x580e) - timestamp = mktime (gmtime (×tamp)); - fseek (f, nextPos, SEEK_SET); - } - if (shutter>-999) { - t = new Tag (exif, lookupAttrib(exifAttribs,"ShutterSpeedValue")); - t->initRational ((int)(shutter*10000), 10000); - exif->addTag (t); - } - if (exptime>-999) { - t = new Tag (exif, lookupAttrib(exifAttribs,"ExposureTime")); - t->initRational ((int)(exptime*10000), 10000); - exif->addTag (t); - } - if (aperture>-999) { - t = new Tag (exif, lookupAttrib(exifAttribs,"ApertureValue")); - t->initRational ((int)(aperture*10), 10); - exif->addTag (t); - } - if (fnumber>-999) { - t = new Tag (exif, lookupAttrib(exifAttribs,"FNumber")); - t->initRational ((int)(fnumber*10), 10); - exif->addTag (t); - } - if (ev>-999) { - t = new Tag (exif, lookupAttrib(exifAttribs,"ExposureBiasValue")); - t->initRational ((int)(ev*1000), 1000); - exif->addTag (t); - } - if (iso>0) { - t = new Tag (exif, lookupAttrib(exifAttribs,"ISOSpeedRatings")); - t->initInt (iso, LONG); - exif->addTag (t); - } - if (focal_len>0) { - t = new Tag (exif, lookupAttrib(exifAttribs,"FocalLength")); - t->initRational (focal_len*32, 32); - exif->addTag (t); - } + if (type == 0x580e) { + timestamp = len; + } - if (timestamp!=time(NULL)) { - struct tm* tim = localtime (×tamp); - strftime (buffer, 20, "%Y:%m:%d %H:%M:%S", tim); - t = new Tag (exif, lookupAttrib(exifAttribs,"DateTimeOriginal")); - t->initString (buffer); - exif->addTag (t); - t = new Tag (exif, lookupAttrib(exifAttribs,"DateTimeDigitized")); - t->initString (buffer); - exif->addTag (t); - t = new Tag (root, lookupAttrib(ifdAttribs,"DateTime")); - t->initString (buffer); - root->addTag (t); - } + if (type == 0x180e) { + timestamp = get4 (f, INTEL); + } + + if ((type | 0x4000) == 0x580e) { + timestamp = mktime (gmtime (×tamp)); + } + + fseek (f, nextPos, SEEK_SET); + } + + if (shutter > -999) { + t = new Tag (exif, lookupAttrib(exifAttribs, "ShutterSpeedValue")); + t->initRational ((int)(shutter * 10000), 10000); + exif->addTag (t); + } + + if (exptime > -999) { + t = new Tag (exif, lookupAttrib(exifAttribs, "ExposureTime")); + t->initRational ((int)(exptime * 10000), 10000); + exif->addTag (t); + } + + if (aperture > -999) { + t = new Tag (exif, lookupAttrib(exifAttribs, "ApertureValue")); + t->initRational ((int)(aperture * 10), 10); + exif->addTag (t); + } + + if (fnumber > -999) { + t = new Tag (exif, lookupAttrib(exifAttribs, "FNumber")); + t->initRational ((int)(fnumber * 10), 10); + exif->addTag (t); + } + + if (ev > -999) { + t = new Tag (exif, lookupAttrib(exifAttribs, "ExposureBiasValue")); + t->initRational ((int)(ev * 1000), 1000); + exif->addTag (t); + } + + if (iso > 0) { + t = new Tag (exif, lookupAttrib(exifAttribs, "ISOSpeedRatings")); + t->initInt (iso, LONG); + exif->addTag (t); + } + + if (focal_len > 0) { + t = new Tag (exif, lookupAttrib(exifAttribs, "FocalLength")); + t->initRational (focal_len * 32, 32); + exif->addTag (t); + } + + if (timestamp != time(NULL)) { + struct tm* tim = localtime (×tamp); + strftime (buffer, 20, "%Y:%m:%d %H:%M:%S", tim); + t = new Tag (exif, lookupAttrib(exifAttribs, "DateTimeOriginal")); + t->initString (buffer); + exif->addTag (t); + t = new Tag (exif, lookupAttrib(exifAttribs, "DateTimeDigitized")); + t->initString (buffer); + exif->addTag (t); + t = new Tag (root, lookupAttrib(ifdAttribs, "DateTime")); + t->initString (buffer); + root->addTag (t); + } } static void -parse_leafdata(TagDirectory* root, ByteOrder order) { +parse_leafdata(TagDirectory* root, ByteOrder order) +{ Tag *leafdata = root->getTag("LeafData"); + if (!leafdata) { return; } + unsigned char *value = leafdata->getValue(); int valuesize = leafdata->getValueSize(); @@ -1710,30 +2180,39 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { int iso_speed = 0; int rotation_angle = 0; int found_count = 0; + while (pos + (int)sizeof(hdr) <= valuesize && found_count < 2) { hdr = (char *)&value[pos]; + if (strncmp(hdr, PKTS_tag, 4) != 0) { // in a few cases the header can be offset a few bytes, don't know why // it does not seem to be some sort of alignment, it appears random, // this check takes care of it, restart if we find an offset match. int offset = 1; + for (; offset <= 3; offset++) { if (strncmp(&hdr[offset], PKTS_tag, 4) == 0) { pos += offset; break; } } + if (offset <= 3) { continue; } + break; } + int size = sget4((unsigned char *)&hdr[48], order); + if (pos + size > valuesize) { break; } + pos += 52; char *val = (char *)&value[pos]; + if (strncmp(&hdr[8], "CameraObj_ISO_speed", 19) == 0) { iso_speed = 25 * (1 << (atoi(val) - 1)); found_count++; @@ -1743,39 +2222,58 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { } else { // check if this is a sub-directory, include test for that strange offset of next header if (size >= 8 && - (strncmp(val, PKTS_tag, 4) == 0 || - strncmp(&val[1], PKTS_tag, 4) == 0 || - strncmp(&val[2], PKTS_tag, 4) == 0 || - strncmp(&val[3], PKTS_tag, 4) == 0)) - { + (strncmp(val, PKTS_tag, 4) == 0 || + strncmp(&val[1], PKTS_tag, 4) == 0 || + strncmp(&val[2], PKTS_tag, 4) == 0 || + strncmp(&val[3], PKTS_tag, 4) == 0)) { // start of next hdr, this is a sub-directory, we skip those for now. size = 0; } } + pos += size; } // create standard tags from the custom Leaf tags Tag* exif = root->getTag ("Exif"); + if (!exif) { exif = new Tag (root, root->getAttrib ("Exif")); exif->initSubDir(); root->addTagFront (exif); } + if (!exif->getDirectory()->getTag("ISOSpeedRatings")) { Tag *t = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); t->initInt (iso_speed, LONG); exif->getDirectory()->addTagFront (t); } + if (!root->getTag("Orientation")) { int orientation; + switch (rotation_angle) { - case 0: orientation = 1; break; - case 90: orientation = 6; break; - case 180: orientation = 3; break; - case 270: orientation = 8; break; - default: orientation = 1; break; + case 0: + orientation = 1; + break; + + case 90: + orientation = 6; + break; + + case 180: + orientation = 3; + break; + + case 270: + orientation = 8; + break; + + default: + orientation = 1; + break; } + Tag *t = new Tag (root, root->getAttrib ("Orientation")); t->initInt (orientation, SHORT); root->addTagFront (t); @@ -1783,43 +2281,53 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { // now look in ApplicationNotes tag for additional information Tag *appnotes = root->getTag("ApplicationNotes"); + if (!appnotes) { return; } + char *xmp = (char *)appnotes->getValue(); char *end, *p; + // Quick-and-dirty value extractor, no real xml parsing. // We could make it more generic, but we just get most important // values we know use to be in there. if ((p = strstr(xmp, "xmlns:tiff")) != NULL && - (end = strstr(p, "")) != NULL) - { + (end = strstr(p, "")) != NULL) { *end = '\0'; + while ((p = strstr(p, "')) == NULL) { break; } + *tagend = '\0'; char *val = &tagend[1]; + if ((p = strstr(val, "getAttrib (tag) && !root->getTag (tag)) { Tag *t = new Tag (root, root->getAttrib (tag)); + if (strcmp(tag, "Make") == 0 || - strcmp(tag, "Model") == 0) - { + strcmp(tag, "Model") == 0) { if (strcmp(tag, "Model") == 0) { // Leaf adds back serial number and camera model to the 'Model' // tag, we strip that away here so the back can be recognized // and matched against DCP profile char *p1 = strchr(val, '('); + if (p1 != NULL) { *p1 = '\0'; } + // Model name also contains a leading "Leaf " which we already // have in the Make name, remove that. if (strstr(val, "Leaf ") == val) { @@ -1827,62 +2335,76 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { } else { t->initString (val); } + if (p1 != NULL) { *p1 = '('; } } else { t->initString (val); } + root->addTagFront (t); } else { delete t; } } + *p = '<'; *tagend = '>'; } + *end = '<'; } + if ((p = strstr(xmp, "xmlns:exif")) != NULL && - (end = strstr(p, "")) != NULL) - { + (end = strstr(p, "")) != NULL) { *end = '\0'; + while ((p = strstr(p, "')) == NULL) { break; } + *tagend = '\0'; char *val = &tagend[1]; + if ((p = strstr(val, "getDirectory()->getAttrib (tag) && !exif->getDirectory()->getTag (tag)) { Tag *t = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib (tag)); int num, denom; struct tm tm; + if (strcmp(tag, "ApertureValue") == 0 && sscanf(val, "%d/%d", &num, &denom) == 2) { t->initRational (num, denom); exif->getDirectory()->addTagFront (t); // we also make an "FNumber" tag since many tools don't interpret ApertureValue // according to Exif standard - t = new Tag (exif->getDirectory(), lookupAttrib(exifAttribs,"FNumber")); + t = new Tag (exif->getDirectory(), lookupAttrib(exifAttribs, "FNumber")); double f = pow(sqrt(2.0), ((double)num / denom)); + if (f > 10.0) { t->initRational ((int)floor(f), 1); } else { t->initRational ((int)floor(f * 10.0), 10); } + exif->getDirectory()->addTagFront (t); } else if (strcmp(tag, "ShutterSpeedValue") == 0 && sscanf(val, "%d/%d", &num, &denom) == 2) { t->initRational (num, denom); exif->getDirectory()->addTagFront (t); // we also make an "ExposureTime" tag since many tools don't interpret ShutterSpeedValue // according to Exif standard - t = new Tag (exif->getDirectory(), lookupAttrib(exifAttribs,"ExposureTime")); + t = new Tag (exif->getDirectory(), lookupAttrib(exifAttribs, "ExposureTime")); double f = 1.0 / pow(2.0, ((double)num / denom)); + if (f > 10.0) { t->initRational ((int)floor(f), 1); } else if (f > 1.0) { @@ -1905,31 +2427,40 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { 8, 6, 5, 4, 3, 2.5, 2, 1.6, 1.5, 1.3, - 1, -1 }; + 1, -1 + }; double diff = etimes[0]; int idx = -1; + for (int i = 1; etimes[i] > 0; i++) { if (abs(etimes[i] - f) < diff) { idx = i; diff = abs(etimes[i] - f); } } + if (idx != -1 && f < etimes[0]) { f = etimes[idx]; } + if (f < 2) { t->initRational (10, (int)(10 * f)); } else { t->initRational (1, (int)f); } } + exif->getDirectory()->addTagFront (t); } else if (strcmp(tag, "FocalLength") == 0 && sscanf(val, "%d/%d", &num, &denom) == 2) { t->initRational (num, denom); exif->getDirectory()->addTagFront (t); } else if (strcmp(tag, "ISOSpeedRatings") == 0) { char *p1 = val; - while (*p1 != '\0' && !isdigit(*p1)) p1++; + + while (*p1 != '\0' && !isdigit(*p1)) { + p1++; + } + if (*p1 != '\0') { t->initInt (atoi(p1), LONG); exif->getDirectory()->addTagFront (t); @@ -1938,8 +2469,7 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { sscanf(val, "%d-%d-%dT%d:%d:%dZ", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, - &tm.tm_min, &tm.tm_sec) == 6) - { + &tm.tm_min, &tm.tm_sec) == 6) { char tstr[64]; sprintf(tstr, "%04d:%02d:%02d %02d:%02d:%02d", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); @@ -1949,37 +2479,53 @@ parse_leafdata(TagDirectory* root, ByteOrder order) { delete t; } } + *p = '<'; *tagend = '>'; } + *end = '<'; } } -TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) { - setlocale(LC_NUMERIC, "C"); // to set decimal point in sscanf - // read tiff header - fseek (f, base, SEEK_SET); - unsigned short bo; - fread (&bo, 1, 2, f); - ByteOrder order = (ByteOrder)((int)bo); - get2 (f, order); - int firstifd = get4 (f, order); +TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) +{ + setlocale(LC_NUMERIC, "C"); // to set decimal point in sscanf + // read tiff header + fseek (f, base, SEEK_SET); + unsigned short bo; + fread (&bo, 1, 2, f); + ByteOrder order = (ByteOrder)((int)bo); + get2 (f, order); + int firstifd = get4 (f, order); - // seek to IFD0 - fseek (f, base+firstifd, SEEK_SET); + // seek to IFD0 + fseek (f, base + firstifd, SEEK_SET); - // first read the IFD directory - TagDirectory* root = new TagDirectory (NULL, f, base, ifdAttribs, order, skipIgnored); + // first read the IFD directory + TagDirectory* root = new TagDirectory (NULL, f, base, ifdAttribs, order, skipIgnored); + + // fix ISO issue with nikon and panasonic cameras + Tag* make = root->getTag ("Make"); + Tag* exif = root->getTag ("Exif"); + + if (exif && !exif->getDirectory()->getTag("ISOSpeedRatings")) { + if (make && !strncmp((char*)make->getValue(), "NIKON", 5)) { + Tag* mn = exif->getDirectory()->getTag("MakerNote"); + + if (mn) { + Tag* iso = mn->getDirectory()->getTag("ISOSpeed"); + + if (iso) { + std::string isov = iso->valueToString (); + Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); + niso->initInt (atoi(isov.c_str()), SHORT); + exif->getDirectory()->addTagFront (niso); + } + } + } else if (make && (!strncmp((char*)make->getValue(), "Panasonic", 9) || !strncmp((char*)make->getValue(), "LEICA", 5))) { + Tag* iso = root->getTag("PanaISO"); - // fix ISO issue with nikon and panasonic cameras - Tag* make = root->getTag ("Make"); - Tag* exif = root->getTag ("Exif"); - if (exif && !exif->getDirectory()->getTag("ISOSpeedRatings")) { - if (make && !strncmp((char*)make->getValue(), "NIKON", 5)) { - Tag* mn = exif->getDirectory()->getTag("MakerNote"); - if (mn) { - Tag* iso = mn->getDirectory()->getTag("ISOSpeed"); if (iso) { std::string isov = iso->valueToString (); Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); @@ -1988,328 +2534,419 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) { } } } - else if (make && (!strncmp((char*)make->getValue(), "Panasonic", 9) || !strncmp((char*)make->getValue(), "LEICA", 5))) { - Tag* iso = root->getTag("PanaISO"); - if (iso) { - std::string isov = iso->valueToString (); - Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); - niso->initInt (atoi(isov.c_str()), SHORT); - exif->getDirectory()->addTagFront (niso); + + if (make && !strncmp((char*)make->getValue(), "Kodak", 5)) { + if (!exif) { + // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir + fseek (f, base + firstifd, SEEK_SET); + TagDirectory* exifdir = new TagDirectory (NULL, f, base, exifAttribs, order, true); + + exif = new Tag (root, root->getAttrib ("Exif")); + exif->initSubDir(exifdir); + root->addTagFront (exif); + + if (!exif->getDirectory()->getTag("ISOSpeedRatings") && exif->getDirectory()->getTag ("ExposureIndex")) { + Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); + niso->initInt (exif->getDirectory()->getTag ("ExposureIndex")->toInt(), SHORT); + exif->getDirectory()->addTagFront (niso); + } + } + + Tag *kodakIFD = root->getTag("KodakIFD"); + + if (kodakIFD && kodakIFD->getDirectory()->getTag("TextualInfo")) { + parseKodakIfdTextualInfo(kodakIFD->getDirectory()->getTag("TextualInfo"), exif); } } - } - if (make && !strncmp((char*)make->getValue(), "Kodak", 5)) { - if (!exif) { - // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir - fseek (f, base+firstifd, SEEK_SET); - TagDirectory* exifdir = new TagDirectory (NULL, f, base, exifAttribs, order, true); - exif = new Tag (root, root->getAttrib ("Exif")); - exif->initSubDir(exifdir); - root->addTagFront (exif); + parse_leafdata(root, order); - if (!exif->getDirectory()->getTag("ISOSpeedRatings") && exif->getDirectory()->getTag ("ExposureIndex")) { - Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); - niso->initInt (exif->getDirectory()->getTag ("ExposureIndex")->toInt(), SHORT); - exif->getDirectory()->addTagFront (niso); - } - } - Tag *kodakIFD = root->getTag("KodakIFD"); - if (kodakIFD && kodakIFD->getDirectory()->getTag("TextualInfo")) { - parseKodakIfdTextualInfo(kodakIFD->getDirectory()->getTag("TextualInfo"), exif); - } - } + if (make && !strncmp((char*)make->getValue(), "Hasselblad", 10)) { + /* + Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly + different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through + Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and + Phocus-generated DNGs. - parse_leafdata(root, order); + FFF usually has a sane model name in Model (and is used as reference for what we shall + call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for + all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body. + V-mount backs may have the model name of the V body instead of the back model. Etc... + as said it's a mess. - if (make && !strncmp((char*)make->getValue(), "Hasselblad", 10)) { - /* - Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly - different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through - Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and - Phocus-generated DNGs. + This code is supposed to handle all raw containers and end up with the same model + regardless of container. - FFF usually has a sane model name in Model (and is used as reference for what we shall - call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for - all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body. - V-mount backs may have the model name of the V body instead of the back model. Etc... - as said it's a mess. + We don't differ between single shot and multi-shot models, and probably there's no use + of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that + tethered. In single-shot mode they should be exactly the same as the single-shot models. + */ + Tag *subd = root->getTag(0x14a); + Tag *iw = (subd) ? subd->getDirectory()->getTag("ImageWidth") : 0; + int sensorWidth = (iw) ? iw->toInt() : 0; + Tag* tmodel = root->getTag ("Model"); + const char *model = (tmodel) ? (const char *)tmodel->getValue() : ""; - This code is supposed to handle all raw containers and end up with the same model - regardless of container. + if (strstr(model, "Hasselblad ") == model) { + model += 11; + } else { + // if HxD is used in flash sync mode for example, we need to fetch model from this tag + Tag* tmodel3 = root->getTag("UniqueCameraModel"); + const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - We don't differ between single shot and multi-shot models, and probably there's no use - of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that - tethered. In single-shot mode they should be exactly the same as the single-shot models. - */ - Tag *subd = root->getTag(0x14a); - Tag *iw = (subd) ? subd->getDirectory()->getTag("ImageWidth") : 0; - int sensorWidth = (iw) ? iw->toInt() : 0; - Tag* tmodel = root->getTag ("Model"); - const char *model = (tmodel) ? (const char *)tmodel->getValue() : ""; - if (strstr(model, "Hasselblad ") == model) { - model += 11; - } else { - // if HxD is used in flash sync mode for example, we need to fetch model from this tag - Tag* tmodel3 = root->getTag("UniqueCameraModel"); - const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - if (strstr(model3, "Hasselblad ") == model3) { - model = model3 + 11; - } - } - // FIXME: due to lack of test files this Hasselblad model identification is not 100% complete - // This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models + if (strstr(model3, "Hasselblad ") == model3) { + model = model3 + 11; + } + } - if (!strcmp(model, "H3D")) { - // We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a - // H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance - // to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50 - // H3D-50 although Hasselblad never released such a model. - switch (sensorWidth) { - case 4096: tmodel->initString("H3D-22"); break; - case 6542: tmodel->initString("H3D-31"); break; - case 7262: tmodel->initString("H3D-39"); break; - case 8282: tmodel->initString("H3DII-50"); break; - } - } else if (!strcmp(model, "H4D")) { - switch (sensorWidth) { - case 6542: tmodel->initString("H4D-31"); break; - case 7410: tmodel->initString("H4D-40"); break; - case 8282: tmodel->initString("H4D-50"); break; - case 9044: tmodel->initString("H4D-60"); break; - } - } else if (!strcmp(model, "H5D")) { - switch (sensorWidth) { - case 7410: tmodel->initString("H5D-40"); break; - case 8282: tmodel->initString("H5D-50"); break; - case 8374: tmodel->initString("H5D-50c"); break; - case 9044: tmodel->initString("H5D-60"); break; - } - } else if (!strcmp(model, "CFV")) { - switch (sensorWidth) { - case 7262: tmodel->initString("CFV-39"); break; - case 8282: tmodel->initString("CFV-50"); break; - case 8374: tmodel->initString("CFV-50c"); break; - } - } + // FIXME: due to lack of test files this Hasselblad model identification is not 100% complete + // This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models - // and a few special cases - Tag* tmodel3 = root->getTag("UniqueCameraModel"); - const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - if (strstr(model3, "Hasselblad ") == model3) { - model3 = model3 + 11; - } - if (!strcmp(model3, "ixpressCF132")) { - tmodel->initString("CF-22"); - } else if (!strcmp(model3, "Hasselblad96")) { - tmodel->initString("CFV"); // popularly called CFV-16, but the official name is CFV - } else if (!strcmp(model3, "Hasselblad234")) { - tmodel->initString("CFV-39"); - } else if (sensorWidth == 4090) { - tmodel->initString("V96C"); - } + if (!strcmp(model, "H3D")) { + // We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a + // H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance + // to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50 + // H3D-50 although Hasselblad never released such a model. + switch (sensorWidth) { + case 4096: + tmodel->initString("H3D-22"); + break; - // and yet some, this is for Adobe-generated DNG files - Tag* tmodel4 = root->getTag("LocalizedCameraModel"); - if (tmodel4) { - const char *model4 = (tmodel4) ? (const char *)tmodel4->getValue() : ""; - if (strstr(model4, "Hasselblad ") == model4) { - model4 = model4 + 11; - } - if (!strcmp(model4, "ixpressCF132-22")) { - tmodel->initString("CF-22"); - } else if (!strcmp(model4, "Hasselblad96-16")) { - tmodel->initString("CFV"); - } else if (!strcmp(model4, "Hasselblad234-39")) { - tmodel->initString("CFV-39"); - } else if (!strcmp(model4, "H3D-50")) { - // Adobe names H3DII-50 incorrectly as H3D-50 - tmodel->initString("H3DII-50"); - } else if (strstr(model4, "H3D-") == model4 || strstr(model4, "H4D-") == model4 || strstr(model4, "H5D-") == model4) { - tmodel->initString(model4); - } - } - } + case 6542: + tmodel->initString("H3D-31"); + break; - if (!root->getTag("Orientation")) { - if (make && !strncmp((char*)make->getValue(), "Phase One", 9)) { - int orientation = 0; - Tag *iw = root->getTag("ImageWidth"); - if (iw) { - // from dcraw, derive orientation from image width - orientation = "0653"[iw->toInt()&3]-'0'; - } - Tag *t = new Tag (root, root->getAttrib ("Orientation")); - t->initInt (orientation, SHORT); - root->addTagFront (t); - } - } + case 7262: + tmodel->initString("H3D-39"); + break; + + case 8282: + tmodel->initString("H3DII-50"); + break; + } + } else if (!strcmp(model, "H4D")) { + switch (sensorWidth) { + case 6542: + tmodel->initString("H4D-31"); + break; + + case 7410: + tmodel->initString("H4D-40"); + break; + + case 8282: + tmodel->initString("H4D-50"); + break; + + case 9044: + tmodel->initString("H4D-60"); + break; + } + } else if (!strcmp(model, "H5D")) { + switch (sensorWidth) { + case 7410: + tmodel->initString("H5D-40"); + break; + + case 8282: + tmodel->initString("H5D-50"); + break; + + case 8374: + tmodel->initString("H5D-50c"); + break; + + case 9044: + tmodel->initString("H5D-60"); + break; + } + } else if (!strcmp(model, "CFV")) { + switch (sensorWidth) { + case 7262: + tmodel->initString("CFV-39"); + break; + + case 8282: + tmodel->initString("CFV-50"); + break; + + case 8374: + tmodel->initString("CFV-50c"); + break; + } + } + + // and a few special cases + Tag* tmodel3 = root->getTag("UniqueCameraModel"); + const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; + + if (strstr(model3, "Hasselblad ") == model3) { + model3 = model3 + 11; + } + + if (!strcmp(model3, "ixpressCF132")) { + tmodel->initString("CF-22"); + } else if (!strcmp(model3, "Hasselblad96")) { + tmodel->initString("CFV"); // popularly called CFV-16, but the official name is CFV + } else if (!strcmp(model3, "Hasselblad234")) { + tmodel->initString("CFV-39"); + } else if (sensorWidth == 4090) { + tmodel->initString("V96C"); + } + + // and yet some, this is for Adobe-generated DNG files + Tag* tmodel4 = root->getTag("LocalizedCameraModel"); + + if (tmodel4) { + const char *model4 = (tmodel4) ? (const char *)tmodel4->getValue() : ""; + + if (strstr(model4, "Hasselblad ") == model4) { + model4 = model4 + 11; + } + + if (!strcmp(model4, "ixpressCF132-22")) { + tmodel->initString("CF-22"); + } else if (!strcmp(model4, "Hasselblad96-16")) { + tmodel->initString("CFV"); + } else if (!strcmp(model4, "Hasselblad234-39")) { + tmodel->initString("CFV-39"); + } else if (!strcmp(model4, "H3D-50")) { + // Adobe names H3DII-50 incorrectly as H3D-50 + tmodel->initString("H3DII-50"); + } else if (strstr(model4, "H3D-") == model4 || strstr(model4, "H4D-") == model4 || strstr(model4, "H5D-") == model4) { + tmodel->initString(model4); + } + } + } + + if (!root->getTag("Orientation")) { + if (make && !strncmp((char*)make->getValue(), "Phase One", 9)) { + int orientation = 0; + Tag *iw = root->getTag("ImageWidth"); + + if (iw) { + // from dcraw, derive orientation from image width + orientation = "0653"[iw->toInt() & 3] - '0'; + } + + Tag *t = new Tag (root, root->getAttrib ("Orientation")); + t->initInt (orientation, SHORT); + root->addTagFront (t); + } + } // root->printAll (); - return root; + return root; } -TagDirectory* ExifManager::parseJPEG (FILE* f) { +TagDirectory* ExifManager::parseJPEG (FILE* f) +{ - fseek (f, 0, SEEK_SET); - unsigned char markerl = 0xff; - unsigned char c; - fread (&c, 1, 1, f); - const char exifid[] = "Exif\0\0"; - char idbuff[8]; - int tiffbase = -1; - while (fread (&c, 1, 1, f)) { - if (c!=markerl) continue; - if (fread (&c, 1, 1, f) && c==0xe1) { // APP1 marker found - if (fread (idbuff, 1, 8, f)<8) - return NULL; - if (!memcmp(idbuff+2, exifid, 6)) { // Exif info found - tiffbase = ftell (f); - return parse (f, tiffbase); - } + fseek (f, 0, SEEK_SET); + unsigned char markerl = 0xff; + unsigned char c; + fread (&c, 1, 1, f); + const char exifid[] = "Exif\0\0"; + char idbuff[8]; + int tiffbase = -1; + + while (fread (&c, 1, 1, f)) { + if (c != markerl) { + continue; + } + + if (fread (&c, 1, 1, f) && c == 0xe1) { // APP1 marker found + if (fread (idbuff, 1, 8, f) < 8) { + return NULL; + } + + if (!memcmp(idbuff + 2, exifid, 6)) { // Exif info found + tiffbase = ftell (f); + return parse (f, tiffbase); + } + } } - } - return NULL; + + return NULL; } -TagDirectory* ExifManager::parseTIFF (FILE* f, bool skipIgnored) { +TagDirectory* ExifManager::parseTIFF (FILE* f, bool skipIgnored) +{ - return parse (f, 0, skipIgnored); + return parse (f, 0, skipIgnored); } -std::vector ExifManager::defTags; +std::vector ExifManager::defTags; // forthis: the byte order will be taken from directory "forthis" -const std::vector& ExifManager::getDefaultTIFFTags (TagDirectory* forthis) { +const std::vector& ExifManager::getDefaultTIFFTags (TagDirectory* forthis) +{ - for (size_t i=0; igetOrder (); - sset2 ((unsigned short)order, buffer+offs, order); offs += 2; - sset2 (42, buffer+offs, order); offs += 2; - sset4 (8, buffer+offs, order); offs += 4; + // write tiff header + int offs = 6; + memcpy (buffer, "Exif\0\0", 6); + ByteOrder order = INTEL; - TagDirectory* cl; - if (root) - cl = (const_cast(root))->clone (NULL); - else - cl = new TagDirectory (NULL, ifdAttribs, INTEL); + if (root) { + order = root->getOrder (); + } - for (rtengine::procparams::ExifPairs::const_iterator i=changeList.begin(); i!=changeList.end(); i++) - cl->applyChange (i->first, i->second); - - getDefaultTIFFTags (cl); - - defTags[0]->setInt (W, 0, LONG); - defTags[1]->setInt (H, 0, LONG); - defTags[8]->setInt (8, 0, SHORT); - - for (int i=defTags.size()-1; i>=0; i--) - cl->replaceTag (defTags[i]->clone (cl)); - cl->sort (); - int size = cl->write (8, buffer+6); + sset2 ((unsigned short)order, buffer + offs, order); + offs += 2; + sset2 (42, buffer + offs, order); + offs += 2; + sset4 (8, buffer + offs, order); + offs += 4; - delete cl; - - return size + 6; + TagDirectory* cl; + + if (root) { + cl = (const_cast(root))->clone (NULL); + } else { + cl = new TagDirectory (NULL, ifdAttribs, INTEL); + } + + for (rtengine::procparams::ExifPairs::const_iterator i = changeList.begin(); i != changeList.end(); i++) { + cl->applyChange (i->first, i->second); + } + + getDefaultTIFFTags (cl); + + defTags[0]->setInt (W, 0, LONG); + defTags[1]->setInt (H, 0, LONG); + defTags[8]->setInt (8, 0, SHORT); + + for (int i = defTags.size() - 1; i >= 0; i--) { + cl->replaceTag (defTags[i]->clone (cl)); + } + + cl->sort (); + int size = cl->write (8, buffer + 6); + + delete cl; + + return size + 6; } -int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char* buffer) { +int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char* buffer) +{ // write tiff header int offs = 0; ByteOrder order = HOSTORDER; - if (root) + + if (root) { order = root->getOrder (); - sset2 ((unsigned short)order, buffer+offs, order); offs += 2; - sset2 (42, buffer+offs, order); offs += 2; - sset4 (8, buffer+offs, order); offs += 4; + } + + sset2 ((unsigned short)order, buffer + offs, order); + offs += 2; + sset2 (42, buffer + offs, order); + offs += 2; + sset4 (8, buffer + offs, order); + offs += 4; TagDirectory* cl; - if (root) - cl = (const_cast(root))->clone (NULL); - else + + if (root) { + cl = (const_cast(root))->clone (NULL); + } else { cl = new TagDirectory (NULL, ifdAttribs, HOSTORDER); + } // add tiff strip data int rps = 8; - int strips = ceil((double)H/rps); - cl->replaceTag (new Tag (cl, lookupAttrib(ifdAttribs,"RowsPerStrip"), rps, LONG)); - Tag* stripBC = new Tag (cl, lookupAttrib(ifdAttribs,"StripByteCounts")); + int strips = ceil((double)H / rps); + cl->replaceTag (new Tag (cl, lookupAttrib(ifdAttribs, "RowsPerStrip"), rps, LONG)); + Tag* stripBC = new Tag (cl, lookupAttrib(ifdAttribs, "StripByteCounts")); stripBC->initInt (0, LONG, strips); cl->replaceTag (stripBC); - Tag* stripOffs = new Tag (cl, lookupAttrib(ifdAttribs,"StripOffsets")); + Tag* stripOffs = new Tag (cl, lookupAttrib(ifdAttribs, "StripOffsets")); stripOffs->initInt (0, LONG, strips); cl->replaceTag (stripOffs); - for (int i=0; isetInt (rps*W*3*bps/8, i*4); - int remaining = (H-rps*floor((double)H/rps))*W*3*bps/8; - if (remaining) - stripBC->setInt (remaining, (strips-1)*4); - else - stripBC->setInt (rps*W*3*bps/8, (strips-1)*4); + + for (int i = 0; i < strips - 1; i++) { + stripBC->setInt (rps * W * 3 * bps / 8, i * 4); + } + + int remaining = (H - rps * floor((double)H / rps)) * W * 3 * bps / 8; + + if (remaining) { + stripBC->setInt (remaining, (strips - 1) * 4); + } else { + stripBC->setInt (rps * W * 3 * bps / 8, (strips - 1) * 4); + } + if (profiledata) { - Tag* icc = new Tag (cl, lookupAttrib(ifdAttribs,"ICCProfile")); + Tag* icc = new Tag (cl, lookupAttrib(ifdAttribs, "ICCProfile")); icc->initUndefArray (profiledata, profilelen); cl->replaceTag (icc); } + if (iptcdata) { - Tag* iptc = new Tag (cl, lookupAttrib(ifdAttribs,"IPTCData")); + Tag* iptc = new Tag (cl, lookupAttrib(ifdAttribs, "IPTCData")); iptc->initLongArray (iptcdata, iptclen); cl->replaceTag (iptc); } - + // apply list of changes - for (rtengine::procparams::ExifPairs::const_iterator i=changeList.begin(); i!=changeList.end(); i++) + for (rtengine::procparams::ExifPairs::const_iterator i = changeList.begin(); i != changeList.end(); i++) { cl->applyChange (i->first, i->second); - - // append default properties - getDefaultTIFFTags (cl); + } + + // append default properties + getDefaultTIFFTags (cl); defTags[0]->setInt (W, 0, LONG); defTags[1]->setInt (H, 0, LONG); defTags[8]->initInt(0, SHORT, 3); - for (int i=0;i<3;i++) defTags[8]->setInt(bps, i*2, SHORT); - - for (int i=defTags.size()-1; i>=0; i--) + + for (int i = 0; i < 3; i++) { + defTags[8]->setInt(bps, i * 2, SHORT); + } + + for (int i = defTags.size() - 1; i >= 0; i--) { cl->replaceTag (defTags[i]->clone (cl)); - -// calculate strip offsets + } + +// calculate strip offsets int size = cl->calculateSize (); int byps = bps / 8; - for (int i=0; isetInt (size + 8 + i*rps*W*3*byps, i*4); + + for (int i = 0; i < strips; i++) { + stripOffs->setInt (size + 8 + i * rps * W * 3 * byps, i * 4); + } cl->sort (); int endOffs = cl->write (8, buffer); - + // cl->printAll(); delete cl; @@ -2319,70 +2956,96 @@ int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::pro //----------------------------------------------------------------------------- // global functions to read byteorder dependent data //----------------------------------------------------------------------------- -unsigned short sget2 (unsigned char *s, rtexif::ByteOrder order) { +unsigned short sget2 (unsigned char *s, rtexif::ByteOrder order) +{ - if (order == rtexif::INTEL) return s[0] | s[1] << 8; - else return s[0] << 8 | s[1]; + if (order == rtexif::INTEL) { + return s[0] | s[1] << 8; + } else { + return s[0] << 8 | s[1]; + } } -int sget4 (unsigned char *s, rtexif::ByteOrder order) { +int sget4 (unsigned char *s, rtexif::ByteOrder order) +{ - if (order == rtexif::INTEL) return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; - else return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; + if (order == rtexif::INTEL) { + return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + } else { + return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; + } } -inline unsigned short get2 (FILE* f, rtexif::ByteOrder order) { +inline unsigned short get2 (FILE* f, rtexif::ByteOrder order) +{ - unsigned char str[2] = { 0xff,0xff }; - fread (str, 1, 2, f); - return rtexif::sget2 (str, order); + unsigned char str[2] = { 0xff, 0xff }; + fread (str, 1, 2, f); + return rtexif::sget2 (str, order); } -int get4 (FILE* f, rtexif::ByteOrder order) { +int get4 (FILE* f, rtexif::ByteOrder order) +{ - unsigned char str[4] = { 0xff,0xff,0xff,0xff }; - fread (str, 1, 4, f); - return rtexif::sget4 (str, order); + unsigned char str[4] = { 0xff, 0xff, 0xff, 0xff }; + fread (str, 1, 4, f); + return rtexif::sget4 (str, order); } -void sset2 (unsigned short v, unsigned char *s, rtexif::ByteOrder order) { +void sset2 (unsigned short v, unsigned char *s, rtexif::ByteOrder order) +{ - if (order == rtexif::INTEL) { - s[0] = v & 0xff; v >>= 8; - s[1] = v; - } - else { - s[1] = v & 0xff; v >>= 8; - s[0] = v; - } + if (order == rtexif::INTEL) { + s[0] = v & 0xff; + v >>= 8; + s[1] = v; + } else { + s[1] = v & 0xff; + v >>= 8; + s[0] = v; + } } -void sset4 (int v, unsigned char *s, rtexif::ByteOrder order) { +void sset4 (int v, unsigned char *s, rtexif::ByteOrder order) +{ - if (order == rtexif::INTEL) { - s[0] = v & 0xff; v >>= 8; - s[1] = v & 0xff; v >>= 8; - s[2] = v & 0xff; v >>= 8; - s[3] = v; - } - else { - s[3] = v & 0xff; v >>= 8; - s[2] = v & 0xff; v >>= 8; - s[1] = v & 0xff; v >>= 8; - s[0] = v; - } + if (order == rtexif::INTEL) { + s[0] = v & 0xff; + v >>= 8; + s[1] = v & 0xff; + v >>= 8; + s[2] = v & 0xff; + v >>= 8; + s[3] = v; + } else { + s[3] = v & 0xff; + v >>= 8; + s[2] = v & 0xff; + v >>= 8; + s[1] = v & 0xff; + v >>= 8; + s[0] = v; + } } -float int_to_float (int i) { - union { int i; float f; } u; - u.i = i; - return u.f; +float int_to_float (int i) +{ + union { + int i; + float f; + } u; + u.i = i; + return u.f; } -short int int2_to_signed (short unsigned int i) { - union { short unsigned int i; short int s; } u; - u.i = i; - return u.s; +short int int2_to_signed (short unsigned int i) +{ + union { + short unsigned int i; + short int s; + } u; + u.i = i; + return u.s; } /* Function to parse and extract focal length and aperture information from description @@ -2392,33 +3055,47 @@ short int int2_to_signed (short unsigned int i) { * -mm f/- * NB: no space between separator '-'; no space between focal length and 'mm' */ -bool extractLensInfo(std::string &fullname,double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal) +bool extractLensInfo(std::string &fullname, double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal) { - minFocal=0.0; - maxFocal=0.0; - maxApertureAtMinFocal=0.0; - maxApertureAtMaxFocal=0.0; - char buffer[1024]; - strcpy(buffer,fullname.c_str()); - char *pF = strstr(buffer,"f/" ); - if( pF ){ - sscanf(pF+2,"%lf-%lf",&maxApertureAtMinFocal,&maxApertureAtMaxFocal); - if(maxApertureAtMinFocal >0. && maxApertureAtMaxFocal==0.) - maxApertureAtMaxFocal= maxApertureAtMinFocal; + minFocal = 0.0; + maxFocal = 0.0; + maxApertureAtMinFocal = 0.0; + maxApertureAtMaxFocal = 0.0; + char buffer[1024]; + strcpy(buffer, fullname.c_str()); + char *pF = strstr(buffer, "f/" ); - char *pMM = pF-3; - while( pMM[0]!= 'm' && pMM[1]!= 'm' && pMM>buffer) pMM--; - if( pMM[0]== 'm' && pMM[1]== 'm' ){ - char *sp=pMM; - while( *sp != ' ' && sp > buffer )sp--; - sscanf(sp+1,"%lf-%lf",&minFocal,&maxFocal); - if(maxFocal==0.) { - maxFocal = minFocal; - } - return true; - } - } - return false; + if( pF ) { + sscanf(pF + 2, "%lf-%lf", &maxApertureAtMinFocal, &maxApertureAtMaxFocal); + + if(maxApertureAtMinFocal > 0. && maxApertureAtMaxFocal == 0.) { + maxApertureAtMaxFocal = maxApertureAtMinFocal; + } + + char *pMM = pF - 3; + + while( pMM[0] != 'm' && pMM[1] != 'm' && pMM > buffer) { + pMM--; + } + + if( pMM[0] == 'm' && pMM[1] == 'm' ) { + char *sp = pMM; + + while( *sp != ' ' && sp > buffer ) { + sp--; + } + + sscanf(sp + 1, "%lf-%lf", &minFocal, &maxFocal); + + if(maxFocal == 0.) { + maxFocal = minFocal; + } + + return true; + } + } + + return false; } } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index f5f238640..f476445d1 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -7,7 +7,7 @@ * 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 @@ -33,26 +33,27 @@ class CacheImageData; -namespace rtexif { +namespace rtexif +{ -enum TagType {INVALID=0, BYTE=1, ASCII=2, SHORT=3, LONG=4, RATIONAL=5, SBYTE=6, UNDEFINED=7, SSHORT=8, SLONG=9, SRATIONAL=10, FLOAT=11, DOUBLE=12, OLYUNDEF=13, AUTO=98, SUBDIR=99}; +enum TagType {INVALID = 0, BYTE = 1, ASCII = 2, SHORT = 3, LONG = 4, RATIONAL = 5, SBYTE = 6, UNDEFINED = 7, SSHORT = 8, SLONG = 9, SRATIONAL = 10, FLOAT = 11, DOUBLE = 12, OLYUNDEF = 13, AUTO = 98, SUBDIR = 99}; enum ActionCode { AC_DONTWRITE, // don't write it to the output AC_WRITE, // write it to the output AC_SYSTEM, // changed by RT (not editable/deletable) - don't write, don't show AC_NEW, // new addition - write, don't show - AC_INVALID=100, // invalid state + AC_INVALID = 100, // invalid state }; -enum ByteOrder {INTEL=0x4949, MOTOROLA=0x4D4D}; +enum ByteOrder {INTEL = 0x4949, MOTOROLA = 0x4D4D}; #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ const enum ByteOrder HOSTORDER = INTEL; #else const enum ByteOrder HOSTORDER = MOTOROLA; #endif -enum MNKind {NOMK, IFD, HEADERIFD, NIKON3, OLYMPUS2, FUJI,TABLESUBDIR}; +enum MNKind {NOMK, IFD, HEADERIFD, NIKON3, OLYMPUS2, FUJI, TABLESUBDIR}; -bool extractLensInfo(std::string &fullname,double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal); +bool extractLensInfo(std::string &fullname, double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal); unsigned short sget2 (unsigned char *s, ByteOrder order); int sget4 (unsigned char *s, ByteOrder order); @@ -65,9 +66,9 @@ short int int2_to_signed (short unsigned int i); struct TIFFHeader { - unsigned short byteOrder; - unsigned short fixed; - unsigned int ifdOffset; + unsigned short byteOrder; + unsigned short fixed; + unsigned int ifdOffset; }; class Tag; @@ -93,29 +94,42 @@ struct TagAttrib { const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field); /// A directory of tags -class TagDirectory { +class TagDirectory +{ - protected: +protected: std::vector tags; // tags in the directory const TagAttrib* attribs; // descriptor table to decode the tags ByteOrder order; // byte order TagDirectory* parent; // parent directory (NULL if root) static Glib::ustring getDumpKey (int tagID, const Glib::ustring tagName); - public: +public: TagDirectory (); - TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored=true); + TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored = true); TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border); virtual ~TagDirectory (); - - inline ByteOrder getOrder () const { return order; } - TagDirectory* getParent () { return parent; } + + inline ByteOrder getOrder () const + { + return order; + } + TagDirectory* getParent () + { + return parent; + } TagDirectory* getRoot (); - inline int getCount () const { return tags.size (); } + inline int getCount () const + { + return tags.size (); + } const TagAttrib* getAttrib (int id); const TagAttrib* getAttrib (const char* name); // Find a Tag by scanning the whole tag tree and stopping at the first occurrence const TagAttrib* getAttribP (const char* name); // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") - const TagAttrib* getAttribTable() { return attribs; } + const TagAttrib* getAttribTable() + { + return attribs; + } Tag* getTag (const char* name) const; // Find a Tag by scanning the whole tag tree and stopping at the first occurrence Tag* getTagP (const char* name) const; // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") Tag* getTag (int ID) const; @@ -126,41 +140,49 @@ class TagDirectory { virtual void addTag (Tag* a); virtual void addTagFront (Tag* a); virtual void replaceTag (Tag* a); - inline Tag* getTagByIndex (int ix) { return tags[ix]; } - inline void setOrder (ByteOrder bo) { order = bo; } + inline Tag* getTagByIndex (int ix) + { + return tags[ix]; + } + inline void setOrder (ByteOrder bo) + { + order = bo; + } virtual int calculateSize (); virtual int write (int start, unsigned char* buffer); virtual TagDirectory* clone (TagDirectory* parent); virtual void applyChange (std::string field, std::string value); - virtual void printAll (unsigned int level=0) const; // reentrant debug function, keep level=0 on first call ! + 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, rtengine::SafeKeyFile *keyFile = NULL, Glib::ustring tagDirName = "") const; virtual void sort (); }; // a table of tags: id are offset from beginning and not identifiers -class TagDirectoryTable: public TagDirectory { - protected: - unsigned char *values; // Tags values are saved internally here - long zeroOffset; // Offset 0 (index 0) could be at an offset from values - long valuesSize; // Size of allocated memory - TagType defaultType; // Default type of all tags in this directory - public: - TagDirectoryTable(); - TagDirectoryTable (TagDirectory* p, unsigned char *v,int memsize,int offs, TagType type, const TagAttrib* ta, ByteOrder border); - TagDirectoryTable (TagDirectory* p, FILE* f, int memsize,int offset, TagType type, const TagAttrib* ta, ByteOrder border); - virtual ~TagDirectoryTable(); - virtual int calculateSize (); - virtual int write (int start, unsigned char* buffer); - virtual TagDirectory* clone (TagDirectory* parent); +class TagDirectoryTable: public TagDirectory +{ +protected: + unsigned char *values; // Tags values are saved internally here + long zeroOffset; // Offset 0 (index 0) could be at an offset from values + long valuesSize; // Size of allocated memory + TagType defaultType; // Default type of all tags in this directory +public: + TagDirectoryTable(); + TagDirectoryTable (TagDirectory* p, unsigned char *v, int memsize, int offs, TagType type, const TagAttrib* ta, ByteOrder border); + TagDirectoryTable (TagDirectory* p, FILE* f, int memsize, int offset, TagType type, const TagAttrib* ta, ByteOrder border); + virtual ~TagDirectoryTable(); + virtual int calculateSize (); + virtual int write (int start, unsigned char* buffer); + virtual TagDirectory* clone (TagDirectory* parent); }; // a class representing a single tag -class Tag { +class Tag +{ - protected: +protected: unsigned short tag; TagType type; unsigned int count; @@ -175,217 +197,329 @@ class Tag { MNKind makerNoteKind; bool parseMakerNote(FILE* f, int base, ByteOrder bom ); - public: +public: Tag (TagDirectory* parent, FILE* f, int base); // parse next tag from the file Tag (TagDirectory* parent, const TagAttrib* attr); Tag (TagDirectory* parent, const TagAttrib* attr, unsigned char *data, TagType t); Tag (TagDirectory* parent, const TagAttrib* attr, int data, TagType t); // create a new tag from array (used Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used - ~Tag (); - void initType (unsigned char *data, TagType type); - void initInt (int data, TagType t, int count=1); - void initString (const char* text); - void initSubDir (); - void initSubDir (TagDirectory* dir); - void initMakerNote (MNKind mnk, const TagAttrib* ta); - void initUndefArray (const char* data, int len); - void initLongArray (const char* data, int len); - void initRational (int num, int den); + ~Tag (); + void initType (unsigned char *data, TagType type); + void initInt (int data, TagType t, int count = 1); + void initString (const char* text); + void initSubDir (); + void initSubDir (TagDirectory* dir); + void initMakerNote (MNKind mnk, const TagAttrib* ta); + void initUndefArray (const char* data, int len); + void initLongArray (const char* data, int len); + void initRational (int num, int den); // get basic tag properties - int getID () const { return tag; } - int getCount () const { return count; } - TagType getType () const { return (attrib && attrib->type > INVALID && attrib->type < AUTO) ? attrib->type : type; } - unsigned char* getValue () const { return value; } - signed char* getSignedValue () const { return reinterpret_cast(value); } - const TagAttrib* getAttrib () const { return attrib; } - inline ByteOrder getOrder () const { return parent ? parent->getOrder() : HOSTORDER; } - inline TagDirectory* getParent () const { return parent; } - int getValueSize () const { return valuesize; } - bool getOwnMemory () const { return allocOwnMemory; } + int getID () const + { + return tag; + } + int getCount () const + { + return count; + } + TagType getType () const + { + return (attrib && attrib->type > INVALID && attrib->type < AUTO) ? attrib->type : type; + } + unsigned char* getValue () const + { + return value; + } + signed char* getSignedValue () const + { + return reinterpret_cast(value); + } + const TagAttrib* getAttrib () const + { + return attrib; + } + inline ByteOrder getOrder () const + { + return parent ? parent->getOrder() : HOSTORDER; + } + inline TagDirectory* getParent () const + { + return parent; + } + int getValueSize () const + { + return valuesize; + } + bool getOwnMemory () const + { + return allocOwnMemory; + } // read/write value - int toInt (int ofs=0, TagType astype=INVALID); + int toInt (int ofs = 0, TagType astype = INVALID); void fromInt (int v); - double toDouble (int ofs=0); - double *toDoubleArray (int ofs=0); - void toRational (int& num, int& denom, int ofs=0); - void toString (char* buffer, int ofs=0); - void fromString (const char* v, int size=-1); - void setInt (int v, int ofs=0, TagType astype=LONG); + double toDouble (int ofs = 0); + double *toDoubleArray (int ofs = 0); + void toRational (int& num, int& denom, int ofs = 0); + void toString (char* buffer, int ofs = 0); + void fromString (const char* v, int size = -1); + void setInt (int v, int ofs = 0, TagType astype = LONG); // additional getter/setter for more comfortable use std::string valueToString (); - std::string nameToString (int i=0); + std::string nameToString (int i = 0); void valueFromString (const std::string& value); - + // functions for writing int calculateSize (); int write (int offs, int dataOffs, unsigned char* buffer); Tag* clone (TagDirectory* parent); - // to control if the tag shall be written - bool getKeep () { return keep; } - void setKeep (bool k) { keep = k; } - + // to control if the tag shall be written + bool getKeep () + { + return keep; + } + void setKeep (bool k) + { + keep = k; + } + // get subdirectory (there can be several, the last is NULL) - bool isDirectory () { return directory!=NULL; } - TagDirectory* getDirectory (int i=0) { return (directory) ? directory[i] : 0; } + bool isDirectory () + { + return directory != NULL; + } + TagDirectory* getDirectory (int i = 0) + { + return (directory) ? directory[i] : 0; + } - MNKind getMakerNoteFormat () { return makerNoteKind; } - }; + MNKind getMakerNoteFormat () + { + return makerNoteKind; + } +}; -class ExifManager { +class ExifManager +{ static std::vector defTags; - + static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name); - public: - static TagDirectory* parse (FILE*f, int base, bool skipIgnored=true); +public: + static TagDirectory* parse (FILE*f, int base, bool skipIgnored = true); static TagDirectory* parseJPEG (FILE*f); - static TagDirectory* parseTIFF (FILE*f, bool skipIgnored=true); + static TagDirectory* parseTIFF (FILE*f, bool skipIgnored = true); static TagDirectory* parseCIFF (FILE* f, int base, int length); static void parseCIFF (FILE* f, int base, int length, TagDirectory* root); - + static const std::vector& getDefaultTIFFTags (TagDirectory* forthis); static int createJPEGMarker (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, unsigned char* buffer); static int createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char* buffer); }; -class Interpreter { - public: - Interpreter () {} - virtual ~Interpreter() {}; - virtual std::string toString (Tag* t) { - char buffer[1024]; - t->toString (buffer); - std::string s(buffer); - std::string::size_type p1 = s.find_first_not_of(' '); - if( p1 == std::string::npos ) - return s; - else - return s.substr(p1, s.find_last_not_of(' ')-p1+1); +class Interpreter +{ +public: + Interpreter () {} + virtual ~Interpreter() {}; + virtual std::string toString (Tag* t) + { + char buffer[1024]; + t->toString (buffer); + std::string s(buffer); + std::string::size_type p1 = s.find_first_not_of(' '); + + if( p1 == std::string::npos ) { + return s; + } else { + return s.substr(p1, s.find_last_not_of(' ') - p1 + 1); } - virtual void fromString (Tag* t, const std::string& value) { - if (t->getType()==SHORT || t->getType()==LONG) - t->fromInt (atoi(value.c_str())); - else - t->fromString (value.c_str()); + } + virtual void fromString (Tag* t, const std::string& value) + { + if (t->getType() == SHORT || t->getType() == LONG) { + t->fromInt (atoi(value.c_str())); + } else { + t->fromString (value.c_str()); } - // Get the value as a double - virtual double toDouble(Tag* t, int ofs=0) { - double ud, dd; - switch (t->getType()) { - case SBYTE: return double(int(t->getSignedValue()[ofs])); - case BYTE: return (double)((int)t->getValue()[ofs]); - case ASCII: return 0.0; - case SSHORT:return (double)int2_to_signed(sget2 (t->getValue()+ofs, t->getOrder())); - case SHORT: return (double)((int)sget2 (t->getValue()+ofs, t->getOrder())); - case SLONG: - case LONG: return (double)((int)sget4 (t->getValue()+ofs, t->getOrder())); - case SRATIONAL: - case RATIONAL: ud = (int)sget4 (t->getValue()+ofs, t->getOrder()); dd = (int)sget4 (t->getValue()+ofs+4, t->getOrder()); return dd==0. ? 0. : (double)ud / (double)dd; - case FLOAT: return double(sget4 (t->getValue()+ofs, t->getOrder())); - case UNDEFINED: return 0.; - default: return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) - } + } + // Get the value as a double + virtual double toDouble(Tag* t, int ofs = 0) + { + double ud, dd; + + switch (t->getType()) { + case SBYTE: + return double(int(t->getSignedValue()[ofs])); + + case BYTE: + return (double)((int)t->getValue()[ofs]); + + case ASCII: + return 0.0; + + case SSHORT: + return (double)int2_to_signed(sget2 (t->getValue() + ofs, t->getOrder())); + + case SHORT: + return (double)((int)sget2 (t->getValue() + ofs, t->getOrder())); + + case SLONG: + case LONG: + return (double)((int)sget4 (t->getValue() + ofs, t->getOrder())); + + case SRATIONAL: + case RATIONAL: + ud = (int)sget4 (t->getValue() + ofs, t->getOrder()); + dd = (int)sget4 (t->getValue() + ofs + 4, t->getOrder()); + return dd == 0. ? 0. : (double)ud / (double)dd; + + case FLOAT: + return double(sget4 (t->getValue() + ofs, t->getOrder())); + + case UNDEFINED: + return 0.; + + default: + return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) } - // Get the value as an int - virtual int toInt (Tag* t, int ofs=0, TagType astype=INVALID) { - int a; - if (astype == INVALID || astype==AUTO) - astype = t->getType(); - switch (astype) { - case SBYTE: return int(t->getSignedValue()[ofs]); - case BYTE: return t->getValue()[ofs]; - case ASCII: return 0; - case SSHORT:return (int)int2_to_signed(sget2 (t->getValue()+ofs, t->getOrder())); - case SHORT: return (int)sget2 (t->getValue()+ofs, t->getOrder()); - case SLONG: - case LONG: return (int)sget4 (t->getValue()+ofs, t->getOrder()); - case SRATIONAL: - case RATIONAL: a = (int)sget4 (t->getValue()+ofs+4, t->getOrder()); return a==0 ? 0 : (int)sget4 (t->getValue()+ofs, t->getOrder()) / a; - case FLOAT: return (int)toDouble(t, ofs); - case UNDEFINED: return 0; - default: return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) - } - return 0; + } + // Get the value as an int + virtual int toInt (Tag* t, int ofs = 0, TagType astype = INVALID) + { + int a; + + if (astype == INVALID || astype == AUTO) { + astype = t->getType(); } + + switch (astype) { + case SBYTE: + return int(t->getSignedValue()[ofs]); + + case BYTE: + return t->getValue()[ofs]; + + case ASCII: + return 0; + + case SSHORT: + return (int)int2_to_signed(sget2 (t->getValue() + ofs, t->getOrder())); + + case SHORT: + return (int)sget2 (t->getValue() + ofs, t->getOrder()); + + case SLONG: + case LONG: + return (int)sget4 (t->getValue() + ofs, t->getOrder()); + + case SRATIONAL: + case RATIONAL: + a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder()); + return a == 0 ? 0 : (int)sget4 (t->getValue() + ofs, t->getOrder()) / a; + + case FLOAT: + return (int)toDouble(t, ofs); + + case UNDEFINED: + return 0; + + default: + return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR) + } + + return 0; + } }; extern Interpreter stdInterpreter; -class ChoiceInterpreter : public Interpreter { - protected: - std::map choices; - public: - ChoiceInterpreter () {}; - virtual std::string toString (Tag* t) { - std::map::iterator r = choices.find (t->toInt()); - if (r!=choices.end()) - return r->second; - else { - char buffer[1024]; - t->toString (buffer); - return std::string (buffer); - } +class ChoiceInterpreter : public Interpreter +{ +protected: + std::map choices; +public: + ChoiceInterpreter () {}; + virtual std::string toString (Tag* t) + { + std::map::iterator r = choices.find (t->toInt()); + + if (r != choices.end()) { + return r->second; + } else { + char buffer[1024]; + t->toString (buffer); + return std::string (buffer); } + } }; template< class T > -class IntLensInterpreter : public Interpreter { +class IntLensInterpreter : public Interpreter +{ protected: typedef std::multimap< T, std::string> container_t; typedef typename std::multimap< T, std::string>::iterator it_t; typedef std::pair< T, std::string> p_t; container_t choices; - virtual std::string guess(const T lensID, double focalLength, double maxApertureAtFocal, double *lensInfoArray) { + virtual std::string guess(const T lensID, double focalLength, double maxApertureAtFocal, double *lensInfoArray) + { it_t r; size_t nFound = choices.count( lensID ); switch( nFound ) { - case 0: // lens Unknown - { + case 0: { // lens Unknown std::ostringstream s; s << lensID; return s.str(); } + case 1: // lens found r = choices.find ( lensID ); return r->second; + default: // More than one hit: we must guess - break; + break; } std::string bestMatch("Unknown"); - double a1,a2,f1,f2; + double a1, a2, f1, f2; /* FIRST TRY * * Get the lens info (min/man focal, min/max aperture) and compare them to the possible choice */ if (lensInfoArray) { - for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); r++ ){ - if( !extractLensInfo( r->second ,f1,f2,a1,a2) ) + for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); r++ ) { + if( !extractLensInfo( r->second , f1, f2, a1, a2) ) { continue; - if (f1==lensInfoArray[0] && f2==lensInfoArray[1] && a1==lensInfoArray[2] && a2==lensInfoArray[3]) - // can't match better! we take this entry as being the one - return r->second; - } - // No lens found, we update the "unknown" string with the lens info values - if (lensInfoArray[0]==lensInfoArray[1]) - bestMatch += Glib::ustring::compose(" (%1mm", int(lensInfoArray[0])); - else - bestMatch += Glib::ustring::compose(" (%1-%2mm", int(lensInfoArray[0]), int(lensInfoArray[1])); + } - if (lensInfoArray[2]==lensInfoArray[3]) + if (f1 == lensInfoArray[0] && f2 == lensInfoArray[1] && a1 == lensInfoArray[2] && a2 == lensInfoArray[3]) + // can't match better! we take this entry as being the one + { + return r->second; + } + } + + // No lens found, we update the "unknown" string with the lens info values + if (lensInfoArray[0] == lensInfoArray[1]) { + bestMatch += Glib::ustring::compose(" (%1mm", int(lensInfoArray[0])); + } else { + bestMatch += Glib::ustring::compose(" (%1-%2mm", int(lensInfoArray[0]), int(lensInfoArray[1])); + } + + if (lensInfoArray[2] == lensInfoArray[3]) { bestMatch += Glib::ustring::compose(" f/%1)", Glib::ustring::format(std::fixed, std::setprecision(1), lensInfoArray[2])); - else + } else bestMatch += Glib::ustring::compose(" f/%1-%2)", - Glib::ustring::format(std::fixed, std::setprecision(1), lensInfoArray[2]), - Glib::ustring::format(std::fixed, std::setprecision(1), lensInfoArray[3])); + Glib::ustring::format(std::fixed, std::setprecision(1), lensInfoArray[2]), + Glib::ustring::format(std::fixed, std::setprecision(1), lensInfoArray[3])); } /* SECOND TRY @@ -397,48 +531,63 @@ protected: */ std::ostringstream candidates; double deltaMin = 1000.; - for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); r++ ){ - double lensAperture,dif; - if( !extractLensInfo( r->second ,f1,f2,a1,a2) ) - continue; - if( f1 == 0. || a1 == 0.) - continue; + for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); r++ ) { + double lensAperture, dif; - if( focalLength < f1 - .5 || focalLength > f2 + 0.5 ) + if( !extractLensInfo( r->second , f1, f2, a1, a2) ) { continue; - if( maxApertureAtFocal > 0.1){ - if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 +0.15) + } + + if( f1 == 0. || a1 == 0.) { + continue; + } + + if( focalLength < f1 - .5 || focalLength > f2 + 0.5 ) { + continue; + } + + if( maxApertureAtFocal > 0.1) { + if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 + 0.15) { continue; + } - if( a1 == a2 || f1 == f2) - lensAperture = a1; - else - lensAperture = exp( log(a1)+(log(a2)-log(a1))/(log(f2)-log(f1))*(log(focalLength)-log(f1)) ); + if( a1 == a2 || f1 == f2) { + lensAperture = a1; + } else { + lensAperture = exp( log(a1) + (log(a2) - log(a1)) / (log(f2) - log(f1)) * (log(focalLength) - log(f1)) ); + } dif = abs(lensAperture - maxApertureAtFocal); - }else + } else { dif = 0; - if( dif < deltaMin ){ + } + + if( dif < deltaMin ) { deltaMin = dif; bestMatch = r->second; } - if( dif < 0.15){ - if( candidates.tellp() ) + + if( dif < 0.15) { + if( candidates.tellp() ) { candidates << "\n or " << r->second; - else + } else { candidates << r->second; + } } } - if( !candidates.tellp() ) + + if( !candidates.tellp() ) { return bestMatch; - else + } else { return candidates.str(); + } } }; -inline static int getTypeSize( TagType type ) { - return ("11124811248484"[type<14?type:0]-'0'); +inline static int getTypeSize( TagType type ) +{ + return ("11124811248484"[type < 14 ? type : 0] - '0'); } extern const TagAttrib exifAttribs[]; diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc index 6e21f502e..4affbf946 100644 --- a/rtexif/sonyminoltaattribs.cc +++ b/rtexif/sonyminoltaattribs.cc @@ -6,7 +6,7 @@ * 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 @@ -22,1027 +22,1134 @@ #include "rtexif.h" -namespace rtexif { +namespace rtexif +{ -class SANoYesInterpreter : public ChoiceInterpreter { - public: - SANoYesInterpreter () { - choices[1] = "No"; - choices[16] = "Yes"; - } +class SANoYesInterpreter : public ChoiceInterpreter +{ +public: + SANoYesInterpreter () + { + choices[1] = "No"; + choices[16] = "Yes"; + } }; SANoYesInterpreter saNoYesInterpreter; -class SAOnOffInterpreter : public ChoiceInterpreter { - public: - SAOnOffInterpreter () { - choices[0] = "Off"; - choices[1] = "On"; - choices[5] = "On"; - } +class SAOnOffInterpreter : public ChoiceInterpreter +{ +public: + SAOnOffInterpreter () + { + choices[0] = "Off"; + choices[1] = "On"; + choices[5] = "On"; + } }; SAOnOffInterpreter saOnOffInterpreter; -class SAOnOffInterpreter2 : public ChoiceInterpreter { - public: - SAOnOffInterpreter2 () { - choices[1] = "Off"; - choices[16] = "On"; - } +class SAOnOffInterpreter2 : public ChoiceInterpreter +{ +public: + SAOnOffInterpreter2 () + { + choices[1] = "Off"; + choices[16] = "On"; + } }; SAOnOffInterpreter2 saOnOffInterpreter2; -class SAOnOffInterpreter3 : public ChoiceInterpreter { - public: - SAOnOffInterpreter3 () { - choices[1] = "Off"; - choices[16] = "On (Auto)"; - choices[17] = "On (Manual)"; - } +class SAOnOffInterpreter3 : public ChoiceInterpreter +{ +public: + SAOnOffInterpreter3 () + { + choices[1] = "Off"; + choices[16] = "On (Auto)"; + choices[17] = "On (Manual)"; + } }; SAOnOffInterpreter3 saOnOffInterpreter3; -class SAOnOffInterpreter4 : public ChoiceInterpreter { - public: - SAOnOffInterpreter4 () { - choices[0] = "n/a"; - choices[1] = "Off"; - choices[16] = "On"; - choices[255] = "None"; - } +class SAOnOffInterpreter4 : public ChoiceInterpreter +{ +public: + SAOnOffInterpreter4 () + { + choices[0] = "n/a"; + choices[1] = "Off"; + choices[16] = "On"; + choices[255] = "None"; + } }; SAOnOffInterpreter4 saOnOffInterpreter4; -class SAOnOffInterpreter5 : public ChoiceInterpreter { - public: - SAOnOffInterpreter5 () { - choices[1] = "On"; - choices[2] = "Off"; - } +class SAOnOffInterpreter5 : public ChoiceInterpreter +{ +public: + SAOnOffInterpreter5 () + { + choices[1] = "On"; + choices[2] = "Off"; + } }; SAOnOffInterpreter5 saOnOffInterpreter5; -class SAHighISONoiseReduction : public ChoiceInterpreter { - public: - SAHighISONoiseReduction () { - choices[0] = "Off"; - choices[1] = "Low"; - choices[2] = "Normal"; - choices[3] = "High"; - choices[256] = "Auto"; - choices[65535] = "n/a"; - } +class SAHighISONoiseReduction : public ChoiceInterpreter +{ +public: + SAHighISONoiseReduction () + { + choices[0] = "Off"; + choices[1] = "Low"; + choices[2] = "Normal"; + choices[3] = "High"; + choices[256] = "Auto"; + choices[65535] = "n/a"; + } }; SAHighISONoiseReduction saHighISONoiseReduction; -class SAHighISONoiseReduction2 : public ChoiceInterpreter { - public: - SAHighISONoiseReduction2 () { - choices[0] = "Normal"; - choices[1] = "High"; - choices[2] = "Low"; - choices[3] = "Off"; - choices[65535] = "n/a"; - } +class SAHighISONoiseReduction2 : public ChoiceInterpreter +{ +public: + SAHighISONoiseReduction2 () + { + choices[0] = "Normal"; + choices[1] = "High"; + choices[2] = "Low"; + choices[3] = "Off"; + choices[65535] = "n/a"; + } }; SAHighISONoiseReduction2 saHighISONoiseReduction2; -class SAHighISONoiseReduction3 : public ChoiceInterpreter { - public: - SAHighISONoiseReduction3 () { - choices[0] = "Normal"; - choices[1] = "Low"; - choices[2] = "High"; - choices[3] = "Off"; - } +class SAHighISONoiseReduction3 : public ChoiceInterpreter +{ +public: + SAHighISONoiseReduction3 () + { + choices[0] = "Normal"; + choices[1] = "Low"; + choices[2] = "High"; + choices[3] = "Off"; + } }; SAHighISONoiseReduction3 saHighISONoiseReduction3; -class SAHighISONoiseReduction4 : public ChoiceInterpreter { - public: - SAHighISONoiseReduction4 () { - choices[0] = "Off"; - choices[1] = "Low"; - choices[2] = "Normal"; - choices[3] = "High"; - } +class SAHighISONoiseReduction4 : public ChoiceInterpreter +{ +public: + SAHighISONoiseReduction4 () + { + choices[0] = "Off"; + choices[1] = "Low"; + choices[2] = "Normal"; + choices[3] = "High"; + } }; SAHighISONoiseReduction4 saHighISONoiseReduction4; -class SAHighISONoiseReduction5 : public ChoiceInterpreter { - public: - SAHighISONoiseReduction5 () { - choices[16] = "Low"; - choices[19] = "Auto"; - } +class SAHighISONoiseReduction5 : public ChoiceInterpreter +{ +public: + SAHighISONoiseReduction5 () + { + choices[16] = "Low"; + choices[19] = "Auto"; + } }; SAHighISONoiseReduction5 saHighISONoiseReduction5; -class SASmileShutterMode : public ChoiceInterpreter { - public: - SASmileShutterMode () { - choices[17] = "Slight smile"; - choices[18] = "Normal smile"; - choices[19] = "Big smile"; - } +class SASmileShutterMode : public ChoiceInterpreter +{ +public: + SASmileShutterMode () + { + choices[17] = "Slight smile"; + choices[18] = "Normal smile"; + choices[19] = "Big smile"; + } }; SASmileShutterMode saSmileShutterMode; -class SAHDRLevel : public ChoiceInterpreter { - public: - SAHDRLevel () { - choices[33] = "1 EV"; - choices[34] = "1.5 EV"; - choices[35] = "2 EV"; - choices[36] = "2.5 EV"; - choices[37] = "3 EV"; - choices[38] = "3.5 EV"; - choices[39] = "4 EV"; - choices[40] = "5 EV"; - choices[41] = "6 EV"; - } +class SAHDRLevel : public ChoiceInterpreter +{ +public: + SAHDRLevel () + { + choices[33] = "1 EV"; + choices[34] = "1.5 EV"; + choices[35] = "2 EV"; + choices[36] = "2.5 EV"; + choices[37] = "3 EV"; + choices[38] = "3.5 EV"; + choices[39] = "4 EV"; + choices[40] = "5 EV"; + choices[41] = "6 EV"; + } }; SAHDRLevel saHDRLevel; -class SAViewingMode : public ChoiceInterpreter { - public: - SAViewingMode () { - choices[0] = "n/a"; - choices[16] = "ViewFinder"; - choices[33] = "Focus Check Live View"; - choices[34] = "Quick AF Live View"; - } +class SAViewingMode : public ChoiceInterpreter +{ +public: + SAViewingMode () + { + choices[0] = "n/a"; + choices[16] = "ViewFinder"; + choices[33] = "Focus Check Live View"; + choices[34] = "Quick AF Live View"; + } }; SAViewingMode saViewingMode; -class SAFlashAction : public ChoiceInterpreter { - public: - SAFlashAction () { - choices[1] = "Did not fire"; - choices[2] = "Fired"; - } +class SAFlashAction : public ChoiceInterpreter +{ +public: + SAFlashAction () + { + choices[1] = "Did not fire"; + choices[2] = "Fired"; + } }; SAFlashAction saFlashAction; -class SALiveViewFocusMode : public ChoiceInterpreter { - public: - SALiveViewFocusMode () { - choices[0] = "n/a"; - choices[1] = "AF"; - choices[16] = "Manual"; - } +class SALiveViewFocusMode : public ChoiceInterpreter +{ +public: + SALiveViewFocusMode () + { + choices[0] = "n/a"; + choices[1] = "AF"; + choices[16] = "Manual"; + } }; SALiveViewFocusMode saLiveViewFocusMode; -class SALensMount : public ChoiceInterpreter { - public: - SALensMount () { - choices[1] = "Unknown"; - choices[16] = "A-Mount"; - choices[17] = "E-Mount"; - } +class SALensMount : public ChoiceInterpreter +{ +public: + SALensMount () + { + choices[1] = "Unknown"; + choices[16] = "A-Mount"; + choices[17] = "E-Mount"; + } }; SALensMount saLensMount; -class SASweepPanoramaSize : public ChoiceInterpreter { - public: - SASweepPanoramaSize () { - choices[1] = "Standard"; - choices[2] = "Wide"; - } +class SASweepPanoramaSize : public ChoiceInterpreter +{ +public: + SASweepPanoramaSize () + { + choices[1] = "Standard"; + choices[2] = "Wide"; + } }; SASweepPanoramaSize saSweepPanoramaSize; -class SASweepPanoramaDirection : public ChoiceInterpreter { - public: - SASweepPanoramaDirection () { - choices[1] = "Right"; - choices[2] = "Left"; - choices[3] = "Up"; - choices[4] = "Down"; - } +class SASweepPanoramaDirection : public ChoiceInterpreter +{ +public: + SASweepPanoramaDirection () + { + choices[1] = "Right"; + choices[2] = "Left"; + choices[3] = "Up"; + choices[4] = "Down"; + } }; SASweepPanoramaDirection saSweepPanoramaDirection; -class SALiveViewAFSetting : public ChoiceInterpreter { - public: - SALiveViewAFSetting () { - choices[0] = "n/a"; - choices[1] = "Phase-detect AF"; - choices[2] = "Contrast AF"; - } +class SALiveViewAFSetting : public ChoiceInterpreter +{ +public: + SALiveViewAFSetting () + { + choices[0] = "n/a"; + choices[1] = "Phase-detect AF"; + choices[2] = "Contrast AF"; + } }; SALiveViewAFSetting saLiveViewAFSetting; -class SAPanoramaSize3D : public ChoiceInterpreter { - public: - SAPanoramaSize3D () { - choices[0] = "n/a"; - choices[1] = "Standard"; - choices[2] = "Wide"; - choices[3] = "16:9"; - } +class SAPanoramaSize3D : public ChoiceInterpreter +{ +public: + SAPanoramaSize3D () + { + choices[0] = "n/a"; + choices[1] = "Standard"; + choices[2] = "Wide"; + choices[3] = "16:9"; + } }; SAPanoramaSize3D saPanoramaSize3D; -class SALiveViewMetering : public ChoiceInterpreter { - public: - SALiveViewMetering () { - choices[0] = "n/a"; - choices[16] = "40 segment"; - choices[32] = "1200-zone Evaluative"; - } +class SALiveViewMetering : public ChoiceInterpreter +{ +public: + SALiveViewMetering () + { + choices[0] = "n/a"; + choices[16] = "40 segment"; + choices[32] = "1200-zone Evaluative"; + } }; SALiveViewMetering saLiveViewMetering; -class SAWhiteBalanceInterpreter: public ChoiceInterpreter { - public: - SAWhiteBalanceInterpreter(){ - choices[ 0x0] = "Auto"; - choices[ 0x1] = "Color Temperature/Color Filter"; - choices[0x10] = "Daylight"; - choices[0x20] = "Cloudy"; - choices[0x30] = "Shade"; - choices[0x40] = "Tungsten"; - choices[0x50] = "Flash"; - choices[0x60] = "Fluorescent"; - choices[0x70] = "Custom"; - } +class SAWhiteBalanceInterpreter: public ChoiceInterpreter +{ +public: + SAWhiteBalanceInterpreter() + { + choices[ 0x0] = "Auto"; + choices[ 0x1] = "Color Temperature/Color Filter"; + choices[0x10] = "Daylight"; + choices[0x20] = "Cloudy"; + choices[0x30] = "Shade"; + choices[0x40] = "Tungsten"; + choices[0x50] = "Flash"; + choices[0x60] = "Fluorescent"; + choices[0x70] = "Custom"; + } }; SAWhiteBalanceInterpreter saWhiteBalanceInterpreter; -class SAWhiteBalanceSettingInterpreter: public ChoiceInterpreter { - public: - SAWhiteBalanceSettingInterpreter(){ - choices[0x10] = "Auto (-3)"; - choices[0x11] = "Auto (-2)"; - choices[0x12] = "Auto (-1)"; - choices[0x13] = "Auto (0)"; - choices[0x14] = "Auto (+1)"; - choices[0x15] = "Auto (+2)"; - choices[0x16] = "Auto (+3)"; - choices[0x20] = "Daylight (-3)"; - choices[0x21] = "Daylight (-2)"; - choices[0x22] = "Daylight (-1)"; - choices[0x23] = "Daylight (0)"; - choices[0x24] = "Daylight (+1)"; - choices[0x25] = "Daylight (+2)"; - choices[0x26] = "Daylight (+3)"; - choices[0x30] = "Shade (-3)"; - choices[0x31] = "Shade (-2)"; - choices[0x32] = "Shade (-1)"; - choices[0x33] = "Shade (0)"; - choices[0x34] = "Shade (+1)"; - choices[0x35] = "Shade (+2)"; - choices[0x36] = "Shade (+3)"; - choices[0x40] = "Cloudy (-3)"; - choices[0x41] = "Cloudy (-2)"; - choices[0x42] = "Cloudy (-1)"; - choices[0x43] = "Cloudy (0)"; - choices[0x44] = "Cloudy (+1)"; - choices[0x45] = "Cloudy (+2)"; - choices[0x46] = "Cloudy (+3)"; - choices[0x50] = "Tungsten (-3)"; - choices[0x51] = "Tungsten (-2)"; - choices[0x52] = "Tungsten (-1)"; - choices[0x53] = "Tungsten (0)"; - choices[0x54] = "Tungsten (+1)"; - choices[0x55] = "Tungsten (+2)"; - choices[0x56] = "Tungsten (+3)"; - choices[0x60] = "Fluorescent (-3)"; - choices[0x61] = "Fluorescent (-2)"; - choices[0x62] = "Fluorescent (-1)"; - choices[0x63] = "Fluorescent (0)"; - choices[0x64] = "Fluorescent (+1)"; - choices[0x65] = "Fluorescent (+2)"; - choices[0x66] = "Fluorescent (+3)"; - choices[0x70] = "Flash (-3)"; - choices[0x71] = "Flash (-2)"; - choices[0x72] = "Flash (-1)"; - choices[0x73] = "Flash (0)"; - choices[0x74] = "Flash (+1)"; - choices[0x75] = "Flash (+2)"; - choices[0x76] = "Flash (+3)"; - choices[0xa3] = "Custom"; - choices[0xf3] = "Color Temperature/Color Filter"; - } +class SAWhiteBalanceSettingInterpreter: public ChoiceInterpreter +{ +public: + SAWhiteBalanceSettingInterpreter() + { + choices[0x10] = "Auto (-3)"; + choices[0x11] = "Auto (-2)"; + choices[0x12] = "Auto (-1)"; + choices[0x13] = "Auto (0)"; + choices[0x14] = "Auto (+1)"; + choices[0x15] = "Auto (+2)"; + choices[0x16] = "Auto (+3)"; + choices[0x20] = "Daylight (-3)"; + choices[0x21] = "Daylight (-2)"; + choices[0x22] = "Daylight (-1)"; + choices[0x23] = "Daylight (0)"; + choices[0x24] = "Daylight (+1)"; + choices[0x25] = "Daylight (+2)"; + choices[0x26] = "Daylight (+3)"; + choices[0x30] = "Shade (-3)"; + choices[0x31] = "Shade (-2)"; + choices[0x32] = "Shade (-1)"; + choices[0x33] = "Shade (0)"; + choices[0x34] = "Shade (+1)"; + choices[0x35] = "Shade (+2)"; + choices[0x36] = "Shade (+3)"; + choices[0x40] = "Cloudy (-3)"; + choices[0x41] = "Cloudy (-2)"; + choices[0x42] = "Cloudy (-1)"; + choices[0x43] = "Cloudy (0)"; + choices[0x44] = "Cloudy (+1)"; + choices[0x45] = "Cloudy (+2)"; + choices[0x46] = "Cloudy (+3)"; + choices[0x50] = "Tungsten (-3)"; + choices[0x51] = "Tungsten (-2)"; + choices[0x52] = "Tungsten (-1)"; + choices[0x53] = "Tungsten (0)"; + choices[0x54] = "Tungsten (+1)"; + choices[0x55] = "Tungsten (+2)"; + choices[0x56] = "Tungsten (+3)"; + choices[0x60] = "Fluorescent (-3)"; + choices[0x61] = "Fluorescent (-2)"; + choices[0x62] = "Fluorescent (-1)"; + choices[0x63] = "Fluorescent (0)"; + choices[0x64] = "Fluorescent (+1)"; + choices[0x65] = "Fluorescent (+2)"; + choices[0x66] = "Fluorescent (+3)"; + choices[0x70] = "Flash (-3)"; + choices[0x71] = "Flash (-2)"; + choices[0x72] = "Flash (-1)"; + choices[0x73] = "Flash (0)"; + choices[0x74] = "Flash (+1)"; + choices[0x75] = "Flash (+2)"; + choices[0x76] = "Flash (+3)"; + choices[0xa3] = "Custom"; + choices[0xf3] = "Color Temperature/Color Filter"; + } }; SAWhiteBalanceSettingInterpreter saWhiteBalanceSettingInterpreter; -class SASceneModeInterpreter : public ChoiceInterpreter { - public: - SASceneModeInterpreter () { - choices[0] = "Normal (P,A,S or M)"; - choices[1] = "Portrait"; - choices[2] = "Text"; - choices[3] = "Night Scene"; - choices[4] = "Sunset"; - choices[5] = "Sports"; - choices[6] = "Landscape"; - choices[8] = "Macro"; - choices[9] = "Super Macro"; - choices[16] = "Auto"; - choices[17] = "Night Portrait"; - choices[18] = "Sweep Panorama"; - choices[19] = "Handheld Night Shot"; - choices[20] = "Anti Motion Blur"; - choices[21] = "Cont.Priority AE"; - choices[22] = "Auto+"; - choices[23] = "3D Sweep Panorama"; - } +class SASceneModeInterpreter : public ChoiceInterpreter +{ +public: + SASceneModeInterpreter () + { + choices[0] = "Normal (P,A,S or M)"; + choices[1] = "Portrait"; + choices[2] = "Text"; + choices[3] = "Night Scene"; + choices[4] = "Sunset"; + choices[5] = "Sports"; + choices[6] = "Landscape"; + choices[8] = "Macro"; + choices[9] = "Super Macro"; + choices[16] = "Auto"; + choices[17] = "Night Portrait"; + choices[18] = "Sweep Panorama"; + choices[19] = "Handheld Night Shot"; + choices[20] = "Anti Motion Blur"; + choices[21] = "Cont.Priority AE"; + choices[22] = "Auto+"; + choices[23] = "3D Sweep Panorama"; + } }; SASceneModeInterpreter saSceneModeInterpreter; -class SAZoneMatchingInterpreter : public ChoiceInterpreter { - public: - SAZoneMatchingInterpreter () { - choices[0] = "ISO Setting Used"; - choices[1] = "High Key"; - choices[2] = "Low Key"; - } +class SAZoneMatchingInterpreter : public ChoiceInterpreter +{ +public: + SAZoneMatchingInterpreter () + { + choices[0] = "ISO Setting Used"; + choices[1] = "High Key"; + choices[2] = "Low Key"; + } }; SAZoneMatchingInterpreter saZoneMatchingInterpreter; -class SADynamicRangeOptimizerInterpreter : public ChoiceInterpreter { - public: - SADynamicRangeOptimizerInterpreter () { - choices[0] = "Off"; - choices[1] = "Standard"; - choices[2] = "Advanced"; - choices[3] = "Auto"; - choices[8] = "Advanced Lv1"; - choices[9] = "Advanced Lv2"; - choices[10] = "Advanced Lv3"; - choices[11] = "Advanced Lv4"; - choices[12] = "Advanced Lv5"; - choices[16] = "Lv1"; - choices[17] = "Lv2"; - choices[18] = "Lv3"; - choices[19] = "Lv4"; - choices[20] = "Lv5"; - } +class SADynamicRangeOptimizerInterpreter : public ChoiceInterpreter +{ +public: + SADynamicRangeOptimizerInterpreter () + { + choices[0] = "Off"; + choices[1] = "Standard"; + choices[2] = "Advanced"; + choices[3] = "Auto"; + choices[8] = "Advanced Lv1"; + choices[9] = "Advanced Lv2"; + choices[10] = "Advanced Lv3"; + choices[11] = "Advanced Lv4"; + choices[12] = "Advanced Lv5"; + choices[16] = "Lv1"; + choices[17] = "Lv2"; + choices[18] = "Lv3"; + choices[19] = "Lv4"; + choices[20] = "Lv5"; + } }; SADynamicRangeOptimizerInterpreter saDynamicRangeOptimizerInterpreter; -class SAColorModeInterpreter : public ChoiceInterpreter { - public: - SAColorModeInterpreter () { - choices[0] = "Standard"; - choices[1] = "Vivid"; - choices[2] = "Portrait"; - choices[3] = "Landscape"; - choices[4] = "Sunset"; - choices[5] = "Night Scene"; - choices[6] = "B&W"; - choices[7] = "Adobe RGB"; - choices[12] = "Neutral"; - choices[13] = "Clear"; - choices[14] = "Deep"; - choices[15] = "Light"; - choices[16] = "Autumn"; - choices[17] = "Sepia"; - choices[100]= "Neutral"; - choices[101]= "Clear"; - choices[102]= "Deep"; - choices[103]= "Light"; - choices[104]= "Night View"; - choices[105]= "Autumn Leaves"; - } +class SAColorModeInterpreter : public ChoiceInterpreter +{ +public: + SAColorModeInterpreter () + { + choices[0] = "Standard"; + choices[1] = "Vivid"; + choices[2] = "Portrait"; + choices[3] = "Landscape"; + choices[4] = "Sunset"; + choices[5] = "Night Scene"; + choices[6] = "B&W"; + choices[7] = "Adobe RGB"; + choices[12] = "Neutral"; + choices[13] = "Clear"; + choices[14] = "Deep"; + choices[15] = "Light"; + choices[16] = "Autumn"; + choices[17] = "Sepia"; + choices[100] = "Neutral"; + choices[101] = "Clear"; + choices[102] = "Deep"; + choices[103] = "Light"; + choices[104] = "Night View"; + choices[105] = "Autumn Leaves"; + } }; SAColorModeInterpreter saColorModeInterpreter; -class SAExposureModeInterpreter : public ChoiceInterpreter { - public: - SAExposureModeInterpreter () { - choices[0] = "Auto"; - choices[1] = "Portrait"; - choices[2] = "Beach"; - choices[4] = "Snow"; - choices[5] = "Landscape"; - choices[6] = "Program"; - choices[7] = "Aperture Priority"; - choices[8] = "Shutter Priority"; - choices[9] = "Night Scene"; - choices[10] = "Hi-Speed Shutter"; - choices[11] = "Twilight Portrait"; - choices[12] = "Soft Snap"; - choices[13] = "Fireworks"; - choices[14] = "Smile Shutter"; - choices[15] = "Manual"; - choices[18] = "High Sensitivity"; - choices[19] = "Macro"; - choices[20] = "Advanced Sports Shooting"; - choices[29] = "Underwater"; - choices[33] = "Gourmet"; - choices[34] = "Panorama"; - choices[35] = "Handheld Twilight"; - choices[36] = "Anti Motion Blur"; - choices[37] = "Pet"; - choices[38] = "Backlight Correction HDR"; - choices[40] = "Background Defocus"; - } +class SAExposureModeInterpreter : public ChoiceInterpreter +{ +public: + SAExposureModeInterpreter () + { + choices[0] = "Auto"; + choices[1] = "Portrait"; + choices[2] = "Beach"; + choices[4] = "Snow"; + choices[5] = "Landscape"; + choices[6] = "Program"; + choices[7] = "Aperture Priority"; + choices[8] = "Shutter Priority"; + choices[9] = "Night Scene"; + choices[10] = "Hi-Speed Shutter"; + choices[11] = "Twilight Portrait"; + choices[12] = "Soft Snap"; + choices[13] = "Fireworks"; + choices[14] = "Smile Shutter"; + choices[15] = "Manual"; + choices[18] = "High Sensitivity"; + choices[19] = "Macro"; + choices[20] = "Advanced Sports Shooting"; + choices[29] = "Underwater"; + choices[33] = "Gourmet"; + choices[34] = "Panorama"; + choices[35] = "Handheld Twilight"; + choices[36] = "Anti Motion Blur"; + choices[37] = "Pet"; + choices[38] = "Backlight Correction HDR"; + choices[40] = "Background Defocus"; + } }; SAExposureModeInterpreter saExposureModeInterpreter; -class SAQualityInterpreter : public ChoiceInterpreter { - public: - SAQualityInterpreter () { - choices[0] = "Normal"; - choices[1] = "Fine"; - } +class SAQualityInterpreter : public ChoiceInterpreter +{ +public: + SAQualityInterpreter () + { + choices[0] = "Normal"; + choices[1] = "Fine"; + } }; SAQualityInterpreter saQualityInterpreter; -class SAAntiBlurInterpreter : public ChoiceInterpreter { - public: - SAAntiBlurInterpreter () { - choices[0] = "Off"; - choices[1] = "On (Continuous)"; - choices[2] = "On (Shooting)"; - choices[65535] = "n/a"; - } +class SAAntiBlurInterpreter : public ChoiceInterpreter +{ +public: + SAAntiBlurInterpreter () + { + choices[0] = "Off"; + choices[1] = "On (Continuous)"; + choices[2] = "On (Shooting)"; + choices[65535] = "n/a"; + } }; SAAntiBlurInterpreter saAntiBlurInterpreter; -class SALensIDInterpreter : public IntLensInterpreter< int > { - public: - SALensIDInterpreter () { // From EXIFTOOL database 'Sony.pm' V1.94 and 'Minolta' 2.04; - // Please do not remove entries on database synchronization, and avoid transferring "categories' header" types - choices.insert(p_t(0, "Minolta AF 28-85mm f/3.5-4.5")); - choices.insert(p_t(1, "Minolta AF 80-200mm f/2.8 HS-APO G")); - choices.insert(p_t(2, "Minolta AF 28-70mm f/2.8 G")); - choices.insert(p_t(3, "Minolta AF 28-80mm f/4-5.6")); - choices.insert(p_t(4, "Minolta AF 85mm f/1.4G")); - choices.insert(p_t(5, "Minolta AF 35-70mm f/3.5-4.5")); - choices.insert(p_t(6, "Minolta AF 24-85mm f/3.5-4.5")); - choices.insert(p_t(7, "Minolta AF 100-300mm f/4.5-5.6 APO")); - choices.insert(p_t(7, "Minolta AF 100-400mm f/4.5-6.7 APO")); - choices.insert(p_t(7, "Sigma AF 100-300mm f/4 EX DG IF")); - choices.insert(p_t(8, "Minolta AF 70-210mm f/4.5-5.6")); - choices.insert(p_t(9, "Minolta AF 50mm f/3.5 Macro")); - choices.insert(p_t(10, "Minolta AF 28-105mm f/3.5-4.5 [New]")); - choices.insert(p_t(11, "Minolta AF 300mm f/4 HS-APO G")); - choices.insert(p_t(12, "Minolta AF 100mm f/2.8 Soft Focus")); - choices.insert(p_t(13, "Minolta AF 75-300mm f/4.5-5.6")); - choices.insert(p_t(14, "Minolta AF 100-400mm f/4.5-6.7 APO")); - choices.insert(p_t(15, "Minolta AF 400mm f/4.5 HS-APO G")); - choices.insert(p_t(16, "Minolta AF 17-35mm f/3.5 G")); - choices.insert(p_t(17, "Minolta AF 20-35mm f/3.5-4.5")); - choices.insert(p_t(18, "Minolta AF 28-80mm f/3.5-5.6 II")); - choices.insert(p_t(19, "Minolta AF 35mm f/1.4 G")); - choices.insert(p_t(20, "Minolta/Sony 135mm f/2.8 [T4.5] STF")); - choices.insert(p_t(22, "Minolta AF 35-80mm f/4-5.6 II")); - choices.insert(p_t(23, "Minolta AF 200mm f/4 Macro APO G")); - choices.insert(p_t(24, "Minolta/Sony AF 24-105mm f/3.5-4.5 (D)")); - choices.insert(p_t(24, "Sigma 18-50mm f/2.8 EX DC Macro")); - choices.insert(p_t(24, "Sigma 17-70mm f/2.8-4.5 DC Macro")); - choices.insert(p_t(24, "Sigma 20-40mm f/2.8 EX DG Aspherical IF")); - choices.insert(p_t(24, "Sigma 18-200mm f/3.5-6.3 DC")); - choices.insert(p_t(24, "Sigma 18-125mm f/4-5,6 DC")); - choices.insert(p_t(24, "Tamron SP AF 28-75mm f/2.8 XR Di (IF) Macro")); - choices.insert(p_t(25, "Minolta AF 100-300mm f/4.5-5.6 APO D")); - choices.insert(p_t(25, "Sigma 100-300mm f/4 EX DG APO")); - choices.insert(p_t(25, "Sigma 70mm f/2.8 EX DG Macro")); - choices.insert(p_t(25, "Sigma 20mm f/1.8 EX DG Aspherical RF")); - choices.insert(p_t(25, "Sigma 30mm f/1.4 EX DC")); - choices.insert(p_t(25, "Sigma 24mm f/1.8 EX DG ASP Macro")); - choices.insert(p_t(27, "Minolta AF 85mm f/1.4 G (D)")); - choices.insert(p_t(28, "Minolta/Sony AF 100mm f/2.8 Macro (D)")); - choices.insert(p_t(28, "Tamron SP AF 90mm f/2.8 Di Macro")); - choices.insert(p_t(28, "Tamron AF 180mm f/3.5 SP Di LD [IF] Macro")); - choices.insert(p_t(29, "Minolta/Sony AF 75-300mm f/4.5-5.6 (D)")); - choices.insert(p_t(30, "Minolta AF 28-80mm f/3.5-5.6 (D)")); - choices.insert(p_t(30, "Sigma AF 10-20mm f/4-5.6 EX DC")); - choices.insert(p_t(30, "Sigma AF 12-24mm f/4.5-5.6 EX DG")); - choices.insert(p_t(30, "Sigma 28-70mm EX DG F2.8")); - choices.insert(p_t(30, "Sigma 55-200mm f/4-5.6 DC")); - choices.insert(p_t(31, "Minolta/Sony AF 50mm f/2.8 Macro (D)")); - choices.insert(p_t(31, "Minolta/Sony AF 50mm f/3.5 Macro")); - choices.insert(p_t(32, "Minolta/Sony AF 300mm f/2.8 G or 1.5x Teleconverter")); - choices.insert(p_t(33, "Minolta/Sony AF 70-200mm f/2.8 G")); - choices.insert(p_t(35, "Minolta AF 85mm f/1.4 G (D) Limited")); - choices.insert(p_t(36, "Minolta AF 28-100mm f/3.5-5.6 (D)")); - choices.insert(p_t(38, "Minolta AF 17-35mm f/2.8-4 (D)")); - choices.insert(p_t(39, "Minolta AF 28-75mm f/2.8 (D)")); - choices.insert(p_t(40, "Minolta/Sony AF DT 18-70mm f/3.5-5.6 (D)")); - choices.insert(p_t(41, "Minolta/Sony AF DT 11-18mm f/4.5-5.6 (D)")); - choices.insert(p_t(41, "Tamron SP AF 11-18mm f/4.5-5.6 Di II LD Aspherical IF")); - choices.insert(p_t(42, "Minolta AF DT 18-200mm f/3.5-6.3 (D)")); - choices.insert(p_t(43, "Minolta AF 35mm f/1.4 G")); - choices.insert(p_t(44, "Sony AF 50mm f/1.4")); - choices.insert(p_t(45, "Carl Zeiss Planar T* 85mm f/1.4 ZA")); - choices.insert(p_t(46, "Carl Zeiss Vario-Sonnar T* DT 16-80mm f/3.5-4.5 ZA")); - choices.insert(p_t(47, "Carl Zeiss Sonnar T* 135mm F1.8 ZA")); - choices.insert(p_t(48, "Carl Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM")); - choices.insert(p_t(49, "Sony AF DT 55-200mm f/4-5.6")); - choices.insert(p_t(50, "Sony AF DT 18-250mm f/3.5-6.3")); - choices.insert(p_t(51, "Sony AF DT 16-105mm f/3.5-5.6")); - choices.insert(p_t(52, "Sony AF 70-300mm f/4.5-5.6 G SSM")); - choices.insert(p_t(52, "Tamron SP 70-300mm f/4-5.6 Di VC USD")); - choices.insert(p_t(53, "Sony AF 70-400mm f/4.5-5.6 G SSM")); - choices.insert(p_t(54, "Carl Zeiss Vario-Sonnar T* 16-35mm f/2.8 ZA SSM")); - choices.insert(p_t(55, "Sony DT 18-55mm f/3.5-5.6 SAM")); - choices.insert(p_t(56, "Sony AF DT 55-200mm f/4-5.6 SAM")); - choices.insert(p_t(57, "Sony AF DT 50mm f/1.8 SAM")); - choices.insert(p_t(57, "Tamron SP AF 60mm f/2 Di II LD [IF] Macro 1:1")); - choices.insert(p_t(57, "Tamron 18-270mm f/3.5-6.3 Di II PZD")); - choices.insert(p_t(58, "Sony AF DT 30mm f/2.8 SAM Macro")); - choices.insert(p_t(59, "Sony AF 28-75mm f/2.8 SAM")); - choices.insert(p_t(60, "Carl Zeiss Distagon T* 24mm f/2 ZA SSM")); - choices.insert(p_t(61, "Sony AF 85mm f/2.8 SAM")); - choices.insert(p_t(62, "Sony DT 35mm f/1.8 SAM")); - choices.insert(p_t(63, "Sony DT 16-50mm f/2.8 SSM")); - choices.insert(p_t(64, "Sony 500mm f/4.0 G SSM")); - choices.insert(p_t(65, "Sony DT 18-135mm f/3.5-5.6 SAM")); - choices.insert(p_t(66, "Sony 300mm f/2.8 G SSM II")); - choices.insert(p_t(67, "Sony 70-20mm f/2.8 G SSM")); - choices.insert(p_t(68, "Sony DT 55-300mm f/4.5-5.6 SAM")); - choices.insert(p_t(69, "Sony 70-400mm f/4-5.6 G SSM II")); - choices.insert(p_t(70, "Carl Zeiss Planar T* 50mm f/1.4 ZA SSM")); - choices.insert(p_t(128, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF)")); - choices.insert(p_t(128, "Tamron AF 28-300mm f/3.5-6.3")); - choices.insert(p_t(128, "Tamron 80-300mm f/3.5-6.3")); - choices.insert(p_t(128, "Tamron AF 28-200mm f/3.8-5.6 XR Di Aspherical [IF] Macro")); - choices.insert(p_t(128, "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF")); - choices.insert(p_t(128, "Sigma AF 50-150mm f/2.8 EX DC APO HSM II")); - choices.insert(p_t(128, "Sigma 10-20mm f/3.5 EX DC HSM")); - choices.insert(p_t(128, "Sigma 70-200mm f/2.8 II EX DG APO Macro HSM")); - choices.insert(p_t(128, "Sigma 10mm f/2.8 EX DC HSM Fisheye")); - choices.insert(p_t(128, "Sigma 35mm f/1.4 DG HSM")); - choices.insert(p_t(128, "Sigma 50mm f/1.4 EX DG HSM")); - choices.insert(p_t(128, "Sigma 85mm f/1.4 EX DG HSM")); - choices.insert(p_t(128, "Sigma 24-70mm f/2.8 IF EX DG HSM")); - choices.insert(p_t(128, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); - choices.insert(p_t(128, "Sigma 17-50mm f/2.8 EX DC HSM")); - choices.insert(p_t(128, "Sigma 17-70mm f/2.8-4 DC Macro HSM")); - choices.insert(p_t(129, "Tamron 200-400mm f/5.6 LD")); - choices.insert(p_t(129, "Tamron 70-300mm f/4-5.6 LD")); - choices.insert(p_t(131, "Tamron 20-40mm f/2.7-3.5 SP Aspherical IF")); - choices.insert(p_t(135, "Vivitar 28-210mm f/3.5-5.6")); - choices.insert(p_t(136, "Tokina EMZ M100 AF 100mm f/3.5")); - choices.insert(p_t(137, "Cosina 70-210mm f/2.8-4 AF")); - choices.insert(p_t(138, "Soligor 19-35mm f/3.5-4.5")); - choices.insert(p_t(142, "Voigtlander 70-300mm f/4.5-5.6")); - choices.insert(p_t(146, "Voigtlander Macro APO-Lanthar 125mm f/2.5 SL")); - choices.insert(p_t(255, "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical")); - choices.insert(p_t(255, "Tamron AF 18-250mm f/3.5-6.3 XR Di II LD")); - choices.insert(p_t(255, "Tamron AF 55-200mm f/4-5.6 Di II LD Macro")); - choices.insert(p_t(255, "Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2")); - choices.insert(p_t(255, "Tamron SP AF 200-500mm f/5.0-6.3 Di LD [IF]")); - choices.insert(p_t(255, "Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical [IF]")); - choices.insert(p_t(255, "Tamron SP AF 70-200mm f/2.8 Di LD Macro [IF]")); - choices.insert(p_t(255, "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF]")); - choices.insert(p_t(2550, "Minolta AF 50mm f/1.7")); - choices.insert(p_t(2551, "Minolta AF 35-70mm f/4")); - choices.insert(p_t(2551, "Sigma UC AF 28-70mm f/3.5-4.5")); - choices.insert(p_t(2551, "Sigma AF 28-70mm f/2.8")); - choices.insert(p_t(2551, "Sigma M-AF 70-200mm f/2.8 EX Aspherical")); - choices.insert(p_t(2551, "Quantaray M-AF 35-80mm f/4-5.6")); - choices.insert(p_t(2552, "Minolta AF 28-85mm f/3.5-4.5 [New]")); - choices.insert(p_t(2552, "Tokina 19-35mm f/3.5-4.5")); - choices.insert(p_t(2552, "Tokina 28-70mm f/2.8 AT-X")); - choices.insert(p_t(2552, "Tokina 80-400mm f/4.5-5.6 AT-X AF II 840")); - choices.insert(p_t(2552, "Tokina AF PRO 28-80mm f/2.8 AT-X 280")); - choices.insert(p_t(2552, "Tokina AT-X PRO II AF 28-70mm f/2.6-2.8 270")); - choices.insert(p_t(2552, "Tamron AF 19-35mm f/3.5-4.5")); - choices.insert(p_t(2552, "Angenieux AF 28-70mm f/2.6")); - choices.insert(p_t(2553, "Minolta AF 28-135mm f/4-4.5")); - choices.insert(p_t(2553, "Sigma ZOOM-alpha 35-135mm f/3.5-4.5")); - choices.insert(p_t(2553, "Sigma 28-105mm f/2.8-4 Aspherical")); - choices.insert(p_t(2554, "Minolta AF 35-105mm f/3.5-4.5")); - choices.insert(p_t(2555, "Minolta AF 70-210mm f/4 Macro")); - choices.insert(p_t(2555, "Sigma 70-210mm f/4-5.6 APO")); - choices.insert(p_t(2555, "Sigma M-AF 70-200mm f/2.8 EX APO")); - choices.insert(p_t(2555, "Sigma 75-200mm f/2.8-3.5")); - choices.insert(p_t(2556, "Minolta AF 135mm f/2.8")); - choices.insert(p_t(2557, "Minolta AF 28mm f/2.8")); - choices.insert(p_t(2558, "Minolta AF 24-50mm f/4")); - choices.insert(p_t(2560, "Minolta AF 100-200mm f/4.5")); - choices.insert(p_t(2561, "Minolta AF 75-300mm f/4.5-5.6")); - choices.insert(p_t(2561, "Sigma 70-300mm f/4-5.6 DL Macro")); - choices.insert(p_t(2561, "Sigma 300mm f/4 APO Macro")); - choices.insert(p_t(2561, "Sigma AF 500mm f/4.5 APO")); - choices.insert(p_t(2561, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); - choices.insert(p_t(2561, "Tokina AT-X AF 300mm f/4")); - choices.insert(p_t(2561, "Tokina AT-X AF 400mm f/5.6 SD")); - choices.insert(p_t(2561, "Tokina AF 730 II 75-300mm f/4.5-5.6")); - choices.insert(p_t(2562, "Minolta/Sony AF 50mm f/1.4 [New]")); - choices.insert(p_t(2563, "Minolta AF 300mm f/2.8 G")); - choices.insert(p_t(2563, "Sigma AF 50-500mm f/4-6.3 EX DG APO")); - choices.insert(p_t(2563, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); - choices.insert(p_t(2563, "Sigma AF 500mm f/4.5 EX DG APO")); - choices.insert(p_t(2563, "Sigma 400mm f/5.6 APO")); - choices.insert(p_t(2564, "Minolta AF 50mm f/2.8 Macro")); - choices.insert(p_t(2564, "Sigma 50mm f/2.8 EX Macro")); - choices.insert(p_t(2565, "Minolta AF 600mm f/4")); - choices.insert(p_t(2566, "Minolta AF 24mm f/2.8")); - choices.insert(p_t(2572, "Minolta/Sony AF 500mm f/8 Reflex")); - choices.insert(p_t(2578, "Minolta AF 16mm f/2.8 Fisheye")); - choices.insert(p_t(2578, "Sigma 8mm f/4 EX DG Fisheye")); - choices.insert(p_t(2578, "Sigma 14mm f/3.5")); - choices.insert(p_t(2578, "Sigma 15mm f/2.8 Fisheye")); - choices.insert(p_t(2579, "Minolta AF 20mm f/2.8")); - choices.insert(p_t(2581, "Minolta/Sony AF 100mm f/2.8 Macro")); - choices.insert(p_t(2581, "Sigma AF 90mm f/2.8 Macro")); - choices.insert(p_t(2581, "Sigma AF 105mm f/2.8 EX DG Macro")); - choices.insert(p_t(2581, "Sigma 180mm f/5.6 Macro")); - choices.insert(p_t(2581, "Tamron AF 90mm f/2.8 Macro")); - choices.insert(p_t(2585, "Minolta AF 35-105mm f/3.5-4.5 New")); - choices.insert(p_t(2585, "Beroflex 35-135mm f/3.5-4.5")); - choices.insert(p_t(2585, "Tamron AF 24-135mm f/3.5-5.6")); - choices.insert(p_t(2588, "Minolta AF 70-210mm f/3.5-4.5")); - choices.insert(p_t(2589, "Minolta AF 80-200 f/2.8 APO")); - choices.insert(p_t(2589, "Tokina 80-200mm f/2.8")); - choices.insert(p_t(2591, "Minolta AF 35mm f/1.4")); - choices.insert(p_t(2592, "Minolta AF 85mm f/1.4 G (D)")); - choices.insert(p_t(2593, "Minolta AF 200mm f/2.8 G APO")); - choices.insert(p_t(2594, "Minolta AF 3x-1x f/1.7-2.8 Macro")); - choices.insert(p_t(2596, "Minolta AF 28mm f/2")); - choices.insert(p_t(2597, "Minolta AF 35mm f/2")); - choices.insert(p_t(2598, "Minolta AF 100mm f/2")); - choices.insert(p_t(2604, "Minolta AF 80-200mm f/4.5-5.6")); - choices.insert(p_t(2605, "Minolta AF 35-80mm f/4-5.6")); - choices.insert(p_t(2606, "Minolta AF 100-300mm f/4.5-5.6 (D)")); - choices.insert(p_t(2607, "Minolta AF 35-80mm f/4-5.6")); - choices.insert(p_t(2608, "Minolta AF 300mm f/2.8 G")); - choices.insert(p_t(2609, "Minolta AF 600mm f/4 HS-APO G")); - choices.insert(p_t(2612, "Minolta AF 200mm f/2.8 G HS-APO")); - choices.insert(p_t(2613, "Minolta AF 50mm f/1.7 New")); - choices.insert(p_t(2615, "Minolta AF 28-105mm f/3.5-4.5 Power Zoom")); - choices.insert(p_t(2616, "Minolta AF 35-200mm f/4.5-5.6 Power Zoom")); - choices.insert(p_t(2618, "Minolta AF 28-80mm f/4-5.6 Power Zoom")); - choices.insert(p_t(2619, "Minolta AF 80-200mm f/4.5-5.6 Power Zoom")); - choices.insert(p_t(2620, "Minolta AF 28-70mm f/2.8 G")); - choices.insert(p_t(2621, "Minolta AF 100-300mm f/4.5-5.6 Power Zoom")); - choices.insert(p_t(2624, "Minolta AF 35-80mm f/4-5.6 Power Zoom")); - choices.insert(p_t(2628, "Minolta AF 80-200mm f/2.8 G")); - choices.insert(p_t(2629, "Minolta AF 85mm f/1.4 New")); - choices.insert(p_t(2631, "Minolta/Sony AF 100-300mm f/4.5-5.6 APO")); - choices.insert(p_t(2632, "Minolta AF 24-50mm f/4 New")); - choices.insert(p_t(2638, "Minolta AF 50mm f/2.8 Macro New")); - choices.insert(p_t(2639, "Minolta AF 100mm f/2.8 Macro")); - choices.insert(p_t(2641, "Minolta AF 20mm f/2.8 New")); - choices.insert(p_t(2642, "Minolta AF 24mm f/2.8 New")); - choices.insert(p_t(2644, "Minolta AF 100-400mm f/4.5-6.7 APO")); - choices.insert(p_t(2662, "Minolta AF 50mm f/1.4 New")); - choices.insert(p_t(2667, "Minolta AF 35mm f/2 New")); - choices.insert(p_t(2668, "Minolta AF 28mm f/2 New")); - choices.insert(p_t(2672, "Minolta AF 24-105mm f/3.5-4.5 (D)")); - choices.insert(p_t(4574, "Minolta AF 200mm f/2.8 G x2")); - choices.insert(p_t(4575, "1.4 x Teleconverter")); - choices.insert(p_t(4585, "Tamron SP AF 300mm f/2.8 LD IF")); - choices.insert(p_t(6553, "Arax MC 35mm f/2.8 Tilt+Shift")); - choices.insert(p_t(6553, "Arax MC 80mm f/2.8 Tilt+Shift")); - choices.insert(p_t(6553, "Zenitar MF 16mm f/2.8 Fisheye M42")); - choices.insert(p_t(6553, "Samyang 500mm Mirror f/8")); - choices.insert(p_t(6553, "Pentacon Auto 135mm f/2.8")); - choices.insert(p_t(6553, "Pentacon Auto 29mm f/2.8")); - choices.insert(p_t(6553, "Helios 44-2 58mm f/2")); - choices.insert(p_t(25501, "Minolta AF 50mm f/1.7")); - choices.insert(p_t(25511, "Minolta AF 35-70mm f/4")); - choices.insert(p_t(25511, "Sigma UC AF 28-70mm f/3.5-4.5")); - choices.insert(p_t(25511, "Sigma AF 28-70mm f/2.8")); - choices.insert(p_t(25511, "Sigma M-AF 70-200mm f/2.8 EX Aspherical")); - choices.insert(p_t(25511, "Quantaray M-AF 35-80mm f/4-5.6")); - choices.insert(p_t(25521, "Minolta AF 28-85mm f/3.5-4.5")); - choices.insert(p_t(25521, "Tokina 19-35mm f/3.5-4.5")); - choices.insert(p_t(25521, "Tokina 28-70mm f/2.8 AT-X")); - choices.insert(p_t(25521, "Tokina 80-400mm f/4.5-5.6 AT-X AF II 840")); - choices.insert(p_t(25521, "Tokina AF PRO 28-80mm f/2.8 AT-X 280")); - choices.insert(p_t(25521, "Tokina AT-X PRO II AF 28-70mm f/2.6-2.8 270")); - choices.insert(p_t(25521, "Tamron AF 19-35mm f/3.5-4.5")); - choices.insert(p_t(25521, "Angenieux AF 28-70mm f/2.6")); - choices.insert(p_t(25521, "Tokina AT-X 17 AF 17mm f/3.5")); - choices.insert(p_t(25531, "Minolta AF 28-135mm f/4-4.5")); - choices.insert(p_t(25531, "Sigma ZOOM-alpha 35-135mm f/3.5-4.5")); - choices.insert(p_t(25531, "Sigma 28-105mm f/2.8-4 Aspherical")); - choices.insert(p_t(25531, "Sigma 28-105mm f/4-5.6 UC")); - choices.insert(p_t(25541, "Minolta AF 35-105mm f/3.5-4.5")); - choices.insert(p_t(25551, "Minolta AF 70-210mm f/4 Macro")); - choices.insert(p_t(25551, "Sigma 70-210mm f/4-5.6 APO")); - choices.insert(p_t(25551, "Sigma M-AF 70-200mm f/2.8 EX APO")); - choices.insert(p_t(25551, "Sigma 75-200mm f/2.8-3.5")); - choices.insert(p_t(25561, "Minolta AF 135mm f/2.8")); - choices.insert(p_t(25571, "Minolta/Sony AF 28mm f/2.8")); - choices.insert(p_t(25581, "Minolta AF 24-50mm f/4")); - choices.insert(p_t(25601, "Minolta AF 100-200mm f/4.5")); - choices.insert(p_t(25611, "Minolta AF 75-300mm f/4.5-5.6")); - choices.insert(p_t(25611, "Sigma 70-300mm f/4-5.6 DL Macro")); - choices.insert(p_t(25611, "Sigma 300mm f/4 APO Macro")); - choices.insert(p_t(25611, "Sigma AF 500mm f/4.5 APO")); - choices.insert(p_t(25611, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); - choices.insert(p_t(25611, "Tokina AT-X AF 300mm f/4")); - choices.insert(p_t(25611, "Tokina AT-X AF 400mm f/5.6 SD")); - choices.insert(p_t(25611, "Tokina AF 730 II 75-300mm f/4.5-5.6")); - choices.insert(p_t(25611, "Sigma 800mm f/5.6 APO")); - choices.insert(p_t(25611, "Sigma AF 400mm f/5.6 APO Macro")); - choices.insert(p_t(25621, "Minolta AF 50mm f/1.4")); - choices.insert(p_t(25631, "Minolta AF 300mm f/2.8 APO")); - choices.insert(p_t(25631, "Sigma AF 50-500mm f/4-6.3 EX DG APO")); - choices.insert(p_t(25631, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); - choices.insert(p_t(25631, "Sigma AF 500mm f/4.5 EX DG APO")); - choices.insert(p_t(25631, "Sigma 400mm f/5.6 APO")); - choices.insert(p_t(25641, "Minolta AF 50mm f/2.8 Macro")); - choices.insert(p_t(25641, "Sigma AF 50mm f/2.8 EX Macro")); - choices.insert(p_t(25651, "Minolta AF 600mm f/4")); - choices.insert(p_t(25661, "Minolta AF 24mm f/2.8")); - choices.insert(p_t(25661, "Sigma 17-35mm f/2.8-4 EX Aspherical")); - choices.insert(p_t(25721, "Minolta/Sony AF 500mm f/8 Reflex")); - choices.insert(p_t(25781, "Minolta/Sony AF 16mm f/2.8 Fisheye")); - choices.insert(p_t(25781, "Sigma 8mm f/4 EX DG Fisheye")); - choices.insert(p_t(25781, "Sigma 14mm f/3.5")); - choices.insert(p_t(25781, "Sigma 15mm f/2.8 Fisheye")); - choices.insert(p_t(25791, "Minolta/Sony AF 20mm f/2.8")); - choices.insert(p_t(25791, "Tokina AT-X Pro DX 11-16mm f/2.8")); - choices.insert(p_t(25811, "Minolta/Sony AF 100mm f/2.8 Macro")); - choices.insert(p_t(25811, "Sigma AF 90mm f/2.8 Macro")); - choices.insert(p_t(25811, "Sigma AF 105mm f/2.8 EX DG Macro")); - choices.insert(p_t(25811, "Sigma 180mm f/5.6 Macro")); - choices.insert(p_t(25811, "Sigma 180mm f/3.5 EX DG Macro")); - choices.insert(p_t(25811, "Tamron 90mm f/2.8 Macro")); - choices.insert(p_t(25851, "Beroflex 35-135mm f/3.5-4.5")); - choices.insert(p_t(25858, "Minolta AF 35-105mm f/3.5-4.5")); - choices.insert(p_t(25858, "Tamron 24-135mm f/3.5-5.6")); - choices.insert(p_t(25881, "Minolta AF 70-210mm f/3.5-4.5")); - choices.insert(p_t(25891, "Minolta AF 80-200mm f/2.8 APO")); - choices.insert(p_t(25891, "Tokina 80-200mm f/2.8")); - choices.insert(p_t(25901, "Minolta AF 200mm f/2.8 G APO + Minolta AF 1.4x APO")); - choices.insert(p_t(25901, "Minolta AF 600mm f/4 HS-APO G + Minolta AF 1.4x APO")); - choices.insert(p_t(25911, "Minolta AF 35mm f/1.4")); - choices.insert(p_t(25921, "Minolta AF 85mm f/1.4 G (D)")); - choices.insert(p_t(25931, "Minolta AF 200mm f/2.8 G APO")); - choices.insert(p_t(25941, "Minolta AF 3x-1x f/1.7-2.8 Macro")); - choices.insert(p_t(25961, "Minolta AF 28mm f/2")); - choices.insert(p_t(25971, "Minolta AF 35mm f/2")); - choices.insert(p_t(25981, "Minolta AF 100mm f/2")); - choices.insert(p_t(26011, "Minolta AF 200mm f/2.8 G APO + Minolta AF 2x APO")); - choices.insert(p_t(26011, "Minolta AF 600mm f/4 HS-APO G + Minolta AF 2x APO")); - choices.insert(p_t(26041, "Minolta AF 80-200mm f/4.5-5.6")); - choices.insert(p_t(26051, "Minolta AF 35-80mm f/4-5.6")); - choices.insert(p_t(26061, "Minolta AF 100-300mm f/4.5-5.6")); - choices.insert(p_t(26071, "Minolta AF 35-80mm f/4-5.6")); - choices.insert(p_t(26081, "Minolta AF 300mm f/2.8 HS-APO G")); - choices.insert(p_t(26091, "Minolta AF 600mm f/4 HS-APO G")); - choices.insert(p_t(26121, "Minolta AF 200mm f/2.8 HS-APO G")); - choices.insert(p_t(26131, "Minolta AF 50mm f/1.7 New")); - choices.insert(p_t(26151, "Minolta AF 28-105mm f/3.5-4.5 xi")); - choices.insert(p_t(26161, "Minolta AF 35-200mm f/4.5-5.6 xi")); - choices.insert(p_t(26181, "Minolta AF 28-80mm f/4-5.6 xi")); - choices.insert(p_t(26191, "Minolta AF 80-200mm f/4.5-5.6 xi")); - choices.insert(p_t(26201, "Minolta AF 28-70mm f/2.8 G")); - choices.insert(p_t(26211, "Minolta AF 100-300mm f/4.5-5.6 xi")); - choices.insert(p_t(26241, "Minolta AF 35-80mm f/4-5.6 Power Zoom")); - choices.insert(p_t(26281, "Minolta AF 80-200mm f/2.8 G")); - choices.insert(p_t(26291, "Minolta AF 85mm f/1.4 New")); - choices.insert(p_t(26311, "Minolta/Sony AF 100-300mm f/4.5-5.6 APO")); - choices.insert(p_t(26321, "Minolta AF 24-50mm f/4 New")); - choices.insert(p_t(26381, "Minolta AF 50mm f/2.8 Macro New")); - choices.insert(p_t(26391, "Minolta AF 100mm f/2.8 Macro")); - choices.insert(p_t(26411, "Minolta/Sony AF 20mm f/2.8 New")); - choices.insert(p_t(26421, "Minolta AF 24mm f/2.8 New")); - choices.insert(p_t(26441, "Minolta AF 100-400mm f/4.5-6.7 APO")); - choices.insert(p_t(26621, "Minolta AF 50mm f/1.4 New")); - choices.insert(p_t(26671, "Minolta AF 35mm f/2 New")); - choices.insert(p_t(26681, "Minolta AF 28mm f/2 New")); - choices.insert(p_t(26721, "Minolta AF 24-105mm f/3.5-4.5 (D)")); - choices.insert(p_t(45671, "Tokina 70-210mm f/4-5.6")); - choices.insert(p_t(45741, "Tamron SP AF 90mm f/2.5")); - choices.insert(p_t(45741, "Tokina RF 500mm f/8.0 x2")); - choices.insert(p_t(45741, "Tokina 300mm f/2.8 x2")); - choices.insert(p_t(45741, "Minolta AF 200mm f/2.8 G x2")); - choices.insert(p_t(45851, "Tamron SP AF 300mm f/2.8 LD IF")); - choices.insert(p_t(45871, "Tamron AF 70-210mm f/2.8 SP LD")); - choices.insert(p_t(65535, "Sony E 16mm f/2.8")); - choices.insert(p_t(65535, "Sony E 18-55mm f/3.5-5.6 OSS")); - choices.insert(p_t(65535, "Sony E 55-210mm f/4.5-6.3 OSS")); - choices.insert(p_t(65535, "Sony E 18-200mm f/3.5-6.3 OSS")); - choices.insert(p_t(65535, "Sony E 30mm f/3.5 Macro")); - choices.insert(p_t(65535, "Sony E 24mm f/1.8 ZA")); - choices.insert(p_t(65535, "Sony E 50mm f/1.8 OSS")); - choices.insert(p_t(65535, "Sony E 16-70mm f/4 ZA OSS")); - choices.insert(p_t(65535, "Sony E 10-18mm f/4 OSS")); - choices.insert(p_t(65535, "Sony E PZ 16-50mm f/3.5-5.6 OSS")); - choices.insert(p_t(65535, "Sony FE 35mm f/2.8 ZA")); - choices.insert(p_t(65535, "Sony FE 24-70mm f/4 ZA OSS")); - choices.insert(p_t(65535, "Sony E 18-200mm f/3.5-6.3 OSS LE")); - choices.insert(p_t(65535, "Sony E 20mm f/2.8")); - choices.insert(p_t(65535, "Sony E 35mm f/1.8 OSS")); - choices.insert(p_t(65535, "Sony E PZ 18-200mm f/3.5-6.3 OSS")); - choices.insert(p_t(65535, "Sony FE 55mm f/1.8 ZA")); - choices.insert(p_t(65535, "Sony FE 28-70mm f/3.5-5.6 OSS")); - choices.insert(p_t(65535, "Sony E PZ 18-105mm f/4 G OSS")); - choices.insert(p_t(65535, "Sony FE 70-200mm f/4 G OSS")); - choices.insert(p_t(65535, "Sigma 19mm f/2.8 [EX] DN")); - choices.insert(p_t(65535, "Sigma 30mm f/2.8 [EX] DN")); - choices.insert(p_t(65535, "Sigma 60mm f/2.8 DN")); - choices.insert(p_t(65535, "Tamron 18-200mm f/3.5-6.3 Di III VC")); - choices.insert(p_t(65535, "Zeiss Touit 12mm f/2.8")); - choices.insert(p_t(65535, "Zeiss Touit 32mm f/1.8")); - choices.insert(p_t(65535, "Arax MC 35mm f/2.8 Tilt+Shift")); - choices.insert(p_t(65535, "Arax MC 80mm f/2.8 Tilt+Shift")); - choices.insert(p_t(65535, "Zenitar MF 16mm f/2.8 Fisheye M42")); - choices.insert(p_t(65535, "Samyang 500mm f/8 Mirror")); - choices.insert(p_t(65535, "Pentacon Auto 135mm f/2.8")); - choices.insert(p_t(65535, "Pentacon Auto 29mm f/2.8")); - choices.insert(p_t(65535, "Helios 44-2 58mm f/2")); +class SALensIDInterpreter : public IntLensInterpreter< int > +{ +public: + SALensIDInterpreter () // From EXIFTOOL database 'Sony.pm' V1.94 and 'Minolta' 2.04; + { + // Please do not remove entries on database synchronization, and avoid transferring "categories' header" types + choices.insert(p_t(0, "Minolta AF 28-85mm f/3.5-4.5")); + choices.insert(p_t(1, "Minolta AF 80-200mm f/2.8 HS-APO G")); + choices.insert(p_t(2, "Minolta AF 28-70mm f/2.8 G")); + choices.insert(p_t(3, "Minolta AF 28-80mm f/4-5.6")); + choices.insert(p_t(4, "Minolta AF 85mm f/1.4G")); + choices.insert(p_t(5, "Minolta AF 35-70mm f/3.5-4.5")); + choices.insert(p_t(6, "Minolta AF 24-85mm f/3.5-4.5")); + choices.insert(p_t(7, "Minolta AF 100-300mm f/4.5-5.6 APO")); + choices.insert(p_t(7, "Minolta AF 100-400mm f/4.5-6.7 APO")); + choices.insert(p_t(7, "Sigma AF 100-300mm f/4 EX DG IF")); + choices.insert(p_t(8, "Minolta AF 70-210mm f/4.5-5.6")); + choices.insert(p_t(9, "Minolta AF 50mm f/3.5 Macro")); + choices.insert(p_t(10, "Minolta AF 28-105mm f/3.5-4.5 [New]")); + choices.insert(p_t(11, "Minolta AF 300mm f/4 HS-APO G")); + choices.insert(p_t(12, "Minolta AF 100mm f/2.8 Soft Focus")); + choices.insert(p_t(13, "Minolta AF 75-300mm f/4.5-5.6")); + choices.insert(p_t(14, "Minolta AF 100-400mm f/4.5-6.7 APO")); + choices.insert(p_t(15, "Minolta AF 400mm f/4.5 HS-APO G")); + choices.insert(p_t(16, "Minolta AF 17-35mm f/3.5 G")); + choices.insert(p_t(17, "Minolta AF 20-35mm f/3.5-4.5")); + choices.insert(p_t(18, "Minolta AF 28-80mm f/3.5-5.6 II")); + choices.insert(p_t(19, "Minolta AF 35mm f/1.4 G")); + choices.insert(p_t(20, "Minolta/Sony 135mm f/2.8 [T4.5] STF")); + choices.insert(p_t(22, "Minolta AF 35-80mm f/4-5.6 II")); + choices.insert(p_t(23, "Minolta AF 200mm f/4 Macro APO G")); + choices.insert(p_t(24, "Minolta/Sony AF 24-105mm f/3.5-4.5 (D)")); + choices.insert(p_t(24, "Sigma 18-50mm f/2.8 EX DC Macro")); + choices.insert(p_t(24, "Sigma 17-70mm f/2.8-4.5 DC Macro")); + choices.insert(p_t(24, "Sigma 20-40mm f/2.8 EX DG Aspherical IF")); + choices.insert(p_t(24, "Sigma 18-200mm f/3.5-6.3 DC")); + choices.insert(p_t(24, "Sigma 18-125mm f/4-5,6 DC")); + choices.insert(p_t(24, "Tamron SP AF 28-75mm f/2.8 XR Di (IF) Macro")); + choices.insert(p_t(25, "Minolta AF 100-300mm f/4.5-5.6 APO D")); + choices.insert(p_t(25, "Sigma 100-300mm f/4 EX DG APO")); + choices.insert(p_t(25, "Sigma 70mm f/2.8 EX DG Macro")); + choices.insert(p_t(25, "Sigma 20mm f/1.8 EX DG Aspherical RF")); + choices.insert(p_t(25, "Sigma 30mm f/1.4 EX DC")); + choices.insert(p_t(25, "Sigma 24mm f/1.8 EX DG ASP Macro")); + choices.insert(p_t(27, "Minolta AF 85mm f/1.4 G (D)")); + choices.insert(p_t(28, "Minolta/Sony AF 100mm f/2.8 Macro (D)")); + choices.insert(p_t(28, "Tamron SP AF 90mm f/2.8 Di Macro")); + choices.insert(p_t(28, "Tamron AF 180mm f/3.5 SP Di LD [IF] Macro")); + choices.insert(p_t(29, "Minolta/Sony AF 75-300mm f/4.5-5.6 (D)")); + choices.insert(p_t(30, "Minolta AF 28-80mm f/3.5-5.6 (D)")); + choices.insert(p_t(30, "Sigma AF 10-20mm f/4-5.6 EX DC")); + choices.insert(p_t(30, "Sigma AF 12-24mm f/4.5-5.6 EX DG")); + choices.insert(p_t(30, "Sigma 28-70mm EX DG F2.8")); + choices.insert(p_t(30, "Sigma 55-200mm f/4-5.6 DC")); + choices.insert(p_t(31, "Minolta/Sony AF 50mm f/2.8 Macro (D)")); + choices.insert(p_t(31, "Minolta/Sony AF 50mm f/3.5 Macro")); + choices.insert(p_t(32, "Minolta/Sony AF 300mm f/2.8 G or 1.5x Teleconverter")); + choices.insert(p_t(33, "Minolta/Sony AF 70-200mm f/2.8 G")); + choices.insert(p_t(35, "Minolta AF 85mm f/1.4 G (D) Limited")); + choices.insert(p_t(36, "Minolta AF 28-100mm f/3.5-5.6 (D)")); + choices.insert(p_t(38, "Minolta AF 17-35mm f/2.8-4 (D)")); + choices.insert(p_t(39, "Minolta AF 28-75mm f/2.8 (D)")); + choices.insert(p_t(40, "Minolta/Sony AF DT 18-70mm f/3.5-5.6 (D)")); + choices.insert(p_t(41, "Minolta/Sony AF DT 11-18mm f/4.5-5.6 (D)")); + choices.insert(p_t(41, "Tamron SP AF 11-18mm f/4.5-5.6 Di II LD Aspherical IF")); + choices.insert(p_t(42, "Minolta AF DT 18-200mm f/3.5-6.3 (D)")); + choices.insert(p_t(43, "Minolta AF 35mm f/1.4 G")); + choices.insert(p_t(44, "Sony AF 50mm f/1.4")); + choices.insert(p_t(45, "Carl Zeiss Planar T* 85mm f/1.4 ZA")); + choices.insert(p_t(46, "Carl Zeiss Vario-Sonnar T* DT 16-80mm f/3.5-4.5 ZA")); + choices.insert(p_t(47, "Carl Zeiss Sonnar T* 135mm F1.8 ZA")); + choices.insert(p_t(48, "Carl Zeiss Vario-Sonnar T* 24-70mm f/2.8 ZA SSM")); + choices.insert(p_t(49, "Sony AF DT 55-200mm f/4-5.6")); + choices.insert(p_t(50, "Sony AF DT 18-250mm f/3.5-6.3")); + choices.insert(p_t(51, "Sony AF DT 16-105mm f/3.5-5.6")); + choices.insert(p_t(52, "Sony AF 70-300mm f/4.5-5.6 G SSM")); + choices.insert(p_t(52, "Tamron SP 70-300mm f/4-5.6 Di VC USD")); + choices.insert(p_t(53, "Sony AF 70-400mm f/4.5-5.6 G SSM")); + choices.insert(p_t(54, "Carl Zeiss Vario-Sonnar T* 16-35mm f/2.8 ZA SSM")); + choices.insert(p_t(55, "Sony DT 18-55mm f/3.5-5.6 SAM")); + choices.insert(p_t(56, "Sony AF DT 55-200mm f/4-5.6 SAM")); + choices.insert(p_t(57, "Sony AF DT 50mm f/1.8 SAM")); + choices.insert(p_t(57, "Tamron SP AF 60mm f/2 Di II LD [IF] Macro 1:1")); + choices.insert(p_t(57, "Tamron 18-270mm f/3.5-6.3 Di II PZD")); + choices.insert(p_t(58, "Sony AF DT 30mm f/2.8 SAM Macro")); + choices.insert(p_t(59, "Sony AF 28-75mm f/2.8 SAM")); + choices.insert(p_t(60, "Carl Zeiss Distagon T* 24mm f/2 ZA SSM")); + choices.insert(p_t(61, "Sony AF 85mm f/2.8 SAM")); + choices.insert(p_t(62, "Sony DT 35mm f/1.8 SAM")); + choices.insert(p_t(63, "Sony DT 16-50mm f/2.8 SSM")); + choices.insert(p_t(64, "Sony 500mm f/4.0 G SSM")); + choices.insert(p_t(65, "Sony DT 18-135mm f/3.5-5.6 SAM")); + choices.insert(p_t(66, "Sony 300mm f/2.8 G SSM II")); + choices.insert(p_t(67, "Sony 70-20mm f/2.8 G SSM")); + choices.insert(p_t(68, "Sony DT 55-300mm f/4.5-5.6 SAM")); + choices.insert(p_t(69, "Sony 70-400mm f/4-5.6 G SSM II")); + choices.insert(p_t(70, "Carl Zeiss Planar T* 50mm f/1.4 ZA SSM")); + choices.insert(p_t(128, "Tamron AF 18-200mm f/3.5-6.3 XR Di II LD Aspherical (IF)")); + choices.insert(p_t(128, "Tamron AF 28-300mm f/3.5-6.3")); + choices.insert(p_t(128, "Tamron 80-300mm f/3.5-6.3")); + choices.insert(p_t(128, "Tamron AF 28-200mm f/3.8-5.6 XR Di Aspherical [IF] Macro")); + choices.insert(p_t(128, "Tamron SP AF 17-35mm f/2.8-4 Di LD Aspherical IF")); + choices.insert(p_t(128, "Sigma AF 50-150mm f/2.8 EX DC APO HSM II")); + choices.insert(p_t(128, "Sigma 10-20mm f/3.5 EX DC HSM")); + choices.insert(p_t(128, "Sigma 70-200mm f/2.8 II EX DG APO Macro HSM")); + choices.insert(p_t(128, "Sigma 10mm f/2.8 EX DC HSM Fisheye")); + choices.insert(p_t(128, "Sigma 35mm f/1.4 DG HSM")); + choices.insert(p_t(128, "Sigma 50mm f/1.4 EX DG HSM")); + choices.insert(p_t(128, "Sigma 85mm f/1.4 EX DG HSM")); + choices.insert(p_t(128, "Sigma 24-70mm f/2.8 IF EX DG HSM")); + choices.insert(p_t(128, "Sigma 18-250mm f/3.5-6.3 DC OS HSM")); + choices.insert(p_t(128, "Sigma 17-50mm f/2.8 EX DC HSM")); + choices.insert(p_t(128, "Sigma 17-70mm f/2.8-4 DC Macro HSM")); + choices.insert(p_t(129, "Tamron 200-400mm f/5.6 LD")); + choices.insert(p_t(129, "Tamron 70-300mm f/4-5.6 LD")); + choices.insert(p_t(131, "Tamron 20-40mm f/2.7-3.5 SP Aspherical IF")); + choices.insert(p_t(135, "Vivitar 28-210mm f/3.5-5.6")); + choices.insert(p_t(136, "Tokina EMZ M100 AF 100mm f/3.5")); + choices.insert(p_t(137, "Cosina 70-210mm f/2.8-4 AF")); + choices.insert(p_t(138, "Soligor 19-35mm f/3.5-4.5")); + choices.insert(p_t(142, "Voigtlander 70-300mm f/4.5-5.6")); + choices.insert(p_t(146, "Voigtlander Macro APO-Lanthar 125mm f/2.5 SL")); + choices.insert(p_t(255, "Tamron SP AF 17-50mm f/2.8 XR Di II LD Aspherical")); + choices.insert(p_t(255, "Tamron AF 18-250mm f/3.5-6.3 XR Di II LD")); + choices.insert(p_t(255, "Tamron AF 55-200mm f/4-5.6 Di II LD Macro")); + choices.insert(p_t(255, "Tamron AF 70-300mm f/4-5.6 Di LD Macro 1:2")); + choices.insert(p_t(255, "Tamron SP AF 200-500mm f/5.0-6.3 Di LD [IF]")); + choices.insert(p_t(255, "Tamron SP AF 10-24mm f/3.5-4.5 Di II LD Aspherical [IF]")); + choices.insert(p_t(255, "Tamron SP AF 70-200mm f/2.8 Di LD Macro [IF]")); + choices.insert(p_t(255, "Tamron SP AF 28-75mm f/2.8 XR Di LD Aspherical [IF]")); + choices.insert(p_t(2550, "Minolta AF 50mm f/1.7")); + choices.insert(p_t(2551, "Minolta AF 35-70mm f/4")); + choices.insert(p_t(2551, "Sigma UC AF 28-70mm f/3.5-4.5")); + choices.insert(p_t(2551, "Sigma AF 28-70mm f/2.8")); + choices.insert(p_t(2551, "Sigma M-AF 70-200mm f/2.8 EX Aspherical")); + choices.insert(p_t(2551, "Quantaray M-AF 35-80mm f/4-5.6")); + choices.insert(p_t(2552, "Minolta AF 28-85mm f/3.5-4.5 [New]")); + choices.insert(p_t(2552, "Tokina 19-35mm f/3.5-4.5")); + choices.insert(p_t(2552, "Tokina 28-70mm f/2.8 AT-X")); + choices.insert(p_t(2552, "Tokina 80-400mm f/4.5-5.6 AT-X AF II 840")); + choices.insert(p_t(2552, "Tokina AF PRO 28-80mm f/2.8 AT-X 280")); + choices.insert(p_t(2552, "Tokina AT-X PRO II AF 28-70mm f/2.6-2.8 270")); + choices.insert(p_t(2552, "Tamron AF 19-35mm f/3.5-4.5")); + choices.insert(p_t(2552, "Angenieux AF 28-70mm f/2.6")); + choices.insert(p_t(2553, "Minolta AF 28-135mm f/4-4.5")); + choices.insert(p_t(2553, "Sigma ZOOM-alpha 35-135mm f/3.5-4.5")); + choices.insert(p_t(2553, "Sigma 28-105mm f/2.8-4 Aspherical")); + choices.insert(p_t(2554, "Minolta AF 35-105mm f/3.5-4.5")); + choices.insert(p_t(2555, "Minolta AF 70-210mm f/4 Macro")); + choices.insert(p_t(2555, "Sigma 70-210mm f/4-5.6 APO")); + choices.insert(p_t(2555, "Sigma M-AF 70-200mm f/2.8 EX APO")); + choices.insert(p_t(2555, "Sigma 75-200mm f/2.8-3.5")); + choices.insert(p_t(2556, "Minolta AF 135mm f/2.8")); + choices.insert(p_t(2557, "Minolta AF 28mm f/2.8")); + choices.insert(p_t(2558, "Minolta AF 24-50mm f/4")); + choices.insert(p_t(2560, "Minolta AF 100-200mm f/4.5")); + choices.insert(p_t(2561, "Minolta AF 75-300mm f/4.5-5.6")); + choices.insert(p_t(2561, "Sigma 70-300mm f/4-5.6 DL Macro")); + choices.insert(p_t(2561, "Sigma 300mm f/4 APO Macro")); + choices.insert(p_t(2561, "Sigma AF 500mm f/4.5 APO")); + choices.insert(p_t(2561, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); + choices.insert(p_t(2561, "Tokina AT-X AF 300mm f/4")); + choices.insert(p_t(2561, "Tokina AT-X AF 400mm f/5.6 SD")); + choices.insert(p_t(2561, "Tokina AF 730 II 75-300mm f/4.5-5.6")); + choices.insert(p_t(2562, "Minolta/Sony AF 50mm f/1.4 [New]")); + choices.insert(p_t(2563, "Minolta AF 300mm f/2.8 G")); + choices.insert(p_t(2563, "Sigma AF 50-500mm f/4-6.3 EX DG APO")); + choices.insert(p_t(2563, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); + choices.insert(p_t(2563, "Sigma AF 500mm f/4.5 EX DG APO")); + choices.insert(p_t(2563, "Sigma 400mm f/5.6 APO")); + choices.insert(p_t(2564, "Minolta AF 50mm f/2.8 Macro")); + choices.insert(p_t(2564, "Sigma 50mm f/2.8 EX Macro")); + choices.insert(p_t(2565, "Minolta AF 600mm f/4")); + choices.insert(p_t(2566, "Minolta AF 24mm f/2.8")); + choices.insert(p_t(2572, "Minolta/Sony AF 500mm f/8 Reflex")); + choices.insert(p_t(2578, "Minolta AF 16mm f/2.8 Fisheye")); + choices.insert(p_t(2578, "Sigma 8mm f/4 EX DG Fisheye")); + choices.insert(p_t(2578, "Sigma 14mm f/3.5")); + choices.insert(p_t(2578, "Sigma 15mm f/2.8 Fisheye")); + choices.insert(p_t(2579, "Minolta AF 20mm f/2.8")); + choices.insert(p_t(2581, "Minolta/Sony AF 100mm f/2.8 Macro")); + choices.insert(p_t(2581, "Sigma AF 90mm f/2.8 Macro")); + choices.insert(p_t(2581, "Sigma AF 105mm f/2.8 EX DG Macro")); + choices.insert(p_t(2581, "Sigma 180mm f/5.6 Macro")); + choices.insert(p_t(2581, "Tamron AF 90mm f/2.8 Macro")); + choices.insert(p_t(2585, "Minolta AF 35-105mm f/3.5-4.5 New")); + choices.insert(p_t(2585, "Beroflex 35-135mm f/3.5-4.5")); + choices.insert(p_t(2585, "Tamron AF 24-135mm f/3.5-5.6")); + choices.insert(p_t(2588, "Minolta AF 70-210mm f/3.5-4.5")); + choices.insert(p_t(2589, "Minolta AF 80-200 f/2.8 APO")); + choices.insert(p_t(2589, "Tokina 80-200mm f/2.8")); + choices.insert(p_t(2591, "Minolta AF 35mm f/1.4")); + choices.insert(p_t(2592, "Minolta AF 85mm f/1.4 G (D)")); + choices.insert(p_t(2593, "Minolta AF 200mm f/2.8 G APO")); + choices.insert(p_t(2594, "Minolta AF 3x-1x f/1.7-2.8 Macro")); + choices.insert(p_t(2596, "Minolta AF 28mm f/2")); + choices.insert(p_t(2597, "Minolta AF 35mm f/2")); + choices.insert(p_t(2598, "Minolta AF 100mm f/2")); + choices.insert(p_t(2604, "Minolta AF 80-200mm f/4.5-5.6")); + choices.insert(p_t(2605, "Minolta AF 35-80mm f/4-5.6")); + choices.insert(p_t(2606, "Minolta AF 100-300mm f/4.5-5.6 (D)")); + choices.insert(p_t(2607, "Minolta AF 35-80mm f/4-5.6")); + choices.insert(p_t(2608, "Minolta AF 300mm f/2.8 G")); + choices.insert(p_t(2609, "Minolta AF 600mm f/4 HS-APO G")); + choices.insert(p_t(2612, "Minolta AF 200mm f/2.8 G HS-APO")); + choices.insert(p_t(2613, "Minolta AF 50mm f/1.7 New")); + choices.insert(p_t(2615, "Minolta AF 28-105mm f/3.5-4.5 Power Zoom")); + choices.insert(p_t(2616, "Minolta AF 35-200mm f/4.5-5.6 Power Zoom")); + choices.insert(p_t(2618, "Minolta AF 28-80mm f/4-5.6 Power Zoom")); + choices.insert(p_t(2619, "Minolta AF 80-200mm f/4.5-5.6 Power Zoom")); + choices.insert(p_t(2620, "Minolta AF 28-70mm f/2.8 G")); + choices.insert(p_t(2621, "Minolta AF 100-300mm f/4.5-5.6 Power Zoom")); + choices.insert(p_t(2624, "Minolta AF 35-80mm f/4-5.6 Power Zoom")); + choices.insert(p_t(2628, "Minolta AF 80-200mm f/2.8 G")); + choices.insert(p_t(2629, "Minolta AF 85mm f/1.4 New")); + choices.insert(p_t(2631, "Minolta/Sony AF 100-300mm f/4.5-5.6 APO")); + choices.insert(p_t(2632, "Minolta AF 24-50mm f/4 New")); + choices.insert(p_t(2638, "Minolta AF 50mm f/2.8 Macro New")); + choices.insert(p_t(2639, "Minolta AF 100mm f/2.8 Macro")); + choices.insert(p_t(2641, "Minolta AF 20mm f/2.8 New")); + choices.insert(p_t(2642, "Minolta AF 24mm f/2.8 New")); + choices.insert(p_t(2644, "Minolta AF 100-400mm f/4.5-6.7 APO")); + choices.insert(p_t(2662, "Minolta AF 50mm f/1.4 New")); + choices.insert(p_t(2667, "Minolta AF 35mm f/2 New")); + choices.insert(p_t(2668, "Minolta AF 28mm f/2 New")); + choices.insert(p_t(2672, "Minolta AF 24-105mm f/3.5-4.5 (D)")); + choices.insert(p_t(4574, "Minolta AF 200mm f/2.8 G x2")); + choices.insert(p_t(4575, "1.4 x Teleconverter")); + choices.insert(p_t(4585, "Tamron SP AF 300mm f/2.8 LD IF")); + choices.insert(p_t(6553, "Arax MC 35mm f/2.8 Tilt+Shift")); + choices.insert(p_t(6553, "Arax MC 80mm f/2.8 Tilt+Shift")); + choices.insert(p_t(6553, "Zenitar MF 16mm f/2.8 Fisheye M42")); + choices.insert(p_t(6553, "Samyang 500mm Mirror f/8")); + choices.insert(p_t(6553, "Pentacon Auto 135mm f/2.8")); + choices.insert(p_t(6553, "Pentacon Auto 29mm f/2.8")); + choices.insert(p_t(6553, "Helios 44-2 58mm f/2")); + choices.insert(p_t(25501, "Minolta AF 50mm f/1.7")); + choices.insert(p_t(25511, "Minolta AF 35-70mm f/4")); + choices.insert(p_t(25511, "Sigma UC AF 28-70mm f/3.5-4.5")); + choices.insert(p_t(25511, "Sigma AF 28-70mm f/2.8")); + choices.insert(p_t(25511, "Sigma M-AF 70-200mm f/2.8 EX Aspherical")); + choices.insert(p_t(25511, "Quantaray M-AF 35-80mm f/4-5.6")); + choices.insert(p_t(25521, "Minolta AF 28-85mm f/3.5-4.5")); + choices.insert(p_t(25521, "Tokina 19-35mm f/3.5-4.5")); + choices.insert(p_t(25521, "Tokina 28-70mm f/2.8 AT-X")); + choices.insert(p_t(25521, "Tokina 80-400mm f/4.5-5.6 AT-X AF II 840")); + choices.insert(p_t(25521, "Tokina AF PRO 28-80mm f/2.8 AT-X 280")); + choices.insert(p_t(25521, "Tokina AT-X PRO II AF 28-70mm f/2.6-2.8 270")); + choices.insert(p_t(25521, "Tamron AF 19-35mm f/3.5-4.5")); + choices.insert(p_t(25521, "Angenieux AF 28-70mm f/2.6")); + choices.insert(p_t(25521, "Tokina AT-X 17 AF 17mm f/3.5")); + choices.insert(p_t(25531, "Minolta AF 28-135mm f/4-4.5")); + choices.insert(p_t(25531, "Sigma ZOOM-alpha 35-135mm f/3.5-4.5")); + choices.insert(p_t(25531, "Sigma 28-105mm f/2.8-4 Aspherical")); + choices.insert(p_t(25531, "Sigma 28-105mm f/4-5.6 UC")); + choices.insert(p_t(25541, "Minolta AF 35-105mm f/3.5-4.5")); + choices.insert(p_t(25551, "Minolta AF 70-210mm f/4 Macro")); + choices.insert(p_t(25551, "Sigma 70-210mm f/4-5.6 APO")); + choices.insert(p_t(25551, "Sigma M-AF 70-200mm f/2.8 EX APO")); + choices.insert(p_t(25551, "Sigma 75-200mm f/2.8-3.5")); + choices.insert(p_t(25561, "Minolta AF 135mm f/2.8")); + choices.insert(p_t(25571, "Minolta/Sony AF 28mm f/2.8")); + choices.insert(p_t(25581, "Minolta AF 24-50mm f/4")); + choices.insert(p_t(25601, "Minolta AF 100-200mm f/4.5")); + choices.insert(p_t(25611, "Minolta AF 75-300mm f/4.5-5.6")); + choices.insert(p_t(25611, "Sigma 70-300mm f/4-5.6 DL Macro")); + choices.insert(p_t(25611, "Sigma 300mm f/4 APO Macro")); + choices.insert(p_t(25611, "Sigma AF 500mm f/4.5 APO")); + choices.insert(p_t(25611, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); + choices.insert(p_t(25611, "Tokina AT-X AF 300mm f/4")); + choices.insert(p_t(25611, "Tokina AT-X AF 400mm f/5.6 SD")); + choices.insert(p_t(25611, "Tokina AF 730 II 75-300mm f/4.5-5.6")); + choices.insert(p_t(25611, "Sigma 800mm f/5.6 APO")); + choices.insert(p_t(25611, "Sigma AF 400mm f/5.6 APO Macro")); + choices.insert(p_t(25621, "Minolta AF 50mm f/1.4")); + choices.insert(p_t(25631, "Minolta AF 300mm f/2.8 APO")); + choices.insert(p_t(25631, "Sigma AF 50-500mm f/4-6.3 EX DG APO")); + choices.insert(p_t(25631, "Sigma AF 170-500mm f/5-6.3 APO Aspherical")); + choices.insert(p_t(25631, "Sigma AF 500mm f/4.5 EX DG APO")); + choices.insert(p_t(25631, "Sigma 400mm f/5.6 APO")); + choices.insert(p_t(25641, "Minolta AF 50mm f/2.8 Macro")); + choices.insert(p_t(25641, "Sigma AF 50mm f/2.8 EX Macro")); + choices.insert(p_t(25651, "Minolta AF 600mm f/4")); + choices.insert(p_t(25661, "Minolta AF 24mm f/2.8")); + choices.insert(p_t(25661, "Sigma 17-35mm f/2.8-4 EX Aspherical")); + choices.insert(p_t(25721, "Minolta/Sony AF 500mm f/8 Reflex")); + choices.insert(p_t(25781, "Minolta/Sony AF 16mm f/2.8 Fisheye")); + choices.insert(p_t(25781, "Sigma 8mm f/4 EX DG Fisheye")); + choices.insert(p_t(25781, "Sigma 14mm f/3.5")); + choices.insert(p_t(25781, "Sigma 15mm f/2.8 Fisheye")); + choices.insert(p_t(25791, "Minolta/Sony AF 20mm f/2.8")); + choices.insert(p_t(25791, "Tokina AT-X Pro DX 11-16mm f/2.8")); + choices.insert(p_t(25811, "Minolta/Sony AF 100mm f/2.8 Macro")); + choices.insert(p_t(25811, "Sigma AF 90mm f/2.8 Macro")); + choices.insert(p_t(25811, "Sigma AF 105mm f/2.8 EX DG Macro")); + choices.insert(p_t(25811, "Sigma 180mm f/5.6 Macro")); + choices.insert(p_t(25811, "Sigma 180mm f/3.5 EX DG Macro")); + choices.insert(p_t(25811, "Tamron 90mm f/2.8 Macro")); + choices.insert(p_t(25851, "Beroflex 35-135mm f/3.5-4.5")); + choices.insert(p_t(25858, "Minolta AF 35-105mm f/3.5-4.5")); + choices.insert(p_t(25858, "Tamron 24-135mm f/3.5-5.6")); + choices.insert(p_t(25881, "Minolta AF 70-210mm f/3.5-4.5")); + choices.insert(p_t(25891, "Minolta AF 80-200mm f/2.8 APO")); + choices.insert(p_t(25891, "Tokina 80-200mm f/2.8")); + choices.insert(p_t(25901, "Minolta AF 200mm f/2.8 G APO + Minolta AF 1.4x APO")); + choices.insert(p_t(25901, "Minolta AF 600mm f/4 HS-APO G + Minolta AF 1.4x APO")); + choices.insert(p_t(25911, "Minolta AF 35mm f/1.4")); + choices.insert(p_t(25921, "Minolta AF 85mm f/1.4 G (D)")); + choices.insert(p_t(25931, "Minolta AF 200mm f/2.8 G APO")); + choices.insert(p_t(25941, "Minolta AF 3x-1x f/1.7-2.8 Macro")); + choices.insert(p_t(25961, "Minolta AF 28mm f/2")); + choices.insert(p_t(25971, "Minolta AF 35mm f/2")); + choices.insert(p_t(25981, "Minolta AF 100mm f/2")); + choices.insert(p_t(26011, "Minolta AF 200mm f/2.8 G APO + Minolta AF 2x APO")); + choices.insert(p_t(26011, "Minolta AF 600mm f/4 HS-APO G + Minolta AF 2x APO")); + choices.insert(p_t(26041, "Minolta AF 80-200mm f/4.5-5.6")); + choices.insert(p_t(26051, "Minolta AF 35-80mm f/4-5.6")); + choices.insert(p_t(26061, "Minolta AF 100-300mm f/4.5-5.6")); + choices.insert(p_t(26071, "Minolta AF 35-80mm f/4-5.6")); + choices.insert(p_t(26081, "Minolta AF 300mm f/2.8 HS-APO G")); + choices.insert(p_t(26091, "Minolta AF 600mm f/4 HS-APO G")); + choices.insert(p_t(26121, "Minolta AF 200mm f/2.8 HS-APO G")); + choices.insert(p_t(26131, "Minolta AF 50mm f/1.7 New")); + choices.insert(p_t(26151, "Minolta AF 28-105mm f/3.5-4.5 xi")); + choices.insert(p_t(26161, "Minolta AF 35-200mm f/4.5-5.6 xi")); + choices.insert(p_t(26181, "Minolta AF 28-80mm f/4-5.6 xi")); + choices.insert(p_t(26191, "Minolta AF 80-200mm f/4.5-5.6 xi")); + choices.insert(p_t(26201, "Minolta AF 28-70mm f/2.8 G")); + choices.insert(p_t(26211, "Minolta AF 100-300mm f/4.5-5.6 xi")); + choices.insert(p_t(26241, "Minolta AF 35-80mm f/4-5.6 Power Zoom")); + choices.insert(p_t(26281, "Minolta AF 80-200mm f/2.8 G")); + choices.insert(p_t(26291, "Minolta AF 85mm f/1.4 New")); + choices.insert(p_t(26311, "Minolta/Sony AF 100-300mm f/4.5-5.6 APO")); + choices.insert(p_t(26321, "Minolta AF 24-50mm f/4 New")); + choices.insert(p_t(26381, "Minolta AF 50mm f/2.8 Macro New")); + choices.insert(p_t(26391, "Minolta AF 100mm f/2.8 Macro")); + choices.insert(p_t(26411, "Minolta/Sony AF 20mm f/2.8 New")); + choices.insert(p_t(26421, "Minolta AF 24mm f/2.8 New")); + choices.insert(p_t(26441, "Minolta AF 100-400mm f/4.5-6.7 APO")); + choices.insert(p_t(26621, "Minolta AF 50mm f/1.4 New")); + choices.insert(p_t(26671, "Minolta AF 35mm f/2 New")); + choices.insert(p_t(26681, "Minolta AF 28mm f/2 New")); + choices.insert(p_t(26721, "Minolta AF 24-105mm f/3.5-4.5 (D)")); + choices.insert(p_t(45671, "Tokina 70-210mm f/4-5.6")); + choices.insert(p_t(45741, "Tamron SP AF 90mm f/2.5")); + choices.insert(p_t(45741, "Tokina RF 500mm f/8.0 x2")); + choices.insert(p_t(45741, "Tokina 300mm f/2.8 x2")); + choices.insert(p_t(45741, "Minolta AF 200mm f/2.8 G x2")); + choices.insert(p_t(45851, "Tamron SP AF 300mm f/2.8 LD IF")); + choices.insert(p_t(45871, "Tamron AF 70-210mm f/2.8 SP LD")); + choices.insert(p_t(65535, "Sony E 16mm f/2.8")); + choices.insert(p_t(65535, "Sony E 18-55mm f/3.5-5.6 OSS")); + choices.insert(p_t(65535, "Sony E 55-210mm f/4.5-6.3 OSS")); + choices.insert(p_t(65535, "Sony E 18-200mm f/3.5-6.3 OSS")); + choices.insert(p_t(65535, "Sony E 30mm f/3.5 Macro")); + choices.insert(p_t(65535, "Sony E 24mm f/1.8 ZA")); + choices.insert(p_t(65535, "Sony E 50mm f/1.8 OSS")); + choices.insert(p_t(65535, "Sony E 16-70mm f/4 ZA OSS")); + choices.insert(p_t(65535, "Sony E 10-18mm f/4 OSS")); + choices.insert(p_t(65535, "Sony E PZ 16-50mm f/3.5-5.6 OSS")); + choices.insert(p_t(65535, "Sony FE 35mm f/2.8 ZA")); + choices.insert(p_t(65535, "Sony FE 24-70mm f/4 ZA OSS")); + choices.insert(p_t(65535, "Sony E 18-200mm f/3.5-6.3 OSS LE")); + choices.insert(p_t(65535, "Sony E 20mm f/2.8")); + choices.insert(p_t(65535, "Sony E 35mm f/1.8 OSS")); + choices.insert(p_t(65535, "Sony E PZ 18-200mm f/3.5-6.3 OSS")); + choices.insert(p_t(65535, "Sony FE 55mm f/1.8 ZA")); + choices.insert(p_t(65535, "Sony FE 28-70mm f/3.5-5.6 OSS")); + choices.insert(p_t(65535, "Sony E PZ 18-105mm f/4 G OSS")); + choices.insert(p_t(65535, "Sony FE 70-200mm f/4 G OSS")); + choices.insert(p_t(65535, "Sigma 19mm f/2.8 [EX] DN")); + choices.insert(p_t(65535, "Sigma 30mm f/2.8 [EX] DN")); + choices.insert(p_t(65535, "Sigma 60mm f/2.8 DN")); + choices.insert(p_t(65535, "Tamron 18-200mm f/3.5-6.3 Di III VC")); + choices.insert(p_t(65535, "Zeiss Touit 12mm f/2.8")); + choices.insert(p_t(65535, "Zeiss Touit 32mm f/1.8")); + choices.insert(p_t(65535, "Arax MC 35mm f/2.8 Tilt+Shift")); + choices.insert(p_t(65535, "Arax MC 80mm f/2.8 Tilt+Shift")); + choices.insert(p_t(65535, "Zenitar MF 16mm f/2.8 Fisheye M42")); + choices.insert(p_t(65535, "Samyang 500mm f/8 Mirror")); + choices.insert(p_t(65535, "Pentacon Auto 135mm f/2.8")); + choices.insert(p_t(65535, "Pentacon Auto 29mm f/2.8")); + choices.insert(p_t(65535, "Helios 44-2 58mm f/2")); + } + + virtual std::string toString (Tag* t) + { + int lensID = t->toInt(); + Tag *lensInfoTag = t->getParent()->getRoot()->findTag("LensInfo"); + Tag *apertureTag = t->getParent()->getRoot()->findTag("MaxApertureValue"); + Tag *focalLengthTag = t->getParent()->getRoot()->findTag("FocalLength"); + double maxApertureAtFocal = 0.; + double focalLength = 0.; + + if( apertureTag ) { + maxApertureAtFocal = pow(2.0, apertureTag->toDouble() / 2.0); } - virtual std::string toString (Tag* t) - { - int lensID = t->toInt(); - Tag *lensInfoTag = t->getParent()->getRoot()->findTag("LensInfo"); - Tag *apertureTag = t->getParent()->getRoot()->findTag("MaxApertureValue"); - Tag *focalLengthTag = t->getParent()->getRoot()->findTag("FocalLength"); - double maxApertureAtFocal = 0.; - double focalLength = 0.; - if( apertureTag ) - maxApertureAtFocal = pow(2.0, apertureTag->toDouble()/2.0); - if( focalLengthTag ) - focalLength = focalLengthTag->toDouble(); - double *liArray = NULL; - if (lensInfoTag) - liArray = lensInfoTag->toDoubleArray(); - std::string retval = guess( lensID, focalLength, maxApertureAtFocal, liArray); - if(liArray) - delete [] liArray; - return retval; + if( focalLengthTag ) { + focalLength = focalLengthTag->toDouble(); } + + double *liArray = NULL; + + if (lensInfoTag) { + liArray = lensInfoTag->toDoubleArray(); + } + + std::string retval = guess( lensID, focalLength, maxApertureAtFocal, liArray); + + if(liArray) { + delete [] liArray; + } + + return retval; + } }; SALensIDInterpreter saLensIDInterpreter; -class SALensID2Interpreter : public IntLensInterpreter< int > { - public: - SALensID2Interpreter () { // From EXIFTOOL database 'Sony.pm' V1.94 and 'Minolta' 2.04; - // Please do not remove entries on database synchronization, and avoid transferring "categories' header" types - choices.insert(p_t(00000, "Unknown E-Mount lens or other lens")); - choices.insert(p_t(00001, "Sony LA-EA1 Adapter")); - choices.insert(p_t(00002, "Sony LA-EA2 Adapter")); - choices.insert(p_t(00006, "Sony LA-EA4 Adapter")); - choices.insert(p_t(32784, "Sony E 16mm f/2.8")); - choices.insert(p_t(32785, "Sony E 18-55mm f/3.5-5.6 OSS")); - choices.insert(p_t(32786, "Sony E 55-210mm f/4.5-6.3 OSS")); - choices.insert(p_t(32787, "Sony E 18-200mm f/3.5-6.3 OSS")); - choices.insert(p_t(32788, "Sony E 30mm f/3.5 Macro")); - choices.insert(p_t(32789, "Sony E 24mm f/1.8 ZA")); - choices.insert(p_t(32790, "Sony E 50mm f/1.8 OSS")); - choices.insert(p_t(32791, "Sony E 16-70mm f/4 ZA OSS")); - choices.insert(p_t(32792, "Sony E 10-18mm f/4 OSS")); - choices.insert(p_t(32793, "Sony E PZ 16-50mm f/3.5-5.6 OSS")); - choices.insert(p_t(32794, "Sony FE 35mm f/2.8 ZA")); - choices.insert(p_t(32795, "Sony FE 24-70mm f/4 ZA OSS")); - choices.insert(p_t(32797, "Sony E 18-200mm f/3.5-6.3 OSS LE")); - choices.insert(p_t(32798, "Sony E 20mm f/2.8")); - choices.insert(p_t(32799, "Sony E 35mm f/1.8 OSS")); - choices.insert(p_t(32807, "Sony E PZ 18-200mm f/3.5-6.3 OSS")); - choices.insert(p_t(32808, "Sony FE 55mm f/1.8 ZA")); - choices.insert(p_t(32813, "Sony FE 28-70mm f/3.5-5.6 OSS")); +class SALensID2Interpreter : public IntLensInterpreter< int > +{ +public: + SALensID2Interpreter () // From EXIFTOOL database 'Sony.pm' V1.94 and 'Minolta' 2.04; + { + // Please do not remove entries on database synchronization, and avoid transferring "categories' header" types + choices.insert(p_t(00000, "Unknown E-Mount lens or other lens")); + choices.insert(p_t(00001, "Sony LA-EA1 Adapter")); + choices.insert(p_t(00002, "Sony LA-EA2 Adapter")); + choices.insert(p_t(00006, "Sony LA-EA4 Adapter")); + choices.insert(p_t(32784, "Sony E 16mm f/2.8")); + choices.insert(p_t(32785, "Sony E 18-55mm f/3.5-5.6 OSS")); + choices.insert(p_t(32786, "Sony E 55-210mm f/4.5-6.3 OSS")); + choices.insert(p_t(32787, "Sony E 18-200mm f/3.5-6.3 OSS")); + choices.insert(p_t(32788, "Sony E 30mm f/3.5 Macro")); + choices.insert(p_t(32789, "Sony E 24mm f/1.8 ZA")); + choices.insert(p_t(32790, "Sony E 50mm f/1.8 OSS")); + choices.insert(p_t(32791, "Sony E 16-70mm f/4 ZA OSS")); + choices.insert(p_t(32792, "Sony E 10-18mm f/4 OSS")); + choices.insert(p_t(32793, "Sony E PZ 16-50mm f/3.5-5.6 OSS")); + choices.insert(p_t(32794, "Sony FE 35mm f/2.8 ZA")); + choices.insert(p_t(32795, "Sony FE 24-70mm f/4 ZA OSS")); + choices.insert(p_t(32797, "Sony E 18-200mm f/3.5-6.3 OSS LE")); + choices.insert(p_t(32798, "Sony E 20mm f/2.8")); + choices.insert(p_t(32799, "Sony E 35mm f/1.8 OSS")); + choices.insert(p_t(32807, "Sony E PZ 18-200mm f/3.5-6.3 OSS")); + choices.insert(p_t(32808, "Sony FE 55mm f/1.8 ZA")); + choices.insert(p_t(32813, "Sony FE 28-70mm f/3.5-5.6 OSS")); + } + + virtual std::string toString (Tag* t) + { + int lensID = t->toInt(); + Tag *lensInfoTag = t->getParent()->getRoot()->findTag("LensInfo"); + Tag *apertureTag = t->getParent()->getRoot()->findTag("MaxApertureValue"); + Tag *focalLengthTag = t->getParent()->getRoot()->findTag("FocalLength"); + double maxApertureAtFocal = 0.; + double focalLength = 0.; + + if( apertureTag ) { + maxApertureAtFocal = pow(2.0, apertureTag->toDouble() / 2.0); } - virtual std::string toString (Tag* t) - { - int lensID = t->toInt(); - Tag *lensInfoTag = t->getParent()->getRoot()->findTag("LensInfo"); - Tag *apertureTag = t->getParent()->getRoot()->findTag("MaxApertureValue"); - Tag *focalLengthTag = t->getParent()->getRoot()->findTag("FocalLength"); - double maxApertureAtFocal = 0.; - double focalLength = 0.; - if( apertureTag ) - maxApertureAtFocal = pow(2.0, apertureTag->toDouble()/2.0); - if( focalLengthTag ) - focalLength = focalLengthTag->toDouble(); - double *liArray = NULL; - if (lensInfoTag) - liArray = lensInfoTag->toDoubleArray(); - std::string retval = guess( lensID, focalLength, maxApertureAtFocal, liArray); - if(liArray) - delete [] liArray; - return retval; + if( focalLengthTag ) { + focalLength = focalLengthTag->toDouble(); } + + double *liArray = NULL; + + if (lensInfoTag) { + liArray = lensInfoTag->toDoubleArray(); + } + + std::string retval = guess( lensID, focalLength, maxApertureAtFocal, liArray); + + if(liArray) { + delete [] liArray; + } + + return retval; + } }; SALensID2Interpreter saLensID2Interpreter; -class MATeleconverterInterpreter : public ChoiceInterpreter { - public: - MATeleconverterInterpreter () { - choices[0] = "None "; - choices[0x48] = "Minolta AF 2x APO (D)"; - choices[0x50] = "Minolta AF 2x APO II"; - choices[0x88] = "Minolta AF 1.4x APO (D)"; - choices[0x90] = "Minolta AF 1.4x APO II"; - } +class MATeleconverterInterpreter : public ChoiceInterpreter +{ +public: + MATeleconverterInterpreter () + { + choices[0] = "None "; + choices[0x48] = "Minolta AF 2x APO (D)"; + choices[0x50] = "Minolta AF 2x APO II"; + choices[0x88] = "Minolta AF 1.4x APO (D)"; + choices[0x90] = "Minolta AF 1.4x APO II"; + } }; MATeleconverterInterpreter maTeleconverterInterpreter; -class MAQualityInterpreter : public ChoiceInterpreter { - public: - MAQualityInterpreter () { - choices[0] = "Raw"; - choices[1] = "Super Fine"; - choices[2] = "Fine"; - choices[3] = "Standard"; - choices[4] = "Economy"; - choices[5] = "Extra fine"; - choices[6] = "RAW + JPEG"; - choices[7] = "cRAW"; - choices[8] = "cRAW + JPEG"; - } +class MAQualityInterpreter : public ChoiceInterpreter +{ +public: + MAQualityInterpreter () + { + choices[0] = "Raw"; + choices[1] = "Super Fine"; + choices[2] = "Fine"; + choices[3] = "Standard"; + choices[4] = "Economy"; + choices[5] = "Extra fine"; + choices[6] = "RAW + JPEG"; + choices[7] = "cRAW"; + choices[8] = "cRAW + JPEG"; + } }; MAQualityInterpreter maQualityInterpreter; -class MAImageSizeInterpreter : public ChoiceInterpreter { - public: - MAImageSizeInterpreter () { - choices[1] = "1600x1200"; - choices[2] = "1280x960"; - choices[3] = "640x480"; - choices[5] = "2560x1920"; - choices[6] = "2272x1704"; - choices[7] = "2048x1536"; - } +class MAImageSizeInterpreter : public ChoiceInterpreter +{ +public: + MAImageSizeInterpreter () + { + choices[1] = "1600x1200"; + choices[2] = "1280x960"; + choices[3] = "640x480"; + choices[5] = "2560x1920"; + choices[6] = "2272x1704"; + choices[7] = "2048x1536"; + } }; MAImageSizeInterpreter maImageSizeInterpreter; -class SAQualityInterpreter2 : public ChoiceInterpreter { - public: - SAQualityInterpreter2 () { - choices[0] = "Raw"; - choices[2] = "cRAW"; - choices[16] = "Extra fine"; - choices[32] = "Fine"; - choices[34] = "RAW + JPEG"; - choices[35] = "cRAW + JPEG"; - choices[48] = "Standard"; - } +class SAQualityInterpreter2 : public ChoiceInterpreter +{ +public: + SAQualityInterpreter2 () + { + choices[0] = "Raw"; + choices[2] = "cRAW"; + choices[16] = "Extra fine"; + choices[32] = "Fine"; + choices[34] = "RAW + JPEG"; + choices[35] = "cRAW + JPEG"; + choices[48] = "Standard"; + } }; SAQualityInterpreter2 saQualityInterpreter2; -class SAQualityInterpreter3 : public ChoiceInterpreter { - public: - SAQualityInterpreter3 () { - choices[2] = "RAW"; - choices[4] = "RAW + JPEG"; - choices[6] = "Fine"; - choices[7] = "Standard"; - } +class SAQualityInterpreter3 : public ChoiceInterpreter +{ +public: + SAQualityInterpreter3 () + { + choices[2] = "RAW"; + choices[4] = "RAW + JPEG"; + choices[6] = "Fine"; + choices[7] = "Standard"; + } }; SAQualityInterpreter3 saQualityInterpreter3; -class SADriveMode : public ChoiceInterpreter { - public: - SADriveMode () { - choices[0] = "Single Frame"; - choices[1] = "Continuous High"; - choices[4] = "Self-timer 10 sec"; - choices[5] = "Self-timer 2 sec"; - choices[7] = "Continuous Bracketing"; - choices[12] = "Continuous Low"; - choices[18] = "White Balance Bracketing Low"; - choices[19] = "D-Range Optimizer Bracketing Low"; - } +class SADriveMode : public ChoiceInterpreter +{ +public: + SADriveMode () + { + choices[0] = "Single Frame"; + choices[1] = "Continuous High"; + choices[4] = "Self-timer 10 sec"; + choices[5] = "Self-timer 2 sec"; + choices[7] = "Continuous Bracketing"; + choices[12] = "Continuous Low"; + choices[18] = "White Balance Bracketing Low"; + choices[19] = "D-Range Optimizer Bracketing Low"; + } }; SADriveMode saDriveMode; -class SADriveMode2 : public ChoiceInterpreter { - public: - SADriveMode2 () { - choices[0] = "Single Frame"; - choices[2] = "Continuous High"; - choices[4] = "Self-timer 10 sec"; - choices[5] = "Self-timer 2 sec, Mirror Lock-up"; - choices[7] = "Continuous Bracketing"; - choices[10] = "Remote Commander"; - choices[11] = "Continuous Self-timer"; - } +class SADriveMode2 : public ChoiceInterpreter +{ +public: + SADriveMode2 () + { + choices[0] = "Single Frame"; + choices[2] = "Continuous High"; + choices[4] = "Self-timer 10 sec"; + choices[5] = "Self-timer 2 sec, Mirror Lock-up"; + choices[7] = "Continuous Bracketing"; + choices[10] = "Remote Commander"; + choices[11] = "Continuous Self-timer"; + } }; SADriveMode2 saDriveMode2; -class SADriveMode3 : public ChoiceInterpreter { - public: - SADriveMode3 () { - choices[0x10] = "Single Frame"; - choices[0x21] = "Continuous High"; - choices[0x22] = "Continuous Low"; - choices[0x30] = "Speed Priority Continuous"; - choices[0x51] = "Self-timer 10 sec"; - choices[0x52] = "Self-timer 2 sec, Mirror Lock-up"; - choices[0x71] = "Continuous Bracketing 0.3 EV"; - choices[0x75] = "Continuous Bracketing 0.7 EV"; - choices[0x91] = "White Balance Bracketing Low"; - choices[0x92] = "White Balance Bracketing High"; - choices[0xC0] = "Remote Commander"; - choices[0xD1] = "Continuous - HDR"; - choices[0xD2] = "Continuous - Multi Frame NR"; - choices[0xD3] = "Continuous - Handheld Night Shot"; - choices[0xD4] = "Continuous - Anti Motion Blur"; - choices[0xD5] = "Continuous - Sweep Panorama"; - choices[0xD6] = "Continuous - 3D Sweep Panorama"; - } +class SADriveMode3 : public ChoiceInterpreter +{ +public: + SADriveMode3 () + { + choices[0x10] = "Single Frame"; + choices[0x21] = "Continuous High"; + choices[0x22] = "Continuous Low"; + choices[0x30] = "Speed Priority Continuous"; + choices[0x51] = "Self-timer 10 sec"; + choices[0x52] = "Self-timer 2 sec, Mirror Lock-up"; + choices[0x71] = "Continuous Bracketing 0.3 EV"; + choices[0x75] = "Continuous Bracketing 0.7 EV"; + choices[0x91] = "White Balance Bracketing Low"; + choices[0x92] = "White Balance Bracketing High"; + choices[0xC0] = "Remote Commander"; + choices[0xD1] = "Continuous - HDR"; + choices[0xD2] = "Continuous - Multi Frame NR"; + choices[0xD3] = "Continuous - Handheld Night Shot"; + choices[0xD4] = "Continuous - Anti Motion Blur"; + choices[0xD5] = "Continuous - Sweep Panorama"; + choices[0xD6] = "Continuous - 3D Sweep Panorama"; + } }; SADriveMode3 saDriveMode3; -class SAFocusMode: public ChoiceInterpreter { - public: - SAFocusMode () { +class SAFocusMode: public ChoiceInterpreter +{ +public: + SAFocusMode () + { choices[0] = "Manual"; choices[1] = "AF-S"; choices[2] = "AF-C"; @@ -1053,9 +1160,11 @@ class SAFocusMode: public ChoiceInterpreter { }; SAFocusMode saFocusMode; -class SAFocusMode2: public ChoiceInterpreter { - public: - SAFocusMode2 () { +class SAFocusMode2: public ChoiceInterpreter +{ +public: + SAFocusMode2 () + { choices[0] = "Manual"; choices[1] = "AF-S"; choices[2] = "AF-C"; @@ -1065,9 +1174,11 @@ class SAFocusMode2: public ChoiceInterpreter { }; SAFocusMode2 saFocusMode2; -class SAFocusModeSetting3: public ChoiceInterpreter { - public: - SAFocusModeSetting3 () { +class SAFocusModeSetting3: public ChoiceInterpreter +{ +public: + SAFocusModeSetting3 () + { choices[17] = "AF-S"; choices[18] = "AF-C"; choices[19] = "AF-A"; @@ -1078,25 +1189,29 @@ class SAFocusModeSetting3: public ChoiceInterpreter { }; SAFocusModeSetting3 saFocusModeSetting3; -class SAAFMode: public ChoiceInterpreter { - public: - SAAFMode(){ - choices[0] = "Default"; - choices[1] = "Multi AF"; - choices[2] = "Center AF"; - choices[3] = "Spot AF"; - choices[4] = "Flexible Spot AF"; - choices[6] = "Touch AF"; - choices[14] = "Manual Focus"; - choices[15] = "Face Detected"; - choices[65535] = "n/a"; - } +class SAAFMode: public ChoiceInterpreter +{ +public: + SAAFMode() + { + choices[0] = "Default"; + choices[1] = "Multi AF"; + choices[2] = "Center AF"; + choices[3] = "Spot AF"; + choices[4] = "Flexible Spot AF"; + choices[6] = "Touch AF"; + choices[14] = "Manual Focus"; + choices[15] = "Face Detected"; + choices[65535] = "n/a"; + } }; SAAFMode saAFMode; -class SAAFAreaMode: public ChoiceInterpreter { - public: - SAAFAreaMode () { +class SAAFAreaMode: public ChoiceInterpreter +{ +public: + SAAFAreaMode () + { choices[0] = "Wide"; choices[1] = "Local"; choices[2] = "Spot"; @@ -1104,9 +1219,11 @@ class SAAFAreaMode: public ChoiceInterpreter { }; SAAFAreaMode saAFAreaMode; -class SAAFAreaMode2: public ChoiceInterpreter { - public: - SAAFAreaMode2 () { +class SAAFAreaMode2: public ChoiceInterpreter +{ +public: + SAAFAreaMode2 () + { choices[1] = "Wide"; choices[2] = "Spot"; choices[3] = "Local"; @@ -1115,893 +1232,1035 @@ class SAAFAreaMode2: public ChoiceInterpreter { }; SAAFAreaMode2 saAFAreaMode2; -class SAAFPointSelected: public ChoiceInterpreter { - public: - SAAFPointSelected () { - choices[1] = "Center"; - choices[2] = "Top"; - choices[3] = "Top-Right"; - choices[4] = "Right"; - choices[5] = "Bottom-Right"; - choices[6] = "Bottom"; - choices[7] = "Bottom-Left"; - choices[8] = "Left"; - choices[9] = "Top-Left"; - choices[10] = "Far Right"; - choices[11] = "Far Left"; - } +class SAAFPointSelected: public ChoiceInterpreter +{ +public: + SAAFPointSelected () + { + choices[1] = "Center"; + choices[2] = "Top"; + choices[3] = "Top-Right"; + choices[4] = "Right"; + choices[5] = "Bottom-Right"; + choices[6] = "Bottom"; + choices[7] = "Bottom-Left"; + choices[8] = "Left"; + choices[9] = "Top-Left"; + choices[10] = "Far Right"; + choices[11] = "Far Left"; + } }; SAAFPointSelected saAFPointSelected; -class SACameraInfoAFPointSelected: public ChoiceInterpreter { - public: - SACameraInfoAFPointSelected () { - choices[0] = "Auto"; - choices[1] = "Center"; - choices[2] = "Top"; - choices[3] = "Upper-Right"; - choices[4] = "Right"; - choices[5] = "Lower-Right"; - choices[6] = "Bottom"; - choices[7] = "Lower-Left"; - choices[8] = "Left"; - choices[9] = "Upper-Left"; - choices[10] = "Far Right"; - choices[11] = "Far Left"; - choices[12] = "Upper-middle"; - choices[13] = "Near Right"; - choices[14] = "Lower-middle"; - choices[15] = "Near Left"; - } +class SACameraInfoAFPointSelected: public ChoiceInterpreter +{ +public: + SACameraInfoAFPointSelected () + { + choices[0] = "Auto"; + choices[1] = "Center"; + choices[2] = "Top"; + choices[3] = "Upper-Right"; + choices[4] = "Right"; + choices[5] = "Lower-Right"; + choices[6] = "Bottom"; + choices[7] = "Lower-Left"; + choices[8] = "Left"; + choices[9] = "Upper-Left"; + choices[10] = "Far Right"; + choices[11] = "Far Left"; + choices[12] = "Upper-middle"; + choices[13] = "Near Right"; + choices[14] = "Lower-middle"; + choices[15] = "Near Left"; + } }; SACameraInfoAFPointSelected saCameraInfoAFPointSelected; -class SACameraInfoAFPoint: public ChoiceInterpreter { - public: - SACameraInfoAFPoint () { - choices[0] = "Upper-Left"; - choices[1] = "Left"; - choices[2] = "Lower-Left"; - choices[3] = "Far Left"; - choices[4] = "Top (horizontal)"; - choices[5] = "Near Right"; - choices[6] = "Center (horizontal)"; - choices[7] = "Near Left"; - choices[8] = "Bottom (horizontal)"; - choices[9] = "Top (vertical)"; - choices[10] = "Center (vertical)"; - choices[11] = "Bottom (vertical)"; - choices[12] = "Far Right"; - choices[13] = "Upper-Right"; - choices[14] = "Right"; - choices[15] = "Lower-Right"; - choices[16] = "Upper-middle"; - choices[17] = "Lower-middle"; - choices[255] = "(none)"; - } +class SACameraInfoAFPoint: public ChoiceInterpreter +{ +public: + SACameraInfoAFPoint () + { + choices[0] = "Upper-Left"; + choices[1] = "Left"; + choices[2] = "Lower-Left"; + choices[3] = "Far Left"; + choices[4] = "Top (horizontal)"; + choices[5] = "Near Right"; + choices[6] = "Center (horizontal)"; + choices[7] = "Near Left"; + choices[8] = "Bottom (horizontal)"; + choices[9] = "Top (vertical)"; + choices[10] = "Center (vertical)"; + choices[11] = "Bottom (vertical)"; + choices[12] = "Far Right"; + choices[13] = "Upper-Right"; + choices[14] = "Right"; + choices[15] = "Lower-Right"; + choices[16] = "Upper-middle"; + choices[17] = "Lower-middle"; + choices[255] = "(none)"; + } }; SACameraInfoAFPoint saCameraInfoAFPoint; -class SAAFPointSelected2: public ChoiceInterpreter { - public: - SAAFPointSelected2 () { - choices[1] = "Center"; - choices[2] = "Top"; - choices[3] = "Top-Right"; - choices[4] = "Right"; - choices[5] = "Bottom-Right"; - choices[6] = "Bottom"; - choices[7] = "Bottom-Left"; - choices[8] = "Left"; - choices[9] = "Top-Left"; - } +class SAAFPointSelected2: public ChoiceInterpreter +{ +public: + SAAFPointSelected2 () + { + choices[1] = "Center"; + choices[2] = "Top"; + choices[3] = "Top-Right"; + choices[4] = "Right"; + choices[5] = "Bottom-Right"; + choices[6] = "Bottom"; + choices[7] = "Bottom-Left"; + choices[8] = "Left"; + choices[9] = "Top-Left"; + } }; SAAFPointSelected2 saAFPointSelected2; -class SAMeteringMode0_3: public ChoiceInterpreter { - public: - SAMeteringMode0_3 () { - choices[0] = "Multi-segment"; - choices[2] = "Center-weighted Average"; - choices[3] = "Spot"; - } +class SAMeteringMode0_3: public ChoiceInterpreter +{ +public: + SAMeteringMode0_3 () + { + choices[0] = "Multi-segment"; + choices[2] = "Center-weighted Average"; + choices[3] = "Spot"; + } }; SAMeteringMode0_3 saMeteringMode0_3; -class SAMeteringMode1_3: public ChoiceInterpreter { - public: - SAMeteringMode1_3 () { - choices[1] = "Multi-segment"; - choices[2] = "Center-weighted Average"; - choices[3] = "Spot"; - } +class SAMeteringMode1_3: public ChoiceInterpreter +{ +public: + SAMeteringMode1_3 () + { + choices[1] = "Multi-segment"; + choices[2] = "Center-weighted Average"; + choices[3] = "Spot"; + } }; SAMeteringMode1_3 saMeteringMode1_3; -class SAMeteringMode1_4: public ChoiceInterpreter { - public: - SAMeteringMode1_4 () { - choices[1] = "Multi-segment"; - choices[2] = "Center-weighted Average"; - choices[4] = "Spot"; - } +class SAMeteringMode1_4: public ChoiceInterpreter +{ +public: + SAMeteringMode1_4 () + { + choices[1] = "Multi-segment"; + choices[2] = "Center-weighted Average"; + choices[4] = "Spot"; + } }; SAMeteringMode1_4 saMeteringMode1_4; -class SADynamicRangeOptimizerMode: public ChoiceInterpreter { - public: - SADynamicRangeOptimizerMode () { - choices[0] = "Off"; - choices[1] = "Standard"; - choices[2] = "Advanced Auto"; - choices[3] = "Advanced Level"; - choices[4097] = "Auto"; - } +class SADynamicRangeOptimizerMode: public ChoiceInterpreter +{ +public: + SADynamicRangeOptimizerMode () + { + choices[0] = "Off"; + choices[1] = "Standard"; + choices[2] = "Advanced Auto"; + choices[3] = "Advanced Level"; + choices[4097] = "Auto"; + } }; SADynamicRangeOptimizerMode saDynamicRangeOptimizerMode; -class SADynamicRangeOptimizerSetting: public ChoiceInterpreter { - public: - SADynamicRangeOptimizerSetting () { - choices[1] = "Off"; - choices[2] = "On (Auto)"; - choices[3] = "On (Manual)"; - } +class SADynamicRangeOptimizerSetting: public ChoiceInterpreter +{ +public: + SADynamicRangeOptimizerSetting () + { + choices[1] = "Off"; + choices[2] = "On (Auto)"; + choices[3] = "On (Manual)"; + } }; SADynamicRangeOptimizerSetting saDynamicRangeOptimizerSetting; -class SACreativeStyle: public ChoiceInterpreter { - public: - SACreativeStyle () { - choices[1] = "Standard"; - choices[2] = "Vivid"; - choices[3] = "Portrait"; - choices[4] = "Landscape"; - choices[5] = "Sunset"; - choices[6] = "Night View/Portrait"; - choices[8] = "B&W"; - choices[9] = "Adobe RGB"; - choices[11] = "Neutral"; - choices[12] = "Clear"; - choices[13] = "Deep"; - choices[14] = "Light"; - choices[15] = "Autumn Leaves"; - choices[16] = "Sepia"; - } +class SACreativeStyle: public ChoiceInterpreter +{ +public: + SACreativeStyle () + { + choices[1] = "Standard"; + choices[2] = "Vivid"; + choices[3] = "Portrait"; + choices[4] = "Landscape"; + choices[5] = "Sunset"; + choices[6] = "Night View/Portrait"; + choices[8] = "B&W"; + choices[9] = "Adobe RGB"; + choices[11] = "Neutral"; + choices[12] = "Clear"; + choices[13] = "Deep"; + choices[14] = "Light"; + choices[15] = "Autumn Leaves"; + choices[16] = "Sepia"; + } }; SACreativeStyle saCreativeStyle; -class SACreativeStyle2: public ChoiceInterpreter { - public: - SACreativeStyle2 () { - choices[1] = "Standard"; - choices[2] = "Vivid"; - choices[3] = "Portrait"; - choices[4] = "Landscape"; - choices[5] = "Sunset"; - choices[6] = "Night View/Portrait"; - choices[8] = "B&W"; - } +class SACreativeStyle2: public ChoiceInterpreter +{ +public: + SACreativeStyle2 () + { + choices[1] = "Standard"; + choices[2] = "Vivid"; + choices[3] = "Portrait"; + choices[4] = "Landscape"; + choices[5] = "Sunset"; + choices[6] = "Night View/Portrait"; + choices[8] = "B&W"; + } }; SACreativeStyle2 saCreativeStyle2; -class SACreativeStyleSetting: public ChoiceInterpreter { - public: - SACreativeStyleSetting () { - choices[16] = "Standard"; - choices[32] = "Vivid"; - choices[64] = "Portrait"; - choices[80] = "Landscape"; - choices[96] = "B&W"; - choices[160] = "Sunset"; - } +class SACreativeStyleSetting: public ChoiceInterpreter +{ +public: + SACreativeStyleSetting () + { + choices[16] = "Standard"; + choices[32] = "Vivid"; + choices[64] = "Portrait"; + choices[80] = "Landscape"; + choices[96] = "B&W"; + choices[160] = "Sunset"; + } }; SACreativeStyleSetting saCreativeStyleSetting; -class SAFlashControl: public ChoiceInterpreter { - public: - SAFlashControl () { - choices[1] = "ADI Flash"; - choices[2] = "Pre-flash TTL"; - } +class SAFlashControl: public ChoiceInterpreter +{ +public: + SAFlashControl () + { + choices[1] = "ADI Flash"; + choices[2] = "Pre-flash TTL"; + } }; SAFlashControl saFlashControl; -class SAFlashMode: public ChoiceInterpreter { - public: - SAFlashMode () { - choices[0] = "ADI"; - choices[1] = "TTL"; - } +class SAFlashMode: public ChoiceInterpreter +{ +public: + SAFlashMode () + { + choices[0] = "ADI"; + choices[1] = "TTL"; + } }; SAFlashMode saFlashMode; -class SAFlashMode2: public ChoiceInterpreter { - public: - SAFlashMode2 () { - choices[1] = "Flash Off"; - choices[16] = "Autoflash"; - choices[17] = "Fill-flash"; - choices[18] = "Slow Sync"; - choices[19] = "Rear Sync"; - choices[20] = "Wireless"; - } +class SAFlashMode2: public ChoiceInterpreter +{ +public: + SAFlashMode2 () + { + choices[1] = "Flash Off"; + choices[16] = "Autoflash"; + choices[17] = "Fill-flash"; + choices[18] = "Slow Sync"; + choices[19] = "Rear Sync"; + choices[20] = "Wireless"; + } }; SAFlashMode2 saFlashMode2; -class SAExposureProgram: public ChoiceInterpreter { - public: - SAExposureProgram () { - choices[0] = "Auto"; - choices[1] = "Manual"; - choices[2] = "Program AE"; - choices[3] = "Aperture-priority AE"; - choices[4] = "Shutter speed priority AE"; - choices[8] = "Program Shift A"; - choices[9] = "Program Shift S"; - choices[16] = "Portrait"; - choices[17] = "Sports"; - choices[18] = "Sunset"; - choices[19] = "Night Portrait"; - choices[20] = "Landscape"; - choices[21] = "Macro"; - choices[35] = "Auto No Flash"; - } +class SAExposureProgram: public ChoiceInterpreter +{ +public: + SAExposureProgram () + { + choices[0] = "Auto"; + choices[1] = "Manual"; + choices[2] = "Program AE"; + choices[3] = "Aperture-priority AE"; + choices[4] = "Shutter speed priority AE"; + choices[8] = "Program Shift A"; + choices[9] = "Program Shift S"; + choices[16] = "Portrait"; + choices[17] = "Sports"; + choices[18] = "Sunset"; + choices[19] = "Night Portrait"; + choices[20] = "Landscape"; + choices[21] = "Macro"; + choices[35] = "Auto No Flash"; + } }; SAExposureProgram saExposureProgram; -class SAExposureProgram2: public ChoiceInterpreter { - public: - SAExposureProgram2 () { - choices[1] = "Program AE"; - choices[2] = "Aperture-priority AE"; - choices[3] = "Shutter speed priority AE"; - choices[4] = "Manual"; - choices[5] = "Cont. Priority AE"; - choices[16] = "Auto"; - choices[17] = "Auto (no flash)"; - choices[18] = "Auto+"; - choices[49] = "Portrait"; - choices[50] = "Landscape"; - choices[51] = "Macro"; - choices[52] = "Sports"; - choices[53] = "Sunset"; - choices[54] = "Night view"; - choices[55] = "Night view/portrait"; - choices[56] = "Handheld Night Shot"; - choices[57] = "3D Sweep Panorama"; - choices[64] = "Auto 2"; - choices[65] = "Auto 2 (no flash)"; - choices[80] = "Sweep Panorama"; - choices[96] = "Anti Motion Blur"; - choices[128] = "Toy Camera"; - choices[129] = "Pop Color"; - choices[130] = "Posterization"; - choices[131] = "Posterization B/W"; - choices[132] = "Retro Photo"; - choices[133] = "High-key"; - choices[134] = "Partial Color Red"; - choices[135] = "Partial Color Green"; - choices[136] = "Partial Color Blue"; - choices[137] = "Partial Color Yellow"; - choices[138] = "High Contrast Monochrome"; - } +class SAExposureProgram2: public ChoiceInterpreter +{ +public: + SAExposureProgram2 () + { + choices[1] = "Program AE"; + choices[2] = "Aperture-priority AE"; + choices[3] = "Shutter speed priority AE"; + choices[4] = "Manual"; + choices[5] = "Cont. Priority AE"; + choices[16] = "Auto"; + choices[17] = "Auto (no flash)"; + choices[18] = "Auto+"; + choices[49] = "Portrait"; + choices[50] = "Landscape"; + choices[51] = "Macro"; + choices[52] = "Sports"; + choices[53] = "Sunset"; + choices[54] = "Night view"; + choices[55] = "Night view/portrait"; + choices[56] = "Handheld Night Shot"; + choices[57] = "3D Sweep Panorama"; + choices[64] = "Auto 2"; + choices[65] = "Auto 2 (no flash)"; + choices[80] = "Sweep Panorama"; + choices[96] = "Anti Motion Blur"; + choices[128] = "Toy Camera"; + choices[129] = "Pop Color"; + choices[130] = "Posterization"; + choices[131] = "Posterization B/W"; + choices[132] = "Retro Photo"; + choices[133] = "High-key"; + choices[134] = "Partial Color Red"; + choices[135] = "Partial Color Green"; + choices[136] = "Partial Color Blue"; + choices[137] = "Partial Color Yellow"; + choices[138] = "High Contrast Monochrome"; + } }; SAExposureProgram2 saExposureProgram2; -class SARotation: public ChoiceInterpreter { - public: - SARotation () { - choices[0] = "Horizontal"; - choices[1] = "Rotate 90 CW"; - choices[2] = "Rotate 270 CW"; - choices[3] = "None"; - } +class SARotation: public ChoiceInterpreter +{ +public: + SARotation () + { + choices[0] = "Horizontal"; + choices[1] = "Rotate 90 CW"; + choices[2] = "Rotate 270 CW"; + choices[3] = "None"; + } }; SARotation saRotation; -class SASonyImageSize: public ChoiceInterpreter { - public: - SASonyImageSize () { - choices[1] = "Large"; - choices[2] = "Medium"; - choices[3] = "Small"; - } +class SASonyImageSize: public ChoiceInterpreter +{ +public: + SASonyImageSize () + { + choices[1] = "Large"; + choices[2] = "Medium"; + choices[3] = "Small"; + } }; SASonyImageSize saSonyImageSize; -class SASonyImageSize3: public ChoiceInterpreter { - public: - SASonyImageSize3 () { - choices[21] = "Large (3:2)"; - choices[22] = "Medium (3:2)"; - choices[23] = "Small (3:2)"; - choices[25] = "Large (16:9)"; - choices[26] = "Medium (16:9) "; - choices[27] = "Small (16:9)"; - } +class SASonyImageSize3: public ChoiceInterpreter +{ +public: + SASonyImageSize3 () + { + choices[21] = "Large (3:2)"; + choices[22] = "Medium (3:2)"; + choices[23] = "Small (3:2)"; + choices[25] = "Large (16:9)"; + choices[26] = "Medium (16:9) "; + choices[27] = "Small (16:9)"; + } }; SASonyImageSize3 saSonyImageSize3; -class SAAspectRatio: public ChoiceInterpreter { - public: - SAAspectRatio () { - choices[1] = "3:2"; - choices[2] = "16:9"; - } +class SAAspectRatio: public ChoiceInterpreter +{ +public: + SAAspectRatio () + { + choices[1] = "3:2"; + choices[2] = "16:9"; + } }; SAAspectRatio saAspectRatio; -class SAAspectRatio2: public ChoiceInterpreter { - public: - SAAspectRatio2 () { - choices[4] = "3:2"; - choices[8] = "16:9"; - } +class SAAspectRatio2: public ChoiceInterpreter +{ +public: + SAAspectRatio2 () + { + choices[4] = "3:2"; + choices[8] = "16:9"; + } }; SAAspectRatio2 saAspectRatio2; -class SAExposureLevelIncrements: public ChoiceInterpreter { - public: - SAExposureLevelIncrements () { - choices[33] = "1/3 EV"; - choices[50] = "1/2 EV"; - } +class SAExposureLevelIncrements: public ChoiceInterpreter +{ +public: + SAExposureLevelIncrements () + { + choices[33] = "1/3 EV"; + choices[50] = "1/2 EV"; + } }; SAExposureLevelIncrements saExposureLevelIncrements; -class SAAFIlluminator: public ChoiceInterpreter { - public: - SAAFIlluminator () { - choices[0] = "Off"; - choices[1] = "Auto"; - choices[65535]="n/a"; - } +class SAAFIlluminator: public ChoiceInterpreter +{ +public: + SAAFIlluminator () + { + choices[0] = "Off"; + choices[1] = "Auto"; + choices[65535] = "n/a"; + } }; SAAFIlluminator saAFIlluminator; -class SAColorSpace1_2: public ChoiceInterpreter { - public: - SAColorSpace1_2 () { - choices[1] = "sRGB"; - choices[2] = "AdobeRGB"; - } +class SAColorSpace1_2: public ChoiceInterpreter +{ +public: + SAColorSpace1_2 () + { + choices[1] = "sRGB"; + choices[2] = "AdobeRGB"; + } }; SAColorSpace1_2 saColorSpace1_2; -class SAColorSpace0_5: public ChoiceInterpreter { - public: - SAColorSpace0_5 () { - choices[0] = "sRGB"; - choices[1] = "AdobeRGB"; - choices[5] = "AdobeRGB"; - } +class SAColorSpace0_5: public ChoiceInterpreter +{ +public: + SAColorSpace0_5 () + { + choices[0] = "sRGB"; + choices[1] = "AdobeRGB"; + choices[5] = "AdobeRGB"; + } }; SAColorSpace0_5 saColorSpace0_5; -class SAColorSpace5_6: public ChoiceInterpreter { - public: - SAColorSpace5_6 () { - choices[5] = "AdobeRGB"; - choices[6] = "sRGB"; - } +class SAColorSpace5_6: public ChoiceInterpreter +{ +public: + SAColorSpace5_6 () + { + choices[5] = "AdobeRGB"; + choices[6] = "sRGB"; + } }; SAColorSpace5_6 saColorSpace5_6; -class SAReleaseModeInterpreter: public ChoiceInterpreter { - public: - SAReleaseModeInterpreter () { - choices[0] = "Normal"; - choices[2] = "Burst"; - choices[5] = "Exposure Bracketing"; - choices[6] = "White Balance Bracketing"; - choices[65535]="n/a"; - } +class SAReleaseModeInterpreter: public ChoiceInterpreter +{ +public: + SAReleaseModeInterpreter () + { + choices[0] = "Normal"; + choices[2] = "Burst"; + choices[5] = "Exposure Bracketing"; + choices[6] = "White Balance Bracketing"; + choices[65535] = "n/a"; + } }; SAReleaseModeInterpreter saReleaseModeInterpreter; -class SAImageStyleInterpreter: public ChoiceInterpreter { - public: - SAImageStyleInterpreter () { - choices[1] = "Standard"; - choices[2] = "Vivid"; - choices[9] = "Adobe RGB"; - choices[11] = "Neutral"; - choices[129]="StyleBox1"; - choices[130]="StyleBox2"; - choices[131]="StyleBox3"; - } +class SAImageStyleInterpreter: public ChoiceInterpreter +{ +public: + SAImageStyleInterpreter () + { + choices[1] = "Standard"; + choices[2] = "Vivid"; + choices[9] = "Adobe RGB"; + choices[11] = "Neutral"; + choices[129] = "StyleBox1"; + choices[130] = "StyleBox2"; + choices[131] = "StyleBox3"; + } }; SAImageStyleInterpreter saImageStyleInterpreter; -class SAPictureEffectInterpreter: public ChoiceInterpreter { - public: - SAPictureEffectInterpreter(){ - choices[0] = "Off"; - choices[1] = "Toy Camera"; - choices[2] = "Pop Color"; - choices[3] = "Posterization"; - choices[4] = "Posterization B/W"; - choices[5] = "Retro Photo"; - choices[6] = "Soft High Key"; - choices[7] = "Partial Color Red"; - choices[8] = "Partial Color Green"; - choices[9] = "Partial Color Blue"; - choices[10] = "Partial Color Yellow"; - choices[13] = "High Contrast Monochrome"; - choices[16] = "Toy Camera 2"; - choices[33] = "Soft Focus"; - choices[48] = "Miniature"; - choices[50] = "Miniature 2"; - choices[51] = "Miniature 3"; - choices[65] = "HDR Painting"; - choices[80] = "Rich-tone Monochrome"; - choices[98] = "Water Color"; - choices[114] = "Illustration"; - } +class SAPictureEffectInterpreter: public ChoiceInterpreter +{ +public: + SAPictureEffectInterpreter() + { + choices[0] = "Off"; + choices[1] = "Toy Camera"; + choices[2] = "Pop Color"; + choices[3] = "Posterization"; + choices[4] = "Posterization B/W"; + choices[5] = "Retro Photo"; + choices[6] = "Soft High Key"; + choices[7] = "Partial Color Red"; + choices[8] = "Partial Color Green"; + choices[9] = "Partial Color Blue"; + choices[10] = "Partial Color Yellow"; + choices[13] = "High Contrast Monochrome"; + choices[16] = "Toy Camera 2"; + choices[33] = "Soft Focus"; + choices[48] = "Miniature"; + choices[50] = "Miniature 2"; + choices[51] = "Miniature 3"; + choices[65] = "HDR Painting"; + choices[80] = "Rich-tone Monochrome"; + choices[98] = "Water Color"; + choices[114] = "Illustration"; + } }; SAPictureEffectInterpreter saPictureEffectInterpreter; -class SACameraInfoFocusStatusInterpreter : public ChoiceInterpreter { - public: - SACameraInfoFocusStatusInterpreter() { - choices[0] = "Manual - Not confirmed (0)"; - choices[4] = "Manual - Not confirmed (4)"; - choices[16] = "AF-C - Confirmed"; - choices[24] = "AF-C - Not Confirmed"; - choices[64] = "AF-S - Confirmed"; - } +class SACameraInfoFocusStatusInterpreter : public ChoiceInterpreter +{ +public: + SACameraInfoFocusStatusInterpreter() + { + choices[0] = "Manual - Not confirmed (0)"; + choices[4] = "Manual - Not confirmed (4)"; + choices[16] = "AF-C - Confirmed"; + choices[24] = "AF-C - Not Confirmed"; + choices[64] = "AF-S - Confirmed"; + } }; SACameraInfoFocusStatusInterpreter saCameraInfoFocusStatusInterpreter; -class SAExposureTimeInterpreter : public Interpreter { - public: - SAExposureTimeInterpreter () {} - virtual std::string toString (Tag* t){ - double a = t->toDouble(); - if(a>0){ - char buffer[10]; - sprintf (buffer, "%.4f", a); - return buffer; - }else - return "n/a"; - } - virtual double toDouble (Tag* t, int ofs){ - // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - TagType astype = t->getType(); - int a; - if (astype==BYTE) - a = t->getValue()[ofs]; - else if (astype==SHORT) - a = (int)sget2 (t->getValue()+ofs, t->getOrder()); +class SAExposureTimeInterpreter : public Interpreter +{ +public: + SAExposureTimeInterpreter () {} + virtual std::string toString (Tag* t) + { + double a = t->toDouble(); - // Decode the value - if(a>0.) - return pow(2., 6.-(double(a)/8.)); - else - return 0.; + if(a > 0) { + char buffer[10]; + sprintf (buffer, "%.4f", a); + return buffer; + } else { + return "n/a"; } - virtual int toInt (Tag* t, int ofs, TagType astype){ - // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - int a; - if (astype==INVALID || astype==AUTO) - astype = t->getType(); - if (astype==BYTE) - a = t->getValue()[ofs]; - else if (astype==SHORT) - a = (int)sget2 (t->getValue()+ofs, t->getOrder()); + } + virtual double toDouble (Tag* t, int ofs) + { + // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT + TagType astype = t->getType(); + int a; - // Decode the value - if(a) - return int(powf(2.f, 6.f-(float(a)/8.f))+0.5f); - else - return 0; + if (astype == BYTE) { + a = t->getValue()[ofs]; + } else if (astype == SHORT) { + a = (int)sget2 (t->getValue() + ofs, t->getOrder()); } + + // Decode the value + if(a > 0.) { + return pow(2., 6. - (double(a) / 8.)); + } else { + return 0.; + } + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT + int a; + + if (astype == INVALID || astype == AUTO) { + astype = t->getType(); + } + + if (astype == BYTE) { + a = t->getValue()[ofs]; + } else if (astype == SHORT) { + a = (int)sget2 (t->getValue() + ofs, t->getOrder()); + } + + // Decode the value + if(a) { + return int(powf(2.f, 6.f - (float(a) / 8.f)) + 0.5f); + } else { + return 0; + } + } }; SAExposureTimeInterpreter saExposureTimeInterpreter; -class SAFNumberInterpreter : public Interpreter { - public: - SAFNumberInterpreter () {} - virtual std::string toString (Tag* t){ - double a = double(t->toDouble()); - if(a){ - char buffer[10]; - sprintf (buffer, "%.1f", a/100. ); - return buffer; - }else - return "n/a"; - } - virtual double toDouble (Tag* t, int ofs){ - // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - TagType astype = t->getType(); - int a; - if (astype==BYTE) - a = t->getValue()[ofs]; - else if (astype==SHORT) - a = (int)sget2 (t->getValue()+ofs, t->getOrder()); +class SAFNumberInterpreter : public Interpreter +{ +public: + SAFNumberInterpreter () {} + virtual std::string toString (Tag* t) + { + double a = double(t->toDouble()); - // Decode the value - if(a>0.) - return pow(2., (double(a)/8. - 1.) / 2.); - else - return 0.; + if(a) { + char buffer[10]; + sprintf (buffer, "%.1f", a / 100. ); + return buffer; + } else { + return "n/a"; } - virtual int toInt (Tag* t, int ofs, TagType astype){ - // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - int a; - if (astype==INVALID || astype==AUTO) - astype = t->getType(); - if (astype==BYTE) - a = t->getValue()[ofs]; - else if (astype==SHORT) - a = (int)sget2 (t->getValue()+ofs, t->getOrder()); + } + virtual double toDouble (Tag* t, int ofs) + { + // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT + TagType astype = t->getType(); + int a; - // Decode the value - if(a) - return int(powf(2.f, (float(a)/8.f - 1.f) / 2.f)+0.5f); - else - return 0; + if (astype == BYTE) { + a = t->getValue()[ofs]; + } else if (astype == SHORT) { + a = (int)sget2 (t->getValue() + ofs, t->getOrder()); } + + // Decode the value + if(a > 0.) { + return pow(2., (double(a) / 8. - 1.) / 2.); + } else { + return 0.; + } + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT + int a; + + if (astype == INVALID || astype == AUTO) { + astype = t->getType(); + } + + if (astype == BYTE) { + a = t->getValue()[ofs]; + } else if (astype == SHORT) { + a = (int)sget2 (t->getValue() + ofs, t->getOrder()); + } + + // Decode the value + if(a) { + return int(powf(2.f, (float(a) / 8.f - 1.f) / 2.f) + 0.5f); + } else { + return 0; + } + } }; SAFNumberInterpreter saFNumberInterpreter; -class SAISOSettingInterpreter : public Interpreter { - public: - SAISOSettingInterpreter () {} - virtual std::string toString (Tag* t){ - int a = t->toInt(); - if(a){ - char buffer[10]; - sprintf (buffer, "%d", a ); - return buffer; - }else - return "Auto"; - } - virtual int toInt (Tag* t, int ofs, TagType astype){ - // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - int a; - if (astype==INVALID || astype==AUTO) - astype = t->getType(); - if (astype==BYTE) - a = t->getValue()[ofs]; - else if (astype==SHORT) - a = (int)sget2 (t->getValue()+ofs, t->getOrder()); +class SAISOSettingInterpreter : public Interpreter +{ +public: + SAISOSettingInterpreter () {} + virtual std::string toString (Tag* t) + { + int a = t->toInt(); - // Decode the value - if(a && a!=254) // 254 = 'Auto' for CameraSettings3, but we might say the same for CameraSettings & CameraSettings2 (?) - return int(expf((double(a)/8.f-6.f)*logf(2.f))*100.f +0.5f); - else - return 0; + if(a) { + char buffer[10]; + sprintf (buffer, "%d", a ); + return buffer; + } else { + return "Auto"; } + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT + int a; + + if (astype == INVALID || astype == AUTO) { + astype = t->getType(); + } + + if (astype == BYTE) { + a = t->getValue()[ofs]; + } else if (astype == SHORT) { + a = (int)sget2 (t->getValue() + ofs, t->getOrder()); + } + + // Decode the value + if(a && a != 254) { // 254 = 'Auto' for CameraSettings3, but we might say the same for CameraSettings & CameraSettings2 (?) + return int(expf((double(a) / 8.f - 6.f) * logf(2.f)) * 100.f + 0.5f); + } else { + return 0; + } + } }; SAISOSettingInterpreter saISOSettingInterpreter; -class SAExposureCompSetInterpreter : public Interpreter { - public: - SAExposureCompSetInterpreter () {} - virtual std::string toString (Tag* t){ - double a = t->toDouble(); - char buffer[10]; - sprintf (buffer, "%.2f", a ); - return buffer; - } - virtual double toDouble (Tag* t, int ofs){ - // Get the value - int a = t->getValue()[ofs]; - // Decode the value - return (double(a) - 128.) / 24.; - } +class SAExposureCompSetInterpreter : public Interpreter +{ +public: + SAExposureCompSetInterpreter () {} + virtual std::string toString (Tag* t) + { + double a = t->toDouble(); + char buffer[10]; + sprintf (buffer, "%.2f", a ); + return buffer; + } + virtual double toDouble (Tag* t, int ofs) + { + // Get the value + int a = t->getValue()[ofs]; + // Decode the value + return (double(a) - 128.) / 24.; + } }; SAExposureCompSetInterpreter saExposureCompSetInterpreter; -class SAAFMicroAdjValueInterpreter : public Interpreter { - public: - SAAFMicroAdjValueInterpreter() {} - virtual std::string toString (Tag* t){ - char buffer[10]; - sprintf (buffer, "%d", t->getValue()[0] - 20); - return buffer; - } - virtual int toInt (Tag* t, int ofs, TagType astype){ - return t->getValue()[0] - 20; - } +class SAAFMicroAdjValueInterpreter : public Interpreter +{ +public: + SAAFMicroAdjValueInterpreter() {} + virtual std::string toString (Tag* t) + { + char buffer[10]; + sprintf (buffer, "%d", t->getValue()[0] - 20); + return buffer; + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + return t->getValue()[0] - 20; + } }; SAAFMicroAdjValueInterpreter saAFMicroAdjValueInterpreter; -class SAAFMicroAdjModeInterpreter : public Interpreter { - public: - SAAFMicroAdjModeInterpreter() {} - virtual std::string toString (Tag* t){ - int a = t->getValue()[0] & 0x80; - if (a==0x80) - return "On"; - return "Off"; - } - virtual int toInt (Tag* t, int ofs, TagType astype){ - return (t->getValue()[0] & 0x80) == 0x80 ? 1 : 0; +class SAAFMicroAdjModeInterpreter : public Interpreter +{ +public: + SAAFMicroAdjModeInterpreter() {} + virtual std::string toString (Tag* t) + { + int a = t->getValue()[0] & 0x80; + + if (a == 0x80) { + return "On"; } + + return "Off"; + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + return (t->getValue()[0] & 0x80) == 0x80 ? 1 : 0; + } }; SAAFMicroAdjModeInterpreter saAFMicroAdjModeInterpreter; -class SAAFMicroAdjRegisteredLensesInterpreter : public Interpreter { - public: - SAAFMicroAdjRegisteredLensesInterpreter() {} - virtual std::string toString (Tag* t){ - char buffer[10]; - sprintf (buffer, "%d", t->getValue()[0] & 0x7f); - return buffer; - } - virtual int toInt (Tag* t, int ofs, TagType astype){ - return t->getValue()[0] & 0x7f; - } +class SAAFMicroAdjRegisteredLensesInterpreter : public Interpreter +{ +public: + SAAFMicroAdjRegisteredLensesInterpreter() {} + virtual std::string toString (Tag* t) + { + char buffer[10]; + sprintf (buffer, "%d", t->getValue()[0] & 0x7f); + return buffer; + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + return t->getValue()[0] & 0x7f; + } }; SAAFMicroAdjRegisteredLensesInterpreter saAFMicroAdjRegisteredLensesInterpreter; -class SAFocusStatusInterpreter : public Interpreter { - public: - SAFocusStatusInterpreter () {} - virtual std::string toString (Tag* t){ - std::string retval; - int a = t->toInt(); - if (a == 0) - retval = "Not confirmed"; - else if (a == 4) - retval = "Not confirmed, Tracking"; - else { - if (a & 1) - retval = "Confirmed"; - if (a & 2) { - if (!retval.empty()) - retval += ", "; - retval += "Failed"; - } - if (a & 4) - if (!retval.empty()) - retval += ", "; - retval += "Tracking"; +class SAFocusStatusInterpreter : public Interpreter +{ +public: + SAFocusStatusInterpreter () {} + virtual std::string toString (Tag* t) + { + std::string retval; + int a = t->toInt(); + + if (a == 0) { + retval = "Not confirmed"; + } else if (a == 4) { + retval = "Not confirmed, Tracking"; + } else { + if (a & 1) { + retval = "Confirmed"; } - return retval; + + if (a & 2) { + if (!retval.empty()) { + retval += ", "; + } + + retval += "Failed"; + } + + if (a & 4) + if (!retval.empty()) { + retval += ", "; + } + + retval += "Tracking"; } + + return retval; + } }; SAFocusStatusInterpreter saFocusStatusInterpreter; -class SAColorTemperatureSettingInterpreter : public Interpreter { - public: - SAColorTemperatureSettingInterpreter () {} - virtual std::string toString (Tag* t){ - char buffer[10]; - sprintf (buffer, "%d", t->toInt()); - return buffer; +class SAColorTemperatureSettingInterpreter : public Interpreter +{ +public: + SAColorTemperatureSettingInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[10]; + sprintf (buffer, "%d", t->toInt()); + return buffer; + } + virtual int toInt (Tag* t, int ofs, TagType astype) + { + int a; + + if (astype == INVALID || astype == AUTO) { + astype = t->getType(); } - virtual int toInt (Tag* t, int ofs, TagType astype){ - int a; - if (astype==INVALID || astype==AUTO) - astype = t->getType(); - if (astype==BYTE) - a = t->getValue()[ofs]; - else if (astype==SHORT) - a = (int)sget2 (t->getValue()+ofs, t->getOrder()); - return a * 100; + + if (astype == BYTE) { + a = t->getValue()[ofs]; + } else if (astype == SHORT) { + a = (int)sget2 (t->getValue() + ofs, t->getOrder()); } + + return a * 100; + } }; SAColorTemperatureSettingInterpreter saColorTemperatureSettingInterpreter; const TagAttrib minoltaAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "MakerNoteVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0001, AUTO, "MinoltaCameraSettingsOld", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0003, AUTO, "MinoltaCameraSettings", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0004, AUTO, "MinoltaCameraSettings7D", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0018, AUTO, "ImageStabilization", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0040, AUTO, "CompressedImageSize", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0081, AUTO, "PreviewImage", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0088, AUTO, "PreviewImageStart", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0089, AUTO, "PreviewImageLength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0100, AUTO, "SceneMode", &saSceneModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0101, AUTO, "ColorMode", &saColorModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0102, AUTO, "MinoltaQuality", &maQualityInterpreter}, - {0, AC_WRITE, 0, 0, 0x0103, AUTO, "MinoltaImageSize", &maImageSizeInterpreter}, - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "FlashExposureComp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0105, AUTO, "Teleconverter", &maTeleconverterInterpreter}, - {0, AC_WRITE, 0, 0, 0x0107, AUTO, "ImageStabilization", &saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x010a, AUTO, "ZoneMatching", &saZoneMatchingInterpreter}, - {0, AC_WRITE, 0, 0, 0x010b, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010c, AUTO, "LensID", &saLensIDInterpreter}, - {0, AC_WRITE, 0, 0, 0x0113, AUTO, "ImageStabilization", &saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0x0114, AUTO, "MinoltaCameraSettings", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0f00, AUTO, "MinoltaCameraSettings2", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "MakerNoteVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0001, AUTO, "MinoltaCameraSettingsOld", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0003, AUTO, "MinoltaCameraSettings", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0004, AUTO, "MinoltaCameraSettings7D", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0018, AUTO, "ImageStabilization", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0040, AUTO, "CompressedImageSize", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0081, AUTO, "PreviewImage", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0088, AUTO, "PreviewImageStart", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0089, AUTO, "PreviewImageLength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0100, AUTO, "SceneMode", &saSceneModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0101, AUTO, "ColorMode", &saColorModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0102, AUTO, "MinoltaQuality", &maQualityInterpreter}, + {0, AC_WRITE, 0, 0, 0x0103, AUTO, "MinoltaImageSize", &maImageSizeInterpreter}, + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0105, AUTO, "Teleconverter", &maTeleconverterInterpreter}, + {0, AC_WRITE, 0, 0, 0x0107, AUTO, "ImageStabilization", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x010a, AUTO, "ZoneMatching", &saZoneMatchingInterpreter}, + {0, AC_WRITE, 0, 0, 0x010b, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010c, AUTO, "LensID", &saLensIDInterpreter}, + {0, AC_WRITE, 0, 0, 0x0113, AUTO, "ImageStabilization", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0x0114, AUTO, "MinoltaCameraSettings", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0f00, AUTO, "MinoltaCameraSettings2", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib sonyAttribs[] = { - {0, AC_WRITE, 0, sonyCameraInfoAttribs, 0x0010, AUTO, "CameraInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0102, AUTO, "Quality", &maQualityInterpreter}, - {0, AC_WRITE, 0, 0, 0x0104, AUTO, "FlashExposureComp",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0106, AUTO, "TeleConverter", &maTeleconverterInterpreter}, - {0, AC_WRITE, 0, sonyCameraSettingsAttribs, 0x0114, AUTO, "SonyCameraSettings",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0115, AUTO, "WhiteBalance",&saWhiteBalanceInterpreter}, - {1, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, - {1, AC_WRITE, 0, 0, 0x2001, AUTO, "PreviewImage", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x2009, AUTO, "HighISONoiseReduction", &saHighISONoiseReduction}, - {0, AC_WRITE, 0, 0, 0x200a, AUTO, "AutoHDR", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x200b, AUTO, "MultiFrameNoiseReduction", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x200e, AUTO, "PictureEffect", &saPictureEffectInterpreter}, - {0, AC_WRITE, 0, 0, 0x2011, AUTO, "VignettingCorrection", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x2012, AUTO, "LateralChromaticAberration", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x2013, AUTO, "DistortionCorrection", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb020, AUTO, "ColorReproduction", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb021, AUTO, "ColorTemperature", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb022, AUTO, "ColorCompensationFilter", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb023, AUTO, "SceneMode", &saSceneModeInterpreter}, - {0, AC_WRITE, 0, 0, 0xb024, AUTO, "ZoneMatching", &saZoneMatchingInterpreter}, - {0, AC_WRITE, 0, 0, 0xb025, AUTO, "DynamicRangeOptimizer", &saDynamicRangeOptimizerInterpreter}, - {0, AC_WRITE, 0, 0, 0xb026, AUTO, "ImageStabilization", &saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0xb027, AUTO, "LensID", &saLensIDInterpreter}, - {0, AC_WRITE, 0, minoltaAttribs, 0xb028, AUTO, "MinoltaMakerNote", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb029, AUTO, "ColorMode", &saColorModeInterpreter}, - {0, AC_WRITE, 0, 0, 0xb040, AUTO, "Macro", &saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0xb041, AUTO, "ExposureMode", &saExposureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0xb042, AUTO, "FocusMode", &saFocusMode}, - {0, AC_WRITE, 0, 0, 0xb043, AUTO, "AFMode", &saAFMode}, - {0, AC_WRITE, 0, 0, 0xb044, AUTO, "AFIlluminator", &saAFIlluminator}, - {0, AC_WRITE, 0, 0, 0xb047, AUTO, "Quality", &saQualityInterpreter}, - {0, AC_WRITE, 0, 0, 0xb048, AUTO, "FlashLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb049, AUTO, "ReleaseMode",&saReleaseModeInterpreter}, - {0, AC_WRITE, 0, 0, 0xb04a, AUTO, "SequenceNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb04b, AUTO, "AntiBlur", &saAntiBlurInterpreter}, - {0, AC_WRITE, 0, 0, 0xb04e, AUTO, "LongExposureNoiseReduction", &saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 0xb04f, AUTO, "DynamicRangeOptimizer", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xb050, AUTO, "HighISONoiseReduction2", &saHighISONoiseReduction2}, - {0, AC_WRITE, 0, 0, 0xb052, AUTO, "IntelligentAuto", &stdInterpreter}, - {0, AC_WRITE, 0, sonyTag9405Attribs, 0x9405, AUTO, "Tag9405", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, sonyCameraInfoAttribs, 0x0010, AUTO, "CameraInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0102, AUTO, "Quality", &maQualityInterpreter}, + {0, AC_WRITE, 0, 0, 0x0104, AUTO, "FlashExposureComp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0106, AUTO, "TeleConverter", &maTeleconverterInterpreter}, + {0, AC_WRITE, 0, sonyCameraSettingsAttribs, 0x0114, AUTO, "SonyCameraSettings", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0115, AUTO, "WhiteBalance", &saWhiteBalanceInterpreter}, + {1, AC_WRITE, 0, 0, 0x0e00, AUTO, "PrintIM", &stdInterpreter}, + {1, AC_WRITE, 0, 0, 0x2001, AUTO, "PreviewImage", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x2009, AUTO, "HighISONoiseReduction", &saHighISONoiseReduction}, + {0, AC_WRITE, 0, 0, 0x200a, AUTO, "AutoHDR", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x200b, AUTO, "MultiFrameNoiseReduction", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x200e, AUTO, "PictureEffect", &saPictureEffectInterpreter}, + {0, AC_WRITE, 0, 0, 0x2011, AUTO, "VignettingCorrection", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x2012, AUTO, "LateralChromaticAberration", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x2013, AUTO, "DistortionCorrection", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb020, AUTO, "ColorReproduction", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb021, AUTO, "ColorTemperature", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb022, AUTO, "ColorCompensationFilter", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb023, AUTO, "SceneMode", &saSceneModeInterpreter}, + {0, AC_WRITE, 0, 0, 0xb024, AUTO, "ZoneMatching", &saZoneMatchingInterpreter}, + {0, AC_WRITE, 0, 0, 0xb025, AUTO, "DynamicRangeOptimizer", &saDynamicRangeOptimizerInterpreter}, + {0, AC_WRITE, 0, 0, 0xb026, AUTO, "ImageStabilization", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0xb027, AUTO, "LensID", &saLensIDInterpreter}, + {0, AC_WRITE, 0, minoltaAttribs, 0xb028, AUTO, "MinoltaMakerNote", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb029, AUTO, "ColorMode", &saColorModeInterpreter}, + {0, AC_WRITE, 0, 0, 0xb040, AUTO, "Macro", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0xb041, AUTO, "ExposureMode", &saExposureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0xb042, AUTO, "FocusMode", &saFocusMode}, + {0, AC_WRITE, 0, 0, 0xb043, AUTO, "AFMode", &saAFMode}, + {0, AC_WRITE, 0, 0, 0xb044, AUTO, "AFIlluminator", &saAFIlluminator}, + {0, AC_WRITE, 0, 0, 0xb047, AUTO, "Quality", &saQualityInterpreter}, + {0, AC_WRITE, 0, 0, 0xb048, AUTO, "FlashLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb049, AUTO, "ReleaseMode", &saReleaseModeInterpreter}, + {0, AC_WRITE, 0, 0, 0xb04a, AUTO, "SequenceNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb04b, AUTO, "AntiBlur", &saAntiBlurInterpreter}, + {0, AC_WRITE, 0, 0, 0xb04e, AUTO, "LongExposureNoiseReduction", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 0xb04f, AUTO, "DynamicRangeOptimizer", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xb050, AUTO, "HighISONoiseReduction2", &saHighISONoiseReduction2}, + {0, AC_WRITE, 0, 0, 0xb052, AUTO, "IntelligentAuto", &stdInterpreter}, + {0, AC_WRITE, 0, sonyTag9405Attribs, 0x9405, AUTO, "Tag9405", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib sonyTag9405Attribs[] = { - {0, AC_WRITE, 0, 0, 0x005d, AUTO, "LensFormat", &stdInterpreter}, // 9405b start here - {0, AC_WRITE, 0, 0, 0x005e, AUTO, "LensMount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0060, SHORT, "LensType2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0062, SHORT, "LensType", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0603, AUTO, "LensFormat", &stdInterpreter}, // 9405a start here - {0, AC_WRITE, 0, 0, 0x0604, AUTO, "LensMount", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0605, SHORT, "LensType2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0608, SHORT, "LensType", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 0x005d, AUTO, "LensFormat", &stdInterpreter}, // 9405b start here + {0, AC_WRITE, 0, 0, 0x005e, AUTO, "LensMount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0060, SHORT, "LensType2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0062, SHORT, "LensType", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0603, AUTO, "LensFormat", &stdInterpreter}, // 9405a start here + {0, AC_WRITE, 0, 0, 0x0604, AUTO, "LensMount", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0605, SHORT, "LensType2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0608, SHORT, "LensType", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib sonyCameraInfoAttribs[] = { - {0, AC_WRITE, 0, 0, 14, SHORT, "FocalLength", &saExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 16, SHORT, "FocalLengthTeleZoom", &saExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 25, AUTO, "FocusStatus", &saCameraInfoFocusStatusInterpreter}, - {0, AC_WRITE, 0, 0, 28, AUTO, "AFPointSelected", &saCameraInfoAFPointSelected}, - {0, AC_WRITE, 0, 0, 29, AUTO, "FocusMode", &saFocusMode2}, - {0, AC_WRITE, 0, 0, 32, AUTO, "AFPoint", &saCameraInfoAFPoint}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 14, SHORT, "FocalLength", &saExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 16, SHORT, "FocalLengthTeleZoom", &saExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 25, AUTO, "FocusStatus", &saCameraInfoFocusStatusInterpreter}, + {0, AC_WRITE, 0, 0, 28, AUTO, "AFPointSelected", &saCameraInfoAFPointSelected}, + {0, AC_WRITE, 0, 0, 29, AUTO, "FocusMode", &saFocusMode2}, + {0, AC_WRITE, 0, 0, 32, AUTO, "AFPoint", &saCameraInfoAFPoint}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; const TagAttrib sonyCameraInfo2Attribs[] = { - {0, AC_WRITE, 0, 0, 304, AUTO, "AFMicroAdjValue", &saAFMicroAdjValueInterpreter}, - {0, AC_WRITE, 0, 0, 305, AUTO, "AFMicroAdjMode", &saAFMicroAdjModeInterpreter}, - {0, AC_WRITE, 0, 0, 305, AUTO, "AFMicroAdjRegisteredLenses", &saAFMicroAdjRegisteredLensesInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; + {0, AC_WRITE, 0, 0, 304, AUTO, "AFMicroAdjValue", &saAFMicroAdjValueInterpreter}, + {0, AC_WRITE, 0, 0, 305, AUTO, "AFMicroAdjMode", &saAFMicroAdjModeInterpreter}, + {0, AC_WRITE, 0, 0, 305, AUTO, "AFMicroAdjRegisteredLenses", &saAFMicroAdjRegisteredLensesInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; -const TagAttrib sonyCameraSettingsAttribs[]={ - {0, AC_WRITE, 0, 0, 0, AUTO, "ExposureTime", &saExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "FNumber", &saFNumberInterpreter}, - {0, AC_WRITE, 0, 0, 4, AUTO, "DriveMode", &saDriveMode}, - {0, AC_WRITE, 0, 0, 6, AUTO, "WhiteBalanceFineTune",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 16, AUTO, "FocusModeSetting",&saFocusMode}, - {0, AC_WRITE, 0, 0, 17, AUTO, "AFAreaMode",&saAFAreaMode}, - {0, AC_WRITE, 0, 0, 18, AUTO, "AFPointSelected", &saAFPointSelected}, - {0, AC_WRITE, 0, 0, 21, AUTO, "MeteringMode",&saMeteringMode1_4}, - {0, AC_WRITE, 0, 0, 22, AUTO, "ISOSetting",&saISOSettingInterpreter}, - {0, AC_WRITE, 0, 0, 24, AUTO, "DynamicRangeOptimizerMode", &saDynamicRangeOptimizerMode}, - {0, AC_WRITE, 0, 0, 25, AUTO, "DynamicRangeOptimizerLevel",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 26, AUTO, "CreativeStyle",&saCreativeStyle}, - {0, AC_WRITE, 0, 0, 28, AUTO, "Sharpness",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 29, AUTO, "Contrast",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 30, AUTO, "Saturation",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 31, AUTO, "ZoneMatchingValue",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 34, AUTO, "Brightness",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 35, AUTO, "FlashMode",&saFlashMode}, - {0, AC_WRITE, 0, 0, 40, AUTO, "PrioritySetupShutterRelease",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 41, AUTO, "AFIlluminator",&saAFIlluminator}, - {0, AC_WRITE, 0, 0, 42, AUTO, "AFWithShutter",&saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 43, AUTO, "LongExposureNoiseReduction",&saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 44, AUTO, "HighISONoiseReduction",&saHighISONoiseReduction3}, - {0, AC_WRITE, 0, 0, 45, AUTO, "ImageStyle",&saImageStyleInterpreter}, - {0, AC_WRITE, 0, 0, 60, AUTO, "ExposureProgram",&saExposureProgram}, - {0, AC_WRITE, 0, 0, 61, AUTO, "ImageStabilization",&saOnOffInterpreter}, - {0, AC_WRITE, 0, 0, 63, AUTO, "Rotation",&saRotation}, - {0, AC_WRITE, 0, 0, 77, AUTO, "FocusMode",&saFocusMode}, - {0, AC_WRITE, 0, 0, 83, AUTO, "FocusStatus",&saFocusStatusInterpreter}, - {0, AC_WRITE, 0, 0, 84, AUTO, "SonyImageSize",&saSonyImageSize}, - {0, AC_WRITE, 0, 0, 85, AUTO, "AspectRatio",&saAspectRatio}, - {0, AC_WRITE, 0, 0, 86, AUTO, "Quality",&saQualityInterpreter2}, - {0, AC_WRITE, 0, 0, 88, AUTO, "ExposureLevelIncrements",&saExposureLevelIncrements}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; +const TagAttrib sonyCameraSettingsAttribs[] = { + {0, AC_WRITE, 0, 0, 0, AUTO, "ExposureTime", &saExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "FNumber", &saFNumberInterpreter}, + {0, AC_WRITE, 0, 0, 4, AUTO, "DriveMode", &saDriveMode}, + {0, AC_WRITE, 0, 0, 6, AUTO, "WhiteBalanceFineTune", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 16, AUTO, "FocusModeSetting", &saFocusMode}, + {0, AC_WRITE, 0, 0, 17, AUTO, "AFAreaMode", &saAFAreaMode}, + {0, AC_WRITE, 0, 0, 18, AUTO, "AFPointSelected", &saAFPointSelected}, + {0, AC_WRITE, 0, 0, 21, AUTO, "MeteringMode", &saMeteringMode1_4}, + {0, AC_WRITE, 0, 0, 22, AUTO, "ISOSetting", &saISOSettingInterpreter}, + {0, AC_WRITE, 0, 0, 24, AUTO, "DynamicRangeOptimizerMode", &saDynamicRangeOptimizerMode}, + {0, AC_WRITE, 0, 0, 25, AUTO, "DynamicRangeOptimizerLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 26, AUTO, "CreativeStyle", &saCreativeStyle}, + {0, AC_WRITE, 0, 0, 28, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 29, AUTO, "Contrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 30, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 31, AUTO, "ZoneMatchingValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 34, AUTO, "Brightness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 35, AUTO, "FlashMode", &saFlashMode}, + {0, AC_WRITE, 0, 0, 40, AUTO, "PrioritySetupShutterRelease", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 41, AUTO, "AFIlluminator", &saAFIlluminator}, + {0, AC_WRITE, 0, 0, 42, AUTO, "AFWithShutter", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 43, AUTO, "LongExposureNoiseReduction", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 44, AUTO, "HighISONoiseReduction", &saHighISONoiseReduction3}, + {0, AC_WRITE, 0, 0, 45, AUTO, "ImageStyle", &saImageStyleInterpreter}, + {0, AC_WRITE, 0, 0, 60, AUTO, "ExposureProgram", &saExposureProgram}, + {0, AC_WRITE, 0, 0, 61, AUTO, "ImageStabilization", &saOnOffInterpreter}, + {0, AC_WRITE, 0, 0, 63, AUTO, "Rotation", &saRotation}, + {0, AC_WRITE, 0, 0, 77, AUTO, "FocusMode", &saFocusMode}, + {0, AC_WRITE, 0, 0, 83, AUTO, "FocusStatus", &saFocusStatusInterpreter}, + {0, AC_WRITE, 0, 0, 84, AUTO, "SonyImageSize", &saSonyImageSize}, + {0, AC_WRITE, 0, 0, 85, AUTO, "AspectRatio", &saAspectRatio}, + {0, AC_WRITE, 0, 0, 86, AUTO, "Quality", &saQualityInterpreter2}, + {0, AC_WRITE, 0, 0, 88, AUTO, "ExposureLevelIncrements", &saExposureLevelIncrements}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; -const TagAttrib sonyCameraSettingsAttribs2[]={ - {0, AC_WRITE, 0, 0, 0, AUTO, "ExposureTime", &saExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "FNumber", &saFNumberInterpreter}, - {0, AC_WRITE, 0, 0, 11, AUTO, "ColorTemperatureSetting", &saColorTemperatureSettingInterpreter}, - {0, AC_WRITE, 0, 0, 15, AUTO, "FocusMode",&saFocusMode2}, - {0, AC_WRITE, 0, 0, 16, AUTO, "AFAreaMode",&saAFAreaMode}, - {0, AC_WRITE, 0, 0, 17, AUTO, "AFPointSelected",&saAFPointSelected2}, - {0, AC_WRITE, 0, 0, 19, AUTO, "MeteringMode",&saMeteringMode1_4}, - {0, AC_WRITE, 0, 0, 20, AUTO, "ISOSetting",&saISOSettingInterpreter}, - {0, AC_WRITE, 0, 0, 22, AUTO, "DynamicRangeOptimizerMode",&saDynamicRangeOptimizerMode}, - {0, AC_WRITE, 0, 0, 23, AUTO, "DynamicRangeOptimizerLevel",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 24, AUTO, "CreativeStyle",&saCreativeStyle2}, - {0, AC_WRITE, 0, 0, 25, AUTO, "Sharpness",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 26, AUTO, "Contrast",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 27, AUTO, "Saturation",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 35, AUTO, "FlashMode",&saFlashMode}, - {0, AC_WRITE, 0, 0, 38, AUTO, "HighISONoiseReduction",&saHighISONoiseReduction4}, - {0, AC_WRITE, 0, 0, 60, AUTO, "ExposureProgram",&saExposureProgram}, - {0, AC_WRITE, 0, 0, 63, AUTO, "Rotation",&saRotation}, - {0, AC_WRITE, 0, 0, 83, AUTO, "FocusStatus",&saFocusStatusInterpreter}, - {0, AC_WRITE, 0, 0, 84, AUTO, "SonyImageSize",&saSonyImageSize}, - {0, AC_WRITE, 0, 0, 85, AUTO, "AspectRatio",&saAspectRatio}, - {0, AC_WRITE, 0, 0, 86, AUTO, "Quality",&saQualityInterpreter2}, - {0, AC_WRITE, 0, 0, 88, AUTO, "ExposureLevelIncrements",&saExposureLevelIncrements}, - {0, AC_WRITE, 0, 0,126, AUTO, "DriveMode", &saDriveMode2}, - {0, AC_WRITE, 0, 0,131, AUTO, "ColorSpace", &saColorSpace5_6}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; +const TagAttrib sonyCameraSettingsAttribs2[] = { + {0, AC_WRITE, 0, 0, 0, AUTO, "ExposureTime", &saExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "FNumber", &saFNumberInterpreter}, + {0, AC_WRITE, 0, 0, 11, AUTO, "ColorTemperatureSetting", &saColorTemperatureSettingInterpreter}, + {0, AC_WRITE, 0, 0, 15, AUTO, "FocusMode", &saFocusMode2}, + {0, AC_WRITE, 0, 0, 16, AUTO, "AFAreaMode", &saAFAreaMode}, + {0, AC_WRITE, 0, 0, 17, AUTO, "AFPointSelected", &saAFPointSelected2}, + {0, AC_WRITE, 0, 0, 19, AUTO, "MeteringMode", &saMeteringMode1_4}, + {0, AC_WRITE, 0, 0, 20, AUTO, "ISOSetting", &saISOSettingInterpreter}, + {0, AC_WRITE, 0, 0, 22, AUTO, "DynamicRangeOptimizerMode", &saDynamicRangeOptimizerMode}, + {0, AC_WRITE, 0, 0, 23, AUTO, "DynamicRangeOptimizerLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 24, AUTO, "CreativeStyle", &saCreativeStyle2}, + {0, AC_WRITE, 0, 0, 25, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 26, AUTO, "Contrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 27, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 35, AUTO, "FlashMode", &saFlashMode}, + {0, AC_WRITE, 0, 0, 38, AUTO, "HighISONoiseReduction", &saHighISONoiseReduction4}, + {0, AC_WRITE, 0, 0, 60, AUTO, "ExposureProgram", &saExposureProgram}, + {0, AC_WRITE, 0, 0, 63, AUTO, "Rotation", &saRotation}, + {0, AC_WRITE, 0, 0, 83, AUTO, "FocusStatus", &saFocusStatusInterpreter}, + {0, AC_WRITE, 0, 0, 84, AUTO, "SonyImageSize", &saSonyImageSize}, + {0, AC_WRITE, 0, 0, 85, AUTO, "AspectRatio", &saAspectRatio}, + {0, AC_WRITE, 0, 0, 86, AUTO, "Quality", &saQualityInterpreter2}, + {0, AC_WRITE, 0, 0, 88, AUTO, "ExposureLevelIncrements", &saExposureLevelIncrements}, + {0, AC_WRITE, 0, 0, 126, AUTO, "DriveMode", &saDriveMode2}, + {0, AC_WRITE, 0, 0, 131, AUTO, "ColorSpace", &saColorSpace5_6}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; -const TagAttrib sonyCameraSettingsAttribs3[]={ - {0, AC_WRITE, 0, 0, 0, AUTO, "ShutterSpeedSetting",&saExposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 1, AUTO, "ApertureSetting",&saFNumberInterpreter}, - {0, AC_WRITE, 0, 0, 2, AUTO, "ISOSetting",&saISOSettingInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "ExposureCompensationSet",&saExposureCompSetInterpreter}, - {0, AC_WRITE, 0, 0, 3, AUTO, "DriveModeSetting",&saDriveMode3}, - {0, AC_WRITE, 0, 0, 5, AUTO, "ExposureProgram",&saExposureProgram2}, - {0, AC_WRITE, 0, 0, 6, AUTO, "FocusModeSetting",&saFocusModeSetting3}, - {0, AC_WRITE, 0, 0, 7, AUTO, "MeteringMode",&saMeteringMode1_3}, - {0, AC_WRITE, 0, 0, 9, AUTO, "SonyImageSize",&saSonyImageSize3}, - {0, AC_WRITE, 0, 0, 10, AUTO, "AspectRatio",&saAspectRatio2}, - {0, AC_WRITE, 0, 0, 11, AUTO, "Quality",&saQualityInterpreter3}, - {0, AC_WRITE, 0, 0, 12, AUTO, "DynamicRangeOptimizerSetting", &saDynamicRangeOptimizerSetting}, - {0, AC_WRITE, 0, 0, 14, AUTO, "ColorSpace", &saColorSpace1_2}, - {0, AC_WRITE, 0, 0, 15, AUTO, "CreativeStyleSetting",&saCreativeStyleSetting}, - {0, AC_WRITE, 0, 0, 16, AUTO, "Contrast",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 17, AUTO, "Saturation",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 18, AUTO, "Sharpness",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 22, AUTO, "WhiteBalance",&saWhiteBalanceSettingInterpreter}, - {0, AC_WRITE, 0, 0, 23, AUTO, "ColorTemperatureSetting", &saColorTemperatureSettingInterpreter}, - {0, AC_WRITE, 0, 0, 23, AUTO, "ColorCompensationFilterSet", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 32, AUTO, "FlashMode",&saFlashMode2}, - {0, AC_WRITE, 0, 0, 33, AUTO, "FlashControl",&saFlashControl}, - {0, AC_WRITE, 0, 0, 35, AUTO, "FlashExposureCompSet", &saExposureCompSetInterpreter}, - {0, AC_WRITE, 0, 0, 36, AUTO, "AFAreaMode",&saAFAreaMode2}, - {0, AC_WRITE, 0, 0, 37, AUTO, "LongExposureNoiseReduction",&saOnOffInterpreter2}, - {0, AC_WRITE, 0, 0, 38, AUTO, "HighISONoiseReduction",&saHighISONoiseReduction5}, - {0, AC_WRITE, 0, 0, 39, AUTO, "SmileShutterMode",&saSmileShutterMode}, - {0, AC_WRITE, 0, 0, 40, AUTO, "RedEyeReduction",&saOnOffInterpreter2}, - {0, AC_WRITE, 0, 0, 45, AUTO, "HDRSetting",&saOnOffInterpreter3}, - {0, AC_WRITE, 0, 0, 46, AUTO, "HDRLevel",&saHDRLevel}, - {0, AC_WRITE, 0, 0, 47, AUTO, "ViewingMode",&saViewingMode}, - {0, AC_WRITE, 0, 0, 48, AUTO, "FaceDetection",&saOnOffInterpreter2}, - {0, AC_WRITE, 0, 0, 49, AUTO, "SmileShutter",&saOnOffInterpreter2}, - {0, AC_WRITE, 0, 0, 50, AUTO, "SweepPanoramaSize",&saSweepPanoramaSize}, - {0, AC_WRITE, 0, 0, 51, AUTO, "SweepPanoramaDirection",&saSweepPanoramaDirection}, - {0, AC_WRITE, 0, 0, 52, AUTO, "DriveMode",&saDriveMode3}, - {0, AC_WRITE, 0, 0, 53, AUTO, "MultiFrameNoiseReduction",&saOnOffInterpreter4}, - {0, AC_WRITE, 0, 0, 54, AUTO, "LiveViewAFSetting",&saLiveViewAFSetting}, - {0, AC_WRITE, 0, 0, 56, AUTO, "PanoramaSize3D",&saPanoramaSize3D}, - {0, AC_WRITE, 0, 0, 131, AUTO, "AFButtonPressed",&saNoYesInterpreter}, - {0, AC_WRITE, 0, 0, 132, AUTO, "LiveViewMetering",&saLiveViewMetering}, - {0, AC_WRITE, 0, 0, 133, AUTO, "ViewingMode2",&saViewingMode}, - {0, AC_WRITE, 0, 0, 134, AUTO, "AELock",&saOnOffInterpreter5}, - {0, AC_WRITE, 0, 0, 135, AUTO, "FlashAction",&saFlashAction}, - {0, AC_WRITE, 0, 0, 139, AUTO, "LiveViewFocusMode",&saLiveViewFocusMode}, - {0, AC_WRITE, 0, 0, 153, AUTO, "LensMount",&saLensMount}, - {0, AC_WRITE, 0, 0, 643, AUTO, "AFButtonPressed",&saNoYesInterpreter}, - {0, AC_WRITE, 0, 0, 644, AUTO, "LiveViewMetering",&saLiveViewMetering}, - {0, AC_WRITE, 0, 0, 645, AUTO, "ViewingMode2",&saViewingMode}, - {0, AC_WRITE, 0, 0, 646, AUTO, "AELock",&saOnOffInterpreter5}, - {0, AC_WRITE, 0, 0, 647, AUTO, "FlashAction",&saFlashAction}, - {0, AC_WRITE, 0, 0, 651, AUTO, "LiveViewFocusMode",&saLiveViewFocusMode}, - {0, AC_WRITE, 0, 0, 1015, SHORT, "LensType2",&saLensID2Interpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; +const TagAttrib sonyCameraSettingsAttribs3[] = { + {0, AC_WRITE, 0, 0, 0, AUTO, "ShutterSpeedSetting", &saExposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 1, AUTO, "ApertureSetting", &saFNumberInterpreter}, + {0, AC_WRITE, 0, 0, 2, AUTO, "ISOSetting", &saISOSettingInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "ExposureCompensationSet", &saExposureCompSetInterpreter}, + {0, AC_WRITE, 0, 0, 3, AUTO, "DriveModeSetting", &saDriveMode3}, + {0, AC_WRITE, 0, 0, 5, AUTO, "ExposureProgram", &saExposureProgram2}, + {0, AC_WRITE, 0, 0, 6, AUTO, "FocusModeSetting", &saFocusModeSetting3}, + {0, AC_WRITE, 0, 0, 7, AUTO, "MeteringMode", &saMeteringMode1_3}, + {0, AC_WRITE, 0, 0, 9, AUTO, "SonyImageSize", &saSonyImageSize3}, + {0, AC_WRITE, 0, 0, 10, AUTO, "AspectRatio", &saAspectRatio2}, + {0, AC_WRITE, 0, 0, 11, AUTO, "Quality", &saQualityInterpreter3}, + {0, AC_WRITE, 0, 0, 12, AUTO, "DynamicRangeOptimizerSetting", &saDynamicRangeOptimizerSetting}, + {0, AC_WRITE, 0, 0, 14, AUTO, "ColorSpace", &saColorSpace1_2}, + {0, AC_WRITE, 0, 0, 15, AUTO, "CreativeStyleSetting", &saCreativeStyleSetting}, + {0, AC_WRITE, 0, 0, 16, AUTO, "Contrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 17, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 18, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 22, AUTO, "WhiteBalance", &saWhiteBalanceSettingInterpreter}, + {0, AC_WRITE, 0, 0, 23, AUTO, "ColorTemperatureSetting", &saColorTemperatureSettingInterpreter}, + {0, AC_WRITE, 0, 0, 23, AUTO, "ColorCompensationFilterSet", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 32, AUTO, "FlashMode", &saFlashMode2}, + {0, AC_WRITE, 0, 0, 33, AUTO, "FlashControl", &saFlashControl}, + {0, AC_WRITE, 0, 0, 35, AUTO, "FlashExposureCompSet", &saExposureCompSetInterpreter}, + {0, AC_WRITE, 0, 0, 36, AUTO, "AFAreaMode", &saAFAreaMode2}, + {0, AC_WRITE, 0, 0, 37, AUTO, "LongExposureNoiseReduction", &saOnOffInterpreter2}, + {0, AC_WRITE, 0, 0, 38, AUTO, "HighISONoiseReduction", &saHighISONoiseReduction5}, + {0, AC_WRITE, 0, 0, 39, AUTO, "SmileShutterMode", &saSmileShutterMode}, + {0, AC_WRITE, 0, 0, 40, AUTO, "RedEyeReduction", &saOnOffInterpreter2}, + {0, AC_WRITE, 0, 0, 45, AUTO, "HDRSetting", &saOnOffInterpreter3}, + {0, AC_WRITE, 0, 0, 46, AUTO, "HDRLevel", &saHDRLevel}, + {0, AC_WRITE, 0, 0, 47, AUTO, "ViewingMode", &saViewingMode}, + {0, AC_WRITE, 0, 0, 48, AUTO, "FaceDetection", &saOnOffInterpreter2}, + {0, AC_WRITE, 0, 0, 49, AUTO, "SmileShutter", &saOnOffInterpreter2}, + {0, AC_WRITE, 0, 0, 50, AUTO, "SweepPanoramaSize", &saSweepPanoramaSize}, + {0, AC_WRITE, 0, 0, 51, AUTO, "SweepPanoramaDirection", &saSweepPanoramaDirection}, + {0, AC_WRITE, 0, 0, 52, AUTO, "DriveMode", &saDriveMode3}, + {0, AC_WRITE, 0, 0, 53, AUTO, "MultiFrameNoiseReduction", &saOnOffInterpreter4}, + {0, AC_WRITE, 0, 0, 54, AUTO, "LiveViewAFSetting", &saLiveViewAFSetting}, + {0, AC_WRITE, 0, 0, 56, AUTO, "PanoramaSize3D", &saPanoramaSize3D}, + {0, AC_WRITE, 0, 0, 131, AUTO, "AFButtonPressed", &saNoYesInterpreter}, + {0, AC_WRITE, 0, 0, 132, AUTO, "LiveViewMetering", &saLiveViewMetering}, + {0, AC_WRITE, 0, 0, 133, AUTO, "ViewingMode2", &saViewingMode}, + {0, AC_WRITE, 0, 0, 134, AUTO, "AELock", &saOnOffInterpreter5}, + {0, AC_WRITE, 0, 0, 135, AUTO, "FlashAction", &saFlashAction}, + {0, AC_WRITE, 0, 0, 139, AUTO, "LiveViewFocusMode", &saLiveViewFocusMode}, + {0, AC_WRITE, 0, 0, 153, AUTO, "LensMount", &saLensMount}, + {0, AC_WRITE, 0, 0, 643, AUTO, "AFButtonPressed", &saNoYesInterpreter}, + {0, AC_WRITE, 0, 0, 644, AUTO, "LiveViewMetering", &saLiveViewMetering}, + {0, AC_WRITE, 0, 0, 645, AUTO, "ViewingMode2", &saViewingMode}, + {0, AC_WRITE, 0, 0, 646, AUTO, "AELock", &saOnOffInterpreter5}, + {0, AC_WRITE, 0, 0, 647, AUTO, "FlashAction", &saFlashAction}, + {0, AC_WRITE, 0, 0, 651, AUTO, "LiveViewFocusMode", &saLiveViewFocusMode}, + {0, AC_WRITE, 0, 0, 1015, SHORT, "LensType2", &saLensID2Interpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; /*const TagAttrib sonyDNGMakerNote[]={ {0, AC_WRITE, 0, 0, 0x7200, AUTO, "SonyOffset", &stdInterpreter}, diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index 0990d3a4c..e50299c3e 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -8,7 +8,7 @@ * 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 @@ -25,391 +25,475 @@ #include "rtexif.h" -namespace rtexif { +namespace rtexif +{ -class ColorSpaceInterpreter : public ChoiceInterpreter { +class ColorSpaceInterpreter : public ChoiceInterpreter +{ - public: - ColorSpaceInterpreter () { - choices[1] = "sRGB"; - choices[2] = "Adobe RGB"; - choices[0xffff] = "Uncalibrated"; - } +public: + ColorSpaceInterpreter () + { + choices[1] = "sRGB"; + choices[2] = "Adobe RGB"; + choices[0xffff] = "Uncalibrated"; + } }; ColorSpaceInterpreter colorSpaceInterpreter; -class PreviewColorSpaceInterpreter : public ChoiceInterpreter { +class PreviewColorSpaceInterpreter : public ChoiceInterpreter +{ - public: - PreviewColorSpaceInterpreter () { - choices[0] = "Unknown"; - choices[1] = "Gray Gamma 2.2"; - choices[2] = "sRGB"; - choices[3] = "Adobe RGB"; - choices[4] = "ProPhoto RGB"; - } +public: + PreviewColorSpaceInterpreter () + { + choices[0] = "Unknown"; + choices[1] = "Gray Gamma 2.2"; + choices[2] = "sRGB"; + choices[3] = "Adobe RGB"; + choices[4] = "ProPhoto RGB"; + } }; PreviewColorSpaceInterpreter previewColorSpaceInterpreter; -class LinearSRGBInterpreter : public ChoiceInterpreter { +class LinearSRGBInterpreter : public ChoiceInterpreter +{ - public: - LinearSRGBInterpreter () { - choices[0] = "Linear"; - choices[1] = "sRGB"; - } +public: + LinearSRGBInterpreter () + { + choices[0] = "Linear"; + choices[1] = "sRGB"; + } }; LinearSRGBInterpreter linearSRGBInterpreter; -class DefaultBlackRenderInterpreter : public ChoiceInterpreter { +class DefaultBlackRenderInterpreter : public ChoiceInterpreter +{ - public: - DefaultBlackRenderInterpreter () { - choices[0] = "Auto"; - choices[1] = "None"; - } +public: + DefaultBlackRenderInterpreter () + { + choices[0] = "Auto"; + choices[1] = "None"; + } }; DefaultBlackRenderInterpreter defaultBlackRenderInterpreter; -class ExposureProgramInterpreter : public ChoiceInterpreter { +class ExposureProgramInterpreter : public ChoiceInterpreter +{ - public: - ExposureProgramInterpreter () { - choices[0] = "Not defined"; - choices[1] = "Manual"; - choices[2] = "Normal program"; - choices[3] = "Aperture priority"; - choices[4] = "Shutter priority"; - choices[5] = "Creative program"; - choices[6] = "Action program"; - choices[7] = "Portrait mode"; - choices[8] = "Landscape mode"; - } +public: + ExposureProgramInterpreter () + { + choices[0] = "Not defined"; + choices[1] = "Manual"; + choices[2] = "Normal program"; + choices[3] = "Aperture priority"; + choices[4] = "Shutter priority"; + choices[5] = "Creative program"; + choices[6] = "Action program"; + choices[7] = "Portrait mode"; + choices[8] = "Landscape mode"; + } }; ExposureProgramInterpreter exposureProgramInterpreter; -class MeteringModeInterpreter : public ChoiceInterpreter { +class MeteringModeInterpreter : public ChoiceInterpreter +{ - public: - MeteringModeInterpreter () { - choices[0] = "Unknown"; - choices[1] = "Average"; - choices[2] = "Center weighted"; - choices[3] = "Spot"; - choices[4] = "Multispot"; - choices[5] = "Pattern"; - choices[6] = "Partial"; - choices[255] = "Other"; - } +public: + MeteringModeInterpreter () + { + choices[0] = "Unknown"; + choices[1] = "Average"; + choices[2] = "Center weighted"; + choices[3] = "Spot"; + choices[4] = "Multispot"; + choices[5] = "Pattern"; + choices[6] = "Partial"; + choices[255] = "Other"; + } }; MeteringModeInterpreter meteringModeInterpreter; -class ExposureModeInterpreter : public ChoiceInterpreter { +class ExposureModeInterpreter : public ChoiceInterpreter +{ - public: - ExposureModeInterpreter () { - choices[0] = "Auto exposure"; - choices[1] = "Manual exposure"; - choices[2] = "Auto bracket"; - } +public: + ExposureModeInterpreter () + { + choices[0] = "Auto exposure"; + choices[1] = "Manual exposure"; + choices[2] = "Auto bracket"; + } }; ExposureModeInterpreter exposureModeInterpreter; -class WhiteBalanceInterpreter : public ChoiceInterpreter { +class WhiteBalanceInterpreter : public ChoiceInterpreter +{ - public: - WhiteBalanceInterpreter () { - choices[0] = "Auto white balance"; - choices[1] = "Manual white balance"; - } +public: + WhiteBalanceInterpreter () + { + choices[0] = "Auto white balance"; + choices[1] = "Manual white balance"; + } }; WhiteBalanceInterpreter whiteBalanceInterpreter; -class SceneCaptureInterpreter : public ChoiceInterpreter { +class SceneCaptureInterpreter : public ChoiceInterpreter +{ - public: - SceneCaptureInterpreter () { - choices[0] = "Standard"; - choices[1] = "Landscape"; - choices[2] = "Portrait"; - choices[3] = "Night scene"; - } +public: + SceneCaptureInterpreter () + { + choices[0] = "Standard"; + choices[1] = "Landscape"; + choices[2] = "Portrait"; + choices[3] = "Night scene"; + } }; SceneCaptureInterpreter sceneCaptureInterpreter; -class GainControlInterpreter : public ChoiceInterpreter { +class GainControlInterpreter : public ChoiceInterpreter +{ - public: - GainControlInterpreter () { - choices[0] = "None"; - choices[1] = "Low gain up"; - choices[2] = "High gain up"; - choices[3] = "Low gain down"; - choices[4] = "High gain down"; - } +public: + GainControlInterpreter () + { + choices[0] = "None"; + choices[1] = "Low gain up"; + choices[2] = "High gain up"; + choices[3] = "Low gain down"; + choices[4] = "High gain down"; + } }; GainControlInterpreter gainControlInterpreter; -class ContrastInterpreter : public ChoiceInterpreter { +class ContrastInterpreter : public ChoiceInterpreter +{ - public: - ContrastInterpreter () { - choices[0] = "Normal"; - choices[1] = "Soft"; - choices[2] = "Hard"; - } +public: + ContrastInterpreter () + { + choices[0] = "Normal"; + choices[1] = "Soft"; + choices[2] = "Hard"; + } }; ContrastInterpreter contrastInterpreter; -class SharpnessInterpreter : public ChoiceInterpreter { +class SharpnessInterpreter : public ChoiceInterpreter +{ - public: - SharpnessInterpreter () { - choices[0] = "Normal"; - choices[1] = "Soft"; - choices[2] = "Hard"; - } +public: + SharpnessInterpreter () + { + choices[0] = "Normal"; + choices[1] = "Soft"; + choices[2] = "Hard"; + } }; SharpnessInterpreter sharpnessInterpreter; -class SaturationInterpreter : public ChoiceInterpreter { +class SaturationInterpreter : public ChoiceInterpreter +{ - public: - SaturationInterpreter () { - choices[0] = "Normal"; - choices[1] = "Low saturation"; - choices[2] = "High saturation"; - } +public: + SaturationInterpreter () + { + choices[0] = "Normal"; + choices[1] = "Low saturation"; + choices[2] = "High saturation"; + } }; SaturationInterpreter saturationInterpreter; -class FlashInterpreter : public ChoiceInterpreter { +class FlashInterpreter : public ChoiceInterpreter +{ - public: - FlashInterpreter () { - choices[0x0000] = "Flash did not fire"; - choices[0x0001] = "Flash fired"; - choices[0x0005] = "Strobe return light not detected"; - choices[0x0007] = "Strobe return light detected"; - choices[0x0009] = "Flash fired, compulsory flash mode"; - choices[0x000D] = "Flash fired, compulsory flash mode, return light not detected"; - choices[0x000F] = "Flash fired, compulsory flash mode, return light detected"; - choices[0x0010] = "Flash did not fire, compulsory flash mode"; - choices[0x0018] = "Flash did not fire, auto mode"; - choices[0x0019] = "Flash fired, auto mode"; - choices[0x001D] = "Flash fired, auto mode, return light not detected"; - choices[0x001F] = "Flash fired, auto mode, return light detected"; - choices[0x0020] = "No flash function"; - choices[0x0041] = "Flash fired, red-eye reduction mode"; - choices[0x0045] = "Flash fired, red-eye reduction mode, return light not detected"; - choices[0x0047] = "Flash fired, red-eye reduction mode, return light detected"; - choices[0x0049] = "Flash fired, compulsory flash mode, red-eye reduction mode"; - choices[0x004D] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected"; - choices[0x004F] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected"; - choices[0x0059] = "Flash fired, auto mode, red-eye reduction mode"; - choices[0x005D] = "Flash fired, auto mode, return light not detected, red-eye reduction mode"; - choices[0x005F] = "Flash fired, auto mode, return light detected, red-eye reduction mode"; - } +public: + FlashInterpreter () + { + choices[0x0000] = "Flash did not fire"; + choices[0x0001] = "Flash fired"; + choices[0x0005] = "Strobe return light not detected"; + choices[0x0007] = "Strobe return light detected"; + choices[0x0009] = "Flash fired, compulsory flash mode"; + choices[0x000D] = "Flash fired, compulsory flash mode, return light not detected"; + choices[0x000F] = "Flash fired, compulsory flash mode, return light detected"; + choices[0x0010] = "Flash did not fire, compulsory flash mode"; + choices[0x0018] = "Flash did not fire, auto mode"; + choices[0x0019] = "Flash fired, auto mode"; + choices[0x001D] = "Flash fired, auto mode, return light not detected"; + choices[0x001F] = "Flash fired, auto mode, return light detected"; + choices[0x0020] = "No flash function"; + choices[0x0041] = "Flash fired, red-eye reduction mode"; + choices[0x0045] = "Flash fired, red-eye reduction mode, return light not detected"; + choices[0x0047] = "Flash fired, red-eye reduction mode, return light detected"; + choices[0x0049] = "Flash fired, compulsory flash mode, red-eye reduction mode"; + choices[0x004D] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected"; + choices[0x004F] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected"; + choices[0x0059] = "Flash fired, auto mode, red-eye reduction mode"; + choices[0x005D] = "Flash fired, auto mode, return light not detected, red-eye reduction mode"; + choices[0x005F] = "Flash fired, auto mode, return light detected, red-eye reduction mode"; + } }; FlashInterpreter flashInterpreter; -class LightSourceInterpreter : public ChoiceInterpreter { +class LightSourceInterpreter : public ChoiceInterpreter +{ - public: - LightSourceInterpreter () { - choices[0] = "Unknown"; - choices[1] = "Daylight"; - choices[2] = "Fluorescent"; - choices[3] = "Tungsten"; - choices[4] = "Flash"; - choices[9] = "Fine weather"; - choices[10] = "Cloudy weather"; - choices[11] = "Shade"; - choices[12] = "Daylight fluorescent"; - choices[13] = "Day white fluorescent"; - choices[14] = "Cool white fluorescent"; - choices[15] = "White fluorescent"; - choices[17] = "Standard light A"; - choices[18] = "Standard light B"; - choices[19] = "Standard light C"; - choices[20] = "D55"; - choices[21] = "D65"; - choices[22] = "D75"; - choices[23] = "D50"; - choices[24] = "ISO studio tungsten"; - choices[255] = "Other light source"; - } +public: + LightSourceInterpreter () + { + choices[0] = "Unknown"; + choices[1] = "Daylight"; + choices[2] = "Fluorescent"; + choices[3] = "Tungsten"; + choices[4] = "Flash"; + choices[9] = "Fine weather"; + choices[10] = "Cloudy weather"; + choices[11] = "Shade"; + choices[12] = "Daylight fluorescent"; + choices[13] = "Day white fluorescent"; + choices[14] = "Cool white fluorescent"; + choices[15] = "White fluorescent"; + choices[17] = "Standard light A"; + choices[18] = "Standard light B"; + choices[19] = "Standard light C"; + choices[20] = "D55"; + choices[21] = "D65"; + choices[22] = "D75"; + choices[23] = "D50"; + choices[24] = "ISO studio tungsten"; + choices[255] = "Other light source"; + } }; LightSourceInterpreter lightSourceInterpreter; -class CompressionInterpreter : public ChoiceInterpreter { +class CompressionInterpreter : public ChoiceInterpreter +{ - public: - CompressionInterpreter () { - choices[1] = "Uncompressed"; - choices[6] = "JPEG Compression"; - } +public: + CompressionInterpreter () + { + choices[1] = "Uncompressed"; + choices[6] = "JPEG Compression"; + } }; CompressionInterpreter compressionInterpreter; -class PhotometricInterpreter : public ChoiceInterpreter { +class PhotometricInterpreter : public ChoiceInterpreter +{ - public: - PhotometricInterpreter () { - choices[2] = "RGB"; - choices[6] = "YCbCr"; - } +public: + PhotometricInterpreter () + { + choices[2] = "RGB"; + choices[6] = "YCbCr"; + } }; PhotometricInterpreter photometricInterpreter; -class ProfileEmbedPolicyInterpreter : public ChoiceInterpreter { +class ProfileEmbedPolicyInterpreter : public ChoiceInterpreter +{ - public: - ProfileEmbedPolicyInterpreter () { - choices[0] = "Allow Copying"; - choices[1] = "Embed if Used"; - choices[2] = "Never Embed"; - choices[3] = "No Restrictions"; - } +public: + ProfileEmbedPolicyInterpreter () + { + choices[0] = "Allow Copying"; + choices[1] = "Embed if Used"; + choices[2] = "Never Embed"; + choices[3] = "No Restrictions"; + } }; ProfileEmbedPolicyInterpreter profileEmbedPolicyInterpreter; -class PlanarConfigInterpreter : public ChoiceInterpreter { +class PlanarConfigInterpreter : public ChoiceInterpreter +{ - public: - PlanarConfigInterpreter () { - choices[1] = "Chunky format"; - choices[2] = "Planar format"; - } +public: + PlanarConfigInterpreter () + { + choices[1] = "Chunky format"; + choices[2] = "Planar format"; + } }; PlanarConfigInterpreter planarConfigInterpreter; -class FNumberInterpreter : public Interpreter { - public: - FNumberInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - double v = t->toDouble(); - if( v < 0. || v > 1000. ) return "undef"; - sprintf (buffer, "%0.1f", v); - return buffer; +class FNumberInterpreter : public Interpreter +{ +public: + FNumberInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + double v = t->toDouble(); + + if( v < 0. || v > 1000. ) { + return "undef"; } + + sprintf (buffer, "%0.1f", v); + return buffer; + } }; FNumberInterpreter fNumberInterpreter; -class ApertureInterpreter : public Interpreter { - public: - ApertureInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - double v = pow(2.0, t->toDouble()/2.0); - if( v < 0. || v > 1000. ) return "undef"; - sprintf (buffer, "%.1f", v ); - return buffer; +class ApertureInterpreter : public Interpreter +{ +public: + ApertureInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + double v = pow(2.0, t->toDouble() / 2.0); + + if( v < 0. || v > 1000. ) { + return "undef"; } + + sprintf (buffer, "%.1f", v ); + return buffer; + } }; ApertureInterpreter apertureInterpreter; -class ExposureBiasInterpreter : public Interpreter { - public: - ExposureBiasInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - double v = t->toDouble(); - if( v < -1000. || v > 1000. ) return "undef"; - sprintf (buffer, "%+0.2f", v ); - return buffer; +class ExposureBiasInterpreter : public Interpreter +{ +public: + ExposureBiasInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + double v = t->toDouble(); + + if( v < -1000. || v > 1000. ) { + return "undef"; } + + sprintf (buffer, "%+0.2f", v ); + return buffer; + } }; ExposureBiasInterpreter exposureBiasInterpreter; -class ShutterSpeedInterpreter : public Interpreter { - public: - ShutterSpeedInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[1024]; - double d = pow (2.0, -t->toDouble()); - if (d > 0.0 && d < 0.9) - sprintf (buffer, "1/%.0f", 1.0 / d); - else - sprintf (buffer, "%.1f", d); - return buffer; +class ShutterSpeedInterpreter : public Interpreter +{ +public: + ShutterSpeedInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[1024]; + double d = pow (2.0, -t->toDouble()); + + if (d > 0.0 && d < 0.9) { + sprintf (buffer, "1/%.0f", 1.0 / d); + } else { + sprintf (buffer, "%.1f", d); } + + return buffer; + } }; ShutterSpeedInterpreter shutterSpeedInterpreter; -class ExposureTimeInterpreter : public Interpreter { - public: - ExposureTimeInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[1024]; - double d = t->toDouble(); - if (d > 0.0 && d < 0.9) - sprintf (buffer, "1/%.0f", 1.0 / d); - else - sprintf (buffer, "%.1f", d); - return buffer; +class ExposureTimeInterpreter : public Interpreter +{ +public: + ExposureTimeInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[1024]; + double d = t->toDouble(); + + if (d > 0.0 && d < 0.9) { + sprintf (buffer, "1/%.0f", 1.0 / d); + } else { + sprintf (buffer, "%.1f", d); } + + return buffer; + } }; ExposureTimeInterpreter exposureTimeInterpreter; -class FocalLengthInterpreter : public Interpreter { - public: - FocalLengthInterpreter () {} - virtual std::string toString (Tag* t) { - char buffer[32]; - double v = t->toDouble(); - if( v>1000000. || v<0 ) return "undef"; - sprintf (buffer, "%.1f", v ); - return buffer; +class FocalLengthInterpreter : public Interpreter +{ +public: + FocalLengthInterpreter () {} + virtual std::string toString (Tag* t) + { + char buffer[32]; + double v = t->toDouble(); + + if( v > 1000000. || v < 0 ) { + return "undef"; } + + sprintf (buffer, "%.1f", v ); + return buffer; + } }; FocalLengthInterpreter focalLengthInterpreter; -class UserCommentInterpreter : public Interpreter { - public: - UserCommentInterpreter () {} - virtual std::string toString (Tag* t) { - char *buffer = new char[t->getCount()]; - if (!strncmp((char*)t->getValue(), "ASCII\0\0\0",8)) { - strncpy (buffer, (char*)t->getValue()+8, t->getCount()-8); - buffer[t->getCount()-8] = '\0'; - } - else - buffer[0]=0; - std::string retVal(buffer); - delete [] buffer; - return retVal; - } - virtual void fromString (Tag* t, const std::string& value) { - char *buffer = new char[t->getCount()]; - memcpy (buffer, "ASCII\0\0\0", 8); - strcpy (buffer+8, value.c_str()); - t->fromString (buffer, value.size() + 9); - delete [] buffer; +class UserCommentInterpreter : public Interpreter +{ +public: + UserCommentInterpreter () {} + virtual std::string toString (Tag* t) + { + char *buffer = new char[t->getCount()]; + + if (!strncmp((char*)t->getValue(), "ASCII\0\0\0", 8)) { + strncpy (buffer, (char*)t->getValue() + 8, t->getCount() - 8); + buffer[t->getCount() - 8] = '\0'; + } else { + buffer[0] = 0; } + + std::string retVal(buffer); + delete [] buffer; + return retVal; + } + virtual void fromString (Tag* t, const std::string& value) + { + char *buffer = new char[t->getCount()]; + memcpy (buffer, "ASCII\0\0\0", 8); + strcpy (buffer + 8, value.c_str()); + t->fromString (buffer, value.size() + 9); + delete [] buffer; + } }; UserCommentInterpreter userCommentInterpreter; -class CFAInterpreter : public Interpreter { +class CFAInterpreter : public Interpreter +{ public: - CFAInterpreter(){} - virtual std::string toString (Tag* t) { - char colors[]="RGB"; - char buffer[1024]; - for( int i=0; i< t->getCount();i++){ - unsigned char c = t->toInt(i,BYTE); - buffer[i]= c<3 ?colors[c]:' '; - } - buffer[t->getCount()]=0; - return buffer; - } + CFAInterpreter() {} + virtual std::string toString (Tag* t) + { + char colors[] = "RGB"; + char buffer[1024]; + + for( int i = 0; i < t->getCount(); i++) { + unsigned char c = t->toInt(i, BYTE); + buffer[i] = c < 3 ? colors[c] : ' '; + } + + buffer[t->getCount()] = 0; + return buffer; + } }; CFAInterpreter cfaInterpreter; -class OrientationInterpreter : public ChoiceInterpreter { +class OrientationInterpreter : public ChoiceInterpreter +{ public: - OrientationInterpreter (){ + OrientationInterpreter () + { choices[1] = "Horizontal (normal)"; choices[2] = "Mirror horizontal "; choices[3] = "Rotate 180"; @@ -420,299 +504,306 @@ public: choices[8] = "Rotate 270 CW"; // '9' is an "unofficial" value for Orientation but used by some older cameras that lacks orientation sensor, such as Kodak DCS choices[9] = "Unknown"; - } + } }; OrientationInterpreter orientationInterpreter; -class UnitsInterpreter : public ChoiceInterpreter { +class UnitsInterpreter : public ChoiceInterpreter +{ public: - UnitsInterpreter(){ + UnitsInterpreter() + { choices[0] = "Unknown"; choices[1] = "inches"; choices[2] = "cm"; - } + } }; UnitsInterpreter unitsInterpreter; -class UTF8BinInterpreter : public Interpreter { - public: - UTF8BinInterpreter () {} +class UTF8BinInterpreter : public Interpreter +{ +public: + UTF8BinInterpreter () {} }; UTF8BinInterpreter utf8BinInterpreter; const TagAttrib exifAttribs[] = { - {0, AC_SYSTEM, 0, 0, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0103, AUTO, "Compression", &compressionInterpreter}, - {0, AC_WRITE, 0, 0, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, - {0, AC_WRITE, 0, 0, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter}, - {0, AC_WRITE, 0, 0, 0x829D, AUTO, "FNumber", &fNumberInterpreter}, - {0, AC_WRITE, 0, 0, 0x8822, AUTO, "ExposureProgram", &exposureProgramInterpreter}, - {0, AC_WRITE, 0, 0, 0x8824, AUTO, "SpectralSensitivity", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x8827, AUTO, "ISOSpeedRatings", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x8828, AUTO, "OECF", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9000, AUTO, "ExifVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x9101, AUTO, "ComponentsConfiguration", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x9102, AUTO, "CompressedBitsPerPixel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9201, AUTO, "ShutterSpeedValue", &shutterSpeedInterpreter}, - {0, AC_WRITE, 0, 0, 0x9202, AUTO, "ApertureValue", &apertureInterpreter}, - {0, AC_WRITE, 0, 0, 0x9203, AUTO, "BrightnessValue", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9204, AUTO, "ExposureBiasValue", &exposureBiasInterpreter}, - {0, AC_WRITE, 0, 0, 0x9205, AUTO, "MaxApertureValue", &apertureInterpreter}, - {0, AC_WRITE, 0, 0, 0x9206, AUTO, "SubjectDistance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9207, AUTO, "MeteringMode", &meteringModeInterpreter}, - {0, AC_WRITE, 0, 0, 0x9208, AUTO, "LightSource", &lightSourceInterpreter}, - {0, AC_WRITE, 0, 0, 0x9209, AUTO, "Flash", &flashInterpreter}, - {0, AC_WRITE, 0, 0, 0x920A, AUTO, "FocalLength", &focalLengthInterpreter}, - {0, AC_WRITE, 0, 0, 0x9214, AUTO, "SubjectArea", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9215, AUTO, "ExposureIndex", &stdInterpreter}, // Note: exists as 0xA215 too, it should be that way - {0, AC_DONTWRITE, 0, 0, 0x9216, AUTO, "TIFFEPSStandardID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9217, AUTO, "SensingMethod", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x927C, AUTO, "MakerNote", &stdInterpreter}, - {0, AC_WRITE, 1, 0, 0x9286, AUTO, "UserComment", &userCommentInterpreter}, - {0, AC_WRITE, 0, 0, 0x9290, AUTO, "SubSecTime", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9291, AUTO, "SubSecTimeOriginal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9292, AUTO, "SubSecTimeDigitized", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0xA000, AUTO, "FlashpixVersion", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xA001, AUTO, "ColorSpace", &colorSpaceInterpreter}, - {0, AC_SYSTEM, 0, 0, 0xA002, AUTO, "PixelXDimension", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0xA003, AUTO, "PixelYDimension", &stdInterpreter}, - {1, AC_DONTWRITE, 0, 0, 0xA004, AUTO, "RelatedSoundFile", &stdInterpreter}, - {0, AC_SYSTEM, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter}, // do not enable, as it causes trouble with FUJI files - {0, AC_WRITE, 0, 0, 0xA20B, AUTO, "FlashEnergy", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA20C, AUTO, "SpatialFrequencyResponse", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA20E, AUTO, "FocalPlaneXResolution", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA20F, AUTO, "FocalPlaneYResolution", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA210, AUTO, "FocalPlaneResolutionUnit", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA214, AUTO, "SubjectLocation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA215, AUTO, "ExposureIndex", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA217, AUTO, "SensingMethod", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA300, AUTO, "FileSource", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA301, AUTO, "SceneType", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xA302, AUTO, "CFAPattern", &cfaInterpreter}, - {0, AC_WRITE, 0, 0, 0xA401, AUTO, "CustomRendered", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA402, AUTO, "ExposureMode", &exposureModeInterpreter}, - {0, AC_WRITE, 0, 0, 0xA403, AUTO, "WhiteBalance", &whiteBalanceInterpreter}, - {0, AC_WRITE, 0, 0, 0xA404, AUTO, "DigitalZoomRatio", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA405, AUTO, "FocalLengthIn35mmFilm", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA406, AUTO, "SceneCaptureType", &sceneCaptureInterpreter}, - {0, AC_WRITE, 0, 0, 0xA407, AUTO, "GainControl", &gainControlInterpreter}, - {0, AC_WRITE, 0, 0, 0xA408, AUTO, "Contrast", &contrastInterpreter}, - {0, AC_WRITE, 0, 0, 0xA409, AUTO, "Saturation", &saturationInterpreter}, - {0, AC_WRITE, 0, 0, 0xA40A, AUTO, "Sharpness", &sharpnessInterpreter}, - {0, AC_WRITE, 0, 0, 0xA40B, AUTO, "DeviceSettingDescription", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA40C, AUTO, "SubjectDistanceRange", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA420, AUTO, "ImageUniqueID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA431, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA432, AUTO, "LensInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA433, AUTO, "LensMake", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA434, AUTO, "LensModel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA435, AUTO, "LensSerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xA500, AUTO, "Gamma", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC618, AUTO, "LinearizationTable", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC619, AUTO, "BlackLevelRepeatDim", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC61A, AUTO, "BlackLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC61B, AUTO, "BlackLevelDeltaH", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC61C, AUTO, "BlackLevelDeltaV", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC61D, AUTO, "WhiteLevel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC61E, AUTO, "DefaultScale", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC61F, AUTO, "DefaultCropOrigin", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC620, AUTO, "DefaultCropSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC621, AUTO, "ColorMatrix1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC622, AUTO, "ColorMatrix2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC623, AUTO, "CameraCalibration1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC624, AUTO, "CameraCalibration2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC625, AUTO, "ReductionMatrix1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC626, AUTO, "ReductionMatrix2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC627, AUTO, "AnalogBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC628, AUTO, "AsShotNeutral", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC629, AUTO, "AsShotWhiteXY", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC62A, AUTO, "BaselineExposure", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC62B, AUTO, "BaselineNoise", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC62C, AUTO, "BaselineSharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC62D, AUTO, "BayerGreenSplit", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC62E, AUTO, "LinearResponseLimit", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC62F, AUTO, "CameraSerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC630, AUTO, "DNGLensInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC631, AUTO, "ChromaBlurRadius", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC632, AUTO, "AntiAliasStrength", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC633, AUTO, "ShadowScale", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC65A, AUTO, "CalibrationIlluminant1", &lightSourceInterpreter}, - {0, AC_WRITE, 0, 0, 0xC65B, AUTO, "CalibrationIlluminant2", &lightSourceInterpreter}, - {0, AC_WRITE, 0, 0, 0xC65C, AUTO, "BestQualityScale", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC65D, AUTO, "RawDataUniqueID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC68D, AUTO, "ActiveArea", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0103, AUTO, "Compression", &compressionInterpreter}, + {0, AC_WRITE, 0, 0, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, + {0, AC_WRITE, 0, 0, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter}, + {0, AC_WRITE, 0, 0, 0x829D, AUTO, "FNumber", &fNumberInterpreter}, + {0, AC_WRITE, 0, 0, 0x8822, AUTO, "ExposureProgram", &exposureProgramInterpreter}, + {0, AC_WRITE, 0, 0, 0x8824, AUTO, "SpectralSensitivity", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x8827, AUTO, "ISOSpeedRatings", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x8828, AUTO, "OECF", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9000, AUTO, "ExifVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x9101, AUTO, "ComponentsConfiguration", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x9102, AUTO, "CompressedBitsPerPixel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9201, AUTO, "ShutterSpeedValue", &shutterSpeedInterpreter}, + {0, AC_WRITE, 0, 0, 0x9202, AUTO, "ApertureValue", &apertureInterpreter}, + {0, AC_WRITE, 0, 0, 0x9203, AUTO, "BrightnessValue", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9204, AUTO, "ExposureBiasValue", &exposureBiasInterpreter}, + {0, AC_WRITE, 0, 0, 0x9205, AUTO, "MaxApertureValue", &apertureInterpreter}, + {0, AC_WRITE, 0, 0, 0x9206, AUTO, "SubjectDistance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9207, AUTO, "MeteringMode", &meteringModeInterpreter}, + {0, AC_WRITE, 0, 0, 0x9208, AUTO, "LightSource", &lightSourceInterpreter}, + {0, AC_WRITE, 0, 0, 0x9209, AUTO, "Flash", &flashInterpreter}, + {0, AC_WRITE, 0, 0, 0x920A, AUTO, "FocalLength", &focalLengthInterpreter}, + {0, AC_WRITE, 0, 0, 0x9214, AUTO, "SubjectArea", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9215, AUTO, "ExposureIndex", &stdInterpreter}, // Note: exists as 0xA215 too, it should be that way + {0, AC_DONTWRITE, 0, 0, 0x9216, AUTO, "TIFFEPSStandardID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9217, AUTO, "SensingMethod", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x927C, AUTO, "MakerNote", &stdInterpreter}, + {0, AC_WRITE, 1, 0, 0x9286, AUTO, "UserComment", &userCommentInterpreter}, + {0, AC_WRITE, 0, 0, 0x9290, AUTO, "SubSecTime", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9291, AUTO, "SubSecTimeOriginal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9292, AUTO, "SubSecTimeDigitized", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0xA000, AUTO, "FlashpixVersion", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xA001, AUTO, "ColorSpace", &colorSpaceInterpreter}, + {0, AC_SYSTEM, 0, 0, 0xA002, AUTO, "PixelXDimension", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0xA003, AUTO, "PixelYDimension", &stdInterpreter}, + {1, AC_DONTWRITE, 0, 0, 0xA004, AUTO, "RelatedSoundFile", &stdInterpreter}, + {0, AC_SYSTEM, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter}, // do not enable, as it causes trouble with FUJI files + {0, AC_WRITE, 0, 0, 0xA20B, AUTO, "FlashEnergy", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA20C, AUTO, "SpatialFrequencyResponse", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA20E, AUTO, "FocalPlaneXResolution", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA20F, AUTO, "FocalPlaneYResolution", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA210, AUTO, "FocalPlaneResolutionUnit", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA214, AUTO, "SubjectLocation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA215, AUTO, "ExposureIndex", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA217, AUTO, "SensingMethod", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA300, AUTO, "FileSource", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA301, AUTO, "SceneType", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xA302, AUTO, "CFAPattern", &cfaInterpreter}, + {0, AC_WRITE, 0, 0, 0xA401, AUTO, "CustomRendered", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA402, AUTO, "ExposureMode", &exposureModeInterpreter}, + {0, AC_WRITE, 0, 0, 0xA403, AUTO, "WhiteBalance", &whiteBalanceInterpreter}, + {0, AC_WRITE, 0, 0, 0xA404, AUTO, "DigitalZoomRatio", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA405, AUTO, "FocalLengthIn35mmFilm", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA406, AUTO, "SceneCaptureType", &sceneCaptureInterpreter}, + {0, AC_WRITE, 0, 0, 0xA407, AUTO, "GainControl", &gainControlInterpreter}, + {0, AC_WRITE, 0, 0, 0xA408, AUTO, "Contrast", &contrastInterpreter}, + {0, AC_WRITE, 0, 0, 0xA409, AUTO, "Saturation", &saturationInterpreter}, + {0, AC_WRITE, 0, 0, 0xA40A, AUTO, "Sharpness", &sharpnessInterpreter}, + {0, AC_WRITE, 0, 0, 0xA40B, AUTO, "DeviceSettingDescription", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA40C, AUTO, "SubjectDistanceRange", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA420, AUTO, "ImageUniqueID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA431, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA432, AUTO, "LensInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA433, AUTO, "LensMake", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA434, AUTO, "LensModel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA435, AUTO, "LensSerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xA500, AUTO, "Gamma", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC618, AUTO, "LinearizationTable", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC619, AUTO, "BlackLevelRepeatDim", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC61A, AUTO, "BlackLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC61B, AUTO, "BlackLevelDeltaH", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC61C, AUTO, "BlackLevelDeltaV", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC61D, AUTO, "WhiteLevel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC61E, AUTO, "DefaultScale", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC61F, AUTO, "DefaultCropOrigin", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC620, AUTO, "DefaultCropSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC621, AUTO, "ColorMatrix1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC622, AUTO, "ColorMatrix2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC623, AUTO, "CameraCalibration1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC624, AUTO, "CameraCalibration2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC625, AUTO, "ReductionMatrix1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC626, AUTO, "ReductionMatrix2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC627, AUTO, "AnalogBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC628, AUTO, "AsShotNeutral", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC629, AUTO, "AsShotWhiteXY", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC62A, AUTO, "BaselineExposure", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC62B, AUTO, "BaselineNoise", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC62C, AUTO, "BaselineSharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC62D, AUTO, "BayerGreenSplit", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC62E, AUTO, "LinearResponseLimit", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC62F, AUTO, "CameraSerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC630, AUTO, "DNGLensInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC631, AUTO, "ChromaBlurRadius", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC632, AUTO, "AntiAliasStrength", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC633, AUTO, "ShadowScale", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC65A, AUTO, "CalibrationIlluminant1", &lightSourceInterpreter}, + {0, AC_WRITE, 0, 0, 0xC65B, AUTO, "CalibrationIlluminant2", &lightSourceInterpreter}, + {0, AC_WRITE, 0, 0, 0xC65C, AUTO, "BestQualityScale", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC65D, AUTO, "RawDataUniqueID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC68D, AUTO, "ActiveArea", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter}, // {0, AC_WRITE, 0, 0, 0xC68F, AUTO, "AsShotICCProfile", & ???}, - {0, AC_WRITE, 0, 0, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter}, // {0, AC_WRITE, 0, 0, 0xC691, AUTO, "CurrentICCProfile", & ???}, - {0, AC_WRITE, 0, 0, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F4, AUTO, "ProfileCalibrationSig", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F5, AUTO, "ProfileIFD", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F6, AUTO, "AsShotProfileName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F7, AUTO, "NoiseReductionApplied", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F8, AUTO, "ProfileName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6F9, AUTO, "ProfileHueSatMapDims", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6FA, AUTO, "ProfileHueSatMapData1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6FB, AUTO, "ProfileHueSatMapData2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6FC, AUTO, "ProfileToneCurve", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6FD, AUTO, "ProfileEmbedPolicy", &profileEmbedPolicyInterpreter}, - {0, AC_WRITE, 0, 0, 0xC6FE, AUTO, "ProfileCopyright", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC714, AUTO, "ForwardMatrix1", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC715, AUTO, "ForwardMatrix2", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC716, AUTO, "PreviewApplicationName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC717, AUTO, "PreviewApplicationVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC718, AUTO, "PreviewSettingsName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC719, AUTO, "PreviewSettingsDigest", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC71A, AUTO, "PreviewColorSpace", &previewColorSpaceInterpreter}, - {0, AC_WRITE, 0, 0, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F4, AUTO, "ProfileCalibrationSig", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F5, AUTO, "ProfileIFD", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F6, AUTO, "AsShotProfileName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F7, AUTO, "NoiseReductionApplied", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F8, AUTO, "ProfileName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6F9, AUTO, "ProfileHueSatMapDims", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6FA, AUTO, "ProfileHueSatMapData1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6FB, AUTO, "ProfileHueSatMapData2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6FC, AUTO, "ProfileToneCurve", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6FD, AUTO, "ProfileEmbedPolicy", &profileEmbedPolicyInterpreter}, + {0, AC_WRITE, 0, 0, 0xC6FE, AUTO, "ProfileCopyright", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC714, AUTO, "ForwardMatrix1", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC715, AUTO, "ForwardMatrix2", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC716, AUTO, "PreviewApplicationName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC717, AUTO, "PreviewApplicationVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC718, AUTO, "PreviewSettingsName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC719, AUTO, "PreviewSettingsDigest", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC71A, AUTO, "PreviewColorSpace", &previewColorSpaceInterpreter}, + {0, AC_WRITE, 0, 0, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter}, // {0, AC_WRITE, 0, 0, 0xC71E, AUTO, "SubTileBlockSize", & ???}, // {0, AC_WRITE, 0, 0, 0xC71F, AUTO, "RowInterleaveFactor", & ???}, - {0, AC_WRITE, 0, 0, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter}, // {0, AC_WRITE, 0, 0, 0xC740, AUTO, "OpcodeList1", & ???}, // {0, AC_WRITE, 0, 0, 0xC741, AUTO, "OpcodeList2", & ???}, // {0, AC_WRITE, 0, 0, 0xC74E, AUTO, "OpcodeList3", & ???}, - {0, AC_WRITE, 0, 0, 0xC761, AUTO, "NoiseProfile", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC763, AUTO, "TimeCodes", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC764, AUTO, "FrameRate", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC772, AUTO, "TStop", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC789, AUTO, "ReelName", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC791, AUTO, "OriginalDefaultFinalSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC792, AUTO, "OriginalBestQualitySize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC793, AUTO, "OriginalDefaultCropSize", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A1, AUTO, "CameraLabel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A3, AUTO, "ProfileHueSatMapEncoding", &linearSRGBInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A4, AUTO, "ProfileLookTableEncoding", &linearSRGBInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A5, AUTO, "BaselineExposureOffset", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A6, AUTO, "DefaultBlackRender", &defaultBlackRenderInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A7, AUTO, "NewRawImageDigest", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7A8, AUTO, "RawToPreviewGain", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC7B5, AUTO, "DefaultUserCrop", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFDE9, AUTO, "SerialNumber", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFDEA, AUTO, "Lens", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE4C, AUTO, "RawFile", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE4D, AUTO, "Converter", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE4E, AUTO, "WhiteBalance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE51, AUTO, "Exposure", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE52, AUTO, "Shadows", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE53, AUTO, "Brightness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE54, AUTO, "Contrast", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE55, AUTO, "Saturation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE56, AUTO, "Sharpness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE57, AUTO, "Smoothness", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xFE58, AUTO, "MoireFilter", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL }}; + {0, AC_WRITE, 0, 0, 0xC761, AUTO, "NoiseProfile", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC763, AUTO, "TimeCodes", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC764, AUTO, "FrameRate", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC772, AUTO, "TStop", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC789, AUTO, "ReelName", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC791, AUTO, "OriginalDefaultFinalSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC792, AUTO, "OriginalBestQualitySize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC793, AUTO, "OriginalDefaultCropSize", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A1, AUTO, "CameraLabel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A3, AUTO, "ProfileHueSatMapEncoding", &linearSRGBInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A4, AUTO, "ProfileLookTableEncoding", &linearSRGBInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A5, AUTO, "BaselineExposureOffset", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A6, AUTO, "DefaultBlackRender", &defaultBlackRenderInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A7, AUTO, "NewRawImageDigest", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7A8, AUTO, "RawToPreviewGain", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC7B5, AUTO, "DefaultUserCrop", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFDE9, AUTO, "SerialNumber", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFDEA, AUTO, "Lens", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE4C, AUTO, "RawFile", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE4D, AUTO, "Converter", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE4E, AUTO, "WhiteBalance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE51, AUTO, "Exposure", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE52, AUTO, "Shadows", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE53, AUTO, "Brightness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE54, AUTO, "Contrast", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE55, AUTO, "Saturation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE56, AUTO, "Sharpness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE57, AUTO, "Smoothness", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xFE58, AUTO, "MoireFilter", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL } +}; const TagAttrib gpsAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0000, AUTO, "GPSVersionID", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0001, AUTO, "GPSLatitudeRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0002, AUTO, "GPSLatitude", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0003, AUTO, "GPSLongitudeRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0004, AUTO, "GPSLongitude", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0005, AUTO, "GPSAltitudeRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0006, AUTO, "GPSAltitude", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0007, AUTO, "GPSTimeStamp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0008, AUTO, "GPSSatelites", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0009, AUTO, "GPSStatus", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000a, AUTO, "GPSMeasureMode", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000b, AUTO, "GPSDOP", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000c, AUTO, "GPSSpeedRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000d, AUTO, "GPSSpeed", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000e, AUTO, "GPSTrackRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x000f, AUTO, "GPSTrack", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0010, AUTO, "GPSImgDirectionRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0011, AUTO, "GPSImgDirection", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0012, AUTO, "GPSMapDatum", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0013, AUTO, "GPSDestLatitudeRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0014, AUTO, "GPSDestLatitude", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0015, AUTO, "GPSDestLongitudeRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0016, AUTO, "GPSDestLongitude", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0017, AUTO, "GPSDestBearingRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0018, AUTO, "GPSDestBearing", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0019, AUTO, "GPSDestDistanceRef", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001a, AUTO, "GPSDestDistance", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001b, AUTO, "GPSProcessingMethod", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001c, AUTO, "GPSAreaInformation", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001d, AUTO, "GPSDateStamp", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x001e, AUTO, "GPSDifferential", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL }}; + {0, AC_WRITE, 0, 0, 0x0000, AUTO, "GPSVersionID", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0001, AUTO, "GPSLatitudeRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0002, AUTO, "GPSLatitude", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0003, AUTO, "GPSLongitudeRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0004, AUTO, "GPSLongitude", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0005, AUTO, "GPSAltitudeRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0006, AUTO, "GPSAltitude", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0007, AUTO, "GPSTimeStamp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0008, AUTO, "GPSSatelites", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0009, AUTO, "GPSStatus", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000a, AUTO, "GPSMeasureMode", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000b, AUTO, "GPSDOP", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000c, AUTO, "GPSSpeedRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000d, AUTO, "GPSSpeed", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000e, AUTO, "GPSTrackRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x000f, AUTO, "GPSTrack", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0010, AUTO, "GPSImgDirectionRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0011, AUTO, "GPSImgDirection", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0012, AUTO, "GPSMapDatum", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0013, AUTO, "GPSDestLatitudeRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0014, AUTO, "GPSDestLatitude", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0015, AUTO, "GPSDestLongitudeRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0016, AUTO, "GPSDestLongitude", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0017, AUTO, "GPSDestBearingRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0018, AUTO, "GPSDestBearing", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0019, AUTO, "GPSDestDistanceRef", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001a, AUTO, "GPSDestDistance", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001b, AUTO, "GPSProcessingMethod", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001c, AUTO, "GPSAreaInformation", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001d, AUTO, "GPSDateStamp", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x001e, AUTO, "GPSDifferential", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL } +}; const TagAttrib iopAttribs[] = { - {0, AC_WRITE, 0, 0, 0x0001, AUTO, "InteroperabilityIndex", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0002, AUTO, "InteroperabilityVersion", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL }}; + {0, AC_WRITE, 0, 0, 0x0001, AUTO, "InteroperabilityIndex", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0002, AUTO, "InteroperabilityVersion", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL } +}; - const TagAttrib ifdAttribs[] = { - {0, AC_SYSTEM, 0, 0, 0x0017, AUTO, "PanaISO", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0103, AUTO, "Compression", &compressionInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0106, AUTO, "PhotometricInterpretation", &photometricInterpreter}, - {0, AC_WRITE, 1, 0, 0x010E, AUTO, "ImageDescription", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x010F, AUTO, "Make", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0110, AUTO, "Model", &stdInterpreter}, - {1, AC_DONTWRITE, 0, 0, 0x0111, AUTO, "StripOffsets", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0112, AUTO, "Orientation", &orientationInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0115, AUTO, "SamplesPerPixel", &stdInterpreter}, - {1, AC_DONTWRITE, 0, 0, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter}, - {1, AC_DONTWRITE, 0, 0, 0x0117, AUTO, "StripByteCounts", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x011A, AUTO, "XResolution", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x011B, AUTO, "YResolution", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x011C, AUTO, "PlanarConfiguration", &planarConfigInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0128, AUTO, "ResolutionUnit", &unitsInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x012D, AUTO, "TransferFunction", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0131, AUTO, "Software", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x0132, AUTO, "DateTime", &stdInterpreter}, - {0, AC_WRITE, 1, 0, 0x013B, AUTO, "Artist", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x013E, AUTO, "WhitePoint", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter}, - {0, AC_WRITE, 0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0212, AUTO, "YCbCrSubSampling", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0213, AUTO, "YCbCrPositioning", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x0214, AUTO, "ReferenceBlackWhite", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x02bc, AUTO, "ApplicationNotes", &utf8BinInterpreter}, // XMP - {0, AC_WRITE, 0, 0, 0x4746, AUTO, "Rating",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x4749, AUTO, "RatingPercent",&stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, - {0, AC_WRITE, 0, kodakIfdAttribs, 0x8290, AUTO, "KodakIFD", &stdInterpreter}, - {0, AC_WRITE, 1, 0, 0x8298, AUTO, "Copyright", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0x8606, AUTO, "LeafData", &stdInterpreter}, // is actually a subdir, but a proprietary format - {0, AC_WRITE, 0, exifAttribs, 0x8769, AUTO, "Exif", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x8773, AUTO, "ICCProfile", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x83BB, AUTO, "IPTCData", &stdInterpreter}, - {0, AC_WRITE, 0, gpsAttribs, 0x8825, AUTO, "GPSInfo", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0x9211, AUTO, "ImageNumber", &stdInterpreter}, - {0, AC_WRITE, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xC4A5, AUTO, "PrintIMInformation", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xC612, AUTO, "DNGVersion", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xC613, AUTO, "DNGBackwardVersion", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC614, AUTO, "UniqueCameraModel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xC615, AUTO, "LocalizedCameraModel", &stdInterpreter}, - {0, AC_WRITE, 0, 0, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData - {0, AC_WRITE, 0, 0, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter}, - {0, AC_DONTWRITE, 0, 0, 0xc761, AUTO, "NoiseProfile", &stdInterpreter}, - {0, AC_SYSTEM, 0, 0, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter}, - {-1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL}}; +const TagAttrib ifdAttribs[] = { + {0, AC_SYSTEM, 0, 0, 0x0017, AUTO, "PanaISO", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0103, AUTO, "Compression", &compressionInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0106, AUTO, "PhotometricInterpretation", &photometricInterpreter}, + {0, AC_WRITE, 1, 0, 0x010E, AUTO, "ImageDescription", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x010F, AUTO, "Make", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0110, AUTO, "Model", &stdInterpreter}, + {1, AC_DONTWRITE, 0, 0, 0x0111, AUTO, "StripOffsets", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0112, AUTO, "Orientation", &orientationInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0115, AUTO, "SamplesPerPixel", &stdInterpreter}, + {1, AC_DONTWRITE, 0, 0, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter}, + {1, AC_DONTWRITE, 0, 0, 0x0117, AUTO, "StripByteCounts", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x011A, AUTO, "XResolution", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x011B, AUTO, "YResolution", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x011C, AUTO, "PlanarConfiguration", &planarConfigInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0128, AUTO, "ResolutionUnit", &unitsInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x012D, AUTO, "TransferFunction", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0131, AUTO, "Software", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x0132, AUTO, "DateTime", &stdInterpreter}, + {0, AC_WRITE, 1, 0, 0x013B, AUTO, "Artist", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x013E, AUTO, "WhitePoint", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter}, + {0, AC_WRITE, 0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0212, AUTO, "YCbCrSubSampling", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0213, AUTO, "YCbCrPositioning", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x0214, AUTO, "ReferenceBlackWhite", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x02bc, AUTO, "ApplicationNotes", &utf8BinInterpreter}, // XMP + {0, AC_WRITE, 0, 0, 0x4746, AUTO, "Rating", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x4749, AUTO, "RatingPercent", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, + {0, AC_WRITE, 0, kodakIfdAttribs, 0x8290, AUTO, "KodakIFD", &stdInterpreter}, + {0, AC_WRITE, 1, 0, 0x8298, AUTO, "Copyright", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0x8606, AUTO, "LeafData", &stdInterpreter}, // is actually a subdir, but a proprietary format + {0, AC_WRITE, 0, exifAttribs, 0x8769, AUTO, "Exif", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x8773, AUTO, "ICCProfile", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x83BB, AUTO, "IPTCData", &stdInterpreter}, + {0, AC_WRITE, 0, gpsAttribs, 0x8825, AUTO, "GPSInfo", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0x9211, AUTO, "ImageNumber", &stdInterpreter}, + {0, AC_WRITE, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xC4A5, AUTO, "PrintIMInformation", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xC612, AUTO, "DNGVersion", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xC613, AUTO, "DNGBackwardVersion", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC614, AUTO, "UniqueCameraModel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xC615, AUTO, "LocalizedCameraModel", &stdInterpreter}, + {0, AC_WRITE, 0, 0, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData + {0, AC_WRITE, 0, 0, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter}, + {0, AC_DONTWRITE, 0, 0, 0xc761, AUTO, "NoiseProfile", &stdInterpreter}, + {0, AC_SYSTEM, 0, 0, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter}, + { -1, AC_DONTWRITE, 0, 0, 0, AUTO, "", NULL} +}; } #endif diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index f9d6b6ef1..8f6ef6685 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -85,28 +85,28 @@ #define ADDSET_DIRPYRDN_PASSES 77 #define ADDSET_RAWFFCLIPCONTROL 78 #define ADDSET_FILMSIMULATION_STRENGTH 79 -#define ADDSET_WA 80 -#define ADDSET_WA_SKINPROTECT 81 -#define ADDSET_WA_THRR 82 -#define ADDSET_WA_THRRH 83 -#define ADDSET_WA_THRES 84 -#define ADDSET_WA_THRESHOLD 85 -#define ADDSET_WA_THRESHOLD2 86 -#define ADDSET_WA_CHRO 87 -#define ADDSET_WA_CHROMA 88 -#define ADDSET_WA_CONTRAST 89 -#define ADDSET_WA_RESCON 90 -#define ADDSET_WA_RESCONH 91 -#define ADDSET_WA_RESCHRO 92 -#define ADDSET_WA_SKYPROTECT 93 -#define ADDSET_WA_EDGRAD 94 -#define ADDSET_WA_EDGVAL 95 -#define ADDSET_WA_STRENGTH 96 -#define ADDSET_WA_EDGEDETECT 97 -#define ADDSET_WA_EDGEDETECTTHR 98 -#define ADDSET_WA_EDGEDETECTTHR2 99 -#define ADDSET_WA_TMRS 100 -#define ADDSET_WA_GAMMA 101 +#define ADDSET_WA 80 +#define ADDSET_WA_SKINPROTECT 81 +#define ADDSET_WA_THRR 82 +#define ADDSET_WA_THRRH 83 +#define ADDSET_WA_THRES 84 +#define ADDSET_WA_THRESHOLD 85 +#define ADDSET_WA_THRESHOLD2 86 +#define ADDSET_WA_CHRO 87 +#define ADDSET_WA_CHROMA 88 +#define ADDSET_WA_CONTRAST 89 +#define ADDSET_WA_RESCON 90 +#define ADDSET_WA_RESCONH 91 +#define ADDSET_WA_RESCHRO 92 +#define ADDSET_WA_SKYPROTECT 93 +#define ADDSET_WA_EDGRAD 94 +#define ADDSET_WA_EDGVAL 95 +#define ADDSET_WA_STRENGTH 96 +#define ADDSET_WA_EDGEDETECT 97 +#define ADDSET_WA_EDGEDETECTTHR 98 +#define ADDSET_WA_EDGEDETECTTHR2 99 +#define ADDSET_WA_TMRS 100 +#define ADDSET_WA_GAMMA 101 // When adding items, make sure to update ADDSET_PARAM_NUM #define ADDSET_PARAM_NUM 102 // THIS IS USED AS A DELIMITER!! diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index c09c4af2e..c47f27e2e 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -7,7 +7,7 @@ * 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 @@ -27,111 +27,134 @@ #define MIN_RESET_BUTTON_HEIGHT 17 -static double one2one(double val) { return val; } - -Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon1, Gtk::Image *imgIcon2, double2double_fun slider2value_, double2double_fun value2slider_) { - - Gtk::HBox *hbox2=NULL; - label = NULL; - adjusterListener = NULL; - afterReset = false; - blocked = false; - automatic = NULL; - eventPending = false; - - slider2value = slider2value_ ? slider2value_ : one2one; - value2slider = value2slider_ ? value2slider_ : one2one; - vMin = vmin; - vMax = vmax; - vStep = vstep; - addMode = false; - - // TODO: let the user chose the default value of Adjuster::delay, for slow machines - delay = options.adjusterDelay; // delay is no more static, so we can set the delay individually (useful for the RAW editor tab) - - set_border_width (0); - set_spacing (0); - - hbox = Gtk::manage (new Gtk::HBox ()); - hbox->set_border_width(0); - hbox->set_spacing(2); - - editedCheckBox = NULL; - - if (!vlabel.empty()) { - adjustmentName = vlabel; - label = Gtk::manage (new Gtk::Label (adjustmentName, Gtk::ALIGN_LEFT)); - } - - reset = Gtk::manage (new Gtk::Button ()); - reset->add (*Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); - reset->set_relief (Gtk::RELIEF_NONE); - reset->set_border_width (0); - reset->set_tooltip_text (M("ADJUSTER_RESET_TO_DEFAULT")); - reset->set_can_focus(false); - - spin = Gtk::manage (new MySpinButton ()); - spin->set_has_frame(false); - spin->set_name("FramelessSpinButton"); - - reset->set_size_request (-1, spin->get_height() > MIN_RESET_BUTTON_HEIGHT ? spin->get_height(): MIN_RESET_BUTTON_HEIGHT); - - slider = Gtk::manage (new MyHScale ()); - slider->set_draw_value (false); - - pack_start (*hbox, true, true); - - if (vlabel.empty()) { - // No label, everything goes in hbox - if (imgIcon1) hbox->pack_start (*imgIcon1, Gtk::PACK_SHRINK, 0); - hbox->pack_start (*slider, Gtk::PACK_EXPAND_WIDGET, 0); - if (imgIcon2) hbox->pack_start (*imgIcon2, Gtk::PACK_SHRINK, 0); - hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); - hbox->pack_end (*spin, Gtk::PACK_SHRINK, 0); - } - else { - // A label is provided, spreading the widgets in 2 rows - hbox->pack_start (*label); - hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); - hbox->pack_end (*spin, Gtk::PACK_SHRINK, 0); - if (!imgIcon1 || !imgIcon2) { - pack_start (*slider, true, true); - } - else { - // A second HBox is necessary - hbox2 = Gtk::manage (new Gtk::HBox()); - if (imgIcon1) hbox2->pack_start (*imgIcon1, Gtk::PACK_SHRINK, 0); - hbox2->pack_start (*slider, true, true); - if (imgIcon2) hbox2->pack_start (*imgIcon2, Gtk::PACK_SHRINK, 0); - pack_start (*hbox2, true, true); - } - } - - setLimits (vmin, vmax, vstep, vdefault); - - defaultVal = shapeValue (vdefault); - ctorDefaultVal = shapeValue (vdefault); - editedState = defEditedState = Irrelevant; - autoState = Irrelevant; - - sliderChange = slider->signal_value_changed().connect( sigc::mem_fun(*this, &Adjuster::sliderChanged) ); - spinChange = spin->signal_value_changed().connect ( sigc::mem_fun(*this, &Adjuster::spinChanged), true); - reset->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &Adjuster::resetPressed) ); - slider->set_update_policy (Gtk::UPDATE_CONTINUOUS); - - show_all (); +static double one2one(double val) +{ + return val; } -Adjuster::~Adjuster () { +Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon1, Gtk::Image *imgIcon2, double2double_fun slider2value_, double2double_fun value2slider_) +{ + + Gtk::HBox *hbox2 = NULL; + label = NULL; + adjusterListener = NULL; + afterReset = false; + blocked = false; + automatic = NULL; + eventPending = false; + + slider2value = slider2value_ ? slider2value_ : one2one; + value2slider = value2slider_ ? value2slider_ : one2one; + vMin = vmin; + vMax = vmax; + vStep = vstep; + addMode = false; + + // TODO: let the user chose the default value of Adjuster::delay, for slow machines + delay = options.adjusterDelay; // delay is no more static, so we can set the delay individually (useful for the RAW editor tab) + + set_border_width (0); + set_spacing (0); + + hbox = Gtk::manage (new Gtk::HBox ()); + hbox->set_border_width(0); + hbox->set_spacing(2); + + editedCheckBox = NULL; + + if (!vlabel.empty()) { + adjustmentName = vlabel; + label = Gtk::manage (new Gtk::Label (adjustmentName, Gtk::ALIGN_LEFT)); + } + + reset = Gtk::manage (new Gtk::Button ()); + reset->add (*Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); + reset->set_relief (Gtk::RELIEF_NONE); + reset->set_border_width (0); + reset->set_tooltip_text (M("ADJUSTER_RESET_TO_DEFAULT")); + reset->set_can_focus(false); + + spin = Gtk::manage (new MySpinButton ()); + spin->set_has_frame(false); + spin->set_name("FramelessSpinButton"); + + reset->set_size_request (-1, spin->get_height() > MIN_RESET_BUTTON_HEIGHT ? spin->get_height() : MIN_RESET_BUTTON_HEIGHT); + + slider = Gtk::manage (new MyHScale ()); + slider->set_draw_value (false); + + pack_start (*hbox, true, true); + + if (vlabel.empty()) { + // No label, everything goes in hbox + if (imgIcon1) { + hbox->pack_start (*imgIcon1, Gtk::PACK_SHRINK, 0); + } + + hbox->pack_start (*slider, Gtk::PACK_EXPAND_WIDGET, 0); + + if (imgIcon2) { + hbox->pack_start (*imgIcon2, Gtk::PACK_SHRINK, 0); + } + + hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); + hbox->pack_end (*spin, Gtk::PACK_SHRINK, 0); + } else { + // A label is provided, spreading the widgets in 2 rows + hbox->pack_start (*label); + hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); + hbox->pack_end (*spin, Gtk::PACK_SHRINK, 0); + + if (!imgIcon1 || !imgIcon2) { + pack_start (*slider, true, true); + } else { + // A second HBox is necessary + hbox2 = Gtk::manage (new Gtk::HBox()); + + if (imgIcon1) { + hbox2->pack_start (*imgIcon1, Gtk::PACK_SHRINK, 0); + } + + hbox2->pack_start (*slider, true, true); + + if (imgIcon2) { + hbox2->pack_start (*imgIcon2, Gtk::PACK_SHRINK, 0); + } + + pack_start (*hbox2, true, true); + } + } + + setLimits (vmin, vmax, vstep, vdefault); + + defaultVal = shapeValue (vdefault); + ctorDefaultVal = shapeValue (vdefault); + editedState = defEditedState = Irrelevant; + autoState = Irrelevant; + + sliderChange = slider->signal_value_changed().connect( sigc::mem_fun(*this, &Adjuster::sliderChanged) ); + spinChange = spin->signal_value_changed().connect ( sigc::mem_fun(*this, &Adjuster::spinChanged), true); + reset->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &Adjuster::resetPressed) ); + slider->set_update_policy (Gtk::UPDATE_CONTINUOUS); + + show_all (); +} + +Adjuster::~Adjuster () +{ sliderChange.block (true); spinChange.block (true); delayConnection.block (true); adjusterListener = NULL; - if (automatic) delete automatic; + + if (automatic) { + delete automatic; + } } -void Adjuster::addAutoButton (Glib::ustring tooltip) { +void Adjuster::addAutoButton (Glib::ustring tooltip) +{ if (!automatic) { automatic = new Gtk::CheckButton (); //automatic->add (*Gtk::manage (new RTImage ("processing.png"))); @@ -144,7 +167,8 @@ void Adjuster::addAutoButton (Glib::ustring tooltip) { } } -void Adjuster::delAutoButton () { +void Adjuster::delAutoButton () +{ if (automatic) { removeIfThere(hbox, automatic); delete automatic; @@ -152,34 +176,44 @@ void Adjuster::delAutoButton () { } } -void Adjuster::throwOnButtonRelease(bool throwOnBRelease) { +void Adjuster::throwOnButtonRelease(bool throwOnBRelease) +{ if (throwOnBRelease) { - if (!buttonReleaseSlider.connected()) + if (!buttonReleaseSlider.connected()) { buttonReleaseSlider = slider->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &Adjuster::sliderReleased) ); - if (!buttonReleaseSpin.connected()) - buttonReleaseSpin = spin->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &Adjuster::spinReleased) ); // Use the same callback hook - } - else { - if (buttonReleaseSlider.connected()) + } + + if (!buttonReleaseSpin.connected()) { + buttonReleaseSpin = spin->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &Adjuster::spinReleased) ); // Use the same callback hook + } + } else { + if (buttonReleaseSlider.connected()) { buttonReleaseSlider.disconnect(); - if (buttonReleaseSpin.connected()) + } + + if (buttonReleaseSpin.connected()) { buttonReleaseSpin.disconnect(); + } } + eventPending = false; } -void Adjuster::setDefault (double def) { +void Adjuster::setDefault (double def) +{ defaultVal = shapeValue (def); } -void Adjuster::setDefaultEditedState (EditedState eState) { +void Adjuster::setDefaultEditedState (EditedState eState) +{ defEditedState = eState; } -void Adjuster::autoToggled () { +void Adjuster::autoToggled () +{ if (!editedCheckBox) { // If not used in the BatchEditor panel @@ -187,205 +221,238 @@ void Adjuster::autoToggled () { // Disable the slider and spin button spin->set_sensitive(false); slider->set_sensitive(false); - } - else { + } else { // Enable the slider and spin button spin->set_sensitive(true); slider->set_sensitive(true); } } - if (adjusterListener!=NULL && !blocked) { + if (adjusterListener != NULL && !blocked) { adjusterListener->adjusterAutoToggled(this, automatic->get_active()); } } -void Adjuster::sliderReleased (GdkEventButton* event) { +void Adjuster::sliderReleased (GdkEventButton* event) +{ if ((event != NULL) && (event->button == 1)) { - if (delayConnection.connected()) + if (delayConnection.connected()) { delayConnection.disconnect (); + } + notifyListener(); } } -void Adjuster::spinReleased (GdkEventButton* event) { +void Adjuster::spinReleased (GdkEventButton* event) +{ - if ((event != NULL) && delay==0) { - if (delayConnection.connected()) + if ((event != NULL) && delay == 0) { + if (delayConnection.connected()) { delayConnection.disconnect (); + } + notifyListener(); } } -void Adjuster::resetValue (bool toInitial) { - if (editedState!=Irrelevant) { +void Adjuster::resetValue (bool toInitial) +{ + if (editedState != Irrelevant) { editedState = defEditedState; + if (editedCheckBox) { editedChange.block (true); - editedCheckBox->set_active (defEditedState==Edited); + editedCheckBox->set_active (defEditedState == Edited); editedChange.block (false); } + refreshLabelStyle (); } + afterReset = true; + if (toInitial) { // resetting to the initial editing value, when the image has been loaded - slider->set_value (addMode ? defaultVal : value2slider(defaultVal)); - } - else { + slider->set_value (addMode ? defaultVal : value2slider(defaultVal)); + } else { // resetting to the slider default value - if (addMode) + if (addMode) { slider->set_value (0.); - else + } else { slider->set_value (value2slider(ctorDefaultVal)); + } } } // Please note that it won't change the "Auto" CheckBox's state, if there -void Adjuster::resetPressed (GdkEventButton* event) { +void Adjuster::resetPressed (GdkEventButton* event) +{ - if ((event != NULL) && (event->state & GDK_CONTROL_MASK) && (event->button == 1)) + if ((event != NULL) && (event->state & GDK_CONTROL_MASK) && (event->button == 1)) { resetValue(true); - else + } else { resetValue(false); + } } -double Adjuster::shapeValue (double a) { +double Adjuster::shapeValue (double a) +{ - return round(a*pow(double(10), digits)) / pow(double(10), digits); + return round(a * pow(double(10), digits)) / pow(double(10), digits); } -void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefault) { +void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefault) +{ - sliderChange.block (true); - spinChange.block (true); - for (digits=0; fabs(vstep*pow(double(10),digits)-floor(vstep*pow(double(10),digits)))>0.000000000001; digits++); - spin->set_digits (digits); - spin->set_increments (vstep, 2.0*vstep); - spin->set_range (vmin, vmax); - spin->updateSize(); - spin->set_value (shapeValue(vdefault)); - slider->set_digits (digits); - slider->set_increments (vstep, 2.0*vstep); - slider->set_range (addMode ? vmin : value2slider(vmin), addMode ? vmax : value2slider(vmax)); - slider->set_value (addMode ? shapeValue(vdefault) : value2slider(shapeValue(vdefault))); - //defaultVal = shapeValue (vdefault); - sliderChange.block (false); - spinChange.block (false); + sliderChange.block (true); + spinChange.block (true); + + for (digits = 0; fabs(vstep * pow(double(10), digits) - floor(vstep * pow(double(10), digits))) > 0.000000000001; digits++); + + spin->set_digits (digits); + spin->set_increments (vstep, 2.0 * vstep); + spin->set_range (vmin, vmax); + spin->updateSize(); + spin->set_value (shapeValue(vdefault)); + slider->set_digits (digits); + slider->set_increments (vstep, 2.0 * vstep); + slider->set_range (addMode ? vmin : value2slider(vmin), addMode ? vmax : value2slider(vmax)); + slider->set_value (addMode ? shapeValue(vdefault) : value2slider(shapeValue(vdefault))); + //defaultVal = shapeValue (vdefault); + sliderChange.block (false); + spinChange.block (false); } -void Adjuster::setAddMode(bool addM) { - if (addM != addMode) { - // Switching the Adjuster to the new mode - addMode = addM; - if (addM) { - // Switching to the relative mode - double range = -vMin + vMax; - if (range < 0.) range = -range; - setLimits(-range, range, vStep, 0); - } - else { - // Switching to the absolute mode - setLimits(vMin, vMax, vStep, defaultVal); - } - } -} +void Adjuster::setAddMode(bool addM) +{ + if (addM != addMode) { + // Switching the Adjuster to the new mode + addMode = addM; -void Adjuster::spinChanged () { + if (addM) { + // Switching to the relative mode + double range = -vMin + vMax; - if (delayConnection.connected()) - delayConnection.disconnect (); + if (range < 0.) { + range = -range; + } - sliderChange.block (true); - slider->set_value (addMode ? spin->get_value () : value2slider(spin->get_value ())); - sliderChange.block (false); - - if (delay==0) { - if (adjusterListener && !blocked) { - if (!buttonReleaseSlider.connected() || afterReset) { - eventPending = false; - adjusterListener->adjusterChanged (this, spin->get_value ()); + setLimits(-range, range, vStep, 0); + } else { + // Switching to the absolute mode + setLimits(vMin, vMax, vStep, defaultVal); } - else eventPending = true; } - } - else { - eventPending = true; - delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Adjuster::notifyListener), delay); - } - - if (editedState==UnEdited) { - editedState = Edited; - if (editedCheckBox) { - editedChange.block (true); - editedCheckBox->set_active (true); - editedChange.block (false); - } - refreshLabelStyle (); - } - afterReset = false; } -void Adjuster::sliderChanged () { - - if (delayConnection.connected()) - delayConnection.disconnect (); +void Adjuster::spinChanged () +{ - spinChange.block (true); - spin->set_value (addMode ? slider->get_value () : slider2value(slider->get_value ())); - spinChange.block (false); - - if (delay==0 || afterReset) { - if (adjusterListener && !blocked) { - if (!buttonReleaseSlider.connected() || afterReset) { - eventPending = false; - adjusterListener->adjusterChanged (this, spin->get_value ()); - } - else eventPending = true; + if (delayConnection.connected()) { + delayConnection.disconnect (); } - } - else { - eventPending = true; - delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Adjuster::notifyListener), delay); - } - if (!afterReset && editedState==UnEdited) { - editedState = Edited; - if (editedCheckBox) { - editedChange.block (true); - editedCheckBox->set_active (true); - editedChange.block (false); + sliderChange.block (true); + slider->set_value (addMode ? spin->get_value () : value2slider(spin->get_value ())); + sliderChange.block (false); + + if (delay == 0) { + if (adjusterListener && !blocked) { + if (!buttonReleaseSlider.connected() || afterReset) { + eventPending = false; + adjusterListener->adjusterChanged (this, spin->get_value ()); + } else { + eventPending = true; + } + } + } else { + eventPending = true; + delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Adjuster::notifyListener), delay); } - refreshLabelStyle (); - } - afterReset = false; + + if (editedState == UnEdited) { + editedState = Edited; + + if (editedCheckBox) { + editedChange.block (true); + editedCheckBox->set_active (true); + editedChange.block (false); + } + + refreshLabelStyle (); + } + + afterReset = false; } -void Adjuster::setValue (double a) { +void Adjuster::sliderChanged () +{ - spinChange.block (true); - sliderChange.block (true); - spin->set_value (shapeValue (a)); - slider->set_value (addMode ? shapeValue(a) : value2slider(shapeValue (a))); - sliderChange.block (false); - spinChange.block (false); - afterReset = false; + if (delayConnection.connected()) { + delayConnection.disconnect (); + } + + spinChange.block (true); + spin->set_value (addMode ? slider->get_value () : slider2value(slider->get_value ())); + spinChange.block (false); + + if (delay == 0 || afterReset) { + if (adjusterListener && !blocked) { + if (!buttonReleaseSlider.connected() || afterReset) { + eventPending = false; + adjusterListener->adjusterChanged (this, spin->get_value ()); + } else { + eventPending = true; + } + } + } else { + eventPending = true; + delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Adjuster::notifyListener), delay); + } + + if (!afterReset && editedState == UnEdited) { + editedState = Edited; + + if (editedCheckBox) { + editedChange.block (true); + editedCheckBox->set_active (true); + editedChange.block (false); + } + + refreshLabelStyle (); + } + + afterReset = false; } -void Adjuster::setAutoValue (bool a) { +void Adjuster::setValue (double a) +{ + + spinChange.block (true); + sliderChange.block (true); + spin->set_value (shapeValue (a)); + slider->set_value (addMode ? shapeValue(a) : value2slider(shapeValue (a))); + sliderChange.block (false); + spinChange.block (false); + afterReset = false; +} + +void Adjuster::setAutoValue (bool a) +{ if (automatic) { bool oldVal = autoChange.block(true); automatic->set_active(a); autoChange.block(oldVal); + if (!editedCheckBox) { // If not used in the BatchEditor panel if (a) { // Disable the slider and spin button spin->set_sensitive(false); slider->set_sensitive(false); - } - else { + } else { // Enable the slider and spin button spin->set_sensitive(true); slider->set_sensitive(true); @@ -394,57 +461,71 @@ void Adjuster::setAutoValue (bool a) { } } -bool Adjuster::notifyListener () { +bool Adjuster::notifyListener () +{ - if (eventPending && adjusterListener!=NULL && !blocked) { - adjusterListener->adjusterChanged (this, spin->get_value ()); - } - eventPending = false; + if (eventPending && adjusterListener != NULL && !blocked) { + adjusterListener->adjusterChanged (this, spin->get_value ()); + } - return false; + eventPending = false; + + return false; } -bool Adjuster::notifyListenerAutoToggled () { +bool Adjuster::notifyListenerAutoToggled () +{ - if (adjusterListener!=NULL && !blocked) { - adjusterListener->adjusterAutoToggled(this, automatic->get_active()); - } - return false; + if (adjusterListener != NULL && !blocked) { + adjusterListener->adjusterAutoToggled(this, automatic->get_active()); + } + + return false; } -void Adjuster::setEnabled (bool enabled) { +void Adjuster::setEnabled (bool enabled) +{ bool autoVal = automatic && !editedCheckBox ? automatic->get_active() : true; spin->set_sensitive (enabled && autoVal); slider->set_sensitive (enabled && autoVal); - if (automatic) + + if (automatic) { automatic->set_sensitive (enabled); + } } -void Adjuster::setEditedState (EditedState eState) { +void Adjuster::setEditedState (EditedState eState) +{ - if (editedState!=eState) { + if (editedState != eState) { if (editedCheckBox) { editedChange.block (true); - editedCheckBox->set_active (eState==Edited); + editedCheckBox->set_active (eState == Edited); editedChange.block (false); } + editedState = eState; refreshLabelStyle (); } } -EditedState Adjuster::getEditedState () { +EditedState Adjuster::getEditedState () +{ - if (editedState!=Irrelevant && editedCheckBox) + if (editedState != Irrelevant && editedCheckBox) { editedState = editedCheckBox->get_active () ? Edited : UnEdited; + } + return editedState; } -void Adjuster::showEditedCB () { +void Adjuster::showEditedCB () +{ - if (label) + if (label) { removeIfThere(hbox, label, false); + } if (!editedCheckBox) { editedCheckBox = Gtk::manage(new Gtk::CheckButton (adjustmentName)); @@ -455,41 +536,59 @@ void Adjuster::showEditedCB () { } } -void Adjuster::refreshLabelStyle () { +void Adjuster::refreshLabelStyle () +{ -/* Glib::RefPtr style = label->get_style (); - Pango::FontDescription fd = style->get_font (); - fd.set_weight (editedState==Edited ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL); - style->set_font (fd); - label->set_style (style); - label->queue_draw ();*/ + /* Glib::RefPtr style = label->get_style (); + Pango::FontDescription fd = style->get_font (); + fd.set_weight (editedState==Edited ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL); + style->set_font (fd); + label->set_style (style); + label->queue_draw ();*/ } -void Adjuster::editedToggled () { +void Adjuster::editedToggled () +{ if (adjusterListener && !blocked) { adjusterListener->adjusterChanged (this, spin->get_value ()); } + eventPending = false; } -double Adjuster::trimValue (double val) { +double Adjuster::trimValue (double val) +{ + + if (val > vMax) { + val = vMax; // shapeValue(vMax) ? + } else if (val < vMin) { + val = vMin; // shapeValue(vMin) ? + } - if (val > vMax) val = vMax; // shapeValue(vMax) ? - else if (val < vMin) val = vMin; // shapeValue(vMin) ? return val; } -int Adjuster::trimValue (int val) { +int Adjuster::trimValue (int val) +{ + + if (val > (int)vMax) { + val = (int)vMax; // shapeValue(vMax) ? + } else if (val < (int)vMin) { + val = (int)vMin; // shapeValue(vMin) ? + } - if (val > (int)vMax) val = (int)vMax; // shapeValue(vMax) ? - else if (val < (int)vMin) val = (int)vMin; // shapeValue(vMin) ? return val; } -float Adjuster::trimValue (float val) { +float Adjuster::trimValue (float val) +{ + + if (val > (float)vMax) { + val = (float)vMax; // shapeValue(vMax) ? + } else if (val < (float)vMin) { + val = (float)vMin; // shapeValue(vMin) ? + } - if (val > (float)vMax) val = (float)vMax; // shapeValue(vMax) ? - else if (val < (float)vMin) val = (float)vMin; // shapeValue(vMin) ? return val; } diff --git a/rtgui/adjuster.h b/rtgui/adjuster.h index 773829df3..4b9ad36a4 100644 --- a/rtgui/adjuster.h +++ b/rtgui/adjuster.h @@ -7,7 +7,7 @@ * 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 @@ -24,9 +24,10 @@ #include "guiutils.h" class Adjuster; -class AdjusterListener { +class AdjusterListener +{ - public: +public: virtual ~AdjusterListener() {}; virtual void adjusterChanged (Adjuster* a, double newval) {} virtual void adjusterAutoToggled (Adjuster* a, bool newval) {} @@ -34,9 +35,10 @@ class AdjusterListener { typedef double(*double2double_fun)(double val); -class Adjuster : public Gtk::VBox { +class Adjuster : public Gtk::VBox +{ - protected: +protected: Glib::ustring adjustmentName; Gtk::HBox* hbox; Gtk::Label* label; @@ -53,8 +55,8 @@ class Adjuster : public Gtk::VBox { sigc::connection buttonReleaseSlider; sigc::connection buttonReleaseSpin; bool listenerReady; - double defaultVal; // current default value (it can change when switching from ADD or SET mode) - double ctorDefaultVal; // default value at construction time + double defaultVal; // current default value (it can change when switching from ADD or SET mode) + double ctorDefaultVal; // default value at construction time EditedState editedState; EditedState defEditedState; EditedState autoState; @@ -73,51 +75,92 @@ class Adjuster : public Gtk::VBox { void refreshLabelStyle (); double2double_fun value2slider, slider2value; - public: +public: int delay; - Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon1=NULL, Gtk::Image *imgIcon2=NULL, double2double_fun slider2value=NULL, double2double_fun value2slider=NULL); + Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon1 = NULL, Gtk::Image *imgIcon2 = NULL, double2double_fun slider2value = NULL, double2double_fun value2slider = NULL); virtual ~Adjuster (); // Add an "Automatic" checkbox next to the reset button. - void addAutoButton(Glib::ustring tooltip=""); + void addAutoButton(Glib::ustring tooltip = ""); // Remove the "Automatic" checkbox next to the reset button. void delAutoButton(); // Send back the value of og the Auto checkbox - bool getAutoValue () { return automatic!=NULL ? automatic->get_active () : false; } + bool getAutoValue () + { + return automatic != NULL ? automatic->get_active () : false; + } void setAutoValue (bool a); bool notifyListenerAutoToggled (); void autoToggled (); - void setAutoInconsistent (bool i) { if (automatic) automatic->set_inconsistent(i); } - bool getAutoInconsistent () { return automatic ? automatic->get_inconsistent() : true /* we have to return something */; } + void setAutoInconsistent (bool i) + { + if (automatic) { + automatic->set_inconsistent(i); + } + } + bool getAutoInconsistent () + { + return automatic ? automatic->get_inconsistent() : true /* we have to return something */; + } - void setAdjusterListener (AdjusterListener* alistener) { adjusterListener = alistener; } + void setAdjusterListener (AdjusterListener* alistener) + { + adjusterListener = alistener; + } // return the value trimmed to the limits at construction time - double getValue () { return shapeValue(spin->get_value ()); } + double getValue () + { + return shapeValue(spin->get_value ()); + } // return the value trimmed to the limits at construction time - int getIntValue () { return spin->get_value_as_int (); } + int getIntValue () + { + return spin->get_value_as_int (); + } // return the value trimmed to the limits at construction time, // method only used by the history manager, so decoration is added if addMode=true - Glib::ustring getTextValue () { if (addMode) return Glib::ustring::compose("%1", spin->get_text ()); else return spin->get_text (); } + Glib::ustring getTextValue () + { + if (addMode) { + return Glib::ustring::compose("%1", spin->get_text ()); + } else { + return spin->get_text (); + } + } - void setLabel (Glib::ustring lbl) { label->set_label(lbl); } + void setLabel (Glib::ustring lbl) + { + label->set_label(lbl); + } void setValue (double a); void setLimits (double vmin, double vmax, double vstep, double vdefault); void setEnabled (bool enabled); void setDefault (double def); // will let the adjuster throw it's "changed" signal when the mouse button is released. Can work altogether with the delay value. - void throwOnButtonRelease(bool throwOnBRelease=true); - void setNbDisplayedChars (int nbr) { spin->set_width_chars(nbr); } + void throwOnButtonRelease(bool throwOnBRelease = true); + void setNbDisplayedChars (int nbr) + { + spin->set_width_chars(nbr); + } void setEditedState (EditedState eState); EditedState getEditedState (); void setDefaultEditedState (EditedState eState); void showEditedCB (); - bool block(bool isBlocked) { bool oldValue = blocked; blocked = isBlocked; return oldValue; } + bool block(bool isBlocked) + { + bool oldValue = blocked; + blocked = isBlocked; + return oldValue; + } void setAddMode(bool addM); - bool getAddMode() { return addMode; }; + bool getAddMode() + { + return addMode; + }; void spinChanged (); void sliderChanged (); bool notifyListener (); diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index b2ba1a831..8dc843a8e 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -7,7 +7,7 @@ * 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 @@ -23,7 +23,7 @@ #include #include -#include +#include #include "thumbnail.h" #include "batchqueue.h" @@ -37,30 +37,38 @@ using namespace std; using namespace rtengine; -BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(NULL), fileCatalog(aFileCatalog), sequence(0), listener(NULL) { +BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(NULL), fileCatalog(aFileCatalog), sequence(0), listener(NULL) +{ location = THLOC_BATCHQUEUE; int p = 0; pmenu = new Gtk::Menu (); - pmenu->attach (*Gtk::manage(open = new Gtk::MenuItem (M("FILEBROWSER_POPUPOPENINEDITOR"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(open = new Gtk::MenuItem (M("FILEBROWSER_POPUPOPENINEDITOR"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; - pmenu->attach (*Gtk::manage(head = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPMOVEHEAD"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(head = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPMOVEHEAD"))), 0, 1, p, p + 1); + p++; head->set_image(*Gtk::manage(new RTImage ("toleftend.png"))); - pmenu->attach (*Gtk::manage(tail = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPMOVEEND"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(tail = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPMOVEEND"))), 0, 1, p, p + 1); + p++; tail->set_image(*Gtk::manage(new RTImage ("torightend.png"))); - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; - pmenu->attach (*Gtk::manage(cancel = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPCANCELJOB"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(cancel = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPCANCELJOB"))), 0, 1, p, p + 1); + p++; cancel->set_image(*Gtk::manage(new RTImage ("gtk-close.png"))); pmenu->show_all (); - + // Accelerators pmaccelgroup = Gtk::AccelGroup::create (); pmenu->set_accel_group (pmaccelgroup); @@ -72,8 +80,8 @@ BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(NULL), fileCatal open->signal_activate().connect(sigc::mem_fun(*this, &BatchQueue::openLastSelectedItemInEditor)); cancel->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::cancelItems), &selected)); - head->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::headItems), &selected)); - tail->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::tailItems), &selected)); + head->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::headItems), &selected)); + tail->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::tailItems), &selected)); selall->signal_activate().connect (sigc::mem_fun(*this, &BatchQueue::selectAll)); setArrangement (ThumbBrowserBase::TB_Vertical); @@ -81,130 +89,142 @@ BatchQueue::BatchQueue (FileCatalog* aFileCatalog) : processing(NULL), fileCatal BatchQueue::~BatchQueue () { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif // The listener merges parameters with old values, so delete afterwards - for (size_t i=0; iresize(getThumbnailHeight()); } } // Reduce the max size of a thumb, since thumb is processed synchronously on adding to queue // leading to very long waiting when adding more images -int BatchQueue::calcMaxThumbnailHeight() { +int BatchQueue::calcMaxThumbnailHeight() +{ return std::min(options.maxThumbnailHeight, 200); } // Function for virtual override in thumbbrowser base -int BatchQueue::getMaxThumbnailHeight() const { +int BatchQueue::getMaxThumbnailHeight() const +{ return calcMaxThumbnailHeight(); } -void BatchQueue::saveThumbnailHeight (int height) { +void BatchQueue::saveThumbnailHeight (int height) +{ options.thumbSizeQueue = height; } -int BatchQueue::getThumbnailHeight () { +int BatchQueue::getThumbnailHeight () +{ // The user could have manually forced the option to a too big value return std::max(std::min(options.thumbSizeQueue, 200), 10); } -void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) { +void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) +{ pmenu->popup (3, this->eventTime); } -void BatchQueue::doubleClicked(ThumbBrowserEntryBase* entry) { +void BatchQueue::doubleClicked(ThumbBrowserEntryBase* entry) +{ openItemInEditor(entry); } -bool BatchQueue::keyPressed (GdkEventKey* event) { - bool ctrl = event->state & GDK_CONTROL_MASK; - - if ((event->keyval==GDK_A || event->keyval==GDK_a) && ctrl) { +bool BatchQueue::keyPressed (GdkEventKey* event) +{ + bool ctrl = event->state & GDK_CONTROL_MASK; + + if ((event->keyval == GDK_A || event->keyval == GDK_a) && ctrl) { selectAll (); return true; - } - else if ((event->keyval==GDK_E || event->keyval== GDK_e) && ctrl) { + } else if ((event->keyval == GDK_E || event->keyval == GDK_e) && ctrl) { openLastSelectedItemInEditor(); return true; - } - else if (event->keyval==GDK_Home) { + } else if (event->keyval == GDK_Home) { headItems (&selected); return true; - } - else if (event->keyval==GDK_End) { + } else if (event->keyval == GDK_End) { tailItems (&selected); return true; - } - else if (event->keyval==GDK_Delete) { + } else if (event->keyval == GDK_Delete) { cancelItems (&selected); return true; } - - return false; + + return false; } void BatchQueue::addEntries ( std::vector &entries, bool head, bool save) { - { - // TODO: Check for Linux - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif + { + // TODO: Check for Linux +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - for( std::vector::iterator entry = entries.begin(); entry != entries.end();entry++ ){ - (*entry)->setParent (this); + for( std::vector::iterator entry = entries.begin(); entry != entries.end(); entry++ ) { + (*entry)->setParent (this); - // BatchQueueButtonSet HAVE TO be added before resizing to take them into account - BatchQueueButtonSet* bqbs = new BatchQueueButtonSet (*entry); - bqbs->setButtonListener (this); - (*entry)->addButtonSet (bqbs); + // BatchQueueButtonSet HAVE TO be added before resizing to take them into account + BatchQueueButtonSet* bqbs = new BatchQueueButtonSet (*entry); + bqbs->setButtonListener (this); + (*entry)->addButtonSet (bqbs); - (*entry)->resize (getThumbnailHeight()); // batch queue might have smaller, restricted size - Glib::ustring tempFile = getTempFilenameForParams( (*entry)->filename ); + (*entry)->resize (getThumbnailHeight()); // batch queue might have smaller, restricted size + Glib::ustring tempFile = getTempFilenameForParams( (*entry)->filename ); - // recovery save - if( !(*entry)->params.save( tempFile ) ) - (*entry)->savedParamsFile = tempFile; + // recovery save + if( !(*entry)->params.save( tempFile ) ) { + (*entry)->savedParamsFile = tempFile; + } - (*entry)->selected = false; - if (!head) - fd.push_back (*entry); - else { - std::vector::iterator pos; - for (pos=fd.begin(); pos!=fd.end(); pos++) - if (!(*pos)->processing) { - fd.insert (pos, *entry); - break; - } - if (pos==fd.end()) - fd.push_back (*entry); - } - if ((*entry)->thumbnail) - (*entry)->thumbnail->imageEnqueued (); - } - } + (*entry)->selected = false; - if (save) - saveBatchQueue( ); + if (!head) { + fd.push_back (*entry); + } else { + std::vector::iterator pos; + + for (pos = fd.begin(); pos != fd.end(); pos++) + if (!(*pos)->processing) { + fd.insert (pos, *entry); + break; + } + + if (pos == fd.end()) { + fd.push_back (*entry); + } + } + + if ((*entry)->thumbnail) { + (*entry)->thumbnail->imageEnqueued (); + } + } + } + + if (save) { + saveBatchQueue( ); + } redraw(); notifyListener (false); @@ -213,36 +233,38 @@ void BatchQueue::addEntries ( std::vector &entries, bool head, bool BatchQueue::saveBatchQueue( ) { Glib::ustring savedQueueFile; - savedQueueFile = options.rtdir+"/batch/queue.csv"; + savedQueueFile = options.rtdir + "/batch/queue.csv"; FILE *f = safe_g_fopen (savedQueueFile, "wt"); - if (f==NULL) + if (f == NULL) { return false; + } { - // TODO: Check for Linux - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif + // TODO: Check for Linux +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - if (fd.size()) - // The column's header is mandatory (the first line will be skipped when loaded) - fprintf(f,"input image full path|param file full path|output image full path|file format|jpeg quality|jpeg subsampling|" - "png bit depth|png compression|tiff bit depth|uncompressed tiff|save output params|force format options|\n"); + if (fd.size()) + // The column's header is mandatory (the first line will be skipped when loaded) + fprintf(f, "input image full path|param file full path|output image full path|file format|jpeg quality|jpeg subsampling|" + "png bit depth|png compression|tiff bit depth|uncompressed tiff|save output params|force format options|\n"); - // method is already running with entryLock, so no need to lock again - for (std::vector::iterator pos=fd.begin(); pos!=fd.end(); pos++){ - BatchQueueEntry* bqe = reinterpret_cast(*pos); - // Warning: for code's simplicity in loadBatchQueue, each field must end by the '|' character, safer than ';' or ',' since it can't be used in paths - fprintf(f,"%s|%s|%s|%s|%d|%d|%d|%d|%d|%d|%d|%d|\n", - bqe->filename.c_str(),bqe->savedParamsFile.c_str(), bqe->outFileName.c_str(), bqe->saveFormat.format.c_str(), - bqe->saveFormat.jpegQuality, bqe->saveFormat.jpegSubSamp, - bqe->saveFormat.pngBits, bqe->saveFormat.pngCompression, - bqe->saveFormat.tiffBits, bqe->saveFormat.tiffUncompressed, - bqe->saveFormat.saveParams, bqe->forceFormatOpts - ); - } + // method is already running with entryLock, so no need to lock again + for (std::vector::iterator pos = fd.begin(); pos != fd.end(); pos++) { + BatchQueueEntry* bqe = reinterpret_cast(*pos); + // Warning: for code's simplicity in loadBatchQueue, each field must end by the '|' character, safer than ';' or ',' since it can't be used in paths + fprintf(f, "%s|%s|%s|%s|%d|%d|%d|%d|%d|%d|%d|%d|\n", + bqe->filename.c_str(), bqe->savedParamsFile.c_str(), bqe->outFileName.c_str(), bqe->saveFormat.format.c_str(), + bqe->saveFormat.jpegQuality, bqe->saveFormat.jpegSubSamp, + bqe->saveFormat.pngBits, bqe->saveFormat.pngCompression, + bqe->saveFormat.tiffBits, bqe->saveFormat.tiffUncompressed, + bqe->saveFormat.saveParams, bqe->forceFormatOpts + ); + } } + fclose (f); return true; } @@ -250,28 +272,28 @@ bool BatchQueue::saveBatchQueue( ) bool BatchQueue::loadBatchQueue( ) { Glib::ustring savedQueueFile; - savedQueueFile = options.rtdir+"/batch/queue.csv"; + savedQueueFile = options.rtdir + "/batch/queue.csv"; FILE *f = safe_g_fopen (savedQueueFile, "rt"); - if (f!=NULL) { + if (f != NULL) { char *buffer = new char[1024]; - unsigned numLoaded=0; + unsigned numLoaded = 0; // skipping the first line - bool firstLine=true; + bool firstLine = true; // Yes, it's better to get the lock for the whole file reading, // to update the list in one shot without any other concurrent access! // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - while (fgets (buffer, 1024, f)){ + while (fgets (buffer, 1024, f)) { if (firstLine) { // skipping the column's title line - firstLine=false; + firstLine = false; continue; } @@ -280,110 +302,145 @@ bool BatchQueue::loadBatchQueue( ) Glib::ustring paramsFile; Glib::ustring outputFile; Glib::ustring saveFmt(options.saveFormat.format); - int jpegQuality=options.saveFormat.jpegQuality, jpegSubSamp =options.saveFormat.jpegSubSamp; - int pngBits =options.saveFormat.pngBits, pngCompression =options.saveFormat.pngCompression; - int tiffBits =options.saveFormat.tiffBits, tiffUncompressed=options.saveFormat.tiffUncompressed; - int saveParams =options.saveFormat.saveParams; - int forceFormatOpts =options.forceFormatOpts; + int jpegQuality = options.saveFormat.jpegQuality, jpegSubSamp = options.saveFormat.jpegSubSamp; + int pngBits = options.saveFormat.pngBits, pngCompression = options.saveFormat.pngCompression; + int tiffBits = options.saveFormat.tiffBits, tiffUncompressed = options.saveFormat.tiffUncompressed; + int saveParams = options.saveFormat.saveParams; + int forceFormatOpts = options.forceFormatOpts; Glib::ustring currLine(buffer); int a = 0; - if (currLine.rfind('\n') != Glib::ustring::npos) a++; - if (currLine.rfind('\r') != Glib::ustring::npos) a++; - if (a) - currLine = currLine.substr(0, currLine.length()-a); + + if (currLine.rfind('\n') != Glib::ustring::npos) { + a++; + } + + if (currLine.rfind('\r') != Glib::ustring::npos) { + a++; + } + + if (a) { + currLine = currLine.substr(0, currLine.length() - a); + } // Looking for the image's full path pos = currLine.find('|'); + if (pos != Glib::ustring::npos) { - source = currLine.substr(0, pos); - currLine = currLine.substr(pos+1); + source = currLine.substr(0, pos); + currLine = currLine.substr(pos + 1); - // Looking for the procparams' full path - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - paramsFile = currLine.substr(0, pos); - currLine = currLine.substr(pos+1); - - // Looking for the full output path; if empty, it'll use the template string - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - outputFile = currLine.substr(0, pos); - currLine = currLine.substr(pos+1); - - // No need to bother reading the last options, they will be ignored if outputFile is empty! - if (!outputFile.empty()) { - - // Looking for the saving format + // Looking for the procparams' full path pos = currLine.find('|'); + if (pos != Glib::ustring::npos) { - saveFmt = currLine.substr(0, pos); - currLine = currLine.substr(pos+1); + paramsFile = currLine.substr(0, pos); + currLine = currLine.substr(pos + 1); - // Looking for the jpeg quality - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - jpegQuality = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + // Looking for the full output path; if empty, it'll use the template string + pos = currLine.find('|'); - // Looking for the jpeg subsampling - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - jpegSubSamp = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + if (pos != Glib::ustring::npos) { + outputFile = currLine.substr(0, pos); + currLine = currLine.substr(pos + 1); - // Looking for the png bit depth - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - pngBits = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + // No need to bother reading the last options, they will be ignored if outputFile is empty! + if (!outputFile.empty()) { - // Looking for the png compression - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - pngCompression = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + // Looking for the saving format + pos = currLine.find('|'); - // Looking for the tiff bit depth - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - tiffBits = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + if (pos != Glib::ustring::npos) { + saveFmt = currLine.substr(0, pos); + currLine = currLine.substr(pos + 1); - // Looking for the tiff uncompression - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - tiffUncompressed = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + // Looking for the jpeg quality + pos = currLine.find('|'); - // Looking out if we have to save the procparams - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - saveParams = atoi(currLine.substr(0, pos).c_str()); - currLine = currLine.substr(pos+1); + if (pos != Glib::ustring::npos) { + jpegQuality = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); - // Looking out if we have to to use the format options - pos = currLine.find('|'); - if (pos != Glib::ustring::npos) { - forceFormatOpts = atoi(currLine.substr(0, pos).c_str()); - // currLine = currLine.substr(pos+1); + // Looking for the jpeg subsampling + pos = currLine.find('|'); - }}}}}}}}}}}}} + if (pos != Glib::ustring::npos) { + jpegSubSamp = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); - if( !source.empty() && !paramsFile.empty() ){ + // Looking for the png bit depth + pos = currLine.find('|'); + + if (pos != Glib::ustring::npos) { + pngBits = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); + + // Looking for the png compression + pos = currLine.find('|'); + + if (pos != Glib::ustring::npos) { + pngCompression = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); + + // Looking for the tiff bit depth + pos = currLine.find('|'); + + if (pos != Glib::ustring::npos) { + tiffBits = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); + + // Looking for the tiff uncompression + pos = currLine.find('|'); + + if (pos != Glib::ustring::npos) { + tiffUncompressed = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); + + // Looking out if we have to save the procparams + pos = currLine.find('|'); + + if (pos != Glib::ustring::npos) { + saveParams = atoi(currLine.substr(0, pos).c_str()); + currLine = currLine.substr(pos + 1); + + // Looking out if we have to to use the format options + pos = currLine.find('|'); + + if (pos != Glib::ustring::npos) { + forceFormatOpts = atoi(currLine.substr(0, pos).c_str()); + // currLine = currLine.substr(pos+1); + + } + } + } + } + } + } + } + } + } + } + } + } + } + + if( !source.empty() && !paramsFile.empty() ) { rtengine::procparams::ProcParams pparams; - if( pparams.load( paramsFile ) ) + + if( pparams.load( paramsFile ) ) { continue; + } ::Thumbnail *thumb = cacheMgr->getEntry( source ); - if( thumb ){ + + if( thumb ) { rtengine::ProcessingJob* job = rtengine::ProcessingJob::create(source, thumb->getType() == FT_Raw, pparams); int prevh = getMaxThumbnailHeight(); int prevw = prevh; thumb->getThumbnailSize (prevw, prevh, &pparams); - BatchQueueEntry *entry = new BatchQueueEntry(job, pparams,source, prevw, prevh, thumb); + BatchQueueEntry *entry = new BatchQueueEntry(job, pparams, source, prevw, prevh, thumb); thumb->decreaseRef(); // Removing the refCount acquired by cacheMgr->getEntry entry->setParent(this); @@ -396,6 +453,7 @@ bool BatchQueue::loadBatchQueue( ) entry->savedParamsFile = paramsFile; entry->selected = false; entry->outFileName = outputFile; + if (!outputFile.empty()) { entry->saveFormat.format = saveFmt; entry->saveFormat.jpegQuality = jpegQuality; @@ -403,18 +461,20 @@ bool BatchQueue::loadBatchQueue( ) entry->saveFormat.pngBits = pngBits; entry->saveFormat.pngCompression = pngCompression; entry->saveFormat.tiffBits = tiffBits; - entry->saveFormat.tiffUncompressed = tiffUncompressed!=0; - entry->saveFormat.saveParams = saveParams!=0; - entry->forceFormatOpts = forceFormatOpts!=0; - } - else + entry->saveFormat.tiffUncompressed = tiffUncompressed != 0; + entry->saveFormat.saveParams = saveParams != 0; + entry->forceFormatOpts = forceFormatOpts != 0; + } else { entry->forceFormatOpts = false; + } + fd.push_back(entry); numLoaded++; } } } + delete [] buffer; fclose(f); } @@ -432,9 +492,9 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename char stringTimestamp [80]; time ( &rawtime ); timeinfo = localtime ( &rawtime ); - strftime (stringTimestamp,sizeof(stringTimestamp),"_%Y%m%d%H%M%S_",timeinfo); + strftime (stringTimestamp, sizeof(stringTimestamp), "_%Y%m%d%H%M%S_", timeinfo); Glib::ustring savedParamPath; - savedParamPath = options.rtdir+"/batch/"; + savedParamPath = options.rtdir + "/batch/"; safe_g_mkdir_with_parents (savedParamPath, 0755); savedParamPath += Glib::path_get_basename (filename); savedParamPath += stringTimestamp; @@ -449,28 +509,39 @@ int cancelItemUI (void* data) return 0; } -void BatchQueue::cancelItems (std::vector* items) { +void BatchQueue::cancelItems (std::vector* items) +{ { // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - for (size_t i=0; isize(); i++) { + for (size_t i = 0; i < items->size(); i++) { BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; - if (entry->processing) + + if (entry->processing) { continue; + } + std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); - if (pos!=fd.end()) { + + if (pos != fd.end()) { fd.erase (pos); rtengine::ProcessingJob::destroy (entry->job); - if (entry->thumbnail) + + if (entry->thumbnail) { entry->thumbnail->imageRemovedFromQueue (); + } + g_idle_add (cancelItemUI, entry); } } - for (size_t i=0; iselected = false; + } + lastClicked = NULL; selected.clear (); } @@ -481,69 +552,84 @@ void BatchQueue::cancelItems (std::vector* items) { notifyListener (false); } -void BatchQueue::headItems (std::vector* items) { - { - // TODO: Check for Linux - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif - - for (int i=items->size()-1; i>=0; i--) { - BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; - if (entry->processing) - continue; - std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); - if (pos!=fd.end() && pos!=fd.begin()) { - fd.erase (pos); - // find the first item that is not under processing - for (pos=fd.begin(); pos!=fd.end(); pos++) - if (!(*pos)->processing) { - fd.insert (pos, entry); - break; - } - } - } - } - saveBatchQueue( ); - - redraw (); -} - -void BatchQueue::tailItems (std::vector* items) { - { - // TODO: Check for Linux - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif - - for (size_t i=0; isize(); i++) { - BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; - if (entry->processing) - continue; - std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); - if (pos!=fd.end()) { - fd.erase (pos); - fd.push_back (entry); - } - } - } - saveBatchQueue( ); - - redraw (); -} - -void BatchQueue::selectAll () { +void BatchQueue::headItems (std::vector* items) +{ { // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif + + for (int i = items->size() - 1; i >= 0; i--) { + BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; + + if (entry->processing) { + continue; + } + + std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); + + if (pos != fd.end() && pos != fd.begin()) { + fd.erase (pos); + + // find the first item that is not under processing + for (pos = fd.begin(); pos != fd.end(); pos++) + if (!(*pos)->processing) { + fd.insert (pos, entry); + break; + } + } + } + } + saveBatchQueue( ); + + redraw (); +} + +void BatchQueue::tailItems (std::vector* items) +{ + { + // TODO: Check for Linux +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif + + for (size_t i = 0; i < items->size(); i++) { + BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; + + if (entry->processing) { + continue; + } + + std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); + + if (pos != fd.end()) { + fd.erase (pos); + fd.push_back (entry); + } + } + } + saveBatchQueue( ); + + redraw (); +} + +void BatchQueue::selectAll () +{ + { + // TODO: Check for Linux +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif lastClicked = NULL; selected.clear (); - for (size_t i=0; iprocessing) + + for (size_t i = 0; i < fd.size(); i++) { + if (fd[i]->processing) { continue; + } + fd[i]->selected = true; selected.push_back (fd[i]); } @@ -551,12 +637,13 @@ void BatchQueue::selectAll () { queue_draw (); } -void BatchQueue::openLastSelectedItemInEditor() { +void BatchQueue::openLastSelectedItemInEditor() +{ { // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif if (selected.size() > 0) { openItemInEditor(selected.back()); @@ -564,7 +651,8 @@ void BatchQueue::openLastSelectedItemInEditor() { } } -void BatchQueue::openItemInEditor(ThumbBrowserEntryBase* item) { +void BatchQueue::openItemInEditor(ThumbBrowserEntryBase* item) +{ if (item) { std::vector< ::Thumbnail*> requestedItem; requestedItem.push_back(item->thumbnail); @@ -573,13 +661,14 @@ void BatchQueue::openItemInEditor(ThumbBrowserEntryBase* item) { } -void BatchQueue::startProcessing () { +void BatchQueue::startProcessing () +{ if (!processing) { // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif if (!fd.empty()) { BatchQueueEntry* next; @@ -589,17 +678,21 @@ void BatchQueue::startProcessing () { next->processing = true; next->sequence = sequence = 1; processing = next; + // remove from selection if (processing->selected) { std::vector::iterator pos = std::find (selected.begin(), selected.end(), processing); - if (pos!=selected.end()) + + if (pos != selected.end()) { selected.erase (pos); + } + processing->selected = false; } - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif // remove button set next->removeButtonSet (); @@ -611,40 +704,48 @@ void BatchQueue::startProcessing () { } } -rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { +rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) +{ // save image img Glib::ustring fname; SaveFormat saveFormat; - if (processing->outFileName=="") { // auto file name + + if (processing->outFileName == "") { // auto file name Glib::ustring s = calcAutoFileNameBase (processing->filename, processing->sequence); saveFormat = options.saveFormatBatch; fname = autoCompleteFileName (s, saveFormat.format); - } - else { // use the save-as filename with automatic completion for uniqueness - if (processing->forceFormatOpts) + } else { // use the save-as filename with automatic completion for uniqueness + if (processing->forceFormatOpts) { saveFormat = processing->saveFormat; - else + } else { saveFormat = options.saveFormatBatch; + } + // The output filename's extension is forced to the current or selected output format, // despite what the user have set in the fielneame's field of the "Save as" dialgo box fname = autoCompleteFileName (removeExtension(processing->outFileName), saveFormat.format); //fname = autoCompleteFileName (removeExtension(processing->outFileName), getExtension(processing->outFileName)); } + //printf ("fname=%s, %s\n", fname.c_str(), removeExtension(fname).c_str()); - if (img && fname!="") { + if (img && fname != "") { int err = 0; - if (saveFormat.format=="tif") - err = img->saveAsTIFF (fname, saveFormat.tiffBits,saveFormat.tiffUncompressed); - else if (saveFormat.format=="png") + + if (saveFormat.format == "tif") { + err = img->saveAsTIFF (fname, saveFormat.tiffBits, saveFormat.tiffUncompressed); + } else if (saveFormat.format == "png") { err = img->saveAsPNG (fname, saveFormat.pngCompression, saveFormat.pngBits); - else if (saveFormat.format=="jpg") + } else if (saveFormat.format == "jpg") { err = img->saveAsJPEG (fname, saveFormat.jpegQuality, saveFormat.jpegSubSamp); + } + img->free (); - if (err) - throw Glib::FileError(Glib::FileError::FAILED, M("MAIN_MSG_CANNOTSAVE")+"\n"+fname); + if (err) { + throw Glib::FileError(Glib::FileError::FAILED, M("MAIN_MSG_CANNOTSAVE") + "\n" + fname); + } if (saveFormat.saveParams) { // We keep the extension to avoid overwriting the profile when we have @@ -658,19 +759,20 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { processing->thumbnail->imageRemovedFromQueue (); } } + // save temporary params file name: delete as last thing Glib::ustring processedParams = processing->savedParamsFile; - + // delete from the queue - bool queueEmptied=false; - bool remove_button_set = false; + bool queueEmptied = false; + bool remove_button_set = false; { // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif - +#endif + delete processing; processing = NULL; @@ -678,49 +780,58 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { // return next job if (fd.empty()) { - queueEmptied=true; - } - else if (listener && listener->canStartNext ()) { + queueEmptied = true; + } else if (listener && listener->canStartNext ()) { BatchQueueEntry* next = static_cast(fd[0]); // tag it as selected and set sequence next->processing = true; next->sequence = ++sequence; processing = next; + // remove from selection if (processing->selected) { std::vector::iterator pos = std::find (selected.begin(), selected.end(), processing); - if (pos!=selected.end()) + + if (pos != selected.end()) { selected.erase (pos); + } + processing->selected = false; } + // remove button set remove_button_set = true; } } - if (remove_button_set) { - // ButtonSet have Cairo::Surface which might be rendered while we're trying to delete them + + if (remove_button_set) { + // ButtonSet have Cairo::Surface which might be rendered while we're trying to delete them GThreadLock lock; processing->removeButtonSet (); - } + } + if (saveBatchQueue( )) { safe_g_remove( processedParams ); // Delete all files in directory \batch when finished, just to be sure to remove zombies // Not sure that locking is necessary, but it should be safer // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif - if( fd.empty() ){ - #if PROTECT_VECTORS +#endif + + if( fd.empty() ) { +#if PROTECT_VECTORS MYREADERLOCK_RELEASE(l); - #endif +#endif 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); - for(std::vector::iterator iter=names.begin(); iter != names.end();iter++ ) + + for(std::vector::iterator iter = names.begin(); iter != names.end(); iter++ ) { safe_g_remove( *iter ); + } } } @@ -732,29 +843,39 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { // Calculates automatic filename of processed batch entry, but just the base name // example output: "c:\out\converted\dsc0121" -Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence) { +Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence) +{ std::vector pa; std::vector da; - for (size_t i=0; i=origFileName.size()) + } + + if (i >= origFileName.size()) { break; + } + Glib::ustring tok = ""; - while ((i=0 && origFileName[extpos]!='.'; extpos--); - for (int k=extpos-1; k>=0 && origFileName[k]!='/' && origFileName[k]!='\\'; k--) + + int extpos = origFileName.size() - 1; + + for (; extpos >= 0 && origFileName[extpos] != '.'; extpos--); + + for (int k = extpos - 1; k >= 0 && origFileName[k] != '/' && origFileName[k] != '\\'; k--) { filename = origFileName[k] + filename; + } // printf ("%d, |%s|\n", extpos, filename.c_str()); - + // constructing full output path // printf ("path=|%s|\n", options.savePath.c_str()); - Glib::ustring path=""; + Glib::ustring path = ""; + if (options.saveUsePathTemplate) { - int ix=0; - while (options.savePathTemplate[ix]!=0) { - if (options.savePathTemplate[ix]=='%') { + int ix = 0; + + while (options.savePathTemplate[ix] != 0) { + if (options.savePathTemplate[ix] == '%') { ix++; - if (options.savePathTemplate[ix]=='p') { + + if (options.savePathTemplate[ix] == 'p') { ix++; - int i = options.savePathTemplate[ix]-'0'; - if (i=1 && w<=9) { + if (w >= 1 && w <= 9) { ix++; seqstr << std::setw (w) << std::setfill ('0'); } @@ -824,18 +955,21 @@ Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileNam } } - else + else { path = path + options.savePathTemplate[ix]; + } + ix++; } - } - else + } else { path = Glib::build_filename (options.savePathFolder, filename); + } return path; } -Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format) { +Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format) +{ // separate filename and the path to the destination directory Glib::ustring dstdir = Glib::path_get_dirname (fileName); @@ -843,60 +977,69 @@ 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) ) + if (safe_g_mkdir_with_parents (dstdir, 0755) ) { return ""; - - // In overwrite mode we TRY to delete the old file first. - // if that's not possible (e.g. locked by viewer, R/O), we revert to the standard naming scheme - bool inOverwriteMode=options.overwriteOutputFile; + } - for (int tries=0; tries<100; tries++) { - if (tries==0) + // In overwrite mode we TRY to delete the old file first. + // if that's not possible (e.g. locked by viewer, R/O), we revert to the standard naming scheme + bool inOverwriteMode = options.overwriteOutputFile; + + for (int tries = 0; tries < 100; tries++) { + if (tries == 0) { fname = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), format); - else + } else { fname = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, format); + } - int fileExists=safe_file_test (fname, Glib::FILE_TEST_EXISTS); - - if (inOverwriteMode && fileExists) { - if (safe_g_remove(fname) == -1) - inOverwriteMode = false; // failed to delete- revert to old naming scheme - else - fileExists = false; // deleted now - } - - if (!fileExists) { + int fileExists = safe_file_test (fname, Glib::FILE_TEST_EXISTS); + + if (inOverwriteMode && fileExists) { + if (safe_g_remove(fname) == -1) { + inOverwriteMode = false; // failed to delete- revert to old naming scheme + } else { + fileExists = false; // deleted now + } + } + + if (!fileExists) { return fname; } } + return ""; } -int setProgressUI (void* p) { - (static_cast(p))->redraw(); +int setProgressUI (void* p) +{ + (static_cast(p))->redraw(); return 0; } -void BatchQueue::setProgress (double p) { +void BatchQueue::setProgress (double p) +{ - if (processing) + if (processing) { processing->progress = p; + } // No need to acquire the GUI, setProgressUI will do it g_idle_add (setProgressUI, this); } -void BatchQueue::buttonPressed (LWButton* button, int actionCode, void* actionData) { - +void BatchQueue::buttonPressed (LWButton* button, int actionCode, void* actionData) +{ + std::vector bqe; bqe.push_back (static_cast(actionData)); - if (actionCode==10) // cancel + if (actionCode == 10) { // cancel cancelItems (&bqe); - else if (actionCode==8) // to head + } else if (actionCode == 8) { // to head headItems (&bqe); - else if (actionCode==9) // to tail + } else if (actionCode == 9) { // to tail tailItems (&bqe); + } } struct NLParams { @@ -907,7 +1050,8 @@ struct NLParams { Glib::ustring queueErrorMessage; }; -int bqnotifylistenerUI (void* data) { +int bqnotifylistenerUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected NLParams* params = static_cast(data); params->listener->queueSizeChanged (params->qsize, params->queueEmptied, params->queueError, params->queueErrorMessage); @@ -915,17 +1059,18 @@ int bqnotifylistenerUI (void* data) { return 0; } -void BatchQueue::notifyListener (bool queueEmptied) { +void BatchQueue::notifyListener (bool queueEmptied) +{ if (listener) { NLParams* params = new NLParams; params->listener = listener; { - // TODO: Check for Linux - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif - params->qsize = fd.size(); + // TODO: Check for Linux +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif + params->qsize = fd.size(); } params->queueEmptied = queueEmptied; params->queueError = false; @@ -933,12 +1078,14 @@ void BatchQueue::notifyListener (bool queueEmptied) { } } -void BatchQueue::redrawNeeded (LWButton* button) { +void BatchQueue::redrawNeeded (LWButton* button) +{ GThreadLock lock; queue_draw (); } -void BatchQueue::error (Glib::ustring msg) { +void BatchQueue::error (Glib::ustring msg) +{ if (processing && processing->processing) { // restore failed thumb @@ -950,6 +1097,7 @@ void BatchQueue::error (Glib::ustring msg) { processing = NULL; redraw (); } + if (listener) { NLParams* params = new NLParams; params->listener = listener; diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index f515bed29..4e97ebc9f 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -6,7 +6,7 @@ * 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 @@ -26,20 +26,22 @@ #include "lwbuttonset.h" #include "thumbbrowserbase.h" -class BatchQueueListener { +class BatchQueueListener +{ - public: - virtual ~BatchQueueListener () {} - virtual void queueSizeChanged (int qsize, bool queueEmptied, bool queueError, Glib::ustring queueErrorMessage) =0; - virtual bool canStartNext () =0; +public: + virtual ~BatchQueueListener () {} + virtual void queueSizeChanged (int qsize, bool queueEmptied, bool queueError, Glib::ustring queueErrorMessage) = 0; + virtual bool canStartNext () = 0; }; class FileCatalog; -class BatchQueue : public ThumbBrowserBase, - public rtengine::BatchProcessingListener, - public LWButtonListener { +class BatchQueue : public ThumbBrowserBase, + public rtengine::BatchProcessingListener, + public LWButtonListener +{ - protected: +protected: int getMaxThumbnailHeight() const; void saveThumbnailHeight (int height); int getThumbnailHeight (); @@ -49,14 +51,14 @@ class BatchQueue : public ThumbBrowserBase, int sequence; // holds the current sequence index Glib::ustring nameTemplate; - + Gtk::ImageMenuItem* cancel; Gtk::ImageMenuItem* head; Gtk::ImageMenuItem* tail; Gtk::MenuItem* selall; Gtk::MenuItem* open; Gtk::Menu* pmenu; - + Glib::RefPtr pmaccelgroup; BatchQueueListener* listener; @@ -66,11 +68,11 @@ class BatchQueue : public ThumbBrowserBase, bool saveBatchQueue( ); void notifyListener (bool queueEmptied); - public: +public: BatchQueue (FileCatalog* aFileCatalog); ~BatchQueue (); - void addEntries (std::vector &entries, bool head=false, bool save=true); + void addEntries (std::vector &entries, bool head = false, bool save = true); void cancelItems (std::vector* items); void headItems (std::vector* items); void tailItems (std::vector* items); @@ -80,12 +82,13 @@ class BatchQueue : public ThumbBrowserBase, void startProcessing (); - bool hasJobs () { + bool hasJobs () + { // not sure that this lock is necessary, but it's safer to keep it... // TODO: Check for Linux - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif return (!fd.empty()); } @@ -97,8 +100,11 @@ class BatchQueue : public ThumbBrowserBase, bool keyPressed (GdkEventKey* event); void buttonPressed (LWButton* button, int actionCode, void* actionData); void redrawNeeded (LWButton* button); - - void setBatchQueueListener (BatchQueueListener* l) { listener = l; } + + void setBatchQueueListener (BatchQueueListener* l) + { + listener = l; + } bool loadBatchQueue (); void resizeLoadedQueue(); diff --git a/rtgui/batchqueuebuttonset.cc b/rtgui/batchqueuebuttonset.cc index f3079a62b..380c4abe3 100644 --- a/rtgui/batchqueuebuttonset.cc +++ b/rtgui/batchqueuebuttonset.cc @@ -7,7 +7,7 @@ * 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 @@ -28,7 +28,8 @@ Cairo::RefPtr BatchQueueButtonSet::cancelIcon; Cairo::RefPtr BatchQueueButtonSet::headIcon; Cairo::RefPtr BatchQueueButtonSet::tailIcon; -BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) { +BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) +{ if (!iconsLoaded) { cancelIcon = safe_create_from_png ("gtk-close.png"); diff --git a/rtgui/batchqueuebuttonset.h b/rtgui/batchqueuebuttonset.h index bd43b5657..cb6ccda56 100644 --- a/rtgui/batchqueuebuttonset.h +++ b/rtgui/batchqueuebuttonset.h @@ -7,7 +7,7 @@ * 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 @@ -23,16 +23,17 @@ #include class BatchQueueEntry; -class BatchQueueButtonSet : public LWButtonSet { +class BatchQueueButtonSet : public LWButtonSet +{ - static bool iconsLoaded; - - public: - static Cairo::RefPtr cancelIcon; - static Cairo::RefPtr headIcon; - static Cairo::RefPtr tailIcon; + static bool iconsLoaded; - BatchQueueButtonSet (BatchQueueEntry* myEntry); +public: + static Cairo::RefPtr cancelIcon; + static Cairo::RefPtr headIcon; + static Cairo::RefPtr tailIcon; + + BatchQueueButtonSet (BatchQueueEntry* myEntry); }; #endif diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc index 3728b3bd3..f5ca6a6d5 100644 --- a/rtgui/batchqueueentry.cc +++ b/rtgui/batchqueueentry.cc @@ -7,7 +7,7 @@ * 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 @@ -31,138 +31,158 @@ Glib::RefPtr BatchQueueEntry::savedAsIcon; BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm) : ThumbBrowserEntryBase(fname), opreview(NULL), origpw(prevw), origph(prevh), opreviewDone(false), - job(pjob), progress(0), outFileName(""), sequence(0), forceFormatOpts(false) { + job(pjob), progress(0), outFileName(""), sequence(0), forceFormatOpts(false) +{ - thumbnail=thm; + thumbnail = thm; params = pparams; - #if 1 //ndef WIN32 +#if 1 //ndef WIN32 // The BatchQueueEntryIdleHelper tracks if an entry has been deleted while it was sitting waiting for "idle" bqih = new BatchQueueEntryIdleHelper; bqih->bqentry = this; bqih->destroyed = false; bqih->pending = 0; - #endif +#endif if (!iconsLoaded) { savedAsIcon = safe_create_from_file ("gtk-save.png"); iconsLoaded = true; } - if (thumbnail) + if (thumbnail) { thumbnail->increaseRef (); + } } -BatchQueueEntry::~BatchQueueEntry () { +BatchQueueEntry::~BatchQueueEntry () +{ batchQueueEntryUpdater.removeJobs (this); - if (opreview) delete [] opreview; opreview=NULL; - if (thumbnail) - thumbnail->decreaseRef (); - if (bqih->pending) + if (opreview) { + delete [] opreview; + } + + opreview = NULL; + + if (thumbnail) { + thumbnail->decreaseRef (); + } + + if (bqih->pending) { bqih->destroyed = true; - else + } else { delete bqih; + } } -void BatchQueueEntry::refreshThumbnailImage () { +void BatchQueueEntry::refreshThumbnailImage () +{ if (!opreviewDone) { // creating the image buffer first //if (!opreview) opreview = new guint8[(origpw+1) * origph * 3]; // this will asynchronously compute the original preview and land at this.updateImage batchQueueEntryUpdater.process (NULL, origpw, origph, preh, this, ¶ms, thumbnail); - } - else { + } else { // this will asynchronously land at this.updateImage batchQueueEntryUpdater.process (opreview, origpw, origph, preh, this); } } -void BatchQueueEntry::calcThumbnailSize () { +void BatchQueueEntry::calcThumbnailSize () +{ prew = preh * origpw / origph; } -void BatchQueueEntry::drawProgressBar (Glib::RefPtr win, Glib::RefPtr gc, const Gdk::Color& foregr, const Gdk::Color& backgr, int x, int w, int y, int h) { +void BatchQueueEntry::drawProgressBar (Glib::RefPtr win, Glib::RefPtr gc, const Gdk::Color& foregr, const Gdk::Color& backgr, int x, int w, int y, int h) +{ - if (processing) { - Cairo::RefPtr cr = win->create_cairo_context(); - cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); - double px = x + w/6.0; - double pw = w*2.0/3.0; - double py = y + h/4.0; - double ph = h/2.0; - cr->move_to (px, py); - cr->line_to (px+pw, py); - cr->set_line_width (ph); - cr->set_line_cap (Cairo::LINE_CAP_ROUND); - cr->set_source_rgb (foregr.get_red_p(), foregr.get_green_p(), foregr.get_blue_p()); - cr->stroke (); + if (processing) { + Cairo::RefPtr cr = win->create_cairo_context(); + cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); + double px = x + w / 6.0; + double pw = w * 2.0 / 3.0; + double py = y + h / 4.0; + double ph = h / 2.0; + cr->move_to (px, py); + cr->line_to (px + pw, py); + cr->set_line_width (ph); + cr->set_line_cap (Cairo::LINE_CAP_ROUND); + cr->set_source_rgb (foregr.get_red_p(), foregr.get_green_p(), foregr.get_blue_p()); + cr->stroke (); - cr->move_to (px, py); - cr->line_to (px+pw, py); - cr->set_line_width (ph*3.0/4.0); - cr->set_source_rgb (backgr.get_red_p(), backgr.get_green_p(), backgr.get_blue_p()); - cr->stroke (); + cr->move_to (px, py); + cr->line_to (px + pw, py); + cr->set_line_width (ph * 3.0 / 4.0); + cr->set_source_rgb (backgr.get_red_p(), backgr.get_green_p(), backgr.get_blue_p()); + cr->stroke (); - cr->move_to (px, py); - cr->line_to (px+pw*progress, py); - cr->set_line_width (ph/2.0); - cr->set_source_rgb (foregr.get_red_p(), foregr.get_green_p(), foregr.get_blue_p()); - cr->stroke (); - } + cr->move_to (px, py); + cr->line_to (px + pw * progress, py); + cr->set_line_width (ph / 2.0); + cr->set_source_rgb (foregr.get_red_p(), foregr.get_green_p(), foregr.get_blue_p()); + cr->stroke (); + } } -void BatchQueueEntry::removeButtonSet () { +void BatchQueueEntry::removeButtonSet () +{ delete buttonSet; buttonSet = NULL; } -std::vector > BatchQueueEntry::getIconsOnImageArea () { +std::vector > BatchQueueEntry::getIconsOnImageArea () +{ std::vector > ret; - if (!outFileName.empty()) + if (!outFileName.empty()) { ret.push_back (savedAsIcon); + } - return ret; + return ret; } -void BatchQueueEntry::getIconSize (int& w, int& h) { +void BatchQueueEntry::getIconSize (int& w, int& h) +{ w = savedAsIcon->get_width (); h = savedAsIcon->get_height (); } -Glib::ustring BatchQueueEntry::getToolTip (int x, int y) { +Glib::ustring BatchQueueEntry::getToolTip (int x, int y) +{ // get the parent class' tooltip first Glib::ustring tooltip = ThumbBrowserEntryBase::getToolTip(x, y); // add the saving param options if (!outFileName.empty()) { tooltip += Glib::ustring::compose("\n\n%1: %2", M("BATCHQUEUE_DESTFILENAME"), outFileName); + if (forceFormatOpts) { tooltip += Glib::ustring::compose("\n\n%1: %2 (%3 bits)", M("SAVEDLG_FILEFORMAT"), saveFormat.format, - saveFormat.format == "png" ? saveFormat.pngBits : - saveFormat.format == "tif" ? saveFormat.tiffBits : 8); + saveFormat.format == "png" ? saveFormat.pngBits : + saveFormat.format == "tif" ? saveFormat.tiffBits : 8); + if (saveFormat.format == "jpg") { tooltip += Glib::ustring::compose("\n%1: %2\n%3: %4", - M("SAVEDLG_JPEGQUAL"), saveFormat.jpegQuality, - M("SAVEDLG_SUBSAMP"), - saveFormat.jpegSubSamp==1 ? M("SAVEDLG_SUBSAMP_1") : - saveFormat.jpegSubSamp==2 ? M("SAVEDLG_SUBSAMP_2") : - M("SAVEDLG_SUBSAMP_3")); - } - else if (saveFormat.format == "png") + M("SAVEDLG_JPEGQUAL"), saveFormat.jpegQuality, + M("SAVEDLG_SUBSAMP"), + saveFormat.jpegSubSamp == 1 ? M("SAVEDLG_SUBSAMP_1") : + saveFormat.jpegSubSamp == 2 ? M("SAVEDLG_SUBSAMP_2") : + M("SAVEDLG_SUBSAMP_3")); + } else if (saveFormat.format == "png") { tooltip += Glib::ustring::compose("\n%1: %2", M("SAVEDLG_PNGCOMPR"), saveFormat.pngCompression); - else if (saveFormat.format == "tif") { - if (saveFormat.tiffUncompressed) - tooltip += Glib::ustring::compose("\n%1", M("SAVEDLG_TIFFUNCOMPRESSED")); + } else if (saveFormat.format == "tif") { + if (saveFormat.tiffUncompressed) { + tooltip += Glib::ustring::compose("\n%1", M("SAVEDLG_TIFFUNCOMPRESSED")); + } } } } @@ -174,10 +194,11 @@ Glib::ustring BatchQueueEntry::getToolTip (int x, int y) { struct BQUpdateParam { BatchQueueEntryIdleHelper* bqih; guint8* img; - int w,h; + int w, h; }; -int updateImageUIThread (void* data) { +int updateImageUIThread (void* data) +{ BQUpdateParam* params = static_cast(data); @@ -187,50 +208,57 @@ int updateImageUIThread (void* data) { // If the BQEntry was destroyed meanwhile, remove all the IdleHelper if all entries came through if (bqih->destroyed) { - if (bqih->pending == 1) + if (bqih->pending == 1) { delete bqih; - else + } else { bqih->pending--; + } + delete [] params->img; delete params; return 0; } - + bqih->bqentry->_updateImage (params->img, params->w, params->h); bqih->pending--; - + delete params; return 0; } // Starts a copy of img->preview via GTK thread -void BatchQueueEntry::updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) { +void BatchQueueEntry::updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) +{ // since the update itself is already called in an async thread and there are problem with accessing opreview in thumbbrowserbase, // it's safer to do this synchronously { GThreadLock lock; - _updateImage(img,w,h); + _updateImage(img, w, h); } } -void BatchQueueEntry::_updateImage (guint8* img, int w, int h) { +void BatchQueueEntry::_updateImage (guint8* img, int w, int h) +{ if (preh == h) { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, lockRW); - #endif +#endif prew = w; assert (preview == NULL); - preview = new guint8 [prew*preh*3]; - memcpy (preview, img, prew*preh*3); - if (parent) + preview = new guint8 [prew * preh * 3]; + memcpy (preview, img, prew * preh * 3); + + if (parent) { parent->redrawNeeded (this); + } } + delete [] img; } diff --git a/rtgui/batchqueueentry.h b/rtgui/batchqueueentry.h index 7c2b360ce..4ee3eb1a3 100644 --- a/rtgui/batchqueueentry.h +++ b/rtgui/batchqueueentry.h @@ -7,7 +7,7 @@ * 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 @@ -32,7 +32,8 @@ struct BatchQueueEntryIdleHelper { int pending; }; -class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListener { +class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListener +{ guint8* opreview; int origpw, origph; @@ -52,13 +53,13 @@ public: int sequence; SaveFormat saveFormat; bool forceFormatOpts; - - BatchQueueEntry (rtengine::ProcessingJob* job, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm=NULL); + + BatchQueueEntry (rtengine::ProcessingJob* job, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm = NULL); ~BatchQueueEntry (); void refreshThumbnailImage (); void calcThumbnailSize (); - + void drawProgressBar (Glib::RefPtr win, Glib::RefPtr gc, const Gdk::Color& foregr, const Gdk::Color& backgr, int x, int w, int y, int h); void removeButtonSet (); diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 2c0c913d6..db78913b0 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -7,7 +7,7 @@ * 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 @@ -29,7 +29,8 @@ struct BQProcessLoaded { BatchQueue* bq; }; -int processLoadedBatchQueueUIThread (void* data) { +int processLoadedBatchQueueUIThread (void* data) +{ BatchQueue* bq = static_cast(data); bq->resizeLoadedQueue(); @@ -38,18 +39,23 @@ int processLoadedBatchQueueUIThread (void* data) { static Glib::ustring makeFolderLabel(Glib::ustring path) { - if (!safe_file_test (path, Glib::FILE_TEST_IS_DIR)) + if (!safe_file_test (path, Glib::FILE_TEST_IS_DIR)) { return "(" + M("GENERAL_NONE") + ")"; + } + if (path.size() > 40) { size_t last_ds = path.find_last_of (G_DIR_SEPARATOR); + if (last_ds != Glib::ustring::npos && last_ds > 10) { path = "..." + path.substr(last_ds); } } + return path; } -BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { +BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) +{ batchQueue = Gtk::manage( new BatchQueue(aFileCatalog) ); @@ -64,11 +70,11 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { start->set_active (false); stop->set_active (true); autoStart->set_active (options.procQueueEnabled); - + start->set_image (*Gtk::manage (new RTImage ("gtk-media-play.png"))); - startConnection = start->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::startBatchProc)); + startConnection = start->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::startBatchProc)); stop->set_image (*Gtk::manage (new RTImage ("gtk-media-stop.png"))); - stopConnection = stop->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::stopBatchProc)); + stopConnection = stop->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::stopBatchProc)); batchQueueButtonBox->pack_start (*start, Gtk::PACK_SHRINK, 4); batchQueueButtonBox->pack_start (*stop, Gtk::PACK_SHRINK, 4); batchQueueButtonBox->pack_start (*autoStart, Gtk::PACK_SHRINK, 4); @@ -78,16 +84,16 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { Gtk::VBox* odvb = Gtk::manage (new Gtk::VBox ()); odvb->set_border_width (4); Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); - useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE")+":")); - hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK,4); + useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE") + ":")); + hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK, 4); outdirTemplate = Gtk::manage (new Gtk::Entry ()); hb2->pack_start (*outdirTemplate); odvb->pack_start (*hb2, Gtk::PACK_SHRINK, 4); outdirTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); useTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); - useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER")+":")); - hb3->pack_start (*useFolder, Gtk::PACK_SHRINK,4); + useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER") + ":")); + hb3->pack_start (*useFolder, Gtk::PACK_SHRINK, 4); #if defined(__APPLE__) || defined(__linux__) // At the time of writing (2013-11-11) the gtkmm FileChooserButton with ACTION_SELECT_FOLDER @@ -108,8 +114,11 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { hb3->pack_start (*outdirFolder); 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 (safe_file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { outdirFolder->set_current_folder (options.savePathFolder); + } + outdirFolderButton = 0; #endif @@ -122,7 +131,7 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { // Output file format selection fformat = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FILEFORMAT"))); saveFormatPanel = Gtk::manage (new SaveFormatPanel ()); - fformat->add (*saveFormatPanel); + fformat->add (*saveFormatPanel); saveFormatPanel->init (options.saveFormatBatch); outdirTemplate->set_text (options.savePathTemplate); @@ -130,9 +139,9 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { useFolder->set_active (!options.saveUsePathTemplate); // setup signal handlers - outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); - useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); - useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); + outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); + useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); + useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); saveFormatPanel->setListener (this); // setup button bar @@ -143,7 +152,7 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { topBox->pack_start (*fdir); topBox->pack_start (*fformat, Gtk::PACK_SHRINK, 4); - // add middle browser area + // add middle browser area pack_start (*batchQueue); // lower box with thumbnail zoom @@ -153,27 +162,28 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { // thumbnail zoom Gtk::HBox* zoomBox = Gtk::manage (new Gtk::HBox ()); zoomBox->pack_start (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); - Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("")+M("FILEBROWSER_THUMBSIZE")+":")); + Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("") + M("FILEBROWSER_THUMBSIZE") + ":")); zoomLabel->set_use_markup (true); - zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4); + zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4); zoomInButton = Gtk::manage (new Gtk::Button ()); zoomInButton->set_image (*Gtk::manage (new RTImage ("gtk-zoom-in.png"))); - zoomInButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn)); + zoomInButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn)); zoomInButton->set_relief (Gtk::RELIEF_NONE); zoomInButton->set_tooltip_markup (M("FILEBROWSER_ZOOMINHINT")); zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK); zoomOutButton = Gtk::manage (new Gtk::Button ()); zoomOutButton->set_image (*Gtk::manage (new RTImage ("gtk-zoom-out.png"))); - zoomOutButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut)); + zoomOutButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut)); zoomOutButton->set_relief (Gtk::RELIEF_NONE); zoomOutButton->set_tooltip_markup (M("FILEBROWSER_ZOOMOUTHINT")); - zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); - bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK); + zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); + bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK); batchQueue->setBatchQueueListener (this); show_all (); + if (batchQueue->loadBatchQueue ()) { g_idle_add_full (G_PRIORITY_LOW, processLoadedBatchQueueUIThread, batchQueue, NULL); } @@ -182,53 +192,57 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) { // it is expected to have a non null forceOrientation value on Preferences update only. In this case, qsize is ingored and computed automatically void BatchQueuePanel::updateTab (int qsize, int forceOrientation) { - Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent()); + Gtk::Notebook *nb = (Gtk::Notebook *)(this->get_parent()); - if (forceOrientation > 0) + if (forceOrientation > 0) { qsize = batchQueue->getEntries().size(); + } - if ((forceOrientation==0 && options.mainNBVertical) || (forceOrientation==2)) { + if ((forceOrientation == 0 && options.mainNBVertical) || (forceOrientation == 2)) { Gtk::VBox* vbb = Gtk::manage (new Gtk::VBox ()); Gtk::Label* l; - if(!qsize ){ + if(!qsize ) { vbb->pack_start (*Gtk::manage (new RTImage ("processing.png"))); - l=Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_BATCHQUEUE")) ); - } else if( start->get_active () ){ + l = Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_BATCHQUEUE")) ); + } else if( start->get_active () ) { vbb->pack_start (*Gtk::manage (new RTImage ("processing-play.png"))); - l=Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]")); + l = Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_BATCHQUEUE") + " [" + Glib::ustring::format( qsize ) + "]")); } else { vbb->pack_start (*Gtk::manage (new RTImage ("processing-pause.png"))); - l=Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" )); + l = Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_BATCHQUEUE") + " [" + Glib::ustring::format( qsize ) + "]" )); } + l->set_angle (90); vbb->pack_start (*l); vbb->set_spacing (2); vbb->set_tooltip_markup (M("MAIN_FRAME_BATCHQUEUE_TOOLTIP")); vbb->show_all (); - nb->set_tab_label(*this,*vbb); + nb->set_tab_label(*this, *vbb); } else { Gtk::HBox* hbb = Gtk::manage (new Gtk::HBox ()); + if (!qsize ) { hbb->pack_start (*Gtk::manage (new RTImage ("processing.png"))); hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") ))); - } else if ( start->get_active () ){ + } else if ( start->get_active () ) { hbb->pack_start (*Gtk::manage (new RTImage ("processing-play.png"))); - hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" ))); + hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") + " [" + Glib::ustring::format( qsize ) + "]" ))); } else { hbb->pack_start (*Gtk::manage (new RTImage ("processing-pause.png"))); - hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" ))); + hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") + " [" + Glib::ustring::format( qsize ) + "]" ))); } + hbb->set_spacing (2); hbb->set_tooltip_markup (M("MAIN_FRAME_BATCHQUEUE_TOOLTIP")); hbb->show_all (); - nb->set_tab_label(*this,*hbb); + nb->set_tab_label(*this, *hbb); } } void BatchQueuePanel::queueSizeChanged (int qsize, bool queueEmptied, bool queueError, Glib::ustring queueErrorMessage) { - updateTab ( qsize); + updateTab ( qsize); if (queueEmptied || queueError) { stopBatchProc (); @@ -237,13 +251,15 @@ void BatchQueuePanel::queueSizeChanged (int qsize, bool queueEmptied, bool queue SoundManager::playSoundAsync(options.sndBatchQueueDone); } + if (queueError) { Gtk::MessageDialog msgd (queueErrorMessage, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.run (); } } -void BatchQueuePanel::startBatchProc () { +void BatchQueuePanel::startBatchProc () +{ stopConnection.block (true); startConnection.block (true); @@ -251,20 +267,21 @@ void BatchQueuePanel::startBatchProc () { start->set_active (true); stopConnection.block (false); startConnection.block (false); - + if (batchQueue->hasJobs()) { fdir->set_sensitive (false); fformat->set_sensitive (false); saveOptions(); batchQueue->startProcessing (); - } - else + } else { stopBatchProc (); + } updateTab (batchQueue->getEntries().size()); } -void BatchQueuePanel::stopBatchProc () { +void BatchQueuePanel::stopBatchProc () +{ stopConnection.block (true); startConnection.block (true); @@ -275,40 +292,46 @@ void BatchQueuePanel::stopBatchProc () { updateTab (batchQueue->getEntries().size()); } -void BatchQueuePanel::addBatchQueueJobs ( std::vector &entries, bool head) { +void BatchQueuePanel::addBatchQueueJobs ( std::vector &entries, bool head) +{ batchQueue->addEntries (entries, head); - - if (stop->get_active () && autoStart->get_active ()) + + if (stop->get_active () && autoStart->get_active ()) { startBatchProc (); + } } -bool BatchQueuePanel::canStartNext () { +bool BatchQueuePanel::canStartNext () +{ - if (start->get_active ()) + if (start->get_active ()) { return true; - else { + } else { fdir->set_sensitive (true); fformat->set_sensitive (true); return false; } } -void BatchQueuePanel::saveOptions () { +void BatchQueuePanel::saveOptions () +{ options.savePathTemplate = outdirTemplate->get_text(); options.saveUsePathTemplate = useTemplate->get_active(); options.procQueueEnabled = autoStart->get_active (); } -void BatchQueuePanel::pathFolderButtonPressed () { +void BatchQueuePanel::pathFolderButtonPressed () +{ - Gtk::FileChooserDialog fc(M("PREFERENCES_OUTDIRFOLDER"),Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); + Gtk::FileChooserDialog fc(M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-ok"), Gtk::RESPONSE_OK); fc.set_filename(options.savePathFolder); fc.set_transient_for(*parent); int result = fc.run(); + if (result == Gtk::RESPONSE_OK) { if (safe_file_test(fc.get_current_folder(), Glib::FILE_TEST_IS_DIR)) { options.savePathFolder = fc.get_current_folder(); @@ -318,30 +341,36 @@ void BatchQueuePanel::pathFolderButtonPressed () { } // We only want to save the following when it changes, -// since these settings are shared with editorpanel : -void BatchQueuePanel::pathFolderChanged () { - +// since these settings are shared with editorpanel : +void BatchQueuePanel::pathFolderChanged () +{ + options.savePathFolder = outdirFolder->get_current_folder(); } -void BatchQueuePanel::formatChanged (Glib::ustring f) { - +void BatchQueuePanel::formatChanged (Glib::ustring f) +{ + options.saveFormatBatch = saveFormatPanel->getFormat (); - + } -bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) { +bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) +{ bool ctrl = event->state & GDK_CONTROL_MASK; - if (ctrl){ + + if (ctrl) { switch(event->keyval) { - case GDK_s: - if (start->get_active()) { - stopBatchProc(); - } else { - startBatchProc(); - } - return true; + case GDK_s: + if (start->get_active()) { + stopBatchProc(); + } else { + startBatchProc(); + } + + return true; } } + return batchQueue->keyPressed (event); } diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 55aad806a..997514bef 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -7,7 +7,7 @@ * 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 @@ -28,52 +28,56 @@ class RTWindow; class FileCatalog; class Thumbnail; class BatchQueuePanel : public Gtk::VBox, - public BatchQueueListener, - public FormatChangeListener { + public BatchQueueListener, + public FormatChangeListener +{ - Gtk::Button* zoomInButton; - Gtk::Button* zoomOutButton; - Gtk::ToggleButton* start; - Gtk::ToggleButton* stop; - Gtk::CheckButton* autoStart; - sigc::connection startConnection; - sigc::connection stopConnection; + Gtk::Button* zoomInButton; + Gtk::Button* zoomOutButton; + Gtk::ToggleButton* start; + Gtk::ToggleButton* stop; + Gtk::CheckButton* autoStart; + sigc::connection startConnection; + sigc::connection stopConnection; - Gtk::Entry* outdirTemplate; - MyFileChooserButton* outdirFolder; - Gtk::Button* outdirFolderButton; - Gtk::RadioButton* useTemplate; - Gtk::RadioButton* useFolder; - SaveFormatPanel* saveFormatPanel; - Gtk::Frame *fdir, *fformat; + Gtk::Entry* outdirTemplate; + MyFileChooserButton* outdirFolder; + Gtk::Button* outdirFolderButton; + Gtk::RadioButton* useTemplate; + Gtk::RadioButton* useFolder; + SaveFormatPanel* saveFormatPanel; + Gtk::Frame *fdir, *fformat; - RTWindow* parent; - BatchQueue* batchQueue; - Gtk::HBox* bottomBox; - Gtk::HBox* topBox; + RTWindow* parent; + BatchQueue* batchQueue; + Gtk::HBox* bottomBox; + Gtk::HBox* topBox; - public: - - BatchQueuePanel (FileCatalog* aFileCatalog); +public: - void setParent (RTWindow* p) { parent = p; } + BatchQueuePanel (FileCatalog* aFileCatalog); - void addBatchQueueJobs (std::vector &entries , bool head=false); + void setParent (RTWindow* p) + { + parent = p; + } - // batchqueuelistener interface - void queueSizeChanged (int qsize, bool queueEmptied, bool queueError, Glib::ustring queueErrorMessage); - bool canStartNext (); - - void startBatchProc (); - void stopBatchProc (); - - void saveOptions (); - void pathFolderChanged (); - void pathFolderButtonPressed (); - void formatChanged (Glib::ustring f); - void updateTab (int qsize, int forceOrientation=0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical - - bool handleShortcutKey (GdkEventKey* event); + void addBatchQueueJobs (std::vector &entries , bool head = false); + + // batchqueuelistener interface + void queueSizeChanged (int qsize, bool queueEmptied, bool queueError, Glib::ustring queueErrorMessage); + bool canStartNext (); + + void startBatchProc (); + void stopBatchProc (); + + void saveOptions (); + void pathFolderChanged (); + void pathFolderButtonPressed (); + void formatChanged (Glib::ustring f); + void updateTab (int qsize, int forceOrientation = 0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical + + bool handleShortcutKey (GdkEventKey* event); }; #endif diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 8e83a6493..95f7f3ec7 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -25,72 +25,93 @@ using namespace rtengine::procparams; -BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), somethingChanged(false), parent(parent) { +BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), somethingChanged(false), parent(parent) +{ - blockedUpdate = false; - // remove exif panel and iptc panel - std::vector::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel); - if (epi!=toolPanels.end()) - toolPanels.erase (epi); - std::vector::iterator ipi = std::find (toolPanels.begin(), toolPanels.end(), iptcpanel); - if (ipi!=toolPanels.end()) - toolPanels.erase (ipi); - toolPanelNotebook->remove_page (*metadataPanel); - metadataPanel = 0; - toiM = 0; + blockedUpdate = false; + // remove exif panel and iptc panel + std::vector::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel); - for (size_t i=0; i::iterator ipi = std::find (toolPanels.begin(), toolPanels.end(), iptcpanel); + + if (ipi != toolPanels.end()) { + toolPanels.erase (ipi); + } + + toolPanelNotebook->remove_page (*metadataPanel); + metadataPanel = 0; + toiM = 0; + + for (size_t i = 0; i < toolPanels.size(); i++) { toolPanels[i]->setBatchMode (true); + } } -void BatchToolPanelCoordinator::selectionChanged (const std::vector& selected) { +void BatchToolPanelCoordinator::selectionChanged (const std::vector& selected) +{ - if (selected!=this->selected) { + if (selected != this->selected) { closeSession (); this->selected = selected; selFileNames.clear (); - for (size_t i=0; igetFileName ()); + } + initSession (); } } -void BatchToolPanelCoordinator::closeSession (bool save) { +void BatchToolPanelCoordinator::closeSession (bool save) +{ pparamsEdited.set (false); - for (size_t i=0; iremoveThumbnailListener (this); + } if (somethingChanged && save) { // read new values from the gui - for (size_t i=0; iwrite (&pparams, &pparamsEdited); + } // combine with initial parameters and set ProcParams newParams; - for (size_t i=0; itrimValues (&newParams); + } selected[i]->setProcParams (newParams, NULL, BATCHEDITOR, true); } } - for (size_t i=0; iclearParamChanges (); + } } -void BatchToolPanelCoordinator::initSession () { +void BatchToolPanelCoordinator::initSession () +{ somethingChanged = false; initialPP.resize (selected.size()); - for (size_t i=0; igetProcParams (); selected[i]->applyAutoExp (initialPP[i]); selected[i]->addThumbnailListener (this); @@ -101,267 +122,551 @@ void BatchToolPanelCoordinator::initSession () { crop->setDimensions (100000, 100000); -/* if (!selected.empty()) { - pparams = selected[0]->getProcParams (); - for (int i=0; isetDefaults (&pparams, &pparamsEdited); - toolPanels[i]->read (&pparams, &pparamsEdited); + /* if (!selected.empty()) { + pparams = selected[0]->getProcParams (); + for (int i=0; isetDefaults (&pparams, &pparamsEdited); + toolPanels[i]->read (&pparams, &pparamsEdited); + } + for (int i=0; iprocParamsChanged (&pparams, rtengine::EvPhotoLoaded, "batch processing", &pparamsEdited); } - for (int i=0; iprocParamsChanged (&pparams, rtengine::EvPhotoLoaded, "batch processing", &pparamsEdited); - } -*/ + */ if (!selected.empty()) { - // The first selected image (in the thumbnail list, not the click list) is used to populate the EditorPanel and set the default values - pparams = selected[0]->getProcParams (); + // The first selected image (in the thumbnail list, not the click list) is used to populate the EditorPanel and set the default values + pparams = selected[0]->getProcParams (); - coarse->initBatchBehavior (); + coarse->initBatchBehavior (); - if (selected.size()==1) { + if (selected.size() == 1) { - for (size_t i=0; isetMultiImage(false); + for (size_t i = 0; i < toolPanels.size(); i++) { + toolPanels.at(i)->setMultiImage(false); + } - toneCurve->setAdjusterBehavior (false, false, false, false, false, false, false, false); - lcurve->setAdjusterBehavior (false, false, false); - whitebalance->setAdjusterBehavior (false, false, false); - vibrance->setAdjusterBehavior (false, false); - vignetting->setAdjusterBehavior (false, false, false, false); - colorappearance->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false); - rotate->setAdjusterBehavior (false); - distortion->setAdjusterBehavior (false); - perspective->setAdjusterBehavior (false); - gradient->setAdjusterBehavior (false, false, false, false); - pcvignette->setAdjusterBehavior (false, false, false); - cacorrection->setAdjusterBehavior (false); - sharpening->setAdjusterBehavior (false); - sharpenEdge->setAdjusterBehavior (false, false); - sharpenMicro->setAdjusterBehavior (false, false); - icm->setAdjusterBehavior (false, false); + toneCurve->setAdjusterBehavior (false, false, false, false, false, false, false, false); + lcurve->setAdjusterBehavior (false, false, false); + whitebalance->setAdjusterBehavior (false, false, false); + vibrance->setAdjusterBehavior (false, false); + vignetting->setAdjusterBehavior (false, false, false, false); + colorappearance->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false); + rotate->setAdjusterBehavior (false); + distortion->setAdjusterBehavior (false); + perspective->setAdjusterBehavior (false); + gradient->setAdjusterBehavior (false, false, false, false); + pcvignette->setAdjusterBehavior (false, false, false); + cacorrection->setAdjusterBehavior (false); + sharpening->setAdjusterBehavior (false); + sharpenEdge->setAdjusterBehavior (false, false); + sharpenMicro->setAdjusterBehavior (false, false); + icm->setAdjusterBehavior (false, false); - chmixer->setAdjusterBehavior (false); - blackwhite->setAdjusterBehavior (false,false); - colortoning->setAdjusterBehavior (false, false, false, false, false); - filmSimulation->setAdjusterBehavior(false); + chmixer->setAdjusterBehavior (false); + blackwhite->setAdjusterBehavior (false, false); + colortoning->setAdjusterBehavior (false, false, false, false, false); + filmSimulation->setAdjusterBehavior(false); - shadowshighlights->setAdjusterBehavior (false, false, false); - dirpyrequalizer->setAdjusterBehavior (false, false, false); - wavelet->setAdjusterBehavior (false, false, false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false, false, false); - dirpyrdenoise->setAdjusterBehavior (false, false,false,false,false,false, false); - bayerpreprocess->setAdjusterBehavior (false, false); - rawcacorrection->setAdjusterBehavior (false); - flatfield->setAdjusterBehavior(false); - rawexposure->setAdjusterBehavior (false, false); - bayerrawexposure->setAdjusterBehavior (false); - xtransrawexposure->setAdjusterBehavior (false); - } - else { + shadowshighlights->setAdjusterBehavior (false, false, false); + dirpyrequalizer->setAdjusterBehavior (false, false, false); + wavelet->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + dirpyrdenoise->setAdjusterBehavior (false, false, false, false, false, false, false); + bayerpreprocess->setAdjusterBehavior (false, false); + rawcacorrection->setAdjusterBehavior (false); + flatfield->setAdjusterBehavior(false); + rawexposure->setAdjusterBehavior (false, false); + bayerrawexposure->setAdjusterBehavior (false); + xtransrawexposure->setAdjusterBehavior (false); + } else { - for (size_t i=0; isetMultiImage(true); + for (size_t i = 0; i < toolPanels.size(); i++) { + toolPanels.at(i)->setMultiImage(true); + } - toneCurve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_HLCOMPAMOUNT],options.baBehav[ADDSET_TC_HLCOMPTHRESH], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL],options.baBehav[ADDSET_TC_SHCOMP], options.baBehav[ADDSET_TC_CONTRAST], options.baBehav[ADDSET_TC_SATURATION]); - lcurve->setAdjusterBehavior (options.baBehav[ADDSET_LC_BRIGHTNESS], options.baBehav[ADDSET_LC_CONTRAST], options.baBehav[ADDSET_LC_CHROMATICITY]); - whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN], options.baBehav[ADDSET_WB_EQUAL]); - vibrance->setAdjusterBehavior (options.baBehav[ADDSET_VIBRANCE_PASTELS], options.baBehav[ADDSET_VIBRANCE_SATURATED]); - vignetting->setAdjusterBehavior (options.baBehav[ADDSET_VIGN_AMOUNT], options.baBehav[ADDSET_VIGN_RADIUS], options.baBehav[ADDSET_VIGN_STRENGTH], options.baBehav[ADDSET_VIGN_CENTER]); - colorappearance->setAdjusterBehavior (options.baBehav[ADDSET_CAT_DEGREE], options.baBehav[ADDSET_CAT_ADAPTSCENE], options.baBehav[ADDSET_CAT_ADAPTVIEWING],options.baBehav[ADDSET_CAT_BADPIX], options.baBehav[ADDSET_CAT_LIGHT], options.baBehav[ADDSET_CAT_CHROMA],options.baBehav[ADDSET_CAT_CONTRAST],options.baBehav[ADDSET_CAT_RSTPRO],options.baBehav[ADDSET_CAT_BRIGHT],options.baBehav[ADDSET_CAT_CONTRAST_Q],options.baBehav[ADDSET_CAT_CHROMA_S],options.baBehav[ADDSET_CAT_CHROMA_M],options.baBehav[ADDSET_CAT_HUE]); - rotate->setAdjusterBehavior (options.baBehav[ADDSET_ROTATE_DEGREE]); - distortion->setAdjusterBehavior (options.baBehav[ADDSET_DIST_AMOUNT]); - perspective->setAdjusterBehavior (options.baBehav[ADDSET_PERSPECTIVE]); - gradient->setAdjusterBehavior (options.baBehav[ADDSET_GRADIENT_DEGREE], options.baBehav[ADDSET_GRADIENT_FEATHER], options.baBehav[ADDSET_GRADIENT_STRENGTH], options.baBehav[ADDSET_GRADIENT_CENTER]); - pcvignette->setAdjusterBehavior (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH], options.baBehav[ADDSET_PCVIGNETTE_FEATHER], options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]); - cacorrection->setAdjusterBehavior (options.baBehav[ADDSET_CA]); - sharpening->setAdjusterBehavior (options.baBehav[ADDSET_SHARP_AMOUNT]); - sharpenEdge->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT],options.baBehav[ADDSET_SHARPENEDGE_PASS]); - sharpenMicro->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT],options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]); - icm->setAdjusterBehavior (options.baBehav[ADDSET_FREE_OUPUT_GAMMA],options.baBehav[ADDSET_FREE_OUTPUT_SLOPE]); -// colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRPROTECT], options.baBehav[ADDSET_COLORTONING_BALANCE]); - colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRENGTH], options.baBehav[ADDSET_COLORTONING_BALANCE]); - filmSimulation->setAdjusterBehavior(options.baBehav[ADDSET_FILMSIMULATION_STRENGTH]); + toneCurve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_HLCOMPAMOUNT], options.baBehav[ADDSET_TC_HLCOMPTHRESH], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL], options.baBehav[ADDSET_TC_SHCOMP], options.baBehav[ADDSET_TC_CONTRAST], options.baBehav[ADDSET_TC_SATURATION]); + lcurve->setAdjusterBehavior (options.baBehav[ADDSET_LC_BRIGHTNESS], options.baBehav[ADDSET_LC_CONTRAST], options.baBehav[ADDSET_LC_CHROMATICITY]); + whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN], options.baBehav[ADDSET_WB_EQUAL]); + vibrance->setAdjusterBehavior (options.baBehav[ADDSET_VIBRANCE_PASTELS], options.baBehav[ADDSET_VIBRANCE_SATURATED]); + vignetting->setAdjusterBehavior (options.baBehav[ADDSET_VIGN_AMOUNT], options.baBehav[ADDSET_VIGN_RADIUS], options.baBehav[ADDSET_VIGN_STRENGTH], options.baBehav[ADDSET_VIGN_CENTER]); + colorappearance->setAdjusterBehavior (options.baBehav[ADDSET_CAT_DEGREE], options.baBehav[ADDSET_CAT_ADAPTSCENE], options.baBehav[ADDSET_CAT_ADAPTVIEWING], options.baBehav[ADDSET_CAT_BADPIX], options.baBehav[ADDSET_CAT_LIGHT], options.baBehav[ADDSET_CAT_CHROMA], options.baBehav[ADDSET_CAT_CONTRAST], options.baBehav[ADDSET_CAT_RSTPRO], options.baBehav[ADDSET_CAT_BRIGHT], options.baBehav[ADDSET_CAT_CONTRAST_Q], options.baBehav[ADDSET_CAT_CHROMA_S], options.baBehav[ADDSET_CAT_CHROMA_M], options.baBehav[ADDSET_CAT_HUE]); + rotate->setAdjusterBehavior (options.baBehav[ADDSET_ROTATE_DEGREE]); + distortion->setAdjusterBehavior (options.baBehav[ADDSET_DIST_AMOUNT]); + perspective->setAdjusterBehavior (options.baBehav[ADDSET_PERSPECTIVE]); + gradient->setAdjusterBehavior (options.baBehav[ADDSET_GRADIENT_DEGREE], options.baBehav[ADDSET_GRADIENT_FEATHER], options.baBehav[ADDSET_GRADIENT_STRENGTH], options.baBehav[ADDSET_GRADIENT_CENTER]); + pcvignette->setAdjusterBehavior (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH], options.baBehav[ADDSET_PCVIGNETTE_FEATHER], options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]); + cacorrection->setAdjusterBehavior (options.baBehav[ADDSET_CA]); + sharpening->setAdjusterBehavior (options.baBehav[ADDSET_SHARP_AMOUNT]); + sharpenEdge->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT], options.baBehav[ADDSET_SHARPENEDGE_PASS]); + sharpenMicro->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT], options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]); + icm->setAdjusterBehavior (options.baBehav[ADDSET_FREE_OUPUT_GAMMA], options.baBehav[ADDSET_FREE_OUTPUT_SLOPE]); +// colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRPROTECT], options.baBehav[ADDSET_COLORTONING_BALANCE]); + colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRENGTH], options.baBehav[ADDSET_COLORTONING_BALANCE]); + filmSimulation->setAdjusterBehavior(options.baBehav[ADDSET_FILMSIMULATION_STRENGTH]); - chmixer->setAdjusterBehavior (options.baBehav[ADDSET_CHMIXER] ); - blackwhite->setAdjusterBehavior (options.baBehav[ADDSET_BLACKWHITE_HUES],options.baBehav[ADDSET_BLACKWHITE_GAMMA]); - shadowshighlights->setAdjusterBehavior (options.baBehav[ADDSET_SH_HIGHLIGHTS], options.baBehav[ADDSET_SH_SHADOWS], options.baBehav[ADDSET_SH_LOCALCONTRAST]); - dirpyrequalizer->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYREQ], options.baBehav[ADDSET_DIRPYREQ_THRESHOLD], options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT]); - wavelet->setAdjusterBehavior (options.baBehav[ADDSET_WA], options.baBehav[ADDSET_WA_THRESHOLD], options.baBehav[ADDSET_WA_THRESHOLD2],options.baBehav[ADDSET_WA_THRES],options.baBehav[ADDSET_WA_CHRO],options.baBehav[ADDSET_WA_CHROMA],options.baBehav[ADDSET_WA_CONTRAST],options.baBehav[ADDSET_WA_SKINPROTECT],options.baBehav[ADDSET_WA_RESCHRO],options.baBehav[ADDSET_WA_TMRS],options.baBehav[ADDSET_WA_RESCON],options.baBehav[ADDSET_WA_RESCONH],options.baBehav[ADDSET_WA_THRR],options.baBehav[ADDSET_WA_THRRH],options.baBehav[ADDSET_WA_SKYPROTECT], options.baBehav[ADDSET_WA_EDGRAD],options.baBehav[ADDSET_WA_EDGVAL],options.baBehav[ADDSET_WA_STRENGTH],options.baBehav[ADDSET_WA_GAMMA],options.baBehav[ADDSET_WA_EDGEDETECT], options.baBehav[ADDSET_WA_EDGEDETECTTHR], options.baBehav[ADDSET_WA_EDGEDETECTTHR2]); - dirpyrdenoise->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYRDN_LUMA],options.baBehav[ADDSET_DIRPYRDN_LUMDET],options.baBehav[ADDSET_DIRPYRDN_CHROMA],options.baBehav[ADDSET_DIRPYRDN_CHROMARED],options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE], options.baBehav[ADDSET_DIRPYRDN_GAMMA], options.baBehav[ADDSET_DIRPYRDN_PASSES]); - bayerpreprocess->setAdjusterBehavior (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE], options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]); - rawcacorrection->setAdjusterBehavior (options.baBehav[ADDSET_RAWCACORR]); - flatfield->setAdjusterBehavior(options.baBehav[ADDSET_RAWFFCLIPCONTROL]); - rawexposure->setAdjusterBehavior (options.baBehav[ADDSET_RAWEXPOS_LINEAR], options.baBehav[ADDSET_RAWEXPOS_PRESER]); - bayerrawexposure->setAdjusterBehavior (options.baBehav[ADDSET_RAWEXPOS_BLACKS]); - xtransrawexposure->setAdjusterBehavior (options.baBehav[ADDSET_RAWEXPOS_BLACKS]); + chmixer->setAdjusterBehavior (options.baBehav[ADDSET_CHMIXER] ); + blackwhite->setAdjusterBehavior (options.baBehav[ADDSET_BLACKWHITE_HUES], options.baBehav[ADDSET_BLACKWHITE_GAMMA]); + shadowshighlights->setAdjusterBehavior (options.baBehav[ADDSET_SH_HIGHLIGHTS], options.baBehav[ADDSET_SH_SHADOWS], options.baBehav[ADDSET_SH_LOCALCONTRAST]); + dirpyrequalizer->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYREQ], options.baBehav[ADDSET_DIRPYREQ_THRESHOLD], options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT]); + wavelet->setAdjusterBehavior (options.baBehav[ADDSET_WA], options.baBehav[ADDSET_WA_THRESHOLD], options.baBehav[ADDSET_WA_THRESHOLD2], options.baBehav[ADDSET_WA_THRES], options.baBehav[ADDSET_WA_CHRO], options.baBehav[ADDSET_WA_CHROMA], options.baBehav[ADDSET_WA_CONTRAST], options.baBehav[ADDSET_WA_SKINPROTECT], options.baBehav[ADDSET_WA_RESCHRO], options.baBehav[ADDSET_WA_TMRS], options.baBehav[ADDSET_WA_RESCON], options.baBehav[ADDSET_WA_RESCONH], options.baBehav[ADDSET_WA_THRR], options.baBehav[ADDSET_WA_THRRH], options.baBehav[ADDSET_WA_SKYPROTECT], options.baBehav[ADDSET_WA_EDGRAD], options.baBehav[ADDSET_WA_EDGVAL], options.baBehav[ADDSET_WA_STRENGTH], options.baBehav[ADDSET_WA_GAMMA], options.baBehav[ADDSET_WA_EDGEDETECT], options.baBehav[ADDSET_WA_EDGEDETECTTHR], options.baBehav[ADDSET_WA_EDGEDETECTTHR2]); + dirpyrdenoise->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYRDN_LUMA], options.baBehav[ADDSET_DIRPYRDN_LUMDET], options.baBehav[ADDSET_DIRPYRDN_CHROMA], options.baBehav[ADDSET_DIRPYRDN_CHROMARED], options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE], options.baBehav[ADDSET_DIRPYRDN_GAMMA], options.baBehav[ADDSET_DIRPYRDN_PASSES]); + bayerpreprocess->setAdjusterBehavior (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE], options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]); + rawcacorrection->setAdjusterBehavior (options.baBehav[ADDSET_RAWCACORR]); + flatfield->setAdjusterBehavior(options.baBehav[ADDSET_RAWFFCLIPCONTROL]); + rawexposure->setAdjusterBehavior (options.baBehav[ADDSET_RAWEXPOS_LINEAR], options.baBehav[ADDSET_RAWEXPOS_PRESER]); + bayerrawexposure->setAdjusterBehavior (options.baBehav[ADDSET_RAWEXPOS_BLACKS]); + xtransrawexposure->setAdjusterBehavior (options.baBehav[ADDSET_RAWEXPOS_BLACKS]); - if (options.baBehav[ADDSET_TC_EXPCOMP]) pparams.toneCurve.expcomp = 0; - if (options.baBehav[ADDSET_TC_HLCOMPAMOUNT]) pparams.toneCurve.hlcompr = 0; - if (options.baBehav[ADDSET_TC_HLCOMPTHRESH]) pparams.toneCurve.hlcomprthresh = 0; - if (options.baBehav[ADDSET_TC_BRIGHTNESS]) pparams.toneCurve.brightness = 0; - if (options.baBehav[ADDSET_TC_BLACKLEVEL]) pparams.toneCurve.black = 0; - if (options.baBehav[ADDSET_TC_SHCOMP]) pparams.toneCurve.shcompr = 0; - if (options.baBehav[ADDSET_TC_CONTRAST]) pparams.toneCurve.contrast = 0; + if (options.baBehav[ADDSET_TC_EXPCOMP]) { + pparams.toneCurve.expcomp = 0; + } - if (options.baBehav[ADDSET_SH_HIGHLIGHTS]) pparams.sh.highlights = 0; - if (options.baBehav[ADDSET_SH_SHADOWS]) pparams.sh.shadows = 0; - if (options.baBehav[ADDSET_SH_LOCALCONTRAST]) pparams.sh.localcontrast = 0; + if (options.baBehav[ADDSET_TC_HLCOMPAMOUNT]) { + pparams.toneCurve.hlcompr = 0; + } - if (options.baBehav[ADDSET_LC_BRIGHTNESS]) pparams.labCurve.brightness = 0; - if (options.baBehav[ADDSET_LC_CONTRAST]) pparams.labCurve.contrast = 0; - if (options.baBehav[ADDSET_LC_CHROMATICITY]) pparams.labCurve.chromaticity = 0; + if (options.baBehav[ADDSET_TC_HLCOMPTHRESH]) { + pparams.toneCurve.hlcomprthresh = 0; + } - if (options.baBehav[ADDSET_SHARP_AMOUNT]) pparams.sharpening.amount = 0; - if (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT]) pparams.sharpenEdge.amount = 0; - if (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT]) pparams.sharpenMicro.amount = 0; - if (options.baBehav[ADDSET_SHARPENEDGE_PASS]) pparams.sharpenEdge.passes = 0; - if (options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]) pparams.sharpenMicro.uniformity = 0; + if (options.baBehav[ADDSET_TC_BRIGHTNESS]) { + pparams.toneCurve.brightness = 0; + } - if (options.baBehav[ADDSET_CHMIXER]) for (int i=0; i<3; i++) pparams.chmixer.red[i] = pparams.chmixer.green[i] = pparams.chmixer.blue[i] = 0; - if (options.baBehav[ADDSET_BLACKWHITE_HUES]) pparams.blackwhite.mixerRed=pparams.blackwhite.mixerOrange=pparams.blackwhite.mixerYellow= - pparams.blackwhite.mixerGreen=pparams.blackwhite.mixerCyan=pparams.blackwhite.mixerBlue= - pparams.blackwhite.mixerMagenta=pparams.blackwhite.mixerPurple=0; - if (options.baBehav[ADDSET_BLACKWHITE_GAMMA]) pparams.blackwhite.gammaRed=pparams.blackwhite.gammaGreen=pparams.blackwhite.gammaBlue = 0; + if (options.baBehav[ADDSET_TC_BLACKLEVEL]) { + pparams.toneCurve.black = 0; + } - //if (options.baBehav[ADDSET_LD_EDGETOLERANCE]) pparams.lumaDenoise.edgetolerance = 0; + if (options.baBehav[ADDSET_TC_SHCOMP]) { + pparams.toneCurve.shcompr = 0; + } - if (options.baBehav[ADDSET_WB_TEMPERATURE]) pparams.wb.temperature = 0; - if (options.baBehav[ADDSET_WB_GREEN]) pparams.wb.green = 0; - if (options.baBehav[ADDSET_WB_EQUAL]) pparams.wb.equal = 0; + if (options.baBehav[ADDSET_TC_CONTRAST]) { + pparams.toneCurve.contrast = 0; + } - if (options.baBehav[ADDSET_VIBRANCE_PASTELS]) pparams.vibrance.pastels = 0; - if (options.baBehav[ADDSET_VIBRANCE_SATURATED]) pparams.vibrance.saturated = 0; + if (options.baBehav[ADDSET_SH_HIGHLIGHTS]) { + pparams.sh.highlights = 0; + } - if (options.baBehav[ADDSET_CAT_DEGREE]) pparams.colorappearance.degree = 0; - if (options.baBehav[ADDSET_CAT_ADAPTSCENE]) pparams.colorappearance.adapscen = 0; - if (options.baBehav[ADDSET_CAT_ADAPTVIEWING]) pparams.colorappearance.adaplum = 0; - if (options.baBehav[ADDSET_CAT_BADPIX]) pparams.colorappearance.badpixsl = 0; - if (options.baBehav[ADDSET_CAT_LIGHT]) pparams.colorappearance.jlight = 0; - if (options.baBehav[ADDSET_CAT_BRIGHT]) pparams.colorappearance.qbright = 0; - if (options.baBehav[ADDSET_CAT_CHROMA]) pparams.colorappearance.chroma = 0; - if (options.baBehav[ADDSET_CAT_CHROMA_S]) pparams.colorappearance.schroma = 0; - if (options.baBehav[ADDSET_CAT_CHROMA_M]) pparams.colorappearance.mchroma = 0; - if (options.baBehav[ADDSET_CAT_RSTPRO]) pparams.colorappearance.rstprotection = 0; - if (options.baBehav[ADDSET_CAT_CONTRAST]) pparams.colorappearance.contrast = 0; - if (options.baBehav[ADDSET_CAT_CONTRAST_Q]) pparams.colorappearance.qcontrast = 0; - if (options.baBehav[ADDSET_CAT_HUE]) pparams.colorappearance.colorh = 0; + if (options.baBehav[ADDSET_SH_SHADOWS]) { + pparams.sh.shadows = 0; + } - if (options.baBehav[ADDSET_FREE_OUPUT_GAMMA]) pparams.icm.gampos = 0; - if (options.baBehav[ADDSET_FREE_OUTPUT_SLOPE]) pparams.icm.slpos = 0; + if (options.baBehav[ADDSET_SH_LOCALCONTRAST]) { + pparams.sh.localcontrast = 0; + } - //if (options.baBehav[ADDSET_CBOOST_AMOUNT]) pparams.colorBoost.amount = 0; + if (options.baBehav[ADDSET_LC_BRIGHTNESS]) { + pparams.labCurve.brightness = 0; + } - //if (options.baBehav[ADDSET_CS_BLUEYELLOW]) pparams.colorShift.a = 0; - //if (options.baBehav[ADDSET_CS_GREENMAGENTA]) pparams.colorShift.b = 0; - if (options.baBehav[ADDSET_COLORTONING_SPLIT]) pparams.colorToning.redlow = pparams.colorToning.greenlow = pparams.colorToning.bluelow = - pparams.colorToning.redmed = pparams.colorToning.greenmed = pparams.colorToning.bluemed = - pparams.colorToning.redhigh = pparams.colorToning.greenhigh = pparams.colorToning.bluehigh = - pparams.colorToning.satlow = pparams.colorToning.sathigh = 0; - if (options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD]) pparams.colorToning.satProtectionThreshold = 0; - if (options.baBehav[ADDSET_COLORTONING_SATOPACITY]) pparams.colorToning.saturatedOpacity = 0; - if (options.baBehav[ADDSET_COLORTONING_BALANCE]) pparams.colorToning.balance = 0; - if (options.baBehav[ADDSET_COLORTONING_STRENGTH]) pparams.colorToning.strength = 0; + if (options.baBehav[ADDSET_LC_CONTRAST]) { + pparams.labCurve.contrast = 0; + } - if (options.baBehav[ADDSET_FILMSIMULATION_STRENGTH]) pparams.filmSimulation.strength = 0; + if (options.baBehav[ADDSET_LC_CHROMATICITY]) { + pparams.labCurve.chromaticity = 0; + } - if (options.baBehav[ADDSET_ROTATE_DEGREE]) pparams.rotate.degree = 0; - if (options.baBehav[ADDSET_DIST_AMOUNT]) pparams.distortion.amount = 0; - if (options.baBehav[ADDSET_PERSPECTIVE]) pparams.perspective.horizontal = pparams.perspective.vertical = 0; - if (options.baBehav[ADDSET_GRADIENT_DEGREE]) pparams.gradient.degree = 0; - if (options.baBehav[ADDSET_GRADIENT_FEATHER]) pparams.gradient.feather = 0; - if (options.baBehav[ADDSET_GRADIENT_STRENGTH]) pparams.gradient.strength = 0; - if (options.baBehav[ADDSET_GRADIENT_CENTER]) pparams.gradient.centerX = 0; - if (options.baBehav[ADDSET_GRADIENT_CENTER]) pparams.gradient.centerY = 0; - if (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH]) pparams.pcvignette.strength = 0; - if (options.baBehav[ADDSET_PCVIGNETTE_FEATHER]) pparams.pcvignette.feather = 0; - if (options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]) pparams.pcvignette.roundness = 0; - if (options.baBehav[ADDSET_CA]) pparams.cacorrection.red = 0; - if (options.baBehav[ADDSET_CA]) pparams.cacorrection.blue = 0; - if (options.baBehav[ADDSET_VIGN_AMOUNT]) pparams.vignetting.amount = 0; - if (options.baBehav[ADDSET_VIGN_RADIUS]) pparams.vignetting.radius = 0; - if (options.baBehav[ADDSET_VIGN_STRENGTH]) pparams.vignetting.strength = 0; - if (options.baBehav[ADDSET_VIGN_CENTER]) pparams.vignetting.centerX = 0; - if (options.baBehav[ADDSET_VIGN_CENTER]) pparams.vignetting.centerY = 0; + if (options.baBehav[ADDSET_SHARP_AMOUNT]) { + pparams.sharpening.amount = 0; + } - if (options.baBehav[ADDSET_DIRPYREQ]) for (int i=0; i<6; i++) pparams.dirpyrequalizer.mult[i] = 0; - if (options.baBehav[ADDSET_DIRPYREQ_THRESHOLD]) pparams.dirpyrequalizer.threshold = 0; - if (options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT]) pparams.dirpyrequalizer.skinprotect = 0; + if (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT]) { + pparams.sharpenEdge.amount = 0; + } - if (options.baBehav[ADDSET_WA]) for (int i=0; i<8; i++) pparams.wavelet.c[i] = 0; - if (options.baBehav[ADDSET_WA_THRESHOLD]) pparams.wavelet.threshold = 0; - if (options.baBehav[ADDSET_WA_THRESHOLD2]) pparams.wavelet.threshold2 = 0; - if (options.baBehav[ADDSET_WA_SKINPROTECT]) pparams.wavelet.skinprotect = 0; - if (options.baBehav[ADDSET_WA_CHRO]) pparams.wavelet.chro = 0; - if (options.baBehav[ADDSET_WA_CHROMA]) pparams.wavelet.chroma = 0; - if (options.baBehav[ADDSET_WA_CONTRAST]) pparams.wavelet.contrast = 0; - if (options.baBehav[ADDSET_WA_THRES]) pparams.wavelet.thres = 0; - if (options.baBehav[ADDSET_WA_RESCON]) pparams.wavelet.rescon = 0; - if (options.baBehav[ADDSET_WA_RESCONH]) pparams.wavelet.resconH = 0; - if (options.baBehav[ADDSET_WA_RESCHRO]) pparams.wavelet.reschro = 0; - if (options.baBehav[ADDSET_WA_TMRS]) pparams.wavelet.tmrs = 0; - if (options.baBehav[ADDSET_WA_THRR]) pparams.wavelet.thr = 0; - if (options.baBehav[ADDSET_WA_THRRH]) pparams.wavelet.thrH = 0; - if (options.baBehav[ADDSET_WA_SKYPROTECT]) pparams.wavelet.sky = 0; - if (options.baBehav[ADDSET_WA_EDGRAD]) pparams.wavelet.edgrad = 0; - if (options.baBehav[ADDSET_WA_EDGVAL]) pparams.wavelet.edgval = 0; - if (options.baBehav[ADDSET_WA_STRENGTH]) pparams.wavelet.strength = 0; - if (options.baBehav[ADDSET_WA_EDGEDETECT]) pparams.wavelet.edgedetect = 0; - if (options.baBehav[ADDSET_WA_GAMMA]) pparams.wavelet.gamma = 0; + if (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT]) { + pparams.sharpenMicro.amount = 0; + } - - if (options.baBehav[ADDSET_DIRPYRDN_LUMA]) pparams.dirpyrDenoise.luma = 0; + if (options.baBehav[ADDSET_SHARPENEDGE_PASS]) { + pparams.sharpenEdge.passes = 0; + } - if (options.baBehav[ADDSET_DIRPYRDN_CHROMA]) pparams.dirpyrDenoise.chroma = 0; - if (options.baBehav[ADDSET_DIRPYRDN_CHROMARED]) pparams.dirpyrDenoise.redchro = 0; - if (options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE]) pparams.dirpyrDenoise.bluechro = 0; -// pparams.dirpyrDenoise.Ldetail = pparams.dirpyrDenoise.luma = pparams.dirpyrDenoise.chroma = 0; - if (options.baBehav[ADDSET_DIRPYRDN_GAMMA]) pparams.dirpyrDenoise.gamma = 0; + if (options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]) { + pparams.sharpenMicro.uniformity = 0; + } - if (options.baBehav[ADDSET_RAWCACORR]) pparams.raw.cablue = pparams.raw.cared = 0; - if (options.baBehav[ADDSET_RAWEXPOS_LINEAR]) pparams.raw.expos = 0; - if (options.baBehav[ADDSET_RAWEXPOS_PRESER]) pparams.raw.preser = 0; - if (options.baBehav[ADDSET_RAWEXPOS_BLACKS]) { - pparams.raw.bayersensor.black0 = pparams.raw.bayersensor.black1 = pparams.raw.bayersensor.black2 = pparams.raw.bayersensor.black3 = 0; - pparams.raw.xtranssensor.blackred = pparams.raw.xtranssensor.blackgreen = pparams.raw.xtranssensor.blackblue = 0; - } - if (options.baBehav[ADDSET_RAWFFCLIPCONTROL]) pparams.raw.ff_clipControl = 0; + if (options.baBehav[ADDSET_CHMIXER]) for (int i = 0; i < 3; i++) { + pparams.chmixer.red[i] = pparams.chmixer.green[i] = pparams.chmixer.blue[i] = 0; + } - if (options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]) pparams.raw.bayersensor.greenthresh = 0; - if (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE]) pparams.raw.bayersensor.linenoise = 0; - } + if (options.baBehav[ADDSET_BLACKWHITE_HUES]) pparams.blackwhite.mixerRed = pparams.blackwhite.mixerOrange = pparams.blackwhite.mixerYellow = + pparams.blackwhite.mixerGreen = pparams.blackwhite.mixerCyan = pparams.blackwhite.mixerBlue = + pparams.blackwhite.mixerMagenta = pparams.blackwhite.mixerPurple = 0; - for (size_t i=0; isetDefaults (&pparams, &pparamsEdited); - toolPanels[i]->read (&pparams, &pparamsEdited); - // TODO: autoOpenCurve has been disabled because initSession is called on each parameter change from the editor panel, - // if the thumbnail remains selected in the DirectoryBrowser (i.e. always, unless the user think about deselecting it) - //toolPanels[i]->autoOpenCurve(); - } - for (size_t i=0; iprocParamsChanged (&pparams, rtengine::EvPhotoLoaded, M("BATCH_PROCESSING"), &pparamsEdited); - } + if (options.baBehav[ADDSET_BLACKWHITE_GAMMA]) { + pparams.blackwhite.gammaRed = pparams.blackwhite.gammaGreen = pparams.blackwhite.gammaBlue = 0; + } + + //if (options.baBehav[ADDSET_LD_EDGETOLERANCE]) pparams.lumaDenoise.edgetolerance = 0; + + if (options.baBehav[ADDSET_WB_TEMPERATURE]) { + pparams.wb.temperature = 0; + } + + if (options.baBehav[ADDSET_WB_GREEN]) { + pparams.wb.green = 0; + } + + if (options.baBehav[ADDSET_WB_EQUAL]) { + pparams.wb.equal = 0; + } + + if (options.baBehav[ADDSET_VIBRANCE_PASTELS]) { + pparams.vibrance.pastels = 0; + } + + if (options.baBehav[ADDSET_VIBRANCE_SATURATED]) { + pparams.vibrance.saturated = 0; + } + + if (options.baBehav[ADDSET_CAT_DEGREE]) { + pparams.colorappearance.degree = 0; + } + + if (options.baBehav[ADDSET_CAT_ADAPTSCENE]) { + pparams.colorappearance.adapscen = 0; + } + + if (options.baBehav[ADDSET_CAT_ADAPTVIEWING]) { + pparams.colorappearance.adaplum = 0; + } + + if (options.baBehav[ADDSET_CAT_BADPIX]) { + pparams.colorappearance.badpixsl = 0; + } + + if (options.baBehav[ADDSET_CAT_LIGHT]) { + pparams.colorappearance.jlight = 0; + } + + if (options.baBehav[ADDSET_CAT_BRIGHT]) { + pparams.colorappearance.qbright = 0; + } + + if (options.baBehav[ADDSET_CAT_CHROMA]) { + pparams.colorappearance.chroma = 0; + } + + if (options.baBehav[ADDSET_CAT_CHROMA_S]) { + pparams.colorappearance.schroma = 0; + } + + if (options.baBehav[ADDSET_CAT_CHROMA_M]) { + pparams.colorappearance.mchroma = 0; + } + + if (options.baBehav[ADDSET_CAT_RSTPRO]) { + pparams.colorappearance.rstprotection = 0; + } + + if (options.baBehav[ADDSET_CAT_CONTRAST]) { + pparams.colorappearance.contrast = 0; + } + + if (options.baBehav[ADDSET_CAT_CONTRAST_Q]) { + pparams.colorappearance.qcontrast = 0; + } + + if (options.baBehav[ADDSET_CAT_HUE]) { + pparams.colorappearance.colorh = 0; + } + + if (options.baBehav[ADDSET_FREE_OUPUT_GAMMA]) { + pparams.icm.gampos = 0; + } + + if (options.baBehav[ADDSET_FREE_OUTPUT_SLOPE]) { + pparams.icm.slpos = 0; + } + + //if (options.baBehav[ADDSET_CBOOST_AMOUNT]) pparams.colorBoost.amount = 0; + + //if (options.baBehav[ADDSET_CS_BLUEYELLOW]) pparams.colorShift.a = 0; + //if (options.baBehav[ADDSET_CS_GREENMAGENTA]) pparams.colorShift.b = 0; + if (options.baBehav[ADDSET_COLORTONING_SPLIT]) pparams.colorToning.redlow = pparams.colorToning.greenlow = pparams.colorToning.bluelow = + pparams.colorToning.redmed = pparams.colorToning.greenmed = pparams.colorToning.bluemed = + pparams.colorToning.redhigh = pparams.colorToning.greenhigh = pparams.colorToning.bluehigh = + pparams.colorToning.satlow = pparams.colorToning.sathigh = 0; + + if (options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD]) { + pparams.colorToning.satProtectionThreshold = 0; + } + + if (options.baBehav[ADDSET_COLORTONING_SATOPACITY]) { + pparams.colorToning.saturatedOpacity = 0; + } + + if (options.baBehav[ADDSET_COLORTONING_BALANCE]) { + pparams.colorToning.balance = 0; + } + + if (options.baBehav[ADDSET_COLORTONING_STRENGTH]) { + pparams.colorToning.strength = 0; + } + + if (options.baBehav[ADDSET_FILMSIMULATION_STRENGTH]) { + pparams.filmSimulation.strength = 0; + } + + if (options.baBehav[ADDSET_ROTATE_DEGREE]) { + pparams.rotate.degree = 0; + } + + if (options.baBehav[ADDSET_DIST_AMOUNT]) { + pparams.distortion.amount = 0; + } + + if (options.baBehav[ADDSET_PERSPECTIVE]) { + pparams.perspective.horizontal = pparams.perspective.vertical = 0; + } + + if (options.baBehav[ADDSET_GRADIENT_DEGREE]) { + pparams.gradient.degree = 0; + } + + if (options.baBehav[ADDSET_GRADIENT_FEATHER]) { + pparams.gradient.feather = 0; + } + + if (options.baBehav[ADDSET_GRADIENT_STRENGTH]) { + pparams.gradient.strength = 0; + } + + if (options.baBehav[ADDSET_GRADIENT_CENTER]) { + pparams.gradient.centerX = 0; + } + + if (options.baBehav[ADDSET_GRADIENT_CENTER]) { + pparams.gradient.centerY = 0; + } + + if (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH]) { + pparams.pcvignette.strength = 0; + } + + if (options.baBehav[ADDSET_PCVIGNETTE_FEATHER]) { + pparams.pcvignette.feather = 0; + } + + if (options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]) { + pparams.pcvignette.roundness = 0; + } + + if (options.baBehav[ADDSET_CA]) { + pparams.cacorrection.red = 0; + } + + if (options.baBehav[ADDSET_CA]) { + pparams.cacorrection.blue = 0; + } + + if (options.baBehav[ADDSET_VIGN_AMOUNT]) { + pparams.vignetting.amount = 0; + } + + if (options.baBehav[ADDSET_VIGN_RADIUS]) { + pparams.vignetting.radius = 0; + } + + if (options.baBehav[ADDSET_VIGN_STRENGTH]) { + pparams.vignetting.strength = 0; + } + + if (options.baBehav[ADDSET_VIGN_CENTER]) { + pparams.vignetting.centerX = 0; + } + + if (options.baBehav[ADDSET_VIGN_CENTER]) { + pparams.vignetting.centerY = 0; + } + + if (options.baBehav[ADDSET_DIRPYREQ]) for (int i = 0; i < 6; i++) { + pparams.dirpyrequalizer.mult[i] = 0; + } + + if (options.baBehav[ADDSET_DIRPYREQ_THRESHOLD]) { + pparams.dirpyrequalizer.threshold = 0; + } + + if (options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT]) { + pparams.dirpyrequalizer.skinprotect = 0; + } + + if (options.baBehav[ADDSET_WA]) for (int i = 0; i < 8; i++) { + pparams.wavelet.c[i] = 0; + } + + if (options.baBehav[ADDSET_WA_THRESHOLD]) { + pparams.wavelet.threshold = 0; + } + + if (options.baBehav[ADDSET_WA_THRESHOLD2]) { + pparams.wavelet.threshold2 = 0; + } + + if (options.baBehav[ADDSET_WA_SKINPROTECT]) { + pparams.wavelet.skinprotect = 0; + } + + if (options.baBehav[ADDSET_WA_CHRO]) { + pparams.wavelet.chro = 0; + } + + if (options.baBehav[ADDSET_WA_CHROMA]) { + pparams.wavelet.chroma = 0; + } + + if (options.baBehav[ADDSET_WA_CONTRAST]) { + pparams.wavelet.contrast = 0; + } + + if (options.baBehav[ADDSET_WA_THRES]) { + pparams.wavelet.thres = 0; + } + + if (options.baBehav[ADDSET_WA_RESCON]) { + pparams.wavelet.rescon = 0; + } + + if (options.baBehav[ADDSET_WA_RESCONH]) { + pparams.wavelet.resconH = 0; + } + + if (options.baBehav[ADDSET_WA_RESCHRO]) { + pparams.wavelet.reschro = 0; + } + + if (options.baBehav[ADDSET_WA_TMRS]) { + pparams.wavelet.tmrs = 0; + } + + if (options.baBehav[ADDSET_WA_THRR]) { + pparams.wavelet.thr = 0; + } + + if (options.baBehav[ADDSET_WA_THRRH]) { + pparams.wavelet.thrH = 0; + } + + if (options.baBehav[ADDSET_WA_SKYPROTECT]) { + pparams.wavelet.sky = 0; + } + + if (options.baBehav[ADDSET_WA_EDGRAD]) { + pparams.wavelet.edgrad = 0; + } + + if (options.baBehav[ADDSET_WA_EDGVAL]) { + pparams.wavelet.edgval = 0; + } + + if (options.baBehav[ADDSET_WA_STRENGTH]) { + pparams.wavelet.strength = 0; + } + + if (options.baBehav[ADDSET_WA_EDGEDETECT]) { + pparams.wavelet.edgedetect = 0; + } + + if (options.baBehav[ADDSET_WA_GAMMA]) { + pparams.wavelet.gamma = 0; + } + + + if (options.baBehav[ADDSET_DIRPYRDN_LUMA]) { + pparams.dirpyrDenoise.luma = 0; + } + + if (options.baBehav[ADDSET_DIRPYRDN_CHROMA]) { + pparams.dirpyrDenoise.chroma = 0; + } + + if (options.baBehav[ADDSET_DIRPYRDN_CHROMARED]) { + pparams.dirpyrDenoise.redchro = 0; + } + + if (options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE]) { + pparams.dirpyrDenoise.bluechro = 0; + } + +// pparams.dirpyrDenoise.Ldetail = pparams.dirpyrDenoise.luma = pparams.dirpyrDenoise.chroma = 0; + if (options.baBehav[ADDSET_DIRPYRDN_GAMMA]) { + pparams.dirpyrDenoise.gamma = 0; + } + + if (options.baBehav[ADDSET_RAWCACORR]) { + pparams.raw.cablue = pparams.raw.cared = 0; + } + + if (options.baBehav[ADDSET_RAWEXPOS_LINEAR]) { + pparams.raw.expos = 0; + } + + if (options.baBehav[ADDSET_RAWEXPOS_PRESER]) { + pparams.raw.preser = 0; + } + + if (options.baBehav[ADDSET_RAWEXPOS_BLACKS]) { + pparams.raw.bayersensor.black0 = pparams.raw.bayersensor.black1 = pparams.raw.bayersensor.black2 = pparams.raw.bayersensor.black3 = 0; + pparams.raw.xtranssensor.blackred = pparams.raw.xtranssensor.blackgreen = pparams.raw.xtranssensor.blackblue = 0; + } + + if (options.baBehav[ADDSET_RAWFFCLIPCONTROL]) { + pparams.raw.ff_clipControl = 0; + } + + if (options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]) { + pparams.raw.bayersensor.greenthresh = 0; + } + + if (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE]) { + pparams.raw.bayersensor.linenoise = 0; + } + } + + for (size_t i = 0; i < toolPanels.size(); i++) { + toolPanels[i]->setDefaults (&pparams, &pparamsEdited); + toolPanels[i]->read (&pparams, &pparamsEdited); + // TODO: autoOpenCurve has been disabled because initSession is called on each parameter change from the editor panel, + // if the thumbnail remains selected in the DirectoryBrowser (i.e. always, unless the user think about deselecting it) + //toolPanels[i]->autoOpenCurve(); + } + + for (size_t i = 0; i < paramcListeners.size(); i++) + // send this initial state to the History + { + paramcListeners[i]->procParamsChanged (&pparams, rtengine::EvPhotoLoaded, M("BATCH_PROCESSING"), &pparamsEdited); + } + } } -void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) { +void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) +{ - if (selected.empty()) + if (selected.empty()) { return; + } somethingChanged = true; pparamsEdited.set (false); + // read new values from the gui - for (size_t i=0; iwrite (&pparams, &pparamsEdited); + } // If only a single item is selected, we emulate the behaviour of the editor tool panel coordinator, // otherwise we adjust the inital parameters on a per-image basis. - if (selected.size()==1) { + if (selected.size() == 1) { // Compensate rotation on flip - if (event==rtengine::EvCTHFlip || event==rtengine::EvCTVFlip) { - if (fabs(pparams.rotate.degree)>0.001) { - pparams.rotate.degree *= -1; + if (event == rtengine::EvCTHFlip || event == rtengine::EvCTVFlip) { + if (fabs(pparams.rotate.degree) > 0.001) { + pparams.rotate.degree *= -1; rotate->read (&pparams); } } @@ -371,29 +676,25 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G crop->setDimensions(w, h); // Some transformations change the crop and resize parameter for convenience. - if (event==rtengine::EvCTHFlip) { + if (event == rtengine::EvCTHFlip) { crop->hFlipCrop (); crop->write (&pparams, &pparamsEdited); - } - else if (event==rtengine::EvCTVFlip) { + } else if (event == rtengine::EvCTVFlip) { crop->vFlipCrop (); crop->write (&pparams, &pparamsEdited); - } - else if (event==rtengine::EvCTRotate) { + } else if (event == rtengine::EvCTRotate) { crop->rotateCrop (pparams.coarse.rotate, pparams.coarse.hflip, pparams.coarse.vflip); crop->write (&pparams, &pparamsEdited); resize->update (pparams.crop.enabled, pparams.crop.w, pparams.crop.h, w, h); resize->write (&pparams, &pparamsEdited); - } - else if (event==rtengine::EvCrop) { + } else if (event == rtengine::EvCrop) { resize->update (pparams.crop.enabled, pparams.crop.w, pparams.crop.h); resize->write (&pparams, &pparamsEdited); } - } - else { + } else { // Compensate rotation on flip - if (event==rtengine::EvCTHFlip || event==rtengine::EvCTVFlip) { - for (size_t i=0; i 0.001) { initialPP[i].rotate.degree *= -1.0; @@ -403,8 +704,8 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G } // some transformations make the crop change for convenience - if (event==rtengine::EvCTHFlip) { - for (size_t i=0; igetFinalSize (selected[i]->getProcParams (), w, h); @@ -413,9 +714,8 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G pparamsEdited.crop.x = false; } - } - else if (event==rtengine::EvCTVFlip) { - for (size_t i=0; igetFinalSize (selected[i]->getProcParams (), w, h); @@ -424,10 +724,10 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G pparamsEdited.crop.y = false; } - } - else if (event==rtengine::EvCTRotate) { + } else if (event == rtengine::EvCTRotate) { int newDeg = pparams.coarse.rotate; - for (size_t i=0; igetFinalSize (selected[i]->getProcParams (), w, h); @@ -436,8 +736,10 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G rtengine::procparams::CropParams& crop = initialPP[i].crop; int rotation = (360 + newDeg - oldDeg) % 360; ProcParams pptemp = selected[i]->getProcParams(); // Get actual procparams - if((pptemp.coarse.hflip != pptemp.coarse.vflip) && ((rotation%180)==90)) - rotation = (rotation + 180)%360; + + if((pptemp.coarse.hflip != pptemp.coarse.vflip) && ((rotation % 180) == 90)) { + rotation = (rotation + 180) % 360; + } switch (rotation) { @@ -447,12 +749,14 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G crop.x = h - crop.x - crop.w; break; + case 270: std::swap(crop.x, crop.y); std::swap(crop.w, crop.h); crop.y = w - crop.y - crop.h; break; + case 180: crop.x = w - crop.x - crop.w; crop.y = h - crop.y - crop.h; @@ -462,6 +766,7 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G initialPP[i].coarse.rotate = newDeg; } + pparamsEdited.crop.x = false; pparamsEdited.crop.y = false; pparamsEdited.crop.w = false; @@ -470,8 +775,8 @@ void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const G } } - if (event==rtengine::EvAutoExp || event==rtengine::EvClip) - for (size_t i=0; iapplyAutoExp (initialPP[i]); } - if (event==rtengine::EvAutoDIST) { - for (size_t i=0; itrimValues (&newParams); + // trim new adjuster's values to the adjuster's limits + for (unsigned int j = 0; j < toolPanels.size(); j++) { + toolPanels[j]->trimValues (&newParams); + } selected[i]->setProcParams (newParams, NULL, BATCHEDITOR, false); } - for (size_t i=0; iprocParamsChanged (&pparams, event, descr, &pparamsEdited); + } } -void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal) { +void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal) +{ - if (!selected.empty()) + if (!selected.empty()) { selected[0]->getAutoWB (temp, green, equal); + } } -void BatchToolPanelCoordinator::getCamWB (double& temp, double& green) { +void BatchToolPanelCoordinator::getCamWB (double& temp, double& green) +{ - if (!selected.empty()) + if (!selected.empty()) { selected[0]->getCamWB (temp, green); + } } -void BatchToolPanelCoordinator::optionsChanged () { +void BatchToolPanelCoordinator::optionsChanged () +{ closeSession (); initSession (); } -void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt) { +void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt) +{ - if (whoChangedIt!=BATCHEDITOR && !blockedUpdate) { + if (whoChangedIt != BATCHEDITOR && !blockedUpdate) { closeSession (false); initSession (); } } -void BatchToolPanelCoordinator::beginBatchPParamsChange(int numberOfEntries) { +void BatchToolPanelCoordinator::beginBatchPParamsChange(int numberOfEntries) +{ blockedUpdate = true; - if (numberOfEntries > 50) // Arbitrary amount + + if (numberOfEntries > 50) { // Arbitrary amount parent->set_sensitive(false); + } } // The end of a batch pparams change triggers a close/initsession -void BatchToolPanelCoordinator::endBatchPParamsChange() { +void BatchToolPanelCoordinator::endBatchPParamsChange() +{ //printf("BatchToolPanelCoordinator::endBatchPParamsChange / Nouvelle session!\n"); closeSession (false); initSession (); @@ -554,79 +872,100 @@ void BatchToolPanelCoordinator::endBatchPParamsChange() { * Using a Profile panel in the batch tool panel editor is actually * not supported by BatchToolPanelCoordinator::profileChange! */ -void BatchToolPanelCoordinator::profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited) { +void BatchToolPanelCoordinator::profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited) +{ - if (event==rtengine::EvProfileChanged) { - // a profile has been selected in a hypothetical Profile panel - // -> ACTUALLY NOT SUPPORTED - return; + if (event == rtengine::EvProfileChanged) { + // a profile has been selected in a hypothetical Profile panel + // -> ACTUALLY NOT SUPPORTED + return; } pparams = *(nparams->pparams); - if (paramsEdited) + + if (paramsEdited) { pparamsEdited = *paramsEdited; + } - for (size_t i=0; iread (&pparams, &pparamsEdited); - // I guess we don't want to automatically unfold curve editors here... + } + + // I guess we don't want to automatically unfold curve editors here... somethingChanged = true; // read new values from the gui - for (size_t i=0; iwrite (&pparams, &pparamsEdited); + } // combine with initial parameters of each image and set ProcParams newParams; - for (size_t i=0; isetProcParams (newParams, NULL, BATCHEDITOR, false); } - for (size_t i=0; iprocParamsChanged (&pparams, event, descr, &pparamsEdited); + } } -void BatchToolPanelCoordinator::cropSelectionReady () { +void BatchToolPanelCoordinator::cropSelectionReady () +{ - toolBar->setTool (TMHand); + toolBar->setTool (TMHand); } -CropGUIListener* BatchToolPanelCoordinator::startCropEditing (Thumbnail* thm) { +CropGUIListener* BatchToolPanelCoordinator::startCropEditing (Thumbnail* thm) +{ if (thm) { int w, h; thm->getFinalSize (thm->getProcParams (), w, h); crop->setDimensions (w, h); } + return crop; } -void BatchToolPanelCoordinator::rotateSelectionReady (double rotate_deg, Thumbnail* thm) { +void BatchToolPanelCoordinator::rotateSelectionReady (double rotate_deg, Thumbnail* thm) +{ - toolBar->setTool (TMHand); - if (rotate_deg!=0.0) - rotate->straighten (rotate_deg); + toolBar->setTool (TMHand); + + if (rotate_deg != 0.0) { + rotate->straighten (rotate_deg); + } } -void BatchToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) { +void BatchToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) +{ // toolBar->setTool (TOOL_HAND); - if (x>0 && y>0 && thm) { - for (size_t i=0; i 0 && y > 0 && thm) { + for (size_t i = 0; i < selected.size(); i++) + if (selected[i] == thm) { double temp; double green; thm->getSpotWB (x, y, whitebalance->getSize(), temp, green); double otemp = initialPP[i].wb.temperature; double ogreen = initialPP[i].wb.green; - if (options.baBehav[12]) + + if (options.baBehav[12]) { temp = temp - otemp; - if (options.baBehav[13]) + } + + if (options.baBehav[13]) { green = green - ogreen; + } + whitebalance->setWB (temp, green); } } diff --git a/rtgui/batchtoolpanelcoord.h b/rtgui/batchtoolpanelcoord.h index 8cdd12c64..e064452b2 100644 --- a/rtgui/batchtoolpanelcoord.h +++ b/rtgui/batchtoolpanelcoord.h @@ -7,7 +7,7 @@ * 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 @@ -27,56 +27,56 @@ #include "thumbnaillistener.h" class FilePanel; -class BatchToolPanelCoordinator : - public ToolPanelCoordinator, - public FileSelectionChangeListener, - public BatchPParamsChangeListener, - public ThumbnailListener +class BatchToolPanelCoordinator : + public ToolPanelCoordinator, + public FileSelectionChangeListener, + public BatchPParamsChangeListener, + public ThumbnailListener { - protected: - rtengine::procparams::ProcParams pparams; - ParamsEdited pparamsEdited; - std::vector selected; - std::vector selFileNames; - std::vector initialPP; - bool somethingChanged; - bool blockedUpdate; - FilePanel* parent; +protected: + rtengine::procparams::ProcParams pparams; + ParamsEdited pparamsEdited; + std::vector selected; + std::vector selFileNames; + std::vector initialPP; + bool somethingChanged; + bool blockedUpdate; + FilePanel* parent; - void closeSession (bool save=true); - void initSession (); + void closeSession (bool save = true); + void initSession (); - public: - - BatchToolPanelCoordinator (FilePanel* parent); +public: - // FileSelectionChangeListener interface - void selectionChanged (const std::vector& selected); + BatchToolPanelCoordinator (FilePanel* parent); - // toolpanellistener interface - void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr); + // FileSelectionChangeListener interface + void selectionChanged (const std::vector& selected); - // profilechangelistener interface - void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited=NULL); + // toolpanellistener interface + void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr); - // wbprovider interface - void getAutoWB (double& temp, double& green, double equal); - void getCamWB (double& temp, double& green); + // profilechangelistener interface + void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited = NULL); - // thumbnaillistener interface - void procParamsChanged (Thumbnail* thm, int whoChangedIt); + // wbprovider interface + void getAutoWB (double& temp, double& green, double equal); + void getCamWB (double& temp, double& green); - // batchpparamschangelistener interface - void beginBatchPParamsChange(int numberOfEntries); - void endBatchPParamsChange(); + // thumbnaillistener interface + void procParamsChanged (Thumbnail* thm, int whoChangedIt); - // imageareatoollistener interface - void spotWBselected (int x, int y, Thumbnail* thm=NULL); - void cropSelectionReady (); - void rotateSelectionReady (double rotate_deg, Thumbnail* thm=NULL); - CropGUIListener* startCropEditing (Thumbnail* thm=NULL); + // batchpparamschangelistener interface + void beginBatchPParamsChange(int numberOfEntries); + void endBatchPParamsChange(); - void optionsChanged (); + // imageareatoollistener interface + void spotWBselected (int x, int y, Thumbnail* thm = NULL); + void cropSelectionReady (); + void rotateSelectionReady (double rotate_deg, Thumbnail* thm = NULL); + CropGUIListener* startCropEditing (Thumbnail* thm = NULL); + + void optionsChanged (); }; #endif diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc index f157bf8ac..8b84902f9 100644 --- a/rtgui/bayerpreprocess.cc +++ b/rtgui/bayerpreprocess.cc @@ -26,92 +26,103 @@ using namespace rtengine::procparams; BayerPreProcess::BayerPreProcess () : FoldableToolPanel(this, "bayerpreprocess", M("TP_PREPROCESS_LABEL"), true) { - lineDenoise = Gtk::manage(new Adjuster (M("TP_PREPROCESS_LINEDENOISE"),0,1000,1,0)); - lineDenoise->setAdjusterListener (this); - if (lineDenoise->delay < 1000) lineDenoise->delay = 1000; - lineDenoise->show(); + lineDenoise = Gtk::manage(new Adjuster (M("TP_PREPROCESS_LINEDENOISE"), 0, 1000, 1, 0)); + lineDenoise->setAdjusterListener (this); - greenEqThreshold = Gtk::manage(new Adjuster (M("TP_PREPROCESS_GREENEQUIL"),0,100,1,0)); - greenEqThreshold->setAdjusterListener (this); - if (greenEqThreshold->delay < 1000) greenEqThreshold->delay = 1000; - greenEqThreshold->show(); + if (lineDenoise->delay < 1000) { + lineDenoise->delay = 1000; + } - pack_start( *lineDenoise, Gtk::PACK_SHRINK, 4); + lineDenoise->show(); - pack_start( *Gtk::manage (new Gtk::HSeparator())); + greenEqThreshold = Gtk::manage(new Adjuster (M("TP_PREPROCESS_GREENEQUIL"), 0, 100, 1, 0)); + greenEqThreshold->setAdjusterListener (this); - pack_start( *greenEqThreshold, Gtk::PACK_SHRINK, 4); + if (greenEqThreshold->delay < 1000) { + greenEqThreshold->delay = 1000; + } + + greenEqThreshold->show(); + + pack_start( *lineDenoise, Gtk::PACK_SHRINK, 4); + + pack_start( *Gtk::manage (new Gtk::HSeparator())); + + pack_start( *greenEqThreshold, Gtk::PACK_SHRINK, 4); } void BayerPreProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener (); - if(pedited ){ - lineDenoise->setEditedState( pedited->raw.bayersensor.linenoise ? Edited : UnEdited ); - greenEqThreshold->setEditedState( pedited->raw.bayersensor.greenEq ? Edited : UnEdited ); - } + if(pedited ) { + lineDenoise->setEditedState( pedited->raw.bayersensor.linenoise ? Edited : UnEdited ); + greenEqThreshold->setEditedState( pedited->raw.bayersensor.greenEq ? Edited : UnEdited ); + } - lineDenoise->setValue (pp->raw.bayersensor.linenoise); - greenEqThreshold->setValue (pp->raw.bayersensor.greenthresh); + lineDenoise->setValue (pp->raw.bayersensor.linenoise); + greenEqThreshold->setValue (pp->raw.bayersensor.greenthresh); - enableListener (); + enableListener (); } void BayerPreProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.bayersensor.linenoise = lineDenoise->getIntValue(); - pp->raw.bayersensor.greenthresh = greenEqThreshold->getIntValue(); + pp->raw.bayersensor.linenoise = lineDenoise->getIntValue(); + pp->raw.bayersensor.greenthresh = greenEqThreshold->getIntValue(); - if (pedited) { - pedited->raw.bayersensor.linenoise = lineDenoise->getEditedState (); - pedited->raw.bayersensor.greenEq= greenEqThreshold->getEditedState (); - } + if (pedited) { + pedited->raw.bayersensor.linenoise = lineDenoise->getEditedState (); + pedited->raw.bayersensor.greenEq = greenEqThreshold->getEditedState (); + } } void BayerPreProcess::adjusterChanged (Adjuster* a, double newval) { - if (listener) { + if (listener) { - Glib::ustring value = a->getTextValue(); + Glib::ustring value = a->getTextValue(); - if (a == greenEqThreshold) - listener->panelChanged (EvPreProcessGEquilThresh, value ); - else if (a == lineDenoise) - listener->panelChanged (EvPreProcessLineDenoise, value ); - } + if (a == greenEqThreshold) { + listener->panelChanged (EvPreProcessGEquilThresh, value ); + } else if (a == lineDenoise) { + listener->panelChanged (EvPreProcessLineDenoise, value ); + } + } } void BayerPreProcess::setBatchMode(bool batchMode) { - ToolPanel::setBatchMode (batchMode); - lineDenoise->showEditedCB (); - greenEqThreshold->showEditedCB (); + ToolPanel::setBatchMode (batchMode); + lineDenoise->showEditedCB (); + greenEqThreshold->showEditedCB (); } void BayerPreProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - lineDenoise->setDefault( defParams->raw.bayersensor.linenoise); - greenEqThreshold->setDefault (defParams->raw.bayersensor.greenthresh); + lineDenoise->setDefault( defParams->raw.bayersensor.linenoise); + greenEqThreshold->setDefault (defParams->raw.bayersensor.greenthresh); - if (pedited) { - lineDenoise->setDefaultEditedState( pedited->raw.bayersensor.linenoise ? Edited : UnEdited); - greenEqThreshold->setDefaultEditedState(pedited->raw.bayersensor.greenEq ? Edited : UnEdited); - } else { - lineDenoise->setDefaultEditedState( Irrelevant ); - greenEqThreshold->setDefaultEditedState(Irrelevant ); - } + if (pedited) { + lineDenoise->setDefaultEditedState( pedited->raw.bayersensor.linenoise ? Edited : UnEdited); + greenEqThreshold->setDefaultEditedState(pedited->raw.bayersensor.greenEq ? Edited : UnEdited); + } else { + lineDenoise->setDefaultEditedState( Irrelevant ); + greenEqThreshold->setDefaultEditedState(Irrelevant ); + } } -void BayerPreProcess::setAdjusterBehavior (bool linedenoiseadd, bool greenequiladd) { +void BayerPreProcess::setAdjusterBehavior (bool linedenoiseadd, bool greenequiladd) +{ - lineDenoise->setAddMode(linedenoiseadd); - greenEqThreshold->setAddMode(greenequiladd); + lineDenoise->setAddMode(linedenoiseadd); + greenEqThreshold->setAddMode(greenequiladd); } -void BayerPreProcess::trimValues (rtengine::procparams::ProcParams* pp) { +void BayerPreProcess::trimValues (rtengine::procparams::ProcParams* pp) +{ - lineDenoise->trimValue(pp->raw.bayersensor.linenoise); - greenEqThreshold->trimValue(pp->raw.bayersensor.greenthresh); + lineDenoise->trimValue(pp->raw.bayersensor.linenoise); + greenEqThreshold->trimValue(pp->raw.bayersensor.greenthresh); } diff --git a/rtgui/bayerpreprocess.h b/rtgui/bayerpreprocess.h index a6e46bc7d..3b7dce4dc 100644 --- a/rtgui/bayerpreprocess.h +++ b/rtgui/bayerpreprocess.h @@ -24,21 +24,22 @@ #include "toolpanel.h" #include "../rtengine/rawimage.h" -class BayerPreProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class BayerPreProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* lineDenoise; Adjuster* greenEqThreshold; - public: +public: BayerPreProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void adjusterChanged (Adjuster* a, double newval); void hotDeadPixelChanged(); diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index f60b0d1ee..74da927dd 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -24,247 +24,278 @@ using namespace rtengine::procparams; BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RAW_LABEL"), true) { - Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); - hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") +": ")),Gtk::PACK_SHRINK, 4); - method = Gtk::manage (new MyComboBoxText ()); - for( size_t i=0; iappend_text(procparams::RAWParams::BayerSensor::methodstring[i]); + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + method = Gtk::manage (new MyComboBoxText ()); - method->set_active(0); - hb1->set_tooltip_markup (M("TP_RAW_DMETHOD_TOOLTIP")); + for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) { + method->append_text(procparams::RAWParams::BayerSensor::methodstring[i]); + } - hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb1, Gtk::PACK_SHRINK, 4); + method->set_active(0); + hb1->set_tooltip_markup (M("TP_RAW_DMETHOD_TOOLTIP")); - dcbOptions = Gtk::manage (new Gtk::VBox ()); - dcbOptions->set_border_width(4); + hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb1, Gtk::PACK_SHRINK, 4); - dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"),0,5,1,2)); - dcbIterations->setAdjusterListener (this); - if (dcbIterations->delay < 1000) dcbIterations->delay = 1000; - dcbIterations->show(); - dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE"))); - dcbOptions->pack_start(*dcbIterations); - dcbOptions->pack_start(*dcbEnhance); - pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4); + dcbOptions = Gtk::manage (new Gtk::VBox ()); + dcbOptions->set_border_width(4); - lmmseOptions = Gtk::manage (new Gtk::VBox ()); - lmmseOptions->set_border_width(4); + dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"), 0, 5, 1, 2)); + dcbIterations->setAdjusterListener (this); - lmmseIterations = Gtk::manage (new Adjuster (M("TP_RAW_LMMSEITERATIONS"),0,6,1,2)); - lmmseIterations->setAdjusterListener (this); - lmmseIterations->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); + if (dcbIterations->delay < 1000) { + dcbIterations->delay = 1000; + } - if (lmmseIterations->delay < 1000) lmmseIterations->delay = 1000; - lmmseIterations->show(); - lmmseOptions->pack_start(*lmmseIterations); - pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); + dcbIterations->show(); + dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE"))); + dcbOptions->pack_start(*dcbIterations); + dcbOptions->pack_start(*dcbEnhance); + pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4); - pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"),0,5,1,0 )); - ccSteps->setAdjusterListener (this); - if (ccSteps->delay < 1000) ccSteps->delay = 1000; - ccSteps->show(); - pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + lmmseOptions = Gtk::manage (new Gtk::VBox ()); + lmmseOptions->set_border_width(4); - //pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - //allOptions = Gtk::manage (new Gtk::VBox ()); - //allOptions->set_border_width(2); - //allEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_ALLENHANCE"))); - //allOptions->pack_start(*allEnhance); - //pack_start( *allOptions, Gtk::PACK_SHRINK, 4); + lmmseIterations = Gtk::manage (new Adjuster (M("TP_RAW_LMMSEITERATIONS"), 0, 6, 1, 2)); + lmmseIterations->setAdjusterListener (this); + lmmseIterations->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); - methodconn = method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) ); - dcbEnhconn = dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::dcbEnhanceChanged), true); - //allEnhconn = allEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::allEnhanceChanged), true); + if (lmmseIterations->delay < 1000) { + lmmseIterations->delay = 1000; + } + + lmmseIterations->show(); + lmmseOptions->pack_start(*lmmseIterations); + pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); + + pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); + ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 )); + ccSteps->setAdjusterListener (this); + + if (ccSteps->delay < 1000) { + ccSteps->delay = 1000; + } + + ccSteps->show(); + pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + + //pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); + //allOptions = Gtk::manage (new Gtk::VBox ()); + //allOptions->set_border_width(2); + //allEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_ALLENHANCE"))); + //allOptions->pack_start(*allEnhance); + //pack_start( *allOptions, Gtk::PACK_SHRINK, 4); + + methodconn = method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) ); + dcbEnhconn = dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::dcbEnhanceChanged), true); + //allEnhconn = allEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::allEnhanceChanged), true); } void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - methodconn.block (true); - dcbEnhconn.block (true); - //allEnhconn.block (true); + disableListener (); + methodconn.block (true); + dcbEnhconn.block (true); + //allEnhconn.block (true); - method->set_active(procparams::RAWParams::BayerSensor::numMethods); - for( size_t i=0; i< procparams::RAWParams::BayerSensor::numMethods; i++) - if( pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[i]){ - method->set_active(i); - oldSelection = i; - break; - } + method->set_active(procparams::RAWParams::BayerSensor::numMethods); - if(pedited ){ - ccSteps->setEditedState (pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); - dcbIterations->setEditedState ( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); - dcbEnhance->set_inconsistent(!pedited->raw.bayersensor.dcbEnhance); - //allEnhance->set_inconsistent(!pedited->raw.bayersensor.allEnhance); - lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); + for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) + if( pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[i]) { + method->set_active(i); + oldSelection = i; + break; + } - if( !pedited->raw.bayersensor.method ) - method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name - } + if(pedited ) { + ccSteps->setEditedState (pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); + dcbIterations->setEditedState ( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); + dcbEnhance->set_inconsistent(!pedited->raw.bayersensor.dcbEnhance); + //allEnhance->set_inconsistent(!pedited->raw.bayersensor.allEnhance); + lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); - //allEnhance->set_active(pp->raw.bayersensor.all_enhance); + if( !pedited->raw.bayersensor.method ) { + method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name + } + } - dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations); - dcbEnhance->set_active(pp->raw.bayersensor.dcb_enhance); - ccSteps->setValue (pp->raw.bayersensor.ccSteps); - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::dcb] || - method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) - dcbOptions->show(); - else - dcbOptions->hide(); + //allEnhance->set_active(pp->raw.bayersensor.all_enhance); - lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations); - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::lmmse] || - method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) - lmmseOptions->show(); - else - lmmseOptions->hide(); + dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations); + dcbEnhance->set_active(pp->raw.bayersensor.dcb_enhance); + ccSteps->setValue (pp->raw.bayersensor.ccSteps); - // Flase color suppression is applied to all demozaicing method, so don't hide anything - /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::eahd] || - pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::hphd] || - pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::vng4]) - ccSteps->show(); - else - ccSteps->hide();*/ + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::dcb] || + method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { + dcbOptions->show(); + } else { + dcbOptions->hide(); + } - lastDCBen = pp->raw.bayersensor.dcb_enhance; - //lastALLen = pp->raw.bayersensor.all_enhance; + lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations); - methodconn.block (false); - dcbEnhconn.block (false); - //allEnhconn.block (false); + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::lmmse] || + method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) { + lmmseOptions->show(); + } else { + lmmseOptions->hide(); + } - enableListener (); + // Flase color suppression is applied to all demozaicing method, so don't hide anything + /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::eahd] || + pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::hphd] || + pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::vng4]) + ccSteps->show(); + else + ccSteps->hide();*/ + + lastDCBen = pp->raw.bayersensor.dcb_enhance; + //lastALLen = pp->raw.bayersensor.all_enhance; + + methodconn.block (false); + dcbEnhconn.block (false); + //allEnhconn.block (false); + + enableListener (); } void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.bayersensor.ccSteps = ccSteps->getIntValue(); - pp->raw.bayersensor.dcb_iterations = dcbIterations->getIntValue(); - pp->raw.bayersensor.dcb_enhance = dcbEnhance->get_active(); - //pp->raw.bayersensor.all_enhance = allEnhance->get_active(); - pp->raw.bayersensor.lmmse_iterations = lmmseIterations->getIntValue(); + pp->raw.bayersensor.ccSteps = ccSteps->getIntValue(); + pp->raw.bayersensor.dcb_iterations = dcbIterations->getIntValue(); + pp->raw.bayersensor.dcb_enhance = dcbEnhance->get_active(); + //pp->raw.bayersensor.all_enhance = allEnhance->get_active(); + pp->raw.bayersensor.lmmse_iterations = lmmseIterations->getIntValue(); - int currentRow = method->get_active_row_number(); - if( currentRow>=0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) - pp->raw.bayersensor.method = procparams::RAWParams::BayerSensor::methodstring[currentRow]; + int currentRow = method->get_active_row_number(); - if (pedited) { - pedited->raw.bayersensor.ccSteps = ccSteps->getEditedState (); - pedited->raw.bayersensor.method = method->get_active_row_number() != procparams::RAWParams::BayerSensor::numMethods; - pedited->raw.bayersensor.dcbIterations = dcbIterations->getEditedState (); - pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent(); - //pedited->raw.bayersensor.allEnhance = !allEnhance->get_inconsistent(); - pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState (); - - } + if( currentRow >= 0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) { + pp->raw.bayersensor.method = procparams::RAWParams::BayerSensor::methodstring[currentRow]; + } + + if (pedited) { + pedited->raw.bayersensor.ccSteps = ccSteps->getEditedState (); + pedited->raw.bayersensor.method = method->get_active_row_number() != procparams::RAWParams::BayerSensor::numMethods; + pedited->raw.bayersensor.dcbIterations = dcbIterations->getEditedState (); + pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent(); + //pedited->raw.bayersensor.allEnhance = !allEnhance->get_inconsistent(); + pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState (); + + } } void BayerProcess::setBatchMode(bool batchMode) { - method->append_text (M("GENERAL_UNCHANGED")); - method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name - dcbOptions->hide(); - lmmseOptions->hide(); - ToolPanel::setBatchMode (batchMode); - ccSteps->showEditedCB (); - dcbIterations->showEditedCB (); - lmmseIterations->showEditedCB (); + method->append_text (M("GENERAL_UNCHANGED")); + method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name + dcbOptions->hide(); + lmmseOptions->hide(); + ToolPanel::setBatchMode (batchMode); + ccSteps->showEditedCB (); + dcbIterations->showEditedCB (); + lmmseIterations->showEditedCB (); } void BayerProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - dcbIterations->setDefault( defParams->raw.bayersensor.dcb_iterations); - lmmseIterations->setDefault( defParams->raw.bayersensor.lmmse_iterations); - ccSteps->setDefault (defParams->raw.bayersensor.ccSteps); - if (pedited) { - dcbIterations->setDefaultEditedState( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); - lmmseIterations->setDefaultEditedState( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); - ccSteps->setDefaultEditedState(pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); - }else{ - dcbIterations->setDefaultEditedState( Irrelevant ); - lmmseIterations->setDefaultEditedState( Irrelevant ); - ccSteps->setDefaultEditedState(Irrelevant ); - } + dcbIterations->setDefault( defParams->raw.bayersensor.dcb_iterations); + lmmseIterations->setDefault( defParams->raw.bayersensor.lmmse_iterations); + ccSteps->setDefault (defParams->raw.bayersensor.ccSteps); + + if (pedited) { + dcbIterations->setDefaultEditedState( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); + lmmseIterations->setDefaultEditedState( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); + ccSteps->setDefaultEditedState(pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); + } else { + dcbIterations->setDefaultEditedState( Irrelevant ); + lmmseIterations->setDefaultEditedState( Irrelevant ); + ccSteps->setDefaultEditedState(Irrelevant ); + } } void BayerProcess::adjusterChanged (Adjuster* a, double newval) { - if (listener) { - if (a == dcbIterations) - listener->panelChanged (EvDemosaicDCBIter, a->getTextValue() ); - else if (a == ccSteps) - listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); - else if (a == lmmseIterations) - listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); - } + if (listener) { + if (a == dcbIterations) { + listener->panelChanged (EvDemosaicDCBIter, a->getTextValue() ); + } else if (a == ccSteps) { + listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); + } else if (a == lmmseIterations) { + listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); + } + } } void BayerProcess::methodChanged () { - int curSelection = method->get_active_row_number(); - if ( curSelection == procparams::RAWParams::BayerSensor::dcb){ - dcbOptions->show(); - }else{ - dcbOptions->hide(); - } - if ( curSelection == procparams::RAWParams::BayerSensor::lmmse){ - lmmseOptions->show(); - }else{ - lmmseOptions->hide(); - } - - Glib::ustring methodName=""; - bool ppreq = false; - if( curSelection>=0 && curSelection < procparams::RAWParams::BayerSensor::numMethods) { - methodName = procparams::RAWParams::BayerSensor::methodstring[curSelection]; - if (curSelection == procparams::RAWParams::BayerSensor::mono || oldSelection == procparams::RAWParams::BayerSensor::mono) { - ppreq = true; - } - } - oldSelection = curSelection; + int curSelection = method->get_active_row_number(); - if (listener) - listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + if ( curSelection == procparams::RAWParams::BayerSensor::dcb) { + dcbOptions->show(); + } else { + dcbOptions->hide(); + } + + if ( curSelection == procparams::RAWParams::BayerSensor::lmmse) { + lmmseOptions->show(); + } else { + lmmseOptions->hide(); + } + + Glib::ustring methodName = ""; + bool ppreq = false; + + if( curSelection >= 0 && curSelection < procparams::RAWParams::BayerSensor::numMethods) { + methodName = procparams::RAWParams::BayerSensor::methodstring[curSelection]; + + if (curSelection == procparams::RAWParams::BayerSensor::mono || oldSelection == procparams::RAWParams::BayerSensor::mono) { + ppreq = true; + } + } + + oldSelection = curSelection; + + if (listener) { + listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + } } void BayerProcess::dcbEnhanceChanged () { - if (batchMode) { - if (dcbEnhance->get_inconsistent()) { - dcbEnhance->set_inconsistent (false); - dcbEnhconn.block (true); - dcbEnhance->set_active (false); - dcbEnhconn.block (false); - } - else if (lastDCBen) - dcbEnhance->set_inconsistent (true); + if (batchMode) { + if (dcbEnhance->get_inconsistent()) { + dcbEnhance->set_inconsistent (false); + dcbEnhconn.block (true); + dcbEnhance->set_active (false); + dcbEnhconn.block (false); + } else if (lastDCBen) { + dcbEnhance->set_inconsistent (true); + } - lastDCBen = dcbEnhance->get_active (); - } - if (listener) - listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + lastDCBen = dcbEnhance->get_active (); + } + + if (listener) { + listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } /*void BayerProcess::allEnhanceChanged () { - if (batchMode) { - if (allEnhance->get_inconsistent()) { - allEnhance->set_inconsistent (false); - allEnhconn.block (true); - allEnhance->set_active (false); - allEnhconn.block (false); - } - else if (lastALLen) - allEnhance->set_inconsistent (true); + if (batchMode) { + if (allEnhance->get_inconsistent()) { + allEnhance->set_inconsistent (false); + allEnhconn.block (true); + allEnhance->set_active (false); + allEnhconn.block (false); + } + else if (lastALLen) + allEnhance->set_inconsistent (true); - lastALLen = allEnhance->get_active (); - } - if (listener) - listener->panelChanged (EvDemosaicALLEnhanced, allEnhance->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + lastALLen = allEnhance->get_active (); + } + if (listener) + listener->panelChanged (EvDemosaicALLEnhanced, allEnhance->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); }*/ diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index 4eed5bf32..35b1cf084 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -25,9 +25,10 @@ #include "toolpanel.h" -class BayerProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel{ +class BayerProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: MyComboBoxText* method; Adjuster* ccSteps; @@ -42,15 +43,15 @@ class BayerProcess : public ToolParamBlock, public AdjusterListener, public Fold bool lastDCBen; int oldSelection; //bool lastALLen; - sigc::connection methodconn,dcbEnhconn; //,allEnhconn; - public: + sigc::connection methodconn, dcbEnhconn; //,allEnhconn; +public: BayerProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void methodChanged (); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index f63912f4d..f420057fa 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -26,160 +26,202 @@ using namespace rtengine::procparams; BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, "bayerrawexposure", M("TP_EXPOS_BLACKPOINT_LABEL"), true) { - PexBlack1 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_1"),-2048,2048,0.1,0));//black level - PexBlack1->setAdjusterListener (this); - if (PexBlack1->delay < 1000) PexBlack1->delay = 1000; - PexBlack1->show(); - PexBlack2 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_2"),-2048,2048,0.1,0));//black level - PexBlack2->setAdjusterListener (this); - if (PexBlack2->delay < 1000) PexBlack2->delay = 1000; - PexBlack2->show(); - PexBlack3 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_3"),-2048,2048,0.1,0));//black level - PexBlack3->setAdjusterListener (this); - if (PexBlack3->delay < 1000) PexBlack3->delay = 1000; - PexBlack3->show(); - PexBlack0 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_0"),-2048,2048,0.1,0));//black level - PexBlack0->setAdjusterListener (this); - if (PexBlack0->delay < 1000) PexBlack0->delay = 1000; - PexBlack0->show(); - PextwoGreen = Gtk::manage(new Gtk::CheckButton((M("TP_RAWEXPOS_TWOGREEN"))));// two green - PextwoGreen->set_active (true); - greenconn = PextwoGreen->signal_toggled().connect ( sigc::mem_fun(*this, &BayerRAWExposure::GreenChanged)); + PexBlack1 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_1"), -2048, 2048, 0.1, 0)); //black level + PexBlack1->setAdjusterListener (this); - pack_start( *PexBlack1, Gtk::PACK_SHRINK, 0);//black R - pack_start( *PexBlack0, Gtk::PACK_SHRINK, 0);//black G1 - pack_start( *PexBlack3, Gtk::PACK_SHRINK, 0);//black G2 - pack_start( *PexBlack2, Gtk::PACK_SHRINK, 0);//black B - pack_start( *PextwoGreen, Gtk::PACK_SHRINK, 0);//black 2 green + if (PexBlack1->delay < 1000) { + PexBlack1->delay = 1000; + } + + PexBlack1->show(); + PexBlack2 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_2"), -2048, 2048, 0.1, 0)); //black level + PexBlack2->setAdjusterListener (this); + + if (PexBlack2->delay < 1000) { + PexBlack2->delay = 1000; + } + + PexBlack2->show(); + PexBlack3 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_3"), -2048, 2048, 0.1, 0)); //black level + PexBlack3->setAdjusterListener (this); + + if (PexBlack3->delay < 1000) { + PexBlack3->delay = 1000; + } + + PexBlack3->show(); + PexBlack0 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_0"), -2048, 2048, 0.1, 0)); //black level + PexBlack0->setAdjusterListener (this); + + if (PexBlack0->delay < 1000) { + PexBlack0->delay = 1000; + } + + PexBlack0->show(); + PextwoGreen = Gtk::manage(new Gtk::CheckButton((M("TP_RAWEXPOS_TWOGREEN"))));// two green + PextwoGreen->set_active (true); + greenconn = PextwoGreen->signal_toggled().connect ( sigc::mem_fun(*this, &BayerRAWExposure::GreenChanged)); + + pack_start( *PexBlack1, Gtk::PACK_SHRINK, 0);//black R + pack_start( *PexBlack0, Gtk::PACK_SHRINK, 0);//black G1 + pack_start( *PexBlack3, Gtk::PACK_SHRINK, 0);//black G2 + pack_start( *PexBlack2, Gtk::PACK_SHRINK, 0);//black B + pack_start( *PextwoGreen, Gtk::PACK_SHRINK, 0);//black 2 green } void BayerRAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener (); - if(pedited ){ - PexBlack0->setEditedState( pedited->raw.bayersensor.exBlack0 ? Edited : UnEdited ); - PexBlack1->setEditedState( pedited->raw.bayersensor.exBlack1 ? Edited : UnEdited ); - PexBlack2->setEditedState( pedited->raw.bayersensor.exBlack2 ? Edited : UnEdited ); - PexBlack3->setEditedState( pedited->raw.bayersensor.exBlack3 ? Edited : UnEdited ); - } - greenconn.block (true); - PextwoGreen->set_active (pp->raw.bayersensor.twogreen); - greenconn.block (false); - lastPextwoGreen = pp->raw.bayersensor.twogreen; - - PexBlack0->setValue (pp->raw.bayersensor.black0);//black - PexBlack1->setValue (pp->raw.bayersensor.black1);//black - PexBlack2->setValue (pp->raw.bayersensor.black2);//black - - if(!PextwoGreen->get_active())PexBlack3->setValue (pp->raw.bayersensor.black3);else PexBlack3->setValue (PexBlack0->getValue()); + if(pedited ) { + PexBlack0->setEditedState( pedited->raw.bayersensor.exBlack0 ? Edited : UnEdited ); + PexBlack1->setEditedState( pedited->raw.bayersensor.exBlack1 ? Edited : UnEdited ); + PexBlack2->setEditedState( pedited->raw.bayersensor.exBlack2 ? Edited : UnEdited ); + PexBlack3->setEditedState( pedited->raw.bayersensor.exBlack3 ? Edited : UnEdited ); + } - enableListener (); + greenconn.block (true); + PextwoGreen->set_active (pp->raw.bayersensor.twogreen); + greenconn.block (false); + lastPextwoGreen = pp->raw.bayersensor.twogreen; + + PexBlack0->setValue (pp->raw.bayersensor.black0);//black + PexBlack1->setValue (pp->raw.bayersensor.black1);//black + PexBlack2->setValue (pp->raw.bayersensor.black2);//black + + if(!PextwoGreen->get_active()) { + PexBlack3->setValue (pp->raw.bayersensor.black3); + } else { + PexBlack3->setValue (PexBlack0->getValue()); + } + + enableListener (); } void BayerRAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.bayersensor.black0 = PexBlack0->getValue();// black - pp->raw.bayersensor.black1 = PexBlack1->getValue();// black - pp->raw.bayersensor.black2 = PexBlack2->getValue();// black - pp->raw.bayersensor.twogreen=PextwoGreen->get_active(); - if(PextwoGreen->get_active()){pp->raw.bayersensor.black3=pp->raw.bayersensor.black0;} else {pp->raw.bayersensor.black3 = PexBlack3->getValue();}// active or desactive 2 green together + pp->raw.bayersensor.black0 = PexBlack0->getValue();// black + pp->raw.bayersensor.black1 = PexBlack1->getValue();// black + pp->raw.bayersensor.black2 = PexBlack2->getValue();// black + pp->raw.bayersensor.twogreen = PextwoGreen->get_active(); - if (pedited) { - pedited->raw.bayersensor.exBlack0 = PexBlack0->getEditedState ();//black - pedited->raw.bayersensor.exBlack1 = PexBlack1->getEditedState ();//black - pedited->raw.bayersensor.exBlack2 = PexBlack2->getEditedState ();//black - pedited->raw.bayersensor.exBlack3 = PexBlack3->getEditedState ();//black - pedited->raw.bayersensor.exTwoGreen =!PextwoGreen->get_inconsistent(); - } + if(PextwoGreen->get_active()) { + pp->raw.bayersensor.black3 = pp->raw.bayersensor.black0; // active or desactive 2 green together + } else { + pp->raw.bayersensor.black3 = PexBlack3->getValue(); + } + + if (pedited) { + pedited->raw.bayersensor.exBlack0 = PexBlack0->getEditedState ();//black + pedited->raw.bayersensor.exBlack1 = PexBlack1->getEditedState ();//black + pedited->raw.bayersensor.exBlack2 = PexBlack2->getEditedState ();//black + pedited->raw.bayersensor.exBlack3 = PexBlack3->getEditedState ();//black + pedited->raw.bayersensor.exTwoGreen = !PextwoGreen->get_inconsistent(); + } } void BayerRAWExposure::adjusterChanged (Adjuster* a, double newval) { - if (listener) { - Glib::ustring value = a->getTextValue(); - if (a == PexBlack0) {if(!PextwoGreen->get_active()) - listener->panelChanged (EvPreProcessExpBlackzero, value ); else {listener->panelChanged (EvPreProcessExpBlackzero, value );PexBlack3->setValue (PexBlack0->getValue());}} - else if (a == PexBlack1) - listener->panelChanged (EvPreProcessExpBlackone, value ); - else if (a == PexBlack2) - listener->panelChanged (EvPreProcessExpBlacktwo, value ); - else if (a == PexBlack3) {if(!PextwoGreen->get_active()) - listener->panelChanged (EvPreProcessExpBlackthree, value ); else {listener->panelChanged (EvPreProcessExpBlackthree, value );PexBlack0->setValue (PexBlack3->getValue());}} - } + if (listener) { + Glib::ustring value = a->getTextValue(); + + if (a == PexBlack0) { + if(!PextwoGreen->get_active()) { + listener->panelChanged (EvPreProcessExpBlackzero, value ); + } else { + listener->panelChanged (EvPreProcessExpBlackzero, value ); + PexBlack3->setValue (PexBlack0->getValue()); + } + } else if (a == PexBlack1) { + listener->panelChanged (EvPreProcessExpBlackone, value ); + } else if (a == PexBlack2) { + listener->panelChanged (EvPreProcessExpBlacktwo, value ); + } else if (a == PexBlack3) { + if(!PextwoGreen->get_active()) { + listener->panelChanged (EvPreProcessExpBlackthree, value ); + } else { + listener->panelChanged (EvPreProcessExpBlackthree, value ); + PexBlack0->setValue (PexBlack3->getValue()); + } + } + } } -void BayerRAWExposure::GreenChanged() { - if (batchMode) { +void BayerRAWExposure::GreenChanged() +{ + if (batchMode) { if (PextwoGreen->get_inconsistent()) { PextwoGreen->set_inconsistent (false); greenconn.block (true); PextwoGreen->set_active (false); greenconn.block (false); - } - else if (lastPextwoGreen) + } else if (lastPextwoGreen) { PextwoGreen->set_inconsistent (true); + } + lastPextwoGreen = PextwoGreen->get_active (); } - + if (listener) { - if (PextwoGreen->get_active()) - { listener->panelChanged (EvPreProcessExptwoGreen, M("GENERAL_ENABLED")); - PexBlack3->setValue (PexBlack0->getValue());//two green together - } - - else - { listener->panelChanged (EvPreProcessExptwoGreen, M("GENERAL_DISABLED")); - } - + if (PextwoGreen->get_active()) { + listener->panelChanged (EvPreProcessExptwoGreen, M("GENERAL_ENABLED")); + PexBlack3->setValue (PexBlack0->getValue());//two green together + } + + else { + listener->panelChanged (EvPreProcessExptwoGreen, M("GENERAL_DISABLED")); + } + } } void BayerRAWExposure::setBatchMode(bool batchMode) { - ToolPanel::setBatchMode (batchMode); - PexBlack0->showEditedCB ();//black - PexBlack1->showEditedCB ();//black - PexBlack2->showEditedCB ();//black - PexBlack3->showEditedCB ();//black - + ToolPanel::setBatchMode (batchMode); + PexBlack0->showEditedCB ();//black + PexBlack1->showEditedCB ();//black + PexBlack2->showEditedCB ();//black + PexBlack3->showEditedCB ();//black + } void BayerRAWExposure::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - PexBlack0->setDefault( defParams->raw.bayersensor.black0); - PexBlack1->setDefault( defParams->raw.bayersensor.black1); - PexBlack2->setDefault( defParams->raw.bayersensor.black2); - PexBlack3->setDefault( defParams->raw.bayersensor.black3); + PexBlack0->setDefault( defParams->raw.bayersensor.black0); + PexBlack1->setDefault( defParams->raw.bayersensor.black1); + PexBlack2->setDefault( defParams->raw.bayersensor.black2); + PexBlack3->setDefault( defParams->raw.bayersensor.black3); - if (pedited) { - PexBlack0->setDefaultEditedState( pedited->raw.bayersensor.exBlack0 ? Edited : UnEdited); - PexBlack1->setDefaultEditedState( pedited->raw.bayersensor.exBlack1 ? Edited : UnEdited); - PexBlack2->setDefaultEditedState( pedited->raw.bayersensor.exBlack2 ? Edited : UnEdited); - PexBlack3->setDefaultEditedState( pedited->raw.bayersensor.exBlack3 ? Edited : UnEdited); - - } else { - PexBlack0->setDefaultEditedState( Irrelevant ); - PexBlack1->setDefaultEditedState( Irrelevant ); - PexBlack2->setDefaultEditedState( Irrelevant ); - PexBlack3->setDefaultEditedState( Irrelevant ); - - } + if (pedited) { + PexBlack0->setDefaultEditedState( pedited->raw.bayersensor.exBlack0 ? Edited : UnEdited); + PexBlack1->setDefaultEditedState( pedited->raw.bayersensor.exBlack1 ? Edited : UnEdited); + PexBlack2->setDefaultEditedState( pedited->raw.bayersensor.exBlack2 ? Edited : UnEdited); + PexBlack3->setDefaultEditedState( pedited->raw.bayersensor.exBlack3 ? Edited : UnEdited); + + } else { + PexBlack0->setDefaultEditedState( Irrelevant ); + PexBlack1->setDefaultEditedState( Irrelevant ); + PexBlack2->setDefaultEditedState( Irrelevant ); + PexBlack3->setDefaultEditedState( Irrelevant ); + + } } -void BayerRAWExposure::setAdjusterBehavior (bool pexblackadd) { +void BayerRAWExposure::setAdjusterBehavior (bool pexblackadd) +{ - PexBlack0->setAddMode(pexblackadd); - PexBlack1->setAddMode(pexblackadd); - PexBlack2->setAddMode(pexblackadd); - PexBlack3->setAddMode(pexblackadd); + PexBlack0->setAddMode(pexblackadd); + PexBlack1->setAddMode(pexblackadd); + PexBlack2->setAddMode(pexblackadd); + PexBlack3->setAddMode(pexblackadd); } -void BayerRAWExposure::trimValues (rtengine::procparams::ProcParams* pp) { +void BayerRAWExposure::trimValues (rtengine::procparams::ProcParams* pp) +{ - PexBlack0->trimValue(pp->raw.bayersensor.black0); - PexBlack1->trimValue(pp->raw.bayersensor.black1); - PexBlack2->trimValue(pp->raw.bayersensor.black2); - PexBlack3->trimValue(pp->raw.bayersensor.black3); + PexBlack0->trimValue(pp->raw.bayersensor.black0); + PexBlack1->trimValue(pp->raw.bayersensor.black1); + PexBlack2->trimValue(pp->raw.bayersensor.black2); + PexBlack3->trimValue(pp->raw.bayersensor.black3); } diff --git a/rtgui/bayerrawexposure.h b/rtgui/bayerrawexposure.h index bb8f9eb20..94987ba1f 100644 --- a/rtgui/bayerrawexposure.h +++ b/rtgui/bayerrawexposure.h @@ -24,31 +24,32 @@ #include "toolpanel.h" #include "../rtengine/rawimage.h" -class BayerRAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class BayerRAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - Adjuster* PexBlack0; - Adjuster* PexBlack1; - Adjuster* PexBlack2; - Adjuster* PexBlack3; - bool lastPextwoGreen; - sigc::connection greenconn; - Gtk::CheckButton* PextwoGreen; + Adjuster* PexBlack0; + Adjuster* PexBlack1; + Adjuster* PexBlack2; + Adjuster* PexBlack3; + bool lastPextwoGreen; + sigc::connection greenconn; + Gtk::CheckButton* PextwoGreen; private: -// Gtk::CheckButton* PextwoGreen; +// Gtk::CheckButton* PextwoGreen; public: - BayerRAWExposure (); + BayerRAWExposure (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void GreenChanged() ; - void adjusterChanged (Adjuster* a, double newval); - void setAdjusterBehavior (bool pexblackadd); - void trimValues (rtengine::procparams::ProcParams* pp); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void GreenChanged() ; + void adjusterChanged (Adjuster* a, double newval); + void setAdjusterBehavior (bool pexblackadd); + void trimValues (rtengine::procparams::ProcParams* pp); }; #endif diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index f631225bb..d9b426fc8 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -7,7 +7,7 @@ * 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 @@ -28,1296 +28,1474 @@ using namespace rtengine; using namespace rtengine::procparams; -BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LABEL"), false, true) { - CurveListener::setMulti(true); - - nextredbw = 0.3333; - nextgreenbw = 0.3333; - nextbluebw = 0.3333; - - //----------- Method combobox ------------------------------ - - Gtk::HBox* metHBox = Gtk::manage (new Gtk::HBox ()); - metHBox->set_border_width (0); - metHBox->set_spacing (2); - Gtk::Label* metLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_MET")+":")); - metHBox->pack_start (*metLabel, Gtk::PACK_SHRINK); - method = Gtk::manage (new MyComboBoxText ()); - method->append_text (M("TP_BWMIX_MET_DESAT")); - method->append_text (M("TP_BWMIX_MET_LUMEQUAL")); - method->append_text (M("TP_BWMIX_MET_CHANMIX")); - - method->set_active (0); - metHBox->pack_start (*method); - pack_start (*metHBox); - methodconn = method->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::methodChanged) ); - - - //----------- Luminance equalizer ------------------------------ - - luminanceSep = Gtk::manage (new Gtk::HSeparator()); - pack_start (*luminanceSep); - - std::vector bottomMilestones; - float R, G, B; - // -0.1 rad < Hue < 1.6 rad - for (int i=0; i<7; i++) { - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - luminanceCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CHANNEL")); - luminanceCEG->setCurveListener (this); - luminanceCurve = static_cast(luminanceCEG->addCurve(CT_Flat, M("TP_BWMIX_VAL"))); - luminanceCurve->setEditID(EUID_BlackWhiteLuminance, BT_SINGLEPLANE_FLOAT); - luminanceCurve->setBottomBarBgGradient(bottomMilestones); - luminanceCurve->setCurveColorProvider(this, 3); - luminanceCurve->setTooltip(M("TP_BWMIX_CURVEEDITOR_LH_TOOLTIP")); - - luminanceCEG->curveListComplete(); - pack_start (*luminanceCEG, Gtk::PACK_SHRINK, 4); - - //----------- Auto and Reset buttons ------------------------------ - - mixerFrame = Gtk::manage (new Gtk::Frame (M("TP_BWMIX_MET_CHANMIX"))); - pack_start (*mixerFrame, Gtk::PACK_SHRINK, 0); - - mixerVBox = Gtk::manage (new Gtk::VBox ()); - mixerVBox->set_border_width(4); - mixerVBox->set_spacing(4); - - autoHBox = Gtk::manage (new Gtk::HBox ()); - autoHBox->set_border_width (2); - - autoch = Gtk::manage (new Gtk::ToggleButton (M("TP_BWMIX_AUTOCH"))); - autoch->set_tooltip_markup (M("TP_BWMIX_AUTOCH_TIP")); - autoconn = autoch->signal_toggled().connect( sigc::mem_fun(*this, &BlackWhite::autoch_toggled) ); - - neutral = Gtk::manage (new Gtk::Button (M("TP_BWMIX_NEUTRAL"))); - RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); - neutral->set_image(*resetImg); - neutral->set_tooltip_text (M("TP_BWMIX_NEUTRAL_TIP")); - neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &BlackWhite::neutral_pressed) ); - neutral->show(); - - autoHBox->pack_start (*autoch); - autoHBox->pack_end (*neutral); - autoHBox->pack_end (*Gtk::manage (new Gtk::Label (" "))); //spacer - mixerVBox->pack_start (*autoHBox); - - //----------- Presets combobox ------------------------------ - - mixerVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); - - settingHBox = Gtk::manage (new Gtk::HBox ()); - settingHBox->set_border_width (0); - settingHBox->set_spacing (2); - settingHBox->set_tooltip_markup (M("TP_BWMIX_SETTING_TOOLTIP")); - Gtk::Label *settingLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_SETTING")+":")); - - settingHBox->pack_start (*settingLabel, Gtk::PACK_SHRINK); - setting = Gtk::manage (new MyComboBoxText ()); - setting->append_text (M("TP_BWMIX_SET_NORMCONTAST")); - setting->append_text (M("TP_BWMIX_SET_HIGHCONTAST")); - setting->append_text (M("TP_BWMIX_SET_LUMINANCE")); - setting->append_text (M("TP_BWMIX_SET_LANDSCAPE")); - setting->append_text (M("TP_BWMIX_SET_PORTRAIT")); - setting->append_text (M("TP_BWMIX_SET_LOWSENSIT")); - setting->append_text (M("TP_BWMIX_SET_HIGHSENSIT")); - setting->append_text (M("TP_BWMIX_SET_PANCHRO")); - setting->append_text (M("TP_BWMIX_SET_HYPERPANCHRO")); - setting->append_text (M("TP_BWMIX_SET_ORTHOCHRO")); - setting->append_text (M("TP_BWMIX_SET_RGBABS")); - setting->append_text (M("TP_BWMIX_SET_RGBREL")); - setting->append_text (M("TP_BWMIX_SET_ROYGCBPMABS")); - setting->append_text (M("TP_BWMIX_SET_ROYGCBPMREL")); - setting->append_text (M("TP_BWMIX_SET_INFRARED")); - - setting->set_active (0); - settingHBox->pack_start (*setting); - mixerVBox->pack_start (*settingHBox); - settingconn = setting->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::settingChanged) ); - - RGBLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); - RGBLabels->set_tooltip_text(M("TP_BWMIX_RGBLABEL_HINT")); - mixerVBox->pack_start (*RGBLabels); - - //----------- Complementary Color checkbox ------------------------------ - - enabledccSep= Gtk::manage (new Gtk::HSeparator()); - mixerVBox->pack_start (*enabledccSep); - - enabledcc = Gtk::manage (new Gtk::CheckButton (M("TP_BWMIX_CC_ENABLED"))); - - enabledcc->set_active (true); - enabledcc->set_tooltip_markup (M("TP_BWMIX_CC_TOOLTIP")); - - mixerVBox->pack_start(*enabledcc, Gtk::PACK_SHRINK, 0); - enabledcc->show (); - enaccconn = enabledcc->signal_toggled().connect( sigc::mem_fun(*this, &BlackWhite::enabledcc_toggled) ); - - //----------- Color Filters ------------------------------ - - filterSep = Gtk::manage (new Gtk::HSeparator()); - mixerVBox->pack_start (*filterSep); - - filterHBox = Gtk::manage (new Gtk::HBox ()); - filterHBox->set_border_width (0); - filterHBox->set_spacing (2); - filterHBox->set_tooltip_markup (M("TP_BWMIX_FILTER_TOOLTIP")); - Gtk::Label *filterLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_FILTER")+":")); - filterHBox->pack_start (*filterLabel, Gtk::PACK_SHRINK); - filter = Gtk::manage (new MyComboBoxText ()); - filter->append_text (M("TP_BWMIX_FILTER_NONE")); - filter->append_text (M("TP_BWMIX_FILTER_RED")); - filter->append_text (M("TP_BWMIX_FILTER_REDYELLOW")); - filter->append_text (M("TP_BWMIX_FILTER_YELLOW")); - filter->append_text (M("TP_BWMIX_FILTER_GREENYELLOW")); - filter->append_text (M("TP_BWMIX_FILTER_GREEN")); - filter->append_text (M("TP_BWMIX_FILTER_BLUEGREEN")); - filter->append_text (M("TP_BWMIX_FILTER_BLUE")); - filter->append_text (M("TP_BWMIX_FILTER_PURPLE")); - - filter->set_active (0); - filterHBox->pack_start (*filter); - mixerVBox->pack_start (*filterHBox); - filterconn = filter->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::filterChanged) ); - - //----------- RGB / ROYGCBPM Mixer ------------------------------ - - imgIcon[0] = Gtk::manage (new RTImage ("Chanmixer-R.png")); - imgIcon[1] = Gtk::manage (new RTImage ("Chanmixer-O.png")); - imgIcon[2] = Gtk::manage (new RTImage ("Chanmixer-Y.png")); - imgIcon[3] = Gtk::manage (new RTImage ("Chanmixer-G.png")); - imgIcon[4] = Gtk::manage (new RTImage ("Chanmixer-C.png")); - imgIcon[5] = Gtk::manage (new RTImage ("Chanmixer-B.png")); - imgIcon[6] = Gtk::manage (new RTImage ("Chanmixer-P.png")); - imgIcon[7] = Gtk::manage (new RTImage ("Chanmixer-M.png")); - - imgIcon[8] = Gtk::manage (new RTImage ("Chanmixer-Rgamma.png")); - imgIcon[9] = Gtk::manage (new RTImage ("Chanmixer-Ggamma.png")); - imgIcon[10] = Gtk::manage (new RTImage ("Chanmixer-Bgamma.png")); - - mixerVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); - - mixerRed= Gtk::manage(new Adjuster (/*M("TP_BWMIX_RED")*/"", -100, 200, 1, 33, imgIcon[0])); - if (mixerRed->delay < 50) mixerRed->delay = 50; - mixerRed->setAdjusterListener (this); - mixerRed->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerRed->show(); - mixerVBox->pack_start( *mixerRed, Gtk::PACK_SHRINK, 0); - - mixerGreen= Gtk::manage(new Adjuster (/*M("TP_BWMIX_GREEN")*/"", -100, 200, 1, 33, imgIcon[3])); - if (mixerGreen->delay < 50) mixerGreen->delay = 50; - mixerGreen->setAdjusterListener (this); - mixerGreen->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerGreen->show(); - mixerVBox->pack_start( *mixerGreen, Gtk::PACK_SHRINK, 0); - - mixerBlue= Gtk::manage(new Adjuster (/*M("TP_BWMIX_BLUE")*/"", -100, 200, 1, 33, imgIcon[5])); - if (mixerBlue->delay < 50) mixerBlue->delay = 50; - mixerBlue->setAdjusterListener (this); - mixerBlue->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerBlue->show(); - mixerVBox->pack_start( *mixerBlue, Gtk::PACK_SHRINK, 0); - - filterSep2 = Gtk::manage (new Gtk::HSeparator()); - mixerVBox->pack_start (*filterSep2); - - algoHBox = Gtk::manage (new Gtk::HBox ()); - algoHBox->set_border_width (0); - algoHBox->set_spacing (2); - algoHBox->set_tooltip_markup (M("TP_BWMIX_ALGO_TOOLTIP")); - - alLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_ALGO")+":")); - algoHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); - - algo = Gtk::manage (new MyComboBoxText ()); - algo->append_text (M("TP_BWMIX_ALGO_LI")); - algo->append_text (M("TP_BWMIX_ALGO_SP")); - algo->set_active (1); - algoHBox->pack_start (*algo); - mixerVBox->pack_start(*algoHBox); - algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::algoChanged) ); - - mixerOrange= Gtk::manage(new Adjuster (/*M("TP_BWMIX_ORANGE")*/"", -100, 200, 1, 33, imgIcon[1])); - if (mixerOrange->delay < 50) mixerOrange->delay = 50; - mixerOrange->setAdjusterListener (this); - mixerOrange->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerOrange->show(); - mixerVBox->pack_start( *mixerOrange, Gtk::PACK_SHRINK, 0); - - mixerYellow= Gtk::manage(new Adjuster (/*M("TP_BWMIX_YELLOW")*/"", -100, 200, 1, 33, imgIcon[2])); - if (mixerYellow->delay < 50) mixerYellow->delay = 50; - mixerYellow->setAdjusterListener (this); - mixerYellow->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerYellow->show(); - mixerVBox->pack_start( *mixerYellow, Gtk::PACK_SHRINK, 0); - - mixerCyan= Gtk::manage(new Adjuster (/*M("TP_BWMIX_CYAN")*/"", -100, 200, 1, 33, imgIcon[4])); - if (mixerCyan->delay < 50) mixerCyan->delay = 50; - mixerCyan->setAdjusterListener (this); - mixerCyan->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerCyan->show(); - mixerVBox->pack_start( *mixerCyan, Gtk::PACK_SHRINK, 0); - - mixerPurple= Gtk::manage(new Adjuster (/*M("TP_BWMIX_PURPLE")*/"", -100, 200, 1, 33, imgIcon[6])); - if (mixerPurple->delay < 50) mixerPurple->delay = 50; - mixerPurple->setAdjusterListener (this); - mixerPurple->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerPurple->show(); - mixerVBox->pack_start( *mixerPurple, Gtk::PACK_SHRINK, 0); - - mixerMagenta= Gtk::manage(new Adjuster (/*M("TP_BWMIX_MAGENTA")*/"", -100, 200, 1, 33, imgIcon[7])); - if (mixerMagenta->delay < 50) mixerMagenta->delay = 50; - mixerMagenta->setAdjusterListener (this); - mixerMagenta->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); - mixerMagenta->show(); - mixerVBox->pack_start( *mixerMagenta, Gtk::PACK_SHRINK, 0); - - mixerFrame->add(*mixerVBox); - - //----------- Gamma sliders ------------------------------ - - gammaFrame = Gtk::manage (new Gtk::Frame (M("TP_BWMIX_GAMMA"))); - pack_start (*gammaFrame, Gtk::PACK_SHRINK, 0); - - Gtk::VBox *gammaVBox = Gtk::manage (new Gtk::VBox()); - gammaVBox->set_spacing(4); - gammaVBox->set_border_width(4); - - - gammaRed= Gtk::manage(new Adjuster (/*M("TP_BWMIX_GAM_RED")*/"", -100, 100, 1, 0, imgIcon[8])); - if (gammaRed->delay < 50) gammaRed->delay = 50; - - gammaRed->setAdjusterListener (this); - gammaRed->set_tooltip_markup (M("TP_BWMIX_GAM_TOOLTIP")); - gammaRed->show(); - gammaVBox->pack_start( *gammaRed, Gtk::PACK_SHRINK, 0); - - gammaGreen= Gtk::manage(new Adjuster (/*M("TP_BWMIX_GAM_GREEN")*/"", -100, 100, 1, 0, imgIcon[9])); - if (gammaGreen->delay < 50) gammaGreen->delay = 50; - gammaGreen->setAdjusterListener (this); - gammaGreen->set_tooltip_markup (M("TP_BWMIX_GAM_TOOLTIP")); - gammaGreen->show(); - gammaVBox->pack_start( *gammaGreen, Gtk::PACK_SHRINK, 0); - - gammaBlue= Gtk::manage(new Adjuster (/*M("TP_BWMIX_GAM_BLUE")*/"", -100, 100, 1, 0, imgIcon[10])); - if (gammaBlue->delay < 50) gammaBlue->delay = 50; - gammaBlue->setAdjusterListener (this); - gammaBlue->set_tooltip_markup (M("TP_BWMIX_GAM_TOOLTIP")); - gammaBlue->show(); - gammaVBox->pack_start( *gammaBlue, Gtk::PACK_SHRINK, 0); - - gammaFrame->add(*gammaVBox); - - //----------- Curve 1 ------------------------------ - - std::vector bottomMilestonesbw; - bottomMilestonesbw.push_back( GradientMilestone(0., 0., 0., 0.) ); - bottomMilestonesbw.push_back( GradientMilestone(1., 1., 1., 1.) ); - - beforeCurveMode = Gtk::manage (new MyComboBoxText ()); - beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_STANDARD")); - beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_WEIGHTEDSTD")); - beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_FILMLIKE")); - beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_SATANDVALBLENDING")); - beforeCurveMode->set_active (0); - - beforeCurveCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CURVEEDITOR1")); - beforeCurveCEG->setCurveListener (this); - - beforeCurve = static_cast(beforeCurveCEG->addCurve(CT_Diagonal, "", beforeCurveMode)); - beforeCurve->setEditID(EUID_BlackWhiteBeforeCurve, BT_IMAGEFLOAT); - beforeCurve->setBottomBarBgGradient(bottomMilestonesbw); - beforeCurve->setLeftBarBgGradient(bottomMilestonesbw); - beforeCurve->setTooltip(M("TP_BWMIX_CURVEEDITOR_BEFORE_TOOLTIP")); - - // This will add the reset button at the end of the curveType buttons - beforeCurveCEG->curveListComplete(); - - pack_start( *beforeCurveCEG, Gtk::PACK_SHRINK, 2); - - tcmodeconn = beforeCurveMode->signal_changed().connect( sigc::mem_fun(*this, &BlackWhite::curveMode1Changed), true ); - - //----------- Curve 2 ------------------------------ -/* - afterCurveMode = Gtk::manage (new MyComboBoxText ()); - afterCurveMode->append_text (M("TP_BWMIX_TCMODE_STANDARD")); - // afterCurveMode->append_text (M("TP_BWMIX_TCMODE_WEIGHTEDSTD")); - afterCurveMode->set_active (0); -*/ - afterCurveCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CURVEEDITOR2")); - afterCurveCEG->setCurveListener (this); - -// afterCurve = static_cast(afterCurveCEG->addCurve(CT_Diagonal, "", afterCurveMode)); - afterCurve = static_cast(afterCurveCEG->addCurve(CT_Diagonal, "")); - afterCurve->setEditID(EUID_BlackWhiteAfterCurve, BT_SINGLEPLANE_FLOAT); - afterCurve->setBottomBarBgGradient(bottomMilestonesbw); - afterCurve->setLeftBarBgGradient(bottomMilestonesbw); - afterCurve->setTooltip(M("TP_BWMIX_CURVEEDITOR_AFTER_TOOLTIP")); - - afterCurveCEG->curveListComplete(); +BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LABEL"), false, true) +{ + CurveListener::setMulti(true); + + nextredbw = 0.3333; + nextgreenbw = 0.3333; + nextbluebw = 0.3333; + + //----------- Method combobox ------------------------------ + + Gtk::HBox* metHBox = Gtk::manage (new Gtk::HBox ()); + metHBox->set_border_width (0); + metHBox->set_spacing (2); + Gtk::Label* metLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_MET") + ":")); + metHBox->pack_start (*metLabel, Gtk::PACK_SHRINK); + method = Gtk::manage (new MyComboBoxText ()); + method->append_text (M("TP_BWMIX_MET_DESAT")); + method->append_text (M("TP_BWMIX_MET_LUMEQUAL")); + method->append_text (M("TP_BWMIX_MET_CHANMIX")); + + method->set_active (0); + metHBox->pack_start (*method); + pack_start (*metHBox); + methodconn = method->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::methodChanged) ); + + + //----------- Luminance equalizer ------------------------------ + + luminanceSep = Gtk::manage (new Gtk::HSeparator()); + pack_start (*luminanceSep); + + std::vector bottomMilestones; + float R, G, B; + + // -0.1 rad < Hue < 1.6 rad + for (int i = 0; i < 7; i++) { + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } + + luminanceCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CHANNEL")); + luminanceCEG->setCurveListener (this); + luminanceCurve = static_cast(luminanceCEG->addCurve(CT_Flat, M("TP_BWMIX_VAL"))); + luminanceCurve->setEditID(EUID_BlackWhiteLuminance, BT_SINGLEPLANE_FLOAT); + luminanceCurve->setBottomBarBgGradient(bottomMilestones); + luminanceCurve->setCurveColorProvider(this, 3); + luminanceCurve->setTooltip(M("TP_BWMIX_CURVEEDITOR_LH_TOOLTIP")); + + luminanceCEG->curveListComplete(); + pack_start (*luminanceCEG, Gtk::PACK_SHRINK, 4); + + //----------- Auto and Reset buttons ------------------------------ + + mixerFrame = Gtk::manage (new Gtk::Frame (M("TP_BWMIX_MET_CHANMIX"))); + pack_start (*mixerFrame, Gtk::PACK_SHRINK, 0); + + mixerVBox = Gtk::manage (new Gtk::VBox ()); + mixerVBox->set_border_width(4); + mixerVBox->set_spacing(4); + + autoHBox = Gtk::manage (new Gtk::HBox ()); + autoHBox->set_border_width (2); + + autoch = Gtk::manage (new Gtk::ToggleButton (M("TP_BWMIX_AUTOCH"))); + autoch->set_tooltip_markup (M("TP_BWMIX_AUTOCH_TIP")); + autoconn = autoch->signal_toggled().connect( sigc::mem_fun(*this, &BlackWhite::autoch_toggled) ); + + neutral = Gtk::manage (new Gtk::Button (M("TP_BWMIX_NEUTRAL"))); + RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); + neutral->set_image(*resetImg); + neutral->set_tooltip_text (M("TP_BWMIX_NEUTRAL_TIP")); + neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &BlackWhite::neutral_pressed) ); + neutral->show(); + + autoHBox->pack_start (*autoch); + autoHBox->pack_end (*neutral); + autoHBox->pack_end (*Gtk::manage (new Gtk::Label (" "))); //spacer + mixerVBox->pack_start (*autoHBox); + + //----------- Presets combobox ------------------------------ + + mixerVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); + + settingHBox = Gtk::manage (new Gtk::HBox ()); + settingHBox->set_border_width (0); + settingHBox->set_spacing (2); + settingHBox->set_tooltip_markup (M("TP_BWMIX_SETTING_TOOLTIP")); + Gtk::Label *settingLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_SETTING") + ":")); + + settingHBox->pack_start (*settingLabel, Gtk::PACK_SHRINK); + setting = Gtk::manage (new MyComboBoxText ()); + setting->append_text (M("TP_BWMIX_SET_NORMCONTAST")); + setting->append_text (M("TP_BWMIX_SET_HIGHCONTAST")); + setting->append_text (M("TP_BWMIX_SET_LUMINANCE")); + setting->append_text (M("TP_BWMIX_SET_LANDSCAPE")); + setting->append_text (M("TP_BWMIX_SET_PORTRAIT")); + setting->append_text (M("TP_BWMIX_SET_LOWSENSIT")); + setting->append_text (M("TP_BWMIX_SET_HIGHSENSIT")); + setting->append_text (M("TP_BWMIX_SET_PANCHRO")); + setting->append_text (M("TP_BWMIX_SET_HYPERPANCHRO")); + setting->append_text (M("TP_BWMIX_SET_ORTHOCHRO")); + setting->append_text (M("TP_BWMIX_SET_RGBABS")); + setting->append_text (M("TP_BWMIX_SET_RGBREL")); + setting->append_text (M("TP_BWMIX_SET_ROYGCBPMABS")); + setting->append_text (M("TP_BWMIX_SET_ROYGCBPMREL")); + setting->append_text (M("TP_BWMIX_SET_INFRARED")); + + setting->set_active (0); + settingHBox->pack_start (*setting); + mixerVBox->pack_start (*settingHBox); + settingconn = setting->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::settingChanged) ); + + RGBLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + RGBLabels->set_tooltip_text(M("TP_BWMIX_RGBLABEL_HINT")); + mixerVBox->pack_start (*RGBLabels); + + //----------- Complementary Color checkbox ------------------------------ + + enabledccSep = Gtk::manage (new Gtk::HSeparator()); + mixerVBox->pack_start (*enabledccSep); + + enabledcc = Gtk::manage (new Gtk::CheckButton (M("TP_BWMIX_CC_ENABLED"))); + + enabledcc->set_active (true); + enabledcc->set_tooltip_markup (M("TP_BWMIX_CC_TOOLTIP")); + + mixerVBox->pack_start(*enabledcc, Gtk::PACK_SHRINK, 0); + enabledcc->show (); + enaccconn = enabledcc->signal_toggled().connect( sigc::mem_fun(*this, &BlackWhite::enabledcc_toggled) ); + + //----------- Color Filters ------------------------------ + + filterSep = Gtk::manage (new Gtk::HSeparator()); + mixerVBox->pack_start (*filterSep); + + filterHBox = Gtk::manage (new Gtk::HBox ()); + filterHBox->set_border_width (0); + filterHBox->set_spacing (2); + filterHBox->set_tooltip_markup (M("TP_BWMIX_FILTER_TOOLTIP")); + Gtk::Label *filterLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_FILTER") + ":")); + filterHBox->pack_start (*filterLabel, Gtk::PACK_SHRINK); + filter = Gtk::manage (new MyComboBoxText ()); + filter->append_text (M("TP_BWMIX_FILTER_NONE")); + filter->append_text (M("TP_BWMIX_FILTER_RED")); + filter->append_text (M("TP_BWMIX_FILTER_REDYELLOW")); + filter->append_text (M("TP_BWMIX_FILTER_YELLOW")); + filter->append_text (M("TP_BWMIX_FILTER_GREENYELLOW")); + filter->append_text (M("TP_BWMIX_FILTER_GREEN")); + filter->append_text (M("TP_BWMIX_FILTER_BLUEGREEN")); + filter->append_text (M("TP_BWMIX_FILTER_BLUE")); + filter->append_text (M("TP_BWMIX_FILTER_PURPLE")); + + filter->set_active (0); + filterHBox->pack_start (*filter); + mixerVBox->pack_start (*filterHBox); + filterconn = filter->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::filterChanged) ); + + //----------- RGB / ROYGCBPM Mixer ------------------------------ + + imgIcon[0] = Gtk::manage (new RTImage ("Chanmixer-R.png")); + imgIcon[1] = Gtk::manage (new RTImage ("Chanmixer-O.png")); + imgIcon[2] = Gtk::manage (new RTImage ("Chanmixer-Y.png")); + imgIcon[3] = Gtk::manage (new RTImage ("Chanmixer-G.png")); + imgIcon[4] = Gtk::manage (new RTImage ("Chanmixer-C.png")); + imgIcon[5] = Gtk::manage (new RTImage ("Chanmixer-B.png")); + imgIcon[6] = Gtk::manage (new RTImage ("Chanmixer-P.png")); + imgIcon[7] = Gtk::manage (new RTImage ("Chanmixer-M.png")); + + imgIcon[8] = Gtk::manage (new RTImage ("Chanmixer-Rgamma.png")); + imgIcon[9] = Gtk::manage (new RTImage ("Chanmixer-Ggamma.png")); + imgIcon[10] = Gtk::manage (new RTImage ("Chanmixer-Bgamma.png")); + + mixerVBox->pack_start (*Gtk::manage (new Gtk::HSeparator())); + + mixerRed = Gtk::manage(new Adjuster (/*M("TP_BWMIX_RED")*/"", -100, 200, 1, 33, imgIcon[0])); + + if (mixerRed->delay < 50) { + mixerRed->delay = 50; + } + + mixerRed->setAdjusterListener (this); + mixerRed->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerRed->show(); + mixerVBox->pack_start( *mixerRed, Gtk::PACK_SHRINK, 0); + + mixerGreen = Gtk::manage(new Adjuster (/*M("TP_BWMIX_GREEN")*/"", -100, 200, 1, 33, imgIcon[3])); + + if (mixerGreen->delay < 50) { + mixerGreen->delay = 50; + } + + mixerGreen->setAdjusterListener (this); + mixerGreen->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerGreen->show(); + mixerVBox->pack_start( *mixerGreen, Gtk::PACK_SHRINK, 0); - pack_start( *afterCurveCEG, Gtk::PACK_SHRINK, 2); + mixerBlue = Gtk::manage(new Adjuster (/*M("TP_BWMIX_BLUE")*/"", -100, 200, 1, 33, imgIcon[5])); -// tcmodeconn2 = afterCurveMode->signal_changed().connect( sigc::mem_fun(*this, &BlackWhite::curveMode1Changed2), true ); + if (mixerBlue->delay < 50) { + mixerBlue->delay = 50; + } - show_all(); + mixerBlue->setAdjusterListener (this); + mixerBlue->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerBlue->show(); + mixerVBox->pack_start( *mixerBlue, Gtk::PACK_SHRINK, 0); - disableListener(); - methodChanged(); - enableListener(); + filterSep2 = Gtk::manage (new Gtk::HSeparator()); + mixerVBox->pack_start (*filterSep2); + + algoHBox = Gtk::manage (new Gtk::HBox ()); + algoHBox->set_border_width (0); + algoHBox->set_spacing (2); + algoHBox->set_tooltip_markup (M("TP_BWMIX_ALGO_TOOLTIP")); + + alLabel = Gtk::manage (new Gtk::Label (M("TP_BWMIX_ALGO") + ":")); + algoHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); + + algo = Gtk::manage (new MyComboBoxText ()); + algo->append_text (M("TP_BWMIX_ALGO_LI")); + algo->append_text (M("TP_BWMIX_ALGO_SP")); + algo->set_active (1); + algoHBox->pack_start (*algo); + mixerVBox->pack_start(*algoHBox); + algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::algoChanged) ); + + mixerOrange = Gtk::manage(new Adjuster (/*M("TP_BWMIX_ORANGE")*/"", -100, 200, 1, 33, imgIcon[1])); + + if (mixerOrange->delay < 50) { + mixerOrange->delay = 50; + } + + mixerOrange->setAdjusterListener (this); + mixerOrange->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerOrange->show(); + mixerVBox->pack_start( *mixerOrange, Gtk::PACK_SHRINK, 0); + + mixerYellow = Gtk::manage(new Adjuster (/*M("TP_BWMIX_YELLOW")*/"", -100, 200, 1, 33, imgIcon[2])); + + if (mixerYellow->delay < 50) { + mixerYellow->delay = 50; + } + + mixerYellow->setAdjusterListener (this); + mixerYellow->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerYellow->show(); + mixerVBox->pack_start( *mixerYellow, Gtk::PACK_SHRINK, 0); + + mixerCyan = Gtk::manage(new Adjuster (/*M("TP_BWMIX_CYAN")*/"", -100, 200, 1, 33, imgIcon[4])); + + if (mixerCyan->delay < 50) { + mixerCyan->delay = 50; + } + + mixerCyan->setAdjusterListener (this); + mixerCyan->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerCyan->show(); + mixerVBox->pack_start( *mixerCyan, Gtk::PACK_SHRINK, 0); + + mixerPurple = Gtk::manage(new Adjuster (/*M("TP_BWMIX_PURPLE")*/"", -100, 200, 1, 33, imgIcon[6])); + + if (mixerPurple->delay < 50) { + mixerPurple->delay = 50; + } + + mixerPurple->setAdjusterListener (this); + mixerPurple->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerPurple->show(); + mixerVBox->pack_start( *mixerPurple, Gtk::PACK_SHRINK, 0); + + mixerMagenta = Gtk::manage(new Adjuster (/*M("TP_BWMIX_MAGENTA")*/"", -100, 200, 1, 33, imgIcon[7])); + + if (mixerMagenta->delay < 50) { + mixerMagenta->delay = 50; + } + + mixerMagenta->setAdjusterListener (this); + mixerMagenta->set_tooltip_markup (M("TP_BWMIX_RGB_TOOLTIP")); + mixerMagenta->show(); + mixerVBox->pack_start( *mixerMagenta, Gtk::PACK_SHRINK, 0); + + mixerFrame->add(*mixerVBox); + + //----------- Gamma sliders ------------------------------ + + gammaFrame = Gtk::manage (new Gtk::Frame (M("TP_BWMIX_GAMMA"))); + pack_start (*gammaFrame, Gtk::PACK_SHRINK, 0); + + Gtk::VBox *gammaVBox = Gtk::manage (new Gtk::VBox()); + gammaVBox->set_spacing(4); + gammaVBox->set_border_width(4); + + + gammaRed = Gtk::manage(new Adjuster (/*M("TP_BWMIX_GAM_RED")*/"", -100, 100, 1, 0, imgIcon[8])); + + if (gammaRed->delay < 50) { + gammaRed->delay = 50; + } + + gammaRed->setAdjusterListener (this); + gammaRed->set_tooltip_markup (M("TP_BWMIX_GAM_TOOLTIP")); + gammaRed->show(); + gammaVBox->pack_start( *gammaRed, Gtk::PACK_SHRINK, 0); + + gammaGreen = Gtk::manage(new Adjuster (/*M("TP_BWMIX_GAM_GREEN")*/"", -100, 100, 1, 0, imgIcon[9])); + + if (gammaGreen->delay < 50) { + gammaGreen->delay = 50; + } + + gammaGreen->setAdjusterListener (this); + gammaGreen->set_tooltip_markup (M("TP_BWMIX_GAM_TOOLTIP")); + gammaGreen->show(); + gammaVBox->pack_start( *gammaGreen, Gtk::PACK_SHRINK, 0); + + gammaBlue = Gtk::manage(new Adjuster (/*M("TP_BWMIX_GAM_BLUE")*/"", -100, 100, 1, 0, imgIcon[10])); + + if (gammaBlue->delay < 50) { + gammaBlue->delay = 50; + } + + gammaBlue->setAdjusterListener (this); + gammaBlue->set_tooltip_markup (M("TP_BWMIX_GAM_TOOLTIP")); + gammaBlue->show(); + gammaVBox->pack_start( *gammaBlue, Gtk::PACK_SHRINK, 0); + + gammaFrame->add(*gammaVBox); + + //----------- Curve 1 ------------------------------ + + std::vector bottomMilestonesbw; + bottomMilestonesbw.push_back( GradientMilestone(0., 0., 0., 0.) ); + bottomMilestonesbw.push_back( GradientMilestone(1., 1., 1., 1.) ); + + beforeCurveMode = Gtk::manage (new MyComboBoxText ()); + beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_STANDARD")); + beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_WEIGHTEDSTD")); + beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_FILMLIKE")); + beforeCurveMode->append_text (M("TP_BWMIX_TCMODE_SATANDVALBLENDING")); + beforeCurveMode->set_active (0); + + beforeCurveCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CURVEEDITOR1")); + beforeCurveCEG->setCurveListener (this); + + beforeCurve = static_cast(beforeCurveCEG->addCurve(CT_Diagonal, "", beforeCurveMode)); + beforeCurve->setEditID(EUID_BlackWhiteBeforeCurve, BT_IMAGEFLOAT); + beforeCurve->setBottomBarBgGradient(bottomMilestonesbw); + beforeCurve->setLeftBarBgGradient(bottomMilestonesbw); + beforeCurve->setTooltip(M("TP_BWMIX_CURVEEDITOR_BEFORE_TOOLTIP")); + + // This will add the reset button at the end of the curveType buttons + beforeCurveCEG->curveListComplete(); + + pack_start( *beforeCurveCEG, Gtk::PACK_SHRINK, 2); + + tcmodeconn = beforeCurveMode->signal_changed().connect( sigc::mem_fun(*this, &BlackWhite::curveMode1Changed), true ); + + //----------- Curve 2 ------------------------------ + /* + afterCurveMode = Gtk::manage (new MyComboBoxText ()); + afterCurveMode->append_text (M("TP_BWMIX_TCMODE_STANDARD")); + // afterCurveMode->append_text (M("TP_BWMIX_TCMODE_WEIGHTEDSTD")); + afterCurveMode->set_active (0); + */ + afterCurveCEG = new CurveEditorGroup (options.lastBWCurvesDir, M("TP_BWMIX_CURVEEDITOR2")); + afterCurveCEG->setCurveListener (this); + +// afterCurve = static_cast(afterCurveCEG->addCurve(CT_Diagonal, "", afterCurveMode)); + afterCurve = static_cast(afterCurveCEG->addCurve(CT_Diagonal, "")); + afterCurve->setEditID(EUID_BlackWhiteAfterCurve, BT_SINGLEPLANE_FLOAT); + afterCurve->setBottomBarBgGradient(bottomMilestonesbw); + afterCurve->setLeftBarBgGradient(bottomMilestonesbw); + afterCurve->setTooltip(M("TP_BWMIX_CURVEEDITOR_AFTER_TOOLTIP")); + + afterCurveCEG->curveListComplete(); + + pack_start( *afterCurveCEG, Gtk::PACK_SHRINK, 2); + +// tcmodeconn2 = afterCurveMode->signal_changed().connect( sigc::mem_fun(*this, &BlackWhite::curveMode1Changed2), true ); + + show_all(); + + disableListener(); + methodChanged(); + enableListener(); } -BlackWhite::~BlackWhite () { - delete luminanceCEG; - delete beforeCurveCEG; - delete afterCurveCEG; +BlackWhite::~BlackWhite () +{ + delete luminanceCEG; + delete beforeCurveCEG; + delete afterCurveCEG; } -int BWChangedUI (void* data) { - GThreadLock lock; - (static_cast(data))->BWComputed_ (); - return 0; +int BWChangedUI (void* data) +{ + GThreadLock lock; + (static_cast(data))->BWComputed_ (); + return 0; } -void BlackWhite::BWChanged (double redbw, double greenbw, double bluebw){ - nextredbw = redbw; - nextgreenbw = greenbw; - nextbluebw = bluebw; - g_idle_add (BWChangedUI, this); +void BlackWhite::BWChanged (double redbw, double greenbw, double bluebw) +{ + nextredbw = redbw; + nextgreenbw = greenbw; + nextbluebw = bluebw; + g_idle_add (BWChangedUI, this); } -bool BlackWhite::BWComputed_ () { +bool BlackWhite::BWComputed_ () +{ - disableListener (); - mixerRed->setValue (nextredbw); - mixerGreen->setValue (nextgreenbw); - mixerBlue->setValue (nextbluebw); - enableListener (); + disableListener (); + mixerRed->setValue (nextredbw); + mixerGreen->setValue (nextgreenbw); + mixerBlue->setValue (nextbluebw); + enableListener (); - updateRGBLabel(); + updateRGBLabel(); - return false; + return false; } -void BlackWhite::read (const ProcParams* pp, const ParamsEdited* pedited) { +void BlackWhite::read (const ProcParams* pp, const ParamsEdited* pedited) +{ - disableListener (); - methodconn.block(true); - //autoconn.block (true); - filterconn.block(true); - settingconn.block(true); - enaccconn.block (true); + disableListener (); + methodconn.block(true); + //autoconn.block (true); + filterconn.block(true); + settingconn.block(true); + enaccconn.block (true); - if (pedited && !pedited->blackwhite.setting) - setting->set_active (15); // "Unchanged" - else if (pp->blackwhite.setting=="NormalContrast") - setting->set_active (0); - else if (pp->blackwhite.setting=="HighContrast") - setting->set_active (1); - else if (pp->blackwhite.setting=="Luminance") - setting->set_active (2); - else if (pp->blackwhite.setting=="Landscape") - setting->set_active (3); - else if (pp->blackwhite.setting=="Portrait") - setting->set_active (4); - else if (pp->blackwhite.setting=="LowSensitivity") - setting->set_active (5); - else if (pp->blackwhite.setting=="HighSensitivity") - setting->set_active (6); - else if (pp->blackwhite.setting=="Panchromatic") - setting->set_active (7); - else if (pp->blackwhite.setting=="HyperPanchromatic") - setting->set_active (8); - else if (pp->blackwhite.setting=="Orthochromatic") - setting->set_active (9); - else if (pp->blackwhite.setting=="RGB-Abs") - setting->set_active (10); - else if (pp->blackwhite.setting=="RGB-Rel") - setting->set_active (11); - else if (pp->blackwhite.setting=="ROYGCBPM-Abs") - setting->set_active (12); - else if (pp->blackwhite.setting=="ROYGCBPM-Rel") - setting->set_active (13); - else if (pp->blackwhite.setting=="InfraRed") - setting->set_active (14); - settingChanged(); + if (pedited && !pedited->blackwhite.setting) { + setting->set_active (15); // "Unchanged" + } else if (pp->blackwhite.setting == "NormalContrast") { + setting->set_active (0); + } else if (pp->blackwhite.setting == "HighContrast") { + setting->set_active (1); + } else if (pp->blackwhite.setting == "Luminance") { + setting->set_active (2); + } else if (pp->blackwhite.setting == "Landscape") { + setting->set_active (3); + } else if (pp->blackwhite.setting == "Portrait") { + setting->set_active (4); + } else if (pp->blackwhite.setting == "LowSensitivity") { + setting->set_active (5); + } else if (pp->blackwhite.setting == "HighSensitivity") { + setting->set_active (6); + } else if (pp->blackwhite.setting == "Panchromatic") { + setting->set_active (7); + } else if (pp->blackwhite.setting == "HyperPanchromatic") { + setting->set_active (8); + } else if (pp->blackwhite.setting == "Orthochromatic") { + setting->set_active (9); + } else if (pp->blackwhite.setting == "RGB-Abs") { + setting->set_active (10); + } else if (pp->blackwhite.setting == "RGB-Rel") { + setting->set_active (11); + } else if (pp->blackwhite.setting == "ROYGCBPM-Abs") { + setting->set_active (12); + } else if (pp->blackwhite.setting == "ROYGCBPM-Rel") { + setting->set_active (13); + } else if (pp->blackwhite.setting == "InfraRed") { + setting->set_active (14); + } + + settingChanged(); - if (pedited && !pedited->blackwhite.method) - method->set_active (3); // "Unchanged" - else if (pp->blackwhite.method=="Desaturation") - method->set_active (0); - else if (pp->blackwhite.method=="LumEqualizer") - method->set_active (1); - else if (pp->blackwhite.method=="ChannelMixer") - method->set_active (2); - methodChanged(); + if (pedited && !pedited->blackwhite.method) { + method->set_active (3); // "Unchanged" + } else if (pp->blackwhite.method == "Desaturation") { + method->set_active (0); + } else if (pp->blackwhite.method == "LumEqualizer") { + method->set_active (1); + } else if (pp->blackwhite.method == "ChannelMixer") { + method->set_active (2); + } - - if (pedited && !pedited->blackwhite.filter) - filter->set_active (9); // "Unchanged" - else if (pp->blackwhite.filter=="None") - filter->set_active (0); - else if (pp->blackwhite.filter=="Red") - filter->set_active (1); - else if (pp->blackwhite.filter=="Orange") - filter->set_active (2); - else if (pp->blackwhite.filter=="Yellow") - filter->set_active (3); - else if (pp->blackwhite.filter=="YellowGreen") - filter->set_active (4); - else if (pp->blackwhite.filter=="Green") - filter->set_active (5); - else if (pp->blackwhite.filter=="Cyan") - filter->set_active (6); - else if (pp->blackwhite.filter=="Blue") - filter->set_active (7); - else if (pp->blackwhite.filter=="Purple") - filter->set_active (8); - filterChanged(); + methodChanged(); - enabledcc->set_active (pp->blackwhite.enabledcc); - lastEnabledcc = pp->blackwhite.enabledcc; - setEnabled (pp->blackwhite.enabled); - mixerRed->setValue (pp->blackwhite.mixerRed); - mixerGreen->setValue (pp->blackwhite.mixerGreen); - mixerBlue->setValue (pp->blackwhite.mixerBlue); - gammaRed->setValue (pp->blackwhite.gammaRed); - gammaGreen->setValue (pp->blackwhite.gammaGreen); - gammaBlue->setValue (pp->blackwhite.gammaBlue); - mixerOrange->setValue (pp->blackwhite.mixerOrange); - mixerYellow->setValue (pp->blackwhite.mixerYellow); - mixerCyan->setValue (pp->blackwhite.mixerCyan); - mixerMagenta->setValue (pp->blackwhite.mixerMagenta); - mixerPurple->setValue (pp->blackwhite.mixerPurple); - luminanceCurve->setCurve (pp->blackwhite.luminanceCurve); - beforeCurve->setCurve (pp->blackwhite.beforeCurve); - beforeCurveMode->set_active(pp->blackwhite.beforeCurveMode); - afterCurve->setCurve (pp->blackwhite.afterCurve); -// afterCurveMode->set_active(pp->blackwhite.afterCurveMode); + if (pedited && !pedited->blackwhite.filter) { + filter->set_active (9); // "Unchanged" + } else if (pp->blackwhite.filter == "None") { + filter->set_active (0); + } else if (pp->blackwhite.filter == "Red") { + filter->set_active (1); + } else if (pp->blackwhite.filter == "Orange") { + filter->set_active (2); + } else if (pp->blackwhite.filter == "Yellow") { + filter->set_active (3); + } else if (pp->blackwhite.filter == "YellowGreen") { + filter->set_active (4); + } else if (pp->blackwhite.filter == "Green") { + filter->set_active (5); + } else if (pp->blackwhite.filter == "Cyan") { + filter->set_active (6); + } else if (pp->blackwhite.filter == "Blue") { + filter->set_active (7); + } else if (pp->blackwhite.filter == "Purple") { + filter->set_active (8); + } - autoch->set_active (pp->blackwhite.autoc); - lastAuto = pp->blackwhite.autoc; + filterChanged(); - algoconn.block(true); - if (pedited && !pedited->blackwhite.algo) - algo->set_active (2); - else if (pp->blackwhite.algo=="LI") - algo->set_active (0); - else if (pp->blackwhite.algo=="SP") - algo->set_active (1); - algoconn.block(false); - algoChanged(); - - - if (pedited) { - luminanceCurve->setUnChanged (!pedited->blackwhite.luminanceCurve); - beforeCurve->setUnChanged (!pedited->blackwhite.beforeCurve); - afterCurve->setUnChanged (!pedited->blackwhite.afterCurve); - autoch->set_inconsistent (!pedited->blackwhite.autoc); - set_inconsistent (multiImage && !pedited->blackwhite.enabled); - enabledcc->set_inconsistent (!pedited->blackwhite.enabledcc); - mixerRed->setEditedState (pedited->blackwhite.mixerRed ? Edited : UnEdited); - mixerGreen->setEditedState (pedited->blackwhite.mixerGreen ? Edited : UnEdited); - mixerBlue->setEditedState (pedited->blackwhite.mixerBlue ? Edited : UnEdited); - gammaRed->setEditedState (pedited->blackwhite.gammaRed ? Edited : UnEdited); - gammaGreen->setEditedState (pedited->blackwhite.gammaGreen ? Edited : UnEdited); - gammaBlue->setEditedState (pedited->blackwhite.gammaBlue ? Edited : UnEdited); - mixerOrange->setEditedState (pedited->blackwhite.mixerOrange ? Edited : UnEdited); - mixerYellow->setEditedState (pedited->blackwhite.mixerYellow ? Edited : UnEdited); - mixerCyan->setEditedState (pedited->blackwhite.mixerCyan ? Edited : UnEdited); - mixerMagenta->setEditedState (pedited->blackwhite.mixerMagenta ? Edited : UnEdited); - mixerPurple->setEditedState (pedited->blackwhite.mixerPurple ? Edited : UnEdited); - if (!pedited->blackwhite.beforeCurveMode) { - beforeCurveMode->set_active(4); // "Unchanged" - } -// if (!pedited->blackwhite.afterCurveMode) { -// afterCurveMode->set_active(1); // "Unchanged" -// } - } - methodconn.block(false); - filterconn.block(false); - settingconn.block(false); - //autoconn.block (false); - enaccconn.block (false); + enabledcc->set_active (pp->blackwhite.enabledcc); + lastEnabledcc = pp->blackwhite.enabledcc; + setEnabled (pp->blackwhite.enabled); - updateRGBLabel(); + mixerRed->setValue (pp->blackwhite.mixerRed); + mixerGreen->setValue (pp->blackwhite.mixerGreen); + mixerBlue->setValue (pp->blackwhite.mixerBlue); + gammaRed->setValue (pp->blackwhite.gammaRed); + gammaGreen->setValue (pp->blackwhite.gammaGreen); + gammaBlue->setValue (pp->blackwhite.gammaBlue); + mixerOrange->setValue (pp->blackwhite.mixerOrange); + mixerYellow->setValue (pp->blackwhite.mixerYellow); + mixerCyan->setValue (pp->blackwhite.mixerCyan); + mixerMagenta->setValue (pp->blackwhite.mixerMagenta); + mixerPurple->setValue (pp->blackwhite.mixerPurple); + luminanceCurve->setCurve (pp->blackwhite.luminanceCurve); + beforeCurve->setCurve (pp->blackwhite.beforeCurve); + beforeCurveMode->set_active(pp->blackwhite.beforeCurveMode); + afterCurve->setCurve (pp->blackwhite.afterCurve); +// afterCurveMode->set_active(pp->blackwhite.afterCurveMode); - enableListener (); + autoch->set_active (pp->blackwhite.autoc); + lastAuto = pp->blackwhite.autoc; + + algoconn.block(true); + + if (pedited && !pedited->blackwhite.algo) { + algo->set_active (2); + } else if (pp->blackwhite.algo == "LI") { + algo->set_active (0); + } else if (pp->blackwhite.algo == "SP") { + algo->set_active (1); + } + + algoconn.block(false); + algoChanged(); + + + if (pedited) { + luminanceCurve->setUnChanged (!pedited->blackwhite.luminanceCurve); + beforeCurve->setUnChanged (!pedited->blackwhite.beforeCurve); + afterCurve->setUnChanged (!pedited->blackwhite.afterCurve); + autoch->set_inconsistent (!pedited->blackwhite.autoc); + set_inconsistent (multiImage && !pedited->blackwhite.enabled); + enabledcc->set_inconsistent (!pedited->blackwhite.enabledcc); + mixerRed->setEditedState (pedited->blackwhite.mixerRed ? Edited : UnEdited); + mixerGreen->setEditedState (pedited->blackwhite.mixerGreen ? Edited : UnEdited); + mixerBlue->setEditedState (pedited->blackwhite.mixerBlue ? Edited : UnEdited); + gammaRed->setEditedState (pedited->blackwhite.gammaRed ? Edited : UnEdited); + gammaGreen->setEditedState (pedited->blackwhite.gammaGreen ? Edited : UnEdited); + gammaBlue->setEditedState (pedited->blackwhite.gammaBlue ? Edited : UnEdited); + mixerOrange->setEditedState (pedited->blackwhite.mixerOrange ? Edited : UnEdited); + mixerYellow->setEditedState (pedited->blackwhite.mixerYellow ? Edited : UnEdited); + mixerCyan->setEditedState (pedited->blackwhite.mixerCyan ? Edited : UnEdited); + mixerMagenta->setEditedState (pedited->blackwhite.mixerMagenta ? Edited : UnEdited); + mixerPurple->setEditedState (pedited->blackwhite.mixerPurple ? Edited : UnEdited); + + if (!pedited->blackwhite.beforeCurveMode) { + beforeCurveMode->set_active(4); // "Unchanged" + } + +// if (!pedited->blackwhite.afterCurveMode) { +// afterCurveMode->set_active(1); // "Unchanged" +// } + } + + methodconn.block(false); + filterconn.block(false); + settingconn.block(false); + //autoconn.block (false); + enaccconn.block (false); + + updateRGBLabel(); + + enableListener (); } -void BlackWhite::write (ProcParams* pp, ParamsEdited* pedited) { - pp->blackwhite.enabled = getEnabled(); - pp->blackwhite.luminanceCurve = luminanceCurve->getCurve (); - pp->blackwhite.autoc = autoch->get_active(); - pp->blackwhite.enabledcc = enabledcc->get_active (); - pp->blackwhite.mixerRed = mixerRed->getValue (); - pp->blackwhite.mixerGreen = mixerGreen->getValue (); - pp->blackwhite.mixerBlue = mixerBlue->getValue (); - pp->blackwhite.gammaRed = gammaRed->getValue (); - pp->blackwhite.gammaGreen = gammaGreen->getValue (); - pp->blackwhite.gammaBlue = gammaBlue->getValue (); - pp->blackwhite.mixerOrange = mixerOrange->getValue (); - pp->blackwhite.mixerYellow = mixerYellow->getValue (); - pp->blackwhite.mixerCyan = mixerCyan->getValue (); - pp->blackwhite.mixerMagenta = mixerMagenta->getValue (); - pp->blackwhite.mixerPurple = mixerPurple->getValue (); - pp->blackwhite.beforeCurve = beforeCurve->getCurve (); - pp->blackwhite.afterCurve = afterCurve->getCurve (); +void BlackWhite::write (ProcParams* pp, ParamsEdited* pedited) +{ + pp->blackwhite.enabled = getEnabled(); + pp->blackwhite.luminanceCurve = luminanceCurve->getCurve (); + pp->blackwhite.autoc = autoch->get_active(); + pp->blackwhite.enabledcc = enabledcc->get_active (); + pp->blackwhite.mixerRed = mixerRed->getValue (); + pp->blackwhite.mixerGreen = mixerGreen->getValue (); + pp->blackwhite.mixerBlue = mixerBlue->getValue (); + pp->blackwhite.gammaRed = gammaRed->getValue (); + pp->blackwhite.gammaGreen = gammaGreen->getValue (); + pp->blackwhite.gammaBlue = gammaBlue->getValue (); + pp->blackwhite.mixerOrange = mixerOrange->getValue (); + pp->blackwhite.mixerYellow = mixerYellow->getValue (); + pp->blackwhite.mixerCyan = mixerCyan->getValue (); + pp->blackwhite.mixerMagenta = mixerMagenta->getValue (); + pp->blackwhite.mixerPurple = mixerPurple->getValue (); + pp->blackwhite.beforeCurve = beforeCurve->getCurve (); + pp->blackwhite.afterCurve = afterCurve->getCurve (); - int tcMode = beforeCurveMode->get_active_row_number(); - if (tcMode == 0) pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_STD_BW; - else if (tcMode == 1) pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW; - else if (tcMode == 2) pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_FILMLIKE_BW; - else if (tcMode == 3) pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW; + int tcMode = beforeCurveMode->get_active_row_number(); -// tcMode = afterCurveMode->get_active_row_number(); -// if (tcMode == 0) pp->blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_STD_BW; - // else if (tcMode == 1) pp->blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD; - - if (pedited) { - pedited->blackwhite.enabled = !get_inconsistent(); - pedited->blackwhite.luminanceCurve = !luminanceCurve->isUnChanged (); - pedited->blackwhite.autoc = !autoch->get_inconsistent(); - pedited->blackwhite.enabledcc = !enabledcc->get_inconsistent(); - pedited->blackwhite.mixerRed = mixerRed->getEditedState (); - pedited->blackwhite.mixerGreen = mixerGreen->getEditedState (); - pedited->blackwhite.mixerBlue = mixerBlue->getEditedState (); - pedited->blackwhite.gammaRed = gammaRed->getEditedState (); - pedited->blackwhite.gammaGreen = gammaGreen->getEditedState (); - pedited->blackwhite.gammaBlue = gammaBlue->getEditedState (); - pedited->blackwhite.filter = filter->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->blackwhite.setting = setting->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->blackwhite.method = method->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->blackwhite.mixerOrange = mixerOrange->getEditedState (); - pedited->blackwhite.mixerYellow = mixerYellow->getEditedState (); - pedited->blackwhite.mixerCyan = mixerCyan->getEditedState (); - pedited->blackwhite.mixerMagenta = mixerMagenta->getEditedState (); - pedited->blackwhite.mixerPurple = mixerPurple->getEditedState (); - pedited->blackwhite.beforeCurve = !beforeCurve->isUnChanged (); - pedited->blackwhite.beforeCurveMode = beforeCurveMode->get_active_row_number() != 4; - pedited->blackwhite.afterCurve = !afterCurve->isUnChanged (); - pedited->blackwhite.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); - -// pedited->blackwhite.afterCurveMode = afterCurveMode->get_active_row_number() != 1; - } - if (method->get_active_row_number()==0) - pp->blackwhite.method = "Desaturation"; - else if (method->get_active_row_number()==1) - pp->blackwhite.method = "LumEqualizer"; - else if (method->get_active_row_number()==2) - pp->blackwhite.method = "ChannelMixer"; + if (tcMode == 0) { + pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_STD_BW; + } else if (tcMode == 1) { + pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD_BW; + } else if (tcMode == 2) { + pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_FILMLIKE_BW; + } else if (tcMode == 3) { + pp->blackwhite.beforeCurveMode = BlackWhiteParams::TC_MODE_SATANDVALBLENDING_BW; + } - if (algo->get_active_row_number()==0) - pp->blackwhite.algo = "LI"; - else if (algo->get_active_row_number()==1) - pp->blackwhite.algo = "SP"; - - pp->blackwhite.setting = getSettingString(); - pp->blackwhite.filter = getFilterString(); +// tcMode = afterCurveMode->get_active_row_number(); +// if (tcMode == 0) pp->blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_STD_BW; + // else if (tcMode == 1) pp->blackwhite.afterCurveMode = BlackWhiteParams::TC_MODE_WEIGHTEDSTD; + + if (pedited) { + pedited->blackwhite.enabled = !get_inconsistent(); + pedited->blackwhite.luminanceCurve = !luminanceCurve->isUnChanged (); + pedited->blackwhite.autoc = !autoch->get_inconsistent(); + pedited->blackwhite.enabledcc = !enabledcc->get_inconsistent(); + pedited->blackwhite.mixerRed = mixerRed->getEditedState (); + pedited->blackwhite.mixerGreen = mixerGreen->getEditedState (); + pedited->blackwhite.mixerBlue = mixerBlue->getEditedState (); + pedited->blackwhite.gammaRed = gammaRed->getEditedState (); + pedited->blackwhite.gammaGreen = gammaGreen->getEditedState (); + pedited->blackwhite.gammaBlue = gammaBlue->getEditedState (); + pedited->blackwhite.filter = filter->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->blackwhite.setting = setting->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->blackwhite.method = method->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->blackwhite.mixerOrange = mixerOrange->getEditedState (); + pedited->blackwhite.mixerYellow = mixerYellow->getEditedState (); + pedited->blackwhite.mixerCyan = mixerCyan->getEditedState (); + pedited->blackwhite.mixerMagenta = mixerMagenta->getEditedState (); + pedited->blackwhite.mixerPurple = mixerPurple->getEditedState (); + pedited->blackwhite.beforeCurve = !beforeCurve->isUnChanged (); + pedited->blackwhite.beforeCurveMode = beforeCurveMode->get_active_row_number() != 4; + pedited->blackwhite.afterCurve = !afterCurve->isUnChanged (); + pedited->blackwhite.algo = algo->get_active_text() != M("GENERAL_UNCHANGED"); + +// pedited->blackwhite.afterCurveMode = afterCurveMode->get_active_row_number() != 1; + } + + if (method->get_active_row_number() == 0) { + pp->blackwhite.method = "Desaturation"; + } else if (method->get_active_row_number() == 1) { + pp->blackwhite.method = "LumEqualizer"; + } else if (method->get_active_row_number() == 2) { + pp->blackwhite.method = "ChannelMixer"; + } + + if (algo->get_active_row_number() == 0) { + pp->blackwhite.algo = "LI"; + } else if (algo->get_active_row_number() == 1) { + pp->blackwhite.algo = "SP"; + } + + pp->blackwhite.setting = getSettingString(); + pp->blackwhite.filter = getFilterString(); } -void BlackWhite::algoChanged () { - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvBWMethodalg, algo->get_active_text ());} +void BlackWhite::algoChanged () +{ + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvBWMethodalg, algo->get_active_text ()); + } } -void BlackWhite::curveChanged (CurveEditor* ce) { - if (listener) { - if (ce == beforeCurve) - listener->panelChanged (EvBWBeforeCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == afterCurve) - listener->panelChanged (EvBWAfterCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == luminanceCurve) - listener->panelChanged (EvBWLuminanceEqual, M("HISTORY_CUSTOMCURVE")); - } +void BlackWhite::curveChanged (CurveEditor* ce) +{ + if (listener) { + if (ce == beforeCurve) { + listener->panelChanged (EvBWBeforeCurve, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == afterCurve) { + listener->panelChanged (EvBWAfterCurve, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == luminanceCurve) { + listener->panelChanged (EvBWLuminanceEqual, M("HISTORY_CUSTOMCURVE")); + } + } } -void BlackWhite::curveMode1Changed () { - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &BlackWhite::curveMode1Changed_)); +void BlackWhite::curveMode1Changed () +{ + if (listener) { + Glib::signal_idle().connect (sigc::mem_fun(*this, &BlackWhite::curveMode1Changed_)); + } } -bool BlackWhite::curveMode1Changed_ () { - if (listener) listener->panelChanged (EvBWBeforeCurveMode, escapeHtmlChars(beforeCurveMode->get_active_text())); - return false; +bool BlackWhite::curveMode1Changed_ () +{ + if (listener) { + listener->panelChanged (EvBWBeforeCurveMode, escapeHtmlChars(beforeCurveMode->get_active_text())); + } + + return false; } /* void BlackWhite::curveMode1Changed2 () { - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &BlackWhite::curveMode1Changed2_)); + if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &BlackWhite::curveMode1Changed2_)); } bool BlackWhite::curveMode1Changed2_ () { - if (listener) listener->panelChanged (EvBWAfterCurveMode, escapeHtmlChars(afterCurveMode->get_active_text())); - return false; + if (listener) listener->panelChanged (EvBWAfterCurveMode, escapeHtmlChars(afterCurveMode->get_active_text())); + return false; } */ -void BlackWhite::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) { +void BlackWhite::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) +{ - float r, g, b; + float r, g, b; - if (elemType == ColorCaller::CCET_VERTICAL_BAR) - valY = 0.5f; + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5f; + } - if (callerId == 1) { // Hue = f(Hue) + if (callerId == 1) { // Hue = f(Hue) - float h = float((valY - 0.5) * 2. + valX); - if (h > 1.0f) - h -= 1.0f; - else if (h < 0.0f) - h += 1.0f; - Color::hsv2rgb01(h, 0.5f, 0.5f, r, g, b); - caller->ccRed = double(r); - caller->ccGreen = double(g); - caller->ccBlue = double(b); - } - else if (callerId == 2) { // Saturation = f(Hue) - Color::hsv2rgb01(float(valX), float(valY), 0.5f, r, g, b); - caller->ccRed = double(r); - caller->ccGreen = double(g); - caller->ccBlue = double(b); - } - else if (callerId == 3) { // Value = f(Hue) - Color::hsv2rgb01(float(valX), 0.5f, float(valY), r, g, b); - caller->ccRed = double(r); - caller->ccGreen = double(g); - caller->ccBlue = double(b); - } - else { - printf("Error: no curve displayed!\n"); - } + float h = float((valY - 0.5) * 2. + valX); + + if (h > 1.0f) { + h -= 1.0f; + } else if (h < 0.0f) { + h += 1.0f; + } + + Color::hsv2rgb01(h, 0.5f, 0.5f, r, g, b); + caller->ccRed = double(r); + caller->ccGreen = double(g); + caller->ccBlue = double(b); + } else if (callerId == 2) { // Saturation = f(Hue) + Color::hsv2rgb01(float(valX), float(valY), 0.5f, r, g, b); + caller->ccRed = double(r); + caller->ccGreen = double(g); + caller->ccBlue = double(b); + } else if (callerId == 3) { // Value = f(Hue) + Color::hsv2rgb01(float(valX), 0.5f, float(valY), r, g, b); + caller->ccRed = double(r); + caller->ccGreen = double(g); + caller->ccBlue = double(b); + } else { + printf("Error: no curve displayed!\n"); + } } -void BlackWhite::settingChanged () { +void BlackWhite::settingChanged () +{ - if ( setting->get_active_row_number()==10 || setting->get_active_row_number()==11 ) { - // RGB Channel Mixer - showMixer(3); - hideEnabledCC(); - showFilter(); - } - else if ( setting->get_active_row_number()==12 || setting->get_active_row_number()==13 ) { - // ROYGCBPM Channel Mixer - showMixer(7); - showEnabledCC(); - showFilter(); - } - else if ( setting->get_active_row_number()==14 ) { - // Infrared - filter->set_active (0); - showMixer(3, false); - hideEnabledCC(); - hideFilter(); - } - else { - // RGB Presets - showMixer(3, false); - hideEnabledCC(); - showFilter(); - } + if ( setting->get_active_row_number() == 10 || setting->get_active_row_number() == 11 ) { + // RGB Channel Mixer + showMixer(3); + hideEnabledCC(); + showFilter(); + } else if ( setting->get_active_row_number() == 12 || setting->get_active_row_number() == 13 ) { + // ROYGCBPM Channel Mixer + showMixer(7); + showEnabledCC(); + showFilter(); + } else if ( setting->get_active_row_number() == 14 ) { + // Infrared + filter->set_active (0); + showMixer(3, false); + hideEnabledCC(); + hideFilter(); + } else { + // RGB Presets + showMixer(3, false); + hideEnabledCC(); + showFilter(); + } - // Checking "listener" to avoid "autoch" getting toggled off because it has to change the sliders when toggling on - if (listener){ - if (multiImage && autoch->get_inconsistent()) - autoch->set_inconsistent (false); - autoconn.block(true); - autoch->set_active (false); - autoconn.block(false); - lastAuto = false; - } + // Checking "listener" to avoid "autoch" getting toggled off because it has to change the sliders when toggling on + if (listener) { + if (multiImage && autoch->get_inconsistent()) { + autoch->set_inconsistent (false); + } - updateRGBLabel(); + autoconn.block(true); + autoch->set_active (false); + autoconn.block(false); + lastAuto = false; + } - if (listener && (multiImage||getEnabled())) { - listener->panelChanged (EvBWsetting, setting->get_active_text ()); - } + updateRGBLabel(); + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged (EvBWsetting, setting->get_active_text ()); + } } -void BlackWhite::filterChanged () { - // Checking "listener" to avoid "autoch" getting toggled off because it has to change the sliders when toggling on - if (listener){ - if (multiImage && autoch->get_inconsistent()) - autoch->set_inconsistent (false); - autoconn.block(true); - autoch->set_active (false); - autoconn.block(false); - lastAuto = false; - } +void BlackWhite::filterChanged () +{ + // Checking "listener" to avoid "autoch" getting toggled off because it has to change the sliders when toggling on + if (listener) { + if (multiImage && autoch->get_inconsistent()) { + autoch->set_inconsistent (false); + } - updateRGBLabel(); + autoconn.block(true); + autoch->set_active (false); + autoconn.block(false); + lastAuto = false; + } - if (listener && (multiImage||getEnabled())) { - listener->panelChanged (EvBWfilter, filter->get_active_text ()); - } + updateRGBLabel(); + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged (EvBWfilter, filter->get_active_text ()); + } } -void BlackWhite::methodChanged () { - if(method->get_active_row_number()==2) { - // Channel Mixer - hideLuminance(); +void BlackWhite::methodChanged () +{ + if(method->get_active_row_number() == 2) { + // Channel Mixer + hideLuminance(); - if(setting->get_active_row_number()==10 || setting->get_active_row_number()==11){ - hideEnabledCC(); - showMixer(3); - } - else if(setting->get_active_row_number()==12 || setting->get_active_row_number()==13) { - showEnabledCC(); - showMixer(7); - } - else { - hideEnabledCC(); - showMixer(3, false); - } - beforeCurveCEG->show(); - afterCurveCEG->show(); + if(setting->get_active_row_number() == 10 || setting->get_active_row_number() == 11) { + hideEnabledCC(); + showMixer(3); + } else if(setting->get_active_row_number() == 12 || setting->get_active_row_number() == 13) { + showEnabledCC(); + showMixer(7); + } else { + hideEnabledCC(); + showMixer(3, false); + } - bool wasEnabled = disableListener(); - settingChanged(); - if (wasEnabled) enableListener(); - } - else if(method->get_active_row_number()==1) { - // Luminance Equalizer - showLuminance(); - hideMixer(); - beforeCurveCEG->show(); - afterCurveCEG->show(); - } - else if(method->get_active_row_number()==0) { - // Desaturation - hideLuminance(); - hideMixer(); - beforeCurveCEG->show(); - afterCurveCEG->show(); - } - if (listener && (multiImage||getEnabled())) { - listener->panelChanged (EvBWmethod, method->get_active_text ()); - } + beforeCurveCEG->show(); + afterCurveCEG->show(); + + bool wasEnabled = disableListener(); + settingChanged(); + + if (wasEnabled) { + enableListener(); + } + } else if(method->get_active_row_number() == 1) { + // Luminance Equalizer + showLuminance(); + hideMixer(); + beforeCurveCEG->show(); + afterCurveCEG->show(); + } else if(method->get_active_row_number() == 0) { + // Desaturation + hideLuminance(); + hideMixer(); + beforeCurveCEG->show(); + afterCurveCEG->show(); + } + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged (EvBWmethod, method->get_active_text ()); + } } -void BlackWhite::enabledChanged () { - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvBWChmixEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvBWChmixEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvBWChmixEnabled, M("GENERAL_DISABLED")); - } +void BlackWhite::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvBWChmixEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvBWChmixEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvBWChmixEnabled, M("GENERAL_DISABLED")); + } + } } -void BlackWhite::neutral_pressed () { - // This method deselects auto chmixer and sets "neutral" values to params - disableListener(); +void BlackWhite::neutral_pressed () +{ + // This method deselects auto chmixer and sets "neutral" values to params + disableListener(); - if (multiImage && autoch->get_inconsistent()) - autoch->set_inconsistent (false); - autoconn.block(true); - autoch->set_active (false); - autoconn.block(false); - lastAuto = false; + if (multiImage && autoch->get_inconsistent()) { + autoch->set_inconsistent (false); + } - int activeSetting = setting->get_active_row_number(); - if (activeSetting < 10 || activeSetting > 13) - setting->set_active (11); - filter->set_active (0); - mixerRed->resetValue(false); - mixerGreen->resetValue(false); - mixerBlue->resetValue(false); - mixerOrange->resetValue(false); - mixerYellow->resetValue(false); - mixerMagenta->resetValue(false); - mixerPurple->resetValue(false); - mixerCyan->resetValue(false); + autoconn.block(true); + autoch->set_active (false); + autoconn.block(false); + lastAuto = false; - enableListener(); + int activeSetting = setting->get_active_row_number(); - updateRGBLabel(); + if (activeSetting < 10 || activeSetting > 13) { + setting->set_active (11); + } - listener->panelChanged (EvNeutralBW, M("ADJUSTER_RESET_TO_DEFAULT")); + filter->set_active (0); + mixerRed->resetValue(false); + mixerGreen->resetValue(false); + mixerBlue->resetValue(false); + mixerOrange->resetValue(false); + mixerYellow->resetValue(false); + mixerMagenta->resetValue(false); + mixerPurple->resetValue(false); + mixerCyan->resetValue(false); + + enableListener(); + + updateRGBLabel(); + + listener->panelChanged (EvNeutralBW, M("ADJUSTER_RESET_TO_DEFAULT")); } -void BlackWhite::enabledcc_toggled () { +void BlackWhite::enabledcc_toggled () +{ - // toggling off the Complementary Colors does switch off the Auto button - if (multiImage) { - // multiple image editing (batch) - if (enabledcc->get_inconsistent()) { - enabledcc->set_inconsistent (false); // set consistent - enaccconn.block (true); - enabledcc->set_active (false); // ... and deactivated - enaccconn.block (false); - } - else if (lastEnabledcc) - enabledcc->set_inconsistent (true); + // toggling off the Complementary Colors does switch off the Auto button + if (multiImage) { + // multiple image editing (batch) + if (enabledcc->get_inconsistent()) { + enabledcc->set_inconsistent (false); // set consistent + enaccconn.block (true); + enabledcc->set_active (false); // ... and deactivated + enaccconn.block (false); + } else if (lastEnabledcc) { + enabledcc->set_inconsistent (true); + } - lastEnabledcc = enabledcc->get_active (); - } + lastEnabledcc = enabledcc->get_active (); + } - if (multiImage && autoch->get_inconsistent()) - autoch->set_inconsistent (false); - autoconn.block(true); - autoch->set_active (false); - autoconn.block(false); - lastAuto = false; + if (multiImage && autoch->get_inconsistent()) { + autoch->set_inconsistent (false); + } - updateRGBLabel(); + autoconn.block(true); + autoch->set_active (false); + autoconn.block(false); + lastAuto = false; - if (listener) { - if (enabledcc->get_inconsistent()) - listener->panelChanged (EvBWChmixEnabledLm, M("GENERAL_UNCHANGED")); - else if (enabledcc->get_active ()) { - listener->panelChanged (EvBWChmixEnabledLm, M("GENERAL_ENABLED")); - } - else { - listener->panelChanged (EvBWChmixEnabledLm, M("GENERAL_DISABLED")); - } - } + updateRGBLabel(); + + if (listener) { + if (enabledcc->get_inconsistent()) { + listener->panelChanged (EvBWChmixEnabledLm, M("GENERAL_UNCHANGED")); + } else if (enabledcc->get_active ()) { + listener->panelChanged (EvBWChmixEnabledLm, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvBWChmixEnabledLm, M("GENERAL_DISABLED")); + } + } } -void BlackWhite::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void BlackWhite::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ - mixerRed->setDefault (defParams->blackwhite.mixerRed); - mixerGreen->setDefault (defParams->blackwhite.mixerGreen); - mixerBlue->setDefault (defParams->blackwhite.mixerBlue); - gammaRed->setDefault (defParams->blackwhite.gammaRed); - gammaGreen->setDefault (defParams->blackwhite.gammaGreen); - gammaBlue->setDefault (defParams->blackwhite.gammaBlue); - mixerOrange->setDefault (defParams->blackwhite.mixerOrange); - mixerYellow->setDefault (defParams->blackwhite.mixerYellow); - mixerCyan->setDefault (defParams->blackwhite.mixerCyan); - mixerMagenta->setDefault (defParams->blackwhite.mixerMagenta); - mixerPurple->setDefault (defParams->blackwhite.mixerPurple); + mixerRed->setDefault (defParams->blackwhite.mixerRed); + mixerGreen->setDefault (defParams->blackwhite.mixerGreen); + mixerBlue->setDefault (defParams->blackwhite.mixerBlue); + gammaRed->setDefault (defParams->blackwhite.gammaRed); + gammaGreen->setDefault (defParams->blackwhite.gammaGreen); + gammaBlue->setDefault (defParams->blackwhite.gammaBlue); + mixerOrange->setDefault (defParams->blackwhite.mixerOrange); + mixerYellow->setDefault (defParams->blackwhite.mixerYellow); + mixerCyan->setDefault (defParams->blackwhite.mixerCyan); + mixerMagenta->setDefault (defParams->blackwhite.mixerMagenta); + mixerPurple->setDefault (defParams->blackwhite.mixerPurple); - if (pedited) { - mixerRed->setDefaultEditedState (pedited->blackwhite.mixerRed ? Edited : UnEdited); - mixerGreen->setDefaultEditedState (pedited->blackwhite.mixerGreen ? Edited : UnEdited); - mixerBlue->setDefaultEditedState (pedited->blackwhite.mixerBlue ? Edited : UnEdited); - gammaRed->setDefaultEditedState (pedited->blackwhite.gammaRed ? Edited : UnEdited); - gammaGreen->setDefaultEditedState (pedited->blackwhite.gammaGreen ? Edited : UnEdited); - gammaBlue->setDefaultEditedState (pedited->blackwhite.gammaBlue ? Edited : UnEdited); - mixerOrange->setDefaultEditedState (pedited->blackwhite.mixerOrange ? Edited : UnEdited); - mixerYellow->setDefaultEditedState (pedited->blackwhite.mixerYellow ? Edited : UnEdited); - mixerCyan->setDefaultEditedState (pedited->blackwhite.mixerCyan ? Edited : UnEdited); - mixerMagenta->setDefaultEditedState (pedited->blackwhite.mixerMagenta ? Edited : UnEdited); - mixerPurple->setDefaultEditedState (pedited->blackwhite.mixerPurple ? Edited : UnEdited); - } - else { - mixerRed->setDefaultEditedState (Irrelevant); - mixerGreen->setDefaultEditedState (Irrelevant); - mixerBlue->setDefaultEditedState (Irrelevant); - gammaRed->setDefaultEditedState (Irrelevant); - gammaGreen->setDefaultEditedState (Irrelevant); - gammaBlue->setDefaultEditedState (Irrelevant); - mixerOrange->setDefaultEditedState (Irrelevant); - mixerYellow->setDefaultEditedState (Irrelevant); - mixerCyan->setDefaultEditedState (Irrelevant); - mixerMagenta->setDefaultEditedState (Irrelevant); - mixerPurple->setDefaultEditedState (Irrelevant); - } + if (pedited) { + mixerRed->setDefaultEditedState (pedited->blackwhite.mixerRed ? Edited : UnEdited); + mixerGreen->setDefaultEditedState (pedited->blackwhite.mixerGreen ? Edited : UnEdited); + mixerBlue->setDefaultEditedState (pedited->blackwhite.mixerBlue ? Edited : UnEdited); + gammaRed->setDefaultEditedState (pedited->blackwhite.gammaRed ? Edited : UnEdited); + gammaGreen->setDefaultEditedState (pedited->blackwhite.gammaGreen ? Edited : UnEdited); + gammaBlue->setDefaultEditedState (pedited->blackwhite.gammaBlue ? Edited : UnEdited); + mixerOrange->setDefaultEditedState (pedited->blackwhite.mixerOrange ? Edited : UnEdited); + mixerYellow->setDefaultEditedState (pedited->blackwhite.mixerYellow ? Edited : UnEdited); + mixerCyan->setDefaultEditedState (pedited->blackwhite.mixerCyan ? Edited : UnEdited); + mixerMagenta->setDefaultEditedState (pedited->blackwhite.mixerMagenta ? Edited : UnEdited); + mixerPurple->setDefaultEditedState (pedited->blackwhite.mixerPurple ? Edited : UnEdited); + } else { + mixerRed->setDefaultEditedState (Irrelevant); + mixerGreen->setDefaultEditedState (Irrelevant); + mixerBlue->setDefaultEditedState (Irrelevant); + gammaRed->setDefaultEditedState (Irrelevant); + gammaGreen->setDefaultEditedState (Irrelevant); + gammaBlue->setDefaultEditedState (Irrelevant); + mixerOrange->setDefaultEditedState (Irrelevant); + mixerYellow->setDefaultEditedState (Irrelevant); + mixerCyan->setDefaultEditedState (Irrelevant); + mixerMagenta->setDefaultEditedState (Irrelevant); + mixerPurple->setDefaultEditedState (Irrelevant); + } } -void BlackWhite::autoch_toggled () { +void BlackWhite::autoch_toggled () +{ - if (batchMode) { - if (multiImage) { - if (autoch->get_inconsistent()) { - autoch->set_inconsistent (false); - autoconn.block (true); - autoch->set_active (false); - autoconn.block (false); - } - else if (lastAuto) - autoch->set_inconsistent (true); - } + if (batchMode) { + if (multiImage) { + if (autoch->get_inconsistent()) { + autoch->set_inconsistent (false); + autoconn.block (true); + autoch->set_active (false); + autoconn.block (false); + } else if (lastAuto) { + autoch->set_inconsistent (true); + } + } - lastAuto = autoch->get_active (); + lastAuto = autoch->get_active (); - mixerRed->setEditedState (UnEdited); - mixerGreen->setEditedState (UnEdited); - mixerBlue->setEditedState (UnEdited); - mixerOrange->setEditedState (UnEdited); - mixerYellow->setEditedState (UnEdited); - mixerPurple->setEditedState (UnEdited); - mixerMagenta->setEditedState (UnEdited); - mixerCyan->setEditedState (UnEdited); - - bool wasEnabled = disableListener(); - if (mixerRed->getAddMode()) - mixerRed->resetValue(false); - if (mixerGreen->getAddMode()) - mixerGreen->resetValue(true); - if (mixerBlue->getAddMode()) - mixerBlue->resetValue(true); - if (mixerOrange->getAddMode()) - mixerOrange->resetValue(true); - if (mixerYellow->getAddMode()) - mixerYellow->resetValue(true); - if (mixerMagenta->getAddMode()) - mixerMagenta->resetValue(true); - if (mixerPurple->getAddMode()) - mixerPurple->resetValue(true); - if (mixerCyan->getAddMode()) - mixerCyan->resetValue(true); - setting->set_active (11); - filter->set_active (0); - if (wasEnabled) enableListener(); + mixerRed->setEditedState (UnEdited); + mixerGreen->setEditedState (UnEdited); + mixerBlue->setEditedState (UnEdited); + mixerOrange->setEditedState (UnEdited); + mixerYellow->setEditedState (UnEdited); + mixerPurple->setEditedState (UnEdited); + mixerMagenta->setEditedState (UnEdited); + mixerCyan->setEditedState (UnEdited); - if (listener) { - if (autoch->get_inconsistent()) - listener->panelChanged (EvAutoch, M("GENERAL_UNCHANGED")); - else if (autoch->get_active ()) - listener->panelChanged (EvAutoch, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvAutoch, M("GENERAL_DISABLED")); - } - } - else { - if (autoch->get_active()) { - bool wasEnabled = disableListener(); - mixerRed->setValue(33); - mixerGreen->setValue(33); - mixerBlue->setValue(33); - mixerOrange->setValue(33); - mixerYellow->setValue(33); - mixerMagenta->setValue(33); - mixerPurple->setValue(33); - mixerCyan->setValue(33); - setting->set_active (11); - filter->set_active (0); - if (wasEnabled) enableListener(); + bool wasEnabled = disableListener(); - updateRGBLabel(); + if (mixerRed->getAddMode()) { + mixerRed->resetValue(false); + } - if (listener) - listener->panelChanged (EvAutoch, M("GENERAL_ENABLED")); - } - else { - if (listener) - listener->panelChanged (EvAutoch, M("GENERAL_DISABLED")); - } - } + if (mixerGreen->getAddMode()) { + mixerGreen->resetValue(true); + } + + if (mixerBlue->getAddMode()) { + mixerBlue->resetValue(true); + } + + if (mixerOrange->getAddMode()) { + mixerOrange->resetValue(true); + } + + if (mixerYellow->getAddMode()) { + mixerYellow->resetValue(true); + } + + if (mixerMagenta->getAddMode()) { + mixerMagenta->resetValue(true); + } + + if (mixerPurple->getAddMode()) { + mixerPurple->resetValue(true); + } + + if (mixerCyan->getAddMode()) { + mixerCyan->resetValue(true); + } + + setting->set_active (11); + filter->set_active (0); + + if (wasEnabled) { + enableListener(); + } + + if (listener) { + if (autoch->get_inconsistent()) { + listener->panelChanged (EvAutoch, M("GENERAL_UNCHANGED")); + } else if (autoch->get_active ()) { + listener->panelChanged (EvAutoch, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvAutoch, M("GENERAL_DISABLED")); + } + } + } else { + if (autoch->get_active()) { + bool wasEnabled = disableListener(); + mixerRed->setValue(33); + mixerGreen->setValue(33); + mixerBlue->setValue(33); + mixerOrange->setValue(33); + mixerYellow->setValue(33); + mixerMagenta->setValue(33); + mixerPurple->setValue(33); + mixerCyan->setValue(33); + setting->set_active (11); + filter->set_active (0); + + if (wasEnabled) { + enableListener(); + } + + updateRGBLabel(); + + if (listener) { + listener->panelChanged (EvAutoch, M("GENERAL_ENABLED")); + } + } else { + if (listener) { + listener->panelChanged (EvAutoch, M("GENERAL_DISABLED")); + } + } + } } -void BlackWhite::adjusterChanged (Adjuster* a, double newval) { +void BlackWhite::adjusterChanged (Adjuster* a, double newval) +{ - // Checking "listener" to avoid "autoch" getting toggled off because it has to change the sliders when toggling on - if (listener && (a==mixerRed || a==mixerGreen || a==mixerBlue || a==mixerOrange || a==mixerYellow || a==mixerMagenta || a==mixerPurple || a==mixerCyan) ) { - if (multiImage && autoch->get_inconsistent()) - autoch->set_inconsistent (false); - autoconn.block(true); - autoch->set_active (false); - autoconn.block(false); - lastAuto = false; - } + // Checking "listener" to avoid "autoch" getting toggled off because it has to change the sliders when toggling on + if (listener && (a == mixerRed || a == mixerGreen || a == mixerBlue || a == mixerOrange || a == mixerYellow || a == mixerMagenta || a == mixerPurple || a == mixerCyan) ) { + if (multiImage && autoch->get_inconsistent()) { + autoch->set_inconsistent (false); + } - if (a == mixerRed || a==mixerGreen || a== mixerBlue - || a == mixerOrange || a == mixerYellow ||a == mixerCyan - || a == mixerMagenta || a == mixerPurple) + autoconn.block(true); + autoch->set_active (false); + autoconn.block(false); + lastAuto = false; + } - updateRGBLabel(); + if (a == mixerRed || a == mixerGreen || a == mixerBlue + || a == mixerOrange || a == mixerYellow || a == mixerCyan + || a == mixerMagenta || a == mixerPurple) - if (listener && (multiImage||getEnabled())) { - Glib::ustring value = a->getTextValue(); - if (a == mixerRed) - listener->panelChanged (EvBWred, value ); - else if (a == mixerGreen) - listener->panelChanged (EvBWgreen, value ); - else if (a == mixerBlue) - listener->panelChanged (EvBWblue, value ); - else if (a == gammaGreen) - listener->panelChanged (EvBWgreengam, value ); - else if (a == gammaBlue) - listener->panelChanged (EvBWbluegam, value ); - else if (a == gammaRed) - listener->panelChanged (EvBWredgam, value ); - else if (a == mixerOrange) - listener->panelChanged (EvBWoran, value ); - else if (a == mixerYellow) - listener->panelChanged (EvBWyell, value ); - else if (a == mixerCyan) - listener->panelChanged (EvBWcyan, value ); - else if (a == mixerMagenta) - listener->panelChanged (EvBWmag, value ); - else if (a == mixerPurple) - listener->panelChanged (EvBWpur, value ); - } + { + updateRGBLabel(); + } + + if (listener && (multiImage || getEnabled())) { + Glib::ustring value = a->getTextValue(); + + if (a == mixerRed) { + listener->panelChanged (EvBWred, value ); + } else if (a == mixerGreen) { + listener->panelChanged (EvBWgreen, value ); + } else if (a == mixerBlue) { + listener->panelChanged (EvBWblue, value ); + } else if (a == gammaGreen) { + listener->panelChanged (EvBWgreengam, value ); + } else if (a == gammaBlue) { + listener->panelChanged (EvBWbluegam, value ); + } else if (a == gammaRed) { + listener->panelChanged (EvBWredgam, value ); + } else if (a == mixerOrange) { + listener->panelChanged (EvBWoran, value ); + } else if (a == mixerYellow) { + listener->panelChanged (EvBWyell, value ); + } else if (a == mixerCyan) { + listener->panelChanged (EvBWcyan, value ); + } else if (a == mixerMagenta) { + listener->panelChanged (EvBWmag, value ); + } else if (a == mixerPurple) { + listener->panelChanged (EvBWpur, value ); + } + } } -void BlackWhite::updateRGBLabel () { - if (!batchMode) { - float kcorrec=1.f; - float r, g, b; - if (autoch->get_active()) { - r = nextredbw; - g = nextgreenbw; - b = nextbluebw; - } - else { - r = mixerRed->getValue(); - g = mixerGreen->getValue(); - b = mixerBlue->getValue(); - } - double mixR, mixG, mixB; - float filcor; - Glib::ustring sSetting = getSettingString(); - Color::computeBWMixerConstants(sSetting, getFilterString(),getalgoString(), filcor, r, g, b, - mixerOrange->getValue(), mixerYellow->getValue(), mixerCyan->getValue(), mixerPurple->getValue(), mixerMagenta->getValue(), - autoch->get_active(), enabledcc->get_active(), kcorrec, mixR, mixG, mixB); - if( filcor!=1.f){ - r=kcorrec*r/(r+g+b); - g=kcorrec*g/(r+g+b); - b=kcorrec*b/(r+g+b); - } - RGBLabels->set_text( - Glib::ustring::compose(M("TP_BWMIX_RGBLABEL"), - Glib::ustring::format(std::fixed, std::setprecision(1), r*100.), - Glib::ustring::format(std::fixed, std::setprecision(1), g*100.), - Glib::ustring::format(std::fixed, std::setprecision(1), b*100.), - Glib::ustring::format(std::fixed, std::setprecision(0), ceil(kcorrec*100./*(r+g+b)*100.)*/))) - ); - // We have to update the RGB sliders too if preset values has been chosen - if (sSetting != "RGB-Abs" && sSetting != "RGB-Rel" && sSetting != "ROYGCBPM-Abs" && sSetting != "ROYGCBPM-Rel") { - mixerRed->setValue(mixR); - mixerGreen->setValue(mixG); - mixerBlue->setValue(mixB); - } - } +void BlackWhite::updateRGBLabel () +{ + if (!batchMode) { + float kcorrec = 1.f; + float r, g, b; + + if (autoch->get_active()) { + r = nextredbw; + g = nextgreenbw; + b = nextbluebw; + } else { + r = mixerRed->getValue(); + g = mixerGreen->getValue(); + b = mixerBlue->getValue(); + } + + double mixR, mixG, mixB; + float filcor; + Glib::ustring sSetting = getSettingString(); + Color::computeBWMixerConstants(sSetting, getFilterString(), getalgoString(), filcor, r, g, b, + mixerOrange->getValue(), mixerYellow->getValue(), mixerCyan->getValue(), mixerPurple->getValue(), mixerMagenta->getValue(), + autoch->get_active(), enabledcc->get_active(), kcorrec, mixR, mixG, mixB); + + if( filcor != 1.f) { + r = kcorrec * r / (r + g + b); + g = kcorrec * g / (r + g + b); + b = kcorrec * b / (r + g + b); + } + + RGBLabels->set_text( + Glib::ustring::compose(M("TP_BWMIX_RGBLABEL"), + Glib::ustring::format(std::fixed, std::setprecision(1), r * 100.), + Glib::ustring::format(std::fixed, std::setprecision(1), g * 100.), + Glib::ustring::format(std::fixed, std::setprecision(1), b * 100.), + Glib::ustring::format(std::fixed, std::setprecision(0), ceil(kcorrec * 100./*(r+g+b)*100.)*/))) + ); + + // We have to update the RGB sliders too if preset values has been chosen + if (sSetting != "RGB-Abs" && sSetting != "RGB-Rel" && sSetting != "ROYGCBPM-Abs" && sSetting != "ROYGCBPM-Rel") { + mixerRed->setValue(mixR); + mixerGreen->setValue(mixG); + mixerBlue->setValue(mixB); + } + } } -void BlackWhite::setBatchMode (bool batchMode) { - removeIfThere (autoHBox, autoch, false); - autoch = Gtk::manage (new Gtk::CheckButton (M("TP_BWMIX_AUTOCH"))); - autoch->set_tooltip_markup (M("TP_BWMIX_AUTOCH_TIP")); - autoconn = autoch->signal_toggled().connect( sigc::mem_fun(*this, &BlackWhite::autoch_toggled) ); - autoHBox->pack_start (*autoch); +void BlackWhite::setBatchMode (bool batchMode) +{ + removeIfThere (autoHBox, autoch, false); + autoch = Gtk::manage (new Gtk::CheckButton (M("TP_BWMIX_AUTOCH"))); + autoch->set_tooltip_markup (M("TP_BWMIX_AUTOCH_TIP")); + autoconn = autoch->signal_toggled().connect( sigc::mem_fun(*this, &BlackWhite::autoch_toggled) ); + autoHBox->pack_start (*autoch); - removeIfThere (mixerVBox, RGBLabels, false); - delete RGBLabels; - RGBLabels = NULL; + removeIfThere (mixerVBox, RGBLabels, false); + delete RGBLabels; + RGBLabels = NULL; - ToolPanel::setBatchMode (batchMode); - mixerRed->showEditedCB (); - mixerOrange->showEditedCB (); - mixerYellow->showEditedCB (); - mixerGreen->showEditedCB (); - mixerCyan->showEditedCB (); - mixerBlue->showEditedCB (); - mixerMagenta->showEditedCB (); - mixerPurple->showEditedCB (); - gammaRed->showEditedCB (); - gammaGreen->showEditedCB (); - gammaBlue->showEditedCB (); - method->append_text (M("GENERAL_UNCHANGED")); - filter->append_text (M("GENERAL_UNCHANGED")); - setting->append_text (M("GENERAL_UNCHANGED")); - luminanceCEG->setBatchMode (batchMode); - beforeCurveCEG->setBatchMode (batchMode); - beforeCurveCEG->show(); - beforeCurveMode->append_text (M("GENERAL_UNCHANGED")); - afterCurveCEG->setBatchMode (batchMode); - afterCurveCEG->show(); -// afterCurveMode->append_text (M("GENERAL_UNCHANGED")); - algo->append_text (M("GENERAL_UNCHANGED")); + ToolPanel::setBatchMode (batchMode); + mixerRed->showEditedCB (); + mixerOrange->showEditedCB (); + mixerYellow->showEditedCB (); + mixerGreen->showEditedCB (); + mixerCyan->showEditedCB (); + mixerBlue->showEditedCB (); + mixerMagenta->showEditedCB (); + mixerPurple->showEditedCB (); + gammaRed->showEditedCB (); + gammaGreen->showEditedCB (); + gammaBlue->showEditedCB (); + method->append_text (M("GENERAL_UNCHANGED")); + filter->append_text (M("GENERAL_UNCHANGED")); + setting->append_text (M("GENERAL_UNCHANGED")); + luminanceCEG->setBatchMode (batchMode); + beforeCurveCEG->setBatchMode (batchMode); + beforeCurveCEG->show(); + beforeCurveMode->append_text (M("GENERAL_UNCHANGED")); + afterCurveCEG->setBatchMode (batchMode); + afterCurveCEG->show(); +// afterCurveMode->append_text (M("GENERAL_UNCHANGED")); + algo->append_text (M("GENERAL_UNCHANGED")); - showLuminance(); - showFilter(); - showEnabledCC(); - showGamma(); - showMixer(7); + showLuminance(); + showFilter(); + showEnabledCC(); + showGamma(); + showMixer(7); } -void BlackWhite::autoOpenCurve () { - luminanceCurve->openIfNonlinear(); - beforeCurve->openIfNonlinear(); - afterCurve->openIfNonlinear(); +void BlackWhite::autoOpenCurve () +{ + luminanceCurve->openIfNonlinear(); + beforeCurve->openIfNonlinear(); + afterCurve->openIfNonlinear(); } -void BlackWhite::setEditProvider (EditDataProvider *provider) { - luminanceCurve->setEditProvider(provider); - beforeCurve->setEditProvider(provider); - afterCurve->setEditProvider(provider); +void BlackWhite::setEditProvider (EditDataProvider *provider) +{ + luminanceCurve->setEditProvider(provider); + beforeCurve->setEditProvider(provider); + afterCurve->setEditProvider(provider); } -void BlackWhite::setAdjusterBehavior (bool bwadd, bool bwgadd) { +void BlackWhite::setAdjusterBehavior (bool bwadd, bool bwgadd) +{ - mixerRed->setAddMode(bwadd); - mixerOrange->setAddMode(bwadd); - mixerYellow->setAddMode(bwadd); - mixerGreen->setAddMode(bwadd); - mixerCyan->setAddMode(bwadd); - mixerBlue->setAddMode(bwadd); - mixerMagenta->setAddMode(bwadd); - mixerPurple->setAddMode(bwadd); + mixerRed->setAddMode(bwadd); + mixerOrange->setAddMode(bwadd); + mixerYellow->setAddMode(bwadd); + mixerGreen->setAddMode(bwadd); + mixerCyan->setAddMode(bwadd); + mixerBlue->setAddMode(bwadd); + mixerMagenta->setAddMode(bwadd); + mixerPurple->setAddMode(bwadd); - gammaRed->setAddMode(bwgadd); - gammaGreen->setAddMode(bwgadd); - gammaBlue->setAddMode(bwgadd); + gammaRed->setAddMode(bwgadd); + gammaGreen->setAddMode(bwgadd); + gammaBlue->setAddMode(bwgadd); } -void BlackWhite::trimValues (rtengine::procparams::ProcParams* pp) { +void BlackWhite::trimValues (rtengine::procparams::ProcParams* pp) +{ - mixerRed->trimValue (pp->blackwhite.mixerRed); - mixerGreen->trimValue (pp->blackwhite.mixerGreen); - mixerBlue->trimValue (pp->blackwhite.mixerBlue); - gammaRed->trimValue (pp->blackwhite.gammaRed); - gammaGreen->trimValue (pp->blackwhite.gammaGreen); - gammaBlue->trimValue (pp->blackwhite.gammaBlue); - mixerOrange->trimValue (pp->blackwhite.mixerOrange); - mixerYellow->trimValue (pp->blackwhite.mixerYellow); - mixerCyan->trimValue (pp->blackwhite.mixerCyan); - mixerMagenta->trimValue (pp->blackwhite.mixerMagenta); - mixerPurple->trimValue (pp->blackwhite.mixerPurple); + mixerRed->trimValue (pp->blackwhite.mixerRed); + mixerGreen->trimValue (pp->blackwhite.mixerGreen); + mixerBlue->trimValue (pp->blackwhite.mixerBlue); + gammaRed->trimValue (pp->blackwhite.gammaRed); + gammaGreen->trimValue (pp->blackwhite.gammaGreen); + gammaBlue->trimValue (pp->blackwhite.gammaBlue); + mixerOrange->trimValue (pp->blackwhite.mixerOrange); + mixerYellow->trimValue (pp->blackwhite.mixerYellow); + mixerCyan->trimValue (pp->blackwhite.mixerCyan); + mixerMagenta->trimValue (pp->blackwhite.mixerMagenta); + mixerPurple->trimValue (pp->blackwhite.mixerPurple); } -void BlackWhite::showLuminance() { - luminanceCEG->show(); - luminanceSep->show(); +void BlackWhite::showLuminance() +{ + luminanceCEG->show(); + luminanceSep->show(); } -void BlackWhite::hideLuminance() { - if (!batchMode) { - luminanceCEG->hide(); - luminanceSep->hide(); - } +void BlackWhite::hideLuminance() +{ + if (!batchMode) { + luminanceCEG->hide(); + luminanceSep->hide(); + } } -void BlackWhite::showFilter() { - filterHBox->show(); - filterSep->show(); +void BlackWhite::showFilter() +{ + filterHBox->show(); + filterSep->show(); } -void BlackWhite::hideFilter() { - if (!batchMode) { - filterHBox->hide(); - filterSep->hide(); - } +void BlackWhite::hideFilter() +{ + if (!batchMode) { + filterHBox->hide(); + filterSep->hide(); + } } -void BlackWhite::showEnabledCC() { - enabledcc->show(); - enabledccSep->show(); +void BlackWhite::showEnabledCC() +{ + enabledcc->show(); + enabledccSep->show(); } -void BlackWhite::hideEnabledCC() { - if (!batchMode) { - enabledcc->hide(); - enabledccSep->hide(); - } +void BlackWhite::hideEnabledCC() +{ + if (!batchMode) { + enabledcc->hide(); + enabledccSep->hide(); + } } -void BlackWhite::showMixer(int nChannels, bool RGBIsSensitive) { - if (!batchMode) - RGBLabels->show(); +void BlackWhite::showMixer(int nChannels, bool RGBIsSensitive) +{ + if (!batchMode) { + RGBLabels->show(); + } - if (!batchMode && nChannels == 3) { - mixerRed->show(); mixerRed->set_sensitive (RGBIsSensitive); - mixerGreen->show(); mixerGreen->set_sensitive (RGBIsSensitive); - mixerBlue->show(); mixerBlue->set_sensitive (RGBIsSensitive); - filterSep2->hide(); - algo->hide(); - alLabel->hide(); - mixerOrange->hide(); - mixerYellow->hide(); - mixerCyan->hide(); - mixerMagenta->hide(); - mixerPurple->hide(); - } - else { - mixerRed->show(); mixerRed->set_sensitive (true); - mixerGreen->show(); mixerGreen->set_sensitive (true); - mixerBlue->show(); mixerBlue->set_sensitive (true); - filterSep2->show(); - mixerOrange->show(); - algo->show(); - alLabel->show(); - mixerYellow->show(); - mixerCyan->show(); - mixerMagenta->show(); - mixerPurple->show(); - } - mixerFrame->show(); + if (!batchMode && nChannels == 3) { + mixerRed->show(); + mixerRed->set_sensitive (RGBIsSensitive); + mixerGreen->show(); + mixerGreen->set_sensitive (RGBIsSensitive); + mixerBlue->show(); + mixerBlue->set_sensitive (RGBIsSensitive); + filterSep2->hide(); + algo->hide(); + alLabel->hide(); + mixerOrange->hide(); + mixerYellow->hide(); + mixerCyan->hide(); + mixerMagenta->hide(); + mixerPurple->hide(); + } else { + mixerRed->show(); + mixerRed->set_sensitive (true); + mixerGreen->show(); + mixerGreen->set_sensitive (true); + mixerBlue->show(); + mixerBlue->set_sensitive (true); + filterSep2->show(); + mixerOrange->show(); + algo->show(); + alLabel->show(); + mixerYellow->show(); + mixerCyan->show(); + mixerMagenta->show(); + mixerPurple->show(); + } + + mixerFrame->show(); } -void BlackWhite::hideMixer() { - if (!batchMode) - mixerFrame->hide(); +void BlackWhite::hideMixer() +{ + if (!batchMode) { + mixerFrame->hide(); + } } -void BlackWhite::showGamma() { - gammaFrame->show(); +void BlackWhite::showGamma() +{ + gammaFrame->show(); } -void BlackWhite::hideGamma() { - if (!batchMode) - gammaFrame->hide(); +void BlackWhite::hideGamma() +{ + if (!batchMode) { + gammaFrame->hide(); + } } -Glib::ustring BlackWhite::getalgoString() { - Glib::ustring retVal; - if (algo->get_active_row_number()==0) - retVal = "LI"; - else if (algo->get_active_row_number()==1) - retVal = "SP"; - return retVal; +Glib::ustring BlackWhite::getalgoString() +{ + Glib::ustring retVal; + + if (algo->get_active_row_number() == 0) { + retVal = "LI"; + } else if (algo->get_active_row_number() == 1) { + retVal = "SP"; + } + + return retVal; } -Glib::ustring BlackWhite::getSettingString() { - Glib::ustring retVal; - if (setting->get_active_row_number()==0) - retVal = "NormalContrast"; - else if (setting->get_active_row_number()==1) - retVal = "HighContrast"; - else if (setting->get_active_row_number()==2) - retVal = "Luminance"; - else if (setting->get_active_row_number()==3) - retVal = "Landscape"; - else if (setting->get_active_row_number()==4) - retVal = "Portrait"; - else if (setting->get_active_row_number()==5) - retVal = "LowSensitivity"; - else if (setting->get_active_row_number()==6) - retVal = "HighSensitivity"; - else if (setting->get_active_row_number()==7) - retVal = "Panchromatic"; - else if (setting->get_active_row_number()==8) - retVal = "HyperPanchromatic"; - else if (setting->get_active_row_number()==9) - retVal = "Orthochromatic"; - else if (setting->get_active_row_number()==10) - retVal = "RGB-Abs"; - else if (setting->get_active_row_number()==11) - retVal = "RGB-Rel"; - else if (setting->get_active_row_number()==12) - retVal = "ROYGCBPM-Abs"; - else if (setting->get_active_row_number()==13) - retVal = "ROYGCBPM-Rel"; - else if (setting->get_active_row_number()==14) - retVal = "InfraRed"; - return retVal; +Glib::ustring BlackWhite::getSettingString() +{ + Glib::ustring retVal; + + if (setting->get_active_row_number() == 0) { + retVal = "NormalContrast"; + } else if (setting->get_active_row_number() == 1) { + retVal = "HighContrast"; + } else if (setting->get_active_row_number() == 2) { + retVal = "Luminance"; + } else if (setting->get_active_row_number() == 3) { + retVal = "Landscape"; + } else if (setting->get_active_row_number() == 4) { + retVal = "Portrait"; + } else if (setting->get_active_row_number() == 5) { + retVal = "LowSensitivity"; + } else if (setting->get_active_row_number() == 6) { + retVal = "HighSensitivity"; + } else if (setting->get_active_row_number() == 7) { + retVal = "Panchromatic"; + } else if (setting->get_active_row_number() == 8) { + retVal = "HyperPanchromatic"; + } else if (setting->get_active_row_number() == 9) { + retVal = "Orthochromatic"; + } else if (setting->get_active_row_number() == 10) { + retVal = "RGB-Abs"; + } else if (setting->get_active_row_number() == 11) { + retVal = "RGB-Rel"; + } else if (setting->get_active_row_number() == 12) { + retVal = "ROYGCBPM-Abs"; + } else if (setting->get_active_row_number() == 13) { + retVal = "ROYGCBPM-Rel"; + } else if (setting->get_active_row_number() == 14) { + retVal = "InfraRed"; + } + + return retVal; } -Glib::ustring BlackWhite::getFilterString() { - Glib::ustring retVal; - if (filter->get_active_row_number()==0) - retVal = "None"; - else if (filter->get_active_row_number()==1) - retVal = "Red"; - else if (filter->get_active_row_number()==2) - retVal = "Orange"; - else if (filter->get_active_row_number()==3) - retVal = "Yellow"; - else if (filter->get_active_row_number()==4) - retVal = "YellowGreen"; - else if (filter->get_active_row_number()==5) - retVal = "Green"; - else if (filter->get_active_row_number()==6) - retVal = "Cyan"; - else if (filter->get_active_row_number()==7) - retVal = "Blue"; - else if (filter->get_active_row_number()==8) - retVal = "Purple"; - return retVal; +Glib::ustring BlackWhite::getFilterString() +{ + Glib::ustring retVal; + + if (filter->get_active_row_number() == 0) { + retVal = "None"; + } else if (filter->get_active_row_number() == 1) { + retVal = "Red"; + } else if (filter->get_active_row_number() == 2) { + retVal = "Orange"; + } else if (filter->get_active_row_number() == 3) { + retVal = "Yellow"; + } else if (filter->get_active_row_number() == 4) { + retVal = "YellowGreen"; + } else if (filter->get_active_row_number() == 5) { + retVal = "Green"; + } else if (filter->get_active_row_number() == 6) { + retVal = "Cyan"; + } else if (filter->get_active_row_number() == 7) { + retVal = "Blue"; + } else if (filter->get_active_row_number() == 8) { + retVal = "Purple"; + } + + return retVal; } diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index 22e032a65..d5e7c0a4f 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -7,7 +7,7 @@ * 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 @@ -28,111 +28,112 @@ #include "mycurve.h" #include "colorprovider.h" -class BlackWhite : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoBWListener, public CurveListener, public ColorProvider{ +class BlackWhite : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoBWListener, public CurveListener, public ColorProvider +{ - protected: - FlatCurveEditor* luminanceCurve; - Gtk::HSeparator* luminanceSep; - CurveEditorGroup* luminanceCEG; - CurveEditorGroup* beforeCurveCEG; - DiagonalCurveEditor* beforeCurve; - MyComboBoxText* beforeCurveMode; - CurveEditorGroup* afterCurveCEG; - DiagonalCurveEditor* afterCurve; - MyComboBoxText* afterCurveMode; - Gtk::ToggleButton* autoch; - Gtk::HBox* autoHBox; - Gtk::Button* neutral; - Gtk::Label* RGBLabels; +protected: + FlatCurveEditor* luminanceCurve; + Gtk::HSeparator* luminanceSep; + CurveEditorGroup* luminanceCEG; + CurveEditorGroup* beforeCurveCEG; + DiagonalCurveEditor* beforeCurve; + MyComboBoxText* beforeCurveMode; + CurveEditorGroup* afterCurveCEG; + DiagonalCurveEditor* afterCurve; + MyComboBoxText* afterCurveMode; + Gtk::ToggleButton* autoch; + Gtk::HBox* autoHBox; + Gtk::Button* neutral; + Gtk::Label* RGBLabels; MyComboBoxText* algo; sigc::connection algoconn; - Gtk::Label* alLabel; - Gtk::HBox* algoHBox; + Gtk::Label* alLabel; + Gtk::HBox* algoHBox; - Adjuster *mixerRed; - Adjuster *mixerGreen; - Adjuster *mixerBlue; - Adjuster *gammaRed; - Adjuster *gammaGreen; - Adjuster *gammaBlue; - Adjuster *mixerOrange; - Adjuster *mixerYellow; - Adjuster *mixerCyan; - Adjuster *mixerMagenta; - Adjuster *mixerPurple; - MyComboBoxText* method; - sigc::connection methodconn; - Gtk::HBox* filterHBox; - Gtk::HSeparator* filterSep, *filterSep2; - MyComboBoxText* filter; - sigc::connection filterconn; - Gtk::HBox* settingHBox; - MyComboBoxText* setting; - sigc::connection settingconn; - Gtk::Frame* mixerFrame; - Gtk::VBox * mixerVBox; - Gtk::Frame* gammaFrame; + Adjuster *mixerRed; + Adjuster *mixerGreen; + Adjuster *mixerBlue; + Adjuster *gammaRed; + Adjuster *gammaGreen; + Adjuster *gammaBlue; + Adjuster *mixerOrange; + Adjuster *mixerYellow; + Adjuster *mixerCyan; + Adjuster *mixerMagenta; + Adjuster *mixerPurple; + MyComboBoxText* method; + sigc::connection methodconn; + Gtk::HBox* filterHBox; + Gtk::HSeparator* filterSep, *filterSep2; + MyComboBoxText* filter; + sigc::connection filterconn; + Gtk::HBox* settingHBox; + MyComboBoxText* setting; + sigc::connection settingconn; + Gtk::Frame* mixerFrame; + Gtk::VBox * mixerVBox; + Gtk::Frame* gammaFrame; - Gtk::Image *imgIcon[11]; + Gtk::Image *imgIcon[11]; - Gtk::HSeparator* enabledccSep; - Gtk::CheckButton* enabledcc; - bool lastEnabledcc, lastAuto; - sigc::connection enaccconn,tcmodeconn,tcmodeconn2, autoconn, neutralconn; + Gtk::HSeparator* enabledccSep; + Gtk::CheckButton* enabledcc; + bool lastEnabledcc, lastAuto; + sigc::connection enaccconn, tcmodeconn, tcmodeconn2, autoconn, neutralconn; - double nextredbw; - double nextgreenbw; - double nextbluebw; + double nextredbw; + double nextgreenbw; + double nextbluebw; - void showLuminance(); - void hideLuminance(); - void showFilter(); - void hideFilter(); - void showEnabledCC(); - void hideEnabledCC(); - void showMixer(int nChannels, bool RGBIsSensitive=true); - void hideMixer(); - void showGamma(); - void hideGamma(); + void showLuminance(); + void hideLuminance(); + void showFilter(); + void hideFilter(); + void showEnabledCC(); + void hideEnabledCC(); + void showMixer(int nChannels, bool RGBIsSensitive = true); + void hideMixer(); + void showGamma(); + void hideGamma(); - public: +public: - BlackWhite (); - ~BlackWhite (); + BlackWhite (); + ~BlackWhite (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void autoOpenCurve (); - void setEditProvider (EditDataProvider *provider); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void autoOpenCurve (); + void setEditProvider (EditDataProvider *provider); - void autoch_toggled (); - void neutral_pressed (); + void autoch_toggled (); + void neutral_pressed (); - void updateRGBLabel (); - void adjusterChanged (Adjuster* a, double newval); - void setAdjusterBehavior (bool bwadd, bool bwgadd); - void trimValues (rtengine::procparams::ProcParams* pp); - void enabledcc_toggled (); + void updateRGBLabel (); + void adjusterChanged (Adjuster* a, double newval); + void setAdjusterBehavior (bool bwadd, bool bwgadd); + void trimValues (rtengine::procparams::ProcParams* pp); + void enabledcc_toggled (); void enabledChanged (); - void methodChanged (); - void filterChanged (); - void settingChanged (); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - void BWChanged (double redbw, double greenbw, double bluebw); - bool BWComputed_ (); - void curveChanged (CurveEditor* ce); - void curveMode1Changed (); - bool curveMode1Changed_ (); - void curveMode1Changed2 (); - bool curveMode1Changed2_ (); + void methodChanged (); + void filterChanged (); + void settingChanged (); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void BWChanged (double redbw, double greenbw, double bluebw); + bool BWComputed_ (); + void curveChanged (CurveEditor* ce); + void curveMode1Changed (); + bool curveMode1Changed_ (); + void curveMode1Changed2 (); + bool curveMode1Changed2_ (); void algoChanged (); - Glib::ustring getSettingString (); - Glib::ustring getFilterString (); - Glib::ustring getalgoString (); - + Glib::ustring getSettingString (); + Glib::ustring getFilterString (); + Glib::ustring getalgoString (); + }; #endif diff --git a/rtgui/bqentryupdater.cc b/rtgui/bqentryupdater.cc index 44395c8ff..040036049 100644 --- a/rtgui/bqentryupdater.cc +++ b/rtgui/bqentryupdater.cc @@ -7,7 +7,7 @@ * 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 @@ -22,24 +22,28 @@ BatchQueueEntryUpdater batchQueueEntryUpdater; -BatchQueueEntryUpdater::BatchQueueEntryUpdater () - : tostop(false), stopped(true), thread(NULL), qMutex(NULL) { +BatchQueueEntryUpdater::BatchQueueEntryUpdater () + : tostop(false), stopped(true), thread(NULL), qMutex(NULL) +{ } -void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams, Thumbnail* thumbnail) { +void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams, Thumbnail* thumbnail) +{ if (!oimg && (!pparams || !thumbnail)) { //printf("WARNING! !oimg && (!pparams || !thumbnail)\n"); return; } - if (!qMutex) + if (!qMutex) { qMutex = new MyMutex (); + } qMutex->lock (); // look up if an older version is in the queue std::list::iterator i; - for (i=jqueue.begin(); i!=jqueue.end(); i++) - if (i->oimg==oimg && i->listener==listener) { + + for (i = jqueue.begin(); i != jqueue.end(); i++) + if (i->oimg == oimg && i->listener == listener) { i->ow = ow; i->oh = oh; i->newh = newh; @@ -50,7 +54,7 @@ void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQ } // not found, create and append new job - if (i==jqueue.end ()) { + if (i == jqueue.end ()) { Job j; j.oimg = oimg; j.ow = ow; @@ -61,6 +65,7 @@ void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQ j.thumbnail = thumbnail; jqueue.push_back (j); } + qMutex->unlock (); // Start thread if not running yet @@ -69,53 +74,66 @@ void BatchQueueEntryUpdater::process (guint8* oimg, int ow, int oh, int newh, BQ tostop = false; #if __GNUC__ == 4 && __GNUC_MINOR__ == 8 && defined( WIN32 ) && defined(__x86_64__) - #undef THREAD_PRIORITY_NORMAL - // See Issue 2384 comment #3 - thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::processThread), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL); +#undef THREAD_PRIORITY_NORMAL + // See Issue 2384 comment #3 + thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::processThread), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL); #else - #undef THREAD_PRIORITY_LOW - thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::processThread), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); +#undef THREAD_PRIORITY_LOW + thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::processThread), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_LOW); #endif } } -void BatchQueueEntryUpdater::processThread () { +void BatchQueueEntryUpdater::processThread () +{ // TODO: process visible jobs first - bool isEmpty=false; + bool isEmpty = false; while (!tostop && !isEmpty) { qMutex->lock (); - isEmpty=jqueue.empty (); // do NOT put into while() since it must be within mutex section + isEmpty = jqueue.empty (); // do NOT put into while() since it must be within mutex section Job current; + if (!isEmpty) { current = jqueue.front (); jqueue.pop_front (); } + qMutex->unlock (); - if(isEmpty) - break; + + if(isEmpty) { + break; + } + rtengine::IImage8* img = NULL; bool newBuffer = false; + if (current.thumbnail && current.pparams) { // the thumbnail and the pparams are provided, it means that we have to build the original preview image double tmpscale; img = current.thumbnail->processThumbImage (*current.pparams, current.oh, tmpscale); + //current.thumbnail->decreaseRef (); // WARNING: decreasing refcount (and maybe deleting) thumbnail, with or without processed image if (img) { int prevw = img->getWidth(); int prevh = img->getHeight(); #ifndef NDEBUG - if (current.ow != img->getW() || current.oh != img->getH()) + + if (current.ow != img->getW() || current.oh != img->getH()) { printf("WARNING! Expected image size: %dx%d ; image size is: %dx%d\n", current.ow, current.oh, img->getW(), img->getH()); - assert ((current.ow+1)*current.oh >= img->getW()*img->getH()); + } + + assert ((current.ow + 1)*current.oh >= img->getW()*img->getH()); #endif current.ow = prevw; current.oh = prevh; + if (!current.oimg) { - current.oimg = new guint8[prevw*prevh*3]; + current.oimg = new guint8[prevw * prevh * 3]; newBuffer = true; } + memcpy(current.oimg, img->getData(), prevw * prevh * 3); img->free(); } @@ -123,53 +141,70 @@ void BatchQueueEntryUpdater::processThread () { if (current.oimg && !isEmpty && current.listener) { int neww = current.newh * current.ow / current.oh; - guint8* img = new guint8 [current.newh*neww*3]; + guint8* img = new guint8 [current.newh * neww * 3]; thumbInterp (current.oimg, current.ow, current.oh, img, neww, current.newh); - current.listener->updateImage (img, neww, current.newh, current.ow, current.oh, newBuffer?current.oimg:NULL); + current.listener->updateImage (img, neww, current.newh, current.ow, current.oh, newBuffer ? current.oimg : NULL); + } + + if(current.oimg) { + delete[] current.oimg; + current.oimg = NULL; } - if(current.oimg) { - delete[] current.oimg; - current.oimg = NULL; - } } stopped = true; } -void BatchQueueEntryUpdater::removeJobs (BQEntryUpdateListener* listener) { - if (!qMutex) return; +void BatchQueueEntryUpdater::removeJobs (BQEntryUpdateListener* listener) +{ + if (!qMutex) { + return; + } qMutex->lock (); bool ready = false; + while (!ready) { ready = true; std::list::iterator i; - for (i=jqueue.begin(); i!=jqueue.end(); i++) + + for (i = jqueue.begin(); i != jqueue.end(); i++) if (i->listener == listener) { jqueue.erase (i); ready = false; break; } } + qMutex->unlock (); } -void BatchQueueEntryUpdater::terminate () { +void BatchQueueEntryUpdater::terminate () +{ // never started or currently not running? - if (!qMutex || stopped) return; + if (!qMutex || stopped) { + return; + } if (!stopped) { // Yield to currently running thread and wait till it's finished GThreadUnLock lock; tostop = true; - Glib::Thread::self()->yield(); - if (!stopped) thread->join (); + Glib::Thread::self()->yield(); + + if (!stopped) { + thread->join (); + } } // Remove remaining jobs qMutex->lock (); - while (!jqueue.empty()) jqueue.pop_front (); + + while (!jqueue.empty()) { + jqueue.pop_front (); + } + qMutex->unlock (); } diff --git a/rtgui/bqentryupdater.h b/rtgui/bqentryupdater.h index f794e4cec..4052649cf 100644 --- a/rtgui/bqentryupdater.h +++ b/rtgui/bqentryupdater.h @@ -7,7 +7,7 @@ * 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 @@ -24,14 +24,16 @@ #include "threadutils.h" #include "thumbnail.h" -class BQEntryUpdateListener { +class BQEntryUpdateListener +{ - public: - virtual ~BQEntryUpdateListener () {} - virtual void updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) {} +public: + virtual ~BQEntryUpdateListener () {} + virtual void updateImage (guint8* img, int w, int h, int origw, int origh, guint8* newOPreview) {} }; -class BatchQueueEntryUpdater { +class BatchQueueEntryUpdater +{ struct Job { guint8* oimg; @@ -41,17 +43,17 @@ class BatchQueueEntryUpdater { Thumbnail* thumbnail; }; - protected: +protected: bool tostop; bool stopped; std::list jqueue; Glib::Thread* thread; MyMutex* qMutex; - public: +public: BatchQueueEntryUpdater (); - void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams=NULL, Thumbnail* thumbnail=NULL); + void process (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener, rtengine::ProcParams* pparams = NULL, Thumbnail* thumbnail = NULL); void removeJobs (BQEntryUpdateListener* listener); void terminate (); diff --git a/rtgui/browserfilter.cc b/rtgui/browserfilter.cc index 4118fcf48..f7d1038ed 100644 --- a/rtgui/browserfilter.cc +++ b/rtgui/browserfilter.cc @@ -7,7 +7,7 @@ * 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 @@ -18,14 +18,17 @@ */ #include "browserfilter.h" -BrowserFilter::BrowserFilter () : exifFilterEnabled (false) { +BrowserFilter::BrowserFilter () : exifFilterEnabled (false) +{ showTrash = true; - for (int i=0; i<6; i++){ + + for (int i = 0; i < 6; i++) { showRanked[i] = true; showCLabeled[i] = true; } - for (int i=0; i<2; i++){ + + for (int i = 0; i < 2; i++) { showEdited[i] = true; showRecentlySaved[i] = true; } diff --git a/rtgui/browserfilter.h b/rtgui/browserfilter.h index acde5c387..6cfa3be62 100644 --- a/rtgui/browserfilter.h +++ b/rtgui/browserfilter.h @@ -7,7 +7,7 @@ * 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 @@ -22,24 +22,25 @@ #include "exiffiltersettings.h" #include -class BrowserFilter { +class BrowserFilter +{ - public: - bool showRanked[6]; - bool showCLabeled[6]; - bool showTrash; - bool showNotTrash; - bool showEdited[2]; - bool showRecentlySaved[2]; - bool multiselect; +public: + bool showRanked[6]; + bool showCLabeled[6]; + bool showTrash; + bool showNotTrash; + bool showEdited[2]; + bool showRecentlySaved[2]; + bool multiselect; - Glib::ustring queryString; - Glib::ustring queryFileName; + Glib::ustring queryString; + Glib::ustring queryFileName; - bool exifFilterEnabled; - ExifFilterSettings exifFilter; - - BrowserFilter (); + bool exifFilterEnabled; + ExifFilterSettings exifFilter; + + BrowserFilter (); }; #endif diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index ca210cf6d..4b276a03b 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -7,7 +7,7 @@ * 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 @@ -24,108 +24,190 @@ #include "version.h" #include -CacheImageData::CacheImageData () +CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), - timeValid(false), exifValid(false), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), thumbImgType(0) { + timeValid(false), exifValid(false), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), thumbImgType(0) +{ } /* * Load the General, DateTime, ExifInfo, File info and ExtraRawInfo sections of the image data file */ -int CacheImageData::load (const Glib::ustring& fname) { +int CacheImageData::load (const Glib::ustring& fname) +{ setlocale(LC_NUMERIC, "C"); // to set decimal point to "." rtengine::SafeKeyFile keyFile; - + try { if (keyFile.load_from_file (fname)) { if (keyFile.has_group ("General")) { - if (keyFile.has_key ("General", "MD5")) md5 = keyFile.get_string ("General", "MD5"); - if (keyFile.has_key ("General", "Version")) version = keyFile.get_string ("General", "Version"); - if (keyFile.has_key ("General", "Supported")) supported = keyFile.get_boolean ("General", "Supported"); - if (keyFile.has_key ("General", "Format")) format = (ThFileType)keyFile.get_integer ("General", "Format"); - if (keyFile.has_key ("General", "Rank")) rankOld = keyFile.get_integer ("General", "Rank"); - if (keyFile.has_key ("General", "InTrash")) inTrashOld = keyFile.get_boolean ("General", "InTrash"); - if (keyFile.has_key ("General", "RecentlySaved")) recentlySaved = keyFile.get_boolean ("General", "RecentlySaved"); + if (keyFile.has_key ("General", "MD5")) { + md5 = keyFile.get_string ("General", "MD5"); + } + + if (keyFile.has_key ("General", "Version")) { + version = keyFile.get_string ("General", "Version"); + } + + if (keyFile.has_key ("General", "Supported")) { + supported = keyFile.get_boolean ("General", "Supported"); + } + + if (keyFile.has_key ("General", "Format")) { + format = (ThFileType)keyFile.get_integer ("General", "Format"); + } + + if (keyFile.has_key ("General", "Rank")) { + rankOld = keyFile.get_integer ("General", "Rank"); + } + + if (keyFile.has_key ("General", "InTrash")) { + inTrashOld = keyFile.get_boolean ("General", "InTrash"); + } + + if (keyFile.has_key ("General", "RecentlySaved")) { + recentlySaved = keyFile.get_boolean ("General", "RecentlySaved"); + } } timeValid = keyFile.has_group ("DateTime"); if (timeValid) { - if (keyFile.has_key ("DateTime", "Year")) year = keyFile.get_integer ("DateTime", "Year"); - if (keyFile.has_key ("DateTime", "Month")) month = keyFile.get_integer ("DateTime", "Month"); - if (keyFile.has_key ("DateTime", "Day")) day = keyFile.get_integer ("DateTime", "Day"); - if (keyFile.has_key ("DateTime", "Hour")) hour = keyFile.get_integer ("DateTime", "Hour"); - if (keyFile.has_key ("DateTime", "Min")) min = keyFile.get_integer ("DateTime", "Min"); - if (keyFile.has_key ("DateTime", "Sec")) sec = keyFile.get_integer ("DateTime", "Sec"); + if (keyFile.has_key ("DateTime", "Year")) { + year = keyFile.get_integer ("DateTime", "Year"); + } + + if (keyFile.has_key ("DateTime", "Month")) { + month = keyFile.get_integer ("DateTime", "Month"); + } + + if (keyFile.has_key ("DateTime", "Day")) { + day = keyFile.get_integer ("DateTime", "Day"); + } + + if (keyFile.has_key ("DateTime", "Hour")) { + hour = keyFile.get_integer ("DateTime", "Hour"); + } + + if (keyFile.has_key ("DateTime", "Min")) { + min = keyFile.get_integer ("DateTime", "Min"); + } + + if (keyFile.has_key ("DateTime", "Sec")) { + sec = keyFile.get_integer ("DateTime", "Sec"); + } } exifValid = false; if (keyFile.has_group ("ExifInfo")) { exifValid = true; - if (keyFile.has_key ("ExifInfo", "Valid")) exifValid = keyFile.get_boolean ("ExifInfo", "Valid"); + + if (keyFile.has_key ("ExifInfo", "Valid")) { + exifValid = keyFile.get_boolean ("ExifInfo", "Valid"); + } if (exifValid) { - if (keyFile.has_key ("ExifInfo", "FNumber")) fnumber = keyFile.get_double ("ExifInfo", "FNumber"); - if (keyFile.has_key ("ExifInfo", "Shutter")) shutter = keyFile.get_double ("ExifInfo", "Shutter"); - if (keyFile.has_key ("ExifInfo", "FocalLen")) focalLen = keyFile.get_double ("ExifInfo", "FocalLen"); - if (keyFile.has_key ("ExifInfo", "FocalLen35mm")) focalLen35mm = keyFile.get_double ("ExifInfo", "FocalLen35mm"); - else focalLen35mm=focalLen; // prevent crashes on old files - if (keyFile.has_key ("ExifInfo", "FocusDist")) focusDist = keyFile.get_double ("ExifInfo", "FocusDist"); - else focusDist=0; - if (keyFile.has_key ("ExifInfo", "ISO")) iso = keyFile.get_integer ("ExifInfo", "ISO"); - if (keyFile.has_key ("ExifInfo", "ExpComp")) expcomp = keyFile.get_string ("ExifInfo", "ExpComp"); + if (keyFile.has_key ("ExifInfo", "FNumber")) { + fnumber = keyFile.get_double ("ExifInfo", "FNumber"); + } + + if (keyFile.has_key ("ExifInfo", "Shutter")) { + shutter = keyFile.get_double ("ExifInfo", "Shutter"); + } + + if (keyFile.has_key ("ExifInfo", "FocalLen")) { + focalLen = keyFile.get_double ("ExifInfo", "FocalLen"); + } + + if (keyFile.has_key ("ExifInfo", "FocalLen35mm")) { + focalLen35mm = keyFile.get_double ("ExifInfo", "FocalLen35mm"); + } else { + focalLen35mm = focalLen; // prevent crashes on old files + } + + if (keyFile.has_key ("ExifInfo", "FocusDist")) { + focusDist = keyFile.get_double ("ExifInfo", "FocusDist"); + } else { + focusDist = 0; + } + + if (keyFile.has_key ("ExifInfo", "ISO")) { + iso = keyFile.get_integer ("ExifInfo", "ISO"); + } + + if (keyFile.has_key ("ExifInfo", "ExpComp")) { + expcomp = keyFile.get_string ("ExifInfo", "ExpComp"); + } + } + + if (keyFile.has_key ("ExifInfo", "Lens")) { + lens = keyFile.get_string ("ExifInfo", "Lens"); + } + + if (keyFile.has_key ("ExifInfo", "CameraMake")) { + camMake = keyFile.get_string ("ExifInfo", "CameraMake"); + } + + if (keyFile.has_key ("ExifInfo", "CameraModel")) { + camModel = keyFile.get_string ("ExifInfo", "CameraModel"); } - if (keyFile.has_key ("ExifInfo", "Lens")) lens = keyFile.get_string ("ExifInfo", "Lens"); - if (keyFile.has_key ("ExifInfo", "CameraMake")) camMake = keyFile.get_string ("ExifInfo", "CameraMake"); - if (keyFile.has_key ("ExifInfo", "CameraModel")) camModel = keyFile.get_string ("ExifInfo", "CameraModel"); } if (keyFile.has_group ("FileInfo")) { - if (keyFile.has_key ("FileInfo", "Filetype")) filetype = keyFile.get_string ("FileInfo", "Filetype"); + if (keyFile.has_key ("FileInfo", "Filetype")) { + filetype = keyFile.get_string ("FileInfo", "Filetype"); + } } - if (format==FT_Raw && keyFile.has_group ("ExtraRawInfo")) { - 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 { + if (format == FT_Raw && keyFile.has_group ("ExtraRawInfo")) { + 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; } + return 0; } - } - catch (Glib::Error &err) { - if (options.rtSettings.verbose) + } catch (Glib::Error &err) { + if (options.rtSettings.verbose) { printf("CacheImageData::load / 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) + } + } catch (...) { + if (options.rtSettings.verbose) { printf("CacheImageData::load / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); + } } + return 1; } /* * Save the General, DateTime, ExifInfo, File info and ExtraRawInfo sections of the image data file */ -int CacheImageData::save (const Glib::ustring& fname) { +int CacheImageData::save (const Glib::ustring& fname) +{ rtengine::SafeKeyFile keyFile; - - if (safe_file_test(fname,Glib::FILE_TEST_EXISTS)) { + + if (safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { try { keyFile.load_from_file (fname); - } - catch (Glib::Error &err) { - if (options.rtSettings.verbose) + } 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) + } + } catch (...) { + if (options.rtSettings.verbose) { printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); + } } } @@ -136,8 +218,13 @@ int CacheImageData::save (const Glib::ustring& fname) { keyFile.set_boolean ("General", "RecentlySaved", recentlySaved); // remove the old implementation of Rank and InTrash from cache - if (keyFile.has_key ("General", "Rank")) keyFile.remove_key("General", "Rank"); - if (keyFile.has_key ("General", "InTrash")) keyFile.remove_key("General", "InTrash"); + if (keyFile.has_key ("General", "Rank")) { + keyFile.remove_key("General", "Rank"); + } + + if (keyFile.has_key ("General", "InTrash")) { + keyFile.remove_key("General", "InTrash"); + } if (timeValid) { keyFile.set_integer ("DateTime", "Year", year); @@ -149,6 +236,7 @@ int CacheImageData::save (const Glib::ustring& fname) { } keyFile.set_boolean ("ExifInfo", "Valid", exifValid); + if (exifValid) { keyFile.set_double ("ExifInfo", "FNumber", fnumber); keyFile.set_double ("ExifInfo", "Shutter", shutter); @@ -158,23 +246,26 @@ int CacheImageData::save (const Glib::ustring& fname) { keyFile.set_integer ("ExifInfo", "ISO", iso); keyFile.set_string ("ExifInfo", "ExpComp", expcomp); } + keyFile.set_string ("ExifInfo", "Lens", lens); keyFile.set_string ("ExifInfo", "CameraMake", camMake); keyFile.set_string ("ExifInfo", "CameraModel", camModel); keyFile.set_string ("FileInfo", "Filetype", filetype); - if (format==FT_Raw) { + if (format == FT_Raw) { keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType); keyFile.set_integer ("ExtraRawInfo", "ThumbImageOffset", thumbOffset); } FILE *f = safe_g_fopen (fname, "wt"); + if (!f) { - if (options.rtSettings.verbose) + if (options.rtSettings.verbose) { printf("CacheImageData::save / Error: unable to open file \"%s\" with write access!\n", fname.c_str()); + } + return 1; - } - else { + } else { fprintf (f, "%s", keyFile.to_data().c_str()); fclose (f); return 0; diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index a04bd7300..91a31ce4f 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -7,7 +7,7 @@ * 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 @@ -22,61 +22,64 @@ #include #include "options.h" -class CacheImageData { +class CacheImageData +{ - public: +public: - // basic informations - Glib::ustring md5; - Glib::ustring version; - bool supported; - ThFileType format; - char rankOld; // old implementation of rank - bool inTrashOld; // old implementation of inTrash - bool recentlySaved; + // basic informations + Glib::ustring md5; + Glib::ustring version; + bool supported; + ThFileType format; + char rankOld; // old implementation of rank + bool inTrashOld; // old implementation of inTrash + bool recentlySaved; - // time/date info - bool timeValid; - short year; - char month; - char day; - char hour; - char min; - char sec; - // exif info - bool exifValid; - double fnumber; - double shutter; - double focalLen,focalLen35mm; - float focusDist; - unsigned iso; - Glib::ustring lens; - Glib::ustring camMake; - Glib::ustring camModel; - Glib::ustring filetype; - Glib::ustring expcomp; + // time/date info + bool timeValid; + short year; + char month; + char day; + char hour; + char min; + char sec; + // exif info + bool exifValid; + double fnumber; + double shutter; + double focalLen, focalLen35mm; + float focusDist; + unsigned iso; + Glib::ustring lens; + Glib::ustring camMake; + Glib::ustring camModel; + Glib::ustring filetype; + Glib::ustring expcomp; - // store a copy of the autoWB's multipliers computed in Thumbnail::_generateThumbnailImage - // they are not stored in the cache file by this class, but by rtengine::Thumbnail - // -1 = Unknown - double redAWBMul, greenAWBMul, blueAWBMul; + // store a copy of the autoWB's multipliers computed in Thumbnail::_generateThumbnailImage + // they are not stored in the cache file by this class, but by rtengine::Thumbnail + // -1 = Unknown + double redAWBMul, greenAWBMul, blueAWBMul; - // additional info on raw images - int rotate; - int thumbImgType; - int thumbOffset; + // additional info on raw images + int rotate; + int thumbImgType; + int thumbOffset; - enum - { - FULL_THUMBNAIL = 0, // was the thumbnail generated from whole file - QUICK_THUMBNAIL = 1 // was the thumbnail generated from embedded jpeg - }; + enum { + FULL_THUMBNAIL = 0, // was the thumbnail generated from whole file + QUICK_THUMBNAIL = 1 // was the thumbnail generated from embedded jpeg + }; - CacheImageData (); - - int load (const Glib::ustring& fname); - int save (const Glib::ustring& fname); + CacheImageData (); - Glib::ustring getCamera() const { return Glib::ustring(camMake+" "+camModel); } + int load (const Glib::ustring& fname); + int save (const Glib::ustring& fname); + + Glib::ustring getCamera() const + { + return Glib::ustring(camMake + " " + camModel); + } }; #endif diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 801c9981e..3d3702176 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -7,7 +7,7 @@ * 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 @@ -30,61 +30,78 @@ CacheManager* CacheManager::getInstance(void) { - static CacheManager* instance_ = 0; - if ( instance_ == 0 ) - { - static MyMutex smutex_; - MyMutex::MyLock lock(smutex_); - if ( instance_ == 0 ) - { - instance_ = new CacheManager(); - } - } - return instance_; + static CacheManager* instance_ = 0; + + if ( instance_ == 0 ) { + static MyMutex smutex_; + MyMutex::MyLock lock(smutex_); + + if ( instance_ == 0 ) { + instance_ = new CacheManager(); + } + } + + return instance_; } -void CacheManager::init () { +void CacheManager::init () +{ MyMutex::MyLock lock(mutex_); openEntries.clear (); baseDir = options.cacheBaseDir; - if (!safe_file_test (baseDir, Glib::FILE_TEST_IS_DIR)) + if (!safe_file_test (baseDir, Glib::FILE_TEST_IS_DIR)) { safe_g_mkdir_with_parents (baseDir, 511); - if (!safe_file_test (Glib::build_filename (baseDir, "profiles"), Glib::FILE_TEST_IS_DIR)) + } + + if (!safe_file_test (Glib::build_filename (baseDir, "profiles"), Glib::FILE_TEST_IS_DIR)) { safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "profiles")), 511); - if (!safe_file_test (Glib::build_filename (baseDir, "images"), Glib::FILE_TEST_IS_DIR)) + } + + if (!safe_file_test (Glib::build_filename (baseDir, "images"), Glib::FILE_TEST_IS_DIR)) { safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "images")), 511); - if (!safe_file_test (Glib::build_filename (baseDir, "aehistograms"), Glib::FILE_TEST_IS_DIR)) + } + + if (!safe_file_test (Glib::build_filename (baseDir, "aehistograms"), Glib::FILE_TEST_IS_DIR)) { safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "aehistograms")), 511); - if (!safe_file_test (Glib::build_filename (baseDir, "embprofiles"), Glib::FILE_TEST_IS_DIR)) + } + + if (!safe_file_test (Glib::build_filename (baseDir, "embprofiles"), Glib::FILE_TEST_IS_DIR)) { safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "embprofiles")), 511); - if (!safe_file_test (Glib::build_filename (baseDir, "data"), Glib::FILE_TEST_IS_DIR)) + } + + if (!safe_file_test (Glib::build_filename (baseDir, "data"), Glib::FILE_TEST_IS_DIR)) { safe_g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "data")), 511); + } } -Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) { +Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) +{ Thumbnail* res = NULL; - + // take manager lock and search for entry, if found return it else release // lock and create it - { + { MyMutex::MyLock lock(mutex_); - string_thumb_map::iterator r = openEntries.find (fname); - // if it is open, return it - if (r!=openEntries.end()) { - r->second->increaseRef (); - return r->second; - } - } + string_thumb_map::iterator r = openEntries.find (fname); + + // if it is open, return it + if (r != openEntries.end()) { + r->second->increaseRef (); + return r->second; + } + } // compute the md5 std::string md5 = getMD5 (fname); - if (md5=="") + + if (md5 == "") { return NULL; + } // build path name Glib::ustring cfname = getCacheFileName ("data", fname, md5) + ".txt"; @@ -93,18 +110,23 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) { if (safe_file_test (cfname, Glib::FILE_TEST_EXISTS)) { CacheImageData* cfs = new CacheImageData (); int e = cfs->load (cfname); - if (!e && cfs->supported==true) + + if (!e && cfs->supported == true) { res = new Thumbnail (this, fname, cfs); + } + if (res && !res->isSupported ()) { delete res; res = NULL; } + delete cfs; } - // if not, create a new one + // if not, create a new one if (!res) { res = new Thumbnail (this, fname, md5); + if (!res->isSupported ()) { delete res; res = NULL; @@ -113,88 +135,95 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) { // retake the lock and see if it was added while we we're unlocked, if it // was use it over our version. if not added we create the cache entry - if (res) - { - MyMutex::MyLock lock(mutex_); + if (res) { + MyMutex::MyLock lock(mutex_); - string_thumb_map::iterator r = openEntries.find (fname); - if (r!=openEntries.end()) { - delete res; - r->second->increaseRef (); - return r->second; - } + string_thumb_map::iterator r = openEntries.find (fname); - // it wasn't, create a new entry - openEntries[fname] = res; - } + if (r != openEntries.end()) { + delete res; + r->second->increaseRef (); + return r->second; + } + + // it wasn't, create a new entry + openEntries[fname] = res; + } return res; } -void CacheManager::deleteEntry (const Glib::ustring& fname) { +void CacheManager::deleteEntry (const Glib::ustring& fname) +{ MyMutex::MyLock lock(mutex_); // check if it is opened string_thumb_map::iterator r = openEntries.find (fname); + // if it is open, dont delete it - if (r!=openEntries.end()) { - std::string md5 = r->second->getMD5 (); + if (r != openEntries.end()) { + std::string md5 = r->second->getMD5 (); // decrease reference count; this will call back into CacheManager so // we release the lock for it. - { + { lock.release(); - r->second->decreaseRef (); + r->second->decreaseRef (); lock.acquire(); - } + } - // if in the editor, the thumbnail still exists. If not, delete it: - r = openEntries.find (fname); - if (r==openEntries.end() && md5!="") { - safe_g_remove (getCacheFileName ("data", fname, md5) + ".txt"); - safe_g_remove (getCacheFileName ("profiles", fname, md5) + paramFileExtension); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".rtti"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust16"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".jpg"); - safe_g_remove (getCacheFileName ("aehistograms", fname, md5)); - safe_g_remove (getCacheFileName ("embprofiles", fname, md5) + ".icc"); - } - } - else { - std::string md5 = getMD5 (fname); - if (md5!="") { - safe_g_remove (getCacheFileName ("data", fname, md5) + ".txt"); - safe_g_remove (getCacheFileName ("profiles", fname, md5) + paramFileExtension); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".rtti"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust16"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".jpg"); - safe_g_remove (getCacheFileName ("aehistograms", fname, md5)); - safe_g_remove (getCacheFileName ("embprofiles", fname, md5) + ".icc"); - } - } + // if in the editor, the thumbnail still exists. If not, delete it: + r = openEntries.find (fname); + + if (r == openEntries.end() && md5 != "") { + safe_g_remove (getCacheFileName ("data", fname, md5) + ".txt"); + safe_g_remove (getCacheFileName ("profiles", fname, md5) + paramFileExtension); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".rtti"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust16"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".jpg"); + safe_g_remove (getCacheFileName ("aehistograms", fname, md5)); + safe_g_remove (getCacheFileName ("embprofiles", fname, md5) + ".icc"); + } + } else { + std::string md5 = getMD5 (fname); + + if (md5 != "") { + safe_g_remove (getCacheFileName ("data", fname, md5) + ".txt"); + safe_g_remove (getCacheFileName ("profiles", fname, md5) + paramFileExtension); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".rtti"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust16"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".jpg"); + safe_g_remove (getCacheFileName ("aehistograms", fname, md5)); + safe_g_remove (getCacheFileName ("embprofiles", fname, md5) + ".icc"); + } + } } -void CacheManager::clearFromCache (const Glib::ustring& fname, bool leavenotrace) { - std::string md5 = getMD5 (fname); - if (md5!="") { - if (leavenotrace){ - safe_g_remove (getCacheFileName ("data", fname, md5) + ".txt"); - safe_g_remove (getCacheFileName ("profiles", fname, md5) + paramFileExtension); - } - safe_g_remove (getCacheFileName ("images", fname, md5) + ".rtti"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust16"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust"); - safe_g_remove (getCacheFileName ("images", fname, md5) + ".jpg"); - safe_g_remove (getCacheFileName ("aehistograms", fname, md5)); - safe_g_remove (getCacheFileName ("embprofiles", fname, md5) + ".icc"); - } +void CacheManager::clearFromCache (const Glib::ustring& fname, bool leavenotrace) +{ + std::string md5 = getMD5 (fname); + + if (md5 != "") { + if (leavenotrace) { + safe_g_remove (getCacheFileName ("data", fname, md5) + ".txt"); + safe_g_remove (getCacheFileName ("profiles", fname, md5) + paramFileExtension); + } + + safe_g_remove (getCacheFileName ("images", fname, md5) + ".rtti"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust16"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".cust"); + safe_g_remove (getCacheFileName ("images", fname, md5) + ".jpg"); + safe_g_remove (getCacheFileName ("aehistograms", fname, md5)); + safe_g_remove (getCacheFileName ("embprofiles", fname, md5) + ".icc"); + } } -void CacheManager::renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename) { +void CacheManager::renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename) +{ MyMutex::MyLock lock(mutex_); @@ -211,8 +240,9 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin // check if it is opened string_thumb_map::iterator r = openEntries.find (oldfilename); + // if it is open, update md5 - if (r!=openEntries.end()) { + if (r != openEntries.end()) { Thumbnail* t = r->second; openEntries.erase (r); t->setFileName (newfilename); @@ -222,25 +252,31 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin } } -void CacheManager::closeThumbnail (Thumbnail* t) { +void CacheManager::closeThumbnail (Thumbnail* t) +{ MyMutex::MyLock lock(mutex_); // t->updateCache (); string_thumb_map::iterator r = openEntries.find (t->getFileName()); - if (r!=openEntries.end()) + + if (r != openEntries.end()) { openEntries.erase (r); + } + delete t; } -void CacheManager::closeCache () { +void CacheManager::closeCache () +{ MyMutex::MyLock lock(mutex_); applyCacheSizeLimitation (); } -void CacheManager::clearAll () { +void CacheManager::clearAll () +{ MyMutex::MyLock lock(mutex_); @@ -249,7 +285,7 @@ void CacheManager::clearAll () { deleteDir ("embprofiles"); deleteDir ("profiles"); deleteDir ("data"); - + // re-generate thumbnail images and clear profiles of open thumbnails //string_thumb_map::iterator i; //for (i=openEntries.begin(); i!=openEntries.end(); i++) { @@ -258,7 +294,8 @@ void CacheManager::clearAll () { // i->second->updateCache (); //} } -void CacheManager::clearThumbImages () { +void CacheManager::clearThumbImages () +{ MyMutex::MyLock lock(mutex_); @@ -267,60 +304,73 @@ void CacheManager::clearThumbImages () { deleteDir ("embprofiles"); } -void CacheManager::clearProfiles () { +void CacheManager::clearProfiles () +{ MyMutex::MyLock lock(mutex_); deleteDir ("profiles"); } -void CacheManager::deleteDir (const Glib::ustring& dirName) { +void CacheManager::deleteDir (const Glib::ustring& dirName) +{ try { Glib::Dir* dir = new Glib::Dir (Glib::build_filename (baseDir, dirName)); - for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { safe_g_remove (Glib::build_filename (Glib::build_filename (baseDir, dirName), *i)); + } + delete dir; - } - catch (const Glib::Error& e) { + } catch (const Glib::Error& e) { } } -std::string CacheManager::getMD5 (const Glib::ustring& fname) { +std::string CacheManager::getMD5 (const Glib::ustring& fname) +{ Glib::RefPtr file = Gio::File::create_for_path (fname); - if (file && file->query_exists()) { - #ifdef WIN32 + if (file && file->query_exists()) { + +#ifdef WIN32 // Windows: file name + size + creation time // Safer because e.g. your camera image counter turns over. Do NOT use modified date, since tagging programs will change that wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL); WIN32_FILE_ATTRIBUTE_DATA fileAttr; - bool success=GetFileAttributesExW(wFname, GetFileExInfoStandard, &fileAttr); + bool success = GetFileAttributesExW(wFname, GetFileExInfoStandard, &fileAttr); g_free(wFname); if (success) { // Just need the low file size, since RAWs are never that large - Glib::ustring fileID= Glib::ustring::compose ("%1-%2-%3-%4", fileAttr.nFileSizeLow, fileAttr.ftCreationTime.dwHighDateTime, fileAttr.ftCreationTime.dwLowDateTime, fname ); + Glib::ustring fileID = Glib::ustring::compose ("%1-%2-%3-%4", fileAttr.nFileSizeLow, fileAttr.ftCreationTime.dwHighDateTime, fileAttr.ftCreationTime.dwLowDateTime, fname ); return Glib::Checksum::compute_checksum (Glib::Checksum::CHECKSUM_MD5, fileID); } - #else + +#else // Least common denominator: file name + size to identify a file Glib::RefPtr info = safe_query_file_info (file); - if (info) + + if (info) { return Glib::Checksum::compute_checksum (Glib::Checksum::CHECKSUM_MD5, Glib::ustring::compose ("%1%2", fname, info->get_size())); - #endif + } + +#endif } + return ""; } -Glib::ustring CacheManager::getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fname, const Glib::ustring& md5) { +Glib::ustring CacheManager::getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fname, const Glib::ustring& md5) +{ Glib::ustring cfn = Glib::build_filename (baseDir, subdir); Glib::ustring cname = Glib::path_get_basename (fname) + "." + md5; return Glib::build_filename (cfn, cname); } -void CacheManager::applyCacheSizeLimitation () { +void CacheManager::applyCacheSizeLimitation () +{ // TODO: Improve this, it just blindly deletes image without looking at create time or something to keep the current ones std::vector flist; @@ -331,6 +381,7 @@ void CacheManager::applyCacheSizeLimitation () { if (flist.size() > options.maxCacheEntries) { std::sort (flist.begin(), flist.end()); + while (flist.size() > options.maxCacheEntries) { safe_g_remove (Glib::build_filename (Glib::build_filename (baseDir, "data"), flist.front().fname) + ".txt"); safe_g_remove (Glib::build_filename (Glib::build_filename (baseDir, "images"), flist.front().fname) + ".rtti"); diff --git a/rtgui/cachemanager.h b/rtgui/cachemanager.h index 6173e1c80..159964104 100644 --- a/rtgui/cachemanager.h +++ b/rtgui/cachemanager.h @@ -7,7 +7,7 @@ * 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 @@ -29,43 +29,48 @@ class Thumbnail; -class CacheManager { +class CacheManager +{ - typedef std::pair string_thumb_pair; - typedef std::map string_thumb_map; + typedef std::pair string_thumb_pair; + typedef std::map string_thumb_map; - string_thumb_map openEntries; - Glib::ustring baseDir; - MyMutex mutex_; + string_thumb_map openEntries; + Glib::ustring baseDir; + MyMutex mutex_; - void deleteDir (const Glib::ustring& dirName); + void deleteDir (const Glib::ustring& dirName); - CacheManager () {} + CacheManager () {} - public: +public: - static CacheManager* getInstance(void); + static CacheManager* getInstance(void); - void init (); - Thumbnail* getEntry (const Glib::ustring& fname); - void deleteEntry (const Glib::ustring& fname); - void renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename); + void init (); + Thumbnail* getEntry (const Glib::ustring& fname); + void deleteEntry (const Glib::ustring& fname); + void renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename); - void closeThumbnail (Thumbnail* t); + void closeThumbnail (Thumbnail* t); - const Glib::ustring& getBaseDir () { MyMutex::MyLock lock(mutex_); return baseDir; } - void closeCache (); + const Glib::ustring& getBaseDir () + { + MyMutex::MyLock lock(mutex_); + return baseDir; + } + void closeCache (); - static std::string getMD5 (const Glib::ustring& fname); + static std::string getMD5 (const Glib::ustring& fname); - void clearAll (); - void clearThumbImages (); - void clearProfiles (); - void clearFromCache(const Glib::ustring& fname, bool leavenotrace); + void clearAll (); + void clearThumbImages (); + void clearProfiles (); + void clearFromCache(const Glib::ustring& fname, bool leavenotrace); - void applyCacheSizeLimitation (); + void applyCacheSizeLimitation (); - Glib::ustring getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fname, const Glib::ustring& md5); + Glib::ustring getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fname, const Glib::ustring& md5); }; #define cacheMgr CacheManager::getInstance() diff --git a/rtgui/cacorrection.cc b/rtgui/cacorrection.cc index 1cf0429d1..e303b5660 100644 --- a/rtgui/cacorrection.cc +++ b/rtgui/cacorrection.cc @@ -7,7 +7,7 @@ * 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 @@ -23,7 +23,8 @@ using namespace rtengine; using namespace rtengine::procparams; -CACorrection::CACorrection () : FoldableToolPanel(this, "cacorrection", M("TP_CACORRECTION_LABEL")) { +CACorrection::CACorrection () : FoldableToolPanel(this, "cacorrection", M("TP_CACORRECTION_LABEL")) +{ Gtk::Image* icaredL = Gtk::manage (new RTImage ("ajd-ca-red1.png")); Gtk::Image* icaredR = Gtk::manage (new RTImage ("ajd-ca-red2.png")); @@ -31,10 +32,10 @@ CACorrection::CACorrection () : FoldableToolPanel(this, "cacorrection", M("TP_CA Gtk::Image* icablueR = Gtk::manage (new RTImage ("ajd-ca-blue2.png")); red = Gtk::manage (new Adjuster (M("TP_CACORRECTION_RED"), -0.005, 0.005, 0.0001, 0, icaredL, icaredR)); - red->setAdjusterListener (this); + red->setAdjusterListener (this); blue = Gtk::manage (new Adjuster (M("TP_CACORRECTION_BLUE"), -0.005, 0.005, 0.0001, 0, icablueL, icablueR)); - blue->setAdjusterListener (this); + blue->setAdjusterListener (this); pack_start (*red); pack_start (*blue); @@ -42,7 +43,8 @@ CACorrection::CACorrection () : FoldableToolPanel(this, "cacorrection", M("TP_CA show_all(); } -void CACorrection::read (const ProcParams* pp, const ParamsEdited* pedited) { +void CACorrection::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -53,11 +55,12 @@ void CACorrection::read (const ProcParams* pp, const ParamsEdited* pedited) { red->setValue (pp->cacorrection.red); blue->setValue (pp->cacorrection.blue); - + enableListener (); } -void CACorrection::write (ProcParams* pp, ParamsEdited* pedited) { +void CACorrection::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->cacorrection.red = red->getValue (); pp->cacorrection.blue = blue->getValue (); @@ -68,7 +71,8 @@ void CACorrection::write (ProcParams* pp, ParamsEdited* pedited) { } } -void CACorrection::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void CACorrection::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ red->setDefault (defParams->cacorrection.red); blue->setDefault (defParams->cacorrection.blue); @@ -76,32 +80,36 @@ void CACorrection::setDefaults (const ProcParams* defParams, const ParamsEdited* if (pedited) { red->setDefaultEditedState (pedited->cacorrection.red ? Edited : UnEdited); blue->setDefaultEditedState (pedited->cacorrection.blue ? Edited : UnEdited); - } - else { + } else { red->setDefaultEditedState (Irrelevant); blue->setDefaultEditedState (Irrelevant); } } -void CACorrection::adjusterChanged (Adjuster* a, double newval) { +void CACorrection::adjusterChanged (Adjuster* a, double newval) +{ - if (listener) + if (listener) { listener->panelChanged (EvCACorr, Glib::ustring::compose ("%1=%3\n%2=%4", M("TP_CACORRECTION_RED"), M("TP_CACORRECTION_BLUE"), Glib::ustring::format (std::setw(5), std::fixed, std::setprecision(4), red->getValue()), Glib::ustring::format (std::setw(5), std::fixed, std::setprecision(4), blue->getValue()))); + } } -void CACorrection::setAdjusterBehavior (bool badd) { +void CACorrection::setAdjusterBehavior (bool badd) +{ - red->setAddMode(badd); - blue->setAddMode(badd); + red->setAddMode(badd); + blue->setAddMode(badd); } -void CACorrection::trimValues (rtengine::procparams::ProcParams* pp) { +void CACorrection::trimValues (rtengine::procparams::ProcParams* pp) +{ - red->trimValue(pp->cacorrection.red); - blue->trimValue(pp->cacorrection.blue); + red->trimValue(pp->cacorrection.red); + blue->trimValue(pp->cacorrection.blue); } -void CACorrection::setBatchMode (bool batchMode) { +void CACorrection::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); red->showEditedCB (); diff --git a/rtgui/cacorrection.h b/rtgui/cacorrection.h index f0d77d286..736242232 100644 --- a/rtgui/cacorrection.h +++ b/rtgui/cacorrection.h @@ -7,7 +7,7 @@ * 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 @@ -23,19 +23,20 @@ #include "adjuster.h" #include "toolpanel.h" -class CACorrection : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class CACorrection : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* red; Adjuster* blue; - public: +public: CACorrection (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/chmixer.cc b/rtgui/chmixer.cc index e74fa6c80..356a274e8 100644 --- a/rtgui/chmixer.cc +++ b/rtgui/chmixer.cc @@ -7,7 +7,7 @@ * 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 @@ -22,7 +22,8 @@ using namespace rtengine; using namespace rtengine::procparams; -ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL")) { +ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL")) +{ imgIcon[0] = Gtk::manage (new RTImage ("Chanmixer-RR.png")); imgIcon[1] = Gtk::manage (new RTImage ("Chanmixer-RG.png")); @@ -45,8 +46,11 @@ ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL")) { Gtk::HSeparator* rsep = Gtk::manage (new Gtk::HSeparator ()); pack_start (*rlabel); - for (int i=0; i<3; i++) + + for (int i = 0; i < 3; i++) { pack_start (*red[i]); + } + pack_start (*rsep, Gtk::PACK_EXPAND_WIDGET, 4); Gtk::Label* glabel = Gtk::manage (new Gtk::Label ()); @@ -61,8 +65,11 @@ ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL")) { Gtk::HSeparator* gsep = Gtk::manage (new Gtk::HSeparator ()); pack_start (*glabel); - for (int i=0; i<3; i++) + + for (int i = 0; i < 3; i++) { pack_start (*green[i]); + } + pack_start (*gsep, Gtk::PACK_EXPAND_WIDGET, 4); Gtk::Label* blabel = Gtk::manage (new Gtk::Label ()); @@ -72,31 +79,34 @@ ChMixer::ChMixer (): FoldableToolPanel(this, "chmixer", M("TP_CHMIXER_LABEL")) { blue[1] = Gtk::manage (new Adjuster ("", -200, 200, 1, 0, imgIcon[7])); blue[2] = Gtk::manage (new Adjuster ("", -200, 200, 1, 100, imgIcon[8])); - for (int i=0; i<3; i++) { - red[i]->setAdjusterListener (this); - green[i]->setAdjusterListener (this); - blue[i]->setAdjusterListener (this); + for (int i = 0; i < 3; i++) { + red[i]->setAdjusterListener (this); + green[i]->setAdjusterListener (this); + blue[i]->setAdjusterListener (this); } pack_start (*blabel); - for (int i=0; i<3; i++) + + for (int i = 0; i < 3; i++) { pack_start (*blue[i]); + } show_all(); } -void ChMixer::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ChMixer::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); - if (pedited) - for (int i=0; i<3; i++) { + if (pedited) + for (int i = 0; i < 3; i++) { red[i]->setEditedState (pedited->chmixer.red[i] ? Edited : UnEdited); green[i]->setEditedState (pedited->chmixer.green[i] ? Edited : UnEdited); blue[i]->setEditedState (pedited->chmixer.blue[i] ? Edited : UnEdited); } - for (int i=0; i<3; i++) { + for (int i = 0; i < 3; i++) { red[i]->setValue (pp->chmixer.red[i]); green[i]->setValue (pp->chmixer.green[i]); blue[i]->setValue (pp->chmixer.blue[i]); @@ -105,79 +115,86 @@ void ChMixer::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void ChMixer::write (ProcParams* pp, ParamsEdited* pedited) { +void ChMixer::write (ProcParams* pp, ParamsEdited* pedited) +{ - for (int i=0; i<3; i++) { + for (int i = 0; i < 3; i++) { pp->chmixer.red[i] = (int) red[i]->getValue (); pp->chmixer.green[i] = (int) green[i]->getValue (); pp->chmixer.blue[i] = (int) blue[i]->getValue (); } - - if (pedited) - for (int i=0; i<3; i++) { + + if (pedited) + for (int i = 0; i < 3; i++) { pedited->chmixer.red[i] = red[i]->getEditedState (); pedited->chmixer.green[i] = green[i]->getEditedState (); pedited->chmixer.blue[i] = blue[i]->getEditedState (); } } -void ChMixer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ChMixer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ - for (int i=0; i<3; i++) { + for (int i = 0; i < 3; i++) { red[i]->setDefault (defParams->chmixer.red[i]); green[i]->setDefault (defParams->chmixer.green[i]); blue[i]->setDefault (defParams->chmixer.blue[i]); } - - if (pedited) - for (int i=0; i<3; i++) { + + if (pedited) + for (int i = 0; i < 3; i++) { red[i]->setDefaultEditedState (pedited->chmixer.red[i] ? Edited : UnEdited); green[i]->setDefaultEditedState (pedited->chmixer.green[i] ? Edited : UnEdited); blue[i]->setDefaultEditedState (pedited->chmixer.blue[i] ? Edited : UnEdited); } - else - for (int i=0; i<3; i++) { + else + for (int i = 0; i < 3; i++) { red[i]->setDefaultEditedState (Irrelevant); green[i]->setDefaultEditedState (Irrelevant); blue[i]->setDefaultEditedState (Irrelevant); } } -void ChMixer::adjusterChanged (Adjuster* a, double newval) { +void ChMixer::adjusterChanged (Adjuster* a, double newval) +{ if (listener) { Glib::ustring descr = Glib::ustring::compose ("R=%1,%2,%3\nG=%4,%5,%6\nB=%7,%8,%9", - (int)red[0]->getValue(), (int)red[1]->getValue(), (int)red[2]->getValue(), - (int)green[0]->getValue(), (int)green[1]->getValue(), (int)green[2]->getValue(), - (int)blue[0]->getValue(), (int)blue[1]->getValue(), (int)blue[2]->getValue()); + (int)red[0]->getValue(), (int)red[1]->getValue(), (int)red[2]->getValue(), + (int)green[0]->getValue(), (int)green[1]->getValue(), (int)green[2]->getValue(), + (int)blue[0]->getValue(), (int)blue[1]->getValue(), (int)blue[2]->getValue()); listener->panelChanged (EvChMixer, descr); } } -void ChMixer::setBatchMode (bool batchMode) { +void ChMixer::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); - for (int i=0; i<3; i++) { + + for (int i = 0; i < 3; i++) { red[i]->showEditedCB (); green[i]->showEditedCB (); blue[i]->showEditedCB (); } } -void ChMixer::setAdjusterBehavior (bool rgbadd) { +void ChMixer::setAdjusterBehavior (bool rgbadd) +{ - for (int i=0; i<3; i++) { - red[i]->setAddMode(rgbadd); - green[i]->setAddMode(rgbadd); - blue[i]->setAddMode(rgbadd); - } + for (int i = 0; i < 3; i++) { + red[i]->setAddMode(rgbadd); + green[i]->setAddMode(rgbadd); + blue[i]->setAddMode(rgbadd); + } } -void ChMixer::trimValues (rtengine::procparams::ProcParams* pp) { +void ChMixer::trimValues (rtengine::procparams::ProcParams* pp) +{ - for (int i=0; i<3; i++) { - red[i]->trimValue(pp->chmixer.red[i]); - green[i]->trimValue(pp->chmixer.green[i]); - blue[i]->trimValue(pp->chmixer.blue[i]); - } + for (int i = 0; i < 3; i++) { + red[i]->trimValue(pp->chmixer.red[i]); + green[i]->trimValue(pp->chmixer.green[i]); + blue[i]->trimValue(pp->chmixer.blue[i]); + } } diff --git a/rtgui/chmixer.h b/rtgui/chmixer.h index 73ee7a865..0bf65736a 100644 --- a/rtgui/chmixer.h +++ b/rtgui/chmixer.h @@ -7,7 +7,7 @@ * 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 @@ -23,21 +23,22 @@ #include "adjuster.h" #include "toolpanel.h" -class ChMixer : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class ChMixer : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster *red[3]; Adjuster *green[3]; Adjuster *blue[3]; Gtk::Image *imgIcon[9]; - public: +public: ChMixer (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/clipboard.cc b/rtgui/clipboard.cc index 175c64c92..ad3ea6386 100644 --- a/rtgui/clipboard.cc +++ b/rtgui/clipboard.cc @@ -7,7 +7,7 @@ * 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 @@ -22,48 +22,58 @@ Clipboard clipboard; Clipboard::Clipboard () : partProfile (false) {} -Clipboard::~Clipboard () { - partProfile.deleteInstance(); +Clipboard::~Clipboard () +{ + partProfile.deleteInstance(); } /* * set both the "pparams" and "pedited" field of the PartialProfile; each one can be NULL */ -void Clipboard::setPartialProfile (const rtengine::procparams::PartialProfile& pprofile) { - if (pprofile.pparams) { - if (!partProfile.pparams) partProfile.pparams = new rtengine::procparams::ProcParams(); - *partProfile.pparams = *pprofile.pparams; - } - else { - if (partProfile.pparams) { - delete partProfile.pparams; - partProfile.pparams = NULL; - } - } +void Clipboard::setPartialProfile (const rtengine::procparams::PartialProfile& pprofile) +{ + if (pprofile.pparams) { + if (!partProfile.pparams) { + partProfile.pparams = new rtengine::procparams::ProcParams(); + } - if (pprofile.pedited) { - if (!partProfile.pedited) partProfile.pedited = new ParamsEdited(); - *partProfile.pedited = *pprofile.pedited; - } - else { - if (partProfile.pedited) { - delete partProfile.pedited; - partProfile.pedited = NULL; - } - } + *partProfile.pparams = *pprofile.pparams; + } else { + if (partProfile.pparams) { + delete partProfile.pparams; + partProfile.pparams = NULL; + } + } + + if (pprofile.pedited) { + if (!partProfile.pedited) { + partProfile.pedited = new ParamsEdited(); + } + + *partProfile.pedited = *pprofile.pedited; + } else { + if (partProfile.pedited) { + delete partProfile.pedited; + partProfile.pedited = NULL; + } + } } /* * this method copy the procparams to "pparams" and delete "pedited" */ -void Clipboard::setProcParams (const rtengine::procparams::ProcParams& pparams) { - // copy procparams - if (!partProfile.pparams) partProfile.pparams = new rtengine::procparams::ProcParams(); - *partProfile.pparams = pparams; +void Clipboard::setProcParams (const rtengine::procparams::ProcParams& pparams) +{ + // copy procparams + if (!partProfile.pparams) { + partProfile.pparams = new rtengine::procparams::ProcParams(); + } - // delete pedited - if (partProfile.pedited) { - delete partProfile.pedited; - partProfile.pedited = NULL; - } + *partProfile.pparams = pparams; + + // delete pedited + if (partProfile.pedited) { + delete partProfile.pedited; + partProfile.pedited = NULL; + } } diff --git a/rtgui/clipboard.h b/rtgui/clipboard.h index 4934cdf81..eff5c08c8 100644 --- a/rtgui/clipboard.h +++ b/rtgui/clipboard.h @@ -7,7 +7,7 @@ * 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 @@ -26,7 +26,8 @@ #include "myflatcurve.h" #include "mydiagonalcurve.h" -class Clipboard { +class Clipboard +{ bool _hasIPTC; rtengine::procparams::IPTCPairs iptc; @@ -37,29 +38,76 @@ class Clipboard { std::vector flatCurve; - public: - void setIPTC (const rtengine::procparams::IPTCPairs& iptcc) { iptc = iptcc; _hasIPTC = true;} - const rtengine::procparams::IPTCPairs& getIPTC () { return iptc; } - bool hasIPTC () { return _hasIPTC; } +public: + void setIPTC (const rtengine::procparams::IPTCPairs& iptcc) + { + iptc = iptcc; + _hasIPTC = true; + } + const rtengine::procparams::IPTCPairs& getIPTC () + { + return iptc; + } + bool hasIPTC () + { + return _hasIPTC; + } - void setPartialProfile (const rtengine::procparams::PartialProfile& pprofile); - const rtengine::procparams::PartialProfile& getPartialProfile () { return partProfile; }; - void setProcParams (const rtengine::procparams::ProcParams& pparams); - const rtengine::procparams::ProcParams& getProcParams () { return *partProfile.pparams; } - const ParamsEdited& getParamsEdited () { return *partProfile.pedited; } - bool hasProcParams () { return partProfile.pparams; } - bool hasPEdited () { return partProfile.pedited; } + void setPartialProfile (const rtengine::procparams::PartialProfile& pprofile); + const rtengine::procparams::PartialProfile& getPartialProfile () + { + return partProfile; + }; + void setProcParams (const rtengine::procparams::ProcParams& pparams); + const rtengine::procparams::ProcParams& getProcParams () + { + return *partProfile.pparams; + } + const ParamsEdited& getParamsEdited () + { + return *partProfile.pedited; + } + bool hasProcParams () + { + return partProfile.pparams; + } + bool hasPEdited () + { + return partProfile.pedited; + } - void setDiagonalCurveData (std::vector& p, DiagonalCurveType type ) { diagonalCurve = p; hasDiagonalCurveDataType = type; return; } - const std::vector & getDiagonalCurveData () { return diagonalCurve; } - DiagonalCurveType hasDiagonalCurveData () { return hasDiagonalCurveDataType; } + void setDiagonalCurveData (std::vector& p, DiagonalCurveType type ) + { + diagonalCurve = p; + hasDiagonalCurveDataType = type; + return; + } + const std::vector & getDiagonalCurveData () + { + return diagonalCurve; + } + DiagonalCurveType hasDiagonalCurveData () + { + return hasDiagonalCurveDataType; + } - void setFlatCurveData (std::vector& p, FlatCurveType type ) { flatCurve = p; hasFlatCurveDataType = type; return; } - const std::vector & getFlatCurveData () { return flatCurve; } - FlatCurveType hasFlatCurveData () { return hasFlatCurveDataType; } + void setFlatCurveData (std::vector& p, FlatCurveType type ) + { + flatCurve = p; + hasFlatCurveDataType = type; + return; + } + const std::vector & getFlatCurveData () + { + return flatCurve; + } + FlatCurveType hasFlatCurveData () + { + return hasFlatCurveDataType; + } - Clipboard (); - ~Clipboard (); + Clipboard (); + ~Clipboard (); }; diff --git a/rtgui/coarsepanel.cc b/rtgui/coarsepanel.cc index 44e19d870..63a9251fb 100644 --- a/rtgui/coarsepanel.cc +++ b/rtgui/coarsepanel.cc @@ -7,7 +7,7 @@ * 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 @@ -22,7 +22,8 @@ using namespace rtengine; using namespace rtengine::procparams; -CoarsePanel::CoarsePanel () : ToolPanel () { +CoarsePanel::CoarsePanel () : ToolPanel () +{ degree = 0; degreechanged = true; @@ -50,7 +51,7 @@ CoarsePanel::CoarsePanel () : ToolPanel () { vflip->add (*flipvi); vflip->set_relief(Gtk::RELIEF_NONE); pack_start (*vflip); - + rotate_left->set_tooltip_markup (M("TP_COARSETRAF_TOOLTIP_ROTLEFT")); rotate_right->set_tooltip_markup (M("TP_COARSETRAF_TOOLTIP_ROTRIGHT")); vflip->set_tooltip_text (M("TP_COARSETRAF_TOOLTIP_VFLIP")); @@ -64,7 +65,8 @@ CoarsePanel::CoarsePanel () : ToolPanel () { show_all_children (); } -void CoarsePanel::read (const ProcParams* pp, const ParamsEdited* pedited) { +void CoarsePanel::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -76,27 +78,30 @@ void CoarsePanel::read (const ProcParams* pp, const ParamsEdited* pedited) { degreechanged = false; oldhflip = pp->coarse.hflip; oldvflip = pp->coarse.vflip; - } - else { + } else { hflip->set_active (pp->coarse.hflip); vflip->set_active (pp->coarse.vflip); } + enableListener (); } -void CoarsePanel::write (ProcParams* pp, ParamsEdited* pedited) { +void CoarsePanel::write (ProcParams* pp, ParamsEdited* pedited) +{ if (pedited) { pedited->coarse.rotate = degreechanged; pedited->coarse.hflip = oldhflip != hflip->get_active (); pedited->coarse.vflip = oldvflip != vflip->get_active (); } + pp->coarse.rotate = degree; pp->coarse.hflip = hflip->get_active (); pp->coarse.vflip = vflip->get_active (); } -void CoarsePanel::initBatchBehavior () { +void CoarsePanel::initBatchBehavior () +{ disableListener (); @@ -107,47 +112,61 @@ void CoarsePanel::initBatchBehavior () { enableListener (); } -void CoarsePanel::rotateLeft () { +void CoarsePanel::rotateLeft () +{ //Rotate one way or the opposite depending if the image is already flipped or not - if ( (vflip->get_active()) == (hflip->get_active ()) ) - degree = (degree + 270) % 360; - else - degree = (degree + 90) % 360; + if ( (vflip->get_active()) == (hflip->get_active ()) ) { + degree = (degree + 270) % 360; + } else { + degree = (degree + 90) % 360; + } + degreechanged = true; - if (listener) - listener->panelChanged (EvCTRotate, Glib::ustring::format (degree)); -} - -void CoarsePanel::rotateRight () { - - //Rotate one way or the opposite depending if the image is already flipped or not - if ( (vflip->get_active()) == (hflip->get_active ()) ) - degree = (degree + 90) % 360; - else - degree = (degree + 270) % 360; - degreechanged = true; - if (listener) - listener->panelChanged (EvCTRotate, Glib::ustring::format (degree)); -} - -void CoarsePanel::flipHorizontal () { if (listener) { - if (hflip->get_active ()) + listener->panelChanged (EvCTRotate, Glib::ustring::format (degree)); + } +} + +void CoarsePanel::rotateRight () +{ + + //Rotate one way or the opposite depending if the image is already flipped or not + if ( (vflip->get_active()) == (hflip->get_active ()) ) { + degree = (degree + 90) % 360; + } else { + degree = (degree + 270) % 360; + } + + degreechanged = true; + + if (listener) { + listener->panelChanged (EvCTRotate, Glib::ustring::format (degree)); + } +} + +void CoarsePanel::flipHorizontal () +{ + + if (listener) { + if (hflip->get_active ()) { listener->panelChanged (EvCTHFlip, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvCTHFlip, M("GENERAL_DISABLED")); + } } } -void CoarsePanel::flipVertical () { +void CoarsePanel::flipVertical () +{ if (listener) { - if (vflip->get_active ()) + if (vflip->get_active ()) { listener->panelChanged (EvCTVFlip, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvCTVFlip, M("GENERAL_DISABLED")); + } } } diff --git a/rtgui/coarsepanel.h b/rtgui/coarsepanel.h index 1fb19db81..abe31d518 100644 --- a/rtgui/coarsepanel.h +++ b/rtgui/coarsepanel.h @@ -7,7 +7,7 @@ * 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 @@ -22,28 +22,29 @@ #include #include "toolpanel.h" -class CoarsePanel : public Gtk::HBox, public ToolPanel { +class CoarsePanel : public Gtk::HBox, public ToolPanel +{ - protected: - Gtk::Button* rotate_left; - Gtk::Button* rotate_right; - Gtk::ToggleButton* hflip; - Gtk::ToggleButton* vflip; - int degree; - bool oldhflip, oldvflip, degreechanged; +protected: + Gtk::Button* rotate_left; + Gtk::Button* rotate_right; + Gtk::ToggleButton* hflip; + Gtk::ToggleButton* vflip; + int degree; + bool oldhflip, oldvflip, degreechanged; - public: +public: - CoarsePanel (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void initBatchBehavior (); - - void rotateLeft (); - void rotateRight (); - void flipHorizontal (); - void flipVertical (); + CoarsePanel (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void initBatchBehavior (); + + void rotateLeft (); + void rotateRight (); + void flipHorizontal (); + void flipVertical (); }; #endif diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index e7ddfed21..4c85ca32e 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -7,7 +7,7 @@ * 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 @@ -24,1174 +24,1322 @@ using namespace rtengine; using namespace rtengine::procparams; -ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", M("TP_COLORAPP_LABEL"), false, true) { - CurveListener::setMulti(true); - std::vector milestones; - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); +ColorAppearance::ColorAppearance () : FoldableToolPanel(this, "colorappearance", M("TP_COLORAPP_LABEL"), false, true) +{ + CurveListener::setMulti(true); + std::vector milestones; + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - // ------------------------ Process #1: Converting to CIECAM + // ------------------------ Process #1: Converting to CIECAM - // Process 1 frame - Gtk::Frame *p1Frame; - // Vertical box container for the content of the Process 1 frame - Gtk::VBox *p1VBox; + // Process 1 frame + Gtk::Frame *p1Frame; + // Vertical box container for the content of the Process 1 frame + Gtk::VBox *p1VBox; - p1Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_SCENE")) ); - p1Frame->set_border_width(0); - p1Frame->set_label_align(0.025, 0.5); + p1Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_SCENE")) ); + p1Frame->set_border_width(0); + p1Frame->set_label_align(0.025, 0.5); - p1VBox = Gtk::manage ( new Gtk::VBox()); - p1VBox->set_border_width(4); - p1VBox->set_spacing(2); + p1VBox = Gtk::manage ( new Gtk::VBox()); + p1VBox->set_border_width(4); + p1VBox->set_spacing(2); - degree = Gtk::manage (new Adjuster (M("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 100.)); - if (degree->delay < 1000) degree->delay = 1000; - degree->throwOnButtonRelease(); - degree->addAutoButton(M("TP_COLORAPP_DEGREE_AUTO_TOOLTIP")); - degree->set_tooltip_markup (M("TP_COLORAPP_DEGREE_TOOLTIP")); - p1VBox->pack_start (*degree); + degree = Gtk::manage (new Adjuster (M("TP_COLORAPP_CIECAT_DEGREE"), 0., 100., 1., 100.)); - surrsource = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_SURSOURCE"))); - surrsource->set_tooltip_markup (M("TP_COLORAPP_SURSOURCE_TOOLTIP")); - p1VBox->pack_start (*surrsource, Gtk::PACK_SHRINK); + if (degree->delay < 1000) { + degree->delay = 1000; + } - Gtk::HBox* wbmHBox = Gtk::manage (new Gtk::HBox ()); - wbmHBox->set_border_width (0); - wbmHBox->set_spacing (2); - wbmHBox->set_tooltip_markup (M("TP_COLORAPP_MODEL_TOOLTIP")); - Gtk::Label* wbmLab = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_MODEL")+":")); - wbmHBox->pack_start (*wbmLab, Gtk::PACK_SHRINK); - wbmodel = Gtk::manage (new MyComboBoxText ()); - wbmodel->append_text (M("TP_COLORAPP_WBRT")); - wbmodel->append_text (M("TP_COLORAPP_WBCAM")); - wbmodel->set_active (0); - wbmHBox->pack_start (*wbmodel); - p1VBox->pack_start (*wbmHBox); + degree->throwOnButtonRelease(); + degree->addAutoButton(M("TP_COLORAPP_DEGREE_AUTO_TOOLTIP")); + degree->set_tooltip_markup (M("TP_COLORAPP_DEGREE_TOOLTIP")); + p1VBox->pack_start (*degree); - adapscen = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTSCENE"), 0.001, 16384., 0.001, 2000.));// EV -7 ==> EV 17 - if (adapscen->delay < 1000) adapscen->delay = 1000; - adapscen->throwOnButtonRelease(); - adapscen->addAutoButton(M("TP_COLORAPP_ADAP_AUTO_TOOLTIP")); - adapscen->set_tooltip_markup (M("TP_COLORAPP_ADAPTSCENE_TOOLTIP")); - p1VBox->pack_start (*adapscen); + surrsource = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_SURSOURCE"))); + surrsource->set_tooltip_markup (M("TP_COLORAPP_SURSOURCE_TOOLTIP")); + p1VBox->pack_start (*surrsource, Gtk::PACK_SHRINK); - p1Frame->add(*p1VBox); - pack_start (*p1Frame, Gtk::PACK_EXPAND_WIDGET, 4); + Gtk::HBox* wbmHBox = Gtk::manage (new Gtk::HBox ()); + wbmHBox->set_border_width (0); + wbmHBox->set_spacing (2); + wbmHBox->set_tooltip_markup (M("TP_COLORAPP_MODEL_TOOLTIP")); + Gtk::Label* wbmLab = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_MODEL") + ":")); + wbmHBox->pack_start (*wbmLab, Gtk::PACK_SHRINK); + wbmodel = Gtk::manage (new MyComboBoxText ()); + wbmodel->append_text (M("TP_COLORAPP_WBRT")); + wbmodel->append_text (M("TP_COLORAPP_WBCAM")); + wbmodel->set_active (0); + wbmHBox->pack_start (*wbmodel); + p1VBox->pack_start (*wbmHBox); + + adapscen = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTSCENE"), 0.001, 16384., 0.001, 2000.));// EV -7 ==> EV 17 + + if (adapscen->delay < 1000) { + adapscen->delay = 1000; + } + + adapscen->throwOnButtonRelease(); + adapscen->addAutoButton(M("TP_COLORAPP_ADAP_AUTO_TOOLTIP")); + adapscen->set_tooltip_markup (M("TP_COLORAPP_ADAPTSCENE_TOOLTIP")); + p1VBox->pack_start (*adapscen); + + p1Frame->add(*p1VBox); + pack_start (*p1Frame, Gtk::PACK_EXPAND_WIDGET, 4); - // ------------------------ Process #2: Modifying image inside CIECAM + // ------------------------ Process #2: Modifying image inside CIECAM - // Process 1 frame - Gtk::Frame *p2Frame; - // Vertical box container for the content of the Process 1 frame - Gtk::VBox *p2VBox; + // Process 1 frame + Gtk::Frame *p2Frame; + // Vertical box container for the content of the Process 1 frame + Gtk::VBox *p2VBox; - p2Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_CAM02")) ); - p2Frame->set_border_width(0); - p2Frame->set_label_align(0.025, 0.5); + p2Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_CAM02")) ); + p2Frame->set_border_width(0); + p2Frame->set_label_align(0.025, 0.5); - p2VBox = Gtk::manage ( new Gtk::VBox()); - p2VBox->set_border_width(4); - p2VBox->set_spacing(2); + p2VBox = Gtk::manage ( new Gtk::VBox()); + p2VBox->set_border_width(4); + p2VBox->set_spacing(2); - Gtk::HBox* alHBox = Gtk::manage (new Gtk::HBox ()); - alHBox->set_border_width (0); - alHBox->set_spacing (2); - alHBox->set_tooltip_markup (M("TP_COLORAPP_ALGO_TOOLTIP")); - Gtk::Label* alLabel = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_ALGO")+":")); - alHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); - algo = Gtk::manage (new MyComboBoxText ()); - algo->append_text (M("TP_COLORAPP_ALGO_JC")); - algo->append_text (M("TP_COLORAPP_ALGO_JS")); - algo->append_text (M("TP_COLORAPP_ALGO_QM")); - algo->append_text (M("TP_COLORAPP_ALGO_ALL")); - algo->set_active (0); - alHBox->pack_start (*algo); - p2VBox->pack_start (*alHBox); + Gtk::HBox* alHBox = Gtk::manage (new Gtk::HBox ()); + alHBox->set_border_width (0); + alHBox->set_spacing (2); + alHBox->set_tooltip_markup (M("TP_COLORAPP_ALGO_TOOLTIP")); + Gtk::Label* alLabel = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_ALGO") + ":")); + alHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); + algo = Gtk::manage (new MyComboBoxText ()); + algo->append_text (M("TP_COLORAPP_ALGO_JC")); + algo->append_text (M("TP_COLORAPP_ALGO_JS")); + algo->append_text (M("TP_COLORAPP_ALGO_QM")); + algo->append_text (M("TP_COLORAPP_ALGO_ALL")); + algo->set_active (0); + alHBox->pack_start (*algo); + p2VBox->pack_start (*alHBox); - p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); + p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); - jlight = Gtk::manage (new Adjuster (M("TP_COLORAPP_LIGHT"), -100.0, 100.0, 0.1, 0.)); - if (jlight->delay < 1000) jlight->delay = 1000; - jlight->throwOnButtonRelease(); - jlight->set_tooltip_markup (M("TP_COLORAPP_LIGHT_TOOLTIP")); - p2VBox->pack_start (*jlight); + jlight = Gtk::manage (new Adjuster (M("TP_COLORAPP_LIGHT"), -100.0, 100.0, 0.1, 0.)); - qbright = Gtk::manage (new Adjuster (M("TP_COLORAPP_BRIGHT"), -100.0, 100.0, 0.1, 0.)); - if (qbright->delay < 1000) qbright->delay = 1000; - qbright->throwOnButtonRelease(); - qbright->set_tooltip_markup (M("TP_COLORAPP_BRIGHT_TOOLTIP")); - p2VBox->pack_start (*qbright); + if (jlight->delay < 1000) { + jlight->delay = 1000; + } - chroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA"), -100.0, 100.0, 0.1, 0.)); - if (chroma->delay < 1000) chroma->delay = 1000; - chroma->throwOnButtonRelease(); - chroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_TOOLTIP")); - p2VBox->pack_start (*chroma); + jlight->throwOnButtonRelease(); + jlight->set_tooltip_markup (M("TP_COLORAPP_LIGHT_TOOLTIP")); + p2VBox->pack_start (*jlight); + + qbright = Gtk::manage (new Adjuster (M("TP_COLORAPP_BRIGHT"), -100.0, 100.0, 0.1, 0.)); + + if (qbright->delay < 1000) { + qbright->delay = 1000; + } + + qbright->throwOnButtonRelease(); + qbright->set_tooltip_markup (M("TP_COLORAPP_BRIGHT_TOOLTIP")); + p2VBox->pack_start (*qbright); + + chroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA"), -100.0, 100.0, 0.1, 0.)); + + if (chroma->delay < 1000) { + chroma->delay = 1000; + } + + chroma->throwOnButtonRelease(); + chroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_TOOLTIP")); + p2VBox->pack_start (*chroma); - schroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_S"), -100.0, 100.0, 0.1, 0.)); - if (schroma->delay < 1000) schroma->delay = 1000; - schroma->throwOnButtonRelease(); - schroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_S_TOOLTIP")); - p2VBox->pack_start (*schroma); + schroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_S"), -100.0, 100.0, 0.1, 0.)); - mchroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_M"), -100.0, 100.0, 0.1, 0.)); - if (mchroma->delay < 1000) mchroma->delay = 1000; - mchroma->throwOnButtonRelease(); - mchroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_M_TOOLTIP")); - p2VBox->pack_start (*mchroma); - - rstprotection = Gtk::manage ( new Adjuster (M("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) ); - if (rstprotection->delay < 1000) rstprotection->delay = 1000; - rstprotection->throwOnButtonRelease(); - rstprotection->set_tooltip_markup (M("TP_COLORAPP_RSTPRO_TOOLTIP")); - p2VBox->pack_start (*rstprotection); + if (schroma->delay < 1000) { + schroma->delay = 1000; + } - contrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST"), -100.0, 100.0, 0.1, 0.)); - if (contrast->delay < 1000) contrast->delay = 1000; - contrast->throwOnButtonRelease(); - contrast->set_tooltip_markup (M("TP_COLORAPP_CONTRAST_TOOLTIP")); - p2VBox->pack_start (*contrast); + schroma->throwOnButtonRelease(); + schroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_S_TOOLTIP")); + p2VBox->pack_start (*schroma); - qcontrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST_Q"), -100.0, 100.0, 0.1, 0.)); - if (qcontrast->delay < 1000) qcontrast->delay = 1000; - qcontrast->throwOnButtonRelease(); - qcontrast->set_tooltip_markup (M("TP_COLORAPP_CONTRAST_Q_TOOLTIP")); - p2VBox->pack_start (*qcontrast); + mchroma = Gtk::manage (new Adjuster (M("TP_COLORAPP_CHROMA_M"), -100.0, 100.0, 0.1, 0.)); - - colorh = Gtk::manage (new Adjuster (M("TP_COLORAPP_HUE"), -100.0, 100.0, 0.1, 0.)); - if (colorh->delay < 1000) colorh->delay = 1000; - colorh->throwOnButtonRelease(); - colorh->set_tooltip_markup (M("TP_COLORAPP_HUE_TOOLTIP")); - p2VBox->pack_start (*colorh); + if (mchroma->delay < 1000) { + mchroma->delay = 1000; + } - tonecie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_TONECIE"))); - tonecie->set_tooltip_markup (M("TP_COLORAPP_TONECIE_TOOLTIP")); - tonecieconn = tonecie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::tonecie_toggled) ); - p2VBox->pack_start (*tonecie); -/* - sharpcie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_SHARPCIE"))); - sharpcie->set_tooltip_markup (M("TP_COLORAPP_SHARPCIE_TOOLTIP")); - sharpcieconn = sharpcie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::sharpcie_toggled) ); - p2VBox->pack_start (*sharpcie); -*/ - p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); + mchroma->throwOnButtonRelease(); + mchroma->set_tooltip_markup (M("TP_COLORAPP_CHROMA_M_TOOLTIP")); + p2VBox->pack_start (*mchroma); - toneCurveMode = Gtk::manage (new MyComboBoxText ()); - toneCurveMode->append_text (M("TP_COLORAPP_TCMODE_LIGHTNESS")); - toneCurveMode->append_text (M("TP_COLORAPP_TCMODE_BRIGHTNESS")); - toneCurveMode->set_active (0); - toneCurveMode->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL1")); + rstprotection = Gtk::manage ( new Adjuster (M("TP_COLORAPP_RSTPRO"), 0., 100., 0.1, 0.) ); - curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR1")); - curveEditorG->setCurveListener (this); - curveEditorG->setTooltip(M("TP_COLORAPP_CURVEEDITOR1_TOOLTIP")); + if (rstprotection->delay < 1000) { + rstprotection->delay = 1000; + } - shape = static_cast(curveEditorG->addCurve(CT_Diagonal, "", toneCurveMode)); + rstprotection->throwOnButtonRelease(); + rstprotection->set_tooltip_markup (M("TP_COLORAPP_RSTPRO_TOOLTIP")); + p2VBox->pack_start (*rstprotection); + + contrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST"), -100.0, 100.0, 0.1, 0.)); + + if (contrast->delay < 1000) { + contrast->delay = 1000; + } + + contrast->throwOnButtonRelease(); + contrast->set_tooltip_markup (M("TP_COLORAPP_CONTRAST_TOOLTIP")); + p2VBox->pack_start (*contrast); + + qcontrast = Gtk::manage (new Adjuster (M("TP_COLORAPP_CONTRAST_Q"), -100.0, 100.0, 0.1, 0.)); + + if (qcontrast->delay < 1000) { + qcontrast->delay = 1000; + } + + qcontrast->throwOnButtonRelease(); + qcontrast->set_tooltip_markup (M("TP_COLORAPP_CONTRAST_Q_TOOLTIP")); + p2VBox->pack_start (*qcontrast); + + + colorh = Gtk::manage (new Adjuster (M("TP_COLORAPP_HUE"), -100.0, 100.0, 0.1, 0.)); + + if (colorh->delay < 1000) { + colorh->delay = 1000; + } + + colorh->throwOnButtonRelease(); + colorh->set_tooltip_markup (M("TP_COLORAPP_HUE_TOOLTIP")); + p2VBox->pack_start (*colorh); + + tonecie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_TONECIE"))); + tonecie->set_tooltip_markup (M("TP_COLORAPP_TONECIE_TOOLTIP")); + tonecieconn = tonecie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::tonecie_toggled) ); + p2VBox->pack_start (*tonecie); + /* + sharpcie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_SHARPCIE"))); + sharpcie->set_tooltip_markup (M("TP_COLORAPP_SHARPCIE_TOOLTIP")); + sharpcieconn = sharpcie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::sharpcie_toggled) ); + p2VBox->pack_start (*sharpcie); + */ + p2VBox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4); + + toneCurveMode = Gtk::manage (new MyComboBoxText ()); + toneCurveMode->append_text (M("TP_COLORAPP_TCMODE_LIGHTNESS")); + toneCurveMode->append_text (M("TP_COLORAPP_TCMODE_BRIGHTNESS")); + toneCurveMode->set_active (0); + toneCurveMode->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL1")); + + curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR1")); + curveEditorG->setCurveListener (this); + curveEditorG->setTooltip(M("TP_COLORAPP_CURVEEDITOR1_TOOLTIP")); + + shape = static_cast(curveEditorG->addCurve(CT_Diagonal, "", toneCurveMode)); - tcmodeconn = toneCurveMode->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed), true ); + tcmodeconn = toneCurveMode->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed), true ); - toneCurveMode2 = Gtk::manage (new MyComboBoxText ()); - toneCurveMode2->append_text (M("TP_COLORAPP_TCMODE_LIGHTNESS")); - toneCurveMode2->append_text (M("TP_COLORAPP_TCMODE_BRIGHTNESS")); - toneCurveMode2->set_active (0); - toneCurveMode2->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL2")); + toneCurveMode2 = Gtk::manage (new MyComboBoxText ()); + toneCurveMode2->append_text (M("TP_COLORAPP_TCMODE_LIGHTNESS")); + toneCurveMode2->append_text (M("TP_COLORAPP_TCMODE_BRIGHTNESS")); + toneCurveMode2->set_active (0); + toneCurveMode2->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL2")); - curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR2")); - curveEditorG2->setCurveListener (this); + curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR2")); + curveEditorG2->setCurveListener (this); - shape2 = static_cast(curveEditorG2->addCurve(CT_Diagonal, "", toneCurveMode2)); + shape2 = static_cast(curveEditorG2->addCurve(CT_Diagonal, "", toneCurveMode2)); - tcmode2conn = toneCurveMode2->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed), true ); + tcmode2conn = toneCurveMode2->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed), true ); - toneCurveMode3 = Gtk::manage (new MyComboBoxText ()); - toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_CHROMA")); - toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_SATUR")); - toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_COLORF")); - toneCurveMode3->set_active (0); - toneCurveMode3->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL3")); + toneCurveMode3 = Gtk::manage (new MyComboBoxText ()); + toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_CHROMA")); + toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_SATUR")); + toneCurveMode3->append_text (M("TP_COLORAPP_TCMODE_COLORF")); + toneCurveMode3->set_active (0); + toneCurveMode3->set_tooltip_text(M("TP_COLORAPP_TCMODE_LABEL3")); - curveEditorG3 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR3")); - curveEditorG3->setCurveListener (this); + curveEditorG3 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_COLORAPP_CURVEEDITOR3")); + curveEditorG3->setCurveListener (this); - shape3 = static_cast(curveEditorG3->addCurve(CT_Diagonal, "", toneCurveMode3)); - shape3->setRangeLabels( - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") - ); - shape3->setBottomBarColorProvider(this, 1); - shape3->setLeftBarColorProvider(this, 1); - shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); - - -// shape3->setBottomBarColorProvider(this, 2); -// shape3->setLeftBarColorProvider(this, 2); -// shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); - - // The milestones are still the same than those define above - //milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - //milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - shape->setBottomBarBgGradient(milestones); - shape->setLeftBarBgGradient(milestones); - shape2->setBottomBarBgGradient(milestones); - shape2->setLeftBarBgGradient(milestones); - - std::vector shape3Milestones; - float R, G, B; - for (int i=0; i<7; i++) { - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - shape3Milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - shape3->setBottomBarBgGradient(shape3Milestones); - shape3->setLeftBarBgGradient(shape3Milestones); - - shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); - - curveEditorG->curveListComplete(); - - curveEditorG2->curveListComplete(); - curveEditorG2->setTooltip(M("TP_COLORAPP_CURVEEDITOR2_TOOLTIP")); - - curveEditorG3->curveListComplete(); - curveEditorG3->setTooltip(M("TP_COLORAPP_CURVEEDITOR3_TOOLTIP")); - tcmode3conn = toneCurveMode3->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed), true ); - - p2VBox->pack_start( *curveEditorG, Gtk::PACK_SHRINK, 2); - p2VBox->pack_start( *curveEditorG2, Gtk::PACK_SHRINK, 2); - p2VBox->pack_start( *curveEditorG3, Gtk::PACK_SHRINK, 2); - - // ------------------------ Choice CIECAM data + shape3 = static_cast(curveEditorG3->addCurve(CT_Diagonal, "", toneCurveMode3)); + shape3->setRangeLabels( + M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), + M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") + ); + shape3->setBottomBarColorProvider(this, 1); + shape3->setLeftBarColorProvider(this, 1); + shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); - datacie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_DATACIE"))); - datacie->set_tooltip_markup (M("TP_COLORAPP_DATACIE_TOOLTIP")); - datacieconn = datacie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::datacie_toggled) ); - p2VBox->pack_start (*datacie); +// shape3->setBottomBarColorProvider(this, 2); +// shape3->setLeftBarColorProvider(this, 2); +// shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); + + // The milestones are still the same than those define above + //milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + //milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + shape->setBottomBarBgGradient(milestones); + shape->setLeftBarBgGradient(milestones); + shape2->setBottomBarBgGradient(milestones); + shape2->setLeftBarBgGradient(milestones); + + std::vector shape3Milestones; + float R, G, B; + + for (int i = 0; i < 7; i++) { + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + shape3Milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } + + shape3->setBottomBarBgGradient(shape3Milestones); + shape3->setLeftBarBgGradient(shape3Milestones); + + shape3->setRangeDefaultMilestones(0.05, 0.2, 0.58); + + curveEditorG->curveListComplete(); + + curveEditorG2->curveListComplete(); + curveEditorG2->setTooltip(M("TP_COLORAPP_CURVEEDITOR2_TOOLTIP")); + + curveEditorG3->curveListComplete(); + curveEditorG3->setTooltip(M("TP_COLORAPP_CURVEEDITOR3_TOOLTIP")); + tcmode3conn = toneCurveMode3->signal_changed().connect( sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed), true ); + + p2VBox->pack_start( *curveEditorG, Gtk::PACK_SHRINK, 2); + p2VBox->pack_start( *curveEditorG2, Gtk::PACK_SHRINK, 2); + p2VBox->pack_start( *curveEditorG3, Gtk::PACK_SHRINK, 2); + + // ------------------------ Choice CIECAM data + + + datacie = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_DATACIE"))); + datacie->set_tooltip_markup (M("TP_COLORAPP_DATACIE_TOOLTIP")); + datacieconn = datacie->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::datacie_toggled) ); + p2VBox->pack_start (*datacie); //------------------------- - - - - p2Frame->add(*p2VBox); - - - pack_start (*p2Frame, Gtk::PACK_EXPAND_WIDGET, 4); - - - - // ------------------------ Process #3: Converting back to Lab/RGB - // Process 3 frame - Gtk::Frame *p3Frame; - // Vertical box container for the content of the Process 3 frame - Gtk::VBox *p3VBox; - p3Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_VIEWING")) ); // "Editing viewing conditions" ??? - p3Frame->set_border_width(0); - p3Frame->set_label_align(0.025, 0.5); - - p3VBox = Gtk::manage ( new Gtk::VBox()); - p3VBox->set_border_width(4); - p3VBox->set_spacing(2); - - adaplum = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTVIEWING"), 0.1, 1000., 0.1, 16.)); - if (adaplum->delay < 1000) adaplum->delay = 1000; - adaplum->throwOnButtonRelease(); - adaplum->set_tooltip_markup (M("TP_COLORAPP_ADAPTVIEWING_TOOLTIP")); - p3VBox->pack_start (*adaplum); - - Gtk::HBox* surrHBox = Gtk::manage (new Gtk::HBox ()); - surrHBox->set_border_width (0); - surrHBox->set_spacing (2); - surrHBox->set_tooltip_markup(M("TP_COLORAPP_SURROUND_TOOLTIP")); - Gtk::Label* surrLabel = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_SURROUND")+":")); - surrHBox->pack_start (*surrLabel, Gtk::PACK_SHRINK); - surround = Gtk::manage (new MyComboBoxText ()); - surround->append_text (M("TP_COLORAPP_SURROUND_AVER")); - surround->append_text (M("TP_COLORAPP_SURROUND_DIM")); - surround->append_text (M("TP_COLORAPP_SURROUND_DARK")); - surround->append_text (M("TP_COLORAPP_SURROUND_EXDARK")); - surround->set_active (1); - surrHBox->pack_start (*surround); - p3VBox->pack_start (*surrHBox); - - p3Frame->add(*p3VBox); - pack_start (*p3Frame, Gtk::PACK_EXPAND_WIDGET, 4); + p2Frame->add(*p2VBox); - // ------------------------ Lab Gamut control + pack_start (*p2Frame, Gtk::PACK_EXPAND_WIDGET, 4); - gamut = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_GAMUT"))); - gamut->set_tooltip_markup (M("TP_COLORAPP_GAMUT_TOOLTIP")); - gamutconn = gamut->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::gamut_toggled) ); - pack_start (*gamut, Gtk::PACK_SHRINK); - - // ------------------------ Bad pixel control -/* - badpix = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_BADPIX"))); - badpix->set_tooltip_markup (M("TP_COLORAPP_BADPIX_TOOLTIP")); - badpixconn = badpix->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::badpix_toggled) ); - pack_start (*badpix, Gtk::PACK_SHRINK); -*/ - badpixsl = Gtk::manage (new Adjuster (M("TP_COLORAPP_BADPIXSL"), 0, 2, 1, 0)); - if (badpixsl->delay < 1000) badpixsl->delay = 1000; - badpixsl->throwOnButtonRelease(); - badpixsl->set_tooltip_markup (M("TP_COLORAPP_BADPIXSL_TOOLTIP")); - pack_start (*badpixsl, Gtk::PACK_SHRINK); - - // ------------------------ Listening events + // ------------------------ Process #3: Converting back to Lab/RGB - surrconn = surrsource->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::surrsource_toggled) ); - wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::wbmodelChanged) ); - algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::algoChanged) ); - surroundconn = surround->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::surroundChanged) ); + // Process 3 frame + Gtk::Frame *p3Frame; + // Vertical box container for the content of the Process 3 frame + Gtk::VBox *p3VBox; - degree->setAdjusterListener (this); - adapscen->setAdjusterListener (this); - adaplum->setAdjusterListener (this); - badpixsl->setAdjusterListener (this); - jlight->setAdjusterListener (this); - qbright->setAdjusterListener (this); - colorh->setAdjusterListener (this); - chroma->setAdjusterListener (this); - schroma->setAdjusterListener (this); - mchroma->setAdjusterListener (this); - contrast->setAdjusterListener (this); - qcontrast->setAdjusterListener (this); - rstprotection->setAdjusterListener (this); + p3Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORAPP_LABEL_VIEWING")) ); // "Editing viewing conditions" ??? + p3Frame->set_border_width(0); + p3Frame->set_label_align(0.025, 0.5); - show_all(); + p3VBox = Gtk::manage ( new Gtk::VBox()); + p3VBox->set_border_width(4); + p3VBox->set_spacing(2); + + adaplum = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTVIEWING"), 0.1, 1000., 0.1, 16.)); + + if (adaplum->delay < 1000) { + adaplum->delay = 1000; + } + + adaplum->throwOnButtonRelease(); + adaplum->set_tooltip_markup (M("TP_COLORAPP_ADAPTVIEWING_TOOLTIP")); + p3VBox->pack_start (*adaplum); + + Gtk::HBox* surrHBox = Gtk::manage (new Gtk::HBox ()); + surrHBox->set_border_width (0); + surrHBox->set_spacing (2); + surrHBox->set_tooltip_markup(M("TP_COLORAPP_SURROUND_TOOLTIP")); + Gtk::Label* surrLabel = Gtk::manage (new Gtk::Label (M("TP_COLORAPP_SURROUND") + ":")); + surrHBox->pack_start (*surrLabel, Gtk::PACK_SHRINK); + surround = Gtk::manage (new MyComboBoxText ()); + surround->append_text (M("TP_COLORAPP_SURROUND_AVER")); + surround->append_text (M("TP_COLORAPP_SURROUND_DIM")); + surround->append_text (M("TP_COLORAPP_SURROUND_DARK")); + surround->append_text (M("TP_COLORAPP_SURROUND_EXDARK")); + surround->set_active (1); + surrHBox->pack_start (*surround); + p3VBox->pack_start (*surrHBox); + + p3Frame->add(*p3VBox); + pack_start (*p3Frame, Gtk::PACK_EXPAND_WIDGET, 4); + + + // ------------------------ Lab Gamut control + + + gamut = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_GAMUT"))); + gamut->set_tooltip_markup (M("TP_COLORAPP_GAMUT_TOOLTIP")); + gamutconn = gamut->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::gamut_toggled) ); + pack_start (*gamut, Gtk::PACK_SHRINK); + + // ------------------------ Bad pixel control + + /* + badpix = Gtk::manage (new Gtk::CheckButton (M("TP_COLORAPP_BADPIX"))); + badpix->set_tooltip_markup (M("TP_COLORAPP_BADPIX_TOOLTIP")); + badpixconn = badpix->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::badpix_toggled) ); + pack_start (*badpix, Gtk::PACK_SHRINK); + */ + badpixsl = Gtk::manage (new Adjuster (M("TP_COLORAPP_BADPIXSL"), 0, 2, 1, 0)); + + if (badpixsl->delay < 1000) { + badpixsl->delay = 1000; + } + + badpixsl->throwOnButtonRelease(); + badpixsl->set_tooltip_markup (M("TP_COLORAPP_BADPIXSL_TOOLTIP")); + pack_start (*badpixsl, Gtk::PACK_SHRINK); + + // ------------------------ Listening events + + + surrconn = surrsource->signal_toggled().connect( sigc::mem_fun(*this, &ColorAppearance::surrsource_toggled) ); + wbmodelconn = wbmodel->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::wbmodelChanged) ); + algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::algoChanged) ); + surroundconn = surround->signal_changed().connect ( sigc::mem_fun(*this, &ColorAppearance::surroundChanged) ); + + degree->setAdjusterListener (this); + adapscen->setAdjusterListener (this); + adaplum->setAdjusterListener (this); + badpixsl->setAdjusterListener (this); + jlight->setAdjusterListener (this); + qbright->setAdjusterListener (this); + colorh->setAdjusterListener (this); + chroma->setAdjusterListener (this); + schroma->setAdjusterListener (this); + mchroma->setAdjusterListener (this); + contrast->setAdjusterListener (this); + qcontrast->setAdjusterListener (this); + rstprotection->setAdjusterListener (this); + + show_all(); } -ColorAppearance::~ColorAppearance () { - delete curveEditorG; - delete curveEditorG2; - delete curveEditorG3; +ColorAppearance::~ColorAppearance () +{ + delete curveEditorG; + delete curveEditorG2; + delete curveEditorG3; } -bool ColorAppearance::bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) { - return true; +bool ColorAppearance::bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) +{ + return true; } -bool ColorAppearance::srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) { - return true; +bool ColorAppearance::srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) +{ + return true; } -void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ColorAppearance::read (const ProcParams* pp, const ParamsEdited* pedited) +{ - disableListener (); - tcmodeconn.block(true); - tcmode2conn.block(true); - tcmode3conn.block(true); - shape->setCurve (pp->colorappearance.curve); - shape2->setCurve (pp->colorappearance.curve2); - shape3->setCurve (pp->colorappearance.curve3); - toneCurveMode->set_active(pp->colorappearance.curveMode); - toneCurveMode2->set_active(pp->colorappearance.curveMode2); - toneCurveMode3->set_active(pp->colorappearance.curveMode3); - curveMode3Changed(); // This will set the correct sensitive state of depending Adjusters - if (pedited) { - degree->setEditedState (pedited->colorappearance.degree ? Edited : UnEdited); - adapscen->setEditedState (pedited->colorappearance.adapscen ? Edited : UnEdited); - adaplum->setEditedState (pedited->colorappearance.adaplum ? Edited : UnEdited); - badpixsl->setEditedState (pedited->colorappearance.badpixsl ? Edited : UnEdited); - jlight->setEditedState (pedited->colorappearance.jlight ? Edited : UnEdited); - qbright->setEditedState (pedited->colorappearance.qbright ? Edited : UnEdited); - chroma->setEditedState (pedited->colorappearance.chroma ? Edited : UnEdited); - schroma->setEditedState (pedited->colorappearance.schroma ? Edited : UnEdited); - mchroma->setEditedState (pedited->colorappearance.mchroma ? Edited : UnEdited); - rstprotection->setEditedState (pedited->colorappearance.rstprotection ? Edited : UnEdited); - contrast->setEditedState (pedited->colorappearance.contrast ? Edited : UnEdited); - qcontrast->setEditedState (pedited->colorappearance.qcontrast ? Edited : UnEdited); - colorh->setEditedState (pedited->colorappearance.colorh ? Edited : UnEdited); - surrsource->set_inconsistent (!pedited->colorappearance.surrsource); - gamut->set_inconsistent (!pedited->colorappearance.gamut); - // badpix->set_inconsistent (!pedited->colorappearance.badpix); - datacie->set_inconsistent (!pedited->colorappearance.datacie); - tonecie->set_inconsistent (!pedited->colorappearance.tonecie); - // sharpcie->set_inconsistent (!pedited->colorappearance.sharpcie); + disableListener (); + tcmodeconn.block(true); + tcmode2conn.block(true); + tcmode3conn.block(true); + shape->setCurve (pp->colorappearance.curve); + shape2->setCurve (pp->colorappearance.curve2); + shape3->setCurve (pp->colorappearance.curve3); + toneCurveMode->set_active(pp->colorappearance.curveMode); + toneCurveMode2->set_active(pp->colorappearance.curveMode2); + toneCurveMode3->set_active(pp->colorappearance.curveMode3); + curveMode3Changed(); // This will set the correct sensitive state of depending Adjusters - degree->setAutoInconsistent (multiImage && !pedited->colorappearance.autodegree); - adapscen->setAutoInconsistent (multiImage && !pedited->colorappearance.autoadapscen); - set_inconsistent (multiImage && !pedited->colorappearance.enabled); - - shape->setUnChanged (!pedited->colorappearance.curve); - shape2->setUnChanged (!pedited->colorappearance.curve2); - shape3->setUnChanged (!pedited->colorappearance.curve3); - if (!pedited->colorappearance.curveMode) { - toneCurveMode->set_active(2); - } - if (!pedited->colorappearance.curveMode2) { - toneCurveMode2->set_active(2); - } - if (!pedited->colorappearance.curveMode3) { - toneCurveMode3->set_active(3); - } + if (pedited) { + degree->setEditedState (pedited->colorappearance.degree ? Edited : UnEdited); + adapscen->setEditedState (pedited->colorappearance.adapscen ? Edited : UnEdited); + adaplum->setEditedState (pedited->colorappearance.adaplum ? Edited : UnEdited); + badpixsl->setEditedState (pedited->colorappearance.badpixsl ? Edited : UnEdited); + jlight->setEditedState (pedited->colorappearance.jlight ? Edited : UnEdited); + qbright->setEditedState (pedited->colorappearance.qbright ? Edited : UnEdited); + chroma->setEditedState (pedited->colorappearance.chroma ? Edited : UnEdited); + schroma->setEditedState (pedited->colorappearance.schroma ? Edited : UnEdited); + mchroma->setEditedState (pedited->colorappearance.mchroma ? Edited : UnEdited); + rstprotection->setEditedState (pedited->colorappearance.rstprotection ? Edited : UnEdited); + contrast->setEditedState (pedited->colorappearance.contrast ? Edited : UnEdited); + qcontrast->setEditedState (pedited->colorappearance.qcontrast ? Edited : UnEdited); + colorh->setEditedState (pedited->colorappearance.colorh ? Edited : UnEdited); + surrsource->set_inconsistent (!pedited->colorappearance.surrsource); + gamut->set_inconsistent (!pedited->colorappearance.gamut); + // badpix->set_inconsistent (!pedited->colorappearance.badpix); + datacie->set_inconsistent (!pedited->colorappearance.datacie); + tonecie->set_inconsistent (!pedited->colorappearance.tonecie); + // sharpcie->set_inconsistent (!pedited->colorappearance.sharpcie); + + degree->setAutoInconsistent (multiImage && !pedited->colorappearance.autodegree); + adapscen->setAutoInconsistent (multiImage && !pedited->colorappearance.autoadapscen); + set_inconsistent (multiImage && !pedited->colorappearance.enabled); + + shape->setUnChanged (!pedited->colorappearance.curve); + shape2->setUnChanged (!pedited->colorappearance.curve2); + shape3->setUnChanged (!pedited->colorappearance.curve3); + + if (!pedited->colorappearance.curveMode) { + toneCurveMode->set_active(2); + } + + if (!pedited->colorappearance.curveMode2) { + toneCurveMode2->set_active(2); + } + + if (!pedited->colorappearance.curveMode3) { + toneCurveMode3->set_active(3); + } - } + } - setEnabled(pp->colorappearance.enabled); + setEnabled(pp->colorappearance.enabled); - surroundconn.block(true); - if (pedited && !pedited->colorappearance.surround) - surround->set_active (4); - else if (pp->colorappearance.surround=="Average") - surround->set_active (0); - else if (pp->colorappearance.surround=="Dim") - surround->set_active (1); - else if (pp->colorappearance.surround=="Dark") - surround->set_active (2); - else if (pp->colorappearance.surround=="ExtremelyDark") - surround->set_active (3); - surroundconn.block(false); - // Have to be manually called to handle initial state update - surroundChanged(); + surroundconn.block(true); - wbmodelconn.block(true); - if (pedited && !pedited->colorappearance.wbmodel) - wbmodel->set_active (2); - else if (pp->colorappearance.wbmodel=="RawT") - wbmodel->set_active (0); - else if (pp->colorappearance.wbmodel=="RawTCAT02") - wbmodel->set_active (1); - wbmodelconn.block(false); - // Have to be manually called to handle initial state update - wbmodelChanged(); + if (pedited && !pedited->colorappearance.surround) { + surround->set_active (4); + } else if (pp->colorappearance.surround == "Average") { + surround->set_active (0); + } else if (pp->colorappearance.surround == "Dim") { + surround->set_active (1); + } else if (pp->colorappearance.surround == "Dark") { + surround->set_active (2); + } else if (pp->colorappearance.surround == "ExtremelyDark") { + surround->set_active (3); + } - algoconn.block(true); - if (pedited && !pedited->colorappearance.algo) - algo->set_active (4); - else if (pp->colorappearance.algo=="JC") - algo->set_active (0); - else if (pp->colorappearance.algo=="JS") - algo->set_active (1); - else if (pp->colorappearance.algo=="QM") - algo->set_active (2); - else if (pp->colorappearance.algo=="ALL") - algo->set_active (3); - algoconn.block(false); - // Have to be manually called to handle initial state update - algoChanged(); + surroundconn.block(false); + // Have to be manually called to handle initial state update + surroundChanged(); - surrconn.block (true); - surrsource->set_active (pp->colorappearance.surrsource); - surrconn.block (false); - gamutconn.block (true); - gamut->set_active (pp->colorappearance.gamut); - gamutconn.block (false); -// badpixconn.block (true); -// badpix->set_active (pp->colorappearance.badpix); -// badpixconn.block (false); - datacieconn.block (true); - datacie->set_active (pp->colorappearance.datacie); - datacieconn.block (false); - tonecieconn.block (true); - tonecie->set_active (pp->colorappearance.tonecie); - tonecieconn.block (false); -// sharpcieconn.block (true); -// sharpcie->set_active (pp->colorappearance.sharpcie); -// sharpcieconn.block (false); + wbmodelconn.block(true); - lastsurr=pp->colorappearance.surrsource; - lastgamut=pp->colorappearance.gamut; -// lastbadpix=pp->colorappearance.badpix; - lastdatacie=pp->colorappearance.datacie; - lasttonecie=pp->colorappearance.tonecie; -// lastsharpcie=pp->colorappearance.sharpcie; + if (pedited && !pedited->colorappearance.wbmodel) { + wbmodel->set_active (2); + } else if (pp->colorappearance.wbmodel == "RawT") { + wbmodel->set_active (0); + } else if (pp->colorappearance.wbmodel == "RawTCAT02") { + wbmodel->set_active (1); + } - lastAutoDegree = pp->colorappearance.autodegree; - lastAutoAdapscen = pp->colorappearance.autoadapscen; + wbmodelconn.block(false); + // Have to be manually called to handle initial state update + wbmodelChanged(); - degree->setValue (pp->colorappearance.degree); - degree->setAutoValue(pp->colorappearance.autodegree); - adapscen->setValue (pp->colorappearance.adapscen); - adapscen->setAutoValue (pp->colorappearance.autoadapscen); - - adaplum->setValue (pp->colorappearance.adaplum); - badpixsl->setValue (pp->colorappearance.badpixsl); - jlight->setValue (pp->colorappearance.jlight); - qbright->setValue (pp->colorappearance.qbright); - chroma->setValue (pp->colorappearance.chroma); - schroma->setValue (pp->colorappearance.schroma); - mchroma->setValue (pp->colorappearance.mchroma); - rstprotection->setValue (pp->colorappearance.rstprotection); - contrast->setValue (pp->colorappearance.contrast); - qcontrast->setValue (pp->colorappearance.qcontrast); - colorh->setValue (pp->colorappearance.colorh); + algoconn.block(true); - tcmode3conn.block(false); - tcmode2conn.block(false); - tcmodeconn.block(false); - enableListener (); + if (pedited && !pedited->colorappearance.algo) { + algo->set_active (4); + } else if (pp->colorappearance.algo == "JC") { + algo->set_active (0); + } else if (pp->colorappearance.algo == "JS") { + algo->set_active (1); + } else if (pp->colorappearance.algo == "QM") { + algo->set_active (2); + } else if (pp->colorappearance.algo == "ALL") { + algo->set_active (3); + } + + algoconn.block(false); + // Have to be manually called to handle initial state update + algoChanged(); + + surrconn.block (true); + surrsource->set_active (pp->colorappearance.surrsource); + surrconn.block (false); + gamutconn.block (true); + gamut->set_active (pp->colorappearance.gamut); + gamutconn.block (false); +// badpixconn.block (true); +// badpix->set_active (pp->colorappearance.badpix); +// badpixconn.block (false); + datacieconn.block (true); + datacie->set_active (pp->colorappearance.datacie); + datacieconn.block (false); + tonecieconn.block (true); + tonecie->set_active (pp->colorappearance.tonecie); + tonecieconn.block (false); +// sharpcieconn.block (true); +// sharpcie->set_active (pp->colorappearance.sharpcie); +// sharpcieconn.block (false); + + lastsurr = pp->colorappearance.surrsource; + lastgamut = pp->colorappearance.gamut; +// lastbadpix=pp->colorappearance.badpix; + lastdatacie = pp->colorappearance.datacie; + lasttonecie = pp->colorappearance.tonecie; +// lastsharpcie=pp->colorappearance.sharpcie; + + lastAutoDegree = pp->colorappearance.autodegree; + lastAutoAdapscen = pp->colorappearance.autoadapscen; + + degree->setValue (pp->colorappearance.degree); + degree->setAutoValue(pp->colorappearance.autodegree); + adapscen->setValue (pp->colorappearance.adapscen); + adapscen->setAutoValue (pp->colorappearance.autoadapscen); + + adaplum->setValue (pp->colorappearance.adaplum); + badpixsl->setValue (pp->colorappearance.badpixsl); + jlight->setValue (pp->colorappearance.jlight); + qbright->setValue (pp->colorappearance.qbright); + chroma->setValue (pp->colorappearance.chroma); + schroma->setValue (pp->colorappearance.schroma); + mchroma->setValue (pp->colorappearance.mchroma); + rstprotection->setValue (pp->colorappearance.rstprotection); + contrast->setValue (pp->colorappearance.contrast); + qcontrast->setValue (pp->colorappearance.qcontrast); + colorh->setValue (pp->colorappearance.colorh); + + tcmode3conn.block(false); + tcmode2conn.block(false); + tcmodeconn.block(false); + enableListener (); } -void ColorAppearance::autoOpenCurve () { - shape->openIfNonlinear(); - shape2->openIfNonlinear(); - shape3->openIfNonlinear(); +void ColorAppearance::autoOpenCurve () +{ + shape->openIfNonlinear(); + shape2->openIfNonlinear(); + shape3->openIfNonlinear(); } -void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited) { +void ColorAppearance::write (ProcParams* pp, ParamsEdited* pedited) +{ - pp->colorappearance.degree = degree->getValue (); - pp->colorappearance.autodegree = degree->getAutoValue (); - pp->colorappearance.enabled = getEnabled(); - pp->colorappearance.adapscen = adapscen->getValue (); - pp->colorappearance.autoadapscen = adapscen->getAutoValue (); - pp->colorappearance.adaplum = adaplum->getValue (); - pp->colorappearance.badpixsl = badpixsl->getValue (); - pp->colorappearance.jlight = jlight->getValue (); - pp->colorappearance.qbright = qbright->getValue (); - pp->colorappearance.chroma = chroma->getValue (); - pp->colorappearance.schroma = schroma->getValue (); - pp->colorappearance.mchroma = mchroma->getValue (); - pp->colorappearance.contrast = contrast->getValue (); - pp->colorappearance.qcontrast = qcontrast->getValue (); - pp->colorappearance.colorh = colorh->getValue (); - pp->colorappearance.rstprotection = rstprotection->getValue (); - pp->colorappearance.surrsource = surrsource->get_active(); - pp->colorappearance.gamut = gamut->get_active(); -// pp->colorappearance.badpix = badpix->get_active(); - pp->colorappearance.datacie = datacie->get_active(); - pp->colorappearance.tonecie = tonecie->get_active(); -// pp->colorappearance.sharpcie = sharpcie->get_active(); - pp->colorappearance.curve = shape->getCurve (); - pp->colorappearance.curve2 = shape2->getCurve (); - pp->colorappearance.curve3 = shape3->getCurve (); - - int tcMode = toneCurveMode->get_active_row_number(); - if (tcMode == 0) pp->colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT; - else if (tcMode == 1) pp->colorappearance.curveMode = ColorAppearanceParams::TC_MODE_BRIGHT; - - tcMode = toneCurveMode2->get_active_row_number(); - if (tcMode == 0) pp->colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT; - else if (tcMode == 1) pp->colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_BRIGHT; - - int tcMode3 = toneCurveMode3->get_active_row_number(); - if (tcMode3 == 0) pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA; - else if (tcMode3 == 1) pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_SATUR; - else if (tcMode3 == 2) pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_COLORF; + pp->colorappearance.degree = degree->getValue (); + pp->colorappearance.autodegree = degree->getAutoValue (); + pp->colorappearance.enabled = getEnabled(); + pp->colorappearance.adapscen = adapscen->getValue (); + pp->colorappearance.autoadapscen = adapscen->getAutoValue (); + pp->colorappearance.adaplum = adaplum->getValue (); + pp->colorappearance.badpixsl = badpixsl->getValue (); + pp->colorappearance.jlight = jlight->getValue (); + pp->colorappearance.qbright = qbright->getValue (); + pp->colorappearance.chroma = chroma->getValue (); + pp->colorappearance.schroma = schroma->getValue (); + pp->colorappearance.mchroma = mchroma->getValue (); + pp->colorappearance.contrast = contrast->getValue (); + pp->colorappearance.qcontrast = qcontrast->getValue (); + pp->colorappearance.colorh = colorh->getValue (); + pp->colorappearance.rstprotection = rstprotection->getValue (); + pp->colorappearance.surrsource = surrsource->get_active(); + pp->colorappearance.gamut = gamut->get_active(); +// pp->colorappearance.badpix = badpix->get_active(); + pp->colorappearance.datacie = datacie->get_active(); + pp->colorappearance.tonecie = tonecie->get_active(); +// pp->colorappearance.sharpcie = sharpcie->get_active(); + pp->colorappearance.curve = shape->getCurve (); + pp->colorappearance.curve2 = shape2->getCurve (); + pp->colorappearance.curve3 = shape3->getCurve (); - if (pedited) { - pedited->colorappearance.degree = degree->getEditedState (); - pedited->colorappearance.adapscen = adapscen->getEditedState (); - pedited->colorappearance.adaplum = adaplum->getEditedState (); - pedited->colorappearance.badpixsl = badpixsl->getEditedState (); - pedited->colorappearance.jlight = jlight->getEditedState (); - pedited->colorappearance.qbright = qbright->getEditedState (); - pedited->colorappearance.chroma = chroma->getEditedState (); - pedited->colorappearance.schroma = schroma->getEditedState (); - pedited->colorappearance.mchroma = mchroma->getEditedState (); - pedited->colorappearance.contrast = contrast->getEditedState (); - pedited->colorappearance.qcontrast = qcontrast->getEditedState (); - pedited->colorappearance.colorh = colorh->getEditedState (); - pedited->colorappearance.rstprotection = rstprotection->getEditedState (); - pedited->colorappearance.autodegree = !degree->getAutoInconsistent(); - pedited->colorappearance.autoadapscen = !adapscen->getAutoInconsistent(); - pedited->colorappearance.enabled = !get_inconsistent(); - pedited->colorappearance.surround = surround->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->colorappearance.wbmodel = wbmodel->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->colorappearance.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->colorappearance.surrsource = !surrsource->get_inconsistent(); - pedited->colorappearance.gamut = !gamut->get_inconsistent(); - // pedited->colorappearance.badpix = !badpix->get_inconsistent(); - pedited->colorappearance.datacie = !datacie->get_inconsistent(); - pedited->colorappearance.tonecie = !tonecie->get_inconsistent(); - // pedited->colorappearance.sharpcie = !sharpcie->get_inconsistent(); - pedited->colorappearance.curve = !shape->isUnChanged (); - pedited->colorappearance.curve2 = !shape2->isUnChanged (); - pedited->colorappearance.curve3 = !shape3->isUnChanged (); - pedited->colorappearance.curveMode = toneCurveMode->get_active_row_number() != 2; - pedited->colorappearance.curveMode2 = toneCurveMode2->get_active_row_number() != 2; - pedited->colorappearance.curveMode3 = toneCurveMode3->get_active_row_number() != 3; - } - if (surround->get_active_row_number()==0) - pp->colorappearance.surround = "Average"; - else if (surround->get_active_row_number()==1) - pp->colorappearance.surround = "Dim"; - else if (surround->get_active_row_number()==2) - pp->colorappearance.surround = "Dark"; - else if (surround->get_active_row_number()==3) - pp->colorappearance.surround = "ExtremelyDark"; + int tcMode = toneCurveMode->get_active_row_number(); - if (wbmodel->get_active_row_number()==0) - pp->colorappearance.wbmodel = "RawT"; - else if (wbmodel->get_active_row_number()==1) - pp->colorappearance.wbmodel = "RawTCAT02"; + if (tcMode == 0) { + pp->colorappearance.curveMode = ColorAppearanceParams::TC_MODE_LIGHT; + } else if (tcMode == 1) { + pp->colorappearance.curveMode = ColorAppearanceParams::TC_MODE_BRIGHT; + } - if (algo->get_active_row_number()==0) - pp->colorappearance.algo = "JC"; - else if (algo->get_active_row_number()==1) - pp->colorappearance.algo = "JS"; - else if (algo->get_active_row_number()==2) - pp->colorappearance.algo = "QM"; - else if (algo->get_active_row_number()==3) - pp->colorappearance.algo = "ALL"; + tcMode = toneCurveMode2->get_active_row_number(); + + if (tcMode == 0) { + pp->colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_LIGHT; + } else if (tcMode == 1) { + pp->colorappearance.curveMode2 = ColorAppearanceParams::TC_MODE_BRIGHT; + } + + int tcMode3 = toneCurveMode3->get_active_row_number(); + + if (tcMode3 == 0) { + pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_CHROMA; + } else if (tcMode3 == 1) { + pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_SATUR; + } else if (tcMode3 == 2) { + pp->colorappearance.curveMode3 = ColorAppearanceParams::TC_MODE_COLORF; + } + + if (pedited) { + pedited->colorappearance.degree = degree->getEditedState (); + pedited->colorappearance.adapscen = adapscen->getEditedState (); + pedited->colorappearance.adaplum = adaplum->getEditedState (); + pedited->colorappearance.badpixsl = badpixsl->getEditedState (); + pedited->colorappearance.jlight = jlight->getEditedState (); + pedited->colorappearance.qbright = qbright->getEditedState (); + pedited->colorappearance.chroma = chroma->getEditedState (); + pedited->colorappearance.schroma = schroma->getEditedState (); + pedited->colorappearance.mchroma = mchroma->getEditedState (); + pedited->colorappearance.contrast = contrast->getEditedState (); + pedited->colorappearance.qcontrast = qcontrast->getEditedState (); + pedited->colorappearance.colorh = colorh->getEditedState (); + pedited->colorappearance.rstprotection = rstprotection->getEditedState (); + pedited->colorappearance.autodegree = !degree->getAutoInconsistent(); + pedited->colorappearance.autoadapscen = !adapscen->getAutoInconsistent(); + pedited->colorappearance.enabled = !get_inconsistent(); + pedited->colorappearance.surround = surround->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->colorappearance.wbmodel = wbmodel->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->colorappearance.algo = algo->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->colorappearance.surrsource = !surrsource->get_inconsistent(); + pedited->colorappearance.gamut = !gamut->get_inconsistent(); + // pedited->colorappearance.badpix = !badpix->get_inconsistent(); + pedited->colorappearance.datacie = !datacie->get_inconsistent(); + pedited->colorappearance.tonecie = !tonecie->get_inconsistent(); + // pedited->colorappearance.sharpcie = !sharpcie->get_inconsistent(); + pedited->colorappearance.curve = !shape->isUnChanged (); + pedited->colorappearance.curve2 = !shape2->isUnChanged (); + pedited->colorappearance.curve3 = !shape3->isUnChanged (); + pedited->colorappearance.curveMode = toneCurveMode->get_active_row_number() != 2; + pedited->colorappearance.curveMode2 = toneCurveMode2->get_active_row_number() != 2; + pedited->colorappearance.curveMode3 = toneCurveMode3->get_active_row_number() != 3; + } + + if (surround->get_active_row_number() == 0) { + pp->colorappearance.surround = "Average"; + } else if (surround->get_active_row_number() == 1) { + pp->colorappearance.surround = "Dim"; + } else if (surround->get_active_row_number() == 2) { + pp->colorappearance.surround = "Dark"; + } else if (surround->get_active_row_number() == 3) { + pp->colorappearance.surround = "ExtremelyDark"; + } + + if (wbmodel->get_active_row_number() == 0) { + pp->colorappearance.wbmodel = "RawT"; + } else if (wbmodel->get_active_row_number() == 1) { + pp->colorappearance.wbmodel = "RawTCAT02"; + } + + if (algo->get_active_row_number() == 0) { + pp->colorappearance.algo = "JC"; + } else if (algo->get_active_row_number() == 1) { + pp->colorappearance.algo = "JS"; + } else if (algo->get_active_row_number() == 2) { + pp->colorappearance.algo = "QM"; + } else if (algo->get_active_row_number() == 3) { + pp->colorappearance.algo = "ALL"; + } } -void ColorAppearance::curveChanged (CurveEditor* ce) { +void ColorAppearance::curveChanged (CurveEditor* ce) +{ - if (listener) { - if (ce == shape) - listener->panelChanged (EvCATCurve1, M("HISTORY_CUSTOMCURVE")); - else if (ce == shape2) - listener->panelChanged (EvCATCurve2, M("HISTORY_CUSTOMCURVE")); - else if (ce == shape3) - listener->panelChanged (EvCATCurve3, M("HISTORY_CUSTOMCURVE")); - } + if (listener) { + if (ce == shape) { + listener->panelChanged (EvCATCurve1, M("HISTORY_CUSTOMCURVE")); + } else if (ce == shape2) { + listener->panelChanged (EvCATCurve2, M("HISTORY_CUSTOMCURVE")); + } else if (ce == shape3) { + listener->panelChanged (EvCATCurve3, M("HISTORY_CUSTOMCURVE")); + } + } } -void ColorAppearance::curveMode1Changed () { - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed_)); +void ColorAppearance::curveMode1Changed () +{ + if (listener) { + Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode1Changed_)); + } } -bool ColorAppearance::curveMode1Changed_ () { - if (listener) listener->panelChanged (EvCATCurveMode1, toneCurveMode->get_active_text()); - return false; +bool ColorAppearance::curveMode1Changed_ () +{ + if (listener) { + listener->panelChanged (EvCATCurveMode1, toneCurveMode->get_active_text()); + } + + return false; } -void ColorAppearance::curveMode2Changed () { - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed_)); +void ColorAppearance::curveMode2Changed () +{ + if (listener) { + Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode2Changed_)); + } } -bool ColorAppearance::curveMode2Changed_ () { - if (listener) listener->panelChanged (EvCATCurveMode2, toneCurveMode2->get_active_text()); - return false; +bool ColorAppearance::curveMode2Changed_ () +{ + if (listener) { + listener->panelChanged (EvCATCurveMode2, toneCurveMode2->get_active_text()); + } + + return false; } -void ColorAppearance::curveMode3Changed () { - int tcMode3 = toneCurveMode3->get_active_row_number(); - if (tcMode3 == 0) {chroma->set_sensitive(true); schroma->set_sensitive(true); } - else if (tcMode3 == 2) {chroma->set_sensitive(false); schroma->set_sensitive(false);} - else if (tcMode3 == 1) {chroma->set_sensitive(false); schroma->set_sensitive(true); } +void ColorAppearance::curveMode3Changed () +{ + int tcMode3 = toneCurveMode3->get_active_row_number(); - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed_)); + if (tcMode3 == 0) { + chroma->set_sensitive(true); + schroma->set_sensitive(true); + } else if (tcMode3 == 2) { + chroma->set_sensitive(false); + schroma->set_sensitive(false); + } else if (tcMode3 == 1) { + chroma->set_sensitive(false); + schroma->set_sensitive(true); + } + + if (listener) { + Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::curveMode3Changed_)); + } } -bool ColorAppearance::curveMode3Changed_ () { - if (listener) { - listener->panelChanged (EvCATCurveMode3, toneCurveMode3->get_active_text()); - } - return false; +bool ColorAppearance::curveMode3Changed_ () +{ + if (listener) { + listener->panelChanged (EvCATCurveMode3, toneCurveMode3->get_active_text()); + } + + return false; } -void ColorAppearance::surrsource_toggled () { +void ColorAppearance::surrsource_toggled () +{ - if (batchMode) { - if (surrsource->get_inconsistent()) { - surrsource->set_inconsistent (false); - surrconn.block (true); - surrsource->set_active (false); - surrconn.block (false); - } - else if (lastsurr) - surrsource->set_inconsistent (true); + if (batchMode) { + if (surrsource->get_inconsistent()) { + surrsource->set_inconsistent (false); + surrconn.block (true); + surrsource->set_active (false); + surrconn.block (false); + } else if (lastsurr) { + surrsource->set_inconsistent (true); + } - lastsurr = surrsource->get_active (); - } + lastsurr = surrsource->get_active (); + } - if (listener) { - if (surrsource->get_active ()) - listener->panelChanged (EvCATsurr, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATsurr, M("GENERAL_DISABLED")); - } + if (listener) { + if (surrsource->get_active ()) { + listener->panelChanged (EvCATsurr, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvCATsurr, M("GENERAL_DISABLED")); + } + } } -void ColorAppearance::gamut_toggled () { +void ColorAppearance::gamut_toggled () +{ - if (batchMode) { - if (gamut->get_inconsistent()) { - gamut->set_inconsistent (false); - gamutconn.block (true); - gamut->set_active (false); - gamutconn.block (false); - } - else if (lastgamut) - gamut->set_inconsistent (true); + if (batchMode) { + if (gamut->get_inconsistent()) { + gamut->set_inconsistent (false); + gamutconn.block (true); + gamut->set_active (false); + gamutconn.block (false); + } else if (lastgamut) { + gamut->set_inconsistent (true); + } + + lastgamut = gamut->get_active (); + } + + if (listener) { + if (gamut->get_active ()) { + listener->panelChanged (EvCATgamut, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvCATgamut, M("GENERAL_DISABLED")); + } + } - lastgamut = gamut->get_active (); - } - if (listener) { - if (gamut->get_active ()) - listener->panelChanged (EvCATgamut, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATgamut, M("GENERAL_DISABLED")); - } - } /* void ColorAppearance::badpix_toggled () { - if (batchMode) { - if (badpix->get_inconsistent()) { - badpix->set_inconsistent (false); - badpixconn.block (true); - badpix->set_active (false); - badpixconn.block (false); - } - else if (lastbadpix) - badpix->set_inconsistent (true); + if (batchMode) { + if (badpix->get_inconsistent()) { + badpix->set_inconsistent (false); + badpixconn.block (true); + badpix->set_active (false); + badpixconn.block (false); + } + else if (lastbadpix) + badpix->set_inconsistent (true); + + lastbadpix = badpix->get_active (); + } + if (listener) { + if (badpix->get_active ()) + listener->panelChanged (EvCATbadpix, M("GENERAL_ENABLED")); + else + listener->panelChanged (EvCATbadpix, M("GENERAL_DISABLED")); + } - lastbadpix = badpix->get_active (); - } - if (listener) { - if (badpix->get_active ()) - listener->panelChanged (EvCATbadpix, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATbadpix, M("GENERAL_DISABLED")); - } - } */ -void ColorAppearance::datacie_toggled () { +void ColorAppearance::datacie_toggled () +{ - if (batchMode) { - if (datacie->get_inconsistent()) { - datacie->set_inconsistent (false); - datacieconn.block (true); - datacie->set_active (false); - datacieconn.block (false); - } - else if (lastdatacie) - datacie->set_inconsistent (true); + if (batchMode) { + if (datacie->get_inconsistent()) { + datacie->set_inconsistent (false); + datacieconn.block (true); + datacie->set_active (false); + datacieconn.block (false); + } else if (lastdatacie) { + datacie->set_inconsistent (true); + } - lastdatacie = datacie->get_active (); - } + lastdatacie = datacie->get_active (); + } - if (listener) { - if (datacie->get_active ()) - listener->panelChanged (EvCATdatacie, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATdatacie, M("GENERAL_DISABLED")); - } + if (listener) { + if (datacie->get_active ()) { + listener->panelChanged (EvCATdatacie, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvCATdatacie, M("GENERAL_DISABLED")); + } + } } -void ColorAppearance::tonecie_toggled () { +void ColorAppearance::tonecie_toggled () +{ - if (batchMode) { - if (tonecie->get_inconsistent()) { - tonecie->set_inconsistent (false); - tonecieconn.block (true); - tonecie->set_active (false); - tonecieconn.block (false); - } - else if (lasttonecie) - tonecie->set_inconsistent (true); + if (batchMode) { + if (tonecie->get_inconsistent()) { + tonecie->set_inconsistent (false); + tonecieconn.block (true); + tonecie->set_active (false); + tonecieconn.block (false); + } else if (lasttonecie) { + tonecie->set_inconsistent (true); + } - lasttonecie = tonecie->get_active (); - } - if (listener) { - if (tonecie->get_active ()) - listener->panelChanged (EvCATtonecie, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATtonecie, M("GENERAL_DISABLED")); - } + lasttonecie = tonecie->get_active (); + } + + if (listener) { + if (tonecie->get_active ()) { + listener->panelChanged (EvCATtonecie, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvCATtonecie, M("GENERAL_DISABLED")); + } + } } /* void ColorAppearance::sharpcie_toggled () { - if (batchMode) { - if (sharpcie->get_inconsistent()) { - sharpcie->set_inconsistent (false); - sharpcieconn.block (true); - sharpcie->set_active (false); - sharpcieconn.block (false); - } - else if (lastsharpcie) - sharpcie->set_inconsistent (true); + if (batchMode) { + if (sharpcie->get_inconsistent()) { + sharpcie->set_inconsistent (false); + sharpcieconn.block (true); + sharpcie->set_active (false); + sharpcieconn.block (false); + } + else if (lastsharpcie) + sharpcie->set_inconsistent (true); - lastsharpcie = sharpcie->get_active (); - } - if (listener) { - if (sharpcie->get_active ()) - listener->panelChanged (EvCATsharpcie, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATsharpcie, M("GENERAL_DISABLED")); - } + lastsharpcie = sharpcie->get_active (); + } + if (listener) { + if (sharpcie->get_active ()) + listener->panelChanged (EvCATsharpcie, M("GENERAL_ENABLED")); + else + listener->panelChanged (EvCATsharpcie, M("GENERAL_DISABLED")); + } } */ -void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ - degree->setDefault (defParams->colorappearance.degree); - adapscen->setDefault (defParams->colorappearance.adapscen); - adaplum->setDefault (defParams->colorappearance.adaplum); - badpixsl->setDefault (defParams->colorappearance.badpixsl); - jlight->setDefault (defParams->colorappearance.jlight); - qbright->setDefault (defParams->colorappearance.qbright); - chroma->setDefault (defParams->colorappearance.chroma); - schroma->setDefault (defParams->colorappearance.schroma); - mchroma->setDefault (defParams->colorappearance.mchroma); - rstprotection->setDefault (defParams->colorappearance.rstprotection); - contrast->setDefault (defParams->colorappearance.contrast); - qcontrast->setDefault (defParams->colorappearance.qcontrast); - colorh->setDefault (defParams->colorappearance.colorh); + degree->setDefault (defParams->colorappearance.degree); + adapscen->setDefault (defParams->colorappearance.adapscen); + adaplum->setDefault (defParams->colorappearance.adaplum); + badpixsl->setDefault (defParams->colorappearance.badpixsl); + jlight->setDefault (defParams->colorappearance.jlight); + qbright->setDefault (defParams->colorappearance.qbright); + chroma->setDefault (defParams->colorappearance.chroma); + schroma->setDefault (defParams->colorappearance.schroma); + mchroma->setDefault (defParams->colorappearance.mchroma); + rstprotection->setDefault (defParams->colorappearance.rstprotection); + contrast->setDefault (defParams->colorappearance.contrast); + qcontrast->setDefault (defParams->colorappearance.qcontrast); + colorh->setDefault (defParams->colorappearance.colorh); - if (pedited) { - degree->setDefaultEditedState (pedited->colorappearance.degree ? Edited : UnEdited); - adapscen->setDefaultEditedState (pedited->colorappearance.adapscen ? Edited : UnEdited); - adaplum->setDefaultEditedState (pedited->colorappearance.adaplum ? Edited : UnEdited); - badpixsl->setDefaultEditedState (pedited->colorappearance.badpixsl ? Edited : UnEdited); - jlight->setDefaultEditedState (pedited->colorappearance.jlight ? Edited : UnEdited); - qbright->setDefaultEditedState (pedited->colorappearance.qbright ? Edited : UnEdited); - chroma->setDefaultEditedState (pedited->colorappearance.chroma ? Edited : UnEdited); - schroma->setDefaultEditedState (pedited->colorappearance.schroma ? Edited : UnEdited); - mchroma->setDefaultEditedState (pedited->colorappearance.mchroma ? Edited : UnEdited); - rstprotection->setDefaultEditedState (pedited->colorappearance.rstprotection ? Edited : UnEdited); - contrast->setDefaultEditedState (pedited->colorappearance.contrast ? Edited : UnEdited); - qcontrast->setDefaultEditedState (pedited->colorappearance.qcontrast ? Edited : UnEdited); - colorh->setDefaultEditedState (pedited->colorappearance.colorh ? Edited : UnEdited); - - } - else { - degree->setDefaultEditedState (Irrelevant); - adapscen->setDefaultEditedState (Irrelevant); - adaplum->setDefaultEditedState (Irrelevant); - badpixsl->setDefaultEditedState (Irrelevant); - jlight->setDefaultEditedState (Irrelevant); - qbright->setDefaultEditedState (Irrelevant); - chroma->setDefaultEditedState (Irrelevant); - schroma->setDefaultEditedState (Irrelevant); - mchroma->setDefaultEditedState (Irrelevant); - contrast->setDefaultEditedState (Irrelevant); - qcontrast->setDefaultEditedState (Irrelevant); - rstprotection->setDefaultEditedState (Irrelevant); - colorh->setDefaultEditedState (Irrelevant); - - } + if (pedited) { + degree->setDefaultEditedState (pedited->colorappearance.degree ? Edited : UnEdited); + adapscen->setDefaultEditedState (pedited->colorappearance.adapscen ? Edited : UnEdited); + adaplum->setDefaultEditedState (pedited->colorappearance.adaplum ? Edited : UnEdited); + badpixsl->setDefaultEditedState (pedited->colorappearance.badpixsl ? Edited : UnEdited); + jlight->setDefaultEditedState (pedited->colorappearance.jlight ? Edited : UnEdited); + qbright->setDefaultEditedState (pedited->colorappearance.qbright ? Edited : UnEdited); + chroma->setDefaultEditedState (pedited->colorappearance.chroma ? Edited : UnEdited); + schroma->setDefaultEditedState (pedited->colorappearance.schroma ? Edited : UnEdited); + mchroma->setDefaultEditedState (pedited->colorappearance.mchroma ? Edited : UnEdited); + rstprotection->setDefaultEditedState (pedited->colorappearance.rstprotection ? Edited : UnEdited); + contrast->setDefaultEditedState (pedited->colorappearance.contrast ? Edited : UnEdited); + qcontrast->setDefaultEditedState (pedited->colorappearance.qcontrast ? Edited : UnEdited); + colorh->setDefaultEditedState (pedited->colorappearance.colorh ? Edited : UnEdited); + + } else { + degree->setDefaultEditedState (Irrelevant); + adapscen->setDefaultEditedState (Irrelevant); + adaplum->setDefaultEditedState (Irrelevant); + badpixsl->setDefaultEditedState (Irrelevant); + jlight->setDefaultEditedState (Irrelevant); + qbright->setDefaultEditedState (Irrelevant); + chroma->setDefaultEditedState (Irrelevant); + schroma->setDefaultEditedState (Irrelevant); + mchroma->setDefaultEditedState (Irrelevant); + contrast->setDefaultEditedState (Irrelevant); + qcontrast->setDefaultEditedState (Irrelevant); + rstprotection->setDefaultEditedState (Irrelevant); + colorh->setDefaultEditedState (Irrelevant); + + } } -int autoCamChangedUI (void* data) { +int autoCamChangedUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected (static_cast(data))->autoCamComputed_ (); return 0; } -void ColorAppearance::autoCamChanged (double ccam) -{ +void ColorAppearance::autoCamChanged (double ccam) +{ nextCcam = ccam; g_idle_add (autoCamChangedUI, this); } -bool ColorAppearance::autoCamComputed_ () { +bool ColorAppearance::autoCamComputed_ () +{ disableListener (); -// degree->setEnabled (true); - degree->setValue (nextCcam); +// degree->setEnabled (true); + degree->setValue (nextCcam); enableListener (); return false; } -int adapCamChangedUI (void* data) { +int adapCamChangedUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected (static_cast(data))->adapCamComputed_ (); return 0; } -void ColorAppearance::adapCamChanged (double cadap) +void ColorAppearance::adapCamChanged (double cadap) { nextCadap = cadap; g_idle_add (adapCamChangedUI, this); } -bool ColorAppearance::adapCamComputed_ () { +bool ColorAppearance::adapCamComputed_ () +{ disableListener (); -// degree->setEnabled (true); - adapscen->setValue (nextCadap); +// degree->setEnabled (true); + adapscen->setValue (nextCadap); enableListener (); return false; } -void ColorAppearance::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { +void ColorAppearance::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) +{ - float R, G, B; + float R, G, B; - if (elemType==ColorCaller::CCET_VERTICAL_BAR) - valY = 0.5; + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } - if (callerId == 1) { // cc - bottom bar + if (callerId == 1) { // cc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - // whole hue range - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); - } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } + + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); } -void ColorAppearance::adjusterChanged (Adjuster* a, double newval) { +void ColorAppearance::adjusterChanged (Adjuster* a, double newval) +{ - if (listener && (multiImage||getEnabled()) ) { - if(a==degree) - listener->panelChanged (EvCATDegree, a->getTextValue()); - else if(a==adapscen) - listener->panelChanged (EvCATAdapscen, a->getTextValue()); - else if(a==adaplum) - listener->panelChanged (EvCATAdapLum, a->getTextValue()); - else if(a==badpixsl) - listener->panelChanged (EvCATbadpix, a->getTextValue()); - else if(a==jlight) - listener->panelChanged (EvCATJLight, a->getTextValue()); - else if(a==qbright) - listener->panelChanged (EvCATQbright, a->getTextValue()); - else if(a==chroma) - listener->panelChanged (EvCATChroma, a->getTextValue()); - else if(a==schroma) - listener->panelChanged (EvCATSChroma, a->getTextValue()); - else if(a==mchroma) - listener->panelChanged (EvCATMChroma, a->getTextValue()); - else if(a==rstprotection) - listener->panelChanged (EvCATRstpro, a->getTextValue()); - else if(a==contrast) - listener->panelChanged (EvCATContrast, a->getTextValue()); - else if(a==colorh) - listener->panelChanged (EvCAThue, a->getTextValue()); - else if(a==qcontrast) - listener->panelChanged (EvCATQContrast, a->getTextValue()); - - } + if (listener && (multiImage || getEnabled()) ) { + if(a == degree) { + listener->panelChanged (EvCATDegree, a->getTextValue()); + } else if(a == adapscen) { + listener->panelChanged (EvCATAdapscen, a->getTextValue()); + } else if(a == adaplum) { + listener->panelChanged (EvCATAdapLum, a->getTextValue()); + } else if(a == badpixsl) { + listener->panelChanged (EvCATbadpix, a->getTextValue()); + } else if(a == jlight) { + listener->panelChanged (EvCATJLight, a->getTextValue()); + } else if(a == qbright) { + listener->panelChanged (EvCATQbright, a->getTextValue()); + } else if(a == chroma) { + listener->panelChanged (EvCATChroma, a->getTextValue()); + } else if(a == schroma) { + listener->panelChanged (EvCATSChroma, a->getTextValue()); + } else if(a == mchroma) { + listener->panelChanged (EvCATMChroma, a->getTextValue()); + } else if(a == rstprotection) { + listener->panelChanged (EvCATRstpro, a->getTextValue()); + } else if(a == contrast) { + listener->panelChanged (EvCATContrast, a->getTextValue()); + } else if(a == colorh) { + listener->panelChanged (EvCAThue, a->getTextValue()); + } else if(a == qcontrast) { + listener->panelChanged (EvCATQContrast, a->getTextValue()); + } + + } } -void ColorAppearance::adjusterAutoToggled (Adjuster* a, bool newval) { +void ColorAppearance::adjusterAutoToggled (Adjuster* a, bool newval) +{ - if (multiImage) { - if (degree->getAutoInconsistent()) { - degree->setAutoInconsistent(false); - degree->setAutoValue(false); - } - else if (lastAutoDegree) - degree->setAutoInconsistent(true); + if (multiImage) { + if (degree->getAutoInconsistent()) { + degree->setAutoInconsistent(false); + degree->setAutoValue(false); + } else if (lastAutoDegree) { + degree->setAutoInconsistent(true); + } - lastAutoDegree = degree->getAutoValue(); - - if (adapscen->getAutoInconsistent()) { - adapscen->setAutoInconsistent(false); - adapscen->setAutoValue(false); - } - else if (lastAutoAdapscen) - adapscen->setAutoInconsistent(true); + lastAutoDegree = degree->getAutoValue(); - lastAutoAdapscen = adapscen->getAutoValue(); - - } + if (adapscen->getAutoInconsistent()) { + adapscen->setAutoInconsistent(false); + adapscen->setAutoValue(false); + } else if (lastAutoAdapscen) { + adapscen->setAutoInconsistent(true); + } - if (listener && (multiImage||getEnabled()) ) { - - if(a==degree) { - if (degree->getAutoInconsistent()) - listener->panelChanged (EvCATAutoDegree, M("GENERAL_UNCHANGED")); - else if (degree->getAutoValue()) - listener->panelChanged (EvCATAutoDegree, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATAutoDegree, M("GENERAL_DISABLED")); - } - if(a==adapscen) { - if (adapscen->getAutoInconsistent()) - listener->panelChanged (EvCATAutoAdap, M("GENERAL_UNCHANGED")); - else if (adapscen->getAutoValue()) - listener->panelChanged (EvCATAutoAdap, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvCATAutoAdap, M("GENERAL_DISABLED")); - } - - - } + lastAutoAdapscen = adapscen->getAutoValue(); + + } + + if (listener && (multiImage || getEnabled()) ) { + + if(a == degree) { + if (degree->getAutoInconsistent()) { + listener->panelChanged (EvCATAutoDegree, M("GENERAL_UNCHANGED")); + } else if (degree->getAutoValue()) { + listener->panelChanged (EvCATAutoDegree, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvCATAutoDegree, M("GENERAL_DISABLED")); + } + } + + if(a == adapscen) { + if (adapscen->getAutoInconsistent()) { + listener->panelChanged (EvCATAutoAdap, M("GENERAL_UNCHANGED")); + } else if (adapscen->getAutoValue()) { + listener->panelChanged (EvCATAutoAdap, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvCATAutoAdap, M("GENERAL_DISABLED")); + } + } + + + } } -void ColorAppearance::enabledChanged () { +void ColorAppearance::enabledChanged () +{ - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvCATEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) { - listener->panelChanged (EvCATEnabled, M("GENERAL_ENABLED")); - curveEditorG->set_sensitive (true); - toneCurveMode->set_sensitive (true); - } - else - listener->panelChanged (EvCATEnabled, M("GENERAL_DISABLED")); - } + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvCATEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvCATEnabled, M("GENERAL_ENABLED")); + curveEditorG->set_sensitive (true); + toneCurveMode->set_sensitive (true); + } else { + listener->panelChanged (EvCATEnabled, M("GENERAL_DISABLED")); + } + } } -void ColorAppearance::surroundChanged () { +void ColorAppearance::surroundChanged () +{ - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvCATMethodsur, surround->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvCATMethodsur, surround->get_active_text ()); + } } -void ColorAppearance::wbmodelChanged () { +void ColorAppearance::wbmodelChanged () +{ - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvCATMethodWB, wbmodel->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvCATMethodWB, wbmodel->get_active_text ()); + } } -void ColorAppearance::algoChanged () { +void ColorAppearance::algoChanged () +{ - if ( algo->get_active_row_number()==0 ) { - contrast->show(); - rstprotection->show(); - qcontrast->hide(); - jlight->show(); - mchroma->hide(); - chroma->show(); - schroma->hide(); - qbright->hide(); - colorh->hide(); - tonecie->hide(); - // sharpcie->hide(); - curveEditorG->show(); - curveEditorG2->show(); - curveEditorG3->show(); - } - else if ( algo->get_active_row_number()==1 ) { - rstprotection->show(); - contrast->show(); - qcontrast->hide(); - jlight->show(); - mchroma->hide(); - chroma->hide(); - schroma->show(); - qbright->hide(); - colorh->hide(); - tonecie->hide(); -// sharpcie->hide(); - curveEditorG->show(); - curveEditorG2->show(); - curveEditorG3->show(); - } - else if ( algo->get_active_row_number()==2 ) { - contrast->hide(); - rstprotection->show(); - qcontrast->show(); - jlight->hide(); - mchroma->show(); - chroma->hide(); - schroma->hide(); - qbright->show(); - colorh->hide(); - tonecie->show(); - // sharpcie->show(); - // sharpcie->hide(); - curveEditorG->show(); - curveEditorG2->show(); - curveEditorG3->show(); - } - else if ( algo->get_active_row_number()>=3 ) { // ">=3" because everything has to be visible with the "(unchanged)" option too - contrast->show(); - rstprotection->show(); - qcontrast->show(); - jlight->show(); - mchroma->show(); - chroma->show(); - schroma->show(); - qbright->show(); - colorh->show(); - tonecie->show(); -// sharpcie->show(); -// sharpcie->hide(); - curveEditorG->show(); - curveEditorG2->show(); - curveEditorG3->show(); - } + if ( algo->get_active_row_number() == 0 ) { + contrast->show(); + rstprotection->show(); + qcontrast->hide(); + jlight->show(); + mchroma->hide(); + chroma->show(); + schroma->hide(); + qbright->hide(); + colorh->hide(); + tonecie->hide(); + // sharpcie->hide(); + curveEditorG->show(); + curveEditorG2->show(); + curveEditorG3->show(); + } else if ( algo->get_active_row_number() == 1 ) { + rstprotection->show(); + contrast->show(); + qcontrast->hide(); + jlight->show(); + mchroma->hide(); + chroma->hide(); + schroma->show(); + qbright->hide(); + colorh->hide(); + tonecie->hide(); +// sharpcie->hide(); + curveEditorG->show(); + curveEditorG2->show(); + curveEditorG3->show(); + } else if ( algo->get_active_row_number() == 2 ) { + contrast->hide(); + rstprotection->show(); + qcontrast->show(); + jlight->hide(); + mchroma->show(); + chroma->hide(); + schroma->hide(); + qbright->show(); + colorh->hide(); + tonecie->show(); + // sharpcie->show(); + // sharpcie->hide(); + curveEditorG->show(); + curveEditorG2->show(); + curveEditorG3->show(); + } else if ( algo->get_active_row_number() >= 3 ) { // ">=3" because everything has to be visible with the "(unchanged)" option too + contrast->show(); + rstprotection->show(); + qcontrast->show(); + jlight->show(); + mchroma->show(); + chroma->show(); + schroma->show(); + qbright->show(); + colorh->show(); + tonecie->show(); +// sharpcie->show(); +// sharpcie->hide(); + curveEditorG->show(); + curveEditorG2->show(); + curveEditorG3->show(); + } - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvCATMethodalg, algo->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvCATMethodalg, algo->get_active_text ()); + } } -void ColorAppearance::setBatchMode (bool batchMode) { +void ColorAppearance::setBatchMode (bool batchMode) +{ - ToolPanel::setBatchMode (batchMode); + ToolPanel::setBatchMode (batchMode); - degree->showEditedCB (); - adapscen->showEditedCB (); - adaplum->showEditedCB (); - badpixsl->showEditedCB (); - jlight->showEditedCB (); - qbright->showEditedCB (); - chroma->showEditedCB (); - schroma->showEditedCB (); - mchroma->showEditedCB (); - rstprotection->showEditedCB (); - contrast->showEditedCB (); - qcontrast->showEditedCB (); - colorh->showEditedCB (); + degree->showEditedCB (); + adapscen->showEditedCB (); + adaplum->showEditedCB (); + badpixsl->showEditedCB (); + jlight->showEditedCB (); + qbright->showEditedCB (); + chroma->showEditedCB (); + schroma->showEditedCB (); + mchroma->showEditedCB (); + rstprotection->showEditedCB (); + contrast->showEditedCB (); + qcontrast->showEditedCB (); + colorh->showEditedCB (); - surround->append_text (M("GENERAL_UNCHANGED")); - wbmodel->append_text (M("GENERAL_UNCHANGED")); - algo->append_text (M("GENERAL_UNCHANGED")); - toneCurveMode->append_text (M("GENERAL_UNCHANGED")); - toneCurveMode2->append_text (M("GENERAL_UNCHANGED")); - toneCurveMode3->append_text (M("GENERAL_UNCHANGED")); + surround->append_text (M("GENERAL_UNCHANGED")); + wbmodel->append_text (M("GENERAL_UNCHANGED")); + algo->append_text (M("GENERAL_UNCHANGED")); + toneCurveMode->append_text (M("GENERAL_UNCHANGED")); + toneCurveMode2->append_text (M("GENERAL_UNCHANGED")); + toneCurveMode3->append_text (M("GENERAL_UNCHANGED")); - curveEditorG->setBatchMode (batchMode); - curveEditorG2->setBatchMode (batchMode); - curveEditorG3->setBatchMode (batchMode); + curveEditorG->setBatchMode (batchMode); + curveEditorG2->setBatchMode (batchMode); + curveEditorG3->setBatchMode (batchMode); } -void ColorAppearance::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma){ +void ColorAppearance::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) +{ - shape->updateBackgroundHistogram (histLCAM); - shape3->updateBackgroundHistogram (histCCAM); + shape->updateBackgroundHistogram (histLCAM); + shape3->updateBackgroundHistogram (histCCAM); } -void ColorAppearance::setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd) { +void ColorAppearance::setAdjusterBehavior (bool degreeadd, bool adapscenadd, bool adaplumadd, bool badpixsladd, bool jlightadd, bool chromaadd, bool contrastadd, bool rstprotectionadd, bool qbrightadd, bool qcontrastadd, bool schromaadd, bool mchromaadd, bool colorhadd) +{ - degree->setAddMode(degreeadd); - adapscen->setAddMode(adapscenadd); - adaplum->setAddMode(adaplumadd); - badpixsl->setAddMode(badpixsladd); - jlight->setAddMode(jlightadd); - qbright->setAddMode(qbrightadd); - chroma->setAddMode(chromaadd); - schroma->setAddMode(schromaadd); - mchroma->setAddMode(mchromaadd); - rstprotection->setAddMode(rstprotectionadd); - contrast->setAddMode(contrastadd); - qcontrast->setAddMode(qcontrastadd); - colorh->setAddMode(colorhadd); + degree->setAddMode(degreeadd); + adapscen->setAddMode(adapscenadd); + adaplum->setAddMode(adaplumadd); + badpixsl->setAddMode(badpixsladd); + jlight->setAddMode(jlightadd); + qbright->setAddMode(qbrightadd); + chroma->setAddMode(chromaadd); + schroma->setAddMode(schromaadd); + mchroma->setAddMode(mchromaadd); + rstprotection->setAddMode(rstprotectionadd); + contrast->setAddMode(contrastadd); + qcontrast->setAddMode(qcontrastadd); + colorh->setAddMode(colorhadd); } -void ColorAppearance::trimValues (rtengine::procparams::ProcParams* pp) { +void ColorAppearance::trimValues (rtengine::procparams::ProcParams* pp) +{ - degree->trimValue(pp->colorappearance.degree); - adapscen->trimValue(pp->colorappearance.adapscen); - adaplum->trimValue(pp->colorappearance.adaplum); - badpixsl->trimValue(pp->colorappearance.badpixsl); - jlight->trimValue(pp->colorappearance.jlight); - qbright->trimValue(pp->colorappearance.qbright); - chroma->trimValue(pp->colorappearance.chroma); - schroma->trimValue(pp->colorappearance.schroma); - mchroma->trimValue(pp->colorappearance.mchroma); - rstprotection->trimValue(pp->colorappearance.rstprotection); - contrast->trimValue(pp->colorappearance.contrast); - qcontrast->trimValue(pp->colorappearance.qcontrast); - colorh->trimValue(pp->colorappearance.colorh); + degree->trimValue(pp->colorappearance.degree); + adapscen->trimValue(pp->colorappearance.adapscen); + adaplum->trimValue(pp->colorappearance.adaplum); + badpixsl->trimValue(pp->colorappearance.badpixsl); + jlight->trimValue(pp->colorappearance.jlight); + qbright->trimValue(pp->colorappearance.qbright); + chroma->trimValue(pp->colorappearance.chroma); + schroma->trimValue(pp->colorappearance.schroma); + mchroma->trimValue(pp->colorappearance.mchroma); + rstprotection->trimValue(pp->colorappearance.rstprotection); + contrast->trimValue(pp->colorappearance.contrast); + qcontrast->trimValue(pp->colorappearance.qcontrast); + colorh->trimValue(pp->colorappearance.colorh); } diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index 5bb821965..977b89ed7 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -7,7 +7,7 @@ * 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 @@ -28,9 +28,10 @@ #include "guiutils.h" #include "colorprovider.h" -class ColorAppearance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoCamListener, public CurveListener, public ColorProvider { +class ColorAppearance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoCamListener, public CurveListener, public ColorProvider +{ - protected: +protected: Glib::RefPtr bgTTips; Glib::RefPtr srTTips; Glib::RefPtr bgPixbuf; @@ -56,10 +57,10 @@ class ColorAppearance : public ToolParamBlock, public AdjusterListener, public F //Adjuster* edge; Gtk::CheckButton* surrsource; Gtk::CheckButton* gamut; - // Gtk::CheckButton* badpix; +// Gtk::CheckButton* badpix; Gtk::CheckButton* datacie; Gtk::CheckButton* tonecie; - // Gtk::CheckButton* sharpcie; + // Gtk::CheckButton* sharpcie; MyComboBoxText* surround; sigc::connection surroundconn; @@ -77,26 +78,26 @@ class ColorAppearance : public ToolParamBlock, public AdjusterListener, public F DiagonalCurveEditor* shape; DiagonalCurveEditor* shape2; DiagonalCurveEditor* shape3; - double nextCcam, nextCadap; + double nextCcam, nextCadap; bool lastAutoDegree; - bool lastAutoAdapscen; + bool lastAutoAdapscen; bool lastsurr; bool lastgamut; -// bool lastbadpix; - bool lastdatacie; - bool lasttonecie; - // bool lastsharpcie; - bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); +// bool lastbadpix; + bool lastdatacie; + bool lasttonecie; +// bool lastsharpcie; + bool bgTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); bool srTTipQuery(int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); - public: +public: ColorAppearance (); ~ColorAppearance (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); void adjusterAutoToggled (Adjuster* a, bool newval); @@ -107,7 +108,7 @@ class ColorAppearance : public ToolParamBlock, public AdjusterListener, public F void algoChanged (); void surrsource_toggled (); void gamut_toggled (); - // void badpix_toggled (); +// void badpix_toggled (); void datacie_toggled (); void tonecie_toggled (); // void sharpcie_toggled (); @@ -115,7 +116,7 @@ class ColorAppearance : public ToolParamBlock, public AdjusterListener, public F bool autoCamComputed_ (); void adapCamChanged (double cadap); bool adapCamComputed_ (); - + void curveChanged (CurveEditor* ce); void curveMode1Changed (); bool curveMode1Changed_ (); diff --git a/rtgui/coloredbar.cc b/rtgui/coloredbar.cc index f13e801c9..192f791fe 100644 --- a/rtgui/coloredbar.cc +++ b/rtgui/coloredbar.cc @@ -19,159 +19,187 @@ #include "coloredbar.h" -ColoredBar::ColoredBar (eRTOrientation orient) { - orientation = orient; - dirty = true; - this->x = this->y = this->w = this->h = 0; +ColoredBar::ColoredBar (eRTOrientation orient) +{ + orientation = orient; + dirty = true; + this->x = this->y = this->w = this->h = 0; } /* * Redraw the bar to a Cairo::ImageSurface */ -void ColoredBar::expose(Cairo::RefPtr destSurface) { - // look out if the Surface has to be redrawn - if (!surfaceCreated() || !destSurface) - return; - draw(); - copySurface(destSurface); +void ColoredBar::expose(Cairo::RefPtr destSurface) +{ + // look out if the Surface has to be redrawn + if (!surfaceCreated() || !destSurface) { + return; + } + + draw(); + copySurface(destSurface); } /* * Redraw the bar to a Gdk::Window */ -void ColoredBar::expose(Glib::RefPtr destWindow) { - // look out if the Surface has to be redrawn - if (!surfaceCreated() || !destWindow) - return; - draw(); - copySurface(destWindow); +void ColoredBar::expose(Glib::RefPtr destWindow) +{ + // look out if the Surface has to be redrawn + if (!surfaceCreated() || !destWindow) { + return; + } + + draw(); + copySurface(destWindow); } /* * Redraw the bar to a Gdk::Window */ -void ColoredBar::expose(BackBuffer *backBuffer) { - // look out if the Surface has to be redrawn - if (!surfaceCreated() || !backBuffer) - return; - draw(); - copySurface(backBuffer); +void ColoredBar::expose(BackBuffer *backBuffer) +{ + // look out if the Surface has to be redrawn + if (!surfaceCreated() || !backBuffer) { + return; + } + + draw(); + copySurface(backBuffer); } -void ColoredBar::draw() { - if (isDirty()) { - Cairo::RefPtr cr = getContext(); - // the bar has to be drawn to the Surface first - if (!bgGradient.empty()) { - // a gradient has been set, we use it - cr->set_line_width(0.); +void ColoredBar::draw() +{ + if (isDirty()) { + Cairo::RefPtr cr = getContext(); - // gradient background - Cairo::RefPtr< Cairo::LinearGradient > bggradient; - switch (orientation) { - case (RTO_Left2Right): - bggradient = Cairo::LinearGradient::create (0., 0., double(w), 0.); - break; - case (RTO_Right2Left): - bggradient = Cairo::LinearGradient::create (double(w), 0., 0., 0.); - break; - case (RTO_Bottom2Top): - bggradient = Cairo::LinearGradient::create (0., double(h), 0., 0.); - break; - case (RTO_Top2Bottom): - default: - bggradient = Cairo::LinearGradient::create (0., 0., 0., double(h)); - break; - } + // the bar has to be drawn to the Surface first + if (!bgGradient.empty()) { + // a gradient has been set, we use it + cr->set_line_width(0.); - for (std::vector::iterator i=bgGradient.begin(); i!=bgGradient.end(); i++) { - bggradient->add_color_stop_rgb (i->position, i->r, i->g, i->b); - } - cr->set_source (bggradient); - cr->rectangle(0, 0, w, h); - cr->fill(); - } - else { - // ask the ColorProvider to provide colors :) for each pixels - if (colorProvider) { - cr->set_antialias(Cairo::ANTIALIAS_NONE); - cr->set_line_width(1.); - switch (orientation) { - case (RTO_Left2Right): - for (int x=0; xcolorForValue (x01, y01, CCET_BACKGROUND, colorCallerId, this); - cr->set_source_rgb(ccRed, ccGreen, ccBlue); - cr->rectangle(x_, y_, 1., 1.); - cr->fill(); - } - } - break; - case (RTO_Right2Left): - for (int x=0; xcolorForValue (x01, y01, CCET_BACKGROUND, colorCallerId, this); - cr->set_source_rgb(ccRed, ccGreen, ccBlue); - cr->rectangle(x_, y_, 1., 1.); - cr->fill(); - } - } - break; - case (RTO_Bottom2Top): - for (int x=0; xcolorForValue (y01, x01, CCET_BACKGROUND, colorCallerId, this); - cr->set_source_rgb(ccRed, ccGreen, ccBlue); - cr->rectangle(x_, y_, 1., 1.); - cr->fill(); - } - } - break; - case (RTO_Top2Bottom): - default: - for (int x=0; xcolorForValue (y01, x01, CCET_BACKGROUND, colorCallerId, this); - cr->set_source_rgb(ccRed, ccGreen, ccBlue); - cr->rectangle(x_, y_, 1., 1.); - cr->fill(); - } - } - break; - } - } - } - // has it been updated or not, we assume that the Surface has been correctly set (we don't handle allocation error) - setDirty(false); - } + // gradient background + Cairo::RefPtr< Cairo::LinearGradient > bggradient; + + switch (orientation) { + case (RTO_Left2Right): + bggradient = Cairo::LinearGradient::create (0., 0., double(w), 0.); + break; + + case (RTO_Right2Left): + bggradient = Cairo::LinearGradient::create (double(w), 0., 0., 0.); + break; + + case (RTO_Bottom2Top): + bggradient = Cairo::LinearGradient::create (0., double(h), 0., 0.); + break; + + case (RTO_Top2Bottom): + default: + bggradient = Cairo::LinearGradient::create (0., 0., 0., double(h)); + break; + } + + for (std::vector::iterator i = bgGradient.begin(); i != bgGradient.end(); i++) { + bggradient->add_color_stop_rgb (i->position, i->r, i->g, i->b); + } + + cr->set_source (bggradient); + cr->rectangle(0, 0, w, h); + cr->fill(); + } else { + // ask the ColorProvider to provide colors :) for each pixels + if (colorProvider) { + cr->set_antialias(Cairo::ANTIALIAS_NONE); + cr->set_line_width(1.); + + switch (orientation) { + case (RTO_Left2Right): + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + double x_ = double( x); + double y_ = double((h - 1) - y); + double x01 = x_ / double(w - 1); + double y01 = double(y) / double(h - 1); + colorProvider->colorForValue (x01, y01, CCET_BACKGROUND, colorCallerId, this); + cr->set_source_rgb(ccRed, ccGreen, ccBlue); + cr->rectangle(x_, y_, 1., 1.); + cr->fill(); + } + } + + break; + + case (RTO_Right2Left): + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + double x_ = double((w - 1) - x); + double y_ = double((h - 1) - y); + double x01 = double(x) / double(w - 1); + double y01 = double(y) / double(h - 1); + colorProvider->colorForValue (x01, y01, CCET_BACKGROUND, colorCallerId, this); + cr->set_source_rgb(ccRed, ccGreen, ccBlue); + cr->rectangle(x_, y_, 1., 1.); + cr->fill(); + } + } + + break; + + case (RTO_Bottom2Top): + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + double x_ = double((w - 1) - x); + double y_ = double((h - 1) - y); + double x01 = double(x) / double(w - 1); + double y01 = double(y) / double(h - 1); + colorProvider->colorForValue (y01, x01, CCET_BACKGROUND, colorCallerId, this); + cr->set_source_rgb(ccRed, ccGreen, ccBlue); + cr->rectangle(x_, y_, 1., 1.); + cr->fill(); + } + } + + break; + + case (RTO_Top2Bottom): + default: + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + double x_ = double( x); + double y_ = double( y); + double x01 = x_ / double(w - 1); + double y01 = y_ / double(h - 1); + colorProvider->colorForValue (y01, x01, CCET_BACKGROUND, colorCallerId, this); + cr->set_source_rgb(ccRed, ccGreen, ccBlue); + cr->rectangle(x_, y_, 1., 1.); + cr->fill(); + } + } + + break; + } + } + } + + // has it been updated or not, we assume that the Surface has been correctly set (we don't handle allocation error) + setDirty(false); + } } -void ColoredBar::setBgGradient (const std::vector &milestones) { - bgGradient = milestones; - setDirty(true); +void ColoredBar::setBgGradient (const std::vector &milestones) +{ + bgGradient = milestones; + setDirty(true); } -void ColoredBar::clearBgGradient () { - bgGradient.clear(); - setDirty(true); +void ColoredBar::clearBgGradient () +{ + bgGradient.clear(); + setDirty(true); } -bool ColoredBar::canGetColors() { - return colorProvider!=NULL || bgGradient.size()>0; +bool ColoredBar::canGetColors() +{ + return colorProvider != NULL || bgGradient.size() > 0; } diff --git a/rtgui/coloredbar.h b/rtgui/coloredbar.h index d0351b6a5..917085e3c 100644 --- a/rtgui/coloredbar.h +++ b/rtgui/coloredbar.h @@ -26,29 +26,30 @@ * Parent class for all colored bar type; a ColorProvider has to be set * thanks to "setColorProvider" to be able to display colors inside the bar */ -class ColoredBar : public BackBuffer, public ColorCaller { +class ColoredBar : public BackBuffer, public ColorCaller +{ - private: - void draw(); +private: + void draw(); - protected: - eRTOrientation orientation; - std::vector bgGradient; +protected: + eRTOrientation orientation; + std::vector bgGradient; - public: - ColoredBar (eRTOrientation orient); +public: + ColoredBar (eRTOrientation orient); - void expose(Glib::RefPtr destWindow); - void expose(Cairo::RefPtr destSurface); - void expose(BackBuffer *backBuffer); + void expose(Glib::RefPtr destWindow); + void expose(Cairo::RefPtr destSurface); + void expose(BackBuffer *backBuffer); - bool canGetColors(); + bool canGetColors(); - // Method for convenience; if no Gradient provided, the ColoredBar will ask colors on a per pixel basis - void setBgGradient (const std::vector &milestones); - // by clearing the gradient, the ColorProvider will have to provide colors on a per pixel basis if a ColorProvider - // has been set, through ColorProvider::colorForValue on next ColoredBar::expose - void clearBgGradient (); + // Method for convenience; if no Gradient provided, the ColoredBar will ask colors on a per pixel basis + void setBgGradient (const std::vector &milestones); + // by clearing the gradient, the ColorProvider will have to provide colors on a per pixel basis if a ColorProvider + // has been set, through ColorProvider::colorForValue on next ColoredBar::expose + void clearBgGradient (); }; #endif diff --git a/rtgui/colorprovider.h b/rtgui/colorprovider.h index 94383f882..ce0c25247 100644 --- a/rtgui/colorprovider.h +++ b/rtgui/colorprovider.h @@ -26,26 +26,31 @@ class ColorProvider; /* * The ColorCaller is the class that will query the ColorProvider */ -class ColorCaller { - protected: - // a class can handle several ColorCaller; - // colorCallerId will let the provider identify the caller - int colorCallerId; - ColorProvider* colorProvider; +class ColorCaller +{ +protected: + // a class can handle several ColorCaller; + // colorCallerId will let the provider identify the caller + int colorCallerId; + ColorProvider* colorProvider; - public: - enum ElemType { - CCET_POINT, - CCET_VERTICAL_BAR, - CCET_HORIZONTAL_BAR, - CCET_BACKGROUND - }; - double ccRed; - double ccGreen; - double ccBlue; +public: + enum ElemType { + CCET_POINT, + CCET_VERTICAL_BAR, + CCET_HORIZONTAL_BAR, + CCET_BACKGROUND + }; + double ccRed; + double ccGreen; + double ccBlue; - ColorCaller() : colorCallerId(-1), colorProvider(NULL), ccRed(0.), ccGreen(0.), ccBlue(0.) {} - void setColorProvider (ColorProvider* p, int id) { colorProvider = p; colorCallerId = id; } + ColorCaller() : colorCallerId(-1), colorProvider(NULL), ccRed(0.), ccGreen(0.), ccBlue(0.) {} + void setColorProvider (ColorProvider* p, int id) + { + colorProvider = p; + colorCallerId = id; + } }; /* @@ -54,11 +59,12 @@ class ColorCaller { * you don't need to declare the instanciator class as BEING a ColorProvider, you'll * still be able to set gradients for e.g. ColoredBar(s) */ -class ColorProvider { +class ColorProvider +{ - public: - virtual ~ColorProvider() {}; - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) {}; +public: + virtual ~ColorProvider() {}; + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) {}; }; #endif diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 3abbffc66..5b6f21412 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -8,1083 +8,1117 @@ using namespace rtengine; using namespace rtengine::procparams; ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLORTONING_LABEL"), false, true) -{ - nextbw=0; - CurveListener::setMulti(true); - - //---------------method - - method = Gtk::manage (new MyComboBoxText ()); - method->append_text (M("TP_COLORTONING_LAB")); - method->append_text (M("TP_COLORTONING_RGBSLIDERS")); - method->append_text (M("TP_COLORTONING_RGBCURVES")); - method->append_text (M("TP_COLORTONING_SPLITCOCO")); - method->append_text (M("TP_COLORTONING_SPLITLR")); - method->set_active (0); - method->set_tooltip_text (M("TP_COLORTONING_METHOD_TOOLTIP")); - - ctbox = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_METHOD"))); - ctbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); - ctbox->pack_start (*method); - pack_start (*ctbox); - - methodconn = method->signal_changed().connect ( sigc::mem_fun(*this, &ColorToning::methodChanged) ); - - //----------- Color curve ------------------------------ - - colorSep = Gtk::manage (new Gtk::HSeparator()); - pack_start (*colorSep); - - colLabel = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_LABCOL"))); - colLabel->set_tooltip_text (M("TP_COLORTONING_LABCOL_TOOLTIP")); - - interLabel = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_LABINT"))); - interLabel->set_tooltip_text (M("TP_COLORTONING_LABINT_TOOLTIP")); - pack_start (*colLabel, Gtk::PACK_SHRINK, 4); - pack_start (*interLabel, Gtk::PACK_SHRINK, 4); - - colorCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_COLOR")); - colorCurveEditorG->setCurveListener (this); - - colorShape = static_cast(colorCurveEditorG->addCurve(CT_Flat, "", NULL, false)); - colorShape->setCurveColorProvider(this, 1); - std::vector milestones; - // whole hue range - for (int i=0; i<7; i++) { - float R, G, B; - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - colorShape->setLeftBarBgGradient(milestones); - - // luminance gradient - milestones.clear(); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - colorShape->setBottomBarBgGradient(milestones); - std::vector defaultCurve; - rtengine::ColorToningParams::getDefaultColorCurve(defaultCurve); - colorShape->setResetCurve(FCT_MinMaxCPoints, defaultCurve); - - // This will add the reset button at the end of the curveType buttons - colorCurveEditorG->curveListComplete(); - colorCurveEditorG->show(); - - pack_start( *colorCurveEditorG, Gtk::PACK_SHRINK, 2); - - //----------------------red green blue yellow colours - - twocolor = Gtk::manage (new MyComboBoxText ()); - twocolor->append_text (M("TP_COLORTONING_TWOSTD")); - twocolor->append_text (M("TP_COLORTONING_TWOALL")); - twocolor->append_text (M("TP_COLORTONING_TWOBY")); - twocolor->append_text (M("TP_COLORTONING_TWO2")); - twocolor->set_tooltip_text (M("TP_COLORTONING_TWOCOLOR_TOOLTIP")); - twocolor->set_active (0); - - twocconn = twocolor->signal_changed().connect( sigc::mem_fun(*this, &ColorToning::twoColorChangedByGui) ); - - pack_start (*twocolor, Gtk::PACK_SHRINK, 4); - - //----------- Opacity curve ------------------------------ - - opacityCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_OPACITY")); - opacityCurveEditorG->setCurveListener (this); - - rtengine::ColorToningParams::getDefaultOpacityCurve(defaultCurve); - opacityShape = static_cast(opacityCurveEditorG->addCurve(CT_Flat, "", NULL, false)); - opacityShape->setIdentityValue(0.); - opacityShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - opacityShape->setBottomBarBgGradient(milestones); - - // This will add the reset button at the end of the curveType buttons - opacityCurveEditorG->curveListComplete(); - opacityCurveEditorG->show(); - - pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); - - //---------Chroma curve 1 -------------------- - iby = Gtk::manage (new RTImage ("Chanmixer-BY.png")); - irg = Gtk::manage (new RTImage ("Chanmixer-RG.png")); - - clCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_CHROMAC")); - clCurveEditorG->setCurveListener (this); - - rtengine::ColorToningParams::getDefaultCLCurve(defaultCurve); - clshape = static_cast(clCurveEditorG->addCurve(CT_Diagonal, M("TP_COLORTONING_AB"),irg)); - clshape->setResetCurve(DiagonalCurveType(defaultCurve.at(0)), defaultCurve); - clshape->setTooltip(M("TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP")); - - clshape->setLeftBarColorProvider(this, 1); - clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - - clshape->setBottomBarBgGradient(milestones); - clCurveEditorG->curveListComplete(); - - pack_start( *clCurveEditorG, Gtk::PACK_SHRINK, 2); - - //---------Chroma curve 2 -------------------- - - cl2CurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_CHROMAC")); - cl2CurveEditorG->setCurveListener (this); - - rtengine::ColorToningParams::getDefaultCL2Curve(defaultCurve); - cl2shape = static_cast(cl2CurveEditorG->addCurve(CT_Diagonal, M("TP_COLORTONING_BY"),iby)); - cl2shape->setResetCurve(DiagonalCurveType(defaultCurve.at(0)), defaultCurve); - cl2shape->setTooltip(M("TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP")); - - cl2shape->setLeftBarColorProvider(this, 1); - cl2shape->setRangeDefaultMilestones(0.25, 0.5, 0.75); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - - cl2shape->setBottomBarBgGradient(milestones); - cl2CurveEditorG->curveListComplete(); - - pack_start( *cl2CurveEditorG, Gtk::PACK_SHRINK, 2); - - //--------------------- Reset curves ----------------------------- - /* Each curve can reset to a different curve, so this button only save one click now... so we remove it. - neutralCurves = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRALCUR"))); - RTImage *resetImgc = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); - neutralCurves->set_image(*resetImgc); - neutralCurves->set_tooltip_text (M("TP_COLORTONING_NEUTRALCUR_TIP")); - neutralcurvesconn = neutralCurves->signal_pressed().connect( sigc::mem_fun(*this, &ColorToning::neutralCurves_pressed) ); - neutralCurves->show(); - - pack_start (*neutralCurves); - */ - - //----------- Sliders + balance ------------------------------ - - hlColSat = Gtk::manage (new ThresholdAdjuster (M("TP_COLORTONING_HIGHLIGHT"), 0., 100., 60., M("TP_COLORTONING_STRENGTH"), 1., 0., 360., 80., M("TP_COLORTONING_HUE"), 1., NULL, false)); - hlColSat->setAdjusterListener (this); - hlColSat->setBgColorProvider(this, 2); - hlColSat->setUpdatePolicy(RTUP_DYNAMIC); - - pack_start( *hlColSat, Gtk::PACK_SHRINK, 0); - - shadowsColSat = Gtk::manage (new ThresholdAdjuster (M("TP_COLORTONING_SHADOWS"), 0., 100., 80., M("TP_COLORTONING_STRENGTH"), 1., 0., 360., 208., M("TP_COLORTONING_HUE"), 1., NULL, false)); - shadowsColSat->setAdjusterListener (this); - shadowsColSat->setBgColorProvider(this, 3); - shadowsColSat->setUpdatePolicy(RTUP_DYNAMIC); - - pack_start( *shadowsColSat, Gtk::PACK_SHRINK, 0); - - - balance = Gtk::manage( new Adjuster(M("TP_COLORTONING_BALANCE"), -100., 100., 1., 0.) ); - balance->setAdjusterListener(this); - - pack_start (*balance, Gtk::PACK_SHRINK, 2); - - //----------- Saturation and strength ------------------------------ - -// satLimiterSep = Gtk::manage (new Gtk::HSeparator()); - - -// pack_start (*satLimiterSep, Gtk::PACK_SHRINK); - -// Gtk::Frame *p1Frame; - // Vertical box container for the content of the Process 1 frame - Gtk::VBox *p1VBox; - p1Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SA")) ); - p1Frame->set_border_width(0); - p1Frame->set_label_align(0.025, 0.5); - - p1VBox = Gtk::manage ( new Gtk::VBox()); - p1VBox->set_border_width(4); - p1VBox->set_spacing(2); - - autosat = Gtk::manage (new Gtk::CheckButton (M("TP_COLORTONING_AUTOSAT"))); - autosat->set_active (true); - autosatConn = autosat->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::autosatChanged) ); - //satFrame->set_label_widget(*autosat); - - p1VBox->pack_start (*autosat, Gtk::PACK_SHRINK, 2); - - satProtectionThreshold = Gtk::manage( new Adjuster(M("TP_COLORTONING_SATURATIONTHRESHOLD"), 0., 100., 1., 80.) ); - satProtectionThreshold->setAdjusterListener(this); - satProtectionThreshold->set_sensitive(false); - - p1VBox->pack_start( *satProtectionThreshold, Gtk::PACK_SHRINK, 2); - - saturatedOpacity = Gtk::manage( new Adjuster(M("TP_COLORTONING_SATURATEDOPACITY"), 0., 100., 1., 30.) );; - saturatedOpacity->setAdjusterListener(this); - saturatedOpacity->set_sensitive(false); - - p1VBox->pack_start( *saturatedOpacity, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer - p1Frame->add(*p1VBox); - pack_start (*p1Frame, Gtk::PACK_EXPAND_WIDGET, 4); - - strength = Gtk::manage( new Adjuster(M("TP_COLORTONING_STR"), 0., 100., 1., 50.) );; - strength->setAdjusterListener(this); - - - - // --------------------Sliders BW Colortoning ------------------- - - chanMixerBox = Gtk::manage (new Gtk::VBox()); - Gtk::VBox *chanMixerHLBox = Gtk::manage (new Gtk::VBox()); - Gtk::VBox *chanMixerMidBox = Gtk::manage (new Gtk::VBox()); - Gtk::VBox *chanMixerShadowsBox = Gtk::manage (new Gtk::VBox()); - - Gtk::Image* iblueR = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* iyelL = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* imagL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - Gtk::Image* icyanL = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); - Gtk::Image* iredR = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); - - Gtk::Image* iblueRm = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* iyelLm = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* imagLm = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenRm = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - Gtk::Image* icyanLm = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); - Gtk::Image* iredRm = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); - - Gtk::Image* iblueRh = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* iyelLh = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* imagLh = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenRh = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - Gtk::Image* icyanLh = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); - Gtk::Image* iredRh = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); - - redhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanLh, iredRh )); - greenhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagLh , igreenRh)); - bluehigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelLh , iblueRh )); - - redmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanLm, iredRm )); - greenmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagLm , igreenRm)); - bluemed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelLm , iblueRm )); - - redlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanL, iredR )); - greenlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagL , igreenR)); - bluelow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelL , iblueR )); - - chanMixerHLBox->pack_start (*redhigh); - chanMixerHLBox->pack_start (*greenhigh); - chanMixerHLBox->pack_start (*bluehigh); - chanMixerMidBox->pack_start (*redmed); - chanMixerMidBox->pack_start (*greenmed); - chanMixerMidBox->pack_start (*bluemed); - chanMixerShadowsBox->pack_start (*redlow); - chanMixerShadowsBox->pack_start (*greenlow); - chanMixerShadowsBox->pack_start (*bluelow); - - Gtk::Frame *chanMixerHLFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT"))); - Gtk::Frame *chanMixerMidFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_MIDTONES"))); - Gtk::Frame *chanMixerShadowsFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SHADOWS"))); - - chanMixerHLFrame->add(*chanMixerHLBox); - chanMixerMidFrame->add(*chanMixerMidBox); - chanMixerShadowsFrame->add(*chanMixerShadowsBox); - - chanMixerBox->pack_start(*chanMixerHLFrame, Gtk::PACK_SHRINK); - chanMixerBox->pack_start(*chanMixerMidFrame, Gtk::PACK_SHRINK); - chanMixerBox->pack_start(*chanMixerShadowsFrame, Gtk::PACK_SHRINK); - - pack_start(*chanMixerBox, Gtk::PACK_SHRINK); - pack_start( *strength, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer - - //--------------------- Reset sliders --------------------------- - neutrHBox = Gtk::manage (new Gtk::HBox ()); - neutrHBox->set_border_width (2); - - neutral = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRAL"))); - RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); - neutral->set_image(*resetImg); - neutral->set_tooltip_text (M("TP_COLORTONING_NEUTRAL_TIP")); - neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &ColorToning::neutral_pressed) ); - neutral->show(); - neutrHBox->pack_start (*neutral); - - pack_start (*neutrHBox); - - //--------------------- Keep luminance checkbox ------------------- - lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_COLORTONING_LUMAMODE"))); - lumamode->set_tooltip_markup (M("TP_COLORTONING_LUMAMODE_TOOLTIP")); - lumamode->set_active (false); - lumamode->show (); - lumamodeConn = lumamode->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::lumamodeChanged) ); - - pack_start (*lumamode); - - - redlow->setAdjusterListener (this); - greenlow->setAdjusterListener (this); - bluelow->setAdjusterListener (this); - balance->setAdjusterListener (this); - redmed->setAdjusterListener (this); - greenmed->setAdjusterListener (this); - bluemed->setAdjusterListener (this); - redhigh->setAdjusterListener (this); - greenhigh->setAdjusterListener (this); - bluehigh->setAdjusterListener (this); - - show_all(); - - disableListener(); - methodChanged(); - enableListener(); +{ + nextbw = 0; + CurveListener::setMulti(true); + + //---------------method + + method = Gtk::manage (new MyComboBoxText ()); + method->append_text (M("TP_COLORTONING_LAB")); + method->append_text (M("TP_COLORTONING_RGBSLIDERS")); + method->append_text (M("TP_COLORTONING_RGBCURVES")); + method->append_text (M("TP_COLORTONING_SPLITCOCO")); + method->append_text (M("TP_COLORTONING_SPLITLR")); + method->set_active (0); + method->set_tooltip_text (M("TP_COLORTONING_METHOD_TOOLTIP")); + + ctbox = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_METHOD"))); + ctbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); + ctbox->pack_start (*method); + pack_start (*ctbox); + + methodconn = method->signal_changed().connect ( sigc::mem_fun(*this, &ColorToning::methodChanged) ); + + //----------- Color curve ------------------------------ + + colorSep = Gtk::manage (new Gtk::HSeparator()); + pack_start (*colorSep); + + colLabel = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_LABCOL"))); + colLabel->set_tooltip_text (M("TP_COLORTONING_LABCOL_TOOLTIP")); + + interLabel = Gtk::manage (new Gtk::Label (M("TP_COLORTONING_LABINT"))); + interLabel->set_tooltip_text (M("TP_COLORTONING_LABINT_TOOLTIP")); + pack_start (*colLabel, Gtk::PACK_SHRINK, 4); + pack_start (*interLabel, Gtk::PACK_SHRINK, 4); + + colorCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_COLOR")); + colorCurveEditorG->setCurveListener (this); + + colorShape = static_cast(colorCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + colorShape->setCurveColorProvider(this, 1); + std::vector milestones; + + // whole hue range + for (int i = 0; i < 7; i++) { + float R, G, B; + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } + + colorShape->setLeftBarBgGradient(milestones); + + // luminance gradient + milestones.clear(); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + colorShape->setBottomBarBgGradient(milestones); + std::vector defaultCurve; + rtengine::ColorToningParams::getDefaultColorCurve(defaultCurve); + colorShape->setResetCurve(FCT_MinMaxCPoints, defaultCurve); + + // This will add the reset button at the end of the curveType buttons + colorCurveEditorG->curveListComplete(); + colorCurveEditorG->show(); + + pack_start( *colorCurveEditorG, Gtk::PACK_SHRINK, 2); + + //----------------------red green blue yellow colours + + twocolor = Gtk::manage (new MyComboBoxText ()); + twocolor->append_text (M("TP_COLORTONING_TWOSTD")); + twocolor->append_text (M("TP_COLORTONING_TWOALL")); + twocolor->append_text (M("TP_COLORTONING_TWOBY")); + twocolor->append_text (M("TP_COLORTONING_TWO2")); + twocolor->set_tooltip_text (M("TP_COLORTONING_TWOCOLOR_TOOLTIP")); + twocolor->set_active (0); + + twocconn = twocolor->signal_changed().connect( sigc::mem_fun(*this, &ColorToning::twoColorChangedByGui) ); + + pack_start (*twocolor, Gtk::PACK_SHRINK, 4); + + //----------- Opacity curve ------------------------------ + + opacityCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_OPACITY")); + opacityCurveEditorG->setCurveListener (this); + + rtengine::ColorToningParams::getDefaultOpacityCurve(defaultCurve); + opacityShape = static_cast(opacityCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + opacityShape->setIdentityValue(0.); + opacityShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + opacityShape->setBottomBarBgGradient(milestones); + + // This will add the reset button at the end of the curveType buttons + opacityCurveEditorG->curveListComplete(); + opacityCurveEditorG->show(); + + pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); + + //---------Chroma curve 1 -------------------- + iby = Gtk::manage (new RTImage ("Chanmixer-BY.png")); + irg = Gtk::manage (new RTImage ("Chanmixer-RG.png")); + + clCurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_CHROMAC")); + clCurveEditorG->setCurveListener (this); + + rtengine::ColorToningParams::getDefaultCLCurve(defaultCurve); + clshape = static_cast(clCurveEditorG->addCurve(CT_Diagonal, M("TP_COLORTONING_AB"), irg)); + clshape->setResetCurve(DiagonalCurveType(defaultCurve.at(0)), defaultCurve); + clshape->setTooltip(M("TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP")); + + clshape->setLeftBarColorProvider(this, 1); + clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + + clshape->setBottomBarBgGradient(milestones); + clCurveEditorG->curveListComplete(); + + pack_start( *clCurveEditorG, Gtk::PACK_SHRINK, 2); + + //---------Chroma curve 2 -------------------- + + cl2CurveEditorG = new CurveEditorGroup (options.lastColorToningCurvesDir, M("TP_COLORTONING_CHROMAC")); + cl2CurveEditorG->setCurveListener (this); + + rtengine::ColorToningParams::getDefaultCL2Curve(defaultCurve); + cl2shape = static_cast(cl2CurveEditorG->addCurve(CT_Diagonal, M("TP_COLORTONING_BY"), iby)); + cl2shape->setResetCurve(DiagonalCurveType(defaultCurve.at(0)), defaultCurve); + cl2shape->setTooltip(M("TP_COLORTONING_CURVEEDITOR_CL_TOOLTIP")); + + cl2shape->setLeftBarColorProvider(this, 1); + cl2shape->setRangeDefaultMilestones(0.25, 0.5, 0.75); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + + cl2shape->setBottomBarBgGradient(milestones); + cl2CurveEditorG->curveListComplete(); + + pack_start( *cl2CurveEditorG, Gtk::PACK_SHRINK, 2); + + //--------------------- Reset curves ----------------------------- + /* Each curve can reset to a different curve, so this button only save one click now... so we remove it. + neutralCurves = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRALCUR"))); + RTImage *resetImgc = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); + neutralCurves->set_image(*resetImgc); + neutralCurves->set_tooltip_text (M("TP_COLORTONING_NEUTRALCUR_TIP")); + neutralcurvesconn = neutralCurves->signal_pressed().connect( sigc::mem_fun(*this, &ColorToning::neutralCurves_pressed) ); + neutralCurves->show(); + + pack_start (*neutralCurves); + */ + + //----------- Sliders + balance ------------------------------ + + hlColSat = Gtk::manage (new ThresholdAdjuster (M("TP_COLORTONING_HIGHLIGHT"), 0., 100., 60., M("TP_COLORTONING_STRENGTH"), 1., 0., 360., 80., M("TP_COLORTONING_HUE"), 1., NULL, false)); + hlColSat->setAdjusterListener (this); + hlColSat->setBgColorProvider(this, 2); + hlColSat->setUpdatePolicy(RTUP_DYNAMIC); + + pack_start( *hlColSat, Gtk::PACK_SHRINK, 0); + + shadowsColSat = Gtk::manage (new ThresholdAdjuster (M("TP_COLORTONING_SHADOWS"), 0., 100., 80., M("TP_COLORTONING_STRENGTH"), 1., 0., 360., 208., M("TP_COLORTONING_HUE"), 1., NULL, false)); + shadowsColSat->setAdjusterListener (this); + shadowsColSat->setBgColorProvider(this, 3); + shadowsColSat->setUpdatePolicy(RTUP_DYNAMIC); + + pack_start( *shadowsColSat, Gtk::PACK_SHRINK, 0); + + + balance = Gtk::manage( new Adjuster(M("TP_COLORTONING_BALANCE"), -100., 100., 1., 0.) ); + balance->setAdjusterListener(this); + + pack_start (*balance, Gtk::PACK_SHRINK, 2); + + //----------- Saturation and strength ------------------------------ + +// satLimiterSep = Gtk::manage (new Gtk::HSeparator()); + + +// pack_start (*satLimiterSep, Gtk::PACK_SHRINK); + +// Gtk::Frame *p1Frame; + // Vertical box container for the content of the Process 1 frame + Gtk::VBox *p1VBox; + p1Frame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SA")) ); + p1Frame->set_border_width(0); + p1Frame->set_label_align(0.025, 0.5); + + p1VBox = Gtk::manage ( new Gtk::VBox()); + p1VBox->set_border_width(4); + p1VBox->set_spacing(2); + + autosat = Gtk::manage (new Gtk::CheckButton (M("TP_COLORTONING_AUTOSAT"))); + autosat->set_active (true); + autosatConn = autosat->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::autosatChanged) ); + //satFrame->set_label_widget(*autosat); + + p1VBox->pack_start (*autosat, Gtk::PACK_SHRINK, 2); + + satProtectionThreshold = Gtk::manage( new Adjuster(M("TP_COLORTONING_SATURATIONTHRESHOLD"), 0., 100., 1., 80.) ); + satProtectionThreshold->setAdjusterListener(this); + satProtectionThreshold->set_sensitive(false); + + p1VBox->pack_start( *satProtectionThreshold, Gtk::PACK_SHRINK, 2); + + saturatedOpacity = Gtk::manage( new Adjuster(M("TP_COLORTONING_SATURATEDOPACITY"), 0., 100., 1., 30.) );; + saturatedOpacity->setAdjusterListener(this); + saturatedOpacity->set_sensitive(false); + + p1VBox->pack_start( *saturatedOpacity, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer + p1Frame->add(*p1VBox); + pack_start (*p1Frame, Gtk::PACK_EXPAND_WIDGET, 4); + + strength = Gtk::manage( new Adjuster(M("TP_COLORTONING_STR"), 0., 100., 1., 50.) );; + strength->setAdjusterListener(this); + + + + // --------------------Sliders BW Colortoning ------------------- + + chanMixerBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerHLBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerMidBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerShadowsBox = Gtk::manage (new Gtk::VBox()); + + Gtk::Image* iblueR = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelL = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* icyanL = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iredR = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + Gtk::Image* iblueRm = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelLm = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagLm = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenRm = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* icyanLm = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iredRm = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + Gtk::Image* iblueRh = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelLh = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagLh = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenRh = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* icyanLh = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iredRh = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + redhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanLh, iredRh )); + greenhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagLh , igreenRh)); + bluehigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelLh , iblueRh )); + + redmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanLm, iredRm )); + greenmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagLm , igreenRm)); + bluemed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelLm , iblueRm )); + + redlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., icyanL, iredR )); + greenlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., imagL , igreenR)); + bluelow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iyelL , iblueR )); + + chanMixerHLBox->pack_start (*redhigh); + chanMixerHLBox->pack_start (*greenhigh); + chanMixerHLBox->pack_start (*bluehigh); + chanMixerMidBox->pack_start (*redmed); + chanMixerMidBox->pack_start (*greenmed); + chanMixerMidBox->pack_start (*bluemed); + chanMixerShadowsBox->pack_start (*redlow); + chanMixerShadowsBox->pack_start (*greenlow); + chanMixerShadowsBox->pack_start (*bluelow); + + Gtk::Frame *chanMixerHLFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT"))); + Gtk::Frame *chanMixerMidFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_MIDTONES"))); + Gtk::Frame *chanMixerShadowsFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SHADOWS"))); + + chanMixerHLFrame->add(*chanMixerHLBox); + chanMixerMidFrame->add(*chanMixerMidBox); + chanMixerShadowsFrame->add(*chanMixerShadowsBox); + + chanMixerBox->pack_start(*chanMixerHLFrame, Gtk::PACK_SHRINK); + chanMixerBox->pack_start(*chanMixerMidFrame, Gtk::PACK_SHRINK); + chanMixerBox->pack_start(*chanMixerShadowsFrame, Gtk::PACK_SHRINK); + + pack_start(*chanMixerBox, Gtk::PACK_SHRINK); + pack_start( *strength, Gtk::PACK_SHRINK, 2); //I have moved after Chanmixer + + //--------------------- Reset sliders --------------------------- + neutrHBox = Gtk::manage (new Gtk::HBox ()); + neutrHBox->set_border_width (2); + + neutral = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRAL"))); + RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); + neutral->set_image(*resetImg); + neutral->set_tooltip_text (M("TP_COLORTONING_NEUTRAL_TIP")); + neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &ColorToning::neutral_pressed) ); + neutral->show(); + neutrHBox->pack_start (*neutral); + + pack_start (*neutrHBox); + + //--------------------- Keep luminance checkbox ------------------- + lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_COLORTONING_LUMAMODE"))); + lumamode->set_tooltip_markup (M("TP_COLORTONING_LUMAMODE_TOOLTIP")); + lumamode->set_active (false); + lumamode->show (); + lumamodeConn = lumamode->signal_toggled().connect( sigc::mem_fun(*this, &ColorToning::lumamodeChanged) ); + + pack_start (*lumamode); + + + redlow->setAdjusterListener (this); + greenlow->setAdjusterListener (this); + bluelow->setAdjusterListener (this); + balance->setAdjusterListener (this); + redmed->setAdjusterListener (this); + greenmed->setAdjusterListener (this); + bluemed->setAdjusterListener (this); + redhigh->setAdjusterListener (this); + greenhigh->setAdjusterListener (this); + bluehigh->setAdjusterListener (this); + + show_all(); + + disableListener(); + methodChanged(); + enableListener(); } -ColorToning::~ColorToning() { - delete colorCurveEditorG; - delete opacityCurveEditorG; - delete clCurveEditorG; - delete cl2CurveEditorG; +ColorToning::~ColorToning() +{ + delete colorCurveEditorG; + delete opacityCurveEditorG; + delete clCurveEditorG; + delete cl2CurveEditorG; } /* void ColorToning::neutralCurves_pressed () { - disableListener(); + disableListener(); - bool changed = false; - changed |= colorShape->reset(); - changed |= opacityShape->reset(); - changed |= clshape->reset(); - changed |= cl2shape->reset(); + bool changed = false; + changed |= colorShape->reset(); + changed |= opacityShape->reset(); + changed |= clshape->reset(); + changed |= cl2shape->reset(); - enableListener(); + enableListener(); - if (listener && enabled->get_active() && changed) - listener->panelChanged (EvColorToningNeutralcur, M("ADJUSTER_RESET_TO_DEFAULT")); + if (listener && enabled->get_active() && changed) + listener->panelChanged (EvColorToningNeutralcur, M("ADJUSTER_RESET_TO_DEFAULT")); } */ // Will only reset the chanel mixer -void ColorToning::neutral_pressed () { - disableListener(); - redlow->resetValue(false); - greenlow->resetValue(false); - bluelow->resetValue(false); - redmed->resetValue(false); - greenmed->resetValue(false); - bluemed->resetValue(false); - redhigh->resetValue(false); - greenhigh->resetValue(false); - bluehigh->resetValue(false); - //balance->resetValue(false); +void ColorToning::neutral_pressed () +{ + disableListener(); + redlow->resetValue(false); + greenlow->resetValue(false); + bluelow->resetValue(false); + redmed->resetValue(false); + greenmed->resetValue(false); + bluemed->resetValue(false); + redhigh->resetValue(false); + greenhigh->resetValue(false); + bluehigh->resetValue(false); + //balance->resetValue(false); - enableListener(); - if (listener && getEnabled()) - listener->panelChanged (EvColorToningNeutral, M("ADJUSTER_RESET_TO_DEFAULT")); + enableListener(); + + if (listener && getEnabled()) { + listener->panelChanged (EvColorToningNeutral, M("ADJUSTER_RESET_TO_DEFAULT")); + } } void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - methodconn.block(true); - twocconn.block(true); - colorShape->setCurve (pp->colorToning.colorCurve); - opacityShape->setCurve (pp->colorToning.opacityCurve); - clshape->setCurve (pp->colorToning.clcurve); - cl2shape->setCurve (pp->colorToning.cl2curve); + disableListener (); + methodconn.block(true); + twocconn.block(true); + colorShape->setCurve (pp->colorToning.colorCurve); + opacityShape->setCurve (pp->colorToning.opacityCurve); + clshape->setCurve (pp->colorToning.clcurve); + cl2shape->setCurve (pp->colorToning.cl2curve); - if (pedited) { - redlow->setEditedState (pedited->colorToning.redlow ? Edited : UnEdited); - greenlow->setEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); - bluelow->setEditedState (pedited->colorToning.bluelow ? Edited : UnEdited); - balance->setEditedState (pedited->colorToning.balance ? Edited : UnEdited); - redmed->setEditedState (pedited->colorToning.redmed ? Edited : UnEdited); - greenmed->setEditedState (pedited->colorToning.greenmed ? Edited : UnEdited); - bluemed->setEditedState (pedited->colorToning.bluemed ? Edited : UnEdited); - redhigh->setEditedState (pedited->colorToning.redhigh ? Edited : UnEdited); - greenhigh->setEditedState (pedited->colorToning.greenhigh ? Edited : UnEdited); - bluehigh->setEditedState (pedited->colorToning.bluehigh ? Edited : UnEdited); - - hlColSat->setEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); - shadowsColSat->setEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); + if (pedited) { + redlow->setEditedState (pedited->colorToning.redlow ? Edited : UnEdited); + greenlow->setEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); + bluelow->setEditedState (pedited->colorToning.bluelow ? Edited : UnEdited); + balance->setEditedState (pedited->colorToning.balance ? Edited : UnEdited); + redmed->setEditedState (pedited->colorToning.redmed ? Edited : UnEdited); + greenmed->setEditedState (pedited->colorToning.greenmed ? Edited : UnEdited); + bluemed->setEditedState (pedited->colorToning.bluemed ? Edited : UnEdited); + redhigh->setEditedState (pedited->colorToning.redhigh ? Edited : UnEdited); + greenhigh->setEditedState (pedited->colorToning.greenhigh ? Edited : UnEdited); + bluehigh->setEditedState (pedited->colorToning.bluehigh ? Edited : UnEdited); - set_inconsistent (multiImage && !pedited->colorToning.enabled); - colorShape->setUnChanged (!pedited->colorToning.colorCurve); - opacityShape->setUnChanged (!pedited->colorToning.opacityCurve); - autosat->set_inconsistent (!pedited->colorToning.autosat); - clshape->setUnChanged (!pedited->colorToning.clcurve); - cl2shape->setUnChanged (!pedited->colorToning.cl2curve); - lumamode->set_inconsistent (!pedited->colorToning.lumamode); - } - redlow->setValue (pp->colorToning.redlow); - greenlow->setValue (pp->colorToning.greenlow); - bluelow->setValue (pp->colorToning.bluelow); - balance->setValue (pp->colorToning.balance); - redmed->setValue (pp->colorToning.redmed); - greenmed->setValue (pp->colorToning.greenmed); - bluemed->setValue (pp->colorToning.bluemed); - redhigh->setValue (pp->colorToning.redhigh); - greenhigh->setValue (pp->colorToning.greenhigh); - bluehigh->setValue (pp->colorToning.bluehigh); - - setEnabled (pp->colorToning.enabled); + hlColSat->setEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); + shadowsColSat->setEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); - autosatConn.block (true); - autosat->set_active (pp->colorToning.autosat); - autosatConn.block (false); - lastautosat = pp->colorToning.autosat; - - satProtectionThreshold->setValue (pp->colorToning.satProtectionThreshold); - saturatedOpacity->setValue (pp->colorToning.saturatedOpacity); - hlColSat->setValue (pp->colorToning.hlColSat); - shadowsColSat->setValue (pp->colorToning.shadowsColSat); - strength->setValue (pp->colorToning.strength); - lumamodeConn.block (true); - lumamode->set_active (pp->colorToning.lumamode); - lumamodeConn.block (false); + set_inconsistent (multiImage && !pedited->colorToning.enabled); + colorShape->setUnChanged (!pedited->colorToning.colorCurve); + opacityShape->setUnChanged (!pedited->colorToning.opacityCurve); + autosat->set_inconsistent (!pedited->colorToning.autosat); + clshape->setUnChanged (!pedited->colorToning.clcurve); + cl2shape->setUnChanged (!pedited->colorToning.cl2curve); + lumamode->set_inconsistent (!pedited->colorToning.lumamode); + } - lastLumamode = pp->colorToning.lumamode; - - if (pedited && !pedited->colorToning.method) - method->set_active (5); - else if (pp->colorToning.method=="Lab") - method->set_active (0); - else if (pp->colorToning.method=="RGBSliders") - method->set_active (1); - else if (pp->colorToning.method=="RGBCurves") - method->set_active (2); - else if (pp->colorToning.method=="Splitco") - method->set_active (3); - else if (pp->colorToning.method=="Splitlr") - method->set_active (4); - methodChanged(); - methodconn.block(false); + redlow->setValue (pp->colorToning.redlow); + greenlow->setValue (pp->colorToning.greenlow); + bluelow->setValue (pp->colorToning.bluelow); + balance->setValue (pp->colorToning.balance); + redmed->setValue (pp->colorToning.redmed); + greenmed->setValue (pp->colorToning.greenmed); + bluemed->setValue (pp->colorToning.bluemed); + redhigh->setValue (pp->colorToning.redhigh); + greenhigh->setValue (pp->colorToning.greenhigh); + bluehigh->setValue (pp->colorToning.bluehigh); + + setEnabled (pp->colorToning.enabled); + + autosatConn.block (true); + autosat->set_active (pp->colorToning.autosat); + autosatConn.block (false); + lastautosat = pp->colorToning.autosat; + + satProtectionThreshold->setValue (pp->colorToning.satProtectionThreshold); + saturatedOpacity->setValue (pp->colorToning.saturatedOpacity); + hlColSat->setValue (pp->colorToning.hlColSat); + shadowsColSat->setValue (pp->colorToning.shadowsColSat); + strength->setValue (pp->colorToning.strength); + lumamodeConn.block (true); + lumamode->set_active (pp->colorToning.lumamode); + lumamodeConn.block (false); + + lastLumamode = pp->colorToning.lumamode; + + if (pedited && !pedited->colorToning.method) { + method->set_active (5); + } else if (pp->colorToning.method == "Lab") { + method->set_active (0); + } else if (pp->colorToning.method == "RGBSliders") { + method->set_active (1); + } else if (pp->colorToning.method == "RGBCurves") { + method->set_active (2); + } else if (pp->colorToning.method == "Splitco") { + method->set_active (3); + } else if (pp->colorToning.method == "Splitlr") { + method->set_active (4); + } + + methodChanged(); + methodconn.block(false); - if (pedited && !pedited->colorToning.twocolor) - twocolor->set_active (4); - else if (pp->colorToning.twocolor=="Std") - twocolor->set_active (0); - else if (pp->colorToning.twocolor=="All") - twocolor->set_active (1); - else if (pp->colorToning.twocolor=="Separ") - twocolor->set_active (2); - else if (pp->colorToning.twocolor=="Two") - twocolor->set_active (3); + if (pedited && !pedited->colorToning.twocolor) { + twocolor->set_active (4); + } else if (pp->colorToning.twocolor == "Std") { + twocolor->set_active (0); + } else if (pp->colorToning.twocolor == "All") { + twocolor->set_active (1); + } else if (pp->colorToning.twocolor == "Separ") { + twocolor->set_active (2); + } else if (pp->colorToning.twocolor == "Two") { + twocolor->set_active (3); + } - twocolorChanged(true); + twocolorChanged(true); - twocconn.block(false); + twocconn.block(false); - enableListener (); + enableListener (); } -void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) { - pp->colorToning.redlow = redlow->getValue (); - pp->colorToning.greenlow = greenlow->getValue (); - pp->colorToning.bluelow = bluelow->getValue (); - pp->colorToning.balance = balance->getIntValue (); - pp->colorToning.redmed = redmed->getValue (); - pp->colorToning.greenmed = greenmed->getValue (); - pp->colorToning.bluemed = bluemed->getValue (); - pp->colorToning.redhigh = redhigh->getValue (); - pp->colorToning.greenhigh = greenhigh->getValue (); - pp->colorToning.bluehigh = bluehigh->getValue (); +void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) +{ + pp->colorToning.redlow = redlow->getValue (); + pp->colorToning.greenlow = greenlow->getValue (); + pp->colorToning.bluelow = bluelow->getValue (); + pp->colorToning.balance = balance->getIntValue (); + pp->colorToning.redmed = redmed->getValue (); + pp->colorToning.greenmed = greenmed->getValue (); + pp->colorToning.bluemed = bluemed->getValue (); + pp->colorToning.redhigh = redhigh->getValue (); + pp->colorToning.greenhigh = greenhigh->getValue (); + pp->colorToning.bluehigh = bluehigh->getValue (); - pp->colorToning.enabled = getEnabled(); - pp->colorToning.colorCurve = colorShape->getCurve (); - pp->colorToning.opacityCurve = opacityShape->getCurve (); - pp->colorToning.clcurve = clshape->getCurve (); - pp->colorToning.cl2curve = cl2shape->getCurve (); - pp->colorToning.lumamode = lumamode->get_active(); + pp->colorToning.enabled = getEnabled(); + pp->colorToning.colorCurve = colorShape->getCurve (); + pp->colorToning.opacityCurve = opacityShape->getCurve (); + pp->colorToning.clcurve = clshape->getCurve (); + pp->colorToning.cl2curve = cl2shape->getCurve (); + pp->colorToning.lumamode = lumamode->get_active(); - pp->colorToning.hlColSat = hlColSat->getValue (); - pp->colorToning.shadowsColSat = shadowsColSat->getValue (); - pp->colorToning.autosat = autosat->get_active(); - pp->colorToning.satProtectionThreshold = satProtectionThreshold->getIntValue(); - pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue(); - pp->colorToning.strength = strength->getIntValue(); + pp->colorToning.hlColSat = hlColSat->getValue (); + pp->colorToning.shadowsColSat = shadowsColSat->getValue (); + pp->colorToning.autosat = autosat->get_active(); + pp->colorToning.satProtectionThreshold = satProtectionThreshold->getIntValue(); + pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue(); + pp->colorToning.strength = strength->getIntValue(); - if (pedited) { - pedited->colorToning.redlow = redlow->getEditedState (); - pedited->colorToning.greenlow = greenlow->getEditedState (); - pedited->colorToning.bluelow = bluelow->getEditedState (); - pedited->colorToning.balance = balance->getEditedState (); - pedited->colorToning.redmed = redmed->getEditedState (); - pedited->colorToning.greenmed = greenmed->getEditedState (); - pedited->colorToning.bluemed = bluemed->getEditedState (); - pedited->colorToning.redhigh = redhigh->getEditedState (); - pedited->colorToning.greenhigh = greenhigh->getEditedState (); - pedited->colorToning.bluehigh = bluehigh->getEditedState (); - pedited->colorToning.method = method->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->colorToning.twocolor = twocolor->get_active_text()!=M("GENERAL_UNCHANGED"); + if (pedited) { + pedited->colorToning.redlow = redlow->getEditedState (); + pedited->colorToning.greenlow = greenlow->getEditedState (); + pedited->colorToning.bluelow = bluelow->getEditedState (); + pedited->colorToning.balance = balance->getEditedState (); + pedited->colorToning.redmed = redmed->getEditedState (); + pedited->colorToning.greenmed = greenmed->getEditedState (); + pedited->colorToning.bluemed = bluemed->getEditedState (); + pedited->colorToning.redhigh = redhigh->getEditedState (); + pedited->colorToning.greenhigh = greenhigh->getEditedState (); + pedited->colorToning.bluehigh = bluehigh->getEditedState (); + pedited->colorToning.method = method->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->colorToning.twocolor = twocolor->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->colorToning.enabled = !get_inconsistent(); - pedited->colorToning.autosat = !autosat->get_inconsistent(); - pedited->colorToning.colorCurve = !colorShape->isUnChanged (); - pedited->colorToning.opacityCurve = !opacityShape->isUnChanged (); - pedited->colorToning.clcurve = !clshape->isUnChanged (); - pedited->colorToning.cl2curve = !cl2shape->isUnChanged (); - pedited->colorToning.lumamode = !lumamode->get_inconsistent(); + pedited->colorToning.enabled = !get_inconsistent(); + pedited->colorToning.autosat = !autosat->get_inconsistent(); + pedited->colorToning.colorCurve = !colorShape->isUnChanged (); + pedited->colorToning.opacityCurve = !opacityShape->isUnChanged (); + pedited->colorToning.clcurve = !clshape->isUnChanged (); + pedited->colorToning.cl2curve = !cl2shape->isUnChanged (); + pedited->colorToning.lumamode = !lumamode->get_inconsistent(); - pedited->colorToning.hlColSat = hlColSat->getEditedState (); - pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState (); - } + pedited->colorToning.hlColSat = hlColSat->getEditedState (); + pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState (); + } - if (method->get_active_row_number()==0) - pp->colorToning.method = "Lab"; - else if (method->get_active_row_number()==1) - pp->colorToning.method = "RGBSliders"; - else if (method->get_active_row_number()==2) - pp->colorToning.method = "RGBCurves"; - else if (method->get_active_row_number()==3) - pp->colorToning.method = "Splitco"; - else if (method->get_active_row_number()==4) - pp->colorToning.method = "Splitlr"; + if (method->get_active_row_number() == 0) { + pp->colorToning.method = "Lab"; + } else if (method->get_active_row_number() == 1) { + pp->colorToning.method = "RGBSliders"; + } else if (method->get_active_row_number() == 2) { + pp->colorToning.method = "RGBCurves"; + } else if (method->get_active_row_number() == 3) { + pp->colorToning.method = "Splitco"; + } else if (method->get_active_row_number() == 4) { + pp->colorToning.method = "Splitlr"; + } - if (twocolor->get_active_row_number()==0) - pp->colorToning.twocolor = "Std"; - else if (twocolor->get_active_row_number()==1) - pp->colorToning.twocolor = "All"; - else if (twocolor->get_active_row_number()==2) - pp->colorToning.twocolor = "Separ"; - else if (twocolor->get_active_row_number()==3) - pp->colorToning.twocolor = "Two"; + if (twocolor->get_active_row_number() == 0) { + pp->colorToning.twocolor = "Std"; + } else if (twocolor->get_active_row_number() == 1) { + pp->colorToning.twocolor = "All"; + } else if (twocolor->get_active_row_number() == 2) { + pp->colorToning.twocolor = "Separ"; + } else if (twocolor->get_active_row_number() == 3) { + pp->colorToning.twocolor = "Two"; + } } -void ColorToning::lumamodeChanged () { +void ColorToning::lumamodeChanged () +{ - if (batchMode) { - if (lumamode->get_inconsistent()) { - lumamode->set_inconsistent (false); - lumamodeConn.block (true); - lumamode->set_active (false); - lumamodeConn.block (false); - } - else if (lastLumamode) - lumamode->set_inconsistent (true); + if (batchMode) { + if (lumamode->get_inconsistent()) { + lumamode->set_inconsistent (false); + lumamodeConn.block (true); + lumamode->set_active (false); + lumamodeConn.block (false); + } else if (lastLumamode) { + lumamode->set_inconsistent (true); + } - lastLumamode = lumamode->get_active (); - } + lastLumamode = lumamode->get_active (); + } - if (listener && getEnabled()) { - if (lumamode->get_active ()) - listener->panelChanged (EvColorToningLumamode, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvColorToningLumamode, M("GENERAL_DISABLED")); - } + if (listener && getEnabled()) { + if (lumamode->get_active ()) { + listener->panelChanged (EvColorToningLumamode, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvColorToningLumamode, M("GENERAL_DISABLED")); + } + } } -void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ - redlow->setDefault (defParams->colorToning.redlow); - greenlow->setDefault (defParams->colorToning.greenlow); - bluelow->setDefault (defParams->colorToning.bluelow); - balance->setDefault (defParams->colorToning.balance); - redmed->setDefault (defParams->colorToning.redmed); - greenmed->setDefault (defParams->colorToning.greenmed); - bluemed->setDefault (defParams->colorToning.bluemed); - redhigh->setDefault (defParams->colorToning.redhigh); - greenhigh->setDefault (defParams->colorToning.greenhigh); - bluehigh->setDefault (defParams->colorToning.bluehigh); - satProtectionThreshold->setDefault (defParams->colorToning.satProtectionThreshold); - saturatedOpacity->setDefault (defParams->colorToning.saturatedOpacity); - hlColSat->setDefault (defParams->colorToning.hlColSat); - shadowsColSat->setDefault (defParams->colorToning.shadowsColSat); - strength->setDefault (defParams->colorToning.strength); + redlow->setDefault (defParams->colorToning.redlow); + greenlow->setDefault (defParams->colorToning.greenlow); + bluelow->setDefault (defParams->colorToning.bluelow); + balance->setDefault (defParams->colorToning.balance); + redmed->setDefault (defParams->colorToning.redmed); + greenmed->setDefault (defParams->colorToning.greenmed); + bluemed->setDefault (defParams->colorToning.bluemed); + redhigh->setDefault (defParams->colorToning.redhigh); + greenhigh->setDefault (defParams->colorToning.greenhigh); + bluehigh->setDefault (defParams->colorToning.bluehigh); + satProtectionThreshold->setDefault (defParams->colorToning.satProtectionThreshold); + saturatedOpacity->setDefault (defParams->colorToning.saturatedOpacity); + hlColSat->setDefault (defParams->colorToning.hlColSat); + shadowsColSat->setDefault (defParams->colorToning.shadowsColSat); + strength->setDefault (defParams->colorToning.strength); - if (pedited) { - redlow->setDefaultEditedState (pedited->colorToning.redlow ? Edited : UnEdited); - greenlow->setDefaultEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); - bluelow->setDefaultEditedState (pedited->colorToning.bluelow ? Edited : UnEdited); - balance->setDefaultEditedState (pedited->colorToning.balance ? Edited : UnEdited); - redmed->setDefaultEditedState (pedited->colorToning.redmed ? Edited : UnEdited); - greenmed->setDefaultEditedState (pedited->colorToning.greenmed ? Edited : UnEdited); - bluemed->setDefaultEditedState (pedited->colorToning.bluemed ? Edited : UnEdited); - redhigh->setDefaultEditedState (pedited->colorToning.redhigh ? Edited : UnEdited); - greenhigh->setDefaultEditedState (pedited->colorToning.greenhigh ? Edited : UnEdited); - bluehigh->setDefaultEditedState (pedited->colorToning.bluehigh ? Edited : UnEdited); - satProtectionThreshold->setDefaultEditedState (pedited->colorToning.satprotectionthreshold ? Edited : UnEdited); - saturatedOpacity->setDefaultEditedState (pedited->colorToning.saturatedopacity ? Edited : UnEdited); - hlColSat->setDefaultEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); - shadowsColSat->setDefaultEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); - strength->setDefaultEditedState (pedited->colorToning.strength ? Edited : UnEdited); - } - else { - redlow->setDefaultEditedState (Irrelevant); - greenlow->setDefaultEditedState (Irrelevant); - bluelow->setDefaultEditedState (Irrelevant); - balance->setDefaultEditedState (Irrelevant); - redmed->setDefaultEditedState (Irrelevant); - greenmed->setDefaultEditedState (Irrelevant); - bluemed->setDefaultEditedState (Irrelevant); - redhigh->setDefaultEditedState (Irrelevant); - greenhigh->setDefaultEditedState (Irrelevant); - bluehigh->setDefaultEditedState (Irrelevant); - satProtectionThreshold->setDefaultEditedState (Irrelevant); - saturatedOpacity->setDefaultEditedState (Irrelevant); - hlColSat->setDefaultEditedState (Irrelevant); - shadowsColSat->setDefaultEditedState (Irrelevant); - strength->setDefaultEditedState (Irrelevant); - } + if (pedited) { + redlow->setDefaultEditedState (pedited->colorToning.redlow ? Edited : UnEdited); + greenlow->setDefaultEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); + bluelow->setDefaultEditedState (pedited->colorToning.bluelow ? Edited : UnEdited); + balance->setDefaultEditedState (pedited->colorToning.balance ? Edited : UnEdited); + redmed->setDefaultEditedState (pedited->colorToning.redmed ? Edited : UnEdited); + greenmed->setDefaultEditedState (pedited->colorToning.greenmed ? Edited : UnEdited); + bluemed->setDefaultEditedState (pedited->colorToning.bluemed ? Edited : UnEdited); + redhigh->setDefaultEditedState (pedited->colorToning.redhigh ? Edited : UnEdited); + greenhigh->setDefaultEditedState (pedited->colorToning.greenhigh ? Edited : UnEdited); + bluehigh->setDefaultEditedState (pedited->colorToning.bluehigh ? Edited : UnEdited); + satProtectionThreshold->setDefaultEditedState (pedited->colorToning.satprotectionthreshold ? Edited : UnEdited); + saturatedOpacity->setDefaultEditedState (pedited->colorToning.saturatedopacity ? Edited : UnEdited); + hlColSat->setDefaultEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); + shadowsColSat->setDefaultEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); + strength->setDefaultEditedState (pedited->colorToning.strength ? Edited : UnEdited); + } else { + redlow->setDefaultEditedState (Irrelevant); + greenlow->setDefaultEditedState (Irrelevant); + bluelow->setDefaultEditedState (Irrelevant); + balance->setDefaultEditedState (Irrelevant); + redmed->setDefaultEditedState (Irrelevant); + greenmed->setDefaultEditedState (Irrelevant); + bluemed->setDefaultEditedState (Irrelevant); + redhigh->setDefaultEditedState (Irrelevant); + greenhigh->setDefaultEditedState (Irrelevant); + bluehigh->setDefaultEditedState (Irrelevant); + satProtectionThreshold->setDefaultEditedState (Irrelevant); + saturatedOpacity->setDefaultEditedState (Irrelevant); + hlColSat->setDefaultEditedState (Irrelevant); + shadowsColSat->setDefaultEditedState (Irrelevant); + strength->setDefaultEditedState (Irrelevant); + } } -void ColorToning::setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd) { - redlow->setAddMode(splitAdd); - greenlow->setAddMode(splitAdd); - bluelow->setAddMode(splitAdd); - balance->setAddMode(splitAdd); - redmed->setAddMode(splitAdd); - greenmed->setAddMode(splitAdd); - bluemed->setAddMode(splitAdd); - redhigh->setAddMode(splitAdd); - greenhigh->setAddMode(splitAdd); - bluehigh->setAddMode(splitAdd); - satProtectionThreshold->setAddMode(satThresholdAdd); - saturatedOpacity->setAddMode(satOpacityAdd); - balance->setAddMode(balanceAdd); - strength->setAddMode(strprotectAdd); - +void ColorToning::setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd) +{ + redlow->setAddMode(splitAdd); + greenlow->setAddMode(splitAdd); + bluelow->setAddMode(splitAdd); + balance->setAddMode(splitAdd); + redmed->setAddMode(splitAdd); + greenmed->setAddMode(splitAdd); + bluemed->setAddMode(splitAdd); + redhigh->setAddMode(splitAdd); + greenhigh->setAddMode(splitAdd); + bluehigh->setAddMode(splitAdd); + satProtectionThreshold->setAddMode(satThresholdAdd); + saturatedOpacity->setAddMode(satOpacityAdd); + balance->setAddMode(balanceAdd); + strength->setAddMode(strprotectAdd); + } -void ColorToning::adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop) { - if (listener && getEnabled()) - listener->panelChanged (a==hlColSat ? EvColorToningHighights : EvColorToningShadows, - Glib::ustring::compose(Glib::ustring(M("TP_COLORTONING_HUE")+": %1"+"\n"+M("TP_COLORTONING_STRENGTH")+": %2"), int(newTop), int(newBottom))); +void ColorToning::adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop) +{ + if (listener && getEnabled()) + listener->panelChanged (a == hlColSat ? EvColorToningHighights : EvColorToningShadows, + Glib::ustring::compose(Glib::ustring(M("TP_COLORTONING_HUE") + ": %1" + "\n" + M("TP_COLORTONING_STRENGTH") + ": %2"), int(newTop), int(newBottom))); } -int CTChanged_UI (void* data) { - GThreadLock lock; - (static_cast(data))->CTComp_ (); - return 0; +int CTChanged_UI (void* data) +{ + GThreadLock lock; + (static_cast(data))->CTComp_ (); + return 0; } -void ColorToning::autoColorTonChanged(int bwct, int satthres, int satprot){ - nextbw = bwct; - nextsatth=satthres; - nextsatpr=satprot; - g_idle_add (CTChanged_UI, this); +void ColorToning::autoColorTonChanged(int bwct, int satthres, int satprot) +{ + nextbw = bwct; + nextsatth = satthres; + nextsatpr = satprot; + g_idle_add (CTChanged_UI, this); } -bool ColorToning::CTComp_ () { +bool ColorToning::CTComp_ () +{ - disableListener (); - saturatedOpacity->setValue (nextsatpr); - satProtectionThreshold->setValue (nextsatth); -/* if(nextbw==1) { - saturatedOpacity->show(); - satProtectionThreshold->show(); - autosat->show(); - } - else { - saturatedOpacity->hide(); - satProtectionThreshold->hide(); - autosat->hide(); - } -*/ - enableListener (); + disableListener (); + saturatedOpacity->setValue (nextsatpr); + satProtectionThreshold->setValue (nextsatth); + /* if(nextbw==1) { + saturatedOpacity->show(); + satProtectionThreshold->show(); + autosat->show(); + } + else { + saturatedOpacity->hide(); + satProtectionThreshold->hide(); + autosat->hide(); + } + */ + enableListener (); - return false; + return false; } -void ColorToning::adjusterChanged (Adjuster* a, double newval) { +void ColorToning::adjusterChanged (Adjuster* a, double newval) +{ - if (!listener || !getEnabled()) - return; + if (!listener || !getEnabled()) { + return; + } - if (a==redlow) - listener->panelChanged (EvColorToningredlow, redlow->getTextValue()); - else if (a==greenlow) - listener->panelChanged (EvColorToninggreenlow, greenlow->getTextValue()); - else if (a==bluelow) - listener->panelChanged (EvColorToningbluelow, bluelow->getTextValue()); - else if (a==redmed) - listener->panelChanged (EvColorToningredmed, redmed->getTextValue()); - else if (a==greenmed) - listener->panelChanged (EvColorToninggreenmed, greenmed->getTextValue()); - else if (a==bluemed) - listener->panelChanged (EvColorToningbluemed, bluemed->getTextValue()); - else if (a==redhigh) - listener->panelChanged (EvColorToningredhigh, redhigh->getTextValue()); - else if (a==greenhigh) - listener->panelChanged (EvColorToninggreenhigh, greenhigh->getTextValue()); - else if (a==bluehigh) - listener->panelChanged (EvColorToningbluehigh, bluehigh->getTextValue()); - else if (a==balance) - listener->panelChanged (EvColorToningbalance, balance->getTextValue()); - else if (a==satProtectionThreshold) - listener->panelChanged (EvColorToningSatThreshold, a->getTextValue()); - else if (a==saturatedOpacity) - listener->panelChanged (EvColorToningSatProtection, a->getTextValue()); - else if (a==strength) - listener->panelChanged (EvColorToningStrength, a->getTextValue()); + if (a == redlow) { + listener->panelChanged (EvColorToningredlow, redlow->getTextValue()); + } else if (a == greenlow) { + listener->panelChanged (EvColorToninggreenlow, greenlow->getTextValue()); + } else if (a == bluelow) { + listener->panelChanged (EvColorToningbluelow, bluelow->getTextValue()); + } else if (a == redmed) { + listener->panelChanged (EvColorToningredmed, redmed->getTextValue()); + } else if (a == greenmed) { + listener->panelChanged (EvColorToninggreenmed, greenmed->getTextValue()); + } else if (a == bluemed) { + listener->panelChanged (EvColorToningbluemed, bluemed->getTextValue()); + } else if (a == redhigh) { + listener->panelChanged (EvColorToningredhigh, redhigh->getTextValue()); + } else if (a == greenhigh) { + listener->panelChanged (EvColorToninggreenhigh, greenhigh->getTextValue()); + } else if (a == bluehigh) { + listener->panelChanged (EvColorToningbluehigh, bluehigh->getTextValue()); + } else if (a == balance) { + listener->panelChanged (EvColorToningbalance, balance->getTextValue()); + } else if (a == satProtectionThreshold) { + listener->panelChanged (EvColorToningSatThreshold, a->getTextValue()); + } else if (a == saturatedOpacity) { + listener->panelChanged (EvColorToningSatProtection, a->getTextValue()); + } else if (a == strength) { + listener->panelChanged (EvColorToningStrength, a->getTextValue()); + } } //Two Color changed -void ColorToning::twocolorChanged (bool changedbymethod) { - if (!batchMode) { - if(method->get_active_row_number()==0) { // Lab - if(twocolor->get_active_row_number()==0) { - colorCurveEditorG->show(); // visible - opacityCurveEditorG->show(); // visible - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - } - else if(twocolor->get_active_row_number()==1 || twocolor->get_active_row_number()==3) { - colorCurveEditorG->show(); // visible - opacityCurveEditorG->hide(); - clCurveEditorG->show(); // visible - cl2CurveEditorG->hide(); - irg->hide(); - - } - else if(twocolor->get_active_row_number()==2) { - colorCurveEditorG->show(); // visible - opacityCurveEditorG->hide(); - clCurveEditorG->show(); // visible - cl2CurveEditorG->show(); // visible - irg->show(); - } - } - else if(method->get_active_row_number()==1) { // RGB Sliders - colorCurveEditorG->hide(); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - } - else if(method->get_active_row_number()==2) { // RGB Curves - colorCurveEditorG->show(); // visible - opacityCurveEditorG->show(); // visible - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - } - else if(method->get_active_row_number()==3) { // Split LR - colorCurveEditorG->hide(); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - } - else if(method->get_active_row_number()==4) { // Split color - colorCurveEditorG->hide(); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - } - } +void ColorToning::twocolorChanged (bool changedbymethod) +{ + if (!batchMode) { + if(method->get_active_row_number() == 0) { // Lab + if(twocolor->get_active_row_number() == 0) { + colorCurveEditorG->show(); // visible + opacityCurveEditorG->show(); // visible + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } else if(twocolor->get_active_row_number() == 1 || twocolor->get_active_row_number() == 3) { + colorCurveEditorG->show(); // visible + opacityCurveEditorG->hide(); + clCurveEditorG->show(); // visible + cl2CurveEditorG->hide(); + irg->hide(); - if (listener && getEnabled() && !changedbymethod) - listener->panelChanged (EvColorToningTwocolor, twocolor->get_active_text ()); + } else if(twocolor->get_active_row_number() == 2) { + colorCurveEditorG->show(); // visible + opacityCurveEditorG->hide(); + clCurveEditorG->show(); // visible + cl2CurveEditorG->show(); // visible + irg->show(); + } + } else if(method->get_active_row_number() == 1) { // RGB Sliders + colorCurveEditorG->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } else if(method->get_active_row_number() == 2) { // RGB Curves + colorCurveEditorG->show(); // visible + opacityCurveEditorG->show(); // visible + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } else if(method->get_active_row_number() == 3) { // Split LR + colorCurveEditorG->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } else if(method->get_active_row_number() == 4) { // Split color + colorCurveEditorG->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + } + } + + if (listener && getEnabled() && !changedbymethod) { + listener->panelChanged (EvColorToningTwocolor, twocolor->get_active_text ()); + } } -void ColorToning::twoColorChangedByGui() { - twocolorChanged(false); +void ColorToning::twoColorChangedByGui() +{ + twocolorChanged(false); } -void ColorToning::methodChanged () { +void ColorToning::methodChanged () +{ - if (!batchMode) { - if (method->get_active_row_number()==0) { // Lab - colorSep->show(); - colLabel->hide(); - interLabel->hide(); - colorCurveEditorG->show(); - twocolor->show(); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - //neutralCurves->show(); - hlColSat->hide(); - shadowsColSat->hide(); - balance->hide(); -// satLimiterSep->show(); - if(autosat->get_active()) { - saturatedOpacity->set_sensitive(false); - satProtectionThreshold->set_sensitive(false); - satProtectionThreshold->show(); - saturatedOpacity->show(); - } - else { - satProtectionThreshold->show(); - saturatedOpacity->show(); - saturatedOpacity->set_sensitive(true); - satProtectionThreshold->set_sensitive(true); - } - autosat->show(); - p1Frame->show(); + if (!batchMode) { + if (method->get_active_row_number() == 0) { // Lab + colorSep->show(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->show(); + twocolor->show(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + //neutralCurves->show(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); - strength->hide(); - chanMixerBox->hide(); - neutrHBox->hide(); - lumamode->hide(); - //splitSep->hide(); - //satlow->hide(); - //sathigh->hide(); +// satLimiterSep->show(); + if(autosat->get_active()) { + saturatedOpacity->set_sensitive(false); + satProtectionThreshold->set_sensitive(false); + satProtectionThreshold->show(); + saturatedOpacity->show(); + } else { + satProtectionThreshold->show(); + saturatedOpacity->show(); + saturatedOpacity->set_sensitive(true); + satProtectionThreshold->set_sensitive(true); + } - twocolorChanged(true); - } - else if (method->get_active_row_number()==1) { // RGB Sliders - colorSep->hide(); - colLabel->hide(); - interLabel->hide(); - colorCurveEditorG->hide(); - twocolor->hide(); - twocolor->set_active (false); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - //neutralCurves->hide(); - hlColSat->show(); - shadowsColSat->show(); - balance->show(); -// satLimiterSep->show(); - autosat->show(); - p1Frame->show(); - if(autosat->get_active()) { - saturatedOpacity->set_sensitive(false); - satProtectionThreshold->set_sensitive(false); - satProtectionThreshold->show(); - saturatedOpacity->show(); - } - else { - satProtectionThreshold->show(); - saturatedOpacity->show(); - saturatedOpacity->set_sensitive(true); - satProtectionThreshold->set_sensitive(true); - } - - strength->hide(); - chanMixerBox->hide(); - neutrHBox->hide(); - lumamode->hide(); + autosat->show(); + p1Frame->show(); - } - else if (method->get_active_row_number()==2) { // RGB Curves - colorSep->hide(); - colLabel->hide(); - interLabel->hide(); - colorCurveEditorG->show(); - twocolor->hide(); - twocolor->set_active (false); - opacityCurveEditorG->show(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - //neutralCurves->show(); - hlColSat->hide(); - shadowsColSat->hide(); - balance->hide(); -// satLimiterSep->show(); - p1Frame->show(); + strength->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); + //splitSep->hide(); + //satlow->hide(); + //sathigh->hide(); - autosat->show(); - if(autosat->get_active()) { - saturatedOpacity->set_sensitive(false); - satProtectionThreshold->set_sensitive(false); - satProtectionThreshold->show(); - saturatedOpacity->show(); - } - else { - satProtectionThreshold->show(); - saturatedOpacity->show(); - saturatedOpacity->set_sensitive(true); - satProtectionThreshold->set_sensitive(true); - } - strength->hide(); - chanMixerBox->hide(); - neutrHBox->hide(); - lumamode->hide(); - } - else if (method->get_active_row_number()==3) { // Split LR - colorSep->hide(); - colLabel->hide(); - interLabel->hide(); - colorCurveEditorG->hide(); - twocolor->hide(); - twocolor->set_active (false); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - //neutralCurves->hide(); - hlColSat->hide(); - shadowsColSat->hide(); - balance->hide(); - p1Frame->hide(); - -// satLimiterSep->hide(); - autosat->hide(); - satProtectionThreshold->hide(); - saturatedOpacity->hide(); - strength->show(); - chanMixerBox->show(); - neutrHBox->show(); - lumamode->show(); - } - else if (method->get_active_row_number()==4) { // Split Color - colorSep->show(); - colLabel->hide(); - interLabel->hide(); - colorCurveEditorG->hide(); - twocolor->hide(); - opacityCurveEditorG->hide(); - clCurveEditorG->hide(); - cl2CurveEditorG->hide(); - //neutralCurves->hide(); - hlColSat->show(); - shadowsColSat->show(); - balance->show(); -// satLimiterSep->hide(); - p1Frame->hide(); + twocolorChanged(true); + } else if (method->get_active_row_number() == 1) { // RGB Sliders + colorSep->hide(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + twocolor->set_active (false); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + //neutralCurves->hide(); + hlColSat->show(); + shadowsColSat->show(); + balance->show(); +// satLimiterSep->show(); + autosat->show(); + p1Frame->show(); - autosat->hide(); - satProtectionThreshold->hide(); - saturatedOpacity->hide(); - strength->show(); + if(autosat->get_active()) { + saturatedOpacity->set_sensitive(false); + satProtectionThreshold->set_sensitive(false); + satProtectionThreshold->show(); + saturatedOpacity->show(); + } else { + satProtectionThreshold->show(); + saturatedOpacity->show(); + saturatedOpacity->set_sensitive(true); + satProtectionThreshold->set_sensitive(true); + } - chanMixerBox->hide(); - neutrHBox->hide(); - lumamode->show(); - } - } + strength->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); - if (listener && getEnabled()) - listener->panelChanged (EvColorToningMethod, method->get_active_text ()); + } else if (method->get_active_row_number() == 2) { // RGB Curves + colorSep->hide(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->show(); + twocolor->hide(); + twocolor->set_active (false); + opacityCurveEditorG->show(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + //neutralCurves->show(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); +// satLimiterSep->show(); + p1Frame->show(); + + autosat->show(); + + if(autosat->get_active()) { + saturatedOpacity->set_sensitive(false); + satProtectionThreshold->set_sensitive(false); + satProtectionThreshold->show(); + saturatedOpacity->show(); + } else { + satProtectionThreshold->show(); + saturatedOpacity->show(); + saturatedOpacity->set_sensitive(true); + satProtectionThreshold->set_sensitive(true); + } + + strength->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); + } else if (method->get_active_row_number() == 3) { // Split LR + colorSep->hide(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + twocolor->set_active (false); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + //neutralCurves->hide(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); + p1Frame->hide(); + +// satLimiterSep->hide(); + autosat->hide(); + satProtectionThreshold->hide(); + saturatedOpacity->hide(); + strength->show(); + chanMixerBox->show(); + neutrHBox->show(); + lumamode->show(); + } else if (method->get_active_row_number() == 4) { // Split Color + colorSep->show(); + colLabel->hide(); + interLabel->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + //neutralCurves->hide(); + hlColSat->show(); + shadowsColSat->show(); + balance->show(); +// satLimiterSep->hide(); + p1Frame->hide(); + + autosat->hide(); + satProtectionThreshold->hide(); + saturatedOpacity->hide(); + strength->show(); + + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->show(); + } + } + + if (listener && getEnabled()) { + listener->panelChanged (EvColorToningMethod, method->get_active_text ()); + } } -void ColorToning::autoOpenCurve () { - colorShape->openIfNonlinear(); - opacityShape->openIfNonlinear(); - clshape->openIfNonlinear(); - cl2shape->openIfNonlinear(); +void ColorToning::autoOpenCurve () +{ + colorShape->openIfNonlinear(); + opacityShape->openIfNonlinear(); + clshape->openIfNonlinear(); + cl2shape->openIfNonlinear(); } -void ColorToning::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { +void ColorToning::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) +{ - float R, G, B; - if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B); - } - else if (callerId == 2) { // Slider 1 background - if (valY > 0.5) - // the hue range - Color::hsv2rgb01(float(valX), 1.0f, 0.5f, R, G, B); - else { - // the strength applied to the current hue - double strength, hue; - float r_, g_, b_; - hlColSat->getValue(strength, hue); - Color::hsv2rgb01(valY*2.f, 1.f, 1.f, r_, g_, b_); - Color::hsv2rgb01(hue/360.f, 1.f, 1.f, R, G, B); - R = r_+(R-r_)*valX; - G = g_+(G-g_)*valX; - B = b_+(B-b_)*valX; - } - } - else if (callerId == 3) { // Slider 2 background - if (valY > 0.5) - // the hue range - Color::hsv2rgb01(float(valX), 1.0f, 0.5f, R, G, B); - else { - // the strength applied to the current hue - double strength, hue; - float r_, g_, b_; - shadowsColSat->getValue(strength, hue); - Color::hsv2rgb01(valY*2.f, 1.f, 1.f, r_, g_, b_); - Color::hsv2rgb01(hue/360.f, 1.f, 1.f, R, G, B); - R = r_+(R-r_)*valX; - G = g_+(G-g_)*valX; - B = b_+(B-b_)*valX; - } - } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + float R, G, B; + + if (callerId == 1) { // ch - main curve + Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B); + } else if (callerId == 2) { // Slider 1 background + if (valY > 0.5) + // the hue range + { + Color::hsv2rgb01(float(valX), 1.0f, 0.5f, R, G, B); + } else { + // the strength applied to the current hue + double strength, hue; + float r_, g_, b_; + hlColSat->getValue(strength, hue); + Color::hsv2rgb01(valY * 2.f, 1.f, 1.f, r_, g_, b_); + Color::hsv2rgb01(hue / 360.f, 1.f, 1.f, R, G, B); + R = r_ + (R - r_) * valX; + G = g_ + (G - g_) * valX; + B = b_ + (B - b_) * valX; + } + } else if (callerId == 3) { // Slider 2 background + if (valY > 0.5) + // the hue range + { + Color::hsv2rgb01(float(valX), 1.0f, 0.5f, R, G, B); + } else { + // the strength applied to the current hue + double strength, hue; + float r_, g_, b_; + shadowsColSat->getValue(strength, hue); + Color::hsv2rgb01(valY * 2.f, 1.f, 1.f, r_, g_, b_); + Color::hsv2rgb01(hue / 360.f, 1.f, 1.f, R, G, B); + R = r_ + (R - r_) * valX; + G = g_ + (G - g_) * valX; + B = b_ + (B - b_) * valX; + } + } + + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); } -void ColorToning::curveChanged (CurveEditor* ce) { +void ColorToning::curveChanged (CurveEditor* ce) +{ - if (listener && getEnabled()) { - if (ce == colorShape) - listener->panelChanged (EvColorToningColor, M("HISTORY_CUSTOMCURVE")); - else if (ce == opacityShape) - listener->panelChanged (EvColorToningOpacity, M("HISTORY_CUSTOMCURVE")); - else if (ce == clshape) - listener->panelChanged (EvColorToningCLCurve, M("HISTORY_CUSTOMCURVE")); - else if (ce == cl2shape) - listener->panelChanged (EvColorToningLLCurve, M("HISTORY_CUSTOMCURVE")); - } + if (listener && getEnabled()) { + if (ce == colorShape) { + listener->panelChanged (EvColorToningColor, M("HISTORY_CUSTOMCURVE")); + } else if (ce == opacityShape) { + listener->panelChanged (EvColorToningOpacity, M("HISTORY_CUSTOMCURVE")); + } else if (ce == clshape) { + listener->panelChanged (EvColorToningCLCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == cl2shape) { + listener->panelChanged (EvColorToningLLCurve, M("HISTORY_CUSTOMCURVE")); + } + } } -void ColorToning::enabledChanged () { +void ColorToning::enabledChanged () +{ - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvColorToningEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvColorToningEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvColorToningEnabled, M("GENERAL_DISABLED")); - } + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvColorToningEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvColorToningEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvColorToningEnabled, M("GENERAL_DISABLED")); + } + } } -void ColorToning::autosatChanged () { +void ColorToning::autosatChanged () +{ - if (batchMode) { - if (autosat->get_inconsistent()) { - autosat->set_inconsistent (false); - autosatConn.block (true); - autosat->set_active (false); - autosatConn.block (false); - } - else if (lastautosat) - autosat->set_inconsistent (true); + if (batchMode) { + if (autosat->get_inconsistent()) { + autosat->set_inconsistent (false); + autosatConn.block (true); + autosat->set_active (false); + autosatConn.block (false); + } else if (lastautosat) { + autosat->set_inconsistent (true); + } - lastautosat = autosat->get_active (); - } - if (listener) { - if (autosat->get_active()) { - if (getEnabled()) - listener->panelChanged (EvColorToningautosat, M("GENERAL_ENABLED")); - saturatedOpacity->set_sensitive(false); - satProtectionThreshold->set_sensitive(false); - } - else { - if (getEnabled()) - listener->panelChanged (EvColorToningautosat, M("GENERAL_DISABLED")); - saturatedOpacity->set_sensitive(true); - satProtectionThreshold->set_sensitive(true); - } + lastautosat = autosat->get_active (); + } - } + if (listener) { + if (autosat->get_active()) { + if (getEnabled()) { + listener->panelChanged (EvColorToningautosat, M("GENERAL_ENABLED")); + } + + saturatedOpacity->set_sensitive(false); + satProtectionThreshold->set_sensitive(false); + } else { + if (getEnabled()) { + listener->panelChanged (EvColorToningautosat, M("GENERAL_DISABLED")); + } + + saturatedOpacity->set_sensitive(true); + satProtectionThreshold->set_sensitive(true); + } + + } } -void ColorToning::trimValues (rtengine::procparams::ProcParams* pp) { +void ColorToning::trimValues (rtengine::procparams::ProcParams* pp) +{ - redlow->trimValue(pp->colorToning.redlow); - greenlow->trimValue(pp->colorToning.greenlow); - bluelow->trimValue(pp->colorToning.bluelow); - balance->trimValue(pp->colorToning.balance); - redmed->trimValue(pp->colorToning.redmed); - greenmed->trimValue(pp->colorToning.greenmed); - bluemed->trimValue(pp->colorToning.bluemed); - redhigh->trimValue(pp->colorToning.redhigh); - greenhigh->trimValue(pp->colorToning.greenhigh); - bluehigh->trimValue(pp->colorToning.bluehigh); + redlow->trimValue(pp->colorToning.redlow); + greenlow->trimValue(pp->colorToning.greenlow); + bluelow->trimValue(pp->colorToning.bluelow); + balance->trimValue(pp->colorToning.balance); + redmed->trimValue(pp->colorToning.redmed); + greenmed->trimValue(pp->colorToning.greenmed); + bluemed->trimValue(pp->colorToning.bluemed); + redhigh->trimValue(pp->colorToning.redhigh); + greenhigh->trimValue(pp->colorToning.greenhigh); + bluehigh->trimValue(pp->colorToning.bluehigh); } void ColorToning::setBatchMode (bool batchMode) { - ToolPanel::setBatchMode (batchMode); - method->append_text (M("GENERAL_UNCHANGED")); - twocolor->append_text (M("GENERAL_UNCHANGED")); - hlColSat->showEditedCB (); - shadowsColSat->showEditedCB (); - redlow->showEditedCB (); - greenlow->showEditedCB (); - bluelow->showEditedCB (); - balance->showEditedCB (); - redmed->showEditedCB (); - greenmed->showEditedCB (); - bluemed->showEditedCB (); - redhigh->showEditedCB (); - greenhigh->showEditedCB (); - bluehigh->showEditedCB (); + ToolPanel::setBatchMode (batchMode); + method->append_text (M("GENERAL_UNCHANGED")); + twocolor->append_text (M("GENERAL_UNCHANGED")); + hlColSat->showEditedCB (); + shadowsColSat->showEditedCB (); + redlow->showEditedCB (); + greenlow->showEditedCB (); + bluelow->showEditedCB (); + balance->showEditedCB (); + redmed->showEditedCB (); + greenmed->showEditedCB (); + bluemed->showEditedCB (); + redhigh->showEditedCB (); + greenhigh->showEditedCB (); + bluehigh->showEditedCB (); - colorCurveEditorG->setBatchMode (batchMode); - opacityCurveEditorG->setBatchMode (batchMode); - clCurveEditorG->setBatchMode (batchMode); - cl2CurveEditorG->setBatchMode (batchMode); + colorCurveEditorG->setBatchMode (batchMode); + opacityCurveEditorG->setBatchMode (batchMode); + clCurveEditorG->setBatchMode (batchMode); + cl2CurveEditorG->setBatchMode (batchMode); } diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index 7f4a650cf..c37d75f22 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -13,10 +13,11 @@ #include "thresholdadjuster.h" #include "colorprovider.h" -class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rtengine::AutoColorTonListener,public CurveListener, public ColorProvider, - public ThresholdAdjusterListener, public AdjusterListener { +class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rtengine::AutoColorTonListener, public CurveListener, public ColorProvider, + public ThresholdAdjusterListener, public AdjusterListener +{ - protected: +protected: //Gtk::HSeparator* splitSep; Gtk::HSeparator* satLimiterSep; Gtk::HSeparator* colorSep; @@ -29,7 +30,7 @@ class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rte DiagonalCurveEditor* clshape; DiagonalCurveEditor* cl2shape; Gtk::HBox* ctbox; - Gtk::Frame *p1Frame; + Gtk::Frame *p1Frame; Gtk::VBox* chanMixerBox; MyComboBoxText* method; @@ -76,19 +77,19 @@ class ColorToning : public ToolParamBlock, public FoldableToolPanel, public rte bool lastLumamode; sigc::connection lumamodeConn; - public: +public: ColorToning (); ~ColorToning(); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void trimValues (rtengine::procparams::ProcParams* pp); void adjusterChanged (Adjuster* a, double newval); void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); void neutral_pressed (); - //void neutralCurves_pressed (); + //void neutralCurves_pressed (); void autoColorTonChanged (int bwct, int satthres, int satprot); bool CTComp_ (); diff --git a/rtgui/coord.h b/rtgui/coord.h index 8b40fa689..cf0d9be29 100644 --- a/rtgui/coord.h +++ b/rtgui/coord.h @@ -22,141 +22,163 @@ class PolarCoord; // Do not confuse with rtengine::Coord2D, Coord is for the GUI -class Coord { +class Coord +{ public: - int x; - int y; + int x; + int y; - Coord() : x(-1), y(-1) {} - Coord(int x, int y) : x(x), y(y) {} + Coord() : x(-1), y(-1) {} + Coord(int x, int y) : x(x), y(y) {} - void set (int x, int y) { - this->x = x; - this->y = y; - } + void set (int x, int y) + { + this->x = x; + this->y = y; + } - void setFromPolar(PolarCoord polar); + void setFromPolar(PolarCoord polar); - /// @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; - } + /// @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; + } - 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; - } + 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 { +class PolarCoord +{ public: - double radius; - double angle; // degree + double radius; + double angle; // degree - PolarCoord() : radius(1.), angle(0.) {} - PolarCoord(double radius, double angle) : radius(radius), angle(angle) {} + PolarCoord() : radius(1.), angle(0.) {} + PolarCoord(double radius, double angle) : radius(radius), angle(angle) {} - void set (double radius, double angle) { - this->radius = radius; - this->angle = angle; - } + 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 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.; - } - } + void setFromCartesian(Coord delta) + { + if (!delta.x && !delta.y) { + // null vector, we set to a default value + radius = 1.; + angle = 0.; + return; + } - 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+(PolarCoord & rhs) { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord += rhsCoord; - PolarCoord result; - result.setFromCartesian(thisCoord); - return result; - } - PolarCoord operator-(PolarCoord & rhs) { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord -= rhsCoord; - PolarCoord result; - result.setFromCartesian(thisCoord); - return result; - } - Coord operator*(double scale) { - Coord result(radius*scale, angle); - return result; - } + 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.; + } + } + } + + 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+(PolarCoord & rhs) + { + Coord thisCoord, rhsCoord; + thisCoord.setFromPolar(*this); + rhsCoord.setFromPolar(rhs); + thisCoord += rhsCoord; + PolarCoord result; + result.setFromCartesian(thisCoord); + return result; + } + PolarCoord operator-(PolarCoord & rhs) + { + Coord thisCoord, rhsCoord; + thisCoord.setFromPolar(*this); + rhsCoord.setFromPolar(rhs); + thisCoord -= rhsCoord; + PolarCoord result; + result.setFromCartesian(thisCoord); + return result; + } + Coord operator*(double scale) + { + Coord result(radius * scale, angle); + return result; + } }; diff --git a/rtgui/coordinateadjuster.cc b/rtgui/coordinateadjuster.cc index 91303ec46..76ad1d50c 100644 --- a/rtgui/coordinateadjuster.cc +++ b/rtgui/coordinateadjuster.cc @@ -23,176 +23,196 @@ #include "curveeditorgroup.h" Axis::Axis() - : label(""), decimal(5), increment(0.001), pageIncrement(0.01), rangeLowerBound(0.), rangeUpperBound(1.) + : label(""), decimal(5), increment(0.001), pageIncrement(0.01), rangeLowerBound(0.), rangeUpperBound(1.) {} -Axis::Axis(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin=0.0, double valMax=1.0) - : label(label), decimal(decimal), increment(increment), pageIncrement(pageIncrement), rangeLowerBound(valMin), rangeUpperBound(valMax) +Axis::Axis(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin = 0.0, double valMax = 1.0) + : label(label), decimal(decimal), increment(increment), pageIncrement(pageIncrement), rangeLowerBound(valMin), rangeUpperBound(valMax) {} -void Axis::setValues(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin, double valMax) { - this->label = label; - this->decimal = decimal; - this->increment = increment; - this->pageIncrement = pageIncrement; - this->rangeLowerBound = valMin; - this->rangeUpperBound = valMax; +void Axis::setValues(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin, double valMax) +{ + this->label = label; + this->decimal = decimal; + this->increment = increment; + this->pageIncrement = pageIncrement; + this->rangeLowerBound = valMin; + this->rangeUpperBound = valMax; } -CoordinateAdjuster::AxisAdjuster::AxisAdjuster(CoordinateAdjuster *parent, const Axis *axis, char index) : idx(index), parent(parent) { - label = Gtk::manage( new Gtk::Label(axis->label) ); - spinButton = Gtk::manage( new Gtk::SpinButton() ); +CoordinateAdjuster::AxisAdjuster::AxisAdjuster(CoordinateAdjuster *parent, const Axis *axis, char index) : idx(index), parent(parent) +{ + label = Gtk::manage( new Gtk::Label(axis->label) ); + spinButton = Gtk::manage( new Gtk::SpinButton() ); - label = Gtk::manage (new Gtk::Label(axis->label)); - //label->set_alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); + label = Gtk::manage (new Gtk::Label(axis->label)); + //label->set_alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); - spinButton = Gtk::manage (new Gtk::SpinButton()); - spinButton->set_name("AxisAdjuster"); - spinButton->set_digits(axis->decimal); - spinButton->set_increments(axis->increment, axis->pageIncrement); - spinButton->set_range(axis->rangeLowerBound, axis->rangeUpperBound); - spinButton->set_sensitive(false); - spinButtonConn = spinButton->signal_value_changed().connect( sigc::mem_fun(*this, &CoordinateAdjuster::AxisAdjuster::valueChanged) ); - //spinButton->signal_key_press_event().connect( sigc::mem_fun(*this, &CoordinateAdjuster::AxisAdjuster::keyPressed) ); + spinButton = Gtk::manage (new Gtk::SpinButton()); + spinButton->set_name("AxisAdjuster"); + spinButton->set_digits(axis->decimal); + spinButton->set_increments(axis->increment, axis->pageIncrement); + spinButton->set_range(axis->rangeLowerBound, axis->rangeUpperBound); + spinButton->set_sensitive(false); + spinButtonConn = spinButton->signal_value_changed().connect( sigc::mem_fun(*this, &CoordinateAdjuster::AxisAdjuster::valueChanged) ); + //spinButton->signal_key_press_event().connect( sigc::mem_fun(*this, &CoordinateAdjuster::AxisAdjuster::keyPressed) ); } -void CoordinateAdjuster::AxisAdjuster::updateGUI(const Axis &axis) { - label->set_text(axis.label); - spinButton->set_digits(axis.decimal); - spinButton->set_increments(axis.increment, axis.pageIncrement); - spinButton->set_range(axis.rangeLowerBound, axis.rangeUpperBound); - spinButton->set_sensitive(false); - rangeLowerBound = axis.rangeLowerBound; - rangeUpperBound = axis.rangeUpperBound; +void CoordinateAdjuster::AxisAdjuster::updateGUI(const Axis &axis) +{ + label->set_text(axis.label); + spinButton->set_digits(axis.decimal); + spinButton->set_increments(axis.increment, axis.pageIncrement); + spinButton->set_range(axis.rangeLowerBound, axis.rangeUpperBound); + spinButton->set_sensitive(false); + rangeLowerBound = axis.rangeLowerBound; + rangeUpperBound = axis.rangeUpperBound; } -void CoordinateAdjuster::AxisAdjuster::setValue(double newValue) { - float range = rangeUpperBound-rangeLowerBound; - spinButtonConn.block(true); - spinButton->set_value(newValue*range+rangeLowerBound); - spinButtonConn.block(false); +void CoordinateAdjuster::AxisAdjuster::setValue(double newValue) +{ + float range = rangeUpperBound - rangeLowerBound; + spinButtonConn.block(true); + spinButton->set_value(newValue * range + rangeLowerBound); + spinButtonConn.block(false); } -void CoordinateAdjuster::AxisAdjuster::valueChanged() { - float range = rangeUpperBound-rangeLowerBound; - parent->updatePos(idx, (spinButton->get_value()-rangeLowerBound)/range); +void CoordinateAdjuster::AxisAdjuster::valueChanged() +{ + float range = rangeUpperBound - rangeLowerBound; + parent->updatePos(idx, (spinButton->get_value() - rangeLowerBound) / range); } CoordinateAdjuster::CoordinateAdjuster(CoordinateProvider *provider, CurveEditorSubGroup *parent, const std::vector &axis) - : status(CA_STATUS_IDLE), parent(parent), coordinateProvider(provider) + : status(CA_STATUS_IDLE), parent(parent), coordinateProvider(provider) { - provider->setListener(this); - createWidgets(axis); + provider->setListener(this); + createWidgets(axis); } CoordinateAdjuster::CoordinateAdjuster(CoordinateProvider *provider, CurveEditorSubGroup *parent) - : status(CA_STATUS_IDLE), parent(parent), coordinateProvider(provider) + : status(CA_STATUS_IDLE), parent(parent), coordinateProvider(provider) { - std::vector defaultAxis; - Axis X(M("CURVEEDITOR_AXIS_IN"), 3, 0.1, 1., 0., 100.); - Axis Y(M("CURVEEDITOR_AXIS_OUT"), 3, 0.1, 1., 0., 100.); - defaultAxis.push_back(X); - defaultAxis.push_back(Y); + std::vector defaultAxis; + Axis X(M("CURVEEDITOR_AXIS_IN"), 3, 0.1, 1., 0., 100.); + Axis Y(M("CURVEEDITOR_AXIS_OUT"), 3, 0.1, 1., 0., 100.); + defaultAxis.push_back(X); + defaultAxis.push_back(Y); - provider->setListener(this); - createWidgets(defaultAxis); + provider->setListener(this); + createWidgets(defaultAxis); } -void CoordinateAdjuster::createWidgets(const std::vector &axis) { - unsigned int count = axis.size(); - if (!count) { - printf("CoordinateAdjuster - Error: the Axis list is empty!\n"); - return; - } - assert (count <= 4); +void CoordinateAdjuster::createWidgets(const std::vector &axis) +{ + unsigned int count = axis.size(); - axisAdjusters.resize(axis.size()); + if (!count) { + printf("CoordinateAdjuster - Error: the Axis list is empty!\n"); + return; + } - set_spacing(3); + assert (count <= 4); - AxisAdjuster *currAdjuster = NULL; + axisAdjusters.resize(axis.size()); - for (unsigned int i=0; irangeLowerBound = currAxis->rangeLowerBound; - currAdjuster->rangeUpperBound = currAxis->rangeUpperBound; + set_spacing(3); - pack_start(*(currAdjuster->label), Gtk::PACK_SHRINK, 0); - pack_start(*(currAdjuster->spinButton), Gtk::PACK_SHRINK, 0); - } + AxisAdjuster *currAdjuster = NULL; + + for (unsigned int i = 0; i < count; ++i) { + const Axis *currAxis = &(axis.at(i)); + axisAdjusters.at(i) = new AxisAdjuster(this, currAxis, i); + currAdjuster = axisAdjusters.at(i); + currAdjuster->rangeLowerBound = currAxis->rangeLowerBound; + currAdjuster->rangeUpperBound = currAxis->rangeUpperBound; + + pack_start(*(currAdjuster->label), Gtk::PACK_SHRINK, 0); + pack_start(*(currAdjuster->spinButton), Gtk::PACK_SHRINK, 0); + } } -void CoordinateAdjuster::updatePos(char index, double value) { - coordinateProvider->setPos(value, index); +void CoordinateAdjuster::updatePos(char index, double value) +{ + coordinateProvider->setPos(value, index); } -void CoordinateAdjuster::setAxis(const std::vector &axis) { - assert (axis.size() == axisAdjusters.size()); - for (size_t i = 0; iupdateGUI(axis.at(i)); - } +void CoordinateAdjuster::setAxis(const std::vector &axis) +{ + assert (axis.size() == axisAdjusters.size()); + + for (size_t i = 0; i < axisAdjusters.size(); ++i) { + axisAdjusters.at(i)->updateGUI(axis.at(i)); + } } -void CoordinateAdjuster::setPos(std::vector &pos) { - if (is_visible()) { - for (size_t i=0; isetValue(pos.at(i)); - } - } +void CoordinateAdjuster::setPos(std::vector &pos) +{ + if (is_visible()) { + for (size_t i = 0; i < pos.size(); ++i) { + axisAdjusters.at(i)->setValue(pos.at(i)); + } + } } -void CoordinateAdjuster::startNumericalAdjustment(const std::vector &newBoundaries) { - for (size_t i=0; ispinButton; - currSpinButton->set_sensitive(true); - float range = axisAdjusters.at(i)->rangeUpperBound-axisAdjusters.at(i)->rangeLowerBound; - currSpinButton->set_range(newBoundaries.at(i).minVal*range+axisAdjusters.at(i)->rangeLowerBound, newBoundaries.at(i).maxVal*range+axisAdjusters.at(i)->rangeUpperBound); - } - axisAdjusters.at(0)->spinButton->grab_focus(); - status = CA_STATUS_EDITING; +void CoordinateAdjuster::startNumericalAdjustment(const std::vector &newBoundaries) +{ + for (size_t i = 0; i < axisAdjusters.size(); ++i) { + Gtk::SpinButton *currSpinButton = axisAdjusters.at(i)->spinButton; + currSpinButton->set_sensitive(true); + float range = axisAdjusters.at(i)->rangeUpperBound - axisAdjusters.at(i)->rangeLowerBound; + currSpinButton->set_range(newBoundaries.at(i).minVal * range + axisAdjusters.at(i)->rangeLowerBound, newBoundaries.at(i).maxVal * range + axisAdjusters.at(i)->rangeUpperBound); + } + + axisAdjusters.at(0)->spinButton->grab_focus(); + status = CA_STATUS_EDITING; } -void CoordinateAdjuster::switchAdjustedPoint(std::vector &pos, const std::vector &newBoundaries) { - if (status != CA_STATUS_EDITING) - return; +void CoordinateAdjuster::switchAdjustedPoint(std::vector &pos, const std::vector &newBoundaries) +{ + if (status != CA_STATUS_EDITING) { + return; + } - for (size_t i=0; ispinButtonConn.block(true); + // disable events + currAxis->spinButtonConn.block(true); - // To avoid trimmed values, we have to... + // To avoid trimmed values, we have to... - // ...enlarge range to the maximum - currAxis->spinButton->set_range(axisAdjusters.at(i)->rangeLowerBound, axisAdjusters.at(i)->rangeUpperBound); + // ...enlarge range to the maximum + currAxis->spinButton->set_range(axisAdjusters.at(i)->rangeLowerBound, axisAdjusters.at(i)->rangeUpperBound); - // ...set the new value - currAxis->setValue(pos.at(i)); + // ...set the new value + currAxis->setValue(pos.at(i)); - // ...narrow the range to the new interval - float range = axisAdjusters.at(i)->rangeUpperBound-axisAdjusters.at(i)->rangeLowerBound; - currAxis->spinButton->set_range(newBoundaries.at(i).minVal*range+axisAdjusters.at(i)->rangeLowerBound, newBoundaries.at(i).maxVal*range+axisAdjusters.at(i)->rangeUpperBound); + // ...narrow the range to the new interval + float range = axisAdjusters.at(i)->rangeUpperBound - axisAdjusters.at(i)->rangeLowerBound; + currAxis->spinButton->set_range(newBoundaries.at(i).minVal * range + axisAdjusters.at(i)->rangeLowerBound, newBoundaries.at(i).maxVal * range + axisAdjusters.at(i)->rangeUpperBound); - // enable events - currAxis->spinButtonConn.block(false); - } - axisAdjusters.at(0)->spinButton->grab_focus(); - status = CA_STATUS_EDITING; + // enable events + currAxis->spinButtonConn.block(false); + } + + axisAdjusters.at(0)->spinButton->grab_focus(); + status = CA_STATUS_EDITING; } -void CoordinateAdjuster::showMe(CoordinateProvider *provider) { - parent->showCoordinateAdjuster(provider); +void CoordinateAdjuster::showMe(CoordinateProvider *provider) +{ + parent->showCoordinateAdjuster(provider); } -void CoordinateAdjuster::stopNumericalAdjustment() { - for (size_t i=0; ispinButtonConn.block(true); - axisAdjusters.at(i)->spinButton->set_sensitive(false); - axisAdjusters.at(i)->spinButton->set_range(axisAdjusters.at(i)->rangeLowerBound, axisAdjusters.at(i)->rangeUpperBound); - axisAdjusters.at(i)->spinButtonConn.block(false); - } - status = CA_STATUS_IDLE; +void CoordinateAdjuster::stopNumericalAdjustment() +{ + for (size_t i = 0; i < axisAdjusters.size(); ++i) { + axisAdjusters.at(i)->spinButtonConn.block(true); + axisAdjusters.at(i)->spinButton->set_sensitive(false); + axisAdjusters.at(i)->spinButton->set_range(axisAdjusters.at(i)->rangeLowerBound, axisAdjusters.at(i)->rangeUpperBound); + axisAdjusters.at(i)->spinButtonConn.block(false); + } + + status = CA_STATUS_IDLE; } diff --git a/rtgui/coordinateadjuster.h b/rtgui/coordinateadjuster.h index de85b6623..cb1eb91ed 100644 --- a/rtgui/coordinateadjuster.h +++ b/rtgui/coordinateadjuster.h @@ -23,39 +23,44 @@ class CurveEditorSubGroup; -class Axis { +class Axis +{ public: - Glib::ustring label; - unsigned int decimal; - double increment; - double pageIncrement; - double rangeLowerBound; - double rangeUpperBound; + Glib::ustring label; + unsigned int decimal; + double increment; + double pageIncrement; + double rangeLowerBound; + double rangeUpperBound; - Axis(); - Axis(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin, double valMax); - void setValues(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin, double valMax); + Axis(); + Axis(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin, double valMax); + void setValues(Glib::ustring label, unsigned int decimal, double increment, double pageIncrement, double valMin, double valMax); }; class CoordinateAdjuster; /** * @brief Object that will emit NewCoordinates events */ -class CoordinateProvider { +class CoordinateProvider +{ protected: - CoordinateAdjuster *coordinateAdjuster; + CoordinateAdjuster *coordinateAdjuster; public: - CoordinateProvider() : coordinateAdjuster(NULL) {} - virtual ~CoordinateProvider() {} - void setListener(CoordinateAdjuster *adjuster) { coordinateAdjuster = adjuster; } + CoordinateProvider() : coordinateAdjuster(NULL) {} + virtual ~CoordinateProvider() {} + void setListener(CoordinateAdjuster *adjuster) + { + coordinateAdjuster = adjuster; + } - /** @brief Update the position of the edited point ; will trigger events - * - * @param pos New position - * @param chanIdx Chanel index as given in the std::vector upon instantiation - */ - virtual void setPos(double pos, int chanIdx)=0; - virtual void stopNumericalAdjustment()=0; + /** @brief Update the position of the edited point ; will trigger events + * + * @param pos New position + * @param chanIdx Chanel index as given in the std::vector upon instantiation + */ + virtual void setPos(double pos, int chanIdx) = 0; + virtual void stopNumericalAdjustment() = 0; }; /** @@ -65,91 +70,94 @@ public: * * The position of the Axis in the vector will be used in the communication between the Adjuster and the Provider to identify the Axis */ -class CoordinateAdjuster : public Gtk::HBox { +class CoordinateAdjuster : public Gtk::HBox +{ public: - //-------------------------------- AxisAdjuster ------------------- - class AxisAdjuster { - private: - char idx; - public: - CoordinateAdjuster *parent; - Gtk::Label *label; - Gtk::SpinButton *spinButton; - sigc::connection spinButtonConn; - float rangeLowerBound; - float rangeUpperBound; + //-------------------------------- AxisAdjuster ------------------- + class AxisAdjuster + { + private: + char idx; + public: + CoordinateAdjuster *parent; + Gtk::Label *label; + Gtk::SpinButton *spinButton; + sigc::connection spinButtonConn; + float rangeLowerBound; + float rangeUpperBound; - AxisAdjuster(CoordinateAdjuster *parent, const Axis *axis, char index); + AxisAdjuster(CoordinateAdjuster *parent, const Axis *axis, char index); - // used to update the AxisAdjuster's parameters - void updateGUI(const Axis &axis); - // useed to update the displayed value - void setValue(double newValue); - //bool keyPressed(GdkEventKey* event); - void valueChanged(); - }; - //---------------------------------------------------------------- + // used to update the AxisAdjuster's parameters + void updateGUI(const Axis &axis); + // useed to update the displayed value + void setValue(double newValue); + //bool keyPressed(GdkEventKey* event); + void valueChanged(); + }; + //---------------------------------------------------------------- - //-------------------------------- Boundaries ------------------- - class Boundaries { - public: - double minVal; - double maxVal; - }; - //--------------------------------------------------------------- + //-------------------------------- Boundaries ------------------- + class Boundaries + { + public: + double minVal; + double maxVal; + }; + //--------------------------------------------------------------- private: - typedef enum { - CA_STATUS_IDLE, - CA_STATUS_EDITING, - CA_STATUS_END_EDITING - } Status; + typedef enum { + CA_STATUS_IDLE, + CA_STATUS_EDITING, + CA_STATUS_END_EDITING + } Status; - std::vector axisAdjusters; - Status status; - CurveEditorSubGroup *parent; + std::vector axisAdjusters; + Status status; + CurveEditorSubGroup *parent; - void createWidgets(const std::vector &axis); + void createWidgets(const std::vector &axis); protected: - friend class AxisAdjuster; + friend class AxisAdjuster; - CoordinateProvider *coordinateProvider; + CoordinateProvider *coordinateProvider; - void updatePos(char index, double value); + void updatePos(char index, double value); public: - /// Basic X/Y adjuster, in the [0-1] range - CoordinateAdjuster(CoordinateProvider *provider, CurveEditorSubGroup *parent); - /// For more complex adjuster - CoordinateAdjuster(CoordinateProvider *provider, CurveEditorSubGroup *parent, const std::vector &axis); + /// Basic X/Y adjuster, in the [0-1] range + CoordinateAdjuster(CoordinateProvider *provider, CurveEditorSubGroup *parent); + /// For more complex adjuster + CoordinateAdjuster(CoordinateProvider *provider, CurveEditorSubGroup *parent, const std::vector &axis); - virtual ~CoordinateAdjuster() {} + virtual ~CoordinateAdjuster() {} - // Update the Axis list, e.g. on Curve change, but MUST have the same axis count - void setAxis(const std::vector &axis); + // Update the Axis list, e.g. on Curve change, but MUST have the same axis count + void setAxis(const std::vector &axis); - /** @brief Update the numbers in the spin buttons ; doesn't trigger any event - * - * @param pos Vector that gives the values of each channels - */ - void setPos(std::vector &pos); + /** @brief Update the numbers in the spin buttons ; doesn't trigger any event + * + * @param pos Vector that gives the values of each channels + */ + void setPos(std::vector &pos); - /// Start the adjustment session (enable the widget) - void startNumericalAdjustment(const std::vector &newBoundaries); + /// Start the adjustment session (enable the widget) + void startNumericalAdjustment(const std::vector &newBoundaries); - /// Edit another point - void switchAdjustedPoint(std::vector &pos, const std::vector &newBoundaries); + /// Edit another point + void switchAdjustedPoint(std::vector &pos, const std::vector &newBoundaries); - /// Trigger the event to show the CoordinateAdjuster - void showMe(CoordinateProvider *provider); + /// Trigger the event to show the CoordinateAdjuster + void showMe(CoordinateProvider *provider); - /// Stop the adjustment session (disable the widget, i.e. you won't be able to edit the values) - void stopNumericalAdjustment(); + /// Stop the adjustment session (disable the widget, i.e. you won't be able to edit the values) + void stopNumericalAdjustment(); }; diff --git a/rtgui/createicon.cc b/rtgui/createicon.cc index 485b33027..32884c182 100644 --- a/rtgui/createicon.cc +++ b/rtgui/createicon.cc @@ -7,7 +7,7 @@ * 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 @@ -18,183 +18,206 @@ */ #include -void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { - png_size_t check; +void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - check = (png_size_t)fread(data, (png_size_t)1, length, (FILE *)png_ptr->io_ptr); + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = (png_size_t)fread(data, (png_size_t)1, length, (FILE *)png_ptr->io_ptr); - if (check != length) - { - png_error(png_ptr, "Read Error"); - } -} - -void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { - png_uint_32 check; - - check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr)); - if (check != length) - { - png_error(png_ptr, "Write Error"); - } -} - -void png_flush(png_structp png_ptr) { - FILE *io_ptr; - io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); - if (io_ptr != NULL) - fflush(io_ptr); -} - - -unsigned char* loadPNG (char* fname, int& w, int& h) { - - FILE *file = fopen (fname,"rb"); - - unsigned char header[8]; - fread (header, 1, 8, file); - - png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); - png_infop info = png_create_info_struct (png); - png_infop end_info = png_create_info_struct (png); - if (setjmp (png_jmpbuf(png))) { - png_destroy_read_struct (&png, &info, &end_info); - fclose (file); - return NULL; + if (check != length) { + png_error(png_ptr, "Read Error"); } - //set up png read +} + +void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr)); + + if (check != length) { + png_error(png_ptr, "Write Error"); + } +} + +void png_flush(png_structp png_ptr) +{ + FILE *io_ptr; + io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); + + if (io_ptr != NULL) { + fflush(io_ptr); + } +} + + +unsigned char* loadPNG (char* fname, int& w, int& h) +{ + + FILE *file = fopen (fname, "rb"); + + unsigned char header[8]; + fread (header, 1, 8, file); + + png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); + png_infop info = png_create_info_struct (png); + png_infop end_info = png_create_info_struct (png); + + if (setjmp (png_jmpbuf(png))) { + png_destroy_read_struct (&png, &info, &end_info); + fclose (file); + return NULL; + } + + //set up png read png_set_read_fn (png, file, png_read_data); - png_set_sig_bytes (png,8); + png_set_sig_bytes (png, 8); - png_read_info(png,info); + png_read_info(png, info); - unsigned long width,height; - int bit_depth,color_type,interlace_type,compression_type,filter_method; - png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type, - &compression_type, &filter_method); + unsigned long width, height; + int bit_depth, color_type, interlace_type, compression_type, filter_method; + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); - //converting to 32bpp format - if (color_type==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); - - if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png); - - if (png_get_valid(png,info,PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); - - if (interlace_type!=PNG_INTERLACE_NONE) { - png_destroy_read_struct (&png, &info, &end_info); - fclose (file); - return NULL; + //converting to 32bpp format + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png); } - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png); + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png); + } - //setting gamma - double gamma; - if (png_get_gAMA(png,info,&gamma)) - png_set_gamma(png, 2.0, gamma); - else - png_set_gamma(png,2.0, 0.45455); + if (png_get_valid(png, info, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png); + } + + if (interlace_type != PNG_INTERLACE_NONE) { + png_destroy_read_struct (&png, &info, &end_info); + fclose (file); + return NULL; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) { + png_set_strip_alpha(png); + } + + //setting gamma + double gamma; + + if (png_get_gAMA(png, info, &gamma)) { + png_set_gamma(png, 2.0, gamma); + } else { + png_set_gamma(png, 2.0, 0.45455); + } int bps = 8; - //updating png info struct - png_read_update_info(png,info); - png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type, - &compression_type, &filter_method); + //updating png info struct + png_read_update_info(png, info); + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png); - - png_read_update_info(png,info); - png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type, - &compression_type, &filter_method); - - - unsigned char* data = new unsigned char[width*height*3]; - int rowlen = width*3; - unsigned char *row = new unsigned char [rowlen]; - - for (unsigned int i=0;ipack_start (*Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("TP_CROP_X") +": "))); - x = Gtk::manage (new MySpinButton ()); - x->set_size_request (60, -1); - hb1->pack_start (*x); + hb1->pack_start (*Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("TP_CROP_X") + ": "))); + x = Gtk::manage (new MySpinButton ()); + x->set_size_request (60, -1); + hb1->pack_start (*x); - hb1->pack_start (*Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("TP_CROP_Y") + ": "))); - y = Gtk::manage (new MySpinButton ()); - y->set_size_request (60, -1); - hb1->pack_start (*y); + hb1->pack_start (*Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("TP_CROP_Y") + ": "))); + y = Gtk::manage (new MySpinButton ()); + y->set_size_request (60, -1); + hb1->pack_start (*y); - pack_start (*hb1, Gtk::PACK_SHRINK, 2); + pack_start (*hb1, Gtk::PACK_SHRINK, 2); - Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); + Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); - hb2->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_W") + ": "))); - w = Gtk::manage (new MySpinButton ()); - w->set_size_request (60, -1); - hb2->pack_start (*w); + hb2->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_W") + ": "))); + w = Gtk::manage (new MySpinButton ()); + w->set_size_request (60, -1); + hb2->pack_start (*w); - hb2->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_H") + ": "))); - h = Gtk::manage (new MySpinButton ()); - h->set_size_request (60, -1); - hb2->pack_start (*h); + hb2->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_H") + ": "))); + h = Gtk::manage (new MySpinButton ()); + h->set_size_request (60, -1); + hb2->pack_start (*h); - pack_start (*hb2, Gtk::PACK_SHRINK, 4); + pack_start (*hb2, Gtk::PACK_SHRINK, 4); - selectCrop = Gtk::manage (new Gtk::Button (M("TP_CROP_SELECTCROP"))); - selectCrop->set_image (*Gtk::manage (new RTImage ("crop.png"))); + selectCrop = Gtk::manage (new Gtk::Button (M("TP_CROP_SELECTCROP"))); + selectCrop->set_image (*Gtk::manage (new RTImage ("crop.png"))); - pack_start (*selectCrop, Gtk::PACK_SHRINK, 2); + pack_start (*selectCrop, Gtk::PACK_SHRINK, 2); - Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); + Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); - fixr = Gtk::manage (new Gtk::CheckButton (M("TP_CROP_FIXRATIO"))); - fixr->set_active (1); + fixr = Gtk::manage (new Gtk::CheckButton (M("TP_CROP_FIXRATIO"))); + fixr->set_active (1); - hb3->pack_start (*fixr, Gtk::PACK_SHRINK, 4); + hb3->pack_start (*fixr, Gtk::PACK_SHRINK, 4); - ratio = Gtk::manage (new MyComboBoxText ()); - hb3->pack_start (*ratio, Gtk::PACK_EXPAND_WIDGET, 4); + ratio = Gtk::manage (new MyComboBoxText ()); + hb3->pack_start (*ratio, Gtk::PACK_EXPAND_WIDGET, 4); - orientation = Gtk::manage (new MyComboBoxText ()); - hb3->pack_start (*orientation); + orientation = Gtk::manage (new MyComboBoxText ()); + hb3->pack_start (*orientation); - pack_start (*hb3, Gtk::PACK_SHRINK, 4); + pack_start (*hb3, Gtk::PACK_SHRINK, 4); - Gtk::HBox* hb31 = Gtk::manage (new Gtk::HBox ()); + Gtk::HBox* hb31 = Gtk::manage (new Gtk::HBox ()); - hb31->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_GUIDETYPE"))), Gtk::PACK_SHRINK, 4); - guide = Gtk::manage (new MyComboBoxText ()); - hb31->pack_start (*guide); + hb31->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_GUIDETYPE"))), Gtk::PACK_SHRINK, 4); + guide = Gtk::manage (new MyComboBoxText ()); + hb31->pack_start (*guide); - pack_start (*hb31, Gtk::PACK_SHRINK, 4); + pack_start (*hb31, Gtk::PACK_SHRINK, 4); - // ppibox START - ppibox = Gtk::manage (new Gtk::VBox()); - ppibox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 2); + // ppibox START + ppibox = Gtk::manage (new Gtk::VBox()); + ppibox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 2); - Gtk::HBox* hb4 = Gtk::manage (new Gtk::HBox ()); - hb4->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_PPI")))); - ppi = Gtk::manage (new MySpinButton ()); - ppi->set_size_request (60, -1); - hb4->pack_start (*ppi); + Gtk::HBox* hb4 = Gtk::manage (new Gtk::HBox ()); + hb4->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_PPI")))); + ppi = Gtk::manage (new MySpinButton ()); + ppi->set_size_request (60, -1); + hb4->pack_start (*ppi); - sizebox = Gtk::manage (new Gtk::VBox()); + sizebox = Gtk::manage (new Gtk::VBox()); - sizecm = Gtk::manage (new Gtk::Label (M("GENERAL_NA") + " cm x " + M("GENERAL_NA") + " cm")); - sizein = Gtk::manage (new Gtk::Label (M("GENERAL_NA") + " in x " + M("GENERAL_NA") + " in")); + sizecm = Gtk::manage (new Gtk::Label (M("GENERAL_NA") + " cm x " + M("GENERAL_NA") + " cm")); + sizein = Gtk::manage (new Gtk::Label (M("GENERAL_NA") + " in x " + M("GENERAL_NA") + " in")); - sizebox->pack_start (*sizecm, Gtk::PACK_SHRINK, 4); - sizebox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 6); - sizebox->pack_start (*sizein, Gtk::PACK_SHRINK, 4); - sizebox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 6); - sizebox->pack_start (*hb4, Gtk::PACK_SHRINK, 2); + sizebox->pack_start (*sizecm, Gtk::PACK_SHRINK, 4); + sizebox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 6); + sizebox->pack_start (*sizein, Gtk::PACK_SHRINK, 4); + sizebox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 6); + sizebox->pack_start (*hb4, Gtk::PACK_SHRINK, 2); - ppibox->pack_start (*sizebox, Gtk::PACK_SHRINK, 1); - pack_start (*ppibox, Gtk::PACK_SHRINK, 0); + ppibox->pack_start (*sizebox, Gtk::PACK_SHRINK, 1); + pack_start (*ppibox, Gtk::PACK_SHRINK, 0); - ppi->set_value (300); - // ppibox END + ppi->set_value (300); + // ppibox END - /**************** - * Crop Ratio - *****************/ - int NumberOfCropRatios = 26; //!!! change this value when adding new crop ratios - cropratio.resize (NumberOfCropRatios); + /**************** + * Crop Ratio + *****************/ + int NumberOfCropRatios = 26; //!!! change this value when adding new crop ratios + cropratio.resize (NumberOfCropRatios); - cropratio[0].label = "3:2"; cropratio[0].value = 3.0/2.0; - cropratio[1].label = "4:3"; cropratio[1].value = 4.0/3.0; - cropratio[2].label = "16:9"; cropratio[2].value = 16.0/9.0; - cropratio[3].label = "16:10"; cropratio[3].value = 16.0/10.0; - cropratio[4].label = "1:1"; cropratio[4].value = 1.0/1.0; - cropratio[5].label = "2:1"; cropratio[5].value = 2.0/1.0; - cropratio[6].label = "3:1"; cropratio[6].value = 3.0/1.0; - cropratio[7].label = "4:1"; cropratio[7].value = 4.0/1.0; - cropratio[8].label = "5:1"; cropratio[8].value = 5.0/1.0; - cropratio[9].label = "6:1"; cropratio[9].value = 6.0/1.0; - cropratio[10].label = "7:1"; cropratio[10].value = 7.0/1.0; - cropratio[11].label = "4:5"; cropratio[11].value = 4.0/5.0; - cropratio[12].label = "5:7"; cropratio[12].value = 5.0/7.0; - cropratio[13].label = "6:7"; cropratio[13].value = 6.0/7.0; - cropratio[14].label = "6:17"; cropratio[14].value = 6.0/17.0; - cropratio[15].label = "24:65 - XPAN"; cropratio[15].value = 24.0/65.0; - cropratio[16].label = "1.414 - DIN EN ISO 216"; cropratio[16].value = 1.414; - cropratio[17].label = "3.5:5"; cropratio[17].value = 3.5/5.0; - cropratio[18].label = "8.5:11 - US Letter"; cropratio[18].value = 8.5/11.0; - cropratio[19].label = "9.5:12"; cropratio[19].value = 9.5/12.0; - cropratio[20].label = "10:12"; cropratio[20].value = 10.0/12.0; - cropratio[21].label = "11:14"; cropratio[21].value = 11.0/14.0; - cropratio[22].label = "11:17 - Tabloid"; cropratio[22].value = 11.0/17.0; - cropratio[23].label = "13:19"; cropratio[23].value = 13.0/19.0; - cropratio[24].label = "17:22"; cropratio[24].value = 17.0/22.0; - cropratio[25].label = "45:35 - ePassport"; cropratio[25].value = 45.0/35.0; + cropratio[0].label = "3:2"; + cropratio[0].value = 3.0 / 2.0; + cropratio[1].label = "4:3"; + cropratio[1].value = 4.0 / 3.0; + cropratio[2].label = "16:9"; + cropratio[2].value = 16.0 / 9.0; + cropratio[3].label = "16:10"; + cropratio[3].value = 16.0 / 10.0; + cropratio[4].label = "1:1"; + cropratio[4].value = 1.0 / 1.0; + cropratio[5].label = "2:1"; + cropratio[5].value = 2.0 / 1.0; + cropratio[6].label = "3:1"; + cropratio[6].value = 3.0 / 1.0; + cropratio[7].label = "4:1"; + cropratio[7].value = 4.0 / 1.0; + cropratio[8].label = "5:1"; + cropratio[8].value = 5.0 / 1.0; + cropratio[9].label = "6:1"; + cropratio[9].value = 6.0 / 1.0; + cropratio[10].label = "7:1"; + cropratio[10].value = 7.0 / 1.0; + cropratio[11].label = "4:5"; + cropratio[11].value = 4.0 / 5.0; + cropratio[12].label = "5:7"; + cropratio[12].value = 5.0 / 7.0; + cropratio[13].label = "6:7"; + cropratio[13].value = 6.0 / 7.0; + cropratio[14].label = "6:17"; + cropratio[14].value = 6.0 / 17.0; + cropratio[15].label = "24:65 - XPAN"; + cropratio[15].value = 24.0 / 65.0; + cropratio[16].label = "1.414 - DIN EN ISO 216"; + cropratio[16].value = 1.414; + cropratio[17].label = "3.5:5"; + cropratio[17].value = 3.5 / 5.0; + cropratio[18].label = "8.5:11 - US Letter"; + cropratio[18].value = 8.5 / 11.0; + cropratio[19].label = "9.5:12"; + cropratio[19].value = 9.5 / 12.0; + cropratio[20].label = "10:12"; + cropratio[20].value = 10.0 / 12.0; + cropratio[21].label = "11:14"; + cropratio[21].value = 11.0 / 14.0; + cropratio[22].label = "11:17 - Tabloid"; + cropratio[22].value = 11.0 / 17.0; + cropratio[23].label = "13:19"; + cropratio[23].value = 13.0 / 19.0; + cropratio[24].label = "17:22"; + cropratio[24].value = 17.0 / 22.0; + cropratio[25].label = "45:35 - ePassport"; + cropratio[25].value = 45.0 / 35.0; - // populate the combobox - for (int i=0; iappend_text (cropratio[i].label); - } + // populate the combobox + for (int i = 0; i < NumberOfCropRatios; i++) { + ratio->append_text (cropratio[i].label); + } - ratio->set_active (0); + ratio->set_active (0); - orientation->append_text (M("GENERAL_LANDSCAPE")); - orientation->append_text (M("GENERAL_PORTRAIT")); - orientation->append_text (M("GENERAL_ASIMAGE")); - orientation->set_active (2); + orientation->append_text (M("GENERAL_LANDSCAPE")); + orientation->append_text (M("GENERAL_PORTRAIT")); + orientation->append_text (M("GENERAL_ASIMAGE")); + orientation->set_active (2); - guide->append_text (M("TP_CROP_GTNONE")); - guide->append_text (M("TP_CROP_GTFRAME")); - guide->append_text (M("TP_CROP_GTRULETHIRDS")); - guide->append_text (M("TP_CROP_GTDIAGONALS")); - guide->append_text (M("TP_CROP_GTHARMMEANS")); - guide->append_text (M("TP_CROP_GTGRID")); - guide->append_text (M("TP_CROP_GTTRIANGLE1")); - guide->append_text (M("TP_CROP_GTTRIANGLE2")); - guide->append_text (M("TP_CROP_GTEPASSPORT")); - guide->set_active (0); + guide->append_text (M("TP_CROP_GTNONE")); + guide->append_text (M("TP_CROP_GTFRAME")); + guide->append_text (M("TP_CROP_GTRULETHIRDS")); + guide->append_text (M("TP_CROP_GTDIAGONALS")); + guide->append_text (M("TP_CROP_GTHARMMEANS")); + guide->append_text (M("TP_CROP_GTGRID")); + guide->append_text (M("TP_CROP_GTTRIANGLE1")); + guide->append_text (M("TP_CROP_GTTRIANGLE2")); + guide->append_text (M("TP_CROP_GTEPASSPORT")); + guide->set_active (0); - w->set_range (0, maxw); - h->set_range (0, maxh); - x->set_range (0, maxw); - y->set_range (0, maxh); + w->set_range (0, maxw); + h->set_range (0, maxh); + x->set_range (0, maxw); + y->set_range (0, maxh); - x->set_digits (0); - x->set_increments (1,100); - x->set_value (0); + x->set_digits (0); + x->set_increments (1, 100); + x->set_value (0); - y->set_digits (0); - y->set_increments (1,100); - y->set_value (0); + y->set_digits (0); + y->set_increments (1, 100); + y->set_value (0); - w->set_digits (0); - w->set_increments (1,100); - w->set_value (200); + w->set_digits (0); + w->set_increments (1, 100); + w->set_value (200); - h->set_digits (0); - h->set_increments (1,100); - h->set_value (200); + h->set_digits (0); + h->set_increments (1, 100); + h->set_value (200); - ppi->set_digits (0); - ppi->set_increments (1,100); - ppi->set_range (50, 12000); - ppi->set_value (300); + ppi->set_digits (0); + ppi->set_increments (1, 100); + ppi->set_range (50, 12000); + ppi->set_value (300); - xconn = x->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::positionChanged), true); - yconn = y->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::positionChanged), true); - wconn = w->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::widthChanged), true); - hconn = h->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::heightChanged), true); - fconn = fixr->signal_toggled().connect( sigc::mem_fun(*this, &Crop::ratioFixedChanged) ); - rconn = ratio->signal_changed().connect( sigc::mem_fun(*this, &Crop::ratioChanged) ); - oconn = orientation->signal_changed().connect( sigc::mem_fun(*this, &Crop::ratioChanged) ); - gconn = guide->signal_changed().connect( sigc::mem_fun(*this, &Crop::notifyListener) ); - selectCrop->signal_pressed().connect( sigc::mem_fun(*this, &Crop::selectPressed) ); - ppi->signal_value_changed().connect( sigc::mem_fun(*this, &Crop::refreshSize) ); + xconn = x->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::positionChanged), true); + yconn = y->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::positionChanged), true); + wconn = w->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::widthChanged), true); + hconn = h->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::heightChanged), true); + fconn = fixr->signal_toggled().connect( sigc::mem_fun(*this, &Crop::ratioFixedChanged) ); + rconn = ratio->signal_changed().connect( sigc::mem_fun(*this, &Crop::ratioChanged) ); + oconn = orientation->signal_changed().connect( sigc::mem_fun(*this, &Crop::ratioChanged) ); + gconn = guide->signal_changed().connect( sigc::mem_fun(*this, &Crop::notifyListener) ); + selectCrop->signal_pressed().connect( sigc::mem_fun(*this, &Crop::selectPressed) ); + ppi->signal_value_changed().connect( sigc::mem_fun(*this, &Crop::refreshSize) ); - nx = ny = nw = nh = 0; - lastRotationDeg = 0; - show_all (); + nx = ny = nw = nh = 0; + lastRotationDeg = 0; + show_all (); } -void Crop::writeOptions () { +void Crop::writeOptions () +{ options.cropPPI = (int)ppi->get_value (); } -void Crop::readOptions () { +void Crop::readOptions () +{ disableListener (); @@ -238,7 +268,8 @@ void Crop::readOptions () { enableListener (); } -void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -257,38 +288,43 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { double tmp, maxw, maxh; w->get_range (tmp, maxw); h->get_range (tmp, maxh); - if (pp->crop.x + pp->crop.w > (int)maxw || pp->crop.y + pp->crop.h > (int)maxh) + + if (pp->crop.x + pp->crop.w > (int)maxw || pp->crop.y + pp->crop.h > (int)maxh) { setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h); + } ratio->set_active_text (pp->crop.ratio); fixr->set_active (pp->crop.fixratio); const bool flip_orientation = pp->crop.fixratio && cropratio[ratio->get_active_row_number()].value < 1.0; - if (pp->crop.orientation == "Landscape") - orientation->set_active (flip_orientation ? 1 : 0); - else if (pp->crop.orientation == "Portrait") - orientation->set_active (flip_orientation ? 0 : 1); - else - orientation->set_active (2); - if (pp->crop.guide == "None") + if (pp->crop.orientation == "Landscape") { + orientation->set_active (flip_orientation ? 1 : 0); + } else if (pp->crop.orientation == "Portrait") { + orientation->set_active (flip_orientation ? 0 : 1); + } else { + orientation->set_active (2); + } + + if (pp->crop.guide == "None") { guide->set_active (0); - else if (pp->crop.guide == "Frame") + } else if (pp->crop.guide == "Frame") { guide->set_active (1); - else if (pp->crop.guide == "Rule of thirds") + } else if (pp->crop.guide == "Rule of thirds") { guide->set_active (2); - else if (pp->crop.guide == "Rule of diagonals") + } else if (pp->crop.guide == "Rule of diagonals") { guide->set_active (3); - else if (!strncmp(pp->crop.guide.data(),"Harmonic means",14)) + } else if (!strncmp(pp->crop.guide.data(), "Harmonic means", 14)) { guide->set_active (4); - else if (pp->crop.guide == "Grid") + } else if (pp->crop.guide == "Grid") { guide->set_active (5); - else if (pp->crop.guide == "Golden Triangle 1") + } else if (pp->crop.guide == "Golden Triangle 1") { guide->set_active (6); - else if (pp->crop.guide == "Golden Triangle 2") + } else if (pp->crop.guide == "Golden Triangle 2") { guide->set_active (7); - else if (pp->crop.guide == "ePassport") + } else if (pp->crop.guide == "ePassport") { guide->set_active (8); + } x->set_value (pp->crop.x); y->set_value (pp->crop.y); @@ -312,12 +348,19 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { hDirty = pedited->crop.h; xDirty = pedited->crop.x; yDirty = pedited->crop.y; - if (!pedited->crop.ratio) + + if (!pedited->crop.ratio) { ratio->set_active_text (M("GENERAL_UNCHANGED")); - if (!pedited->crop.orientation) + } + + if (!pedited->crop.orientation) { orientation->set_active_text (M("GENERAL_UNCHANGED")); - if (!pedited->crop.guide) + } + + if (!pedited->crop.guide) { guide->set_active_text (M("GENERAL_UNCHANGED")); + } + set_inconsistent (multiImage && !pedited->crop.enabled); fixr->set_inconsistent (!pedited->crop.fixratio); } @@ -336,42 +379,47 @@ void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void Crop::write (ProcParams* pp, ParamsEdited* pedited) { +void Crop::write (ProcParams* pp, ParamsEdited* pedited) +{ - pp->crop.enabled = getEnabled (); - pp->crop.x = nx; - pp->crop.y = ny; - pp->crop.w = nw; - pp->crop.h = nh; - pp->crop.fixratio = fixr->get_active (); - pp->crop.ratio = ratio->get_active_text (); + pp->crop.enabled = getEnabled (); + pp->crop.x = nx; + pp->crop.y = ny; + pp->crop.w = nw; + pp->crop.h = nh; + pp->crop.fixratio = fixr->get_active (); + pp->crop.ratio = ratio->get_active_text (); - // for historical reasons we store orientation different if ratio is written as 2:3 instead of 3:2, but in GUI 'landscape' is always long side horizontal regardless of the ratio is written short or long side first. - const bool flip_orientation = fixr->get_active() && cropratio[ratio->get_active_row_number()].value < 1.0; - if (orientation->get_active_row_number()==0) - pp->crop.orientation = flip_orientation ? "Portrait" : "Landscape"; - else if (orientation->get_active_row_number()==1) - pp->crop.orientation = flip_orientation ? "Landscape" : "Portrait"; - else - pp->crop.orientation = "As Image"; - if (guide->get_active_row_number()==0) - pp->crop.guide = "None"; - else if (guide->get_active_row_number()==1) - pp->crop.guide = "Frame"; - else if (guide->get_active_row_number()==2) - pp->crop.guide = "Rule of thirds"; - else if (guide->get_active_row_number()==3) - pp->crop.guide = "Rule of diagonals"; - else if (guide->get_active_row_number()==4) - pp->crop.guide = "Harmonic means"; - else if (guide->get_active_row_number()==5) - pp->crop.guide = "Grid"; - else if (guide->get_active_row_number()==6) - pp->crop.guide = "Golden Triangle 1"; - else if (guide->get_active_row_number()==7) - pp->crop.guide = "Golden Triangle 2"; - else if (guide->get_active_row_number()==8) - pp->crop.guide = "ePassport"; + // for historical reasons we store orientation different if ratio is written as 2:3 instead of 3:2, but in GUI 'landscape' is always long side horizontal regardless of the ratio is written short or long side first. + const bool flip_orientation = fixr->get_active() && cropratio[ratio->get_active_row_number()].value < 1.0; + + if (orientation->get_active_row_number() == 0) { + pp->crop.orientation = flip_orientation ? "Portrait" : "Landscape"; + } else if (orientation->get_active_row_number() == 1) { + pp->crop.orientation = flip_orientation ? "Landscape" : "Portrait"; + } else { + pp->crop.orientation = "As Image"; + } + + if (guide->get_active_row_number() == 0) { + pp->crop.guide = "None"; + } else if (guide->get_active_row_number() == 1) { + pp->crop.guide = "Frame"; + } else if (guide->get_active_row_number() == 2) { + pp->crop.guide = "Rule of thirds"; + } else if (guide->get_active_row_number() == 3) { + pp->crop.guide = "Rule of diagonals"; + } else if (guide->get_active_row_number() == 4) { + pp->crop.guide = "Harmonic means"; + } else if (guide->get_active_row_number() == 5) { + pp->crop.guide = "Grid"; + } else if (guide->get_active_row_number() == 6) { + pp->crop.guide = "Golden Triangle 1"; + } else if (guide->get_active_row_number() == 7) { + pp->crop.guide = "Golden Triangle 2"; + } else if (guide->get_active_row_number() == 8) { + pp->crop.guide = "ePassport"; + } if (pedited) { pedited->crop.enabled = !get_inconsistent(); @@ -387,45 +435,50 @@ void Crop::write (ProcParams* pp, ParamsEdited* pedited) { } -void Crop::trim (ProcParams* pp, int ow, int oh) { +void Crop::trim (ProcParams* pp, int ow, int oh) +{ - int xmin = pp->crop.x; - int ymin = pp->crop.y; + int xmin = pp->crop.x; + int ymin = pp->crop.y; - if (xmin > ow || ymin > oh) { - // the crop is completely out of the image, so we disable the crop - pp->crop.enabled = false; - // and we set the values to the defaults - pp->crop.x = 0; - pp->crop.y = 0; - pp->crop.w = ow; - pp->crop.h = oh; - // the ratio is now not guaranteed, so we set it off - pp->crop.fixratio = false; - } - else { - if ((xmin + pp->crop.w) > ow) { - // crop overflow in the width dimension ; we trim it - pp->crop.w = ow-xmin; - } - if ((ymin + pp->crop.h) > oh) { - // crop overflow in the height dimension ; we trim it - pp->crop.h = oh-ymin; - } - } + if (xmin > ow || ymin > oh) { + // the crop is completely out of the image, so we disable the crop + pp->crop.enabled = false; + // and we set the values to the defaults + pp->crop.x = 0; + pp->crop.y = 0; + pp->crop.w = ow; + pp->crop.h = oh; + // the ratio is now not guaranteed, so we set it off + pp->crop.fixratio = false; + } else { + if ((xmin + pp->crop.w) > ow) { + // crop overflow in the width dimension ; we trim it + pp->crop.w = ow - xmin; + } + + if ((ymin + pp->crop.h) > oh) { + // crop overflow in the height dimension ; we trim it + pp->crop.h = oh - ymin; + } + } } -bool Crop::inImageArea (int x, int y) { - return x>=0 && x=0 && y= 0 && x < maxw && y >= 0 && y < maxh; } -void Crop::selectPressed () { +void Crop::selectPressed () +{ - if (clistener) - clistener->cropSelectRequested (); + if (clistener) { + clistener->cropSelectRequested (); + } } -void Crop::notifyListener () { +void Crop::notifyListener () +{ if (listener && getEnabled ()) { if (nw == 1 && nh == 1) { @@ -435,31 +488,35 @@ void Crop::notifyListener () { nw = (int)w->get_value (); nh = (int)h->get_value (); listener->panelChanged (EvCrop, M("GENERAL_DISABLED")); - } - else + } else { listener->panelChanged (EvCrop, Glib::ustring::compose ("%1=%2, %3=%4\n%5=%6, %7=%8", M("TP_CROP_X"), nx, M("TP_CROP_Y"), ny, M("TP_CROP_W"), nw, M("TP_CROP_H"), nh)); + } } } -void Crop::enabledChanged () { +void Crop::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvCrop, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvCrop, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvCrop, M("GENERAL_DISABLED")); + } } } -int notifyListenerUI (void* data) { +int notifyListenerUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected (static_cast(data))->notifyListener (); return 0; } -int refreshSpinsUI (void* data) { +int refreshSpinsUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected RefreshSpinHelper* rsh = static_cast(data); rsh->crop->refreshSpins (rsh->notify); @@ -467,51 +524,62 @@ int refreshSpinsUI (void* data) { return 0; } -void Crop::hFlipCrop () { +void Crop::hFlipCrop () +{ nx = maxw - nx - nw; g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::vFlipCrop () { +void Crop::vFlipCrop () +{ ny = maxh - ny - nh; g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::rotateCrop (int deg, bool hflip, bool vflip) { +void Crop::rotateCrop (int deg, bool hflip, bool vflip) +{ + + int rotation = (360 + deg - lastRotationDeg) % 360; + + if((hflip != vflip) && ((rotation % 180) == 90)) { + rotation = (rotation + 180) % 360; + } + + int tmp; + + switch (rotation) { + case 90: + tmp = nx; + nx = maxh - ny - nh; + ny = tmp; + tmp = nw; + nw = nh; + nh = tmp; + break; + + case 270: + tmp = ny; + ny = maxw - nx - nw; + nx = tmp; + tmp = nw; + nw = nh; + nh = tmp; + break; + + case 180: + nx = maxw - nx - nw; + ny = maxh - ny - nh; + break; + } - int rotation = (360+deg-lastRotationDeg)%360; - if((hflip != vflip) && ((rotation%180)==90)) - rotation = (rotation + 180)%360; - int tmp; - switch (rotation) { - case 90: - tmp = nx; - nx = maxh - ny - nh; - ny = tmp; - tmp = nw; - nw = nh; - nh = tmp; - break; - case 270: - tmp = ny; - ny = maxw - nx - nw; - nx = tmp; - tmp = nw; - nw = nh; - nh = tmp; - break; - case 180: - nx = maxw - nx - nw; - ny = maxh - ny - nh; - break; - } lastRotationDeg = deg; g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::positionChanged () { +void Crop::positionChanged () +{ xDirty = true; yDirty = true; @@ -524,7 +592,8 @@ void Crop::positionChanged () { g_idle_add (notifyListenerUI, this); } -void Crop::widthChanged () { +void Crop::widthChanged () +{ wDirty = true; @@ -536,7 +605,8 @@ void Crop::widthChanged () { g_idle_add (notifyListenerUI, this); } -void Crop::heightChanged () { +void Crop::heightChanged () +{ hDirty = true; @@ -549,7 +619,8 @@ void Crop::heightChanged () { } // Fixed ratio toggle button -void Crop::ratioFixedChanged () { +void Crop::ratioFixedChanged () +{ // Batch mode handling when enabling/disabling fixed crop if (batchMode && lastFixRatio != fixr->get_active ()) { if (fixr->get_inconsistent()) { @@ -557,9 +628,9 @@ void Crop::ratioFixedChanged () { fconn.block (true); fixr->set_active (false); fconn.block (false); - } - else if (lastFixRatio) + } else if (lastFixRatio) { fixr->set_inconsistent (true); + } } lastFixRatio = fixr->get_active (); @@ -567,15 +638,18 @@ void Crop::ratioFixedChanged () { } // change to orientation or ration -void Crop::ratioChanged () { - if (!fixr->get_active ()) - fixr->set_active(true); // will ajust ratio anyway - else +void Crop::ratioChanged () +{ + if (!fixr->get_active ()) { + fixr->set_active(true); // will ajust ratio anyway + } else { adjustCropToRatio(); + } } // Correct current crop if it doesn't fit -void Crop::adjustCropToRatio() { +void Crop::adjustCropToRatio() +{ if (fixr->get_active() && !fixr->get_inconsistent()) { // int W = w->get_value (); @@ -584,31 +658,34 @@ void Crop::adjustCropToRatio() { int H = nh; int X = nx; int Y = ny; - if (W>=H) - cropWidth2Resized (X, Y, W, H); - else - cropHeight2Resized (X, Y, W, H); + + if (W >= H) { + cropWidth2Resized (X, Y, W, H); + } else { + cropHeight2Resized (X, Y, W, H); + } } // This will save the options g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, true)); } -void Crop::refreshSize () { +void Crop::refreshSize () +{ if (!batchMode) { std::ostringstream ostrin; ostrin.precision (3); - // ostrin << h->get_value()/ppi->get_value() << " in x " << w->get_value()/ppi->get_value() << " in";; - ostrin << nh/ppi->get_value() << " in x " << nw/ppi->get_value() << " in";; + // ostrin << h->get_value()/ppi->get_value() << " in x " << w->get_value()/ppi->get_value() << " in";; + ostrin << nh / ppi->get_value() << " in x " << nw / ppi->get_value() << " in";; sizein->set_text (ostrin.str ()); std::ostringstream ostrcm; ostrcm.precision (3); - // ostrcm << h->get_value()/ppi->get_value()*2.54 << " cm x " << w->get_value()/ppi->get_value()*2.54 << " cm";; - ostrcm << nh/ppi->get_value()*2.54 << " cm x " << nw/ppi->get_value()*2.54 << " cm";; + // ostrcm << h->get_value()/ppi->get_value()*2.54 << " cm x " << w->get_value()/ppi->get_value()*2.54 << " cm";; + ostrcm << nh / ppi->get_value() * 2.54 << " cm x " << nw / ppi->get_value() * 2.54 << " cm";; sizecm->set_text (ostrcm.str ()); } @@ -618,35 +695,48 @@ void Crop::refreshSize () { * Set the maximum dimensions of the image. This method can be called with wrong values, then * called with the good ones !? */ -void Crop::setDimensions (int mw, int mh) { +void Crop::setDimensions (int mw, int mh) +{ - maxw = mw; - maxh = mh; + maxw = mw; + maxh = mh; - bool xconnWasBlocked = xconn.block (true); - bool yconnWasBlocked = yconn.block (true); - bool wconnWasBlocked = wconn.block (true); - bool hconnWasBlocked = hconn.block (true); + bool xconnWasBlocked = xconn.block (true); + bool yconnWasBlocked = yconn.block (true); + bool wconnWasBlocked = wconn.block (true); + bool hconnWasBlocked = hconn.block (true); - w->set_range (0, maxw); - h->set_range (0, maxh); - x->set_range (0, maxw); - y->set_range (0, maxh); + w->set_range (0, maxw); + h->set_range (0, maxh); + x->set_range (0, maxw); + y->set_range (0, maxh); - if (!xconnWasBlocked) xconn.block (false); - if (!yconnWasBlocked) yconn.block (false); - if (!wconnWasBlocked) wconn.block (false); - if (!hconnWasBlocked) hconn.block (false); + if (!xconnWasBlocked) { + xconn.block (false); + } - if (!getEnabled()) { - nx = 0; - ny = 0; - nw = mw; - nh = mh; + if (!yconnWasBlocked) { + yconn.block (false); + } - refreshSpins (); - } - refreshSize (); + if (!wconnWasBlocked) { + wconn.block (false); + } + + if (!hconnWasBlocked) { + hconn.block (false); + } + + if (!getEnabled()) { + nx = 0; + ny = 0; + nw = mw; + nh = mh; + + refreshSpins (); + } + + refreshSize (); } struct setdimparams { @@ -655,7 +745,8 @@ struct setdimparams { int y; }; -int sizeChangedUI (void* data) { +int sizeChangedUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected setdimparams* params = static_cast(data); params->crop->setDimensions (params->x, params->y); @@ -663,7 +754,8 @@ int sizeChangedUI (void* data) { return 0; } -void Crop::sizeChanged (int x, int y, int ow, int oh) { +void Crop::sizeChanged (int x, int y, int ow, int oh) +{ setdimparams* params = new setdimparams; params->x = x; @@ -672,77 +764,105 @@ void Crop::sizeChanged (int x, int y, int ow, int oh) { g_idle_add (sizeChangedUI, params); } -bool Crop::refreshSpins (bool notify) { +bool Crop::refreshSpins (bool notify) +{ - xconn.block (true); - yconn.block (true); - wconn.block (true); - hconn.block (true); + xconn.block (true); + yconn.block (true); + wconn.block (true); + hconn.block (true); - x->set_value (nx); - y->set_value (ny); - w->set_value (nw); - h->set_value (nh); + x->set_value (nx); + y->set_value (ny); + w->set_value (nw); + h->set_value (nh); - xDirty = true; - yDirty = true; - wDirty = true; - hDirty = true; + xDirty = true; + yDirty = true; + wDirty = true; + hDirty = true; - xconn.block (false); - yconn.block (false); - wconn.block (false); - hconn.block (false); + xconn.block (false); + yconn.block (false); + wconn.block (false); + hconn.block (false); - refreshSize (); - if (notify) - notifyListener (); + refreshSize (); - return false; + if (notify) { + notifyListener (); + } + + return false; } -void Crop::cropMoved (int &X, int &Y, int &W, int &H) { +void Crop::cropMoved (int &X, int &Y, int &W, int &H) +{ // W = w->get_value (); // H = h->get_value (); - W = nw; - H = nh; + W = nw; + H = nh; - if (X+W>maxw) - X = maxw-W; - if (Y+H>maxh) - Y = maxh-H; - if (X<0) - X = 0; - if (Y<0) - Y = 0; + if (X + W > maxw) { + X = maxw - W; + } - nx = X; - ny = Y; - nw = W; - nh = H; + if (Y + H > maxh) { + Y = maxh - H; + } - g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); + if (X < 0) { + X = 0; + } + + if (Y < 0) { + Y = 0; + } + + nx = X; + ny = Y; + nw = W; + nh = H; + + g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); // Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins)); } -void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) { +void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) +{ int oldXR = nx + nw; - if (W < 0) W = 0; - if (W > oldXR) W = oldXR; + + if (W < 0) { + W = 0; + } + + if (W > oldXR) { + W = oldXR; + } + if (fixr->get_active()) { double r = getRatio(); H = (int)round(W / r); int Hmax = min(ny + nh, maxh - ny); + if (H > Hmax) { H = Hmax; W = H * r; } + ny = ny - (H - nh) / 2.0; - if (ny < 0) ny = 0; - if (ny + H > maxh) ny = maxh - H; + + if (ny < 0) { + ny = 0; + } + + if (ny + H > maxh) { + ny = maxh - H; + } } + X = oldXR - W; Y = ny; nx = X; @@ -752,22 +872,38 @@ void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) { +void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) +{ + + if (W < 0) { + W = 0; + } + + if (W > maxw - nx) { + W = maxw - nx; + } - if (W < 0) W = 0; - if (W > maxw - nx) W = maxw - nx; if (fixr->get_active()) { double r = getRatio(); H = (int)round(W / r); int Hmax = min(ny + nh, maxh - ny); + if (H > Hmax) { H = Hmax; W = H * r; } + ny = ny - (H - nh) / 2.0; - if (ny < 0) ny = 0; - if (ny + H > maxh) ny = maxh - H; + + if (ny < 0) { + ny = 0; + } + + if (ny + H > maxh) { + ny = maxh - H; + } } + X = nx; Y = ny; nw = W; @@ -776,23 +912,40 @@ void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) { +void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) +{ int oldYB = ny + nh; - if (H < 0) H = 0; - if (H > oldYB) H = oldYB; + + if (H < 0) { + H = 0; + } + + if (H > oldYB) { + H = oldYB; + } + if (fixr->get_active()) { double r = getRatio(); W = (int)round(H * r); int Wmax = min(nx + nw, maxw - nx); + if (W > Wmax) { W = Wmax; H = W / r; } + nx = nx - (W - nw) / 2.0; - if (nx < 0) nx = 0; - if (nx + W > maxw) nx = maxw - W; + + if (nx < 0) { + nx = 0; + } + + if (nx + W > maxw) { + nx = maxw - W; + } } + X = nx; Y = oldYB - H; ny = Y; @@ -802,22 +955,38 @@ void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) { +void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) +{ + + if (H < 0) { + H = 0; + } + + if (H > maxh - ny) { + H = maxh - ny; + } - if (H < 0) H = 0; - if (H > maxh - ny) H = maxh - ny; if (fixr->get_active()) { double r = getRatio(); W = (int)round(H * r); int Wmax = min(nx + nw, maxw - nx); + if (W > Wmax) { W = Wmax; H = W / r; } + nx = nx - (W - nw) / 2.0; // nx must be floating point to avoid drifting - if (nx < 0) nx = 0; - if (nx + W > maxw) nx = maxw - W; + + if (nx < 0) { + nx = 0; + } + + if (nx + W > maxw) { + nx = maxw - W; + } } + X = nx; Y = ny; nw = W; @@ -826,22 +995,38 @@ void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) { +void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) +{ int oldXR = nx + nw; // right side int oldYB = ny + nh; // bottom side - if (W < 0) W = 0; - if (H < 0) H = 0; - if (W > oldXR) W = oldXR; - if (H > oldYB) H = oldYB; + + if (W < 0) { + W = 0; + } + + if (H < 0) { + H = 0; + } + + if (W > oldXR) { + W = oldXR; + } + + if (H > oldYB) { + H = oldYB; + } + if (fixr->get_active()) { double r = getRatio(); W = (int)round(H * r); + if (W > oldXR) { W = oldXR; H = (int)round(W / r); } } + X = oldXR - W; Y = oldYB - H; nx = X; @@ -852,21 +1037,37 @@ void Crop::cropTopLeftResized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) { +void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) +{ int oldYB = ny + nh; - if (W < 0) W = 0; - if (H < 0) H = 0; - if (W > maxw - nx) W = maxw - nx; - if (H > oldYB) H = oldYB; + + if (W < 0) { + W = 0; + } + + if (H < 0) { + H = 0; + } + + if (W > maxw - nx) { + W = maxw - nx; + } + + if (H > oldYB) { + H = oldYB; + } + if (fixr->get_active()) { double r = getRatio(); W = (int)round(H * r); + if (W > maxw - nx) { W = maxw - nx; H = (int)round(W / r); } } + X = nx; Y = oldYB - H; ny = Y; @@ -876,21 +1077,37 @@ void Crop::cropTopRightResized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) { +void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) +{ int oldXR = nx + nw; - if (W < 0) W = 0; - if (H < 0) H = 0; - if (W > oldXR) W = oldXR; - if (H > maxh - ny) H = maxh - ny; + + if (W < 0) { + W = 0; + } + + if (H < 0) { + H = 0; + } + + if (W > oldXR) { + W = oldXR; + } + + if (H > maxh - ny) { + H = maxh - ny; + } + if (fixr->get_active()) { double r = getRatio(); W = (int)round(H * r); + if (W > oldXR) { W = oldXR; H = (int)round(W / r); } } + X = oldXR - W; Y = ny; nx = X; @@ -900,20 +1117,35 @@ void Crop::cropBottomLeftResized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) { +void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) +{ + + if (W < 0) { + W = 0; + } + + if (H < 0) { + H = 0; + } + + if (W > maxw - nx) { + W = maxw - nx; + } + + if (H > maxh - ny) { + H = maxh - ny; + } - if (W < 0) W = 0; - if (H < 0) H = 0; - if (W > maxw - nx) W = maxw - nx; - if (H > maxh - ny) H = maxh - ny; if (fixr->get_active()) { double r = getRatio(); W = (int)round(H * r); + if (W > maxw - nx) { W = maxw - nx; H = (int)round(W / r); } } + X = nx; Y = ny; nw = W; @@ -922,126 +1154,157 @@ void Crop::cropBottomRightResized (int &X, int &Y, int &W, int &H) { g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropInit (int &x, int &y, int &w, int &h) { +void Crop::cropInit (int &x, int &y, int &w, int &h) +{ - nx = x; - ny = y; - nw = 1; - nh = 1; + nx = x; + ny = y; + nw = 1; + nh = 1; - w = 1; h = 1; + w = 1; + h = 1; - setEnabled(true); + setEnabled(true); } -void Crop::cropResized (int &x, int &y, int& x2, int& y2) { +void Crop::cropResized (int &x, int &y, int& x2, int& y2) +{ - if (x2<0) - x2 = 0; - if (y2<0) - y2 = 0; - if (x2>=maxw) - x2 = maxw-1; - if (y2>=maxh) - y2 = maxh-1; - - int X, Y; - int W; - if (xmaxw) - W = maxw; - if (H>maxh) - H = maxh; - - if (fixr->get_active()) { - double r = getRatio (); - if (y<=y2) { - int W2max = (int)round ((maxh-Y) * r); - if (W>W2max) - W = W2max; + if (x2 < 0) { + x2 = 0; } - else { - int W2max = (int)round (y * r); - if (W>W2max) - W = W2max; + + if (y2 < 0) { + y2 = 0; } - H = (int)round(W / r); - if (x= maxw) { + x2 = maxw - 1; + } - nx = X; - ny = Y; - nw = W; - nh = H; + if (y2 >= maxh) { + y2 = maxh - 1; + } - g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); + int X, Y; + int W; + + if (x < x2) { + W = x2 - x + 1; + X = x; + } else { + W = x - x2 + 1; + X = x2; + } + + int H; + + if (y < y2) { + H = y2 - y + 1; + Y = y; + } else { + H = y - y2 + 1; + Y = y2; + } + + if (W > maxw) { + W = maxw; + } + + if (H > maxh) { + H = maxh; + } + + if (fixr->get_active()) { + double r = getRatio (); + + if (y <= y2) { + int W2max = (int)round ((maxh - Y) * r); + + if (W > W2max) { + W = W2max; + } + } else { + int W2max = (int)round (y * r); + + if (W > W2max) { + W = W2max; + } + } + + H = (int)round(W / r); + + if (x < x2) { + x2 = x + W - 1; + } else { + x2 = x - W + 1; + } + + if (y < y2) { + y2 = y + H - 1; + } else { + y2 = y - H + 1; + } + } + + if (x < x2) { + W = x2 - x + 1; + X = x; + } else { + W = x - x2 + 1; + X = x2; + } + + if (y < y2) { + H = y2 - y + 1; + Y = y; + } else { + H = y - y2 + 1; + Y = y2; + } + + nx = X; + ny = Y; + nw = W; + nh = H; + + g_idle_add (refreshSpinsUI, new RefreshSpinHelper (this, false)); } -void Crop::cropManipReady () { +void Crop::cropManipReady () +{ - g_idle_add (notifyListenerUI, this); + g_idle_add (notifyListenerUI, this); } -double Crop::getRatio () { +double Crop::getRatio () +{ - double r = -1.0; - if (fixr->get_active()==false) - return r; + double r = -1.0; - r = cropratio[ratio->get_active_row_number()].value; - if (r < 1.0) - r = 1.0 / r; // convert to long side first (eg 4:5 becomes 5:4) + if (fixr->get_active() == false) { + return r; + } + + r = cropratio[ratio->get_active_row_number()].value; + + if (r < 1.0) { + r = 1.0 / r; // convert to long side first (eg 4:5 becomes 5:4) + } + + if (orientation->get_active_row_number() == 0) { + return r; + } else if(orientation->get_active_row_number() == 1) { + return 1.0 / r; + } else { + return maxh <= maxw ? r : 1.0 / r; + } - if (orientation->get_active_row_number()==0) - return r; - else if(orientation->get_active_row_number()==1) - return 1.0 / r; - else return maxh <= maxw ? r : 1.0 /r; - } -void Crop::setBatchMode (bool batchMode) { +void Crop::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); diff --git a/rtgui/crop.h b/rtgui/crop.h index 40bb1877b..2b29e46aa 100644 --- a/rtgui/crop.h +++ b/rtgui/crop.h @@ -7,7 +7,7 @@ * 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 @@ -25,22 +25,25 @@ #include "guiutils.h" #include -class CropPanelListener { +class CropPanelListener +{ - public: +public: virtual void cropSelectRequested () {} }; -class CropRatio { +class CropRatio +{ - public: - Glib::ustring label; - double value; +public: + Glib::ustring label; + double value; }; -class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolPanel, public rtengine::SizeListener { +class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolPanel, public rtengine::SizeListener +{ - protected: +protected: Gtk::CheckButton* fixr; MyComboBoxText* ratio; MyComboBoxText* orientation; @@ -66,14 +69,14 @@ class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolP void adjustCropToRatio(); std::vector cropratio; - public: +public: Crop (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - + void ratioChanged (); void ratioFixedChanged (); // The toggle button void refreshSize (); @@ -83,7 +86,7 @@ class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolP void positionChanged (); void widthChanged (); void heightChanged (); - bool refreshSpins (bool notify=false); + bool refreshSpins (bool notify = false); void notifyListener (); void sizeChanged (int w, int h, int ow, int oh); void trim (rtengine::procparams::ProcParams* pp, int ow, int oh); @@ -105,7 +108,10 @@ class Crop : public ToolParamBlock, public CropGUIListener, public FoldableToolP bool inImageArea (int x, int y); double getRatio (); - void setCropPanelListener (CropPanelListener* cl) { clistener = cl; } + void setCropPanelListener (CropPanelListener* cl) + { + clistener = cl; + } void resizeScaleChanged (double rsc); void hFlipCrop (); diff --git a/rtgui/cropguilistener.h b/rtgui/cropguilistener.h index 64ecfa1a8..5124ece5f 100644 --- a/rtgui/cropguilistener.h +++ b/rtgui/cropguilistener.h @@ -7,7 +7,7 @@ * 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 @@ -19,24 +19,25 @@ #ifndef __CROPGUILISTENER__ #define __CROPGUILISTENER__ -class CropGUIListener { +class CropGUIListener +{ - public: +public: virtual ~CropGUIListener() {} - virtual void cropMoved (int &x, int &y, int &w, int &h) =0; - virtual void cropWidth1Resized (int &x, int &y, int &w, int &h) =0; - virtual void cropWidth2Resized (int &x, int &y, int &w, int &h) =0; - virtual void cropHeight1Resized (int &x, int &y, int &w, int &h) =0; - virtual void cropHeight2Resized (int &x, int &y, int &w, int &h) =0; - virtual void cropTopLeftResized (int &x, int &y, int &w, int &h) =0; - virtual void cropTopRightResized (int &x, int &y, int &w, int &h) =0; - virtual void cropBottomLeftResized (int &x, int &y, int &w, int &h) =0; - virtual void cropBottomRightResized (int &x, int &y, int &w, int &h) =0; - virtual void cropInit (int &x, int &y, int &w, int &h) =0; - virtual void cropResized (int &x, int &y, int& x2, int& y2) =0; - virtual void cropManipReady () =0; - virtual bool inImageArea (int x, int y) =0; - virtual double getRatio () =0; + virtual void cropMoved (int &x, int &y, int &w, int &h) = 0; + virtual void cropWidth1Resized (int &x, int &y, int &w, int &h) = 0; + virtual void cropWidth2Resized (int &x, int &y, int &w, int &h) = 0; + virtual void cropHeight1Resized (int &x, int &y, int &w, int &h) = 0; + virtual void cropHeight2Resized (int &x, int &y, int &w, int &h) = 0; + virtual void cropTopLeftResized (int &x, int &y, int &w, int &h) = 0; + virtual void cropTopRightResized (int &x, int &y, int &w, int &h) = 0; + virtual void cropBottomLeftResized (int &x, int &y, int &w, int &h) = 0; + virtual void cropBottomRightResized (int &x, int &y, int &w, int &h) = 0; + virtual void cropInit (int &x, int &y, int &w, int &h) = 0; + virtual void cropResized (int &x, int &y, int& x2, int& y2) = 0; + virtual void cropManipReady () = 0; + virtual bool inImageArea (int x, int y) = 0; + virtual double getRatio () = 0; }; #endif diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 9c25eea64..4342c4973 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -7,7 +7,7 @@ * 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 @@ -29,8 +29,9 @@ using namespace rtengine; CropHandler::CropHandler () : zoom(10), ww(0), wh(0), cx(0), cy(0), cw(0), ch(0), - cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), - cropimg(NULL), cropimgtrue(NULL), ipc(NULL), crop(NULL), listener(NULL), isLowUpdatePriority(false) { + cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), + cropimg(NULL), cropimgtrue(NULL), ipc(NULL), crop(NULL), listener(NULL), isLowUpdatePriority(false) +{ chi = new CropHandlerIdleHelper; chi->destroyed = false; @@ -38,165 +39,199 @@ CropHandler::CropHandler () chi->cropHandler = this; } -CropHandler::~CropHandler () { +CropHandler::~CropHandler () +{ - if (ipc) + if (ipc) { ipc->delSizeListener (this); + } setEnabled (false); + if (crop) { //crop->destroy (); delete crop; // will do the same than destroy, plus delete the object crop = NULL; } + cimg.lock (); - if (chi->pending) + + if (chi->pending) { chi->destroyed = true; - else + } else { delete chi; + } + cimg.unlock (); } -void CropHandler::setEditSubscriber (EditSubscriber* newSubscriber) { +void CropHandler::setEditSubscriber (EditSubscriber* newSubscriber) +{ (static_cast(crop))->setEditSubscriber(newSubscriber); } -void CropHandler::newImage (StagedImageProcessor* ipc_, bool isDetailWindow) { +void CropHandler::newImage (StagedImageProcessor* ipc_, bool isDetailWindow) +{ ipc = ipc_; cx = 0; cy = 0; - - if (!ipc) + + if (!ipc) { return; + } EditDataProvider *editDataProvider = NULL; CropWindow *cropWin = listener ? static_cast(listener) : NULL; - if (cropWin) + + if (cropWin) { editDataProvider = cropWin->getImageArea(); + } + crop = ipc->createCrop (editDataProvider, isDetailWindow); ipc->setSizeListener (this); crop->setListener (enabled ? this : NULL); initial = true; } -void CropHandler::sizeChanged (int x, int y, int ow, int oh) { // the ipc notifies it to keep track size changes like rotation +void CropHandler::sizeChanged (int x, int y, int ow, int oh) // the ipc notifies it to keep track size changes like rotation +{ compDim (); // this should be put into an idle source!!! -/* if (listener) - listener->cropWindowChanged (); - */ + /* if (listener) + listener->cropWindowChanged (); + */ } -double CropHandler::getFitCropZoom () { - double z1 = (double) wh / cropParams.h; - double z2 = (double) ww / cropParams.w; - return z1getFullHeight (); double z2 = (double) ww / ipc->getFullWidth (); - return z1=0) - x = centerx; - if (centery>=0) - y = centery; - + if (centerx >= 0) { + x = centerx; + } + + if (centery >= 0) { + y = centery; + } + // maybe demosaic etc. if we cross the border to >100% - bool needsFullRefresh = (z>=1000 && zoom<1000); + bool needsFullRefresh = (z >= 1000 && zoom < 1000); zoom = z; - if (zoom>=1000) { + + if (zoom >= 1000) { cw = ww * 1000 / zoom; ch = wh * 1000 / zoom; - } - else { + } else { cw = ww * zoom; ch = wh * zoom; } + cx = x - cw / 2; cy = y - ch / 2; compDim (); + if (enabled) { - if (needsFullRefresh) + if (needsFullRefresh) { ipc->startProcessing(M_HIGHQUAL); - else - update (); -} + } else { + update (); + } + } } -void CropHandler::setWSize (int w, int h) { +void CropHandler::setWSize (int w, int h) +{ ww = w; wh = h; - if (zoom>=1000) { + + if (zoom >= 1000) { cw = ww * 1000 / zoom; ch = wh * 1000 / zoom; - } - else { + } else { cw = ww * zoom; ch = wh * zoom; } compDim (); - if (enabled) - update (); + + if (enabled) { + update (); + } } -void CropHandler::getWSize (int& w, int &h) { +void CropHandler::getWSize (int& w, int &h) +{ w = ww; h = wh; } -void CropHandler::setPosition (int x, int y, bool update_) { +void CropHandler::setPosition (int x, int y, bool update_) +{ cx = x; cy = y; compDim (); - if (enabled && update_) - update (); + + if (enabled && update_) { + update (); + } } -void CropHandler::getPosition (int& x, int& y) { +void CropHandler::getPosition (int& x, int& y) +{ x = cropX; y = cropY; } -int createpixbufs (void* data) { +int createpixbufs (void* data) +{ GThreadLock lock; CropHandlerIdleHelper* chi = static_cast(data); + if (chi->destroyed) { - if (chi->pending == 1) + if (chi->pending == 1) { delete chi; - else + } else { chi->pending--; + } return 0; } - + CropHandler* ch = chi->cropHandler; ch->cimg.lock (); @@ -212,71 +247,87 @@ int createpixbufs (void* data) { } if (ch->cropimg) { - if (ch->cix==ch->cropX && ch->ciy==ch->cropY && ch->ciw==ch->cropW && ch->cih==ch->cropH && ch->cis==(ch->zoom>=1000?1:ch->zoom)) { + if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) { // calculate final image size - int czoom = ch->zoom<1000 ? 1000 : ch->zoom; + int czoom = ch->zoom < 1000 ? 1000 : ch->zoom; int imw = ch->cropimg_width * czoom / 1000; int imh = ch->cropimg_height * czoom / 1000; - if (imw>ch->ww) - imw = ch->ww; - if (imh>ch->wh) - imh = ch->wh; - Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2*ch->cropimg_height, 3*ch->cropimg_width); + if (imw > ch->ww) { + imw = ch->ww; + } + + if (imh > ch->wh) { + imh = ch->wh; + } + + Glib::RefPtr tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); - tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST); + tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); tmpPixbuf.clear (); - Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2*ch->cropimg_height, 3*ch->cropimg_width); + Glib::RefPtr tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, 2 * ch->cropimg_height, 3 * ch->cropimg_width); ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); - tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST); + tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST); tmpPixbuftrue.clear (); } + delete [] ch->cropimg; ch->cropimg = NULL; delete [] ch->cropimgtrue; ch->cropimgtrue = NULL; } + ch->cimg.unlock (); + if (ch->listener) { ch->listener->cropImageUpdated (); + if (ch->initial) { ch->listener->initialImageArrived (); ch->initial = false; } } - + chi->pending--; - + return 0; } void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procparams::ColorManagementParams cmp, - rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) { + rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) +{ - if (!enabled) + if (!enabled) { return; + } cimg.lock (); cropParams = cp; - colorParams = cmp; + colorParams = cmp; cropPixbuf.clear (); - if (cropimg) + + if (cropimg) { delete [] cropimg; + } + cropimg = NULL; - if (cropimgtrue) + + if (cropimgtrue) { delete [] cropimgtrue; + } + cropimgtrue = NULL; - if (ax==cropX && ay==cropY && aw==cropW && ah==cropH && askip==(zoom>=1000?1:zoom)) { + if (ax == cropX && ay == cropY && aw == cropW && ah == cropH && askip == (zoom >= 1000 ? 1 : zoom)) { cropimg_width = im->getWidth (); cropimg_height = im->getHeight (); - cropimg = new unsigned char [3*cropimg_width*cropimg_height]; - cropimgtrue = new unsigned char [3*cropimg_width*cropimg_height]; - memcpy (cropimg, im->getData(), 3*cropimg_width*cropimg_height); - memcpy (cropimgtrue, imtrue->getData(), 3*cropimg_width*cropimg_height); + cropimg = new unsigned char [3 * cropimg_width * cropimg_height]; + cropimgtrue = new unsigned char [3 * cropimg_width * cropimg_height]; + memcpy (cropimg, im->getData(), 3 * cropimg_width * cropimg_height); + memcpy (cropimgtrue, imtrue->getData(), 3 * cropimg_width * cropimg_height); cix = ax; ciy = ay; ciw = aw; @@ -285,83 +336,98 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp chi->pending++; g_idle_add (createpixbufs, chi); } - cimg.unlock (); - } -bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip) { - + cimg.unlock (); +} + +bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip) +{ + cwx = cropX; cwy = cropY; cww = cropW; cwh = cropH; // hack: if called before first size allocation the size will be 0 - if (cww<10) + if (cww < 10) { cww = 10; - if (cwh<32) + } + + if (cwh < 32) { cwh = 32; + } - cskip = zoom>=1000 ? 1 : zoom; + cskip = zoom >= 1000 ? 1 : zoom; - return true; + return true; } -void CropHandler::update () { +void CropHandler::update () +{ if (crop) { // crop->setWindow (cropX, cropY, cropW, cropH, zoom>=1000 ? 1 : zoom); --> we use the "getWindow" hook instead of setting the size before crop->setListener (this); cropPixbuf.clear (); - // To save threads, try to mark "needUpdate" without a thread first - if (crop->tryUpdate()) { - if (isLowUpdatePriority) + // To save threads, try to mark "needUpdate" without a thread first + if (crop->tryUpdate()) { + if (isLowUpdatePriority) { Glib::Thread::create(sigc::mem_fun(*crop, &DetailedCrop::fullUpdate), 0, false, true, Glib::THREAD_PRIORITY_LOW); - else - Glib::Thread::create(sigc::mem_fun(*crop, &DetailedCrop::fullUpdate), false ); - } + } else { + Glib::Thread::create(sigc::mem_fun(*crop, &DetailedCrop::fullUpdate), false ); + } + } } } -void CropHandler::setEnabled (bool e) { +void CropHandler::setEnabled (bool e) +{ enabled = e; + if (!enabled) { - if (crop) + if (crop) { crop->setListener (NULL); + } + cimg.lock (); delete [] cropimg; cropimg = NULL; - delete [] cropimgtrue; + delete [] cropimgtrue; cropimgtrue = NULL; cropPixbuf.clear (); cimg.unlock (); - } - else + } else { update (); + } } -bool CropHandler::getEnabled () { +bool CropHandler::getEnabled () +{ return enabled; } -void CropHandler::getSize (int& w, int& h) { - +void CropHandler::getSize (int& w, int& h) +{ + w = cropW; h = cropH; } -void CropHandler::getFullImageSize (int& w, int& h) { +void CropHandler::getFullImageSize (int& w, int& h) +{ if (ipc) { w = ipc->getFullWidth (); h = ipc->getFullHeight (); } else { - w=h=0; + w = h = 0; } } -void CropHandler::compDim () { +void CropHandler::compDim () +{ cropX = cx; cropY = cy; @@ -371,20 +437,32 @@ void CropHandler::compDim () { cutRectToImgBounds (cropX, cropY, cropW, cropH); } -void CropHandler::cutRectToImgBounds (int& x, int& y, int& w, int& h) { +void CropHandler::cutRectToImgBounds (int& x, int& y, int& w, int& h) +{ if (ipc) { - if (w > ipc->getFullWidth()) + if (w > ipc->getFullWidth()) { w = ipc->getFullWidth(); - if (h > ipc->getFullHeight()) + } + + if (h > ipc->getFullHeight()) { h = ipc->getFullHeight(); - if (x < 0) + } + + if (x < 0) { x = 0; - if (y < 0) + } + + if (y < 0) { y = 0; - if (x + w >= ipc->getFullWidth()) + } + + if (x + w >= ipc->getFullWidth()) { x = ipc->getFullWidth() - w; - if (y + h >= ipc->getFullHeight()) + } + + if (y + h >= ipc->getFullHeight()) { y = ipc->getFullHeight() - h; + } } } diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index a42f5085f..60d7956ca 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -7,7 +7,7 @@ * 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 @@ -24,13 +24,14 @@ #include "edit.h" #include -class CropHandlerListener { +class CropHandlerListener +{ - public: - virtual ~CropHandlerListener() {} - virtual void cropImageUpdated () {} - virtual void cropWindowChanged () {} - virtual void initialImageArrived () {} +public: + virtual ~CropHandlerListener() {} + virtual void cropImageUpdated () {} + virtual void cropWindowChanged () {} + virtual void initialImageArrived () {} }; class CropHandler; @@ -40,72 +41,79 @@ struct CropHandlerIdleHelper { int pending; }; -class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener { +class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener +{ friend int createpixbufs (void* data); - protected: - int zoom; - int ww, wh; // size of the crop view on the screen - int cx, cy, cw, ch; // position and size of the requested crop - int cropX, cropY, cropW, cropH; // position and size of the crop corresponding to cropPixbuf - bool enabled; - unsigned char* cropimg; - unsigned char* cropimgtrue; - int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; - bool initial; - bool isLowUpdatePriority; +protected: + int zoom; + int ww, wh; // size of the crop view on the screen + int cx, cy, cw, ch; // position and size of the requested crop + int cropX, cropY, cropW, cropH; // position and size of the crop corresponding to cropPixbuf + bool enabled; + unsigned char* cropimg; + unsigned char* cropimgtrue; + int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; + bool initial; + bool isLowUpdatePriority; - rtengine::StagedImageProcessor* ipc; - rtengine::DetailedCrop* crop; + rtengine::StagedImageProcessor* ipc; + rtengine::DetailedCrop* crop; - CropHandlerListener* listener; - CropHandlerIdleHelper* chi; + CropHandlerListener* listener; + CropHandlerIdleHelper* chi; - void compDim (); + void compDim (); - public: +public: - void update (); + void update (); - rtengine::procparams::CropParams cropParams; - rtengine::procparams::ColorManagementParams colorParams; - Glib::RefPtr cropPixbuf; - Glib::RefPtr cropPixbuftrue; + rtengine::procparams::CropParams cropParams; + rtengine::procparams::ColorManagementParams colorParams; + Glib::RefPtr cropPixbuf; + Glib::RefPtr cropPixbuftrue; - MyMutex cimg; + MyMutex cimg; - CropHandler (); - ~CropHandler (); + CropHandler (); + ~CropHandler (); - void setCropHandlerListener (CropHandlerListener* l) { listener = l; } - void setEditSubscriber (EditSubscriber* newSubscriber); + void setCropHandlerListener (CropHandlerListener* l) + { + listener = l; + } + void setEditSubscriber (EditSubscriber* newSubscriber); - void newImage (rtengine::StagedImageProcessor* ipc_, bool isDetailWindow); - void setZoom (int z, int centerx=-1, int centery=-1); - double getFitZoom (); - double getFitCropZoom(); - void setWSize (int w, int h); - void getWSize (int& w, int &h); - void setPosition (int x, int y, bool update=true); - void getPosition (int& x, int& y); - void getSize (int& w, int& h); - void getFullImageSize (int& w, int& h); + void newImage (rtengine::StagedImageProcessor* ipc_, bool isDetailWindow); + void setZoom (int z, int centerx = -1, int centery = -1); + double getFitZoom (); + double getFitCropZoom(); + void setWSize (int w, int h); + void getWSize (int& w, int &h); + void setPosition (int x, int y, bool update = true); + void getPosition (int& x, int& y); + void getSize (int& w, int& h); + void getFullImageSize (int& w, int& h); - void setEnabled (bool e); - bool getEnabled (); + void setEnabled (bool e); + bool getEnabled (); - rtengine::DetailedCrop* getCrop() { return crop; } + rtengine::DetailedCrop* getCrop() + { + return crop; + } - // DetailedCropListener interface - void setDetailedCrop (rtengine::IImage8* im, rtengine::IImage8* imworking,rtengine::procparams::ColorManagementParams cmp, - rtengine::procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip); - bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip); - // SizeListener interface - void sizeChanged (int w, int h, int ow, int oh); + // DetailedCropListener interface + void setDetailedCrop (rtengine::IImage8* im, rtengine::IImage8* imworking, rtengine::procparams::ColorManagementParams cmp, + rtengine::procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip); + bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip); + // SizeListener interface + void sizeChanged (int w, int h, int ow, int oh); - void cutRectToImgBounds (int& x, int& y, int& w, int& h); + void cutRectToImgBounds (int& x, int& y, int& w, int& h); }; #endif diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 6dd99228e..e787a11e1 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -7,7 +7,7 @@ * 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 @@ -31,78 +31,81 @@ using namespace rtengine; -struct ZoomStep { +struct ZoomStep { Glib::ustring label; double zoom; int czoom; }; ZoomStep zoomSteps[] = { - {" 1%", 0.01, 100}, - {" 2%", 0.02, 50}, - {" 5%", 0.05, 20}, - {"6.7%", 1.0/15.0,15}, - {" 8%", 1.0/12.0,12}, - {" 10%", 0.1, 10}, - {"12.5%", 0.125, 8}, - {" 14%", 1.0/7.0, 7}, - {"16.6%", 1.0/6.0, 6}, - {" 20%", 0.2, 5}, - {" 25%", 0.25, 4}, - {" 33%", 1.0/3.0, 3}, - {" 50%", 0.5, 2}, - {"100%", 1.0, 1000}, - {"200%", 2.0, 2000}, - {"300%", 3.0, 3000}, - {"400%", 4.0, 4000}, - {"500%", 5.0, 5000}, - {"600%", 6.0, 6000}, - {"700%", 7.0, 7000}, - {"800%", 8.0, 8000}}; + {" 1%", 0.01, 100}, + {" 2%", 0.02, 50}, + {" 5%", 0.05, 20}, + {"6.7%", 1.0 / 15.0, 15}, + {" 8%", 1.0 / 12.0, 12}, + {" 10%", 0.1, 10}, + {"12.5%", 0.125, 8}, + {" 14%", 1.0 / 7.0, 7}, + {"16.6%", 1.0 / 6.0, 6}, + {" 20%", 0.2, 5}, + {" 25%", 0.25, 4}, + {" 33%", 1.0 / 3.0, 3}, + {" 50%", 0.5, 2}, + {"100%", 1.0, 1000}, + {"200%", 2.0, 2000}, + {"300%", 3.0, 3000}, + {"400%", 4.0, 4000}, + {"500%", 5.0, 5000}, + {"600%", 6.0, 6000}, + {"700%", 7.0, 7000}, + {"800%", 8.0, 8000} +}; #define MAXZOOMSTEPS 20 #define ZOOM11INDEX 13 -CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow) +CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow) : onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), - backColor(options.bgcolor), decorated(true), titleHeight(30), - sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), - xpos(30), ypos(30), imgX(0), imgY(0), imgW(1), imgH(1), iarea(parent), - cropZoom(0), cropgl(NULL), pmlistener(NULL), observedCropWin(NULL), ipc(ipc_), isFlawnOver(false) { + backColor(options.bgcolor), decorated(true), titleHeight(30), + sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), + xpos(30), ypos(30), imgX(0), imgY(0), imgW(1), imgH(1), iarea(parent), + cropZoom(0), cropgl(NULL), pmlistener(NULL), observedCropWin(NULL), ipc(ipc_), isFlawnOver(false) +{ Glib::RefPtr context = parent->get_pango_context () ; - Pango::FontDescription fontd = context->get_font_description (); + Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); - fontd.set_size(8*Pango::SCALE); + fontd.set_size(8 * Pango::SCALE); context->set_font_description (fontd); cropLabel = "100%"; Glib::RefPtr cllayout = parent->create_pango_layout("1000%"); exposeVersion = zoomVersion = 0; - + int iw, ih; cllayout->get_pixel_size (iw, ih); - + 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"); - + buttonSet.add (bZoomOut); buttonSet.add (bZoomIn); buttonSet.add (bZoom100); buttonSet.add (bClose); - + buttonSet.setColors (Gdk::Color("black"), Gdk::Color("white")); buttonSet.setButtonListener (this); int bsw, bsh; buttonSet.getMinimalDimensions (bsw, bsh); - if (bsh>titleHeight) + if (bsh > titleHeight) { titleHeight = bsh; + } - minWidth = bsw + iw + 2*sideBorderWidth; + minWidth = bsw + iw + 2 * sideBorderWidth; cropHandler.setCropHandlerListener (this); cropHandler.newImage (ipc_, isDetailWindow); @@ -110,137 +113,163 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, state = SNormal; } -void CropWindow::enable() { +void CropWindow::enable() +{ cropHandler.setEnabled (true); } -void CropWindow::setPosition (int x, int y) { - - if (y<0) +void CropWindow::setPosition (int x, int y) +{ + + if (y < 0) { y = 0; + } + xpos = x; ypos = y; - if (decorated) - buttonSet.arrangeButtons (xpos + sideBorderWidth, ypos + upperBorderWidth, width - 2*sideBorderWidth, titleHeight); + + if (decorated) { + buttonSet.arrangeButtons (xpos + sideBorderWidth, ypos + upperBorderWidth, width - 2 * sideBorderWidth, titleHeight); + } } -void CropWindow::getPosition (int& x, int& y) { - +void CropWindow::getPosition (int& x, int& y) +{ + x = xpos; y = ypos; } -void CropWindow::getCropPosition (int& x, int& y) { - +void CropWindow::getCropPosition (int& x, int& y) +{ + int cropX, cropY; cropHandler.getPosition (cropX, cropY); - if (state!=SCropImgMove) { + + if (state != SCropImgMove) { x = cropX; y = cropY; - } - else { + } else { x = cropX + action_x; y = cropY + action_y; } } -void CropWindow::getCropRectangle (int& x, int& y, int& w, int& h) { - +void CropWindow::getCropRectangle (int& x, int& y, int& w, int& h) +{ + int cropX, cropY, cropW, cropH; cropHandler.getPosition (cropX, cropY); cropHandler.getSize (cropW, cropH); - if (state!=SCropImgMove) { + + if (state != SCropImgMove) { x = cropX; y = cropY; - } - else { + } else { x = cropX + action_x; y = cropY + action_y; } - if (state!=SCropWinResize) { + + if (state != SCropWinResize) { w = cropW; h = cropH; - } - else { + } else { w = imgAreaW; h = imgAreaH; } + cropHandler.cutRectToImgBounds (x, y, w, h); } -void CropWindow::setCropPosition (int x, int y, bool update) { - +void CropWindow::setCropPosition (int x, int y, bool update) +{ + cropHandler.setPosition (x, y, update); - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropPositionChanged (this); + } } -void CropWindow::setSize (int w, int h, bool norefresh) { +void CropWindow::setSize (int w, int h, bool norefresh) +{ width = w; - height = h; - + height = h; + fitZoom = false; - - if (widthredraw (); } -void CropWindow::getSize (int& w, int& h) { - +void CropWindow::getSize (int& w, int& h) +{ + w = width; h = height; } -void CropWindow::getCropSize (int& w, int& h) { - +void CropWindow::getCropSize (int& w, int& h) +{ + w = imgAreaW; h = imgAreaH; } -bool CropWindow::isInside (int x, int y) { - - return x>=xpos && x=ypos && y= xpos && x < xpos + width && y >= ypos && y < ypos + height; } -void CropWindow::leaveNotify (GdkEventCrossing* event) { +void CropWindow::leaveNotify (GdkEventCrossing* event) +{ EditSubscriber* subscriber = iarea->getCurrSubscriber(); - if (state==SNormal && subscriber && subscriber->getEditingType()==ET_PIPETTE) { + + if (state == SNormal && subscriber && subscriber->getEditingType() == ET_PIPETTE) { iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; + if (subscriber->mouseOver(0)) { iarea->redraw(); } } } -void CropWindow::flawnOver (bool isFlawnOver) { +void CropWindow::flawnOver (bool isFlawnOver) +{ this->isFlawnOver = isFlawnOver; } -void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { +void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) +{ iarea->grabFocus (this); - if (button==1 && type==GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state==SNormal || state==SCropImgMove)) { + + if (button == 1 && type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state == SNormal || state == SCropImgMove)) { if (fitZoomEnabled) { if (fitZoom) { state = SNormal; @@ -248,20 +277,21 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { screenCoordToImage (x, y, action_x, action_y); changeZoom (ZOOM11INDEX, true, action_x, action_y); fitZoom = false; - } - else + } else { zoomFit (); - } - else + } + } else { zoom11 (); + } + state = SNormal; } - //below code is no longer working/needed after adding buttons for each of the backColor values - /*else if (button==1 && type==GDK_2BUTTON_PRESS && onArea (CropBorder, x, y)) { - backColor = (backColor+1) % 3; - options.bgcolor = backColor; - }*/ - else if (button==1 && type==GDK_BUTTON_PRESS && state==SNormal && onArea (CropToolBar, x, y)) { + //below code is no longer working/needed after adding buttons for each of the backColor values + /*else if (button==1 && type==GDK_2BUTTON_PRESS && onArea (CropBorder, x, y)) { + backColor = (backColor+1) % 3; + options.bgcolor = backColor; + }*/ + else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropToolBar, x, y)) { if (!decorated || !buttonSet.pressNotify (x, y)) { state = SCropWinMove; action_x = x; @@ -269,123 +299,105 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { press_x = xpos; press_y = ypos; } - } - else if (button==1 && type==GDK_BUTTON_PRESS && state==SNormal && onArea (CropResize, x, y)) { + } else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropResize, x, y)) { state = SCropWinResize; action_x = x; action_y = y; press_x = width; press_y = height; - } - else if (button==1 && type==GDK_BUTTON_PRESS && state==SNormal && onArea (CropImage, x, y)) { + } else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropImage, x, y)) { if (onArea (CropTopLeft, x, y)) { state = SResizeTL; press_x = x; action_x = cropHandler.cropParams.x; press_y = y; action_y = cropHandler.cropParams.y; - } - else if (onArea (CropTopRight, x, y)) { + } else if (onArea (CropTopRight, x, y)) { state = SResizeTR; press_x = x; action_x = cropHandler.cropParams.w; press_y = y; action_y = cropHandler.cropParams.y; - } - else if (onArea (CropBottomLeft, x, y)) { + } else if (onArea (CropBottomLeft, x, y)) { state = SResizeBL; press_x = x; action_x = cropHandler.cropParams.x; press_y = y; action_y = cropHandler.cropParams.h; - } - else if (onArea (CropBottomRight, x, y)) { + } else if (onArea (CropBottomRight, x, y)) { state = SResizeBR; press_x = x; action_x = cropHandler.cropParams.w; press_y = y; action_y = cropHandler.cropParams.h; - } - else if (onArea (CropTop, x, y)) { + } else if (onArea (CropTop, x, y)) { state = SResizeH1; press_y = y; action_y = cropHandler.cropParams.y; - } - else if (onArea (CropBottom, x, y)) { + } else if (onArea (CropBottom, x, y)) { state = SResizeH2; press_y = y; action_y = cropHandler.cropParams.h; - } - else if (onArea (CropLeft, x, y)) { + } else if (onArea (CropLeft, x, y)) { state = SResizeW1; press_x = x; action_x = cropHandler.cropParams.x; - } - else if (onArea (CropRight, x, y)) { + } else if (onArea (CropRight, x, y)) { state = SResizeW2; press_x = x; action_x = cropHandler.cropParams.w; - } - else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) { + } else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) { state = SCropMove; press_x = x; press_y = y; action_x = cropHandler.cropParams.x; action_y = cropHandler.cropParams.y; - } - else if (iarea->getToolMode () == TMHand) { + } else if (iarea->getToolMode () == TMHand) { EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - if (button==1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType()==ET_OBJECTS && iarea->object>-1) ) { + if (button == 1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_OBJECTS && iarea->object > -1) ) { editSubscriber->button1Pressed(bstate); - state=SEditDrag; + state = SEditDrag; press_x = x; press_y = y; action_x = 0; action_y = 0; - } - else if (onArea (CropObserved, x, y)) { + } else if (onArea (CropObserved, x, y)) { state = SObservedMove; press_x = x; press_y = y; action_x = 0; action_y = 0; - } - else if (button==1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType()==ET_PIPETTE && (bstate & GDK_CONTROL_MASK)) ) { + } else if (button == 1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK)) ) { editSubscriber->button1Pressed(bstate); - state=SEditDrag; + state = SEditDrag; press_x = x; press_y = y; action_x = 0; action_y = 0; - } - else if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible + } else if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible state = SCropImgMove; press_x = x; press_y = y; action_x = 0; action_y = 0; } - } - else if (onArea (CropObserved, x, y)) { + } else if (onArea (CropObserved, x, y)) { state = SObservedMove; press_x = x; press_y = y; - } - else if (iarea->getToolMode () == TMStraighten) { + } else if (iarea->getToolMode () == TMStraighten) { state = SRotateSelecting; press_x = x; press_y = y; action_x = x; action_y = y; rot_deg = 0; - } - else if (iarea->getToolMode () == TMSpotWB) { - int spotx, spoty; - screenCoordToImage (x, y, spotx, spoty); - iarea->spotWBSelected (spotx, spoty); - } - else if (iarea->getToolMode () == TMCropSelect && cropgl) { + } else if (iarea->getToolMode () == TMSpotWB) { + int spotx, spoty; + screenCoordToImage (x, y, spotx, spoty); + iarea->spotWBSelected (spotx, spoty); + } else if (iarea->getToolMode () == TMCropSelect && cropgl) { state = SCropSelecting; screenCoordToImage (x, y, press_x, press_y); cropHandler.cropParams.enabled = true; @@ -395,61 +407,74 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { cropgl->cropInit (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); } } - if (button==3) { + + if (button == 3) { iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - if (editSubscriber && editSubscriber->getEditingType()==ET_PIPETTE) + + if (editSubscriber && editSubscriber->getEditingType() == ET_PIPETTE) { editSubscriber->mouseOver(0); + } + state = SNormal; iarea->setToolHand (); + if (pmhlistener) { - pmhlistener->toggleFreeze(); + pmhlistener->toggleFreeze(); } } + iarea->redraw (); updateCursor (x, y); } -void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) { +void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) +{ EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); bool needRedraw = false; - if (state==SCropWinResize) { - int newWidth = press_x + x - action_x; - int newHeight = press_y + y - action_y; - setSize(newWidth, newHeight); - if (decorated) { - options.detailWindowWidth = newWidth; - options.detailWindowHeight = newHeight; - } + + if (state == SCropWinResize) { + int newWidth = press_x + x - action_x; + int newHeight = press_y + y - action_y; + setSize(newWidth, newHeight); + + if (decorated) { + options.detailWindowWidth = newWidth; + options.detailWindowHeight = newHeight; + } + state = SNormal; - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropWindowSizeChanged (this); + } + needRedraw = true; - } - else if (state==SCropImgMove) { + } else if (state == SCropImgMove) { int cropX, cropY; cropHandler.getPosition (cropX, cropY); cropHandler.setPosition (cropX + action_x, cropY + action_y); cropHandler.getPosition (cropX, cropY); state = SNormal; - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropPositionChanged (this); + } + needRedraw = true; - } - else if (state==SRotateSelecting) { + } else if (state == SRotateSelecting) { iarea->straightenReady (rot_deg); iarea->setToolHand (); needRedraw = true; - } - else if (state==SObservedMove) { + } else if (state == SObservedMove) { observedCropWin->remoteMoveReady (); state = SNormal; needRedraw = true; - } - else if (state==SEditDrag) { + } else if (state == SEditDrag) { editSubscriber->button1Released(); + if (editSubscriber) { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); Coord imgPos; @@ -462,29 +487,32 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) { Coord cropPos; screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y); - if (editSubscriber->getEditingType()==ET_PIPETTE) { + + if (editSubscriber->getEditingType() == ET_PIPETTE) { iarea->object = onArea (CropImage, x, y) && !onArea (CropObserved, x, y) ? 1 : 0; + //iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0; if (iarea->object) { crop->getPipetteData(iarea->pipetteVal, cropPos.x, cropPos.y, iarea->getPipetteRectSize()); //printf("PipetteData: %.3f %.3f %.3f\n", iarea->pipetteVal[0], iarea->pipetteVal[1], iarea->pipetteVal[2]); - } - else { + } else { iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; } - } - else if (editSubscriber->getEditingType()==ET_OBJECTS) { - if (onArea (CropImage, x, y)) + } else if (editSubscriber->getEditingType() == ET_OBJECTS) { + if (onArea (CropImage, x, y)) { iarea->object = crop->getObjectID(cropPos); - else + } else { iarea->object = -1; + } } - if (editSubscriber->mouseOver(bstate)) + if (editSubscriber->mouseOver(bstate)) { iarea->redraw (); - } - else + } + } else { iarea->object = 0; + } + iarea->deltaImage.set(0, 0); iarea->deltaScreen.set(0, 0); iarea->deltaPrevImage.set(0, 0); @@ -492,15 +520,16 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) { state = SNormal; needRedraw = true; } - if (cropgl && (state==SCropSelecting || state==SResizeH1 || state==SResizeH2 || state==SResizeW1 || state==SResizeW2 || state==SResizeTL || state==SResizeTR || state==SResizeBL || state==SResizeBR || state==SCropMove)) - { + + if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) { cropgl->cropManipReady (); iarea->setToolHand (); needRedraw = true; } - if (decorated) + if (decorated) { buttonSet.releaseNotify (x, y); + } if (deleted) { iarea->flawnOverWindow = NULL; @@ -510,139 +539,138 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) { state = SNormal; iarea->grabFocus (NULL); - if (needRedraw) + + if (needRedraw) { iarea->redraw (); + } + updateCursor (x, y); } -void CropWindow::pointerMoved (int bstate, int x, int y) { +void CropWindow::pointerMoved (int bstate, int x, int y) +{ EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - if (state==SCropWinMove) { + if (state == SCropWinMove) { setPosition (press_x + x - action_x, press_y + y - action_y); iarea->redraw (); - } - else if (state==SCropWinResize) { + } else if (state == SCropWinResize) { setSize (press_x + x - action_x, press_y + y - action_y, true); - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropWindowSizeChanged (this); + } + iarea->redraw (); - } - else if (state==SCropImgMove) { + } else if (state == SCropImgMove) { // multiplier is the amplification factor ; disabled if the user selected "1" (no amplification) double factor = options.panAccelFactor == 1 ? 1.0 : options.panAccelFactor * zoomSteps[cropZoom].zoom; + // never move the preview slower than the cursor - if (factor < 1.0) + if (factor < 1.0) { factor = 1.0; + } + action_x = (press_x - x) / zoomSteps[cropZoom].zoom * factor; action_y = (press_y - y) / zoomSteps[cropZoom].zoom * factor; - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropPositionChanged (this); + } + iarea->redraw (); - } - else if (state==SRotateSelecting) { + } else if (state == SRotateSelecting) { action_x = x; action_y = y; iarea->redraw (); - } - else if (state==SNormal && iarea->getToolMode () == TMSpotWB) { + } else if (state == SNormal && iarea->getToolMode () == TMSpotWB) { action_x = x; action_y = y; iarea->redraw (); - } - else if (state==SResizeH1 && cropgl) { + } else if (state == SResizeH1 && cropgl) { int oy = cropHandler.cropParams.y; - cropHandler.cropParams.y = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.y = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropHandler.cropParams.h += oy - cropHandler.cropParams.y; cropgl->cropHeight1Resized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeH2 && cropgl) { - cropHandler.cropParams.h = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + } else if (state == SResizeH2 && cropgl) { + cropHandler.cropParams.h = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropgl->cropHeight2Resized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeW1 && cropgl) { + } else if (state == SResizeW1 && cropgl) { int ox = cropHandler.cropParams.x; - cropHandler.cropParams.x = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.x = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; cropHandler.cropParams.w += ox - cropHandler.cropParams.x; cropgl->cropWidth1Resized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeW2 && cropgl) { - cropHandler.cropParams.w = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; + } else if (state == SResizeW2 && cropgl) { + cropHandler.cropParams.w = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; cropgl->cropWidth2Resized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeTL && cropgl) { + } else if (state == SResizeTL && cropgl) { int ox = cropHandler.cropParams.x; - cropHandler.cropParams.x = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.x = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; cropHandler.cropParams.w += ox - cropHandler.cropParams.x; int oy = cropHandler.cropParams.y; - cropHandler.cropParams.y = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.y = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropHandler.cropParams.h += oy - cropHandler.cropParams.y; cropgl->cropTopLeftResized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeTR && cropgl) { - cropHandler.cropParams.w = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; + } else if (state == SResizeTR && cropgl) { + cropHandler.cropParams.w = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; int oy = cropHandler.cropParams.y; - cropHandler.cropParams.y = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.y = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropHandler.cropParams.h += oy - cropHandler.cropParams.y; cropgl->cropTopRightResized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeBL && cropgl) { + } else if (state == SResizeBL && cropgl) { int ox = cropHandler.cropParams.x; - cropHandler.cropParams.x = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.x = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; cropHandler.cropParams.w += ox - cropHandler.cropParams.x; - cropHandler.cropParams.h = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.h = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropgl->cropBottomLeftResized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SResizeBR && cropgl) { - cropHandler.cropParams.w = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; - cropHandler.cropParams.h = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + } else if (state == SResizeBR && cropgl) { + cropHandler.cropParams.w = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.h = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropgl->cropBottomRightResized (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SCropMove && cropgl) { - cropHandler.cropParams.x = action_x + (x-press_x) / zoomSteps[cropZoom].zoom; - cropHandler.cropParams.y = action_y + (y-press_y) / zoomSteps[cropZoom].zoom; + } else if (state == SCropMove && cropgl) { + cropHandler.cropParams.x = action_x + (x - press_x) / zoomSteps[cropZoom].zoom; + cropHandler.cropParams.y = action_y + (y - press_y) / zoomSteps[cropZoom].zoom; cropgl->cropMoved (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h); iarea->redraw (); - } - else if (state==SCropSelecting && cropgl) { + } else if (state == SCropSelecting && cropgl) { screenCoordToImage (x, y, action_x, action_y); int cx1 = press_x, cy1 = press_y; int cx2 = action_x, cy2 = action_y; cropgl->cropResized (cx1, cy1, cx2, cy2); + if (cx2 > cx1) { cropHandler.cropParams.x = cx1; cropHandler.cropParams.w = cx2 - cx1 + 1; - } - else { + } else { cropHandler.cropParams.x = cx2; cropHandler.cropParams.w = cx1 - cx2 + 1; } + if (cy2 > cy1) { cropHandler.cropParams.y = cy1; cropHandler.cropParams.h = cy2 - cy1 + 1; - } - else { + } else { cropHandler.cropParams.y = cy2; cropHandler.cropParams.h = cy1 - cy2 + 1; } + iarea->redraw (); - } - else if (state==SObservedMove) { - observedCropWin->remoteMove ((x - press_x)/zoomSteps[cropZoom].zoom, (y - press_y)/zoomSteps[cropZoom].zoom); + } else if (state == SObservedMove) { + observedCropWin->remoteMove ((x - press_x) / zoomSteps[cropZoom].zoom, (y - press_y) / zoomSteps[cropZoom].zoom); iarea->redraw (); - } - else if (editSubscriber) { + } else if (editSubscriber) { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); - if (state==SNormal) { + + if (state == SNormal) { Coord imgPos; action_x = x; action_y = y; @@ -653,77 +681,85 @@ void CropWindow::pointerMoved (int bstate, int x, int y) { Coord cropPos; screenCoordToCropBuffer(x, y, cropPos.x, cropPos.y); - if (editSubscriber->getEditingType()==ET_PIPETTE) { + + if (editSubscriber->getEditingType() == ET_PIPETTE) { iarea->object = onArea (CropImage, x, y) && !onArea (CropObserved, x, y) ? 1 : 0; + //iarea->object = cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) ? 1 : 0; if (iarea->object) { crop->getPipetteData(iarea->pipetteVal, cropPos.x, cropPos.y, iarea->getPipetteRectSize()); //printf("PipetteData: %.3f %.3f %.3f\n", iarea->pipetteVal[0], iarea->pipetteVal[1], iarea->pipetteVal[2]); - } - else { + } else { iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; } - } - else if (editSubscriber->getEditingType()==ET_OBJECTS) { - if (onArea (CropImage, x, y)) + } else if (editSubscriber->getEditingType() == ET_OBJECTS) { + if (onArea (CropImage, x, y)) { iarea->object = crop->getObjectID(cropPos); - else + } else { iarea->object = -1; + } } - if (editSubscriber->mouseOver(bstate)) + if (editSubscriber->mouseOver(bstate)) { iarea->redraw (); - } - else if (state==SEditDrag) { + } + } else if (state == SEditDrag) { Coord currPos; action_x = x; action_y = y; - Coord oldPosImage = iarea->posImage+iarea->deltaImage; + Coord oldPosImage = iarea->posImage + iarea->deltaImage; //printf(">>> IMG / ImgPrev(%d x %d) = (%d x %d) + (%d x %d)\n", oldPosImage.x, oldPosImage.y, iarea->posImage.x, iarea->posImage.y, iarea->deltaImage.x, iarea->deltaImage.y); screenCoordToImage (x, y, currPos.x, currPos.y); iarea->deltaImage = currPos - iarea->posImage; iarea->deltaPrevImage = currPos - oldPosImage; //printf(" action_ & xy (%d x %d) -> (%d x %d) = (%d x %d) + (%d x %d) / deltaPrev(%d x %d)\n", action_x, action_y, currPos.x, currPos.y, iarea->posImage.x, iarea->posImage.y, iarea->deltaImage.x, iarea->deltaImage.y, iarea->deltaPrevImage.x, iarea->deltaPrevImage.y); - Coord oldPosScreen = iarea->posScreen+iarea->deltaScreen; + Coord oldPosScreen = iarea->posScreen + iarea->deltaScreen; //printf(">>> SCR / ScrPrev(%d x %d) = (%d x %d) + (%d x %d)\n", oldPosScreen.x, oldPosScreen.y, iarea->posScreen.x, iarea->posScreen.y, iarea->deltaScreen.x, iarea->deltaScreen.y); currPos.set(x, y); iarea->deltaScreen = currPos - iarea->posScreen; iarea->deltaPrevScreen = currPos - oldPosScreen; //printf(" action_ & xy (%d x %d) -> (%d x %d) = (%d x %d) + (%d x %d) / deltaPrev(%d x %d)\n", action_x, action_y, currPos.x, currPos.y, iarea->posScreen.x, iarea->posScreen.y, iarea->deltaScreen.x, iarea->deltaScreen.y, iarea->deltaPrevScreen.x, iarea->deltaPrevScreen.y); - if (editSubscriber->drag(bstate)) + if (editSubscriber->drag(bstate)) { iarea->redraw (); + } } } + updateCursor (x, y); - + bool oRA = onArea (CropResize, x, y); - if (oRA!=onResizeArea) { + + if (oRA != onResizeArea) { onResizeArea = oRA; iarea->redraw (); } - if (decorated) + if (decorated) { buttonSet.motionNotify (x, y); + } if (pmlistener) { int mx, my; screenCoordToImage (x, y, mx, my); + if (!onArea (CropImage, x, y) || !cropHandler.cropPixbuf) { - cropHandler.getFullImageSize(mx,my); - // pmlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1); - // if (pmhlistener) pmhlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1); - /* Glib::ustring outputProfile; - outputProfile =cropHandler.colorParams.output ; - printf("Using \"%s\" output\n", outputProfile.c_str()); - if(outputProfile=="RT_sRGB") printf("OK SRGB2"); - */ - pmlistener->pointerMoved (false, cropHandler.colorParams.output,cropHandler.colorParams.working, mx, my, -1, -1, -1); - if (pmhlistener) pmhlistener->pointerMoved (false, cropHandler.colorParams.output,cropHandler.colorParams.working, mx, my, -1, -1, -1); - - } - else { + cropHandler.getFullImageSize(mx, my); + // pmlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1); + // if (pmhlistener) pmhlistener->pointerMoved (false, cropHandler.colorParams.working, mx, my, -1, -1, -1); + /* Glib::ustring outputProfile; + outputProfile =cropHandler.colorParams.output ; + printf("Using \"%s\" output\n", outputProfile.c_str()); + if(outputProfile=="RT_sRGB") printf("OK SRGB2"); + */ + pmlistener->pointerMoved (false, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, -1, -1, -1); + + if (pmhlistener) { + pmhlistener->pointerMoved (false, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, -1, -1, -1); + } + + } else { /*MyMutex::MyLock lock(cropHandler.cimg); int vx = x - xpos - imgX; @@ -742,245 +778,279 @@ void CropWindow::pointerMoved (int bstate, int x, int y) { // pmlistener->pointerMoved (true, mx, my, pix[0], pix[1], pix[2]); int imwidth = cropHandler.cropPixbuf->get_width(); int imheight = cropHandler.cropPixbuf->get_height(); - guint8* pix = cropHandler.cropPixbuftrue->get_pixels() + vy*cropHandler.cropPixbuf->get_rowstride() + vx*3; + guint8* pix = cropHandler.cropPixbuftrue->get_pixels() + vy * cropHandler.cropPixbuf->get_rowstride() + vx * 3; + if (vx < imwidth && vy < imheight) { - // pmlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); - pmlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working,mx, my, pix[0], pix[1], pix[2]); + // pmlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); + pmlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); + if (pmhlistener) - // pmhlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); - pmhlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working,mx, my, pix[0], pix[1], pix[2]); + // pmhlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); + { + pmhlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]); + } } + cropHandler.cimg.unlock (); } } } -bool CropWindow::onArea (CursorArea a, int x, int y) { +bool CropWindow::onArea (CursorArea a, int x, int y) +{ int CROPRESIZEBORDER = 6 / zoomSteps[cropZoom].zoom; int x1, y1, w, h; + switch (a) { - case CropWinButtons: - return decorated && buttonSet.inside (x, y); - case CropToolBar: - return x>xpos && y>ypos && x=xpos+imgX && y>=ypos+imgY && x=xpos+imgAreaX && y>=ypos+imgAreaY && x=xpos+imgX && y>=ypos+imgY && x=cropHandler.cropParams.y-CROPRESIZEBORDER && - y1<=cropHandler.cropParams.y+CROPRESIZEBORDER && - y>=ypos+imgY && - x1>=cropHandler.cropParams.x-CROPRESIZEBORDER && - x1<=cropHandler.cropParams.x+CROPRESIZEBORDER && - x>=xpos+imgX; - case CropTopRight: - screenCoordToImage (x, y, x1, y1); - return cropHandler.cropParams.enabled && - y1>=cropHandler.cropParams.y-CROPRESIZEBORDER && - y1<=cropHandler.cropParams.y+CROPRESIZEBORDER && - y>=ypos+imgY && - x1>=cropHandler.cropParams.x+cropHandler.cropParams.w-1-CROPRESIZEBORDER && - x1<=cropHandler.cropParams.x+cropHandler.cropParams.w-1+CROPRESIZEBORDER && - x=cropHandler.cropParams.y+cropHandler.cropParams.h-1-CROPRESIZEBORDER && - y1<=cropHandler.cropParams.y+cropHandler.cropParams.h-1+CROPRESIZEBORDER && - y=cropHandler.cropParams.x-CROPRESIZEBORDER && - x1<=cropHandler.cropParams.x+CROPRESIZEBORDER && - x>=xpos+imgX; - case CropBottomRight: - screenCoordToImage (x, y, x1, y1); - return cropHandler.cropParams.enabled && - y1>=cropHandler.cropParams.y+cropHandler.cropParams.h-1-CROPRESIZEBORDER && - y1<=cropHandler.cropParams.y+cropHandler.cropParams.h-1+CROPRESIZEBORDER && - y=cropHandler.cropParams.x+cropHandler.cropParams.w-1-CROPRESIZEBORDER && - x1<=cropHandler.cropParams.x+cropHandler.cropParams.w-1+CROPRESIZEBORDER && - xcropHandler.cropParams.x+CROPRESIZEBORDER && - x1cropHandler.cropParams.y-CROPRESIZEBORDER && - y1=ypos+imgY; - case CropBottom: - screenCoordToImage (x, y, x1, y1); - return cropHandler.cropParams.enabled && - x1>cropHandler.cropParams.x+CROPRESIZEBORDER && - x1cropHandler.cropParams.y+cropHandler.cropParams.h-1-CROPRESIZEBORDER && - y1cropHandler.cropParams.y+CROPRESIZEBORDER && - y1cropHandler.cropParams.x-CROPRESIZEBORDER && - x1=xpos+imgX; - case CropRight: - screenCoordToImage (x, y, x1, y1); - return cropHandler.cropParams.enabled && - y1>cropHandler.cropParams.y+CROPRESIZEBORDER && - y1cropHandler.cropParams.x+cropHandler.cropParams.w-1-CROPRESIZEBORDER && - x1cropHandler.cropParams.y && - y1cropHandler.cropParams.x && - x1=xpos+width-16 && y>=ypos+height-16 && xx1-6 && y>y1-6 && xx1+2 && y>y1+2 && x xpos && y > ypos && x < xpos + width - 1 && y < ypos + imgAreaY; + + case CropImage: + return x >= xpos + imgX && y >= ypos + imgY && x < xpos + imgX + imgW && y < ypos + imgY + imgH; + + case CropBorder: + return + (x >= xpos + imgAreaX && y >= ypos + imgAreaY && x < xpos + imgAreaX + imgAreaW && y < ypos + imgAreaY + imgAreaH) && + !(x >= xpos + imgX && y >= ypos + imgY && x < xpos + imgX + imgW && y < ypos + imgY + imgH); + + case CropTopLeft: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 >= cropHandler.cropParams.y - CROPRESIZEBORDER && + y1 <= cropHandler.cropParams.y + CROPRESIZEBORDER && + y >= ypos + imgY && + x1 >= cropHandler.cropParams.x - CROPRESIZEBORDER && + x1 <= cropHandler.cropParams.x + CROPRESIZEBORDER && + x >= xpos + imgX; + + case CropTopRight: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 >= cropHandler.cropParams.y - CROPRESIZEBORDER && + y1 <= cropHandler.cropParams.y + CROPRESIZEBORDER && + y >= ypos + imgY && + x1 >= cropHandler.cropParams.x + cropHandler.cropParams.w - 1 - CROPRESIZEBORDER && + x1 <= cropHandler.cropParams.x + cropHandler.cropParams.w - 1 + CROPRESIZEBORDER && + x < xpos + imgX + imgW; + + case CropBottomLeft: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 >= cropHandler.cropParams.y + cropHandler.cropParams.h - 1 - CROPRESIZEBORDER && + y1 <= cropHandler.cropParams.y + cropHandler.cropParams.h - 1 + CROPRESIZEBORDER && + y < ypos + imgY + imgH && + x1 >= cropHandler.cropParams.x - CROPRESIZEBORDER && + x1 <= cropHandler.cropParams.x + CROPRESIZEBORDER && + x >= xpos + imgX; + + case CropBottomRight: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 >= cropHandler.cropParams.y + cropHandler.cropParams.h - 1 - CROPRESIZEBORDER && + y1 <= cropHandler.cropParams.y + cropHandler.cropParams.h - 1 + CROPRESIZEBORDER && + y < ypos + imgY + imgH && + x1 >= cropHandler.cropParams.x + cropHandler.cropParams.w - 1 - CROPRESIZEBORDER && + x1 <= cropHandler.cropParams.x + cropHandler.cropParams.w - 1 + CROPRESIZEBORDER && + x < xpos + imgX + imgW; + + case CropTop: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + x1 > cropHandler.cropParams.x + CROPRESIZEBORDER && + x1 < cropHandler.cropParams.x + cropHandler.cropParams.w - 1 - CROPRESIZEBORDER && + y1 > cropHandler.cropParams.y - CROPRESIZEBORDER && + y1 < cropHandler.cropParams.y + CROPRESIZEBORDER && + y >= ypos + imgY; + + case CropBottom: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + x1 > cropHandler.cropParams.x + CROPRESIZEBORDER && + x1 < cropHandler.cropParams.x + cropHandler.cropParams.w - 1 - CROPRESIZEBORDER && + y1 > cropHandler.cropParams.y + cropHandler.cropParams.h - 1 - CROPRESIZEBORDER && + y1 < cropHandler.cropParams.y + cropHandler.cropParams.h - 1 + CROPRESIZEBORDER && + y < ypos + imgY + imgH; + + case CropLeft: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 > cropHandler.cropParams.y + CROPRESIZEBORDER && + y1 < cropHandler.cropParams.y + cropHandler.cropParams.h - 1 - CROPRESIZEBORDER && + x1 > cropHandler.cropParams.x - CROPRESIZEBORDER && + x1 < cropHandler.cropParams.x + CROPRESIZEBORDER && + x >= xpos + imgX; + + case CropRight: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 > cropHandler.cropParams.y + CROPRESIZEBORDER && + y1 < cropHandler.cropParams.y + cropHandler.cropParams.h - 1 - CROPRESIZEBORDER && + x1 > cropHandler.cropParams.x + cropHandler.cropParams.w - 1 - CROPRESIZEBORDER && + x1 < cropHandler.cropParams.x + cropHandler.cropParams.w - 1 + CROPRESIZEBORDER && + x < xpos + imgX + imgW; + + case CropInside: + screenCoordToImage (x, y, x1, y1); + return cropHandler.cropParams.enabled && + y1 > cropHandler.cropParams.y && + y1 < cropHandler.cropParams.y + cropHandler.cropParams.h - 1 && + x1 > cropHandler.cropParams.x && + x1 < cropHandler.cropParams.x + cropHandler.cropParams.w - 1; + + case CropResize: + return decorated && x >= xpos + width - 16 && y >= ypos + height - 16 && x < xpos + width && y < ypos + height; + + case CropObserved: + if (!observedCropWin) { + return false; + } + + getObservedFrameArea (x1, y1, w, h); + return x > x1 - 6 && y > y1 - 6 && x < x1 + w - 1 + 6 && y < y1 + h - 1 + 6 && + !(x > x1 + 2 && y > y1 + 2 && x < x1 + w - 1 - 2 && y < y1 + h - 1 - 2); } + return false; } -void CropWindow::updateCursor (int x, int y) { +void CropWindow::updateCursor (int x, int y) +{ EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); ToolMode tm = iarea->getToolMode (); - if (state==SNormal) { - if (onArea (CropWinButtons, x, y)) + if (state == SNormal) { + if (onArea (CropWinButtons, x, y)) { cursorManager.setCursor (iarea->get_window(), CSArrow); - else if (onArea (CropToolBar, x, y)) + } else if (onArea (CropToolBar, x, y)) { cursorManager.setCursor (iarea->get_window(), CSMove); - else if (onArea (CropResize, x, y)) + } else if (onArea (CropResize, x, y)) { cursorManager.setCursor (iarea->get_window(), CSResizeDiagonal); - else if (tm==TMHand && (onArea (CropTopLeft, x, y))) + } else if (tm == TMHand && (onArea (CropTopLeft, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeTopLeft); - else if (tm==TMHand && (onArea (CropTopRight, x, y))) + } else if (tm == TMHand && (onArea (CropTopRight, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeTopRight); - else if (tm==TMHand && (onArea (CropBottomLeft, x, y))) + } else if (tm == TMHand && (onArea (CropBottomLeft, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeBottomLeft); - else if (tm==TMHand && (onArea (CropBottomRight, x, y))) + } else if (tm == TMHand && (onArea (CropBottomRight, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeBottomRight); - else if (tm==TMHand && (onArea (CropTop, x, y) || onArea (CropBottom, x, y))) + } else if (tm == TMHand && (onArea (CropTop, x, y) || onArea (CropBottom, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeHeight); - else if (tm==TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y))) + } else if (tm == TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeWidth); - else if (onArea (CropImage, x, y)) { + } else if (onArea (CropImage, x, y)) { int objectID = -1; + if (editSubscriber) { Coord cropPos; screenCoordToCropBuffer(iarea->posScreen.x, iarea->posScreen.y, cropPos.x, cropPos.y); objectID = static_cast(cropHandler.getCrop())->getObjectID(cropPos); } + if (objectID > -1) { cursorManager.setCursor (iarea->get_window(), editSubscriber->getCursor(objectID)); - } - else if (tm==TMHand) { - if (onArea (CropObserved, x, y)) + } else if (tm == TMHand) { + if (onArea (CropObserved, x, y)) { cursorManager.setCursor (iarea->get_window(), CSMove); - else + } else { cursorManager.setCursor (iarea->get_window(), CSOpenHand); - } - else if (tm==TMSpotWB) + } + } else if (tm == TMSpotWB) { cursorManager.setCursor (iarea->get_window(), CSSpotWB); - else if (tm==TMCropSelect) + } else if (tm == TMCropSelect) { cursorManager.setCursor (iarea->get_window(), CSCropSelect); - else if (tm==TMStraighten) + } else if (tm == TMStraighten) { cursorManager.setCursor (iarea->get_window(), CSStraighten); - } - else + } + } else { cursorManager.setCursor (iarea->get_window(), CSArrow); - } - else if (state==SCropSelecting) + } + } else if (state == SCropSelecting) { cursorManager.setCursor (iarea->get_window(), CSCropSelect); - else if (state==SRotateSelecting) + } else if (state == SRotateSelecting) { cursorManager.setCursor (iarea->get_window(), CSStraighten); - else if (state==SCropMove || state==SCropWinMove || state==SObservedMove) + } else if (state == SCropMove || state == SCropWinMove || state == SObservedMove) { cursorManager.setCursor (iarea->get_window(), CSMove); - else if (state==SHandMove || state==SCropImgMove) + } else if (state == SHandMove || state == SCropImgMove) { cursorManager.setCursor (iarea->get_window(), CSClosedHand); - else if (state==SResizeW1 || state==SResizeW2) + } else if (state == SResizeW1 || state == SResizeW2) { cursorManager.setCursor (iarea->get_window(), CSResizeWidth); - else if (state==SResizeH1 || state==SResizeH2) + } else if (state == SResizeH1 || state == SResizeH2) { cursorManager.setCursor (iarea->get_window(), CSResizeHeight); - else if (state==SResizeTL) + } else if (state == SResizeTL) { cursorManager.setCursor (iarea->get_window(), CSResizeTopLeft); - else if (state==SResizeTR) + } else if (state == SResizeTR) { cursorManager.setCursor (iarea->get_window(), CSResizeTopRight); - else if (state==SResizeBL) + } else if (state == SResizeBL) { cursorManager.setCursor (iarea->get_window(), CSResizeBottomLeft); - else if (state==SResizeBR) + } else if (state == SResizeBR) { cursorManager.setCursor (iarea->get_window(), CSResizeBottomRight); - else if (state==SCropWinResize) + } else if (state == SCropWinResize) { cursorManager.setCursor (iarea->get_window(), CSResizeDiagonal); + } } -void CropWindow::expose (Cairo::RefPtr cr) { +void CropWindow::expose (Cairo::RefPtr cr) +{ MyMutex::MyLock lock(cropHandler.cimg); - if (decorated) + if (decorated) { drawDecoration (cr); + } int x = xpos, y = ypos, h = height, w = width; - + // draw the background backColor = iarea->previewModePanel->GetbackColor(); options.bgcolor = backColor; - if (backColor==0) { + + if (backColor == 0) { Gdk::Color cback = iarea->get_style()->get_bg(Gtk::STATE_NORMAL); cr->set_source_rgb (cback.get_red_p(), cback.get_green_p(), cback.get_blue_p()); + } else if (backColor == 1) { + cr->set_source_rgb (0, 0, 0); + } else if (backColor == 2) { + cr->set_source_rgb (1, 1, 1); } - else if (backColor==1) - cr->set_source_rgb (0,0,0); - else if (backColor==2) - cr->set_source_rgb (1,1,1); cr->set_line_width (0.); - cr->rectangle (x+imgAreaX, y+imgAreaY, imgAreaW, imgAreaH); + cr->rectangle (x + imgAreaX, y + imgAreaY, imgAreaW, imgAreaH); cr->stroke_preserve (); cr->fill (); // draw image - if (state==SCropImgMove || state==SCropWinResize) { + if (state == SCropImgMove || state == SCropWinResize) { // draw a rough image int cropX, cropY; cropHandler.getPosition (cropX, cropY); - if (state==SCropImgMove) { + + if (state == SCropImgMove) { cropX += action_x; cropY += action_y; } + Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); + if (rough) { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x+imgAreaX+(imgAreaW-rough->get_width())/2, y+imgAreaY+(imgAreaH-rough->get_height())/2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); // if (cropHandler.cropParams.enabled) // drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); } - if (observedCropWin) + + if (observedCropWin) { drawObservedFrame (cr); - } - else { + } + } else { if (cropHandler.cropPixbuf) { imgW = cropHandler.cropPixbuf->get_width (); imgH = cropHandler.cropPixbuf->get_height (); - imgX = imgAreaX + (imgAreaW-imgW)/2; - imgY = imgAreaY + (imgAreaH-imgH)/2; + imgX = imgAreaX + (imgAreaW - imgW) / 2; + imgY = imgAreaY + (imgAreaH - imgH) / 2; exposeVersion++; bool showcs = iarea->indClippedPanel->showClippedShadows(); @@ -993,11 +1063,14 @@ void CropWindow::expose (Cairo::RefPtr cr) { // While the Right-side ALT is pressed, auto-enable highlight and shadow clipping indicators // TODO: Add linux/MacOS specific functions for alternative - #ifdef WIN32 - if (GetKeyState(VK_RMENU)<0) { - showcs=true; showch=true; +#ifdef WIN32 + + if (GetKeyState(VK_RMENU) < 0) { + showcs = true; + showch = true; } - #endif + +#endif if (showcs || showch || showR || showG || showB || showL || showFocusMask) { Glib::RefPtr tmp = cropHandler.cropPixbuf->copy (); @@ -1007,315 +1080,395 @@ void CropWindow::expose (Cairo::RefPtr cr) { const int pixRowStride = tmp->get_rowstride (); const int pixWSRowStride = cropHandler.cropPixbuftrue->get_rowstride (); - const int bHeight = tmp->get_height(); - const int bWidth = tmp->get_width(); + const int bHeight = tmp->get_height(); + const int bWidth = tmp->get_width(); if (showFocusMask) { // modulate preview to display focus mask - const int blur_radius2 = 1; // radius of small kernel. 1 => 3x3 kernel - const int blur_dim2 = 2*blur_radius2+1; // dimension of small kernel - const int blur_radius = (blur_dim2*blur_dim2)/2; // radius of big kernel - const float kernel_size = SQR(2.f*blur_radius+1.f); // count of pixels in the big blur kernel - const float rkernel_size = 1.0f/kernel_size; // reciprocal of kernel_size to avoid divisions - const float kernel_size2 = SQR(2.f*blur_radius2+1.f); // count of pixels in the small blur kernel - const float rkernel_size2 = 1.0f/kernel_size2; // reciprocal of kernel_size to avoid divisions + const int blur_radius2 = 1; // radius of small kernel. 1 => 3x3 kernel + const int blur_dim2 = 2 * blur_radius2 + 1; // dimension of small kernel + const int blur_radius = (blur_dim2 * blur_dim2) / 2; // radius of big kernel + const float kernel_size = SQR(2.f * blur_radius + 1.f); // count of pixels in the big blur kernel + const float rkernel_size = 1.0f / kernel_size; // reciprocal of kernel_size to avoid divisions + const float kernel_size2 = SQR(2.f * blur_radius2 + 1.f); // count of pixels in the small blur kernel + const float rkernel_size2 = 1.0f / kernel_size2; // reciprocal of kernel_size to avoid divisions - // aloocate buffer for precalculated Luminance - float* tmpL = (float*)malloc(bHeight * bWidth * sizeof(float) ); - // aloocate buffers for sums and sums of squares of small kernel - float* tmpLsum = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); - float* tmpLsumSq = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); - float* tmpstdDev2 = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); - float maxstdDev_L2 = 0.f; + // aloocate buffer for precalculated Luminance + float* tmpL = (float*)malloc(bHeight * bWidth * sizeof(float) ); + // aloocate buffers for sums and sums of squares of small kernel + float* tmpLsum = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); + float* tmpLsumSq = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); + float* tmpstdDev2 = (float*)malloc((bHeight) * (bWidth) * sizeof(float) ); + float maxstdDev_L2 = 0.f; #ifdef _OPENMP -#pragma omp parallel + #pragma omp parallel #endif -{ + { #ifdef _OPENMP -#pragma omp for + #pragma omp for #endif - // precalculate Luminance - for(int i=0;i maxthrstdDev_L2) - maxthrstdDev_L2 = stdDev_L2; - tmpstdDev2[i*bWidth+j] = stdDev_L2; - } - } -#pragma omp critical -{ - if(maxthrstdDev_L2 > maxstdDev_L2) - maxstdDev_L2 = maxthrstdDev_L2; -} -} - const float focus_thresh = 80.f; - maxstdDev_L2 = std::min(maxstdDev_L2,focus_thresh); - const float focus_threshby10 = focus_thresh / 10.f; - #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) - #endif - for (int i=blur_radius+1; i maxthrstdDev_L2) { + maxthrstdDev_L2 = stdDev_L2; + } + + tmpstdDev2[i * bWidth + j] = stdDev_L2; + } + } + + #pragma omp critical + { + if(maxthrstdDev_L2 > maxstdDev_L2) { + maxstdDev_L2 = maxthrstdDev_L2; + } + } + } + + const float focus_thresh = 80.f; + maxstdDev_L2 = std::min(maxstdDev_L2, focus_thresh); + const float focus_threshby10 = focus_thresh / 10.f; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int i = blur_radius + 1; i < bHeight - blur_radius; i++) { + guint8* curr = pix + i * pixRowStride + 3 * (blur_radius + 1); + guint8* currWs = pixWrkSpace + i * pixWSRowStride + 3 * (blur_radius + 1); + + for (int j = blur_radius + 1; j < bWidth - blur_radius; j++) { + + //************* + // Copyright (c) 2011 Michael Ezra michael@michaelezra.com + // determine if pixel is in the sharp area of the image using + // standard deviation analysis on two different scales + //float focus_thresh2; + //float opacity = 0.9;//TODO: implement opacity + //TODO: evaluate effects of altering sampling frequency - //TODO: dynamically determine appropriate values based on image analysis + //TODO: dynamically determine appropriate values based on image analysis - // calculate average in +-blur_radius pixels area around the current pixel - // speed up: calculate sum of squares in the same loops + // calculate average in +-blur_radius pixels area around the current pixel + // speed up: calculate sum of squares in the same loops - float sum_L = 0.f; - float sumsq_L = 0.f; - // use precalculated values of small kernel to reduce number of iterations - for (int kh=-blur_radius+blur_radius2; kh<=blur_radius-blur_radius2;kh+=blur_dim2){ - float* currLsum = &tmpLsum[(i+kh)*bWidth+j-blur_radius+1]; - float* currLsumSqu = &tmpLsumSq[(i+kh)*bWidth+j-blur_radius+1]; - for (int k=-blur_radius+blur_radius2; k<=blur_radius-blur_radius2;k+=blur_dim2,currLsum+=blur_dim2,currLsumSqu+=blur_dim2){ - sum_L += *currLsum; - sumsq_L += *currLsumSqu; - } - } - float sum_L2 = tmpLsum[i*bWidth+j]; - float sumsq_L2 = tmpLsumSq[i*bWidth+j]; - //************* - // averages - // Optimized formulas to avoid divisions - float stdDev_L = rkernel_size * sqrtf(sumsq_L * kernel_size - sum_L * sum_L); - float stdDev_L2 = tmpstdDev2[i*bWidth+j]; -// float stdDev_L2 = rkernel_size2 * sqrtf(sumsq_L2 * kernel_size2 - sum_L2 * sum_L2); + float sum_L = 0.f; + float sumsq_L = 0.f; - //TODO: try to normalize by average L of the entire (preview) image + // use precalculated values of small kernel to reduce number of iterations + for (int kh = -blur_radius + blur_radius2; kh <= blur_radius - blur_radius2; kh += blur_dim2) { + float* currLsum = &tmpLsum[(i + kh) * bWidth + j - blur_radius + 1]; + float* currLsumSqu = &tmpLsumSq[(i + kh) * bWidth + j - blur_radius + 1]; - //detection method 1: detect focus in features - //there is no strict condition between stdDev_L and stdDev_L2 themselves - /* if (stdDev_L2>focus_thresh2 - && (stdDev_L focus_thresh2 + && (stdDev_L = stdDev_L2 //TODO: could vary this to bypass noise better + && stdDev_L2 > stdDev_L //this is the key to select fine detail within lower contrast on larger scale + && stdDev_L > focus_threshby10 //options.highlightThreshold + ) { + // transpareny depends on sdtDev_L2 and maxstdDev_L2 + float transparency = 1.f - std::min(stdDev_L2 / maxstdDev_L2, 1.0f) ; + // first row of circle + guint8* currtmp = &curr[0] + (-3 * pixRowStride); + guint8* currtmpWS = &currWs[0] + (-3 * pixWSRowStride); + + for(int jj = -3; jj <= 3; jj += 3) { + guint8* currtmpl = currtmp + jj; + guint8* currtmpWSl = currtmpWS + jj; + //transparent green + currtmpl[0] = transparency * currtmpWSl[0]; + currtmpl[1] = transparency * currtmpWSl[1] + (1.f - transparency) * 255.f; + currtmpl[2] = transparency * currtmpWSl[2]; + } + + // second row of circle + currtmp = &curr[0] + (-2 * pixRowStride); + currtmpWS = &currWs[0] + (-2 * pixWSRowStride); + + for(int jj = -6; jj <= 6; jj += 3) { + guint8* currtmpl = currtmp + jj; + guint8* currtmpWSl = currtmpWS + jj; + //transparent green + currtmpl[0] = transparency * currtmpWSl[0]; + currtmpl[1] = transparency * currtmpWSl[1] + (1.f - transparency) * 255.f; + currtmpl[2] = transparency * currtmpWSl[2]; + } + + // three middle row of circle + for(int ii = -1; ii <= 1; ii++) { + currtmp = &curr[0] + (ii * pixRowStride); + currtmpWS = &currWs[0] + (ii * pixWSRowStride); + + for(int jj = -9; jj <= 9; jj += 3) { + guint8* currtmpl = currtmp + jj; + guint8* currtmpWSl = currtmpWS + jj; + //transparent green + currtmpl[0] = transparency * currtmpWSl[0]; + currtmpl[1] = transparency * currtmpWSl[1] + (1.f - transparency) * 255.f; + currtmpl[2] = transparency * currtmpWSl[2]; + } + } + + // second last row of circle + currtmp = &curr[0] + (2 * pixRowStride); + currtmpWS = &currWs[0] + (2 * pixWSRowStride); + + for(int jj = -6; jj <= 6; jj += 3) { + guint8* currtmpl = currtmp + jj; + guint8* currtmpWSl = currtmpWS + jj; + //transparent green + currtmpl[0] = transparency * currtmpWSl[0]; + currtmpl[1] = transparency * currtmpWSl[1] + (1.f - transparency) * 255.f; + currtmpl[2] = transparency * currtmpWSl[2]; + } + + // last row of circle + currtmp = &curr[0] + (3 * pixRowStride); + currtmpWS = &currWs[0] + (3 * pixWSRowStride); + + for(int jj = -3; jj <= 3; jj += 3) { + guint8* currtmpl = currtmp + jj; + guint8* currtmpWSl = currtmpWS + jj; + //transparent green + currtmpl[0] = transparency * currtmpWSl[0]; + currtmpl[1] = transparency * currtmpWSl[1] + (1.f - transparency) * 255.f; + currtmpl[2] = transparency * currtmpWSl[2]; + } + } + + curr += 3; + currWs += 3; + } + } + + free(tmpL); + free(tmpLsum); + free(tmpLsumSq); + free(tmpstdDev2); - //detection method 2: detect focus in texture - // key point is std deviation on lower scale is higher than for the larger scale - // plus some boundary conditions - if (focus_thresh >= stdDev_L2 //TODO: could vary this to bypass noise better - && stdDev_L2 > stdDev_L //this is the key to select fine detail within lower contrast on larger scale - && stdDev_L > focus_threshby10 //options.highlightThreshold - ){ - // transpareny depends on sdtDev_L2 and maxstdDev_L2 - float transparency = 1.f - std::min(stdDev_L2 / maxstdDev_L2, 1.0f) ; - // first row of circle - guint8* currtmp = &curr[0] + (-3*pixRowStride); - guint8* currtmpWS = &currWs[0] + (-3*pixWSRowStride); - for(int jj=-3;jj<=3;jj+=3) { - guint8* currtmpl=currtmp+jj; - guint8* currtmpWSl=currtmpWS+jj; - //transparent green - currtmpl[0] = transparency * currtmpWSl[0]; - currtmpl[1] = transparency * currtmpWSl[1] + (1.f-transparency)*255.f; - currtmpl[2] = transparency * currtmpWSl[2]; - } - // second row of circle - currtmp = &curr[0] + (-2*pixRowStride); - currtmpWS = &currWs[0] + (-2*pixWSRowStride); - for(int jj=-6;jj<=6;jj+=3) { - guint8* currtmpl=currtmp+jj; - guint8* currtmpWSl=currtmpWS+jj; - //transparent green - currtmpl[0] = transparency * currtmpWSl[0]; - currtmpl[1] = transparency * currtmpWSl[1] + (1.f-transparency)*255.f; - currtmpl[2] = transparency * currtmpWSl[2]; - } - // three middle row of circle - for(int ii=-1;ii<=1;ii++) { - currtmp = &curr[0] + (ii*pixRowStride); - currtmpWS = &currWs[0] + (ii*pixWSRowStride); - for(int jj=-9;jj<=9;jj+=3) { - guint8* currtmpl=currtmp+jj; - guint8* currtmpWSl=currtmpWS+jj; - //transparent green - currtmpl[0] = transparency * currtmpWSl[0]; - currtmpl[1] = transparency * currtmpWSl[1] + (1.f-transparency)*255.f; - currtmpl[2] = transparency * currtmpWSl[2]; - } - } - // second last row of circle - currtmp = &curr[0] + (2*pixRowStride); - currtmpWS = &currWs[0] + (2*pixWSRowStride); - for(int jj=-6;jj<=6;jj+=3) { - guint8* currtmpl=currtmp+jj; - guint8* currtmpWSl=currtmpWS+jj; - //transparent green - currtmpl[0] = transparency * currtmpWSl[0]; - currtmpl[1] = transparency * currtmpWSl[1] + (1.f-transparency)*255.f; - currtmpl[2] = transparency * currtmpWSl[2]; - } - // last row of circle - currtmp = &curr[0] + (3*pixRowStride); - currtmpWS = &currWs[0] + (3*pixWSRowStride); - for(int jj=-3;jj<=3;jj+=3) { - guint8* currtmpl=currtmp+jj; - guint8* currtmpWSl=currtmpWS+jj; - //transparent green - currtmpl[0] = transparency * currtmpWSl[0]; - currtmpl[1] = transparency * currtmpWSl[1] + (1.f-transparency)*255.f; - currtmpl[2] = transparency * currtmpWSl[2]; - } - } - curr+=3; currWs+=3; - } - } - free(tmpL); - free(tmpLsum); - free(tmpLsumSq); - free(tmpstdDev2); - } else { // !showFocusMask - - const int hlThreshold = options.highlightThreshold; - const int shThreshold = options.shadowThreshold; - const float ShawdowFac = 64 / (options.shadowThreshold+1); - const float HighlightFac = 64 / (256-options.highlightThreshold); - const bool showclippedAny = (!showR && !showG && !showB && !showL); // will show clipping if any of RGB chanels is clipped + + const int hlThreshold = options.highlightThreshold; + const int shThreshold = options.shadowThreshold; + const float ShawdowFac = 64 / (options.shadowThreshold + 1); + const float HighlightFac = 64 / (256 - options.highlightThreshold); + const bool showclippedAny = (!showR && !showG && !showB && !showL); // will show clipping if any of RGB chanels is clipped #ifdef _OPENMP -#pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for (int i=0; i=hlThreshold ) { delta += 255-currWS[0]; changedHL=true; } - if ((showclippedAny || showG) && currWS[1]>=hlThreshold ) { delta += 255-currWS[1]; changedHL=true; } - if ((showclippedAny || showB) && currWS[2]>=hlThreshold ) { delta += 255-currWS[2]; changedHL=true; } - if (showL && currWS_L>= hlThreshold ) { delta += 255-currWS_L ; changedHL=true; } - if (changedHL) { - delta *= HighlightFac; - if (showclippedAny) curr[0]=curr[1]=curr[2]=delta; // indicate clipped highlights in gray - else {curr[0]=255; curr[1]=curr[2]=delta;} // indicate clipped highlights in red + if (showL && (showch || showcs)) { + currWS_L = (int)(0.299f * currWS[0] + 0.587f * currWS[1] + 0.114f * currWS[2]); + } + + if (showch) { + if ((showclippedAny || showR) && currWS[0] >= hlThreshold ) { + delta += 255 - currWS[0]; + changedHL = true; + } + + if ((showclippedAny || showG) && currWS[1] >= hlThreshold ) { + delta += 255 - currWS[1]; + changedHL = true; + } + + if ((showclippedAny || showB) && currWS[2] >= hlThreshold ) { + delta += 255 - currWS[2]; + changedHL = true; + } + + if (showL && currWS_L >= hlThreshold ) { + delta += 255 - currWS_L ; + changedHL = true; + } + + if (changedHL) { + delta *= HighlightFac; + + if (showclippedAny) { + curr[0] = curr[1] = curr[2] = delta; // indicate clipped highlights in gray + } else { + curr[0] = 255; // indicate clipped highlights in red + curr[1] = curr[2] = delta; + } } } + if (showcs) { - if ((showclippedAny || showR) && currWS[0]<=shThreshold ) { delta += currWS[0]; changedSH=true; } - if ((showclippedAny || showG) && currWS[1]<=shThreshold ) { delta += currWS[1]; changedSH=true; } - if ((showclippedAny || showB) && currWS[2]<=shThreshold ) { delta += currWS[2]; changedSH=true; } - if (showL && currWS_L <=shThreshold ) { delta += currWS_L ; changedSH=true; } + if ((showclippedAny || showR) && currWS[0] <= shThreshold ) { + delta += currWS[0]; + changedSH = true; + } + + if ((showclippedAny || showG) && currWS[1] <= shThreshold ) { + delta += currWS[1]; + changedSH = true; + } + + if ((showclippedAny || showB) && currWS[2] <= shThreshold ) { + delta += currWS[2]; + changedSH = true; + } + + if (showL && currWS_L <= shThreshold ) { + delta += currWS_L ; + changedSH = true; + } if (changedSH) { if (showclippedAny) { delta = 255 - (delta * ShawdowFac); - curr[0]=curr[1]=curr[2]=delta; // indicate clipped shadows in gray - } - else { + curr[0] = curr[1] = curr[2] = delta; // indicate clipped shadows in gray + } else { delta *= ShawdowFac; - curr[2]=255; curr[0]=curr[1]=delta; // indicate clipped shadows in blue + curr[2] = 255; + curr[0] = curr[1] = delta; // indicate clipped shadows in blue } } } //if (showcs) - + // modulate the preview of channels & L; - if (!changedHL && !changedSH && !showclippedAny){ //This condition allows clipping indicators for RGB channels to remain in color - if (showR) curr[1]=curr[2]=curr[0]; //Red channel in grayscale - if (showG) curr[0]=curr[2]=curr[1]; //Green channel in grayscale - if (showB) curr[0]=curr[1]=curr[2]; //Blue channel in grayscale + if (!changedHL && !changedSH && !showclippedAny) { //This condition allows clipping indicators for RGB channels to remain in color + if (showR) { + curr[1] = curr[2] = curr[0]; //Red channel in grayscale + } + + if (showG) { + curr[0] = curr[2] = curr[1]; //Green channel in grayscale + } + + if (showB) { + curr[0] = curr[1] = curr[2]; //Blue channel in grayscale + } + if (showL) { //Luminosity // see http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness for more info //int L = (int)(0.212671*curr[0]+0.715160*curr[1]+0.072169*curr[2]); - int L = (int)(0.299*curr[0]+0.587*curr[1]+0.114*curr[2]); //Lightness - this matches Luminosity mode in Photoshop CS5 - curr[0]=curr[1]=curr[2]=L; + int L = (int)(0.299 * curr[0] + 0.587 * curr[1] + 0.114 * curr[2]); //Lightness - this matches Luminosity mode in Photoshop CS5 + curr[0] = curr[1] = curr[2] = L; } } - /* - if (showch && (currWS[0]>=options.highlightThreshold || currWS[1]>=options.highlightThreshold || currWS[2]>=options.highlightThreshold)) - curr[0] = curr[1] = curr[2] = 0; - else if (showcs && (currWS[0]<=options.shadowThreshold || currWS[1]<=options.shadowThreshold || currWS[2]<=options.shadowThreshold)) - curr[0] = curr[1] = curr[2] = 255; - //if (showch && ((0.299*curr[0]+0.587*curr[1]+0.114*curr[2])>=options.highlightThreshold)) - // curr[0] = curr[1] = curr[2] = 0; - //else if (showcs && ((0.299*curr[0]+0.587*curr[1]+0.114*curr[2])<=options.shadowThreshold)) - // curr[0] = curr[1] = curr[2] = 255; - */ + /* + if (showch && (currWS[0]>=options.highlightThreshold || currWS[1]>=options.highlightThreshold || currWS[2]>=options.highlightThreshold)) + curr[0] = curr[1] = curr[2] = 0; + else if (showcs && (currWS[0]<=options.shadowThreshold || currWS[1]<=options.shadowThreshold || currWS[2]<=options.shadowThreshold)) + curr[0] = curr[1] = curr[2] = 255; + //if (showch && ((0.299*curr[0]+0.587*curr[1]+0.114*curr[2])>=options.highlightThreshold)) + // curr[0] = curr[1] = curr[2] = 0; + //else if (showcs && ((0.299*curr[0]+0.587*curr[1]+0.114*curr[2])<=options.shadowThreshold)) + // curr[0] = curr[1] = curr[2] = 255; + */ - curr+=3; currWS+=3; - } - } + curr += 3; + currWS += 3; + } + } } + //printf("zoomSteps[cropZoom].zoom=%d\n",zoomSteps[cropZoom].zoom); - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x+imgX, y+imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x + imgX, y + imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + } else { + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x + imgX, y + imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); } - else - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x+imgX, y+imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); if (cropHandler.cropParams.enabled) { int cropX, cropY; cropHandler.getPosition (cropX, cropY); - drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams,(this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom() ); + drawCrop (cr, x + imgX, y + imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom() ); } - if (observedCropWin) + + if (observedCropWin) { drawObservedFrame (cr); + } EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); rtengine::Crop* crop = static_cast(cropHandler.getCrop()); + if (editSubscriber && crop->bufferCreated()) { // clip the region if (this != iarea->mainCropWindow) { cr->set_line_width (0.); - cr->rectangle (x+imgX, y+imgY, imgW, imgH); + cr->rectangle (x + imgX, y + imgY, imgW, imgH); cr->clip(); } @@ -1326,19 +1479,23 @@ void CropWindow::expose (Cairo::RefPtr cr) { cr->set_line_join(Cairo::LINE_JOIN_ROUND); // drawing outer lines - for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) + for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) { (*i)->drawOuterGeometry(cr, crop, *this); + } // drawing inner lines - for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) + for (std::vector::const_iterator i = visibleGeom.begin(); i != visibleGeom.end(); ++i) { (*i)->drawInnerGeometry(cr, crop, *this); + } - if (this != iarea->mainCropWindow) + if (this != iarea->mainCropWindow) { cr->reset_clip(); + } // drawing to the "mouse over" channel if (editSubscriber->getEditingType() == ET_OBJECTS) { const std::vector mouseOverGeom = editSubscriber->getMouseOverGeometry(); + if (mouseOverGeom.size()) { //printf("ObjectMap (%d x %d)\n", crop->getObjectMap()->get_width(), crop->getObjectMap()->get_height()); Cairo::RefPtr crMO = Cairo::Context::create(crop->getObjectMap()); @@ -1354,6 +1511,7 @@ void CropWindow::expose (Cairo::RefPtr cr) { crMO->fill(); Cairo::RefPtr crMO2; + if (crop->getObjectMode() > OM_255) { crMO2 = Cairo::Context::create(crop->getObjectMap2()); crMO2->set_antialias(Cairo::ANTIALIAS_NONE); @@ -1367,63 +1525,77 @@ void CropWindow::expose (Cairo::RefPtr cr) { crMO2->set_line_width(0.); crMO2->fill(); } + std::vector::const_iterator i; int a; - for (a=0, i=mouseOverGeom.begin(); i != mouseOverGeom.end(); ++i, ++a) { + + for (a = 0, i = mouseOverGeom.begin(); i != mouseOverGeom.end(); ++i, ++a) { (*i)->drawToMOChannel(crMO, crMO2, a, crop, *this); } // Debug code: save the "mouse over" image to a new file at each occurrence - #if 0 +#if 0 { - static unsigned int count=0; - int w = crop->getObjectMap()->get_width(); - int h = crop->getObjectMap()->get_height(); - Glib::RefPtr img = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, w, h); - guint8 *dst = img->get_pixels(); - unsigned char *src1 = crop->getObjectMap()->get_data(); - unsigned char *src2 = crop->getObjectMode() > OM_255 ? crop->getObjectMap()->get_data() : NULL; - memcpy(dst, src1, w*h); - for (int n=0, n3=0; ngetObjectMap()->get_width(); + int h = crop->getObjectMap()->get_height(); + Glib::RefPtr img = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, w, h); + guint8 *dst = img->get_pixels(); + unsigned char *src1 = crop->getObjectMap()->get_data(); + unsigned char *src2 = crop->getObjectMode() > OM_255 ? crop->getObjectMap()->get_data() : NULL; + memcpy(dst, src1, w * h); + + for (int n = 0, n3 = 0; n < w * h;) { + dst[n3++] = src1[n]; + + if (src2) { + dst[n3++] = src2[n]; + } else { + dst[n3++] = 0; + } + dst[n3++] = 0; - dst[n3++] = 0; - ++n; + ++n; + } + + img->save(Glib::ustring::compose("mouseOverImage-%1.png", count++), "png"); } - img->save(Glib::ustring::compose("mouseOverImage-%1.png", count++), "png"); - } - #endif +#endif } } } - } - else { + } else { // cropHandler.cropPixbuf is null int cropX, cropY; cropHandler.getPosition (cropX, cropY); Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); + if (rough) { - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x+imgAreaX+(imgAreaW-rough->get_width())/2, y+imgAreaY+(imgAreaH-rough->get_height())/2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); + if (cropHandler.cropParams.enabled) { - drawCrop (cr, x+imgAreaX+(imgAreaW-rough->get_width())/2, y+imgAreaY+(imgAreaH-rough->get_height())/2, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()); + drawCrop (cr, x + imgAreaX + (imgAreaW - rough->get_width()) / 2, y + imgAreaY + (imgAreaH - rough->get_height()) / 2, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams, (this == iarea->mainCropWindow), true, zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()); } - if (observedCropWin) + + if (observedCropWin) { drawObservedFrame (cr, rough->get_width(), rough->get_height()); + } } } } - if (state==SRotateSelecting) + if (state == SRotateSelecting) { drawStraightenGuide (cr); - if (state==SNormal && isFlawnOver) { + } + + if (state == SNormal && isFlawnOver) { EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); - if (iarea->getToolMode () == TMHand && editSubscriber && editSubscriber->getEditingType()==ET_PIPETTE && iarea->object) + + if (iarea->getToolMode () == TMHand && editSubscriber && editSubscriber->getEditingType() == ET_PIPETTE && iarea->object) { drawUnscaledSpotRectangle (cr, iarea->getPipetteRectSize ()); - else if (iarea->getToolMode () == TMSpotWB) + } else if (iarea->getToolMode () == TMSpotWB) { drawScaledSpotRectangle (cr, iarea->getSpotWBRectSize ()); + } } //t2.set (); @@ -1431,26 +1603,28 @@ void CropWindow::expose (Cairo::RefPtr cr) { } // calculate the center of the zoomed in/out preview given a cursor position -void CropWindow::findCenter (int deltaZoom, int& x, int& y) { - int cursorX, cursorY; - screenCoordToImage(x, y, cursorX, cursorY); +void CropWindow::findCenter (int deltaZoom, int& x, int& y) +{ + int cursorX, cursorY; + screenCoordToImage(x, y, cursorX, cursorY); - int cropX, cropY, cropW, cropH, skip; - cropHandler.getWindow (cropX, cropY, cropW, cropH, skip); + int cropX, cropY, cropW, cropH, skip; + cropHandler.getWindow (cropX, cropY, cropW, cropH, skip); - int currCenterX = cropX + cropW/2; - int currCenterY = cropY + cropH/2; + int currCenterX = cropX + cropW / 2; + int currCenterY = cropY + cropH / 2; - int deltaX = currCenterX - cursorX; - int deltaY = currCenterY - cursorY; + int deltaX = currCenterX - cursorX; + int deltaY = currCenterY - cursorY; - double factor = zoomSteps[cropZoom].zoom / zoomSteps[cropZoom+deltaZoom].zoom; - x = cursorX + (int)((double)(deltaX)*factor); - y = cursorY + (int)((double)(deltaY)*factor); + double factor = zoomSteps[cropZoom].zoom / zoomSteps[cropZoom + deltaZoom].zoom; + x = cursorX + (int)((double)(deltaX) * factor); + y = cursorY + (int)((double)(deltaY) * factor); } // zoom* is called from the zoomPanel or the scroll wheel in the preview area -void CropWindow::zoomIn (bool toCursor, int cursorX, int cursorY) { +void CropWindow::zoomIn (bool toCursor, int cursorX, int cursorY) +{ int x = -1; int y = -1; @@ -1469,16 +1643,19 @@ void CropWindow::zoomIn (bool toCursor, int cursorX, int cursorY) { x = fw / 2; y = fh / 2; } + zoomVersion = exposeVersion; } else if (zoomVersion != exposeVersion) { - screenCoordToImage(xpos+imgX+imgW/2, ypos+imgY+imgH/2, x, y); + screenCoordToImage(xpos + imgX + imgW / 2, ypos + imgY + imgH / 2, x, y); + if (cropHandler.cropParams.enabled) { // add some gravity towards crop center int x1 = cropHandler.cropParams.x + cropHandler.cropParams.w / 2; int y1 = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; - double cropd = sqrt(cropHandler.cropParams.h*cropHandler.cropParams.h+cropHandler.cropParams.w*cropHandler.cropParams.w) * zoomSteps[cropZoom].zoom; - double imd = sqrt(imgW*imgW+imgH+imgH); + double cropd = sqrt(cropHandler.cropParams.h * cropHandler.cropParams.h + cropHandler.cropParams.w * cropHandler.cropParams.w) * zoomSteps[cropZoom].zoom; + double imd = sqrt(imgW * imgW + imgH + imgH); double d; + // the more we can see of the crop, the more gravity towards crop center if (cropd > imd) { d = 0.8; @@ -1487,18 +1664,21 @@ void CropWindow::zoomIn (bool toCursor, int cursorX, int cursorY) { } else { d = 1.6 * (cropd - imd * 0.5) / imd; } + x = d * x + (1.0 - d) * x1; y = d * y + (1.0 - d) * y1; } + zoomVersion = exposeVersion; } } - changeZoom (cropZoom+1, true, x, y); + changeZoom (cropZoom + 1, true, x, y); fitZoom = false; } -void CropWindow::zoomOut (bool toCursor, int cursorX, int cursorY) { +void CropWindow::zoomOut (bool toCursor, int cursorX, int cursorY) +{ int x = -1; int y = -1; @@ -1509,14 +1689,16 @@ void CropWindow::zoomOut (bool toCursor, int cursorX, int cursorY) { } zoomVersion = exposeVersion; - changeZoom (cropZoom-1, true, x, y); + changeZoom (cropZoom - 1, true, x, y); fitZoom = false; } -void CropWindow::zoom11 () { +void CropWindow::zoom11 () +{ int x = -1; int y = -1; + if (zoomSteps[cropZoom].zoom <= cropHandler.getFitZoom()) { if (cropHandler.cropParams.enabled) { x = cropHandler.cropParams.x + cropHandler.cropParams.w / 2; @@ -1524,275 +1706,317 @@ void CropWindow::zoom11 () { } else { int fw, fh; cropHandler.getFullImageSize(fw, fh); - x = fw/2; - y = fh/2; + x = fw / 2; + y = fh / 2; } + zoomVersion = exposeVersion; } + changeZoom (ZOOM11INDEX, true, x, y); fitZoom = false; } -double CropWindow::getZoom () { +double CropWindow::getZoom () +{ return zoomSteps[cropZoom].zoom; } -bool CropWindow::isMinZoom () { +bool CropWindow::isMinZoom () +{ return cropZoom <= 0; } -bool CropWindow::isMaxZoom () { +bool CropWindow::isMaxZoom () +{ return cropZoom >= MAXZOOMSTEPS; } -void CropWindow::setZoom (double zoom) { +void CropWindow::setZoom (double zoom) +{ int cz = MAXZOOMSTEPS; - if (zoom < zoomSteps[0].zoom) + + if (zoom < zoomSteps[0].zoom) { cz = 0; - else - for (int i=0; i zoom) { + } else + for (int i = 0; i < MAXZOOMSTEPS; i++) + if (zoomSteps[i].zoom <= zoom && zoomSteps[i + 1].zoom > zoom) { cz = i; break; } + changeZoom (cz, false); } -double CropWindow::getZoomFitVal () { +double CropWindow::getZoomFitVal () +{ double z = cropHandler.getFitZoom (); int cz = MAXZOOMSTEPS; - if (z < zoomSteps[0].zoom) + + if (z < zoomSteps[0].zoom) { cz = 0; - else - for (int i=0; i z) { + } else + for (int i = 0; i < MAXZOOMSTEPS; i++) + if (zoomSteps[i].zoom <= z && zoomSteps[i + 1].zoom > z) { cz = i; break; } - return zoomSteps[cz].zoom; + + return zoomSteps[cz].zoom; } -void CropWindow::zoomFit (bool skipZoomIfUnchanged) { +void CropWindow::zoomFit (bool skipZoomIfUnchanged) +{ double z = cropHandler.getFitZoom (); int cz = MAXZOOMSTEPS; - if (z < zoomSteps[0].zoom) + + if (z < zoomSteps[0].zoom) { cz = 0; - else - for (int i=0; i z) { + } else + for (int i = 0; i < MAXZOOMSTEPS; i++) + if (zoomSteps[i].zoom <= z && zoomSteps[i + 1].zoom > z) { cz = i; break; } + zoomVersion = exposeVersion; changeZoom (cz, true, -1, -1, skipZoomIfUnchanged); fitZoom = true; } -void CropWindow::zoomFitCrop () { +void CropWindow::zoomFitCrop () +{ if(cropHandler.cropParams.enabled) { - double z = cropHandler.getFitCropZoom (); - int cz = MAXZOOMSTEPS; - if (z < zoomSteps[0].zoom) - cz = 0; - else - for (int i=0; i z) { - cz = i; - break; - } - zoomVersion = exposeVersion; - int centerX,centerY; - centerX = cropHandler.cropParams.x + cropHandler.cropParams.w / 2; - centerY = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; - changeZoom (cz, true, centerX, centerY, false); - fitZoom = false; - } -} + double z = cropHandler.getFitCropZoom (); + int cz = MAXZOOMSTEPS; -void CropWindow::buttonPressed (LWButton* button, int actionCode, void* actionData) { + if (z < zoomSteps[0].zoom) { + cz = 0; + } else + for (int i = 0; i < MAXZOOMSTEPS; i++) + if (zoomSteps[i].zoom <= z && zoomSteps[i + 1].zoom > z) { + cz = i; + break; + } - if (button==bZoomIn) // zoom in - zoomIn (); - else if (button==bZoomOut) // zoom out - zoomOut (); - else if (button==bZoom100) // zoom 100 - zoom11 (); - else if (button==bClose) {// close - if(ipc->updateTryLock()) { - deleted = true; - iarea->cropWindowClosed (this); - ipc->updateUnLock(); - } + zoomVersion = exposeVersion; + int centerX, centerY; + centerX = cropHandler.cropParams.x + cropHandler.cropParams.w / 2; + centerY = cropHandler.cropParams.y + cropHandler.cropParams.h / 2; + changeZoom (cz, true, centerX, centerY, false); + fitZoom = false; } } -void CropWindow::redrawNeeded (LWButton* button) { - +void CropWindow::buttonPressed (LWButton* button, int actionCode, void* actionData) +{ + + if (button == bZoomIn) { // zoom in + zoomIn (); + } else if (button == bZoomOut) { // zoom out + zoomOut (); + } else if (button == bZoom100) { // zoom 100 + zoom11 (); + } else if (button == bClose) { // close + if(ipc->updateTryLock()) { + deleted = true; + iarea->cropWindowClosed (this); + ipc->updateUnLock(); + } + } +} + +void CropWindow::redrawNeeded (LWButton* button) +{ + iarea->redraw (); } -void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, bool skipZoomIfUnchanged) { +void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery, bool skipZoomIfUnchanged) +{ - if (zoom<0) + if (zoom < 0) { zoom = 0; - else if (zoom>MAXZOOMSTEPS) + } else if (zoom > MAXZOOMSTEPS) { zoom = MAXZOOMSTEPS; - - if (cropZoom == zoom && skipZoomIfUnchanged) { - // We are already at the start/end of the zoom range, so we do nothing - return; } - cropZoom = zoom; + if (cropZoom == zoom && skipZoomIfUnchanged) { + // We are already at the start/end of the zoom range, so we do nothing + return; + } + + cropZoom = zoom; cropLabel = zoomSteps[cropZoom].label; cropHandler.setZoom (zoomSteps[cropZoom].czoom, centerx, centery); + if (notify) - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropZoomChanged (this); + } + iarea->redraw (); } -void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy) { +void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy) +{ rtengine::Crop* crop = static_cast(cropHandler.getCrop()); cropx = phyx - xpos - imgX; cropy = phyy - ypos - imgY; + if (zoomSteps[cropZoom].zoom > 1.) { - cropx = int(double(cropx)/zoomSteps[cropZoom].zoom); - cropy = int(double(cropy)/zoomSteps[cropZoom].zoom); + cropx = int(double(cropx) / zoomSteps[cropZoom].zoom); + cropy = int(double(cropy) / zoomSteps[cropZoom].zoom); } + cropx += crop->getLeftBorder(); cropy += crop->getUpperBorder(); } -void CropWindow::screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) { +void CropWindow::screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) +{ int cropX, cropY; cropHandler.getPosition (cropX, cropY); - imgx = cropX + (phyx - xpos - imgX)/zoomSteps[cropZoom].zoom; - imgy = cropY + (phyy - ypos - imgY)/zoomSteps[cropZoom].zoom; + imgx = cropX + (phyx - xpos - imgX) / zoomSteps[cropZoom].zoom; + imgy = cropY + (phyy - ypos - imgY) / zoomSteps[cropZoom].zoom; } -void CropWindow::screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy) { +void CropWindow::screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy) +{ prevx = phyx - xpos - imgX; prevy = phyy - ypos - imgY; } -void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) { +void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) +{ int cropX, cropY; cropHandler.getPosition (cropX, cropY); - phyx = (imgx - cropX)*zoomSteps[cropZoom].zoom + xpos + imgX; - phyy = (imgy - cropY)*zoomSteps[cropZoom].zoom + ypos + imgY; - // printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + xpos + imgX; + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + ypos + imgY; + // printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); } -void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) { +void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) +{ int cropX, cropY; rtengine::Crop* crop = static_cast(cropHandler.getCrop()); cropHandler.getPosition (cropX, cropY); - phyx = (imgx - cropX)*zoomSteps[cropZoom].zoom + /*xpos + imgX +*/ crop->getLeftBorder(); - phyy = (imgy - cropY)*zoomSteps[cropZoom].zoom + /*ypos + imgY +*/ crop->getUpperBorder(); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom + /*xpos + imgX +*/ crop->getLeftBorder(); + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + /*ypos + imgY +*/ crop->getUpperBorder(); //printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); } -int CropWindow::scaleValueToImage (int value) { - return int(double(value)/zoomSteps[cropZoom].zoom); +int CropWindow::scaleValueToImage (int value) +{ + return int(double(value) / zoomSteps[cropZoom].zoom); } -float CropWindow::scaleValueToImage (float value) { - return float(double(value)/zoomSteps[cropZoom].zoom); +float CropWindow::scaleValueToImage (float value) +{ + return float(double(value) / zoomSteps[cropZoom].zoom); } -double CropWindow::scaleValueToImage (double value) { - return value/zoomSteps[cropZoom].zoom; +double CropWindow::scaleValueToImage (double value) +{ + return value / zoomSteps[cropZoom].zoom; } -int CropWindow::scaleValueToScreen (int value) { - return int(double(value)*zoomSteps[cropZoom].zoom); +int CropWindow::scaleValueToScreen (int value) +{ + return int(double(value) * zoomSteps[cropZoom].zoom); } -float CropWindow::scaleValueToScreen (float value) { - return float(double(value)*zoomSteps[cropZoom].zoom); +float CropWindow::scaleValueToScreen (float value) +{ + return float(double(value) * zoomSteps[cropZoom].zoom); } -double CropWindow::scaleValueToScreen (double value) { - return value*zoomSteps[cropZoom].zoom; +double CropWindow::scaleValueToScreen (double value) +{ + return value * zoomSteps[cropZoom].zoom; } -void CropWindow::drawDecoration (Cairo::RefPtr cr) { +void CropWindow::drawDecoration (Cairo::RefPtr cr) +{ - int x = xpos, y = ypos; - // prepare label - Glib::RefPtr context = iarea->get_pango_context () ; - Pango::FontDescription fontd = context->get_font_description (); - fontd.set_weight (Pango::WEIGHT_BOLD); - fontd.set_size(8*Pango::SCALE); - context->set_font_description (fontd); - Glib::RefPtr cllayout = iarea->create_pango_layout(cropLabel); - int iw, ih; - cllayout->get_pixel_size (iw, ih); + int x = xpos, y = ypos; + // prepare label + Glib::RefPtr context = iarea->get_pango_context () ; + Pango::FontDescription fontd = context->get_font_description (); + fontd.set_weight (Pango::WEIGHT_BOLD); + fontd.set_size(8 * Pango::SCALE); + context->set_font_description (fontd); + Glib::RefPtr cllayout = iarea->create_pango_layout(cropLabel); + int iw, ih; + cllayout->get_pixel_size (iw, ih); - // draw decoration (border) - int h = height, w = width; + // draw decoration (border) + int h = height, w = width; - cr->set_source_rgb (0.1,0.1,0.1); - cr->set_line_width (1.0); - cr->move_to (x+2.5, y+titleHeight+2.5 ); - cr->line_to (x+2.5, y+h-2.5); - cr->line_to (x+w-2.5, y+h-2.5); - cr->line_to (x+w-2.5, y+titleHeight+2.5 ); + cr->set_source_rgb (0.1, 0.1, 0.1); + cr->set_line_width (1.0); + cr->move_to (x + 2.5, y + titleHeight + 2.5 ); + cr->line_to (x + 2.5, y + h - 2.5); + cr->line_to (x + w - 2.5, y + h - 2.5); + cr->line_to (x + w - 2.5, y + titleHeight + 2.5 ); - cr->set_source_rgba (0.0,0.0,0.0,0.5); - cr->rectangle (x+2.5, y+0.5, w-5, titleHeight+2); + cr->set_source_rgba (0.0, 0.0, 0.0, 0.5); + cr->rectangle (x + 2.5, y + 0.5, w - 5, titleHeight + 2); cr->stroke_preserve (); cr->fill (); - + // draw label - cr->set_source_rgba (1,1,1,0.5); - cr->move_to (x+10+sideBorderWidth+bZoomIn->getIcon()->get_width()+bZoomOut->getIcon()->get_width()+bZoom100->getIcon()->get_width(), y+1+upperBorderWidth+(titleHeight-ih)/2); + cr->set_source_rgba (1, 1, 1, 0.5); + cr->move_to (x + 10 + sideBorderWidth + bZoomIn->getIcon()->get_width() + bZoomOut->getIcon()->get_width() + bZoom100->getIcon()->get_width(), y + 1 + upperBorderWidth + (titleHeight - ih) / 2); cllayout->add_to_cairo_context (cr); cr->fill (); buttonSet.redraw (cr); } -void CropWindow::drawStraightenGuide (Cairo::RefPtr cr) { +void CropWindow::drawStraightenGuide (Cairo::RefPtr cr) +{ - if (action_x!=press_x || action_y!=press_y) { - double arg = (press_x-action_x) / sqrt(double((press_x-action_x)*(press_x-action_x)+(press_y-action_y)*(press_y-action_y))); + if (action_x != press_x || action_y != press_y) { + double arg = (press_x - action_x) / sqrt(double((press_x - action_x) * (press_x - action_x) + (press_y - action_y) * (press_y - action_y))); double sol1, sol2; double pi = M_PI; - if (press_y>action_y) { - sol1 = acos(arg)*180/pi; - sol2 = -acos(-arg)*180/pi; - } - else { - sol1 = acos(-arg)*180/pi; - sol2 = -acos(arg)*180/pi; - } - if (fabs(sol1)45) - rot_deg = - 90.0 + rot_deg; - } - else + if (press_y > action_y) { + sol1 = acos(arg) * 180 / pi; + sol2 = -acos(-arg) * 180 / pi; + } else { + sol1 = acos(-arg) * 180 / pi; + sol2 = -acos(arg) * 180 / pi; + } + + if (fabs(sol1) < fabs(sol2)) { + rot_deg = sol1; + } else { + rot_deg = sol2; + } + + if (rot_deg < -45) { + rot_deg = 90.0 + rot_deg; + } else if (rot_deg > 45) { + rot_deg = - 90.0 + rot_deg; + } + } else { rot_deg = 0; + } Glib::RefPtr context = iarea->get_pango_context () ; Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); - fontd.set_size (8*Pango::SCALE); + fontd.set_size (8 * Pango::SCALE); context->set_font_description (fontd); Glib::RefPtr deglayout = iarea->create_pango_layout(Glib::ustring::compose ("%1 deg", Glib::ustring::format(std::setprecision(2), rot_deg))); @@ -1800,69 +2024,71 @@ void CropWindow::drawStraightenGuide (Cairo::RefPtr cr) { int y1 = press_y; int y2 = action_y; int x2 = action_x; -/* if (x1<0) x1 = 0; - if (y1<0) y1 = 0; - if (x2<0) x2 = 0; - if (y2<0) y2 = 0; - if (x2>=image->getWidth()) x2 = image->getWidth()-1; - if (y2>=image->getHeight()) y2 = image->getHeight()-1; - if (x1>=image->getWidth()) x1 = image->getWidth()-1; - if (y1>=image->getHeight()) y1 = image->getHeight()-1; -*/ + /* if (x1<0) x1 = 0; + if (y1<0) y1 = 0; + if (x2<0) x2 = 0; + if (y2<0) y2 = 0; + if (x2>=image->getWidth()) x2 = image->getWidth()-1; + if (y2>=image->getHeight()) y2 = image->getHeight()-1; + if (x1>=image->getWidth()) x1 = image->getWidth()-1; + if (y1>=image->getHeight()) y1 = image->getHeight()-1; + */ cr->set_line_width (1); cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); - cr->move_to (x1+0.5, y1+0.5); - cr->line_to (x2+0.5, y2+0.5); + cr->move_to (x1 + 0.5, y1 + 0.5); + cr->line_to (x2 + 0.5, y2 + 0.5); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); - cr->move_to (x1+0.5, y1+0.5); - cr->line_to (x2+0.5, y2+0.5); + cr->move_to (x1 + 0.5, y1 + 0.5); + cr->line_to (x2 + 0.5, y2 + 0.5); cr->stroke (); - if (press_x!=action_x && press_y!=action_y) { + if (press_x != action_x && press_y != action_y) { cr->set_source_rgb (0.0, 0.0, 0.0); - cr->move_to ((x1+x2)/2+1, (y1+y2)/2+1); + cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 + 1); deglayout->add_to_cairo_context (cr); - cr->move_to ((x1+x2)/2+1, (y1+y2)/2-1); + cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 - 1); deglayout->add_to_cairo_context (cr); - cr->move_to ((x1+x2)/2-1, (y1+y2)/2+1); + cr->move_to ((x1 + x2) / 2 - 1, (y1 + y2) / 2 + 1); deglayout->add_to_cairo_context (cr); - cr->move_to ((x1+x2)/2+1, (y1+y2)/2+1); + cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 + 1); deglayout->add_to_cairo_context (cr); cr->fill (); cr->set_source_rgb (1.0, 1.0, 1.0); - cr->move_to ((x1+x2)/2, (y1+y2)/2); + cr->move_to ((x1 + x2) / 2, (y1 + y2) / 2); deglayout->add_to_cairo_context (cr); cr->fill (); } } -void CropWindow::drawScaledSpotRectangle (Cairo::RefPtr cr, int rectSize) { +void CropWindow::drawScaledSpotRectangle (Cairo::RefPtr cr, int rectSize) +{ - int x1 = action_x/zoomSteps[cropZoom].zoom - rectSize; - int y1 = action_y/zoomSteps[cropZoom].zoom - rectSize; - int y2 = action_y/zoomSteps[cropZoom].zoom + rectSize; - int x2 = action_x/zoomSteps[cropZoom].zoom + rectSize; + int x1 = action_x / zoomSteps[cropZoom].zoom - rectSize; + int y1 = action_y / zoomSteps[cropZoom].zoom - rectSize; + int y2 = action_y / zoomSteps[cropZoom].zoom + rectSize; + int x2 = action_x / zoomSteps[cropZoom].zoom + rectSize; cr->set_line_width (1.0); - cr->rectangle (xpos+imgX-0.5, ypos+imgY-0.5, imgW, imgH); + cr->rectangle (xpos + imgX - 0.5, ypos + imgY - 0.5, imgW, imgH); cr->clip (); cr->set_source_rgb (1.0, 1.0, 1.0); - cr->rectangle (x1*zoomSteps[cropZoom].zoom-1.5, y1*zoomSteps[cropZoom].zoom-1.5, x2*zoomSteps[cropZoom].zoom-x1*zoomSteps[cropZoom].zoom+2, y2*zoomSteps[cropZoom].zoom-y1*zoomSteps[cropZoom].zoom+2); + cr->rectangle (x1 * zoomSteps[cropZoom].zoom - 1.5, y1 * zoomSteps[cropZoom].zoom - 1.5, x2 * zoomSteps[cropZoom].zoom - x1 * zoomSteps[cropZoom].zoom + 2, y2 * zoomSteps[cropZoom].zoom - y1 * zoomSteps[cropZoom].zoom + 2); cr->stroke (); cr->set_source_rgb (0.0, 0.0, 0.0); - cr->rectangle (x1*zoomSteps[cropZoom].zoom-0.5, y1*zoomSteps[cropZoom].zoom-0.5, x2*zoomSteps[cropZoom].zoom-x1*zoomSteps[cropZoom].zoom, y2*zoomSteps[cropZoom].zoom-y1*zoomSteps[cropZoom].zoom); + cr->rectangle (x1 * zoomSteps[cropZoom].zoom - 0.5, y1 * zoomSteps[cropZoom].zoom - 0.5, x2 * zoomSteps[cropZoom].zoom - x1 * zoomSteps[cropZoom].zoom, y2 * zoomSteps[cropZoom].zoom - y1 * zoomSteps[cropZoom].zoom); cr->stroke (); - + cr->reset_clip (); } -void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize) { +void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize) +{ int x1 = action_x - rectSize; int y1 = action_y - rectSize; @@ -1870,40 +2096,42 @@ void CropWindow::drawUnscaledSpotRectangle (Cairo::RefPtr cr, in int x2 = action_x + rectSize; cr->set_line_width (1.0); - cr->rectangle (xpos+imgX-0.5, ypos+imgY-0.5, imgW, imgH); + cr->rectangle (xpos + imgX - 0.5, ypos + imgY - 0.5, imgW, imgH); cr->clip (); cr->set_source_rgb (1.0, 1.0, 1.0); - cr->rectangle (x1-1.5, y1-1.5, x2-x1+2, y2-y1+2); + cr->rectangle (x1 - 1.5, y1 - 1.5, x2 - x1 + 2, y2 - y1 + 2); cr->stroke (); cr->set_source_rgb (0.0, 0.0, 0.0); - cr->rectangle (x1-0.5, y1-0.5, x2-x1, y2-y1); + cr->rectangle (x1 - 0.5, y1 - 0.5, x2 - x1, y2 - y1); cr->stroke (); cr->reset_clip (); } -void CropWindow::getObservedFrameArea (int& x, int& y, int& w, int& h, int rw, int rh) { +void CropWindow::getObservedFrameArea (int& x, int& y, int& w, int& h, int rw, int rh) +{ int cropX, cropY, cropW, cropH; observedCropWin->getCropRectangle (cropX, cropY, cropW, cropH); int myCropX, myCropY, myCropW, myCropH; getCropRectangle (myCropX, myCropY, myCropW, myCropH); - + // translate it to screen coordinates if (rw) { - x = xpos + imgAreaX+(imgAreaW-rw)/2 + (cropX-myCropX)*zoomSteps[cropZoom].zoom; - y = ypos + imgAreaY+(imgAreaH-rh)/2 + (cropY-myCropY)*zoomSteps[cropZoom].zoom; - } - else { - x = xpos + imgX + (cropX-myCropX)*zoomSteps[cropZoom].zoom; - y = ypos + imgY + (cropY-myCropY)*zoomSteps[cropZoom].zoom; + x = xpos + imgAreaX + (imgAreaW - rw) / 2 + (cropX - myCropX) * zoomSteps[cropZoom].zoom; + y = ypos + imgAreaY + (imgAreaH - rh) / 2 + (cropY - myCropY) * zoomSteps[cropZoom].zoom; + } else { + x = xpos + imgX + (cropX - myCropX) * zoomSteps[cropZoom].zoom; + y = ypos + imgY + (cropY - myCropY) * zoomSteps[cropZoom].zoom; } + w = cropW * zoomSteps[cropZoom].zoom; h = cropH * zoomSteps[cropZoom].zoom; } -void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, int rh) { +void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, int rh) +{ int x, y, w, h; getObservedFrameArea (x, y, w, h, rw, rh); @@ -1911,64 +2139,80 @@ void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, in // draw a black "shadow" line cr->set_source_rgba( 0, 0, 0, 0.65); cr->set_line_width (1); - cr->rectangle (x-0.5, y-0.5, w+4, h+4); + cr->rectangle (x - 0.5, y - 0.5, w + 4, h + 4); cr->stroke (); // draw a "frame" line. Color of frame line can be set in preferences cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1, 1, 1, 1.0); - cr->rectangle (x-1.5, y-1.5, w+4, h+4); + cr->rectangle (x - 1.5, y - 1.5, w + 4, h + 4); cr->stroke (); } -void CropWindow::cropImageUpdated () { +void CropWindow::cropImageUpdated () +{ iarea->redraw (); } -void CropWindow::cropWindowChanged () { +void CropWindow::cropWindowChanged () +{ - if (!decorated) + if (!decorated) { iarea->syncBeforeAfterViews (); + } + iarea->redraw (); } -void CropWindow::initialImageArrived () { +void CropWindow::initialImageArrived () +{ - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->initialImageArrived (this); + } } -void CropWindow::remoteMove (int deltaX, int deltaY) { +void CropWindow::remoteMove (int deltaX, int deltaY) +{ state = SCropImgMove; action_x = deltaX; action_y = deltaY; - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropPositionChanged (this); + } } -void CropWindow::remoteMoveReady () { +void CropWindow::remoteMoveReady () +{ int cropX, cropY; cropHandler.getPosition (cropX, cropY); cropHandler.setPosition (cropX + action_x, cropY + action_y); cropHandler.getPosition (cropX, cropY); state = SNormal; - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->cropPositionChanged (this); + } } -void CropWindow::delCropWindowListener (CropWindowListener* l) { +void CropWindow::delCropWindowListener (CropWindowListener* l) +{ - std::list::iterator i=listeners.begin(); - while (i!=listeners.end()) - if (*i==l) + std::list::iterator i = listeners.begin(); + + while (i != listeners.end()) + if (*i == l) { i = listeners.erase (i); - else + } else { i++; + } } -EditDataProvider* CropWindow::getImageArea() { +EditDataProvider* CropWindow::getImageArea() +{ return iarea; } diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index a6a55905f..aad6b9ef5 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -7,7 +7,7 @@ * 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 @@ -30,150 +30,173 @@ #include "pointermotionlistener.h" class CropWindow; -class CropWindowListener { - - public: - virtual ~CropWindowListener() {} - virtual void cropPositionChanged (CropWindow*) {} - virtual void cropWindowSizeChanged (CropWindow*) {} - virtual void cropZoomChanged (CropWindow*) {} - virtual void initialImageArrived (CropWindow*) {} +class CropWindowListener +{ + +public: + virtual ~CropWindowListener() {} + virtual void cropPositionChanged (CropWindow*) {} + virtual void cropWindowSizeChanged (CropWindow*) {} + virtual void cropZoomChanged (CropWindow*) {} + virtual void initialImageArrived (CropWindow*) {} }; class ImageArea; -class CropWindow : public LWButtonListener, public CropHandlerListener, public EditCoordSystem { +class CropWindow : public LWButtonListener, public CropHandlerListener, public EditCoordSystem +{ - // state management - ImgEditState state; // current state of user (see enum State) - int action_x, action_y, press_x, press_y; - double rot_deg; - bool onResizeArea; - bool deleted; - bool fitZoomEnabled; - bool fitZoom; - bool isLowUpdatePriority; + // state management + ImgEditState state; // current state of user (see enum State) + int action_x, action_y, press_x, press_y; + double rot_deg; + bool onResizeArea; + bool deleted; + bool fitZoomEnabled; + bool fitZoom; + bool isLowUpdatePriority; - // decoration - LWButton *bZoomIn, *bZoomOut, *bZoom100, /**bZoomFit,*/ *bClose; - LWButtonSet buttonSet; - Glib::ustring cropLabel; - int backColor; - bool decorated; - bool isFlawnOver; + // decoration + LWButton *bZoomIn, *bZoomOut, *bZoom100, /**bZoomFit,*/ *bClose; + LWButtonSet buttonSet; + Glib::ustring cropLabel; + int backColor; + bool decorated; + bool isFlawnOver; - // crop frame description - int titleHeight, sideBorderWidth, lowerBorderWidth, upperBorderWidth, sepWidth, minWidth; - // size & position of the crop relative to the top left corner - // of the main preview area - int xpos, ypos, width, height; - // size & pos of the drawable area relative to the top left corner of the crop - int imgAreaX, imgAreaY, imgAreaW, imgAreaH; - // size & pos of the piece of preview image relative to the top left corner of the crop - int imgX, imgY, imgW, imgH; + // crop frame description + int titleHeight, sideBorderWidth, lowerBorderWidth, upperBorderWidth, sepWidth, minWidth; + // size & position of the crop relative to the top left corner + // of the main preview area + int xpos, ypos, width, height; + // size & pos of the drawable area relative to the top left corner of the crop + int imgAreaX, imgAreaY, imgAreaW, imgAreaH; + // size & pos of the piece of preview image relative to the top left corner of the crop + int imgX, imgY, imgW, imgH; - // image handling + // image handling - ImageArea* iarea; - int cropZoom; // *1000 - unsigned int zoomVersion, exposeVersion; + ImageArea* iarea; + int cropZoom; // *1000 + unsigned int zoomVersion, exposeVersion; - // crop gui listener - CropGUIListener* cropgl; - PointerMotionListener* pmlistener; - PointerMotionListener* pmhlistener; - std::list listeners; - - CropWindow* observedCropWin; - rtengine::StagedImageProcessor* ipc; + // crop gui listener + CropGUIListener* cropgl; + PointerMotionListener* pmlistener; + PointerMotionListener* pmhlistener; + std::list listeners; - bool onArea (CursorArea a, int x, int y); - void updateCursor (int x, int y); - void drawDecoration (Cairo::RefPtr cr); - void drawStraightenGuide (Cairo::RefPtr cr); - void drawScaledSpotRectangle (Cairo::RefPtr cr, int rectSize); - void drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize); - void drawObservedFrame (Cairo::RefPtr cr, int rw=0, int rh=0); - void changeZoom (int zoom, bool notify=true, int centerx=-1, int centery=-1, bool skipZoomIfUnchanged = true); - void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw=0, int rh=0); + CropWindow* observedCropWin; + rtengine::StagedImageProcessor* ipc; - public: - CropHandler cropHandler; - CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow); + bool onArea (CursorArea a, int x, int y); + void updateCursor (int x, int y); + void drawDecoration (Cairo::RefPtr cr); + void drawStraightenGuide (Cairo::RefPtr cr); + void drawScaledSpotRectangle (Cairo::RefPtr cr, int rectSize); + void drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize); + void drawObservedFrame (Cairo::RefPtr cr, int rw = 0, int rh = 0); + void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1, bool skipZoomIfUnchanged = true); + void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw = 0, int rh = 0); - void setDecorated (bool decorated) { this->decorated = decorated; } - void setFitZoomEnabled (bool fze) { fitZoomEnabled = fze; } - void setObservedCropWin (CropWindow* cw) { observedCropWin = cw; } +public: + CropHandler cropHandler; + CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow); - void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy); - void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy); - void screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy); - void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy); - void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy); - int scaleValueToImage (int value); - float scaleValueToImage (float value); - double scaleValueToImage (double value); - int scaleValueToScreen (int value); - float scaleValueToScreen (float value); - double scaleValueToScreen (double value); - double getZoomFitVal (); - void setPosition (int x, int y); - void getPosition (int& x, int& y); - void setSize (int w, int h, bool norefresh=false); - void getSize (int& w, int& h); - void enable (); + void setDecorated (bool decorated) + { + this->decorated = decorated; + } + void setFitZoomEnabled (bool fze) + { + fitZoomEnabled = fze; + } + void setObservedCropWin (CropWindow* cw) + { + observedCropWin = cw; + } - void leaveNotify (GdkEventCrossing* event); - void flawnOver (bool isFlawnOver); + void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy); + void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy); + void screenCoordToPreview (int phyx, int phyy, int& prevx, int& prevy); + void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy); + void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy); + int scaleValueToImage (int value); + float scaleValueToImage (float value); + double scaleValueToImage (double value); + int scaleValueToScreen (int value); + float scaleValueToScreen (float value); + double scaleValueToScreen (double value); + double getZoomFitVal (); + void setPosition (int x, int y); + void getPosition (int& x, int& y); + void setSize (int w, int h, bool norefresh = false); + void getSize (int& w, int& h); + void enable (); - // zoomlistener interface - void zoomIn (bool toCursor=false, int cursorX=-1, int cursorY=-1); - void zoomOut (bool toCursor=false, int cursorX=-1, int cursorY=-1); - void zoom11 (); - void zoomFit (bool skipZoomIfUnchanged=true); - void zoomFitCrop (); - double getZoom (); - bool isMinZoom (); - bool isMaxZoom (); - void setZoom (double zoom); + void leaveNotify (GdkEventCrossing* event); + void flawnOver (bool isFlawnOver); - void findCenter (int deltaZoom, int& x, int& y); - bool isInside (int x, int y); + // zoomlistener interface + void zoomIn (bool toCursor = false, int cursorX = -1, int cursorY = -1); + void zoomOut (bool toCursor = false, int cursorX = -1, int cursorY = -1); + void zoom11 (); + void zoomFit (bool skipZoomIfUnchanged = true); + void zoomFitCrop (); + double getZoom (); + bool isMinZoom (); + bool isMaxZoom (); + void setZoom (double zoom); + + void findCenter (int deltaZoom, int& x, int& y); + bool isInside (int x, int y); - void buttonPress (int button, int num, int state, int x, int y); - void buttonRelease (int button, int num, int state, int x, int y); - void pointerMoved (int bstate, int x, int y); + void buttonPress (int button, int num, int state, int x, int y); + void buttonRelease (int button, int num, int state, int x, int y); + void pointerMoved (int bstate, int x, int y); - void expose (Cairo::RefPtr cr); + void expose (Cairo::RefPtr cr); - // interface lwbuttonlistener - void buttonPressed (LWButton* button, int actionCode, void* actionData); - void redrawNeeded (LWButton* button); + // interface lwbuttonlistener + void buttonPressed (LWButton* button, int actionCode, void* actionData); + void redrawNeeded (LWButton* button); - // crop handling - void getCropRectangle (int& x, int& y, int& w, int& h); - void getCropPosition (int& x, int& y); - void setCropPosition (int x, int y, bool update = true); - void getCropSize (int& w, int& h); + // crop handling + void getCropRectangle (int& x, int& y, int& w, int& h); + void getCropPosition (int& x, int& y); + void setCropPosition (int x, int y, bool update = true); + void getCropSize (int& w, int& h); - // listeners - void setCropGUIListener (CropGUIListener* cgl) { cropgl = cgl; } - void setPointerMotionListener (PointerMotionListener* pml) { pmlistener = pml; } - void setPointerMotionHListener (PointerMotionListener* pml) { pmhlistener = pml; } + // listeners + void setCropGUIListener (CropGUIListener* cgl) + { + cropgl = cgl; + } + void setPointerMotionListener (PointerMotionListener* pml) + { + pmlistener = pml; + } + void setPointerMotionHListener (PointerMotionListener* pml) + { + pmhlistener = pml; + } - // crop window listeners - void addCropWindowListener (CropWindowListener* l) { listeners.push_back (l); } - void delCropWindowListener (CropWindowListener* l); + // crop window listeners + void addCropWindowListener (CropWindowListener* l) + { + listeners.push_back (l); + } + void delCropWindowListener (CropWindowListener* l); - // crophandlerlistener interface - void cropImageUpdated (); - void cropWindowChanged (); - void initialImageArrived (); + // crophandlerlistener interface + void cropImageUpdated (); + void cropWindowChanged (); + void initialImageArrived (); - void remoteMove (int deltaX, int deltaY); - void remoteMoveReady (); + void remoteMove (int deltaX, int deltaY); + void remoteMoveReady (); - EditDataProvider* getImageArea(); + EditDataProvider* getImageArea(); }; #endif diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc index e0704fe48..45426a557 100644 --- a/rtgui/cursormanager.cc +++ b/rtgui/cursormanager.cc @@ -7,7 +7,7 @@ * 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 @@ -23,7 +23,8 @@ CursorManager cursorManager; -void CursorManager::init (Glib::RefPtr mainWin) { +void CursorManager::init (Glib::RefPtr mainWin) +{ cResizeWidth = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW); cResizeHeight = new Gdk::Cursor (Gdk::SB_V_DOUBLE_ARROW); @@ -62,59 +63,63 @@ void CursorManager::init (Glib::RefPtr mainWin) { } /* Set the cursor of the given window */ -void CursorManager::setCursor (Glib::RefPtr window, CursorShape shape) { +void CursorManager::setCursor (Glib::RefPtr window, CursorShape shape) +{ - if (shape==CSArrow) - // set_cursor without any arguments to select system default + if (shape == CSArrow) + // set_cursor without any arguments to select system default + { window->set_cursor (); - else if (shape==CSOpenHand) + } else if (shape == CSOpenHand) { window->set_cursor (*cHand); - else if (shape==CSClosedHand) + } else if (shape == CSClosedHand) { window->set_cursor (*cClosedHand); - else if (shape==CSMove) + } else if (shape == CSMove) { window->set_cursor (*cCropMove); - else if (shape==CSResizeWidth) + } else if (shape == CSResizeWidth) { window->set_cursor (*cResizeWidth); - else if (shape==CSResizeHeight) + } else if (shape == CSResizeHeight) { window->set_cursor (*cResizeHeight); - else if (shape==CSResizeDiagonal) + } else if (shape == CSResizeDiagonal) { window->set_cursor (*cResizeDiag); - else if (shape==CSResizeTopLeft) + } else if (shape == CSResizeTopLeft) { window->set_cursor (*cResizeTopLeft); - else if (shape==CSResizeTopRight) + } else if (shape == CSResizeTopRight) { window->set_cursor (*cResizeTopRight); - else if (shape==CSResizeBottomLeft) + } else if (shape == CSResizeBottomLeft) { window->set_cursor (*cResizeBottomLeft); - else if (shape==CSResizeBottomRight) + } else if (shape == CSResizeBottomRight) { window->set_cursor (*cResizeBottomRight); - else if (shape==CSMove2D) + } else if (shape == CSMove2D) { window->set_cursor (*cMove2D); - else if (shape==CSMove1DH) + } else if (shape == CSMove1DH) { window->set_cursor (*cMove1DH); - else if (shape==CSMove1DV) + } else if (shape == CSMove1DV) { window->set_cursor (*cMove1DV); - else if (shape==CSMoveRotate) + } else if (shape == CSMoveRotate) { window->set_cursor (*cMoveRotate); - else if (shape==CSSpotWB) + } else if (shape == CSSpotWB) { window->set_cursor (*cWB); - else if (shape==CSCropSelect) + } else if (shape == CSCropSelect) { window->set_cursor (*cHand); - else if (shape==CSMoveLeft) + } else if (shape == CSMoveLeft) { window->set_cursor (*cLeftTanMove); - else if (shape==CSMoveRight) + } else if (shape == CSMoveRight) { window->set_cursor (*cRightTanMove); - else if (shape==CSStraighten) + } else if (shape == CSStraighten) { window->set_cursor (*cHand); - else if (shape==CSWait) + } else if (shape == CSWait) { window->set_cursor (*cWait); - else if (shape==CSPlus) + } else if (shape == CSPlus) { window->set_cursor (*cAdd); - else if (shape==CSEmpty) + } else if (shape == CSEmpty) { window->set_cursor (*cHidden); + } } /* Set the cursor of the main window */ -void CursorManager::setCursor (CursorShape shape) { - setCursor(mainWindow, shape); +void CursorManager::setCursor (CursorShape shape) +{ + setCursor(mainWindow, shape); } diff --git a/rtgui/cursormanager.h b/rtgui/cursormanager.h index 1302708c7..b51fb1e38 100644 --- a/rtgui/cursormanager.h +++ b/rtgui/cursormanager.h @@ -7,7 +7,7 @@ * 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 @@ -29,38 +29,39 @@ enum CursorShape { CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSWait, CSEmpty }; -class CursorManager { +class CursorManager +{ - protected: - Gdk::Cursor* cResizeWidth; - Gdk::Cursor* cResizeHeight; - Gdk::Cursor* cResizeDiag; - Gdk::Cursor* cResizeTopLeft; - Gdk::Cursor* cResizeTopRight; - Gdk::Cursor* cResizeBottomLeft; - Gdk::Cursor* cResizeBottomRight; - Gdk::Cursor* cCropMove; - Gdk::Cursor* cCropMoving; - Gdk::Cursor* cLeftTanMove; - Gdk::Cursor* cRightTanMove; - Gdk::Cursor* cNormal; - Gdk::Cursor* cCropSelection; - Gdk::Cursor* cAdd; - Gdk::Cursor* cWait; - Gdk::Cursor* cHand; - Gdk::Cursor* cClosedHand; - Gdk::Cursor* cWB; - Gdk::Cursor* cHidden; - Gdk::Cursor* cMove2D; - Gdk::Cursor* cMove1DH; - Gdk::Cursor* cMove1DV; - Gdk::Cursor* cMoveRotate; - Glib::RefPtr mainWindow; +protected: + Gdk::Cursor* cResizeWidth; + Gdk::Cursor* cResizeHeight; + Gdk::Cursor* cResizeDiag; + Gdk::Cursor* cResizeTopLeft; + Gdk::Cursor* cResizeTopRight; + Gdk::Cursor* cResizeBottomLeft; + Gdk::Cursor* cResizeBottomRight; + Gdk::Cursor* cCropMove; + Gdk::Cursor* cCropMoving; + Gdk::Cursor* cLeftTanMove; + Gdk::Cursor* cRightTanMove; + Gdk::Cursor* cNormal; + Gdk::Cursor* cCropSelection; + Gdk::Cursor* cAdd; + Gdk::Cursor* cWait; + Gdk::Cursor* cHand; + Gdk::Cursor* cClosedHand; + Gdk::Cursor* cWB; + Gdk::Cursor* cHidden; + Gdk::Cursor* cMove2D; + Gdk::Cursor* cMove1DH; + Gdk::Cursor* cMove1DV; + Gdk::Cursor* cMoveRotate; + Glib::RefPtr mainWindow; - public: - void init (Glib::RefPtr mainWin); - void setCursor (Glib::RefPtr window, CursorShape shape); - void setCursor (CursorShape shape); +public: + void init (Glib::RefPtr mainWin); + void setCursor (Glib::RefPtr window, CursorShape shape); + void setCursor (CursorShape shape); }; extern CursorManager cursorManager; diff --git a/rtgui/curveeditor.cc b/rtgui/curveeditor.cc index 1cadad6a6..840ea25e9 100644 --- a/rtgui/curveeditor.cc +++ b/rtgui/curveeditor.cc @@ -7,7 +7,7 @@ * 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. - * + * * 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. @@ -25,17 +25,19 @@ #include -bool CurveEditor::reset() { - return subGroup->curveReset(this); +bool CurveEditor::reset() +{ + return subGroup->curveReset(this); } -DiagonalCurveEditor::DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : CurveEditor::CurveEditor(text, static_cast(ceGroup), ceSubGroup) { +DiagonalCurveEditor::DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : CurveEditor::CurveEditor(text, static_cast(ceGroup), ceSubGroup) +{ // Order set in the same order than "enum DiagonalCurveType". Shouldn't change, for compatibility reason - curveType->addEntry("curveType-linear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear - curveType->addEntry("curveType-spline.png", M("CURVEEDITOR_CUSTOM")); // 1 Spline - curveType->addEntry("curveType-parametric.png", M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric - curveType->addEntry("curveType-NURBS.png", M("CURVEEDITOR_NURBS")); // 3 NURBS + curveType->addEntry("curveType-linear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear + curveType->addEntry("curveType-spline.png", M("CURVEEDITOR_CUSTOM")); // 1 Spline + curveType->addEntry("curveType-parametric.png", M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric + curveType->addEntry("curveType-NURBS.png", M("CURVEEDITOR_NURBS")); // 3 NURBS curveType->setSelected(DCT_Linear); curveType->show(); @@ -49,50 +51,66 @@ DiagonalCurveEditor::DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* rangeMilestones[2] = 0.75; } -std::vector DiagonalCurveEditor::getCurve () { - std::vector curve; +std::vector DiagonalCurveEditor::getCurve () +{ + std::vector curve; - switch (selected) { - case (DCT_Spline): + switch (selected) { + case (DCT_Spline): return curve = customCurveEd; - case (DCT_Parametric): + + case (DCT_Parametric): return curve = paramCurveEd; - case (DCT_NURBS): + + case (DCT_NURBS): return curve = NURBSCurveEd; - default: - // returning Linear or Unchanged - curve.push_back((double)(selected)); - return curve; - } + + default: + // returning Linear or Unchanged + curve.push_back((double)(selected)); + return curve; + } } -void DiagonalCurveEditor::setResetCurve(DiagonalCurveType cType, const std::vector &resetCurve) { - switch (cType) { - case (DCT_NURBS): - if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) - NURBSResetCurve = resetCurve; - break; - case (DCT_Parametric): - if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) - paramResetCurve = resetCurve; - break; - case (DCT_Spline): - if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) - customResetCurve = resetCurve; - break; - default: - break; - } +void DiagonalCurveEditor::setResetCurve(DiagonalCurveType cType, const std::vector &resetCurve) +{ + switch (cType) { + case (DCT_NURBS): + if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) { + NURBSResetCurve = resetCurve; + } + + break; + + case (DCT_Parametric): + if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) { + paramResetCurve = resetCurve; + } + + break; + + case (DCT_Spline): + if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) { + customResetCurve = resetCurve; + } + + break; + + default: + break; + } } -void DiagonalCurveEditor::setRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4) { +void DiagonalCurveEditor::setRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4) +{ rangeLabels[0] = r1; rangeLabels[1] = r2; rangeLabels[2] = r3; rangeLabels[3] = r4; } -void DiagonalCurveEditor::getRangeLabels(Glib::ustring &r1, Glib::ustring &r2, Glib::ustring &r3, Glib::ustring &r4) { +void DiagonalCurveEditor::getRangeLabels(Glib::ustring &r1, Glib::ustring &r2, Glib::ustring &r3, Glib::ustring &r4) +{ r1 = rangeLabels[0]; r2 = rangeLabels[1]; r3 = rangeLabels[2]; @@ -102,7 +120,8 @@ void DiagonalCurveEditor::getRangeLabels(Glib::ustring &r1, Glib::ustring &r2, G /* * Admittedly that this method is called just after the instantiation of this class, we set the shcselector's default values */ -void DiagonalCurveEditor::setRangeDefaultMilestones(double m1, double m2, double m3) { +void DiagonalCurveEditor::setRangeDefaultMilestones(double m1, double m2, double m3) +{ rangeMilestones[0] = m1; rangeMilestones[1] = m2; rangeMilestones[2] = m3; @@ -112,125 +131,143 @@ void DiagonalCurveEditor::setRangeDefaultMilestones(double m1, double m2, double paramCurveEd.at(3) = m3; } -void DiagonalCurveEditor::getRangeDefaultMilestones(double &m1, double &m2, double &m3) { +void DiagonalCurveEditor::getRangeDefaultMilestones(double &m1, double &m2, double &m3) +{ m1 = rangeMilestones[0]; m2 = rangeMilestones[1]; m3 = rangeMilestones[2]; } -FlatCurveEditor::FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic) : CurveEditor::CurveEditor(text, static_cast(ceGroup), ceSubGroup) { +FlatCurveEditor::FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic) : CurveEditor::CurveEditor(text, static_cast(ceGroup), ceSubGroup) +{ periodic = isPeriodic; identityValue = 0.5; // Order set in the same order than "enum FlatCurveType". Shouldn't change, for compatibility reason - curveType->addEntry("curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear - curveType->addEntry("curveType-controlPoints.png", M("CURVEEDITOR_MINMAXCPOINTS")); // 1 Min/Max ControlPoints + curveType->addEntry("curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear + curveType->addEntry("curveType-controlPoints.png", M("CURVEEDITOR_MINMAXCPOINTS")); // 1 Min/Max ControlPoints curveType->setSelected(FCT_Linear); curveType->show(); } -std::vector FlatCurveEditor::getCurve () { - std::vector curve; +std::vector FlatCurveEditor::getCurve () +{ + std::vector curve; - switch (selected) { - //case (Parametric): + switch (selected) { + //case (Parametric): // return curve = paramCurveEd; - case (FCT_MinMaxCPoints): + case (FCT_MinMaxCPoints): return curve = controlPointsCurveEd; - default: - // returning Linear or Unchanged - curve.push_back((double)(selected)); - return curve; - } + + default: + // returning Linear or Unchanged + curve.push_back((double)(selected)); + return curve; + } } -void FlatCurveEditor::setResetCurve(FlatCurveType cType, const std::vector &resetCurve) { - switch (cType) { - case (FCT_MinMaxCPoints): - if (resetCurve.size() && FlatCurveType(resetCurve.at(0)) == cType) - controlPointsResetCurve = resetCurve; - break; - default: - break; - } +void FlatCurveEditor::setResetCurve(FlatCurveType cType, const std::vector &resetCurve) +{ + switch (cType) { + case (FCT_MinMaxCPoints): + if (resetCurve.size() && FlatCurveType(resetCurve.at(0)) == cType) { + controlPointsResetCurve = resetCurve; + } + + break; + + default: + break; + } } /* * CurveEditor (CurveEditorGroup* ceGroup, Glib::ustring text) * * parameters: - * ceGroup = NULL or the address of the Widget that will receive the CurveTypeToggleButton - * text = (optional) label of the curve, displayed in the CurveTypeToggleButton, next to the image + * ceGroup = NULL or the address of the Widget that will receive the CurveTypeToggleButton + * text = (optional) label of the curve, displayed in the CurveTypeToggleButton, next to the image */ -CurveEditor::CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : EditSubscriber(ET_PIPETTE) { +CurveEditor::CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : EditSubscriber(ET_PIPETTE) +{ - bgHistValid = false; - remoteDrag = false; - selected = DCT_Linear; - bottomBarCP = NULL; - leftBarCP = NULL; - curveCP = NULL; - relatedWidget = NULL; + bgHistValid = false; + remoteDrag = false; + selected = DCT_Linear; + bottomBarCP = NULL; + leftBarCP = NULL; + curveCP = NULL; + relatedWidget = NULL; - group = ceGroup; - subGroup = ceSubGroup; + group = ceGroup; + subGroup = ceSubGroup; - if (group && text.size()) - curveType = new PopUpToggleButton(text + ":"); - else - curveType = new PopUpToggleButton(); + if (group && text.size()) { + curveType = new PopUpToggleButton(text + ":"); + } else { + curveType = new PopUpToggleButton(); + } - curveType->set_tooltip_text(M("CURVEEDITOR_TYPE")); - // TODO: Does this signal have to be blocked when on curve type change ? - curveType->signal_toggled().connect ( sigc::mem_fun(*this, &CurveEditor::curveTypeToggled) ); - typeconn = curveType->signal_changed().connect (sigc::mem_fun(*this, &CurveEditor::typeSelectionChanged) ); + curveType->set_tooltip_text(M("CURVEEDITOR_TYPE")); + // TODO: Does this signal have to be blocked when on curve type change ? + curveType->signal_toggled().connect ( sigc::mem_fun(*this, &CurveEditor::curveTypeToggled) ); + typeconn = curveType->signal_changed().connect (sigc::mem_fun(*this, &CurveEditor::typeSelectionChanged) ); } -void CurveEditor::setCurve (const std::vector& p) { - tempCurve = p; - group->setCurveExternal(this, p); +void CurveEditor::setCurve (const std::vector& p) +{ + tempCurve = p; + group->setCurveExternal(this, p); } -CurveEditor::~CurveEditor () { +CurveEditor::~CurveEditor () +{ delete curveType; } -void CurveEditor::typeSelectionChanged (int n) { - group->typeSelectionChanged(this, n); +void CurveEditor::typeSelectionChanged (int n) +{ + group->typeSelectionChanged(this, n); } -void CurveEditor::curveTypeToggled() { - group->curveTypeToggled(this); +void CurveEditor::curveTypeToggled() +{ + group->curveTypeToggled(this); } -bool CurveEditor::isUnChanged () { - return curveType->getSelected()==subGroup->getValUnchanged(); +bool CurveEditor::isUnChanged () +{ + return curveType->getSelected() == subGroup->getValUnchanged(); } -void CurveEditor::setUnChanged (bool uc) { - group->setUnChanged(uc, this); +void CurveEditor::setUnChanged (bool uc) +{ + group->setUnChanged(uc, this); } /* * Update the backgrounds histograms */ -void CurveEditor::updateBackgroundHistogram (LUTu & hist) { - // Copy the histogram in the curve editor cache - if (hist) { - histogram=hist; - bgHistValid = true; - } - else - bgHistValid = false; - - // Then call the curve editor group to eventually update the histogram - subGroup->updateBackgroundHistogram (this); +void CurveEditor::updateBackgroundHistogram (LUTu & hist) +{ + // Copy the histogram in the curve editor cache + if (hist) { + histogram = hist; + bgHistValid = true; + } else { + bgHistValid = false; + } + + // Then call the curve editor group to eventually update the histogram + subGroup->updateBackgroundHistogram (this); } // Open up the curve if it has modifications and it's not already opened // Returns: true if curve was non linear and opened -bool CurveEditor::openIfNonlinear() { +bool CurveEditor::openIfNonlinear() +{ bool nonLinear = tempCurve.size() && (tempCurve[0] > subGroup->getValLinear()) && (tempCurve[0] < subGroup->getValUnchanged()); @@ -243,131 +280,161 @@ bool CurveEditor::openIfNonlinear() { } // Handles markup tooltips -void CurveEditor::setTooltip(Glib::ustring ttip) { - curveType->set_tooltip_text(ttip.empty() ? - Glib::ustring::compose("%1 ", M("CURVEEDITOR_TYPE")) : - Glib::ustring::compose("%1\n%2", ttip, M("CURVEEDITOR_TYPE"))); +void CurveEditor::setTooltip(Glib::ustring ttip) +{ + curveType->set_tooltip_text(ttip.empty() ? + Glib::ustring::compose("%1 ", M("CURVEEDITOR_TYPE")) : + Glib::ustring::compose("%1\n%2", ttip, M("CURVEEDITOR_TYPE"))); } -void CurveEditor::setLeftBarColorProvider(ColorProvider* cp, int callerId) { - leftBarCP = cp; - leftBarCId = callerId; +void CurveEditor::setLeftBarColorProvider(ColorProvider* cp, int callerId) +{ + leftBarCP = cp; + leftBarCId = callerId; } -void CurveEditor::setBottomBarColorProvider(ColorProvider* cp, int callerId) { - bottomBarCP = cp; - bottomBarCId = callerId; +void CurveEditor::setBottomBarColorProvider(ColorProvider* cp, int callerId) +{ + bottomBarCP = cp; + bottomBarCId = callerId; } -void CurveEditor::setLeftBarBgGradient (const std::vector &milestones) { - leftBarBgGradient = milestones; +void CurveEditor::setLeftBarBgGradient (const std::vector &milestones) +{ + leftBarBgGradient = milestones; } -void CurveEditor::setBottomBarBgGradient (const std::vector &milestones) { - bottomBarBgGradient = milestones; +void CurveEditor::setBottomBarBgGradient (const std::vector &milestones) +{ + bottomBarBgGradient = milestones; } -void CurveEditor::refresh () { - subGroup->refresh(this); +void CurveEditor::refresh () +{ + subGroup->refresh(this); } -void CurveEditor::setCurveColorProvider(ColorProvider* cp, int callerId) { - curveCP = cp; - curveCId = callerId; +void CurveEditor::setCurveColorProvider(ColorProvider* cp, int callerId) +{ + curveCP = cp; + curveCId = callerId; } -ColorProvider* CurveEditor::getLeftBarColorProvider() { - return leftBarCP; +ColorProvider* CurveEditor::getLeftBarColorProvider() +{ + return leftBarCP; } -ColorProvider* CurveEditor::getBottomBarColorProvider() { - return bottomBarCP; +ColorProvider* CurveEditor::getBottomBarColorProvider() +{ + return bottomBarCP; } -ColorProvider* CurveEditor::getCurveColorProvider() { - return curveCP; +ColorProvider* CurveEditor::getCurveColorProvider() +{ + return curveCP; } -int CurveEditor::getLeftBarCallerId() { - return leftBarCId; +int CurveEditor::getLeftBarCallerId() +{ + return leftBarCId; } -int CurveEditor::getBottomBarCallerId() { - return bottomBarCId; +int CurveEditor::getBottomBarCallerId() +{ + return bottomBarCId; } -int CurveEditor::getCurveCallerId() { - return curveCId; +int CurveEditor::getCurveCallerId() +{ + return curveCId; } -std::vector CurveEditor::getBottomBarBgGradient () const { - return bottomBarBgGradient; +std::vector CurveEditor::getBottomBarBgGradient () const +{ + return bottomBarBgGradient; } -std::vector CurveEditor::getLeftBarBgGradient () const { - return leftBarBgGradient; +std::vector CurveEditor::getLeftBarBgGradient () const +{ + return leftBarBgGradient; } -sigc::signal CurveEditor::signal_curvegraph_enter() { - return sig_curvegraph_enter; +sigc::signal CurveEditor::signal_curvegraph_enter() +{ + return sig_curvegraph_enter; } -sigc::signal CurveEditor::signal_curvegraph_leave() { - return sig_curvegraph_leave; +sigc::signal CurveEditor::signal_curvegraph_leave() +{ + return sig_curvegraph_leave; } -sigc::signal CurveEditor::signal_curvepoint_click() { - return sig_curvepoint_click; +sigc::signal CurveEditor::signal_curvepoint_click() +{ + return sig_curvepoint_click; } -sigc::signal CurveEditor::signal_curvepoint_release() { - return sig_curvepoint_release; +sigc::signal CurveEditor::signal_curvepoint_release() +{ + return sig_curvepoint_release; } -void CurveEditor::switchOffEditMode () { - if (EditSubscriber::getEditID() != EUID_None) { - // switching off the toggle button - if (group->displayedCurve == this) { - subGroup->editModeSwitchedOff(); - } - } - EditSubscriber::switchOffEditMode(); // disconnect +void CurveEditor::switchOffEditMode () +{ + if (EditSubscriber::getEditID() != EUID_None) { + // switching off the toggle button + if (group->displayedCurve == this) { + subGroup->editModeSwitchedOff(); + } + } + + EditSubscriber::switchOffEditMode(); // disconnect } -bool CurveEditor::mouseOver(int modifierKey) { - EditDataProvider* provider = getEditProvider(); - subGroup->pipetteMouseOver(provider, modifierKey); - subGroup->refresh(this); - return true; // return true will ask the preview to be redrawn, for the cursor +bool CurveEditor::mouseOver(int modifierKey) +{ + EditDataProvider* provider = getEditProvider(); + subGroup->pipetteMouseOver(provider, modifierKey); + subGroup->refresh(this); + return true; // return true will ask the preview to be redrawn, for the cursor } -bool CurveEditor::button1Pressed(int modifierKey) { - EditDataProvider* provider = getEditProvider(); - if (provider->object) { - subGroup->pipetteButton1Pressed(provider, modifierKey); - remoteDrag = true; - } - subGroup->refresh(this); - return true; +bool CurveEditor::button1Pressed(int modifierKey) +{ + EditDataProvider* provider = getEditProvider(); + + if (provider->object) { + subGroup->pipetteButton1Pressed(provider, modifierKey); + remoteDrag = true; + } + + subGroup->refresh(this); + return true; } -bool CurveEditor::button1Released() { - EditDataProvider* provider = getEditProvider(); - subGroup->pipetteButton1Released(provider); - remoteDrag = false; - subGroup->refresh(this); - return true; +bool CurveEditor::button1Released() +{ + EditDataProvider* provider = getEditProvider(); + subGroup->pipetteButton1Released(provider); + remoteDrag = false; + subGroup->refresh(this); + return true; } -bool CurveEditor::drag(int modifierKey) { - EditDataProvider* provider = getEditProvider(); - subGroup->pipetteDrag(provider, modifierKey); - subGroup->refresh(this); - return false; +bool CurveEditor::drag(int modifierKey) +{ + EditDataProvider* provider = getEditProvider(); + subGroup->pipetteDrag(provider, modifierKey); + subGroup->refresh(this); + return false; } -CursorShape CurveEditor::getCursor(int objectID) { - if (remoteDrag) - return CSResizeHeight; - return CSOpenHand; +CursorShape CurveEditor::getCursor(int objectID) +{ + if (remoteDrag) { + return CSResizeHeight; + } + + return CSOpenHand; } diff --git a/rtgui/curveeditor.h b/rtgui/curveeditor.h index aafe3a1a9..2708c4df2 100644 --- a/rtgui/curveeditor.h +++ b/rtgui/curveeditor.h @@ -7,7 +7,7 @@ * 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 @@ -39,96 +39,100 @@ class CurveEditorSubGroup; * This class is an interface between RT and the curve editor group ; it handles the methods * related to a specific curve. It is created by CurveEditorGroup::addCurve */ -class CurveEditor : public EditSubscriber { +class CurveEditor : public EditSubscriber +{ - friend class CurveEditorGroup; - friend class CurveEditorSubGroup; - friend class DiagonalCurveEditorSubGroup; - friend class FlatCurveEditorSubGroup; - friend class DiagonalCurveEditor; - friend class FlatCurveEditor; + friend class CurveEditorGroup; + friend class CurveEditorSubGroup; + friend class DiagonalCurveEditorSubGroup; + friend class FlatCurveEditorSubGroup; + friend class DiagonalCurveEditor; + friend class FlatCurveEditor; - protected: +protected: - /* - * The curve editor contains only one widget (the curve type button) to receive the signals - * but it's co-handled by the CurveEditorGroup too - */ + /* + * The curve editor contains only one widget (the curve type button) to receive the signals + * but it's co-handled by the CurveEditorGroup too + */ - PopUpToggleButton* curveType; - LUTu histogram; // histogram values - bool bgHistValid; + PopUpToggleButton* curveType; + LUTu histogram; // histogram values + bool bgHistValid; - bool remoteDrag; + bool remoteDrag; - int selected; + int selected; - CurveEditorGroup* group; - CurveEditorSubGroup* subGroup; - Gtk::Widget* relatedWidget; + CurveEditorGroup* group; + CurveEditorSubGroup* subGroup; + Gtk::Widget* relatedWidget; - std::vector tempCurve; - sigc::connection typeconn; + std::vector tempCurve; + sigc::connection typeconn; - ColorProvider* bottomBarCP; - ColorProvider* leftBarCP; - ColorProvider* curveCP; - int bottomBarCId; - int leftBarCId; - int curveCId; - std::vector bottomBarBgGradient; - std::vector leftBarBgGradient; + ColorProvider* bottomBarCP; + ColorProvider* leftBarCP; + ColorProvider* curveCP; + int bottomBarCId; + int leftBarCId; + int curveCId; + std::vector bottomBarBgGradient; + std::vector leftBarBgGradient; - sigc::signal sig_curvegraph_enter; - sigc::signal sig_curvegraph_leave; - sigc::signal sig_curvepoint_click; - sigc::signal sig_curvepoint_release; + sigc::signal sig_curvegraph_enter; + sigc::signal sig_curvegraph_leave; + sigc::signal sig_curvepoint_click; + sigc::signal sig_curvepoint_release; - public: +public: - CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup); - virtual ~CurveEditor (); - void typeSelectionChanged (int n); - void curveTypeToggled(); - bool isUnChanged (); - void setUnChanged (bool uc); - void updateBackgroundHistogram (LUTu & hist); + CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup); + virtual ~CurveEditor (); + void typeSelectionChanged (int n); + void curveTypeToggled(); + bool isUnChanged (); + void setUnChanged (bool uc); + void updateBackgroundHistogram (LUTu & hist); - void setLeftBarColorProvider(ColorProvider* cp, int callerId); - void setBottomBarColorProvider(ColorProvider* cp, int callerId); - void setCurveColorProvider(ColorProvider* cp, int callerId); - void setBottomBarBgGradient (const std::vector &milestones); - void setLeftBarBgGradient (const std::vector &milestones); - ColorProvider* getLeftBarColorProvider(); - ColorProvider* getBottomBarColorProvider(); - ColorProvider* getCurveColorProvider(); - int getLeftBarCallerId(); - int getBottomBarCallerId(); - int getCurveCallerId(); - std::vector getBottomBarBgGradient () const; - std::vector getLeftBarBgGradient () const; + void setLeftBarColorProvider(ColorProvider* cp, int callerId); + void setBottomBarColorProvider(ColorProvider* cp, int callerId); + void setCurveColorProvider(ColorProvider* cp, int callerId); + void setBottomBarBgGradient (const std::vector &milestones); + void setLeftBarBgGradient (const std::vector &milestones); + ColorProvider* getLeftBarColorProvider(); + ColorProvider* getBottomBarColorProvider(); + ColorProvider* getCurveColorProvider(); + int getLeftBarCallerId(); + int getBottomBarCallerId(); + int getCurveCallerId(); + std::vector getBottomBarBgGradient () const; + std::vector getLeftBarBgGradient () const; - void refresh (); // refresh the display of the CurveEditor (e.g. when a ColoredBar has been changed from the outside) - bool openIfNonlinear(); // Open up the curve if it has modifications and it's not already opened + void refresh (); // refresh the display of the CurveEditor (e.g. when a ColoredBar has been changed from the outside) + bool openIfNonlinear(); // Open up the curve if it has modifications and it's not already opened - void setCurve (const std::vector& p); - virtual void setIdentityValue (const double iValue=0.5) {}; - virtual double getIdentityValue () { return 0.5; }; - virtual std::vector getCurve () = 0; - bool reset(); - void setTooltip(Glib::ustring ttip); + void setCurve (const std::vector& p); + virtual void setIdentityValue (const double iValue = 0.5) {}; + virtual double getIdentityValue () + { + return 0.5; + }; + virtual std::vector getCurve () = 0; + bool reset(); + void setTooltip(Glib::ustring ttip); - sigc::signal signal_curvegraph_enter(); - sigc::signal signal_curvegraph_leave(); - sigc::signal signal_curvepoint_click(); - sigc::signal signal_curvepoint_release(); + sigc::signal signal_curvegraph_enter(); + sigc::signal signal_curvegraph_leave(); + sigc::signal signal_curvepoint_click(); + sigc::signal signal_curvepoint_release(); - void switchOffEditMode (); - bool mouseOver(int modifierKey); - bool button1Pressed(int modifierKey); - bool button1Released(); - bool drag(int modifierKey); - CursorShape getCursor(int objectID); + void switchOffEditMode (); + bool mouseOver(int modifierKey); + bool button1Pressed(int modifierKey); + bool button1Released(); + bool drag(int modifierKey); + CursorShape getCursor(int objectID); }; @@ -139,31 +143,32 @@ class CurveEditor : public EditSubscriber { */ -class DiagonalCurveEditor : public CurveEditor { +class DiagonalCurveEditor : public CurveEditor +{ - friend class DiagonalCurveEditorSubGroup; + friend class DiagonalCurveEditorSubGroup; - protected: - // reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value - std::vector customCurveEd; - std::vector customResetCurve; - std::vector paramCurveEd; - std::vector paramResetCurve; - std::vector NURBSCurveEd; - std::vector NURBSResetCurve; - Glib::ustring rangeLabels[4]; - double rangeMilestones[3]; +protected: + // reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value + std::vector customCurveEd; + std::vector customResetCurve; + std::vector paramCurveEd; + std::vector paramResetCurve; + std::vector NURBSCurveEd; + std::vector NURBSResetCurve; + Glib::ustring rangeLabels[4]; + double rangeMilestones[3]; - public: - DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup); - std::vector getCurve (); - void setRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4); - void getRangeLabels(Glib::ustring &r1, Glib::ustring &r2, Glib::ustring &r3, Glib::ustring &r4); - void setRangeDefaultMilestones(double m1, double m2, double m3); - void getRangeDefaultMilestones(double &m1, double &m2, double &m3); +public: + DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup); + std::vector getCurve (); + void setRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4); + void getRangeLabels(Glib::ustring &r1, Glib::ustring &r2, Glib::ustring &r3, Glib::ustring &r4); + void setRangeDefaultMilestones(double m1, double m2, double m3); + void getRangeDefaultMilestones(double &m1, double &m2, double &m3); - // set the reset curve for a given curve type. This is optional; all curve type have a default reset curve - void setResetCurve(DiagonalCurveType cType, const std::vector &resetCurve); + // set the reset curve for a given curve type. This is optional; all curve type have a default reset curve + void setResetCurve(DiagonalCurveType cType, const std::vector &resetCurve); }; @@ -172,25 +177,32 @@ class DiagonalCurveEditor : public CurveEditor { */ -class FlatCurveEditor : public CurveEditor { +class FlatCurveEditor : public CurveEditor +{ - friend class FlatCurveEditorSubGroup; + friend class FlatCurveEditorSubGroup; - protected: - // reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value - std::vector controlPointsCurveEd; - std::vector controlPointsResetCurve; - bool periodic; - double identityValue; +protected: + // reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value + std::vector controlPointsCurveEd; + std::vector controlPointsResetCurve; + bool periodic; + double identityValue; - public: - FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic = true); - virtual void setIdentityValue (const double iValue=0.5) { identityValue = iValue; } - virtual double getIdentityValue () { return identityValue; }; - std::vector getCurve (); +public: + FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic = true); + virtual void setIdentityValue (const double iValue = 0.5) + { + identityValue = iValue; + } + virtual double getIdentityValue () + { + return identityValue; + }; + std::vector getCurve (); - // set the reset curve for a given curve type. This is optional; all curve type have a default reset curve - void setResetCurve(FlatCurveType cType, const std::vector &resetCurve); + // set the reset curve for a given curve type. This is optional; all curve type have a default reset curve + void setResetCurve(FlatCurveType cType, const std::vector &resetCurve); }; #endif diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index ae3c7d141..c1915436d 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -7,7 +7,7 @@ * 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 @@ -28,30 +28,37 @@ #include "rtimage.h" CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel) : curveDir(curveDir), curve_reset(NULL), - displayedCurve(0), flatSubGroup(0), diagonalSubGroup(0), cl(NULL), numberOfPackedCurve(0) + displayedCurve(0), flatSubGroup(0), diagonalSubGroup(0), cl(NULL), numberOfPackedCurve(0) { - // We set the label to the one provided as parameter, even if it's an empty string - curveGroupLabel = Gtk::manage (new Gtk::Label (groupLabel+":", Gtk::ALIGN_LEFT)); + // We set the label to the one provided as parameter, even if it's an empty string + curveGroupLabel = Gtk::manage (new Gtk::Label (groupLabel + ":", Gtk::ALIGN_LEFT)); } -CurveEditorGroup::~CurveEditorGroup() { - for (std::vector::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) - { +CurveEditorGroup::~CurveEditorGroup() +{ + for (std::vector::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) { delete *i; } + delete flatSubGroup; delete diagonalSubGroup; } -void CurveEditorGroup::hideCurrentCurve() { - // Setting the curve type to 'Unchanged' hide the CurveEditor - if (diagonalSubGroup) - diagonalSubGroup->stopNumericalAdjustment(); - if (flatSubGroup) - flatSubGroup->stopNumericalAdjustment(); - if (displayedCurve) - displayedCurve->curveType->set_active(false); +void CurveEditorGroup::hideCurrentCurve() +{ + // Setting the curve type to 'Unchanged' hide the CurveEditor + if (diagonalSubGroup) { + diagonalSubGroup->stopNumericalAdjustment(); + } + + if (flatSubGroup) { + flatSubGroup->stopNumericalAdjustment(); + } + + if (displayedCurve) { + displayedCurve->curveType->set_active(false); + } } /* @@ -67,74 +74,84 @@ void CurveEditorGroup::hideCurrentCurve() { * periodic: for FlatCurve only, ask the curve to be periodic (default: True) * */ -CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabel, Gtk::Widget *relatedWidget, bool periodic) { - switch (cType) { - case (CT_Diagonal): - { - if (!diagonalSubGroup) { - diagonalSubGroup = new DiagonalCurveEditorSubGroup(this, curveDir); - } - // We add it to the curve editor list - DiagonalCurveEditor* newCE = diagonalSubGroup->addCurve(curveLabel); - newCE->relatedWidget = relatedWidget; - curveEditors.push_back(newCE); - return (newCE); - } - case (CT_Flat): - { - if (!flatSubGroup) { - flatSubGroup = new FlatCurveEditorSubGroup(this, curveDir); - } - // We add it to the curve editor list - FlatCurveEditor* newCE = flatSubGroup->addCurve(curveLabel, periodic); - newCE->relatedWidget = relatedWidget; - curveEditors.push_back(newCE); - return (newCE); - } - default: - return (static_cast(NULL)); - break; - } - return NULL; // to avoid complains from Gcc +CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabel, Gtk::Widget *relatedWidget, bool periodic) +{ + switch (cType) { + case (CT_Diagonal): { + if (!diagonalSubGroup) { + diagonalSubGroup = new DiagonalCurveEditorSubGroup(this, curveDir); + } + + // We add it to the curve editor list + DiagonalCurveEditor* newCE = diagonalSubGroup->addCurve(curveLabel); + newCE->relatedWidget = relatedWidget; + curveEditors.push_back(newCE); + return (newCE); + } + + case (CT_Flat): { + if (!flatSubGroup) { + flatSubGroup = new FlatCurveEditorSubGroup(this, curveDir); + } + + // We add it to the curve editor list + FlatCurveEditor* newCE = flatSubGroup->addCurve(curveLabel, periodic); + newCE->relatedWidget = relatedWidget; + curveEditors.push_back(newCE); + return (newCE); + } + + default: + return (static_cast(NULL)); + break; + } + + return NULL; // to avoid complains from Gcc } /* * Use this method to start a new line of button */ -void CurveEditorGroup::newLine() { - Gtk::HBox* headerBox; +void CurveEditorGroup::newLine() +{ + Gtk::HBox* headerBox; - if (curveEditors.size() > numberOfPackedCurve) { - headerBox = Gtk::manage (new Gtk::HBox ()); + if (curveEditors.size() > numberOfPackedCurve) { + headerBox = Gtk::manage (new Gtk::HBox ()); - if (!numberOfPackedCurve) { - headerBox->pack_start(*curveGroupLabel, Gtk::PACK_SHRINK, 2); + if (!numberOfPackedCurve) { + headerBox->pack_start(*curveGroupLabel, Gtk::PACK_SHRINK, 2); - curve_reset = Gtk::manage (new Gtk::Button ()); - curve_reset->add (*Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); - curve_reset->set_relief (Gtk::RELIEF_NONE); - curve_reset->set_border_width (0); - curve_reset->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLINEAR")); - curve_reset->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::curveResetPressed) ); + curve_reset = Gtk::manage (new Gtk::Button ()); + curve_reset->add (*Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); + curve_reset->set_relief (Gtk::RELIEF_NONE); + curve_reset->set_border_width (0); + curve_reset->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLINEAR")); + curve_reset->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::curveResetPressed) ); - headerBox->pack_end (*curve_reset, Gtk::PACK_SHRINK, 0); - } + headerBox->pack_end (*curve_reset, Gtk::PACK_SHRINK, 0); + } - int j = numberOfPackedCurve; - bool hasRelatedWidget = false; - for (int i = (int)(curveEditors.size())-1; i >= j; i--) { - if (curveEditors[i]->relatedWidget != NULL) - hasRelatedWidget = true; - } - for (int i = (int)(curveEditors.size())-1; i >= j; i--) { - if (curveEditors[i]->relatedWidget != NULL) - headerBox->pack_end (*curveEditors[i]->relatedWidget, Gtk::PACK_EXPAND_WIDGET, 2); - headerBox->pack_end (*curveEditors[i]->curveType->buttonGroup, hasRelatedWidget ? Gtk::PACK_SHRINK : Gtk::PACK_EXPAND_WIDGET, 2); - numberOfPackedCurve++; - } + int j = numberOfPackedCurve; + bool hasRelatedWidget = false; - pack_start (*headerBox, Gtk::PACK_SHRINK, 2); - } + for (int i = (int)(curveEditors.size()) - 1; i >= j; i--) { + if (curveEditors[i]->relatedWidget != NULL) { + hasRelatedWidget = true; + } + } + + for (int i = (int)(curveEditors.size()) - 1; i >= j; i--) { + if (curveEditors[i]->relatedWidget != NULL) { + headerBox->pack_end (*curveEditors[i]->relatedWidget, Gtk::PACK_EXPAND_WIDGET, 2); + } + + headerBox->pack_end (*curveEditors[i]->curveType->buttonGroup, hasRelatedWidget ? Gtk::PACK_SHRINK : Gtk::PACK_EXPAND_WIDGET, 2); + numberOfPackedCurve++; + } + + pack_start (*headerBox, Gtk::PACK_SHRINK, 2); + } } @@ -144,226 +161,266 @@ void CurveEditorGroup::newLine() { * This method should handle all curve number correctly, i.e. eventually display the curve type buttons * in a grid (or table) */ -void CurveEditorGroup::curveListComplete() { - newLine(); +void CurveEditorGroup::curveListComplete() +{ + newLine(); - // We check the length of the label ; if it contains only one char (':'), we set it to the right default string - if (curveGroupLabel->get_label().size()==1) - curveGroupLabel->set_label(M(curveEditors.size() > 1 ? "CURVEEDITOR_CURVES" : "CURVEEDITOR_CURVE") + ":"); + // We check the length of the label ; if it contains only one char (':'), we set it to the right default string + if (curveGroupLabel->get_label().size() == 1) { + curveGroupLabel->set_label(M(curveEditors.size() > 1 ? "CURVEEDITOR_CURVES" : "CURVEEDITOR_CURVE") + ":"); + } - if (curveEditors.size() > 1) - cl->setMulti(true); + if (curveEditors.size() > 1) { + cl->setMulti(true); + } } /* * Callback method used when a curve type button has changed ; * it will activate the button, and so emit 'signal_toggled' (-> curveTypeToggled here under) */ -void CurveEditorGroup::typeSelectionChanged (CurveEditor* ce, int n) { - // Same type : do nothing - if (ce==displayedCurve && n==(int)ce->selected) - return; +void CurveEditorGroup::typeSelectionChanged (CurveEditor* ce, int n) +{ + // Same type : do nothing + if (ce == displayedCurve && n == (int)ce->selected) { + return; + } - if (nsubGroup->valUnchanged) - ce->selected = n; + if (n < ce->subGroup->valUnchanged) { + ce->selected = n; + } - // The user selected a new type from a toggled off button - if (ce!=displayedCurve) - // We toggle off the other curve: it will emit the toggle off signal - hideCurrentCurve(); + // The user selected a new type from a toggled off button + if (ce != displayedCurve) + // We toggle off the other curve: it will emit the toggle off signal + { + hideCurrentCurve(); + } - // If the button was not pressed before - if (!ce->curveType->get_active()) { - ce->subGroup->storeDisplayedCurve(); - // We set it pressed : it will emit the toggle on signal and update the GUI - ce->curveType->set_active( n>ce->subGroup->valLinear && nsubGroup->valUnchanged ); - if (n==ce->subGroup->valLinear || n==ce->subGroup->valUnchanged) { - // Since we do not activate the curve when the user switch the toggled off button to 'Linear', we have to - // to call the curve listener manually, because 'curveChanged' uses displayedCurve... - if (cl) { - if (cl->isMulti()) - cl->curveChanged (ce); - else - cl->curveChanged (); - } - } - else - curveChanged (); - } - else { - // The button is already pressed so we switch the GUI ourselves - ce->subGroup->switchGUI(); - curveChanged (); - } + // If the button was not pressed before + if (!ce->curveType->get_active()) { + ce->subGroup->storeDisplayedCurve(); + // We set it pressed : it will emit the toggle on signal and update the GUI + ce->curveType->set_active( n > ce->subGroup->valLinear && n < ce->subGroup->valUnchanged ); + + if (n == ce->subGroup->valLinear || n == ce->subGroup->valUnchanged) { + // Since we do not activate the curve when the user switch the toggled off button to 'Linear', we have to + // to call the curve listener manually, because 'curveChanged' uses displayedCurve... + if (cl) { + if (cl->isMulti()) { + cl->curveChanged (ce); + } else { + cl->curveChanged (); + } + } + } else { + curveChanged (); + } + } else { + // The button is already pressed so we switch the GUI ourselves + ce->subGroup->switchGUI(); + curveChanged (); + } } /* * Callback method used when a button has been toggled on/off * It then hide any other displayed curve and display it's curve */ -void CurveEditorGroup::curveTypeToggled(CurveEditor* ce) { - bool curveRestored = false; +void CurveEditorGroup::curveTypeToggled(CurveEditor* ce) +{ + bool curveRestored = false; - if (displayedCurve) { - EditDataProvider* editProvider = displayedCurve->getEditProvider(); - if (editProvider && editProvider->getCurrSubscriber() == displayedCurve) - displayedCurve->switchOffEditMode(); - } + if (displayedCurve) { + EditDataProvider* editProvider = displayedCurve->getEditProvider(); - // Looking for the button state - if (ce->curveType->get_active()) { - // The button is now pressed, so we have to first hide all other CurveEditor - hideCurrentCurve(); + if (editProvider && editProvider->getCurrSubscriber() == displayedCurve) { + displayedCurve->switchOffEditMode(); + } + } - displayedCurve = ce; + // Looking for the button state + if (ce->curveType->get_active()) { + // The button is now pressed, so we have to first hide all other CurveEditor + hideCurrentCurve(); - if (ce->curveType->getSelected()==ce->subGroup->valUnchanged) { - curveRestored = true; - ce->curveType->setSelected(ce->selected); - } + displayedCurve = ce; - // then show this CurveEditor - int ct = ce->curveType->getSelected(); - if (ct < ce->subGroup->valUnchanged) - ce->subGroup->restoreDisplayedHistogram(); - } - else { - // The button is now released, so we have to hide this CurveEditor - displayedCurve = 0; - } - ce->subGroup->switchGUI(); + if (ce->curveType->getSelected() == ce->subGroup->valUnchanged) { + curveRestored = true; + ce->curveType->setSelected(ce->selected); + } - if (curveRestored) - curveChanged (); + // then show this CurveEditor + int ct = ce->curveType->getSelected(); + + if (ct < ce->subGroup->valUnchanged) { + ce->subGroup->restoreDisplayedHistogram(); + } + } else { + // The button is now released, so we have to hide this CurveEditor + displayedCurve = 0; + } + + ce->subGroup->switchGUI(); + + if (curveRestored) { + curveChanged (); + } } /* * Update the GUI if the given curveEditor is currently displayed */ -void CurveEditorGroup::updateGUI (CurveEditor* ce) { - if (!ce) { - return; +void CurveEditorGroup::updateGUI (CurveEditor* ce) +{ + if (!ce) { + return; } - // we update the curve type button to the corresponding curve type, only if it is not currently set to 'Unchanged' - if (ce->curveType->getSelected()subGroup->valUnchanged) - ce->curveType->setSelected(ce->selected); + // we update the curve type button to the corresponding curve type, only if it is not currently set to 'Unchanged' + if (ce->curveType->getSelected() < ce->subGroup->valUnchanged) { + ce->curveType->setSelected(ce->selected); + } // if not displayed or "unchanged" is selected, do not change gui - if (ce==displayedCurve && ce->curveType->getSelected()subGroup->valUnchanged) { - ce->subGroup->switchGUI(); + if (ce == displayedCurve && ce->curveType->getSelected() < ce->subGroup->valUnchanged) { + ce->subGroup->switchGUI(); } } /* * Called from the outside to set the curve type & values */ -void CurveEditorGroup::setCurveExternal (CurveEditor* ce, const std::vector& c) { - if (!c.empty()) { - ce->subGroup->storeCurveValues(ce, c); // The new curve is saved in the CurveEditor - (ce)->selected = c[0]; // We set the selected curve type in the CurveEditor to the one of the specified curve - } - updateGUI(static_cast(ce)); // And we update the GUI if necessary +void CurveEditorGroup::setCurveExternal (CurveEditor* ce, const std::vector& c) +{ + if (!c.empty()) { + ce->subGroup->storeCurveValues(ce, c); // The new curve is saved in the CurveEditor + (ce)->selected = c[0]; // We set the selected curve type in the CurveEditor to the one of the specified curve + } + + updateGUI(static_cast(ce)); // And we update the GUI if necessary } /* * Listener called when the user has modified the curve */ -void CurveEditorGroup::curveChanged () { +void CurveEditorGroup::curveChanged () +{ + + displayedCurve->subGroup->storeDisplayedCurve(); - displayedCurve->subGroup->storeDisplayedCurve(); if (cl) { - if (cl->isMulti()) - cl->curveChanged (displayedCurve); - else - cl->curveChanged (); + if (cl->isMulti()) { + cl->curveChanged (displayedCurve); + } else { + cl->curveChanged (); + } } } /* * Listener called when the user has modified the curve */ -float CurveEditorGroup::blendPipetteValues (CurveEditor* ce, float chan1, float chan2, float chan3) { +float CurveEditorGroup::blendPipetteValues (CurveEditor* ce, float chan1, float chan2, float chan3) +{ - if (cl) - return cl->blendPipetteValues(ce, chan1, chan2, chan3); + if (cl) { + return cl->blendPipetteValues(ce, chan1, chan2, chan3); + } - return -1.f; + return -1.f; } /* * Call back method when the reset button is pressed : * reset the currently toggled on curve editor */ -void CurveEditorGroup::curveResetPressed () { - if (displayedCurve) { - if (displayedCurve->subGroup->curveReset(displayedCurve)) { - curveChanged(); - } - } +void CurveEditorGroup::curveResetPressed () +{ + if (displayedCurve) { + if (displayedCurve->subGroup->curveReset(displayedCurve)) { + curveChanged(); + } + } } /* * Set the tooltip text of the label of the curve group */ -void CurveEditorGroup::setTooltip( Glib::ustring ttip) { - curveGroupLabel->set_tooltip_text( ttip ); +void CurveEditorGroup::setTooltip( Glib::ustring ttip) +{ + curveGroupLabel->set_tooltip_text( ttip ); } -void CurveEditorGroup::setBatchMode (bool batchMode) { - for (std::vector::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) { - (*i)->curveType->addEntry("curveType-unchanged.png", M("GENERAL_UNCHANGED")); - (*i)->curveType->show(); - } +void CurveEditorGroup::setBatchMode (bool batchMode) +{ + for (std::vector::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) { + (*i)->curveType->addEntry("curveType-unchanged.png", M("GENERAL_UNCHANGED")); + (*i)->curveType->show(); + } } -void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) { - if (uc) { - // the user selected several thumbnails, so we hide the editors and set the curveEditor selection to 'Unchanged' - //ce->typeconn.block(true); - // we hide the editor widgets - hideCurrentCurve(); - // the curve type selected option is set to unchanged - ce->curveType->setSelected(ce->subGroup->valUnchanged); - //ce->typeconn.block(false); - } - else { - // we want it to use back the 'CurveEditor::setCurve' memorized in CurveEditor::tempCurve - //ce->typeconn.block(true); - // we switch back the curve type selected option to the one of the used curve - ce->curveType->setSelected(ce->selected); - updateGUI (ce); - //ce->typeconn.block(false); - } +void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) +{ + if (uc) { + // the user selected several thumbnails, so we hide the editors and set the curveEditor selection to 'Unchanged' + //ce->typeconn.block(true); + // we hide the editor widgets + hideCurrentCurve(); + // the curve type selected option is set to unchanged + ce->curveType->setSelected(ce->subGroup->valUnchanged); + //ce->typeconn.block(false); + } else { + // we want it to use back the 'CurveEditor::setCurve' memorized in CurveEditor::tempCurve + //ce->typeconn.block(true); + // we switch back the curve type selected option to the one of the used curve + ce->curveType->setSelected(ce->selected); + updateGUI (ce); + //ce->typeconn.block(false); + } } -CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : curveDir(curveDir), lastFilename("") { - leftBar = NULL; - bottomBar = NULL; +CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : curveDir(curveDir), lastFilename("") +{ + leftBar = NULL; + bottomBar = NULL; } -CurveEditorSubGroup::~CurveEditorSubGroup() { - if (leftBar) delete leftBar; - if (bottomBar) delete bottomBar; +CurveEditorSubGroup::~CurveEditorSubGroup() +{ + if (leftBar) { + delete leftBar; + } + + if (bottomBar) { + delete bottomBar; + } } -void CurveEditorSubGroup::updateEditButton(CurveEditor* curve, Gtk::ToggleButton *button, sigc::connection &connection) { - if (!curve->getEditProvider() || curve->getEditID() == EUID_None) { - button->hide(); - } - else { - button->show(); - bool prevstate = connection.block(true); - if (curve->isCurrentSubscriber()) - button->set_active(true); - else - button->set_active(false); - if (!prevstate) connection.block(false); - } +void CurveEditorSubGroup::updateEditButton(CurveEditor* curve, Gtk::ToggleButton *button, sigc::connection &connection) +{ + if (!curve->getEditProvider() || curve->getEditID() == EUID_None) { + button->hide(); + } else { + button->show(); + bool prevstate = connection.block(true); + + if (curve->isCurrentSubscriber()) { + button->set_active(true); + } else { + button->set_active(false); + } + + if (!prevstate) { + connection.block(false); + } + } } -Glib::ustring CurveEditorSubGroup::outputFile () { +Glib::ustring CurveEditorSubGroup::outputFile () +{ Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); FileChooserLastFolderPersister persister(&dialog, curveDir); @@ -385,11 +442,15 @@ Glib::ustring CurveEditorSubGroup::outputFile () { //dialog.set_do_overwrite_confirmation (true); Glib::ustring fname; + do { if (dialog.run() == Gtk::RESPONSE_APPLY) { fname = dialog.get_filename(); - if (getExtension (fname) != "rtc") + + if (getExtension (fname) != "rtc") { fname += ".rtc"; + } + if (confirmOverwrite (dialog, fname)) { lastFilename = Glib::path_get_basename (fname); break; @@ -403,7 +464,8 @@ Glib::ustring CurveEditorSubGroup::outputFile () { return fname; } -Glib::ustring CurveEditorSubGroup::inputFile () { +Glib::ustring CurveEditorSubGroup::inputFile () +{ Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); FileChooserLastFolderPersister persister(&dialog, curveDir); @@ -423,12 +485,16 @@ Glib::ustring CurveEditorSubGroup::inputFile () { int result = dialog.run(); - Glib::ustring fname; - if (result==Gtk::RESPONSE_APPLY) { - fname = dialog.get_filename(); - if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) - return fname; + Glib::ustring fname; + + if (result == Gtk::RESPONSE_APPLY) { + fname = dialog.get_filename(); + + if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) { + return fname; + } } + fname = ""; return fname; } diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h index 052633f84..1f1120f83 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -7,7 +7,7 @@ * 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 @@ -39,117 +39,131 @@ class FlatCurveEditorSubGroup; * - to start a new line of curve button, use the 'newLine' method * - if you add more than one curve, you must add a "CurveEditor* ce" parameter to your listener */ -class CurveEditorGroup : public Gtk::VBox, public CurveListener { +class CurveEditorGroup : public Gtk::VBox, public CurveListener +{ - friend class CurveEditor; - friend class CurveEditorSubGroup; - friend class DiagonalCurveEditorSubGroup; - friend class FlatCurveEditorSubGroup; + friend class CurveEditor; + friend class CurveEditorSubGroup; + friend class DiagonalCurveEditorSubGroup; + friend class FlatCurveEditorSubGroup; private: - Glib::ustring& curveDir; + Glib::ustring& curveDir; protected: - Gtk::Label* curveGroupLabel; - Gtk::Button* curve_reset; - std::vector curveEditors; - CurveEditor* displayedCurve; - FlatCurveEditorSubGroup* flatSubGroup; - DiagonalCurveEditorSubGroup* diagonalSubGroup; + Gtk::Label* curveGroupLabel; + Gtk::Button* curve_reset; + std::vector curveEditors; + CurveEditor* displayedCurve; + FlatCurveEditorSubGroup* flatSubGroup; + DiagonalCurveEditorSubGroup* diagonalSubGroup; - CurveListener* cl; + CurveListener* cl; - unsigned int numberOfPackedCurve; + unsigned int numberOfPackedCurve; public: - /** - * @param curveDir The folder used by load and save dialogs for the curve. - * This variable will be updated with actions in the - * dialogs. - */ + /** + * @param curveDir The folder used by load and save dialogs for the curve. + * This variable will be updated with actions in the + * dialogs. + */ - CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); - ~CurveEditorGroup(); - void newLine(); - void curveListComplete(); - void setBatchMode (bool batchMode); - void setCurveExternal (CurveEditor* ce, const std::vector& c); - void setCurveListener (CurveListener* l) { cl = l; } - void setTooltip (Glib::ustring ttip); - CurveEditor* getDisplayedCurve () { return displayedCurve; } - //void on_realize (); - CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel, Gtk::Widget *relatedWidget=NULL, bool periodic=true); + CurveEditorGroup(Glib::ustring& curveDir, Glib::ustring groupLabel = ""); + ~CurveEditorGroup(); + void newLine(); + void curveListComplete(); + void setBatchMode (bool batchMode); + void setCurveExternal (CurveEditor* ce, const std::vector& c); + void setCurveListener (CurveListener* l) + { + cl = l; + } + void setTooltip (Glib::ustring ttip); + CurveEditor* getDisplayedCurve () + { + return displayedCurve; + } + //void on_realize (); + CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel, Gtk::Widget *relatedWidget = NULL, bool periodic = true); protected: - //void curveTypeToggled (); - void curveTypeToggled (CurveEditor* ce); - //void typeSelectionChanged (int n); - void typeSelectionChanged (CurveEditor* ce, int n); - void hideCurrentCurve (); - void updateGUI (CurveEditor* ce); - void curveResetPressed (); - void curveChanged (); - float blendPipetteValues(CurveEditor* ce, float chan1, float chan2, float chan3); - void setUnChanged (bool uc, CurveEditor* ce); + //void curveTypeToggled (); + void curveTypeToggled (CurveEditor* ce); + //void typeSelectionChanged (int n); + void typeSelectionChanged (CurveEditor* ce, int n); + void hideCurrentCurve (); + void updateGUI (CurveEditor* ce); + void curveResetPressed (); + void curveChanged (); + float blendPipetteValues(CurveEditor* ce, float chan1, float chan2, float chan3); + void setUnChanged (bool uc, CurveEditor* ce); }; class CoordinateProvider; -class CurveEditorSubGroup { +class CurveEditorSubGroup +{ - friend class CurveEditorGroup; + friend class CurveEditorGroup; private: - Glib::ustring& curveDir; - Glib::ustring lastFilename; + Glib::ustring& curveDir; + Glib::ustring lastFilename; protected: - int valLinear; - int valUnchanged; - CurveEditorGroup *parent; - int curveBBoxPos; // 0=above, 1=right, 2=below, 3=left + int valLinear; + int valUnchanged; + CurveEditorGroup *parent; + int curveBBoxPos; // 0=above, 1=right, 2=below, 3=left - ColoredBar* leftBar; - ColoredBar* bottomBar; + ColoredBar* leftBar; + ColoredBar* bottomBar; public: - virtual ~CurveEditorSubGroup(); - int getValUnchanged() { return valUnchanged; } - int getValLinear() { return valLinear; } - void updateEditButton(CurveEditor* curve, Gtk::ToggleButton *button, sigc::connection &connection); - virtual void updateBackgroundHistogram (CurveEditor* ce) {} - virtual void switchGUI() = 0; - virtual void refresh(CurveEditor *curveToRefresh) = 0; - virtual void editModeSwitchedOff() = 0; + virtual ~CurveEditorSubGroup(); + int getValUnchanged() + { + return valUnchanged; + } + int getValLinear() + { + return valLinear; + } + void updateEditButton(CurveEditor* curve, Gtk::ToggleButton *button, sigc::connection &connection); + virtual void updateBackgroundHistogram (CurveEditor* ce) {} + virtual void switchGUI() = 0; + virtual void refresh(CurveEditor *curveToRefresh) = 0; + virtual void editModeSwitchedOff() = 0; - virtual void showCoordinateAdjuster(CoordinateProvider *provider) = 0; - virtual void stopNumericalAdjustment() = 0; + virtual void showCoordinateAdjuster(CoordinateProvider *provider) = 0; + virtual void stopNumericalAdjustment() = 0; - virtual void pipetteMouseOver(EditDataProvider *provider, int modifierKey) =0; - virtual void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) =0; - virtual void pipetteButton1Released(EditDataProvider *provider) =0; - virtual void pipetteDrag(EditDataProvider *provider, int modifierKey) =0; + virtual void pipetteMouseOver(EditDataProvider *provider, int modifierKey) = 0; + virtual void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) = 0; + virtual void pipetteButton1Released(EditDataProvider *provider) = 0; + virtual void pipetteDrag(EditDataProvider *provider, int modifierKey) = 0; - virtual bool curveReset (CurveEditor *ce) = 0; // Reset a curve editor, return TRUE if successful (curve changed) + virtual bool curveReset (CurveEditor *ce) = 0; // Reset a curve editor, return TRUE if successful (curve changed) protected: - /** - * @param curveDir The folder used by load and save dialogs for the curve. - * This variable will be updated with actions in the - * dialogs. - */ - CurveEditorSubGroup(Glib::ustring& curveDir); + /** + * @param curveDir The folder used by load and save dialogs for the curve. + * This variable will be updated with actions in the + * dialogs. + */ + CurveEditorSubGroup(Glib::ustring& curveDir); - Glib::ustring outputFile (); - Glib::ustring inputFile (); + Glib::ustring outputFile (); + Glib::ustring inputFile (); - virtual void storeCurveValues (CurveEditor* ce, const std::vector& p) = 0; - virtual void storeDisplayedCurve () = 0; - virtual void restoreDisplayedHistogram() {}; - virtual void removeEditor () = 0; - virtual const std::vector getCurveFromGUI (int type) = 0; + virtual void storeCurveValues (CurveEditor* ce, const std::vector& p) = 0; + virtual void storeDisplayedCurve () = 0; + virtual void restoreDisplayedHistogram() {}; + virtual void removeEditor () = 0; + virtual const std::vector getCurveFromGUI (int type) = 0; }; diff --git a/rtgui/curvelistener.h b/rtgui/curvelistener.h index 682c98b29..3c85db712 100644 --- a/rtgui/curvelistener.h +++ b/rtgui/curvelistener.h @@ -7,7 +7,7 @@ * 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 @@ -23,51 +23,68 @@ class CurveEditor; -class CurveListener { +class CurveListener +{ - private: - bool multi; - public: - CurveListener() : multi(false) {} - virtual ~CurveListener() {} - virtual void curveChanged () {} - virtual void curveChanged (CurveEditor* ce) {} - void setMulti(bool value) { multi = value; } - bool isMulti() { return multi; } +private: + bool multi; +public: + CurveListener() : multi(false) {} + virtual ~CurveListener() {} + virtual void curveChanged () {} + virtual void curveChanged (CurveEditor* ce) {} + void setMulti(bool value) + { + multi = value; + } + bool isMulti() + { + return multi; + } - /** @brief Ask the reset curve for a given curve type - * @param ce CurveEditor that we want to reset - * @param curve Actual curve for the return value. The actual curve type (given by the first value of the vector) - * should be kept the same. Change the curve type if REALLY necessary! */ - virtual bool getResetCurve(CurveEditor *ce, std::vector &curve) { return false; } + /** @brief Ask the reset curve for a given curve type + * @param ce CurveEditor that we want to reset + * @param curve Actual curve for the return value. The actual curve type (given by the first value of the vector) + * should be kept the same. Change the curve type if REALLY necessary! */ + virtual bool getResetCurve(CurveEditor *ce, std::vector &curve) + { + return false; + } - /** @brief Blend pipette values from its different channels into a single value - If the buffer has more than one channel and one channel, this method will blend them together. - @param chan1 first channel's value - @param chan2 second channel's value - @param chan3 third channel's value - @return the blended value */ - virtual float blendPipetteValues(CurveEditor *ce, float chan1, float chan2, float chan3) { - float retVal = 0.f; - int n = 0; - if (chan1 != -1.f) { - retVal += chan1; - ++n; - } - if (chan2 != -1.f) { - retVal += chan2; - ++n; - } - if (chan3 != -1.f) { - retVal += chan3; - ++n; - } - if (n>1) - retVal /= n; - else if (!n) - retVal = -1.f; - return retVal; + /** @brief Blend pipette values from its different channels into a single value + If the buffer has more than one channel and one channel, this method will blend them together. + @param chan1 first channel's value + @param chan2 second channel's value + @param chan3 third channel's value + @return the blended value */ + virtual float blendPipetteValues(CurveEditor *ce, float chan1, float chan2, float chan3) + { + float retVal = 0.f; + int n = 0; + + if (chan1 != -1.f) { + retVal += chan1; + ++n; } + + if (chan2 != -1.f) { + retVal += chan2; + ++n; + } + + if (chan3 != -1.f) { + retVal += chan3; + ++n; + } + + if (n > 1) { + retVal /= n; + } else if (!n) { + retVal = -1.f; + } + + return retVal; + } }; #endif diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index baf0e8f89..e16817cb6 100644 --- a/rtgui/darkframe.cc +++ b/rtgui/darkframe.cc @@ -28,129 +28,133 @@ using namespace rtengine::procparams; DarkFrame::DarkFrame () : FoldableToolPanel(this, "darkframe", M("TP_DARKFRAME_LABEL")) { - hbdf = Gtk::manage(new Gtk::HBox()); - hbdf->set_spacing(4); - darkFrameFile = Gtk::manage(new MyFileChooserButton(M("TP_DARKFRAME_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); - darkFrameFilePersister.reset(new FileChooserLastFolderPersister(darkFrameFile, options.lastDarkframeDir)); - dfLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); - btnReset = Gtk::manage(new Gtk::Button()); - btnReset->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); - hbdf->pack_start(*dfLabel, Gtk::PACK_SHRINK, 0); - hbdf->pack_start(*darkFrameFile); - hbdf->pack_start(*btnReset, Gtk::PACK_SHRINK, 0); - dfAuto = Gtk::manage(new Gtk::CheckButton((M("TP_DARKFRAME_AUTOSELECT")))); - dfInfo = Gtk::manage(new Gtk::Label("")); - dfInfo->set_alignment(0,0); //left align + hbdf = Gtk::manage(new Gtk::HBox()); + hbdf->set_spacing(4); + darkFrameFile = Gtk::manage(new MyFileChooserButton(M("TP_DARKFRAME_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); + darkFrameFilePersister.reset(new FileChooserLastFolderPersister(darkFrameFile, options.lastDarkframeDir)); + dfLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); + btnReset = Gtk::manage(new Gtk::Button()); + btnReset->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); + hbdf->pack_start(*dfLabel, Gtk::PACK_SHRINK, 0); + hbdf->pack_start(*darkFrameFile); + hbdf->pack_start(*btnReset, Gtk::PACK_SHRINK, 0); + dfAuto = Gtk::manage(new Gtk::CheckButton((M("TP_DARKFRAME_AUTOSELECT")))); + dfInfo = Gtk::manage(new Gtk::Label("")); + dfInfo->set_alignment(0, 0); //left align - pack_start( *hbdf, Gtk::PACK_SHRINK, 0); - pack_start( *dfAuto, Gtk::PACK_SHRINK, 0); - pack_start( *dfInfo, Gtk::PACK_SHRINK, 0); + pack_start( *hbdf, Gtk::PACK_SHRINK, 0); + pack_start( *dfAuto, Gtk::PACK_SHRINK, 0); + pack_start( *dfInfo, Gtk::PACK_SHRINK, 0); - dfautoconn = dfAuto->signal_toggled().connect ( sigc::mem_fun(*this, &DarkFrame::dfAutoChanged), true); - dfFile = darkFrameFile->signal_file_set().connect ( sigc::mem_fun(*this, &DarkFrame::darkFrameChanged), true); - btnReset->signal_clicked().connect( sigc::mem_fun(*this, &DarkFrame::darkFrameReset), true ); - - // Set filename filters - b_filter_asCurrent = false; - Gtk::FileFilter *filter_any = Gtk::manage(new Gtk::FileFilter); + dfautoconn = dfAuto->signal_toggled().connect ( sigc::mem_fun(*this, &DarkFrame::dfAutoChanged), true); + dfFile = darkFrameFile->signal_file_set().connect ( sigc::mem_fun(*this, &DarkFrame::darkFrameChanged), true); + btnReset->signal_clicked().connect( sigc::mem_fun(*this, &DarkFrame::darkFrameReset), true ); + + // Set filename filters + b_filter_asCurrent = false; + Gtk::FileFilter *filter_any = Gtk::manage(new Gtk::FileFilter); filter_any->add_pattern("*"); filter_any->set_name(M("FILECHOOSER_FILTER_ANY")); darkFrameFile->add_filter (*filter_any); - - // filters for all supported non-raw extensions - for (size_t i=0; iadd_pattern("*." + options.parseExtensions[i]); - filter_df->add_pattern("*." + options.parseExtensions[i].uppercase()); - filter_df->set_name(options.parseExtensions[i].uppercase()); - darkFrameFile->add_filter (*filter_df); - //printf("adding filter %s \n",options.parseExtensions[i].uppercase().c_str()); + + // filters for all supported non-raw extensions + for (size_t i = 0; i < options.parseExtensions.size(); i++) { + if (options.parseExtensionsEnabled[i] && options.parseExtensions[i].uppercase() != "JPG" && options.parseExtensions[i].uppercase() != "JPEG" && options.parseExtensions[i].uppercase() != "PNG" && options.parseExtensions[i].uppercase() != "TIF" && options.parseExtensions[i].uppercase() != "TIFF" ) { + Gtk::FileFilter *filter_df = Gtk::manage(new Gtk::FileFilter); + filter_df->add_pattern("*." + options.parseExtensions[i]); + filter_df->add_pattern("*." + options.parseExtensions[i].uppercase()); + filter_df->set_name(options.parseExtensions[i].uppercase()); + darkFrameFile->add_filter (*filter_df); + //printf("adding filter %s \n",options.parseExtensions[i].uppercase().c_str()); } } } void DarkFrame::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - dfautoconn.block(true); + disableListener (); + dfautoconn.block(true); - dfAuto->set_active( pp->raw.df_autoselect ); + dfAuto->set_active( pp->raw.df_autoselect ); - if(pedited ){ - dfAuto->set_inconsistent(!pedited->raw.dfAuto ); - } - if (safe_file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) - darkFrameFile->set_filename (pp->raw.dark_frame); - else - darkFrameReset(); - hbdf->set_sensitive( !pp->raw.df_autoselect ); + if(pedited ) { + dfAuto->set_inconsistent(!pedited->raw.dfAuto ); + } - lastDFauto = pp->raw.df_autoselect; + if (safe_file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) { + darkFrameFile->set_filename (pp->raw.dark_frame); + } else { + darkFrameReset(); + } - if( pp->raw.df_autoselect && dfp && !multiImage){ - // retrieve the auto-selected df filename - rtengine::RawImage *img = dfp->getDF(); - if( img ){ - dfInfo->set_text( Glib::ustring::compose("%1: %2ISO %3s", Glib::path_get_basename(img->get_filename()), img->get_ISOspeed(), img->get_shutter()) ); - }else{ - dfInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); - } - } - else dfInfo->set_text(""); + hbdf->set_sensitive( !pp->raw.df_autoselect ); - dfChanged = false; + lastDFauto = pp->raw.df_autoselect; - dfautoconn.block(false); - enableListener (); - - // Add filter with the current file extension if the current file is raw - if (dfp && !batchMode){ - - if (b_filter_asCurrent){ - //First, remove last filter_asCurrent if it was set for a raw file - std::vector filters = darkFrameFile->list_filters(); - darkFrameFile->remove_filter(**(filters.end()-1)); - b_filter_asCurrent = false; - } + if( pp->raw.df_autoselect && dfp && !multiImage) { + // retrieve the auto-selected df filename + rtengine::RawImage *img = dfp->getDF(); - Glib::ustring fname = Glib::path_get_basename(dfp->GetCurrentImageFilePath()); - Glib::ustring filetype; + if( img ) { + dfInfo->set_text( Glib::ustring::compose("%1: %2ISO %3s", Glib::path_get_basename(img->get_filename()), img->get_ISOspeed(), img->get_shutter()) ); + } else { + dfInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); + } + } else { + dfInfo->set_text(""); + } - if (fname!=""){ - // get image filetype, set filter to the same as current image's filetype - std::string::size_type idx; - idx = fname.rfind('.'); - if(idx != std::string::npos){ - filetype = fname.substr(idx+1); - israw = filetype.uppercase()!="JPG" && filetype.uppercase()!="JPEG" && filetype.uppercase()!="PNG" && filetype.uppercase()!="TIF" && filetype.uppercase()!="TIFF"; + dfChanged = false; - //exclude non-raw - if (israw) - { - b_filter_asCurrent = true; - Gtk::FileFilter *filter_asCurrent = Gtk::manage(new Gtk::FileFilter); - filter_asCurrent->add_pattern("*." + filetype); - filter_asCurrent->set_name(M("FILECHOOSER_FILTER_SAME") + " (" + filetype + ")"); - darkFrameFile->add_filter (*filter_asCurrent); - darkFrameFile->set_filter (*filter_asCurrent); - } - } - } - } + dfautoconn.block(false); + enableListener (); + + // Add filter with the current file extension if the current file is raw + if (dfp && !batchMode) { + + if (b_filter_asCurrent) { + //First, remove last filter_asCurrent if it was set for a raw file + std::vector filters = darkFrameFile->list_filters(); + darkFrameFile->remove_filter(**(filters.end() - 1)); + b_filter_asCurrent = false; + } + + Glib::ustring fname = Glib::path_get_basename(dfp->GetCurrentImageFilePath()); + Glib::ustring filetype; + + if (fname != "") { + // get image filetype, set filter to the same as current image's filetype + std::string::size_type idx; + idx = fname.rfind('.'); + + if(idx != std::string::npos) { + filetype = fname.substr(idx + 1); + israw = filetype.uppercase() != "JPG" && filetype.uppercase() != "JPEG" && filetype.uppercase() != "PNG" && filetype.uppercase() != "TIF" && filetype.uppercase() != "TIFF"; + + //exclude non-raw + if (israw) { + b_filter_asCurrent = true; + Gtk::FileFilter *filter_asCurrent = Gtk::manage(new Gtk::FileFilter); + filter_asCurrent->add_pattern("*." + filetype); + filter_asCurrent->set_name(M("FILECHOOSER_FILTER_SAME") + " (" + filetype + ")"); + darkFrameFile->add_filter (*filter_asCurrent); + darkFrameFile->set_filter (*filter_asCurrent); + } + } + } + } } void DarkFrame::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.dark_frame = darkFrameFile->get_filename(); - pp->raw.df_autoselect = dfAuto->get_active(); + pp->raw.dark_frame = darkFrameFile->get_filename(); + pp->raw.df_autoselect = dfAuto->get_active(); - if (pedited) { - pedited->raw.darkFrame = dfChanged; - pedited->raw.dfAuto = !dfAuto->get_inconsistent(); - } + if (pedited) { + pedited->raw.darkFrame = dfChanged; + pedited->raw.dfAuto = !dfAuto->get_inconsistent(); + } } @@ -158,55 +162,64 @@ void DarkFrame::dfAutoChanged() { if (batchMode) { if (dfAuto->get_inconsistent()) { - dfAuto->set_inconsistent (false); - dfautoconn.block (true); - dfAuto->set_active (false); - dfautoconn.block (false); + dfAuto->set_inconsistent (false); + dfautoconn.block (true); + dfAuto->set_active (false); + dfautoconn.block (false); + } else if (lastDFauto) { + dfAuto->set_inconsistent (true); } - else if (lastDFauto) - dfAuto->set_inconsistent (true); lastDFauto = dfAuto->get_active (); } - if(dfAuto->get_active() && dfp && !batchMode){ - // retrieve the auto-selected df filename - rtengine::RawImage *img = dfp->getDF(); - if( img ){ - dfInfo->set_text( Glib::ustring::compose("%1: %2ISO %3s", Glib::path_get_basename(img->get_filename()), img->get_ISOspeed(), img->get_shutter()) ); - }else{ - dfInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); - } - } - else{dfInfo->set_text("");} + if(dfAuto->get_active() && dfp && !batchMode) { + // retrieve the auto-selected df filename + rtengine::RawImage *img = dfp->getDF(); - hbdf->set_sensitive( !dfAuto->get_active() ); - if (listener) - listener->panelChanged (EvPreProcessAutoDF, dfAuto->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + if( img ) { + dfInfo->set_text( Glib::ustring::compose("%1: %2ISO %3s", Glib::path_get_basename(img->get_filename()), img->get_ISOspeed(), img->get_shutter()) ); + } else { + dfInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); + } + } else { + dfInfo->set_text(""); + } + + hbdf->set_sensitive( !dfAuto->get_active() ); + + if (listener) { + listener->panelChanged (EvPreProcessAutoDF, dfAuto->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } void DarkFrame::darkFrameChanged() { - dfChanged=true; - if (listener) + dfChanged = true; + + if (listener) { listener->panelChanged (EvPreProcessDFFile, Glib::path_get_basename(darkFrameFile->get_filename())); + } } void DarkFrame::darkFrameReset() { - dfChanged=true; + dfChanged = true; // caution: I had to make this hack, because set_current_folder() doesn't work correctly! // Because szeva doesn't exist since he was committed to happy hunting ground in Issue 316 // we can use him now for this hack - darkFrameFile->set_filename (options.lastDarkframeDir + "/szeva"); + darkFrameFile->set_filename (options.lastDarkframeDir + "/szeva"); // end of the hack - if (!options.lastDarkframeDir.empty()) - darkFrameFile->set_current_folder(options.lastDarkframeDir); + if (!options.lastDarkframeDir.empty()) { + darkFrameFile->set_current_folder(options.lastDarkframeDir); + } - dfInfo->set_text(""); - if (listener) + dfInfo->set_text(""); + + if (listener) { listener->panelChanged (EvPreProcessDFFile, M("GENERAL_NONE")); + } } diff --git a/rtgui/darkframe.h b/rtgui/darkframe.h index 785db8dc5..5f8e32d90 100644 --- a/rtgui/darkframe.h +++ b/rtgui/darkframe.h @@ -25,42 +25,47 @@ #include "../rtengine/rawimage.h" #include "guiutils.h" -class DFProvider { - public: +class DFProvider +{ +public: virtual rtengine::RawImage* getDF() = 0; virtual Glib::ustring GetCurrentImageFilePath() = 0; // add other info here }; -class DarkFrame : public ToolParamBlock, public FoldableToolPanel { +class DarkFrame : public ToolParamBlock, public FoldableToolPanel +{ protected: - MyFileChooserButton *darkFrameFile; - std::auto_ptr darkFrameFilePersister; + MyFileChooserButton *darkFrameFile; + std::auto_ptr darkFrameFilePersister; Gtk::HBox *hbdf; Gtk::Button *btnReset; Gtk::Label *dfLabel; - Gtk::Label *dfInfo; + Gtk::Label *dfInfo; Gtk::CheckButton* dfAuto; bool dfChanged; - bool lastDFauto; + bool lastDFauto; DFProvider *dfp; - sigc::connection dfautoconn, dfFile; + sigc::connection dfautoconn, dfFile; bool b_filter_asCurrent; bool israw; public: - DarkFrame (); + DarkFrame (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void darkFrameChanged (); void darkFrameReset (); void dfAutoChanged (); - void setDFProvider (DFProvider* p) { dfp = p; }; + void setDFProvider (DFProvider* p) + { + dfp = p; + }; }; #endif diff --git a/rtgui/defringe.cc b/rtgui/defringe.cc index 18c877249..5da21185c 100644 --- a/rtgui/defringe.cc +++ b/rtgui/defringe.cc @@ -7,7 +7,7 @@ * 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 @@ -23,64 +23,71 @@ using namespace rtengine; using namespace rtengine::procparams; -Defringe::Defringe () : FoldableToolPanel(this, "defringe", M("TP_DEFRINGE_LABEL"), true, true) { +Defringe::Defringe () : FoldableToolPanel(this, "defringe", M("TP_DEFRINGE_LABEL"), true, true) +{ - std::vector bottomMilestones; - float R, G, B; - for (int i=0; i<7; i++) { - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - - setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); + std::vector bottomMilestones; + float R, G, B; - curveEditorPF = new CurveEditorGroup (options.lastPFCurvesDir); - curveEditorPF->setCurveListener (this); - chshape = static_cast(curveEditorPF->addCurve(CT_Flat, M("TP_PFCURVE_CURVEEDITOR_CH"))); - chshape->setTooltip(M("TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP")); - chshape->setIdentityValue(0.); - chshape->setBottomBarBgGradient(bottomMilestones); - chshape->setCurveColorProvider(this, 1); + for (int i = 0; i < 7; i++) { + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } - //edgConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Defringe::edgeChanged) ); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); - radius = Gtk::manage (new Adjuster (M("TP_DEFRINGE_RADIUS"), 0.5, 5.0, 0.1, 2.0)); - threshold = Gtk::manage (new Adjuster (M("TP_DEFRINGE_THRESHOLD"), 0, 100, 1, 13)); - radius->setAdjusterListener (this); - threshold->setAdjusterListener (this); - // radius->show(); - // threshold->show(); + curveEditorPF = new CurveEditorGroup (options.lastPFCurvesDir); + curveEditorPF->setCurveListener (this); + chshape = static_cast(curveEditorPF->addCurve(CT_Flat, M("TP_PFCURVE_CURVEEDITOR_CH"))); + chshape->setTooltip(M("TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP")); + chshape->setIdentityValue(0.); + chshape->setBottomBarBgGradient(bottomMilestones); + chshape->setCurveColorProvider(this, 1); - pack_start (*radius); - pack_start (*threshold); - curveEditorPF->curveListComplete(); + //edgConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Defringe::edgeChanged) ); - pack_start (*curveEditorPF, Gtk::PACK_SHRINK, 4); - - show (); + radius = Gtk::manage (new Adjuster (M("TP_DEFRINGE_RADIUS"), 0.5, 5.0, 0.1, 2.0)); + threshold = Gtk::manage (new Adjuster (M("TP_DEFRINGE_THRESHOLD"), 0, 100, 1, 13)); + radius->setAdjusterListener (this); + threshold->setAdjusterListener (this); +// radius->show(); +// threshold->show(); + + pack_start (*radius); + pack_start (*threshold); + curveEditorPF->curveListComplete(); + + pack_start (*curveEditorPF, Gtk::PACK_SHRINK, 4); + + show (); } -Defringe::~Defringe () { +Defringe::~Defringe () +{ delete curveEditorPF; } -void Defringe::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { +void Defringe::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) +{ float R, G, B; - if (elemType==ColorCaller::CCET_VERTICAL_BAR) + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { valY = 0.5; + } if (callerId == 1) { // ch Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); } + caller->ccRed = double(R); caller->ccGreen = double(G); caller->ccBlue = double(B); } -void Defringe::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Defringe::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -101,17 +108,19 @@ void Defringe::read (const ProcParams* pp, const ParamsEdited* pedited) { } -void Defringe::autoOpenCurve () { +void Defringe::autoOpenCurve () +{ // WARNING: The following line won't work, since linear is a flat curve at 0. - // chshape->openIfNonlinear(); + // chshape->openIfNonlinear(); } -void Defringe::write (ProcParams* pp, ParamsEdited* pedited) { +void Defringe::write (ProcParams* pp, ParamsEdited* pedited) +{ - pp->defringe.radius = radius->getValue (); - pp->defringe.threshold = (int)threshold->getValue (); - pp->defringe.enabled = getEnabled(); - pp->defringe.huecurve = chshape->getCurve (); + pp->defringe.radius = radius->getValue (); + pp->defringe.threshold = (int)threshold->getValue (); + pp->defringe.enabled = getEnabled(); + pp->defringe.huecurve = chshape->getCurve (); if (pedited) { pedited->defringe.radius = radius->getEditedState (); @@ -121,7 +130,8 @@ void Defringe::write (ProcParams* pp, ParamsEdited* pedited) { } } -void Defringe::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void Defringe::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ radius->setDefault (defParams->defringe.radius); threshold->setDefault (defParams->defringe.threshold); @@ -129,41 +139,48 @@ void Defringe::setDefaults (const ProcParams* defParams, const ParamsEdited* ped if (pedited) { radius->setDefaultEditedState (pedited->defringe.radius ? Edited : UnEdited); threshold->setDefaultEditedState (pedited->defringe.threshold ? Edited : UnEdited); - } - else { + } else { radius->setDefaultEditedState (Irrelevant); threshold->setDefaultEditedState (Irrelevant); } } -void Defringe::curveChanged () { - - if (listener && getEnabled()) listener->panelChanged (EvPFCurve, M("HISTORY_CUSTOMCURVE")); -} - -void Defringe::adjusterChanged (Adjuster* a, double newval) { +void Defringe::curveChanged () +{ if (listener && getEnabled()) { - - if (a==radius) - listener->panelChanged (EvDefringeRadius, Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue())); - else if (a==threshold) - listener->panelChanged (EvDefringeThreshold, Glib::ustring::format ((int)a->getValue())); + listener->panelChanged (EvPFCurve, M("HISTORY_CUSTOMCURVE")); } } -void Defringe::enabledChanged () { +void Defringe::adjusterChanged (Adjuster* a, double newval) +{ + + if (listener && getEnabled()) { + + if (a == radius) { + listener->panelChanged (EvDefringeRadius, Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue())); + } else if (a == threshold) { + listener->panelChanged (EvDefringeThreshold, Glib::ustring::format ((int)a->getValue())); + } + } +} + +void Defringe::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvDefringeEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvDefringeEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvDefringeEnabled, M("GENERAL_DISABLED")); + } } } -void Defringe::setBatchMode (bool batchMode) { +void Defringe::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); radius->showEditedCB (); diff --git a/rtgui/defringe.h b/rtgui/defringe.h index fb84e86c0..1d076ed4b 100644 --- a/rtgui/defringe.h +++ b/rtgui/defringe.h @@ -7,7 +7,7 @@ * 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 @@ -27,23 +27,24 @@ #include "curveeditorgroup.h" #include "colorprovider.h" -class Defringe : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider{ +class Defringe : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider +{ - protected: +protected: CurveEditorGroup* curveEditorPF; FlatCurveEditor* chshape; Adjuster* radius; Adjuster* threshold; - bool edges; + bool edges; - public: +public: Defringe (); ~Defringe (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void autoOpenCurve (); void curveChanged (); diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index adcb0e8db..ad896789f 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -31,1052 +31,1181 @@ #include "curveeditor.h" #include "diagonalcurveeditorsubgroup.h" -DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) { +DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) +{ - editedAdjuster = NULL; - editedAdjusterValue = 0; + editedAdjuster = NULL; + editedAdjusterValue = 0; - curveBBoxPos = options.curvebboxpos; + curveBBoxPos = options.curvebboxpos; - valLinear = (int)DCT_Linear; - valUnchanged = (int)DCT_Unchanged; - parent = prt; + valLinear = (int)DCT_Linear; + valUnchanged = (int)DCT_Unchanged; + parent = prt; - activeParamControl = -1; + activeParamControl = -1; - // custom curve - customCurveBox = new Gtk::VBox (); - customCurveBox->set_spacing(4); - Gtk::HBox* customCurveAndButtons = Gtk::manage (new Gtk::HBox ()); - customCurveAndButtons->set_spacing(4); - customCurve = Gtk::manage (new MyDiagonalCurve ()); - customCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS); - customCurve->setType (DCT_Spline); + // custom curve + customCurveBox = new Gtk::VBox (); + customCurveBox->set_spacing(4); + Gtk::HBox* customCurveAndButtons = Gtk::manage (new Gtk::HBox ()); + customCurveAndButtons->set_spacing(4); + customCurve = Gtk::manage (new MyDiagonalCurve ()); + customCurve->set_size_request (GRAPH_SIZE + 2 * RADIUS, GRAPH_SIZE + 2 * RADIUS); + customCurve->setType (DCT_Spline); - Gtk::Box* custombbox; // curvebboxpos 0=above, 1=right, 2=below, 3=left - if (options.curvebboxpos==1 || options.curvebboxpos==3) { - custombbox = Gtk::manage (new Gtk::VBox ()); - } else { - custombbox = Gtk::manage (new Gtk::HBox ()); - } - custombbox->set_spacing(4); + Gtk::Box* custombbox; // curvebboxpos 0=above, 1=right, 2=below, 3=left - pasteCustom = Gtk::manage (new Gtk::Button ()); - pasteCustom->add (*Gtk::manage (new RTImage ("edit-paste.png"))); - copyCustom = Gtk::manage (new Gtk::Button ()); - copyCustom->add (*Gtk::manage (new RTImage ("edit-copy.png"))); - saveCustom = Gtk::manage (new Gtk::Button ()); - saveCustom->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); - loadCustom = Gtk::manage (new Gtk::Button ()); - loadCustom->add (*Gtk::manage (new RTImage ("gtk-open.png"))); - editPointCustom = Gtk::manage (new Gtk::ToggleButton ()); - editPointCustom->add (*Gtk::manage (new RTImage ("gtk-edit.png"))); - editPointCustom->set_tooltip_text(M("CURVEEDITOR_EDITPOINT_HINT")); - editCustom = Gtk::manage (new Gtk::ToggleButton()); - editCustom->add (*Gtk::manage (new RTImage ("editmodehand.png"))); - editCustom->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); - editCustom->hide(); + if (options.curvebboxpos == 1 || options.curvebboxpos == 3) { + custombbox = Gtk::manage (new Gtk::VBox ()); + } else { + custombbox = Gtk::manage (new Gtk::HBox ()); + } - custombbox->pack_end (*pasteCustom, Gtk::PACK_SHRINK, 0); - custombbox->pack_end (*copyCustom, Gtk::PACK_SHRINK, 0); - custombbox->pack_end (*saveCustom, Gtk::PACK_SHRINK, 0); - custombbox->pack_end (*loadCustom, Gtk::PACK_SHRINK, 0); - custombbox->pack_start(*editPointCustom, Gtk::PACK_SHRINK, 0); - custombbox->pack_start(*editCustom, Gtk::PACK_SHRINK, 0); + custombbox->set_spacing(4); - customCurveAndButtons->pack_start (*customCurve, Gtk::PACK_EXPAND_WIDGET, 0); - customCurveAndButtons->pack_start (*custombbox, Gtk::PACK_SHRINK, 0); - customCurveBox->pack_start (*customCurveAndButtons, Gtk::PACK_EXPAND_WIDGET); - if (options.curvebboxpos==0) { - removeIfThere (customCurveAndButtons, custombbox, false); - customCurveBox->pack_start (*custombbox); - customCurveBox->reorder_child(*custombbox, 0); - } else if (options.curvebboxpos==2) { - removeIfThere (customCurveAndButtons, custombbox, false); - customCurveBox->pack_start (*custombbox); - } else if (options.curvebboxpos==3) { - customCurveAndButtons->reorder_child(*custombbox, 0); - } + pasteCustom = Gtk::manage (new Gtk::Button ()); + pasteCustom->add (*Gtk::manage (new RTImage ("edit-paste.png"))); + copyCustom = Gtk::manage (new Gtk::Button ()); + copyCustom->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + saveCustom = Gtk::manage (new Gtk::Button ()); + saveCustom->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); + loadCustom = Gtk::manage (new Gtk::Button ()); + loadCustom->add (*Gtk::manage (new RTImage ("gtk-open.png"))); + editPointCustom = Gtk::manage (new Gtk::ToggleButton ()); + editPointCustom->add (*Gtk::manage (new RTImage ("gtk-edit.png"))); + editPointCustom->set_tooltip_text(M("CURVEEDITOR_EDITPOINT_HINT")); + editCustom = Gtk::manage (new Gtk::ToggleButton()); + editCustom->add (*Gtk::manage (new RTImage ("editmodehand.png"))); + editCustom->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); + editCustom->hide(); - customCoordAdjuster = Gtk::manage (new CoordinateAdjuster(customCurve, this)); - customCurveBox->pack_start(*customCoordAdjuster, Gtk::PACK_SHRINK, 0); - if (options.curvebboxpos == 2) - customCurveBox->reorder_child(*customCoordAdjuster, 2); - customCoordAdjuster->show_all(); + custombbox->pack_end (*pasteCustom, Gtk::PACK_SHRINK, 0); + custombbox->pack_end (*copyCustom, Gtk::PACK_SHRINK, 0); + custombbox->pack_end (*saveCustom, Gtk::PACK_SHRINK, 0); + custombbox->pack_end (*loadCustom, Gtk::PACK_SHRINK, 0); + custombbox->pack_start(*editPointCustom, Gtk::PACK_SHRINK, 0); + custombbox->pack_start(*editCustom, Gtk::PACK_SHRINK, 0); - customCurveBox->show_all (); - customCoordAdjuster->hide(); + customCurveAndButtons->pack_start (*customCurve, Gtk::PACK_EXPAND_WIDGET, 0); + customCurveAndButtons->pack_start (*custombbox, Gtk::PACK_SHRINK, 0); + customCurveBox->pack_start (*customCurveAndButtons, Gtk::PACK_EXPAND_WIDGET); - saveCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) ); - loadCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) ); - copyCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) ); - pasteCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) ); - editPointCustomConn = editPointCustom->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editPointToggled), editPointCustom) ); - editCustomConn = editCustom->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editCustom) ); + if (options.curvebboxpos == 0) { + removeIfThere (customCurveAndButtons, custombbox, false); + customCurveBox->pack_start (*custombbox); + customCurveBox->reorder_child(*custombbox, 0); + } else if (options.curvebboxpos == 2) { + removeIfThere (customCurveAndButtons, custombbox, false); + customCurveBox->pack_start (*custombbox); + } else if (options.curvebboxpos == 3) { + customCurveAndButtons->reorder_child(*custombbox, 0); + } - saveCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); - loadCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); - copyCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); - pasteCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); - // Custom curve end + customCoordAdjuster = Gtk::manage (new CoordinateAdjuster(customCurve, this)); + customCurveBox->pack_start(*customCoordAdjuster, Gtk::PACK_SHRINK, 0); + + if (options.curvebboxpos == 2) { + customCurveBox->reorder_child(*customCoordAdjuster, 2); + } + + customCoordAdjuster->show_all(); + + customCurveBox->show_all (); + customCoordAdjuster->hide(); + + saveCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) ); + loadCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) ); + copyCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) ); + pasteCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) ); + editPointCustomConn = editPointCustom->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editPointToggled), editPointCustom) ); + editCustomConn = editCustom->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editCustom) ); + + saveCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); + loadCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); + copyCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); + pasteCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); + // Custom curve end - // NURBS curve - NURBSCurveBox = new Gtk::VBox (); - NURBSCurveBox->set_spacing(4); - Gtk::HBox* NURBSCurveAndButtons = Gtk::manage (new Gtk::HBox ()); - NURBSCurveAndButtons->set_spacing(4); - NURBSCurve = Gtk::manage (new MyDiagonalCurve ()); - NURBSCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS); - NURBSCurve->setType (DCT_NURBS); + // NURBS curve + NURBSCurveBox = new Gtk::VBox (); + NURBSCurveBox->set_spacing(4); + Gtk::HBox* NURBSCurveAndButtons = Gtk::manage (new Gtk::HBox ()); + NURBSCurveAndButtons->set_spacing(4); + NURBSCurve = Gtk::manage (new MyDiagonalCurve ()); + NURBSCurve->set_size_request (GRAPH_SIZE + 2 * RADIUS, GRAPH_SIZE + 2 * RADIUS); + NURBSCurve->setType (DCT_NURBS); - Gtk::Box* NURBSbbox; - if (options.curvebboxpos==1 || options.curvebboxpos==3) { - NURBSbbox = Gtk::manage (new Gtk::VBox ()); - } else { - NURBSbbox = Gtk::manage (new Gtk::HBox ()); - } - NURBSbbox->set_spacing(4); + Gtk::Box* NURBSbbox; - pasteNURBS = Gtk::manage (new Gtk::Button ()); - pasteNURBS->add (*Gtk::manage (new RTImage ("edit-paste.png"))); - copyNURBS = Gtk::manage (new Gtk::Button ()); - copyNURBS->add (*Gtk::manage (new RTImage ("edit-copy.png"))); - saveNURBS = Gtk::manage (new Gtk::Button ()); - saveNURBS->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); - loadNURBS = Gtk::manage (new Gtk::Button ()); - loadNURBS->add (*Gtk::manage (new RTImage ("gtk-open.png"))); - editPointNURBS = Gtk::manage (new Gtk::ToggleButton ()); - editPointNURBS->add (*Gtk::manage (new RTImage ("gtk-edit.png"))); - editPointNURBS->set_tooltip_text(M("CURVEEDITOR_EDITPOINT_HINT")); - editNURBS = Gtk::manage (new Gtk::ToggleButton()); - editNURBS->add (*Gtk::manage (new RTImage ("editmodehand.png"))); - editNURBS->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); - editNURBS->hide(); - NURBSbbox->pack_end (*pasteNURBS, Gtk::PACK_SHRINK, 0); - NURBSbbox->pack_end (*copyNURBS, Gtk::PACK_SHRINK, 0); - NURBSbbox->pack_end (*saveNURBS, Gtk::PACK_SHRINK, 0); - NURBSbbox->pack_end (*loadNURBS, Gtk::PACK_SHRINK, 0); - NURBSbbox->pack_start(*editPointNURBS, Gtk::PACK_SHRINK, 0); - NURBSbbox->pack_start(*editNURBS, Gtk::PACK_SHRINK, 0); + if (options.curvebboxpos == 1 || options.curvebboxpos == 3) { + NURBSbbox = Gtk::manage (new Gtk::VBox ()); + } else { + NURBSbbox = Gtk::manage (new Gtk::HBox ()); + } - NURBSCurveAndButtons->pack_start (*NURBSCurve, Gtk::PACK_EXPAND_WIDGET, 0); - NURBSCurveAndButtons->pack_start (*NURBSbbox, Gtk::PACK_SHRINK, 0); - NURBSCurveBox->pack_start (*NURBSCurveAndButtons, Gtk::PACK_EXPAND_WIDGET); - if (options.curvebboxpos==0) { - removeIfThere (NURBSCurveAndButtons, NURBSbbox, false); - NURBSCurveBox->pack_start (*NURBSbbox); - NURBSCurveBox->reorder_child(*NURBSbbox, 0); - } else if (options.curvebboxpos==2) { - removeIfThere (NURBSCurveAndButtons, NURBSbbox, false); - NURBSCurveBox->pack_start (*NURBSbbox); - } else if (options.curvebboxpos==3) { - NURBSCurveAndButtons->reorder_child(*NURBSbbox, 0); - } + NURBSbbox->set_spacing(4); - NURBSCoordAdjuster = Gtk::manage (new CoordinateAdjuster(NURBSCurve, this)); - NURBSCurveBox->pack_start(*NURBSCoordAdjuster, Gtk::PACK_SHRINK, 0); - if (options.curvebboxpos == 2) - NURBSCurveBox->reorder_child(*NURBSCoordAdjuster, 2); - NURBSCoordAdjuster->show_all(); + pasteNURBS = Gtk::manage (new Gtk::Button ()); + pasteNURBS->add (*Gtk::manage (new RTImage ("edit-paste.png"))); + copyNURBS = Gtk::manage (new Gtk::Button ()); + copyNURBS->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + saveNURBS = Gtk::manage (new Gtk::Button ()); + saveNURBS->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); + loadNURBS = Gtk::manage (new Gtk::Button ()); + loadNURBS->add (*Gtk::manage (new RTImage ("gtk-open.png"))); + editPointNURBS = Gtk::manage (new Gtk::ToggleButton ()); + editPointNURBS->add (*Gtk::manage (new RTImage ("gtk-edit.png"))); + editPointNURBS->set_tooltip_text(M("CURVEEDITOR_EDITPOINT_HINT")); + editNURBS = Gtk::manage (new Gtk::ToggleButton()); + editNURBS->add (*Gtk::manage (new RTImage ("editmodehand.png"))); + editNURBS->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); + editNURBS->hide(); + NURBSbbox->pack_end (*pasteNURBS, Gtk::PACK_SHRINK, 0); + NURBSbbox->pack_end (*copyNURBS, Gtk::PACK_SHRINK, 0); + NURBSbbox->pack_end (*saveNURBS, Gtk::PACK_SHRINK, 0); + NURBSbbox->pack_end (*loadNURBS, Gtk::PACK_SHRINK, 0); + NURBSbbox->pack_start(*editPointNURBS, Gtk::PACK_SHRINK, 0); + NURBSbbox->pack_start(*editNURBS, Gtk::PACK_SHRINK, 0); - NURBSCurveBox->show_all (); - NURBSCoordAdjuster->hide(); + NURBSCurveAndButtons->pack_start (*NURBSCurve, Gtk::PACK_EXPAND_WIDGET, 0); + NURBSCurveAndButtons->pack_start (*NURBSbbox, Gtk::PACK_SHRINK, 0); + NURBSCurveBox->pack_start (*NURBSCurveAndButtons, Gtk::PACK_EXPAND_WIDGET); - saveNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) ); - loadNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) ); - pasteNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) ); - copyNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) ); - editPointNURBSConn = editPointNURBS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editPointToggled), editPointNURBS) ); - editNURBSConn = editNURBS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editNURBS) ); + if (options.curvebboxpos == 0) { + removeIfThere (NURBSCurveAndButtons, NURBSbbox, false); + NURBSCurveBox->pack_start (*NURBSbbox); + NURBSCurveBox->reorder_child(*NURBSbbox, 0); + } else if (options.curvebboxpos == 2) { + removeIfThere (NURBSCurveAndButtons, NURBSbbox, false); + NURBSCurveBox->pack_start (*NURBSbbox); + } else if (options.curvebboxpos == 3) { + NURBSCurveAndButtons->reorder_child(*NURBSbbox, 0); + } - saveNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); - loadNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); - pasteNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); - copyNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); - // NURBS curve end + NURBSCoordAdjuster = Gtk::manage (new CoordinateAdjuster(NURBSCurve, this)); + NURBSCurveBox->pack_start(*NURBSCoordAdjuster, Gtk::PACK_SHRINK, 0); + + if (options.curvebboxpos == 2) { + NURBSCurveBox->reorder_child(*NURBSCoordAdjuster, 2); + } + + NURBSCoordAdjuster->show_all(); + + NURBSCurveBox->show_all (); + NURBSCoordAdjuster->hide(); + + saveNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) ); + loadNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) ); + pasteNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) ); + copyNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) ); + editPointNURBSConn = editPointNURBS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editPointToggled), editPointNURBS) ); + editNURBSConn = editNURBS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editNURBS) ); + + saveNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); + loadNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); + pasteNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); + copyNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); + // NURBS curve end - // parametric curve - paramCurveBox = new Gtk::VBox (); - paramCurveBox->set_spacing(4); - Gtk::HBox* paramCurveAndButtons = Gtk::manage (new Gtk::HBox ()); - paramCurveAndButtons->set_spacing(4); - Gtk::VBox* paramCurveAndShcVBox = Gtk::manage (new Gtk::VBox ()); - paramCurve = Gtk::manage (new MyDiagonalCurve ()); - paramCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS); - paramCurve->setType (DCT_Parametric); + // parametric curve + paramCurveBox = new Gtk::VBox (); + paramCurveBox->set_spacing(4); + Gtk::HBox* paramCurveAndButtons = Gtk::manage (new Gtk::HBox ()); + paramCurveAndButtons->set_spacing(4); + Gtk::VBox* paramCurveAndShcVBox = Gtk::manage (new Gtk::VBox ()); + paramCurve = Gtk::manage (new MyDiagonalCurve ()); + paramCurve->set_size_request (GRAPH_SIZE + 2 * RADIUS, GRAPH_SIZE + 2 * RADIUS); + paramCurve->setType (DCT_Parametric); - Gtk::Box* parambbox; - if (options.curvebboxpos==1 || options.curvebboxpos==3) { - parambbox = Gtk::manage (new Gtk::VBox ()); - } else { - parambbox = Gtk::manage (new Gtk::HBox ()); - } - parambbox->set_spacing(4); + Gtk::Box* parambbox; - shcSelector = Gtk::manage (new SHCSelector ()); - shcSelector->set_size_request (GRAPH_SIZE-100, 10); // width, height - //* shcSelector->set_size_request ((GRAPH_SIZE+2*RADIUS)-20, 20); + if (options.curvebboxpos == 1 || options.curvebboxpos == 3) { + parambbox = Gtk::manage (new Gtk::VBox ()); + } else { + parambbox = Gtk::manage (new Gtk::HBox ()); + } - pasteParam = Gtk::manage (new Gtk::Button ()); - pasteParam->add (*Gtk::manage (new RTImage ("edit-paste.png"))); - copyParam = Gtk::manage (new Gtk::Button ()); - copyParam->add (*Gtk::manage (new RTImage ("edit-copy.png"))); - saveParam = Gtk::manage (new Gtk::Button ()); - saveParam->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); - loadParam = Gtk::manage (new Gtk::Button ()); - loadParam->add (*Gtk::manage (new RTImage ("gtk-open.png"))); - editParam = Gtk::manage (new Gtk::ToggleButton()); - editParam->add (*Gtk::manage (new RTImage ("editmodehand.png"))); - editParam->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); - editParam->hide(); - parambbox->pack_end (*pasteParam, Gtk::PACK_SHRINK, 0); - parambbox->pack_end (*copyParam, Gtk::PACK_SHRINK, 0); - parambbox->pack_end (*saveParam, Gtk::PACK_SHRINK, 0); - parambbox->pack_end (*loadParam, Gtk::PACK_SHRINK, 0); - parambbox->pack_start(*editParam, Gtk::PACK_SHRINK, 0); + parambbox->set_spacing(4); - saveParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) ); - loadParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) ); - pasteParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) ); - copyParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) ); - editParamConn = editParam->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editParam) ); + shcSelector = Gtk::manage (new SHCSelector ()); + shcSelector->set_size_request (GRAPH_SIZE - 100, 10); // width, height + //* shcSelector->set_size_request ((GRAPH_SIZE+2*RADIUS)-20, 20); - saveParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); - loadParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); - pasteParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); - copyParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); + pasteParam = Gtk::manage (new Gtk::Button ()); + pasteParam->add (*Gtk::manage (new RTImage ("edit-paste.png"))); + copyParam = Gtk::manage (new Gtk::Button ()); + copyParam->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + saveParam = Gtk::manage (new Gtk::Button ()); + saveParam->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); + loadParam = Gtk::manage (new Gtk::Button ()); + loadParam->add (*Gtk::manage (new RTImage ("gtk-open.png"))); + editParam = Gtk::manage (new Gtk::ToggleButton()); + editParam->add (*Gtk::manage (new RTImage ("editmodehand.png"))); + editParam->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); + editParam->hide(); + parambbox->pack_end (*pasteParam, Gtk::PACK_SHRINK, 0); + parambbox->pack_end (*copyParam, Gtk::PACK_SHRINK, 0); + parambbox->pack_end (*saveParam, Gtk::PACK_SHRINK, 0); + parambbox->pack_end (*loadParam, Gtk::PACK_SHRINK, 0); + parambbox->pack_start(*editParam, Gtk::PACK_SHRINK, 0); - highlights = Gtk::manage (new Adjuster (M("CURVEEDITOR_HIGHLIGHTS"), -100, 100, 1, 0)); - lights = Gtk::manage (new Adjuster (M("CURVEEDITOR_LIGHTS"), -100, 100, 1, 0)); - darks = Gtk::manage (new Adjuster (M("CURVEEDITOR_DARKS"), -100, 100, 1, 0)); - shadows = Gtk::manage (new Adjuster (M("CURVEEDITOR_SHADOWS"), -100, 100, 1, 0)); + saveParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) ); + loadParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) ); + pasteParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) ); + copyParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) ); + editParamConn = editParam->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editParam) ); - Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ()); - Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ()); - Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ()); - Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ()); + saveParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); + loadParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); + pasteParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); + copyParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); - evhighlights->add (*highlights); - evlights->add (*lights); - evdarks->add (*darks); - evshadows->add (*shadows); + highlights = Gtk::manage (new Adjuster (M("CURVEEDITOR_HIGHLIGHTS"), -100, 100, 1, 0)); + lights = Gtk::manage (new Adjuster (M("CURVEEDITOR_LIGHTS"), -100, 100, 1, 0)); + darks = Gtk::manage (new Adjuster (M("CURVEEDITOR_DARKS"), -100, 100, 1, 0)); + shadows = Gtk::manage (new Adjuster (M("CURVEEDITOR_SHADOWS"), -100, 100, 1, 0)); - // paramCurveSliderBox needed to set vspacing(4) between curve+shc and sliders without vspacing between each slider - Gtk::VBox* paramCurveSliderBox = Gtk::manage (new Gtk::VBox ()); - paramCurveSliderBox->set_spacing(4); + Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ()); + Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ()); + Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ()); + Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ()); - paramCurveSliderBox->pack_start (*evhighlights); - paramCurveSliderBox->pack_start (*evlights); - paramCurveSliderBox->pack_start (*evdarks); - paramCurveSliderBox->pack_start (*evshadows); + evhighlights->add (*highlights); + evlights->add (*lights); + evdarks->add (*darks); + evshadows->add (*shadows); - paramCurveBox->show_all (); + // paramCurveSliderBox needed to set vspacing(4) between curve+shc and sliders without vspacing between each slider + Gtk::VBox* paramCurveSliderBox = Gtk::manage (new Gtk::VBox ()); + paramCurveSliderBox->set_spacing(4); - paramCurveAndShcVBox->pack_start (*paramCurve, Gtk::PACK_EXPAND_WIDGET); - paramCurveAndShcVBox->pack_start (*shcSelector, Gtk::PACK_EXPAND_WIDGET); - paramCurveAndButtons->pack_start (*paramCurveAndShcVBox); - paramCurveAndButtons->pack_start (*parambbox, Gtk::PACK_SHRINK); - paramCurveBox->pack_start (*paramCurveAndButtons); - paramCurveBox->pack_start (*paramCurveSliderBox); - if (options.curvebboxpos==0) { - removeIfThere (paramCurveAndButtons, parambbox, false); - paramCurveBox->pack_start (*parambbox); - paramCurveBox->reorder_child(*parambbox, 0); - } else if (options.curvebboxpos==2) { - removeIfThere (paramCurveAndButtons, parambbox, false); - paramCurveBox->pack_start (*parambbox); - //paramCurveBox->reorder_child(*parambbox, 1); - } else if (options.curvebboxpos==3) { - paramCurveAndButtons->reorder_child(*parambbox, 0); - } - paramCurveBox->show_all (); - // parametric curve end + paramCurveSliderBox->pack_start (*evhighlights); + paramCurveSliderBox->pack_start (*evlights); + paramCurveSliderBox->pack_start (*evdarks); + paramCurveSliderBox->pack_start (*evshadows); + + paramCurveBox->show_all (); + + paramCurveAndShcVBox->pack_start (*paramCurve, Gtk::PACK_EXPAND_WIDGET); + paramCurveAndShcVBox->pack_start (*shcSelector, Gtk::PACK_EXPAND_WIDGET); + paramCurveAndButtons->pack_start (*paramCurveAndShcVBox); + paramCurveAndButtons->pack_start (*parambbox, Gtk::PACK_SHRINK); + paramCurveBox->pack_start (*paramCurveAndButtons); + paramCurveBox->pack_start (*paramCurveSliderBox); + + if (options.curvebboxpos == 0) { + removeIfThere (paramCurveAndButtons, parambbox, false); + paramCurveBox->pack_start (*parambbox); + paramCurveBox->reorder_child(*parambbox, 0); + } else if (options.curvebboxpos == 2) { + removeIfThere (paramCurveAndButtons, parambbox, false); + paramCurveBox->pack_start (*parambbox); + //paramCurveBox->reorder_child(*parambbox, 1); + } else if (options.curvebboxpos == 3) { + paramCurveAndButtons->reorder_child(*parambbox, 0); + } + + paramCurveBox->show_all (); + // parametric curve end - customCurveBox->reference (); - paramCurveBox->reference (); + customCurveBox->reference (); + paramCurveBox->reference (); - customCurve->setCurveListener (parent); // Send the message directly to the parent - NURBSCurve->setCurveListener (parent); - paramCurve->setCurveListener (parent); - shcSelector->setSHCListener (this); + customCurve->setCurveListener (parent); // Send the message directly to the parent + NURBSCurve->setCurveListener (parent); + paramCurve->setCurveListener (parent); + shcSelector->setSHCListener (this); - highlights->setAdjusterListener (this); - lights->setAdjusterListener (this); - darks->setAdjusterListener (this); - shadows->setAdjusterListener (this); + highlights->setAdjusterListener (this); + lights->setAdjusterListener (this); + darks->setAdjusterListener (this); + shadows->setAdjusterListener (this); - evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); - evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); - evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); - evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); - evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 4)); - evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 5)); - evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 6)); - evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 7)); - evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 4)); - evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 5)); - evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 6)); - evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 7)); + evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 4)); + evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 5)); + evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 6)); + evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 7)); + evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 4)); + evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 5)); + evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 6)); + evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 7)); } -DiagonalCurveEditorSubGroup::~DiagonalCurveEditorSubGroup() { - delete customCurveBox; - delete paramCurveBox; - delete NURBSCurveBox; +DiagonalCurveEditorSubGroup::~DiagonalCurveEditorSubGroup() +{ + delete customCurveBox; + delete paramCurveBox; + delete NURBSCurveBox; } /* * Add a new curve to the curves list */ -DiagonalCurveEditor* DiagonalCurveEditorSubGroup::addCurve(Glib::ustring curveLabel) { - DiagonalCurveEditor* newCE = new DiagonalCurveEditor(curveLabel, parent, this); +DiagonalCurveEditor* DiagonalCurveEditorSubGroup::addCurve(Glib::ustring curveLabel) +{ + DiagonalCurveEditor* newCE = new DiagonalCurveEditor(curveLabel, parent, this); - // Initialization of the new curve - storeCurveValues(newCE, getCurveFromGUI(DCT_Spline)); - storeCurveValues(newCE, getCurveFromGUI(DCT_Parametric)); - storeCurveValues(newCE, getCurveFromGUI(DCT_NURBS)); - return newCE; + // Initialization of the new curve + storeCurveValues(newCE, getCurveFromGUI(DCT_Spline)); + storeCurveValues(newCE, getCurveFromGUI(DCT_Parametric)); + storeCurveValues(newCE, getCurveFromGUI(DCT_NURBS)); + return newCE; } /* * Switch off the edit button */ -void DiagonalCurveEditorSubGroup::editModeSwitchedOff () { - // toggling off all edit buttons, even if only one is toggle on - bool prevState; - prevState = editCustomConn.block(true); - editCustom->set_active(false); - customCurve->pipetteMouseOver(NULL, NULL, 0); - customCurve->setDirty(true); - if (!prevState) editCustomConn.block(false); - prevState = editNURBSConn.block(true); - editNURBS->set_active(false); - NURBSCurve->pipetteMouseOver(NULL, NULL, 0); - NURBSCurve->setDirty(true); - if (!prevState) editNURBSConn.block(false); - prevState = editParamConn.block(true); - editParam->set_active(false); - paramCurve->pipetteMouseOver(NULL, NULL, 0); - paramCurve->setDirty(true); - if (!prevState) editParamConn.block(false); +void DiagonalCurveEditorSubGroup::editModeSwitchedOff () +{ + // toggling off all edit buttons, even if only one is toggle on + bool prevState; + prevState = editCustomConn.block(true); + editCustom->set_active(false); + customCurve->pipetteMouseOver(NULL, NULL, 0); + customCurve->setDirty(true); + + if (!prevState) { + editCustomConn.block(false); + } + + prevState = editNURBSConn.block(true); + editNURBS->set_active(false); + NURBSCurve->pipetteMouseOver(NULL, NULL, 0); + NURBSCurve->setDirty(true); + + if (!prevState) { + editNURBSConn.block(false); + } + + prevState = editParamConn.block(true); + editParam->set_active(false); + paramCurve->pipetteMouseOver(NULL, NULL, 0); + paramCurve->setDirty(true); + + if (!prevState) { + editParamConn.block(false); + } } -void DiagonalCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, int modifierKey) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { - case (DCT_Spline): - customCurve->pipetteMouseOver(curveEditor, provider, modifierKey); - customCurve->setDirty(true); - break; - case (DCT_Parametric): - { - paramCurve->pipetteMouseOver(curveEditor, provider, modifierKey); - paramCurve->setDirty(true); - float pipetteVal = 0.f; - editedAdjuster = NULL; - int n = 0; - if (provider->pipetteVal[0] != -1.f) { - pipetteVal += provider->pipetteVal[0]; - ++n; - } - if (provider->pipetteVal[1] != -1.f) { - pipetteVal += provider->pipetteVal[1]; - ++n; - } - if (provider->pipetteVal[2] != -1.f) { - pipetteVal += provider->pipetteVal[2]; - ++n; - } - if (n>1) { - pipetteVal /= n; - } - else if (!n) - pipetteVal = -1.f; +void DiagonalCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, int modifierKey) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); - if (pipetteVal != -1.f) { - double pos[3]; - shcSelector->getPositions(pos[0], pos[1], pos[2]); - if (pipetteVal>=pos[2]) { - editedAdjuster = highlights; - paramCurve->setActiveParam(4); - } - else if(pipetteVal>=pos[1]) { - editedAdjuster = lights; - paramCurve->setActiveParam(5); - } - else if(pipetteVal>=pos[0]) { - editedAdjuster = darks; - paramCurve->setActiveParam(6); - } - else { - editedAdjuster = shadows; - paramCurve->setActiveParam(7); - } - } - else - paramCurve->setActiveParam(-1); - } - break; - case (DCT_NURBS): - NURBSCurve->pipetteMouseOver(curveEditor, provider, modifierKey); - NURBSCurve->setDirty(true); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } + switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { + case (DCT_Spline): + customCurve->pipetteMouseOver(curveEditor, provider, modifierKey); + customCurve->setDirty(true); + break; + + case (DCT_Parametric): { + paramCurve->pipetteMouseOver(curveEditor, provider, modifierKey); + paramCurve->setDirty(true); + float pipetteVal = 0.f; + editedAdjuster = NULL; + int n = 0; + + if (provider->pipetteVal[0] != -1.f) { + pipetteVal += provider->pipetteVal[0]; + ++n; + } + + if (provider->pipetteVal[1] != -1.f) { + pipetteVal += provider->pipetteVal[1]; + ++n; + } + + if (provider->pipetteVal[2] != -1.f) { + pipetteVal += provider->pipetteVal[2]; + ++n; + } + + if (n > 1) { + pipetteVal /= n; + } else if (!n) { + pipetteVal = -1.f; + } + + if (pipetteVal != -1.f) { + double pos[3]; + shcSelector->getPositions(pos[0], pos[1], pos[2]); + + if (pipetteVal >= pos[2]) { + editedAdjuster = highlights; + paramCurve->setActiveParam(4); + } else if(pipetteVal >= pos[1]) { + editedAdjuster = lights; + paramCurve->setActiveParam(5); + } else if(pipetteVal >= pos[0]) { + editedAdjuster = darks; + paramCurve->setActiveParam(6); + } else { + editedAdjuster = shadows; + paramCurve->setActiveParam(7); + } + } else { + paramCurve->setActiveParam(-1); + } + } + break; + + case (DCT_NURBS): + NURBSCurve->pipetteMouseOver(curveEditor, provider, modifierKey); + NURBSCurve->setDirty(true); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void DiagonalCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { - case (DCT_Spline): - customCurve->pipetteButton1Pressed(provider, modifierKey); - break; - case (DCT_Parametric): - if (editedAdjuster) - editedAdjusterValue = editedAdjuster->getIntValue(); - break; - case (DCT_NURBS): - NURBSCurve->pipetteButton1Pressed(provider, modifierKey); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void DiagonalCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { + case (DCT_Spline): + customCurve->pipetteButton1Pressed(provider, modifierKey); + break; + + case (DCT_Parametric): + if (editedAdjuster) { + editedAdjusterValue = editedAdjuster->getIntValue(); + } + + break; + + case (DCT_NURBS): + NURBSCurve->pipetteButton1Pressed(provider, modifierKey); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void DiagonalCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { - case (DCT_Spline): - customCurve->pipetteButton1Released(provider); - break; - case (DCT_Parametric): - editedAdjuster = NULL; - break; - case (DCT_NURBS): - NURBSCurve->pipetteButton1Released(provider); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void DiagonalCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { + case (DCT_Spline): + customCurve->pipetteButton1Released(provider); + break; + + case (DCT_Parametric): + editedAdjuster = NULL; + break; + + case (DCT_NURBS): + NURBSCurve->pipetteButton1Released(provider); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void DiagonalCurveEditorSubGroup::pipetteDrag(EditDataProvider *provider, int modifierKey) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { - case (DCT_Spline): - customCurve->pipetteDrag(provider, modifierKey); - break; - case (DCT_Parametric): - if (editedAdjuster) { - int trimmedValue = editedAdjuster->trimValue(editedAdjusterValue-(provider->deltaScreen.y/2)); - if (trimmedValue != editedAdjuster->getIntValue()) { - editedAdjuster->setValue(trimmedValue); - adjusterChanged(editedAdjuster, trimmedValue); - } - } - break; - case (DCT_NURBS): - NURBSCurve->pipetteDrag(provider, modifierKey); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void DiagonalCurveEditorSubGroup::pipetteDrag(EditDataProvider *provider, int modifierKey) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) { + case (DCT_Spline): + customCurve->pipetteDrag(provider, modifierKey); + break; + + case (DCT_Parametric): + if (editedAdjuster) { + int trimmedValue = editedAdjuster->trimValue(editedAdjusterValue - (provider->deltaScreen.y / 2)); + + if (trimmedValue != editedAdjuster->getIntValue()) { + editedAdjuster->setValue(trimmedValue); + adjusterChanged(editedAdjuster, trimmedValue); + } + } + + break; + + case (DCT_NURBS): + NURBSCurve->pipetteDrag(provider, modifierKey); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void DiagonalCurveEditorSubGroup::showCoordinateAdjuster(CoordinateProvider *provider) { - if (provider == customCurve) { - if (!editPointCustom->get_active()) editPointCustom->set_active(true); - } - else if (provider == NURBSCurve) { - if (!editPointNURBS->get_active()) editPointNURBS->set_active(true); - } +void DiagonalCurveEditorSubGroup::showCoordinateAdjuster(CoordinateProvider *provider) +{ + if (provider == customCurve) { + if (!editPointCustom->get_active()) { + editPointCustom->set_active(true); + } + } else if (provider == NURBSCurve) { + if (!editPointNURBS->get_active()) { + editPointNURBS->set_active(true); + } + } } -void DiagonalCurveEditorSubGroup::stopNumericalAdjustment() { - customCurve->stopNumericalAdjustment(); - NURBSCurve->stopNumericalAdjustment(); +void DiagonalCurveEditorSubGroup::stopNumericalAdjustment() +{ + customCurve->stopNumericalAdjustment(); + NURBSCurve->stopNumericalAdjustment(); } /* * Force the resize of the curve editor, if the displayed one is the requested one */ -void DiagonalCurveEditorSubGroup::refresh(CurveEditor *curveToRefresh) { - if (curveToRefresh != NULL && curveToRefresh == static_cast(parent->displayedCurve)) { - switch((DiagonalCurveType)(curveToRefresh->curveType->getSelected())) { - case (DCT_Spline): - customCurve->refresh(); - break; - case (DCT_Parametric): - paramCurve->refresh(); - shcSelector->refresh(); - break; - case (DCT_NURBS): - NURBSCurve->refresh(); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } - } +void DiagonalCurveEditorSubGroup::refresh(CurveEditor *curveToRefresh) +{ + if (curveToRefresh != NULL && curveToRefresh == static_cast(parent->displayedCurve)) { + switch((DiagonalCurveType)(curveToRefresh->curveType->getSelected())) { + case (DCT_Spline): + customCurve->refresh(); + break; + + case (DCT_Parametric): + paramCurve->refresh(); + shcSelector->refresh(); + break; + + case (DCT_NURBS): + NURBSCurve->refresh(); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } + } } /* * Switch the editor widgets to the currently edited curve */ -void DiagonalCurveEditorSubGroup::switchGUI() { +void DiagonalCurveEditorSubGroup::switchGUI() +{ - removeEditor(); + removeEditor(); - DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); + DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); - if (dCurve) { + if (dCurve) { - // Initializing GUI values + repacking the appropriated widget - //dCurve->typeconn.block(true); + // Initializing GUI values + repacking the appropriated widget + //dCurve->typeconn.block(true); - // first we update the colored bar + // first we update the colored bar - ColorProvider *barColorProvider = dCurve->getLeftBarColorProvider(); - std::vector bgGradient = dCurve->getLeftBarBgGradient(); - if (barColorProvider == NULL && bgGradient.size() == 0) { - // dCurve has no left colored bar, so we delete the object - if (leftBar) { - delete leftBar; - leftBar = NULL; - } - } - else { - // dCurve ave a ColorProvider or a background gradient defined, so we create/update the object - if (!leftBar) { - leftBar = new ColoredBar(RTO_Bottom2Top); - } - if (barColorProvider) { - bgGradient.clear(); - leftBar->setColorProvider(barColorProvider, dCurve->getLeftBarCallerId()); - leftBar->setBgGradient (bgGradient); - } - else { - leftBar->setColorProvider(NULL, -1); - leftBar->setBgGradient (bgGradient); - } - } + ColorProvider *barColorProvider = dCurve->getLeftBarColorProvider(); + std::vector bgGradient = dCurve->getLeftBarBgGradient(); - barColorProvider = dCurve->getBottomBarColorProvider(); - bgGradient = dCurve->getBottomBarBgGradient(); - if (barColorProvider == NULL && bgGradient.size() == 0) { - // dCurve has no bottom colored bar, so we delete the object - if (bottomBar) { - delete bottomBar; - bottomBar = NULL; - } - } - else { - // dCurve has a ColorProvider or a background gradient defined, so we create/update the object - if (!bottomBar) { - bottomBar = new ColoredBar(RTO_Left2Right); - } - if (barColorProvider) { - bgGradient.clear(); - bottomBar->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId()); - bottomBar->setBgGradient (bgGradient); - } - else { - bottomBar->setColorProvider(NULL, -1); - bottomBar->setBgGradient (bgGradient); - } - } + if (barColorProvider == NULL && bgGradient.size() == 0) { + // dCurve has no left colored bar, so we delete the object + if (leftBar) { + delete leftBar; + leftBar = NULL; + } + } else { + // dCurve ave a ColorProvider or a background gradient defined, so we create/update the object + if (!leftBar) { + leftBar = new ColoredBar(RTO_Bottom2Top); + } - switch((DiagonalCurveType)(dCurve->curveType->getSelected())) { - case (DCT_Spline): - customCurve->setPoints (dCurve->customCurveEd); - customCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId()); - customCurve->setColoredBar(leftBar, bottomBar); - customCurve->forceResize(); - updateEditButton(dCurve, editCustom, editCustomConn); - parent->pack_start (*customCurveBox); - customCurveBox->check_resize(); - break; - case (DCT_Parametric): - { - Glib::ustring label[4]; - dCurve->getRangeLabels(label[0], label[1], label[2], label[3]); - double mileStone[3]; - dCurve->getRangeDefaultMilestones(mileStone[0], mileStone[1], mileStone[2]); - paramCurve->setPoints (dCurve->paramCurveEd); - shcSelector->setDefaults(mileStone[0], mileStone[1], mileStone[2]); - shcSelector->setPositions ( - dCurve->paramCurveEd.at(1), - dCurve->paramCurveEd.at(2), - dCurve->paramCurveEd.at(3) - ); + if (barColorProvider) { + bgGradient.clear(); + leftBar->setColorProvider(barColorProvider, dCurve->getLeftBarCallerId()); + leftBar->setBgGradient (bgGradient); + } else { + leftBar->setColorProvider(NULL, -1); + leftBar->setBgGradient (bgGradient); + } + } - highlights->setValue (dCurve->paramCurveEd.at(4)); - highlights->setLabel(label[3]); - lights->setValue (dCurve->paramCurveEd.at(5)); - lights->setLabel(label[2]); - darks->setValue (dCurve->paramCurveEd.at(6)); - darks->setLabel(label[1]); - shadows->setValue (dCurve->paramCurveEd.at(7)); - shadows->setLabel(label[0]); - shcSelector->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId()); - shcSelector->setBgGradient(bgGradient); - shcSelector->setMargins( (leftBar ? MyCurve::getBarWidth()+CBAR_MARGIN : RADIUS), RADIUS ); - paramCurve->setColoredBar(leftBar, NULL); - paramCurve->forceResize(); - updateEditButton(dCurve, editParam, editParamConn); - parent->pack_start (*paramCurveBox); - break; - } - case (DCT_NURBS): - NURBSCurve->setPoints (dCurve->NURBSCurveEd); - NURBSCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId()); - NURBSCurve->setColoredBar(leftBar, bottomBar); - NURBSCurve->forceResize(); - updateEditButton(dCurve, editNURBS, editNURBSConn); - parent->pack_start (*NURBSCurveBox); - NURBSCurveBox->check_resize(); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } + barColorProvider = dCurve->getBottomBarColorProvider(); + bgGradient = dCurve->getBottomBarBgGradient(); - //dCurve->typeconn.block(false); - } + if (barColorProvider == NULL && bgGradient.size() == 0) { + // dCurve has no bottom colored bar, so we delete the object + if (bottomBar) { + delete bottomBar; + bottomBar = NULL; + } + } else { + // dCurve has a ColorProvider or a background gradient defined, so we create/update the object + if (!bottomBar) { + bottomBar = new ColoredBar(RTO_Left2Right); + } + + if (barColorProvider) { + bgGradient.clear(); + bottomBar->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId()); + bottomBar->setBgGradient (bgGradient); + } else { + bottomBar->setColorProvider(NULL, -1); + bottomBar->setBgGradient (bgGradient); + } + } + + switch((DiagonalCurveType)(dCurve->curveType->getSelected())) { + case (DCT_Spline): + customCurve->setPoints (dCurve->customCurveEd); + customCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId()); + customCurve->setColoredBar(leftBar, bottomBar); + customCurve->forceResize(); + updateEditButton(dCurve, editCustom, editCustomConn); + parent->pack_start (*customCurveBox); + customCurveBox->check_resize(); + break; + + case (DCT_Parametric): { + Glib::ustring label[4]; + dCurve->getRangeLabels(label[0], label[1], label[2], label[3]); + double mileStone[3]; + dCurve->getRangeDefaultMilestones(mileStone[0], mileStone[1], mileStone[2]); + paramCurve->setPoints (dCurve->paramCurveEd); + shcSelector->setDefaults(mileStone[0], mileStone[1], mileStone[2]); + shcSelector->setPositions ( + dCurve->paramCurveEd.at(1), + dCurve->paramCurveEd.at(2), + dCurve->paramCurveEd.at(3) + ); + + highlights->setValue (dCurve->paramCurveEd.at(4)); + highlights->setLabel(label[3]); + lights->setValue (dCurve->paramCurveEd.at(5)); + lights->setLabel(label[2]); + darks->setValue (dCurve->paramCurveEd.at(6)); + darks->setLabel(label[1]); + shadows->setValue (dCurve->paramCurveEd.at(7)); + shadows->setLabel(label[0]); + shcSelector->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId()); + shcSelector->setBgGradient(bgGradient); + shcSelector->setMargins( (leftBar ? MyCurve::getBarWidth() + CBAR_MARGIN : RADIUS), RADIUS ); + paramCurve->setColoredBar(leftBar, NULL); + paramCurve->forceResize(); + updateEditButton(dCurve, editParam, editParamConn); + parent->pack_start (*paramCurveBox); + break; + } + + case (DCT_NURBS): + NURBSCurve->setPoints (dCurve->NURBSCurveEd); + NURBSCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId()); + NURBSCurve->setColoredBar(leftBar, bottomBar); + NURBSCurve->forceResize(); + updateEditButton(dCurve, editNURBS, editNURBSConn); + parent->pack_start (*NURBSCurveBox); + NURBSCurveBox->check_resize(); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } + + //dCurve->typeconn.block(false); + } } -void DiagonalCurveEditorSubGroup::savePressed () { +void DiagonalCurveEditorSubGroup::savePressed () +{ - Glib::ustring fname = outputFile(); - if (fname.size()) { - std::ofstream f (fname.c_str()); - std::vector p; - //std::vector p = customCurve->getPoints (); + Glib::ustring fname = outputFile(); - switch (parent->displayedCurve->selected) { - case DCT_Spline: // custom - p = customCurve->getPoints (); - break; - case DCT_NURBS: // NURBS - p = NURBSCurve->getPoints (); - break; - case DCT_Parametric: - p = paramCurve->getPoints (); - break; - default: - break; - } + if (fname.size()) { + std::ofstream f (fname.c_str()); + std::vector p; + //std::vector p = customCurve->getPoints (); - int ix = 0; - if (p[ix]==(double)(DCT_Linear)) - f << "Linear" << std::endl; - else if (p[ix]==(double)(DCT_Spline)) - f << "Spline" << std::endl; - else if (p[ix]==(double)(DCT_NURBS)) - f << "NURBS" << std::endl; - else if (p[ix]==(double)(DCT_Parametric)) - f << "Parametric" << std::endl; - if (p[ix]==(double)(DCT_Parametric)) { - ix++; - for (unsigned int i=0; idisplayedCurve->selected) { + case DCT_Spline: // custom + p = customCurve->getPoints (); + break; - f.close (); - } + case DCT_NURBS: // NURBS + p = NURBSCurve->getPoints (); + break; + + case DCT_Parametric: + p = paramCurve->getPoints (); + break; + + default: + break; + } + + int ix = 0; + + if (p[ix] == (double)(DCT_Linear)) { + f << "Linear" << std::endl; + } else if (p[ix] == (double)(DCT_Spline)) { + f << "Spline" << std::endl; + } else if (p[ix] == (double)(DCT_NURBS)) { + f << "NURBS" << std::endl; + } else if (p[ix] == (double)(DCT_Parametric)) { + f << "Parametric" << std::endl; + } + + if (p[ix] == (double)(DCT_Parametric)) { + ix++; + + for (unsigned int i = 0; i < p.size() - 1; i++, ix++) { + f << p[ix] << std::endl; + } + } else { + ix++; + + for (unsigned int i = 0; i < p.size() / 2; i++, ix += 2) { + f << p[ix] << ' ' << p[ix + 1] << std::endl; + } + } + + f.close (); + } } -void DiagonalCurveEditorSubGroup::loadPressed () { +void DiagonalCurveEditorSubGroup::loadPressed () +{ - Glib::ustring fname = inputFile(); - if (fname.size()) { - std::ifstream f (fname.c_str()); - if (f) { - std::vector p; - std::string s; - f >> s; - if (s=="Linear") - p.push_back ((double)(DCT_Linear)); - else if (s=="Spline") - p.push_back ((double)(DCT_Spline)); - else if (s=="NURBS") - p.push_back ((double)(DCT_NURBS)); - else if (s=="Parametric") - p.push_back ((double)(DCT_Parametric)); - else return; + Glib::ustring fname = inputFile(); - double x; - while (f) { - f >> x; - if (f) - p.push_back (x); - } - if (p[0] == (double)(DCT_Spline)) { - customCurve->setPoints (p); - customCurve->queue_draw (); - customCurve->notifyListener (); - } - else if (p[0] == (double)(DCT_NURBS)) { - NURBSCurve->setPoints (p); - NURBSCurve->queue_draw (); - NURBSCurve->notifyListener (); - } - else if (p[0] == (double)(DCT_Parametric)) { - shcSelector->setPositions ( p[1], p[2], p[3] ); - highlights->setValue (p[4]); - lights->setValue (p[5]); - darks->setValue (p[6]); - shadows->setValue (p[7]); - paramCurve->setPoints (p); - paramCurve->queue_draw (); - paramCurve->notifyListener (); - } - } - } + if (fname.size()) { + std::ifstream f (fname.c_str()); + + if (f) { + std::vector p; + std::string s; + f >> s; + + if (s == "Linear") { + p.push_back ((double)(DCT_Linear)); + } else if (s == "Spline") { + p.push_back ((double)(DCT_Spline)); + } else if (s == "NURBS") { + p.push_back ((double)(DCT_NURBS)); + } else if (s == "Parametric") { + p.push_back ((double)(DCT_Parametric)); + } else { + return; + } + + double x; + + while (f) { + f >> x; + + if (f) { + p.push_back (x); + } + } + + if (p[0] == (double)(DCT_Spline)) { + customCurve->setPoints (p); + customCurve->queue_draw (); + customCurve->notifyListener (); + } else if (p[0] == (double)(DCT_NURBS)) { + NURBSCurve->setPoints (p); + NURBSCurve->queue_draw (); + NURBSCurve->notifyListener (); + } else if (p[0] == (double)(DCT_Parametric)) { + shcSelector->setPositions ( p[1], p[2], p[3] ); + highlights->setValue (p[4]); + lights->setValue (p[5]); + darks->setValue (p[6]); + shadows->setValue (p[7]); + paramCurve->setPoints (p); + paramCurve->queue_draw (); + paramCurve->notifyListener (); + } + } + } } -void DiagonalCurveEditorSubGroup::copyPressed () { +void DiagonalCurveEditorSubGroup::copyPressed () +{ // For compatibility use enum DiagonalCurveType here - std::vector curve; + std::vector curve; - switch (parent->displayedCurve->selected) { - case DCT_Spline: // custom - curve = customCurve->getPoints (); - clipboard.setDiagonalCurveData (curve,DCT_Spline); - break; - case DCT_Parametric: // parametric - // ... do something, first add save/load functions - curve = paramCurve->getPoints (); - clipboard.setDiagonalCurveData (curve,DCT_Parametric); - break; - case DCT_NURBS: // NURBS - curve = NURBSCurve->getPoints (); - clipboard.setDiagonalCurveData (curve,DCT_NURBS); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } + switch (parent->displayedCurve->selected) { + case DCT_Spline: // custom + curve = customCurve->getPoints (); + clipboard.setDiagonalCurveData (curve, DCT_Spline); + break; + + case DCT_Parametric: // parametric + // ... do something, first add save/load functions + curve = paramCurve->getPoints (); + clipboard.setDiagonalCurveData (curve, DCT_Parametric); + break; + + case DCT_NURBS: // NURBS + curve = NURBSCurve->getPoints (); + clipboard.setDiagonalCurveData (curve, DCT_NURBS); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void DiagonalCurveEditorSubGroup::pastePressed () { +void DiagonalCurveEditorSubGroup::pastePressed () +{ // For compatibility use enum DiagonalCurveType here - std::vector curve; - DiagonalCurveType type; + std::vector curve; + DiagonalCurveType type; - type = clipboard.hasDiagonalCurveData(); + type = clipboard.hasDiagonalCurveData(); - if (type == (DiagonalCurveType)parent->displayedCurve->selected) { - curve = clipboard.getDiagonalCurveData (); - switch (type) { - case DCT_Spline: // custom - customCurve->setPoints (curve); - customCurve->queue_draw (); - customCurve->notifyListener (); - break; - case DCT_Parametric: // parametric - // ... do something, first add save/load functions - shcSelector->setPositions ( - curve[1], - curve[2], - curve[3] ); - highlights->setValue (curve[4]); - lights->setValue (curve[5]); - darks->setValue (curve[6]); - shadows->setValue (curve[7]); - paramCurve->setPoints (curve); - paramCurve->queue_draw (); - paramCurve->notifyListener (); - break; - case DCT_NURBS: // NURBS - NURBSCurve->setPoints (curve); - NURBSCurve->queue_draw (); - NURBSCurve->notifyListener (); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } - } - return; + if (type == (DiagonalCurveType)parent->displayedCurve->selected) { + curve = clipboard.getDiagonalCurveData (); + + switch (type) { + case DCT_Spline: // custom + customCurve->setPoints (curve); + customCurve->queue_draw (); + customCurve->notifyListener (); + break; + + case DCT_Parametric: // parametric + // ... do something, first add save/load functions + shcSelector->setPositions ( + curve[1], + curve[2], + curve[3] ); + highlights->setValue (curve[4]); + lights->setValue (curve[5]); + darks->setValue (curve[6]); + shadows->setValue (curve[7]); + paramCurve->setPoints (curve); + paramCurve->queue_draw (); + paramCurve->notifyListener (); + break; + + case DCT_NURBS: // NURBS + NURBSCurve->setPoints (curve); + NURBSCurve->queue_draw (); + NURBSCurve->notifyListener (); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } + } + + return; } -void DiagonalCurveEditorSubGroup::editPointToggled(Gtk::ToggleButton *button) { - if (button->get_active()) { - customCoordAdjuster->show(); - NURBSCoordAdjuster->show(); - } - else { - if (customCoordAdjuster) { - customCurve->stopNumericalAdjustment(); - customCoordAdjuster->hide(); - NURBSCurve->stopNumericalAdjustment(); - NURBSCoordAdjuster->hide(); - } - } - if (button == editPointCustom) { - editPointNURBSConn.block(true); - editPointNURBS->set_active(!editPointNURBS->get_active()); - editPointNURBSConn.block(false); - } - else { - editPointCustomConn.block(true); - editPointCustom->set_active(!editPointCustom->get_active()); - editPointCustomConn.block(false); - } +void DiagonalCurveEditorSubGroup::editPointToggled(Gtk::ToggleButton *button) +{ + if (button->get_active()) { + customCoordAdjuster->show(); + NURBSCoordAdjuster->show(); + } else { + if (customCoordAdjuster) { + customCurve->stopNumericalAdjustment(); + customCoordAdjuster->hide(); + NURBSCurve->stopNumericalAdjustment(); + NURBSCoordAdjuster->hide(); + } + } + + if (button == editPointCustom) { + editPointNURBSConn.block(true); + editPointNURBS->set_active(!editPointNURBS->get_active()); + editPointNURBSConn.block(false); + } else { + editPointCustomConn.block(true); + editPointCustom->set_active(!editPointCustom->get_active()); + editPointCustomConn.block(false); + } } -void DiagonalCurveEditorSubGroup::editToggled (Gtk::ToggleButton *button) { - DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); - if (!dCurve) - // should never happen! - return; +void DiagonalCurveEditorSubGroup::editToggled (Gtk::ToggleButton *button) +{ + DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); - if (button->get_active()) { - dCurve->subscribe(); - if (button == editCustom) - customCurve->notifyListener (); - else if (button == editNURBS) - NURBSCurve->notifyListener (); - else if (button == editParam) - paramCurve->notifyListener (); + if (!dCurve) + // should never happen! + { + return; + } - /* - if (button != editCustom) { - editCustomConn.block(true); - editCustom->set_active(true); - editCustomConn.block(false); - } - else { - // will throw the event of curveChanged, which will now build the edit's buffer - customCurve->notifyListener (); - } - if (button != editNURBS) { - editNURBSConn.block(true); - editNURBS->set_active(true); - editNURBSConn.block(false); - } - else { - NURBSCurve->notifyListener (); - } - if (button != editParam) { - editParamConn.block(true); - editParam->set_active(true); - editParamConn.block(false); - } - else { - paramCurve->notifyListener (); - } - */ - } - else { - dCurve->unsubscribe(); - /* - if (button != editCustom ) { editCustomConn.block(true); editCustom->set_active(false); editCustomConn.block(false); } - if (button != editNURBS ) { editNURBSConn.block(true); editNURBS->set_active(false); editNURBSConn.block(false); } - if (button != editParam ) { editParamConn.block(true); editParam->set_active(false); editParamConn.block(false); } - */ - } + if (button->get_active()) { + dCurve->subscribe(); + + if (button == editCustom) { + customCurve->notifyListener (); + } else if (button == editNURBS) { + NURBSCurve->notifyListener (); + } else if (button == editParam) { + paramCurve->notifyListener (); + } + + /* + if (button != editCustom) { + editCustomConn.block(true); + editCustom->set_active(true); + editCustomConn.block(false); + } + else { + // will throw the event of curveChanged, which will now build the edit's buffer + customCurve->notifyListener (); + } + if (button != editNURBS) { + editNURBSConn.block(true); + editNURBS->set_active(true); + editNURBSConn.block(false); + } + else { + NURBSCurve->notifyListener (); + } + if (button != editParam) { + editParamConn.block(true); + editParam->set_active(true); + editParamConn.block(false); + } + else { + paramCurve->notifyListener (); + } + */ + } else { + dCurve->unsubscribe(); + /* + if (button != editCustom ) { editCustomConn.block(true); editCustom->set_active(false); editCustomConn.block(false); } + if (button != editNURBS ) { editNURBSConn.block(true); editNURBS->set_active(false); editNURBSConn.block(false); } + if (button != editParam ) { editParamConn.block(true); editParam->set_active(false); editParamConn.block(false); } + */ + } } /* * Store the curves of the currently displayed type from the widgets to the CurveEditor object */ -void DiagonalCurveEditorSubGroup::storeDisplayedCurve() { - if (parent->displayedCurve) { - switch (parent->displayedCurve->selected) { - case (DCT_Spline): - storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Spline)); - break; - case (DCT_Parametric): - storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Parametric)); - break; - case (DCT_NURBS): - storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_NURBS)); - break; - default: - break; - } - } +void DiagonalCurveEditorSubGroup::storeDisplayedCurve() +{ + if (parent->displayedCurve) { + switch (parent->displayedCurve->selected) { + case (DCT_Spline): + storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Spline)); + break; + + case (DCT_Parametric): + storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Parametric)); + break; + + case (DCT_NURBS): + storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_NURBS)); + break; + + default: + break; + } + } } /* * Restore the histogram to all types from the CurveEditor object to the widgets */ -void DiagonalCurveEditorSubGroup::restoreDisplayedHistogram() { - if (parent->displayedCurve /*&& initslope==1*/) { - paramCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); - customCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); - NURBSCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); - } - +void DiagonalCurveEditorSubGroup::restoreDisplayedHistogram() +{ + if (parent->displayedCurve /*&& initslope==1*/) { + paramCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); + customCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); + NURBSCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); + } + } -void DiagonalCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector& p) { - if (!p.empty()) { - DiagonalCurveType t = (DiagonalCurveType)p[0]; +void DiagonalCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector& p) +{ + if (!p.empty()) { + DiagonalCurveType t = (DiagonalCurveType)p[0]; - switch (t) { - case (DCT_Spline): - (static_cast(ce))->customCurveEd = p; - break; - case (DCT_Parametric): - (static_cast(ce))->paramCurveEd = p; - break; - case (DCT_NURBS): - (static_cast(ce))->NURBSCurveEd = p; - break; - default: - break; - } - } + switch (t) { + case (DCT_Spline): + (static_cast(ce))->customCurveEd = p; + break; + + case (DCT_Parametric): + (static_cast(ce))->paramCurveEd = p; + break; + + case (DCT_NURBS): + (static_cast(ce))->NURBSCurveEd = p; + break; + + default: + break; + } + } } /* * Called to update the parametric curve graph with new slider values */ -const std::vector DiagonalCurveEditorSubGroup::getCurveFromGUI (int type) { - switch ((DiagonalCurveType)type) { - case (DCT_Parametric): { - std::vector lcurve (8); - lcurve[0] = (double)(DCT_Parametric); - shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]); - lcurve[4] = highlights->getValue (); - lcurve[5] = lights->getValue (); - lcurve[6] = darks->getValue (); - lcurve[7] = shadows->getValue (); - return lcurve; - } - case (DCT_Spline): - return customCurve->getPoints (); - case (DCT_NURBS): - return NURBSCurve->getPoints (); - default: { - // linear and other solutions - std::vector lcurve (1); - lcurve[0] = (double)(DCT_Linear); - return lcurve; - } - } +const std::vector DiagonalCurveEditorSubGroup::getCurveFromGUI (int type) +{ + switch ((DiagonalCurveType)type) { + case (DCT_Parametric): { + std::vector lcurve (8); + lcurve[0] = (double)(DCT_Parametric); + shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]); + lcurve[4] = highlights->getValue (); + lcurve[5] = lights->getValue (); + lcurve[6] = darks->getValue (); + lcurve[7] = shadows->getValue (); + return lcurve; + } + + case (DCT_Spline): + return customCurve->getPoints (); + + case (DCT_NURBS): + return NURBSCurve->getPoints (); + + default: { + // linear and other solutions + std::vector lcurve (1); + lcurve[0] = (double)(DCT_Linear); + return lcurve; + } + } } /* * Unlink the tree editor widgets from their parent box to hide them */ -void DiagonalCurveEditorSubGroup::removeEditor () { - removeIfThere (parent, customCurveBox, false); - removeIfThere (parent, paramCurveBox, false); - removeIfThere (parent, NURBSCurveBox, false); +void DiagonalCurveEditorSubGroup::removeEditor () +{ + removeIfThere (parent, customCurveBox, false); + removeIfThere (parent, paramCurveBox, false); + removeIfThere (parent, NURBSCurveBox, false); } -bool DiagonalCurveEditorSubGroup::curveReset(CurveEditor *ce) { - if (!ce) - return false; +bool DiagonalCurveEditorSubGroup::curveReset(CurveEditor *ce) +{ + if (!ce) { + return false; + } - DiagonalCurveEditor *dce = static_cast(ce); + DiagonalCurveEditor *dce = static_cast(ce); - switch (ce->selected) { - case (DCT_NURBS) : // = Control cage - NURBSCurve->reset (dce->NURBSResetCurve, dce->getIdentityValue()); - return true; - break; - case (DCT_Spline) : // = Custom - customCurve->reset (dce->customResetCurve, dce->getIdentityValue()); - return true; - break; - case (DCT_Parametric) : - { - DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); - double mileStone[3]; - dCurve->getRangeDefaultMilestones(mileStone[0], mileStone[1], mileStone[2]); + switch (ce->selected) { + case (DCT_NURBS) : // = Control cage + NURBSCurve->reset (dce->NURBSResetCurve, dce->getIdentityValue()); + return true; + break; - highlights->resetPressed(NULL); - lights->resetPressed(NULL); - darks->resetPressed(NULL); - shadows->resetPressed(NULL); - shcSelector->setDefaults(mileStone[0], mileStone[1], mileStone[2]); - shcSelector->reset(); - paramCurve->reset (dce->paramResetCurve, dce->getIdentityValue()); - return true; - break; - } - default: - return false; - break; - } - return true; + case (DCT_Spline) : // = Custom + customCurve->reset (dce->customResetCurve, dce->getIdentityValue()); + return true; + break; + + case (DCT_Parametric) : { + DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); + double mileStone[3]; + dCurve->getRangeDefaultMilestones(mileStone[0], mileStone[1], mileStone[2]); + + highlights->resetPressed(NULL); + lights->resetPressed(NULL); + darks->resetPressed(NULL); + shadows->resetPressed(NULL); + shcSelector->setDefaults(mileStone[0], mileStone[1], mileStone[2]); + shcSelector->reset(); + paramCurve->reset (dce->paramResetCurve, dce->getIdentityValue()); + return true; + break; + } + + default: + return false; + break; + } + + return true; } /* * Listener */ -void DiagonalCurveEditorSubGroup::shcChanged () { +void DiagonalCurveEditorSubGroup::shcChanged () +{ paramCurve->setPoints (getCurveFromGUI(DCT_Parametric)); - storeDisplayedCurve(); - parent->curveChanged (); + storeDisplayedCurve(); + parent->curveChanged (); } /* * Listener */ -void DiagonalCurveEditorSubGroup::adjusterChanged (Adjuster* a, double newval) { +void DiagonalCurveEditorSubGroup::adjusterChanged (Adjuster* a, double newval) +{ - paramCurve->setPoints (getCurveFromGUI(DCT_Parametric)); - storeDisplayedCurve(); - parent->curveChanged (); + paramCurve->setPoints (getCurveFromGUI(DCT_Parametric)); + storeDisplayedCurve(); + parent->curveChanged (); } /* * Listener called when the mouse is over a parametric curve's slider */ -bool DiagonalCurveEditorSubGroup::adjusterEntered (GdkEventCrossing* ev, int ac) { +bool DiagonalCurveEditorSubGroup::adjusterEntered (GdkEventCrossing* ev, int ac) +{ - if (ev->detail != GDK_NOTIFY_INFERIOR) { - activeParamControl = ac; - paramCurve->setActiveParam (activeParamControl); - } - return true; + if (ev->detail != GDK_NOTIFY_INFERIOR) { + activeParamControl = ac; + paramCurve->setActiveParam (activeParamControl); + } + + return true; } /* * Listener called when the mouse left the parametric curve's slider */ -bool DiagonalCurveEditorSubGroup::adjusterLeft (GdkEventCrossing* ev, int ac) { +bool DiagonalCurveEditorSubGroup::adjusterLeft (GdkEventCrossing* ev, int ac) +{ - if (ev->detail != GDK_NOTIFY_INFERIOR) { - activeParamControl = -1; - paramCurve->setActiveParam (activeParamControl); - } - return true; + if (ev->detail != GDK_NOTIFY_INFERIOR) { + activeParamControl = -1; + paramCurve->setActiveParam (activeParamControl); + } + + return true; } -void DiagonalCurveEditorSubGroup::updateBackgroundHistogram (CurveEditor* ce) { - if (ce==parent->displayedCurve /*&& initslope==1*/) { - paramCurve->updateBackgroundHistogram (ce->histogram); - customCurve->updateBackgroundHistogram (ce->histogram); - NURBSCurve->updateBackgroundHistogram (ce->histogram); - } +void DiagonalCurveEditorSubGroup::updateBackgroundHistogram (CurveEditor* ce) +{ + if (ce == parent->displayedCurve /*&& initslope==1*/) { + paramCurve->updateBackgroundHistogram (ce->histogram); + customCurve->updateBackgroundHistogram (ce->histogram); + NURBSCurve->updateBackgroundHistogram (ce->histogram); + } } -void DiagonalCurveEditorSubGroup::setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4) { - shadows->setLabel(r1); - darks->setLabel(r2); - lights->setLabel(r3); - highlights->setLabel(r4); +void DiagonalCurveEditorSubGroup::setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4) +{ + shadows->setLabel(r1); + darks->setLabel(r2); + lights->setLabel(r3); + highlights->setLabel(r4); } diff --git a/rtgui/diagonalcurveeditorsubgroup.h b/rtgui/diagonalcurveeditorsubgroup.h index 827cebac3..8178eb56a 100644 --- a/rtgui/diagonalcurveeditorsubgroup.h +++ b/rtgui/diagonalcurveeditorsubgroup.h @@ -24,90 +24,91 @@ class DiagonalCurveEditor; -class DiagonalCurveEditorSubGroup : public CurveEditorSubGroup, public SHCListener, public AdjusterListener { +class DiagonalCurveEditorSubGroup : public CurveEditorSubGroup, public SHCListener, public AdjusterListener +{ - friend class DiagonalCurveEditor; + friend class DiagonalCurveEditor; protected: - Gtk::VBox* customCurveBox; - Gtk::VBox* NURBSCurveBox; - Gtk::VBox* paramCurveBox; + Gtk::VBox* customCurveBox; + Gtk::VBox* NURBSCurveBox; + Gtk::VBox* paramCurveBox; - MyDiagonalCurve* customCurve; - MyDiagonalCurve* NURBSCurve; - MyDiagonalCurve* paramCurve; + MyDiagonalCurve* customCurve; + MyDiagonalCurve* NURBSCurve; + MyDiagonalCurve* paramCurve; - SHCSelector* shcSelector; - Adjuster* highlights; - Adjuster* lights; - Adjuster* darks; - Adjuster* shadows; + SHCSelector* shcSelector; + Adjuster* highlights; + Adjuster* lights; + Adjuster* darks; + Adjuster* shadows; - Adjuster *editedAdjuster; - int editedAdjusterValue; + Adjuster *editedAdjuster; + int editedAdjusterValue; - CoordinateAdjuster *customCoordAdjuster; - CoordinateAdjuster *NURBSCoordAdjuster; + CoordinateAdjuster *customCoordAdjuster; + CoordinateAdjuster *NURBSCoordAdjuster; - Gtk::Button* saveCustom; - Gtk::Button* loadCustom; - Gtk::Button* copyCustom; - Gtk::Button* pasteCustom; - Gtk::ToggleButton* editPointCustom; - Gtk::ToggleButton* editCustom; - sigc::connection editCustomConn, editPointCustomConn; - Gtk::Button* saveNURBS; - Gtk::Button* loadNURBS; - Gtk::Button* copyNURBS; - Gtk::Button* pasteNURBS; - Gtk::ToggleButton* editPointNURBS; - Gtk::ToggleButton* editNURBS; - sigc::connection editNURBSConn, editPointNURBSConn; - Gtk::Button* saveParam; - Gtk::Button* loadParam; - Gtk::Button* copyParam; - Gtk::Button* pasteParam; - Gtk::ToggleButton* editParam; - sigc::connection editParamConn; + Gtk::Button* saveCustom; + Gtk::Button* loadCustom; + Gtk::Button* copyCustom; + Gtk::Button* pasteCustom; + Gtk::ToggleButton* editPointCustom; + Gtk::ToggleButton* editCustom; + sigc::connection editCustomConn, editPointCustomConn; + Gtk::Button* saveNURBS; + Gtk::Button* loadNURBS; + Gtk::Button* copyNURBS; + Gtk::Button* pasteNURBS; + Gtk::ToggleButton* editPointNURBS; + Gtk::ToggleButton* editNURBS; + sigc::connection editNURBSConn, editPointNURBSConn; + Gtk::Button* saveParam; + Gtk::Button* loadParam; + Gtk::Button* copyParam; + Gtk::Button* pasteParam; + Gtk::ToggleButton* editParam; + sigc::connection editParamConn; - int activeParamControl; + int activeParamControl; public: - DiagonalCurveEditorSubGroup(CurveEditorGroup* prt, Glib::ustring& curveDir); - virtual ~DiagonalCurveEditorSubGroup(); + DiagonalCurveEditorSubGroup(CurveEditorGroup* prt, Glib::ustring& curveDir); + virtual ~DiagonalCurveEditorSubGroup(); - DiagonalCurveEditor* addCurve(Glib::ustring curveLabel = ""); - virtual void updateBackgroundHistogram (CurveEditor* ce); - void switchGUI(); - void refresh(CurveEditor *curveToRefresh); - void editModeSwitchedOff (); - void pipetteMouseOver(EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); - void pipetteButton1Released(EditDataProvider *provider); - void pipetteDrag(EditDataProvider *provider, int modifierKey); - void showCoordinateAdjuster(CoordinateProvider *provider); - void stopNumericalAdjustment(); + DiagonalCurveEditor* addCurve(Glib::ustring curveLabel = ""); + virtual void updateBackgroundHistogram (CurveEditor* ce); + void switchGUI(); + void refresh(CurveEditor *curveToRefresh); + void editModeSwitchedOff (); + void pipetteMouseOver(EditDataProvider *provider, int modifierKey); + void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + void pipetteButton1Released(EditDataProvider *provider); + void pipetteDrag(EditDataProvider *provider, int modifierKey); + void showCoordinateAdjuster(CoordinateProvider *provider); + void stopNumericalAdjustment(); - bool curveReset (CurveEditor *ce); + bool curveReset (CurveEditor *ce); protected: - void storeCurveValues (CurveEditor* ce, const std::vector& p); - void storeDisplayedCurve (); - void restoreDisplayedHistogram (); - void savePressed (); - void loadPressed (); - void copyPressed (); - void pastePressed (); - void editPointToggled(Gtk::ToggleButton *button); - void editToggled (Gtk::ToggleButton *button); - void removeEditor (); - const std::vector getCurveFromGUI (int type); - void shcChanged (); - void adjusterChanged (Adjuster* a, double newval); - bool adjusterEntered (GdkEventCrossing* ev, int ac); - bool adjusterLeft (GdkEventCrossing* ev, int ac); - void setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4); - void setSubGroupBottomBarBgGradient(); + void storeCurveValues (CurveEditor* ce, const std::vector& p); + void storeDisplayedCurve (); + void restoreDisplayedHistogram (); + void savePressed (); + void loadPressed (); + void copyPressed (); + void pastePressed (); + void editPointToggled(Gtk::ToggleButton *button); + void editToggled (Gtk::ToggleButton *button); + void removeEditor (); + const std::vector getCurveFromGUI (int type); + void shcChanged (); + void adjusterChanged (Adjuster* a, double newval); + bool adjusterEntered (GdkEventCrossing* ev, int ac); + bool adjusterLeft (GdkEventCrossing* ev, int ac); + void setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4); + void setSubGroupBottomBarBgGradient(); }; #endif diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index c08680c64..914b74ef5 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -7,7 +7,7 @@ * 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 @@ -33,113 +33,113 @@ struct DirNameComparator { template - bool operator()(T const &firstDir, T const &secondDir) const { + bool operator()(T const &firstDir, T const &secondDir) const + { return options.dirBrowserSortType == Gtk::SORT_ASCENDING ? firstDir < secondDir : firstDir > secondDir; } }; DirBrowser::DirBrowser () : dirTreeModel(), - dtColumns(), - tvc(M("DIRBROWSER_FOLDERS")), - expandSuccess(false) - #ifdef WIN32 - , volumes(0) - #endif + dtColumns(), + tvc(M("DIRBROWSER_FOLDERS")), + expandSuccess(false) +#ifdef WIN32 + , volumes(0) +#endif { - dirtree = Gtk::manage ( new Gtk::TreeView() ); - scrolledwindow4 = Gtk::manage ( new Gtk::ScrolledWindow() ); + dirtree = Gtk::manage ( new Gtk::TreeView() ); + scrolledwindow4 = Gtk::manage ( new Gtk::ScrolledWindow() ); // dirtree->set_flags(Gtk::CAN_FOCUS); - dirtree->set_headers_visible(); - dirtree->set_headers_clickable(); - dirtree->set_rules_hint(false); - dirtree->set_reorderable(false); - dirtree->set_enable_search(false); - scrolledwindow4->set_flags(Gtk::CAN_FOCUS); - scrolledwindow4->set_border_width(2); - scrolledwindow4->set_shadow_type(Gtk::SHADOW_NONE); - scrolledwindow4->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - scrolledwindow4->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); - scrolledwindow4->add(*dirtree); + dirtree->set_headers_visible(); + dirtree->set_headers_clickable(); + dirtree->set_rules_hint(false); + dirtree->set_reorderable(false); + dirtree->set_enable_search(false); + scrolledwindow4->set_flags(Gtk::CAN_FOCUS); + scrolledwindow4->set_border_width(2); + scrolledwindow4->set_shadow_type(Gtk::SHADOW_NONE); + scrolledwindow4->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + scrolledwindow4->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); + scrolledwindow4->add(*dirtree); - pack_start (*scrolledwindow4); - dirtree->show (); - scrolledwindow4->show (); + pack_start (*scrolledwindow4); + dirtree->show (); + scrolledwindow4->show (); } -void DirBrowser::fillDirTree () { +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 = 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"); - //Create the Tree model: - dirTreeModel = Gtk::TreeStore::create(dtColumns); - dirtree->set_model (dirTreeModel); + //Create the Tree model: + dirTreeModel = Gtk::TreeStore::create(dtColumns); + dirtree->set_model (dirTreeModel); - fillRoot (); + fillRoot (); - Gtk::CellRendererPixbuf* render_pb = Gtk::manage ( new Gtk::CellRendererPixbuf () ); - tvc.pack_start (*render_pb, false); - tvc.add_attribute(*render_pb, "pixbuf-expander-closed", dtColumns.icon2); - tvc.add_attribute(*render_pb, "pixbuf", dtColumns.icon2); - tvc.add_attribute(*render_pb, "pixbuf-expander-open", dtColumns.icon1); - tvc.pack_start (crt); - tvc.add_attribute(crt, "text", dtColumns.filename); + Gtk::CellRendererPixbuf* render_pb = Gtk::manage ( new Gtk::CellRendererPixbuf () ); + tvc.pack_start (*render_pb, false); + tvc.add_attribute(*render_pb, "pixbuf-expander-closed", dtColumns.icon2); + tvc.add_attribute(*render_pb, "pixbuf", dtColumns.icon2); + tvc.add_attribute(*render_pb, "pixbuf-expander-open", dtColumns.icon1); + tvc.pack_start (crt); + tvc.add_attribute(crt, "text", dtColumns.filename); - dirtree->append_column(tvc); + dirtree->append_column(tvc); - tvc.set_sort_order(options.dirBrowserSortType); - tvc.set_sort_column(dtColumns.filename); - tvc.set_sort_indicator(true); - tvc.set_clickable(); + tvc.set_sort_order(options.dirBrowserSortType); + tvc.set_sort_column(dtColumns.filename); + tvc.set_sort_indicator(true); + tvc.set_clickable(); - dirTreeModel->set_sort_column(dtColumns.filename, options.dirBrowserSortType); + dirTreeModel->set_sort_column(dtColumns.filename, options.dirBrowserSortType); - crt.property_ypad() = 0; - render_pb->property_ypad() = 0; + crt.property_ypad() = 0; + render_pb->property_ypad() = 0; - dirtree->signal_row_expanded().connect(sigc::mem_fun(*this, &DirBrowser::row_expanded)); - dirtree->signal_row_activated().connect(sigc::mem_fun(*this, &DirBrowser::row_activated)); - dirTreeModel->signal_sort_column_changed().connect(sigc::mem_fun(*this, &DirBrowser::on_sort_column_changed)); + dirtree->signal_row_expanded().connect(sigc::mem_fun(*this, &DirBrowser::row_expanded)); + dirtree->signal_row_activated().connect(sigc::mem_fun(*this, &DirBrowser::row_activated)); + dirTreeModel->signal_sort_column_changed().connect(sigc::mem_fun(*this, &DirBrowser::on_sort_column_changed)); } #ifdef WIN32 -void DirBrowser::addRoot (char letter) { +void DirBrowser::addRoot (char letter) +{ char volume[4]; volume[0] = letter; - strcpy (volume+1, ":\\"); + strcpy (volume + 1, ":\\"); Gtk::TreeModel::iterator root = dirTreeModel->append(); root->set_value (dtColumns.filename, Glib::ustring(volume)); root->set_value (dtColumns.dirname, Glib::ustring(volume)); int type = GetDriveType (volume); - if (type==DRIVE_CDROM) { + + if (type == DRIVE_CDROM) { root->set_value (0, icdrom); root->set_value (1, icdrom); - } - else if (type==DRIVE_REMOVABLE) { - if (letter-'A'<2) { + } else if (type == DRIVE_REMOVABLE) { + if (letter - 'A' < 2) { root->set_value (0, ifloppy); root->set_value (1, ifloppy); - } - else { + } else { root->set_value (0, iremovable); root->set_value (1, iremovable); } - } - else if (type==DRIVE_REMOTE) { + } else if (type == DRIVE_REMOTE) { root->set_value (0, inetwork); root->set_value (1, inetwork); - } - else if (type==DRIVE_FIXED) { + } else if (type == DRIVE_FIXED) { root->set_value (0, ihdd); root->set_value (1, ihdd); } @@ -148,154 +148,178 @@ void DirBrowser::addRoot (char letter) { child->set_value (dtColumns.filename, Glib::ustring("foo")); } -void DirBrowser::updateDirTreeRoot () { +void DirBrowser::updateDirTreeRoot () +{ - for (Gtk::TreeModel::iterator i=dirTreeModel->children().begin(); i!=dirTreeModel->children().end(); i++) - updateDirTree (i); + for (Gtk::TreeModel::iterator i = dirTreeModel->children().begin(); i != dirTreeModel->children().end(); i++) { + updateDirTree (i); + } } -void DirBrowser::updateDirTree (const Gtk::TreeModel::iterator& iter) { - - if (dirtree->row_expanded (dirTreeModel->get_path (iter))) { - updateDir (iter); - for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++) - updateDirTree (i); - } +void DirBrowser::updateDirTree (const Gtk::TreeModel::iterator& iter) +{ + + if (dirtree->row_expanded (dirTreeModel->get_path (iter))) { + updateDir (iter); + + for (Gtk::TreeModel::iterator i = iter->children().begin(); i != iter->children().end(); i++) { + updateDirTree (i); + } + } } -void DirBrowser::updateVolumes () { +void DirBrowser::updateVolumes () +{ int nvolumes = GetLogicalDrives (); - if (nvolumes!=volumes) { + + if (nvolumes != volumes) { GThreadLock lock; - for (int i=0; i<32; i++) + for (int i = 0; i < 32; i++) if (((volumes >> i) & 1) && !((nvolumes >> i) & 1)) { // volume i has been deleted - for (Gtk::TreeModel::iterator iter = dirTreeModel->children().begin(); iter!=dirTreeModel->children().end(); iter++) - if (iter->get_value (dtColumns.filename).c_str()[0]-'A' == i) { + for (Gtk::TreeModel::iterator iter = dirTreeModel->children().begin(); iter != dirTreeModel->children().end(); iter++) + if (iter->get_value (dtColumns.filename).c_str()[0] - 'A' == i) { dirTreeModel->erase (iter); break; } + } else if (!((volumes >> i) & 1) && ((nvolumes >> i) & 1)) { + addRoot ('A' + i); // volume i has been added } - else if (!((volumes >> i) & 1) && ((nvolumes >> i) & 1)) - addRoot ('A'+i); // volume i has been added + volumes = nvolumes; } } -int updateVolumesUI (void* br) { +int updateVolumesUI (void* br) +{ (static_cast(br))->updateVolumes (); return 1; } -int updateDirTreeUI (void* br) { +int updateDirTreeUI (void* br) +{ (static_cast(br))->updateDirTreeRoot (); return 0; } -void DirBrowser::winDirChanged () { +void DirBrowser::winDirChanged () +{ g_idle_add (updateDirTreeUI, this); } #endif -void DirBrowser::fillRoot () { +void DirBrowser::fillRoot () +{ #ifdef WIN32 - volumes = GetLogicalDrives (); - for (int i=0; i<32; i++) - if ((volumes >> i) & 1) - addRoot ('A'+i); - // since sigc++ is not thread safe, we have to use the glib function - g_timeout_add (CHECKTIME, updateVolumesUI, this); + volumes = GetLogicalDrives (); + + for (int i = 0; i < 32; i++) + if ((volumes >> i) & 1) { + addRoot ('A' + i); + } + + // since sigc++ is not thread safe, we have to use the glib function + g_timeout_add (CHECKTIME, updateVolumesUI, this); #else - Gtk::TreeModel::Row rootRow = *(dirTreeModel->append()); - rootRow[dtColumns.filename] = "/"; - rootRow[dtColumns.dirname] = "/"; - Gtk::TreeModel::Row childRow = *(dirTreeModel->append(rootRow.children())); - childRow[dtColumns.filename] = "foo"; + Gtk::TreeModel::Row rootRow = *(dirTreeModel->append()); + rootRow[dtColumns.filename] = "/"; + rootRow[dtColumns.dirname] = "/"; + Gtk::TreeModel::Row childRow = *(dirTreeModel->append(rootRow.children())); + childRow[dtColumns.filename] = "foo"; #endif } -void DirBrowser::on_sort_column_changed() const { - options.dirBrowserSortType = tvc.get_sort_order(); +void DirBrowser::on_sort_column_changed() const +{ + options.dirBrowserSortType = tvc.get_sort_order(); } -void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path) { +void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path) +{ - expandSuccess = false; + expandSuccess = false; - // 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 - // 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); + // 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 + // 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; + 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); + DirPathType subDirs; + Glib::RefPtr dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); - if (subDirs.empty()) { - dirtree->collapse_row(path); - } - else { - Gtk::TreeNodeChildren children = iter->children(); - std::list forErase(children.begin(), children.end()); + safe_build_subdir_list (dir, subDirs, options.fbShowHidden); - DirNameComparator comparator; - sort(subDirs.begin(), subDirs.end(), comparator); + if (subDirs.empty()) { + dirtree->collapse_row(path); + } else { + Gtk::TreeNodeChildren children = iter->children(); + std::list forErase(children.begin(), children.end()); - for (DirPathType::const_iterator it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { - addDir(iter, *it); + DirNameComparator comparator; + sort(subDirs.begin(), subDirs.end(), comparator); + + for (DirPathType::const_iterator 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) { + dirTreeModel->erase(*it); + } + + dirTreeModel->set_sort_column(prevSortColumn, prevSortType); + + expandSuccess = true; } - for (std::list::const_iterator it = forErase.begin(), end = forErase.end(); it != end; ++it) { - dirTreeModel->erase(*it); - } - dirTreeModel->set_sort_column(prevSortColumn, prevSortType); - - expandSuccess = true; - } #ifdef WIN32 - Glib::RefPtr monitor = Glib::RefPtr(new WinDirMonitor (iter->get_value (dtColumns.dirname), this)); - iter->set_value (dtColumns.monitor, monitor); + Glib::RefPtr monitor = Glib::RefPtr(new WinDirMonitor (iter->get_value (dtColumns.dirname), this)); + iter->set_value (dtColumns.monitor, monitor); #else - Glib::RefPtr monitor = dir->monitor_directory (); - iter->set_value (dtColumns.monitor, monitor); - monitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &DirBrowser::file_changed), iter, dir->get_parse_name())); + Glib::RefPtr monitor = dir->monitor_directory (); + iter->set_value (dtColumns.monitor, monitor); + monitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &DirBrowser::file_changed), iter, dir->get_parse_name())); #endif } -void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) { +void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) +{ // first test if some files are deleted bool change = true; + while (change) { 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)) { + + 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)) { GThreadLock lock; dirTreeModel->erase (it); change = true; break; } } + // 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); - for (int i=0; ichildren().begin(); it!=iter->children().end() && !found ; it++) - found = (it->get_value (dtColumns.filename)==subDirs[i]); + + for (Gtk::TreeModel::iterator it = iter->children().begin(); it != iter->children().end() && !found ; it++) { + found = (it->get_value (dtColumns.filename) == subDirs[i]); + } if (!found) { GThreadLock lock; @@ -304,7 +328,8 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) { } } -void DirBrowser::addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirname) { +void DirBrowser::addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirname) +{ Gtk::TreeModel::iterator child = dirTreeModel->append(iter->children()); child->set_value (dtColumns.filename, dirname); @@ -316,15 +341,19 @@ void DirBrowser::addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustri fooRow->set_value (dtColumns.filename, Glib::ustring("foo")); } -void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) { +void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) +{ Glib::ustring dname = dirTreeModel->get_iter (path)->get_value (dtColumns.dirname); - if (safe_file_test (dname, Glib::FILE_TEST_IS_DIR)) - for (size_t i=0; idirSelected (dname); + } } -Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) { +Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) +{ Gtk::TreeModel::Path path; path.append_index(0); @@ -345,18 +374,24 @@ Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) { while (dir) { Glib::ustring dirstr = dir; #ifdef WIN32 - if (count==0) + + if (count == 0) { dirstr = dirstr + "\\"; + } + #endif Gtk::TreeModel::iterator i = dirTreeModel->get_iter (path); int ix = 0; + while (i && expandSuccess) { Gtk::TreeModel::Row crow = *i; - Glib::ustring str =crow[dtColumns.filename]; + Glib::ustring str = crow[dtColumns.filename]; #ifdef WIN32 - if (str.casefold()==dirstr.casefold()) { + + if (str.casefold() == dirstr.casefold()) { #else - if (str==dirstr) { + + if (str == dirstr) { #endif path.up (); path.append_index (ix); @@ -364,9 +399,11 @@ Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) { path.append_index (0); break; } + ix++; i++; } + count++; dir = strtok(NULL, "/\\"); } @@ -379,36 +416,46 @@ Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) { return path; } -void DirBrowser::open (const Glib::ustring& dirname, const Glib::ustring& fileName) { - +void DirBrowser::open (const Glib::ustring& dirname, const Glib::ustring& fileName) +{ + dirtree->collapse_all (); // WARNING & TODO: One should test here if the directory/file has R/W access permission to avoid crash Glib::RefPtr dir = Gio::File::create_for_path(dirname); - if( !dir->query_exists()) - return; + + if( !dir->query_exists()) { + return; + } + Glib::ustring absDirPath = dir->get_parse_name (); Gtk::TreePath path = expandToDir (absDirPath); - dirtree->scroll_to_row (path); - dirtree->get_selection()->select (path); - Glib::ustring absFilePath; - if (!fileName.empty()) - absFilePath = Glib::build_filename (absDirPath, fileName); - for (size_t i=0; idirSelected (absDirPath, absFilePath); - } + dirtree->scroll_to_row (path); + dirtree->get_selection()->select (path); + Glib::ustring absFilePath; + + if (!fileName.empty()) { + absFilePath = Glib::build_filename (absDirPath, fileName); + } + + for (size_t i = 0; i < dllisteners.size(); i++) { + dllisteners[i]->dirSelected (absDirPath, absFilePath); + } } -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) { +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 || !safe_file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type == Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) { return; + } updateDir (iter); } -void DirBrowser::selectDir (Glib::ustring dir) { +void DirBrowser::selectDir (Glib::ustring dir) +{ open (dir, ""); } diff --git a/rtgui/dirbrowser.h b/rtgui/dirbrowser.h index dc9c21522..fcba64ce0 100644 --- a/rtgui/dirbrowser.h +++ b/rtgui/dirbrowser.h @@ -7,7 +7,7 @@ * 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 @@ -31,25 +31,32 @@ class DirBrowser : public Gtk::VBox, public DirBrowserRemoteInterface #ifdef WIN32 , public WinDirChangeListener #endif - { +{ - private: +private: Glib::RefPtr dirTreeModel; - + struct DirTreeColumns : public Gtk::TreeModelColumnRecord { - public: + public: Gtk::TreeModelColumn filename; Gtk::TreeModelColumn > icon1; Gtk::TreeModelColumn > icon2; Gtk::TreeModelColumn dirname; - #ifdef WIN32 +#ifdef WIN32 Gtk::TreeModelColumn > monitor; - #else +#else Gtk::TreeModelColumn > monitor; - #endif - - DirTreeColumns() { add(icon1); add(icon2); add(filename); add(dirname); add(monitor); } +#endif + + DirTreeColumns() + { + add(icon1); + add(icon2); + add(filename); + add(dirname); + add(monitor); + } }; DirTreeColumns dtColumns; @@ -74,22 +81,22 @@ class DirBrowser : public Gtk::VBox, public DirBrowserRemoteInterface bool expandSuccess; - #ifdef WIN32 +#ifdef WIN32 int volumes; - public: +public: void updateVolumes (); - void updateDirTree (const Gtk::TreeModel::iterator& iter); - void updateDirTreeRoot (); + void updateDirTree (const Gtk::TreeModel::iterator& iter); + void updateDirTreeRoot (); void winDirChanged (); - private: +private: void addRoot (char letter); - #endif +#endif void addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirname); Gtk::TreePath expandToDir (const Glib::ustring& dirName); void updateDir (const Gtk::TreeModel::iterator& iter); void notifyListeners (); - public: +public: DirBrowser (); void fillDirTree (); @@ -97,9 +104,12 @@ class DirBrowser : public Gtk::VBox, public DirBrowserRemoteInterface void row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path); void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); void file_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirName); - void open (const Glib::ustring& dirName, const Glib::ustring& fileName=""); // goes to dir "dirName" and selects file "fileName" - void addDirSelectionListener (DirSelectionListener* l) { dllisteners.push_back (l); } + void open (const Glib::ustring& dirName, const Glib::ustring& fileName = ""); // goes to dir "dirName" and selects file "fileName" + void addDirSelectionListener (DirSelectionListener* l) + { + dllisteners.push_back (l); + } void selectDir (Glib::ustring dir); -}; +}; #endif diff --git a/rtgui/dirbrowserremoteinterface.h b/rtgui/dirbrowserremoteinterface.h index e5ae9c847..dda78bc47 100644 --- a/rtgui/dirbrowserremoteinterface.h +++ b/rtgui/dirbrowserremoteinterface.h @@ -7,7 +7,7 @@ * 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 @@ -21,10 +21,11 @@ #include -class DirBrowserRemoteInterface { +class DirBrowserRemoteInterface +{ - public: - virtual void selectDir (Glib::ustring dir) {} +public: + virtual void selectDir (Glib::ustring dir) {} }; #endif diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index 3c0acbcd2..5eac04b2a 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -7,7 +7,7 @@ * 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 @@ -26,447 +26,462 @@ using namespace rtengine; using namespace rtengine::procparams; extern Options options; -DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastenhance(false) { - std::vector milestones; - CurveListener::setMulti(true); - nextnresid=0.; - nexthighresid=0.; - nextchroma=15.; - nextred=0.; - nextblue=0.; - - setEnabledTooltipMarkup(M("TP_DIRPYRDENOISE_ENABLED_TOOLTIP")); +DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastenhance(false) +{ + std::vector milestones; + CurveListener::setMulti(true); + nextnresid = 0.; + nexthighresid = 0.; + nextchroma = 15.; + nextred = 0.; + nextblue = 0.; - std::vector defaultCurve; - - Gtk::Frame* lumaFrame = Gtk::manage (new Gtk::Frame (M("TP_DIRPYRDENOISE_LUMAFR")) ); - lumaFrame->set_tooltip_text(M("TP_DIRPYRDENOISE_LUMAFR_TOOLTIP")); - lumaFrame->set_border_width(0); - lumaFrame->set_label_align(0.025, 0.5); - - Gtk::VBox * lumaVBox = Gtk::manage ( new Gtk::VBox()); - lumaVBox->set_border_width(4); - lumaVBox->set_spacing(2); + setEnabledTooltipMarkup(M("TP_DIRPYRDENOISE_ENABLED_TOOLTIP")); - - - ctboxL = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labmL = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_LTYPE")+":")); - ctboxL->pack_start (*labmL, Gtk::PACK_SHRINK, 1); - - Lmethod = Gtk::manage (new MyComboBoxText ()); - Lmethod->append_text (M("TP_DIRPYRDENOISE_CUR")); - Lmethod->append_text (M("TP_DIRPYRDENOISE_SLI")); - Lmethod->set_active(0); - Lmethodconn = Lmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::LmethodChanged) ); - - luma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LUMA"), 0, 100, 0.01, 0)); - Ldetail = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LDETAIL"), 0, 100, 0.01, 50)); - NoiscurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_LCURVE")); - //curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); - NoiscurveEditorG->setCurveListener (this); - rtengine::DirPyrDenoiseParams::getDefaultNoisCurve(defaultCurve); - lshape = static_cast(NoiscurveEditorG->addCurve(CT_Flat, "", NULL, false)); - lshape->setIdentityValue(0.); - lshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + std::vector defaultCurve; - lshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_L_TOOLTIP")); - //lshape->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - lshape->setBottomBarBgGradient(milestones); - //lshape->setLeftBarBgGradient(milestones); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - NoiscurveEditorG->curveListComplete(); - NoiscurveEditorG->show(); - - Gtk::Frame* chromaFrame = Gtk::manage (new Gtk::Frame (M("TP_DIRPYRDENOISE_CHROMAFR")) ); - chromaFrame->set_border_width(0); - chromaFrame->set_label_align(0.025, 0.5); - - Gtk::VBox *chromaVBox = Gtk::manage ( new Gtk::VBox()); - chromaVBox->set_spacing(2); - chromaVBox->set_border_width(4); - - autochroma=Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_AUTO"))); - autochroma->set_active (true); - autochroma->set_tooltip_text (M("TP_DIRPYRDENOISE_AUTO_TOOLTIP")); - - ctboxC = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labmC = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE")+":")); - ctboxC->pack_start (*labmC, Gtk::PACK_SHRINK, 1); - ctboxC->set_tooltip_markup (M("TP_DIRPYRDENOISE_CTYPE_TOOLTIP")); - - Cmethod = Gtk::manage (new MyComboBoxText ()); - Cmethod->append_text (M("TP_DIRPYRDENOISE_MAN")); - Cmethod->append_text (M("TP_DIRPYRDENOISE_AUT")); - Cmethod->append_text (M("TP_DIRPYRDENOISE_PON")); - Cmethod->append_text (M("TP_DIRPYRDENOISE_PRE")); - Cmethod->set_active(0); - Cmethodconn = Cmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::CmethodChanged) ); - - ctboxC2 = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labmC2 = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE")+":")); - ctboxC2->pack_start (*labmC2, Gtk::PACK_SHRINK, 1); - ctboxC2->set_tooltip_markup (M("TP_DIRPYRDENOISE_C2TYPE_TOOLTIP")); - - C2method = Gtk::manage (new MyComboBoxText ()); - C2method->append_text (M("TP_DIRPYRDENOISE_MANU")); - C2method->append_text (M("TP_DIRPYRDENOISE_AUTO")); - C2method->append_text (M("TP_DIRPYRDENOISE_PREV")); - C2method->set_active(0); - C2methodconn = C2method->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::C2methodChanged) ); - - - NoiseLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); - NoiseLabels->set_tooltip_text(M("TP_DIRPYRDENOISE_NRESID_TOOLTIP")); + Gtk::Frame* lumaFrame = Gtk::manage (new Gtk::Frame (M("TP_DIRPYRDENOISE_LUMAFR")) ); + lumaFrame->set_tooltip_text(M("TP_DIRPYRDENOISE_LUMAFR_TOOLTIP")); + lumaFrame->set_border_width(0); + lumaFrame->set_label_align(0.025, 0.5); - TileLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); - PrevLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); - - chroma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_CHROMA"), 0, 100, 0.01, 15)); - redchro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_RED"), -100, 100, 0.1, 0)); - bluechro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_BLUE"), -100, 100, 0.1, 0)); - - gamma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_GAMMA"), 1.0, 3.0, 0.01, 1.7)); - gamma->set_tooltip_text (M("TP_DIRPYRDENOISE_GAMMA_TOOLTIP")); + Gtk::VBox * lumaVBox = Gtk::manage ( new Gtk::VBox()); + lumaVBox->set_border_width(4); + lumaVBox->set_spacing(2); - - Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); - hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_METHOD") +": ")),Gtk::PACK_SHRINK, 4); - hb1->set_tooltip_markup (M("TP_DIRPYRDENOISE_METHOD_TOOLTIP")); - - dmethod = Gtk::manage (new MyComboBoxText ()); - dmethod->append_text (M("TP_DIRPYRDENOISE_LAB")); - dmethod->append_text (M("TP_DIRPYRDENOISE_RGB")); - dmethod->set_active(0); - hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb1, Gtk::PACK_SHRINK, 4); - - dmethodconn = dmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::dmethodChanged) ); - - luma->setAdjusterListener (this); - Ldetail->setAdjusterListener (this); - chroma->setAdjusterListener (this); - redchro->setAdjusterListener (this); - bluechro->setAdjusterListener (this); - - CCcurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_CCCURVE")); - CCcurveEditorG->setCurveListener (this); - rtengine::DirPyrDenoiseParams::getDefaultCCCurve(defaultCurve); - ccshape = static_cast(CCcurveEditorG->addCurve(CT_Flat, "", NULL, false)); - ccshape->setIdentityValue(0.); - ccshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - ccshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_CC_TOOLTIP")); - ccshape->setBottomBarColorProvider(this, 2); + ctboxL = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmL = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_LTYPE") + ":")); + ctboxL->pack_start (*labmL, Gtk::PACK_SHRINK, 1); - CCcurveEditorG->curveListComplete(); + Lmethod = Gtk::manage (new MyComboBoxText ()); + Lmethod->append_text (M("TP_DIRPYRDENOISE_CUR")); + Lmethod->append_text (M("TP_DIRPYRDENOISE_SLI")); + Lmethod->set_active(0); + Lmethodconn = Lmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::LmethodChanged) ); + + luma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LUMA"), 0, 100, 0.01, 0)); + Ldetail = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LDETAIL"), 0, 100, 0.01, 50)); + NoiscurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_LCURVE")); + //curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); + NoiscurveEditorG->setCurveListener (this); + rtengine::DirPyrDenoiseParams::getDefaultNoisCurve(defaultCurve); + lshape = static_cast(NoiscurveEditorG->addCurve(CT_Flat, "", NULL, false)); + lshape->setIdentityValue(0.); + lshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + + lshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_L_TOOLTIP")); + //lshape->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + lshape->setBottomBarBgGradient(milestones); + //lshape->setLeftBarBgGradient(milestones); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + NoiscurveEditorG->curveListComplete(); + NoiscurveEditorG->show(); + + Gtk::Frame* chromaFrame = Gtk::manage (new Gtk::Frame (M("TP_DIRPYRDENOISE_CHROMAFR")) ); + chromaFrame->set_border_width(0); + chromaFrame->set_label_align(0.025, 0.5); + + Gtk::VBox *chromaVBox = Gtk::manage ( new Gtk::VBox()); + chromaVBox->set_spacing(2); + chromaVBox->set_border_width(4); + + autochroma = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_AUTO"))); + autochroma->set_active (true); + autochroma->set_tooltip_text (M("TP_DIRPYRDENOISE_AUTO_TOOLTIP")); + + ctboxC = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmC = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE") + ":")); + ctboxC->pack_start (*labmC, Gtk::PACK_SHRINK, 1); + ctboxC->set_tooltip_markup (M("TP_DIRPYRDENOISE_CTYPE_TOOLTIP")); + + Cmethod = Gtk::manage (new MyComboBoxText ()); + Cmethod->append_text (M("TP_DIRPYRDENOISE_MAN")); + Cmethod->append_text (M("TP_DIRPYRDENOISE_AUT")); + Cmethod->append_text (M("TP_DIRPYRDENOISE_PON")); + Cmethod->append_text (M("TP_DIRPYRDENOISE_PRE")); + Cmethod->set_active(0); + Cmethodconn = Cmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::CmethodChanged) ); + + ctboxC2 = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmC2 = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE") + ":")); + ctboxC2->pack_start (*labmC2, Gtk::PACK_SHRINK, 1); + ctboxC2->set_tooltip_markup (M("TP_DIRPYRDENOISE_C2TYPE_TOOLTIP")); + + C2method = Gtk::manage (new MyComboBoxText ()); + C2method->append_text (M("TP_DIRPYRDENOISE_MANU")); + C2method->append_text (M("TP_DIRPYRDENOISE_AUTO")); + C2method->append_text (M("TP_DIRPYRDENOISE_PREV")); + C2method->set_active(0); + C2methodconn = C2method->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::C2methodChanged) ); + + + NoiseLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + NoiseLabels->set_tooltip_text(M("TP_DIRPYRDENOISE_NRESID_TOOLTIP")); + + TileLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + PrevLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + + chroma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_CHROMA"), 0, 100, 0.01, 15)); + redchro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_RED"), -100, 100, 0.1, 0)); + bluechro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_BLUE"), -100, 100, 0.1, 0)); + + gamma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_GAMMA"), 1.0, 3.0, 0.01, 1.7)); + gamma->set_tooltip_text (M("TP_DIRPYRDENOISE_GAMMA_TOOLTIP")); + + + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_METHOD") + ": ")), Gtk::PACK_SHRINK, 4); + hb1->set_tooltip_markup (M("TP_DIRPYRDENOISE_METHOD_TOOLTIP")); + + dmethod = Gtk::manage (new MyComboBoxText ()); + dmethod->append_text (M("TP_DIRPYRDENOISE_LAB")); + dmethod->append_text (M("TP_DIRPYRDENOISE_RGB")); + dmethod->set_active(0); + hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb1, Gtk::PACK_SHRINK, 4); + + + dmethodconn = dmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::dmethodChanged) ); + + luma->setAdjusterListener (this); + Ldetail->setAdjusterListener (this); + chroma->setAdjusterListener (this); + redchro->setAdjusterListener (this); + bluechro->setAdjusterListener (this); + + CCcurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_CCCURVE")); + CCcurveEditorG->setCurveListener (this); + rtengine::DirPyrDenoiseParams::getDefaultCCCurve(defaultCurve); + ccshape = static_cast(CCcurveEditorG->addCurve(CT_Flat, "", NULL, false)); + ccshape->setIdentityValue(0.); + ccshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + + ccshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_CC_TOOLTIP")); + ccshape->setBottomBarColorProvider(this, 2); + + CCcurveEditorG->curveListComplete(); + + + //----------------------------------------- + + gamma->setAdjusterListener (this); - - //----------------------------------------- - - gamma->setAdjusterListener (this); - luma->hide(); Ldetail->show(); -// autochroma->show(); - NoiseLabels->show(); - TileLabels->show(); - PrevLabels->show(); +// autochroma->show(); + NoiseLabels->show(); + TileLabels->show(); + PrevLabels->show(); chroma->show(); redchro->show(); bluechro->show(); -// perform->show(); - gamma->show(); -// perform->set_active (true); +// perform->show(); + gamma->show(); +// perform->set_active (true); - enhance = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_ENH"))); - enhance->set_active (false); - enhance->set_tooltip_text (M("TP_DIRPYRDENOISE_ENH_TOOLTIP")); - // ---- Median FIltering ---- + enhance = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_ENH"))); + enhance->set_active (false); + enhance->set_tooltip_text (M("TP_DIRPYRDENOISE_ENH_TOOLTIP")); + // ---- Median FIltering ---- - Gtk::Frame* medianFrame = Gtk::manage (new Gtk::Frame ()); - medianFrame->set_border_width(0); - medianFrame->set_label_align(0.025, 0.5); - - Gtk::VBox *medianVBox = Gtk::manage ( new Gtk::VBox()); - medianVBox->set_spacing(2); - medianVBox->set_border_width(4); + Gtk::Frame* medianFrame = Gtk::manage (new Gtk::Frame ()); + medianFrame->set_border_width(0); + medianFrame->set_label_align(0.025, 0.5); - median = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_MED")+":")); - median->set_active (true); - median->set_tooltip_text (M("TP_DIRPYRDENOISE_MED_TOOLTIP")); - medianFrame->set_label_widget(*median); + Gtk::VBox *medianVBox = Gtk::manage ( new Gtk::VBox()); + medianVBox->set_spacing(2); + medianVBox->set_border_width(4); - - Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); - hsep2->show (); - - methodmed = Gtk::manage (new MyComboBoxText ()); - methodmed->append_text (M("TP_DIRPYRDENOISE_LM")); - methodmed->append_text (M("TP_DIRPYRDENOISE_ABM")); - methodmed->append_text (M("TP_DIRPYRDENOISE_LPLABM")); - methodmed->append_text (M("TP_DIRPYRDENOISE_LABM")); - methodmed->append_text (M("TP_DIRPYRDENOISE_RGBM")); - methodmed->set_active (0); - methodmed->set_tooltip_text (M("TP_DIRPYRDENOISE_METM_TOOLTIP")); - methodmedconn = methodmed->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::methodmedChanged) ); - - rgbmethod = Gtk::manage (new MyComboBoxText ()); - rgbmethod->append_text (M("TP_DIRPYRDENOISE_SOFT")); - rgbmethod->append_text (M("TP_DIRPYRDENOISE_33")); - rgbmethod->append_text (M("TP_DIRPYRDENOISE_55SOFT")); - rgbmethod->set_active (0); - rgbmethod->set_tooltip_text (M("TP_DIRPYRDENOISE_MET_TOOLTIP")); - rgbmethodconn = rgbmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::rgbmethodChanged) ); - - - medmethod = Gtk::manage (new MyComboBoxText ()); - medmethod->append_text (M("TP_DIRPYRDENOISE_SOFT")); - medmethod->append_text (M("TP_DIRPYRDENOISE_33")); - medmethod->append_text (M("TP_DIRPYRDENOISE_55SOFT")); - medmethod->append_text (M("TP_DIRPYRDENOISE_55")); - medmethod->append_text (M("TP_DIRPYRDENOISE_77")); - medmethod->append_text (M("TP_DIRPYRDENOISE_99")); - medmethod->set_active (0); - medmethod->set_tooltip_text (M("TP_DIRPYRDENOISE_MET_TOOLTIP")); - medmethodconn = medmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::medmethodChanged) ); - - ctboxm = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labmm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDMETHOD")+":")); - ctboxm->pack_start (*labmm, Gtk::PACK_SHRINK, 1); - - ctbox = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE")+":")); - ctbox->pack_start (*labm, Gtk::PACK_SHRINK, 1); - - ctboxrgb = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labrgb = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE")+":")); - ctboxrgb->pack_start (*labrgb, Gtk::PACK_SHRINK, 1); + median = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_MED") + ":")); + median->set_active (true); + median->set_tooltip_text (M("TP_DIRPYRDENOISE_MED_TOOLTIP")); + medianFrame->set_label_widget(*median); - Gtk::HSeparator *hsep4 = Gtk::manage (new Gtk::HSeparator()); - hsep4->show (); + Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); + hsep2->show (); - Gtk::HBox* hb11 = Gtk::manage (new Gtk::HBox ()); - hb11->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_METHOD11") +": ")),Gtk::PACK_SHRINK, 4); - hb11->set_tooltip_markup (M("TP_DIRPYRDENOISE_METHOD11_TOOLTIP")); - - smethod = Gtk::manage (new MyComboBoxText ()); - smethod->append_text (M("TP_DIRPYRDENOISE_SHAL")); -// smethod->append_text (M("TP_DIRPYRDENOISE_SHBI")); - smethod->append_text (M("TP_DIRPYRDENOISE_SHALBI")); -// smethod->append_text (M("TP_DIRPYRDENOISE_SHALAL")); -// smethod->append_text (M("TP_DIRPYRDENOISE_SHBIBI")); - smethod->set_active(1); - hb11->pack_start (*smethod, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb11, Gtk::PACK_SHRINK, 4); - smethodconn = smethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::smethodChanged) ); + methodmed = Gtk::manage (new MyComboBoxText ()); + methodmed->append_text (M("TP_DIRPYRDENOISE_LM")); + methodmed->append_text (M("TP_DIRPYRDENOISE_ABM")); + methodmed->append_text (M("TP_DIRPYRDENOISE_LPLABM")); + methodmed->append_text (M("TP_DIRPYRDENOISE_LABM")); + methodmed->append_text (M("TP_DIRPYRDENOISE_RGBM")); + methodmed->set_active (0); + methodmed->set_tooltip_text (M("TP_DIRPYRDENOISE_METM_TOOLTIP")); + methodmedconn = methodmed->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::methodmedChanged) ); - passes = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_PASSES"), 1.0, 3.0, 1., 1.)); - passes->set_tooltip_text (M("TP_DIRPYRDENOISE_PASSES_TOOLTIP")); - passes->setAdjusterListener (this); - passes->show(); - ctboxL->pack_start (*Lmethod); - lumaVBox->pack_start (*ctboxL); - lumaVBox->pack_start (*luma); - lumaVBox->pack_start (*NoiscurveEditorG, Gtk::PACK_SHRINK, 4); - lumaVBox->pack_start (*Ldetail); - lumaFrame->add(*lumaVBox); - pack_start (*lumaFrame); - - ctboxC->pack_start (*Cmethod); - ctboxC2->pack_start (*C2method); - if(options.rtSettings.leveldnautsimpl==1){ - chromaVBox->pack_start (*ctboxC); - } - else { - chromaVBox->pack_start (*ctboxC2); - } - chromaVBox->pack_start (*NoiseLabels); - chromaVBox->pack_start (*TileLabels); - chromaVBox->pack_start (*PrevLabels); - - chromaVBox->pack_start (*chroma); - chromaVBox->pack_start (*redchro); - chromaVBox->pack_start (*bluechro); - chromaVBox->pack_start (*CCcurveEditorG, Gtk::PACK_SHRINK, 4); - chromaFrame->add(*chromaVBox); - pack_start (*chromaFrame); + rgbmethod = Gtk::manage (new MyComboBoxText ()); + rgbmethod->append_text (M("TP_DIRPYRDENOISE_SOFT")); + rgbmethod->append_text (M("TP_DIRPYRDENOISE_33")); + rgbmethod->append_text (M("TP_DIRPYRDENOISE_55SOFT")); + rgbmethod->set_active (0); + rgbmethod->set_tooltip_text (M("TP_DIRPYRDENOISE_MET_TOOLTIP")); + rgbmethodconn = rgbmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::rgbmethodChanged) ); - pack_start (*gamma); - //pack_start (*enhance); - pack_start (*hsep4); - -// pack_start( *hb11, Gtk::PACK_SHRINK, 4); - -// pack_start (*hsep2); -// pack_start (*median); - - ctboxm->pack_start (*methodmed); - ctbox->pack_start (*medmethod); - ctboxrgb->pack_start (*rgbmethod); -// pack_start (*ctboxm); -// pack_start (*ctbox); -// pack_start (*ctboxrgb); -// pack_start (*passes,Gtk::PACK_SHRINK, 1); - - medianVBox->pack_start (*ctboxm); - medianVBox->pack_start (*ctbox); - medianVBox->pack_start (*ctboxrgb); - medianVBox->pack_start (*passes); - medianFrame->add(*medianVBox); + medmethod = Gtk::manage (new MyComboBoxText ()); + medmethod->append_text (M("TP_DIRPYRDENOISE_SOFT")); + medmethod->append_text (M("TP_DIRPYRDENOISE_33")); + medmethod->append_text (M("TP_DIRPYRDENOISE_55SOFT")); + medmethod->append_text (M("TP_DIRPYRDENOISE_55")); + medmethod->append_text (M("TP_DIRPYRDENOISE_77")); + medmethod->append_text (M("TP_DIRPYRDENOISE_99")); + medmethod->set_active (0); + medmethod->set_tooltip_text (M("TP_DIRPYRDENOISE_MET_TOOLTIP")); + medmethodconn = medmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::medmethodChanged) ); + + ctboxm = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDMETHOD") + ":")); + ctboxm->pack_start (*labmm, Gtk::PACK_SHRINK, 1); + + ctbox = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE") + ":")); + ctbox->pack_start (*labm, Gtk::PACK_SHRINK, 1); + + ctboxrgb = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labrgb = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE") + ":")); + ctboxrgb->pack_start (*labrgb, Gtk::PACK_SHRINK, 1); + + + Gtk::HSeparator *hsep4 = Gtk::manage (new Gtk::HSeparator()); + hsep4->show (); + + Gtk::HBox* hb11 = Gtk::manage (new Gtk::HBox ()); + hb11->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_METHOD11") + ": ")), Gtk::PACK_SHRINK, 4); + hb11->set_tooltip_markup (M("TP_DIRPYRDENOISE_METHOD11_TOOLTIP")); + + smethod = Gtk::manage (new MyComboBoxText ()); + smethod->append_text (M("TP_DIRPYRDENOISE_SHAL")); +// smethod->append_text (M("TP_DIRPYRDENOISE_SHBI")); + smethod->append_text (M("TP_DIRPYRDENOISE_SHALBI")); +// smethod->append_text (M("TP_DIRPYRDENOISE_SHALAL")); +// smethod->append_text (M("TP_DIRPYRDENOISE_SHBIBI")); + smethod->set_active(1); + hb11->pack_start (*smethod, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb11, Gtk::PACK_SHRINK, 4); + smethodconn = smethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::smethodChanged) ); + + passes = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_PASSES"), 1.0, 3.0, 1., 1.)); + passes->set_tooltip_text (M("TP_DIRPYRDENOISE_PASSES_TOOLTIP")); + passes->setAdjusterListener (this); + passes->show(); + ctboxL->pack_start (*Lmethod); + lumaVBox->pack_start (*ctboxL); + lumaVBox->pack_start (*luma); + lumaVBox->pack_start (*NoiscurveEditorG, Gtk::PACK_SHRINK, 4); + lumaVBox->pack_start (*Ldetail); + lumaFrame->add(*lumaVBox); + pack_start (*lumaFrame); + + ctboxC->pack_start (*Cmethod); + ctboxC2->pack_start (*C2method); + + if(options.rtSettings.leveldnautsimpl == 1) { + chromaVBox->pack_start (*ctboxC); + } else { + chromaVBox->pack_start (*ctboxC2); + } + + chromaVBox->pack_start (*NoiseLabels); + chromaVBox->pack_start (*TileLabels); + chromaVBox->pack_start (*PrevLabels); + + chromaVBox->pack_start (*chroma); + chromaVBox->pack_start (*redchro); + chromaVBox->pack_start (*bluechro); + chromaVBox->pack_start (*CCcurveEditorG, Gtk::PACK_SHRINK, 4); + chromaFrame->add(*chromaVBox); + pack_start (*chromaFrame); + + + pack_start (*gamma); + //pack_start (*enhance); + pack_start (*hsep4); + +// pack_start( *hb11, Gtk::PACK_SHRINK, 4); + +// pack_start (*hsep2); +// pack_start (*median); + + ctboxm->pack_start (*methodmed); + ctbox->pack_start (*medmethod); + ctboxrgb->pack_start (*rgbmethod); +// pack_start (*ctboxm); +// pack_start (*ctbox); +// pack_start (*ctboxrgb); +// pack_start (*passes,Gtk::PACK_SHRINK, 1); + + medianVBox->pack_start (*ctboxm); + medianVBox->pack_start (*ctbox); + medianVBox->pack_start (*ctboxrgb); + medianVBox->pack_start (*passes); + medianFrame->add(*medianVBox); + + pack_start (*medianFrame); + + +// pack_start (*perform); + enhanConn = enhance->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::enhanceChanged) ); + autochromaConn = autochroma->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::autochromaChanged) ); + medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::medianChanged) ); + ctboxrgb->hide(); - pack_start (*medianFrame); - - -// pack_start (*perform); - enhanConn = enhance->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::enhanceChanged) ); - autochromaConn = autochroma->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::autochromaChanged) ); - medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::medianChanged) ); - ctboxrgb->hide(); - } -DirPyrDenoise::~DirPyrDenoise () { - delete NoiscurveEditorG; - delete CCcurveEditorG; - +DirPyrDenoise::~DirPyrDenoise () +{ + delete NoiscurveEditorG; + delete CCcurveEditorG; + } -int chromaChangedUI (void* data) { +int chromaChangedUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected (static_cast(data))->chromaComputed_ (); return 0; } -void DirPyrDenoise::chromaChanged (double autchroma, double autred, double autblue) +void DirPyrDenoise::chromaChanged (double autchroma, double autred, double autblue) { nextchroma = autchroma; -// printf("CHROM=%f\n",nextchroma); - nextred=autred; - nextblue=autblue; +// printf("CHROM=%f\n",nextchroma); + nextred = autred; + nextblue = autblue; g_idle_add (chromaChangedUI, this); } - -bool DirPyrDenoise::chromaComputed_ () { + +bool DirPyrDenoise::chromaComputed_ () +{ disableListener (); - chroma->setValue (nextchroma); - redchro->setValue (nextred); - bluechro->setValue (nextblue); + chroma->setValue (nextchroma); + redchro->setValue (nextred); + bluechro->setValue (nextblue); enableListener (); - updateNoiseLabel (); + updateNoiseLabel (); return false; } -int TilePrevChangedUI (void* data) { +int TilePrevChangedUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected (static_cast(data))->TilePrevComputed_ (); - return 0; + return 0; } void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) { - nexttileX=tileX; - nexttileY=tileY; - nextprevX=prevX; - nextprevY=prevY; - nextsizeT=sizeT; - nextsizeP=sizeP; - + nexttileX = tileX; + nexttileY = tileY; + nextprevX = prevX; + nextprevY = prevY; + nextsizeT = sizeT; + nextsizeP = sizeP; + g_idle_add (TilePrevChangedUI, this); } -bool DirPyrDenoise::TilePrevComputed_ () { +bool DirPyrDenoise::TilePrevComputed_ () +{ disableListener (); enableListener (); - updateTileLabel (); - updatePrevLabel (); + updateTileLabel (); + updatePrevLabel (); return false; } -void DirPyrDenoise::updateTileLabel () { - if (!batchMode) { - float sT; - float nX, nY; - sT=nextsizeT; - nX = nexttileX; - nY = nexttileY; - { - TileLabels->set_text( - Glib::ustring::compose(M("TP_DIRPYRDENOISE_TILELABEL"), - Glib::ustring::format(std::fixed, std::setprecision(0), sT), - Glib::ustring::format(std::fixed, std::setprecision(0), nX), - Glib::ustring::format(std::fixed, std::setprecision(0), nY)) - ); - } - } +void DirPyrDenoise::updateTileLabel () +{ + if (!batchMode) { + float sT; + float nX, nY; + sT = nextsizeT; + nX = nexttileX; + nY = nexttileY; + { + TileLabels->set_text( + Glib::ustring::compose(M("TP_DIRPYRDENOISE_TILELABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), sT), + Glib::ustring::format(std::fixed, std::setprecision(0), nX), + Glib::ustring::format(std::fixed, std::setprecision(0), nY)) + ); + } + } } -void DirPyrDenoise::updatePrevLabel () { - if (!batchMode) { - float sP; - float pX, pY; - sP=nextsizeP; - pX = nextprevX; - pY = nextprevY; - { - PrevLabels->set_text( - Glib::ustring::compose(M("TP_DIRPYRDENOISE_PREVLABEL"), - Glib::ustring::format(std::fixed, std::setprecision(0), sP), - Glib::ustring::format(std::fixed, std::setprecision(0), pX), - Glib::ustring::format(std::fixed, std::setprecision(0), pY)) - ); - } - } +void DirPyrDenoise::updatePrevLabel () +{ + if (!batchMode) { + float sP; + float pX, pY; + sP = nextsizeP; + pX = nextprevX; + pY = nextprevY; + { + PrevLabels->set_text( + Glib::ustring::compose(M("TP_DIRPYRDENOISE_PREVLABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), sP), + Glib::ustring::format(std::fixed, std::setprecision(0), pX), + Glib::ustring::format(std::fixed, std::setprecision(0), pY)) + ); + } + } } -int noiseChangedUI (void* data) { +int noiseChangedUI (void* data) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected (static_cast(data))->noiseComputed_ (); - return 0; + return 0; } -void DirPyrDenoise::noiseChanged (double nresid, double highresid) +void DirPyrDenoise::noiseChanged (double nresid, double highresid) { - nextnresid=nresid; - nexthighresid=highresid; + nextnresid = nresid; + nexthighresid = highresid; g_idle_add (noiseChangedUI, this); } -bool DirPyrDenoise::noiseComputed_ () { +bool DirPyrDenoise::noiseComputed_ () +{ disableListener (); enableListener (); - updateNoiseLabel (); + updateNoiseLabel (); return false; } -void DirPyrDenoise::updateNoiseLabel () { - if (!batchMode) { - float nois, high; - nois = nextnresid; - high= nexthighresid; - if(nois==0.f && high==0.f) NoiseLabels->set_text(M("TP_DIRPYRDENOISE_NOISELABELEMPTY")); - else { - NoiseLabels->set_text( - Glib::ustring::compose(M("TP_DIRPYRDENOISE_NOISELABEL"), - Glib::ustring::format(std::fixed, std::setprecision(0), nois), - Glib::ustring::format(std::fixed, std::setprecision(0), high)) - ); - } - } +void DirPyrDenoise::updateNoiseLabel () +{ + if (!batchMode) { + float nois, high; + nois = nextnresid; + high = nexthighresid; + + if(nois == 0.f && high == 0.f) { + NoiseLabels->set_text(M("TP_DIRPYRDENOISE_NOISELABELEMPTY")); + } else { + NoiseLabels->set_text( + Glib::ustring::compose(M("TP_DIRPYRDENOISE_NOISELABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), nois), + Glib::ustring::format(std::fixed, std::setprecision(0), high)) + ); + } + } } -void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { +void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); dmethodconn.block(true); @@ -474,125 +489,163 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { Cmethodconn.block(true); C2methodconn.block(true); smethodconn.block(true); - autochromaConn.block(true); - medmethodconn.block(true); - rgbmethodconn.block(true); - methodmedconn.block(true); + autochromaConn.block(true); + medmethodconn.block(true); + rgbmethodconn.block(true); + methodmedconn.block(true); - - autochromaChanged (); + + autochromaChanged (); dmethod->set_active (0); - if (pp->dirpyrDenoise.dmethod=="Lab") + + if (pp->dirpyrDenoise.dmethod == "Lab") { dmethod->set_active (0); - else if (pp->dirpyrDenoise.dmethod=="RGB") + } else if (pp->dirpyrDenoise.dmethod == "RGB") { dmethod->set_active (1); - dmethodChanged (); - + } + + dmethodChanged (); + Lmethod->set_active (0); - if (pp->dirpyrDenoise.Lmethod=="CUR") + + if (pp->dirpyrDenoise.Lmethod == "CUR") { Lmethod->set_active (0); - else if (pp->dirpyrDenoise.Lmethod=="SLI") + } else if (pp->dirpyrDenoise.Lmethod == "SLI") { Lmethod->set_active (1); - LmethodChanged(); - - if(options.rtSettings.leveldnautsimpl==1){ - Cmethod->set_active (0); - if (pp->dirpyrDenoise.Cmethod=="MAN") - Cmethod->set_active (0); - else if (pp->dirpyrDenoise.Cmethod=="AUT") - Cmethod->set_active (1); - else if (pp->dirpyrDenoise.Cmethod=="PON") - Cmethod->set_active (2); - else if (pp->dirpyrDenoise.Cmethod=="PRE") - Cmethod->set_active (3); - CmethodChanged(); - } - else { - C2method->set_active (0); - if (pp->dirpyrDenoise.C2method=="MANU") - C2method->set_active (0); - else if (pp->dirpyrDenoise.C2method=="AUTO") - C2method->set_active (1); - else if (pp->dirpyrDenoise.C2method=="PREV") - C2method->set_active (2); - - C2methodChanged(); - } - + } + + LmethodChanged(); + + if(options.rtSettings.leveldnautsimpl == 1) { + Cmethod->set_active (0); + + if (pp->dirpyrDenoise.Cmethod == "MAN") { + Cmethod->set_active (0); + } else if (pp->dirpyrDenoise.Cmethod == "AUT") { + Cmethod->set_active (1); + } else if (pp->dirpyrDenoise.Cmethod == "PON") { + Cmethod->set_active (2); + } else if (pp->dirpyrDenoise.Cmethod == "PRE") { + Cmethod->set_active (3); + } + + CmethodChanged(); + } else { + C2method->set_active (0); + + if (pp->dirpyrDenoise.C2method == "MANU") { + C2method->set_active (0); + } else if (pp->dirpyrDenoise.C2method == "AUTO") { + C2method->set_active (1); + } else if (pp->dirpyrDenoise.C2method == "PREV") { + C2method->set_active (2); + } + + C2methodChanged(); + } + smethod->set_active (0); - if (pp->dirpyrDenoise.smethod=="shal") + + if (pp->dirpyrDenoise.smethod == "shal") { smethod->set_active (0); + } // else if (pp->dirpyrDenoise.smethod=="shbi") // smethod->set_active (1); - else if (pp->dirpyrDenoise.smethod=="shalbi") + else if (pp->dirpyrDenoise.smethod == "shalbi") { smethod->set_active (1); - // else if (pp->dirpyrDenoise.smethod=="shalal") - // smethod->set_active (3); - // else if (pp->dirpyrDenoise.smethod=="shbibi") - // smethod->set_active (4); - + } + +// else if (pp->dirpyrDenoise.smethod=="shalal") +// smethod->set_active (3); +// else if (pp->dirpyrDenoise.smethod=="shbibi") +// smethod->set_active (4); + methodmed->set_active (0); - // if (pp->dirpyrDenoise.methodmed=="none") - // methodmed->set_active (0); - if (pp->dirpyrDenoise.methodmed=="Lonly") + +// if (pp->dirpyrDenoise.methodmed=="none") +// methodmed->set_active (0); + if (pp->dirpyrDenoise.methodmed == "Lonly") { methodmed->set_active (0); - else if (pp->dirpyrDenoise.methodmed=="ab") + } else if (pp->dirpyrDenoise.methodmed == "ab") { methodmed->set_active (1); - else if (pp->dirpyrDenoise.methodmed=="Lpab") - methodmed->set_active (2); - else if (pp->dirpyrDenoise.methodmed=="Lab") + } else if (pp->dirpyrDenoise.methodmed == "Lpab") { + methodmed->set_active (2); + } else if (pp->dirpyrDenoise.methodmed == "Lab") { methodmed->set_active (3); - else if (pp->dirpyrDenoise.methodmed=="RGB") + } else if (pp->dirpyrDenoise.methodmed == "RGB") { methodmed->set_active (4); - methodmedChanged(); - + } + + methodmedChanged(); + medmethod->set_active (0); + // if (pp->dirpyrDenoise.medmethod=="none") // medmethod->set_active (0); - if (pp->dirpyrDenoise.medmethod=="soft") + if (pp->dirpyrDenoise.medmethod == "soft") { medmethod->set_active (0); - else if (pp->dirpyrDenoise.medmethod=="33") + } else if (pp->dirpyrDenoise.medmethod == "33") { medmethod->set_active (1); - else if (pp->dirpyrDenoise.medmethod=="55soft") + } else if (pp->dirpyrDenoise.medmethod == "55soft") { medmethod->set_active (2); - else if (pp->dirpyrDenoise.medmethod=="55") + } else if (pp->dirpyrDenoise.medmethod == "55") { medmethod->set_active (3); - else if (pp->dirpyrDenoise.medmethod=="77") + } else if (pp->dirpyrDenoise.medmethod == "77") { medmethod->set_active (4); - else if (pp->dirpyrDenoise.medmethod=="99") + } else if (pp->dirpyrDenoise.medmethod == "99") { medmethod->set_active (5); - medmethodChanged(); - + } + + medmethodChanged(); + rgbmethod->set_active (0); + // if (pp->dirpyrDenoise.medmethod=="none") // medmethod->set_active (0); - if (pp->dirpyrDenoise.rgbmethod=="soft") + if (pp->dirpyrDenoise.rgbmethod == "soft") { rgbmethod->set_active (0); - else if (pp->dirpyrDenoise.rgbmethod=="33") + } else if (pp->dirpyrDenoise.rgbmethod == "33") { rgbmethod->set_active (1); - else if (pp->dirpyrDenoise.rgbmethod=="55soft") + } else if (pp->dirpyrDenoise.rgbmethod == "55soft") { rgbmethod->set_active (2); - rgbmethodChanged(); - - + } + + rgbmethodChanged(); + + if (pedited) { - if (!pedited->dirpyrDenoise.dmethod) + if (!pedited->dirpyrDenoise.dmethod) { dmethod->set_active (2); - if (!pedited->dirpyrDenoise.smethod) + } + + if (!pedited->dirpyrDenoise.smethod) { smethod->set_active (2); - if (!pedited->dirpyrDenoise.rgbmethod) + } + + if (!pedited->dirpyrDenoise.rgbmethod) { rgbmethod->set_active (2); - if (!pedited->dirpyrDenoise.medmethod) + } + + if (!pedited->dirpyrDenoise.medmethod) { medmethod->set_active (6); - if (!pedited->dirpyrDenoise.methodmed) + } + + if (!pedited->dirpyrDenoise.methodmed) { methodmed->set_active (5); - if (!pedited->dirpyrDenoise.Cmethod) + } + + if (!pedited->dirpyrDenoise.Cmethod) { Cmethod->set_active (4); - if (!pedited->dirpyrDenoise.C2method) + } + + if (!pedited->dirpyrDenoise.C2method) { C2method->set_active (3); - if (!pedited->dirpyrDenoise.Lmethod) + } + + if (!pedited->dirpyrDenoise.Lmethod) { Lmethod->set_active (2); - + } + luma->setEditedState (pedited->dirpyrDenoise.luma ? Edited : UnEdited); Ldetail->setEditedState (pedited->dirpyrDenoise.Ldetail ? Edited : UnEdited); chroma->setEditedState (pedited->dirpyrDenoise.chroma ? Edited : UnEdited); @@ -606,20 +659,21 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { median->set_inconsistent (!pedited->dirpyrDenoise.median); ccshape->setUnChanged (!pedited->dirpyrDenoise.cccurve); - // perform->set_inconsistent (!pedited->dirpyrDenoise.perform); + // perform->set_inconsistent (!pedited->dirpyrDenoise.perform); } -// perfconn.block (true); + +// perfconn.block (true); setEnabled(pp->dirpyrDenoise.enabled); enhance->set_active (pp->dirpyrDenoise.enhance); - // perform->set_active (pp->dirpyrDenoise.perform); +// perform->set_active (pp->dirpyrDenoise.perform); median->set_active (pp->dirpyrDenoise.median); autochroma->set_active (pp->dirpyrDenoise.autochroma); - // perfconn.block (false); +// perfconn.block (false); lastmedian = pp->dirpyrDenoise.median; lastautochroma = pp->dirpyrDenoise.autochroma; lastenhance = pp->dirpyrDenoise.enhance; -// lastperform = pp->dirpyrDenoise.perform; +// lastperform = pp->dirpyrDenoise.perform; luma->setValue (pp->dirpyrDenoise.luma); Ldetail->setValue (pp->dirpyrDenoise.Ldetail); chroma->setValue (pp->dirpyrDenoise.chroma); @@ -631,7 +685,7 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { lshape->setCurve (pp->dirpyrDenoise.lcurve); ccshape->setCurve (pp->dirpyrDenoise.cccurve); - autochromaConn.block(false); + autochromaConn.block(false); dmethodconn.block(false); Lmethodconn.block(false); @@ -641,37 +695,40 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { medmethodconn.block(false); rgbmethodconn.block(false); methodmedconn.block(false); - updateNoiseLabel (); - + updateNoiseLabel (); + enableListener (); } -void DirPyrDenoise::setEditProvider (EditDataProvider *provider) { +void DirPyrDenoise::setEditProvider (EditDataProvider *provider) +{ lshape->setEditProvider(provider); ccshape->setEditProvider(provider); - + } -void DirPyrDenoise::autoOpenCurve () { +void DirPyrDenoise::autoOpenCurve () +{ lshape->openIfNonlinear(); - ccshape->openIfNonlinear(); + ccshape->openIfNonlinear(); } -void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) { - - pp->dirpyrDenoise.luma = luma->getValue (); - pp->dirpyrDenoise.Ldetail = Ldetail->getValue (); - pp->dirpyrDenoise.chroma = chroma->getValue (); - pp->dirpyrDenoise.redchro = redchro->getValue (); - pp->dirpyrDenoise.bluechro = bluechro->getValue (); - pp->dirpyrDenoise.gamma = gamma->getValue (); - pp->dirpyrDenoise.passes = passes->getValue (); - pp->dirpyrDenoise.enabled = getEnabled(); - pp->dirpyrDenoise.enhance = enhance->get_active(); -// pp->dirpyrDenoise.perform = perform->get_active(); - pp->dirpyrDenoise.median = median->get_active(); - pp->dirpyrDenoise.autochroma = autochroma->get_active(); +void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) +{ + + pp->dirpyrDenoise.luma = luma->getValue (); + pp->dirpyrDenoise.Ldetail = Ldetail->getValue (); + pp->dirpyrDenoise.chroma = chroma->getValue (); + pp->dirpyrDenoise.redchro = redchro->getValue (); + pp->dirpyrDenoise.bluechro = bluechro->getValue (); + pp->dirpyrDenoise.gamma = gamma->getValue (); + pp->dirpyrDenoise.passes = passes->getValue (); + pp->dirpyrDenoise.enabled = getEnabled(); + pp->dirpyrDenoise.enhance = enhance->get_active(); +// pp->dirpyrDenoise.perform = perform->get_active(); + pp->dirpyrDenoise.median = median->get_active(); + pp->dirpyrDenoise.autochroma = autochroma->get_active(); pp->dirpyrDenoise.lcurve = lshape->getCurve (); pp->dirpyrDenoise.cccurve = ccshape->getCurve (); - + if (pedited) { pedited->dirpyrDenoise.dmethod = dmethod->get_active_row_number() != 2; pedited->dirpyrDenoise.Lmethod = Lmethod->get_active_row_number() != 2; @@ -694,415 +751,448 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) { pedited->dirpyrDenoise.autochroma = !autochroma->get_inconsistent(); pedited->dirpyrDenoise.lcurve = !lshape->isUnChanged (); pedited->dirpyrDenoise.cccurve = !ccshape->isUnChanged (); - - // pedited->dirpyrDenoise.perform = !perform->get_inconsistent(); - } - if (dmethod->get_active_row_number()==0) - pp->dirpyrDenoise.dmethod = "Lab"; - else if (dmethod->get_active_row_number()==1) - pp->dirpyrDenoise.dmethod = "RGB"; - if (Lmethod->get_active_row_number()==0) + // pedited->dirpyrDenoise.perform = !perform->get_inconsistent(); + } + + if (dmethod->get_active_row_number() == 0) { + pp->dirpyrDenoise.dmethod = "Lab"; + } else if (dmethod->get_active_row_number() == 1) { + pp->dirpyrDenoise.dmethod = "RGB"; + } + + if (Lmethod->get_active_row_number() == 0) { pp->dirpyrDenoise.Lmethod = "CUR"; - else if (Lmethod->get_active_row_number()==1) + } else if (Lmethod->get_active_row_number() == 1) { pp->dirpyrDenoise.Lmethod = "SLI"; - if(options.rtSettings.leveldnautsimpl==1){ - if (Cmethod->get_active_row_number()==0) - pp->dirpyrDenoise.Cmethod = "MAN"; - else if (Cmethod->get_active_row_number()==1) - pp->dirpyrDenoise.Cmethod = "AUT"; - else if (Cmethod->get_active_row_number()==2) - pp->dirpyrDenoise.Cmethod = "PON"; - else if (Cmethod->get_active_row_number()==3) - pp->dirpyrDenoise.Cmethod = "PRE"; - } - else - { - if (C2method->get_active_row_number()==0) - pp->dirpyrDenoise.C2method = "MANU"; - else if (C2method->get_active_row_number()==1) - pp->dirpyrDenoise.C2method = "AUTO"; - else if (C2method->get_active_row_number()==2) - pp->dirpyrDenoise.C2method = "PREV"; - } - if (smethod->get_active_row_number()==0) + } + + if(options.rtSettings.leveldnautsimpl == 1) { + if (Cmethod->get_active_row_number() == 0) { + pp->dirpyrDenoise.Cmethod = "MAN"; + } else if (Cmethod->get_active_row_number() == 1) { + pp->dirpyrDenoise.Cmethod = "AUT"; + } else if (Cmethod->get_active_row_number() == 2) { + pp->dirpyrDenoise.Cmethod = "PON"; + } else if (Cmethod->get_active_row_number() == 3) { + pp->dirpyrDenoise.Cmethod = "PRE"; + } + } else { + if (C2method->get_active_row_number() == 0) { + pp->dirpyrDenoise.C2method = "MANU"; + } else if (C2method->get_active_row_number() == 1) { + pp->dirpyrDenoise.C2method = "AUTO"; + } else if (C2method->get_active_row_number() == 2) { + pp->dirpyrDenoise.C2method = "PREV"; + } + } + + if (smethod->get_active_row_number() == 0) { pp->dirpyrDenoise.smethod = "shal"; - // else if (smethod->get_active_row_number()==1) + } +// else if (smethod->get_active_row_number()==1) // pp->dirpyrDenoise.smethod = "shbi"; - else if (smethod->get_active_row_number()==1) + else if (smethod->get_active_row_number() == 1) { pp->dirpyrDenoise.smethod = "shalbi"; + } + // else if (smethod->get_active_row_number()==3) // pp->dirpyrDenoise.smethod = "shalal"; // else if (smethod->get_active_row_number()==4) // pp->dirpyrDenoise.smethod = "shbibi"; - - // if (methodmed->get_active_row_number()==0) - // pp->dirpyrDenoise.methodmed = "none"; - if (methodmed->get_active_row_number()==0) + + // if (methodmed->get_active_row_number()==0) + // pp->dirpyrDenoise.methodmed = "none"; + if (methodmed->get_active_row_number() == 0) { pp->dirpyrDenoise.methodmed = "Lonly"; - else if (methodmed->get_active_row_number()==1) - pp->dirpyrDenoise.methodmed = "ab"; - else if (methodmed->get_active_row_number()==2) - pp->dirpyrDenoise.methodmed = "Lpab"; - else if (methodmed->get_active_row_number()==3) + } else if (methodmed->get_active_row_number() == 1) { + pp->dirpyrDenoise.methodmed = "ab"; + } else if (methodmed->get_active_row_number() == 2) { + pp->dirpyrDenoise.methodmed = "Lpab"; + } else if (methodmed->get_active_row_number() == 3) { pp->dirpyrDenoise.methodmed = "Lab"; - else if (methodmed->get_active_row_number()==4) + } else if (methodmed->get_active_row_number() == 4) { pp->dirpyrDenoise.methodmed = "RGB"; + } - - // if (medmethod->get_active_row_number()==0) - // pp->dirpyrDenoise.medmethod = "none"; - if (medmethod->get_active_row_number()==0) + +// if (medmethod->get_active_row_number()==0) +// pp->dirpyrDenoise.medmethod = "none"; + if (medmethod->get_active_row_number() == 0) { pp->dirpyrDenoise.medmethod = "soft"; - else if (medmethod->get_active_row_number()==1) + } else if (medmethod->get_active_row_number() == 1) { pp->dirpyrDenoise.medmethod = "33"; - else if (medmethod->get_active_row_number()==2) + } else if (medmethod->get_active_row_number() == 2) { pp->dirpyrDenoise.medmethod = "55soft"; - else if (medmethod->get_active_row_number()==3) + } else if (medmethod->get_active_row_number() == 3) { pp->dirpyrDenoise.medmethod = "55"; - else if (medmethod->get_active_row_number()==4) + } else if (medmethod->get_active_row_number() == 4) { pp->dirpyrDenoise.medmethod = "77"; - else if (medmethod->get_active_row_number()==5) + } else if (medmethod->get_active_row_number() == 5) { pp->dirpyrDenoise.medmethod = "99"; + } - if (rgbmethod->get_active_row_number()==0) + if (rgbmethod->get_active_row_number() == 0) { pp->dirpyrDenoise.rgbmethod = "soft"; - else if (rgbmethod->get_active_row_number()==1) + } else if (rgbmethod->get_active_row_number() == 1) { pp->dirpyrDenoise.rgbmethod = "33"; - else if (rgbmethod->get_active_row_number()==2) + } else if (rgbmethod->get_active_row_number() == 2) { pp->dirpyrDenoise.rgbmethod = "55soft"; - + } + } -void DirPyrDenoise::curveChanged (CurveEditor* ce) { +void DirPyrDenoise::curveChanged (CurveEditor* ce) +{ if (listener && getEnabled()) { - if (ce == lshape) + if (ce == lshape) { listener->panelChanged (EvDPDNLCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == ccshape) - listener->panelChanged (EvDPDNCCCurve, M("HISTORY_CUSTOMCURVE")); - } + } + + if (ce == ccshape) { + listener->panelChanged (EvDPDNCCCurve, M("HISTORY_CUSTOMCURVE")); + } + } } -void DirPyrDenoise::dmethodChanged () { +void DirPyrDenoise::dmethodChanged () +{ - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvDPDNmet, dmethod->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvDPDNmet, dmethod->get_active_text ()); + } } -void DirPyrDenoise::LmethodChanged () { - if (!batchMode) { - if(Lmethod->get_active_row_number()==0) { // CUR - luma->hide(); - NoiscurveEditorG->show(); - } - else if(Lmethod->get_active_row_number()==1) { // SLI - luma->show(); - NoiscurveEditorG->hide(); - } - } - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvDPDNLmet, Lmethod->get_active_text ()); - } +void DirPyrDenoise::LmethodChanged () +{ + if (!batchMode) { + if(Lmethod->get_active_row_number() == 0) { // CUR + luma->hide(); + NoiscurveEditorG->show(); + } else if(Lmethod->get_active_row_number() == 1) { // SLI + luma->show(); + NoiscurveEditorG->hide(); + } + } + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvDPDNLmet, Lmethod->get_active_text ()); + } } -void DirPyrDenoise::CmethodChanged () { - if (!batchMode) { - if(Cmethod->get_active_row_number()==0 ) { //MAN - chroma->show(); - redchro->show(); - bluechro->show(); - chroma->set_sensitive(true); - redchro->set_sensitive(true); - bluechro->set_sensitive(true); - NoiseLabels->show(); - TileLabels->hide(); - PrevLabels->hide(); - - } - else if(Cmethod->get_active_row_number()==1) { // AUT - chroma->show(); - redchro->show(); - bluechro->show(); - NoiseLabels->show(); - TileLabels->hide(); - PrevLabels->hide(); - - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } - else if(Cmethod->get_active_row_number()==2) { // PON - chroma->hide(); - redchro->hide(); - bluechro->hide(); - NoiseLabels->hide(); - TileLabels->hide(); - PrevLabels->hide(); - - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } - else if(Cmethod->get_active_row_number()==3) { // PRE - chroma->show(); - redchro->show(); - bluechro->show(); - NoiseLabels->show(); - TileLabels->show(); - PrevLabels->show(); - - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } - - } - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvDPDNCmet, Cmethod->get_active_text ()); - } +void DirPyrDenoise::CmethodChanged () +{ + if (!batchMode) { + if(Cmethod->get_active_row_number() == 0 ) { //MAN + chroma->show(); + redchro->show(); + bluechro->show(); + chroma->set_sensitive(true); + redchro->set_sensitive(true); + bluechro->set_sensitive(true); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + } else if(Cmethod->get_active_row_number() == 1) { // AUT + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } else if(Cmethod->get_active_row_number() == 2) { // PON + chroma->hide(); + redchro->hide(); + bluechro->hide(); + NoiseLabels->hide(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } else if(Cmethod->get_active_row_number() == 3) { // PRE + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->show(); + PrevLabels->show(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + + } + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvDPDNCmet, Cmethod->get_active_text ()); + } } -void DirPyrDenoise::C2methodChanged () { - if (!batchMode) { - if(C2method->get_active_row_number()==0 ) { //MAN - chroma->show(); - redchro->show(); - bluechro->show(); - chroma->set_sensitive(true); - redchro->set_sensitive(true); - bluechro->set_sensitive(true); - NoiseLabels->show(); - TileLabels->hide(); - PrevLabels->hide(); - - } - else if(C2method->get_active_row_number()==1) { // AUTO - chroma->show(); - redchro->show(); - bluechro->show(); - NoiseLabels->show(); - TileLabels->hide(); - PrevLabels->hide(); - - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } - else if(C2method->get_active_row_number()==2) { // PREV - chroma->show(); - redchro->show(); - bluechro->show(); - NoiseLabels->show(); - TileLabels->hide(); - PrevLabels->hide(); - - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } - - - } - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvDPDNC2met, C2method->get_active_text ()); - } +void DirPyrDenoise::C2methodChanged () +{ + if (!batchMode) { + if(C2method->get_active_row_number() == 0 ) { //MAN + chroma->show(); + redchro->show(); + bluechro->show(); + chroma->set_sensitive(true); + redchro->set_sensitive(true); + bluechro->set_sensitive(true); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + } else if(C2method->get_active_row_number() == 1) { // AUTO + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } else if(C2method->get_active_row_number() == 2) { // PREV + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + + + } + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvDPDNC2met, C2method->get_active_text ()); + } } -void DirPyrDenoise::smethodChanged () { +void DirPyrDenoise::smethodChanged () +{ - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvDPDNsmet, smethod->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvDPDNsmet, smethod->get_active_text ()); + } } -void DirPyrDenoise::medmethodChanged () { - - - if (listener && (multiImage||getEnabled()) && median->get_active() ) { - listener->panelChanged (EvDPDNmedmet, medmethod->get_active_text ()); - } +void DirPyrDenoise::medmethodChanged () +{ + + + if (listener && (multiImage || getEnabled()) && median->get_active() ) { + listener->panelChanged (EvDPDNmedmet, medmethod->get_active_text ()); + } } -void DirPyrDenoise::rgbmethodChanged () { - ctboxrgb->hide(); - if(methodmed->get_active_row_number()==4) ctboxrgb->show(); - if (listener && (multiImage||getEnabled()) && median->get_active()) { - listener->panelChanged (EvDPDNrgbmet, rgbmethod->get_active_text ()); - } +void DirPyrDenoise::rgbmethodChanged () +{ + ctboxrgb->hide(); + + if(methodmed->get_active_row_number() == 4) { + ctboxrgb->show(); + } + + if (listener && (multiImage || getEnabled()) && median->get_active()) { + listener->panelChanged (EvDPDNrgbmet, rgbmethod->get_active_text ()); + } } -void DirPyrDenoise::methodmedChanged () { - if(methodmed->get_active_row_number()==4) {ctboxrgb->show();ctbox->hide();} - else {ctboxrgb->hide();ctbox->show();} +void DirPyrDenoise::methodmedChanged () +{ + if(methodmed->get_active_row_number() == 4) { + ctboxrgb->show(); + ctbox->hide(); + } else { + ctboxrgb->hide(); + ctbox->show(); + } - if (listener && (multiImage||getEnabled()) && median->get_active()) { - listener->panelChanged (EvDPDNmetmed, methodmed->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) && median->get_active()) { + listener->panelChanged (EvDPDNmetmed, methodmed->get_active_text ()); + } } -void DirPyrDenoise::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { - - luma->setDefault (defParams->dirpyrDenoise.luma); - Ldetail->setDefault (defParams->dirpyrDenoise.Ldetail); - chroma->setDefault (defParams->dirpyrDenoise.chroma); - redchro->setDefault (defParams->dirpyrDenoise.redchro); - bluechro->setDefault (defParams->dirpyrDenoise.bluechro); - gamma->setDefault (defParams->dirpyrDenoise.gamma); - passes->setDefault (defParams->dirpyrDenoise.passes); +void DirPyrDenoise::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ + + luma->setDefault (defParams->dirpyrDenoise.luma); + Ldetail->setDefault (defParams->dirpyrDenoise.Ldetail); + chroma->setDefault (defParams->dirpyrDenoise.chroma); + redchro->setDefault (defParams->dirpyrDenoise.redchro); + bluechro->setDefault (defParams->dirpyrDenoise.bluechro); + gamma->setDefault (defParams->dirpyrDenoise.gamma); + passes->setDefault (defParams->dirpyrDenoise.passes); if (pedited) { - luma->setDefaultEditedState (pedited->dirpyrDenoise.luma ? Edited : UnEdited); - Ldetail->setDefaultEditedState (pedited->dirpyrDenoise.Ldetail ? Edited : UnEdited); - chroma->setDefaultEditedState (pedited->dirpyrDenoise.chroma ? Edited : UnEdited); - redchro->setDefaultEditedState (pedited->dirpyrDenoise.redchro ? Edited : UnEdited); - bluechro->setDefaultEditedState (pedited->dirpyrDenoise.bluechro ? Edited : UnEdited); - gamma->setDefaultEditedState (pedited->dirpyrDenoise.gamma ? Edited : UnEdited); - passes->setDefaultEditedState (pedited->dirpyrDenoise.passes ? Edited : UnEdited); - } - else { - luma->setDefaultEditedState (Irrelevant); - Ldetail->setDefaultEditedState (Irrelevant); - chroma->setDefaultEditedState (Irrelevant); - redchro->setDefaultEditedState (Irrelevant); - bluechro->setDefaultEditedState (Irrelevant); + luma->setDefaultEditedState (pedited->dirpyrDenoise.luma ? Edited : UnEdited); + Ldetail->setDefaultEditedState (pedited->dirpyrDenoise.Ldetail ? Edited : UnEdited); + chroma->setDefaultEditedState (pedited->dirpyrDenoise.chroma ? Edited : UnEdited); + redchro->setDefaultEditedState (pedited->dirpyrDenoise.redchro ? Edited : UnEdited); + bluechro->setDefaultEditedState (pedited->dirpyrDenoise.bluechro ? Edited : UnEdited); + gamma->setDefaultEditedState (pedited->dirpyrDenoise.gamma ? Edited : UnEdited); + passes->setDefaultEditedState (pedited->dirpyrDenoise.passes ? Edited : UnEdited); + } else { + luma->setDefaultEditedState (Irrelevant); + Ldetail->setDefaultEditedState (Irrelevant); + chroma->setDefaultEditedState (Irrelevant); + redchro->setDefaultEditedState (Irrelevant); + bluechro->setDefaultEditedState (Irrelevant); gamma->setDefaultEditedState (Irrelevant); passes->setDefaultEditedState (Irrelevant); } } -void DirPyrDenoise::adjusterChanged (Adjuster* a, double newval) { - - Glib::ustring costr; +void DirPyrDenoise::adjusterChanged (Adjuster* a, double newval) +{ + + Glib::ustring costr; costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); - + if (listener && getEnabled()) { - if (a==Ldetail) + if (a == Ldetail) { listener->panelChanged (EvDPDNLdetail, costr); - else if (a==luma) + } else if (a == luma) { listener->panelChanged (EvDPDNLuma, costr); - else if (a==chroma) + } else if (a == chroma) { listener->panelChanged (EvDPDNChroma, costr); - else if (a==redchro) + } else if (a == redchro) { listener->panelChanged (EvDPDNredchro, costr); - else if (a==bluechro) - listener->panelChanged (EvDPDNbluechro, costr); - else if (a==gamma) - listener->panelChanged (EvDPDNGamma, costr); - else if (a==passes && median->get_active()) - listener->panelChanged (EvDPDNpasses, costr); - } -} - -void DirPyrDenoise::enabledChanged () { - - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvDPDNEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvDPDNEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvDPDNEnabled, M("GENERAL_DISABLED")); + } else if (a == bluechro) { + listener->panelChanged (EvDPDNbluechro, costr); + } else if (a == gamma) { + listener->panelChanged (EvDPDNGamma, costr); + } else if (a == passes && median->get_active()) { + listener->panelChanged (EvDPDNpasses, costr); + } } } -void DirPyrDenoise::enhanceChanged () { - +void DirPyrDenoise::enabledChanged () +{ + + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvDPDNEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvDPDNEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvDPDNEnabled, M("GENERAL_DISABLED")); + } + } +} + +void DirPyrDenoise::enhanceChanged () +{ + if (batchMode) { if (enhance->get_inconsistent()) { enhance->set_inconsistent (false); enhanConn.block (true); enhance->set_active (false); enhanConn.block (false); - } - else if (lastenhance) + } else if (lastenhance) { enhance->set_inconsistent (true); - + } + lastenhance = enhance->get_active (); } - + if (listener) { - if (enhance->get_active ()) + if (enhance->get_active ()) { listener->panelChanged (EvDPDNenhance, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvDPDNenhance, M("GENERAL_DISABLED")); - } + } + } } -void DirPyrDenoise::medianChanged () { - +void DirPyrDenoise::medianChanged () +{ + if (batchMode) { if (median->get_inconsistent()) { median->set_inconsistent (false); medianConn.block (true); median->set_active (false); medianConn.block (false); - } - else if (lastmedian) + } else if (lastmedian) { median->set_inconsistent (true); - + } + lastmedian = median->get_active (); } - + if (listener) { - if (median->get_active ()) - { listener->panelChanged (EvDPDNmedian, M("GENERAL_ENABLED")); - } - else - { listener->panelChanged (EvDPDNmedian, M("GENERAL_DISABLED")); - } - - - } + if (median->get_active ()) { + listener->panelChanged (EvDPDNmedian, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvDPDNmedian, M("GENERAL_DISABLED")); + } + + + } } -void DirPyrDenoise::autochromaChanged () { -// printf("Autochroma\n"); +void DirPyrDenoise::autochromaChanged () +{ +// printf("Autochroma\n"); if (batchMode) { if (autochroma->get_inconsistent()) { autochroma->set_inconsistent (false); autochromaConn.block (true); autochroma->set_active (false); autochromaConn.block (false); - } - else if (lastautochroma) + } else if (lastautochroma) { autochroma->set_inconsistent (true); - + } + lastautochroma = autochroma->get_active (); } - if (autochroma->get_active ()) - { - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } - else - { - chroma->set_sensitive(true); - redchro->set_sensitive(true); - bluechro->set_sensitive(true); - } - + + if (autochroma->get_active ()) { + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } else { + chroma->set_sensitive(true); + redchro->set_sensitive(true); + bluechro->set_sensitive(true); + } + if (listener) { - if (autochroma->get_active ()) - { listener->panelChanged (EvDPDNautochroma, M("GENERAL_ENABLED")); - // chroma->set_sensitive(false); - // redchro->set_sensitive(false); - // bluechro->set_sensitive(false); - } - else - {listener->panelChanged (EvDPDNautochroma, M("GENERAL_DISABLED")); - //chroma->set_sensitive(true); - //redchro->set_sensitive(true); - //bluechro->set_sensitive(true); - } - - - } + if (autochroma->get_active ()) { + listener->panelChanged (EvDPDNautochroma, M("GENERAL_ENABLED")); + // chroma->set_sensitive(false); + // redchro->set_sensitive(false); + // bluechro->set_sensitive(false); + } else { + listener->panelChanged (EvDPDNautochroma, M("GENERAL_DISABLED")); + //chroma->set_sensitive(true); + //redchro->set_sensitive(true); + //bluechro->set_sensitive(true); + } + + + } } @@ -1125,14 +1215,15 @@ void DirPyrDenoise::perform_toggled () { if (listener) { if (perform->get_active ()) listener->panelChanged (EvDPDNperform, M("GENERAL_ENABLED")); - else + else listener->panelChanged (EvDPDNperform, M("GENERAL_DISABLED")); } } */ -void DirPyrDenoise::setBatchMode (bool batchMode) { - +void DirPyrDenoise::setBatchMode (bool batchMode) +{ + ToolPanel::setBatchMode (batchMode); luma->showEditedCB (); Ldetail->showEditedCB (); @@ -1141,9 +1232,9 @@ void DirPyrDenoise::setBatchMode (bool batchMode) { bluechro->showEditedCB (); gamma->showEditedCB (); passes->showEditedCB (); - NoiscurveEditorG->setBatchMode (batchMode); - CCcurveEditorG->setBatchMode (batchMode); - + NoiscurveEditorG->setBatchMode (batchMode); + CCcurveEditorG->setBatchMode (batchMode); + dmethod->append_text (M("GENERAL_UNCHANGED")); Lmethod->append_text (M("GENERAL_UNCHANGED")); Cmethod->append_text (M("GENERAL_UNCHANGED")); @@ -1152,69 +1243,74 @@ void DirPyrDenoise::setBatchMode (bool batchMode) { medmethod->append_text (M("GENERAL_UNCHANGED")); methodmed->append_text (M("GENERAL_UNCHANGED")); rgbmethod->append_text (M("GENERAL_UNCHANGED")); - + } -void DirPyrDenoise::setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd) { +void DirPyrDenoise::setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd) +{ + + luma->setAddMode(lumaadd); + Ldetail->setAddMode(lumdetadd); + chroma->setAddMode(chromaadd); + redchro->setAddMode(chromaredadd); + bluechro->setAddMode(chromablueadd); + gamma->setAddMode(gammaadd); + passes->setAddMode(passesadd); - luma->setAddMode(lumaadd); - Ldetail->setAddMode(lumdetadd); - chroma->setAddMode(chromaadd); - redchro->setAddMode(chromaredadd); - bluechro->setAddMode(chromablueadd); - gamma->setAddMode(gammaadd); - passes->setAddMode(passesadd); - } -void DirPyrDenoise::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { +void DirPyrDenoise::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) +{ - float R, G, B; + float R, G, B; - if (elemType==ColorCaller::CCET_VERTICAL_BAR) - valY = 0.5; + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } - if (callerId == 1) { // ch - main curve + if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); - } - else if (callerId == 2) { // cc - bottom bar + Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); + } else if (callerId == 2) { // cc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - // whole hue range - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); - } - else if (callerId == 3) { // lc - bottom bar + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } else if (callerId == 3) { // lc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - // whole hue range - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); - } + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } - else if (callerId == 4) { // LH - bottom bar - Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); - } - else if (callerId == 5) { // HH - bottom bar - float h = float((valY - 0.5) * 0.3 + valX); - if (h > 1.0f) - h -= 1.0f; - else if (h < 0.0f) - h += 1.0f; - Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); - } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + else if (callerId == 4) { // LH - bottom bar + Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); + } else if (callerId == 5) { // HH - bottom bar + float h = float((valY - 0.5) * 0.3 + valX); + + if (h > 1.0f) { + h -= 1.0f; + } else if (h < 0.0f) { + h += 1.0f; + } + + Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); + } + + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); } -void DirPyrDenoise::trimValues (rtengine::procparams::ProcParams* pp) { +void DirPyrDenoise::trimValues (rtengine::procparams::ProcParams* pp) +{ - luma->trimValue(pp->dirpyrDenoise.luma); - Ldetail->trimValue(pp->dirpyrDenoise.Ldetail); - chroma->trimValue(pp->dirpyrDenoise.chroma); - redchro->trimValue(pp->dirpyrDenoise.redchro); - bluechro->trimValue(pp->dirpyrDenoise.bluechro); - gamma->trimValue(pp->dirpyrDenoise.gamma); - passes->trimValue(pp->dirpyrDenoise.passes); + luma->trimValue(pp->dirpyrDenoise.luma); + Ldetail->trimValue(pp->dirpyrDenoise.Ldetail); + chroma->trimValue(pp->dirpyrDenoise.chroma); + redchro->trimValue(pp->dirpyrDenoise.redchro); + bluechro->trimValue(pp->dirpyrDenoise.bluechro); + gamma->trimValue(pp->dirpyrDenoise.gamma); + passes->trimValue(pp->dirpyrDenoise.passes); } diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index ecfb91f37..0a5a00e3f 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -7,7 +7,7 @@ * 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 @@ -28,18 +28,19 @@ #include "guiutils.h" #include "options.h" -class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoChromaListener, public CurveListener, public ColorProvider { +class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoChromaListener, public CurveListener, public ColorProvider +{ - protected: +protected: CurveEditorGroup* NoiscurveEditorG; CurveEditorGroup* CCcurveEditorG; - Adjuster* luma; - Adjuster* Ldetail; - Adjuster* chroma; - Adjuster* redchro; - Adjuster* bluechro; - Adjuster* gamma; - Adjuster* passes; + Adjuster* luma; + Adjuster* Ldetail; + Adjuster* chroma; + Adjuster* redchro; + Adjuster* bluechro; + Adjuster* gamma; + Adjuster* passes; FlatCurveEditor* lshape; FlatCurveEditor* ccshape; @@ -50,10 +51,10 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol bool lastmedian; Gtk::CheckButton* autochroma; bool lastautochroma; - Gtk::Label* NoiseLabels; - Gtk::Label* TileLabels; - Gtk::Label* PrevLabels; - + Gtk::Label* NoiseLabels; + Gtk::Label* TileLabels; + Gtk::Label* PrevLabels; + // Gtk::CheckButton* perform; // bool lastperform; // sigc::connection perfconn; @@ -76,31 +77,31 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol MyComboBoxText* rgbmethod; sigc::connection rgbmethodconn; Gtk::HBox* ctboxrgb; - double nextchroma; - double nextred; - double nextblue; - double nextnresid; - double nexthighresid; + double nextchroma; + double nextred; + double nextblue; + double nextnresid; + double nexthighresid; Gtk::HBox* ctboxL; Gtk::HBox* ctboxC; Gtk::HBox* ctboxC2; - int nexttileX; - int nexttileY; - int nextprevX; - int nextprevY; - int nextsizeT; - int nextsizeP; - - public: + int nexttileX; + int nexttileY; + int nextprevX; + int nextprevY; + int nextsizeT; + int nextsizeP; + +public: DirPyrDenoise (); ~DirPyrDenoise (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void curveChanged (CurveEditor* ce); + void curveChanged (CurveEditor* ce); void setEditProvider (EditDataProvider *provider); void autoOpenCurve (); @@ -115,14 +116,14 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol bool noiseComputed_ (); void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP); bool TilePrevComputed_ (); - + // void perform_toggled (); - void updateNoiseLabel (); + void updateNoiseLabel (); void LmethodChanged (); void CmethodChanged (); void C2methodChanged (); - void updateTileLabel (); - void updatePrevLabel (); + void updateTileLabel (); + void updatePrevLabel (); void dmethodChanged (); void medmethodChanged (); @@ -133,8 +134,8 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd); void trimValues (rtengine::procparams::ProcParams* pp); - Glib::ustring getSettingString (); - + Glib::ustring getSettingString (); + }; #endif diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index d6f888788..5d8a7011e 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -5,7 +5,7 @@ * 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 @@ -22,51 +22,67 @@ using namespace rtengine; using namespace rtengine::procparams; -DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", M("TP_DIRPYREQUALIZER_LABEL"), true, true) { +DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", M("TP_DIRPYREQUALIZER_LABEL"), true, true) +{ - std::vector milestones; + std::vector milestones; - float r, g, b; - Color::hsv2rgb01(0.7500, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0. , r, g, b) ); // hsv: 0.75 rad: -0.9 - Color::hsv2rgb01(0.8560, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.1470, r, g, b) ); // hsv: 0.856 rad: -0.4 - Color::hsv2rgb01(0.9200, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.2353, r, g, b) ); // hsv: 0.92 rad: -0.1 - Color::hsv2rgb01(0.9300, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.2647, r, g, b) ); // hsv: 0.93 rad: 0 - Color::hsv2rgb01(0.9600, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.3380, r, g, b) ); // hsv: 0.96 rad: 0.25 - Color::hsv2rgb01(1.0000, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.4412, r, g, b) ); // hsv: 1. rad: 0.6 - Color::hsv2rgb01(0.0675, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.6176, r, g, b) ); // hsv: 0.0675 rad: 1.2 - Color::hsv2rgb01(0.0900, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.6764, r, g, b) ); // hsv: 0.09 rad: 1.4 - Color::hsv2rgb01(0.1700, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.7647, r, g, b) ); // hsv: 0.17 rad: 1.7 - Color::hsv2rgb01(0.2650, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.8824, r, g, b) ); // hsv: 0.265 rad: 2.1 - 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 + float r, g, b; + Color::hsv2rgb01(0.7500, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0. , r, g, b) ); // hsv: 0.75 rad: -0.9 + Color::hsv2rgb01(0.8560, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.1470, r, g, b) ); // hsv: 0.856 rad: -0.4 + Color::hsv2rgb01(0.9200, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.2353, r, g, b) ); // hsv: 0.92 rad: -0.1 + Color::hsv2rgb01(0.9300, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.2647, r, g, b) ); // hsv: 0.93 rad: 0 + Color::hsv2rgb01(0.9600, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.3380, r, g, b) ); // hsv: 0.96 rad: 0.25 + Color::hsv2rgb01(1.0000, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.4412, r, g, b) ); // hsv: 1. rad: 0.6 + Color::hsv2rgb01(0.0675, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.6176, r, g, b) ); // hsv: 0.0675 rad: 1.2 + Color::hsv2rgb01(0.0900, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.6764, r, g, b) ); // hsv: 0.09 rad: 1.4 + Color::hsv2rgb01(0.1700, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.7647, r, g, b) ); // hsv: 0.17 rad: 1.7 + Color::hsv2rgb01(0.2650, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.8824, r, g, b) ); // hsv: 0.265 rad: 2.1 + 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 - setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); Gtk::HBox * buttonBox1 = Gtk::manage (new Gtk::HBox(true, 10)); pack_start(*buttonBox1); - Gtk::Button * lumacontrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS"))); - buttonBox1->pack_start(*lumacontrastMinusButton); - lumacontrastMinusPressedConn = lumacontrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumacontrastMinusPressed)); + Gtk::Button * lumacontrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS"))); + buttonBox1->pack_start(*lumacontrastMinusButton); + lumacontrastMinusPressedConn = lumacontrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumacontrastMinusPressed)); - Gtk::Button * lumaneutralButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMANEUTRAL"))); - buttonBox1->pack_start(*lumaneutralButton); - lumaneutralPressedConn = lumaneutralButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumaneutralPressed)); + Gtk::Button * lumaneutralButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMANEUTRAL"))); + buttonBox1->pack_start(*lumaneutralButton); + lumaneutralPressedConn = lumaneutralButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumaneutralPressed)); - Gtk::Button * lumacontrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS"))); - buttonBox1->pack_start(*lumacontrastPlusButton); - lumacontrastPlusPressedConn = lumacontrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumacontrastPlusPressed)); + Gtk::Button * lumacontrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS"))); + buttonBox1->pack_start(*lumacontrastPlusButton); + lumacontrastPlusPressedConn = lumacontrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::lumacontrastPlusPressed)); buttonBox1->show_all_children(); Gtk::HSeparator *separator2 = Gtk::manage (new Gtk::HSeparator()); pack_start(*separator2, Gtk::PACK_SHRINK, 2); - for(int i = 0; i < 6; i++) - { + for(int i = 0; i < 6; i++) { Glib::ustring ss; ss = Glib::ustring::format(i); - if (i == 0) ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMAFINEST")); - else if(i == 5) ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMACOARSEST")); + + if (i == 0) { + ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMAFINEST")); + } else if(i == 5) { + ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMACOARSEST")); + } + multiplier[i] = Gtk::manage ( new Adjuster (ss, 0, 4, 0.01, 1.0) ); multiplier[i]->setAdjusterListener(this); pack_start(*multiplier[i]); @@ -81,30 +97,30 @@ DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", Gtk::HSeparator *separator4 = Gtk::manage (new Gtk::HSeparator()); pack_start(*separator4, Gtk::PACK_SHRINK, 2); -/* - algoHBox = Gtk::manage (new Gtk::HBox ()); - algoHBox->set_border_width (0); - algoHBox->set_spacing (2); - algoHBox->set_tooltip_markup (M("TP_DIRPYREQUALIZER_ALGO_TOOLTIP")); -*/ + /* + algoHBox = Gtk::manage (new Gtk::HBox ()); + algoHBox->set_border_width (0); + algoHBox->set_spacing (2); + algoHBox->set_tooltip_markup (M("TP_DIRPYREQUALIZER_ALGO_TOOLTIP")); + */ // alLabel = Gtk::manage (new Gtk::Label (M("TP_DIRPYREQUALIZER_ALGO")+":")); -// algoHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); -/* - algo = Gtk::manage (new MyComboBoxText ()); - algo->append_text (M("TP_DIRPYREQUALIZER_ALGO_FI")); - algo->append_text (M("TP_DIRPYREQUALIZER_ALGO_LA")); - algo->set_active (1); -// algoHBox->pack_start (*algo); -// pack_start(*algoHBox); - algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrEqualizer::algoChanged) ); -*/ +// algoHBox->pack_start (*alLabel, Gtk::PACK_SHRINK); + /* + algo = Gtk::manage (new MyComboBoxText ()); + algo->append_text (M("TP_DIRPYREQUALIZER_ALGO_FI")); + algo->append_text (M("TP_DIRPYREQUALIZER_ALGO_LA")); + algo->set_active (1); + // algoHBox->pack_start (*algo); + // pack_start(*algoHBox); + algoconn = algo->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrEqualizer::algoChanged) ); + */ hueskin = Gtk::manage (new ThresholdAdjuster (M("TP_DIRPYREQUALIZER_HUESKIN"), -40., 210., -5., 25., 170., 120., 0, false)); //default (b_l 0, t_l 30, b_r 170, t_r 120); hueskin->set_tooltip_markup (M("TP_DIRPYREQUALIZER_HUESKIN_TOOLTIP")); hueskin->setBgGradient(milestones); pack_start(*hueskin); - skinprotect = Gtk::manage ( new Adjuster (M("TP_DIRPYREQUALIZER_SKIN"), -100, 100, 1, 0.) ); + skinprotect = Gtk::manage ( new Adjuster (M("TP_DIRPYREQUALIZER_SKIN"), -100, 100, 1, 0.) ); skinprotect->setAdjusterListener(this); pack_start(*skinprotect); skinprotect->set_tooltip_markup (M("TP_DIRPYREQUALIZER_SKIN_TOOLTIP")); @@ -115,17 +131,19 @@ DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", gamutlabConn = gamutlab->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrEqualizer::gamutlabToggled) ); gamutlab->set_tooltip_markup (M("TP_DIRPYREQUALIZER_TOOLTIP")); - hueskin->setAdjusterListener (this); + hueskin->setAdjusterListener (this); show_all_children (); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } -DirPyrEqualizer::~DirPyrEqualizer () { +DirPyrEqualizer::~DirPyrEqualizer () +{ } -void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { +void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -137,32 +155,34 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { for(int i = 0; i < 6; i++) { multiplier[i]->setEditedState (pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited); } + threshold->setEditedState (pedited->dirpyrequalizer.threshold ? Edited : UnEdited); skinprotect->setEditedState (pedited->dirpyrequalizer.skinprotect ? Edited : UnEdited); - hueskin->setEditedState (pedited->dirpyrequalizer.hueskin ? Edited : UnEdited); + hueskin->setEditedState (pedited->dirpyrequalizer.hueskin ? Edited : UnEdited); } setEnabled(pp->dirpyrequalizer.enabled); -/* - algoconn.block(true); - if (pedited && !pedited->dirpyrequalizer.algo) - algo->set_active (2); - else if (pp->dirpyrequalizer.algo=="FI") - algo->set_active (0); - else if (pp->dirpyrequalizer.algo=="LA") - algo->set_active (1); - algoconn.block(false); - algoChanged(); -*/ + /* + algoconn.block(true); + if (pedited && !pedited->dirpyrequalizer.algo) + algo->set_active (2); + else if (pp->dirpyrequalizer.algo=="FI") + algo->set_active (0); + else if (pp->dirpyrequalizer.algo=="LA") + algo->set_active (1); + algoconn.block(false); + algoChanged(); + */ gamutlabConn.block (true); gamutlab->set_active (pp->dirpyrequalizer.gamutlab); gamutlabConn.block (false); lastgamutlab = pp->dirpyrequalizer.gamutlab; - + for (int i = 0; i < 6; i++) { multiplier[i]->setValue(pp->dirpyrequalizer.mult[i]); } + threshold->setValue(pp->dirpyrequalizer.threshold); skinprotect->setValue(pp->dirpyrequalizer.skinprotect); hueskin->setValue(pp->dirpyrequalizer.hueskin); @@ -170,7 +190,8 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) { +void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->dirpyrequalizer.enabled = getEnabled(); pp->dirpyrequalizer.gamutlab = gamutlab->get_active (); @@ -179,26 +200,29 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) { for (int i = 0; i < 6; i++) { pp->dirpyrequalizer.mult[i] = multiplier[i]->getValue(); } + pp->dirpyrequalizer.threshold = threshold->getValue(); pp->dirpyrequalizer.skinprotect = skinprotect->getValue(); if (pedited) { pedited->dirpyrequalizer.enabled = !get_inconsistent(); - pedited->dirpyrequalizer.hueskin = hueskin->getEditedState (); + pedited->dirpyrequalizer.hueskin = hueskin->getEditedState (); for(int i = 0; i < 6; i++) { pedited->dirpyrequalizer.mult[i] = multiplier[i]->getEditedState(); } + pedited->dirpyrequalizer.threshold = threshold->getEditedState(); pedited->dirpyrequalizer.skinprotect = skinprotect->getEditedState(); - // pedited->dirpyrequalizer.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); +// pedited->dirpyrequalizer.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); } -/* if (algo->get_active_row_number()==0) - pp->dirpyrequalizer.algo = "FI"; - else if (algo->get_active_row_number()==1) - pp->dirpyrequalizer.algo = "LA"; - */ + + /* if (algo->get_active_row_number()==0) + pp->dirpyrequalizer.algo = "FI"; + else if (algo->get_active_row_number()==1) + pp->dirpyrequalizer.algo = "LA"; + */ } /* void DirPyrEqualizer::algoChanged () { @@ -206,11 +230,13 @@ void DirPyrEqualizer::algoChanged () { listener->panelChanged (EvDirPyrEqualizeralg, algo->get_active_text ());} } */ -void DirPyrEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void DirPyrEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ for (int i = 0; i < 6; i++) { multiplier[i]->setDefault(defParams->dirpyrequalizer.mult[i]); } + threshold->setDefault(defParams->dirpyrequalizer.threshold); hueskin->setDefault (defParams->dirpyrequalizer.hueskin); @@ -218,82 +244,88 @@ void DirPyrEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdit for (int i = 0; i < 6; i++) { multiplier[i]->setDefaultEditedState(pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited); } + threshold->setDefaultEditedState(pedited->dirpyrequalizer.threshold ? Edited : UnEdited); skinprotect->setDefaultEditedState(pedited->dirpyrequalizer.skinprotect ? Edited : UnEdited); - hueskin->setDefaultEditedState (pedited->dirpyrequalizer.hueskin ? Edited : UnEdited); - } - else { + hueskin->setDefaultEditedState (pedited->dirpyrequalizer.hueskin ? Edited : UnEdited); + } else { for (int i = 0; i < 6; i++) { multiplier[i]->setDefaultEditedState(Irrelevant); } + threshold->setDefaultEditedState(Irrelevant); skinprotect->setDefaultEditedState(Irrelevant); hueskin->setDefaultEditedState (Irrelevant); } } -void DirPyrEqualizer::adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) { - if (listener && (multiImage||getEnabled()) ) { +void DirPyrEqualizer::adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) +{ + if (listener && (multiImage || getEnabled()) ) { listener->panelChanged (EvDirPyrEqualizerHueskin, hueskin->getHistoryString()); } } -void DirPyrEqualizer::setBatchMode (bool batchMode) { +void DirPyrEqualizer::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); for (int i = 0; i < 6; i++) { multiplier[i]->showEditedCB(); } + threshold->showEditedCB(); skinprotect->showEditedCB(); hueskin->showEditedCB (); - // algo->append_text (M("GENERAL_UNCHANGED")); +// algo->append_text (M("GENERAL_UNCHANGED")); } -void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) { +void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) +{ if (listener && getEnabled()) { if (a == threshold) { listener->panelChanged (EvDirPyrEqualizerThreshold, - Glib::ustring::compose("%1", - Glib::ustring::format(std::fixed, std::setprecision(2), threshold->getValue())) - ); - } - else if (a == skinprotect) { + Glib::ustring::compose("%1", + Glib::ustring::format(std::fixed, std::setprecision(2), threshold->getValue())) + ); + } else if (a == skinprotect) { listener->panelChanged (EvDirPyrEqualizerSkin, - Glib::ustring::compose("%1", - Glib::ustring::format(std::fixed, std::setprecision(2), skinprotect->getValue())) - ); - } - else { + Glib::ustring::compose("%1", + Glib::ustring::format(std::fixed, std::setprecision(2), skinprotect->getValue())) + ); + } else { listener->panelChanged (EvDirPyrEqualizer, - Glib::ustring::compose("%1, %2, %3, %4, %5, %6", - Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[0]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[1]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[2]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[3]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[4]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[5]->getValue())) - ); + Glib::ustring::compose("%1, %2, %3, %4, %5, %6", + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[0]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[1]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[2]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[3]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[4]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[5]->getValue())) + ); } } } -void DirPyrEqualizer::enabledChanged () { +void DirPyrEqualizer::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvDirPyrEqlEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvDirPyrEqlEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvDirPyrEqlEnabled, M("GENERAL_DISABLED")); + } } } -void DirPyrEqualizer::gamutlabToggled () { +void DirPyrEqualizer::gamutlabToggled () +{ if (batchMode) { if (gamutlab->get_inconsistent()) { @@ -301,22 +333,24 @@ void DirPyrEqualizer::gamutlabToggled () { gamutlabConn.block (true); gamutlab->set_active (false); gamutlabConn.block (false); - } - else if (lastgamutlab) + } else if (lastgamutlab) { gamutlab->set_inconsistent (true); + } lastgamutlab = gamutlab->get_active (); } if (listener) { - if (gamutlab->get_active ()) + if (gamutlab->get_active ()) { listener->panelChanged (EvDirPyrEqlgamutlab, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvDirPyrEqlgamutlab, M("GENERAL_DISABLED")); + } } } -void DirPyrEqualizer::lumaneutralPressed () { +void DirPyrEqualizer::lumaneutralPressed () +{ for (int i = 0; i < 6; i++) { multiplier[i]->setValue(1.0); @@ -325,7 +359,8 @@ void DirPyrEqualizer::lumaneutralPressed () { } -void DirPyrEqualizer::lumacontrastPlusPressed () { +void DirPyrEqualizer::lumacontrastPlusPressed () +{ for (int i = 0; i < 6; i++) { float inc = 0.05 * (6 - i); @@ -335,7 +370,8 @@ void DirPyrEqualizer::lumacontrastPlusPressed () { } -void DirPyrEqualizer::lumacontrastMinusPressed () { +void DirPyrEqualizer::lumacontrastMinusPressed () +{ for (int i = 0; i < 6; i++) { float inc = -0.05 * (6 - i); @@ -344,18 +380,24 @@ void DirPyrEqualizer::lumacontrastMinusPressed () { } } -void DirPyrEqualizer::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool skinadd) { +void DirPyrEqualizer::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool skinadd) +{ - for (int i=0; i<6; i++) - multiplier[i]->setAddMode(multiplieradd); - threshold->setAddMode(thresholdadd); - skinprotect->setAddMode(skinadd); + for (int i = 0; i < 6; i++) { + multiplier[i]->setAddMode(multiplieradd); + } + + threshold->setAddMode(thresholdadd); + skinprotect->setAddMode(skinadd); } -void DirPyrEqualizer::trimValues (rtengine::procparams::ProcParams* pp) { +void DirPyrEqualizer::trimValues (rtengine::procparams::ProcParams* pp) +{ - for (int i=0; i<6; i++) - multiplier[i]->trimValue(pp->dirpyrequalizer.mult[i]); - threshold->trimValue(pp->dirpyrequalizer.threshold); - skinprotect->trimValue(pp->dirpyrequalizer.skinprotect); + for (int i = 0; i < 6; i++) { + multiplier[i]->trimValue(pp->dirpyrequalizer.mult[i]); + } + + threshold->trimValue(pp->dirpyrequalizer.threshold); + skinprotect->trimValue(pp->dirpyrequalizer.skinprotect); } diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index 3b5227331..6c0a4613d 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -5,7 +5,7 @@ * 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 @@ -16,7 +16,7 @@ * * © 2010 Emil Martinec */ - + #ifndef DIRPYREQUALIZER_H_INCLUDED #define DIRPYREQUALIZER_H_INCLUDED @@ -32,14 +32,14 @@ class DirPyrEqualizer : public ToolParamBlock, public ThresholdAdjusterListener, protected: Gtk::CheckButton * gamutlab; - Adjuster* multiplier[6]; + Adjuster* multiplier[6]; Adjuster* threshold; Adjuster* skinprotect; ThresholdAdjuster* hueskin; - // MyComboBoxText* algo; - // sigc::connection algoconn; - // Gtk::Label* alLabel; - // Gtk::HBox* algoHBox; + // MyComboBoxText* algo; + // sigc::connection algoconn; + // Gtk::Label* alLabel; + // Gtk::HBox* algoHBox; sigc::connection gamutlabConn; sigc::connection lumaneutralPressedConn; @@ -53,9 +53,9 @@ public: DirPyrEqualizer (); virtual ~DirPyrEqualizer (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool skinadd); void trimValues (rtengine::procparams::ProcParams* pp); diff --git a/rtgui/dirselectionlistener.h b/rtgui/dirselectionlistener.h index 2c1eaa0ed..3225487cb 100644 --- a/rtgui/dirselectionlistener.h +++ b/rtgui/dirselectionlistener.h @@ -7,7 +7,7 @@ * 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 @@ -21,11 +21,12 @@ #include -class DirSelectionListener { +class DirSelectionListener +{ - public: +public: virtual ~DirSelectionListener () {} - virtual void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="") {} + virtual void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile = "") {} }; #endif diff --git a/rtgui/distortion.cc b/rtgui/distortion.cc index 50795bbab..d63868e85 100644 --- a/rtgui/distortion.cc +++ b/rtgui/distortion.cc @@ -7,7 +7,7 @@ * 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 @@ -23,7 +23,8 @@ using namespace rtengine; using namespace rtengine::procparams; -Distortion::Distortion (): FoldableToolPanel(this, "distortion", M("TP_DISTORTION_LABEL")) { +Distortion::Distortion (): FoldableToolPanel(this, "distortion", M("TP_DISTORTION_LABEL")) +{ rlistener = NULL; autoDistor = Gtk::manage (new Gtk::Button (M("TP_DISTORTION_AUTO"))); @@ -37,12 +38,13 @@ Distortion::Distortion (): FoldableToolPanel(this, "distortion", M("TP_DISTORTIO Gtk::Image* idistR = Gtk::manage (new RTImage ("distortion-barrel.png")); distor = Gtk::manage (new Adjuster (M("TP_DISTORTION_AMOUNT"), -0.5, 0.5, 0.001, 0, idistL, idistR)); - distor->setAdjusterListener (this); + distor->setAdjusterListener (this); distor->show(); pack_start (*distor); } -void Distortion::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Distortion::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -51,11 +53,12 @@ void Distortion::read (const ProcParams* pp, const ParamsEdited* pedited) { } distor->setValue (pp->distortion.amount); - + enableListener (); } -void Distortion::write (ProcParams* pp, ParamsEdited* pedited) { +void Distortion::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->distortion.amount = distor->getValue (); @@ -64,34 +67,40 @@ void Distortion::write (ProcParams* pp, ParamsEdited* pedited) { } } -void Distortion::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void Distortion::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ distor->setDefault (defParams->distortion.amount); if (pedited) { distor->setDefaultEditedState (pedited->distortion.amount ? Edited : UnEdited); - } - else { + } else { distor->setDefaultEditedState (Irrelevant); } } -void Distortion::adjusterChanged (Adjuster* a, double newval) { +void Distortion::adjusterChanged (Adjuster* a, double newval) +{ - if (listener) + if (listener) { listener->panelChanged (EvDISTAmount, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), a->getValue())); + } } -void Distortion::setBatchMode (bool batchMode) { +void Distortion::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); + if (batchMode) { autoDistor->set_sensitive(false); } + distor->showEditedCB (); } -void Distortion::idPressed () { +void Distortion::idPressed () +{ if (!batchMode) { if (rlistener) { double new_amount = rlistener->autoDistorRequested(); @@ -101,12 +110,14 @@ void Distortion::idPressed () { } } -void Distortion::setAdjusterBehavior (bool vadd) { +void Distortion::setAdjusterBehavior (bool vadd) +{ - distor->setAddMode(vadd); + distor->setAddMode(vadd); } -void Distortion::trimValues (rtengine::procparams::ProcParams* pp) { +void Distortion::trimValues (rtengine::procparams::ProcParams* pp) +{ - distor->trimValue(pp->distortion.amount); + distor->trimValue(pp->distortion.amount); } diff --git a/rtgui/distortion.h b/rtgui/distortion.h index ecaa2b4e7..304f9dcd7 100644 --- a/rtgui/distortion.h +++ b/rtgui/distortion.h @@ -7,7 +7,7 @@ * 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 @@ -24,28 +24,32 @@ #include "toolpanel.h" #include "lensgeomlistener.h" -class Distortion : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class Distortion : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Gtk::Button* autoDistor; Adjuster* distor; sigc::connection idConn; LensGeomListener * rlistener; - public: +public: Distortion (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); void setAdjusterBehavior (bool vadd); void trimValues (rtengine::procparams::ProcParams* pp); void idPressed (); - void setLensGeomListener (LensGeomListener* l) { rlistener = l; } + void setLensGeomListener (LensGeomListener* l) + { + rlistener = l; + } }; #endif diff --git a/rtgui/edit.cc b/rtgui/edit.cc index 6f1344f6e..dc054cdc1 100644 --- a/rtgui/edit.cc +++ b/rtgui/edit.cc @@ -20,602 +20,745 @@ #include "edit.h" #include "../rtengine/editbuffer.h" -void Coord::setFromPolar(PolarCoord polar) { - while (polar.angle < 0.f) polar.angle += 360.f; - while (polar.angle > 360.f) polar.angle -= 360.f; - x = polar.radius * cos(polar.angle/180.f*M_PI); - y = polar.radius * sin(polar.angle/180.f*M_PI); +void Coord::setFromPolar(PolarCoord polar) +{ + while (polar.angle < 0.f) { + polar.angle += 360.f; + } + + while (polar.angle > 360.f) { + polar.angle -= 360.f; + } + + x = polar.radius * cos(polar.angle / 180.f * M_PI); + y = polar.radius * sin(polar.angle / 180.f * M_PI); } -RGBColor Geometry::getInnerLineColor () { - RGBColor color; - if (flags & AUTO_COLOR) { - if (state == NORMAL) { color.setColor (1., 1., 1.); } // White - else if (state == PRELIGHT) { color.setColor (1., 1., 0.); } // Orange - else if (state == DRAGGED) { color.setColor (1., 0., 0.); } // Red - } - else { color = innerLineColor; } - return color; +RGBColor Geometry::getInnerLineColor () +{ + RGBColor color; + + if (flags & AUTO_COLOR) { + if (state == NORMAL) { + color.setColor (1., 1., 1.); // White + } else if (state == PRELIGHT) { + color.setColor (1., 1., 0.); // Orange + } else if (state == DRAGGED) { + color.setColor (1., 0., 0.); // Red + } + } else { + color = innerLineColor; + } + + return color; } -RGBColor Geometry::getOuterLineColor () { - RGBColor color; - if (flags & AUTO_COLOR) { - /* - if (state == NORMAL) { color.setColor (0., 0., 0.); } // Black - else if (state == PRELIGHT) { color.setColor (0., 0., 0.); } // Black - else if (state == DRAGGED) { color.setColor (1., 0., 0.); } // Black - */ - color.setColor (0., 0., 0.); // Black - } - else { color = outerLineColor; } - return color; +RGBColor Geometry::getOuterLineColor () +{ + RGBColor color; + + if (flags & AUTO_COLOR) { + /* + if (state == NORMAL) { color.setColor (0., 0., 0.); } // Black + else if (state == PRELIGHT) { color.setColor (0., 0., 0.); } // Black + else if (state == DRAGGED) { color.setColor (1., 0., 0.); } // Black + */ + color.setColor (0., 0., 0.); // Black + } else { + color = outerLineColor; + } + + return color; } -void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getOuterLineColor(); - else - color = outerLineColor; +void Circle::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( getOuterLineWidth() ); + if (flags & AUTO_COLOR) { + color = getOuterLineColor(); + } else { + color = outerLineColor; + } - Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); - if (datum == IMAGE) { - coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); - } - else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; - } - else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - } - cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0., 2.*M_PI); - cr->stroke(); - } + cr->set_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( getOuterLineWidth() ); + + Coord center_ = center; + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); + } else if (datum == CLICKED_POINT) { + center_ += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); + cr->stroke(); + } } -void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getInnerLineColor(); - else - color = innerLineColor; +void Circle::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( innerLineWidth ); + if (flags & AUTO_COLOR) { + color = getInnerLineColor(); + } else { + color = innerLineColor; + } - Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); - if (datum == IMAGE) { - coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); - } - else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; - } - else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - } - if (filled) { - cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0., 2.*M_PI); - if (innerLineWidth > 0.) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->fill(); - } - else if (innerLineWidth > 0.) { - cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0., 2.*M_PI); - cr->stroke(); - } - } + cr->set_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( innerLineWidth ); + + Coord center_ = center; + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(center.x, center.y, center_.x, center_.y); + } else if (datum == CLICKED_POINT) { + center_ += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + if (filled) { + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); + + if (innerLineWidth > 0.) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->fill(); + } + } else if (innerLineWidth > 0.) { + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0., 2.*M_PI); + cr->stroke(); + } + } } -void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - cr->set_line_width( getMouseOverLineWidth() ); - Coord center_ = center; - double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); - if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(center.x, center.y, center_.x, center_.y); - } - else if (datum == CLICKED_POINT) { - center_ += editBuffer->getDataProvider()->posScreen; - } - else if (datum == CURSOR) { - center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - } +void Circle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + cr->set_line_width( getMouseOverLineWidth() ); + Coord center_ = center; + double radius_ = radiusInImageSpace ? coordSystem.scaleValueToScreen(double(radius)) : double(radius); - // drawing the lower byte's value - unsigned short a = (id+1) & 0xFF; - cr->set_source_rgba (0.,0., 0., double(a)/255.); - cr->arc(center_.x+0.5, center_.y+0.5, radius_, 0, 2.*M_PI); - if (filled) { - if (innerLineWidth > 0.) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->fill(); - } - else - cr->stroke(); + if (datum == IMAGE) { + coordSystem.imageCoordToCropBuffer(center.x, center.y, center_.x, center_.y); + } else if (datum == CLICKED_POINT) { + center_ += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + center_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id+1)>>8; - cr2->set_source_rgba (0.,0., 0., double(a)/255.); - cr2->arc(center_.x+0.5, center_.y+0.5, radius_, 0, 2.*M_PI); - if (filled) { - if (innerLineWidth > 0.) { - cr2->fill_preserve(); - cr2->stroke(); - } - else - cr2->fill(); - } - else - cr2->stroke(); - } - } + // drawing the lower byte's value + unsigned short a = (id + 1) & 0xFF; + cr->set_source_rgba (0., 0., 0., double(a) / 255.); + cr->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*M_PI); + + if (filled) { + if (innerLineWidth > 0.) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->fill(); + } + } else { + cr->stroke(); + } + + // drawing the higher byte's value + if (editBuffer->getObjectMode() == OM_65535) { + a = (id + 1) >> 8; + cr2->set_source_rgba (0., 0., 0., double(a) / 255.); + cr2->arc(center_.x + 0.5, center_.y + 0.5, radius_, 0, 2.*M_PI); + + if (filled) { + if (innerLineWidth > 0.) { + cr2->fill_preserve(); + cr2->stroke(); + } else { + cr2->fill(); + } + } else { + cr2->stroke(); + } + } + } } -void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getOuterLineColor(); - else - color = outerLineColor; +void Line::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( getOuterLineWidth() ); + if (flags & AUTO_COLOR) { + color = getOuterLineColor(); + } else { + color = outerLineColor; + } - Coord begin_ = begin; - Coord end_ = end; - if (datum == IMAGE) { - coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); - } - else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; - } - else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - } - cr->move_to(begin_.x+0.5, begin_.y+0.5); - cr->line_to(end_.x+0.5, end_.y+0.5); - cr->stroke(); - } + cr->set_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( getOuterLineWidth() ); + + Coord begin_ = begin; + Coord end_ = end; + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); + } else if (datum == CLICKED_POINT) { + begin_ += editBuffer->getDataProvider()->posScreen; + end_ += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + cr->move_to(begin_.x + 0.5, begin_.y + 0.5); + cr->line_to(end_.x + 0.5, end_.y + 0.5); + cr->stroke(); + } } -void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if ((flags & ACTIVE) && innerLineWidth > 0.) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getInnerLineColor(); - else - color = innerLineColor; +void Line::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if ((flags & ACTIVE) && innerLineWidth > 0.) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width(innerLineWidth); + if (flags & AUTO_COLOR) { + color = getInnerLineColor(); + } else { + color = innerLineColor; + } - Coord begin_ = begin; - Coord end_ = end; - if (datum == IMAGE) { - coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); - } - else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; - } - else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - } - cr->move_to(begin_.x+0.5, begin_.y+0.5); - cr->line_to(end_.x+0.5, end_.y+0.5); - cr->stroke(); - } + cr->set_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width(innerLineWidth); + + Coord begin_ = begin; + Coord end_ = end; + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToScreen(end.x, end.y, end_.x, end_.y); + } else if (datum == CLICKED_POINT) { + begin_ += editBuffer->getDataProvider()->posScreen; + end_ += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + cr->move_to(begin_.x + 0.5, begin_.y + 0.5); + cr->line_to(end_.x + 0.5, end_.y + 0.5); + cr->stroke(); + } } -void Line::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - cr->set_line_width( getMouseOverLineWidth() ); - Coord begin_ = begin; - Coord end_ = end; - if (datum == IMAGE) { - coordSystem.imageCoordToCropBuffer(begin.x, begin.y, begin_.x, begin_.y); - coordSystem.imageCoordToCropBuffer(end.x, end.y, end_.x, end_.y); - } - else if (datum == CLICKED_POINT) { - begin_ += editBuffer->getDataProvider()->posScreen; - end_ += editBuffer->getDataProvider()->posScreen; - } - else if (datum == CURSOR) { - begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; - } +void Line::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + cr->set_line_width( getMouseOverLineWidth() ); + Coord begin_ = begin; + Coord end_ = end; - // drawing the lower byte's value - unsigned short a = (id+1) & 0xFF; - cr->set_source_rgba (0.,0., 0., double(a)/255.); - cr->move_to(begin_.x+0.5, begin_.y+0.5); - cr->line_to(end_.x+0.5, end_.y+0.5); - cr->stroke(); + if (datum == IMAGE) { + coordSystem.imageCoordToCropBuffer(begin.x, begin.y, begin_.x, begin_.y); + coordSystem.imageCoordToCropBuffer(end.x, end.y, end_.x, end_.y); + } else if (datum == CLICKED_POINT) { + begin_ += editBuffer->getDataProvider()->posScreen; + end_ += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + begin_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + end_ += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id+1)>>8; - cr2->set_source_rgba (0.,0., 0., double(a)/255.); - cr2->move_to(begin_.x+0.5, begin_.y+0.5); - cr2->line_to(end_.x+0.5, end_.y+0.5); - cr2->stroke(); - } - } + // drawing the lower byte's value + unsigned short a = (id + 1) & 0xFF; + cr->set_source_rgba (0., 0., 0., double(a) / 255.); + cr->move_to(begin_.x + 0.5, begin_.y + 0.5); + cr->line_to(end_.x + 0.5, end_.y + 0.5); + cr->stroke(); + + // drawing the higher byte's value + if (editBuffer->getObjectMode() == OM_65535) { + a = (id + 1) >> 8; + cr2->set_source_rgba (0., 0., 0., double(a) / 255.); + cr2->move_to(begin_.x + 0.5, begin_.y + 0.5); + cr2->line_to(end_.x + 0.5, end_.y + 0.5); + cr2->stroke(); + } + } } -void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if ((flags & ACTIVE) && points.size()>1) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getOuterLineColor(); - else - color = outerLineColor; +void Polyline::drawOuterGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if ((flags & ACTIVE) && points.size() > 1) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( getOuterLineWidth() ); + if (flags & AUTO_COLOR) { + color = getOuterLineColor(); + } else { + color = outerLineColor; + } - Coord currPos; - for (unsigned int i=0; iset_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( getOuterLineWidth() ); - if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); - else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + Coord currPos; - if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5); - else cr->line_to(currPos.x+0.5, currPos.y+0.5); - } - if (filled) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->stroke(); - } + for (unsigned int i = 0; i < points.size(); ++i) { + currPos = points.at(i); + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + } else if (datum == CLICKED_POINT) { + currPos += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + if (!i) { + cr->move_to(currPos.x + 0.5, currPos.y + 0.5); + } else { + cr->line_to(currPos.x + 0.5, currPos.y + 0.5); + } + } + + if (filled) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->stroke(); + } + } } -void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if ((flags & ACTIVE) && points.size()>1) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getInnerLineColor(); - else - color = innerLineColor; +void Polyline::drawInnerGeometry(Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if ((flags & ACTIVE) && points.size() > 1) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( getOuterLineWidth() ); + if (flags & AUTO_COLOR) { + color = getInnerLineColor(); + } else { + color = innerLineColor; + } - if (filled) { - Coord currPos; - for (unsigned int i=0; iset_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( getOuterLineWidth() ); - if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); - else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + if (filled) { + Coord currPos; - if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5); - else cr->line_to(currPos.x+0.5, currPos.y+0.5); - } + for (unsigned int i = 0; i < points.size(); ++i) { + currPos = points.at(i); - if (innerLineWidth > 0.) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->fill(); - } - else if (innerLineWidth > 0.) { - Coord currPos; - for (unsigned int i=0; igetDataProvider()->posScreen; + } else if (datum == CURSOR) { + currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - if (datum == IMAGE) coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); - else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + if (!i) { + cr->move_to(currPos.x + 0.5, currPos.y + 0.5); + } else { + cr->line_to(currPos.x + 0.5, currPos.y + 0.5); + } + } - if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5); - else cr->line_to(currPos.x+0.5, currPos.y+0.5); - } - cr->stroke(); - } - } + if (innerLineWidth > 0.) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->fill(); + } + } else if (innerLineWidth > 0.) { + Coord currPos; + + for (unsigned int i = 0; i < points.size(); ++i) { + currPos = points.at(i); + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + } else if (datum == CLICKED_POINT) { + currPos += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + if (!i) { + cr->move_to(currPos.x + 0.5, currPos.y + 0.5); + } else { + cr->line_to(currPos.x + 0.5, currPos.y + 0.5); + } + } + + cr->stroke(); + } + } } -void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if ((flags & ACTIVE) && points.size()>1) { - Coord currPos; +void Polyline::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if ((flags & ACTIVE) && points.size() > 1) { + Coord currPos; - // drawing the lower byte's value - unsigned short a = (id+1) & 0xFF; - cr->set_source_rgba (0.,0., 0., double(a)/255.); - for (unsigned int i=0; iset_line_width( getOuterLineWidth() ); - currPos = points.at(i); + // drawing the lower byte's value + unsigned short a = (id + 1) & 0xFF; + cr->set_source_rgba (0., 0., 0., double(a) / 255.); - if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); - else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + for (unsigned int i = 0; i < points.size(); ++i) { + cr->set_line_width( getOuterLineWidth() ); + currPos = points.at(i); - if (!i) cr->move_to(currPos.x+0.5, currPos.y+0.5); - else cr->line_to(currPos.x+0.5, currPos.y+0.5); - } - if (filled) { - if (innerLineWidth > 0.) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->fill(); - } - else - cr->stroke(); + if (datum == IMAGE) { + coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + } else if (datum == CLICKED_POINT) { + currPos += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id+1)>>8; - cr2->set_source_rgba (0.,0., 0., double(a)/255.); - for (unsigned int i=0; iset_line_width( getOuterLineWidth() ); - currPos = points.at(i); + if (!i) { + cr->move_to(currPos.x + 0.5, currPos.y + 0.5); + } else { + cr->line_to(currPos.x + 0.5, currPos.y + 0.5); + } + } - if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); - else if (datum == CLICKED_POINT) currPos += editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + if (filled) { + if (innerLineWidth > 0.) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->fill(); + } + } else { + cr->stroke(); + } - if (!i) cr2->move_to(currPos.x+0.5, currPos.y+0.5); - else cr2->line_to(currPos.x+0.5, currPos.y+0.5); - } - if (filled) { - if (innerLineWidth > 0.) { - cr2->fill_preserve(); - cr2->stroke(); - } - else - cr2->fill(); - } - else - cr2->stroke(); - } - } + // drawing the higher byte's value + if (editBuffer->getObjectMode() == OM_65535) { + a = (id + 1) >> 8; + cr2->set_source_rgba (0., 0., 0., double(a) / 255.); + + for (unsigned int i = 0; i < points.size(); ++i) { + cr2->set_line_width( getOuterLineWidth() ); + currPos = points.at(i); + + if (datum == IMAGE) { + coordSystem.imageCoordToCropBuffer(points.at(i).x, points.at(i).y, currPos.x, currPos.y); + } else if (datum == CLICKED_POINT) { + currPos += editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + currPos += editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + if (!i) { + cr2->move_to(currPos.x + 0.5, currPos.y + 0.5); + } else { + cr2->line_to(currPos.x + 0.5, currPos.y + 0.5); + } + } + + if (filled) { + if (innerLineWidth > 0.) { + cr2->fill_preserve(); + cr2->stroke(); + } else { + cr2->fill(); + } + } else { + cr2->stroke(); + } + } + } } -void Rectangle::setXYWH(int left, int top, int width, int height) { - topLeft.set(left, top); - bottomRight.set(left+width, top+height); +void Rectangle::setXYWH(int left, int top, int width, int height) +{ + topLeft.set(left, top); + bottomRight.set(left + width, top + height); } -void Rectangle::setXYXY(int left, int top, int right, int bottom) { - topLeft.set(left, top); - bottomRight.set(right, bottom); +void Rectangle::setXYXY(int left, int top, int right, int bottom) +{ + topLeft.set(left, top); + bottomRight.set(right, bottom); } -void Rectangle::setXYWH(Coord topLeft, Coord widthHeight) { - this->topLeft = topLeft; - this->bottomRight = topLeft + widthHeight; +void Rectangle::setXYWH(Coord topLeft, Coord widthHeight) +{ + this->topLeft = topLeft; + this->bottomRight = topLeft + widthHeight; } -void Rectangle::setXYXY(Coord topLeft, Coord bottomRight) { - this->topLeft = topLeft; - this->bottomRight = bottomRight; +void Rectangle::setXYXY(Coord topLeft, Coord bottomRight) +{ + this->topLeft = topLeft; + this->bottomRight = bottomRight; } -void Rectangle::drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if ((flags & ACTIVE)) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getOuterLineColor(); - else - color = outerLineColor; +void Rectangle::drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if ((flags & ACTIVE)) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( getOuterLineWidth() ); + if (flags & AUTO_COLOR) { + color = getOuterLineColor(); + } else { + color = outerLineColor; + } - Coord tl, br; + cr->set_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( getOuterLineWidth() ); - if (datum == IMAGE) coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); - else if (datum == CLICKED_POINT) tl = topLeft + editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) tl = topLeft +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + Coord tl, br; - if (datum == IMAGE) coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); - else if (datum == CLICKED_POINT) br = bottomRight + editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) br = bottomRight +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); + } else if (datum == CLICKED_POINT) { + tl = topLeft + editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y); + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); + } else if (datum == CLICKED_POINT) { + br = bottomRight + editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - if (filled) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->stroke(); - } + cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); + + if (filled) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->stroke(); + } + } } -void Rectangle::drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - RGBColor color; - if (flags & AUTO_COLOR) - color = getInnerLineColor(); - else - color = innerLineColor; +void Rectangle::drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + RGBColor color; - cr->set_source_rgb (color.getR(), color.getG(), color.getB()); - cr->set_line_width( innerLineWidth ); + if (flags & AUTO_COLOR) { + color = getInnerLineColor(); + } else { + color = innerLineColor; + } - Coord tl, br; - if (datum == IMAGE) coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); - else if (datum == CLICKED_POINT) tl = topLeft + editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) tl = topLeft +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + cr->set_source_rgb (color.getR(), color.getG(), color.getB()); + cr->set_line_width( innerLineWidth ); - if (datum == IMAGE) coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); - else if (datum == CLICKED_POINT) br = bottomRight + editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) br = bottomRight +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + Coord tl, br; - if (filled) { - cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y); - if (innerLineWidth > 0.) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->fill(); - } - else if (innerLineWidth > 0.) { - cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y); - cr->stroke(); - } - } + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(topLeft.x, topLeft.y, tl.x, tl.y); + } else if (datum == CLICKED_POINT) { + tl = topLeft + editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + if (datum == IMAGE) { + coordSystem.imageCoordToScreen(bottomRight.x, bottomRight.y, br.x, br.y); + } else if (datum == CLICKED_POINT) { + br = bottomRight + editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } + + if (filled) { + cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); + + if (innerLineWidth > 0.) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->fill(); + } + } else if (innerLineWidth > 0.) { + cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); + cr->stroke(); + } + } } -void Rectangle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) { - if (flags & ACTIVE) { - cr->set_line_width( getMouseOverLineWidth() ); +void Rectangle::drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) +{ + if (flags & ACTIVE) { + cr->set_line_width( getMouseOverLineWidth() ); - Coord tl, br; - if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(topLeft.x, topLeft.y, tl.x, tl.y); - else if (datum == CLICKED_POINT) tl = topLeft + editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) tl = topLeft +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + Coord tl, br; - if (datum == IMAGE) coordSystem.imageCoordToCropBuffer(bottomRight.x, bottomRight.y, br.x, br.y); - else if (datum == CLICKED_POINT) br = bottomRight + editBuffer->getDataProvider()->posScreen; - else if (datum == CURSOR) br = bottomRight +editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + if (datum == IMAGE) { + coordSystem.imageCoordToCropBuffer(topLeft.x, topLeft.y, tl.x, tl.y); + } else if (datum == CLICKED_POINT) { + tl = topLeft + editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + tl = topLeft + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - // drawing the lower byte's value - unsigned short a = (id+1) & 0xFF; - cr->set_source_rgba (0.,0., 0., double(a)/255.); - cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y); - if (filled) { - if (innerLineWidth > 0.) { - cr->fill_preserve(); - cr->stroke(); - } - else - cr->fill(); - } - else - cr->stroke(); + if (datum == IMAGE) { + coordSystem.imageCoordToCropBuffer(bottomRight.x, bottomRight.y, br.x, br.y); + } else if (datum == CLICKED_POINT) { + br = bottomRight + editBuffer->getDataProvider()->posScreen; + } else if (datum == CURSOR) { + br = bottomRight + editBuffer->getDataProvider()->posScreen + editBuffer->getDataProvider()->deltaPrevScreen; + } - // drawing the higher byte's value - if (editBuffer->getObjectMode() == OM_65535) { - a = (id+1)>>8; - cr2->set_source_rgba (0.,0., 0., double(a)/255.); - cr->rectangle(tl.x+0.5, tl.y+0.5, br.x-tl.x, br.y-tl.y); - if (filled) { - if (innerLineWidth > 0.) { - cr2->fill_preserve(); - cr2->stroke(); - } - else - cr2->fill(); - } - else - cr2->stroke(); - } - } + // drawing the lower byte's value + unsigned short a = (id + 1) & 0xFF; + cr->set_source_rgba (0., 0., 0., double(a) / 255.); + cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); + + if (filled) { + if (innerLineWidth > 0.) { + cr->fill_preserve(); + cr->stroke(); + } else { + cr->fill(); + } + } else { + cr->stroke(); + } + + // drawing the higher byte's value + if (editBuffer->getObjectMode() == OM_65535) { + a = (id + 1) >> 8; + cr2->set_source_rgba (0., 0., 0., double(a) / 255.); + cr->rectangle(tl.x + 0.5, tl.y + 0.5, br.x - tl.x, br.y - tl.y); + + if (filled) { + if (innerLineWidth > 0.) { + cr2->fill_preserve(); + cr2->stroke(); + } else { + cr2->fill(); + } + } else { + cr2->stroke(); + } + } + } } EditSubscriber::EditSubscriber (EditType editType) : ID(EUID_None), editingType(editType), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL) {} -void EditSubscriber::setEditProvider(EditDataProvider *provider) { - this->provider = provider; +void EditSubscriber::setEditProvider(EditDataProvider *provider) +{ + this->provider = provider; } -void EditSubscriber::setEditID(EditUniqueID ID, BufferType buffType) { - this->ID = ID; - bufferType = buffType; +void EditSubscriber::setEditID(EditUniqueID ID, BufferType buffType) +{ + this->ID = ID; + bufferType = buffType; } -bool EditSubscriber::isCurrentSubscriber() { - //if (provider && provider->getCurrSubscriber()) - // return provider->getCurrSubscriber()->getEditID() == ID; +bool EditSubscriber::isCurrentSubscriber() +{ + //if (provider && provider->getCurrSubscriber()) + // return provider->getCurrSubscriber()->getEditID() == ID; - if (provider) - return provider->getCurrSubscriber() == this; + if (provider) { + return provider->getCurrSubscriber() == this; + } - return false; + return false; } -void EditSubscriber::subscribe() { - if (provider) - provider->subscribe(this); +void EditSubscriber::subscribe() +{ + if (provider) { + provider->subscribe(this); + } } -void EditSubscriber::unsubscribe() { - if (provider) - provider->unsubscribe(); +void EditSubscriber::unsubscribe() +{ + if (provider) { + provider->unsubscribe(); + } } -void EditSubscriber::switchOffEditMode() { - unsubscribe(); +void EditSubscriber::switchOffEditMode() +{ + unsubscribe(); } -EditUniqueID EditSubscriber::getEditID() { - return ID; +EditUniqueID EditSubscriber::getEditID() +{ + return ID; } -EditType EditSubscriber::getEditingType() { - return editingType; +EditType EditSubscriber::getEditingType() +{ + return editingType; } -BufferType EditSubscriber::getEditBufferType() { - return bufferType; +BufferType EditSubscriber::getEditBufferType() +{ + return bufferType; } //-------------------------------------------------------------------------------------------------- -EditDataProvider::EditDataProvider() : currSubscriber(NULL), object(0), posScreen(-1,-1), posImage(-1,-1), - deltaScreen(0,0), deltaImage(0,0), deltaPrevScreen(0,0), deltaPrevImage(0,0) { - pipetteVal[0] = pipetteVal[1] = pipetteVal[2] = 0.f; +EditDataProvider::EditDataProvider() : currSubscriber(NULL), object(0), posScreen(-1, -1), posImage(-1, -1), + deltaScreen(0, 0), deltaImage(0, 0), deltaPrevScreen(0, 0), deltaPrevImage(0, 0) +{ + pipetteVal[0] = pipetteVal[1] = pipetteVal[2] = 0.f; } -void EditDataProvider::subscribe(EditSubscriber *subscriber) { - if (currSubscriber) - currSubscriber->switchOffEditMode(); +void EditDataProvider::subscribe(EditSubscriber *subscriber) +{ + if (currSubscriber) { + currSubscriber->switchOffEditMode(); + } - currSubscriber = subscriber; + currSubscriber = subscriber; } -void EditDataProvider::unsubscribe() { - currSubscriber = NULL; +void EditDataProvider::unsubscribe() +{ + currSubscriber = NULL; } -void EditDataProvider::switchOffEditMode() { - if (currSubscriber) - currSubscriber->switchOffEditMode (); +void EditDataProvider::switchOffEditMode() +{ + if (currSubscriber) { + currSubscriber->switchOffEditMode (); + } } -CursorShape EditDataProvider::getCursor(int objectID) { - if (currSubscriber) - currSubscriber->getCursor(objectID); +CursorShape EditDataProvider::getCursor(int objectID) +{ + if (currSubscriber) { + currSubscriber->getCursor(objectID); + } - return CSOpenHand; + return CSOpenHand; } -EditSubscriber* EditDataProvider::getCurrSubscriber() { - return currSubscriber; +EditSubscriber* EditDataProvider::getCurrSubscriber() +{ + return currSubscriber; } diff --git a/rtgui/edit.h b/rtgui/edit.h index 1e7159384..134b373ea 100644 --- a/rtgui/edit.h +++ b/rtgui/edit.h @@ -28,7 +28,8 @@ class EditDataProvider; -namespace rtengine { +namespace rtengine +{ class EditBuffer; } @@ -66,224 +67,303 @@ class EditBuffer; * * The EditCoordSystem is used to define a screen and an image coordinate system. */ -class EditCoordSystem { +class EditCoordSystem +{ public: - virtual ~EditCoordSystem() {} + virtual ~EditCoordSystem() {} - /// Convert the widget's DrawingArea (i.e. preview area) coords to the edit buffer coords - virtual void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy) =0; - /// Convert the widget's DrawingArea (i.e. preview area) coords to the full image coords - virtual void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) =0; - /// Convert the image coords to the widget's DrawingArea (i.e. preview area) coords - virtual void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) =0; - /// Convert the image coords to the edit buffer coords - virtual void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) =0; - /// Convert a size value from the preview's scale to the image's scale - virtual int scaleValueToImage (int value) =0; - /// Convert a size value from the preview's scale to the image's scale - virtual float scaleValueToImage (float value) =0; - /// Convert a size value from the preview's scale to the image's scale - virtual double scaleValueToImage (double value) =0; - /// Convert a size value from the image's scale to the preview's scale - virtual int scaleValueToScreen (int value) =0; - /// Convert a size value from the image's scale to the preview's scale - virtual float scaleValueToScreen (float value) =0; - /// Convert a size value from the image's scale to the preview's scale - virtual double scaleValueToScreen (double value) =0; + /// Convert the widget's DrawingArea (i.e. preview area) coords to the edit buffer coords + virtual void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy) = 0; + /// Convert the widget's DrawingArea (i.e. preview area) coords to the full image coords + virtual void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) = 0; + /// Convert the image coords to the widget's DrawingArea (i.e. preview area) coords + virtual void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) = 0; + /// Convert the image coords to the edit buffer coords + virtual void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) = 0; + /// Convert a size value from the preview's scale to the image's scale + virtual int scaleValueToImage (int value) = 0; + /// Convert a size value from the preview's scale to the image's scale + virtual float scaleValueToImage (float value) = 0; + /// Convert a size value from the preview's scale to the image's scale + virtual double scaleValueToImage (double value) = 0; + /// Convert a size value from the image's scale to the preview's scale + virtual int scaleValueToScreen (int value) = 0; + /// Convert a size value from the image's scale to the preview's scale + virtual float scaleValueToScreen (float value) = 0; + /// Convert a size value from the image's scale to the preview's scale + virtual double scaleValueToScreen (double value) = 0; }; -class RGBColor { - double r; - double g; - double b; +class RGBColor +{ + double r; + double g; + double b; public: - RGBColor () : r(0.), g(0.), b(0.) {} - explicit RGBColor (double r, double g, double b) : r(r), g(g), b(b) {} - explicit RGBColor (char r, char g, char b) : r(double(r)/255.), g(double(g)/255.), b(double(b)/255.) {} + RGBColor () : r(0.), g(0.), b(0.) {} + explicit RGBColor (double r, double g, double b) : r(r), g(g), b(b) {} + explicit RGBColor (char r, char g, char b) : r(double(r) / 255.), g(double(g) / 255.), b(double(b) / 255.) {} - void setColor(double r, double g, double b) { - this->r = r; - this->g = g; - this->b = b; - } + void setColor(double r, double g, double b) + { + this->r = r; + this->g = g; + this->b = b; + } - void setColor(char r, char g, char b) { - this->r = double(r)/255.; - this->g = double(g)/255.; - this->b = double(b)/255.; - } + void setColor(char r, char g, char b) + { + this->r = double(r) / 255.; + this->g = double(g) / 255.; + this->b = double(b) / 255.; + } - double getR() { return r; } - double getG() { return g; } - double getB() { return b; } + double getR() + { + return r; + } + double getG() + { + return g; + } + double getB() + { + return b; + } }; -class Geometry { +class Geometry +{ public: - enum State { - NORMAL, - PRELIGHT, - DRAGGED - }; - enum Datum { - IMAGE, - CLICKED_POINT, - CURSOR - }; - enum Flags { - ACTIVE = 1<<0, // true if the geometry is active and have to be drawn - AUTO_COLOR = 1<<1, // true if the color depend on the state value, not the color field above - }; + enum State { + NORMAL, + PRELIGHT, + DRAGGED + }; + enum Datum { + IMAGE, + CLICKED_POINT, + CURSOR + }; + enum Flags { + ACTIVE = 1 << 0, // true if the geometry is active and have to be drawn + AUTO_COLOR = 1 << 1, // true if the color depend on the state value, not the color field above + }; protected: - RGBColor innerLineColor; - RGBColor outerLineColor; - short flags; + RGBColor innerLineColor; + RGBColor outerLineColor; + short flags; public: - float innerLineWidth; // ...outerLineWidth = innerLineWidth+2 - Datum datum; - State state; // set by the Subscriber + float innerLineWidth; // ...outerLineWidth = innerLineWidth+2 + Datum datum; + State state; // set by the Subscriber - Geometry () : innerLineColor(char(255), char(255), char(255)), outerLineColor(char(0), char(0), char(0)), flags(ACTIVE|AUTO_COLOR), innerLineWidth(1.f), datum(IMAGE), state(NORMAL) {} - virtual ~Geometry() {} + Geometry () : innerLineColor(char(255), char(255), char(255)), outerLineColor(char(0), char(0), char(0)), flags(ACTIVE | AUTO_COLOR), innerLineWidth(1.f), datum(IMAGE), state(NORMAL) {} + virtual ~Geometry() {} - void setInnerLineColor (double r, double g, double b) { innerLineColor.setColor(r, g, b); flags &= ~AUTO_COLOR; } - void setInnerLineColor (char r, char g, char b) { innerLineColor.setColor(r, g, b); flags &= ~AUTO_COLOR; } - RGBColor getInnerLineColor (); - void setOuterLineColor (double r, double g, double b) { outerLineColor.setColor(r, g, b); flags &= ~AUTO_COLOR; } - void setOuterLineColor (char r, char g, char b) { outerLineColor.setColor(r, g, b); flags &= ~AUTO_COLOR; } - RGBColor getOuterLineColor (); - double getOuterLineWidth () { return double(innerLineWidth)+2.; } - double getMouseOverLineWidth () { return getOuterLineWidth()+2.; } - void setAutoColor (bool aColor) { if (aColor) flags |= AUTO_COLOR; else flags &= ~AUTO_COLOR; } - void setActive (bool active) { if (active) flags |= ACTIVE; else flags &= ~ACTIVE; } + void setInnerLineColor (double r, double g, double b) + { + innerLineColor.setColor(r, g, b); + flags &= ~AUTO_COLOR; + } + void setInnerLineColor (char r, char g, char b) + { + innerLineColor.setColor(r, g, b); + flags &= ~AUTO_COLOR; + } + RGBColor getInnerLineColor (); + void setOuterLineColor (double r, double g, double b) + { + outerLineColor.setColor(r, g, b); + flags &= ~AUTO_COLOR; + } + void setOuterLineColor (char r, char g, char b) + { + outerLineColor.setColor(r, g, b); + flags &= ~AUTO_COLOR; + } + RGBColor getOuterLineColor (); + double getOuterLineWidth () + { + return double(innerLineWidth) + 2.; + } + double getMouseOverLineWidth () + { + return getOuterLineWidth() + 2.; + } + void setAutoColor (bool aColor) + { + if (aColor) { + flags |= AUTO_COLOR; + } else { + flags &= ~AUTO_COLOR; + } + } + void setActive (bool active) + { + if (active) { + flags |= ACTIVE; + } else { + flags &= ~ACTIVE; + } + } - virtual void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) =0; - virtual void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) =0; - virtual void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) =0; + virtual void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) = 0; + virtual void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *parent, EditCoordSystem &coordSystem) = 0; + virtual void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem) = 0; }; -class Circle : public Geometry { +class Circle : public Geometry +{ public: - Coord center; - int radius; - bool filled; - bool radiusInImageSpace; /// If true, the radius depend on the image scale; if false, it is a fixed 'screen' size + Coord center; + int radius; + bool filled; + bool radiusInImageSpace; /// If true, the radius depend on the image scale; if false, it is a fixed 'screen' size - Circle () : center(100,100), radius(10), filled(false), radiusInImageSpace(false) {} - Circle (Coord ¢er, int radius, bool filled=false, bool radiusInImageSpace=false) : center(center), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} - Circle (int centerX, int centerY, int radius, bool filled=false, bool radiusInImageSpace=false) : center(centerX, centerY), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} + Circle () : center(100, 100), radius(10), filled(false), radiusInImageSpace(false) {} + Circle (Coord ¢er, int radius, bool filled = false, bool radiusInImageSpace = false) : center(center), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} + Circle (int centerX, int centerY, int radius, bool filled = false, bool radiusInImageSpace = false) : center(centerX, centerY), radius(radius), filled(filled), radiusInImageSpace(radiusInImageSpace) {} - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); }; -class Line : public Geometry { +class Line : public Geometry +{ public: - Coord begin; - Coord end; + Coord begin; + Coord end; - Line () : begin(10,10), end(100,100) {} - Line (Coord &begin, Coord &end) : begin(begin), end(end) {} - Line (int beginX, int beginY, int endX, int endY) : begin(beginX, beginY), end(endX, endY) {} + Line () : begin(10, 10), end(100, 100) {} + Line (Coord &begin, Coord &end) : begin(begin), end(end) {} + Line (int beginX, int beginY, int endX, int endY) : begin(beginX, beginY), end(endX, endY) {} - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); }; -class Polyline : public Geometry { +class Polyline : public Geometry +{ public: - std::vector points; - bool filled; + std::vector points; + bool filled; - Polyline() : filled(false) {} + Polyline() : filled(false) {} - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); }; -class Rectangle : public Geometry { +class Rectangle : public Geometry +{ public: - Coord topLeft; - Coord bottomRight; - bool filled; + Coord topLeft; + Coord bottomRight; + bool filled; - Rectangle() : topLeft(0,0), bottomRight(10,10), filled(false) {} + Rectangle() : topLeft(0, 0), bottomRight(10, 10), filled(false) {} - void setXYWH(int left, int top, int width, int height); - void setXYXY(int left, int top, int right, int bottom); - void setXYWH(Coord topLeft, Coord widthHeight); - void setXYXY(Coord topLeft, Coord bottomRight); - void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); - void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void setXYWH(int left, int top, int width, int height); + void setXYXY(int left, int top, int right, int bottom); + void setXYWH(Coord topLeft, Coord widthHeight); + void setXYXY(Coord topLeft, Coord bottomRight); + void drawOuterGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawInnerGeometry (Cairo::RefPtr &cr, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); + void drawToMOChannel (Cairo::RefPtr &cr, Cairo::RefPtr &cr2, unsigned short id, rtengine::EditBuffer *editBuffer, EditCoordSystem &coordSystem); }; /// @brief Method for client tools needing Edit information -class EditSubscriber { +class EditSubscriber +{ public: private: - EditUniqueID ID; /// this will be used in improcfun to locate the data that has to be stored in the buffer; it must be unique in RT - EditType editingType; - BufferType bufferType; - EditDataProvider *provider; + EditUniqueID ID; /// this will be used in improcfun to locate the data that has to be stored in the buffer; it must be unique in RT + EditType editingType; + BufferType bufferType; + EditDataProvider *provider; protected: - std::vector visibleGeometry; - std::vector mouseOverGeometry; + std::vector visibleGeometry; + std::vector mouseOverGeometry; public: - EditSubscriber (EditType editType); - virtual ~EditSubscriber () {} + EditSubscriber (EditType editType); + virtual ~EditSubscriber () {} - void setEditProvider(EditDataProvider *provider); - EditDataProvider* getEditProvider() { return provider; } - void setEditID(EditUniqueID ID, BufferType buffType); - bool isCurrentSubscriber(); - virtual void subscribe(); - virtual void unsubscribe(); - virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode - EditUniqueID getEditID(); - EditType getEditingType(); - BufferType getEditBufferType(); + void setEditProvider(EditDataProvider *provider); + EditDataProvider* getEditProvider() + { + return provider; + } + void setEditID(EditUniqueID ID, BufferType buffType); + bool isCurrentSubscriber(); + virtual void subscribe(); + virtual void unsubscribe(); + virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode + EditUniqueID getEditID(); + EditType getEditingType(); + BufferType getEditBufferType(); - /** @brief Get the cursor to be displayed when above handles - @param objectID object currently "hovered" */ - virtual CursorShape getCursor(int objectID) { return CSOpenHand; } + /** @brief Get the cursor to be displayed when above handles + @param objectID object currently "hovered" */ + virtual CursorShape getCursor(int objectID) + { + return CSOpenHand; + } - /** @brief Triggered when the mouse is moving over an object - This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode - @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) - @param editBuffer buffer to get the pipette values and the from - @return true if the preview has to be redrawn, false otherwise */ - virtual bool mouseOver(int modifierKey) { return false; } + /** @brief Triggered when the mouse is moving over an object + This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode + @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) + @param editBuffer buffer to get the pipette values and the from + @return true if the preview has to be redrawn, false otherwise */ + virtual bool mouseOver(int modifierKey) + { + return false; + } - /** @brief Triggered when mouse button 1 is pressed, together with the CTRL modifier key if the subscriber is of type ET_PIPETTE - @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) - @return true if the preview has to be redrawn, false otherwise */ - virtual bool button1Pressed(int modifierKey) { return false; } + /** @brief Triggered when mouse button 1 is pressed, together with the CTRL modifier key if the subscriber is of type ET_PIPETTE + @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) + @return true if the preview has to be redrawn, false otherwise */ + virtual bool button1Pressed(int modifierKey) + { + return false; + } - /** @brief Triggered when mouse button 1 is released - @return true if the preview has to be redrawn, false otherwise */ - virtual bool button1Released() { return false; } + /** @brief Triggered when mouse button 1 is released + @return true if the preview has to be redrawn, false otherwise */ + virtual bool button1Released() + { + return false; + } - /** @brief Triggered when the user is moving while holding down mouse button 1 - @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) - @return true if the preview has to be redrawn, false otherwise */ - virtual bool drag(int modifierKey) { return false; } + /** @brief Triggered when the user is moving while holding down mouse button 1 + @param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...) + @return true if the preview has to be redrawn, false otherwise */ + virtual bool drag(int modifierKey) + { + return false; + } - /** @brief Get the geometry to be shown to the user */ - const std::vector & getVisibleGeometry() { return visibleGeometry; } + /** @brief Get the geometry to be shown to the user */ + const std::vector & getVisibleGeometry() + { + return visibleGeometry; + } - /** @brief Get the geometry to be drawn in the "mouse over" channel, hidden from the user */ - const std::vector & getMouseOverGeometry() { return mouseOverGeometry; } + /** @brief Get the geometry to be drawn in the "mouse over" channel, hidden from the user */ + const std::vector & getMouseOverGeometry() + { + return mouseOverGeometry; + } }; /** @brief Class to handle the furniture of data to the subscribers. @@ -291,32 +371,36 @@ public: * It is admitted that only one Subscriber can ask data at a time. If the Subscriber is of type ET_PIPETTE, it will have to * trigger the usual event so that the image will be reprocessed to compute the buffer of the current subscriber. */ -class EditDataProvider { +class EditDataProvider +{ private: - EditSubscriber *currSubscriber; + EditSubscriber *currSubscriber; public: - int object; /// ET_OBJECTS mode: Object detected under the cursor, 0 otherwise; ET_PIPETTE mode: 1 if above the image, 0 otherwise - float pipetteVal[3]; /// Current pipette values; if bufferType==BT_SINGLEPLANE_FLOAT, #2 & #3 will be set to 0 + int object; /// ET_OBJECTS mode: Object detected under the cursor, 0 otherwise; ET_PIPETTE mode: 1 if above the image, 0 otherwise + float pipetteVal[3]; /// Current pipette values; if bufferType==BT_SINGLEPLANE_FLOAT, #2 & #3 will be set to 0 - Coord posScreen; /// Location of the mouse button press, in preview image space - Coord posImage; /// Location of the mouse button press, in the full image space - Coord deltaScreen; /// Delta relative to posScreen - Coord deltaImage; /// Delta relative to posImage - Coord deltaPrevScreen; /// Delta relative to the previous mouse location, in preview image space - Coord deltaPrevImage; /// Delta relative to the previous mouse location, in the full image space + Coord posScreen; /// Location of the mouse button press, in preview image space + Coord posImage; /// Location of the mouse button press, in the full image space + Coord deltaScreen; /// Delta relative to posScreen + Coord deltaImage; /// Delta relative to posImage + Coord deltaPrevScreen; /// Delta relative to the previous mouse location, in preview image space + Coord deltaPrevImage; /// Delta relative to the previous mouse location, in the full image space - EditDataProvider(); - virtual ~EditDataProvider() {} + EditDataProvider(); + virtual ~EditDataProvider() {} - virtual void subscribe(EditSubscriber *subscriber); - virtual void unsubscribe(); /// Occurs when the subscriber has been switched off first - virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode - virtual CursorShape getCursor(int objectID); - int getPipetteRectSize() { return 8; } // TODO: make a GUI - EditSubscriber* getCurrSubscriber(); - virtual void getImageSize (int &w, int&h) =0; + virtual void subscribe(EditSubscriber *subscriber); + virtual void unsubscribe(); /// Occurs when the subscriber has been switched off first + virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode + virtual CursorShape getCursor(int objectID); + int getPipetteRectSize() + { + return 8; // TODO: make a GUI + } + EditSubscriber* getCurrSubscriber(); + virtual void getImageSize (int &w, int&h) = 0; }; #endif diff --git a/rtgui/editedstate.h b/rtgui/editedstate.h index 003c2f29f..db416c531 100644 --- a/rtgui/editedstate.h +++ b/rtgui/editedstate.h @@ -7,7 +7,7 @@ * 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 @@ -19,7 +19,7 @@ #ifndef _EDITEDSTATE_ #define _EDITEDSTATE_ -enum EditedState { UnEdited=0, Edited=1, Irrelevant=2 }; +enum EditedState { UnEdited = 0, Edited = 1, Irrelevant = 2 }; #endif diff --git a/rtgui/editenums.h b/rtgui/editenums.h index e92114b58..32b114643 100644 --- a/rtgui/editenums.h +++ b/rtgui/editenums.h @@ -7,7 +7,7 @@ * 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 @@ -20,8 +20,10 @@ #define _EDITENUMS_ enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SResizeTL, SResizeTR, SResizeBL, SResizeBR, - SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, SEditDrag}; + SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, SEditDrag + }; enum CursorArea {CropWinButtons, CropToolBar, CropImage, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft, - CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved}; + CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved + }; #endif diff --git a/rtgui/editid.h b/rtgui/editid.h index 35308f5fa..6bc808c87 100644 --- a/rtgui/editid.h +++ b/rtgui/editid.h @@ -22,50 +22,50 @@ /// @brief List of pipette editing operation enum EditUniqueID { - EUID_None, /// special value (default) + EUID_None, /// special value (default) + + EUID_ToneCurve1, + EUID_ToneCurve2, + EUID_Lab_LCurve, + EUID_Lab_CCurve, + EUID_Lab_LCCurve, + EUID_Lab_CLCurve, + EUID_Lab_LHCurve, + EUID_Lab_CHCurve, + EUID_Lab_HHCurve, + EUID_Lab_aCurve, + EUID_Lab_bCurve, + EUID_RGB_R, + EUID_RGB_G, + EUID_RGB_B, + EUID_HSV_H, + EUID_HSV_S, + EUID_HSV_V, + EUID_BlackWhiteLuminance, + EUID_BlackWhiteBeforeCurve, + EUID_BlackWhiteAfterCurve, + EUID_WW_HHCurve, - EUID_ToneCurve1, - EUID_ToneCurve2, - EUID_Lab_LCurve, - EUID_Lab_CCurve, - EUID_Lab_LCCurve, - EUID_Lab_CLCurve, - EUID_Lab_LHCurve, - EUID_Lab_CHCurve, - EUID_Lab_HHCurve, - EUID_Lab_aCurve, - EUID_Lab_bCurve, - EUID_RGB_R, - EUID_RGB_G, - EUID_RGB_B, - EUID_HSV_H, - EUID_HSV_S, - EUID_HSV_V, - EUID_BlackWhiteLuminance, - EUID_BlackWhiteBeforeCurve, - EUID_BlackWhiteAfterCurve, - EUID_WW_HHCurve, - }; /// @brief Editing mechanisms // TODO: Look out if it has to be a bitfield to allow both mechanisms at a time enum EditType { - ET_PIPETTE, /// Will trigger dedicated methods; can have a geometry list to be displayed, but without "mouse over" capabilities - ET_OBJECTS /// The objects are geometrical widgets with "mouse over" capabilities + ET_PIPETTE, /// Will trigger dedicated methods; can have a geometry list to be displayed, but without "mouse over" capabilities + ET_OBJECTS /// The objects are geometrical widgets with "mouse over" capabilities }; /// @brief Buffer type for ET_PIPETTE type editing enum BufferType { - BT_IMAGEFLOAT, - BT_LABIMAGE, - BT_SINGLEPLANE_FLOAT + BT_IMAGEFLOAT, + BT_LABIMAGE, + BT_SINGLEPLANE_FLOAT }; /// @brief Number of object to be handled (for optimization purpose) enum ObjectMode { - OM_255, /// less or equal than 255 objects - OM_65535 /// less or equal than 65535 objects + OM_255, /// less or equal than 255 objects + OM_65535 /// less or equal than 65535 objects }; #endif diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index ed513c74e..7a234acb3 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -31,14 +31,15 @@ using namespace rtengine::procparams; -EditorPanel::EditorPanel (FilePanel* filePanel) - : realized(false), iHistoryShow(NULL), iHistoryHide(NULL), iTopPanel_1_Show(NULL), iTopPanel_1_Hide(NULL), iRightPanel_1_Show(NULL), iRightPanel_1_Hide(NULL), iBeforeLockON(NULL),iBeforeLockOFF(NULL), beforePreviewHandler(NULL), beforeIarea(NULL), beforeBox(NULL), afterBox(NULL), afterHeaderBox(NULL), parent(NULL), openThm(NULL), ipc(NULL), beforeIpc(NULL), isProcessing(false), catalogPane(NULL) { +EditorPanel::EditorPanel (FilePanel* filePanel) + : realized(false), iHistoryShow(NULL), iHistoryHide(NULL), iTopPanel_1_Show(NULL), iTopPanel_1_Hide(NULL), iRightPanel_1_Show(NULL), iRightPanel_1_Hide(NULL), iBeforeLockON(NULL), iBeforeLockOFF(NULL), beforePreviewHandler(NULL), beforeIarea(NULL), beforeBox(NULL), afterBox(NULL), afterHeaderBox(NULL), parent(NULL), openThm(NULL), ipc(NULL), beforeIpc(NULL), isProcessing(false), catalogPane(NULL) +{ epih = new EditorPanelIdleHelper; epih->epanel = this; epih->destroyed = false; epih->pending = 0; - //rtengine::befaf=true; + //rtengine::befaf=true; processingStartedTime = 0; firstProcessingDone = false; @@ -50,7 +51,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) // build left side panel leftbox = new Gtk::VBox (); leftbox->set_border_width (2); - leftbox->set_size_request(100,250); + leftbox->set_size_request(100, 250); histogramPanel = NULL; @@ -100,14 +101,15 @@ EditorPanel::EditorPanel (FilePanel* filePanel) hidehp->set_relief(Gtk::RELIEF_NONE); hidehp->set_active (options.showHistory); hidehp->set_tooltip_markup (M("MAIN_TOOLTIP_HIDEHP")); - if (options.showHistory){ + + if (options.showHistory) { hidehp->set_image (*iHistoryHide); - } - else { + } else { hidehp->set_image (*iHistoryShow); } tbTopPanel_1 = NULL; + if (!simpleEditor && filePanel) { tbTopPanel_1 = new Gtk::ToggleButton (); iTopPanel_1_Show = new RTImage ("panel-to-bottom.png"); @@ -148,6 +150,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) Gtk::VSeparator* vsep1 = Gtk::manage (new Gtk::VSeparator ()); toolBarPanel->pack_end (*vsep1, Gtk::PACK_SHRINK, 2); } + toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 2); toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 2); toolBarPanel->pack_end (*iareapanel->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0); @@ -161,12 +164,12 @@ EditorPanel::EditorPanel (FilePanel* filePanel) beforeAfterBox = Gtk::manage (new Gtk::HBox()); beforeAfterBox->pack_start (*afterBox); - editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK,0); + editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK, 0); editbox->pack_start (*beforeAfterBox); // build right side panel vboxright = new Gtk::VBox (false, 0); - vboxright->set_size_request(100,250); + vboxright->set_size_request(100, 250); vboxright->set_border_width (2); @@ -194,8 +197,11 @@ EditorPanel::EditorPanel (FilePanel* filePanel) sendtogimp->set_tooltip_markup(M("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP")); iops->pack_start (*saveimgas, Gtk::PACK_SHRINK); - if(!simpleEditor) - iops->pack_start (*queueimg, Gtk::PACK_SHRINK); + + if(!simpleEditor) { + iops->pack_start (*queueimg, Gtk::PACK_SHRINK); + } + iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK); // Status box @@ -208,9 +214,9 @@ EditorPanel::EditorPanel (FilePanel* filePanel) iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 2); // tbRightPanel_1 - iops->pack_end (*tbRightPanel_1, Gtk::PACK_SHRINK,0); + iops->pack_end (*tbRightPanel_1, Gtk::PACK_SHRINK, 0); - // ShowHideSidePanels + // ShowHideSidePanels tbShowHideSidePanels = new Gtk::ToggleButton (); iShowHideSidePanels = new RTImage ("crossed-arrows-out.png"); iShowHideSidePanels_exit = new RTImage ("crossed-arrows-in.png"); @@ -218,43 +224,44 @@ EditorPanel::EditorPanel (FilePanel* filePanel) tbShowHideSidePanels->set_active (false); tbShowHideSidePanels->set_tooltip_markup (M("MAIN_BUTTON_SHOWHIDESIDEPANELS_TOOLTIP")); tbShowHideSidePanels->set_image (*iShowHideSidePanels); - iops->pack_end (*tbShowHideSidePanels, Gtk::PACK_SHRINK,0); - iops->pack_end (*vsepz2, Gtk::PACK_SHRINK,1); + iops->pack_end (*tbShowHideSidePanels, Gtk::PACK_SHRINK, 0); + iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 1); // Zoom panel iops->pack_end (*iareapanel->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1); iops->pack_end (*vsepz3, Gtk::PACK_SHRINK, 2); - navPrev = navNext = navSync = NULL; - if (!simpleEditor && !options.tabbedUI){ - // Navigation buttons - Gtk::Image *navPrevImage = Gtk::manage (new RTImage ("nav-prev.png")); - navPrevImage->set_padding(0,0); - navPrev = Gtk::manage (new Gtk::Button ()); - navPrev->add(*navPrevImage); - navPrev->set_relief(Gtk::RELIEF_NONE); - navPrev->set_tooltip_markup(M("MAIN_BUTTON_NAVPREV_TOOLTIP")); - - Gtk::Image *navNextImage = Gtk::manage (new RTImage ("nav-next.png")); - navNextImage->set_padding(0,0); - navNext = Gtk::manage (new Gtk::Button ()); - navNext->add(*navNextImage); - navNext->set_relief(Gtk::RELIEF_NONE); - navNext->set_tooltip_markup(M("MAIN_BUTTON_NAVNEXT_TOOLTIP")); + navPrev = navNext = navSync = NULL; - Gtk::Image *navSyncImage = Gtk::manage (new RTImage ("nav-sync.png")); - navSyncImage->set_padding(0,0); - navSync = Gtk::manage (new Gtk::Button ()); - navSync->add(*navSyncImage); - navSync->set_relief(Gtk::RELIEF_NONE); - navSync->set_tooltip_markup(M("MAIN_BUTTON_NAVSYNC_TOOLTIP")); - - iops->pack_end (*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_SHRINK, 0); + if (!simpleEditor && !options.tabbedUI) { + // Navigation buttons + Gtk::Image *navPrevImage = Gtk::manage (new RTImage ("nav-prev.png")); + navPrevImage->set_padding(0, 0); + navPrev = Gtk::manage (new Gtk::Button ()); + navPrev->add(*navPrevImage); + navPrev->set_relief(Gtk::RELIEF_NONE); + navPrev->set_tooltip_markup(M("MAIN_BUTTON_NAVPREV_TOOLTIP")); + + Gtk::Image *navNextImage = Gtk::manage (new RTImage ("nav-next.png")); + navNextImage->set_padding(0, 0); + navNext = Gtk::manage (new Gtk::Button ()); + navNext->add(*navNextImage); + navNext->set_relief(Gtk::RELIEF_NONE); + navNext->set_tooltip_markup(M("MAIN_BUTTON_NAVNEXT_TOOLTIP")); + + Gtk::Image *navSyncImage = Gtk::manage (new RTImage ("nav-sync.png")); + navSyncImage->set_padding(0, 0); + navSync = Gtk::manage (new Gtk::Button ()); + navSync->add(*navSyncImage); + navSync->set_relief(Gtk::RELIEF_NONE); + navSync->set_tooltip_markup(M("MAIN_BUTTON_NAVSYNC_TOOLTIP")); + + iops->pack_end (*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_SHRINK, 0); iops->pack_end (*navNext, Gtk::PACK_SHRINK, 0); iops->pack_end (*navSync, Gtk::PACK_SHRINK, 0); iops->pack_end (*navPrev, Gtk::PACK_SHRINK, 0); } - + editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0); editbox->pack_start (*iops, Gtk::PACK_SHRINK, 0); editbox->show_all (); @@ -264,25 +271,27 @@ EditorPanel::EditorPanel (FilePanel* filePanel) hpanedr = Gtk::manage (new Gtk::HPaned()); leftbox->reference (); vboxright->reference (); + if (options.showHistory) { - hpanedl->pack1(*leftbox, false, true); - hpanedl->set_position (options.historyPanelWidth); + hpanedl->pack1(*leftbox, false, true); + hpanedl->set_position (options.historyPanelWidth); } - + Gtk::VPaned * viewpaned = Gtk::manage (new Gtk::VPaned()); fPanel = filePanel; - if(filePanel) - { + + if(filePanel) { catalogPane = new Gtk::Paned(); viewpaned->pack1(*catalogPane, false, true); } + viewpaned->pack2(*editbox, true, true); - Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ()); + Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ()); vbfr->add (*viewpaned); - vbfr->set_size_request(100,250); + vbfr->set_size_request(100, 250); hpanedl->pack2(*vbfr, true, true); hpanedr->pack1(*hpanedl, true, true); @@ -295,15 +304,15 @@ EditorPanel::EditorPanel (FilePanel* filePanel) updateHistogramPosition (0, options.histogramPosition); show_all (); -/* - // save as dialog - if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) - saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); - else - saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); + /* + // save as dialog + if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) + saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); + else + saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); - saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); -*/ + saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); + */ // connect listeners profilep->setProfileChangeListener (tpc); history->setProfileChangeListener (tpc); @@ -327,18 +336,28 @@ EditorPanel::EditorPanel (FilePanel* filePanel) saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) ); queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) ); sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) ); - if(navPrev) - navPrev->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::openPreviousEditorImage) ); - if(navNext) - navNext->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::openNextEditorImage) ); - if(navSync) - navSync->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::syncFileBrowser) ); + + if(navPrev) { + navPrev->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::openPreviousEditorImage) ); + } + + if(navNext) { + navNext->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::openNextEditorImage) ); + } + + if(navSync) { + navSync->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::syncFileBrowser) ); + } + ShowHideSidePanelsconn = tbShowHideSidePanels->signal_toggled().connect ( sigc::mem_fun(*this, &EditorPanel::toggleSidePanels), true); - if (tbTopPanel_1) - tbTopPanel_1->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::tbTopPanel_1_toggled) ); + + if (tbTopPanel_1) { + tbTopPanel_1->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::tbTopPanel_1_toggled) ); + } } -EditorPanel::~EditorPanel () { +EditorPanel::~EditorPanel () +{ history->setHistoryBeforeLineListener (NULL); // the order is important! @@ -346,96 +365,135 @@ EditorPanel::~EditorPanel () { delete iareapanel; iareapanel = NULL; - if (beforeIpc) + if (beforeIpc) { beforeIpc->stopProcessing (); + } delete beforeIarea; beforeIarea = NULL; - if (beforeIpc){ + if (beforeIpc) { beforeIpc->setPreviewImageListener (NULL); - } + } + delete beforePreviewHandler; beforePreviewHandler = NULL; - if (beforeIpc) + + if (beforeIpc) { rtengine::StagedImageProcessor::destroy (beforeIpc); + } + beforeIpc = NULL; close (); - if (epih->pending) + if (epih->pending) { epih->destroyed = true; - else + } else { delete epih; + } delete tpc; delete ppframe; delete leftbox; delete vboxright; + //delete saveAsDialog; - if(catalogPane) + if(catalogPane) { delete catalogPane; + } - if (iTopPanel_1_Show) delete iTopPanel_1_Show; - if (iTopPanel_1_Hide) delete iTopPanel_1_Hide; - if (iHistoryShow) - delete iHistoryShow; - if (iHistoryHide) - delete iHistoryHide; - if(iBeforeLockON) + if (iTopPanel_1_Show) { + delete iTopPanel_1_Show; + } + + if (iTopPanel_1_Hide) { + delete iTopPanel_1_Hide; + } + + if (iHistoryShow) { + delete iHistoryShow; + } + + if (iHistoryHide) { + delete iHistoryHide; + } + + if(iBeforeLockON) { delete iBeforeLockON; - if(iBeforeLockOFF) + } + + if(iBeforeLockOFF) { delete iBeforeLockOFF; - if(iRightPanel_1_Show) + } + + if(iRightPanel_1_Show) { delete iRightPanel_1_Show; - if(iRightPanel_1_Hide) + } + + if(iRightPanel_1_Hide) { delete iRightPanel_1_Hide; + } } -void EditorPanel::leftPaneButtonReleased(GdkEventButton *event) { - if (event->button == 1) { - // Button 1 released : it's a resize - options.historyPanelWidth = hpanedl->get_position(); - } - /*else if (event->button == 3) { - }*/ +void EditorPanel::leftPaneButtonReleased(GdkEventButton *event) +{ + if (event->button == 1) { + // Button 1 released : it's a resize + options.historyPanelWidth = hpanedl->get_position(); + } + + /*else if (event->button == 3) { + }*/ } -void EditorPanel::rightPaneButtonReleased(GdkEventButton *event) { - if (event->button == 1) { - int winW, winH; - parent->get_size(winW, winH); - // Button 1 released : it's a resize - options.toolPanelWidth = winW - hpanedr->get_position(); - } - /*else if (event->button == 3) { - }*/ +void EditorPanel::rightPaneButtonReleased(GdkEventButton *event) +{ + if (event->button == 1) { + int winW, winH; + parent->get_size(winW, winH); + // Button 1 released : it's a resize + options.toolPanelWidth = winW - hpanedr->get_position(); + } + + /*else if (event->button == 3) { + }*/ } -void EditorPanel::writeOptions() { - if (profilep) - profilep->writeOptions(); - if (tpc) - tpc->writeOptions(); +void EditorPanel::writeOptions() +{ + if (profilep) { + profilep->writeOptions(); + } + + if (tpc) { + tpc->writeOptions(); + } } -void EditorPanel::showTopPanel(bool show) { - if (tbTopPanel_1->get_active() != show) - tbTopPanel_1->set_active(show); +void EditorPanel::showTopPanel(bool show) +{ + if (tbTopPanel_1->get_active() != show) { + tbTopPanel_1->set_active(show); + } } -void EditorPanel::setAspect () { - int winW, winH; - parent->get_size(winW, winH); - hpanedl->set_position(options.historyPanelWidth); - hpanedr->set_position(winW - options.toolPanelWidth); - // initialize components - if (info->get_active() != options.showInfo) - info->set_active (options.showInfo); +void EditorPanel::setAspect () +{ + int winW, winH; + parent->get_size(winW, winH); + hpanedl->set_position(options.historyPanelWidth); + hpanedr->set_position(winW - options.toolPanelWidth); + + // initialize components + if (info->get_active() != options.showInfo) { + info->set_active (options.showInfo); + } } -void EditorPanel::on_realize () { +void EditorPanel::on_realize () +{ realized = true; Gtk::VBox::on_realize (); // This line is needed to avoid autoexpansion of the window :-/ @@ -443,17 +501,18 @@ void EditorPanel::on_realize () { tpc->updateToolState(); } -void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { +void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) +{ close(); - isProcessing=true; // prevents closing-on-init + isProcessing = true; // prevents closing-on-init // initialize everything openThm = tmb; openThm->increaseRef (); - fname=openThm->getFileName(); + fname = openThm->getFileName(); lastSaveAsFileName = removeExtension (Glib::path_get_basename (fname)); previewHandler = new PreviewHandler (); @@ -464,7 +523,7 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { ipc->setProgressListener (this); ipc->setPreviewImageListener (previewHandler); ipc->setPreviewScale (10); // Important - tpc->initImage (ipc, tmb->getType()==FT_Raw); + tpc->initImage (ipc, tmb->getType() == FT_Raw); ipc->setHistogramListener (this); // iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen @@ -473,38 +532,36 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { navigator->previewWindow->setPreviewHandler (previewHandler); navigator->previewWindow->setImageArea (iareapanel->imageArea); - rtengine::ImageSource* is=isrc->getImageSource(); + rtengine::ImageSource* is = isrc->getImageSource(); is->setProgressListener( this ); // try to load the last saved parameters from the cache or from the paramfile file - ProcParams* ldprof = openThm->createProcParamsForUpdate(true,false); // will be freed by initProfile + ProcParams* ldprof = openThm->createProcParamsForUpdate(true, false); // will be freed by initProfile // initialize profile - Glib::ustring defProf = openThm->getType()==FT_Raw ? options.defProfRaw : options.defProfImg; + Glib::ustring defProf = openThm->getType() == FT_Raw ? options.defProfRaw : options.defProfImg; profilep->initProfile (defProf, ldprof); profilep->setInitialFileName (fname); openThm->addThumbnailListener (this); info_toggled (); - - if (beforeIarea) - { + + if (beforeIarea) { beforeAfterToggled(); beforeAfterToggled(); } // If in single tab mode, the main crop window is not constructed the very first time // since there was no resize event - if (iareapanel->imageArea->mainCropWindow) - { + if (iareapanel->imageArea->mainCropWindow) { iareapanel->imageArea->mainCropWindow->cropHandler.newImage(ipc, false); iareapanel->imageArea->mainCropWindow->initialImageArrived(); - // In single tab mode, the image is not always updated between switches - // normal redraw don't work, so this is the hard way - // Disabled this with Issue 2435 because it seems to work fine now + // In single tab mode, the image is not always updated between switches + // normal redraw don't work, so this is the hard way + // Disabled this with Issue 2435 because it seems to work fine now // if (!options.tabbedUI && iareapanel->imageArea->mainCropWindow->getZoomFitVal() == 1.0) { -// iareapanel->imageArea->mainCropWindow->cropHandler.update(); +// iareapanel->imageArea->mainCropWindow->cropHandler.update(); // } } else { Gtk::Allocation alloc; @@ -512,69 +569,81 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { } } -void EditorPanel::close () { - if (ipc) - { +void EditorPanel::close () +{ + if (ipc) { saveProfile (); // close image processor and the current thumbnail tpc->closeImage (); // this call stops image processing tpc->writeOptions (); - rtengine::ImageSource* is=isrc->getImageSource(); + rtengine::ImageSource* is = isrc->getImageSource(); is->setProgressListener( NULL ); if (ipc) { ipc->setPreviewImageListener (NULL); - } + } - if (beforeIpc){ + if (beforeIpc) { beforeIpc->setPreviewImageListener (NULL); - } - - delete previewHandler; - previewHandler= NULL; + } - if(iareapanel) - { + delete previewHandler; + previewHandler = NULL; + + if(iareapanel) { iareapanel->imageArea->setPreviewHandler (NULL); iareapanel->imageArea->setImProcCoordinator (NULL); } + rtengine::StagedImageProcessor::destroy (ipc); ipc = NULL; 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)) { - openThm->removeThumbnailListener (this); - openThm->decreaseRef (); + openThm->removeThumbnailListener (this); + openThm->decreaseRef (); } } } -void EditorPanel::saveProfile () { - if (!ipc || !openThm) return; +void EditorPanel::saveProfile () +{ + if (!ipc || !openThm) { + return; + } // If the file was deleted, do not generate ghost entries if (safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { - ProcParams params; - ipc->getParams (¶ms); + ProcParams params; + ipc->getParams (¶ms); // Will call updateCache, which will update both the cached and sidecar files if necessary openThm->setProcParams (params, NULL, EDITOR); -} + } } -Glib::ustring EditorPanel::getShortName () { - if (openThm) return Glib::path_get_basename (openThm->getFileName ()); - else return ""; +Glib::ustring EditorPanel::getShortName () +{ + if (openThm) { + return Glib::path_get_basename (openThm->getFileName ()); + } else { + return ""; + } } -Glib::ustring EditorPanel::getFileName () { - if (openThm) return openThm->getFileName (); - else return ""; +Glib::ustring EditorPanel::getFileName () +{ + if (openThm) { + return openThm->getFileName (); + } else { + return ""; + } } // TODO!!! -void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { +void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) +{ // if (ev!=EvPhotoLoaded) // saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); @@ -585,15 +654,18 @@ struct spsparams { EditorPanelIdleHelper* epih; }; -int setProgressStateUIThread (void* data) { +int setProgressStateUIThread (void* data) +{ spsparams* p = static_cast(data); if (p->epih->destroyed) { - if (p->epih->pending == 1) + if (p->epih->pending == 1) { delete p->epih; - else + } else { p->epih->pending--; + } + delete p; return 0; @@ -606,7 +678,8 @@ int setProgressStateUIThread (void* data) { return 0; } -void EditorPanel::setProgressState (bool inProcessing) { +void EditorPanel::setProgressState (bool inProcessing) +{ epih->pending++; @@ -624,81 +697,94 @@ struct spparams { int setprogressStrUI( void *p ) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected - spparams *s= static_cast(p); + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + spparams *s = static_cast(p); - if( ! s->str.empty() ) - s->pProgress->set_text( M(s->str) ); - if( s->val >=0 ){ - s->pProgress->set_fraction( s->val ); - if( s->val <1.0 ) - s->pProgress->modify_bg( Gtk::STATE_NORMAL,Gdk::Color("red") ); - else - s->pProgress->modify_bg( Gtk::STATE_NORMAL,Gdk::Color("grey") ); - } + if( ! s->str.empty() ) { + s->pProgress->set_text( M(s->str) ); + } - delete s; - return 0; + if( s->val >= 0 ) { + s->pProgress->set_fraction( s->val ); + + if( s->val < 1.0 ) { + s->pProgress->modify_bg( Gtk::STATE_NORMAL, Gdk::Color("red") ); + } else { + s->pProgress->modify_bg( Gtk::STATE_NORMAL, Gdk::Color("grey") ); + } + } + + delete s; + return 0; } void EditorPanel::setProgress (double p) { - spparams *s=new spparams; - s->val = p; - s->pProgress = progressLabel; - g_idle_add (setprogressStrUI, s); + spparams *s = new spparams; + s->val = p; + s->pProgress = progressLabel; + g_idle_add (setprogressStrUI, s); } void EditorPanel::setProgressStr (Glib::ustring str) { - spparams *s=new spparams; - s->str = str; - s->val = -1; - s->pProgress = progressLabel; - g_idle_add (setprogressStrUI, s); + spparams *s = new spparams; + s->str = str; + s->val = -1; + s->pProgress = progressLabel; + g_idle_add (setprogressStrUI, s); } // This is only called from the ThreadUI, so within the gtk thread -void EditorPanel::refreshProcessingState (bool inProcessingP) { - spparams *s=new spparams; +void EditorPanel::refreshProcessingState (bool inProcessingP) +{ + spparams *s = new spparams; s->pProgress = progressLabel; if (inProcessingP) { - if (processingStartedTime==0) processingStartedTime = ::time(NULL); + if (processingStartedTime == 0) { + processingStartedTime = ::time(NULL); + } - s->str = "PROGRESSBAR_PROCESSING"; - s->val = 0.0; + s->str = "PROGRESSBAR_PROCESSING"; + s->val = 0.0; } else { - // Set proc params of thumbnail. It saves it into the cache and updates the file browser. - if (ipc && openThm && tpc->getChangedState()) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); + // Set proc params of thumbnail. It saves it into the cache and updates the file browser. + if (ipc && openThm && tpc->getChangedState()) { + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); openThm->setProcParams (pparams, NULL, EDITOR, false); - } + } - // Ring a sound if it was a long event - if (processingStartedTime!=0) { - time_t curTime= ::time(NULL); - if (::difftime(curTime, processingStartedTime) > options.sndLngEditProcDoneSecs) + // Ring a sound if it was a long event + if (processingStartedTime != 0) { + time_t curTime = ::time(NULL); + + if (::difftime(curTime, processingStartedTime) > options.sndLngEditProcDoneSecs) { SoundManager::playSoundAsync(options.sndLngEditProcDone); + } processingStartedTime = 0; } - // Set progress bar "done" - s->str = "PROGRESSBAR_READY"; - s->val = 1.0; + // Set progress bar "done" + s->str = "PROGRESSBAR_READY"; + s->val = 1.0; #ifdef WIN32 - // Maybe accessing "parent", which is a Gtk object, can justify to get the Gtk lock... - if (!firstProcessingDone && static_cast(parent)->getIsFullscreen()) { parent->fullscreen(); } + + // Maybe accessing "parent", which is a Gtk object, can justify to get the Gtk lock... + if (!firstProcessingDone && static_cast(parent)->getIsFullscreen()) { + parent->fullscreen(); + } + #endif firstProcessingDone = true; -} + } - isProcessing=inProcessingP; + isProcessing = inProcessingP; - setprogressStrUI(s); + setprogressStrUI(s); } struct errparams { @@ -707,28 +793,32 @@ struct errparams { EditorPanelIdleHelper* epih; }; -void EditorPanel::displayError (Glib::ustring title, Glib::ustring descr) { - GtkWidget* msgd = gtk_message_dialog_new_with_markup (NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", - descr.data()); - gtk_window_set_title((GtkWindow*)msgd, title.data()); - g_signal_connect_swapped (msgd, "response", - G_CALLBACK (gtk_widget_destroy), - msgd); - gtk_widget_show_all (msgd); +void EditorPanel::displayError (Glib::ustring title, Glib::ustring descr) +{ + GtkWidget* msgd = gtk_message_dialog_new_with_markup (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", + descr.data()); + gtk_window_set_title((GtkWindow*)msgd, title.data()); + g_signal_connect_swapped (msgd, "response", + G_CALLBACK (gtk_widget_destroy), + msgd); + gtk_widget_show_all (msgd); } -int disperrorUI (void* data) { +int disperrorUI (void* data) +{ errparams* p = static_cast(data); if (p->epih->destroyed) { - if (p->epih->pending == 1) + if (p->epih->pending == 1) { delete p->epih; - else + } else { p->epih->pending--; + } + delete p; return 0; @@ -741,7 +831,8 @@ int disperrorUI (void* data) { return 0; } -void EditorPanel::error (Glib::ustring title, Glib::ustring descr) { +void EditorPanel::error (Glib::ustring title, Glib::ustring descr) +{ epih->pending++; errparams* p = new errparams; @@ -751,7 +842,8 @@ void EditorPanel::error (Glib::ustring title, Glib::ustring descr) { g_idle_add (disperrorUI, p); } -void EditorPanel::info_toggled () { +void EditorPanel::info_toggled () +{ Glib::ustring infoString; Glib::ustring infoString1; //1-st line @@ -760,121 +852,134 @@ void EditorPanel::info_toggled () { Glib::ustring infoString4; //4-th line Glib::ustring expcomp; - if (!ipc || !openThm) return; + if (!ipc || !openThm) { + return; + } + const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); - if (idata && idata->hasExif()){ - infoString1 = Glib::ustring::compose ("%1 + %2", - Glib::ustring(idata->getMake()+" "+idata->getModel()), - Glib::ustring(idata->getLens())); + + if (idata && idata->hasExif()) { + infoString1 = Glib::ustring::compose ("%1 + %2", + Glib::ustring(idata->getMake() + " " + idata->getModel()), + Glib::ustring(idata->getLens())); infoString2 = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", - Glib::ustring(idata->apertureToString(idata->getFNumber())), - Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), - M("QINFO_ISO"), idata->getISOSpeed(), - Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), idata->getFocalLen())); + Glib::ustring(idata->apertureToString(idata->getFNumber())), + Glib::ustring(idata->shutterToString(idata->getShutterSpeed())), + M("QINFO_ISO"), idata->getISOSpeed(), + Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), idata->getFocalLen())); - expcomp = Glib::ustring(idata->expcompToString(idata->getExpComp(),true)); // maskZeroexpcomp - if (expcomp!=""){ - infoString2 = Glib::ustring::compose("%1 %2EV", - infoString2, - expcomp /*Glib::ustring(idata->expcompToString(idata->getExpComp()))*/); + expcomp = Glib::ustring(idata->expcompToString(idata->getExpComp(), true)); // maskZeroexpcomp + + if (expcomp != "") { + infoString2 = Glib::ustring::compose("%1 %2EV", + infoString2, + expcomp /*Glib::ustring(idata->expcompToString(idata->getExpComp()))*/); } infoString3 = Glib::ustring::compose ("%1%2", - escapeHtmlChars(Glib::path_get_dirname(openThm->getFileName())) + G_DIR_SEPARATOR_S, - escapeHtmlChars(Glib::path_get_basename(openThm->getFileName())) ); + escapeHtmlChars(Glib::path_get_dirname(openThm->getFileName())) + G_DIR_SEPARATOR_S, + escapeHtmlChars(Glib::path_get_basename(openThm->getFileName())) ); - int ww= ipc->getFullWidth(); - int hh= ipc->getFullHeight(); + int ww = ipc->getFullWidth(); + int hh = ipc->getFullHeight(); //megapixels - infoString4 = Glib::ustring::compose ("%1 MP (%2x%3)", Glib::ustring::format(std::setw(4), std::fixed, std::setprecision(1), (float)ww*hh/1000000), ww, hh); + infoString4 = Glib::ustring::compose ("%1 MP (%2x%3)", Glib::ustring::format(std::setw(4), std::fixed, std::setprecision(1), (float)ww * hh / 1000000), ww, hh); - infoString = Glib::ustring::compose ("%1\n%2\n%3\n%4",infoString1, infoString2, infoString3, infoString4); - } - else + infoString = Glib::ustring::compose ("%1\n%2\n%3\n%4", infoString1, infoString2, infoString3, infoString4); + } else { infoString = M("QINFO_NOEXIF"); + } iareapanel->imageArea->setInfoText (infoString); iareapanel->imageArea->infoEnabled (info->get_active ()); } -void EditorPanel::hideHistoryActivated () { +void EditorPanel::hideHistoryActivated () +{ removeIfThere (hpanedl, leftbox, false); - if (hidehp->get_active()) + + if (hidehp->get_active()) { hpanedl->pack1 (*leftbox, false, true); + } + options.showHistory = hidehp->get_active(); - if (options.showHistory){ - hidehp->set_image (*iHistoryHide); - } - else { - hidehp->set_image (*iHistoryShow); + if (options.showHistory) { + hidehp->set_image (*iHistoryHide); + } else { + hidehp->set_image (*iHistoryShow); } tbShowHideSidePanels_managestate(); } -void EditorPanel::tbRightPanel_1_toggled () { -/* - removeIfThere (hpanedr, vboxright, false); - if (tbRightPanel_1->get_active()){ - hpanedr->pack2(*vboxright, false, true); - tbRightPanel_1->set_image (*iRightPanel_1_Hide); +void EditorPanel::tbRightPanel_1_toggled () +{ + /* + removeIfThere (hpanedr, vboxright, false); + if (tbRightPanel_1->get_active()){ + hpanedr->pack2(*vboxright, false, true); + tbRightPanel_1->set_image (*iRightPanel_1_Hide); + } + else { + tbRightPanel_1->set_image (*iRightPanel_1_Show); + } + tbShowHideSidePanels_managestate(); + */ + if (vboxright) { + if (tbRightPanel_1->get_active()) { + vboxright->show(); + tbRightPanel_1->set_image (*iRightPanel_1_Hide); + } else { + vboxright->hide(); + tbRightPanel_1->set_image (*iRightPanel_1_Show); + } + + tbShowHideSidePanels_managestate(); } - else { - tbRightPanel_1->set_image (*iRightPanel_1_Show); - } - tbShowHideSidePanels_managestate(); - */ - if (vboxright){ - if (tbRightPanel_1->get_active()){ - vboxright->show(); - tbRightPanel_1->set_image (*iRightPanel_1_Hide); - } - else{ - vboxright->hide(); - tbRightPanel_1->set_image (*iRightPanel_1_Show); - } - tbShowHideSidePanels_managestate(); - } } -void EditorPanel::tbTopPanel_1_visible (bool visible){ - if (!tbTopPanel_1) - return; +void EditorPanel::tbTopPanel_1_visible (bool visible) +{ + if (!tbTopPanel_1) { + return; + } - if (visible) - tbTopPanel_1->show(); - else - tbTopPanel_1->hide(); + if (visible) { + tbTopPanel_1->show(); + } else { + tbTopPanel_1->hide(); + } } -void EditorPanel::tbTopPanel_1_toggled () { +void EditorPanel::tbTopPanel_1_toggled () +{ - if (catalogPane){ // catalogPane does not exist in multitab mode + if (catalogPane) { // catalogPane does not exist in multitab mode - if (tbTopPanel_1->get_active()){ - catalogPane->show(); - tbTopPanel_1->set_image (*iTopPanel_1_Hide); - options.editorFilmStripOpened = true; - } - else { - catalogPane->hide(); - tbTopPanel_1->set_image (*iTopPanel_1_Show); - options.editorFilmStripOpened = false; - } + if (tbTopPanel_1->get_active()) { + catalogPane->show(); + tbTopPanel_1->set_image (*iTopPanel_1_Hide); + options.editorFilmStripOpened = true; + } else { + catalogPane->hide(); + tbTopPanel_1->set_image (*iTopPanel_1_Show); + options.editorFilmStripOpened = false; + } - tbShowHideSidePanels_managestate(); - } + tbShowHideSidePanels_managestate(); + } } /* * WARNING: Take care of the simpleEditor value when adding or modifying shortcut keys, * since handleShortcutKey is now also triggered in simple editor mode */ -bool EditorPanel::handleShortcutKey (GdkEventKey* event) { +bool EditorPanel::handleShortcutKey (GdkEventKey* event) +{ bool ctrl = event->state & GDK_CONTROL_MASK; bool shift = event->state & GDK_SHIFT_MASK; @@ -887,207 +992,262 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { // Editor Layout switch(event->keyval) { - case GDK_L: - if (tbTopPanel_1) - tbTopPanel_1->set_active (!tbTopPanel_1->get_active()); // toggle top panel - if (ctrl) hidehp->set_active (!hidehp->get_active()); // toggle History (left panel) - if (alt) tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel - return true; - break; - case GDK_l: - if (!shift && !alt /*&& !ctrl*/){ - hidehp->set_active (!hidehp->get_active()); // toggle History (left panel) - return true; - } - if (alt && !ctrl){ // toggle right panel - tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); - return true; - } - if (alt && ctrl){ // toggle left and right panels - hidehp->set_active (!hidehp->get_active()); - tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); - return true; - } - break; - case GDK_m: // Maximize preview panel: hide top AND right AND history panels - if (!ctrl && !alt) { - toggleSidePanels(); - return true; - } - break; - case GDK_M: // Maximize preview panel: hide top AND right AND history panels AND (fit image preview) - if (!ctrl && !alt) { - toggleSidePanelsZoomFit(); - return true; - } - break; + case GDK_L: + if (tbTopPanel_1) { + tbTopPanel_1->set_active (!tbTopPanel_1->get_active()); // toggle top panel + } + + if (ctrl) { + hidehp->set_active (!hidehp->get_active()); // toggle History (left panel) + } + + if (alt) { + tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel + } + + return true; + break; + + case GDK_l: + if (!shift && !alt /*&& !ctrl*/) { + hidehp->set_active (!hidehp->get_active()); // toggle History (left panel) + return true; + } + + if (alt && !ctrl) { // toggle right panel + tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); + return true; + } + + if (alt && ctrl) { // toggle left and right panels + hidehp->set_active (!hidehp->get_active()); + tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); + return true; + } + + break; + + case GDK_m: // Maximize preview panel: hide top AND right AND history panels + if (!ctrl && !alt) { + toggleSidePanels(); + return true; + } + + break; + + case GDK_M: // Maximize preview panel: hide top AND right AND history panels AND (fit image preview) + if (!ctrl && !alt) { + toggleSidePanelsZoomFit(); + return true; + } + + break; } + #ifdef __WIN32__ + if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x39 ) { - iareapanel->imageArea->previewModePanel->togglebackColor(); - return true; + iareapanel->imageArea->previewModePanel->togglebackColor(); + return true; } + #else + if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x12 ) { - iareapanel->imageArea->previewModePanel->togglebackColor(); - return true; + iareapanel->imageArea->previewModePanel->togglebackColor(); + return true; } -#endif - if (!alt){ - if (!ctrl) { - // Normal - switch(event->keyval) { - case GDK_bracketright: - tpc->coarse->rotateRight(); - return true; - case GDK_bracketleft: - tpc->coarse->rotateLeft(); - return true; - case GDK_i: - case GDK_I: - info->set_active (!info->get_active()); - return true; - case GDK_B: - beforeAfter->set_active (!beforeAfter->get_active()); - return true; - case GDK_plus: - case GDK_equal: - case GDK_KP_Add: - iareapanel->imageArea->zoomPanel->zoomInClicked(); - return true; - case GDK_minus: - case GDK_underscore: - case GDK_KP_Subtract: - iareapanel->imageArea->zoomPanel->zoomOutClicked(); - return true; - case GDK_z://GDK_1 - iareapanel->imageArea->zoomPanel->zoom11Clicked(); - return true; -/* -#ifndef __WIN32__ - case GDK_9: // toggle background color of the preview - iareapanel->imageArea->previewModePanel->togglebackColor(); - return true; -#endif -*/ - case GDK_r: //preview mode Red - iareapanel->imageArea->previewModePanel->toggleR(); - return true; - case GDK_g: //preview mode Green - iareapanel->imageArea->previewModePanel->toggleG(); - return true; - case GDK_b: //preview mode Blue - iareapanel->imageArea->previewModePanel->toggleB(); - return true; - case GDK_v: //preview mode Luminosity - iareapanel->imageArea->previewModePanel->toggleL(); - return true; - case GDK_F: //preview mode Focus Mask - iareapanel->imageArea->previewModePanel->toggleFocusMask(); - return true; - case GDK_f: - iareapanel->imageArea->zoomPanel->zoomFitClicked(); - return true; - case GDK_less: - iareapanel->imageArea->indClippedPanel->toggleClipped(true); - return true; - case GDK_greater: - iareapanel->imageArea->indClippedPanel->toggleClipped(false); - return true; +#endif - case GDK_F5: - openThm->openDefaultViewer((event->state & GDK_SHIFT_MASK) ? 2 : 1); - return true; - case GDK_y: // synchronize filebrowser with image in Editor - if (!simpleEditor && fPanel && !fname.empty()){ - fPanel->fileCatalog->selectImage(fname, false); - return true; - } - break; // to avoid gcc complain - case GDK_x: // clear filters and synchronize filebrowser with image in Editor - if (!simpleEditor && fPanel && !fname.empty()){ - fPanel->fileCatalog->selectImage(fname, true); - return true; - } - break; // to avoid gcc complain - } - } - else { - // With control - switch (event->keyval) { - case GDK_S: - saveProfile(); - setProgressStr(M("PROGRESSBAR_PROCESSING_PROFILESAVED")); - return true; - case GDK_s: - saveAsPressed(); - return true; - case GDK_b: - if (!simpleEditor) - queueImgPressed(); - return true; - case GDK_e: - sendToGimpPressed(); - return true; - case GDK_z: - history->undo (); - return true; - case GDK_Z: - history->redo (); - return true; - case GDK_F5: - openThm->openDefaultViewer(3); - return true; - } - } //if (!ctrl) + if (!alt) { + if (!ctrl) { + // Normal + switch(event->keyval) { + case GDK_bracketright: + tpc->coarse->rotateRight(); + return true; + + case GDK_bracketleft: + tpc->coarse->rotateLeft(); + return true; + + case GDK_i: + case GDK_I: + info->set_active (!info->get_active()); + return true; + + case GDK_B: + beforeAfter->set_active (!beforeAfter->get_active()); + return true; + + case GDK_plus: + case GDK_equal: + case GDK_KP_Add: + iareapanel->imageArea->zoomPanel->zoomInClicked(); + return true; + + case GDK_minus: + case GDK_underscore: + case GDK_KP_Subtract: + iareapanel->imageArea->zoomPanel->zoomOutClicked(); + return true; + + case GDK_z://GDK_1 + iareapanel->imageArea->zoomPanel->zoom11Clicked(); + return true; + + /* + #ifndef __WIN32__ + case GDK_9: // toggle background color of the preview + iareapanel->imageArea->previewModePanel->togglebackColor(); + return true; + #endif + */ + case GDK_r: //preview mode Red + iareapanel->imageArea->previewModePanel->toggleR(); + return true; + + case GDK_g: //preview mode Green + iareapanel->imageArea->previewModePanel->toggleG(); + return true; + + case GDK_b: //preview mode Blue + iareapanel->imageArea->previewModePanel->toggleB(); + return true; + + case GDK_v: //preview mode Luminosity + iareapanel->imageArea->previewModePanel->toggleL(); + return true; + + case GDK_F: //preview mode Focus Mask + iareapanel->imageArea->previewModePanel->toggleFocusMask(); + return true; + + case GDK_f: + iareapanel->imageArea->zoomPanel->zoomFitClicked(); + return true; + + case GDK_less: + iareapanel->imageArea->indClippedPanel->toggleClipped(true); + return true; + + case GDK_greater: + iareapanel->imageArea->indClippedPanel->toggleClipped(false); + return true; + + case GDK_F5: + openThm->openDefaultViewer((event->state & GDK_SHIFT_MASK) ? 2 : 1); + return true; + + case GDK_y: // synchronize filebrowser with image in Editor + if (!simpleEditor && fPanel && !fname.empty()) { + fPanel->fileCatalog->selectImage(fname, false); + return true; + } + + break; // to avoid gcc complain + + case GDK_x: // clear filters and synchronize filebrowser with image in Editor + if (!simpleEditor && fPanel && !fname.empty()) { + fPanel->fileCatalog->selectImage(fname, true); + return true; + } + + break; // to avoid gcc complain + } + } else { + // With control + switch (event->keyval) { + case GDK_S: + saveProfile(); + setProgressStr(M("PROGRESSBAR_PROCESSING_PROFILESAVED")); + return true; + + case GDK_s: + saveAsPressed(); + return true; + + case GDK_b: + if (!simpleEditor) { + queueImgPressed(); + } + + return true; + + case GDK_e: + sendToGimpPressed(); + return true; + + case GDK_z: + history->undo (); + return true; + + case GDK_Z: + history->redo (); + return true; + + case GDK_F5: + openThm->openDefaultViewer(3); + return true; + } + } //if (!ctrl) } //if (!alt) - if (alt){ - switch (event->keyval) { - case GDK_s: - history->addBookmarkPressed (); - setProgressStr(M("PROGRESSBAR_SNAPSHOT_ADDED")); - return true; - case GDK_f: - iareapanel->imageArea->zoomPanel->zoomFitCropClicked(); - return true; - } - } - - if (shift){ - switch (event->keyval) { - case GDK_F3: // open Previous image from Editor's perspective - if (!simpleEditor && fPanel && !fname.empty()){ - EditorPanel::openPreviousEditorImage(); - return true; - } - break; // to avoid gcc complain - case GDK_F4: // open next image from Editor's perspective - if (!simpleEditor && fPanel && !fname.empty()){ - EditorPanel::openNextEditorImage(); - return true; - } - break; // to avoid gcc complain - } + if (alt) { + switch (event->keyval) { + case GDK_s: + history->addBookmarkPressed (); + setProgressStr(M("PROGRESSBAR_SNAPSHOT_ADDED")); + return true; + + case GDK_f: + iareapanel->imageArea->zoomPanel->zoomFitCropClicked(); + return true; + } } - if(tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey(event)) - return true; - if(tpc->handleShortcutKey(event)) - return true; + if (shift) { + switch (event->keyval) { + case GDK_F3: // open Previous image from Editor's perspective + if (!simpleEditor && fPanel && !fname.empty()) { + EditorPanel::openPreviousEditorImage(); + return true; + } - if (!simpleEditor && fPanel){ - if (fPanel->handleShortcutKey(event)) + break; // to avoid gcc complain + + case GDK_F4: // open next image from Editor's perspective + if (!simpleEditor && fPanel && !fname.empty()) { + EditorPanel::openNextEditorImage(); + return true; + } + + break; // to avoid gcc complain + } + } + + if(tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey(event)) { return true; } + if(tpc->handleShortcutKey(event)) { + return true; + } + + if (!simpleEditor && fPanel) { + if (fPanel->handleShortcutKey(event)) { + return true; + } + } + return false; } -void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) { +void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) +{ - if (whoChangedIt!=EDITOR) { + if (whoChangedIt != EDITOR) { PartialProfile pp(true); pp.set(true); *(pp.pparams) = openThm->getProcParams(); @@ -1096,78 +1256,86 @@ void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) { } } -bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf) { - rtengine::IImage16* img = pc->returnValue(); - delete pc; - if( img ) { - setProgressStr(M("GENERAL_SAVE")); setProgress(0.9f); +bool EditorPanel::idle_saveImage (ProgressConnector *pc, Glib::ustring fname, SaveFormat sf) +{ + rtengine::IImage16* img = pc->returnValue(); + delete pc; + + if( img ) { + setProgressStr(M("GENERAL_SAVE")); + setProgress(0.9f); ProgressConnector *ld = new ProgressConnector(); img->setSaveProgressListener (parent->getProgressListener()); - if (sf.format=="tif") + + if (sf.format == "tif") ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fname, sf.tiffBits, sf.tiffUncompressed), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fname, sf)); - else if (sf.format=="png") + sigc::bind(sigc::mem_fun(*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf)); + else if (sf.format == "png") ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fname, sf.pngCompression, sf.pngBits), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fname, sf)); - else if (sf.format=="jpg") + sigc::bind(sigc::mem_fun(*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf)); + else if (sf.format == "jpg") ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fname, sf.jpegQuality, sf.jpegSubSamp), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_imageSaved), ld, img, fname, sf)); + sigc::bind(sigc::mem_fun(*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf)); } else { - Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image processing\n"; - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); + Glib::ustring msg_ = Glib::ustring("") + fname + ": Error during image processing\n"; + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); saveimgas->set_sensitive(true); sendtogimp->set_sensitive(true); isProcessing = false; - } - rtengine::ImageSource* imgsrc = isrc->getImageSource (); + } + + rtengine::ImageSource* imgsrc = isrc->getImageSource (); imgsrc->setProgressListener(this); - return false; + return false; } -bool EditorPanel::idle_imageSaved(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring fname, SaveFormat sf){ - img->free (); +bool EditorPanel::idle_imageSaved(ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf) +{ + img->free (); - if (! pc->returnValue() ) { - openThm->imageDeveloped (); - // save processing parameters, if needed - if (sf.saveParams) { - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - // We keep the extension to avoid overwriting the profile when we have - // the same output filename with different extension - //pparams.save (removeExtension (fname) + ".out" + paramFileExtension); - pparams.save (fname + ".out" + paramFileExtension); - } - } else { - error(M("MAIN_MSG_CANNOTSAVE"), fname); + if (! pc->returnValue() ) { + openThm->imageDeveloped (); + + // save processing parameters, if needed + if (sf.saveParams) { + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + // We keep the extension to avoid overwriting the profile when we have + // the same output filename with different extension + //pparams.save (removeExtension (fname) + ".out" + paramFileExtension); + pparams.save (fname + ".out" + paramFileExtension); + } + } else { + error(M("MAIN_MSG_CANNOTSAVE"), fname); } saveimgas->set_sensitive(true); sendtogimp->set_sensitive(true); - parent->setProgressStr(""); - parent->setProgress(0.); + parent->setProgressStr(""); + parent->setProgress(0.); setProgressState(false); - delete pc; - SoundManager::playSoundAsync(options.sndBatchQueueDone); - isProcessing = false; + delete pc; + SoundManager::playSoundAsync(options.sndBatchQueueDone); + isProcessing = false; return false; } -BatchQueueEntry* EditorPanel::createBatchQueueEntry () { +BatchQueueEntry* EditorPanel::createBatchQueueEntry () +{ rtengine::procparams::ProcParams pparams; ipc->getParams (&pparams); //rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType()==FT_Raw, pparams); - int fullW=0, fullH=0; - isrc->getImageSource()->getFullSize(fullW, fullH, pparams.coarse.rotate==90 || pparams.coarse.rotate==270 ? TR_R90 : TR_NONE); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType() == FT_Raw, pparams); + int fullW = 0, fullH = 0; + isrc->getImageSource()->getFullSize(fullW, fullH, pparams.coarse.rotate == 90 || pparams.coarse.rotate == 270 ? TR_R90 : TR_NONE); int prevh = BatchQueue::calcMaxThumbnailHeight(); int prevw = int((size_t)fullW * (size_t)prevh / (size_t)fullH); return new BatchQueueEntry (job, pparams, openThm->getFileName(), prevw, prevh, openThm); @@ -1175,135 +1343,161 @@ BatchQueueEntry* EditorPanel::createBatchQueueEntry () { -void EditorPanel::saveAsPressed () { - if (!ipc || !openThm) return; - bool fnameOK = false; - Glib::ustring fnameOut; +void EditorPanel::saveAsPressed () +{ + if (!ipc || !openThm) { + return; + } - SaveAsDialog* saveAsDialog; - if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) - saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); - else - saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); + bool fnameOK = false; + Glib::ustring fnameOut; - saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); - saveAsDialog->setInitialFileName (lastSaveAsFileName); - saveAsDialog->setImagePath (fname); + SaveAsDialog* saveAsDialog; - do { - int result = saveAsDialog->run (); + if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) { + saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); + } else { + saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); + } - // The SaveAsDialog ensure that a filename has been specified - fnameOut = saveAsDialog->getFileName (); + saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); + saveAsDialog->setInitialFileName (lastSaveAsFileName); + saveAsDialog->setImagePath (fname); - options.lastSaveAsPath = saveAsDialog->getDirectory (); - options.saveAsDialogWidth = saveAsDialog->get_width (); - options.saveAsDialogHeight = saveAsDialog->get_height (); - options.autoSuffix = saveAsDialog->getAutoSuffix (); - options.saveMethodNum = saveAsDialog->getSaveMethodNum (); - lastSaveAsFileName = Glib::path_get_basename (removeExtension (fnameOut)); - SaveFormat sf = saveAsDialog->getFormat (); - options.saveFormat = sf; - options.forceFormatOpts = saveAsDialog->getForceFormatOpts (); + do { + int result = saveAsDialog->run (); - if (result != Gtk::RESPONSE_OK) - break; + // The SaveAsDialog ensure that a filename has been specified + fnameOut = saveAsDialog->getFileName (); - if (saveAsDialog->getImmediately ()) { - // separate filename and the path to the destination directory - Glib::ustring dstdir = Glib::path_get_dirname (fnameOut); - Glib::ustring dstfname = Glib::path_get_basename (removeExtension(fnameOut)); - Glib::ustring dstext = getExtension (fnameOut); + options.lastSaveAsPath = saveAsDialog->getDirectory (); + options.saveAsDialogWidth = saveAsDialog->get_width (); + options.saveAsDialogHeight = saveAsDialog->get_height (); + options.autoSuffix = saveAsDialog->getAutoSuffix (); + options.saveMethodNum = saveAsDialog->getSaveMethodNum (); + lastSaveAsFileName = Glib::path_get_basename (removeExtension (fnameOut)); + SaveFormat sf = saveAsDialog->getFormat (); + options.saveFormat = sf; + options.forceFormatOpts = saveAsDialog->getForceFormatOpts (); - if (saveAsDialog->getAutoSuffix()) { + if (result != Gtk::RESPONSE_OK) { + break; + } - Glib::ustring fnameTemp; - for (int tries=0; tries<100; tries++) { - if (tries==0) - fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), dstext); - else - fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, dstext); + if (saveAsDialog->getImmediately ()) { + // separate filename and the path to the destination directory + Glib::ustring dstdir = Glib::path_get_dirname (fnameOut); + Glib::ustring dstfname = Glib::path_get_basename (removeExtension(fnameOut)); + Glib::ustring dstext = getExtension (fnameOut); - if (!safe_file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { - fnameOut = fnameTemp; - fnameOK = true; - break; - } - } - } - // check if it exists - if (!fnameOK) { - fnameOK = confirmOverwrite (*saveAsDialog, fnameOut); - } + if (saveAsDialog->getAutoSuffix()) { - if (fnameOK) { - isProcessing = true; - // save image - rtengine::procparams::ProcParams pparams; - ipc->getParams (&pparams); - rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + Glib::ustring fnameTemp; - ProgressConnector *ld = new ProgressConnector(); - ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData, false ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_saveImage ),ld,fnameOut,sf )); - saveimgas->set_sensitive(false); - sendtogimp->set_sensitive(false); - } - } - else { - BatchQueueEntry* bqe = createBatchQueueEntry (); - bqe->outFileName = fnameOut; - bqe->saveFormat = saveAsDialog->getFormat (); - bqe->forceFormatOpts = saveAsDialog->getForceFormatOpts (); - parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); - fnameOK = true; - } - // ask parent to redraw file browser - // ... or does it automatically when the tab is switched to it - } while (!fnameOK); + for (int tries = 0; tries < 100; tries++) { + if (tries == 0) { + fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), dstext); + } else { + fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, dstext); + } - saveAsDialog->hide(); + if (!safe_file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { + fnameOut = fnameTemp; + fnameOK = true; + break; + } + } + } + + // check if it exists + if (!fnameOK) { + fnameOK = confirmOverwrite (*saveAsDialog, fnameOut); + } + + if (fnameOK) { + isProcessing = true; + // save image + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); + + ProgressConnector *ld = new ProgressConnector(); + ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData, false ), + sigc::bind(sigc::mem_fun( *this, &EditorPanel::idle_saveImage ), ld, fnameOut, sf )); + saveimgas->set_sensitive(false); + sendtogimp->set_sensitive(false); + } + } else { + BatchQueueEntry* bqe = createBatchQueueEntry (); + bqe->outFileName = fnameOut; + bqe->saveFormat = saveAsDialog->getFormat (); + bqe->forceFormatOpts = saveAsDialog->getForceFormatOpts (); + parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ()); + fnameOK = true; + } + + // ask parent to redraw file browser + // ... or does it automatically when the tab is switched to it + } while (!fnameOK); + + saveAsDialog->hide(); } -void EditorPanel::queueImgPressed () { - if (!ipc || !openThm) return; +void EditorPanel::queueImgPressed () +{ + if (!ipc || !openThm) { + return; + } + saveProfile (); parent->addBatchQueueJob (createBatchQueueEntry ()); } -void EditorPanel::sendToGimpPressed () { - if (!ipc || !openThm) return; +void EditorPanel::sendToGimpPressed () +{ + if (!ipc || !openThm) { + return; + } + // develop image rtengine::procparams::ProcParams pparams; ipc->getParams (&pparams); rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams); ProgressConnector *ld = new ProgressConnector(); ld->startFunc(sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData, false ), - sigc::bind(sigc::mem_fun( *this,&EditorPanel::idle_sendToGimp ),ld, openThm->getFileName() )); + sigc::bind(sigc::mem_fun( *this, &EditorPanel::idle_sendToGimp ), ld, openThm->getFileName() )); saveimgas->set_sensitive(false); sendtogimp->set_sensitive(false); } -void EditorPanel::openPreviousEditorImage() { - if (!simpleEditor && fPanel && !fname.empty()) - fPanel->fileCatalog->openNextPreviousEditorImage(fname, false, NAV_PREVIOUS); +void EditorPanel::openPreviousEditorImage() +{ + if (!simpleEditor && fPanel && !fname.empty()) { + fPanel->fileCatalog->openNextPreviousEditorImage(fname, false, NAV_PREVIOUS); + } } -void EditorPanel::openNextEditorImage() { - if (!simpleEditor && fPanel && !fname.empty()) - fPanel->fileCatalog->openNextPreviousEditorImage(fname, false, NAV_NEXT); +void EditorPanel::openNextEditorImage() +{ + if (!simpleEditor && fPanel && !fname.empty()) { + fPanel->fileCatalog->openNextPreviousEditorImage(fname, false, NAV_NEXT); + } } -void EditorPanel::syncFileBrowser() { // synchronize filebrowser with image in Editor - if (!simpleEditor && fPanel && !fname.empty()) - fPanel->fileCatalog->selectImage(fname, false); +void EditorPanel::syncFileBrowser() // synchronize filebrowser with image in Editor +{ + if (!simpleEditor && fPanel && !fname.empty()) { + fPanel->fileCatalog->selectImage(fname, false); + } } -bool EditorPanel::idle_sendToGimp( ProgressConnector *pc, Glib::ustring fname){ +bool EditorPanel::idle_sendToGimp( ProgressConnector *pc, Glib::ustring fname) +{ + + rtengine::IImage16* img = pc->returnValue(); + delete pc; - rtengine::IImage16* img = pc->returnValue(); - delete pc; if (img) { // get file name base Glib::ustring shortname = removeExtension (Glib::path_get_basename (fname)); @@ -1318,129 +1512,145 @@ bool EditorPanel::idle_sendToGimp( ProgressConnector *pc, G Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); - 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); - tries++; - } - if (tries==1000){ - img->free (); - return false; - } + 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); + tries++; + } + + if (tries == 1000) { + img->free (); + return false; + } ProgressConnector *ld = new ProgressConnector(); img->setSaveProgressListener (parent->getProgressListener()); - ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), - sigc::bind(sigc::mem_fun(*this,&EditorPanel::idle_sentToGimp), ld, img, fileName)); - }else{ - Glib::ustring msg_ = Glib::ustring(" Error during image processing\n"); - Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); + ld->startFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed), + sigc::bind(sigc::mem_fun(*this, &EditorPanel::idle_sentToGimp), ld, img, fileName)); + } else { + Glib::ustring msg_ = Glib::ustring(" Error during image processing\n"); + Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); saveimgas->set_sensitive(true); sendtogimp->set_sensitive(true); } + return false; } -bool EditorPanel::idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring filename){ +bool EditorPanel::idle_sentToGimp(ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename) +{ img->free (); int errore = pc->returnValue(); delete pc; + if (!errore) { - saveimgas->set_sensitive(true); - sendtogimp->set_sensitive(true); - parent->setProgressStr(""); - parent->setProgress(0.); - bool success=false; - Glib::ustring cmdLine; - Glib::ustring executable; - // start gimp - if (options.editorToSendTo==1) { + saveimgas->set_sensitive(true); + sendtogimp->set_sensitive(true); + 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); - } + 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("\'"); + 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 \"") + filename + Glib::ustring("\""); - success = safe_spawn_command_line_async (cmdLine); + cmdLine = Glib::ustring("gimp-remote \"") + filename + Glib::ustring("\""); + success = safe_spawn_command_line_async (cmdLine); std::cout << cmdLine << std::endl; #endif - if (!success){ + } + } else if (options.editorToSendTo == 2) { #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 - } - } - 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 - } - 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 - } + executable = Glib::build_filename(options.psDir, "Photoshop.exe"); - 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; - } + 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 + } 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 + } + + 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; + } } return false; } -void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) { +void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) +{ if (beforeIpc) { ProcParams* pparams = beforeIpc->beginUpdateParams (); @@ -1449,36 +1659,48 @@ void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcPara } } -void EditorPanel::beforeAfterToggled () { +void EditorPanel::beforeAfterToggled () +{ - if(!ipc) + if(!ipc) { return; + } removeIfThere (beforeAfterBox, beforeBox, false); removeIfThere (afterBox, afterHeaderBox, false); + if (beforeIarea) { - if (beforeIpc) + if (beforeIpc) { beforeIpc->stopProcessing (); + } + iareapanel->setBeforeAfterViews (NULL, iareapanel); iareapanel->imageArea->iLinkedImageArea = NULL; delete beforeIarea; beforeIarea = NULL; - if (beforeIpc) - { beforeIpc->setPreviewImageListener (NULL); - } + + if (beforeIpc) { + beforeIpc->setPreviewImageListener (NULL); + } + delete beforePreviewHandler; beforePreviewHandler = NULL; - if (beforeIpc) + + if (beforeIpc) { rtengine::StagedImageProcessor::destroy (beforeIpc); + } + beforeIpc = NULL; } if (beforeAfter->get_active ()) { - - int errorCode=0; - rtengine::InitialImage *beforeImg = rtengine::InitialImage::load ( isrc->getImageSource ()->getFileName(), openThm->getType()==FT_Raw , &errorCode, NULL); - if( !beforeImg || errorCode ) - return; + + int errorCode = 0; + rtengine::InitialImage *beforeImg = rtengine::InitialImage::load ( isrc->getImageSource ()->getFileName(), openThm->getType() == FT_Raw , &errorCode, NULL); + + if( !beforeImg || errorCode ) { + return; + } beforeIarea = new ImageAreaPanel (); @@ -1488,13 +1710,13 @@ void EditorPanel::beforeAfterToggled () { beforeLabel->set_markup (Glib::ustring("") + M("GENERAL_BEFORE") + ""); tbBeforeLock = Gtk::manage (new Gtk::ToggleButton ()); tbBeforeLock->set_tooltip_markup (M("MAIN_TOOLTIP_BEFOREAFTERLOCK")); - tbBeforeLock->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::tbBeforeLock_toggled) ); - beforeHeaderBox = Gtk::manage (new Gtk::HBox ()); - beforeHeaderBox->pack_end (*tbBeforeLock, Gtk::PACK_SHRINK, 2); + tbBeforeLock->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::tbBeforeLock_toggled) ); + beforeHeaderBox = Gtk::manage (new Gtk::HBox ()); + beforeHeaderBox->pack_end (*tbBeforeLock, Gtk::PACK_SHRINK, 2); beforeHeaderBox->pack_end (*beforeLabel, Gtk::PACK_SHRINK, 2); beforeHeaderBox->set_size_request(0, HeaderBoxHeight); - history->blistenerLock ? tbBeforeLock->set_image (*iBeforeLockON):tbBeforeLock->set_image (*iBeforeLockOFF); + history->blistenerLock ? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF); tbBeforeLock->set_active(history->blistenerLock); beforeBox = Gtk::manage (new Gtk::VBox ()); @@ -1529,128 +1751,159 @@ void EditorPanel::beforeAfterToggled () { beforeIarea->setBeforeAfterViews (beforeIarea, iareapanel); rtengine::procparams::ProcParams params; - if (history->getBeforeLineParams (params)) + + if (history->getBeforeLineParams (params)) { historyBeforeLineChanged (params); + } } } -void EditorPanel::tbBeforeLock_toggled () { - history->blistenerLock = tbBeforeLock->get_active(); - tbBeforeLock->get_active()? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF); +void EditorPanel::tbBeforeLock_toggled () +{ + history->blistenerLock = tbBeforeLock->get_active(); + tbBeforeLock->get_active() ? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF); } void EditorPanel::histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, - LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw , LUTu & histChroma) { + LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw , LUTu & histChroma) +{ + + if (histogramPanel) { + histogramPanel->histogramChanged (histRed, histGreen, histBlue, histLuma, histRedRaw, histGreenRaw, histBlueRaw, histChroma); + } - if (histogramPanel) histogramPanel->histogramChanged (histRed, histGreen, histBlue, histLuma, histRedRaw, histGreenRaw, histBlueRaw, histChroma); tpc->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve,/*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma); } -bool EditorPanel::CheckSidePanelsVisibility() { - if (tbTopPanel_1) { - if(tbTopPanel_1->get_active()==false && tbRightPanel_1->get_active()==false && hidehp->get_active()==false) - return false; - return true; - } - if(tbRightPanel_1->get_active()==false && hidehp->get_active()==false) - return false; - return true; +bool EditorPanel::CheckSidePanelsVisibility() +{ + if (tbTopPanel_1) { + if(tbTopPanel_1->get_active() == false && tbRightPanel_1->get_active() == false && hidehp->get_active() == false) { + return false; + } + + return true; + } + + if(tbRightPanel_1->get_active() == false && hidehp->get_active() == false) { + return false; + } + + return true; } -void EditorPanel::toggleSidePanels(){ - // Maximize preview panel: - // toggle top AND right AND history panels +void EditorPanel::toggleSidePanels() +{ + // Maximize preview panel: + // toggle top AND right AND history panels - bool bAllSidePanelsVisible; - bAllSidePanelsVisible= CheckSidePanelsVisibility(); + bool bAllSidePanelsVisible; + bAllSidePanelsVisible = CheckSidePanelsVisibility(); - if (tbTopPanel_1) - tbTopPanel_1->set_active (!bAllSidePanelsVisible); - tbRightPanel_1->set_active (!bAllSidePanelsVisible); - hidehp->set_active (!bAllSidePanelsVisible); - if (bAllSidePanelsVisible == false) - tbShowHideSidePanels->set_image (*iShowHideSidePanels); - else - tbShowHideSidePanels->set_image (*iShowHideSidePanels_exit); + if (tbTopPanel_1) { + tbTopPanel_1->set_active (!bAllSidePanelsVisible); + } + + tbRightPanel_1->set_active (!bAllSidePanelsVisible); + hidehp->set_active (!bAllSidePanelsVisible); + + if (bAllSidePanelsVisible == false) { + tbShowHideSidePanels->set_image (*iShowHideSidePanels); + } else { + tbShowHideSidePanels->set_image (*iShowHideSidePanels_exit); + } } -void EditorPanel::toggleSidePanelsZoomFit() { - toggleSidePanels(); +void EditorPanel::toggleSidePanelsZoomFit() +{ + toggleSidePanels(); - // fit image preview - // !!! TODO this does not want to work... seems to have an effect on a subsequent key press - // iarea->imageArea->zoomPanel->zoomFitClicked(); + // fit image preview + // !!! TODO this does not want to work... seems to have an effect on a subsequent key press + // iarea->imageArea->zoomPanel->zoomFitClicked(); } -void EditorPanel::tbShowHideSidePanels_managestate() { - bool bAllSidePanelsVisible; - bAllSidePanelsVisible = CheckSidePanelsVisibility(); - ShowHideSidePanelsconn.block (true); +void EditorPanel::tbShowHideSidePanels_managestate() +{ + bool bAllSidePanelsVisible; + bAllSidePanelsVisible = CheckSidePanelsVisibility(); + ShowHideSidePanelsconn.block (true); - tbShowHideSidePanels->set_active (!bAllSidePanelsVisible); + tbShowHideSidePanels->set_active (!bAllSidePanelsVisible); - ShowHideSidePanelsconn.block (false); + ShowHideSidePanelsconn.block (false); } -void EditorPanel::updateTPVScrollbar (bool hide) { - tpc->updateTPVScrollbar (hide); +void EditorPanel::updateTPVScrollbar (bool hide) +{ + tpc->updateTPVScrollbar (hide); } -void EditorPanel::updateTabsUsesIcons (bool useIcons) { - tpc->updateTabsUsesIcons (useIcons); +void EditorPanel::updateTabsUsesIcons (bool useIcons) +{ + tpc->updateTabsUsesIcons (useIcons); } -void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) { +void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition) +{ - switch (newPosition) { - case 0: - // No histogram - if (!oldPosition) { - // An histogram actually exist, we delete it - if (oldPosition == 1) - removeIfThere(leftbox, histogramPanel, false); - else if (oldPosition == 2) - removeIfThere(vboxright, histogramPanel, false); - delete histogramPanel; - histogramPanel = NULL; - } - // else no need to create it - break; - case 1: - // Histogram on the left pane - if (oldPosition == 0) { - // There was no Histogram before, so we create it - histogramPanel = Gtk::manage (new HistogramPanel ()); - leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); - } - else if (oldPosition == 2) { - // The histogram was on the right side, so we move it to the left - histogramPanel->reference(); - removeIfThere(vboxright, histogramPanel, false); - leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); - histogramPanel->unreference(); - } - histogramPanel->reorder(Gtk::ALIGN_LEFT); - leftbox->reorder_child(*histogramPanel, 0); - break; - case 2: - default: - // Histogram on the right pane - if (oldPosition == 0) { - // There was no Histogram before, so we create it - histogramPanel = Gtk::manage (new HistogramPanel ()); - vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); - } - else if (oldPosition == 1) { - // The histogram was on the left side, so we move it to the right - histogramPanel->reference(); - removeIfThere(leftbox, histogramPanel, false); - vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); - histogramPanel->unreference(); - } - histogramPanel->reorder(Gtk::ALIGN_RIGHT); - vboxright->reorder_child(*histogramPanel, 0); - break; - } + switch (newPosition) { + case 0: + + // No histogram + if (!oldPosition) { + // An histogram actually exist, we delete it + if (oldPosition == 1) { + removeIfThere(leftbox, histogramPanel, false); + } else if (oldPosition == 2) { + removeIfThere(vboxright, histogramPanel, false); + } + + delete histogramPanel; + histogramPanel = NULL; + } + + // else no need to create it + break; + + case 1: + + // Histogram on the left pane + if (oldPosition == 0) { + // There was no Histogram before, so we create it + histogramPanel = Gtk::manage (new HistogramPanel ()); + leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + } else if (oldPosition == 2) { + // The histogram was on the right side, so we move it to the left + histogramPanel->reference(); + removeIfThere(vboxright, histogramPanel, false); + leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + histogramPanel->unreference(); + } + + histogramPanel->reorder(Gtk::ALIGN_LEFT); + leftbox->reorder_child(*histogramPanel, 0); + break; + + case 2: + default: + + // Histogram on the right pane + if (oldPosition == 0) { + // There was no Histogram before, so we create it + histogramPanel = Gtk::manage (new HistogramPanel ()); + vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + } else if (oldPosition == 1) { + // The histogram was on the left side, so we move it to the right + histogramPanel->reference(); + removeIfThere(leftbox, histogramPanel, false); + vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2); + histogramPanel->unreference(); + } + + histogramPanel->reorder(Gtk::ALIGN_RIGHT); + vboxright->reorder_child(*histogramPanel, 0); + break; + } iareapanel->imageArea->setPointerMotionHListener (histogramPanel); } diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index bdeb7b64a..abe511ad1 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -8,7 +8,7 @@ * 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 @@ -43,164 +43,174 @@ struct EditorPanelIdleHelper { }; class RTWindow; -class EditorPanel : public Gtk::VBox, - public PParamsChangeListener, - public rtengine::ProgressListener, - public ThumbnailListener, - public HistoryBeforeLineListener, - public rtengine::HistogramListener { - private: +class EditorPanel : public Gtk::VBox, + public PParamsChangeListener, + public rtengine::ProgressListener, + public ThumbnailListener, + public HistoryBeforeLineListener, + public rtengine::HistogramListener +{ +private: - Glib::ustring lastSaveAsFileName; - bool realized; + Glib::ustring lastSaveAsFileName; + bool realized; - protected: - Gtk::ProgressBar *progressLabel; - Gtk::ToggleButton* info; - Gtk::ToggleButton* hidehp; - Gtk::ToggleButton* tbShowHideSidePanels; - Gtk::ToggleButton* tbTopPanel_1; - Gtk::ToggleButton* tbRightPanel_1; - Gtk::ToggleButton* tbBeforeLock; - //bool bAllSidePanelsVisible; - Gtk::ToggleButton* beforeAfter; - Gtk::HPaned* hpanedl; - Gtk::HPaned* hpanedr; - Gtk::HBox* statusBox; - Gtk::Image *iHistoryShow, *iHistoryHide; - Gtk::Image *iTopPanel_1_Show, *iTopPanel_1_Hide; - Gtk::Image *iRightPanel_1_Show, *iRightPanel_1_Hide; - Gtk::Image *iShowHideSidePanels; - Gtk::Image *iShowHideSidePanels_exit; - Gtk::Image *iBeforeLockON, *iBeforeLockOFF; - Gtk::VBox *leftbox; - Gtk::VBox *vboxright; +protected: + Gtk::ProgressBar *progressLabel; + Gtk::ToggleButton* info; + Gtk::ToggleButton* hidehp; + Gtk::ToggleButton* tbShowHideSidePanels; + Gtk::ToggleButton* tbTopPanel_1; + Gtk::ToggleButton* tbRightPanel_1; + Gtk::ToggleButton* tbBeforeLock; + //bool bAllSidePanelsVisible; + Gtk::ToggleButton* beforeAfter; + Gtk::HPaned* hpanedl; + Gtk::HPaned* hpanedr; + Gtk::HBox* statusBox; + Gtk::Image *iHistoryShow, *iHistoryHide; + Gtk::Image *iTopPanel_1_Show, *iTopPanel_1_Hide; + Gtk::Image *iRightPanel_1_Show, *iRightPanel_1_Hide; + Gtk::Image *iShowHideSidePanels; + Gtk::Image *iShowHideSidePanels_exit; + Gtk::Image *iBeforeLockON, *iBeforeLockOFF; + Gtk::VBox *leftbox; + Gtk::VBox *vboxright; - Gtk::Button* queueimg; - Gtk::Button* saveimgas; - Gtk::Button* sendtogimp; - Gtk::Button* navSync; - Gtk::Button* navNext; - Gtk::Button* navPrev; + Gtk::Button* queueimg; + Gtk::Button* saveimgas; + Gtk::Button* sendtogimp; + Gtk::Button* navSync; + Gtk::Button* navNext; + Gtk::Button* navPrev; - ImageAreaPanel* iareapanel; - PreviewHandler* previewHandler; - PreviewHandler* beforePreviewHandler; // for the before-after view - PreviewHandler* previewHandler2; - Navigator* navigator; - ImageAreaPanel* beforeIarea; // for the before-after view - Gtk::VBox* beforeBox; - Gtk::VBox* afterBox; - Gtk::Label* beforeLabel; - Gtk::Label* afterLabel; - Gtk::HBox* beforeAfterBox; - Gtk::HBox* beforeHeaderBox; - Gtk::HBox* afterHeaderBox; - - Gtk::Frame* ppframe; - ProfilePanel* profilep; - History* history; - HistogramPanel* histogramPanel; - ToolPanelCoordinator* tpc; - RTWindow* parent; - //SaveAsDialog* saveAsDialog; - BatchToolPanelCoordinator* btpCoordinator; - FilePanel* fPanel; - - bool firstProcessingDone; - - Thumbnail* openThm; // may get invalid on external delete event - Glib::ustring fname; // must be saved separately + ImageAreaPanel* iareapanel; + PreviewHandler* previewHandler; + PreviewHandler* beforePreviewHandler; // for the before-after view + PreviewHandler* previewHandler2; + Navigator* navigator; + ImageAreaPanel* beforeIarea; // for the before-after view + Gtk::VBox* beforeBox; + Gtk::VBox* afterBox; + Gtk::Label* beforeLabel; + Gtk::Label* afterLabel; + Gtk::HBox* beforeAfterBox; + Gtk::HBox* beforeHeaderBox; + Gtk::HBox* afterHeaderBox; - rtengine::InitialImage* isrc; - rtengine::StagedImageProcessor* ipc; - rtengine::StagedImageProcessor* beforeIpc; // for the before-after view + Gtk::Frame* ppframe; + ProfilePanel* profilep; + History* history; + HistogramPanel* histogramPanel; + ToolPanelCoordinator* tpc; + RTWindow* parent; + //SaveAsDialog* saveAsDialog; + BatchToolPanelCoordinator* btpCoordinator; + FilePanel* fPanel; - EditorPanelIdleHelper* epih; + bool firstProcessingDone; - void close (); + Thumbnail* openThm; // may get invalid on external delete event + Glib::ustring fname; // must be saved separately - BatchQueueEntry* createBatchQueueEntry (); - bool idle_imageSaved(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring fname, SaveFormat sf); - bool idle_saveImage(ProgressConnector *pc,Glib::ustring fname, SaveFormat sf); - bool idle_sendToGimp( ProgressConnector *pc, Glib::ustring fname); - bool idle_sentToGimp(ProgressConnector *pc,rtengine::IImage16* img,Glib::ustring filename); - int err; + rtengine::InitialImage* isrc; + rtengine::StagedImageProcessor* ipc; + rtengine::StagedImageProcessor* beforeIpc; // for the before-after view - time_t processingStartedTime; + EditorPanelIdleHelper* epih; - sigc::connection ShowHideSidePanelsconn; + void close (); - bool isProcessing; + BatchQueueEntry* createBatchQueueEntry (); + bool idle_imageSaved(ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf); + bool idle_saveImage(ProgressConnector *pc, Glib::ustring fname, SaveFormat sf); + bool idle_sendToGimp( ProgressConnector *pc, Glib::ustring fname); + bool idle_sentToGimp(ProgressConnector *pc, rtengine::IImage16* img, Glib::ustring filename); + int err; + + time_t processingStartedTime; + + sigc::connection ShowHideSidePanelsconn; + + bool isProcessing; - public: - EditorPanel (FilePanel* filePanel = NULL); - virtual ~EditorPanel (); +public: + EditorPanel (FilePanel* filePanel = NULL); + virtual ~EditorPanel (); - void open (Thumbnail* tmb, rtengine::InitialImage* isrc); - void setAspect (); - void on_realize (); - void leftPaneButtonReleased(GdkEventButton *event); - void rightPaneButtonReleased(GdkEventButton *event); + void open (Thumbnail* tmb, rtengine::InitialImage* isrc); + void setAspect (); + void on_realize (); + void leftPaneButtonReleased(GdkEventButton *event); + void rightPaneButtonReleased(GdkEventButton *event); - void setParent (RTWindow* p) { parent = p; } - void writeOptions(); + void setParent (RTWindow* p) + { + parent = p; + } + void writeOptions(); - void showTopPanel(bool show); - bool isRealized() { return realized; } - // progresslistener interface - void setProgress (double p); - void setProgressStr (Glib::ustring str); - void setProgressState (bool inProcessing); - void error (Glib::ustring title, Glib::ustring descr); - void displayError (Glib::ustring title, Glib::ustring descr); // this is called by error in the gtk thread - void refreshProcessingState (bool inProcessing); // this is called by setProcessingState in the gtk thread - - // PParamsChangeListener interface - void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL); + void showTopPanel(bool show); + bool isRealized() + { + return realized; + } + // progresslistener interface + void setProgress (double p); + void setProgressStr (Glib::ustring str); + void setProgressState (bool inProcessing); + void error (Glib::ustring title, Glib::ustring descr); + void displayError (Glib::ustring title, Glib::ustring descr); // this is called by error in the gtk thread + void refreshProcessingState (bool inProcessing); // this is called by setProcessingState in the gtk thread - // thumbnaillistener interface - void procParamsChanged (Thumbnail* thm, int whoChangedIt); - - // HistoryBeforeLineListener - void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params); - - // HistogramListener - void histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, - LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw, LUTu & histChroma); + // PParamsChangeListener interface + void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited = NULL); - // event handlers - void info_toggled (); - void hideHistoryActivated (); - void tbRightPanel_1_toggled (); - void tbTopPanel_1_toggled (); - void beforeAfterToggled (); - void tbBeforeLock_toggled(); - void saveAsPressed (); - void queueImgPressed (); - void sendToGimpPressed (); - void openNextEditorImage (); - void openPreviousEditorImage (); - void syncFileBrowser (); + // thumbnaillistener interface + void procParamsChanged (Thumbnail* thm, int whoChangedIt); - void tbTopPanel_1_visible (bool visible); - bool CheckSidePanelsVisibility(); - void tbShowHideSidePanels_managestate(); - void toggleSidePanels(); - void toggleSidePanelsZoomFit(); + // HistoryBeforeLineListener + void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params); - void saveProfile (); - Glib::ustring getShortName (); - Glib::ustring getFileName (); - bool handleShortcutKey (GdkEventKey* event); + // HistogramListener + void histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, + LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw, LUTu & histChroma); - bool getIsProcessing() const { return isProcessing; } - void updateTPVScrollbar (bool hide); - void updateTabsUsesIcons (bool useIcons); - void updateHistogramPosition (int oldPosition, int newPosition); + // event handlers + void info_toggled (); + void hideHistoryActivated (); + void tbRightPanel_1_toggled (); + void tbTopPanel_1_toggled (); + void beforeAfterToggled (); + void tbBeforeLock_toggled(); + void saveAsPressed (); + void queueImgPressed (); + void sendToGimpPressed (); + void openNextEditorImage (); + void openPreviousEditorImage (); + void syncFileBrowser (); - Gtk::Paned *catalogPane; + void tbTopPanel_1_visible (bool visible); + bool CheckSidePanelsVisibility(); + void tbShowHideSidePanels_managestate(); + void toggleSidePanels(); + void toggleSidePanelsZoomFit(); + + void saveProfile (); + Glib::ustring getShortName (); + Glib::ustring getFileName (); + bool handleShortcutKey (GdkEventKey* event); + + bool getIsProcessing() const + { + return isProcessing; + } + void updateTPVScrollbar (bool hide); + void updateTabsUsesIcons (bool useIcons); + void updateHistogramPosition (int oldPosition, int newPosition); + + Gtk::Paned *catalogPane; }; #endif diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc index c57898da2..3b99f57e5 100644 --- a/rtgui/editwindow.cc +++ b/rtgui/editwindow.cc @@ -5,7 +5,7 @@ * 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 @@ -27,8 +27,9 @@ static EditWindow* editWnd = NULL; // Check if the system has more than one display and option is set -bool EditWindow::isMultiDisplayEnabled() { - return options.multiDisplayMode>0 && Gdk::Screen::get_default()->get_n_monitors ()>1; +bool EditWindow::isMultiDisplayEnabled() +{ + return options.multiDisplayMode > 0 && Gdk::Screen::get_default()->get_n_monitors () > 1; } // Should only be created once, auto-creates window on correct display @@ -38,15 +39,16 @@ EditWindow* EditWindow::getInstance(RTWindow* p) if (editWnd == NULL) { static MyMutex smutex_; MyMutex::MyLock lock(smutex_); + if ( editWnd == 0 ) { editWnd = new EditWindow(p); // Determine the other display and maximize the window on that - const Glib::RefPtr< Gdk::Window >& wnd=p->get_window(); - int monNo=p->get_screen()->get_monitor_at_window (wnd); + const Glib::RefPtr< Gdk::Window >& wnd = p->get_window(); + int monNo = p->get_screen()->get_monitor_at_window (wnd); Gdk::Rectangle lMonitorRect; - editWnd->get_screen()->get_monitor_geometry(isMultiDisplayEnabled() ? (monNo==0 ? 1 : 0) : monNo, lMonitorRect); + editWnd->get_screen()->get_monitor_geometry(isMultiDisplayEnabled() ? (monNo == 0 ? 1 : 0) : monNo, lMonitorRect); editWnd->move(lMonitorRect.get_x(), lMonitorRect.get_y()); editWnd->maximize(); editWnd->show(); @@ -58,20 +60,27 @@ EditWindow* EditWindow::getInstance(RTWindow* p) return editWnd; } -EditWindow::EditWindow (RTWindow* p) : parent(p) , isFullscreen(false) { +EditWindow::EditWindow (RTWindow* p) : parent(p) , isFullscreen(false) +{ Glib::ustring fName = "rt-logo.png"; Glib::ustring fullPath = RTImage::findIconAbsolutePath(fName); #ifdef GLIBMM_EXCEPTIONS_ENABLED - try { set_default_icon_from_file (fullPath); - } catch(Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); } + + try { + set_default_icon_from_file (fullPath); + } catch(Glib::Exception& ex) { + printf ("%s\n", ex.what().c_str()); + } + #else - { std::auto_ptr error; - set_default_icon_from_file (fullPath, error); + { + std::auto_ptr error; + set_default_icon_from_file (fullPath, error); } #endif //GLIBMM_EXCEPTIONS_ENABLED - set_title_decorated(""); + set_title_decorated(""); property_allow_shrink() = true; set_modal(false); set_resizable(true); @@ -86,57 +95,62 @@ EditWindow::EditWindow (RTWindow* p) : parent(p) , isFullscreen(false) { signal_key_press_event().connect( sigc::mem_fun(*this, &EditWindow::keyPressed) ); Gtk::VBox* mainBox = Gtk::manage (new Gtk::VBox ()); - mainBox->pack_start (*mainNB); + mainBox->pack_start (*mainNB); add (*mainBox); show_all (); } -void EditWindow::on_realize () { +void EditWindow::on_realize () +{ Gtk::Window::on_realize (); cursorManager.init (get_window()); } -bool EditWindow::on_window_state_event(GdkEventWindowState* event) { +bool EditWindow::on_window_state_event(GdkEventWindowState* event) +{ if (!event->new_window_state) { // Window mode options.windowMaximized = false; - } - else if (event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) { + } else if (event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) { // Fullscreen mode options.windowMaximized = true; } + return true; } -void EditWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) { +void EditWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) +{ //if (page_num > 1) { - EditorPanel *ep = static_cast(mainNB->get_nth_page(page_num)); - - if (mainNB->get_n_pages()>1 && page_num<=(filesEdited.size()-1)){ - set_title_decorated(ep->getFileName()); - } + EditorPanel *ep = static_cast(mainNB->get_nth_page(page_num)); + + if (mainNB->get_n_pages() > 1 && page_num <= (filesEdited.size() - 1)) { + set_title_decorated(ep->getFileName()); + } + ep->setAspect(); //} } -void EditWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { +void EditWindow::addEditorPanel (EditorPanel* ep, const std::string &name) +{ ep->setParent (parent); // construct closeable tab for the image Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); - hb->pack_start (*Gtk::manage (new RTImage ("rtwindow.png"))); + hb->pack_start (*Gtk::manage (new RTImage ("rtwindow.png"))); hb->pack_start (*Gtk::manage (new Gtk::Label (Glib::path_get_basename (name)))); hb->set_tooltip_markup (name); Gtk::Button* closeb = Gtk::manage (new Gtk::Button ()); - closeb->set_image (*Gtk::manage(new RTImage ("gtk-close.png"))); + closeb->set_image (*Gtk::manage(new RTImage ("gtk-close.png"))); closeb->set_relief (Gtk::RELIEF_NONE); closeb->set_focus_on_click (false); // make the button as small as possible Glib::RefPtr style = Gtk::RcStyle::create (); style->set_xthickness (0); - style->set_ythickness (0); + style->set_ythickness (0); closeb->modify_style (style); closeb->signal_clicked().connect( sigc::bind (sigc::mem_fun(*this, &EditWindow::remEditorPanel) , ep)); @@ -156,76 +170,89 @@ void EditWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { ep->setAspect(); } -void EditWindow::remEditorPanel (EditorPanel* ep) { - if (ep->getIsProcessing()) - return; // Will crash if destroyed while loading - +void EditWindow::remEditorPanel (EditorPanel* ep) +{ + if (ep->getIsProcessing()) { + return; // Will crash if destroyed while loading + } + epanels.erase (ep->getFileName()); filesEdited.erase (ep->getFileName ()); parent->fpanel->refreshEditedState (filesEdited); mainNB->remove_page (*ep); - if (mainNB->get_n_pages()>0){ - EditorPanel* ep1 = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); - set_title_decorated(ep1->getFileName()); - } - else set_title_decorated(""); + + if (mainNB->get_n_pages() > 0) { + EditorPanel* ep1 = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); + set_title_decorated(ep1->getFileName()); + } else { + set_title_decorated(""); + } + // TODO: save options if wanted } -bool EditWindow::selectEditorPanel(const std::string &name) { +bool EditWindow::selectEditorPanel(const std::string &name) +{ std::map::iterator iep = epanels.find(name); - if (iep!=epanels.end()) { + if (iep != epanels.end()) { mainNB->set_current_page (mainNB->page_num (*iep->second)); set_title_decorated(name); return true; } + return false; } -bool EditWindow::keyPressed (GdkEventKey* event) { - bool ctrl = event->state & GDK_CONTROL_MASK; +bool EditWindow::keyPressed (GdkEventKey* event) +{ + bool ctrl = event->state & GDK_CONTROL_MASK; if(event->keyval == GDK_F11) { toggleFullscreen(); return true; - } - else { - if(mainNB->get_n_pages ()>0) { //pass the handling for the editor panels, if there are any - if (event->keyval == GDK_w && ctrl){ //remove editor panel - EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); - remEditorPanel (ep); - return true; - } - else if(mainNB->get_n_pages ()>0){ - EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); - return ep->handleShortcutKey (event); - } - } - return false; + } else { + if(mainNB->get_n_pages () > 0) { //pass the handling for the editor panels, if there are any + if (event->keyval == GDK_w && ctrl) { //remove editor panel + EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); + remEditorPanel (ep); + return true; + } else if(mainNB->get_n_pages () > 0) { + EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); + return ep->handleShortcutKey (event); + } + } + + return false; } } -void EditWindow::toggleFullscreen () { +void EditWindow::toggleFullscreen () +{ isFullscreen ? unfullscreen() : fullscreen(); isFullscreen = !isFullscreen; } -bool EditWindow::on_delete_event(GdkEventAny* event) { +bool EditWindow::on_delete_event(GdkEventAny* event) +{ // Check if any editor is still processing, and do NOT quit if so. Otherwise crashes and inconsistent caches - bool isProcessing=false; + bool isProcessing = false; for ( std::set ::iterator iter = filesEdited.begin(); iter != filesEdited.end() && !isProcessing; iter++ ) { - if (epanels[*iter]->getIsProcessing()) isProcessing=true; + if (epanels[*iter]->getIsProcessing()) { + isProcessing = true; + } } - if (isProcessing) - return true; + if (isProcessing) { + return true; + } - for ( std::set ::iterator iter = filesEdited.begin(); iter != filesEdited.end(); iter++ ) + for ( std::set ::iterator iter = filesEdited.begin(); iter != filesEdited.end(); iter++ ) { mainNB->remove_page (*epanels[*iter]); + } epanels.clear(); @@ -236,8 +263,13 @@ bool EditWindow::on_delete_event(GdkEventAny* event) { return false; } -void EditWindow::set_title_decorated(Glib::ustring fname){ - Glib::ustring subtitle; - if (!fname.empty()) subtitle= " - " + fname; - set_title("RawTherapee "+ M("EDITWINDOW_TITLE") + subtitle); +void EditWindow::set_title_decorated(Glib::ustring fname) +{ + Glib::ustring subtitle; + + if (!fname.empty()) { + subtitle = " - " + fname; + } + + set_title("RawTherapee " + M("EDITWINDOW_TITLE") + subtitle); } diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h index 7b8fb08c7..fa47de489 100644 --- a/rtgui/editwindow.h +++ b/rtgui/editwindow.h @@ -5,7 +5,7 @@ * 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 @@ -22,38 +22,39 @@ #include "editorpanel.h" #include -class EditWindow : public Gtk::Window { +class EditWindow : public Gtk::Window +{ - private: - RTWindow* parent; +private: + RTWindow* parent; - Gtk::Notebook* mainNB; - std::set filesEdited; - std::map epanels; + Gtk::Notebook* mainNB; + std::set filesEdited; + std::map epanels; - bool isFullscreen; - void toggleFullscreen (); + bool isFullscreen; + void toggleFullscreen (); - public: - // Check if the system has more than one display and option is set - static bool isMultiDisplayEnabled(); +public: + // Check if the system has more than one display and option is set + static bool isMultiDisplayEnabled(); - // Should only be created once, auto-creates window on correct display - static EditWindow* getInstance(RTWindow* p); + // Should only be created once, auto-creates window on correct display + static EditWindow* getInstance(RTWindow* p); - EditWindow (RTWindow* p); + EditWindow (RTWindow* p); - void addEditorPanel (EditorPanel* ep,const std::string &name); - void remEditorPanel (EditorPanel* ep); - bool selectEditorPanel(const std::string &name); + void addEditorPanel (EditorPanel* ep, const std::string &name); + void remEditorPanel (EditorPanel* ep); + bool selectEditorPanel(const std::string &name); - bool keyPressed (GdkEventKey* event); - bool on_delete_event(GdkEventAny* event); - bool on_window_state_event(GdkEventWindowState* event); - void on_mainNB_switch_page(GtkNotebookPage* page, guint page_num); - void set_title_decorated(Glib::ustring fname); + bool keyPressed (GdkEventKey* event); + bool on_delete_event(GdkEventAny* event); + bool on_window_state_event(GdkEventWindowState* event); + void on_mainNB_switch_page(GtkNotebookPage* page, guint page_num); + void set_title_decorated(Glib::ustring fname); - void on_realize (); + void on_realize (); }; #endif diff --git a/rtgui/epd.cc b/rtgui/epd.cc index 34f6a6842..15f15f607 100644 --- a/rtgui/epd.cc +++ b/rtgui/epd.cc @@ -7,7 +7,7 @@ * 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 @@ -23,138 +23,162 @@ using namespace rtengine; using namespace rtengine::procparams; -EdgePreservingDecompositionUI::EdgePreservingDecompositionUI () : FoldableToolPanel(this, "epd", M("TP_EPD_LABEL"), true, true) { +EdgePreservingDecompositionUI::EdgePreservingDecompositionUI () : FoldableToolPanel(this, "epd", M("TP_EPD_LABEL"), true, true) +{ - setEnabledTooltipMarkup(M("TP_EPD_TOOLTIP")); + setEnabledTooltipMarkup(M("TP_EPD_TOOLTIP")); - strength = Gtk::manage(new Adjuster (M("TP_EPD_STRENGTH"), -1.0, 2.0, 0.01, 0.5)); - gamma = Gtk::manage(new Adjuster (M("TP_EPD_GAMMA"), 0.8, 1.5, 0.01, 1.)); - edgeStopping = Gtk::manage(new Adjuster (M("TP_EPD_EDGESTOPPING"), 0.1, 4.0, 0.01, 1.4)); - scale = Gtk::manage(new Adjuster (M("TP_EPD_SCALE"), 0.1, 10.0, 0.01, 0.3)); - reweightingIterates = Gtk::manage(new Adjuster (M("TP_EPD_REWEIGHTINGITERATES"), 0, 9, 1, 0)); + strength = Gtk::manage(new Adjuster (M("TP_EPD_STRENGTH"), -1.0, 2.0, 0.01, 0.5)); + gamma = Gtk::manage(new Adjuster (M("TP_EPD_GAMMA"), 0.8, 1.5, 0.01, 1.)); + edgeStopping = Gtk::manage(new Adjuster (M("TP_EPD_EDGESTOPPING"), 0.1, 4.0, 0.01, 1.4)); + scale = Gtk::manage(new Adjuster (M("TP_EPD_SCALE"), 0.1, 10.0, 0.01, 0.3)); + reweightingIterates = Gtk::manage(new Adjuster (M("TP_EPD_REWEIGHTINGITERATES"), 0, 9, 1, 0)); - strength->setAdjusterListener(this); - gamma->setAdjusterListener(this); - edgeStopping->setAdjusterListener(this); - scale->setAdjusterListener(this); - reweightingIterates->setAdjusterListener(this); + strength->setAdjusterListener(this); + gamma->setAdjusterListener(this); + edgeStopping->setAdjusterListener(this); + scale->setAdjusterListener(this); + reweightingIterates->setAdjusterListener(this); - strength->show(); - gamma->show(); - edgeStopping->show(); - scale->show(); - reweightingIterates->show(); + strength->show(); + gamma->show(); + edgeStopping->show(); + scale->show(); + reweightingIterates->show(); - pack_start(*strength); - pack_start(*gamma); - pack_start(*edgeStopping); - pack_start(*scale); - pack_start(*reweightingIterates); + pack_start(*strength); + pack_start(*gamma); + pack_start(*edgeStopping); + pack_start(*scale); + pack_start(*reweightingIterates); } -void EdgePreservingDecompositionUI::read(const ProcParams *pp, const ParamsEdited *pedited){ - disableListener(); +void EdgePreservingDecompositionUI::read(const ProcParams *pp, const ParamsEdited *pedited) +{ + disableListener(); - if(pedited){ - strength->setEditedState(pedited->epd.strength ? Edited : UnEdited); - gamma->setEditedState(pedited->epd.gamma ? Edited : UnEdited); - edgeStopping->setEditedState(pedited->epd.edgeStopping ? Edited : UnEdited); - scale->setEditedState(pedited->epd.scale ? Edited : UnEdited); - reweightingIterates->setEditedState(pedited->epd.reweightingIterates ? Edited : UnEdited); - set_inconsistent(multiImage && !pedited->epd.enabled); - } + if(pedited) { + strength->setEditedState(pedited->epd.strength ? Edited : UnEdited); + gamma->setEditedState(pedited->epd.gamma ? Edited : UnEdited); + edgeStopping->setEditedState(pedited->epd.edgeStopping ? Edited : UnEdited); + scale->setEditedState(pedited->epd.scale ? Edited : UnEdited); + reweightingIterates->setEditedState(pedited->epd.reweightingIterates ? Edited : UnEdited); + set_inconsistent(multiImage && !pedited->epd.enabled); + } - setEnabled(pp->epd.enabled); - strength->set_sensitive (true); - if(pp->wavelet.enabled){ - if(pp->wavelet.tmrs==0) {strength->set_sensitive (true);gamma->set_sensitive (true);} - else {strength->set_sensitive (false);gamma->set_sensitive (false);} - } - strength->setValue(pp->epd.strength); - gamma->setValue(pp->epd.gamma); - edgeStopping->setValue(pp->epd.edgeStopping); - scale->setValue(pp->epd.scale); - reweightingIterates->setValue(pp->epd.reweightingIterates); + setEnabled(pp->epd.enabled); + strength->set_sensitive (true); - enableListener(); + if(pp->wavelet.enabled) { + if(pp->wavelet.tmrs == 0) { + strength->set_sensitive (true); + gamma->set_sensitive (true); + } else { + strength->set_sensitive (false); + gamma->set_sensitive (false); + } + } + + strength->setValue(pp->epd.strength); + gamma->setValue(pp->epd.gamma); + edgeStopping->setValue(pp->epd.edgeStopping); + scale->setValue(pp->epd.scale); + reweightingIterates->setValue(pp->epd.reweightingIterates); + + enableListener(); } -void EdgePreservingDecompositionUI::write(ProcParams *pp, ParamsEdited *pedited){ - pp->epd.strength = strength->getValue(); - pp->epd.gamma = gamma->getValue(); - pp->epd.edgeStopping = edgeStopping->getValue(); - pp->epd.scale = scale->getValue(); - pp->epd.reweightingIterates = reweightingIterates->getValue(); - pp->epd.enabled = getEnabled(); - strength->set_sensitive (true); - if(pp->wavelet.enabled){ - if(pp->wavelet.tmrs==0) {strength->set_sensitive (true);gamma->set_sensitive (true);} else {strength->set_sensitive (false);gamma->set_sensitive (false);} - } - if(pedited){ - pedited->epd.strength = strength->getEditedState(); - pedited->epd.gamma = gamma->getEditedState(); - pedited->epd.edgeStopping = edgeStopping->getEditedState(); - pedited->epd.scale = scale->getEditedState(); - pedited->epd.reweightingIterates = reweightingIterates->getEditedState(); - pedited->epd.enabled = !get_inconsistent(); - } +void EdgePreservingDecompositionUI::write(ProcParams *pp, ParamsEdited *pedited) +{ + pp->epd.strength = strength->getValue(); + pp->epd.gamma = gamma->getValue(); + pp->epd.edgeStopping = edgeStopping->getValue(); + pp->epd.scale = scale->getValue(); + pp->epd.reweightingIterates = reweightingIterates->getValue(); + pp->epd.enabled = getEnabled(); + strength->set_sensitive (true); + + if(pp->wavelet.enabled) { + if(pp->wavelet.tmrs == 0) { + strength->set_sensitive (true); + gamma->set_sensitive (true); + } else { + strength->set_sensitive (false); + gamma->set_sensitive (false); + } + } + + if(pedited) { + pedited->epd.strength = strength->getEditedState(); + pedited->epd.gamma = gamma->getEditedState(); + pedited->epd.edgeStopping = edgeStopping->getEditedState(); + pedited->epd.scale = scale->getEditedState(); + pedited->epd.reweightingIterates = reweightingIterates->getEditedState(); + pedited->epd.enabled = !get_inconsistent(); + } } -void EdgePreservingDecompositionUI::setDefaults(const ProcParams *defParams, const ParamsEdited *pedited){ - strength->setDefault(defParams->epd.strength); - gamma->setDefault(defParams->epd.gamma); - edgeStopping->setDefault(defParams->epd.edgeStopping); - scale->setDefault(defParams->epd.scale); - reweightingIterates->setDefault(defParams->epd.reweightingIterates); +void EdgePreservingDecompositionUI::setDefaults(const ProcParams *defParams, const ParamsEdited *pedited) +{ + strength->setDefault(defParams->epd.strength); + gamma->setDefault(defParams->epd.gamma); + edgeStopping->setDefault(defParams->epd.edgeStopping); + scale->setDefault(defParams->epd.scale); + reweightingIterates->setDefault(defParams->epd.reweightingIterates); - if(pedited){ - strength->setDefaultEditedState(pedited->epd.strength ? Edited : UnEdited); - gamma->setDefaultEditedState(pedited->epd.gamma ? Edited : UnEdited); - edgeStopping->setDefaultEditedState(pedited->epd.edgeStopping ? Edited : UnEdited); - scale->setDefaultEditedState(pedited->epd.scale ? Edited : UnEdited); - reweightingIterates->setDefaultEditedState(pedited->epd.reweightingIterates ? Edited : UnEdited); - }else{ - strength->setDefaultEditedState(Irrelevant); - gamma->setDefaultEditedState(Irrelevant); - edgeStopping->setDefaultEditedState(Irrelevant); - scale->setDefaultEditedState(Irrelevant); - reweightingIterates->setDefaultEditedState(Irrelevant); - } + if(pedited) { + strength->setDefaultEditedState(pedited->epd.strength ? Edited : UnEdited); + gamma->setDefaultEditedState(pedited->epd.gamma ? Edited : UnEdited); + edgeStopping->setDefaultEditedState(pedited->epd.edgeStopping ? Edited : UnEdited); + scale->setDefaultEditedState(pedited->epd.scale ? Edited : UnEdited); + reweightingIterates->setDefaultEditedState(pedited->epd.reweightingIterates ? Edited : UnEdited); + } else { + strength->setDefaultEditedState(Irrelevant); + gamma->setDefaultEditedState(Irrelevant); + edgeStopping->setDefaultEditedState(Irrelevant); + scale->setDefaultEditedState(Irrelevant); + reweightingIterates->setDefaultEditedState(Irrelevant); + } } -void EdgePreservingDecompositionUI::adjusterChanged(Adjuster* a, double newval){ - if(listener && getEnabled()){ - if(a == strength) - listener->panelChanged(EvEPDStrength, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); - else if(a == gamma) - listener->panelChanged(EvEPDgamma, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); - else if(a == edgeStopping) - listener->panelChanged(EvEPDEdgeStopping, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); - else if(a == scale) - listener->panelChanged(EvEPDScale, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); - else if(a == reweightingIterates) - listener->panelChanged(EvEPDReweightingIterates, Glib::ustring::format((int)a->getValue())); - } +void EdgePreservingDecompositionUI::adjusterChanged(Adjuster* a, double newval) +{ + if(listener && getEnabled()) { + if(a == strength) { + listener->panelChanged(EvEPDStrength, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); + } else if(a == gamma) { + listener->panelChanged(EvEPDgamma, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); + } else if(a == edgeStopping) { + listener->panelChanged(EvEPDEdgeStopping, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); + } else if(a == scale) { + listener->panelChanged(EvEPDScale, Glib::ustring::format(std::setw(2), std::fixed, std::setprecision(2), a->getValue())); + } else if(a == reweightingIterates) { + listener->panelChanged(EvEPDReweightingIterates, Glib::ustring::format((int)a->getValue())); + } + } } -void EdgePreservingDecompositionUI::enabledChanged () { - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvEPDEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvEPDEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvEPDEnabled, M("GENERAL_DISABLED")); - } +void EdgePreservingDecompositionUI::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvEPDEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvEPDEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvEPDEnabled, M("GENERAL_DISABLED")); + } + } } -void EdgePreservingDecompositionUI::setBatchMode(bool batchMode){ - ToolPanel::setBatchMode(batchMode); +void EdgePreservingDecompositionUI::setBatchMode(bool batchMode) +{ + ToolPanel::setBatchMode(batchMode); - strength->showEditedCB(); - gamma->showEditedCB(); - edgeStopping->showEditedCB(); - scale->showEditedCB(); - reweightingIterates->showEditedCB(); + strength->showEditedCB(); + gamma->showEditedCB(); + edgeStopping->showEditedCB(); + scale->showEditedCB(); + reweightingIterates->showEditedCB(); } diff --git a/rtgui/epd.h b/rtgui/epd.h index c0559a10a..6156d947c 100644 --- a/rtgui/epd.h +++ b/rtgui/epd.h @@ -7,7 +7,7 @@ * 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 @@ -23,24 +23,25 @@ #include "adjuster.h" #include "toolpanel.h" -class EdgePreservingDecompositionUI : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class EdgePreservingDecompositionUI : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - Adjuster *strength; - Adjuster *gamma; - Adjuster *edgeStopping; - Adjuster *scale; - Adjuster *reweightingIterates; + Adjuster *strength; + Adjuster *gamma; + Adjuster *edgeStopping; + Adjuster *scale; + Adjuster *reweightingIterates; public: - EdgePreservingDecompositionUI(); + EdgePreservingDecompositionUI(); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); - void adjusterChanged (Adjuster* a, double newval); + void adjusterChanged (Adjuster* a, double newval); void enabledChanged (); }; diff --git a/rtgui/exiffiltersettings.cc b/rtgui/exiffiltersettings.cc index 6c47e6b1f..0218677d8 100644 --- a/rtgui/exiffiltersettings.cc +++ b/rtgui/exiffiltersettings.cc @@ -7,7 +7,7 @@ * 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 @@ -18,12 +18,14 @@ */ #include "exiffiltersettings.h" -ExifFilterSettings::ExifFilterSettings () { +ExifFilterSettings::ExifFilterSettings () +{ - clear (); + clear (); } -void ExifFilterSettings::clear () { +void ExifFilterSettings::clear () +{ fnumberFrom = 100; fnumberTo = 0; shutterFrom = 100; @@ -36,13 +38,13 @@ void ExifFilterSettings::clear () { cameras.clear (); expcomp.clear (); filetypes.clear (); - - filterFNumber = false; - filterShutter = false; - filterFocalLen = false; - filterISO = false; - filterExpComp = false; - filterCamera = false; - filterLens = false; - filterFiletype = false; + + filterFNumber = false; + filterShutter = false; + filterFocalLen = false; + filterISO = false; + filterExpComp = false; + filterCamera = false; + filterLens = false; + filterFiletype = false; } diff --git a/rtgui/exiffiltersettings.h b/rtgui/exiffiltersettings.h index da049df05..f462ddc30 100644 --- a/rtgui/exiffiltersettings.h +++ b/rtgui/exiffiltersettings.h @@ -7,7 +7,7 @@ * 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 @@ -22,32 +22,33 @@ #include #include -class ExifFilterSettings { +class ExifFilterSettings +{ - public: - std::set filetypes; - std::set cameras; - std::set lenses; - std::set expcomp; - double fnumberFrom; - double fnumberTo; - double shutterFrom; - double shutterTo; - double focalFrom; - double focalTo; - int isoFrom; - int isoTo; +public: + std::set filetypes; + std::set cameras; + std::set lenses; + std::set expcomp; + double fnumberFrom; + double fnumberTo; + double shutterFrom; + double shutterTo; + double focalFrom; + double focalTo; + int isoFrom; + int isoTo; - bool filterFNumber; - bool filterShutter; - bool filterFocalLen; - bool filterISO; - bool filterExpComp; - bool filterCamera; - bool filterLens; - bool filterFiletype; - - ExifFilterSettings (); + bool filterFNumber; + bool filterShutter; + bool filterFocalLen; + bool filterISO; + bool filterExpComp; + bool filterCamera; + bool filterLens; + bool filterFiletype; + + ExifFilterSettings (); void clear (); }; diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 58a46bd42..9a8656592 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -7,7 +7,7 @@ * 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 @@ -25,104 +25,107 @@ using namespace rtengine; using namespace rtengine::procparams; using namespace rtexif; -ExifPanel::ExifPanel () : idata(NULL) { +ExifPanel::ExifPanel () : idata(NULL) +{ - recursiveOp = true; + recursiveOp = true; - exifTree = Gtk::manage(new Gtk::TreeView()); - scrolledWindow = Gtk::manage(new Gtk::ScrolledWindow()); + exifTree = Gtk::manage(new Gtk::TreeView()); + scrolledWindow = Gtk::manage(new Gtk::ScrolledWindow()); - exifTree->set_headers_visible(false); - exifTree->set_rules_hint(false); - exifTree->set_reorderable(false); - exifTree->set_enable_search(true); - exifTree->get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); - scrolledWindow->set_border_width(2); - scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE); - scrolledWindow->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); - scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); - scrolledWindow->add(*exifTree); - - exifTreeModel = Gtk::TreeStore::create(exifColumns); - exifTree->set_model (exifTreeModel); + exifTree->set_headers_visible(false); + exifTree->set_rules_hint(false); + exifTree->set_reorderable(false); + exifTree->set_enable_search(true); + exifTree->get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); + scrolledWindow->set_border_width(2); + scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE); + scrolledWindow->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); + scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); + scrolledWindow->add(*exifTree); - delicon = safe_create_from_file ("gtk-close.png"); - keepicon = safe_create_from_file ("gtk-apply.png"); - editicon = safe_create_from_file ("gtk-add.png"); + exifTreeModel = Gtk::TreeStore::create(exifColumns); + exifTree->set_model (exifTreeModel); - Gtk::TreeView::Column *viewcol = Gtk::manage(new Gtk::TreeView::Column ("Field Name")); - Gtk::CellRendererPixbuf* render_pb = Gtk::manage(new Gtk::CellRendererPixbuf ()); - Gtk::CellRendererText *render_txt = Gtk::manage(new Gtk::CellRendererText()); - viewcol->pack_start (*render_pb, false); - viewcol->pack_start (*render_txt, true); - viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon); - viewcol->add_attribute (*render_txt, "markup", exifColumns.field); - - render_pb->property_ypad() = 0; - render_txt->property_ypad() = 0; - render_pb->property_yalign() = 0; - render_txt->property_yalign() = 0; - - exifTree->append_column (*viewcol); - - Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value")); - Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText()); - viewcolv->pack_start (*render_txtv, true); - viewcolv->add_attribute (*render_txtv, "markup", exifColumns.value); - - render_txtv->property_ypad() = 0; - - exifTree->append_column (*viewcolv); - - pack_start (*scrolledWindow); - - Gtk::HBox* buttons1 = Gtk::manage(new Gtk::HBox ()); - Gtk::HBox* buttons2 = Gtk::manage(new Gtk::HBox ()); - - remove = Gtk::manage(new Gtk::Button (M("EXIFPANEL_REMOVE"))); - remove->set_image (*Gtk::manage(new Gtk::Image (delicon))); - remove->set_tooltip_text (M("EXIFPANEL_REMOVEHINT")); - buttons1->pack_start (*remove); - - keep = Gtk::manage(new Gtk::Button (M("EXIFPANEL_KEEP"))); - keep->set_image (*Gtk::manage(new Gtk::Image (keepicon))); - keep->set_tooltip_text (M("EXIFPANEL_KEEPHINT")); - buttons1->pack_start (*keep); + delicon = safe_create_from_file ("gtk-close.png"); + keepicon = safe_create_from_file ("gtk-apply.png"); + editicon = safe_create_from_file ("gtk-add.png"); - add = Gtk::manage(new Gtk::Button (M("EXIFPANEL_ADDEDIT"))); - add->set_image (*Gtk::manage(new Gtk::Image (editicon))); - add->set_tooltip_text (M("EXIFPANEL_ADDEDITHINT")); - buttons1->pack_start (*add); + Gtk::TreeView::Column *viewcol = Gtk::manage(new Gtk::TreeView::Column ("Field Name")); + Gtk::CellRendererPixbuf* render_pb = Gtk::manage(new Gtk::CellRendererPixbuf ()); + Gtk::CellRendererText *render_txt = Gtk::manage(new Gtk::CellRendererText()); + viewcol->pack_start (*render_pb, false); + viewcol->pack_start (*render_txt, true); + viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon); + viewcol->add_attribute (*render_txt, "markup", exifColumns.field); - reset = Gtk::manage(new Gtk::Button (M("EXIFPANEL_RESET"))); - reset->set_image (*Gtk::manage(new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); - reset->set_tooltip_text (M("EXIFPANEL_RESETHINT")); - buttons2->pack_start (*reset); + render_pb->property_ypad() = 0; + render_txt->property_ypad() = 0; + render_pb->property_yalign() = 0; + render_txt->property_yalign() = 0; - resetAll = Gtk::manage(new Gtk::Button (M("EXIFPANEL_RESETALL"))); - resetAll->set_image (*Gtk::manage(new RTImage ("gtk-undoall-ltr.png", "gtk-undoall-rtl.png"))); - resetAll->set_tooltip_text (M("EXIFPANEL_RESETALLHINT")); - buttons2->pack_start (*resetAll); + exifTree->append_column (*viewcol); - pack_end (*buttons2, Gtk::PACK_SHRINK); - pack_end (*buttons1, Gtk::PACK_SHRINK); + Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value")); + Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText()); + viewcolv->pack_start (*render_txtv, true); + viewcolv->add_attribute (*render_txtv, "markup", exifColumns.value); - exifTree->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &ExifPanel::exifSelectionChanged)); - exifTree->signal_row_activated().connect(sigc::mem_fun(*this, &ExifPanel::row_activated)); + render_txtv->property_ypad() = 0; - remove->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::removePressed) ); - keep->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::keepPressed) ); - reset->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetPressed) ); - resetAll->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetAllPressed) ); - add->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::addPressed) ); - - show_all (); + exifTree->append_column (*viewcolv); + + pack_start (*scrolledWindow); + + Gtk::HBox* buttons1 = Gtk::manage(new Gtk::HBox ()); + Gtk::HBox* buttons2 = Gtk::manage(new Gtk::HBox ()); + + remove = Gtk::manage(new Gtk::Button (M("EXIFPANEL_REMOVE"))); + remove->set_image (*Gtk::manage(new Gtk::Image (delicon))); + remove->set_tooltip_text (M("EXIFPANEL_REMOVEHINT")); + buttons1->pack_start (*remove); + + keep = Gtk::manage(new Gtk::Button (M("EXIFPANEL_KEEP"))); + keep->set_image (*Gtk::manage(new Gtk::Image (keepicon))); + keep->set_tooltip_text (M("EXIFPANEL_KEEPHINT")); + buttons1->pack_start (*keep); + + add = Gtk::manage(new Gtk::Button (M("EXIFPANEL_ADDEDIT"))); + add->set_image (*Gtk::manage(new Gtk::Image (editicon))); + add->set_tooltip_text (M("EXIFPANEL_ADDEDITHINT")); + buttons1->pack_start (*add); + + reset = Gtk::manage(new Gtk::Button (M("EXIFPANEL_RESET"))); + reset->set_image (*Gtk::manage(new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); + reset->set_tooltip_text (M("EXIFPANEL_RESETHINT")); + buttons2->pack_start (*reset); + + resetAll = Gtk::manage(new Gtk::Button (M("EXIFPANEL_RESETALL"))); + resetAll->set_image (*Gtk::manage(new RTImage ("gtk-undoall-ltr.png", "gtk-undoall-rtl.png"))); + resetAll->set_tooltip_text (M("EXIFPANEL_RESETALLHINT")); + buttons2->pack_start (*resetAll); + + pack_end (*buttons2, Gtk::PACK_SHRINK); + pack_end (*buttons1, Gtk::PACK_SHRINK); + + exifTree->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &ExifPanel::exifSelectionChanged)); + exifTree->signal_row_activated().connect(sigc::mem_fun(*this, &ExifPanel::row_activated)); + + remove->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::removePressed) ); + keep->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::keepPressed) ); + reset->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetPressed) ); + resetAll->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetAllPressed) ); + add->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::addPressed) ); + + show_all (); } -ExifPanel::~ExifPanel () { +ExifPanel::~ExifPanel () +{ } -void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -130,40 +133,46 @@ void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { setImageData (idata); applyChangeList (); exifSelectionChanged (); - + enableListener (); } -void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited) { - +void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited) +{ + // updateChangeList (); pp->exif = changeList; } -void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ defChangeList = defParams->exif; } - -void ExifPanel::setImageData (const ImageMetaData* id) { - - idata = id; + +void ExifPanel::setImageData (const ImageMetaData* id) +{ + + idata = id; exifTreeModel->clear (); const std::vector& defTags = ExifManager::getDefaultTIFFTags (NULL); - for (size_t i=0; inameToString() == "ImageWidth" || defTags[i]->nameToString() == "ImageHeight" || defTags[i]->nameToString() == "BitsPerSample") + + for (size_t i = 0; i < defTags.size(); i++) + if (defTags[i]->nameToString() == "ImageWidth" || defTags[i]->nameToString() == "ImageHeight" || defTags[i]->nameToString() == "BitsPerSample") { addTag (exifTreeModel->children(), defTags[i]->nameToString(), "?", AC_SYSTEM, false); - else + } else { addTag (exifTreeModel->children(), defTags[i]->nameToString(), defTags[i]->valueToString(), AC_SYSTEM, false); - + } + if (id && id->getExifData ()) { -// id->getExifData ()->printAll (); +// id->getExifData ()->printAll (); addDirectory (id->getExifData (), exifTreeModel->children()); } } -Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable) { +Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable) +{ Gtk::TreeModel::Row row = *(exifTreeModel->append(root)); row[exifColumns.action] = action; @@ -172,123 +181,141 @@ Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root row[exifColumns.field_nopango] = field; row[exifColumns.value_nopango] = value; row[exifColumns.orig_value] = value; - - if (action==AC_WRITE) + + if (action == AC_WRITE) { row[exifColumns.icon] = keepicon; - else if (action==AC_DONTWRITE) + } else if (action == AC_DONTWRITE) { row[exifColumns.icon] = delicon; - + } + if (editable) { row[exifColumns.field] = Glib::ustring("") + escapeHtmlChars(field) + ""; row[exifColumns.value] = Glib::ustring("") + escapeHtmlChars(value) + ""; - } - else if (action==AC_SYSTEM) { + } else if (action == AC_SYSTEM) { row[exifColumns.field] = Glib::ustring("") + escapeHtmlChars(field) + ""; row[exifColumns.value] = Glib::ustring("") + escapeHtmlChars(value) + ""; - } - else { + } else { row[exifColumns.field] = escapeHtmlChars(field); row[exifColumns.value] = escapeHtmlChars(value); } - + return row.children(); } -void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root) { +void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root) +{ - for (int i=0; igetCount(); i++) { - Tag* t = (const_cast(dir))->getTagByIndex (i); - if (t->getAttrib() && t->getAttrib()->action==AC_SYSTEM) + for (int i = 0; i < dir->getCount(); i++) { + Tag* t = (const_cast(dir))->getTagByIndex (i); + + if (t->getAttrib() && t->getAttrib()->action == AC_SYSTEM) { continue; - if (t->isDirectory()) - for (int j=0; t->getDirectory(j); j++) { + } + + if (t->isDirectory()) + for (int j = 0; t->getDirectory(j); j++) { Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M("EXIFPANEL_SUBDIRECTORY"), t->getAttrib() ? t->getAttrib()->action : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); addDirectory (t->getDirectory(j), ch); } - else - addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? (t->getOwnMemory()?t->getAttrib()->action:AC_SYSTEM) : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); + else { + addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? (t->getOwnMemory() ? t->getAttrib()->action : AC_SYSTEM) : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); + } } } -void ExifPanel::exifSelectionChanged () { +void ExifPanel::exifSelectionChanged () +{ Glib::RefPtr selection = exifTree->get_selection(); std::vector sel = selection->get_selected_rows(); - if (sel.size()>1) { + + if (sel.size() > 1) { remove->set_sensitive (1); keep->set_sensitive (1); reset->set_sensitive (1); - } - else if (sel.size()==1) { + } else if (sel.size() == 1) { Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (sel[0]); - if (iter->get_value (exifColumns.action)==AC_SYSTEM) { + + if (iter->get_value (exifColumns.action) == AC_SYSTEM) { remove->set_sensitive (0); keep->set_sensitive (0); reset->set_sensitive (0); - } - else if (!iter->children().empty()) { + } else if (!iter->children().empty()) { remove->set_sensitive (1); keep->set_sensitive (1); reset->set_sensitive (1); - } - else if (iter->get_value(exifColumns.icon)==delicon) { + } else if (iter->get_value(exifColumns.icon) == delicon) { remove->set_sensitive (0); keep->set_sensitive (1); reset->set_sensitive (1); - } - else if (iter->get_value(exifColumns.icon)==keepicon || iter->get_value(exifColumns.icon)==editicon) { + } else if (iter->get_value(exifColumns.icon) == keepicon || iter->get_value(exifColumns.icon) == editicon) { keep->set_sensitive (0); remove->set_sensitive (1); reset->set_sensitive (1); } - } - else { + } else { remove->set_sensitive (0); keep->set_sensitive (0); reset->set_sensitive (0); } } -void ExifPanel::delIt (Gtk::TreeModel::iterator iter) { - - if (!iter) - return; +void ExifPanel::delIt (Gtk::TreeModel::iterator iter) +{ - if (iter->get_value (exifColumns.action) != AC_SYSTEM) + if (!iter) { + return; + } + + if (iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, delicon); + } + if (recursiveOp) - for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++) + for (Gtk::TreeModel::iterator i = iter->children().begin(); i != iter->children().end(); i++) { delIt (i); + } } -void ExifPanel::removePressed () { +void ExifPanel::removePressed () +{ std::vector sel = exifTree->get_selection()->get_selected_rows(); - for (size_t i=0; iget_iter (sel[i])); + } exifSelectionChanged (); updateChangeList (); notifyListener (); } -void ExifPanel::keepIt (Gtk::TreeModel::iterator iter) { - - if (!iter) - return; +void ExifPanel::keepIt (Gtk::TreeModel::iterator iter) +{ - if (iter->get_value (exifColumns.action) != AC_SYSTEM) + if (!iter) { + return; + } + + if (iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, iter->get_value (exifColumns.edited) ? editicon : keepicon); + } + if (recursiveOp) - for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++) + for (Gtk::TreeModel::iterator i = iter->children().begin(); i != iter->children().end(); i++) { keepIt (i); + } } -void ExifPanel::keepPressed () { +void ExifPanel::keepPressed () +{ std::vector sel = exifTree->get_selection()->get_selected_rows(); - for (size_t i=0; iget_iter (sel[i])); + } exifSelectionChanged (); updateChangeList (); @@ -296,7 +323,7 @@ void ExifPanel::keepPressed () { } /*void ExifPanel::resetIt (Gtk::TreeModel::iterator iter) { - + if (!iter) return; @@ -309,46 +336,56 @@ void ExifPanel::keepPressed () { } if (iter->get_value (exifColumns.action)==AC_INVALID) exifTreeModel->erase (iter); - else + else if (recursiveOp) for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++) resetIt (i); }*/ -Gtk::TreeModel::iterator ExifPanel::resetIt (Gtk::TreeModel::iterator iter) { - - if (!iter) - return iter; +Gtk::TreeModel::iterator ExifPanel::resetIt (Gtk::TreeModel::iterator iter) +{ - if (iter->get_value (exifColumns.action)!=AC_SYSTEM) + if (!iter) { + return iter; + } + + if (iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, iter->get_value (exifColumns.action) ? keepicon : delicon); + } + if (iter->get_value (exifColumns.edited)) { iter->set_value (exifColumns.value, Glib::ustring("") + iter->get_value(exifColumns.orig_value) + ""); iter->set_value (exifColumns.value_nopango, iter->get_value(exifColumns.orig_value)); iter->set_value (exifColumns.edited, false); } - if (iter->get_value (exifColumns.action)==AC_INVALID) { + + if (iter->get_value (exifColumns.action) == AC_INVALID) { return exifTreeModel->erase (iter); - } - else - if (recursiveOp) { + } else if (recursiveOp) { Gtk::TreeModel::iterator i = iter->children().begin(); - while (i && i != iter->children().end()) + + while (i && i != iter->children().end()) { i = resetIt (i); + } } + return ++iter; } -void ExifPanel::resetPressed () { +void ExifPanel::resetPressed () +{ std::vector sel = exifTree->get_selection()->get_selected_rows(); - for (size_t i=0; iget_iter (sel[i])); + } exifSelectionChanged (); updateChangeList (); notifyListener (); } -void ExifPanel::resetAllPressed () { +void ExifPanel::resetAllPressed () +{ setImageData (idata); changeList = defChangeList; @@ -357,43 +394,47 @@ void ExifPanel::resetAllPressed () { notifyListener (); } -void ExifPanel::addPressed () { +void ExifPanel::addPressed () +{ Gtk::Dialog* dialog = new Gtk::Dialog (M("EXIFPANEL_ADDTAGDLG_TITLE"), *((Gtk::Window*)get_toplevel()), true, true); - dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); dialog->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - + Gtk::HBox* hb1 = new Gtk::HBox (); Gtk::HBox* hb2 = new Gtk::HBox (); - - Gtk::Label* tlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_SELECTTAG")+":"); + + Gtk::Label* tlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":"); MyComboBoxText* tcombo = new MyComboBoxText (); - + tcombo->append_text ("Artist"); tcombo->append_text ("Copyright"); tcombo->append_text ("ImageDescription"); tcombo->append_text ("Exif.UserComment"); - + hb1->pack_start (*tlabel, Gtk::PACK_SHRINK, 4); hb1->pack_start (*tcombo); - Gtk::Label* vlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_ENTERVALUE")+":"); + Gtk::Label* vlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_ENTERVALUE") + ":"); Gtk::Entry* ventry = new Gtk::Entry (); hb2->pack_start (*vlabel, Gtk::PACK_SHRINK, 4); hb2->pack_start (*ventry); Glib::ustring sel = getSelection (true); - if (sel=="") + + if (sel == "") { tcombo->set_active_text ("Exif.UserComment"); - else { + } else { tcombo->set_active_text (sel); - if (tcombo->get_active ()<0) { + + if (tcombo->get_active () < 0) { tcombo->append_text (sel); tcombo->set_active_text (sel); } + ventry->set_text (getSelectedValue ()); } - + ventry->set_activates_default (true); dialog->set_default_response (Gtk::RESPONSE_OK); dialog->get_vbox()->pack_start (*hb1, Gtk::PACK_SHRINK); @@ -404,37 +445,41 @@ void ExifPanel::addPressed () { ventry->show (); hb1->show (); hb2->show (); - - if (dialog->run ()== Gtk::RESPONSE_OK) { + + if (dialog->run () == Gtk::RESPONSE_OK) { editTag (exifTreeModel->children(), tcombo->get_active_text(), ventry->get_text()); updateChangeList (); notifyListener (); } - + delete dialog; delete tlabel; - delete tcombo; + delete tcombo; delete vlabel; - delete ventry; + delete ventry; delete hb1; - delete hb2; + delete hb2; } -void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value) { +void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value) +{ Glib::ustring::size_type dp = name.find_first_of ('.'); - Glib::ustring fseg = name.substr (0,dp); + Glib::ustring fseg = name.substr (0, dp); // look up first segment of the path Gtk::TreeModel::iterator iter; - for (iter = root.begin(); iter!=root.end(); iter++) - if (iter->get_value (exifColumns.field_nopango) == fseg) + + for (iter = root.begin(); iter != root.end(); iter++) + if (iter->get_value (exifColumns.field_nopango) == fseg) { break; - - if (iter==root.end() && value!="#keep" && value!="#delete") { + } + + if (iter == root.end() && value != "#keep" && value != "#delete") { iter = exifTreeModel->append(root); iter->set_value (exifColumns.field_nopango, fseg); iter->set_value (exifColumns.action, AC_INVALID); - if (dp==Glib::ustring::npos) { + + if (dp == Glib::ustring::npos) { iter->set_value (exifColumns.value, Glib::ustring("") + value + ""); iter->set_value (exifColumns.value_nopango, value); iter->set_value (exifColumns.orig_value, value); @@ -442,8 +487,7 @@ void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib iter->set_value (exifColumns.edited, true); iter->set_value (exifColumns.editable, true); iter->set_value (exifColumns.icon, editicon); - } - else { + } else { iter->set_value (exifColumns.value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); iter->set_value (exifColumns.value_nopango, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); iter->set_value (exifColumns.field, fseg); @@ -451,108 +495,139 @@ void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib iter->set_value (exifColumns.orig_value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); } } - - if (dp==Glib::ustring::npos) { - if (value=="#keep" && iter->get_value (exifColumns.action)!=AC_SYSTEM) + + if (dp == Glib::ustring::npos) { + if (value == "#keep" && iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, iter->get_value (exifColumns.edited) ? editicon : keepicon); - else if (value=="#delete" && iter->get_value (exifColumns.action)!=AC_SYSTEM) + } else if (value == "#delete" && iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, delicon); - else { + } else { iter->set_value (exifColumns.value, Glib::ustring("") + value + ""); iter->set_value (exifColumns.value_nopango, value); iter->set_value (exifColumns.edited, true); iter->set_value (exifColumns.icon, editicon); } + } else { + editTag (iter->children(), name.substr (dp + 1, Glib::ustring::npos), value); } - else - editTag (iter->children(), name.substr (dp+1, Glib::ustring::npos), value); } -Glib::ustring ExifPanel::getSelectedValue () { +Glib::ustring ExifPanel::getSelectedValue () +{ Glib::RefPtr selection = exifTree->get_selection(); - std::vector rows = selection->get_selected_rows(); - if (rows.size()!=1) - return ""; + std::vector rows = selection->get_selected_rows(); + + if (rows.size() != 1) { + return ""; + } + Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]); - if (iter) + + if (iter) { return iter->get_value (exifColumns.value_nopango); + } + return ""; } -Glib::ustring ExifPanel::getSelection (bool onlyeditable) { +Glib::ustring ExifPanel::getSelection (bool onlyeditable) +{ Glib::RefPtr selection = exifTree->get_selection(); - std::vector rows = selection->get_selected_rows(); + std::vector rows = selection->get_selected_rows(); + + if (rows.size() != 1) { + return ""; + } - if (rows.size()!=1) - return ""; Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]); Glib::ustring ret = ""; bool first = true; bool editable = false; + while (iter) { - if (first) + if (first) { ret = iter->get_value (exifColumns.field_nopango); - else + } else { ret = iter->get_value (exifColumns.field_nopango) + "." + ret; + } + editable = iter->get_value (exifColumns.editable); iter = iter->parent (); first = false; } - if (!editable && onlyeditable) + + if (!editable && onlyeditable) { return ""; + } + return ret; } -void ExifPanel::updateChangeList (Gtk::TreeModel::Children root, std::string prefix) { +void ExifPanel::updateChangeList (Gtk::TreeModel::Children root, std::string prefix) +{ - if (prefix!="") + if (prefix != "") { prefix = prefix + "."; + } Gtk::TreeModel::iterator iter; - for (iter = root.begin(); iter!=root.end(); iter++) { - if (iter->get_value (exifColumns.edited) == true) - changeList[ prefix+iter->get_value (exifColumns.field_nopango) ] = iter->get_value (exifColumns.value_nopango); - else if (iter->get_value (exifColumns.action) == AC_WRITE && iter->get_value (exifColumns.icon) == delicon) - changeList[ prefix+iter->get_value (exifColumns.field_nopango) ] = "#delete"; - else if (iter->get_value (exifColumns.action) == AC_DONTWRITE && iter->get_value (exifColumns.icon) == keepicon) - changeList[ prefix+iter->get_value (exifColumns.field_nopango) ] = "#keep"; - if (iter->get_value (exifColumns.icon) == keepicon) + + for (iter = root.begin(); iter != root.end(); iter++) { + if (iter->get_value (exifColumns.edited) == true) { + changeList[ prefix + iter->get_value (exifColumns.field_nopango) ] = iter->get_value (exifColumns.value_nopango); + } else if (iter->get_value (exifColumns.action) == AC_WRITE && iter->get_value (exifColumns.icon) == delicon) { + changeList[ prefix + iter->get_value (exifColumns.field_nopango) ] = "#delete"; + } else if (iter->get_value (exifColumns.action) == AC_DONTWRITE && iter->get_value (exifColumns.icon) == keepicon) { + changeList[ prefix + iter->get_value (exifColumns.field_nopango) ] = "#keep"; + } + + if (iter->get_value (exifColumns.icon) == keepicon) { updateChangeList (iter->children(), prefix + iter->get_value (exifColumns.field_nopango)); + } } } -void ExifPanel::updateChangeList () { +void ExifPanel::updateChangeList () +{ changeList.clear (); updateChangeList (exifTreeModel->children(), ""); } -void ExifPanel::applyChangeList () { +void ExifPanel::applyChangeList () +{ - for (rtengine::procparams::ExifPairs::iterator i=changeList.begin(); i!=changeList.end(); i++) + for (rtengine::procparams::ExifPairs::iterator i = changeList.begin(); i != changeList.end(); i++) { editTag (exifTreeModel->children(), i->first, i->second); + } } -void ExifPanel::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) { +void ExifPanel::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) +{ Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (path); + if (iter) { if (!iter->children().empty()) - if (exifTree->row_expanded (path)) + if (exifTree->row_expanded (path)) { exifTree->collapse_row (path); - else + } else { exifTree->expand_row (path, false); - else if (iter->get_value (exifColumns.editable)) + } + else if (iter->get_value (exifColumns.editable)) { addPressed (); + } } } -void ExifPanel::notifyListener () { - - if (listener) +void ExifPanel::notifyListener () +{ + + if (listener) { listener->panelChanged (EvExif, M("HISTORY_CHANGED")); + } } diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index 1a5513031..2269fed25 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -7,7 +7,7 @@ * 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 @@ -22,75 +22,88 @@ #include #include "toolpanel.h" -class ExifPanel : public Gtk::VBox, public ToolPanel { +class ExifPanel : public Gtk::VBox, public ToolPanel +{ - private: - const rtengine::ImageMetaData* idata; - int fullw, fullh, cx, cy, cw, ch; - bool crenabled; - rtengine::procparams::ExifPairs changeList; - rtengine::procparams::ExifPairs defChangeList; - bool recursiveOp; +private: + const rtengine::ImageMetaData* idata; + int fullw, fullh, cx, cy, cw, ch; + bool crenabled; + rtengine::procparams::ExifPairs changeList; + rtengine::procparams::ExifPairs defChangeList; + bool recursiveOp; - class ExifColumns : public Gtk::TreeModelColumnRecord { - public: - Gtk::TreeModelColumn > icon; - Gtk::TreeModelColumn field; - Gtk::TreeModelColumn field_nopango; - Gtk::TreeModelColumn value; - Gtk::TreeModelColumn value_nopango; - Gtk::TreeModelColumn orig_value; - Gtk::TreeModelColumn action; - Gtk::TreeModelColumn editable; - Gtk::TreeModelColumn edited; - - ExifColumns() { add(field); add(value); add(icon); add(action); add(edited); add(field_nopango); add(value_nopango); add(editable); add(orig_value); } - }; - Glib::RefPtr delicon; - Glib::RefPtr keepicon; - Glib::RefPtr editicon; - - ExifColumns exifColumns; - Gtk::TreeView* exifTree; - Gtk::ScrolledWindow* scrolledWindow; - Glib::RefPtr exifTreeModel; - - Gtk::Button* remove; - Gtk::Button* keep; - Gtk::Button* add; - Gtk::Button* reset; - Gtk::Button* resetAll; - - Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable); - void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value); - void updateChangeList (Gtk::TreeModel::Children root, std::string prefix); - void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root); - Glib::ustring getSelection (bool onlyifeditable=false); - Glib::ustring getSelectedValue (); - void updateChangeList (); - void applyChangeList (); - void keepIt (Gtk::TreeModel::iterator iter); - void delIt (Gtk::TreeModel::iterator iter); - Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter); + class ExifColumns : public Gtk::TreeModelColumnRecord + { public: - ExifPanel (); - virtual ~ExifPanel (); + Gtk::TreeModelColumn > icon; + Gtk::TreeModelColumn field; + Gtk::TreeModelColumn field_nopango; + Gtk::TreeModelColumn value; + Gtk::TreeModelColumn value_nopango; + Gtk::TreeModelColumn orig_value; + Gtk::TreeModelColumn action; + Gtk::TreeModelColumn editable; + Gtk::TreeModelColumn edited; - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + ExifColumns() + { + add(field); + add(value); + add(icon); + add(action); + add(edited); + add(field_nopango); + add(value_nopango); + add(editable); + add(orig_value); + } + }; + Glib::RefPtr delicon; + Glib::RefPtr keepicon; + Glib::RefPtr editicon; - void setImageData (const rtengine::ImageMetaData* id); + ExifColumns exifColumns; + Gtk::TreeView* exifTree; + Gtk::ScrolledWindow* scrolledWindow; + Glib::RefPtr exifTreeModel; - void exifSelectionChanged (); - void removePressed (); - void keepPressed (); - void resetPressed (); - void resetAllPressed (); - void addPressed (); - void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); + Gtk::Button* remove; + Gtk::Button* keep; + Gtk::Button* add; + Gtk::Button* reset; + Gtk::Button* resetAll; - void notifyListener (); + Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable); + void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value); + void updateChangeList (Gtk::TreeModel::Children root, std::string prefix); + void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root); + Glib::ustring getSelection (bool onlyifeditable = false); + Glib::ustring getSelectedValue (); + void updateChangeList (); + void applyChangeList (); + void keepIt (Gtk::TreeModel::iterator iter); + void delIt (Gtk::TreeModel::iterator iter); + Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter); +public: + ExifPanel (); + virtual ~ExifPanel (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + + void setImageData (const rtengine::ImageMetaData* id); + + void exifSelectionChanged (); + void removePressed (); + void keepPressed (); + void resetPressed (); + void resetAllPressed (); + void addPressed (); + void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); + + void notifyListener (); }; diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc index 28e80e1c4..67ea092f2 100644 --- a/rtgui/exportpanel.cc +++ b/rtgui/exportpanel.cc @@ -3,7 +3,7 @@ * * Copyright (c) 2004-2010 Gabor Horvath * Copyright (c) 2012 Michael Ezra - * + * * 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 @@ -21,142 +21,147 @@ #include "multilangmgr.h" #include "options.h" #include "rtimage.h" - + using namespace rtengine; using namespace rtengine::procparams; -ExportPanel::ExportPanel () : listener (NULL) { +ExportPanel::ExportPanel () : listener (NULL) +{ - set_border_width (4); + set_border_width (4); - /*enabled = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_ENABLE")) ); - pack_start(*enabled, Gtk::PACK_SHRINK, 4); - pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2);*/ + /*enabled = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_ENABLE")) ); + pack_start(*enabled, Gtk::PACK_SHRINK, 4); + pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2);*/ - Gtk::Label* labExportTitle = Gtk::manage ( new Gtk::Label (M("EXPORT_FASTEXPORTOPTIONS")) ); - labExportTitle->set_use_markup (true); - labExportTitle->set_tooltip_text (M("EXPORT_INSTRUCTIONS")); - labExportTitle->set_alignment(Gtk::ALIGN_LEFT); - pack_start(*labExportTitle, Gtk::PACK_SHRINK, 4); + Gtk::Label* labExportTitle = Gtk::manage ( new Gtk::Label (M("EXPORT_FASTEXPORTOPTIONS")) ); + labExportTitle->set_use_markup (true); + labExportTitle->set_tooltip_text (M("EXPORT_INSTRUCTIONS")); + labExportTitle->set_alignment(Gtk::ALIGN_LEFT); + pack_start(*labExportTitle, Gtk::PACK_SHRINK, 4); - bypass_ALL = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_ALL"))); - bypass_sharpening = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENING"))); - bypass_sharpenEdge = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENEDGE"))); - bypass_sharpenMicro = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENMICRO"))); - //bypass_lumaDenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_LUMADENOISE"))); - //bypass_colorDenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_COLORDENOISE"))); - bypass_defringe = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_DEFRINGE"))); - bypass_dirpyrDenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_DIRPYRDENOISE"))); - bypass_sh_hq = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SH_HQ"))); - bypass_dirpyrequalizer = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_DIRPYREQUALIZER"))); - bypass_wavelet = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_EQUALIZER"))); - bypass_raw_ccSteps = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_CCSTEPS"))); - bypass_raw_ca = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_CA"))); - bypass_raw_df = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DF"))); - bypass_raw_ff = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_FF"))); + bypass_ALL = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_ALL"))); + bypass_sharpening = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENING"))); + bypass_sharpenEdge = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENEDGE"))); + bypass_sharpenMicro = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SHARPENMICRO"))); + //bypass_lumaDenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_LUMADENOISE"))); + //bypass_colorDenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_COLORDENOISE"))); + bypass_defringe = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_DEFRINGE"))); + bypass_dirpyrDenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_DIRPYRDENOISE"))); + bypass_sh_hq = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_SH_HQ"))); + bypass_dirpyrequalizer = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_DIRPYREQUALIZER"))); + bypass_wavelet = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_EQUALIZER"))); + bypass_raw_ccSteps = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_CCSTEPS"))); + bypass_raw_ca = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_CA"))); + bypass_raw_df = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DF"))); + bypass_raw_ff = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_FF"))); - // ---------------------- Bayer sensor frame ----------------------- + // ---------------------- Bayer sensor frame ----------------------- - Gtk::Frame *bayerFrame = Gtk::manage( new Gtk::Frame(M("TP_RAW_SENSOR_BAYER"))); - Gtk::VBox* bayerFrameVBox = Gtk::manage (new Gtk::VBox ()); + Gtk::Frame *bayerFrame = Gtk::manage( new Gtk::Frame(M("TP_RAW_SENSOR_BAYER"))); + Gtk::VBox* bayerFrameVBox = Gtk::manage (new Gtk::VBox ()); - Gtk::HBox* hb_raw_bayer_method = Gtk::manage (new Gtk::HBox ()); - hb_raw_bayer_method->pack_start (*Gtk::manage (new Gtk::Label ( M("EXPORT_RAW_DMETHOD") +": ")),Gtk::PACK_SHRINK, 4); - raw_bayer_method = Gtk::manage (new MyComboBoxText ()); - for( size_t i=0; i< procparams::RAWParams::BayerSensor::numMethods;i++) - raw_bayer_method->append_text(procparams::RAWParams::BayerSensor::methodstring[i]); + Gtk::HBox* hb_raw_bayer_method = Gtk::manage (new Gtk::HBox ()); + hb_raw_bayer_method->pack_start (*Gtk::manage (new Gtk::Label ( M("EXPORT_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + raw_bayer_method = Gtk::manage (new MyComboBoxText ()); - raw_bayer_method->set_active(0); - hb_raw_bayer_method->pack_end (*raw_bayer_method, Gtk::PACK_EXPAND_WIDGET, 4); + for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) { + raw_bayer_method->append_text(procparams::RAWParams::BayerSensor::methodstring[i]); + } - //bypass_raw_all_enhance = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_ALL_ENHANCE"))); - bypass_raw_bayer_linenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_LINENOISE"))); - bypass_raw_bayer_greenthresh = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_GREENTHRESH"))); - bypass_raw_bayer_dcb_iterations = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DCB_ITERATIONS"))); - bypass_raw_bayer_dcb_enhance = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DCB_ENHANCE"))); - bypass_raw_bayer_lmmse_iterations = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_LMMSE_ITERATIONS"))); + raw_bayer_method->set_active(0); + hb_raw_bayer_method->pack_end (*raw_bayer_method, Gtk::PACK_EXPAND_WIDGET, 4); - // ---------------------- Bayer sensor frame ----------------------- + //bypass_raw_all_enhance = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_ALL_ENHANCE"))); + bypass_raw_bayer_linenoise = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_LINENOISE"))); + bypass_raw_bayer_greenthresh = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_GREENTHRESH"))); + bypass_raw_bayer_dcb_iterations = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DCB_ITERATIONS"))); + bypass_raw_bayer_dcb_enhance = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DCB_ENHANCE"))); + bypass_raw_bayer_lmmse_iterations = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_LMMSE_ITERATIONS"))); - Gtk::Frame *xtransFrame = Gtk::manage( new Gtk::Frame(M("TP_RAW_SENSOR_XTRANS"))); - Gtk::VBox* xtransFrameVBox = Gtk::manage (new Gtk::VBox ()); + // ---------------------- Bayer sensor frame ----------------------- - Gtk::HBox* hb_raw_xtrans_method = Gtk::manage (new Gtk::HBox ()); - hb_raw_xtrans_method->pack_start (*Gtk::manage (new Gtk::Label ( M("EXPORT_RAW_DMETHOD") +": ")),Gtk::PACK_SHRINK, 4); - raw_xtrans_method = Gtk::manage (new MyComboBoxText ()); - for( size_t i=0; i< procparams::RAWParams::XTransSensor::numMethods;i++) - raw_xtrans_method->append_text(procparams::RAWParams::XTransSensor::methodstring[i]); + Gtk::Frame *xtransFrame = Gtk::manage( new Gtk::Frame(M("TP_RAW_SENSOR_XTRANS"))); + Gtk::VBox* xtransFrameVBox = Gtk::manage (new Gtk::VBox ()); - raw_xtrans_method->set_active(0); - hb_raw_xtrans_method->pack_end (*raw_xtrans_method, Gtk::PACK_EXPAND_WIDGET, 4); + Gtk::HBox* hb_raw_xtrans_method = Gtk::manage (new Gtk::HBox ()); + hb_raw_xtrans_method->pack_start (*Gtk::manage (new Gtk::Label ( M("EXPORT_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + raw_xtrans_method = Gtk::manage (new MyComboBoxText ()); - // ---------------------------------------------------------------- + for( size_t i = 0; i < procparams::RAWParams::XTransSensor::numMethods; i++) { + raw_xtrans_method->append_text(procparams::RAWParams::XTransSensor::methodstring[i]); + } - // start global packing - pack_start(*bypass_ALL , Gtk::PACK_SHRINK, 4); - pack_start(*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 4); - pack_start(*bypass_sharpening , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_sharpenEdge , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_sharpenMicro , Gtk::PACK_SHRINK, 4); - //pack_start(*bypass_lumaDenoise , Gtk::PACK_SHRINK, 4); - //pack_start(*bypass_colorDenoise , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_defringe , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_dirpyrDenoise, Gtk::PACK_SHRINK, 4); - pack_start(*bypass_sh_hq , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_dirpyrequalizer , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_wavelet , Gtk::PACK_SHRINK, 4); + raw_xtrans_method->set_active(0); + hb_raw_xtrans_method->pack_end (*raw_xtrans_method, Gtk::PACK_EXPAND_WIDGET, 4); - bayerFrameVBox->pack_start(*hb_raw_bayer_method, Gtk::PACK_SHRINK, 4); - //bayerFrameVBox->pack_start(*bypass_raw_all_enhance , Gtk::PACK_SHRINK, 4); - bayerFrameVBox->pack_start(*bypass_raw_bayer_dcb_iterations, Gtk::PACK_SHRINK, 4); - bayerFrameVBox->pack_start(*bypass_raw_bayer_dcb_enhance , Gtk::PACK_SHRINK, 4); - bayerFrameVBox->pack_start(*bypass_raw_bayer_lmmse_iterations, Gtk::PACK_SHRINK, 4); - bayerFrameVBox->pack_start(*bypass_raw_bayer_linenoise , Gtk::PACK_SHRINK, 4); - bayerFrameVBox->pack_start(*bypass_raw_bayer_greenthresh , Gtk::PACK_SHRINK, 4); - bayerFrame->add(*bayerFrameVBox); + // ---------------------------------------------------------------- - xtransFrameVBox->pack_start(*hb_raw_xtrans_method, Gtk::PACK_SHRINK, 4); - xtransFrame->add(*xtransFrameVBox); + // start global packing + pack_start(*bypass_ALL , Gtk::PACK_SHRINK, 4); + pack_start(*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 4); + pack_start(*bypass_sharpening , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_sharpenEdge , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_sharpenMicro , Gtk::PACK_SHRINK, 4); + //pack_start(*bypass_lumaDenoise , Gtk::PACK_SHRINK, 4); + //pack_start(*bypass_colorDenoise , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_defringe , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_dirpyrDenoise, Gtk::PACK_SHRINK, 4); + pack_start(*bypass_sh_hq , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_dirpyrequalizer , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_wavelet , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_raw_ccSteps , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_raw_ca , Gtk::PACK_SHRINK, 4); + bayerFrameVBox->pack_start(*hb_raw_bayer_method, Gtk::PACK_SHRINK, 4); + //bayerFrameVBox->pack_start(*bypass_raw_all_enhance , Gtk::PACK_SHRINK, 4); + bayerFrameVBox->pack_start(*bypass_raw_bayer_dcb_iterations, Gtk::PACK_SHRINK, 4); + bayerFrameVBox->pack_start(*bypass_raw_bayer_dcb_enhance , Gtk::PACK_SHRINK, 4); + bayerFrameVBox->pack_start(*bypass_raw_bayer_lmmse_iterations, Gtk::PACK_SHRINK, 4); + bayerFrameVBox->pack_start(*bypass_raw_bayer_linenoise , Gtk::PACK_SHRINK, 4); + bayerFrameVBox->pack_start(*bypass_raw_bayer_greenthresh , Gtk::PACK_SHRINK, 4); + bayerFrame->add(*bayerFrameVBox); - pack_start(*bypass_raw_df , Gtk::PACK_SHRINK, 4); - pack_start(*bypass_raw_ff , Gtk::PACK_SHRINK, 4); + xtransFrameVBox->pack_start(*hb_raw_xtrans_method, Gtk::PACK_SHRINK, 4); + xtransFrame->add(*xtransFrameVBox); - pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2); + pack_start(*bypass_raw_ccSteps , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_raw_ca , Gtk::PACK_SHRINK, 4); - // Resize options + pack_start(*bypass_raw_df , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_raw_ff , Gtk::PACK_SHRINK, 4); - Gtk::HBox* rmbox = Gtk::manage (new Gtk::HBox ()); - rmbox->pack_start (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_LABEL"))), Gtk::PACK_SHRINK, 4); - pack_start (*rmbox, Gtk::PACK_SHRINK, 4); + pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2); - Gtk::HBox* wbox = Gtk::manage (new Gtk::HBox ()); - Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox ()); - MaxWidth = Gtk::manage (new MySpinButton ()); - MaxHeight = Gtk::manage (new MySpinButton ()); - wbox->pack_start (*Gtk::manage (new Gtk::Label (M("EXPORT_MAXWIDTH"))), Gtk::PACK_SHRINK, 4); - wbox->pack_start (*MaxWidth); - hbox->pack_start (*Gtk::manage (new Gtk::Label (M("EXPORT_MAXHEIGHT"))), Gtk::PACK_SHRINK, 4); - hbox->pack_start (*MaxHeight); - pack_start (*wbox, Gtk::PACK_SHRINK, 4); - pack_start (*hbox, Gtk::PACK_SHRINK, 4); + // Resize options - MaxWidth->set_digits (0); - MaxWidth->set_increments (1,100); - MaxWidth->set_value (options.fastexport_resize_width); - MaxWidth->set_range (32, 3000); + Gtk::HBox* rmbox = Gtk::manage (new Gtk::HBox ()); + rmbox->pack_start (*Gtk::manage (new Gtk::Label (M("TP_RESIZE_LABEL"))), Gtk::PACK_SHRINK, 4); + pack_start (*rmbox, Gtk::PACK_SHRINK, 4); - MaxHeight->set_digits (0); - MaxHeight->set_increments (1,100); - MaxHeight->set_value (options.fastexport_resize_height); - MaxHeight->set_range (32, 3000); + Gtk::HBox* wbox = Gtk::manage (new Gtk::HBox ()); + Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox ()); + MaxWidth = Gtk::manage (new MySpinButton ()); + MaxHeight = Gtk::manage (new MySpinButton ()); + wbox->pack_start (*Gtk::manage (new Gtk::Label (M("EXPORT_MAXWIDTH"))), Gtk::PACK_SHRINK, 4); + wbox->pack_start (*MaxWidth); + hbox->pack_start (*Gtk::manage (new Gtk::Label (M("EXPORT_MAXHEIGHT"))), Gtk::PACK_SHRINK, 4); + hbox->pack_start (*MaxHeight); + pack_start (*wbox, Gtk::PACK_SHRINK, 4); + pack_start (*hbox, Gtk::PACK_SHRINK, 4); - // Buttons - btnFastExport = Gtk::manage ( new Gtk::Button (M("EXPORT_PUTTOQUEUEFAST")) ); - btnFastExport->set_image (*Gtk::manage (new RTImage ("processing.png"))); - pack_start(*btnFastExport, Gtk::PACK_SHRINK, 4); + MaxWidth->set_digits (0); + MaxWidth->set_increments (1, 100); + MaxWidth->set_value (options.fastexport_resize_width); + MaxWidth->set_range (32, 3000); + + MaxHeight->set_digits (0); + MaxHeight->set_increments (1, 100); + MaxHeight->set_value (options.fastexport_resize_height); + MaxHeight->set_range (32, 3000); + + // Buttons + btnFastExport = Gtk::manage ( new Gtk::Button (M("EXPORT_PUTTOQUEUEFAST")) ); + btnFastExport->set_image (*Gtk::manage (new RTImage ("processing.png"))); + pack_start(*btnFastExport, Gtk::PACK_SHRINK, 4); // add panel ending @@ -168,135 +173,145 @@ ExportPanel::ExportPanel () : listener (NULL) { pack_start(*vboxpe, Gtk::PACK_SHRINK, 0); - btnFastExport->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::FastExportPressed) ); - //btnExportLoadSettings->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::LoadSettings) ); - //btnExportSaveSettings->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::SaveSettings) ); - bypass_ALLconn = bypass_ALL->signal_toggled().connect (sigc::mem_fun(*this, &ExportPanel::bypassALL_Toggled)); + btnFastExport->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::FastExportPressed) ); + //btnExportLoadSettings->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::LoadSettings) ); + //btnExportSaveSettings->signal_clicked().connect( sigc::mem_fun(*this, &ExportPanel::SaveSettings) ); + bypass_ALLconn = bypass_ALL->signal_toggled().connect (sigc::mem_fun(*this, &ExportPanel::bypassALL_Toggled)); - bypass_sharpeningConn = bypass_sharpening->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_sharpenEdgeConn = bypass_sharpenEdge->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_sharpenMicroConn = bypass_sharpenMicro->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - //bypass_lumaDenoiseConn = bypass_lumaDenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - //bypass_colorDenoiseConn = bypass_colorDenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_defringeConn = bypass_defringe->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_dirpyrDenoiseConn = bypass_dirpyrDenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_sh_hqConn = bypass_sh_hq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_dirpyrequalizerConn = bypass_dirpyrequalizer->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_waveletConn = bypass_wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - //bypass_raw_all_enhanceConn = bypass_raw_bayer_all_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_bayer_dcb_iterationsConn = bypass_raw_bayer_dcb_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_bayer_dcb_enhanceConn = bypass_raw_bayer_dcb_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_bayer_lmmse_iterationsConn = bypass_raw_bayer_lmmse_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_bayer_linenoiseConn = bypass_raw_bayer_linenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_bayer_greenthreshConn = bypass_raw_bayer_greenthresh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_ccStepsConn = bypass_raw_ccSteps->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_caConn = bypass_raw_ca->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_dfConn = bypass_raw_df->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - bypass_raw_ffConn = bypass_raw_ff->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_sharpeningConn = bypass_sharpening->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_sharpenEdgeConn = bypass_sharpenEdge->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_sharpenMicroConn = bypass_sharpenMicro->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + //bypass_lumaDenoiseConn = bypass_lumaDenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + //bypass_colorDenoiseConn = bypass_colorDenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_defringeConn = bypass_defringe->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_dirpyrDenoiseConn = bypass_dirpyrDenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_sh_hqConn = bypass_sh_hq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_dirpyrequalizerConn = bypass_dirpyrequalizer->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_waveletConn = bypass_wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + //bypass_raw_all_enhanceConn = bypass_raw_bayer_all_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_bayer_dcb_iterationsConn = bypass_raw_bayer_dcb_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_bayer_dcb_enhanceConn = bypass_raw_bayer_dcb_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_bayer_lmmse_iterationsConn = bypass_raw_bayer_lmmse_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_bayer_linenoiseConn = bypass_raw_bayer_linenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_bayer_greenthreshConn = bypass_raw_bayer_greenthresh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_ccStepsConn = bypass_raw_ccSteps->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_caConn = bypass_raw_ca->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_dfConn = bypass_raw_df->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_ffConn = bypass_raw_ff->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); - LoadDefaultSettings(); + LoadDefaultSettings(); } /*bool ExportPanel::isEnabled () { - return enabled->get_active () && is_sensitive(); + return enabled->get_active () && is_sensitive(); }*/ -void ExportPanel::FastExportPressed (){ - // options is the container for making these settings available globally. - // Therefore, settings must be saved to options before they are used further - SaveSettingsAsDefault(); +void ExportPanel::FastExportPressed () +{ + // options is the container for making these settings available globally. + // Therefore, settings must be saved to options before they are used further + SaveSettingsAsDefault(); - if (listener) - listener->exportRequested (); + if (listener) { + listener->exportRequested (); + } } -void ExportPanel::SaveSettingsAsDefault(){ - // Save fast export settings to options - options.fastexport_bypass_sharpening = bypass_sharpening->get_active (); - options.fastexport_bypass_sharpenEdge = bypass_sharpenEdge->get_active (); - options.fastexport_bypass_sharpenMicro = bypass_sharpenMicro->get_active (); - //options.fastexport_bypass_lumaDenoise = bypass_lumaDenoise->get_active (); - //options.fastexport_bypass_colorDenoise = bypass_colorDenoise->get_active (); - options.fastexport_bypass_defringe = bypass_defringe->get_active (); - options.fastexport_bypass_dirpyrDenoise = bypass_dirpyrDenoise->get_active (); - options.fastexport_bypass_sh_hq = bypass_sh_hq->get_active (); - options.fastexport_bypass_dirpyrequalizer = bypass_dirpyrequalizer->get_active (); - options.fastexport_bypass_wavelet = bypass_wavelet->get_active (); - //options.fastexport_bypass_raw_bayer_all_enhance = bypass_raw_all_enhance->get_active (); - options.fastexport_bypass_raw_bayer_dcb_iterations = bypass_raw_bayer_dcb_iterations->get_active (); - options.fastexport_bypass_raw_bayer_dcb_enhance = bypass_raw_bayer_dcb_enhance->get_active (); - options.fastexport_bypass_raw_bayer_lmmse_iterations = bypass_raw_bayer_lmmse_iterations->get_active(); - options.fastexport_bypass_raw_bayer_linenoise = bypass_raw_bayer_linenoise->get_active (); - options.fastexport_bypass_raw_bayer_greenthresh = bypass_raw_bayer_greenthresh->get_active (); - options.fastexport_bypass_raw_ccSteps = bypass_raw_ccSteps->get_active (); - options.fastexport_bypass_raw_ca = bypass_raw_ca->get_active (); - options.fastexport_bypass_raw_df = bypass_raw_df->get_active (); - options.fastexport_bypass_raw_ff = bypass_raw_ff->get_active (); +void ExportPanel::SaveSettingsAsDefault() +{ + // Save fast export settings to options + options.fastexport_bypass_sharpening = bypass_sharpening->get_active (); + options.fastexport_bypass_sharpenEdge = bypass_sharpenEdge->get_active (); + options.fastexport_bypass_sharpenMicro = bypass_sharpenMicro->get_active (); + //options.fastexport_bypass_lumaDenoise = bypass_lumaDenoise->get_active (); + //options.fastexport_bypass_colorDenoise = bypass_colorDenoise->get_active (); + options.fastexport_bypass_defringe = bypass_defringe->get_active (); + options.fastexport_bypass_dirpyrDenoise = bypass_dirpyrDenoise->get_active (); + options.fastexport_bypass_sh_hq = bypass_sh_hq->get_active (); + options.fastexport_bypass_dirpyrequalizer = bypass_dirpyrequalizer->get_active (); + options.fastexport_bypass_wavelet = bypass_wavelet->get_active (); + //options.fastexport_bypass_raw_bayer_all_enhance = bypass_raw_all_enhance->get_active (); + options.fastexport_bypass_raw_bayer_dcb_iterations = bypass_raw_bayer_dcb_iterations->get_active (); + options.fastexport_bypass_raw_bayer_dcb_enhance = bypass_raw_bayer_dcb_enhance->get_active (); + options.fastexport_bypass_raw_bayer_lmmse_iterations = bypass_raw_bayer_lmmse_iterations->get_active(); + options.fastexport_bypass_raw_bayer_linenoise = bypass_raw_bayer_linenoise->get_active (); + options.fastexport_bypass_raw_bayer_greenthresh = bypass_raw_bayer_greenthresh->get_active (); + options.fastexport_bypass_raw_ccSteps = bypass_raw_ccSteps->get_active (); + options.fastexport_bypass_raw_ca = bypass_raw_ca->get_active (); + options.fastexport_bypass_raw_df = bypass_raw_df->get_active (); + options.fastexport_bypass_raw_ff = bypass_raw_ff->get_active (); - //saving Bayer demosaic_method - int currentRow = raw_bayer_method->get_active_row_number(); - if( currentRow>=0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) - options.fastexport_raw_bayer_method = procparams::RAWParams::BayerSensor::methodstring[currentRow]; + //saving Bayer demosaic_method + int currentRow = raw_bayer_method->get_active_row_number(); - //saving X-Trans demosaic_method - currentRow = raw_xtrans_method->get_active_row_number(); - if( currentRow>=0 && currentRow < procparams::RAWParams::XTransSensor::numMethods) - options.fastexport_raw_xtrans_method = procparams::RAWParams::XTransSensor::methodstring[currentRow]; + if( currentRow >= 0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) { + options.fastexport_raw_bayer_method = procparams::RAWParams::BayerSensor::methodstring[currentRow]; + } -// options.fastexport_icm_input = icm_input ; -// options.fastexport_icm_working = icm_working ; -// options.fastexport_icm_output = icm_output ; -// options.fastexport_icm_gamma = icm_gamma ; -// options.fastexport_resize_enabled = resize_enabled ; -// options.fastexport_resize_scale = resize_scale ; -// options.fastexport_resize_appliesTo = resize_appliesTo; -// options.fastexport_resize_dataspec = resize_dataspec ; + //saving X-Trans demosaic_method + currentRow = raw_xtrans_method->get_active_row_number(); - options.fastexport_resize_method = "Lanczos"; - options.fastexport_resize_width = MaxWidth->get_value_as_int (); - options.fastexport_resize_height = MaxHeight->get_value_as_int (); + if( currentRow >= 0 && currentRow < procparams::RAWParams::XTransSensor::numMethods) { + options.fastexport_raw_xtrans_method = procparams::RAWParams::XTransSensor::methodstring[currentRow]; + } + +// options.fastexport_icm_input = icm_input ; +// options.fastexport_icm_working = icm_working ; +// options.fastexport_icm_output = icm_output ; +// options.fastexport_icm_gamma = icm_gamma ; +// options.fastexport_resize_enabled = resize_enabled ; +// options.fastexport_resize_scale = resize_scale ; +// options.fastexport_resize_appliesTo = resize_appliesTo; +// options.fastexport_resize_dataspec = resize_dataspec ; + + options.fastexport_resize_method = "Lanczos"; + options.fastexport_resize_width = MaxWidth->get_value_as_int (); + options.fastexport_resize_height = MaxHeight->get_value_as_int (); } -void ExportPanel::LoadDefaultSettings(){ - // Load fast export settings from options - bypass_sharpening->set_active (options.fastexport_bypass_sharpening ); - bypass_sharpenEdge->set_active (options.fastexport_bypass_sharpenEdge ); - bypass_sharpenMicro->set_active (options.fastexport_bypass_sharpenMicro ); - //bypass_lumaDenoise->set_active (options.fastexport_bypass_lumaDenoise ); - //bypass_colorDenoise->set_active (options.fastexport_bypass_colorDenoise ); - bypass_defringe->set_active (options.fastexport_bypass_defringe ); - bypass_dirpyrDenoise->set_active (options.fastexport_bypass_dirpyrDenoise ); - bypass_sh_hq->set_active (options.fastexport_bypass_sh_hq ); - bypass_dirpyrequalizer->set_active (options.fastexport_bypass_dirpyrequalizer ); - bypass_wavelet->set_active (options.fastexport_bypass_wavelet ); - //bypass_raw_bayer_all_enhance->set_active (options.fastexport_bypass_raw_bayer_all_enhance ); - bypass_raw_bayer_dcb_iterations->set_active (options.fastexport_bypass_raw_bayer_dcb_iterations ); - bypass_raw_bayer_dcb_enhance->set_active (options.fastexport_bypass_raw_bayer_dcb_enhance ); - bypass_raw_bayer_lmmse_iterations->set_active(options.fastexport_bypass_raw_bayer_lmmse_iterations); - bypass_raw_bayer_linenoise->set_active (options.fastexport_bypass_raw_bayer_linenoise ); - bypass_raw_bayer_greenthresh->set_active (options.fastexport_bypass_raw_bayer_greenthresh ); - bypass_raw_ccSteps->set_active (options.fastexport_bypass_raw_ccSteps ); - bypass_raw_ca->set_active (options.fastexport_bypass_raw_ca ); - bypass_raw_df->set_active (options.fastexport_bypass_raw_df ); - bypass_raw_ff->set_active (options.fastexport_bypass_raw_ff ); +void ExportPanel::LoadDefaultSettings() +{ + // Load fast export settings from options + bypass_sharpening->set_active (options.fastexport_bypass_sharpening ); + bypass_sharpenEdge->set_active (options.fastexport_bypass_sharpenEdge ); + bypass_sharpenMicro->set_active (options.fastexport_bypass_sharpenMicro ); + //bypass_lumaDenoise->set_active (options.fastexport_bypass_lumaDenoise ); + //bypass_colorDenoise->set_active (options.fastexport_bypass_colorDenoise ); + bypass_defringe->set_active (options.fastexport_bypass_defringe ); + bypass_dirpyrDenoise->set_active (options.fastexport_bypass_dirpyrDenoise ); + bypass_sh_hq->set_active (options.fastexport_bypass_sh_hq ); + bypass_dirpyrequalizer->set_active (options.fastexport_bypass_dirpyrequalizer ); + bypass_wavelet->set_active (options.fastexport_bypass_wavelet ); + //bypass_raw_bayer_all_enhance->set_active (options.fastexport_bypass_raw_bayer_all_enhance ); + bypass_raw_bayer_dcb_iterations->set_active (options.fastexport_bypass_raw_bayer_dcb_iterations ); + bypass_raw_bayer_dcb_enhance->set_active (options.fastexport_bypass_raw_bayer_dcb_enhance ); + bypass_raw_bayer_lmmse_iterations->set_active(options.fastexport_bypass_raw_bayer_lmmse_iterations); + bypass_raw_bayer_linenoise->set_active (options.fastexport_bypass_raw_bayer_linenoise ); + bypass_raw_bayer_greenthresh->set_active (options.fastexport_bypass_raw_bayer_greenthresh ); + bypass_raw_ccSteps->set_active (options.fastexport_bypass_raw_ccSteps ); + bypass_raw_ca->set_active (options.fastexport_bypass_raw_ca ); + bypass_raw_df->set_active (options.fastexport_bypass_raw_df ); + bypass_raw_ff->set_active (options.fastexport_bypass_raw_ff ); - // Bayer demosaic method - raw_bayer_method->set_active(procparams::RAWParams::BayerSensor::numMethods); - for( size_t i=0; i< procparams::RAWParams::BayerSensor::numMethods;i++) - if( options.fastexport_raw_bayer_method == procparams::RAWParams::BayerSensor::methodstring[i]) { - raw_bayer_method->set_active(i); - break; - } + // Bayer demosaic method + raw_bayer_method->set_active(procparams::RAWParams::BayerSensor::numMethods); - // X-Trans demosaic method - raw_xtrans_method->set_active(procparams::RAWParams::XTransSensor::numMethods); - for( size_t i=0; i< procparams::RAWParams::XTransSensor::numMethods;i++) - if( options.fastexport_raw_xtrans_method == procparams::RAWParams::XTransSensor::methodstring[i]) { - raw_xtrans_method->set_active(i); - break; - } + for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) + if( options.fastexport_raw_bayer_method == procparams::RAWParams::BayerSensor::methodstring[i]) { + raw_bayer_method->set_active(i); + break; + } + + // X-Trans demosaic method + raw_xtrans_method->set_active(procparams::RAWParams::XTransSensor::numMethods); + + for( size_t i = 0; i < procparams::RAWParams::XTransSensor::numMethods; i++) + if( options.fastexport_raw_xtrans_method == procparams::RAWParams::XTransSensor::methodstring[i]) { + raw_xtrans_method->set_active(i); + break; + } // icm_input = options.fastexport_icm_input ; // icm_working = options.fastexport_icm_working ; @@ -311,80 +326,83 @@ void ExportPanel::LoadDefaultSettings(){ MaxHeight->set_value(options.fastexport_resize_height); } -void ExportPanel::LoadSettings(){ - // load settings from file +void ExportPanel::LoadSettings() +{ + // load settings from file } -void ExportPanel::SaveSettings(){ - // save settings to file +void ExportPanel::SaveSettings() +{ + // save settings to file } -void ExportPanel::bypassALL_Toggled(){ - bypass_sharpeningConn.block (true); - bypass_sharpenEdgeConn.block (true); - bypass_sharpenMicroConn.block (true); - //bypass_lumaDenoiseConn.block (true); - //bypass_colorDenoiseConn.block (true); - bypass_defringeConn.block (true); - bypass_dirpyrDenoiseConn.block (true); - bypass_sh_hqConn.block (true); - bypass_dirpyrequalizerConn.block (true); - bypass_waveletConn.block (true); - //bypass_raw_bayer_all_enhanceConn.block (true); - bypass_raw_bayer_dcb_iterationsConn.block (true); - bypass_raw_bayer_dcb_enhanceConn.block (true); - bypass_raw_bayer_lmmse_iterationsConn.block (true); - bypass_raw_bayer_linenoiseConn.block (true); - bypass_raw_bayer_greenthreshConn.block (true); - bypass_raw_ccStepsConn.block (true); - bypass_raw_caConn.block (true); - bypass_raw_dfConn.block (true); - bypass_raw_ffConn.block (true); +void ExportPanel::bypassALL_Toggled() +{ + bypass_sharpeningConn.block (true); + bypass_sharpenEdgeConn.block (true); + bypass_sharpenMicroConn.block (true); + //bypass_lumaDenoiseConn.block (true); + //bypass_colorDenoiseConn.block (true); + bypass_defringeConn.block (true); + bypass_dirpyrDenoiseConn.block (true); + bypass_sh_hqConn.block (true); + bypass_dirpyrequalizerConn.block (true); + bypass_waveletConn.block (true); + //bypass_raw_bayer_all_enhanceConn.block (true); + bypass_raw_bayer_dcb_iterationsConn.block (true); + bypass_raw_bayer_dcb_enhanceConn.block (true); + bypass_raw_bayer_lmmse_iterationsConn.block (true); + bypass_raw_bayer_linenoiseConn.block (true); + bypass_raw_bayer_greenthreshConn.block (true); + bypass_raw_ccStepsConn.block (true); + bypass_raw_caConn.block (true); + bypass_raw_dfConn.block (true); + bypass_raw_ffConn.block (true); - bypass_ALL->set_inconsistent (false); + bypass_ALL->set_inconsistent (false); - bypass_sharpening->set_active(bypass_ALL->get_active()); - bypass_sharpenEdge->set_active(bypass_ALL->get_active()); - bypass_sharpenMicro->set_active(bypass_ALL->get_active()); - //bypass_lumaDenoise->set_active(bypass_ALL->get_active()); - //bypass_colorDenoise->set_active(bypass_ALL->get_active()); - bypass_defringe->set_active(bypass_ALL->get_active()); - bypass_dirpyrDenoise->set_active(bypass_ALL->get_active()); - bypass_sh_hq->set_active(bypass_ALL->get_active()); - bypass_dirpyrequalizer->set_active(bypass_ALL->get_active()); - bypass_wavelet->set_active(bypass_ALL->get_active()); - //bypass_raw_bayer_all_enhance->set_active(bypass_ALL->get_active()); - bypass_raw_bayer_dcb_iterations->set_active(bypass_ALL->get_active()); - bypass_raw_bayer_dcb_enhance->set_active(bypass_ALL->get_active()); - bypass_raw_bayer_lmmse_iterations->set_active(bypass_ALL->get_active()); - bypass_raw_bayer_linenoise->set_active(bypass_ALL->get_active()); - bypass_raw_bayer_greenthresh->set_active(bypass_ALL->get_active()); - bypass_raw_ccSteps->set_active(bypass_ALL->get_active()); - bypass_raw_ca->set_active(bypass_ALL->get_active()); - bypass_raw_df->set_active(bypass_ALL->get_active()); - bypass_raw_ff->set_active(bypass_ALL->get_active()); + bypass_sharpening->set_active(bypass_ALL->get_active()); + bypass_sharpenEdge->set_active(bypass_ALL->get_active()); + bypass_sharpenMicro->set_active(bypass_ALL->get_active()); + //bypass_lumaDenoise->set_active(bypass_ALL->get_active()); + //bypass_colorDenoise->set_active(bypass_ALL->get_active()); + bypass_defringe->set_active(bypass_ALL->get_active()); + bypass_dirpyrDenoise->set_active(bypass_ALL->get_active()); + bypass_sh_hq->set_active(bypass_ALL->get_active()); + bypass_dirpyrequalizer->set_active(bypass_ALL->get_active()); + bypass_wavelet->set_active(bypass_ALL->get_active()); + //bypass_raw_bayer_all_enhance->set_active(bypass_ALL->get_active()); + bypass_raw_bayer_dcb_iterations->set_active(bypass_ALL->get_active()); + bypass_raw_bayer_dcb_enhance->set_active(bypass_ALL->get_active()); + bypass_raw_bayer_lmmse_iterations->set_active(bypass_ALL->get_active()); + bypass_raw_bayer_linenoise->set_active(bypass_ALL->get_active()); + bypass_raw_bayer_greenthresh->set_active(bypass_ALL->get_active()); + bypass_raw_ccSteps->set_active(bypass_ALL->get_active()); + bypass_raw_ca->set_active(bypass_ALL->get_active()); + bypass_raw_df->set_active(bypass_ALL->get_active()); + bypass_raw_ff->set_active(bypass_ALL->get_active()); - bypass_sharpeningConn.block (false); - bypass_sharpenEdgeConn.block (false); - bypass_sharpenMicroConn.block (false); - //bypass_lumaDenoiseConn.block (false); - //bypass_colorDenoiseConn.block (false); - bypass_defringeConn.block (false); - bypass_dirpyrDenoiseConn.block (false); - bypass_sh_hqConn.block (false); - bypass_dirpyrequalizerConn.block (false); - bypass_waveletConn.block (false); - //bypass_raw_bayer_all_enhanceConn.block (false); - bypass_raw_bayer_dcb_iterationsConn.block (false); - bypass_raw_bayer_dcb_enhanceConn.block (false); - bypass_raw_bayer_lmmse_iterationsConn.block (false); - bypass_raw_bayer_linenoiseConn.block (false); - bypass_raw_bayer_greenthreshConn.block (false); - bypass_raw_ccStepsConn.block (false); - bypass_raw_caConn.block (false); - bypass_raw_dfConn.block (false); - bypass_raw_ffConn.block (false); + bypass_sharpeningConn.block (false); + bypass_sharpenEdgeConn.block (false); + bypass_sharpenMicroConn.block (false); + //bypass_lumaDenoiseConn.block (false); + //bypass_colorDenoiseConn.block (false); + bypass_defringeConn.block (false); + bypass_dirpyrDenoiseConn.block (false); + bypass_sh_hqConn.block (false); + bypass_dirpyrequalizerConn.block (false); + bypass_waveletConn.block (false); + //bypass_raw_bayer_all_enhanceConn.block (false); + bypass_raw_bayer_dcb_iterationsConn.block (false); + bypass_raw_bayer_dcb_enhanceConn.block (false); + bypass_raw_bayer_lmmse_iterationsConn.block (false); + bypass_raw_bayer_linenoiseConn.block (false); + bypass_raw_bayer_greenthreshConn.block (false); + bypass_raw_ccStepsConn.block (false); + bypass_raw_caConn.block (false); + bypass_raw_dfConn.block (false); + bypass_raw_ffConn.block (false); } /* diff --git a/rtgui/exportpanel.h b/rtgui/exportpanel.h index bdcb8a4cb..840a4638d 100644 --- a/rtgui/exportpanel.h +++ b/rtgui/exportpanel.h @@ -19,102 +19,107 @@ */ #ifndef _EXPORTPANEL_ #define _EXPORTPANEL_ - + #include #include "guiutils.h" #include "adjuster.h" -class ExportPanelListener { +class ExportPanelListener +{ - public: - virtual void exportRequested () {} +public: + virtual void exportRequested () {} }; -class ExportPanel : public Gtk::VBox { +class ExportPanel : public Gtk::VBox +{ - protected: +protected: - //Gtk::CheckButton* enabled; - Gtk::CheckButton* bypass_ALL; - Gtk::CheckButton* bypass_sharpenEdge; - Gtk::CheckButton* bypass_sharpenMicro; - Gtk::CheckButton* bypass_sharpening; - //Gtk::CheckButton* bypass_lumaDenoise; - //Gtk::CheckButton* bypass_colorDenoise; - Gtk::CheckButton* bypass_defringe; - Gtk::CheckButton* bypass_dirpyrDenoise; - Gtk::CheckButton* bypass_sh_hq; + //Gtk::CheckButton* enabled; + Gtk::CheckButton* bypass_ALL; + Gtk::CheckButton* bypass_sharpenEdge; + Gtk::CheckButton* bypass_sharpenMicro; + Gtk::CheckButton* bypass_sharpening; + //Gtk::CheckButton* bypass_lumaDenoise; + //Gtk::CheckButton* bypass_colorDenoise; + Gtk::CheckButton* bypass_defringe; + Gtk::CheckButton* bypass_dirpyrDenoise; + Gtk::CheckButton* bypass_sh_hq; -/* icm_input = "(camera)"; - icm_working = "sRGB"; - icm_output = "RT_sRGB"; - icm_gamma = "default"; -*/ - Gtk::CheckButton* bypass_dirpyrequalizer; // also could leave untouched but disable only small radius adjustments - //Gtk::CheckButton* bypass_raw_all_enhance; - Gtk::CheckButton* bypass_wavelet; // also could leave untouched but disable only small radius adjustments + /* icm_input = "(camera)"; + icm_working = "sRGB"; + icm_output = "RT_sRGB"; + icm_gamma = "default"; + */ + Gtk::CheckButton* bypass_dirpyrequalizer; // also could leave untouched but disable only small radius adjustments + //Gtk::CheckButton* bypass_raw_all_enhance; + Gtk::CheckButton* bypass_wavelet; // also could leave untouched but disable only small radius adjustments - MyComboBoxText* raw_bayer_method; + MyComboBoxText* raw_bayer_method; - Gtk::CheckButton* bypass_raw_bayer_dcb_iterations; - Gtk::CheckButton* bypass_raw_bayer_dcb_enhance; - Gtk::CheckButton* bypass_raw_bayer_lmmse_iterations; - //Gtk::CheckButton* bypass_raw_bayer_all_enhance; - Gtk::CheckButton* bypass_raw_bayer_linenoise; - Gtk::CheckButton* bypass_raw_bayer_greenthresh; + Gtk::CheckButton* bypass_raw_bayer_dcb_iterations; + Gtk::CheckButton* bypass_raw_bayer_dcb_enhance; + Gtk::CheckButton* bypass_raw_bayer_lmmse_iterations; + //Gtk::CheckButton* bypass_raw_bayer_all_enhance; + Gtk::CheckButton* bypass_raw_bayer_linenoise; + Gtk::CheckButton* bypass_raw_bayer_greenthresh; - Gtk::CheckButton* bypass_raw_ccSteps; - Gtk::CheckButton* bypass_raw_ca; //wraps raw.cared, raw.cablue, raw.ca_autocorrect - Gtk::CheckButton* bypass_raw_df; //wraps raw.dark_frame, raw.df_AutoSelect - Gtk::CheckButton* bypass_raw_ff; //wraps raw.ff_file, raw.ff_AutoSelect + Gtk::CheckButton* bypass_raw_ccSteps; + Gtk::CheckButton* bypass_raw_ca; //wraps raw.cared, raw.cablue, raw.ca_autocorrect + Gtk::CheckButton* bypass_raw_df; //wraps raw.dark_frame, raw.df_AutoSelect + Gtk::CheckButton* bypass_raw_ff; //wraps raw.ff_file, raw.ff_AutoSelect - MyComboBoxText* raw_xtrans_method; + MyComboBoxText* raw_xtrans_method; - Gtk::Button* btnFastExport; - Gtk::Button* btnExportLoadSettings; - Gtk::Button* btnExportSaveSettings; + Gtk::Button* btnFastExport; + Gtk::Button* btnExportLoadSettings; + Gtk::Button* btnExportSaveSettings; - MySpinButton* MaxWidth; - MySpinButton* MaxHeight; + MySpinButton* MaxWidth; + MySpinButton* MaxHeight; - sigc::connection enabledconn, bypass_ALLconn, FastExportconn, ExportLoadSettingsconn, ExportSaveSettingsconn; - sigc::connection bypass_sharpeningConn ; - sigc::connection bypass_sharpenEdgeConn ; - sigc::connection bypass_sharpenMicroConn ; - //sigc::connection bypass_lumaDenoiseConn ; - //sigc::connection bypass_colorDenoiseConn ; - sigc::connection bypass_defringeConn ; - sigc::connection bypass_dirpyrDenoiseConn ; - sigc::connection bypass_sh_hqConn ; - sigc::connection bypass_dirpyrequalizerConn ; - sigc::connection bypass_waveletConn ; - //sigc::connection bypass_raw_bayer_all_enhanceConn ; - sigc::connection bypass_raw_bayer_dcb_iterationsConn ; - sigc::connection bypass_raw_bayer_dcb_enhanceConn ; - sigc::connection bypass_raw_bayer_lmmse_iterationsConn; - sigc::connection bypass_raw_bayer_linenoiseConn ; - sigc::connection bypass_raw_bayer_greenthreshConn ; - sigc::connection bypass_raw_ccStepsConn ; - sigc::connection bypass_raw_caConn ; - sigc::connection bypass_raw_dfConn ; - sigc::connection bypass_raw_ffConn ; + sigc::connection enabledconn, bypass_ALLconn, FastExportconn, ExportLoadSettingsconn, ExportSaveSettingsconn; + sigc::connection bypass_sharpeningConn ; + sigc::connection bypass_sharpenEdgeConn ; + sigc::connection bypass_sharpenMicroConn ; + //sigc::connection bypass_lumaDenoiseConn ; + //sigc::connection bypass_colorDenoiseConn ; + sigc::connection bypass_defringeConn ; + sigc::connection bypass_dirpyrDenoiseConn ; + sigc::connection bypass_sh_hqConn ; + sigc::connection bypass_dirpyrequalizerConn ; + sigc::connection bypass_waveletConn ; + //sigc::connection bypass_raw_bayer_all_enhanceConn ; + sigc::connection bypass_raw_bayer_dcb_iterationsConn ; + sigc::connection bypass_raw_bayer_dcb_enhanceConn ; + sigc::connection bypass_raw_bayer_lmmse_iterationsConn; + sigc::connection bypass_raw_bayer_linenoiseConn ; + sigc::connection bypass_raw_bayer_greenthreshConn ; + sigc::connection bypass_raw_ccStepsConn ; + sigc::connection bypass_raw_caConn ; + sigc::connection bypass_raw_dfConn ; + sigc::connection bypass_raw_ffConn ; - ExportPanelListener* listener; + ExportPanelListener* listener; - void bypassALL_Toggled(); - void SaveSettingsAsDefault(); - void LoadDefaultSettings(); - void LoadSettings(); - void SaveSettings(); + void bypassALL_Toggled(); + void SaveSettingsAsDefault(); + void LoadDefaultSettings(); + void LoadSettings(); + void SaveSettings(); - public: - ExportPanel (); +public: + ExportPanel (); - void FastExportPressed (); - //bool isEnabled (); + void FastExportPressed (); + //bool isEnabled (); - void setExportPanelListener (ExportPanelListener* l) { listener = l; } + void setExportPanelListener (ExportPanelListener* l) + { + listener = l; + } }; #endif diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index a20414ba4..8e0ab225f 100644 --- a/rtgui/extprog.cc +++ b/rtgui/extprog.cc @@ -7,7 +7,7 @@ * 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 @@ -34,18 +34,22 @@ using namespace std; ExtProgAction::ExtProgAction() {} -ExtProgAction::ExtProgAction(const ExtProgAction* other, int target) +ExtProgAction::ExtProgAction(const ExtProgAction* other, int target) : target(target), filePathEXE(other->filePathEXE), preparams(other->preparams), name(other->name) { } -Glib::ustring ExtProgAction::GetFullName() { - return name+ " [" + M(Glib::ustring::compose("EXTPROGTARGET_%1", target)) + "]"; +Glib::ustring ExtProgAction::GetFullName() +{ + return name + " [" + M(Glib::ustring::compose("EXTPROGTARGET_%1", target)) + "]"; } -bool ExtProgAction::Execute(std::vector fileNames) { - if (fileNames.empty()) return false; +bool ExtProgAction::Execute(std::vector fileNames) +{ + if (fileNames.empty()) { + return false; + } // Check if they all exists (maybe not precessed yet) - for (int i=0;i fileNames) { } } - Glib::ustring cmdLine="\"" + filePathEXE + "\""; - if (preparams.length()>0) cmdLine += " " + preparams; + Glib::ustring cmdLine = "\"" + filePathEXE + "\""; - for (int i=0;i 0) { + cmdLine += " " + preparams; + } + + for (int i = 0; i < fileNames.size(); i++) { + cmdLine += " \"" + fileNames[i] + "\""; + } return safe_spawn_command_line_async (cmdLine); } @@ -66,24 +75,29 @@ bool ExtProgAction::Execute(std::vector fileNames) { ExtProgStore* ExtProgStore::getInstance() { static ExtProgStore* instance_ = 0; - if ( instance_ == 0 ) - { + + if ( instance_ == 0 ) { static MyMutex smutex_; MyMutex::MyLock lock(smutex_); - if ( instance_ == 0 ) - { + + if ( instance_ == 0 ) { instance_ = new ExtProgStore(); } } + return instance_; } -ExtProgStore::~ExtProgStore() { - for (list::iterator it=lActions.begin();it!=lActions.end();it++) delete *it; +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 () { +void ExtProgStore::init () +{ MyMutex::MyLock lock(mtx); lActions.clear(); @@ -99,11 +113,12 @@ void ExtProgStore::init () { SearchProg("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true); SearchProg("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true); - 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); - } + 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); + } + } } // DO NOT add obscure little tools here, only widely used programs with proper setup program to have a standard path @@ -111,63 +126,82 @@ void ExtProgStore::init () { } -bool ExtProgStore::SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess) { - bool found=false; +bool ExtProgStore::SearchProg(Glib::ustring name, Glib::ustring exePath, 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; + static Glib::ustring progFilesDir, progFilesDirx86; if (progFilesDir.empty()) { - WCHAR pathW[MAX_PATH]={0}; char pathA[MAX_PATH]; + WCHAR pathW[MAX_PATH] = {0}; + char pathA[MAX_PATH]; // First prio folder (64bit, otherwise 32bit) - if (SHGetSpecialFolderPathW(NULL,pathW,CSIDL_PROGRAM_FILES,false)) { + 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); - } + WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); + progFilesDir = Glib::ustring(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)) { + WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); + progFilesDirx86 = Glib::ustring(pathA); } } - if (exePath86.empty()) exePath86=exePath; + if (exePath86.empty()) { + exePath86 = exePath; + } - ExtProgAction *pAct=new ExtProgAction(); - pAct->name=name; - pAct->target= (allowRaw?1:2); + ExtProgAction *pAct = new ExtProgAction(); + pAct->name = name; + pAct->target = (allowRaw ? 1 : 2); - 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)) break; + if (maxVer > 0) { + for (int verNo = maxVer; verNo >= 0; verNo--) { + pAct->filePathEXE = progFilesDir + "\\" + Glib::ustring::compose(exePath, verNo); - pAct->filePathEXE=progFilesDirx86+"\\"+Glib::ustring::compose(exePath86,verNo); - if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) break; + if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + break; + } - pAct->filePathEXE=""; + pAct->filePathEXE = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, verNo); + + if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + break; + } + + pAct->filePathEXE = ""; } } else { - pAct->filePathEXE=progFilesDir+"\\"+exePath; + pAct->filePathEXE = progFilesDir + "\\" + exePath; + if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { - pAct->filePathEXE=progFilesDirx86+"\\"+exePath86; - if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) pAct->filePathEXE=""; + pAct->filePathEXE = progFilesDirx86 + "\\" + exePath86; + + if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + pAct->filePathEXE = ""; + } } } - if (pAct->filePathEXE.length()>0){ + if (pAct->filePathEXE.length() > 0) { lActions.push_back(pAct); // Copy for second target - if (allowRaw && allowQueueProcess) lActions.push_back(new ExtProgAction(pAct,2)); + if (allowRaw && allowQueueProcess) { + lActions.push_back(new ExtProgAction(pAct, 2)); + } + + found = true; + } else { + delete pAct; + } - found=true; - } else delete pAct; #endif return found; diff --git a/rtgui/extprog.h b/rtgui/extprog.h index f2d528fc6..2069bc8e8 100644 --- a/rtgui/extprog.h +++ b/rtgui/extprog.h @@ -7,7 +7,7 @@ * 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 @@ -24,7 +24,8 @@ #include #include "threadutils.h" -class ExtProgAction { +class ExtProgAction +{ public: ExtProgAction(); ExtProgAction(const ExtProgAction* other, int target); @@ -40,7 +41,8 @@ public: }; // Stores all external programs that could be called by the user -class ExtProgStore { +class ExtProgStore +{ MyMutex mtx; // covers actions bool SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess); diff --git a/rtgui/favoritbrowser.cc b/rtgui/favoritbrowser.cc index 9b66aad8b..8ce4caf8f 100644 --- a/rtgui/favoritbrowser.cc +++ b/rtgui/favoritbrowser.cc @@ -7,7 +7,7 @@ * 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 @@ -20,7 +20,8 @@ #include "multilangmgr.h" #include "rtimage.h" -FavoritBrowser::FavoritBrowser () : listener (NULL), lastSelectedDir ("") { +FavoritBrowser::FavoritBrowser () : listener (NULL), lastSelectedDir ("") +{ scrollw = Gtk::manage (new Gtk::ScrolledWindow ()); scrollw->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); @@ -29,10 +30,10 @@ FavoritBrowser::FavoritBrowser () : listener (NULL), lastSelectedDir ("") { frame->add (*scrollw); pack_start (*frame); - + treeView = Gtk::manage (new Gtk::TreeView ()); scrollw->add (*treeView); - + favoritModel = Gtk::ListStore::create (favoritColumns); treeView->set_model (favoritModel); treeView->set_headers_visible (false); @@ -64,36 +65,47 @@ FavoritBrowser::FavoritBrowser () : listener (NULL), lastSelectedDir ("") { show_all (); } -void FavoritBrowser::selectionChanged () { +void FavoritBrowser::selectionChanged () +{ Glib::RefPtr selection = treeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); - if (iter && listener) + + if (iter && listener) { listener->selectDir (iter->get_value (favoritColumns.fulldir)); + } } -void FavoritBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { +void FavoritBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) +{ lastSelectedDir = dirname; } -void FavoritBrowser::addPressed () { +void FavoritBrowser::addPressed () +{ - if (lastSelectedDir=="") + if (lastSelectedDir == "") { return; + } // check if the dirname is already in the list. If yes, return. Gtk::TreeModel::iterator iter = favoritModel->children ().begin(); + while (iter != favoritModel->children().end()) { - if (iter->get_value (favoritColumns.fulldir) == lastSelectedDir) + if (iter->get_value (favoritColumns.fulldir) == lastSelectedDir) { return; + } + iter++; } Glib::RefPtr hfile = Gio::File::create_for_parse_name (lastSelectedDir); + if (hfile) { Glib::RefPtr info = hfile->query_info (); - if (info) { + + if (info) { Gtk::TreeModel::Row newrow = *(favoritModel->append()); newrow[favoritColumns.shortdir] = info->get_display_name (); newrow[favoritColumns.fulldir] = lastSelectedDir; @@ -102,13 +114,15 @@ void FavoritBrowser::addPressed () { } } -void FavoritBrowser::delPressed () { +void FavoritBrowser::delPressed () +{ // lookup the selected item in the bookmark Glib::RefPtr selection = treeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); - if (iter) + if (iter) { favoritModel->erase (iter); + } } diff --git a/rtgui/favoritbrowser.h b/rtgui/favoritbrowser.h index 36f964bb8..ed522c1c4 100644 --- a/rtgui/favoritbrowser.h +++ b/rtgui/favoritbrowser.h @@ -7,7 +7,7 @@ * 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 @@ -23,34 +23,43 @@ #include "dirbrowserremoteinterface.h" #include "dirselectionlistener.h" -class FavoritBrowser : public Gtk::VBox, public DirSelectionListener { +class FavoritBrowser : public Gtk::VBox, public DirSelectionListener +{ - class FavoritColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn > icon; - Gtk::TreeModelColumn shortdir; - Gtk::TreeModelColumn fulldir; - FavoritColumns() { add(icon); add(shortdir), add(fulldir); } - }; - - FavoritColumns favoritColumns; - Gtk::ScrolledWindow* scrollw; - Gtk::TreeView* treeView; - Glib::RefPtr favoritModel; - DirBrowserRemoteInterface* listener; - Glib::ustring lastSelectedDir; - Gtk::Button* add; - Gtk::Button* del; + class FavoritColumns : public Gtk::TreeModel::ColumnRecord + { public: - - FavoritBrowser (); - - void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { listener = l; } - void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile=""); - - void addPressed (); - void delPressed (); - void selectionChanged (); + Gtk::TreeModelColumn > icon; + Gtk::TreeModelColumn shortdir; + Gtk::TreeModelColumn fulldir; + FavoritColumns() + { + add(icon); + add(shortdir), add(fulldir); + } + }; + + FavoritColumns favoritColumns; + Gtk::ScrolledWindow* scrollw; + Gtk::TreeView* treeView; + Glib::RefPtr favoritModel; + DirBrowserRemoteInterface* listener; + Glib::ustring lastSelectedDir; + Gtk::Button* add; + Gtk::Button* del; +public: + + FavoritBrowser (); + + void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) + { + listener = l; + } + void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile = ""); + + void addPressed (); + void delPressed (); + void selectionChanged (); }; #endif diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index e8edc4fb2..294c074bb 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -9,7 +9,7 @@ * 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 @@ -32,8 +32,9 @@ extern Options options; -FileBrowser::FileBrowser () - : tbl(NULL),numFiltered(0), partialPasteDlg(M("PARTIALPASTE_DIALOGLABEL")) { +FileBrowser::FileBrowser () + : tbl(NULL), numFiltered(0), partialPasteDlg(M("PARTIALPASTE_DIALOGLABEL")) +{ fbih = new FileBrowserIdleHelper; fbih->fbrowser = this; @@ -44,185 +45,255 @@ FileBrowser::FileBrowser () int p = 0; pmenu = new Gtk::Menu (); - pmenu->attach (*Gtk::manage(open = new Gtk::MenuItem (M("FILEBROWSER_POPUPOPEN"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(develop = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPPROCESS"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(open = new Gtk::MenuItem (M("FILEBROWSER_POPUPOPEN"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(develop = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPPROCESS"))), 0, 1, p, p + 1); + p++; develop->set_image(*Gtk::manage(new RTImage ("processing.png"))); - pmenu->attach (*Gtk::manage(developfast = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPPROCESSFAST"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(developfast = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPPROCESSFAST"))), 0, 1, p, p + 1); + p++; - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p + 1); + p++; /*********************** * rank ***********************/ - if (options.menuGroupRank){ - pmenu->attach (*Gtk::manage(menuRank = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK"))), 0, 1, p, p+1); p++; - Gtk::Menu* submenuRank = Gtk::manage (new Gtk::Menu ()); - submenuRank->attach (*Gtk::manage(rank[0] = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNRANK"))), 0, 1, p, p+1); p++; - for (int i=1; i<=5; i++){ - submenuRank->attach (*Gtk::manage(rank[i] = new Gtk::MenuItem (M(Glib::ustring::compose("%1%2","FILEBROWSER_POPUPRANK",i)))), 0, 1, p, p+1); p++; - } - submenuRank->show_all (); - menuRank->set_submenu (*submenuRank); - } - else{ - pmenu->attach (*Gtk::manage(rank[0] = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNRANK"))), 0, 1, p, p+1); p++; - for (int i=1; i<=5; i++){ - pmenu->attach (*Gtk::manage(rank[i] = new Gtk::MenuItem (M(Glib::ustring::compose("%1%2","FILEBROWSER_POPUPRANK",i)))), 0, 1, p, p+1); p++; - } - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + if (options.menuGroupRank) { + pmenu->attach (*Gtk::manage(menuRank = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK"))), 0, 1, p, p + 1); + p++; + Gtk::Menu* submenuRank = Gtk::manage (new Gtk::Menu ()); + submenuRank->attach (*Gtk::manage(rank[0] = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNRANK"))), 0, 1, p, p + 1); + p++; + + for (int i = 1; i <= 5; i++) { + submenuRank->attach (*Gtk::manage(rank[i] = new Gtk::MenuItem (M(Glib::ustring::compose("%1%2", "FILEBROWSER_POPUPRANK", i)))), 0, 1, p, p + 1); + p++; + } + + submenuRank->show_all (); + menuRank->set_submenu (*submenuRank); + } else { + pmenu->attach (*Gtk::manage(rank[0] = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNRANK"))), 0, 1, p, p + 1); + p++; + + for (int i = 1; i <= 5; i++) { + pmenu->attach (*Gtk::manage(rank[i] = new Gtk::MenuItem (M(Glib::ustring::compose("%1%2", "FILEBROWSER_POPUPRANK", i)))), 0, 1, p, p + 1); + p++; + } + + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; } - if (!options.menuGroupRank || !options.menuGroupLabel) // separate Rank and Color Labels if either is not grouped - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + if (!options.menuGroupRank || !options.menuGroupLabel) { // separate Rank and Color Labels if either is not grouped + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + } + + p++; /*********************** * color labels ***********************/ - if (options.menuGroupLabel){ - pmenu->attach (*Gtk::manage(menuLabel = new Gtk::MenuItem (M("FILEBROWSER_POPUPCOLORLABEL"))), 0, 1, p, p+1); p++; - Gtk::Menu* submenuLabel = Gtk::manage (new Gtk::Menu ()); + if (options.menuGroupLabel) { + pmenu->attach (*Gtk::manage(menuLabel = new Gtk::MenuItem (M("FILEBROWSER_POPUPCOLORLABEL"))), 0, 1, p, p + 1); + p++; + Gtk::Menu* submenuLabel = Gtk::manage (new Gtk::Menu ()); - for (int i=0; i<=5; i++){ - submenuLabel->attach (*Gtk::manage(colorlabel[i] = new Gtk::ImageMenuItem (M(Glib::ustring::compose("%1%2","FILEBROWSER_POPUPCOLORLABEL",i)))), 0, 1, p, p+1); p++; - } - submenuLabel->show_all (); - menuLabel->set_submenu (*submenuLabel); - } - else{ - for (int i=0; i<=5; i++){ - pmenu->attach (*Gtk::manage(colorlabel[i] = new Gtk::ImageMenuItem (M(Glib::ustring::compose("%1%2","FILEBROWSER_POPUPCOLORLABEL",i)))), 0, 1, p, p+1); p++; - } + for (int i = 0; i <= 5; i++) { + submenuLabel->attach (*Gtk::manage(colorlabel[i] = new Gtk::ImageMenuItem (M(Glib::ustring::compose("%1%2", "FILEBROWSER_POPUPCOLORLABEL", i)))), 0, 1, p, p + 1); + p++; + } + + submenuLabel->show_all (); + menuLabel->set_submenu (*submenuLabel); + } else { + for (int i = 0; i <= 5; i++) { + pmenu->attach (*Gtk::manage(colorlabel[i] = new Gtk::ImageMenuItem (M(Glib::ustring::compose("%1%2", "FILEBROWSER_POPUPCOLORLABEL", i)))), 0, 1, p, p + 1); + p++; + } } - //set color label images - colorlabel[0]->set_image(*Gtk::manage(new RTImage ("cglabel0.png"))); - for (int i=1; i<=5; i++){ - colorlabel[i]->set_image(*Gtk::manage(new RTImage (Glib::ustring::compose("%1%2%3","clabel",i,".png")))); + //set color label images + colorlabel[0]->set_image(*Gtk::manage(new RTImage ("cglabel0.png"))); + + for (int i = 1; i <= 5; i++) { + colorlabel[i]->set_image(*Gtk::manage(new RTImage (Glib::ustring::compose("%1%2%3", "clabel", i, ".png")))); } - - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; /*********************** * external programs * *********************/ #if defined(WIN32) && defined(PROTECT_VECTORS) - Gtk::manage(miOpenDefaultViewer=new Gtk::MenuItem (M("FILEBROWSER_OPENDEFAULTVIEWER"))); + Gtk::manage(miOpenDefaultViewer = new Gtk::MenuItem (M("FILEBROWSER_OPENDEFAULTVIEWER"))); #else - miOpenDefaultViewer=NULL; + miOpenDefaultViewer = NULL; #endif // Build a list of menu items - mMenuExtProgs.clear(); amiExtProg=NULL; - for (std::list::iterator it=extProgStore->lActions.begin();it!=extProgStore->lActions.end();it++) { - ExtProgAction* pAct=*it; + mMenuExtProgs.clear(); + amiExtProg = NULL; - if (pAct->target==1 || pAct->target==2) mMenuExtProgs[pAct->GetFullName()]=pAct; + 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; + } } // Attach them to menu - if (!mMenuExtProgs.empty() || miOpenDefaultViewer!=NULL) { - amiExtProg=new Gtk::MenuItem*[mMenuExtProgs.size()]; - int itemNo=0; + if (!mMenuExtProgs.empty() || miOpenDefaultViewer != NULL) { + amiExtProg = new Gtk::MenuItem*[mMenuExtProgs.size()]; + int itemNo = 0; if (options.menuGroupExtProg) { - pmenu->attach (*Gtk::manage(menuExtProg = new Gtk::MenuItem (M("FILEBROWSER_EXTPROGMENU"))), 0, 1, p, p+1); p++; - Gtk::Menu* submenuExtProg = Gtk::manage (new Gtk::Menu()); - - if (miOpenDefaultViewer!=NULL) { - submenuExtProg->attach (*miOpenDefaultViewer, 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(menuExtProg = new Gtk::MenuItem (M("FILEBROWSER_EXTPROGMENU"))), 0, 1, p, p + 1); + p++; + Gtk::Menu* submenuExtProg = Gtk::manage (new Gtk::Menu()); + + if (miOpenDefaultViewer != NULL) { + submenuExtProg->attach (*miOpenDefaultViewer, 0, 1, p, p + 1); + p++; } - for (std::map::iterator 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++; + for (std::map::iterator 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++; } submenuExtProg->show_all (); - menuExtProg->set_submenu (*submenuExtProg); + menuExtProg->set_submenu (*submenuExtProg); } else { - if (miOpenDefaultViewer!=NULL) { - pmenu->attach (*miOpenDefaultViewer, 0, 1, p, p+1); p++; + if (miOpenDefaultViewer != NULL) { + pmenu->attach (*miOpenDefaultViewer, 0, 1, p, p + 1); + p++; } - for (std::map::iterator 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++; + for (std::map::iterator 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++; } } - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; } /*********************** * File Operations * *********************/ - if (options.menuGroupFileOperations){ - pmenu->attach (*Gtk::manage(menuFileOperations = new Gtk::MenuItem (M("FILEBROWSER_POPUPFILEOPERATIONS"))), 0, 1, p, p+1); p++; - Gtk::Menu* submenuFileOperations = Gtk::manage (new Gtk::Menu ()); + if (options.menuGroupFileOperations) { + pmenu->attach (*Gtk::manage(menuFileOperations = new Gtk::MenuItem (M("FILEBROWSER_POPUPFILEOPERATIONS"))), 0, 1, p, p + 1); + p++; + Gtk::Menu* submenuFileOperations = Gtk::manage (new Gtk::Menu ()); - submenuFileOperations->attach (*Gtk::manage(trash = new Gtk::MenuItem (M("FILEBROWSER_POPUPTRASH"))), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(untrash = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNTRASH"))), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(rename = new Gtk::MenuItem (M("FILEBROWSER_POPUPRENAME"))), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(remove = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVE"))), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(removeInclProc = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVEINCLPROC"))), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(copyTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPCOPYTO"))), 0, 1, p, p+1); p++; - submenuFileOperations->attach (*Gtk::manage(moveTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVETO"))), 0, 1, p, p+1); p++; + submenuFileOperations->attach (*Gtk::manage(trash = new Gtk::MenuItem (M("FILEBROWSER_POPUPTRASH"))), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(untrash = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNTRASH"))), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(rename = new Gtk::MenuItem (M("FILEBROWSER_POPUPRENAME"))), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(remove = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVE"))), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(removeInclProc = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVEINCLPROC"))), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(copyTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPCOPYTO"))), 0, 1, p, p + 1); + p++; + submenuFileOperations->attach (*Gtk::manage(moveTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVETO"))), 0, 1, p, p + 1); + p++; - submenuFileOperations->show_all (); - menuFileOperations->set_submenu (*submenuFileOperations); - } - else{ - pmenu->attach (*Gtk::manage(trash = new Gtk::MenuItem (M("FILEBROWSER_POPUPTRASH"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(untrash = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNTRASH"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(rename = new Gtk::MenuItem (M("FILEBROWSER_POPUPRENAME"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(remove = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVE"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(removeInclProc = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVEINCLPROC"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(copyTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPCOPYTO"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(moveTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVETO"))), 0, 1, p, p+1); p++; + submenuFileOperations->show_all (); + menuFileOperations->set_submenu (*submenuFileOperations); + } else { + pmenu->attach (*Gtk::manage(trash = new Gtk::MenuItem (M("FILEBROWSER_POPUPTRASH"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(untrash = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNTRASH"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(rename = new Gtk::MenuItem (M("FILEBROWSER_POPUPRENAME"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(remove = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVE"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(removeInclProc = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVEINCLPROC"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(copyTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPCOPYTO"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(moveTo = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVETO"))), 0, 1, p, p + 1); + p++; } - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; /*********************** * Profile Operations * *********************/ - if (options.menuGroupProfileOperations){ - pmenu->attach (*Gtk::manage(menuProfileOperations = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPPROFILEOPERATIONS"))), 0, 1, p, p+1); p++; - menuProfileOperations->set_image(*Gtk::manage(new RTImage ("logoicon-wind.png"))); + if (options.menuGroupProfileOperations) { + pmenu->attach (*Gtk::manage(menuProfileOperations = new Gtk::ImageMenuItem (M("FILEBROWSER_POPUPPROFILEOPERATIONS"))), 0, 1, p, p + 1); + p++; + menuProfileOperations->set_image(*Gtk::manage(new RTImage ("logoicon-wind.png"))); - Gtk::Menu* submenuProfileOperations = Gtk::manage (new Gtk::Menu ()); + Gtk::Menu* submenuProfileOperations = Gtk::manage (new Gtk::Menu ()); - submenuProfileOperations->attach (*Gtk::manage(copyprof = new Gtk::MenuItem (M("FILEBROWSER_COPYPROFILE"))), 0, 1, p, p+1); p++; - submenuProfileOperations->attach (*Gtk::manage(pasteprof = new Gtk::MenuItem (M("FILEBROWSER_PASTEPROFILE"))), 0, 1, p, p+1); p++; - submenuProfileOperations->attach (*Gtk::manage(partpasteprof = new Gtk::MenuItem (M("FILEBROWSER_PARTIALPASTEPROFILE"))), 0, 1, p, p+1); p++; - submenuProfileOperations->attach (*Gtk::manage(applyprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE"))), 0, 1, p, p+1); p++; - submenuProfileOperations->attach (*Gtk::manage(applypartprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE_PARTIAL"))), 0, 1, p, p+1); p++; - submenuProfileOperations->attach (*Gtk::manage(execcustprof = new Gtk::MenuItem (M("FILEBROWSER_EXEC_CPB"))), 0, 1, p, p+1); p++; - submenuProfileOperations->attach (*Gtk::manage(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p+1); p++; + submenuProfileOperations->attach (*Gtk::manage(copyprof = new Gtk::MenuItem (M("FILEBROWSER_COPYPROFILE"))), 0, 1, p, p + 1); + p++; + submenuProfileOperations->attach (*Gtk::manage(pasteprof = new Gtk::MenuItem (M("FILEBROWSER_PASTEPROFILE"))), 0, 1, p, p + 1); + p++; + submenuProfileOperations->attach (*Gtk::manage(partpasteprof = new Gtk::MenuItem (M("FILEBROWSER_PARTIALPASTEPROFILE"))), 0, 1, p, p + 1); + p++; + submenuProfileOperations->attach (*Gtk::manage(applyprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE"))), 0, 1, p, p + 1); + p++; + submenuProfileOperations->attach (*Gtk::manage(applypartprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE_PARTIAL"))), 0, 1, p, p + 1); + p++; + submenuProfileOperations->attach (*Gtk::manage(execcustprof = new Gtk::MenuItem (M("FILEBROWSER_EXEC_CPB"))), 0, 1, p, p + 1); + p++; + submenuProfileOperations->attach (*Gtk::manage(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p + 1); + p++; - submenuProfileOperations->show_all (); - menuProfileOperations->set_submenu (*submenuProfileOperations); - } - else{ - pmenu->attach (*Gtk::manage(copyprof = new Gtk::MenuItem (M("FILEBROWSER_COPYPROFILE"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(pasteprof = new Gtk::MenuItem (M("FILEBROWSER_PASTEPROFILE"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(partpasteprof = new Gtk::MenuItem (M("FILEBROWSER_PARTIALPASTEPROFILE"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(applyprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(applypartprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE_PARTIAL"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(execcustprof = new Gtk::MenuItem (M("FILEBROWSER_EXEC_CPB"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p+1); p++; + submenuProfileOperations->show_all (); + menuProfileOperations->set_submenu (*submenuProfileOperations); + } else { + pmenu->attach (*Gtk::manage(copyprof = new Gtk::MenuItem (M("FILEBROWSER_COPYPROFILE"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(pasteprof = new Gtk::MenuItem (M("FILEBROWSER_PASTEPROFILE"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(partpasteprof = new Gtk::MenuItem (M("FILEBROWSER_PARTIALPASTEPROFILE"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(applyprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(applypartprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE_PARTIAL"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(execcustprof = new Gtk::MenuItem (M("FILEBROWSER_EXEC_CPB"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p + 1); + p++; } - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(menuDF = new Gtk::MenuItem (M("FILEBROWSER_DARKFRAME"))), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(menuFF = new Gtk::MenuItem (M("FILEBROWSER_FLATFIELD"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(menuDF = new Gtk::MenuItem (M("FILEBROWSER_DARKFRAME"))), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(menuFF = new Gtk::MenuItem (M("FILEBROWSER_FLATFIELD"))), 0, 1, p, p + 1); + p++; - pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; - pmenu->attach (*Gtk::manage(cachemenu = new Gtk::MenuItem (M("FILEBROWSER_CACHE"))), 0, 1, p, p+1); p++; + pmenu->attach (*Gtk::manage(new Gtk::SeparatorMenuItem ()), 0, 1, p, p + 1); + p++; + pmenu->attach (*Gtk::manage(cachemenu = new Gtk::MenuItem (M("FILEBROWSER_CACHE"))), 0, 1, p, p + 1); + p++; pmenu->show_all (); @@ -241,35 +312,40 @@ FileBrowser::FileBrowser () partpasteprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_V, Gdk::CONTROL_MASK | Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE); // Bind to event handlers - open->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), open)); - for (int i=0; i<6; i++) + open->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), open)); + + for (int i = 0; i < 6; i++) { rank[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), rank[i])); - for (int i=0; i<6; i++) - colorlabel[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), colorlabel[i])); + } - for (int i=0; isignal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), amiExtProg[i])); + for (int i = 0; i < 6; i++) { + colorlabel[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), colorlabel[i])); + } - if (miOpenDefaultViewer!=NULL) { + for (int i = 0; i < mMenuExtProgs.size(); i++) { + amiExtProg[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), amiExtProg[i])); + } + + if (miOpenDefaultViewer != NULL) { miOpenDefaultViewer->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), miOpenDefaultViewer)); } - trash->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), trash)); - untrash->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), untrash)); - develop->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), develop)); + trash->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), trash)); + untrash->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), untrash)); + develop->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), develop)); developfast->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), developfast)); - rename->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), rename)); - remove->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), remove)); + rename->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), rename)); + remove->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), remove)); removeInclProc->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), removeInclProc)); selall->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selall)); copyTo->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), copyTo)); moveTo->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), moveTo)); - copyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), copyprof)); - pasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), pasteprof)); - partpasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), partpasteprof)); - applyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), applyprof)); + copyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), copyprof)); + pasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), pasteprof)); + partpasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), partpasteprof)); + applyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), applyprof)); applypartprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), applypartprof)); - execcustprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), execcustprof)); + execcustprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), execcustprof)); clearprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), clearprof)); cachemenu->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), cachemenu)); @@ -278,22 +354,28 @@ FileBrowser::FileBrowser () // A separate pop-up menu for Color Labels int c = 0; pmenuColorLabels = new Gtk::Menu (); - for (int i=0; i<=5; i++){ - pmenuColorLabels->attach (*Gtk::manage(colorlabel_pop[i] = new Gtk::ImageMenuItem (M(Glib::ustring::compose("%1%2","FILEBROWSER_POPUPCOLORLABEL",i)))), 0, 1, c, c+1); c++; - } - //set color label images - colorlabel_pop[0]->set_image(*Gtk::manage(new RTImage ("cglabel0.png"))); - for (int i=1; i<=5; i++){ - colorlabel_pop[i]->set_image(*Gtk::manage(new RTImage (Glib::ustring::compose("%1%2%3","clabel",i,".png")))); - } - pmenuColorLabels->show_all (); + + for (int i = 0; i <= 5; i++) { + pmenuColorLabels->attach (*Gtk::manage(colorlabel_pop[i] = new Gtk::ImageMenuItem (M(Glib::ustring::compose("%1%2", "FILEBROWSER_POPUPCOLORLABEL", i)))), 0, 1, c, c + 1); + c++; + } + + //set color label images + colorlabel_pop[0]->set_image(*Gtk::manage(new RTImage ("cglabel0.png"))); + + for (int i = 1; i <= 5; i++) { + colorlabel_pop[i]->set_image(*Gtk::manage(new RTImage (Glib::ustring::compose("%1%2%3", "clabel", i, ".png")))); + } + + pmenuColorLabels->show_all (); // Has to be located after creation of applyprof and applypartprof updateProfileList (); // Bind to event handlers - for (int i=0; i<=5; i++) - colorlabel_pop[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuColorlabelActivated), colorlabel_pop[i])); + for (int i = 0; i <= 5; i++) { + colorlabel_pop[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuColorlabelActivated), colorlabel_pop[i])); + } } FileBrowser::~FileBrowser () @@ -304,61 +386,72 @@ FileBrowser::~FileBrowser () delete[] amiExtProg; } -void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) { +void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) +{ { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - trash->set_sensitive (false); - untrash->set_sensitive (false); - for (size_t i=0; i(selected[i]))->thumbnail->getStage()==1) { - untrash->set_sensitive (true); - break; - } - for (size_t i=0; i(selected[i]))->thumbnail->getStage()==0) { - trash->set_sensitive (true); - break; - } + trash->set_sensitive (false); + untrash->set_sensitive (false); - pasteprof->set_sensitive (clipboard.hasProcParams()); - partpasteprof->set_sensitive (clipboard.hasProcParams()); - copyprof->set_sensitive (selected.size()==1); - clearprof->set_sensitive (!selected.empty()); + for (size_t i = 0; i < selected.size(); i++) + if ((static_cast(selected[i]))->thumbnail->getStage() == 1) { + untrash->set_sensitive (true); + break; + } + + for (size_t i = 0; i < selected.size(); i++) + if ((static_cast(selected[i]))->thumbnail->getStage() == 0) { + trash->set_sensitive (true); + break; + } + + pasteprof->set_sensitive (clipboard.hasProcParams()); + partpasteprof->set_sensitive (clipboard.hasProcParams()); + copyprof->set_sensitive (selected.size() == 1); + clearprof->set_sensitive (!selected.empty()); } // submenuDF int p = 0; Gtk::Menu* submenuDF = Gtk::manage (new Gtk::Menu ()); - submenuDF->attach (*Gtk::manage(selectDF = new Gtk::MenuItem (M("FILEBROWSER_SELECTDARKFRAME"))), 0, 1, p, p+1); p++; - submenuDF->attach (*Gtk::manage(autoDF = new Gtk::MenuItem (M("FILEBROWSER_AUTODARKFRAME"))), 0, 1, p, p+1); p++; - submenuDF->attach (*Gtk::manage(thisIsDF = new Gtk::MenuItem (M("FILEBROWSER_MOVETODARKFDIR"))), 0, 1, p, p+1); p++; + submenuDF->attach (*Gtk::manage(selectDF = new Gtk::MenuItem (M("FILEBROWSER_SELECTDARKFRAME"))), 0, 1, p, p + 1); + p++; + submenuDF->attach (*Gtk::manage(autoDF = new Gtk::MenuItem (M("FILEBROWSER_AUTODARKFRAME"))), 0, 1, p, p + 1); + p++; + submenuDF->attach (*Gtk::manage(thisIsDF = new Gtk::MenuItem (M("FILEBROWSER_MOVETODARKFDIR"))), 0, 1, p, p + 1); + p++; selectDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selectDF)); - autoDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), autoDF)); - thisIsDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated),thisIsDF )); - submenuDF->show_all (); - menuDF->set_submenu (*submenuDF); + autoDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), autoDF)); + thisIsDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), thisIsDF )); + submenuDF->show_all (); + menuDF->set_submenu (*submenuDF); - // submenuFF - p = 0; - Gtk::Menu* submenuFF = Gtk::manage (new Gtk::Menu ()); - submenuFF->attach (*Gtk::manage(selectFF = new Gtk::MenuItem (M("FILEBROWSER_SELECTFLATFIELD"))), 0, 1, p, p+1); p++; - submenuFF->attach (*Gtk::manage(autoFF = new Gtk::MenuItem (M("FILEBROWSER_AUTOFLATFIELD"))), 0, 1, p, p+1); p++; - submenuFF->attach (*Gtk::manage(thisIsFF = new Gtk::MenuItem (M("FILEBROWSER_MOVETOFLATFIELDDIR"))), 0, 1, p, p+1); p++; - selectFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selectFF)); - autoFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), autoFF)); - thisIsFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated),thisIsFF )); - submenuFF->show_all (); - menuFF->set_submenu (*submenuFF); + // submenuFF + p = 0; + Gtk::Menu* submenuFF = Gtk::manage (new Gtk::Menu ()); + submenuFF->attach (*Gtk::manage(selectFF = new Gtk::MenuItem (M("FILEBROWSER_SELECTFLATFIELD"))), 0, 1, p, p + 1); + p++; + submenuFF->attach (*Gtk::manage(autoFF = new Gtk::MenuItem (M("FILEBROWSER_AUTOFLATFIELD"))), 0, 1, p, p + 1); + p++; + submenuFF->attach (*Gtk::manage(thisIsFF = new Gtk::MenuItem (M("FILEBROWSER_MOVETOFLATFIELDDIR"))), 0, 1, p, p + 1); + p++; + selectFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selectFF)); + autoFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), autoFF)); + thisIsFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), thisIsFF )); + submenuFF->show_all (); + menuFF->set_submenu (*submenuFF); // build cache sub menu p = 0; - Gtk::Menu* cachesubmenu = Gtk::manage (new Gtk::Menu ()); - cachesubmenu->attach (*Gtk::manage(clearFromCache = new Gtk::MenuItem (M("FILEBROWSER_CACHECLEARFROMPARTIAL"))), 0, 1, p, p+1); p++; - cachesubmenu->attach (*Gtk::manage(clearFromCacheFull = new Gtk::MenuItem (M("FILEBROWSER_CACHECLEARFROMFULL"))), 0, 1, p, p+1); p++; + Gtk::Menu* cachesubmenu = Gtk::manage (new Gtk::Menu ()); + cachesubmenu->attach (*Gtk::manage(clearFromCache = new Gtk::MenuItem (M("FILEBROWSER_CACHECLEARFROMPARTIAL"))), 0, 1, p, p + 1); + p++; + cachesubmenu->attach (*Gtk::manage(clearFromCacheFull = new Gtk::MenuItem (M("FILEBROWSER_CACHECLEARFROMFULL"))), 0, 1, p, p + 1); + p++; clearFromCache->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), clearFromCache)); clearFromCacheFull->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), clearFromCacheFull)); cachesubmenu->show_all (); @@ -367,11 +460,12 @@ void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) { pmenu->popup (3, this->eventTime); } -void FileBrowser::doubleClicked (ThumbBrowserEntryBase* entry) { +void FileBrowser::doubleClicked (ThumbBrowserEntryBase* entry) +{ if (tbl && entry) { std::vector entries; - entries.push_back ((static_cast(entry))->thumbnail); + entries.push_back ((static_cast(entry))->thumbnail); tbl->openRequested (entries); } } @@ -381,16 +475,19 @@ struct addparams { FileBrowserEntry* entry; }; -int AddEntryUIThread (void* data) { - +int AddEntryUIThread (void* data) +{ + addparams* ap = static_cast(data); FileBrowserIdleHelper* fbih = ap->fbih; if (fbih->destroyed) { - if (fbih->pending == 1) + if (fbih->pending == 1) { delete fbih; - else + } else { fbih->pending--; + } + delete ap->entry; delete ap; @@ -404,7 +501,8 @@ int AddEntryUIThread (void* data) { return 0; } -void FileBrowser::addEntry (FileBrowserEntry* entry) { +void FileBrowser::addEntry (FileBrowserEntry* entry) +{ fbih->pending++; entry->setParent (this); @@ -414,30 +512,33 @@ void FileBrowser::addEntry (FileBrowserEntry* entry) { g_idle_add (AddEntryUIThread, ap); } -void FileBrowser::addEntry_ (FileBrowserEntry* entry) { +void FileBrowser::addEntry_ (FileBrowserEntry* entry) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected entry->selected = false; entry->drawable = false; - entry->framed = editedFiles.find (entry->filename)!=editedFiles.end(); - + entry->framed = editedFiles.find (entry->filename) != editedFiles.end(); + // add button set to the thumbbrowserentry entry->addButtonSet (new FileThumbnailButtonSet (entry)); entry->getThumbButtonSet()->setRank (entry->thumbnail->getRank()); entry->getThumbButtonSet()->setColorLabel (entry->thumbnail->getColorLabel()); - entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage()==1); + entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage() == 1); entry->getThumbButtonSet()->setButtonListener (this); entry->resize (getThumbnailHeight()); // find place in abc order { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif std::vector::iterator i = fd.begin(); - while (i!=fd.end() && *entry < *((FileBrowserEntry*)*i)) + + while (i != fd.end() && *entry < * ((FileBrowserEntry*)*i)) { i++; - + } + fd.insert (i, entry); initEntry (entry); @@ -448,42 +549,51 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) { trash_changed().emit(); } -FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) { - #if PROTECT_VECTORS +FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) +{ +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - for (std::vector::iterator i=fd.begin(); i!=fd.end(); i++) - if ((*i)->filename==fname) { + for (std::vector::iterator i = fd.begin(); i != fd.end(); i++) + if ((*i)->filename == fname) { ThumbBrowserEntryBase* entry = *i; entry->selected = false; fd.erase (i); std::vector::iterator j = std::find (selected.begin(), selected.end(), entry); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif + + if (j != selected.end()) { + if (checkFilter (*j)) { + numFiltered--; + } - if (j!=selected.end()) { - if (checkFilter (*j)) numFiltered--; selected.erase (j); notifySelectionListener (); } - if (lastClicked==entry) + if (lastClicked == entry) { lastClicked = NULL; + } + redraw (); return (static_cast(entry)); } + return NULL; } -void FileBrowser::close () { - if (fbih->pending) +void FileBrowser::close () +{ + if (fbih->pending) { fbih->destroyed = true; - else + } else { delete fbih; + } fbih = new FileBrowserIdleHelper; fbih->fbrowser = this; @@ -491,84 +601,92 @@ void FileBrowser::close () { fbih->pending = 0; { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif selected.clear (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); // notifySelectionListener will need read access! - #endif +#endif notifySelectionListener (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_ACQUIRE(l); - #endif +#endif // The listener merges parameters with old values, so delete afterwards - for (size_t i=0; i tbe; tbe.push_back (static_cast(colorLabel_actionData)); - - for (int i=0; i<6; i++) - if (m==colorlabel_pop[i]) { + + for (int i = 0; i < 6; i++) + if (m == colorlabel_pop[i]) { colorlabelRequested (tbe, i); return; } } -void FileBrowser::menuItemActivated (Gtk::MenuItem* m) { +void FileBrowser::menuItemActivated (Gtk::MenuItem* m) +{ std::vector mselected; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - for (size_t i=0; i(selected[i])); + for (size_t i = 0; i < selected.size(); i++) { + mselected.push_back (static_cast(selected[i])); + } } - if (!tbl || (m!=selall && mselected.empty()) ) + if (!tbl || (m != selall && mselected.empty()) ) { return; + } - for (int i=0; i<6; i++) - if (m==rank[i]) { + for (int i = 0; i < 6; i++) + if (m == rank[i]) { rankingRequested (mselected, i); return; } - for (int i=0; i<6; i++) - if (m==colorlabel[i]) { + + for (int i = 0; i < 6; i++) + if (m == colorlabel[i]) { colorlabelRequested (mselected, i); return; } - for (int j=0; jget_label()]; // Build vector of all file names std::vector selFileNames; - for (int i=0; ithumbnail->getFileName(); + + for (int i = 0; i < mselected.size(); i++) { + Glib::ustring fn = mselected[i]->thumbnail->getFileName(); // Maybe batch processed version - if (pAct->target==2) fn = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fn), options.saveFormatBatch.format); + if (pAct->target == 2) { + fn = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fn), options.saveFormatBatch.format); + } selFileNames.push_back(fn); } @@ -578,33 +696,36 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) { } } - if (m==open) + if (m == open) { openRequested(mselected); - else if (m==remove) + } else if (m == remove) { tbl->deleteRequested (mselected, false); - else if (m==removeInclProc) + } else if (m == removeInclProc) { tbl->deleteRequested (mselected, true); - else if (m==trash) + } else if (m == trash) { toTrashRequested (mselected); - else if (m==untrash) + } else if (m == untrash) { fromTrashRequested (mselected); + } - else if (m==develop) + else if (m == develop) { tbl->developRequested (mselected, false); - else if (m==developfast) + } else if (m == developfast) { tbl->developRequested (mselected, true); + } - else if (m==rename) + else if (m == rename) { tbl->renameRequested (mselected); - else if (m==selall) { + } else if (m == selall) { lastClicked = NULL; { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif selected.clear (); - for (size_t i=0; iselected = true; selected.push_back (fd[i]); @@ -612,208 +733,247 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) { } queue_draw (); notifySelectionListener (); - } - else if( m==copyTo){ - tbl->copyMoveRequested (mselected, false); + } else if( m == copyTo) { + tbl->copyMoveRequested (mselected, false); } - else if( m==moveTo){ - tbl->copyMoveRequested (mselected, true); + else if( m == moveTo) { + tbl->copyMoveRequested (mselected, true); } - else if (m==autoDF){ - if (!mselected.empty() && bppcl) + else if (m == autoDF) { + if (!mselected.empty() && bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (size_t i=0; ithumbnail->getProcParams(); - pp.raw.df_autoselect= true; - pp.raw.dark_frame.clear(); - mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false); } - if (!mselected.empty() && bppcl) - bppcl->endBatchPParamsChange(); - }else if (m==selectDF){ - if( !mselected.empty() ){ - rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams(); - Gtk::FileChooserDialog fc("Dark Frame",Gtk::FILE_CHOOSER_ACTION_OPEN ); + for (size_t i = 0; i < mselected.size(); i++) { + rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams(); + pp.raw.df_autoselect = true; + pp.raw.dark_frame.clear(); + mselected[i]->thumbnail->setProcParams(pp, NULL, FILEBROWSER, false); + } + + if (!mselected.empty() && bppcl) { + bppcl->endBatchPParamsChange(); + } + + } else if (m == selectDF) { + if( !mselected.empty() ) { + rtengine::procparams::ProcParams pp = mselected[0]->thumbnail->getProcParams(); + Gtk::FileChooserDialog fc("Dark Frame", Gtk::FILE_CHOOSER_ACTION_OPEN ); FileChooserLastFolderPersister persister(&fc, options.lastDarkframeDir); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); - if(!pp.raw.dark_frame.empty()) + + if(!pp.raw.dark_frame.empty()) { fc.set_filename( pp.raw.dark_frame ); + } + if( fc.run() == Gtk::RESPONSE_APPLY ) { - if (bppcl) + if (bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (size_t i=0; ithumbnail->getProcParams(); - pp.raw.dark_frame= fc.get_filename(); - pp.raw.df_autoselect= false; - mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false); } - if (bppcl) + + for (size_t i = 0; i < mselected.size(); i++) { + rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams(); + pp.raw.dark_frame = fc.get_filename(); + pp.raw.df_autoselect = false; + mselected[i]->thumbnail->setProcParams(pp, NULL, FILEBROWSER, false); + } + + if (bppcl) { bppcl->endBatchPParamsChange(); + } } } - }else if( m==thisIsDF){ + } else if( m == thisIsDF) { if( !options.rtSettings.darkFramesPath.empty()) { - if (Gio::File::create_for_path(options.rtSettings.darkFramesPath)->query_exists() ){ - for (size_t i=0; iquery_exists() ) { + for (size_t i = 0; i < mselected.size(); i++) { Glib::RefPtr file = Gio::File::create_for_path ( mselected[i]->filename ); - if( !file )continue; - Glib::ustring destName = options.rtSettings.darkFramesPath+ "/" + file->get_basename(); + + if( !file ) { + continue; + } + + Glib::ustring destName = options.rtSettings.darkFramesPath + "/" + file->get_basename(); Glib::RefPtr dest = Gio::File::create_for_path ( destName ); file->move( dest ); } + // Reinit cache rtengine::dfm.init( options.rtSettings.darkFramesPath ); - } - else { + } else { // Target directory creation failed, we clear the darkFramesPath setting options.rtSettings.darkFramesPath.clear(); Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), options.rtSettings.darkFramesPath) - +"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED"); + + "\n\n" + M("MAIN_MSG_OPERATIONCANCELLED"); Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.set_title(M("TP_DARKFRAME_LABEL")); msgd.run (); } - } - else { - Glib::ustring msg_ = M("MAIN_MSG_SETPATHFIRST")+"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED"); + } else { + Glib::ustring msg_ = M("MAIN_MSG_SETPATHFIRST") + "\n\n" + M("MAIN_MSG_OPERATIONCANCELLED"); Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.set_title(M("TP_DARKFRAME_LABEL")); msgd.run (); } - } - else if (m==autoFF){ - if (!mselected.empty() && bppcl) + } else if (m == autoFF) { + if (!mselected.empty() && bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (size_t i=0; ithumbnail->getProcParams(); - pp.raw.ff_AutoSelect= true; - pp.raw.ff_file.clear(); - mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false); } - if (!mselected.empty() && bppcl) + + for (size_t i = 0; i < mselected.size(); i++) { + rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams(); + pp.raw.ff_AutoSelect = true; + pp.raw.ff_file.clear(); + mselected[i]->thumbnail->setProcParams(pp, NULL, FILEBROWSER, false); + } + + if (!mselected.empty() && bppcl) { bppcl->endBatchPParamsChange(); - } - else if (m==selectFF){ - if( !mselected.empty() ){ - rtengine::procparams::ProcParams pp=mselected[0]->thumbnail->getProcParams(); - Gtk::FileChooserDialog fc("Flat Field",Gtk::FILE_CHOOSER_ACTION_OPEN ); + } + } else if (m == selectFF) { + if( !mselected.empty() ) { + rtengine::procparams::ProcParams pp = mselected[0]->thumbnail->getProcParams(); + Gtk::FileChooserDialog fc("Flat Field", Gtk::FILE_CHOOSER_ACTION_OPEN ); FileChooserLastFolderPersister persister(&fc, options.lastFlatfieldDir); fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); fc.add_button( Gtk::StockID("gtk-apply"), Gtk::RESPONSE_APPLY); - if(!pp.raw.ff_file.empty()) + + if(!pp.raw.ff_file.empty()) { fc.set_filename( pp.raw.ff_file ); + } + if( fc.run() == Gtk::RESPONSE_APPLY ) { - if (bppcl) + if (bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (size_t i=0; ithumbnail->getProcParams(); - pp.raw.ff_file= fc.get_filename(); - pp.raw.ff_AutoSelect= false; - mselected[i]->thumbnail->setProcParams(pp,NULL,FILEBROWSER,false); } - if (bppcl) + + for (size_t i = 0; i < mselected.size(); i++) { + rtengine::procparams::ProcParams pp = mselected[i]->thumbnail->getProcParams(); + pp.raw.ff_file = fc.get_filename(); + pp.raw.ff_AutoSelect = false; + mselected[i]->thumbnail->setProcParams(pp, NULL, FILEBROWSER, false); + } + + if (bppcl) { bppcl->endBatchPParamsChange(); + } } } - } - else if( m==thisIsFF){ - if( !options.rtSettings.flatFieldsPath.empty()) { - if (Gio::File::create_for_path(options.rtSettings.flatFieldsPath)->query_exists() ){ - for (size_t i=0; i file = Gio::File::create_for_path ( mselected[i]->filename ); - if( !file )continue; - Glib::ustring destName = options.rtSettings.flatFieldsPath+ "/" + file->get_basename(); - Glib::RefPtr dest = Gio::File::create_for_path ( destName ); - file->move( dest ); - } - // Reinit cache - rtengine::ffm.init( options.rtSettings.flatFieldsPath ); - } - else { - // Target directory creation failed, we clear the flatFieldsPath setting - options.rtSettings.flatFieldsPath.clear(); - Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), options.rtSettings.flatFieldsPath) - +"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED"); - Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.set_title(M("TP_FLATFIELD_LABEL")); - msgd.run (); - } - } - else { - Glib::ustring msg_ = M("MAIN_MSG_SETPATHFIRST")+"\n\n"+M("MAIN_MSG_OPERATIONCANCELLED"); - Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.set_title(M("TP_FLATFIELD_LABEL")); - msgd.run (); - } - } - else if (m==copyprof) + } else if( m == thisIsFF) { + if( !options.rtSettings.flatFieldsPath.empty()) { + if (Gio::File::create_for_path(options.rtSettings.flatFieldsPath)->query_exists() ) { + for (size_t i = 0; i < mselected.size(); i++) { + Glib::RefPtr file = Gio::File::create_for_path ( mselected[i]->filename ); + + if( !file ) { + continue; + } + + Glib::ustring destName = options.rtSettings.flatFieldsPath + "/" + file->get_basename(); + Glib::RefPtr dest = Gio::File::create_for_path ( destName ); + file->move( dest ); + } + + // Reinit cache + rtengine::ffm.init( options.rtSettings.flatFieldsPath ); + } else { + // Target directory creation failed, we clear the flatFieldsPath setting + options.rtSettings.flatFieldsPath.clear(); + Glib::ustring msg_ = Glib::ustring::compose (M("MAIN_MSG_PATHDOESNTEXIST"), options.rtSettings.flatFieldsPath) + + "\n\n" + M("MAIN_MSG_OPERATIONCANCELLED"); + Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.set_title(M("TP_FLATFIELD_LABEL")); + msgd.run (); + } + } else { + Glib::ustring msg_ = M("MAIN_MSG_SETPATHFIRST") + "\n\n" + M("MAIN_MSG_OPERATIONCANCELLED"); + Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.set_title(M("TP_FLATFIELD_LABEL")); + msgd.run (); + } + } else if (m == copyprof) { copyProfile (); - else if (m==pasteprof) + } else if (m == pasteprof) { pasteProfile (); - else if (m==partpasteprof) + } else if (m == partpasteprof) { partPasteProfile (); - else if (m==clearprof) { - for (size_t i=0; ithumbnail->clearProcParams (FILEBROWSER); + } + queue_draw (); - } else if (m==execcustprof) { - if (!mselected.empty() && bppcl) + } else if (m == execcustprof) { + if (!mselected.empty() && bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (size_t i=0; ithumbnail->createProcParamsForUpdate (false, true); // Empty run to update the thumb rtengine::procparams::ProcParams params = mselected[i]->thumbnail->getProcParams (); mselected[i]->thumbnail->setProcParams (params, NULL, FILEBROWSER); } - if (!mselected.empty() && bppcl) + + if (!mselected.empty() && bppcl) { bppcl->endBatchPParamsChange(); - } else if (m==clearFromCache) { - for (size_t i=0; iclearFromCacheRequested (mselected, false); - //queue_draw (); - } - else if (m==clearFromCacheFull) { - for (size_t i=0; iclearFromCacheRequested (mselected, true); - //queue_draw (); - } else if (miOpenDefaultViewer!=NULL && m==miOpenDefaultViewer) { + } + } else if (m == clearFromCache) { + for (size_t i = 0; i < mselected.size(); i++) { + tbl->clearFromCacheRequested (mselected, false); + } + + //queue_draw (); + } else if (m == clearFromCacheFull) { + for (size_t i = 0; i < mselected.size(); i++) { + tbl->clearFromCacheRequested (mselected, true); + } + + //queue_draw (); + } else if (miOpenDefaultViewer != NULL && m == miOpenDefaultViewer) { openDefaultViewer(1); } } -void FileBrowser::copyProfile () { - #if PROTECT_VECTORS +void FileBrowser::copyProfile () +{ +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif - if (selected.size()==1) - clipboard.setProcParams ((static_cast(selected[0]))->thumbnail->getProcParams()); + if (selected.size() == 1) { + clipboard.setProcParams ((static_cast(selected[0]))->thumbnail->getProcParams()); + } } -void FileBrowser::pasteProfile () { +void FileBrowser::pasteProfile () +{ if (clipboard.hasProcParams()) { std::vector mselected; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - for (unsigned int i=0; i(selected[i])); + for (unsigned int i = 0; i < selected.size(); i++) { + mselected.push_back (static_cast(selected[i])); + } } - if (!tbl || mselected.empty()) + if (!tbl || mselected.empty()) { return; + } - if (!mselected.empty() && bppcl) + if (!mselected.empty() && bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (unsigned int i=0; ithumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER); pastedPartProf.deleteInstance(); } - if (!mselected.empty() && bppcl) + + if (!mselected.empty() && bppcl) { bppcl->endBatchPParamsChange(); + } queue_draw (); } } -void FileBrowser::partPasteProfile () { +void FileBrowser::partPasteProfile () +{ if (clipboard.hasProcParams()) { std::vector mselected; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - for (unsigned int i=0; i(selected[i])); + for (unsigned int i = 0; i < selected.size(); i++) { + mselected.push_back (static_cast(selected[i])); + } } - if (!tbl || mselected.empty()) + if (!tbl || mselected.empty()) { return; + } int i = partialPasteDlg.run (); + if (i == Gtk::RESPONSE_OK) { - if (!mselected.empty() && bppcl) + if (!mselected.empty() && bppcl) { bppcl->beginBatchPParamsChange(mselected.size()); - for (unsigned int i=0; ithumbnail->createProcParamsForUpdate(false,false); // this can execute customprofilebuilder to generate param file + mselected[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file rtengine::procparams::PartialProfile cbPartProf = clipboard.getPartialProfile(); rtengine::procparams::PartialProfile pastedPartProf(&mselected[i]->thumbnail->getProcParams (), NULL); @@ -864,25 +1032,30 @@ void FileBrowser::partPasteProfile () { mselected[i]->thumbnail->setProcParams (*pastedPartProf.pparams, pastedPartProf.pedited, FILEBROWSER); pastedPartProf.deleteInstance(); } - if (!mselected.empty() && bppcl) + + if (!mselected.empty() && bppcl) { bppcl->endBatchPParamsChange(); + } queue_draw (); } + partialPasteDlg.hide (); } } -void FileBrowser::openDefaultViewer (int destination) { - bool success=true; +void FileBrowser::openDefaultViewer (int destination) +{ + bool success = true; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - if (selected.size()==1) - success=(static_cast(selected[0]))->thumbnail->openDefaultViewer(destination); + if (selected.size() == 1) { + success = (static_cast(selected[0]))->thumbnail->openDefaultViewer(destination); + } } if (!success) { @@ -891,101 +1064,87 @@ void FileBrowser::openDefaultViewer (int destination) { } } -bool FileBrowser::keyPressed (GdkEventKey* event) { +bool FileBrowser::keyPressed (GdkEventKey* event) +{ bool ctrl = event->state & GDK_CONTROL_MASK; bool shift = event->state & GDK_SHIFT_MASK; bool alt = event->state & GDK_MOD1_MASK; bool altgr = event->state & GDK_MOD2_MASK; - if ((event->keyval==GDK_C || event->keyval==GDK_c || event->keyval==GDK_Insert) && ctrl) { + if ((event->keyval == GDK_C || event->keyval == GDK_c || event->keyval == GDK_Insert) && ctrl) { copyProfile (); return true; - } - else if ((event->keyval==GDK_V || event->keyval==GDK_v) && ctrl && !shift) { + } else if ((event->keyval == GDK_V || event->keyval == GDK_v) && ctrl && !shift) { pasteProfile (); return true; - } - else if (event->keyval==GDK_Insert && shift) { + } else if (event->keyval == GDK_Insert && shift) { pasteProfile (); return true; - } - else if ((event->keyval==GDK_V || event->keyval==GDK_v) && ctrl && shift) { + } else if ((event->keyval == GDK_V || event->keyval == GDK_v) && ctrl && shift) { partPasteProfile (); return true; - } - else if (event->keyval==GDK_Delete && !shift) { + } else if (event->keyval == GDK_Delete && !shift) { menuItemActivated (trash); return true; - } - else if (event->keyval==GDK_Delete && shift) { + } else if (event->keyval == GDK_Delete && shift) { menuItemActivated (untrash); return true; - } - else if ((event->keyval==GDK_B || event->keyval==GDK_b) && ctrl) { + } else if ((event->keyval == GDK_B || event->keyval == GDK_b) && ctrl) { menuItemActivated (develop); return true; - } - else if ((event->keyval==GDK_A || event->keyval==GDK_a) && ctrl) { + } else if ((event->keyval == GDK_A || event->keyval == GDK_a) && ctrl) { menuItemActivated (selall); return true; - } - else if (event->keyval==GDK_F2 && !ctrl) { + } else if (event->keyval == GDK_F2 && !ctrl) { menuItemActivated (rename); return true; - } - else if (event->keyval==GDK_F3 && !(ctrl || shift || alt)) { // open Previous image from FileBrowser perspective - FileBrowser::openPrevImage (); + } else if (event->keyval == GDK_F3 && !(ctrl || shift || alt)) { // open Previous image from FileBrowser perspective + FileBrowser::openPrevImage (); return true; - } - else if (event->keyval==GDK_F4 && !(ctrl || shift || alt)) { // open Next image from FileBrowser perspective - FileBrowser::openNextImage (); + } else if (event->keyval == GDK_F4 && !(ctrl || shift || alt)) { // open Next image from FileBrowser perspective + FileBrowser::openNextImage (); return true; - } - else if (event->keyval==GDK_Left) { + } else if (event->keyval == GDK_Left) { selectPrev (1, shift); return true; - } - else if (event->keyval==GDK_Right) { + } else if (event->keyval == GDK_Right) { selectNext (1, shift); return true; - } - else if (event->keyval==GDK_Up) { + } else if (event->keyval == GDK_Up) { selectPrev (numOfCols, shift); return true; - } - else if (event->keyval==GDK_Down) { + } else if (event->keyval == GDK_Down) { selectNext (numOfCols, shift); return true; - } - else if (event->keyval==GDK_Home) { + } else if (event->keyval == GDK_Home) { selectFirst (shift); return true; - } - else if (event->keyval==GDK_End) { + } else if (event->keyval == GDK_End) { selectLast (shift); return true; - } - else if(event->keyval==GDK_Return || event->keyval==GDK_KP_Enter) { + } else if(event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) { std::vector mselected; - for (size_t i=0; i(selected[i])); + } + openRequested(mselected); - } - else if (event->keyval==GDK_F5) { + } else if (event->keyval == GDK_F5) { int dest = 1; - if (event->state & GDK_SHIFT_MASK) + + if (event->state & GDK_SHIFT_MASK) { dest = 2; - else if (event->state & GDK_CONTROL_MASK) + } else if (event->state & GDK_CONTROL_MASK) { dest = 3; + } openDefaultViewer (dest); return true; - } - else if (event->keyval==GDK_Page_Up) { + } else if (event->keyval == GDK_Page_Up) { scrollPage(GDK_SCROLL_UP); return true; - } - else if (event->keyval==GDK_Page_Down) { + } else if (event->keyval == GDK_Page_Down) { scrollPage(GDK_SCROLL_DOWN); return true; } @@ -993,307 +1152,364 @@ bool FileBrowser::keyPressed (GdkEventKey* event) { #ifdef __WIN32__ else if (shift && !ctrl && !alt && !altgr) { // rank switch(event->hardware_keycode) { - case 0x30: // 0-key - requestRanking (0); - return true; - case 0x31: // 1-key - requestRanking (1); - return true; - case 0x32: // 2-key - requestRanking (2); - return true; - case 0x33: // 3-key - requestRanking (3); - return true; - case 0x34: // 4-key - requestRanking (4); - return true; - case 0x35: // 5-key - requestRanking (5); - return true; + case 0x30: // 0-key + requestRanking (0); + return true; + + case 0x31: // 1-key + requestRanking (1); + return true; + + case 0x32: // 2-key + requestRanking (2); + return true; + + case 0x33: // 3-key + requestRanking (3); + return true; + + case 0x34: // 4-key + requestRanking (4); + return true; + + case 0x35: // 5-key + requestRanking (5); + return true; } - } - else if (shift && ctrl && !alt && !altgr) { // color labels + } else if (shift && ctrl && !alt && !altgr) { // color labels switch(event->hardware_keycode) { - case 0x30: // 0-key - requestColorLabel (0); - return true; - case 0x31: // 1-key - requestColorLabel (1); - return true; - case 0x32: // 2-key - requestColorLabel (2); - return true; - case 0x33: // 3-key - requestColorLabel (3); - return true; - case 0x34: // 4-key - requestColorLabel (4); - return true; - case 0x35: // 5-key - requestColorLabel (5); - return true; + case 0x30: // 0-key + requestColorLabel (0); + return true; + + case 0x31: // 1-key + requestColorLabel (1); + return true; + + case 0x32: // 2-key + requestColorLabel (2); + return true; + + case 0x33: // 3-key + requestColorLabel (3); + return true; + + case 0x34: // 4-key + requestColorLabel (4); + return true; + + case 0x35: // 5-key + requestColorLabel (5); + return true; } } + #else - else if (shift && !ctrl && !alt) { // rank - switch(event->hardware_keycode) { - case 0x13: - requestRanking (0); - return true; - case 0x0a: - requestRanking (1); - return true; - case 0x0b: - requestRanking (2); - return true; - case 0x0c: - requestRanking (3); - return true; - case 0x0d: - requestRanking (4); - return true; - case 0x0e: - requestRanking (5); - return true; - } - } - else if (shift && ctrl && !alt) { // color labels - switch(event->hardware_keycode) { - case 0x13: - requestColorLabel (0); - return true; - case 0x0a: - requestColorLabel (1); - return true; - case 0x0b: - requestColorLabel (2); - return true; - case 0x0c: - requestColorLabel (3); - return true; - case 0x0d: - requestColorLabel (4); - return true; - case 0x0e: - requestColorLabel (5); - return true; - } + else if (shift && !ctrl && !alt) { // rank + switch(event->hardware_keycode) { + case 0x13: + requestRanking (0); + return true; + + case 0x0a: + requestRanking (1); + return true; + + case 0x0b: + requestRanking (2); + return true; + + case 0x0c: + requestRanking (3); + return true; + + case 0x0d: + requestRanking (4); + return true; + + case 0x0e: + requestRanking (5); + return true; + } + } else if (shift && ctrl && !alt) { // color labels + switch(event->hardware_keycode) { + case 0x13: + requestColorLabel (0); + return true; + + case 0x0a: + requestColorLabel (1); + return true; + + case 0x0b: + requestColorLabel (2); + return true; + + case 0x0c: + requestColorLabel (3); + return true; + + case 0x0d: + requestColorLabel (4); + return true; + + case 0x0e: + requestColorLabel (5); + return true; + } } + #endif return false; } -void FileBrowser::saveThumbnailHeight (int height) { - if (!options.sameThumbSize && getLocation()==THLOC_EDITOR) +void FileBrowser::saveThumbnailHeight (int height) +{ + if (!options.sameThumbSize && getLocation() == THLOC_EDITOR) { options.thumbSizeTab = height; - else + } else { options.thumbSize = height; + } } -int FileBrowser::getThumbnailHeight () { +int FileBrowser::getThumbnailHeight () +{ // The user could have manually forced the option to a too big value - if (!options.sameThumbSize && getLocation()==THLOC_EDITOR) + if (!options.sameThumbSize && getLocation() == THLOC_EDITOR) { return std::max(std::min(options.thumbSizeTab, 800), 10); - else + } else { return std::max(std::min(options.thumbSize, 800), 10); + } } -void FileBrowser::applyMenuItemActivated (ProfileStoreLabel *label) { +void FileBrowser::applyMenuItemActivated (ProfileStoreLabel *label) +{ - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif const rtengine::procparams::PartialProfile* partProfile = profileStore.getProfile (label->entry); + if (partProfile->pparams && !selected.empty()) { - if (bppcl) + if (bppcl) { bppcl->beginBatchPParamsChange(selected.size()); - for (size_t i=0; i(selected[i]))->thumbnail->setProcParams (*partProfile->pparams, partProfile->pedited, FILEBROWSER); - if (bppcl) + } + + if (bppcl) { bppcl->endBatchPParamsChange(); + } + queue_draw (); } } -void FileBrowser::applyPartialMenuItemActivated (ProfileStoreLabel *label) { +void FileBrowser::applyPartialMenuItemActivated (ProfileStoreLabel *label) +{ - { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif + { +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - if (!tbl || selected.empty()) - return; - } + if (!tbl || selected.empty()) { + return; + } + } - const rtengine::procparams::PartialProfile* srcProfiles = profileStore.getProfile (label->entry); + const rtengine::procparams::PartialProfile* srcProfiles = profileStore.getProfile (label->entry); - if (srcProfiles->pparams) { - if (partialPasteDlg.run()==Gtk::RESPONSE_OK) { + if (srcProfiles->pparams) { + if (partialPasteDlg.run() == Gtk::RESPONSE_OK) { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - if (bppcl) - bppcl->beginBatchPParamsChange(selected.size()); - for (size_t i=0; ithumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file + if (bppcl) { + bppcl->beginBatchPParamsChange(selected.size()); + } - rtengine::procparams::PartialProfile dstProfile(true); - *dstProfile.pparams = (static_cast(selected[i]))->thumbnail->getProcParams (); - dstProfile.set(true); - partialPasteDlg.applyPaste (dstProfile.pparams, dstProfile.pedited, srcProfiles->pparams, srcProfiles->pedited); - (static_cast(selected[i]))->thumbnail->setProcParams (*dstProfile.pparams, dstProfile.pedited, FILEBROWSER); - dstProfile.deleteInstance(); - } - if (bppcl) - bppcl->endBatchPParamsChange(); - queue_draw (); - } - partialPasteDlg.hide (); - } + for (size_t i = 0; i < selected.size(); i++) { + selected[i]->thumbnail->createProcParamsForUpdate(false, false); // this can execute customprofilebuilder to generate param file + + rtengine::procparams::PartialProfile dstProfile(true); + *dstProfile.pparams = (static_cast(selected[i]))->thumbnail->getProcParams (); + dstProfile.set(true); + partialPasteDlg.applyPaste (dstProfile.pparams, dstProfile.pedited, srcProfiles->pparams, srcProfiles->pedited); + (static_cast(selected[i]))->thumbnail->setProcParams (*dstProfile.pparams, dstProfile.pedited, FILEBROWSER); + dstProfile.deleteInstance(); + } + + if (bppcl) { + bppcl->endBatchPParamsChange(); + } + + queue_draw (); + } + + partialPasteDlg.hide (); + } } -void FileBrowser::applyFilter (const BrowserFilter& filter) { +void FileBrowser::applyFilter (const BrowserFilter& filter) +{ this->filter = filter; // remove items not complying the filter from the selection bool selchanged = false; - numFiltered=0; + numFiltered = 0; { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); // Don't make this a writer lock! HOMBRE: Why? 'selected' is modified here - #endif +#endif - for (size_t i=0; iselected ) { + } else if (fd[i]->selected ) { fd[i]->selected = false; std::vector::iterator j = std::find (selected.begin(), selected.end(), fd[i]); selected.erase (j); - if (lastClicked==fd[i]) + + if (lastClicked == fd[i]) { lastClicked = NULL; + } + selchanged = true; } } } - if (selchanged) + if (selchanged) { notifySelectionListener (); + } + tbl->filterApplied(); redraw (); } -bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) { // true -> entry complies filter - +bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry complies filter +{ + FileBrowserEntry* entry = static_cast(entryb); + // return false if basic filter settings are not satisfied - if ((filter.showRanked[entry->thumbnail->getRank()]==false ) || - (filter.showCLabeled[entry->thumbnail->getColorLabel()]==false ) || + if ((filter.showRanked[entry->thumbnail->getRank()] == false ) || + (filter.showCLabeled[entry->thumbnail->getColorLabel()] == false ) || - ((entry->thumbnail->hasProcParams() && filter.showEdited[0]) && !filter.showEdited[1]) || - ((!entry->thumbnail->hasProcParams() && filter.showEdited[1])&& !filter.showEdited[0]) || + ((entry->thumbnail->hasProcParams() && filter.showEdited[0]) && !filter.showEdited[1]) || + ((!entry->thumbnail->hasProcParams() && filter.showEdited[1]) && !filter.showEdited[0]) || - ((entry->thumbnail->isRecentlySaved() && filter.showRecentlySaved[0]) && !filter.showRecentlySaved[1]) || - ((!entry->thumbnail->isRecentlySaved() && filter.showRecentlySaved[1]) && !filter.showRecentlySaved[0]) || + ((entry->thumbnail->isRecentlySaved() && filter.showRecentlySaved[0]) && !filter.showRecentlySaved[1]) || + ((!entry->thumbnail->isRecentlySaved() && filter.showRecentlySaved[1]) && !filter.showRecentlySaved[0]) || - (entry->thumbnail->getStage()==1 && !filter.showTrash) || - (entry->thumbnail->getStage()==0 && !filter.showNotTrash)) + (entry->thumbnail->getStage() == 1 && !filter.showTrash) || + (entry->thumbnail->getStage() == 0 && !filter.showNotTrash)) { return false; + } // return false is query is not satisfied - if (!filter.queryFileName.empty()){ - // check if image's FileName contains queryFileName (case insensitive) - // TODO should we provide case-sensitive search option via preferences? - Glib::ustring FileName; - FileName = Glib::path_get_basename (entry->thumbnail->getFileName()); - FileName = FileName.uppercase(); - //printf("FileBrowser::checkFilter FileName = '%s'; find() result= %i \n",FileName.c_str(), FileName.find(filter.queryFileName.uppercase())); - - Glib::ustring decodedQueryFileName; - bool MatchEqual; + if (!filter.queryFileName.empty()) { + // check if image's FileName contains queryFileName (case insensitive) + // TODO should we provide case-sensitive search option via preferences? + Glib::ustring FileName; + FileName = Glib::path_get_basename (entry->thumbnail->getFileName()); + FileName = FileName.uppercase(); + //printf("FileBrowser::checkFilter FileName = '%s'; find() result= %i \n",FileName.c_str(), FileName.find(filter.queryFileName.uppercase())); - // Determine the match mode - check if the first 2 characters are equal to "!=" - if (filter.queryFileName.find("!=")==0){ - decodedQueryFileName = filter.queryFileName.substr (2,filter.queryFileName.length()-2); - MatchEqual = false; - } - else { - decodedQueryFileName = filter.queryFileName; - MatchEqual = true; - } + Glib::ustring decodedQueryFileName; + bool MatchEqual; - // Consider that queryFileName consist of comma separated values (FilterString) - // Evaluate if ANY of these FilterString are contained in the filename - // This will construct OR filter within the filter.queryFileName - int iFilenameMatch=0; - std::vector vFilterStrings = Glib::Regex::split_simple(",", decodedQueryFileName.uppercase()); - for(int i=0; i 0) { // match is found for at least one of vFilterStrings in FileName + return false; + } + } + + /*experimental Regex support, this is unlikely to be useful to photographers*/ + //bool matchfound=Glib::Regex::match_simple(filter.queryFileName.uppercase(),FileName); + //if (!matchfound) return false; } // check exif filter const CacheImageData* cfs = entry->thumbnail->getCacheImageData(); double tol = 0.01; double tol2 = 1e-8; - - if (!filter.exifFilterEnabled) - return true; - - Glib::ustring camera(cfs->getCamera()); - if (!cfs->exifValid) - return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera)>0) - && (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens)>0) - && (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype)>0) - && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp)>0); + if (!filter.exifFilterEnabled) { + return true; + } - return - (!filter.exifFilter.filterShutter || (rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom-tol2 && rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo+tol2)) - && (!filter.exifFilter.filterFNumber || (rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom-tol2 && rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo+tol2)) - && (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom-tol && cfs->focalLen <= filter.exifFilter.focalTo+tol)) - && (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo)) - && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp)>0) - && (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera)>0) - && (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens)>0) - && (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype)>0); + Glib::ustring camera(cfs->getCamera()); + + if (!cfs->exifValid) + return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera) > 0) + && (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens) > 0) + && (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype) > 0) + && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0); + + return + (!filter.exifFilter.filterShutter || (rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2)) + && (!filter.exifFilter.filterFNumber || (rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom - tol2 && rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo + tol2)) + && (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom - tol && cfs->focalLen <= filter.exifFilter.focalTo + tol)) + && (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo)) + && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0) + && (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(camera) > 0) + && (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens) > 0) + && (!filter.exifFilter.filterFiletype || filter.exifFilter.filetypes.count(cfs->filetype) > 0); } -void FileBrowser::toTrashRequested (std::vector tbe) { +void FileBrowser::toTrashRequested (std::vector tbe) +{ - for (size_t i=0; ithumbnail->createProcParamsForUpdate(false, false, true); // this can execute customprofilebuilder to generate param file in "flagging" mode + for (size_t i = 0; i < tbe.size(); i++) { + // try to load the last saved parameters from the cache or from the paramfile file + tbe[i]->thumbnail->createProcParamsForUpdate(false, false, true); // this can execute customprofilebuilder to generate param file in "flagging" mode - // no need to notify listeners as item goes to trash, likely to be deleted + // no need to notify listeners as item goes to trash, likely to be deleted + + if (tbe[i]->thumbnail->getStage() == 1) { + continue; + } - if (tbe[i]->thumbnail->getStage()==1) - continue; tbe[i]->thumbnail->setStage (1); + if (tbe[i]->getThumbButtonSet()) { tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank()); tbe[i]->getThumbButtonSet()->setColorLabel (tbe[i]->thumbnail->getColorLabel()); @@ -1301,18 +1517,23 @@ void FileBrowser::toTrashRequested (std::vector tbe) { tbe[i]->thumbnail->updateCache (); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file } } + trash_changed().emit(); applyFilter (filter); } -void FileBrowser::fromTrashRequested (std::vector tbe) { +void FileBrowser::fromTrashRequested (std::vector tbe) +{ - for (size_t i=0; ithumbnail->getStage()==0) + if (tbe[i]->thumbnail->getStage() == 0) { continue; + } + tbe[i]->thumbnail->setStage (0); + if (tbe[i]->getThumbButtonSet()) { tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank()); tbe[i]->getThumbButtonSet()->setColorLabel (tbe[i]->thumbnail->getColorLabel()); @@ -1320,16 +1541,19 @@ void FileBrowser::fromTrashRequested (std::vector tbe) { tbe[i]->thumbnail->updateCache (); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file } } + trash_changed().emit(); applyFilter (filter); } -void FileBrowser::rankingRequested (std::vector tbe, int rank) { +void FileBrowser::rankingRequested (std::vector tbe, int rank) +{ - if (!tbe.empty() && bppcl) + if (!tbe.empty() && bppcl) { bppcl->beginBatchPParamsChange(tbe.size()); + } - for (size_t i=0; ithumbnail->createProcParamsForUpdate(false, false, true); // this can execute customprofilebuilder to generate param file in "flagging" mode @@ -1341,21 +1565,26 @@ void FileBrowser::rankingRequested (std::vector tbe, int rank tbe[i]->thumbnail->updateCache (); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file //TODO? - should update pparams instead? - if (tbe[i]->getThumbButtonSet()) + if (tbe[i]->getThumbButtonSet()) { tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank()); + } } + applyFilter (filter); - if (!tbe.empty() && bppcl) + if (!tbe.empty() && bppcl) { bppcl->endBatchPParamsChange(); + } } -void FileBrowser::colorlabelRequested (std::vector tbe, int colorlabel) { +void FileBrowser::colorlabelRequested (std::vector tbe, int colorlabel) +{ - if (!tbe.empty() && bppcl) + if (!tbe.empty() && bppcl) { bppcl->beginBatchPParamsChange(tbe.size()); + } - for (size_t i=0; ithumbnail->createProcParamsForUpdate(false, false, true); // this can execute customprofilebuilder to generate param file in "flagging" mode @@ -1364,86 +1593,99 @@ void FileBrowser::colorlabelRequested (std::vector tbe, int c tbe[i]->thumbnail->setColorLabel (colorlabel); tbe[i]->thumbnail->updateCache(); // needed to save the colorlabel to disk in the procparam file(s) and the cache image data file + //TODO? - should update pparams instead? - if (tbe[i]->getThumbButtonSet()) + if (tbe[i]->getThumbButtonSet()) { tbe[i]->getThumbButtonSet()->setColorLabel (tbe[i]->thumbnail->getColorLabel()); + } } + applyFilter (filter); - if (!tbe.empty() && bppcl) + if (!tbe.empty() && bppcl) { bppcl->endBatchPParamsChange(); + } } -void FileBrowser::requestRanking(int rank){ +void FileBrowser::requestRanking(int rank) +{ std::vector mselected; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif - for (size_t i=0; i(selected[i])); +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif + + for (size_t i = 0; i < selected.size(); i++) { + mselected.push_back (static_cast(selected[i])); + } } rankingRequested (mselected, rank); } -void FileBrowser::requestColorLabel(int colorlabel){ +void FileBrowser::requestColorLabel(int colorlabel) +{ std::vector mselected; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif - for (size_t i=0; i(selected[i])); +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif + + for (size_t i = 0; i < selected.size(); i++) { + mselected.push_back (static_cast(selected[i])); + } } colorlabelRequested (mselected, colorlabel); } -void FileBrowser::buttonPressed (LWButton* button, int actionCode, void* actionData) { +void FileBrowser::buttonPressed (LWButton* button, int actionCode, void* actionData) +{ - if (actionCode>=0 && actionCode<=5) { // rank + if (actionCode >= 0 && actionCode <= 5) { // rank std::vector tbe; - tbe.push_back (static_cast(actionData)); + tbe.push_back (static_cast(actionData)); rankingRequested (tbe, actionCode); - } - else if (actionCode==6 && tbl) { // to processing queue + } else if (actionCode == 6 && tbl) { // to processing queue std::vector tbe; - tbe.push_back (static_cast(actionData)); + tbe.push_back (static_cast(actionData)); tbl->developRequested (tbe, false); // not a fast, but a FULL mode - } - else if (actionCode==7) { // to trash / undelete + } else if (actionCode == 7) { // to trash / undelete std::vector tbe; - FileBrowserEntry* entry = static_cast(actionData); + FileBrowserEntry* entry = static_cast(actionData); tbe.push_back (entry); - if (entry->thumbnail->getStage()==0) + + if (entry->thumbnail->getStage() == 0) { toTrashRequested (tbe); - else + } else { fromTrashRequested (tbe); - } - else if (actionCode==8 && tbl) { // color label - // show popup menu - colorLabel_actionData = actionData;// this will be reused when pmenuColorLabels is clicked - pmenuColorLabels->popup (3, this->eventTime); + } + } else if (actionCode == 8 && tbl) { // color label + // show popup menu + colorLabel_actionData = actionData;// this will be reused when pmenuColorLabels is clicked + pmenuColorLabels->popup (3, this->eventTime); } } -void FileBrowser::openNextImage () { - #if PROTECT_VECTORS +void FileBrowser::openNextImage () +{ +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - if (!fd.empty() && selected.size()>0 && !options.tabbedUI) { + if (!fd.empty() && selected.size() > 0 && !options.tabbedUI) { - for (size_t i=0; ithumbnail->getFileName()==fd[i]->filename) {// located 1-st image in current selection - if (ithumbnail->getFileName() == fd[i]->filename) { // located 1-st image in current selection + if (i < fd.size() && tbl) { // find the first not-filtered-out (next) image - for (size_t k=i+1; kfiltered/*checkFilter (fd[k])*/){ + for (size_t k = i + 1; k < fd.size(); k++) { + if (!fd[k]->filtered/*checkFilter (fd[k])*/) { // clear current selection - for (size_t j=0; jselected = false; + } + selected.clear (); // set new selection @@ -1451,36 +1693,39 @@ void FileBrowser::openNextImage () { selected.push_back (fd[k]); //queue_draw (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif // this will require a read access notifySelectionListener (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_ACQUIRE(l); - #endif +#endif // scroll to the selected position double h1, v1; - getScrollPosition(h1,v1); + getScrollPosition(h1, v1); - double h2=selected[0]->getStartX(); - double v2=selected[0]->getStartY(); + double h2 = selected[0]->getStartX(); + double v2 = selected[0]->getStartY(); Thumbnail* thumb = (static_cast(fd[k]))->thumbnail; - int minWidth = get_width()-fd[k]->getMinimalWidth(); + int minWidth = get_width() - fd[k]->getMinimalWidth(); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif // scroll only when selected[0] is outside of the displayed bounds - if (h2+minWidth-h1 > get_width()) - setScrollPosition(h2-minWidth,v2); - if (h1>h2) - setScrollPosition(h2,v2); + if (h2 + minWidth - h1 > get_width()) { + setScrollPosition(h2 - minWidth, v2); + } + + if (h1 > h2) { + setScrollPosition(h2, v2); + } // open the selected image std::vector entries; @@ -1495,22 +1740,25 @@ void FileBrowser::openNextImage () { } } -void FileBrowser::openPrevImage () { - #if PROTECT_VECTORS +void FileBrowser::openPrevImage () +{ +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - if (!fd.empty() && selected.size()>0 && !options.tabbedUI) { + if (!fd.empty() && selected.size() > 0 && !options.tabbedUI) { - for (size_t i=1; ithumbnail->getFileName()==fd[i]->filename) {// located 1-st image in current selection - if (i>0 && tbl) { + for (size_t i = 1; i < fd.size(); i++) { + if (selected[0]->thumbnail->getFileName() == fd[i]->filename) { // located 1-st image in current selection + if (i > 0 && tbl) { // find the first not-filtered-out (previous) image - for (ssize_t k=(ssize_t)i-1; k>=0; k--){ - if (!fd[k]->filtered/*checkFilter (fd[k])*/){ + for (ssize_t k = (ssize_t)i - 1; k >= 0; k--) { + if (!fd[k]->filtered/*checkFilter (fd[k])*/) { // clear current selection - for (size_t j=0; jselected = false; + } + selected.clear (); // set new selection @@ -1518,36 +1766,39 @@ void FileBrowser::openPrevImage () { selected.push_back (fd[k]); //queue_draw (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif // this will require a read access notifySelectionListener (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_ACQUIRE(l); - #endif +#endif // scroll to the selected position double h1, v1; - getScrollPosition(h1,v1); + getScrollPosition(h1, v1); - double h2=selected[0]->getStartX(); - double v2=selected[0]->getStartY(); + double h2 = selected[0]->getStartX(); + double v2 = selected[0]->getStartY(); Thumbnail* thumb = (static_cast(fd[k]))->thumbnail; - int minWidth = get_width()-fd[k]->getMinimalWidth(); + int minWidth = get_width() - fd[k]->getMinimalWidth(); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif // scroll only when selected[0] is outside of the displayed bounds - if (h2+minWidth-h1 > get_width()) - setScrollPosition(h2-minWidth,v2); - if (h1>h2) - setScrollPosition(h2,v2); + if (h2 + minWidth - h1 > get_width()) { + setScrollPosition(h2 - minWidth, v2); + } + + if (h1 > h2) { + setScrollPosition(h2, v2); + } // open the selected image std::vector entries; @@ -1563,22 +1814,25 @@ void FileBrowser::openPrevImage () { } -void FileBrowser::selectImage (Glib::ustring fname) { +void FileBrowser::selectImage (Glib::ustring fname) +{ // need to clear the filter in filecatalog - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif if (!fd.empty() && !options.tabbedUI) { - for (size_t i=0; ifilename && !fd[i]->filtered) { + for (size_t i = 0; i < fd.size(); i++) { + if (fname == fd[i]->filename && !fd[i]->filtered) { // matching file found for sync // clear current selection - for (size_t j=0; jselected = false; + } + selected.clear (); // set new selection @@ -1586,100 +1840,115 @@ void FileBrowser::selectImage (Glib::ustring fname) { selected.push_back (fd[i]); queue_draw (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif // this will require a read access notifySelectionListener (); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_ACQUIRE(l); - #endif +#endif // scroll to the selected position - double h=selected[0]->getStartX(); - double v=selected[0]->getStartY(); + double h = selected[0]->getStartX(); + double v = selected[0]->getStartY(); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif + + setScrollPosition(h, v); - setScrollPosition(h,v); - return; } } } } -void FileBrowser::openNextPreviousEditorImage (Glib::ustring fname, eRTNav nextPrevious) { +void FileBrowser::openNextPreviousEditorImage (Glib::ustring fname, eRTNav nextPrevious) +{ // let FileBrowser acquire Editor's perspective selectImage (fname); // now switch to the requested image - if (nextPrevious==NAV_NEXT) + if (nextPrevious == NAV_NEXT) { openNextImage(); - else if (nextPrevious==NAV_PREVIOUS) + } else if (nextPrevious == NAV_PREVIOUS) { openPrevImage(); + } } -int refreshThumbImagesUI (void* data) { - (static_cast(data))->_thumbRearrangementNeeded (); +int refreshThumbImagesUI (void* data) +{ + (static_cast(data))->_thumbRearrangementNeeded (); return 0; } -void FileBrowser::_thumbRearrangementNeeded () { +void FileBrowser::_thumbRearrangementNeeded () +{ refreshThumbImages (); // arrangeFiles is NOT enough } -void FileBrowser::thumbRearrangementNeeded () { +void FileBrowser::thumbRearrangementNeeded () +{ // refreshThumbImagesUI will handle thread safety itself g_idle_add (refreshThumbImagesUI, this); } -void FileBrowser::selectionChanged () { +void FileBrowser::selectionChanged () +{ notifySelectionListener (); } -void FileBrowser::notifySelectionListener () { +void FileBrowser::notifySelectionListener () +{ if (tbl) { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif std::vector thm; - for (size_t i=0; i(selected[i]))->thumbnail); + } + tbl->selectionChanged (thm); } } -void FileBrowser::redrawNeeded (LWButton* button) { +void FileBrowser::redrawNeeded (LWButton* button) +{ GThreadLock lock; queue_draw (); } -FileBrowser::type_trash_changed FileBrowser::trash_changed () { +FileBrowser::type_trash_changed FileBrowser::trash_changed () +{ return m_trash_changed; } // ExportPanel interface -void FileBrowser::exportRequested (){ - FileBrowser::menuItemActivated(developfast); +void FileBrowser::exportRequested () +{ + FileBrowser::menuItemActivated(developfast); } -void FileBrowser::setExportPanel (ExportPanel* expanel) { +void FileBrowser::setExportPanel (ExportPanel* expanel) +{ - exportPanel = expanel; - exportPanel->set_sensitive (false); - exportPanel->setExportPanelListener (this); + exportPanel = expanel; + exportPanel->set_sensitive (false); + exportPanel->setExportPanelListener (this); } -void FileBrowser::updateProfileList () { +void FileBrowser::updateProfileList () +{ // submenu applmenu int p = 0; @@ -1690,7 +1959,7 @@ void FileBrowser::updateProfileList () { subMenuList[0] = Gtk::manage (new Gtk::Menu ()); // adding the root submenu // iterate the profile store's profile list - for (size_t i=0; isize(); i++) { + for (size_t i = 0; i < profEntries->size(); i++) { // create a new label for the current entry (be it a folder or file) ProfileStoreLabel *currLabel = Gtk::manage(new ProfileStoreLabel( profEntries->at(i) )); @@ -1710,16 +1979,22 @@ void FileBrowser::updateProfileList () { } // Hombre: ... does parentMenuId sounds like a hack? ... Yes. - int parentMenuId = !options.useBundledProfiles && currLabel->entry->parentFolderId==1 ? 0 : currLabel->entry->parentFolderId; - subMenuList[parentMenuId]->attach (*mi, 0, 1, p, p+1); p++; - if (currLabel->entry->type == PSET_FILE) + int parentMenuId = !options.useBundledProfiles && currLabel->entry->parentFolderId == 1 ? 0 : currLabel->entry->parentFolderId; + subMenuList[parentMenuId]->attach (*mi, 0, 1, p, p + 1); + p++; + + if (currLabel->entry->type == PSET_FILE) { mi->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::applyMenuItemActivated), currLabel)); + } + mi->show (); } if (subMenuList.size() && applyprof) // TODO: Check that the previous one has been deleted, including all childrens + { applyprof->set_submenu (*(subMenuList.at(0))); + } subMenuList.clear(); subMenuList[0] = Gtk::manage (new Gtk::Menu ()); // adding the root submenu @@ -1727,7 +2002,8 @@ void FileBrowser::updateProfileList () { // submenu applpartmenu p = 0; - for (size_t i=0; isize(); i++) { + + for (size_t i = 0; i < profEntries->size(); i++) { ProfileStoreLabel *currLabel = Gtk::manage(new ProfileStoreLabel( profEntries->at(i) )); Gtk::MenuItem* mi = Gtk::manage (new Gtk::MenuItem (*currLabel)); @@ -1742,27 +2018,38 @@ void FileBrowser::updateProfileList () { // add it to the parent MenuItem mi->set_submenu(*subMenu); } + // Hombre: ... does parentMenuId sounds like a hack? ... yes. - int parentMenuId = !options.useBundledProfiles && currLabel->entry->parentFolderId==1 ? 0 : currLabel->entry->parentFolderId; - subMenuList[parentMenuId]->attach (*mi, 0, 1, p, p+1); p++; - if (currLabel->entry->type == PSET_FILE) + int parentMenuId = !options.useBundledProfiles && currLabel->entry->parentFolderId == 1 ? 0 : currLabel->entry->parentFolderId; + subMenuList[parentMenuId]->attach (*mi, 0, 1, p, p + 1); + p++; + + if (currLabel->entry->type == PSET_FILE) { mi->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::applyPartialMenuItemActivated), currLabel)); + } + mi->show (); } if (subMenuList.size() && applypartprof) // TODO: Check that the previous one has been deleted, including all childrens + { applypartprof->set_submenu (*(subMenuList.at(0))); + } profileStore.releaseFileList(); subMenuList.clear(); } -void FileBrowser::openRequested( std::vector mselected) { +void FileBrowser::openRequested( std::vector mselected) +{ std::vector entries; // in Single Editor Mode open only last selected image - size_t openStart = options.tabbedUI ? 0 : ( mselected.size() > 0 ? mselected.size()-1 : 0); - for (size_t i=openStart; i 0 ? mselected.size() - 1 : 0); + + for (size_t i = openStart; i < mselected.size(); i++) { entries.push_back (mselected[i]->thumbnail); + } + tbl->openRequested (entries); } diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h index 5ae501fa1..a444b0a0e 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -7,7 +7,7 @@ * 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 @@ -34,19 +34,23 @@ class ProfileStoreLabel; class FileBrowser; class FileBrowserEntry; -class FileBrowserListener { +class FileBrowserListener +{ - public: - virtual ~FileBrowserListener () {} - virtual void filterApplied () {} - virtual void openRequested (std::vector tbe) {} - virtual void developRequested (std::vector tbe, bool fastmode) {} - virtual void renameRequested (std::vector tbe) {} - virtual void deleteRequested (std::vector tbe, bool inclBatchProcessed) {} - virtual void copyMoveRequested (std::vector tbe, bool moveRequested) {} - virtual void selectionChanged (std::vector tbe) {} - virtual void clearFromCacheRequested(std::vector tbe, bool leavenotrace) {} - virtual bool isInTabMode () { return false; } +public: + virtual ~FileBrowserListener () {} + virtual void filterApplied () {} + virtual void openRequested (std::vector tbe) {} + virtual void developRequested (std::vector tbe, bool fastmode) {} + virtual void renameRequested (std::vector tbe) {} + virtual void deleteRequested (std::vector tbe, bool inclBatchProcessed) {} + virtual void copyMoveRequested (std::vector tbe, bool moveRequested) {} + virtual void selectionChanged (std::vector tbe) {} + virtual void clearFromCacheRequested(std::vector tbe, bool leavenotrace) {} + virtual bool isInTabMode () + { + return false; + } }; struct FileBrowserIdleHelper { @@ -59,13 +63,14 @@ struct FileBrowserIdleHelper { * Class handling actions common to all thumbnails of the file browser */ class FileBrowser : public ThumbBrowserBase, - public LWButtonListener, - public ExportPanelListener, - public ProfileStoreListener { + public LWButtonListener, + public ExportPanelListener, + public ProfileStoreListener +{ typedef sigc::signal type_trash_changed; - protected: +protected: Gtk::MenuItem* rank[6]; Gtk::ImageMenuItem* colorlabel[6]; @@ -75,7 +80,7 @@ class FileBrowser : public ThumbBrowserBase, Gtk::ImageMenuItem* developfast; Gtk::MenuItem* rename; Gtk::MenuItem* remove; - Gtk::MenuItem* removeInclProc; + Gtk::MenuItem* removeInclProc; Gtk::MenuItem* open; Gtk::MenuItem* selall; Gtk::MenuItem* copyTo; @@ -115,7 +120,7 @@ class FileBrowser : public ThumbBrowserBase, Gtk::ImageMenuItem* colorlabel_pop[6]; Gtk::Menu* pmenuColorLabels; void* colorLabel_actionData; - void menuColorlabelActivated (Gtk::MenuItem* m); // use only when menu is invoked via FileBrowser::buttonPressed to pass actionData + void menuColorlabelActivated (Gtk::MenuItem* m); // use only when menu is invoked via FileBrowser::buttonPressed to pass actionData Glib::RefPtr pmaccelgroup; @@ -137,26 +142,35 @@ class FileBrowser : public ThumbBrowserBase, ExportPanel* exportPanel; type_trash_changed m_trash_changed; - - public: - + +public: + FileBrowser (); ~FileBrowser (); void addEntry (FileBrowserEntry* entry); // can be called from any thread - void addEntry_ (FileBrowserEntry* entry); // this must be executed inside the gtk thread + void addEntry_ (FileBrowserEntry* entry); // this must be executed inside the gtk thread FileBrowserEntry* delEntry (const Glib::ustring& fname); // return the entry if found here return NULL otherwise void close (); - - void setBatchPParamsChangeListener (BatchPParamsChangeListener* l) { bppcl = l; } - void setFileBrowserListener (FileBrowserListener* l) { tbl = l; } - + + void setBatchPParamsChangeListener (BatchPParamsChangeListener* l) + { + bppcl = l; + } + void setFileBrowserListener (FileBrowserListener* l) + { + tbl = l; + } + void menuItemActivated (Gtk::MenuItem* m); void applyMenuItemActivated (ProfileStoreLabel *label); void applyPartialMenuItemActivated (ProfileStoreLabel *label); void applyFilter (const BrowserFilter& filter); - int getNumFiltered(){ return numFiltered;} + int getNumFiltered() + { + return numFiltered; + } void buttonPressed (LWButton* button, int actionCode, void* actionData); void redrawNeeded (LWButton* button); @@ -168,7 +182,10 @@ class FileBrowser : public ThumbBrowserBase, void saveThumbnailHeight (int height); int getThumbnailHeight (); - bool isInTabMode() { return tbl ? tbl->isInTabMode() : false; } + bool isInTabMode() + { + return tbl ? tbl->isInTabMode() : false; + } void openNextImage (); void openPrevImage (); @@ -182,12 +199,12 @@ class FileBrowser : public ThumbBrowserBase, void thumbRearrangementNeeded (); void _thumbRearrangementNeeded (); - + void selectionChanged (); - + void setExportPanel (ExportPanel* expanel); - // exportpanel interface - void exportRequested(); + // exportpanel interface + void exportRequested(); void updateProfileList (); diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 33e948085..4e31c2a25 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -7,7 +7,7 @@ * 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 @@ -34,126 +34,143 @@ Glib::RefPtr FileBrowserEntry::editedIcon; Glib::RefPtr FileBrowserEntry::recentlySavedIcon; Glib::RefPtr FileBrowserEntry::enqueuedIcon; -FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) - : ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(NULL), cropgl(NULL), state(SNormal) { - thumbnail=thm; +FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) + : ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(NULL), cropgl(NULL), state(SNormal) +{ + thumbnail = thm; feih = new FileBrowserEntryIdleHelper; feih->fbentry = this; feih->destroyed = false; feih->pending = 0; - + italicstyle = thumbnail->getType() != FT_Raw; datetimeline = thumbnail->getDateTimeString (); exifline = thumbnail->getExifString (); 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"); iconsLoaded = true; } - - if (thm) + + if (thm) { thm->addThumbnailListener (this); + } } -FileBrowserEntry::~FileBrowserEntry () { +FileBrowserEntry::~FileBrowserEntry () +{ - // so jobs arriving now do nothing - if (feih->pending) - { + // so jobs arriving now do nothing + if (feih->pending) { feih->destroyed = true; - } - else - { + } else { delete feih; - feih = 0; - } + feih = 0; + } thumbImageUpdater->removeJobs (this); - if (thumbnail){ + + if (thumbnail) { thumbnail->removeThumbnailListener (this); thumbnail->decreaseRef (); } } -void FileBrowserEntry::refreshThumbnailImage () { +void FileBrowserEntry::refreshThumbnailImage () +{ - if (!thumbnail) + if (!thumbnail) { return; + } - thumbImageUpdater->add (this, &updatepriority, false, this); + thumbImageUpdater->add (this, &updatepriority, false, this); } -void FileBrowserEntry::refreshQuickThumbnailImage () { +void FileBrowserEntry::refreshQuickThumbnailImage () +{ - if (!thumbnail) + if (!thumbnail) { return; + } // Only make a (slow) processed preview if the picture has been edited at all bool upgrade_to_processed = (!options.internalThumbIfUntouched || thumbnail->isPParamsValid()); thumbImageUpdater->add(this, &updatepriority, upgrade_to_processed, this); } -void FileBrowserEntry::calcThumbnailSize () { +void FileBrowserEntry::calcThumbnailSize () +{ - if (thumbnail) + if (thumbnail) { thumbnail->getThumbnailSize (prew, preh); + } } -std::vector > FileBrowserEntry::getIconsOnImageArea () { +std::vector > FileBrowserEntry::getIconsOnImageArea () +{ std::vector > ret; - - if (!thumbnail) + + if (!thumbnail) { return ret; + } - if (thumbnail->hasProcParams() && editedIcon) + if (thumbnail->hasProcParams() && editedIcon) { ret.push_back (editedIcon); - if (thumbnail->isRecentlySaved() && recentlySavedIcon) + } + + if (thumbnail->isRecentlySaved() && recentlySavedIcon) { ret.push_back (recentlySavedIcon); - if (thumbnail->isEnqueued () && enqueuedIcon) + } + + if (thumbnail->isEnqueued () && enqueuedIcon) { ret.push_back (enqueuedIcon); + } - return ret; + return ret; } -void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) { - if(scale != 1.0 && cropParams.enabled) { // somewhere in pipeline customBackBufferUpdate is called when scale == 1.0, which is nonsense for a thumb - if (state==SCropSelecting || state==SResizeH1 || state==SResizeH2 || state==SResizeW1 || state==SResizeW2 || state==SResizeTL || state==SResizeTR || state==SResizeBL || state==SResizeBR || state==SCropMove) - drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cropParams, true, false); - else { - rtengine::procparams::CropParams cparams = thumbnail->getProcParams().crop; - if (cparams.enabled && !thumbnail->isQuick()) // Quick thumb have arbitrary sizes, so don't apply the crop - drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cparams, true, false); - } - } +void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) +{ + if(scale != 1.0 && cropParams.enabled) { // somewhere in pipeline customBackBufferUpdate is called when scale == 1.0, which is nonsense for a thumb + if (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove) { + drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cropParams, true, false); + } else { + rtengine::procparams::CropParams cparams = thumbnail->getProcParams().crop; + + if (cparams.enabled && !thumbnail->isQuick()) { // Quick thumb have arbitrary sizes, so don't apply the crop + drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cparams, true, false); + } + } + } } -void FileBrowserEntry::getIconSize (int& w, int& h) { +void FileBrowserEntry::getIconSize (int& w, int& h) +{ w = editedIcon->get_width (); h = editedIcon->get_height (); } -FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet () { +FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet () +{ - return (static_cast(buttonSet)); + return (static_cast(buttonSet)); } -void FileBrowserEntry::procParamsChanged (Thumbnail* thm, int whoChangedIt) { +void FileBrowserEntry::procParamsChanged (Thumbnail* thm, int whoChangedIt) +{ - if ( thumbnail->isQuick() ) - { - refreshQuickThumbnailImage (); - } - else - { - refreshThumbnailImage (); - } + if ( thumbnail->isQuick() ) { + refreshQuickThumbnailImage (); + } else { + refreshThumbnailImage (); + } } struct tiupdate { @@ -163,44 +180,47 @@ struct tiupdate { rtengine::procparams::CropParams cropParams; }; -int updateImageUI (void* data) { - +int updateImageUI (void* data) +{ + tiupdate* params = static_cast(data); FileBrowserEntryIdleHelper* feih = params->feih; if (feih->destroyed) { - if (feih->pending == 1) + if (feih->pending == 1) { delete feih; - else + } else { feih->pending--; + } + params->img->free (); delete params; return 0; } - + feih->fbentry->_updateImage (params->img, params->scale, params->cropParams); feih->pending--; delete params; - + return 0; } -void FileBrowserEntry::updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) { +void FileBrowserEntry::updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) +{ - { - GThreadLock lock; + { + GThreadLock lock; - if ( feih == 0 || - feih->destroyed ) - { - img->free(); - return; - } + if ( feih == 0 || + feih->destroyed ) { + img->free(); + return; + } - redrawRequests++; - feih->pending++; - } + redrawRequests++; + feih->pending++; + } tiupdate* param = new tiupdate (); param->feih = feih; @@ -214,18 +234,19 @@ void FileBrowserEntry::updateImage (rtengine::IImage8* img, double scale, rtengi #endif } -void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine::procparams::CropParams cropParams) { +void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine::procparams::CropParams cropParams) +{ - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, lockRW); - #endif +#endif - redrawRequests--; + redrawRequests--; scale = s; this->cropParams = cropParams; bool newLandscape = img->getWidth() > img->getHeight(); - bool rotated=false; + bool rotated = false; if (preh == img->getHeight ()) { prew = img->getWidth (); @@ -233,173 +254,172 @@ void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine: GThreadLock lock; // Check if image has been rotated since last time - rotated = preview!=NULL && newLandscape!=landscape; + rotated = preview != NULL && newLandscape != landscape; guint8* temp = preview; preview = NULL; delete [] temp; - temp = new guint8 [prew*preh*3]; - memcpy (temp, img->getData(), prew*preh*3); + temp = new guint8 [prew * preh * 3]; + memcpy (temp, img->getData(), prew * preh * 3); preview = temp; updateBackBuffer (); } - + landscape = newLandscape; img->free (); - if (parent!=NULL) { - if (rotated) + if (parent != NULL) { + if (rotated) { parent->thumbRearrangementNeeded(); - else if (redrawRequests==0) + } else if (redrawRequests == 0) { parent->redrawNeeded (this); + } } } -bool FileBrowserEntry::motionNotify (int x, int y) { - +bool FileBrowserEntry::motionNotify (int x, int y) +{ + bool b = ThumbBrowserEntryBase::motionNotify (x, y); - + int ix = x - startx - ofsX; int iy = y - starty - ofsY; Inspector* inspector = parent->getInspector(); + if (inspector && inspector->isActive() && !parent->isInTabMode()) { - rtengine::Coord2D coord(-1.,-1.); - getPosInImgSpace(x, y, coord); - if (coord.x != -1.) { - if (!wasInside) { - inspector->switchImage(filename); - } - wasInside = true; - inspector->mouseMove(coord, 0); - } - else { + rtengine::Coord2D coord(-1., -1.); + getPosInImgSpace(x, y, coord); + + if (coord.x != -1.) { + if (!wasInside) { + inspector->switchImage(filename); + } + + wasInside = true; + inspector->mouseMove(coord, 0); + } else { if (wasInside) { wasInside = false; - rtengine::Coord2D coord(-1,-1); + rtengine::Coord2D coord(-1, -1); } } } - if (inside (x,y)) + if (inside (x, y)) { updateCursor (ix, iy); + } - if (state==SRotateSelecting) { + if (state == SRotateSelecting) { action_x = x; action_y = y; parent->redrawNeeded (this); - } - else if (state==SResizeH1 && cropgl) { + } else if (state == SResizeH1 && cropgl) { int oy = cropParams.y; - cropParams.y = action_y + (y-press_y) / scale; + cropParams.y = action_y + (y - press_y) / scale; cropParams.h += oy - cropParams.y; cropgl->cropHeight1Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeH2 && cropgl) { - cropParams.h = action_y + (y-press_y) / scale; + } else if (state == SResizeH2 && cropgl) { + cropParams.h = action_y + (y - press_y) / scale; cropgl->cropHeight2Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeW1 && cropgl) { + } else if (state == SResizeW1 && cropgl) { int ox = cropParams.x; - cropParams.x = action_x + (x-press_x) / scale; + cropParams.x = action_x + (x - press_x) / scale; cropParams.w += ox - cropParams.x; cropgl->cropWidth1Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeW2 && cropgl) { - cropParams.w = action_x + (x-press_x) / scale; + } else if (state == SResizeW2 && cropgl) { + cropParams.w = action_x + (x - press_x) / scale; cropgl->cropWidth2Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeTL && cropgl) { + } else if (state == SResizeTL && cropgl) { int ox = cropParams.x; - cropParams.x = action_x + (x-press_x) / scale; + cropParams.x = action_x + (x - press_x) / scale; cropParams.w += ox - cropParams.x; int oy = cropParams.y; - cropParams.y = action_y + (y-press_y) / scale; + cropParams.y = action_y + (y - press_y) / scale; cropParams.h += oy - cropParams.y; cropgl->cropTopLeftResized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeTR && cropgl) { - cropParams.w = action_x + (x-press_x) / scale; + } else if (state == SResizeTR && cropgl) { + cropParams.w = action_x + (x - press_x) / scale; int oy = cropParams.y; - cropParams.y = action_y + (y-press_y) / scale; + cropParams.y = action_y + (y - press_y) / scale; cropParams.h += oy - cropParams.y; cropgl->cropTopRightResized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeBL && cropgl) { + } else if (state == SResizeBL && cropgl) { int ox = cropParams.x; - cropParams.x = action_x + (x-press_x) / scale; + cropParams.x = action_x + (x - press_x) / scale; cropParams.w += ox - cropParams.x; - cropParams.h = action_y + (y-press_y) / scale; + cropParams.h = action_y + (y - press_y) / scale; cropgl->cropBottomLeftResized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SResizeBR && cropgl) { - cropParams.w = action_x + (x-press_x) / scale; - cropParams.h = action_y + (y-press_y) / scale; + } else if (state == SResizeBR && cropgl) { + cropParams.w = action_x + (x - press_x) / scale; + cropParams.h = action_y + (y - press_y) / scale; cropgl->cropBottomRightResized (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SCropMove && cropgl) { - cropParams.x = action_x + (x-press_x) / scale; - cropParams.y = action_y + (y-press_y) / scale; + } else if (state == SCropMove && cropgl) { + cropParams.x = action_x + (x - press_x) / scale; + cropParams.y = action_y + (y - press_y) / scale; cropgl->cropMoved (cropParams.x, cropParams.y, cropParams.w, cropParams.h); updateBackBuffer (); parent->redrawNeeded (this); - } - else if (state==SCropSelecting && cropgl) { + } else if (state == SCropSelecting && cropgl) { int cx1 = press_x, cy1 = press_y; - int cx2 = (ix-prex) / scale, cy2 = (iy-prey) / scale; + int cx2 = (ix - prex) / scale, cy2 = (iy - prey) / scale; cropgl->cropResized (cx1, cy1, cx2, cy2); + if (cx2 > cx1) { cropParams.x = cx1; cropParams.w = cx2 - cx1 + 1; - } - else { + } else { cropParams.x = cx2; cropParams.w = cx1 - cx2 + 1; } + if (cy2 > cy1) { cropParams.y = cy1; cropParams.h = cy2 - cy1 + 1; - } - else { + } else { cropParams.y = cy2; cropParams.h = cy1 - cy2 + 1; } + updateBackBuffer (); parent->redrawNeeded (this); } - + return b; } -bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, int y) { +bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, int y) +{ bool b = ThumbBrowserEntryBase::pressNotify (button, type, bstate, x, y); - if (!iatlistener || !iatlistener->getToolBar()) + if (!iatlistener || !iatlistener->getToolBar()) { return true; + } ToolMode tm = iatlistener->getToolBar()->getTool (); int ix = x - startx - ofsX; int iy = y - starty - ofsY; - if (!b && selected && inside (x,y)) { - if (button==1 && type==GDK_BUTTON_PRESS && state==SNormal) { + + if (!b && selected && inside (x, y)) { + if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal) { if (onArea (CropTopLeft, ix, iy)) { state = SResizeTL; press_x = x; @@ -408,8 +428,7 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i action_y = cropParams.y; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropTopRight, ix, iy)) { + } else if (onArea (CropTopRight, ix, iy)) { state = SResizeTR; press_x = x; action_x = cropParams.w; @@ -417,8 +436,7 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i action_y = cropParams.y; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropBottomLeft, ix, iy)) { + } else if (onArea (CropBottomLeft, ix, iy)) { state = SResizeBL; press_x = x; action_x = cropParams.x; @@ -426,8 +444,7 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i action_y = cropParams.h; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropBottomRight, ix, iy)) { + } else if (onArea (CropBottomRight, ix, iy)) { state = SResizeBR; press_x = x; action_x = cropParams.w; @@ -435,36 +452,31 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i action_y = cropParams.h; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropTop, ix, iy)) { + } else if (onArea (CropTop, ix, iy)) { state = SResizeH1; press_y = y; action_y = cropParams.y; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropBottom, ix, iy)) { + } else if (onArea (CropBottom, ix, iy)) { state = SResizeH2; press_y = y; action_y = cropParams.h; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropLeft, ix, iy)) { + } else if (onArea (CropLeft, ix, iy)) { state = SResizeW1; press_x = x; action_x = cropParams.x; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropRight, ix, iy)) { + } else if (onArea (CropRight, ix, iy)) { state = SResizeW2; press_x = x; action_x = cropParams.w; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, ix, iy)) { + } else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, ix, iy)) { state = SCropMove; press_x = x; press_y = y; @@ -472,8 +484,7 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i action_y = cropParams.y; cropgl = iatlistener->startCropEditing (thumbnail); b = true; - } - else if (onArea (CropImage, ix, iy)) { + } else if (onArea (CropImage, ix, iy)) { if (tm == TMStraighten) { state = SRotateSelecting; press_x = x; @@ -482,17 +493,16 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i action_y = y; rot_deg = 0; b = true; - } - else if (tm == TMSpotWB) { - iatlistener->spotWBselected ((ix-prex)/scale, (iy-prey)/scale, thumbnail); + } else if (tm == TMSpotWB) { + iatlistener->spotWBselected ((ix - prex) / scale, (iy - prey) / scale, thumbnail); b = true; - } - else if (tm == TMCropSelect) { + } else if (tm == TMCropSelect) { cropgl = iatlistener->startCropEditing (thumbnail); + if (cropgl) { state = SCropSelecting; - press_x = cropParams.x = (ix-prex) / scale; - press_y = cropParams.y = (iy-prey) / scale; + press_x = cropParams.x = (ix - prex) / scale; + press_y = cropParams.y = (iy - prey) / scale; cropParams.w = cropParams.h = 1; cropgl->cropInit (cropParams.x, cropParams.y, cropParams.w, cropParams.h); b = true; @@ -500,206 +510,241 @@ bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, i } } } + updateCursor (ix, iy); } + return b; } -bool FileBrowserEntry::releaseNotify (int button, int type, int bstate, int x, int y) { +bool FileBrowserEntry::releaseNotify (int button, int type, int bstate, int x, int y) +{ bool b = ThumbBrowserEntryBase::releaseNotify (button, type, bstate, x, y); - + int ix = x - startx - ofsX; int iy = y - starty - ofsY; + if (!b) { - if (state==SRotateSelecting) { + if (state == SRotateSelecting) { iatlistener->rotateSelectionReady (rot_deg, thumbnail); - if (iatlistener->getToolBar()) iatlistener->getToolBar()->setTool (TMHand); - } - else if (cropgl && (state==SCropSelecting || state==SResizeH1 || state==SResizeH2 || state==SResizeW1 || state==SResizeW2 || state==SResizeTL || state==SResizeTR || state==SResizeBL || state==SResizeBR || state==SCropMove)) { + + if (iatlistener->getToolBar()) { + iatlistener->getToolBar()->setTool (TMHand); + } + } else if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) { cropgl->cropManipReady (); cropgl = NULL; iatlistener->cropSelectionReady (); - if (iatlistener->getToolBar()) iatlistener->getToolBar()->setTool (TMHand); + + if (iatlistener->getToolBar()) { + iatlistener->getToolBar()->setTool (TMHand); + } } + state = SNormal; - if (parent) + + if (parent) { parent->redrawNeeded (this); + } + updateCursor (ix, iy); - } - + } + return b; } -bool FileBrowserEntry::onArea (CursorArea a, int x, int y) { +bool FileBrowserEntry::onArea (CursorArea a, int x, int y) +{ - if (!drawable || !preview) + if (!drawable || !preview) { return false; - - int x1 = (x-prex) / scale; - int y1 = (y-prey) / scale; - int cropResizeBorder = CROPRESIZEBORDER / scale; - switch (a) { - case CropImage: - return x>=prex && x=prey && y=cropParams.y-cropResizeBorder && - y1<=cropParams.y+cropResizeBorder && - x1>=cropParams.x-cropResizeBorder && - x1<=cropParams.x+cropResizeBorder; - case CropTopRight: - return cropParams.enabled && - y1>=cropParams.y-cropResizeBorder && - y1<=cropParams.y+cropResizeBorder && - x1>=cropParams.x+cropParams.w-1-cropResizeBorder && - x1<=cropParams.x+cropParams.w-1+cropResizeBorder; - case CropBottomLeft: - return cropParams.enabled && - y1>=cropParams.y+cropParams.h-1-cropResizeBorder && - y1<=cropParams.y+cropParams.h-1+cropResizeBorder && - x1>=cropParams.x-cropResizeBorder && - x1<=cropParams.x+cropResizeBorder; - case CropBottomRight: - return cropParams.enabled && - y1>=cropParams.y+cropParams.h-1-cropResizeBorder && - y1<=cropParams.y+cropParams.h-1+cropResizeBorder && - x1>=cropParams.x+cropParams.w-1-cropResizeBorder && - x1<=cropParams.x+cropParams.w-1+cropResizeBorder; - case CropTop: - return cropParams.enabled && - x1>cropParams.x+cropResizeBorder && - x1cropParams.y-cropResizeBorder && - y1cropParams.x+cropResizeBorder && - x1cropParams.y+cropParams.h-1-cropResizeBorder && - y1cropParams.y+cropResizeBorder && - y1cropParams.x-cropResizeBorder && - x1cropParams.y+cropResizeBorder && - y1cropParams.x+cropParams.w-1-cropResizeBorder && - x1cropParams.y && - y1cropParams.x && - x1= prex && x < prex + prew && y >= prey && y < prey + preh; + + case CropTopLeft: + return cropParams.enabled && + y1 >= cropParams.y - cropResizeBorder && + y1 <= cropParams.y + cropResizeBorder && + x1 >= cropParams.x - cropResizeBorder && + x1 <= cropParams.x + cropResizeBorder; + + case CropTopRight: + return cropParams.enabled && + y1 >= cropParams.y - cropResizeBorder && + y1 <= cropParams.y + cropResizeBorder && + x1 >= cropParams.x + cropParams.w - 1 - cropResizeBorder && + x1 <= cropParams.x + cropParams.w - 1 + cropResizeBorder; + + case CropBottomLeft: + return cropParams.enabled && + y1 >= cropParams.y + cropParams.h - 1 - cropResizeBorder && + y1 <= cropParams.y + cropParams.h - 1 + cropResizeBorder && + x1 >= cropParams.x - cropResizeBorder && + x1 <= cropParams.x + cropResizeBorder; + + case CropBottomRight: + return cropParams.enabled && + y1 >= cropParams.y + cropParams.h - 1 - cropResizeBorder && + y1 <= cropParams.y + cropParams.h - 1 + cropResizeBorder && + x1 >= cropParams.x + cropParams.w - 1 - cropResizeBorder && + x1 <= cropParams.x + cropParams.w - 1 + cropResizeBorder; + + case CropTop: + return cropParams.enabled && + x1 > cropParams.x + cropResizeBorder && + x1 < cropParams.x + cropParams.w - 1 - cropResizeBorder && + y1 > cropParams.y - cropResizeBorder && + y1 < cropParams.y + cropResizeBorder; + + case CropBottom: + return cropParams.enabled && + x1 > cropParams.x + cropResizeBorder && + x1 < cropParams.x + cropParams.w - 1 - cropResizeBorder && + y1 > cropParams.y + cropParams.h - 1 - cropResizeBorder && + y1 < cropParams.y + cropParams.h - 1 + cropResizeBorder; + + case CropLeft: + return cropParams.enabled && + y1 > cropParams.y + cropResizeBorder && + y1 < cropParams.y + cropParams.h - 1 - cropResizeBorder && + x1 > cropParams.x - cropResizeBorder && + x1 < cropParams.x + cropResizeBorder; + + case CropRight: + return cropParams.enabled && + y1 > cropParams.y + cropResizeBorder && + y1 < cropParams.y + cropParams.h - 1 - cropResizeBorder && + x1 > cropParams.x + cropParams.w - 1 - cropResizeBorder && + x1 < cropParams.x + cropParams.w - 1 + cropResizeBorder; + + case CropInside: + return cropParams.enabled && + y1 > cropParams.y && + y1 < cropParams.y + cropParams.h - 1 && + x1 > cropParams.x && + x1 < cropParams.x + cropParams.w - 1; + } + return false; } -void FileBrowserEntry::updateCursor (int x, int y) { - - if (!iatlistener || !iatlistener->getToolBar()) +void FileBrowserEntry::updateCursor (int x, int y) +{ + + if (!iatlistener || !iatlistener->getToolBar()) { return; - + } + ToolMode tm = iatlistener->getToolBar()->getTool (); Glib::RefPtr w = parent->getDrawingArea ()->get_window(); - + if (!selected) { cursorManager.setCursor (w, CSArrow); return; } - - if (state==SNormal) { - if (tm==TMHand && (onArea (CropTop, x, y) || onArea (CropBottom, x, y))) + + if (state == SNormal) { + if (tm == TMHand && (onArea (CropTop, x, y) || onArea (CropBottom, x, y))) { cursorManager.setCursor (w, CSResizeHeight); - else if (tm==TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y))) + } else if (tm == TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y))) { cursorManager.setCursor (w, CSResizeWidth); - else if (tm==TMHand && (onArea (CropTopLeft, x, y))) + } else if (tm == TMHand && (onArea (CropTopLeft, x, y))) { cursorManager.setCursor (w, CSResizeTopLeft); - else if (tm==TMHand && (onArea (CropTopRight, x, y))) + } else if (tm == TMHand && (onArea (CropTopRight, x, y))) { cursorManager.setCursor (w, CSResizeTopRight); - else if (tm==TMHand && (onArea (CropBottomLeft, x, y))) + } else if (tm == TMHand && (onArea (CropBottomLeft, x, y))) { cursorManager.setCursor (w, CSResizeBottomLeft); - else if (tm==TMHand && (onArea (CropBottomRight, x, y))) + } else if (tm == TMHand && (onArea (CropBottomRight, x, y))) { cursorManager.setCursor (w, CSResizeBottomRight); - else if (onArea (CropImage, x, y)) { - if (tm==TMHand) + } else if (onArea (CropImage, x, y)) { + if (tm == TMHand) { cursorManager.setCursor (w, CSArrow); - else if (tm==TMSpotWB) + } else if (tm == TMSpotWB) { cursorManager.setCursor (w, CSSpotWB); - else if (tm==TMCropSelect) + } else if (tm == TMCropSelect) { cursorManager.setCursor (w, CSCropSelect); - else if (tm==TMStraighten) + } else if (tm == TMStraighten) { cursorManager.setCursor (w, CSStraighten); - } - else + } + } else { cursorManager.setCursor (w, CSArrow); - } - else if (state==SCropSelecting) + } + } else if (state == SCropSelecting) { cursorManager.setCursor (w, CSCropSelect); - else if (state==SRotateSelecting) + } else if (state == SRotateSelecting) { cursorManager.setCursor (w, CSStraighten); - else if (state==SCropMove) + } else if (state == SCropMove) { cursorManager.setCursor (w, CSMove); - else if (state==SResizeW1 || state==SResizeW2) + } else if (state == SResizeW1 || state == SResizeW2) { cursorManager.setCursor (w, CSResizeWidth); - else if (state==SResizeH1 || state==SResizeH2) + } else if (state == SResizeH1 || state == SResizeH2) { cursorManager.setCursor (w, CSResizeHeight); - else if (state==SResizeTL) + } else if (state == SResizeTL) { cursorManager.setCursor (w, CSResizeTopLeft); - else if (state==SResizeTR) + } else if (state == SResizeTR) { cursorManager.setCursor (w, CSResizeTopRight); - else if (state==SResizeBL) + } else if (state == SResizeBL) { cursorManager.setCursor (w, CSResizeBottomLeft); - else if (state==SResizeBR) + } else if (state == SResizeBR) { cursorManager.setCursor (w, CSResizeBottomRight); + } } -void FileBrowserEntry::draw () { +void FileBrowserEntry::draw () +{ ThumbBrowserEntryBase::draw (); - if (state==SRotateSelecting) { + + if (state == SRotateSelecting) { Cairo::RefPtr cr = parent->getDrawingArea ()->get_window()->create_cairo_context(); drawStraightenGuide (cr); } } -void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) { +void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) +{ - if (action_x!=press_x || action_y!=press_y) { - double arg = (press_x-action_x) / sqrt(double((press_x-action_x)*(press_x-action_x)+(press_y-action_y)*(press_y-action_y))); + if (action_x != press_x || action_y != press_y) { + double arg = (press_x - action_x) / sqrt(double((press_x - action_x) * (press_x - action_x) + (press_y - action_y) * (press_y - action_y))); double sol1, sol2; double pi = M_PI; - if (press_y>action_y) { - sol1 = acos(arg)*180/pi; - sol2 = -acos(-arg)*180/pi; - } - else { - sol1 = acos(-arg)*180/pi; - sol2 = -acos(arg)*180/pi; - } - if (fabs(sol1)45) - rot_deg = - 90.0 + rot_deg; - } - else + if (press_y > action_y) { + sol1 = acos(arg) * 180 / pi; + sol2 = -acos(-arg) * 180 / pi; + } else { + sol1 = acos(-arg) * 180 / pi; + sol2 = -acos(arg) * 180 / pi; + } + + if (fabs(sol1) < fabs(sol2)) { + rot_deg = sol1; + } else { + rot_deg = sol2; + } + + if (rot_deg < -45) { + rot_deg = 90.0 + rot_deg; + } else if (rot_deg > 45) { + rot_deg = - 90.0 + rot_deg; + } + } else { rot_deg = 0; + } Glib::RefPtr context = parent->getDrawingArea()->get_pango_context () ; Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); - fontd.set_size (8*Pango::SCALE); + fontd.set_size (8 * Pango::SCALE); context->set_font_description (fontd); Glib::RefPtr deglayout = parent->getDrawingArea()->create_pango_layout(Glib::ustring::compose ("%1 deg", Glib::ustring::format(std::setprecision(2), rot_deg))); @@ -707,22 +752,21 @@ void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) { int y1 = press_y; int y2 = action_y; int x2 = action_x; - - if (x2= prew + prex + ofsX + startx) { + y2 = y1 - (double)(y1 - y2) * (x1 - (prew + prex + ofsX + startx - 1)) / (x1 - x2); + x2 = prew + prex + ofsX + startx - 1; } - else if (x2>=prew+prex+ofsX+startx) { - y2 = y1 - (double)(y1-y2)*(x1 - (prew+prex+ofsX+startx-1)) / (x1-x2); - x2 = prew+prex+ofsX+startx-1; - } - if (y2=preh+prey+ofsY+starty) { - x2 = x1 - (double)(x1-x2)*(y1 - (preh+prey+ofsY+starty-1)) / (y1-y2); - y2 = preh+prey+ofsY+starty-1; + + if (y2 < prey + ofsY + starty) { + x2 = x1 - (double)(x1 - x2) * (y1 - (prey + ofsY + starty)) / (y1 - y2); + y2 = prey + ofsY + starty; + } else if (y2 >= preh + prey + ofsY + starty) { + x2 = x1 - (double)(x1 - x2) * (y1 - (preh + prey + ofsY + starty - 1)) / (y1 - y2); + y2 = preh + prey + ofsY + starty - 1; } cr->set_line_width (1.5); @@ -738,19 +782,19 @@ void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr cr) { cr->line_to (x2, y2); cr->stroke (); - if (press_x!=action_x && press_y!=action_y) { + if (press_x != action_x && press_y != action_y) { cr->set_source_rgb (0.0, 0.0, 0.0); - cr->move_to ((x1+x2)/2+1, (y1+y2)/2+1); + cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 + 1); deglayout->add_to_cairo_context (cr); - cr->move_to ((x1+x2)/2+1, (y1+y2)/2-1); + cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 - 1); deglayout->add_to_cairo_context (cr); - cr->move_to ((x1+x2)/2-1, (y1+y2)/2+1); + cr->move_to ((x1 + x2) / 2 - 1, (y1 + y2) / 2 + 1); deglayout->add_to_cairo_context (cr); - cr->move_to ((x1+x2)/2+1, (y1+y2)/2+1); + cr->move_to ((x1 + x2) / 2 + 1, (y1 + y2) / 2 + 1); deglayout->add_to_cairo_context (cr); cr->fill (); cr->set_source_rgb (1.0, 1.0, 1.0); - cr->move_to ((x1+x2)/2, (y1+y2)/2); + cr->move_to ((x1 + x2) / 2, (y1 + y2) / 2); deglayout->add_to_cairo_context (cr); cr->fill (); } diff --git a/rtgui/filebrowserentry.h b/rtgui/filebrowserentry.h index bc52273a0..8aaa54b1c 100644 --- a/rtgui/filebrowserentry.h +++ b/rtgui/filebrowserentry.h @@ -7,7 +7,7 @@ * 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 @@ -39,9 +39,10 @@ struct FileBrowserEntryIdleHelper { }; class FileThumbnailButtonSet; -class FileBrowserEntry : public ThumbBrowserEntryBase, - public ThumbnailListener, - public ThumbImageUpdateListener { +class FileBrowserEntry : public ThumbBrowserEntryBase, + public ThumbnailListener, + public ThumbImageUpdateListener +{ double scale; static bool iconsLoaded; @@ -53,7 +54,7 @@ class FileBrowserEntry : public ThumbBrowserEntryBase, rtengine::procparams::CropParams cropParams; CropGUIListener* cropgl; FileBrowserEntryIdleHelper* feih; - + ImgEditState state; bool onArea (CursorArea a, int x, int y); @@ -66,15 +67,18 @@ public: static Glib::RefPtr editedIcon; static Glib::RefPtr recentlySavedIcon; static Glib::RefPtr enqueuedIcon; - + FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname); ~FileBrowserEntry (); void draw (); - - void setImageAreaToolListener (ImageAreaToolListener* l) { iatlistener = l; } + + void setImageAreaToolListener (ImageAreaToolListener* l) + { + iatlistener = l; + } FileThumbnailButtonSet* getThumbButtonSet (); - + void refreshThumbnailImage (); void refreshQuickThumbnailImage (); void calcThumbnailSize (); diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 3ab622c58..d40b7d720 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -8,7 +8,7 @@ * 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 @@ -21,7 +21,7 @@ #include #include #include "../rtengine/rt_math.h" - + #include "filecatalog.h" #include "filepanel.h" #include "options.h" @@ -39,38 +39,38 @@ using namespace std; #define CHECKTIME 2000 FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : - filepanel(filepanel), - selectedDirectoryId(1), - listener(NULL), - fslistener(NULL), - dirlistener(NULL), - hasValidCurrentEFS(false), - filterPanel(NULL), - previewsToLoad(0), - previewsLoaded(0), - coarsePanel(cp), - toolBar(tb) - { + filepanel(filepanel), + selectedDirectoryId(1), + listener(NULL), + fslistener(NULL), + dirlistener(NULL), + hasValidCurrentEFS(false), + filterPanel(NULL), + previewsToLoad(0), + previewsLoaded(0), + coarsePanel(cp), + toolBar(tb) +{ - inTabMode=false; + inTabMode = false; // construct and initialize thumbnail browsers - fileBrowser = Gtk::manage( new FileBrowser() ); - fileBrowser->setFileBrowserListener (this); - fileBrowser->setArrangement (ThumbBrowserBase::TB_Vertical); - fileBrowser->show (); + fileBrowser = Gtk::manage( new FileBrowser() ); + fileBrowser->setFileBrowserListener (this); + fileBrowser->setArrangement (ThumbBrowserBase::TB_Vertical); + fileBrowser->show (); - set_size_request(0,250); + set_size_request(0, 250); // construct trash panel with the extra "empty trash" button trashButtonBox = Gtk::manage( new Gtk::VBox ); Gtk::Button* emptyT = Gtk::manage( new Gtk::Button (M("FILEBROWSER_EMPTYTRASH"))); emptyT->set_tooltip_markup (M("FILEBROWSER_EMPTYTRASHHINT")); emptyT->set_image (*Gtk::manage(new RTImage ("trash.png"))); - emptyT->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::emptyTrash)); + emptyT->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::emptyTrash)); trashButtonBox->pack_start (*emptyT, Gtk::PACK_SHRINK, 4); emptyT->show (); trashButtonBox->show (); - + //initialize hbToolBar1 hbToolBar1 = Gtk::manage(new Gtk::HBox ()); @@ -87,9 +87,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : buttonBrowsePath->set_tooltip_markup (M("FILEBROWSER_BROWSEPATHBUTTONHINT")); buttonBrowsePath->set_relief (Gtk::RELIEF_NONE); buttonBrowsePath->signal_clicked().connect( sigc::mem_fun(*this, &FileCatalog::buttonBrowsePathPressed) ); - hbBrowsePath->pack_start (*BrowsePath, Gtk::PACK_EXPAND_WIDGET,0); - hbBrowsePath->pack_start (*buttonBrowsePath,Gtk::PACK_SHRINK, 0); - hbToolBar1->pack_start (*hbBrowsePath, Gtk::PACK_EXPAND_WIDGET,0); + hbBrowsePath->pack_start (*BrowsePath, Gtk::PACK_EXPAND_WIDGET, 0); + hbBrowsePath->pack_start (*buttonBrowsePath, Gtk::PACK_SHRINK, 0); + hbToolBar1->pack_start (*hbBrowsePath, Gtk::PACK_EXPAND_WIDGET, 0); BrowsePath->signal_activate().connect (sigc::mem_fun(*this, &FileCatalog::buttonBrowsePathPressed)); //respond to the Enter key BrowsePath->signal_key_press_event().connect(sigc::mem_fun(*this, &FileCatalog::BrowsePath_key_pressed)); @@ -107,21 +107,23 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : buttonQueryClear->set_tooltip_markup (M("FILEBROWSER_QUERYBUTTONHINT")); buttonQueryClear->set_relief (Gtk::RELIEF_NONE); buttonQueryClear->signal_clicked().connect( sigc::mem_fun(*this, &FileCatalog::buttonQueryClearPressed) ); - hbQuery->pack_start (*labelQuery,Gtk::PACK_SHRINK, 0); - hbQuery->pack_start (*Query,Gtk::PACK_SHRINK, 0); - hbQuery->pack_start (*buttonQueryClear,Gtk::PACK_SHRINK, 0); - hbToolBar1->pack_start (*hbQuery, Gtk::PACK_SHRINK,0); + hbQuery->pack_start (*labelQuery, Gtk::PACK_SHRINK, 0); + hbQuery->pack_start (*Query, Gtk::PACK_SHRINK, 0); + hbQuery->pack_start (*buttonQueryClear, Gtk::PACK_SHRINK, 0); + hbToolBar1->pack_start (*hbQuery, Gtk::PACK_SHRINK, 0); Query->signal_activate().connect (sigc::mem_fun(*this, &FileCatalog::executeQuery)); //respond to the Enter key Query->signal_key_press_event().connect(sigc::mem_fun(*this, &FileCatalog::Query_key_pressed)); // if NOT a single row toolbar - if (!options.FileBrowserToolbarSingleRow) pack_start (*hbToolBar1, Gtk::PACK_SHRINK,0); + if (!options.FileBrowserToolbarSingleRow) { + pack_start (*hbToolBar1, Gtk::PACK_SHRINK, 0); + } // setup button bar buttonBar = Gtk::manage( new Gtk::HBox () ); pack_start (*buttonBar, Gtk::PACK_SHRINK); - + buttonBar->pack_start (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK); tbLeftPanel_1 = new Gtk::ToggleButton (); @@ -145,7 +147,7 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bFilterClear->set_image(*iFilterClear);// (*Gtk::manage(new RTImage ("filterclear.png"))); bFilterClear->set_relief (Gtk::RELIEF_NONE); bFilterClear->set_tooltip_markup (M("FILEBROWSER_SHOWDIRHINT")); - bFilterClear->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + bFilterClear->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); bCateg[0] = bFilterClear->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bFilterClear, true)); buttonBar->pack_start (*bFilterClear, Gtk::PACK_SHRINK); buttonBar->pack_start (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK); @@ -163,9 +165,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bUnRanked->set_tooltip_markup (M("FILEBROWSER_SHOWUNRANKHINT")); bCateg[1] = bUnRanked->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bUnRanked, true)); fltrRankbox->pack_start (*bUnRanked, Gtk::PACK_SHRINK); - bUnRanked->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + bUnRanked->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); - for (int i=0; i<5; i++) { + for (int i = 0; i < 5; i++) { iranked[i] = new RTImage ("rated.png"); igranked[i] = new RTImage ("grayrated.png"); iranked[i]->show (); @@ -174,9 +176,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bRank[i]->set_image (*igranked[i]); bRank[i]->set_relief (Gtk::RELIEF_NONE); fltrRankbox->pack_start (*bRank[i], Gtk::PACK_SHRINK); - bCateg[i+2] = bRank[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRank[i], true)); - bRank[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); - } + bCateg[i + 2] = bRank[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRank[i], true)); + bRank[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); + } iUnCLabeled = new RTImage ("clabel0.png"); igUnCLabeled = new RTImage ("cglabel0.png"); @@ -187,23 +189,23 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bUnCLabeled->set_tooltip_markup (M("FILEBROWSER_SHOWUNCOLORHINT")); bCateg[7] = bUnCLabeled->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bUnCLabeled, true)); fltrLabelbox->pack_start (*bUnCLabeled, Gtk::PACK_SHRINK); - bUnCLabeled->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + bUnCLabeled->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); - for (int i=0; i<5; i++) { - iCLabeled[i] = new RTImage (Glib::ustring::compose("%1%2%3","clabel",i+1,".png")); - igCLabeled[i] = new RTImage (Glib::ustring::compose("%1%2%3","cglabel",i+1,".png")); - iCLabeled[i]->show (); - igCLabeled[i]->show (); - bCLabel[i] = Gtk::manage(new Gtk::ToggleButton ()); - bCLabel[i]->set_image (*igCLabeled[i]); - bCLabel[i]->set_relief (Gtk::RELIEF_NONE); - fltrLabelbox->pack_start (*bCLabel[i], Gtk::PACK_SHRINK); - bCateg[i+8] = bCLabel[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bCLabel[i], true)); - bCLabel[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + for (int i = 0; i < 5; i++) { + iCLabeled[i] = new RTImage (Glib::ustring::compose("%1%2%3", "clabel", i + 1, ".png")); + igCLabeled[i] = new RTImage (Glib::ustring::compose("%1%2%3", "cglabel", i + 1, ".png")); + iCLabeled[i]->show (); + igCLabeled[i]->show (); + bCLabel[i] = Gtk::manage(new Gtk::ToggleButton ()); + bCLabel[i]->set_image (*igCLabeled[i]); + bCLabel[i]->set_relief (Gtk::RELIEF_NONE); + fltrLabelbox->pack_start (*bCLabel[i], Gtk::PACK_SHRINK); + bCateg[i + 8] = bCLabel[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bCLabel[i], true)); + bCLabel[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); } - fltrVbox1->pack_start (*fltrRankbox, Gtk::PACK_SHRINK,0); - fltrVbox1->pack_start (*fltrLabelbox, Gtk::PACK_SHRINK,0); + fltrVbox1->pack_start (*fltrRankbox, Gtk::PACK_SHRINK, 0); + fltrVbox1->pack_start (*fltrLabelbox, Gtk::PACK_SHRINK, 0); buttonBar->pack_start (*fltrVbox1, Gtk::PACK_SHRINK); bRank[0]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK1HINT")); @@ -211,7 +213,7 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bRank[2]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK3HINT")); bRank[3]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK4HINT")); bRank[4]->set_tooltip_markup (M("FILEBROWSER_SHOWRANK5HINT")); - + bCLabel[0]->set_tooltip_markup (M("FILEBROWSER_SHOWCOLORLABEL1HINT")); bCLabel[1]->set_tooltip_markup (M("FILEBROWSER_SHOWCOLORLABEL2HINT")); bCLabel[2]->set_tooltip_markup (M("FILEBROWSER_SHOWCOLORLABEL3HINT")); @@ -229,17 +231,19 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : igEdited[0] = new RTImage ("editednotg-small.png"); iEdited[1] = new RTImage ("edited-small.png"); igEdited[1] = new RTImage ("editedg-small.png"); - for (int i=0; i<2; i++) { - iEdited[i]->show (); - bEdited[i] = Gtk::manage(new Gtk::ToggleButton ()); - bEdited[i]->set_active (false); - bEdited[i]->set_image (*igEdited[i]); - bEdited[i]->set_relief (Gtk::RELIEF_NONE); - fltrEditedBox->pack_start (*bEdited[i], Gtk::PACK_SHRINK); - //13, 14 - bCateg[i+13] = bEdited[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bEdited[i], true)); - bEdited[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + + for (int i = 0; i < 2; i++) { + iEdited[i]->show (); + bEdited[i] = Gtk::manage(new Gtk::ToggleButton ()); + bEdited[i]->set_active (false); + bEdited[i]->set_image (*igEdited[i]); + bEdited[i]->set_relief (Gtk::RELIEF_NONE); + fltrEditedBox->pack_start (*bEdited[i], Gtk::PACK_SHRINK); + //13, 14 + bCateg[i + 13] = bEdited[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bEdited[i], true)); + bEdited[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); } + bEdited[0]->set_tooltip_markup (M("FILEBROWSER_SHOWEDITEDNOTHINT")); bEdited[1]->set_tooltip_markup (M("FILEBROWSER_SHOWEDITEDHINT")); @@ -248,22 +252,24 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : igRecentlySaved[0] = new RTImage ("savednotg.png"); iRecentlySaved[1] = new RTImage ("saved.png"); igRecentlySaved[1] = new RTImage ("savedg.png"); - for (int i=0; i<2; i++) { - iRecentlySaved[i]->show (); - bRecentlySaved[i] = Gtk::manage(new Gtk::ToggleButton ()); - bRecentlySaved[i]->set_active (false); - bRecentlySaved[i]->set_image (*igRecentlySaved[i]); - bRecentlySaved[i]->set_relief (Gtk::RELIEF_NONE); - fltrRecentlySavedBox->pack_start (*bRecentlySaved[i], Gtk::PACK_SHRINK); - //15, 16 - bCateg[i+15] = bRecentlySaved[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRecentlySaved[i], true)); - bRecentlySaved[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + + for (int i = 0; i < 2; i++) { + iRecentlySaved[i]->show (); + bRecentlySaved[i] = Gtk::manage(new Gtk::ToggleButton ()); + bRecentlySaved[i]->set_active (false); + bRecentlySaved[i]->set_image (*igRecentlySaved[i]); + bRecentlySaved[i]->set_relief (Gtk::RELIEF_NONE); + fltrRecentlySavedBox->pack_start (*bRecentlySaved[i], Gtk::PACK_SHRINK); + //15, 16 + bCateg[i + 15] = bRecentlySaved[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRecentlySaved[i], true)); + bRecentlySaved[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); } + bRecentlySaved[0]->set_tooltip_markup (M("FILEBROWSER_SHOWRECENTLYSAVEDNOTHINT")); bRecentlySaved[1]->set_tooltip_markup (M("FILEBROWSER_SHOWRECENTLYSAVEDHINT")); - fltrVbox2->pack_start (*fltrEditedBox, Gtk::PACK_SHRINK,0); - fltrVbox2->pack_start (*fltrRecentlySavedBox, Gtk::PACK_SHRINK,0); + fltrVbox2->pack_start (*fltrEditedBox, Gtk::PACK_SHRINK, 0); + fltrVbox2->pack_start (*fltrRecentlySavedBox, Gtk::PACK_SHRINK, 0); buttonBar->pack_start (*fltrVbox2, Gtk::PACK_SHRINK); buttonBar->pack_start (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK); @@ -275,9 +281,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bTrash = Gtk::manage( new Gtk::ToggleButton () ); bTrash->set_image (*iTrashEmpty); bTrash->set_relief (Gtk::RELIEF_NONE); - bTrash->set_tooltip_markup (M("FILEBROWSER_SHOWTRASHHINT")); + bTrash->set_tooltip_markup (M("FILEBROWSER_SHOWTRASHHINT")); bCateg[17] = bTrash->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bTrash, true)); - bTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + bTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); iNotTrash = new RTImage("trash-hide-deleted.png") ; @@ -286,7 +292,7 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : bNotTrash->set_relief (Gtk::RELIEF_NONE); bNotTrash->set_tooltip_markup (M("FILEBROWSER_SHOWNOTTRASHHINT")); bCateg[18] = bNotTrash->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bNotTrash, true)); - bNotTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false); + bNotTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false); buttonBar->pack_start (*bTrash, Gtk::PACK_SHRINK); buttonBar->pack_start (*bNotTrash, Gtk::PACK_SHRINK); @@ -315,11 +321,25 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : categoryButtons[0] = bFilterClear; categoryButtons[1] = bUnRanked; - for (int i=0; i<5; i++){ categoryButtons[i+2] = bRank[i];} + + for (int i = 0; i < 5; i++) { + categoryButtons[i + 2] = bRank[i]; + } + categoryButtons[7] = bUnCLabeled; - for (int i=0; i<5; i++){ categoryButtons[i+8] = bCLabel[i];} - for (int i=0; i<2; i++){ categoryButtons[i+13] = bEdited[i];} - for (int i=0; i<2; i++){ categoryButtons[i+15] = bRecentlySaved[i];} + + for (int i = 0; i < 5; i++) { + categoryButtons[i + 8] = bCLabel[i]; + } + + for (int i = 0; i < 2; i++) { + categoryButtons[i + 13] = bEdited[i]; + } + + for (int i = 0; i < 2; i++) { + categoryButtons[i + 15] = bRecentlySaved[i]; + } + categoryButtons[17] = bTrash; categoryButtons[18] = bNotTrash; @@ -344,7 +364,7 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : zoomOutButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomOut)); zoomOutButton->set_relief (Gtk::RELIEF_NONE); zoomOutButton->set_tooltip_markup (M("FILEBROWSER_ZOOMOUTHINT")); - zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); + zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); buttonBar->pack_start (*zoomBox, Gtk::PACK_SHRINK); buttonBar->pack_start (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK); @@ -353,7 +373,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : //iRightArrow_red = new RTImage("right_red.png"); // if it IS a single row toolbar - if (options.FileBrowserToolbarSingleRow) buttonBar->pack_start (*hbToolBar1, Gtk::PACK_EXPAND_WIDGET,0); + if (options.FileBrowserToolbarSingleRow) { + buttonBar->pack_start (*hbToolBar1, Gtk::PACK_EXPAND_WIDGET, 0); + } tbRightPanel_1 = new Gtk::ToggleButton (); iRightPanel_1_Show = new RTImage("panel-to-left.png"); @@ -366,9 +388,9 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : tbRightPanel_1->signal_toggled().connect( sigc::mem_fun(*this, &FileCatalog::tbRightPanel_1_toggled) ); buttonBar->pack_end (*tbRightPanel_1, Gtk::PACK_SHRINK); - buttonBar->pack_end (*coarsePanel, Gtk::PACK_SHRINK); + buttonBar->pack_end (*coarsePanel, Gtk::PACK_SHRINK); buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); - buttonBar->pack_end (*toolBar, Gtk::PACK_SHRINK); + buttonBar->pack_end (*toolBar, Gtk::PACK_SHRINK); buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); // add default panel @@ -379,51 +401,56 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : //printf("FileCatalog::FileCatalog fileBrowser->applyFilter (getFilter())\n"); pack_start (*hBox); - enabled = true; + enabled = true; lastScrollPos = 0; - for (int i=0; i<18; i++) { + + for (int i = 0; i < 18; i++) { hScrollPos[i] = 0; vScrollPos[i] = 0; } - + selectedDirectory = ""; #ifdef WIN32 wdMonitor = NULL; -#endif +#endif } -FileCatalog::~FileCatalog(){ - for (int i=0; i<5; i++) { - delete iranked[i]; - delete igranked[i]; - delete iCLabeled[i]; - delete igCLabeled[i]; - } - for (int i=0; i<2; i++) { - delete iEdited[i]; - delete igEdited[i]; - delete iRecentlySaved[i]; - delete igRecentlySaved[i]; +FileCatalog::~FileCatalog() +{ + for (int i = 0; i < 5; i++) { + delete iranked[i]; + delete igranked[i]; + delete iCLabeled[i]; + delete igCLabeled[i]; } + + for (int i = 0; i < 2; i++) { + delete iEdited[i]; + delete igEdited[i]; + delete iRecentlySaved[i]; + delete igRecentlySaved[i]; + } + delete iFilterClear; delete igFilterClear; delete iUnRanked; delete igUnRanked; delete iUnCLabeled; delete igUnCLabeled; - delete iTrashEmpty; - delete iTrashFull; - delete iRefreshWhite; - delete iRefreshRed; - delete iQueryClear; - delete iLeftPanel_1_Show; - delete iLeftPanel_1_Hide; - delete iRightPanel_1_Show; - delete iRightPanel_1_Hide; + delete iTrashEmpty; + delete iTrashFull; + delete iRefreshWhite; + delete iRefreshRed; + delete iQueryClear; + delete iLeftPanel_1_Show; + delete iLeftPanel_1_Hide; + delete iRightPanel_1_Show; + delete iRightPanel_1_Hide; } -bool FileCatalog::capture_event(GdkEventButton* event){ +bool FileCatalog::capture_event(GdkEventButton* event) +{ // need to record modifiers on the button press, because signal_toggled does not pass the event. modifierKey = event->state; return false; @@ -431,41 +458,52 @@ bool FileCatalog::capture_event(GdkEventButton* event){ void FileCatalog::exifInfoButtonToggled() { - if (inTabMode) - options.filmStripShowFileNames = exifInfo->get_active(); - else - options.showFileNames = exifInfo->get_active(); - fileBrowser->refreshThumbImages (); + if (inTabMode) { + options.filmStripShowFileNames = exifInfo->get_active(); + } else { + options.showFileNames = exifInfo->get_active(); + } + + fileBrowser->refreshThumbImages (); } -void FileCatalog::on_realize() { +void FileCatalog::on_realize() +{ Gtk::VBox::on_realize(); - Pango::FontDescription fontd = get_pango_context()->get_font_description (); + Pango::FontDescription fontd = get_pango_context()->get_font_description (); fileBrowser->get_pango_context()->set_font_description (fontd); // batchQueue->get_pango_context()->set_font_description (fontd); } -void FileCatalog::closeDir () { +void FileCatalog::closeDir () +{ - if (filterPanel) - filterPanel->set_sensitive (false); - - if (exportPanel) - exportPanel->set_sensitive (false); + if (filterPanel) { + filterPanel->set_sensitive (false); + } + + if (exportPanel) { + exportPanel->set_sensitive (false); + } #ifndef WIN32 - if (dirMonitor) + + if (dirMonitor) { dirMonitor->cancel (); + } + #else + if (wdMonitor) { delete wdMonitor; wdMonitor = NULL; } + #endif - // ignore old requests - ++selectedDirectoryId; + // ignore old requests + ++selectedDirectoryId; // terminate thumbnail preview loading previewLoader->removeAllJobs (); @@ -475,18 +513,19 @@ void FileCatalog::closeDir () { // remove entries selectedDirectory = ""; - fileBrowser->close (); + fileBrowser->close (); fileNameList.clear (); { - MyMutex::MyLock lock(dirEFSMutex); - dirEFS.clear (); + MyMutex::MyLock lock(dirEFSMutex); + dirEFS.clear (); } hasValidCurrentEFS = false; redrawAll (); } -std::vector FileCatalog::getFileList () { +std::vector FileCatalog::getFileList () +{ std::vector names; Glib::RefPtr dir = Gio::File::create_for_path (selectedDirectory); @@ -495,155 +534,193 @@ std::vector FileCatalog::getFileList () { return names; } -void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { +void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) +{ try { Glib::RefPtr dir = Gio::File::create_for_path (dirname); - if (!dir) + if (!dir) { return; + } + closeDir (); previewsToLoad = 0; previewsLoaded = 0; - // if openfile exists, we have to open it first (it is a command line argument) - if (!openfile.empty()) - addAndOpenFile (openfile); - selectedDirectory = dir->get_parse_name(); - //printf("FileCatalog::dirSelected selectedDirectory = %s\n",selectedDirectory.c_str()); - BrowsePath->set_text (selectedDirectory); - buttonBrowsePath->set_image (*iRefreshWhite); + // if openfile exists, we have to open it first (it is a command line argument) + if (!openfile.empty()) { + addAndOpenFile (openfile); + } + + selectedDirectory = dir->get_parse_name(); + //printf("FileCatalog::dirSelected selectedDirectory = %s\n",selectedDirectory.c_str()); + BrowsePath->set_text (selectedDirectory); + buttonBrowsePath->set_image (*iRefreshWhite); fileNameList = getFileList (); - for (unsigned int i=0; i f = Gio::File::create_for_path(fileNameList[i]); - if (f->get_parse_name() != openfile) // if we opened a file at the beginning don't add it again + + if (f->get_parse_name() != openfile) { // if we opened a file at the beginning don't add it again checkAndAddFile (f); + } } _refreshProgressBar (); + if (previewsToLoad == 0) { - filepanel->loadingThumbs(M("PROGRESSBAR_NOIMAGES"),0); + filepanel->loadingThumbs(M("PROGRESSBAR_NOIMAGES"), 0); } else { - filepanel->loadingThumbs(M("PROGRESSBAR_LOADINGTHUMBS"),0); + filepanel->loadingThumbs(M("PROGRESSBAR_LOADINGTHUMBS"), 0); } #ifdef WIN32 - wdMonitor = new WinDirMonitor (selectedDirectory, this); + wdMonitor = new WinDirMonitor (selectedDirectory, this); #else dirMonitor = dir->monitor_directory (); dirMonitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false)); #endif - } - catch (Glib::Exception& ex) { + } catch (Glib::Exception& ex) { std::cout << ex.what(); } } -void FileCatalog::enableTabMode(bool enable) { +void FileCatalog::enableTabMode(bool enable) +{ inTabMode = enable; if (enable) { - if (options.showFilmStripToolBar) + if (options.showFilmStripToolBar) { showToolBar(); - else + } else { hideToolBar(); + } + exifInfo->set_active( options.filmStripShowFileNames ); - } - else { + } else { buttonBar->show(); hbToolBar1->show(); exifInfo->set_active( options.showFileNames ); } + fileBrowser->enableTabMode(inTabMode); redrawAll(); } -void FileCatalog::_refreshProgressBar () { +void FileCatalog::_refreshProgressBar () +{ // In tab mode, no progress bar at all // Also mention that this progress bar only measures the FIRST pass (quick thumbnails) // The second, usually longer pass is done multithreaded down in the single entries and is NOT measured by this if (!inTabMode) { GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected - Gtk::Notebook *nb =(Gtk::Notebook *)(filepanel->get_parent()); - Gtk::Box* hbb=NULL; - Gtk::Label *label=NULL; - if( options.mainNBVertical ) + Gtk::Notebook *nb = (Gtk::Notebook *)(filepanel->get_parent()); + Gtk::Box* hbb = NULL; + Gtk::Label *label = NULL; + + if( options.mainNBVertical ) { hbb = Gtk::manage (new Gtk::VBox ()); - else + } else { hbb = Gtk::manage (new Gtk::HBox ()); + } + if (!previewsToLoad ) { hbb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU))); - int filteredCount = min(fileBrowser->getNumFiltered(),previewsLoaded); + int filteredCount = min(fileBrowser->getNumFiltered(), previewsLoaded); - label = Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER")+ - (filteredCount!=previewsLoaded ? " ["+ Glib::ustring::format(filteredCount)+"/" : " (") - + Glib::ustring::format(previewsLoaded) + - (filteredCount!=previewsLoaded ? "]" : ")"))); + label = Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER") + + (filteredCount != previewsLoaded ? " [" + Glib::ustring::format(filteredCount) + "/" : " (") + + Glib::ustring::format(previewsLoaded) + + (filteredCount != previewsLoaded ? "]" : ")"))); } else { hbb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::FIND, Gtk::ICON_SIZE_MENU))); - label = Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER")+" [" +Glib::ustring::format(std::fixed, std::setprecision(0), std::setw(3), (double)previewsLoaded / previewsToLoad*100 )+"%]" )); - filepanel->loadingThumbs("",(double)previewsLoaded / previewsToLoad); + label = Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER") + " [" + Glib::ustring::format(std::fixed, std::setprecision(0), std::setw(3), (double)previewsLoaded / previewsToLoad * 100 ) + "%]" )); + filepanel->loadingThumbs("", (double)previewsLoaded / previewsToLoad); } - if( options.mainNBVertical ) - label->set_angle(90); + + if( options.mainNBVertical ) { + label->set_angle(90); + } + hbb->pack_start (*label); hbb->set_spacing (2); hbb->set_tooltip_markup (M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); hbb->show_all (); - nb->set_tab_label(*filepanel,*hbb); + nb->set_tab_label(*filepanel, *hbb); } } -int refreshProgressBarUI (void* data) { +int refreshProgressBarUI (void* data) +{ (static_cast(data))->_refreshProgressBar (); return 0; } -void FileCatalog::filterApplied() { +void FileCatalog::filterApplied() +{ g_idle_add (refreshProgressBarUI, this); } -void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) { +void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) +{ - if ( dir_id != selectedDirectoryId ) + if ( dir_id != selectedDirectoryId ) { return; + } // put it into the "full directory" browser fdn->setImageAreaToolListener (iatlistener); fileBrowser->addEntry (fdn); - + // update exif filter settings (minimal & maximal values of exif tags, cameras, lenses, etc...) const CacheImageData* cfs = fdn->thumbnail->getCacheImageData(); { - MyMutex::MyLock lock(dirEFSMutex); - if (cfs->exifValid) { - if (cfs->fnumber < dirEFS.fnumberFrom) - dirEFS.fnumberFrom = cfs->fnumber; - if (cfs->fnumber > dirEFS.fnumberTo) - dirEFS.fnumberTo = cfs->fnumber; - if (cfs->shutter < dirEFS.shutterFrom) - dirEFS.shutterFrom = cfs->shutter; - if (cfs->shutter > dirEFS.shutterTo) - dirEFS.shutterTo = cfs->shutter; - if (cfs->iso>0 && (int)cfs->iso < dirEFS.isoFrom) - dirEFS.isoFrom = (int)cfs->iso; - if (cfs->iso>0 && (int)cfs->iso > dirEFS.isoTo) - dirEFS.isoTo = (int)cfs->iso; - if (cfs->focalLen < dirEFS.focalFrom) - dirEFS.focalFrom = cfs->focalLen; - if (cfs->focalLen > dirEFS.focalTo) - dirEFS.focalTo = cfs->focalLen; - } - dirEFS.filetypes.insert (cfs->filetype); - dirEFS.cameras.insert (cfs->getCamera()); - dirEFS.lenses.insert (cfs->lens); - dirEFS.expcomp.insert (cfs->expcomp); + MyMutex::MyLock lock(dirEFSMutex); + + if (cfs->exifValid) { + if (cfs->fnumber < dirEFS.fnumberFrom) { + dirEFS.fnumberFrom = cfs->fnumber; + } + + if (cfs->fnumber > dirEFS.fnumberTo) { + dirEFS.fnumberTo = cfs->fnumber; + } + + if (cfs->shutter < dirEFS.shutterFrom) { + dirEFS.shutterFrom = cfs->shutter; + } + + if (cfs->shutter > dirEFS.shutterTo) { + dirEFS.shutterTo = cfs->shutter; + } + + if (cfs->iso > 0 && (int)cfs->iso < dirEFS.isoFrom) { + dirEFS.isoFrom = (int)cfs->iso; + } + + if (cfs->iso > 0 && (int)cfs->iso > dirEFS.isoTo) { + dirEFS.isoTo = (int)cfs->iso; + } + + if (cfs->focalLen < dirEFS.focalFrom) { + dirEFS.focalFrom = cfs->focalLen; + } + + if (cfs->focalLen > dirEFS.focalTo) { + dirEFS.focalTo = cfs->focalLen; + } + } + + dirEFS.filetypes.insert (cfs->filetype); + dirEFS.cameras.insert (cfs->getCamera()); + dirEFS.lenses.insert (cfs->lens); + dirEFS.expcomp.insert (cfs->expcomp); } previewsLoaded++; @@ -651,13 +728,15 @@ void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) { g_idle_add (refreshProgressBarUI, this); } -int prevfinished (void* data) { +int prevfinished (void* data) +{ (static_cast(data))->previewsFinishedUI (); return 0; } // Called within GTK UI thread -void FileCatalog::previewsFinishedUI () { +void FileCatalog::previewsFinishedUI () +{ { GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected @@ -666,43 +745,45 @@ void FileCatalog::previewsFinishedUI () { if (filterPanel) { filterPanel->set_sensitive (true); - if ( !hasValidCurrentEFS ){ + + if ( !hasValidCurrentEFS ) { MyMutex::MyLock lock(dirEFSMutex); currentEFS = dirEFS; - filterPanel->setFilter ( dirEFS,true ); - }else { - filterPanel->setFilter ( currentEFS,false ); + filterPanel->setFilter ( dirEFS, true ); + } else { + filterPanel->setFilter ( currentEFS, false ); } } - if (exportPanel) + if (exportPanel) { exportPanel->set_sensitive (true); + } // restart anything that might have been loaded low quality fileBrowser->refreshQuickThumbImages(); fileBrowser->applyFilter (getFilter()); // refresh total image count _refreshProgressBar(); } - filepanel->loadingThumbs(M("PROGRESSBAR_READY"),0); + filepanel->loadingThumbs(M("PROGRESSBAR_READY"), 0); - if (!imageToSelect_fname.empty()){ + if (!imageToSelect_fname.empty()) { fileBrowser->selectImage(imageToSelect_fname); imageToSelect_fname = ""; } - if (!refImageForOpen_fname.empty() && actionNextPrevious!=NAV_NONE){ - fileBrowser->openNextPreviousEditorImage(refImageForOpen_fname,actionNextPrevious); + if (!refImageForOpen_fname.empty() && actionNextPrevious != NAV_NONE) { + fileBrowser->openNextPreviousEditorImage(refImageForOpen_fname, actionNextPrevious); refImageForOpen_fname = ""; actionNextPrevious = NAV_NONE; } } -void FileCatalog::previewsFinished (int dir_id) { +void FileCatalog::previewsFinished (int dir_id) +{ - if ( dir_id != selectedDirectoryId ) - { - return; - } + if ( dir_id != selectedDirectoryId ) { + return; + } if (!hasValidCurrentEFS) { MyMutex::MyLock lock(dirEFSMutex); @@ -712,41 +793,55 @@ void FileCatalog::previewsFinished (int dir_id) { g_idle_add (prevfinished, this); } -void FileCatalog::setEnabled (bool e) { +void FileCatalog::setEnabled (bool e) +{ enabled = e; } -void FileCatalog::redrawAll () { +void FileCatalog::redrawAll () +{ fileBrowser->queue_draw (); } -void FileCatalog::refreshThumbImages () { +void FileCatalog::refreshThumbImages () +{ fileBrowser->refreshThumbImages (); } -void FileCatalog::refreshHeight () { +void FileCatalog::refreshHeight () +{ int newHeight = fileBrowser->getEffectiveHeight(); + if (newHeight < 5) { // This may occure if there's no thumbnail. int w, h; get_size_request(w, h); newHeight = h; } - if (hbToolBar1->is_visible() && !options.FileBrowserToolbarSingleRow) + + if (hbToolBar1->is_visible() && !options.FileBrowserToolbarSingleRow) { newHeight += hbToolBar1->get_height(); - if (buttonBar->is_visible()) + } + + if (buttonBar->is_visible()) { newHeight += buttonBar->get_height(); - set_size_request(0, newHeight+2); // HOMBRE: yeah, +2, there's always 2 pixels missing... sorry for this dirty hack O:) + } + + set_size_request(0, newHeight + 2); // HOMBRE: yeah, +2, there's always 2 pixels missing... sorry for this dirty hack O:) } -void FileCatalog::_openImage (std::vector tmb) { +void FileCatalog::_openImage (std::vector tmb) +{ + + if (enabled && listener != NULL) { + bool continueToLoad = true; + + for (size_t i = 0; i < tmb.size() && continueToLoad; i++) { + // Open the image here, and stop if in Single Editor mode, or if an image couldn't + // be opened, would it be because the file doesn't exist or because of lack of RAM + if( !(listener->fileSelected (tmb[i])) && !options.tabbedUI ) { + continueToLoad = false; + } - if (enabled && listener!=NULL) { - bool continueToLoad=true; - for (size_t i=0; i< tmb.size() && continueToLoad; i++) { - // Open the image here, and stop if in Single Editor mode, or if an image couldn't - // be opened, would it be because the file doesn't exist or because of lack of RAM - if( !(listener->fileSelected (tmb[i])) && !options.tabbedUI ) - continueToLoad = false; tmb[i]->decreaseRef (); } } @@ -757,7 +852,8 @@ struct FCOIParams { std::vector tmb; }; -int openRequestedUI (void* p) { +int openRequestedUI (void* p) +{ FCOIParams* params = static_cast(p); params->catalog->_openImage (params->tmb); delete params; @@ -765,26 +861,32 @@ int openRequestedUI (void* p) { return 0; } -void FileCatalog::openRequested (std::vector tmb) { +void FileCatalog::openRequested (std::vector tmb) +{ FCOIParams* params = new FCOIParams; params->catalog = this; params->tmb = tmb; - for (size_t i=0; iincreaseRef (); + } + g_idle_add (openRequestedUI, params); } -void FileCatalog::deleteRequested (std::vector tbe, bool inclBatchProcessed) { +void FileCatalog::deleteRequested (std::vector tbe, bool inclBatchProcessed) +{ - if (tbe.empty()) + if (tbe.empty()) { return; + } Gtk::MessageDialog msd (M("FILEBROWSER_DELETEDLGLABEL"), true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true); msd.set_secondary_text(Glib::ustring::compose ( inclBatchProcessed ? M("FILEBROWSER_DELETEDLGMSGINCLPROC") : M("FILEBROWSER_DELETEDLGMSG"), tbe.size()), true); - if (msd.run()==Gtk::RESPONSE_YES) { - for (unsigned int i=0; ifilename; // remove from browser FileBrowserEntry* t = fileBrowser->delEntry (fname); @@ -795,135 +897,159 @@ void FileCatalog::deleteRequested (std::vector tbe, bool inc // delete from file system safe_g_remove (fname); // delete paramfile if found - safe_g_remove (Glib::ustring(fname+paramFileExtension)); - safe_g_remove (Glib::ustring(removeExtension(fname)+paramFileExtension)); + safe_g_remove (Glib::ustring(fname + paramFileExtension)); + safe_g_remove (Glib::ustring(removeExtension(fname) + paramFileExtension)); // delete .thm file - safe_g_remove (Glib::ustring(removeExtension(fname)+".thm")); - safe_g_remove (Glib::ustring(removeExtension(fname)+".THM")); + safe_g_remove (Glib::ustring(removeExtension(fname) + ".thm")); + safe_g_remove (Glib::ustring(removeExtension(fname) + ".THM")); - if (inclBatchProcessed) { - Glib::ustring procfName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - if (safe_file_test (procfName, Glib::FILE_TEST_EXISTS)) safe_g_remove (procfName); + if (inclBatchProcessed) { + Glib::ustring procfName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - // 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); - } + 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); + } + } previewsLoaded--; } _refreshProgressBar(); - redrawAll (); + redrawAll (); } } -void FileCatalog::copyMoveRequested (std::vector tbe, bool moveRequested) { +void FileCatalog::copyMoveRequested (std::vector tbe, bool moveRequested) +{ - if (tbe.empty()) + if (tbe.empty()) { return; + } Glib::ustring fc_title; - if (moveRequested) fc_title=M("FILEBROWSER_POPUPMOVETO"); - else fc_title=M("FILEBROWSER_POPUPCOPYTO"); - Gtk::FileChooserDialog fc(fc_title,Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); - fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); - fc.add_button( Gtk::StockID("gtk-ok"), Gtk::RESPONSE_OK); - // open dialog at the 1-st file's path - fc.set_filename(tbe[0]->filename); - //!!! TODO prevent dialog closing on "enter" key press - bool filecopymovecomplete; - int i_copyindex; + if (moveRequested) { + fc_title = M("FILEBROWSER_POPUPMOVETO"); + } else { + fc_title = M("FILEBROWSER_POPUPCOPYTO"); + } - if( fc.run() == Gtk::RESPONSE_OK ){ - Glib::ustring dest_Dir = fc.get_current_folder(); + Gtk::FileChooserDialog fc(fc_title, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); + fc.add_button( Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); + fc.add_button( Gtk::StockID("gtk-ok"), Gtk::RESPONSE_OK); + // open dialog at the 1-st file's path + fc.set_filename(tbe[0]->filename); + //!!! TODO prevent dialog closing on "enter" key press - // iterate through selected files - for (unsigned int i=0; ifilename; - Glib::ustring src_Dir = Glib::path_get_dirname(src_fPath); - Glib::RefPtr src_file = Gio::File::create_for_path ( src_fPath ); - if( !src_file ) continue; // if file is missing - skip it + bool filecopymovecomplete; + int i_copyindex; - Glib::ustring fname=src_file->get_basename(); - Glib::ustring fname_noExt = removeExtension(fname); - Glib::ustring fname_Ext = getExtension(fname); + if( fc.run() == Gtk::RESPONSE_OK ) { + Glib::ustring dest_Dir = fc.get_current_folder(); - // construct destination File Paths - Glib::ustring dest_fPath = Glib::build_filename (dest_Dir, fname); - Glib::ustring dest_fPath_param= dest_fPath + paramFileExtension; + // iterate through selected files + for (unsigned int i = 0; i < tbe.size(); i++) { + Glib::ustring src_fPath = tbe[i]->filename; + Glib::ustring src_Dir = Glib::path_get_dirname(src_fPath); + Glib::RefPtr src_file = Gio::File::create_for_path ( src_fPath ); - if (moveRequested && (src_Dir==dest_Dir)) continue; - /* comparison of src_Dir and dest_Dir is done per image for compatibility with - possible future use of Collections as source where each file's source path may be different.*/ + if( !src_file ) { + continue; // if file is missing - skip it + } - filecopymovecomplete = false; - i_copyindex = 1; - 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)){ - // copy/move file to destination - Glib::RefPtr dest_file = Gio::File::create_for_path ( dest_fPath ); - if (moveRequested) { - // move file - src_file->move(dest_file); - // re-attach cache files - cacheMgr->renameEntry (src_fPath, tbe[i]->thumbnail->getMD5(), dest_fPath); - // remove from browser - fileBrowser->delEntry (src_fPath); + Glib::ustring fname = src_file->get_basename(); + Glib::ustring fname_noExt = removeExtension(fname); + Glib::ustring fname_Ext = getExtension(fname); + + // construct destination File Paths + Glib::ustring dest_fPath = Glib::build_filename (dest_Dir, fname); + Glib::ustring dest_fPath_param = dest_fPath + paramFileExtension; + + if (moveRequested && (src_Dir == dest_Dir)) { + continue; + } + + /* comparison of src_Dir and dest_Dir is done per image for compatibility with + possible future use of Collections as source where each file's source path may be different.*/ + + filecopymovecomplete = false; + i_copyindex = 1; + + 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)) { + // copy/move file to destination + Glib::RefPtr dest_file = Gio::File::create_for_path ( dest_fPath ); + + if (moveRequested) { + // move file + src_file->move(dest_file); + // re-attach cache files + cacheMgr->renameEntry (src_fPath, tbe[i]->thumbnail->getMD5(), dest_fPath); + // remove from browser + fileBrowser->delEntry (src_fPath); previewsLoaded--; - } - else - src_file->copy(dest_file); + } else { + src_file->copy(dest_file); + } - // 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 ); + // 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)){ - 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)){ - // profile already got copied to destination from cache after cacheMgr->renameEntry - // delete source profile as cleanup - safe_g_remove (src_fPath + paramFileExtension); - } - else - scr_param->move(dest_param); - } - else - scr_param->copy(dest_param); - } - filecopymovecomplete = true; - } - else{ - // adjust destination fname to avoid conflicts (append "_", preserve extension) - Glib::ustring dest_fname = Glib::ustring::compose("%1%2%3%4%5",fname_noExt,"_",i_copyindex,".",fname_Ext); - // re-construct destination File Paths - dest_fPath = Glib::build_filename (dest_Dir, dest_fname); - dest_fPath_param= dest_fPath + paramFileExtension; - i_copyindex++; - } - }//while - } // i 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)) { + // profile already got copied to destination from cache after cacheMgr->renameEntry + // delete source profile as cleanup + safe_g_remove (src_fPath + paramFileExtension); + } else { + scr_param->move(dest_param); + } + } else { + scr_param->copy(dest_param); + } + } + + filecopymovecomplete = true; + } else { + // adjust destination fname to avoid conflicts (append "_", preserve extension) + Glib::ustring dest_fname = Glib::ustring::compose("%1%2%3%4%5", fname_noExt, "_", i_copyindex, ".", fname_Ext); + // re-construct destination File Paths + dest_fPath = Glib::build_filename (dest_Dir, dest_fname); + dest_fPath_param = dest_fPath + paramFileExtension; + i_copyindex++; + } + }//while + } // i tbe, bool fastmode) { +void FileCatalog::developRequested (std::vector tbe, bool fastmode) +{ if (listener) { - std::vector entries; + std::vector entries; // TODO: (HOMBRE) should we still use parallelization here, now that thumbnails are processed asynchronously...? //#pragma omp parallel for ordered - for (size_t i=0; ithumbnail; rtengine::procparams::ProcParams params = th->getProcParams(); @@ -932,43 +1058,98 @@ void FileCatalog::developRequested (std::vector tbe, bool fas // controlling time and resource consuming tasks // and also those which effect is not pronounced after reducing the image size // TODO!!! could expose selections below via preferences - if (fastmode){ - if (options.fastexport_bypass_sharpening ) params.sharpening.enabled = false; - if (options.fastexport_bypass_sharpenEdge ) params.sharpenEdge.enabled = false; - if (options.fastexport_bypass_sharpenMicro ) params.sharpenMicro.enabled = false; - //if (options.fastexport_bypass_lumaDenoise ) params.lumaDenoise.enabled = false; - //if (options.fastexport_bypass_colorDenoise ) params.colorDenoise.enabled = false; - if (options.fastexport_bypass_defringe ) params.defringe.enabled = false; - if (options.fastexport_bypass_dirpyrDenoise ) params.dirpyrDenoise.enabled = false; - if (options.fastexport_bypass_sh_hq ) params.sh.hq = false; - if (options.fastexport_bypass_dirpyrequalizer ) params.dirpyrequalizer.enabled = false; - if (options.fastexport_bypass_wavelet ) params.wavelet.enabled = false; - //if (options.fastexport_bypass_raw_bayer_all_enhance ) params.raw.bayersensor.all_enhance = false; - if (options.fastexport_bypass_raw_bayer_dcb_iterations ) params.raw.bayersensor.dcb_iterations = 0; - if (options.fastexport_bypass_raw_bayer_dcb_enhance ) params.raw.bayersensor.dcb_enhance = false; - if (options.fastexport_bypass_raw_bayer_lmmse_iterations) params.raw.bayersensor.lmmse_iterations = 0; - if (options.fastexport_bypass_raw_bayer_linenoise ) params.raw.bayersensor.linenoise = 0; - if (options.fastexport_bypass_raw_bayer_greenthresh ) params.raw.bayersensor.greenthresh = 0; - if (options.fastexport_bypass_raw_ccSteps ) {params.raw.bayersensor.ccSteps = params.raw.xtranssensor.ccSteps = 0;} - if (options.fastexport_bypass_raw_ca ) {params.raw.ca_autocorrect = false; params.raw.cared=0; params.raw.cablue=0;} - if (options.fastexport_bypass_raw_df ) {params.raw.df_autoselect = false; params.raw.dark_frame="";} - if (options.fastexport_bypass_raw_ff ) {params.raw.ff_AutoSelect = false; params.raw.ff_file="";} - params.raw.bayersensor.method = options.fastexport_raw_bayer_method ; - params.raw.xtranssensor.method = options.fastexport_raw_xtrans_method; - params.icm.input = options.fastexport_icm_input ; - params.icm.working = options.fastexport_icm_working ; - params.icm.output = options.fastexport_icm_output ; - params.icm.gamma = options.fastexport_icm_gamma ; - params.resize.enabled = options.fastexport_resize_enabled ; - params.resize.scale = options.fastexport_resize_scale ; - params.resize.appliesTo = options.fastexport_resize_appliesTo ; - params.resize.method = options.fastexport_resize_method ; - params.resize.dataspec = options.fastexport_resize_dataspec ; - params.resize.width = options.fastexport_resize_width ; - params.resize.height = options.fastexport_resize_height ; + if (fastmode) { + if (options.fastexport_bypass_sharpening ) { + params.sharpening.enabled = false; + } + + if (options.fastexport_bypass_sharpenEdge ) { + params.sharpenEdge.enabled = false; + } + + if (options.fastexport_bypass_sharpenMicro ) { + params.sharpenMicro.enabled = false; + } + + //if (options.fastexport_bypass_lumaDenoise ) params.lumaDenoise.enabled = false; + //if (options.fastexport_bypass_colorDenoise ) params.colorDenoise.enabled = false; + if (options.fastexport_bypass_defringe ) { + params.defringe.enabled = false; + } + + if (options.fastexport_bypass_dirpyrDenoise ) { + params.dirpyrDenoise.enabled = false; + } + + if (options.fastexport_bypass_sh_hq ) { + params.sh.hq = false; + } + + if (options.fastexport_bypass_dirpyrequalizer ) { + params.dirpyrequalizer.enabled = false; + } + + if (options.fastexport_bypass_wavelet ) { + params.wavelet.enabled = false; + } + + //if (options.fastexport_bypass_raw_bayer_all_enhance ) params.raw.bayersensor.all_enhance = false; + if (options.fastexport_bypass_raw_bayer_dcb_iterations ) { + params.raw.bayersensor.dcb_iterations = 0; + } + + if (options.fastexport_bypass_raw_bayer_dcb_enhance ) { + params.raw.bayersensor.dcb_enhance = false; + } + + if (options.fastexport_bypass_raw_bayer_lmmse_iterations) { + params.raw.bayersensor.lmmse_iterations = 0; + } + + if (options.fastexport_bypass_raw_bayer_linenoise ) { + params.raw.bayersensor.linenoise = 0; + } + + if (options.fastexport_bypass_raw_bayer_greenthresh ) { + params.raw.bayersensor.greenthresh = 0; + } + + if (options.fastexport_bypass_raw_ccSteps ) { + params.raw.bayersensor.ccSteps = params.raw.xtranssensor.ccSteps = 0; + } + + if (options.fastexport_bypass_raw_ca ) { + params.raw.ca_autocorrect = false; + params.raw.cared = 0; + params.raw.cablue = 0; + } + + if (options.fastexport_bypass_raw_df ) { + params.raw.df_autoselect = false; + params.raw.dark_frame = ""; + } + + if (options.fastexport_bypass_raw_ff ) { + params.raw.ff_AutoSelect = false; + params.raw.ff_file = ""; + } + + params.raw.bayersensor.method = options.fastexport_raw_bayer_method ; + params.raw.xtranssensor.method = options.fastexport_raw_xtrans_method; + params.icm.input = options.fastexport_icm_input ; + params.icm.working = options.fastexport_icm_working ; + params.icm.output = options.fastexport_icm_output ; + params.icm.gamma = options.fastexport_icm_gamma ; + params.resize.enabled = options.fastexport_resize_enabled ; + params.resize.scale = options.fastexport_resize_scale ; + params.resize.appliesTo = options.fastexport_resize_appliesTo ; + params.resize.method = options.fastexport_resize_method ; + params.resize.dataspec = options.fastexport_resize_dataspec ; + params.resize.width = options.fastexport_resize_width ; + params.resize.height = options.fastexport_resize_height ; } - rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType()==FT_Raw, params); + rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params); int pw; int ph = BatchQueue::calcMaxThumbnailHeight(); @@ -977,8 +1158,8 @@ void FileCatalog::developRequested (std::vector tbe, bool fas // processThumbImage is the processing intensive part, but adding to queue must be ordered //#pragma omp ordered //{ - BatchQueueEntry* bqh = new BatchQueueEntry (pjob, params, fbe->filename, pw, ph, th); - entries.push_back(bqh); + BatchQueueEntry* bqh = new BatchQueueEntry (pjob, params, fbe->filename, pw, ph, th); + entries.push_back(bqh); //} } @@ -986,128 +1167,143 @@ void FileCatalog::developRequested (std::vector tbe, bool fas } } -void FileCatalog::exportRequested (){ +void FileCatalog::exportRequested () +{ } -void FileCatalog::setExportPanel (ExportPanel* expanel) { +void FileCatalog::setExportPanel (ExportPanel* expanel) +{ - exportPanel = expanel; - exportPanel->set_sensitive (false); - exportPanel->setExportPanelListener (this); - fileBrowser->setExportPanel(expanel); + exportPanel = expanel; + exportPanel->set_sensitive (false); + exportPanel->setExportPanelListener (this); + fileBrowser->setExportPanel(expanel); } -void FileCatalog::renameRequested (std::vector tbe) { +void FileCatalog::renameRequested (std::vector tbe) +{ - bool success; + bool success; RenameDialog* renameDlg = new RenameDialog ((Gtk::Window*)get_toplevel()); - for (size_t i=0; iinitName (Glib::path_get_basename (tbe[i]->filename), tbe[i]->thumbnail->getCacheImageData()); + for (size_t i = 0; i < tbe.size(); i++) { + renameDlg->initName (Glib::path_get_basename (tbe[i]->filename), tbe[i]->thumbnail->getCacheImageData()); Glib::ustring ofname = tbe[i]->filename; Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); - success = false; + success = false; + do { - if (renameDlg->run ()== Gtk::RESPONSE_OK) { - Glib::ustring nBaseName = renameDlg->getNewName (); - // if path has directory components, exit - if (Glib::path_get_dirname (nBaseName) != ".") - continue; - // if no extension is given, concatenate the extension of the original file - Glib::ustring ext = getExtension (nBaseName); - if (ext.empty()) - nBaseName += "." + getExtension (baseName); - Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); + if (renameDlg->run () == Gtk::RESPONSE_OK) { + Glib::ustring nBaseName = renameDlg->getNewName (); - /* check if filename already exists*/ - if (safe_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)) { - cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - safe_g_remove(ofname + paramFileExtension); - reparseDirectory (); - } - } - } - else - success = true; - } while (!success); - renameDlg->hide (); - } - delete renameDlg; -/* // ask for new file name - Gtk::Dialog dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *((Gtk::Window*)get_toplevel()), true, true); - - dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); - dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + // if path has directory components, exit + if (Glib::path_get_dirname (nBaseName) != ".") { + continue; + } - Gtk::Label l; - dialog.get_vbox()->pack_start (l, Gtk::PACK_SHRINK); + // if no extension is given, concatenate the extension of the original file + Glib::ustring ext = getExtension (nBaseName); - Gtk::Entry nfentry; + if (ext.empty()) { + nBaseName += "." + getExtension (baseName); + } - dialog.get_vbox()->pack_start (nfentry, Gtk::PACK_SHRINK); - dialog.get_vbox()->show_all (); + Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); - nfentry.set_activates_default (true); - dialog.set_default_response (Gtk::RESPONSE_OK); + /* check if filename already exists*/ + if (safe_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; - for (int i=0; ifilename; - Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); - Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); - - l.set_markup (Glib::ustring("") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("")); - nfentry.set_text (baseName); - nfentry.select_region (0, baseName.size()); - - if (dialog.run ()== Gtk::RESPONSE_OK) { - Glib::ustring nBaseName = nfentry.get_text (); - // if path has directory components, exit - if (Glib::path_get_dirname (nBaseName) != ".") - continue; - // if no extension is given, concatenate the extension of the original file - if (nBaseName.find ('.')==nBaseName.npos) { - size_t lastdot = baseName.find_last_of ('.'); - nBaseName += "." + (lastdot!=Glib::ustring::npos ? baseName.substr (lastdot+1) : ""); + if (!safe_g_rename (ofname, nfname)) { + cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); + safe_g_remove(ofname + paramFileExtension); + reparseDirectory (); + } + } + } else { + success = true; } - Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); - if (!safe_g_rename (ofname, nfname)) { - cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - // the remaining part (removing old and adding new entry) is done by the directory monitor - reparseDirectory (); -// on_dir_changed (Gio::File::create_for_path (nfname), Gio::File::create_for_path (nfname), Gio::FILE_MONITOR_EVENT_CHANGED, true); + } while (!success); + + renameDlg->hide (); + } + + delete renameDlg; + /* // ask for new file name + Gtk::Dialog dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *((Gtk::Window*)get_toplevel()), true, true); + + dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + + Gtk::Label l; + dialog.get_vbox()->pack_start (l, Gtk::PACK_SHRINK); + + Gtk::Entry nfentry; + + dialog.get_vbox()->pack_start (nfentry, Gtk::PACK_SHRINK); + dialog.get_vbox()->show_all (); + + nfentry.set_activates_default (true); + dialog.set_default_response (Gtk::RESPONSE_OK); + + for (int i=0; ifilename; + Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); + Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); + + l.set_markup (Glib::ustring("") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("")); + nfentry.set_text (baseName); + nfentry.select_region (0, baseName.size()); + + if (dialog.run ()== Gtk::RESPONSE_OK) { + Glib::ustring nBaseName = nfentry.get_text (); + // if path has directory components, exit + if (Glib::path_get_dirname (nBaseName) != ".") + continue; + // if no extension is given, concatenate the extension of the original file + if (nBaseName.find ('.')==nBaseName.npos) { + size_t lastdot = baseName.find_last_of ('.'); + nBaseName += "." + (lastdot!=Glib::ustring::npos ? baseName.substr (lastdot+1) : ""); + } + Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); + if (!safe_g_rename (ofname, nfname)) { + cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); + // the remaining part (removing old and adding new entry) is done by the directory monitor + reparseDirectory (); + // on_dir_changed (Gio::File::create_for_path (nfname), Gio::File::create_for_path (nfname), Gio::FILE_MONITOR_EVENT_CHANGED, true); + } } } + */ +} + +void FileCatalog::clearFromCacheRequested (std::vector tbe, bool leavenotrace) +{ + + if (tbe.empty()) { + return; + } + + for (unsigned int i = 0; i < tbe.size(); i++) { + Glib::ustring fname = tbe[i]->filename; + // remove from cache + cacheMgr->clearFromCache (fname, leavenotrace); } - */ } -void FileCatalog::clearFromCacheRequested (std::vector tbe, bool leavenotrace) { +void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick) +{ - if (tbe.empty()) - return; - - for (unsigned int i=0; ifilename; - // remove from cache - cacheMgr->clearFromCache (fname,leavenotrace); - } -} - -void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick) { - //was control key pressed bool control_down = modifierKey & GDK_CONTROL_MASK; @@ -1120,271 +1316,360 @@ void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick const int numCateg = sizeof(bCateg) / sizeof(bCateg[0]); const int numButtons = sizeof(categoryButtons) / sizeof(categoryButtons[0]); - for (int i=0; iset_active(!b->get_active()); + if (isMouseClick) { + b->set_active(!b->get_active()); + } //if both control and shift keys were pressed, do nothing if (!(control_down && shift_down)) { - fileBrowser->getScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); + fileBrowser->getScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); - //we look how many stars are already toggled on, if any - int toggled_stars_count=0, buttons=0, start_star=0, toggled_button=0; + //we look how many stars are already toggled on, if any + int toggled_stars_count = 0, buttons = 0, start_star = 0, toggled_button = 0; - for (int i=0; iget_active()) { - if (i>0 && i<17) { - toggled_stars_count ++; - start_star = i; - } - buttons |= (1 << i); - } - if (categoryButtons[i] == b) toggled_button = i; - } + for (int i = 0; i < numButtons; i++) { + if (categoryButtons[i]->get_active()) { + if (i > 0 && i < 17) { + toggled_stars_count ++; + start_star = i; + } - // if no modifier key is pressed, - if (!(control_down || shift_down)) { + buttons |= (1 << i); + } + + if (categoryButtons[i] == b) { + toggled_button = i; + } + } + + // if no modifier key is pressed, + if (!(control_down || shift_down)) { // if we're deselecting non-trashed if (toggled_button == 18 && (buttons & (1 << toggled_button))) { categoryButtons[0]->set_active (true); - for (int i=1; iset_active (false); + } } - // if we're deselecting the only star still active + // if we're deselecting the only star still active else if (toggled_stars_count == 1 && (buttons & (1 << toggled_button))) { - // activate clear-filters - categoryButtons[0]->set_active (true); - // deactivate the toggled filter - categoryButtons[toggled_button]->set_active (false); - } - // if we're deselecting trash - else if (toggled_button == 17 && (buttons & (1 << toggled_button))) { - categoryButtons[0]->set_active (true); - categoryButtons[17]->set_active (false); - } - else { - // activate the toggled filter, deactivate the rest - for (int i=0; iset_active (i==toggled_button); - } - } + // activate clear-filters + categoryButtons[0]->set_active (true); + // deactivate the toggled filter + categoryButtons[toggled_button]->set_active (false); + } + // if we're deselecting trash + else if (toggled_button == 17 && (buttons & (1 << toggled_button))) { + categoryButtons[0]->set_active (true); + categoryButtons[17]->set_active (false); + } else { + // activate the toggled filter, deactivate the rest + for (int i = 0; i < numButtons; i++) { + categoryButtons[i]->set_active (i == toggled_button); + } + } + } //modifier key allowed only for stars and color labels... - else if (toggled_button>0 && toggled_button<17) { - if (control_down) { - //control is pressed - if (toggled_stars_count == 1 && (buttons & (1 << toggled_button))) { - //we're deselecting the only star still active, so we activate clear-filters - categoryButtons[0]->set_active(true); - //and we deselect the toggled star - categoryButtons[toggled_button]->set_active (false); - } - else if (toggled_stars_count >= 1) { - //we toggle the state of a star (eventually another one than the only one selected) - categoryButtons[toggled_button]->set_active(!categoryButtons[toggled_button]->get_active()); - } - else { - //no star selected - //we deselect the 2 non star filters - if (buttons & 1 ) categoryButtons[0]->set_active(false); - if (buttons & (1 << 17)) categoryButtons[17]->set_active(false); - //and we toggle on the star - categoryButtons[toggled_button]->set_active (true); - } - } - else { - //shift is pressed, only allowed if 0 or 1 star & labels is selected - if (!toggled_stars_count) { - //we deselect the 2 non star filters - if (buttons & 1 ) categoryButtons[0]->set_active(false); - if (buttons & (1 << 7)) categoryButtons[7]->set_active(false); - if (buttons & (1 << 13)) categoryButtons[13]->set_active(false); - if (buttons & (1 << 17)) categoryButtons[17]->set_active(false); - //and we set the start star to 1 (unrated images) - start_star = 1; - //we act as if one star were selected - toggled_stars_count = 1; - } - if (toggled_stars_count == 1) { - int current_star=min(start_star,toggled_button); - int last_star =max(start_star,toggled_button); - //we permute the start and the end star for the next loop - for (; current_star <= last_star; current_star++) { - //we toggle on all the star in the range - if (!(buttons & (1 << current_star))) categoryButtons[current_star]->set_active(true); - } - } - //if more than one star & color label is selected, do nothing - } - } + else if (toggled_button > 0 && toggled_button < 17) { + if (control_down) { + //control is pressed + if (toggled_stars_count == 1 && (buttons & (1 << toggled_button))) { + //we're deselecting the only star still active, so we activate clear-filters + categoryButtons[0]->set_active(true); + //and we deselect the toggled star + categoryButtons[toggled_button]->set_active (false); + } else if (toggled_stars_count >= 1) { + //we toggle the state of a star (eventually another one than the only one selected) + categoryButtons[toggled_button]->set_active(!categoryButtons[toggled_button]->get_active()); + } else { + //no star selected + //we deselect the 2 non star filters + if (buttons & 1 ) { + categoryButtons[0]->set_active(false); + } + + if (buttons & (1 << 17)) { + categoryButtons[17]->set_active(false); + } + + //and we toggle on the star + categoryButtons[toggled_button]->set_active (true); + } + } else { + //shift is pressed, only allowed if 0 or 1 star & labels is selected + if (!toggled_stars_count) { + //we deselect the 2 non star filters + if (buttons & 1 ) { + categoryButtons[0]->set_active(false); + } + + if (buttons & (1 << 7)) { + categoryButtons[7]->set_active(false); + } + + if (buttons & (1 << 13)) { + categoryButtons[13]->set_active(false); + } + + if (buttons & (1 << 17)) { + categoryButtons[17]->set_active(false); + } + + //and we set the start star to 1 (unrated images) + start_star = 1; + //we act as if one star were selected + toggled_stars_count = 1; + } + + if (toggled_stars_count == 1) { + int current_star = min(start_star, toggled_button); + int last_star = max(start_star, toggled_button); + + //we permute the start and the end star for the next loop + for (; current_star <= last_star; current_star++) { + //we toggle on all the star in the range + if (!(buttons & (1 << current_star))) { + categoryButtons[current_star]->set_active(true); + } + } + } + + //if more than one star & color label is selected, do nothing + } + } // ...or non-trashed with Control modifier - else if (toggled_button == 18 && control_down) - { + else if (toggled_button == 18 && control_down) { bNotTrash->set_active (!bNotTrash->get_active ()); } - bool active_now, active_before; + bool active_now, active_before; - // FilterClear: set the right images - // TODO: swapping FilterClear icon needs more work in categoryButtonToggled - /*active_now = bFilterClear->get_active(); - active_before = buttons & (1 << (0)); // 0 - if ( active_now && !active_before) bFilterClear->set_image (*iFilterClear); - else if (!active_now && active_before) bFilterClear->set_image (*igFilterClear);*/ + // FilterClear: set the right images + // TODO: swapping FilterClear icon needs more work in categoryButtonToggled + /*active_now = bFilterClear->get_active(); + active_before = buttons & (1 << (0)); // 0 + if ( active_now && !active_before) bFilterClear->set_image (*iFilterClear); + else if (!active_now && active_before) bFilterClear->set_image (*igFilterClear);*/ - // rank: set the right images - for (int i=0; i<5; i++) { - active_now = bRank[i]->get_active(); - active_before = buttons & (1 << (i+2)); // 2,3,4,5,6 - if ( active_now && !active_before) bRank[i]->set_image (*iranked[i]); - else if (!active_now && active_before) bRank[i]->set_image (*igranked[i]); - } - active_now = bUnRanked->get_active(); - active_before = buttons & (1 << (1)); // 1 - if ( active_now && !active_before) bUnRanked->set_image (*iUnRanked); - else if (!active_now && active_before) bUnRanked->set_image (*igUnRanked); + // rank: set the right images + for (int i = 0; i < 5; i++) { + active_now = bRank[i]->get_active(); + active_before = buttons & (1 << (i + 2)); // 2,3,4,5,6 - // color labels: set the right images - for (int i=0; i<5; i++) { - active_now = bCLabel[i]->get_active(); - active_before = buttons & (1 << (i+8)); // 8,9,10,11,12 - if ( active_now && !active_before) bCLabel[i]->set_image (*iCLabeled[i]); - else if (!active_now && active_before) bCLabel[i]->set_image (*igCLabeled[i]); - } - active_now = bUnCLabeled->get_active(); - active_before = buttons & (1 << (7)); // 7 - if ( active_now && !active_before) bUnCLabeled->set_image (*iUnCLabeled); - else if (!active_now && active_before) bUnCLabeled->set_image (*igUnCLabeled); + if ( active_now && !active_before) { + bRank[i]->set_image (*iranked[i]); + } else if (!active_now && active_before) { + bRank[i]->set_image (*igranked[i]); + } + } - // Edited: set the right images - for (int i=0; i<2; i++) { - active_now = bEdited[i]->get_active(); - active_before = buttons & (1 << (i+13)); //13,14 - if ( active_now && !active_before) bEdited[i]->set_image (*iEdited[i]); - else if (!active_now && active_before) bEdited[i]->set_image (*igEdited[i]); - } + active_now = bUnRanked->get_active(); + active_before = buttons & (1 << (1)); // 1 - // RecentlySaved: set the right images - for (int i=0; i<2; i++) { - active_now = bRecentlySaved[i]->get_active(); - active_before = buttons & (1 << (i+15));//15,16 - if ( active_now && !active_before) bRecentlySaved[i]->set_image (*iRecentlySaved[i]); - else if (!active_now && active_before) bRecentlySaved[i]->set_image (*igRecentlySaved[i]); - } + if ( active_now && !active_before) { + bUnRanked->set_image (*iUnRanked); + } else if (!active_now && active_before) { + bUnRanked->set_image (*igUnRanked); + } - fileBrowser->applyFilter (getFilter ()); - _refreshProgressBar(); + // color labels: set the right images + for (int i = 0; i < 5; i++) { + active_now = bCLabel[i]->get_active(); + active_before = buttons & (1 << (i + 8)); // 8,9,10,11,12 - //rearrange panels according to the selected filter - removeIfThere (hBox, trashButtonBox); - if (bTrash->get_active ()) - hBox->pack_start (*trashButtonBox, Gtk::PACK_SHRINK, 4); - hBox->queue_draw (); + if ( active_now && !active_before) { + bCLabel[i]->set_image (*iCLabeled[i]); + } else if (!active_now && active_before) { + bCLabel[i]->set_image (*igCLabeled[i]); + } + } - fileBrowser->setScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); + active_now = bUnCLabeled->get_active(); + active_before = buttons & (1 << (7)); // 7 + + if ( active_now && !active_before) { + bUnCLabeled->set_image (*iUnCLabeled); + } else if (!active_now && active_before) { + bUnCLabeled->set_image (*igUnCLabeled); + } + + // Edited: set the right images + for (int i = 0; i < 2; i++) { + active_now = bEdited[i]->get_active(); + active_before = buttons & (1 << (i + 13)); //13,14 + + if ( active_now && !active_before) { + bEdited[i]->set_image (*iEdited[i]); + } else if (!active_now && active_before) { + bEdited[i]->set_image (*igEdited[i]); + } + } + + // RecentlySaved: set the right images + for (int i = 0; i < 2; i++) { + active_now = bRecentlySaved[i]->get_active(); + active_before = buttons & (1 << (i + 15)); //15,16 + + if ( active_now && !active_before) { + bRecentlySaved[i]->set_image (*iRecentlySaved[i]); + } else if (!active_now && active_before) { + bRecentlySaved[i]->set_image (*igRecentlySaved[i]); + } + } + + fileBrowser->applyFilter (getFilter ()); + _refreshProgressBar(); + + //rearrange panels according to the selected filter + removeIfThere (hBox, trashButtonBox); + + if (bTrash->get_active ()) { + hBox->pack_start (*trashButtonBox, Gtk::PACK_SHRINK, 4); + } + + hBox->queue_draw (); + + fileBrowser->setScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]); } - for (int i=0; iget_active () || bRank[0]->get_active () || bRank[1]->get_active () || bRank[2]->get_active () || bRank[3]->get_active () || bRank[4]->get_active (); - bool anyCLabelFilterActive = bUnCLabeled->get_active () || bCLabel[0]->get_active ()|| bCLabel[1]->get_active ()|| bCLabel[2]->get_active ()|| bCLabel[3]->get_active ()|| bCLabel[4]->get_active (); - bool anyEditedFilterActive = bEdited[0]->get_active() || bEdited[1]->get_active(); - bool anyRecentlySavedFilterActive = bRecentlySaved[0]->get_active() || bRecentlySaved[1]->get_active(); + bool anyRankFilterActive = bUnRanked->get_active () || bRank[0]->get_active () || bRank[1]->get_active () || bRank[2]->get_active () || bRank[3]->get_active () || bRank[4]->get_active (); + bool anyCLabelFilterActive = bUnCLabeled->get_active () || bCLabel[0]->get_active () || bCLabel[1]->get_active () || bCLabel[2]->get_active () || bCLabel[3]->get_active () || bCLabel[4]->get_active (); + bool anyEditedFilterActive = bEdited[0]->get_active() || bEdited[1]->get_active(); + bool anyRecentlySavedFilterActive = bRecentlySaved[0]->get_active() || bRecentlySaved[1]->get_active(); const bool nonTrashedActive = bNotTrash->get_active(); - /* - * filter is setup in 2 steps - * Step 1: handle individual filters - */ + /* + * filter is setup in 2 steps + * Step 1: handle individual filters + */ filter.showRanked[0] = bFilterClear->get_active() || bUnRanked->get_active () || bTrash->get_active () || nonTrashedActive || anyCLabelFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive; filter.showCLabeled[0] = bFilterClear->get_active() || bUnCLabeled->get_active () || bTrash->get_active () || nonTrashedActive || - anyRankFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive; + anyRankFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive; - for (int i=1; i<=5; i++){ - filter.showRanked[i] = bFilterClear->get_active() || bRank[i-1]->get_active () || bTrash->get_active () || nonTrashedActive || + for (int i = 1; i <= 5; i++) { + filter.showRanked[i] = bFilterClear->get_active() || bRank[i - 1]->get_active () || bTrash->get_active () || nonTrashedActive || anyCLabelFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive; - filter.showCLabeled[i] = bFilterClear->get_active() || bCLabel[i-1]->get_active () || bTrash->get_active () || nonTrashedActive || + filter.showCLabeled[i] = bFilterClear->get_active() || bCLabel[i - 1]->get_active () || bTrash->get_active () || nonTrashedActive || anyRankFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive; } - for (int i=0; i<2; i++){ + for (int i = 0; i < 2; i++) { filter.showEdited[i] = bFilterClear->get_active() || bEdited[i]->get_active () || bTrash->get_active () || nonTrashedActive || anyRankFilterActive || anyCLabelFilterActive || anyRecentlySavedFilterActive; filter.showRecentlySaved[i] = bFilterClear->get_active() || bRecentlySaved[i]->get_active () || bTrash->get_active () || nonTrashedActive || - anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive; + anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive; } - if( options.rtSettings.verbose ){ - printf ("\n**************** FileCatalog::getFilter *** AFTER STEP 1 \n"); - for (int i=0; i<=5; i++) printf ("filter.showRanked[%i] = %i\n",i,filter.showRanked[i]); - for (int i=0; i<=5; i++) printf ("filter.showCLabeled[%i] = %i\n",i,filter.showCLabeled[i]); - for (int i=0; i<2; i++) printf ("filter.showEdited[%i] = %i\n",i,filter.showEdited[i]); - for (int i=0; i<2; i++) printf ("filter.showRecentlySaved[%i] = %i\n",i,filter.showRecentlySaved[i]); - } - filter.multiselect = false; - /* - * Step 2 - * handle the case when more than 1 filter is selected. This overrides values set in Step - * if no filters in a group are active, filter.show for each member of that group will be set to true - * otherwise they are set based on UI input - */ + if( options.rtSettings.verbose ) { + printf ("\n**************** FileCatalog::getFilter *** AFTER STEP 1 \n"); + + for (int i = 0; i <= 5; i++) { + printf ("filter.showRanked[%i] = %i\n", i, filter.showRanked[i]); + } + + for (int i = 0; i <= 5; i++) { + printf ("filter.showCLabeled[%i] = %i\n", i, filter.showCLabeled[i]); + } + + for (int i = 0; i < 2; i++) { + printf ("filter.showEdited[%i] = %i\n", i, filter.showEdited[i]); + } + + for (int i = 0; i < 2; i++) { + printf ("filter.showRecentlySaved[%i] = %i\n", i, filter.showRecentlySaved[i]); + } + } + + filter.multiselect = false; + + /* + * Step 2 + * handle the case when more than 1 filter is selected. This overrides values set in Step + * if no filters in a group are active, filter.show for each member of that group will be set to true + * otherwise they are set based on UI input + */ if ((anyRankFilterActive && anyCLabelFilterActive ) || - (anyRankFilterActive && anyEditedFilterActive ) || - (anyRankFilterActive && anyRecentlySavedFilterActive ) || - (anyCLabelFilterActive && anyEditedFilterActive ) || - (anyCLabelFilterActive && anyRecentlySavedFilterActive ) || - (anyEditedFilterActive && anyRecentlySavedFilterActive) || - (nonTrashedActive && (anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive))){ + (anyRankFilterActive && anyEditedFilterActive ) || + (anyRankFilterActive && anyRecentlySavedFilterActive ) || + (anyCLabelFilterActive && anyEditedFilterActive ) || + (anyCLabelFilterActive && anyRecentlySavedFilterActive ) || + (anyEditedFilterActive && anyRecentlySavedFilterActive) || + (nonTrashedActive && (anyRankFilterActive || anyCLabelFilterActive || anyEditedFilterActive || anyRecentlySavedFilterActive))) { - filter.multiselect = true; - filter.showRanked[0] = anyRankFilterActive?bUnRanked->get_active ():true; - filter.showCLabeled[0] = anyCLabelFilterActive?bUnCLabeled->get_active ():true; + filter.multiselect = true; + filter.showRanked[0] = anyRankFilterActive ? bUnRanked->get_active () : true; + filter.showCLabeled[0] = anyCLabelFilterActive ? bUnCLabeled->get_active () : true; - for (int i=1; i<=5; i++){ - filter.showRanked[i] = anyRankFilterActive?bRank[i-1]->get_active ():true; - filter.showCLabeled[i] = anyCLabelFilterActive?bCLabel[i-1]->get_active ():true; - } - for (int i=0; i<2; i++){ - filter.showEdited[i] = anyEditedFilterActive?bEdited[i]->get_active():true; - filter.showRecentlySaved[i] = anyRecentlySavedFilterActive?bRecentlySaved[i]->get_active():true; - } - if( options.rtSettings.verbose ){ - printf ("\n**************** FileCatalog::getFilter *** AFTER STEP 2 \n"); - for (int i=0; i<=5; i++) printf ("filter.showRanked[%i] = %i\n",i,filter.showRanked[i]); - for (int i=0; i<=5; i++) printf ("filter.showCLabeled[%i] = %i\n",i,filter.showCLabeled[i]); - for (int i=0; i<2; i++) printf ("filter.showEdited[%i] = %i\n",i,filter.showEdited[i]); - for (int i=0; i<2; i++) printf ("filter.showRecentlySaved[%i] = %i\n",i,filter.showRecentlySaved[i]); - printf ("filter.multiselect = %i\n",filter.multiselect); - } + for (int i = 1; i <= 5; i++) { + filter.showRanked[i] = anyRankFilterActive ? bRank[i - 1]->get_active () : true; + filter.showCLabeled[i] = anyCLabelFilterActive ? bCLabel[i - 1]->get_active () : true; + } + + for (int i = 0; i < 2; i++) { + filter.showEdited[i] = anyEditedFilterActive ? bEdited[i]->get_active() : true; + filter.showRecentlySaved[i] = anyRecentlySavedFilterActive ? bRecentlySaved[i]->get_active() : true; + } + + if( options.rtSettings.verbose ) { + printf ("\n**************** FileCatalog::getFilter *** AFTER STEP 2 \n"); + + for (int i = 0; i <= 5; i++) { + printf ("filter.showRanked[%i] = %i\n", i, filter.showRanked[i]); + } + + for (int i = 0; i <= 5; i++) { + printf ("filter.showCLabeled[%i] = %i\n", i, filter.showCLabeled[i]); + } + + for (int i = 0; i < 2; i++) { + printf ("filter.showEdited[%i] = %i\n", i, filter.showEdited[i]); + } + + for (int i = 0; i < 2; i++) { + printf ("filter.showRecentlySaved[%i] = %i\n", i, filter.showRecentlySaved[i]); + } + + printf ("filter.multiselect = %i\n", filter.multiselect); + } } filter.showTrash = bTrash->get_active () || !bNotTrash->get_active (); filter.showNotTrash = !bTrash->get_active (); - if (!filterPanel) - filter.exifFilterEnabled = false; - else { - if (!hasValidCurrentEFS) { - MyMutex::MyLock lock(dirEFSMutex); - filter.exifFilter = dirEFS; - } - else - filter.exifFilter = currentEFS; - filter.exifFilterEnabled = filterPanel->isEnabled (); - } + + if (!filterPanel) { + filter.exifFilterEnabled = false; + } else { + if (!hasValidCurrentEFS) { + MyMutex::MyLock lock(dirEFSMutex); + filter.exifFilter = dirEFS; + } else { + filter.exifFilter = currentEFS; + } + + filter.exifFilterEnabled = filterPanel->isEnabled (); + } //TODO add support for more query options. e.g by date, iso, f-number, etc //TODO could use date:;iso: etc @@ -1401,114 +1686,143 @@ BrowserFilter FileCatalog::getFilter () { return filter; } -void FileCatalog::filterChanged () { +void FileCatalog::filterChanged () +{ //TODO !!! there is too many repetitive and unnecessary executions of - // " fileBrowser->applyFilter (getFilter()); " throughout the code - // this needs further analysis and cleanup + // " fileBrowser->applyFilter (getFilter()); " throughout the code + // this needs further analysis and cleanup fileBrowser->applyFilter (getFilter()); _refreshProgressBar(); } -void FileCatalog::reparseDirectory () { +void FileCatalog::reparseDirectory () +{ - if (selectedDirectory.empty()) + if (selectedDirectory.empty()) { return; + } if (!safe_file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { closeDir (); - return; - } - - std::vector nfileNameList = getFileList (); + return; + } - // check if a thumbnailed file has been deleted - const std::vector& t = fileBrowser->getEntries (); - std::vector fileNamesToDel; - for (size_t i=0; ifilename, Glib::FILE_TEST_EXISTS)) - fileNamesToDel.push_back (t[i]->filename); - for (size_t i=0; idelEntry (fileNamesToDel[i]); - cacheMgr->deleteEntry (fileNamesToDel[i]); - } + std::vector nfileNameList = getFileList (); - // check if a new file has been added - for (size_t i=0; i& t = fileBrowser->getEntries (); + std::vector fileNamesToDel; + + for (size_t i = 0; i < t.size(); i++) + if (!safe_file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) { + fileNamesToDel.push_back (t[i]->filename); + } + + for (size_t i = 0; i < fileNamesToDel.size(); i++) { + delete fileBrowser->delEntry (fileNamesToDel[i]); + cacheMgr->deleteEntry (fileNamesToDel[i]); + } + + // check if a new file has been added + for (size_t i = 0; i < nfileNameList.size(); i++) { + bool found = false; + + for (size_t j = 0; j < fileNameList.size(); j++) + if (nfileNameList[i] == fileNameList[j]) { + found = true; + break; + } + + if (!found) { + checkAndAddFile (Gio::File::create_for_parse_name (nfileNameList[i])); _refreshProgressBar (); - } - } + } + } - fileNameList = nfileNameList; + fileNameList = nfileNameList; } #ifdef WIN32 -int winDirChangedUITread (void* cat) { +int winDirChangedUITread (void* cat) +{ (static_cast(cat))->reparseDirectory (); return 0; } -void FileCatalog::winDirChanged () { - g_idle_add(winDirChangedUITread, this); +void FileCatalog::winDirChanged () +{ + g_idle_add(winDirChangedUITread, this); } #else -void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal) { +void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal) +{ - if (options.has_retained_extention(file->get_parse_name()) - && (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)) { - if (!internal) { - GThreadLock lock; - reparseDirectory (); - } - else - reparseDirectory (); - } + if (options.has_retained_extention(file->get_parse_name()) + && (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)) { + if (!internal) { + GThreadLock lock; + reparseDirectory (); + } else { + reparseDirectory (); + } + } } #endif -void FileCatalog::checkAndAddFile (Glib::RefPtr file) { +void FileCatalog::checkAndAddFile (Glib::RefPtr file) +{ - if (!file ) + if (!file ) { return; - if( !file->query_exists()) - return; + } + + if( !file->query_exists()) { + return; + } + Glib::RefPtr info = safe_query_file_info(file); + if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); - if (options.is_extention_enabled(lastdot!=Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){ - previewLoader->add (selectedDirectoryId,file->get_parse_name(),this); + size_t lastdot = info->get_name().find_last_of ('.'); + + if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { + previewLoader->add (selectedDirectoryId, file->get_parse_name(), this); previewsToLoad++; - } + } } } -void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { +void FileCatalog::addAndOpenFile (const Glib::ustring& fname) +{ Glib::RefPtr file = Gio::File::create_for_path (fname); - if (!file ) + + if (!file ) { return; - if( !file->query_exists()) - return; + } + + if( !file->query_exists()) { + return; + } + Glib::RefPtr info = safe_query_file_info(file); - if( !info ) - return; + + if( !info ) { + return; + } + 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 (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); + previewReady (selectedDirectoryId, entry); // open the file FCOIParams* params = new FCOIParams; params->catalog = this; @@ -1519,52 +1833,65 @@ void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { } } -void FileCatalog::emptyTrash () { - +void FileCatalog::emptyTrash () +{ + const std::vector t = fileBrowser->getEntries (); std::vector toDel; - for (size_t i=0; i(t[i]))->thumbnail->getStage()==1) - toDel.push_back (static_cast(t[i])); + + for (size_t i = 0; i < t.size(); i++) + if ((static_cast(t[i]))->thumbnail->getStage() == 1) { + toDel.push_back (static_cast(t[i])); + } + deleteRequested (toDel, false); trashChanged(); } -bool FileCatalog::trashIsEmpty () { +bool FileCatalog::trashIsEmpty () +{ const std::vector t = fileBrowser->getEntries (); - for (size_t i=0; i(t[i]))->thumbnail->getStage()==1) + + for (size_t i = 0; i < t.size(); i++) + if ((static_cast(t[i]))->thumbnail->getStage() == 1) { return false; + } return true; } -void FileCatalog::zoomIn () { +void FileCatalog::zoomIn () +{ fileBrowser->zoomIn (); refreshHeight(); - + } -void FileCatalog::zoomOut () { +void FileCatalog::zoomOut () +{ fileBrowser->zoomOut (); refreshHeight(); - + } -void FileCatalog::refreshEditedState (const std::set& efiles) { +void FileCatalog::refreshEditedState (const std::set& efiles) +{ editedFiles = efiles; fileBrowser->refreshEditedState (efiles); } -void FileCatalog::selectionChanged (std::vector tbe) { +void FileCatalog::selectionChanged (std::vector tbe) +{ - if (fslistener) + if (fslistener) { fslistener->selectionChanged (tbe); + } } // Called within GTK UI thread -void FileCatalog::exifFilterChanged () { +void FileCatalog::exifFilterChanged () +{ currentEFS = filterPanel->getFilter (); hasValidCurrentEFS = true; @@ -1572,257 +1899,299 @@ void FileCatalog::exifFilterChanged () { _refreshProgressBar(); } -void FileCatalog::setFilterPanel (FilterPanel* fpanel) { +void FileCatalog::setFilterPanel (FilterPanel* fpanel) +{ - filterPanel = fpanel; - filterPanel->set_sensitive (false); - filterPanel->setFilterPanelListener (this); + filterPanel = fpanel; + filterPanel->set_sensitive (false); + filterPanel->setFilterPanelListener (this); } -void FileCatalog::trashChanged () { +void FileCatalog::trashChanged () +{ if (trashIsEmpty()) { bTrash->set_image(*iTrashEmpty); - } - else { + } else { bTrash->set_image(*iTrashFull); } } // Called within GTK UI thread -void FileCatalog::buttonQueryClearPressed () { - Query->set_text(""); - FileCatalog::executeQuery (); +void FileCatalog::buttonQueryClearPressed () +{ + Query->set_text(""); + FileCatalog::executeQuery (); } // Called within GTK UI thread -void FileCatalog::executeQuery(){ - // if BrowsePath text was changed, do a full browse; - // otherwise filter only +void FileCatalog::executeQuery() +{ + // if BrowsePath text was changed, do a full browse; + // otherwise filter only - if (BrowsePath->get_text()!=selectedDirectory) - buttonBrowsePathPressed (); - else - FileCatalog::filterChanged (); + if (BrowsePath->get_text() != selectedDirectory) { + buttonBrowsePathPressed (); + } else { + FileCatalog::filterChanged (); + } } -bool FileCatalog::Query_key_pressed (GdkEventKey *event){ +bool FileCatalog::Query_key_pressed (GdkEventKey *event) +{ bool shift = event->state & GDK_SHIFT_MASK; switch (event->keyval) { case GDK_Escape: + // Clear Query if the Escape character is pressed within it - if (!shift){ + if (!shift) { FileCatalog::buttonQueryClearPressed (); return true; } + break; + default: break; } + return false; } -void FileCatalog::updateFBQueryTB (bool singleRow) { - hbToolBar1->reference(); - if (singleRow) { - bool removed = removeIfThere(this, hbToolBar1, false); - if (removed) { - buttonBar->pack_start(*hbToolBar1, Gtk::PACK_EXPAND_WIDGET, 0); - } - } - else { - bool removed = removeIfThere(buttonBar, hbToolBar1, false); - if (removed) { - pack_start(*hbToolBar1, Gtk::PACK_SHRINK, 0); - reorder_child(*hbToolBar1, 0); - } - } - hbToolBar1->unreference(); +void FileCatalog::updateFBQueryTB (bool singleRow) +{ + hbToolBar1->reference(); + + if (singleRow) { + bool removed = removeIfThere(this, hbToolBar1, false); + + if (removed) { + buttonBar->pack_start(*hbToolBar1, Gtk::PACK_EXPAND_WIDGET, 0); + } + } else { + bool removed = removeIfThere(buttonBar, hbToolBar1, false); + + if (removed) { + pack_start(*hbToolBar1, Gtk::PACK_SHRINK, 0); + reorder_child(*hbToolBar1, 0); + } + } + + hbToolBar1->unreference(); } -void FileCatalog::updateFBToolBarVisibility (bool showFilmStripToolBar){ - if (showFilmStripToolBar) - showToolBar(); - else - hideToolBar(); - refreshHeight(); +void FileCatalog::updateFBToolBarVisibility (bool showFilmStripToolBar) +{ + if (showFilmStripToolBar) { + showToolBar(); + } else { + hideToolBar(); + } + + refreshHeight(); } -void FileCatalog::buttonBrowsePathPressed () { - Glib::ustring BrowsePathValue = BrowsePath->get_text(); - Glib::ustring DecodedPathPrefix=""; - Glib::ustring FirstChar; +void FileCatalog::buttonBrowsePathPressed () +{ + Glib::ustring BrowsePathValue = BrowsePath->get_text(); + Glib::ustring DecodedPathPrefix = ""; + Glib::ustring FirstChar; - // handle shortcuts in the BrowsePath -- START - // read the 1-st character from the path - FirstChar = BrowsePathValue.substr (0,1); + // handle shortcuts in the BrowsePath -- START + // read the 1-st character from the path + FirstChar = BrowsePathValue.substr (0, 1); - if (FirstChar=="~"){ // home directory - DecodedPathPrefix = Glib::get_home_dir(); - } - else if (FirstChar=="!"){ // user's pictures directory - //DecodedPathPrefix = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES); - DecodedPathPrefix = safe_get_user_picture_dir(); - } + if (FirstChar == "~") { // home directory + DecodedPathPrefix = Glib::get_home_dir(); + } else if (FirstChar == "!") { // user's pictures directory + //DecodedPathPrefix = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES); + DecodedPathPrefix = safe_get_user_picture_dir(); + } - if (!DecodedPathPrefix.empty()){ - BrowsePathValue = Glib::ustring::compose ("%1%2",DecodedPathPrefix,BrowsePathValue.substr (1,BrowsePath->get_text_length()-1)); - BrowsePath->set_text(BrowsePathValue); - } - // handle shortcuts in the BrowsePath -- END + if (!DecodedPathPrefix.empty()) { + BrowsePathValue = Glib::ustring::compose ("%1%2", DecodedPathPrefix, BrowsePathValue.substr (1, BrowsePath->get_text_length() - 1)); + BrowsePath->set_text(BrowsePathValue); + } - // validate the path - if (safe_file_test(BrowsePathValue, Glib::FILE_TEST_IS_DIR) && dirlistener){ - dirlistener->selectDir (BrowsePathValue); - } - else - // error, likely path not found: show red arrow - buttonBrowsePath->set_image (*iRefreshRed); + // handle shortcuts in the BrowsePath -- END + + // validate the path + if (safe_file_test(BrowsePathValue, Glib::FILE_TEST_IS_DIR) && dirlistener) { + dirlistener->selectDir (BrowsePathValue); + } else + // error, likely path not found: show red arrow + { + buttonBrowsePath->set_image (*iRefreshRed); + } } -bool FileCatalog::BrowsePath_key_pressed (GdkEventKey *event){ +bool FileCatalog::BrowsePath_key_pressed (GdkEventKey *event) +{ bool shift = event->state & GDK_SHIFT_MASK; switch (event->keyval) { case GDK_Escape: - // On Escape character Reset BrowsePath to selectedDirectory - if (!shift){ + + // On Escape character Reset BrowsePath to selectedDirectory + if (!shift) { BrowsePath->set_text(selectedDirectory); // place cursor at the end BrowsePath->select_region(BrowsePath->get_text_length(), BrowsePath->get_text_length()); return true; } + break; + default: break; } + return false; } -void FileCatalog::tbLeftPanel_1_visible (bool visible){ - if (visible) - tbLeftPanel_1->show(); - else - tbLeftPanel_1->hide(); +void FileCatalog::tbLeftPanel_1_visible (bool visible) +{ + if (visible) { + tbLeftPanel_1->show(); + } else { + tbLeftPanel_1->hide(); + } } -void FileCatalog::tbRightPanel_1_visible (bool visible){ - if (visible) - tbRightPanel_1->show(); - else - tbRightPanel_1->hide(); +void FileCatalog::tbRightPanel_1_visible (bool visible) +{ + if (visible) { + tbRightPanel_1->show(); + } else { + tbRightPanel_1->hide(); + } } -void FileCatalog::tbLeftPanel_1_toggled () { +void FileCatalog::tbLeftPanel_1_toggled () +{ removeIfThere (filepanel->dirpaned, filepanel->placespaned, false); - if (tbLeftPanel_1->get_active()){ + + if (tbLeftPanel_1->get_active()) { filepanel->dirpaned->pack1 (*filepanel->placespaned, false, true); tbLeftPanel_1->set_image (*iLeftPanel_1_Hide); options.browserDirPanelOpened = true; - } - else { + } else { tbLeftPanel_1->set_image (*iLeftPanel_1_Show); options.browserDirPanelOpened = false; } } -void FileCatalog::tbRightPanel_1_toggled () { - if (tbRightPanel_1->get_active()){ +void FileCatalog::tbRightPanel_1_toggled () +{ + if (tbRightPanel_1->get_active()) { filepanel->rightBox->show(); tbRightPanel_1->set_image (*iRightPanel_1_Hide); options.browserToolPanelOpened = true; - } - else{ + } else { filepanel->rightBox->hide(); tbRightPanel_1->set_image (*iRightPanel_1_Show); options.browserToolPanelOpened = false; } } -bool FileCatalog::CheckSidePanelsVisibility(){ - if(tbLeftPanel_1->get_active()==false && tbRightPanel_1->get_active()==false) - return false; - else - return true; +bool FileCatalog::CheckSidePanelsVisibility() +{ + if(tbLeftPanel_1->get_active() == false && tbRightPanel_1->get_active() == false) { + return false; + } else { + return true; + } } -void FileCatalog::toggleSidePanels(){ - // toggle left AND right panels +void FileCatalog::toggleSidePanels() +{ + // toggle left AND right panels - bool bAllSidePanelsVisible; - bAllSidePanelsVisible= CheckSidePanelsVisibility(); + bool bAllSidePanelsVisible; + bAllSidePanelsVisible = CheckSidePanelsVisibility(); - tbLeftPanel_1->set_active (!bAllSidePanelsVisible); - tbRightPanel_1->set_active (!bAllSidePanelsVisible); + tbLeftPanel_1->set_active (!bAllSidePanelsVisible); + tbRightPanel_1->set_active (!bAllSidePanelsVisible); } -void FileCatalog::toggleLeftPanel() { - tbLeftPanel_1->set_active (!tbLeftPanel_1->get_active()); +void FileCatalog::toggleLeftPanel() +{ + tbLeftPanel_1->set_active (!tbLeftPanel_1->get_active()); } -void FileCatalog::toggleRightPanel() { - tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); +void FileCatalog::toggleRightPanel() +{ + tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); } -void FileCatalog::selectImage (Glib::ustring fname, bool clearFilters) { +void FileCatalog::selectImage (Glib::ustring fname, bool clearFilters) +{ - Glib::ustring dirname = Glib::path_get_dirname(fname); - if (!dirname.empty()){ - BrowsePath->set_text(dirname); + Glib::ustring dirname = Glib::path_get_dirname(fname); - - if (clearFilters){ // clear all filters - Query->set_text(""); - categoryButtonToggled(bFilterClear,false); - // disable exif filters - if (filterPanel->isEnabled()) filterPanel->setEnabled (false); - } - - if (BrowsePath->get_text()!=selectedDirectory){ - // reload or refresh thumbs and select image - buttonBrowsePathPressed (); - // the actual selection of image will be handled asynchronously at the end of FileCatalog::previewsFinishedUI - imageToSelect_fname = fname; - } - else{ - // FileCatalog::filterChanged ();//this will be replaced by queue_draw() in fileBrowser->selectImage - fileBrowser->selectImage(fname); - imageToSelect_fname = ""; - } - } + if (!dirname.empty()) { + BrowsePath->set_text(dirname); + + + if (clearFilters) { // clear all filters + Query->set_text(""); + categoryButtonToggled(bFilterClear, false); + + // disable exif filters + if (filterPanel->isEnabled()) { + filterPanel->setEnabled (false); + } + } + + if (BrowsePath->get_text() != selectedDirectory) { + // reload or refresh thumbs and select image + buttonBrowsePathPressed (); + // the actual selection of image will be handled asynchronously at the end of FileCatalog::previewsFinishedUI + imageToSelect_fname = fname; + } else { + // FileCatalog::filterChanged ();//this will be replaced by queue_draw() in fileBrowser->selectImage + fileBrowser->selectImage(fname); + imageToSelect_fname = ""; + } + } } -void FileCatalog::openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious) { +void FileCatalog::openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious) +{ - Glib::ustring dirname = Glib::path_get_dirname(fname); - if (!dirname.empty()){ - BrowsePath->set_text(dirname); + Glib::ustring dirname = Glib::path_get_dirname(fname); + + if (!dirname.empty()) { + BrowsePath->set_text(dirname); - if (clearFilters){ // clear all filters - Query->set_text(""); - categoryButtonToggled(bFilterClear,false); - // disable exif filters - if (filterPanel->isEnabled()) filterPanel->setEnabled (false); - } + if (clearFilters) { // clear all filters + Query->set_text(""); + categoryButtonToggled(bFilterClear, false); - if (BrowsePath->get_text()!=selectedDirectory){ - // reload or refresh thumbs and select image - buttonBrowsePathPressed (); - // the actual selection of image will be handled asynchronously at the end of FileCatalog::previewsFinishedUI - refImageForOpen_fname = fname; - actionNextPrevious = nextPrevious; - } - else{ - // FileCatalog::filterChanged ();//this was replace by queue_draw() in fileBrowser->selectImage - fileBrowser->openNextPreviousEditorImage(fname,nextPrevious); - refImageForOpen_fname = ""; - actionNextPrevious = NAV_NONE; - } - } + // disable exif filters + if (filterPanel->isEnabled()) { + filterPanel->setEnabled (false); + } + } + + if (BrowsePath->get_text() != selectedDirectory) { + // reload or refresh thumbs and select image + buttonBrowsePathPressed (); + // the actual selection of image will be handled asynchronously at the end of FileCatalog::previewsFinishedUI + refImageForOpen_fname = fname; + actionNextPrevious = nextPrevious; + } else { + // FileCatalog::filterChanged ();//this was replace by queue_draw() in fileBrowser->selectImage + fileBrowser->openNextPreviousEditorImage(fname, nextPrevious); + refImageForOpen_fname = ""; + actionNextPrevious = NAV_NONE; + } + } } -bool FileCatalog::handleShortcutKey (GdkEventKey* event) { +bool FileCatalog::handleShortcutKey (GdkEventKey* event) +{ bool ctrl = event->state & GDK_CONTROL_MASK; bool shift = event->state & GDK_SHIFT_MASK; @@ -1833,268 +2202,337 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) { bool altgr = event->state & GDK_MOD5_MASK; #endif modifierKey = event->state; - + // GUI Layout switch(event->keyval) { - case GDK_l: - if (!alt)tbLeftPanel_1->set_active (!tbLeftPanel_1->get_active()); // toggle left panel - if (alt && !ctrl) tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel - if (alt && ctrl) { - tbLeftPanel_1->set_active (!tbLeftPanel_1->get_active()); // toggle left panel - tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel - } - return true; - case GDK_m: - if (!ctrl && !alt) toggleSidePanels(); - return true; + case GDK_l: + if (!alt) { + tbLeftPanel_1->set_active (!tbLeftPanel_1->get_active()); // toggle left panel + } + + if (alt && !ctrl) { + tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel + } + + if (alt && ctrl) { + tbLeftPanel_1->set_active (!tbLeftPanel_1->get_active()); // toggle left panel + tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel + } + + return true; + + case GDK_m: + if (!ctrl && !alt) { + toggleSidePanels(); + } + + return true; } - if (shift){ + if (shift) { switch(event->keyval) { - case GDK_Escape: - BrowsePath->set_text(selectedDirectory); - // set focus on something neutral, this is useful to remove focus from BrowsePath and Query - // when need to execute a shortcut, which otherwise will be typed into those fields - filepanel->grab_focus(); - return true; + case GDK_Escape: + BrowsePath->set_text(selectedDirectory); + // set focus on something neutral, this is useful to remove focus from BrowsePath and Query + // when need to execute a shortcut, which otherwise will be typed into those fields + filepanel->grab_focus(); + return true; } } #ifdef __WIN32__ - if (!alt && !shift && !altgr) { // shift is reserved for ranking - switch(event->hardware_keycode) { - case 0x30: - categoryButtonToggled(bUnRanked,false); - return true; - case 0x31: - categoryButtonToggled(bRank[0],false); - return true; - case 0x32: - categoryButtonToggled(bRank[1],false); - return true; - case 0x33: - categoryButtonToggled(bRank[2],false); - return true; - case 0x34: - categoryButtonToggled(bRank[3],false); - return true; - case 0x35: - categoryButtonToggled(bRank[4],false); - return true; - case 0x36: - categoryButtonToggled(bEdited[0],false); - return true; - case 0x37: - categoryButtonToggled(bEdited[1],false); - return true; - } - } + + if (!alt && !shift && !altgr) { // shift is reserved for ranking + switch(event->hardware_keycode) { + case 0x30: + categoryButtonToggled(bUnRanked, false); + return true; + + case 0x31: + categoryButtonToggled(bRank[0], false); + return true; + + case 0x32: + categoryButtonToggled(bRank[1], false); + return true; + + case 0x33: + categoryButtonToggled(bRank[2], false); + return true; + + case 0x34: + categoryButtonToggled(bRank[3], false); + return true; + + case 0x35: + categoryButtonToggled(bRank[4], false); + return true; + + case 0x36: + categoryButtonToggled(bEdited[0], false); + return true; + + case 0x37: + categoryButtonToggled(bEdited[1], false); + return true; + } + } + if (!alt && !shift) { switch(event->keyval) { - case GDK_Return: - case GDK_KP_Enter: - if (BrowsePath->is_focus()){ - FileCatalog::buttonBrowsePathPressed (); - return true; - } - break; + case GDK_Return: + case GDK_KP_Enter: + if (BrowsePath->is_focus()) { + FileCatalog::buttonBrowsePathPressed (); + return true; + } + + break; } } - + if (alt && !shift) { // shift is reserved for color labeling switch(event->hardware_keycode) { - case 0x30: - categoryButtonToggled(bUnCLabeled,false); - return true; - case 0x31: - categoryButtonToggled(bCLabel[0],false); - return true; - case 0x32: - categoryButtonToggled(bCLabel[1],false); - return true; - case 0x33: - categoryButtonToggled(bCLabel[2],false); - return true; - case 0x34: - categoryButtonToggled(bCLabel[3],false); - return true; - case 0x35: - categoryButtonToggled(bCLabel[4],false); - return true; - case 0x36: - categoryButtonToggled(bRecentlySaved[0],false); - return true; - case 0x37: - categoryButtonToggled(bRecentlySaved[1],false); - return true; + case 0x30: + categoryButtonToggled(bUnCLabeled, false); + return true; + + case 0x31: + categoryButtonToggled(bCLabel[0], false); + return true; + + case 0x32: + categoryButtonToggled(bCLabel[1], false); + return true; + + case 0x33: + categoryButtonToggled(bCLabel[2], false); + return true; + + case 0x34: + categoryButtonToggled(bCLabel[3], false); + return true; + + case 0x35: + categoryButtonToggled(bCLabel[4], false); + return true; + + case 0x36: + categoryButtonToggled(bRecentlySaved[0], false); + return true; + + case 0x37: + categoryButtonToggled(bRecentlySaved[1], false); + return true; } } + #else - if (!alt && !shift && !altgr) { // shift is reserved for ranking - switch(event->hardware_keycode) { - case 0x13: - categoryButtonToggled(bUnRanked,false); - return true; - case 0x0a: - categoryButtonToggled(bRank[0],false); - return true; - case 0x0b: - categoryButtonToggled(bRank[1],false); - return true; - case 0x0c: - categoryButtonToggled(bRank[2],false); - return true; - case 0x0d: - categoryButtonToggled(bRank[3],false); - return true; - case 0x0e: - categoryButtonToggled(bRank[4],false); - return true; - case 0x0f: - categoryButtonToggled(bEdited[0],false); - return true; - case 0x10: - categoryButtonToggled(bEdited[1],false); - return true; - } - } + + if (!alt && !shift && !altgr) { // shift is reserved for ranking + switch(event->hardware_keycode) { + case 0x13: + categoryButtonToggled(bUnRanked, false); + return true; + + case 0x0a: + categoryButtonToggled(bRank[0], false); + return true; + + case 0x0b: + categoryButtonToggled(bRank[1], false); + return true; + + case 0x0c: + categoryButtonToggled(bRank[2], false); + return true; + + case 0x0d: + categoryButtonToggled(bRank[3], false); + return true; + + case 0x0e: + categoryButtonToggled(bRank[4], false); + return true; + + case 0x0f: + categoryButtonToggled(bEdited[0], false); + return true; + + case 0x10: + categoryButtonToggled(bEdited[1], false); + return true; + } + } + if (!alt && !shift) { switch(event->keyval) { - case GDK_Return: - case GDK_KP_Enter: - if (BrowsePath->is_focus()){ - FileCatalog::buttonBrowsePathPressed (); - return true; - } - break; + case GDK_Return: + case GDK_KP_Enter: + if (BrowsePath->is_focus()) { + FileCatalog::buttonBrowsePathPressed (); + return true; + } + + break; } } - + if (alt && !shift) { // shift is reserved for color labeling switch(event->hardware_keycode) { - case 0x13: - categoryButtonToggled(bUnCLabeled,false); - return true; - case 0x0a: - categoryButtonToggled(bCLabel[0],false); - return true; - case 0x0b: - categoryButtonToggled(bCLabel[1],false); - return true; - case 0x0c: - categoryButtonToggled(bCLabel[2],false); - return true; - case 0x0d: - categoryButtonToggled(bCLabel[3],false); - return true; - case 0x0e: - categoryButtonToggled(bCLabel[4],false); - return true; - case 0x0f: - categoryButtonToggled(bRecentlySaved[0],false); - return true; - case 0x10: - categoryButtonToggled(bRecentlySaved[1],false); - return true; + case 0x13: + categoryButtonToggled(bUnCLabeled, false); + return true; + + case 0x0a: + categoryButtonToggled(bCLabel[0], false); + return true; + + case 0x0b: + categoryButtonToggled(bCLabel[1], false); + return true; + + case 0x0c: + categoryButtonToggled(bCLabel[2], false); + return true; + + case 0x0d: + categoryButtonToggled(bCLabel[3], false); + return true; + + case 0x0e: + categoryButtonToggled(bCLabel[4], false); + return true; + + case 0x0f: + categoryButtonToggled(bRecentlySaved[0], false); + return true; + + case 0x10: + categoryButtonToggled(bRecentlySaved[1], false); + return true; } } + #endif + if (!ctrl && !alt) { switch(event->keyval) { - case GDK_d: - case GDK_D: - categoryButtonToggled(bFilterClear,false); - return true; + case GDK_d: + case GDK_D: + categoryButtonToggled(bFilterClear, false); + return true; } } if (!ctrl || (alt && !options.tabbedUI)) { switch(event->keyval) { - case GDK_bracketright: - coarsePanel->rotateRight(); - return true; - case GDK_bracketleft: - coarsePanel->rotateLeft(); - return true; - case GDK_i: - case GDK_I: - exifInfo->set_active (!exifInfo->get_active()); - return true; + case GDK_bracketright: + coarsePanel->rotateRight(); + return true; - case GDK_plus: - case GDK_equal: - zoomIn(); - return true; - case GDK_minus: - case GDK_underscore: - zoomOut(); - return true; + case GDK_bracketleft: + coarsePanel->rotateLeft(); + return true; + + case GDK_i: + case GDK_I: + exifInfo->set_active (!exifInfo->get_active()); + return true; + + case GDK_plus: + case GDK_equal: + zoomIn(); + return true; + + case GDK_minus: + case GDK_underscore: + zoomOut(); + return true; } } + if (ctrl && !alt) { switch (event->keyval) { - case GDK_o: - BrowsePath->select_region(0, BrowsePath->get_text_length()); - BrowsePath->grab_focus(); - return true; - case GDK_f: - Query->select_region(0, Query->get_text_length()); - Query->grab_focus(); - return true; - case GDK_t: - case GDK_T: - modifierKey = 0; // HOMBRE: yet another hack.... otherwise the shortcut won't work - categoryButtonToggled(bTrash,false); - return true; - } - } - if (!ctrl && !alt && shift) { - switch (event->keyval) { - case GDK_t: - case GDK_T: - if (inTabMode) { - if (options.showFilmStripToolBar) - hideToolBar(); - else - showToolBar(); - options.showFilmStripToolBar = !options.showFilmStripToolBar; - } - return true; - } - } - if (!ctrl && !alt && !shift) { - switch (event->keyval) { - case GDK_t: - case GDK_T: - if (inTabMode) { - if (options.showFilmStripToolBar) - hideToolBar(); - else - showToolBar(); - options.showFilmStripToolBar = !options.showFilmStripToolBar; - } - refreshHeight(); - return true; + case GDK_o: + BrowsePath->select_region(0, BrowsePath->get_text_length()); + BrowsePath->grab_focus(); + return true; + + case GDK_f: + Query->select_region(0, Query->get_text_length()); + Query->grab_focus(); + return true; + + case GDK_t: + case GDK_T: + modifierKey = 0; // HOMBRE: yet another hack.... otherwise the shortcut won't work + categoryButtonToggled(bTrash, false); + return true; } } - if (fileBrowser->keyPressed(event)) + if (!ctrl && !alt && shift) { + switch (event->keyval) { + case GDK_t: + case GDK_T: + if (inTabMode) { + if (options.showFilmStripToolBar) { + hideToolBar(); + } else { + showToolBar(); + } + + options.showFilmStripToolBar = !options.showFilmStripToolBar; + } + + return true; + } + } + + if (!ctrl && !alt && !shift) { + switch (event->keyval) { + case GDK_t: + case GDK_T: + if (inTabMode) { + if (options.showFilmStripToolBar) { + hideToolBar(); + } else { + showToolBar(); + } + + options.showFilmStripToolBar = !options.showFilmStripToolBar; + } + + refreshHeight(); + return true; + } + } + + if (fileBrowser->keyPressed(event)) { return true; + } return false; } -void FileCatalog::showToolBar() { - if (!options.FileBrowserToolbarSingleRow) +void FileCatalog::showToolBar() +{ + if (!options.FileBrowserToolbarSingleRow) { hbToolBar1->show(); + } + buttonBar->show(); } -void FileCatalog::hideToolBar() { - if (!options.FileBrowserToolbarSingleRow) +void FileCatalog::hideToolBar() +{ + if (!options.FileBrowserToolbarSingleRow) { hbToolBar1->hide(); + } + buttonBar->hide(); } diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index a8b4d954f..377a6b0da 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -7,7 +7,7 @@ * 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 @@ -39,16 +39,18 @@ #include "threadutils.h" -class DirEntry { +class DirEntry +{ - public: - Glib::ustring fullName; - - DirEntry (const Glib::ustring& n) : fullName (n) {} - - bool operator< (DirEntry& other) { - return fullName.casefold() < other.fullName.casefold(); - } +public: + Glib::ustring fullName; + + DirEntry (const Glib::ustring& n) : fullName (n) {} + + bool operator< (DirEntry& other) + { + return fullName.casefold() < other.fullName.casefold(); + } }; class FilePanel; /* @@ -58,214 +60,253 @@ class FilePanel; * - monitoring the directory (for any change) */ class FileCatalog : public Gtk::VBox, - public DirSelectionListener, - public PreviewLoaderListener, - public FilterPanelListener, - public FileBrowserListener, - public ExportPanelListener + public DirSelectionListener, + public PreviewLoaderListener, + public FilterPanelListener, + public FileBrowserListener, + public ExportPanelListener #ifdef WIN32 - , public WinDirChangeListener + , public WinDirChangeListener #endif - { +{ - private: - FilePanel* filepanel; - Gtk::HBox* hBox; - Glib::ustring selectedDirectory; - int selectedDirectoryId; - bool enabled; - bool inTabMode; // Tab mode has e.g. different progress bar handling - Glib::ustring imageToSelect_fname; - Glib::ustring refImageForOpen_fname; // Next/previous for Editor's perspective - eRTNav actionNextPrevious; +private: + FilePanel* filepanel; + Gtk::HBox* hBox; + Glib::ustring selectedDirectory; + int selectedDirectoryId; + bool enabled; + bool inTabMode; // Tab mode has e.g. different progress bar handling + Glib::ustring imageToSelect_fname; + Glib::ustring refImageForOpen_fname; // Next/previous for Editor's perspective + eRTNav actionNextPrevious; - FileSelectionListener* listener; - FileSelectionChangeListener* fslistener; - ImageAreaToolListener* iatlistener; - DirBrowserRemoteInterface* dirlistener; + FileSelectionListener* listener; + FileSelectionChangeListener* fslistener; + ImageAreaToolListener* iatlistener; + DirBrowserRemoteInterface* dirlistener; - Gtk::HBox* buttonBar; - Gtk::HBox* hbToolBar1; + Gtk::HBox* buttonBar; + Gtk::HBox* hbToolBar1; - Gtk::HBox* fltrRankbox; - Gtk::HBox* fltrLabelbox; - Gtk::VBox* fltrVbox1; + Gtk::HBox* fltrRankbox; + Gtk::HBox* fltrLabelbox; + Gtk::VBox* fltrVbox1; - Gtk::HBox* fltrEditedBox; - Gtk::HBox* fltrRecentlySavedBox; - Gtk::VBox* fltrVbox2; + Gtk::HBox* fltrEditedBox; + Gtk::HBox* fltrRecentlySavedBox; + Gtk::VBox* fltrVbox2; - Gtk::ToggleButton* tbLeftPanel_1; - Gtk::ToggleButton* tbRightPanel_1; - Gtk::ToggleButton* bFilterClear; - Gtk::ToggleButton* bUnRanked; - Gtk::ToggleButton* bRank[5]; - Gtk::ToggleButton* bUnCLabeled; - Gtk::ToggleButton* bCLabel[5];//color label - Gtk::ToggleButton* bEdited[2]; - Gtk::ToggleButton* bRecentlySaved[2]; - Gtk::ToggleButton* bTrash; - Gtk::ToggleButton* bNotTrash; - Gtk::ToggleButton* categoryButtons[19]; - Gtk::ToggleButton* exifInfo; - sigc::connection bCateg[19]; - Gtk::Image* iFilterClear, *igFilterClear; - Gtk::Image* iranked[5], *igranked[5], *iUnRanked, *igUnRanked; - Gtk::Image* iCLabeled[5], *igCLabeled[5], *iUnCLabeled, *igUnCLabeled; - Gtk::Image* iEdited[2], *igEdited[2]; - Gtk::Image* iRecentlySaved[2], *igRecentlySaved[2]; - Gtk::Image *iTrashEmpty, *iTrashFull; - Gtk::Image *iNotTrash; - Gtk::Image *iRefreshWhite, *iRefreshRed; - Gtk::Image *iLeftPanel_1_Show, *iLeftPanel_1_Hide, *iRightPanel_1_Show, *iRightPanel_1_Hide; - Gtk::Image *iQueryClear; - - Gtk::Entry* BrowsePath; - Gtk::Button* buttonBrowsePath; - - Gtk::Entry* Query; - Gtk::Button* buttonQueryClear; + Gtk::ToggleButton* tbLeftPanel_1; + Gtk::ToggleButton* tbRightPanel_1; + Gtk::ToggleButton* bFilterClear; + Gtk::ToggleButton* bUnRanked; + Gtk::ToggleButton* bRank[5]; + Gtk::ToggleButton* bUnCLabeled; + Gtk::ToggleButton* bCLabel[5];//color label + Gtk::ToggleButton* bEdited[2]; + Gtk::ToggleButton* bRecentlySaved[2]; + Gtk::ToggleButton* bTrash; + Gtk::ToggleButton* bNotTrash; + Gtk::ToggleButton* categoryButtons[19]; + Gtk::ToggleButton* exifInfo; + sigc::connection bCateg[19]; + Gtk::Image* iFilterClear, *igFilterClear; + Gtk::Image* iranked[5], *igranked[5], *iUnRanked, *igUnRanked; + Gtk::Image* iCLabeled[5], *igCLabeled[5], *iUnCLabeled, *igUnCLabeled; + Gtk::Image* iEdited[2], *igEdited[2]; + Gtk::Image* iRecentlySaved[2], *igRecentlySaved[2]; + Gtk::Image *iTrashEmpty, *iTrashFull; + Gtk::Image *iNotTrash; + Gtk::Image *iRefreshWhite, *iRefreshRed; + Gtk::Image *iLeftPanel_1_Show, *iLeftPanel_1_Hide, *iRightPanel_1_Show, *iRightPanel_1_Hide; + Gtk::Image *iQueryClear; - double hScrollPos[18]; - double vScrollPos[18]; - int lastScrollPos; + Gtk::Entry* BrowsePath; + Gtk::Button* buttonBrowsePath; - Gtk::VBox* trashButtonBox; - - Gtk::Button* zoomInButton; - Gtk::Button* zoomOutButton; + Gtk::Entry* Query; + Gtk::Button* buttonQueryClear; - MyMutex dirEFSMutex; - ExifFilterSettings dirEFS; - ExifFilterSettings currentEFS; - bool hasValidCurrentEFS; + double hScrollPos[18]; + double vScrollPos[18]; + int lastScrollPos; - FilterPanel* filterPanel; - ExportPanel* exportPanel; + Gtk::VBox* trashButtonBox; - int previewsToLoad; - int previewsLoaded; + Gtk::Button* zoomInButton; + Gtk::Button* zoomOutButton; + + MyMutex dirEFSMutex; + ExifFilterSettings dirEFS; + ExifFilterSettings currentEFS; + bool hasValidCurrentEFS; + + FilterPanel* filterPanel; + ExportPanel* exportPanel; + + int previewsToLoad; + int previewsLoaded; - std::vector fileNameList; - std::set editedFiles; - guint modifierKey; // any modifiers held when rank button was pressed + std::vector fileNameList; + std::set editedFiles; + guint modifierKey; // any modifiers held when rank button was pressed #ifndef _WIN32 - Glib::RefPtr dirMonitor; + Glib::RefPtr dirMonitor; #else - WinDirMonitor* wdMonitor; + WinDirMonitor* wdMonitor; #endif - void addAndOpenFile (const Glib::ustring& fname); - void checkAndAddFile (Glib::RefPtr info); - std::vector getFileList (); - BrowserFilter getFilter (); - void trashChanged (); + void addAndOpenFile (const Glib::ustring& fname); + void checkAndAddFile (Glib::RefPtr info); + std::vector getFileList (); + BrowserFilter getFilter (); + void trashChanged (); - public: - // thumbnail browsers - FileBrowser* fileBrowser; - - CoarsePanel* coarsePanel; - ToolBar* toolBar; +public: + // thumbnail browsers + FileBrowser* fileBrowser; - FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel); - ~FileCatalog(); - void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile=""); - void closeDir (); - void refreshEditedState (const std::set& efiles); + CoarsePanel* coarsePanel; + ToolBar* toolBar; - // previewloaderlistener interface - void previewReady (int dir_id, FileBrowserEntry* fdn); - void previewsFinished (int dir_id); - void previewsFinishedUI (); - void _refreshProgressBar (); + FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel); + ~FileCatalog(); + void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile = ""); + void closeDir (); + void refreshEditedState (const std::set& efiles); - void setInspector(Inspector* inspector) { if (fileBrowser) fileBrowser->setInspector(inspector); } - void disableInspector() { if (fileBrowser) fileBrowser->disableInspector(); } - void enableInspector() { if (fileBrowser) fileBrowser->enableInspector(); } + // previewloaderlistener interface + void previewReady (int dir_id, FileBrowserEntry* fdn); + void previewsFinished (int dir_id); + void previewsFinishedUI (); + void _refreshProgressBar (); - // filterpanel interface - void exifFilterChanged (); + void setInspector(Inspector* inspector) + { + if (fileBrowser) { + fileBrowser->setInspector(inspector); + } + } + void disableInspector() + { + if (fileBrowser) { + fileBrowser->disableInspector(); + } + } + void enableInspector() + { + if (fileBrowser) { + fileBrowser->enableInspector(); + } + } - // exportpanel interface - void exportRequested(); + // filterpanel interface + void exifFilterChanged (); - Glib::ustring lastSelectedDir () { return selectedDirectory; } - void setEnabled (bool e); // if not enabled, it does not open image - void enableTabMode(bool enable); // sets progress bar + // exportpanel interface + void exportRequested(); - // accessors for FileBrowser - void redrawAll (); - void refreshThumbImages (); - void refreshHeight (); - - void openRequested (std::vector tbe); - void deleteRequested (std::vector tbe, bool inclBatchProcessed); - void copyMoveRequested (std::vector tbe, bool moveRequested); - void developRequested (std::vector tbe, bool fastmode); - void renameRequested (std::vector tbe); - void clearFromCacheRequested(std::vector tbe, bool leavenotrace); - void selectionChanged (std::vector tbe); - void emptyTrash (); - bool trashIsEmpty (); - - void setFileSelectionListener (FileSelectionListener* l) { listener = l; } - void setFileSelectionChangeListener (FileSelectionChangeListener* l) { fslistener = l; } - void setImageAreaToolListener (ImageAreaToolListener* l) { iatlistener = l; } - void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { dirlistener = l; } + Glib::ustring lastSelectedDir () + { + return selectedDirectory; + } + void setEnabled (bool e); // if not enabled, it does not open image + void enableTabMode(bool enable); // sets progress bar - void setFilterPanel (FilterPanel* fpanel); - void setExportPanel (ExportPanel* expanel); - void exifInfoButtonToggled(); - void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick); - bool capture_event(GdkEventButton* event); - void filterChanged (); - void runFilterDialog (); + // accessors for FileBrowser + void redrawAll (); + void refreshThumbImages (); + void refreshHeight (); - void on_realize(); - void reparseDirectory (); - void _openImage (std::vector tmb); + void openRequested (std::vector tbe); + void deleteRequested (std::vector tbe, bool inclBatchProcessed); + void copyMoveRequested (std::vector tbe, bool moveRequested); + void developRequested (std::vector tbe, bool fastmode); + void renameRequested (std::vector tbe); + void clearFromCacheRequested(std::vector tbe, bool leavenotrace); + void selectionChanged (std::vector tbe); + void emptyTrash (); + bool trashIsEmpty (); - void zoomIn (); - void zoomOut (); + void setFileSelectionListener (FileSelectionListener* l) + { + listener = l; + } + void setFileSelectionChangeListener (FileSelectionChangeListener* l) + { + fslistener = l; + } + void setImageAreaToolListener (ImageAreaToolListener* l) + { + iatlistener = l; + } + void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) + { + dirlistener = l; + } - void buttonBrowsePathPressed (); - bool BrowsePath_key_pressed (GdkEventKey *event); - void buttonQueryClearPressed (); - void executeQuery (); - bool Query_key_pressed(GdkEventKey *event); - void updateFBQueryTB (bool singleRow); - void updateFBToolBarVisibility (bool showFilmStripToolBar); + void setFilterPanel (FilterPanel* fpanel); + void setExportPanel (ExportPanel* expanel); + void exifInfoButtonToggled(); + void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick); + bool capture_event(GdkEventButton* event); + void filterChanged (); + void runFilterDialog (); - void tbLeftPanel_1_toggled (); - void tbLeftPanel_1_visible (bool visible); - void tbRightPanel_1_toggled (); - void tbRightPanel_1_visible (bool visible); + void on_realize(); + void reparseDirectory (); + void _openImage (std::vector tmb); - void openNextImage () { fileBrowser->openNextImage(); } - void openPrevImage () { fileBrowser->openPrevImage(); } - void selectImage (Glib::ustring fname, bool clearFilters); - void openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious); + void zoomIn (); + void zoomOut (); - bool handleShortcutKey (GdkEventKey* event); + void buttonBrowsePathPressed (); + bool BrowsePath_key_pressed (GdkEventKey *event); + void buttonQueryClearPressed (); + void executeQuery (); + bool Query_key_pressed(GdkEventKey *event); + void updateFBQueryTB (bool singleRow); + void updateFBToolBarVisibility (bool showFilmStripToolBar); - bool isInTabMode() { return inTabMode; } + void tbLeftPanel_1_toggled (); + void tbLeftPanel_1_visible (bool visible); + void tbRightPanel_1_toggled (); + void tbRightPanel_1_visible (bool visible); - bool CheckSidePanelsVisibility(); - void toggleSidePanels(); - void toggleLeftPanel(); - void toggleRightPanel(); + void openNextImage () + { + fileBrowser->openNextImage(); + } + void openPrevImage () + { + fileBrowser->openPrevImage(); + } + void selectImage (Glib::ustring fname, bool clearFilters); + void openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious); - void showToolBar(); - void hideToolBar(); - void filterApplied(); + bool handleShortcutKey (GdkEventKey* event); + + bool isInTabMode() + { + return inTabMode; + } + + bool CheckSidePanelsVisibility(); + void toggleSidePanels(); + void toggleLeftPanel(); + void toggleRightPanel(); + + void showToolBar(); + void hideToolBar(); + void filterApplied(); #ifndef _WIN32 - void on_dir_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal); + void on_dir_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, bool internal); #else - void winDirChanged (); + void winDirChanged (); #endif }; diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index f5ab9423a..5be2ab0df 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -8,7 +8,7 @@ * 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 @@ -22,12 +22,14 @@ #include "../rtengine/safegtk.h" #include "inspector.h" -int FilePanelInitUI (void* data) { +int FilePanelInitUI (void* data) +{ (static_cast(data))->init (); return 0; } -FilePanel::FilePanel () : parent(NULL) { +FilePanel::FilePanel () : parent(NULL) +{ dirpaned = Gtk::manage ( new Gtk::HPaned () ); dirpaned->set_position (options.dirBrowserWidth); @@ -37,7 +39,7 @@ FilePanel::FilePanel () : parent(NULL) { recentBrowser = Gtk::manage ( new RecentBrowser () ); placespaned = Gtk::manage ( new Gtk::VPaned () ); - placespaned->set_size_request(50,100); + placespaned->set_size_request(50, 100); placespaned->set_position (options.dirBrowserHeight); Gtk::VBox* obox = Gtk::manage (new Gtk::VBox ()); @@ -51,10 +53,10 @@ FilePanel::FilePanel () : parent(NULL) { tpc = new BatchToolPanelCoordinator (this); tpc->removeWbTool(); - fileCatalog = Gtk::manage ( new FileCatalog (tpc->coarse, tpc->getToolBar(),this) ); + fileCatalog = Gtk::manage ( new FileCatalog (tpc->coarse, tpc->getToolBar(), this) ); ribbonPane = Gtk::manage ( new Gtk::Paned() ); ribbonPane->add(*fileCatalog); - ribbonPane->set_size_request(50,150); + ribbonPane->set_size_request(50, 150); dirpaned->pack2 (*ribbonPane, true, true); placesBrowser->setDirBrowserRemoteInterface (dirBrowser); @@ -67,7 +69,7 @@ FilePanel::FilePanel () : parent(NULL) { fileCatalog->setDirBrowserRemoteInterface (dirBrowser); rightBox = Gtk::manage ( new Gtk::HBox () ); - rightBox->set_size_request(50,100); + rightBox->set_size_request(50, 100); rightNotebook = Gtk::manage ( new Gtk::Notebook () ); rightNotebookSwitchConn = rightNotebook->signal_switch_page().connect_notify( sigc::mem_fun(*this, &FilePanel::on_NB_switch_page) ); //Gtk::VBox* taggingBox = Gtk::manage ( new Gtk::VBox () ); @@ -78,20 +80,20 @@ FilePanel::FilePanel () : parent(NULL) { history->setProfileChangeListener (tpc); Gtk::ScrolledWindow* sFilterPanel = Gtk::manage ( new Gtk::ScrolledWindow() ); - filterPanel = Gtk::manage ( new FilterPanel () ); - sFilterPanel->add (*filterPanel); - sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + filterPanel = Gtk::manage ( new FilterPanel () ); + sFilterPanel->add (*filterPanel); + sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); inspectorPanel = new Inspector(); fileCatalog->setInspector(inspectorPanel); Gtk::ScrolledWindow* sExportPanel = Gtk::manage ( new Gtk::ScrolledWindow() ); exportPanel = Gtk::manage ( new ExportPanel () ); - sExportPanel->add (*exportPanel); - sExportPanel->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + sExportPanel->add (*exportPanel); + sExportPanel->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - fileCatalog->setFilterPanel (filterPanel); - fileCatalog->setExportPanel (exportPanel); + fileCatalog->setFilterPanel (filterPanel); + fileCatalog->setExportPanel (exportPanel); fileCatalog->setImageAreaToolListener (tpc); fileCatalog->fileBrowser->setBatchPParamsChangeListener (tpc); @@ -133,48 +135,58 @@ FilePanel::FilePanel () : parent(NULL) { show_all (); } -FilePanel::~FilePanel () { +FilePanel::~FilePanel () +{ rightNotebookSwitchConn.disconnect(); - if (inspectorPanel) + + if (inspectorPanel) { delete inspectorPanel; + } } -void FilePanel::on_realize () { +void FilePanel::on_realize () +{ Gtk::HPaned::on_realize (); tpc->closeAllTools(); } -void FilePanel::setAspect () { - int winW, winH; - parent->get_size(winW, winH); - placespaned->set_position(options.dirBrowserHeight); - dirpaned->set_position(options.dirBrowserWidth); - tpcPaned->set_position(options.browserToolPanelHeight); - set_position(winW - options.browserToolPanelWidth); - if (!options.browserDirPanelOpened) - fileCatalog->toggleLeftPanel(); - if (!options.browserToolPanelOpened) - fileCatalog->toggleRightPanel(); +void FilePanel::setAspect () +{ + int winW, winH; + parent->get_size(winW, winH); + placespaned->set_position(options.dirBrowserHeight); + dirpaned->set_position(options.dirBrowserWidth); + tpcPaned->set_position(options.browserToolPanelHeight); + set_position(winW - options.browserToolPanelWidth); + + if (!options.browserDirPanelOpened) { + fileCatalog->toggleLeftPanel(); + } + + if (!options.browserToolPanelOpened) { + fileCatalog->toggleRightPanel(); + } } -void FilePanel::init () { - +void FilePanel::init () +{ + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected dirBrowser->fillDirTree (); placesBrowser->refreshPlacesList (); - if (argv1!="" && safe_file_test (argv1, Glib::FILE_TEST_IS_DIR)) + if (argv1 != "" && safe_file_test (argv1, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (argv1); - else { - if (options.startupDir==STARTUPDIR_HOME) + } else { + if (options.startupDir == STARTUPDIR_HOME) { dirBrowser->open (safe_get_user_picture_dir()); - else if (options.startupDir==STARTUPDIR_CURRENT) + } 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)) + } 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)) { dirBrowser->open (options.startupPath); - else { + } else { // Fallback option if the path is empty or the folder doesn't exist dirBrowser->open (safe_get_user_picture_dir()); } @@ -182,29 +194,35 @@ void FilePanel::init () { } } -void FilePanel::on_NB_switch_page(GtkNotebookPage* page, guint page_num) { +void FilePanel::on_NB_switch_page(GtkNotebookPage* page, guint page_num) +{ if (page_num == 1) { // switching the inspector "on" fileCatalog->enableInspector(); - } - else { + } else { // switching the inspector "off" fileCatalog->disableInspector(); } } -bool FilePanel::fileSelected (Thumbnail* thm) { +bool FilePanel::fileSelected (Thumbnail* thm) +{ - if (!parent) + if (!parent) { return false; + } // Check if it's already open BEFORE loading the file - if (options.tabbedUI && parent->selectEditorPanel(thm->getFileName())) + if (options.tabbedUI && parent->selectEditorPanel(thm->getFileName())) { return true; + } // try to open the file bool loading = thm->imageLoad( true ); - if( !loading ) return false; + + if( !loading ) { + return false; + } pendingLoadMutex.lock(); pendingLoad *pl = new pendingLoad(); @@ -215,13 +233,15 @@ bool FilePanel::fileSelected (Thumbnail* thm) { pendingLoadMutex.unlock(); ProgressConnector *ld = new ProgressConnector(); - ld->startFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), thm->getFileName (), thm->getType()==FT_Raw, &error, parent->getProgressListener()), - sigc::bind(sigc::mem_fun(*this,&FilePanel::imageLoaded), thm, ld) ); + ld->startFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), thm->getFileName (), thm->getType() == FT_Raw, &error, parent->getProgressListener()), + sigc::bind(sigc::mem_fun(*this, &FilePanel::imageLoaded), thm, ld) ); return true; } -bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector *pc ){ +bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector *pc ) +{ pendingLoadMutex.lock(); + // find our place in the array and mark the entry as complete for (unsigned int i = 0; i < pendingLoads.size(); i++) { if (pendingLoads[i]->thm == thm) { @@ -230,24 +250,28 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector 0 && pendingLoads.front()->complete) { pendingLoad *pl = pendingLoads.front(); + if (pl->pc->returnValue()) { if (options.tabbedUI) { EditorPanel* epanel; { - GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm - epanel = Gtk::manage (new EditorPanel ()); - parent->addEditorPanel (epanel,pl->thm->getFileName()); + GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm + epanel = Gtk::manage (new EditorPanel ()); + parent->addEditorPanel (epanel, pl->thm->getFileName()); } epanel->open(pl->thm, pl->pc->returnValue() ); - if (!(options.multiDisplayMode>0)) + + if (!(options.multiDisplayMode > 0)) { parent->set_title_decorated(pl->thm->getFileName()); + } } else { { - GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm - parent->SetEditorCurrent(); + GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm + parent->SetEditorCurrent(); } parent->epanel->open(pl->thm, pl->pc->returnValue() ); parent->set_title_decorated(pl->thm->getFileName()); @@ -257,17 +281,19 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnectorpc; { - GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm - parent->setProgress(0.); - parent->setProgressStr(""); + GThreadLock lock; // Acquiring the GUI... not sure that it's necessary, but it shouldn't harm + parent->setProgress(0.); + parent->setProgressStr(""); } pendingLoads.erase(pendingLoads.begin()); delete pl; } + pendingLoadMutex.unlock(); thm->imageLoad( false ); @@ -275,7 +301,8 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnectorget_size(winW, winH); @@ -283,69 +310,86 @@ void FilePanel::saveOptions () { options.dirBrowserHeight = placespaned->get_position (); options.browserToolPanelWidth = winW - get_position(); options.browserToolPanelHeight = tpcPaned->get_position (); - if (options.startupDir==STARTUPDIR_LAST && fileCatalog->lastSelectedDir ()!="") + + if (options.startupDir == STARTUPDIR_LAST && fileCatalog->lastSelectedDir () != "") { options.startupPath = fileCatalog->lastSelectedDir (); + } + fileCatalog->closeDir (); } -void FilePanel::open (const Glib::ustring& d) { +void FilePanel::open (const Glib::ustring& d) +{ - if (safe_file_test (d, Glib::FILE_TEST_IS_DIR)) + if (safe_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 (safe_file_test (d, Glib::FILE_TEST_EXISTS)) { dirBrowser->open (Glib::path_get_dirname(d), Glib::path_get_basename(d)); + } } -bool FilePanel::addBatchQueueJobs ( std::vector &entries ) { +bool FilePanel::addBatchQueueJobs ( std::vector &entries ) +{ - if (parent) + if (parent) { parent->addBatchQueueJobs (entries); - return true; + } + + return true; } -void FilePanel::optionsChanged () { +void FilePanel::optionsChanged () +{ tpc->optionsChanged (); fileCatalog->refreshThumbImages (); } -bool FilePanel::handleShortcutKey (GdkEventKey* event) { +bool FilePanel::handleShortcutKey (GdkEventKey* event) +{ bool ctrl = event->state & GDK_CONTROL_MASK; - + if (!ctrl) { switch(event->keyval) { } - } - else { + } else { switch (event->keyval) { } } - - if(tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey(event)) - return true; - - if(tpc->handleShortcutKey(event)) - return true; - if(fileCatalog->handleShortcutKey(event)) + if(tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey(event)) { return true; + } + + if(tpc->handleShortcutKey(event)) { + return true; + } + + if(fileCatalog->handleShortcutKey(event)) { + return true; + } return false; } void FilePanel::loadingThumbs(Glib::ustring str, double rate) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected - if( !str.empty()) - parent->setProgressStr(str); - parent->setProgress( rate ); + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + + if( !str.empty()) { + parent->setProgressStr(str); + } + + parent->setProgress( rate ); } -void FilePanel::updateTPVScrollbar (bool hide) { - tpc->updateTPVScrollbar (hide); +void FilePanel::updateTPVScrollbar (bool hide) +{ + tpc->updateTPVScrollbar (hide); } -void FilePanel::updateTabsUsesIcons (bool useIcons) { - tpc->updateTabsUsesIcons (useIcons); +void FilePanel::updateTabsUsesIcons (bool useIcons) +{ + tpc->updateTabsUsesIcons (useIcons); } diff --git a/rtgui/filepanel.h b/rtgui/filepanel.h index d5fd7fad2..9d31628e4 100644 --- a/rtgui/filepanel.h +++ b/rtgui/filepanel.h @@ -7,7 +7,7 @@ * 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 @@ -34,73 +34,79 @@ class RTWindow; class FilePanel : public Gtk::HPaned, - public FileSelectionListener, - public PParamsChangeListener + public FileSelectionListener, + public PParamsChangeListener { - protected: - //DirBrowser* dirBrowser; - PlacesBrowser* placesBrowser; - RecentBrowser* recentBrowser; - // FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it +protected: + //DirBrowser* dirBrowser; + PlacesBrowser* placesBrowser; + RecentBrowser* recentBrowser; + // FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it - Inspector* inspectorPanel; - Gtk::VPaned* tpcPaned; - BatchToolPanelCoordinator* tpc; - History* history; - //FilterPanel* filterPanel; - RTWindow* parent; - Gtk::Notebook* rightNotebook; - sigc::connection rightNotebookSwitchConn; + Inspector* inspectorPanel; + Gtk::VPaned* tpcPaned; + BatchToolPanelCoordinator* tpc; + History* history; + //FilterPanel* filterPanel; + RTWindow* parent; + Gtk::Notebook* rightNotebook; + sigc::connection rightNotebookSwitchConn; - struct pendingLoad { - bool complete; - ProgressConnector *pc; - Thumbnail *thm; - }; - MyMutex pendingLoadMutex; - std::vector pendingLoads; + struct pendingLoad { + bool complete; + ProgressConnector *pc; + Thumbnail *thm; + }; + MyMutex pendingLoadMutex; + std::vector pendingLoads; - int error; + int error; - void on_NB_switch_page(GtkNotebookPage* page, guint page_num); + void on_NB_switch_page(GtkNotebookPage* page, guint page_num); - public: - FilePanel (); - ~FilePanel (); +public: + FilePanel (); + ~FilePanel (); - Gtk::Paned* placespaned; - Gtk::HPaned* dirpaned; + Gtk::Paned* placespaned; + Gtk::HPaned* dirpaned; - Gtk::HBox* rightBox; + Gtk::HBox* rightBox; - DirBrowser* dirBrowser; - FilterPanel* filterPanel; - ExportPanel* exportPanel; - FileCatalog* fileCatalog; - Gtk::Paned *ribbonPane; + DirBrowser* dirBrowser; + FilterPanel* filterPanel; + ExportPanel* exportPanel; + FileCatalog* fileCatalog; + Gtk::Paned *ribbonPane; - void setParent (RTWindow* p) { parent = p; } - void init (); // dont call it directly, the constructor calls it as idle source - void on_realize (); - void setAspect(); - void open (const Glib::ustring& d); // open a file or a directory - void refreshEditedState (const std::set& efiles) { fileCatalog->refreshEditedState (efiles); } - void loadingThumbs(Glib::ustring str, double rate); + void setParent (RTWindow* p) + { + parent = p; + } + void init (); // dont call it directly, the constructor calls it as idle source + void on_realize (); + void setAspect(); + void open (const Glib::ustring& d); // open a file or a directory + void refreshEditedState (const std::set& efiles) + { + fileCatalog->refreshEditedState (efiles); + } + void loadingThumbs(Glib::ustring str, double rate); - // call this before closing RT: it saves file browser's related things into options - void saveOptions (); + // call this before closing RT: it saves file browser's related things into options + void saveOptions (); - // interface fileselectionlistener - bool fileSelected (Thumbnail* thm); - bool addBatchQueueJobs ( std::vector &entries ); + // interface fileselectionlistener + bool fileSelected (Thumbnail* thm); + bool addBatchQueueJobs ( std::vector &entries ); - void optionsChanged (); - bool imageLoaded( Thumbnail* thm, ProgressConnector * ); + void optionsChanged (); + bool imageLoaded( Thumbnail* thm, ProgressConnector * ); - bool handleShortcutKey (GdkEventKey* event); - void updateTPVScrollbar (bool hide); - void updateTabsUsesIcons (bool useIcons); + bool handleShortcutKey (GdkEventKey* event); + void updateTPVScrollbar (bool hide); + void updateTabsUsesIcons (bool useIcons); }; #endif diff --git a/rtgui/fileselectionchangelistener.h b/rtgui/fileselectionchangelistener.h index c8e0a9a8c..1ad905d17 100644 --- a/rtgui/fileselectionchangelistener.h +++ b/rtgui/fileselectionchangelistener.h @@ -7,7 +7,7 @@ * 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 @@ -21,9 +21,10 @@ #include "thumbnail.h" -class FileSelectionChangeListener { +class FileSelectionChangeListener +{ - public: +public: virtual void selectionChanged (const std::vector& selected) {} }; diff --git a/rtgui/fileselectionlistener.h b/rtgui/fileselectionlistener.h index 0da740f31..dc6434dab 100644 --- a/rtgui/fileselectionlistener.h +++ b/rtgui/fileselectionlistener.h @@ -7,7 +7,7 @@ * 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 @@ -22,11 +22,12 @@ #include "thumbnail.h" #include "batchqueueentry.h" -class FileSelectionListener { +class FileSelectionListener +{ - public: - virtual bool fileSelected (Thumbnail* thm) =0; - virtual bool addBatchQueueJobs ( std::vector &entries ) =0; +public: + virtual bool fileSelected (Thumbnail* thm) = 0; + virtual bool addBatchQueueJobs ( std::vector &entries ) = 0; }; #endif diff --git a/rtgui/filethumbnailbuttonset.cc b/rtgui/filethumbnailbuttonset.cc index 5111017d7..e9970b177 100644 --- a/rtgui/filethumbnailbuttonset.cc +++ b/rtgui/filethumbnailbuttonset.cc @@ -7,7 +7,7 @@ * 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 @@ -37,29 +37,33 @@ Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_3; Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_4; Cairo::RefPtr FileThumbnailButtonSet::colorLabelIcon_5; -FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) { +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 = 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"); - 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"); - iconsLoaded = true; + 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"); + iconsLoaded = true; } add (new LWButton (processIcon, 6, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPPROCESS"))); add (new LWButton (unRankIcon, 0, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_UNRANK_TOOLTIP"))); - for (int i=0; i<5; i++) - add (new LWButton (rankIcon, i+1, myEntry, LWButton::Left)); + + for (int i = 0; i < 5; i++) { + add (new LWButton (rankIcon, i + 1, myEntry, LWButton::Left)); + } + add (new LWButton (trashIcon, 7, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_POPUPTRASH"))); add (new LWButton (colorLabelIcon_0, 8, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_COLORLABEL_TOOLTIP"))); @@ -71,24 +75,45 @@ FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) { buttons[6]->setToolTip (M("FILEBROWSER_RANK5_TOOLTIP")); } -void FileThumbnailButtonSet::setRank (int stars) { +void FileThumbnailButtonSet::setRank (int stars) +{ - for (int i=1; i<=5; i++) - buttons[i+1]->setIcon (i<=stars ? rankIcon : gRankIcon); + for (int i = 1; i <= 5; i++) { + buttons[i + 1]->setIcon (i <= stars ? rankIcon : gRankIcon); + } } -void FileThumbnailButtonSet::setColorLabel (int colorLabel) { +void FileThumbnailButtonSet::setColorLabel (int colorLabel) +{ - if (colorLabel==0) buttons[8]->setIcon (colorLabelIcon_0); //transparent label - if (colorLabel==1) buttons[8]->setIcon (colorLabelIcon_1); - if (colorLabel==2) buttons[8]->setIcon (colorLabelIcon_2); - if (colorLabel==3) buttons[8]->setIcon (colorLabelIcon_3); - if (colorLabel==4) buttons[8]->setIcon (colorLabelIcon_4); - if (colorLabel==5) buttons[8]->setIcon (colorLabelIcon_5); + if (colorLabel == 0) { + buttons[8]->setIcon (colorLabelIcon_0); //transparent label + } + + if (colorLabel == 1) { + buttons[8]->setIcon (colorLabelIcon_1); + } + + if (colorLabel == 2) { + buttons[8]->setIcon (colorLabelIcon_2); + } + + if (colorLabel == 3) { + buttons[8]->setIcon (colorLabelIcon_3); + } + + if (colorLabel == 4) { + buttons[8]->setIcon (colorLabelIcon_4); + } + + if (colorLabel == 5) { + buttons[8]->setIcon (colorLabelIcon_5); + } } -void FileThumbnailButtonSet::setInTrash (bool inTrash) { +void FileThumbnailButtonSet::setInTrash (bool inTrash) +{ - buttons[7]->setIcon (inTrash ? unTrashIcon : trashIcon); - buttons[7]->setToolTip (inTrash ? M("FILEBROWSER_POPUPUNTRASH") : M("FILEBROWSER_POPUPTRASH")); + buttons[7]->setIcon (inTrash ? unTrashIcon : trashIcon); + buttons[7]->setToolTip (inTrash ? M("FILEBROWSER_POPUPUNTRASH") : M("FILEBROWSER_POPUPTRASH")); } diff --git a/rtgui/filethumbnailbuttonset.h b/rtgui/filethumbnailbuttonset.h index 3ba6408f3..b152c3853 100644 --- a/rtgui/filethumbnailbuttonset.h +++ b/rtgui/filethumbnailbuttonset.h @@ -7,7 +7,7 @@ * 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 @@ -24,29 +24,30 @@ #include "filebrowserentry.h" class FileBrowserEntry; -class FileThumbnailButtonSet : public LWButtonSet { +class FileThumbnailButtonSet : public LWButtonSet +{ - static bool iconsLoaded; - - public: - static Cairo::RefPtr rankIcon; - static Cairo::RefPtr gRankIcon; - static Cairo::RefPtr unRankIcon; - static Cairo::RefPtr trashIcon; - static Cairo::RefPtr unTrashIcon; - static Cairo::RefPtr processIcon; - - static Cairo::RefPtr colorLabelIcon_0; - static Cairo::RefPtr colorLabelIcon_1; - static Cairo::RefPtr colorLabelIcon_2; - static Cairo::RefPtr colorLabelIcon_3; - static Cairo::RefPtr colorLabelIcon_4; - static Cairo::RefPtr colorLabelIcon_5; + static bool iconsLoaded; - FileThumbnailButtonSet (FileBrowserEntry* myEntry); - void setRank (int stars); - void setColorLabel (int colorlabel); - void setInTrash (bool inTrash); +public: + static Cairo::RefPtr rankIcon; + static Cairo::RefPtr gRankIcon; + static Cairo::RefPtr unRankIcon; + static Cairo::RefPtr trashIcon; + static Cairo::RefPtr unTrashIcon; + static Cairo::RefPtr processIcon; + + static Cairo::RefPtr colorLabelIcon_0; + static Cairo::RefPtr colorLabelIcon_1; + static Cairo::RefPtr colorLabelIcon_2; + static Cairo::RefPtr colorLabelIcon_3; + static Cairo::RefPtr colorLabelIcon_4; + static Cairo::RefPtr colorLabelIcon_5; + + FileThumbnailButtonSet (FileBrowserEntry* myEntry); + void setRank (int stars); + void setColorLabel (int colorlabel); + void setInTrash (bool inTrash); }; diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index b17760319..907f5578a 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -9,15 +9,16 @@ using namespace rtengine::procparams; typedef std::vector Strings; FilmSimulation::FilmSimulation() -: FoldableToolPanel( this, "filmsimulation", M("TP_FILMSIMULATION_LABEL"), false, true ) + : FoldableToolPanel( this, "filmsimulation", M("TP_FILMSIMULATION_LABEL"), false, true ) { m_clutComboBox = Gtk::manage( new ClutComboBox() ); int foundClutsCount = m_clutComboBox->fillFromDir( options.clutsDir ); - if ( foundClutsCount == 0 ) - { + + if ( foundClutsCount == 0 ) { pack_start( *Gtk::manage( new Gtk::Label( M("TP_FILMSIMULATION_ZEROCLUTSFOUND") ) ) ); } - m_clutComboBoxConn = m_clutComboBox->signal_changed().connect( sigc::mem_fun( *this, &FilmSimulation::onClutSelected ) ); + + m_clutComboBoxConn = m_clutComboBox->signal_changed().connect( sigc::mem_fun( *this, &FilmSimulation::onClutSelected ) ); pack_start( *m_clutComboBox ); m_strength = Gtk::manage( new Adjuster( M("TP_FILMSIMULATION_STRENGTH"), 0., 100, 1., 100 ) ); @@ -31,32 +32,32 @@ void FilmSimulation::onClutSelected() { Glib::ustring currentClutFilename = m_clutComboBox->getSelectedClut(); - if ( getEnabled() && !currentClutFilename.empty() && listener && currentClutFilename != m_oldClutFilename ) - { + if ( getEnabled() && !currentClutFilename.empty() && listener && currentClutFilename != m_oldClutFilename ) { Glib::ustring clutName, dummy; splitClutFilename( currentClutFilename, clutName, dummy, dummy ); listener->panelChanged( EvFilmSimulationFilename, clutName ); m_oldClutFilename = currentClutFilename; - } + } } -void FilmSimulation::enabledChanged () { +void FilmSimulation::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvFilmSimulationEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvFilmSimulationEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvFilmSimulationEnabled, M("GENERAL_DISABLED")); + } } } void FilmSimulation::adjusterChanged( Adjuster* a, double newval ) { - if (listener && (multiImage||getEnabled()) ) - { + if (listener && (multiImage || getEnabled()) ) { Glib::ustring value = a->getTextValue(); listener->panelChanged ( EvFilmSimulationStrength, value ); } @@ -75,21 +76,26 @@ void FilmSimulation::read( const rtengine::procparams::ProcParams* pp, const Par updateDisable( true ); setEnabled (pp->filmSimulation.enabled); - if ( !pp->filmSimulation.clutFilename.empty() ) + + if ( !pp->filmSimulation.clutFilename.empty() ) { m_clutComboBox->setSelectedClut( pp->filmSimulation.clutFilename ); + } + m_strength->setValue( pp->filmSimulation.strength ); - if (pedited) - { + if (pedited) { set_inconsistent (multiImage && !pedited->filmSimulation.enabled); m_strength->setEditedState (pedited->filmSimulation.strength ? Edited : UnEdited); - if ( !pedited->filmSimulation.clutFilename ) + + if ( !pedited->filmSimulation.clutFilename ) { m_clutComboBox->setSelectedClut("NULL"); + } } - if ( !get_inconsistent() && !pp->filmSimulation.enabled ) - { - if (options.clutCacheSize == 1) - clutStore.clearCache(); + + if ( !get_inconsistent() && !pp->filmSimulation.enabled ) { + if (options.clutCacheSize == 1) { + clutStore.clearCache(); + } } updateDisable( false ); @@ -103,8 +109,7 @@ void FilmSimulation::updateDisable( bool value ) void FilmSimulation::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited ) { - if ( pedited ) - { + if ( pedited ) { pedited->filmSimulation.enabled = !get_inconsistent(); pedited->filmSimulation.strength = m_strength->getEditedState (); pedited->filmSimulation.clutFilename = m_clutComboBox->getSelectedClut() != "NULL"; @@ -112,8 +117,11 @@ void FilmSimulation::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pp->filmSimulation.enabled = getEnabled(); Glib::ustring clutFName = m_clutComboBox->getSelectedClut(); - if ( clutFName != "NULL" ) // We do not want to set "NULL" in clutFilename, even if "unedited" + + if ( clutFName != "NULL" ) { // We do not want to set "NULL" in clutFilename, even if "unedited" pp->filmSimulation.clutFilename = clutFName; + } + pp->filmSimulation.strength = m_strength->getValue(); } @@ -138,73 +146,71 @@ ClutComboBox::ClutColumns::ClutColumns() int ClutComboBox::fillFromDir( Glib::ustring path ) { int result = 0; - if ( !path.empty() ) - { + + if ( !path.empty() ) { m_model.clear(); m_model = Gtk::TreeStore::create( m_columns ); set_model( m_model ); result = parseDir( path, 0 ); pack_start( m_columns.label, false ); } + return result; } Gtk::TreeIter appendToModel( Glib::RefPtr model, Gtk::TreeModel::Row *parent ) { Gtk::TreeIter result; - if ( parent ) - { + + if ( parent ) { result = model->append( parent->children() ); - - } - else - { + + } else { result = model->append(); } + return result; } int ClutComboBox::parseDir( Glib::ustring path, Gtk::TreeModel::Row *parentRow ) { int result = 0; - if ( path.empty() || !safe_file_test( path, Glib::FILE_TEST_EXISTS ) || !safe_file_test ( path, Glib::FILE_TEST_IS_DIR ) ) + + if ( path.empty() || !safe_file_test( path, Glib::FILE_TEST_EXISTS ) || !safe_file_test ( path, Glib::FILE_TEST_IS_DIR ) ) { return result; + } Glib::Dir* dir = new Glib::Dir( path ); Strings names; - for( Glib::DirIterator it = dir->begin(); it != dir->end(); ++it ) - { + for( Glib::DirIterator it = dir->begin(); it != dir->end(); ++it ) { Glib::ustring current = *it; - if ( current != "." && current != ".." ) - { - names.push_back( current ); + + if ( current != "." && current != ".." ) { + names.push_back( current ); } } std::sort( names.begin(), names.end() ); - for ( Strings::iterator it = names.begin(); it != names.end(); ++it ) - { + for ( Strings::iterator it = names.begin(); it != names.end(); ++it ) { Glib::ustring current = *it; Glib::ustring fullname = Glib::build_filename( path, current ); - if ( safe_file_test( fullname, Glib::FILE_TEST_IS_DIR ) ) - { - - Gtk::TreeModel::Row newFolderMenu = *appendToModel( m_model, parentRow ); - newFolderMenu[ m_columns.label ] = current; - result += parseDir( fullname, &newFolderMenu ); - } - else - { + + if ( safe_file_test( fullname, Glib::FILE_TEST_IS_DIR ) ) { + + Gtk::TreeModel::Row newFolderMenu = *appendToModel( m_model, parentRow ); + newFolderMenu[ m_columns.label ] = current; + result += parseDir( fullname, &newFolderMenu ); + } else { Glib::ustring name, extension, profileName; splitClutFilename( current, name, extension, profileName ); + if ( extension == "tif" || - extension == "TIF" || - extension == "png" || - extension == "PNG" ) - { + extension == "TIF" || + extension == "png" || + extension == "PNG" ) { Gtk::TreeModel::Row newClut = *appendToModel( m_model, parentRow ); newClut[ m_columns.label ] = name; newClut[ m_columns.clutFilename ] = fullname; @@ -212,6 +218,7 @@ int ClutComboBox::parseDir( Glib::ustring path, Gtk::TreeModel::Row *parentRow ) } } } + return result; } @@ -220,20 +227,20 @@ Glib::ustring ClutComboBox::getSelectedClut() Glib::ustring result; Gtk::TreeModel::iterator current = get_active(); Gtk::TreeModel::Row row = *current; - if ( row ) - { + + if ( row ) { result = row[ m_columns.clutFilename ]; } + return result; } void ClutComboBox::setSelectedClut( Glib::ustring filename ) { - if ( !filename.empty() ) - { + if ( !filename.empty() ) { Gtk::TreeIter found = findRowByClutFilename( m_model->children(), filename ); - if ( found ) - { + + if ( found ) { set_active( found ); } } @@ -242,22 +249,22 @@ void ClutComboBox::setSelectedClut( Glib::ustring filename ) Gtk::TreeIter ClutComboBox::findRowByClutFilename( Gtk::TreeModel::Children childs, Glib::ustring filename ) { Gtk::TreeIter result = childs.end(); - for( Gtk::TreeModel::Children::iterator it = childs.begin(); !result && it != childs.end(); ++it ) - { + + for( Gtk::TreeModel::Children::iterator it = childs.begin(); !result && it != childs.end(); ++it ) { Gtk::TreeModel::Row row = *it; - if ( row[ m_columns.clutFilename ] == filename ) - { + + if ( row[ m_columns.clutFilename ] == filename ) { result = it; - } - else - { + } else { result = findRowByClutFilename( it->children(), filename ); } } + return result; } -void ClutComboBox::addUnchangedEntry() { +void ClutComboBox::addUnchangedEntry() +{ Gtk::TreeModel::Row row = *(m_model->append()); row[m_columns.label] = M("GENERAL_UNCHANGED"); row[m_columns.clutFilename] = "NULL"; diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index c5c447495..89e9f6fa3 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -17,7 +17,7 @@ public: void addUnchangedEntry(); private: - class ClutColumns : public Gtk::TreeModel::ColumnRecord + class ClutColumns : public Gtk::TreeModel::ColumnRecord { public: Gtk::TreeModelColumn label; diff --git a/rtgui/filterpanel.cc b/rtgui/filterpanel.cc index ab746a9fa..bc4396aca 100644 --- a/rtgui/filterpanel.cc +++ b/rtgui/filterpanel.cc @@ -7,7 +7,7 @@ * 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 @@ -23,109 +23,110 @@ using namespace rtengine; -FilterPanel::FilterPanel () : listener (NULL) { +FilterPanel::FilterPanel () : listener (NULL) +{ - set_border_width (4); + set_border_width (4); - enabled = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_METADATAFILTER"))); - pack_start (*enabled, Gtk::PACK_SHRINK, 2); - pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2); - - enaFNumber = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_APERTURE")+":")); - Gtk::VBox* fnvb = Gtk::manage(new Gtk::VBox ()); + enabled = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_METADATAFILTER"))); + pack_start (*enabled, Gtk::PACK_SHRINK, 2); + pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2); + + enaFNumber = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_APERTURE") + ":")); + Gtk::VBox* fnvb = Gtk::manage(new Gtk::VBox ()); Gtk::HBox* fnhb = Gtk::manage(new Gtk::HBox ()); - fnvb->pack_start (*enaFNumber, Gtk::PACK_SHRINK, 0); + fnvb->pack_start (*enaFNumber, Gtk::PACK_SHRINK, 0); fnumberFrom = Gtk::manage(new Gtk::Entry ()); - fnumberTo = Gtk::manage(new Gtk::Entry ()); + fnumberTo = Gtk::manage(new Gtk::Entry ()); fnhb->pack_start (*fnumberFrom, true, true, 2); fnhb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); fnhb->pack_start (*fnumberTo, true, true, 2); - fnvb->pack_start (*fnhb, Gtk::PACK_SHRINK, 0); - pack_start (*fnvb, Gtk::PACK_SHRINK, 4); + fnvb->pack_start (*fnhb, Gtk::PACK_SHRINK, 0); + pack_start (*fnvb, Gtk::PACK_SHRINK, 4); - enaShutter = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_SHUTTER")+":")); - Gtk::VBox* svb = Gtk::manage(new Gtk::VBox ()); + enaShutter = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_SHUTTER") + ":")); + Gtk::VBox* svb = Gtk::manage(new Gtk::VBox ()); Gtk::HBox* shb = Gtk::manage(new Gtk::HBox ()); - svb->pack_start (*enaShutter, Gtk::PACK_SHRINK, 0); + svb->pack_start (*enaShutter, Gtk::PACK_SHRINK, 0); shutterFrom = Gtk::manage(new Gtk::Entry ()); - shutterTo = Gtk::manage(new Gtk::Entry ()); + shutterTo = Gtk::manage(new Gtk::Entry ()); shb->pack_start (*shutterFrom, true, true, 2); shb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); shb->pack_start (*shutterTo, true, true, 2); - svb->pack_start (*shb, Gtk::PACK_SHRINK, 0); - pack_start (*svb, Gtk::PACK_SHRINK, 4); + svb->pack_start (*shb, Gtk::PACK_SHRINK, 0); + pack_start (*svb, Gtk::PACK_SHRINK, 4); - enaISO = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_ISO")+":")); - Gtk::VBox* ivb = Gtk::manage(new Gtk::VBox ()); + enaISO = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_ISO") + ":")); + Gtk::VBox* ivb = Gtk::manage(new Gtk::VBox ()); Gtk::HBox* ihb = Gtk::manage(new Gtk::HBox ()); - ivb->pack_start (*enaISO, Gtk::PACK_SHRINK, 0); + ivb->pack_start (*enaISO, Gtk::PACK_SHRINK, 0); isoFrom = Gtk::manage(new Gtk::Entry ()); - isoTo = Gtk::manage(new Gtk::Entry ()); + isoTo = Gtk::manage(new Gtk::Entry ()); ihb->pack_start (*isoFrom, true, true, 2); ihb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); ihb->pack_start (*isoTo, true, true, 2); - ivb->pack_start (*ihb, Gtk::PACK_SHRINK, 0); - pack_start (*ivb, Gtk::PACK_SHRINK, 4); - - enaFocalLen = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FOCALLEN")+":")); + ivb->pack_start (*ihb, Gtk::PACK_SHRINK, 0); + pack_start (*ivb, Gtk::PACK_SHRINK, 4); + + enaFocalLen = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FOCALLEN") + ":")); Gtk::VBox* fvb = Gtk::manage(new Gtk::VBox ()); Gtk::HBox* fhb = Gtk::manage(new Gtk::HBox ()); - fvb->pack_start (*enaFocalLen, Gtk::PACK_SHRINK, 0); + fvb->pack_start (*enaFocalLen, Gtk::PACK_SHRINK, 0); focalFrom = Gtk::manage(new Gtk::Entry ()); - focalTo = Gtk::manage(new Gtk::Entry ()); + focalTo = Gtk::manage(new Gtk::Entry ()); fhb->pack_start (*focalFrom, true, true, 2); fhb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4); fhb->pack_start (*focalTo, true, true, 2); - fvb->pack_start (*fhb, Gtk::PACK_SHRINK, 0); - pack_start (*fvb, Gtk::PACK_SHRINK, 4); + fvb->pack_start (*fhb, Gtk::PACK_SHRINK, 0); + pack_start (*fvb, Gtk::PACK_SHRINK, 4); - enaExpComp = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_EXPOSURECOMPENSATION")+":")); + enaExpComp = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_EXPOSURECOMPENSATION") + ":")); Gtk::VBox* evb = Gtk::manage(new Gtk::VBox ()); evb->pack_start (*enaExpComp, Gtk::PACK_SHRINK, 0); expcomp = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); expcomp->set_headers_visible (false); Gtk::ScrolledWindow* sexpcomp = Gtk::manage(new Gtk::ScrolledWindow()); sexpcomp->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); - sexpcomp->set_size_request(-1, 80); + sexpcomp->set_size_request(-1, 80); sexpcomp->add(*expcomp); evb->pack_start (*sexpcomp, Gtk::PACK_SHRINK, 0); pack_start (*evb, Gtk::PACK_SHRINK, 4); - enaCamera = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_CAMERA")+":")); + enaCamera = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_CAMERA") + ":")); Gtk::VBox* cvb = Gtk::manage(new Gtk::VBox ()); - cvb->pack_start (*enaCamera, Gtk::PACK_SHRINK, 0); + cvb->pack_start (*enaCamera, Gtk::PACK_SHRINK, 0); camera = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); camera->set_headers_visible (false); Gtk::ScrolledWindow* scamera = Gtk::manage(new Gtk::ScrolledWindow()); scamera->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); - scamera->set_size_request(-1, 80); + scamera->set_size_request(-1, 80); scamera->add(*camera); - cvb->pack_start (*scamera, Gtk::PACK_SHRINK, 0); - pack_start (*cvb, Gtk::PACK_SHRINK, 4); + cvb->pack_start (*scamera, Gtk::PACK_SHRINK, 0); + pack_start (*cvb, Gtk::PACK_SHRINK, 4); - enaLens = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_LENS")+":")); + enaLens = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_LENS") + ":")); Gtk::VBox* lvb = Gtk::manage(new Gtk::VBox ()); - lvb->pack_start (*enaLens, Gtk::PACK_SHRINK, 0); + lvb->pack_start (*enaLens, Gtk::PACK_SHRINK, 0); lens = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); lens->set_headers_visible (false); Gtk::ScrolledWindow* slens = Gtk::manage(new Gtk::ScrolledWindow()); slens->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); - slens->set_size_request(-1, 80); + slens->set_size_request(-1, 80); slens->add(*lens); - lvb->pack_start (*slens, Gtk::PACK_SHRINK, 0); - pack_start (*lvb, Gtk::PACK_SHRINK, 4); - - enaFiletype = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FILETYPE")+":")); - Gtk::VBox* ftvb = Gtk::manage(new Gtk::VBox ()); - ftvb->pack_start (*enaFiletype, Gtk::PACK_SHRINK, 0); - filetype = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); - filetype->set_headers_visible (false); - Gtk::ScrolledWindow* sfiletype = Gtk::manage(new Gtk::ScrolledWindow()); - sfiletype->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); - sfiletype->set_size_request(-1, 80); - sfiletype->add(*filetype); - ftvb->pack_start (*sfiletype, Gtk::PACK_SHRINK, 0); - pack_start (*ftvb, Gtk::PACK_SHRINK, 4); + lvb->pack_start (*slens, Gtk::PACK_SHRINK, 0); + pack_start (*lvb, Gtk::PACK_SHRINK, 4); + + enaFiletype = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FILETYPE") + ":")); + Gtk::VBox* ftvb = Gtk::manage(new Gtk::VBox ()); + ftvb->pack_start (*enaFiletype, Gtk::PACK_SHRINK, 0); + filetype = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); + filetype->set_headers_visible (false); + Gtk::ScrolledWindow* sfiletype = Gtk::manage(new Gtk::ScrolledWindow()); + sfiletype->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); + sfiletype->set_size_request(-1, 80); + sfiletype->add(*filetype); + ftvb->pack_start (*sfiletype, Gtk::PACK_SHRINK, 0); + pack_start (*ftvb, Gtk::PACK_SHRINK, 4); // add panel ending Gtk::VBox* vboxpe = Gtk::manage (new Gtk::VBox ()); @@ -135,7 +136,7 @@ FilterPanel::FilterPanel () : listener (NULL) { vboxpe->pack_start(*peImg); pack_start(*vboxpe, Gtk::PACK_SHRINK, 0); - conns = 0; + conns = 0; sChange[conns++] = fnumberFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); sChange[conns++] = fnumberTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); sChange[conns++] = shutterFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged)); @@ -158,131 +159,156 @@ FilterPanel::FilterPanel () : listener (NULL) { sChange[conns++] = enabled->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); sChange[conns++] = enaFiletype->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) ); - set_size_request (0, -1); - - show_all (); + set_size_request (0, -1); + + show_all (); } -void FilterPanel::setFilter (ExifFilterSettings& defefs, bool updateLists) { +void FilterPanel::setFilter (ExifFilterSettings& defefs, bool updateLists) +{ - - for (int i=0; iset_active (curefs.filterFNumber); + + for (int i = 0; i < conns; i++) { + sChange[i].block (true); + } + +// enaFNumber->set_active (curefs.filterFNumber); fnumberFrom->set_text (ImageMetaData::apertureToString (defefs.fnumberFrom)); curefs.fnumberFrom = defefs.fnumberFrom; fnumberTo->set_text (ImageMetaData::apertureToString (defefs.fnumberTo)); curefs.fnumberTo = defefs.fnumberTo; -// enaShutter->set_active (curefs.filterShutter); +// enaShutter->set_active (curefs.filterShutter); shutterFrom->set_text (ImageMetaData::shutterToString (defefs.shutterFrom)); curefs.shutterFrom = defefs.shutterFrom; shutterTo->set_text (ImageMetaData::shutterToString (defefs.shutterTo)); curefs.shutterTo = defefs.shutterTo; -// enaISO->set_active (curefs.filterISO); +// enaISO->set_active (curefs.filterISO); isoFrom->set_text (Glib::ustring::format (defefs.isoFrom)); curefs.isoFrom = defefs.isoFrom; isoTo->set_text (Glib::ustring::format (defefs.isoTo)); curefs.isoTo = defefs.isoTo; -// enaFocalLen->set_active (curefs.filterFocalLen); +// enaFocalLen->set_active (curefs.filterFocalLen); focalFrom->set_text (Glib::ustring::format (defefs.focalFrom)); curefs.focalFrom = defefs.focalFrom; focalTo->set_text (Glib::ustring::format (defefs.focalTo)); curefs.focalTo = defefs.focalTo; -// enaCompExp->set_active (curefs.filterExpComp); - Glib::RefPtr eselection = expcomp->get_selection (); +// enaCompExp->set_active (curefs.filterExpComp); + Glib::RefPtr eselection = expcomp->get_selection (); -// enaFiletype->set_active (curefs.filterFiletype); - Glib::RefPtr ftselection = filetype->get_selection (); +// enaFiletype->set_active (curefs.filterFiletype); + Glib::RefPtr ftselection = filetype->get_selection (); -// enaCamera->set_active (curefs.filterCamera); +// enaCamera->set_active (curefs.filterCamera); Glib::RefPtr cselection = camera->get_selection (); -// enaLens->set_active (curefs.filterLens); +// enaLens->set_active (curefs.filterLens); Glib::RefPtr lselection = lens->get_selection (); - if( updateLists ){ - expcomp->clear_items(); - curefs.expcomp.clear(); - for (std::set::iterator i = defefs.expcomp.begin(); i!=defefs.expcomp.end(); i++) { - expcomp->append_text (*i); - curefs.expcomp.insert(*i); - } - eselection->select_all(); - lens->clear_items(); - curefs.lenses.clear(); - for (std::set::iterator i = defefs.lenses.begin(); i!=defefs.lenses.end(); i++) { - lens->append_text (*i); - curefs.lenses.insert(*i); - } - lselection->select_all(); + if( updateLists ) { + expcomp->clear_items(); + curefs.expcomp.clear(); - camera->clear_items(); - curefs.cameras.clear(); - for (std::set::iterator i = defefs.cameras.begin(); i!=defefs.cameras.end(); i++) { - camera->append_text(*i); - curefs.cameras.insert(*i); - } - cselection->select_all(); + for (std::set::iterator i = defefs.expcomp.begin(); i != defefs.expcomp.end(); i++) { + expcomp->append_text (*i); + curefs.expcomp.insert(*i); + } - filetype->clear_items(); - curefs.filetypes.clear(); - for (std::set::iterator i = defefs.filetypes.begin(); i!=defefs.filetypes.end(); i++) { - filetype->append_text(*i); - curefs.filetypes.insert(*i); - } - ftselection->select_all(); - }else{ - for( Gtk::TreeModel::Children::iterator iter = expcomp->get_model()->children().begin(); iter != expcomp->get_model()->children().end();iter++){ - Glib::ustring v; - iter->get_value(0,v); - if( defefs.expcomp.find( v ) != defefs.expcomp.end() ) - eselection->select( iter ); - else - eselection->unselect( iter ); - } - for( Gtk::TreeModel::Children::iterator iter = lens->get_model()->children().begin(); iter != lens->get_model()->children().end();iter++){ - Glib::ustring v; - iter->get_value(0,v); - if( defefs.lenses.find( v ) != defefs.lenses.end() ) - lselection->select( iter ); - else - lselection->unselect( iter ); - } - for( Gtk::TreeModel::Children::iterator iter = camera->get_model()->children().begin(); iter != camera->get_model()->children().end();iter++){ - Glib::ustring v; - iter->get_value(0,v); - if( defefs.cameras.find( v ) != defefs.cameras.end() ) - cselection->select(iter); - else - cselection->unselect(iter); - } - for( Gtk::TreeModel::Children::iterator iter = filetype->get_model()->children().begin(); iter != filetype->get_model()->children().end();iter++){ - Glib::ustring v; - iter->get_value(0,v); - if( defefs.filetypes.find( v ) != defefs.filetypes.end() ) - ftselection->select(iter); - else - ftselection->unselect(iter); - } + eselection->select_all(); + + lens->clear_items(); + curefs.lenses.clear(); + + for (std::set::iterator i = defefs.lenses.begin(); i != defefs.lenses.end(); i++) { + lens->append_text (*i); + curefs.lenses.insert(*i); + } + + lselection->select_all(); + + camera->clear_items(); + curefs.cameras.clear(); + + for (std::set::iterator i = defefs.cameras.begin(); i != defefs.cameras.end(); i++) { + camera->append_text(*i); + curefs.cameras.insert(*i); + } + + cselection->select_all(); + + filetype->clear_items(); + curefs.filetypes.clear(); + + for (std::set::iterator i = defefs.filetypes.begin(); i != defefs.filetypes.end(); i++) { + filetype->append_text(*i); + curefs.filetypes.insert(*i); + } + + ftselection->select_all(); + } else { + for( Gtk::TreeModel::Children::iterator iter = expcomp->get_model()->children().begin(); iter != expcomp->get_model()->children().end(); iter++) { + Glib::ustring v; + iter->get_value(0, v); + + if( defefs.expcomp.find( v ) != defefs.expcomp.end() ) { + eselection->select( iter ); + } else { + eselection->unselect( iter ); + } + } + + for( Gtk::TreeModel::Children::iterator iter = lens->get_model()->children().begin(); iter != lens->get_model()->children().end(); iter++) { + Glib::ustring v; + iter->get_value(0, v); + + if( defefs.lenses.find( v ) != defefs.lenses.end() ) { + lselection->select( iter ); + } else { + lselection->unselect( iter ); + } + } + + for( Gtk::TreeModel::Children::iterator iter = camera->get_model()->children().begin(); iter != camera->get_model()->children().end(); iter++) { + Glib::ustring v; + iter->get_value(0, v); + + if( defefs.cameras.find( v ) != defefs.cameras.end() ) { + cselection->select(iter); + } else { + cselection->unselect(iter); + } + } + + for( Gtk::TreeModel::Children::iterator iter = filetype->get_model()->children().begin(); iter != filetype->get_model()->children().end(); iter++) { + Glib::ustring v; + iter->get_value(0, v); + + if( defefs.filetypes.find( v ) != defefs.filetypes.end() ) { + ftselection->select(iter); + } else { + ftselection->unselect(iter); + } + } } - curefs = defefs; + curefs = defefs; - for (int i=0; iget_active () && is_sensitive(); + return enabled->get_active () && is_sensitive(); } -ExifFilterSettings FilterPanel::getFilter () { +ExifFilterSettings FilterPanel::getFilter () +{ ExifFilterSettings efs; efs.fnumberFrom = atof (fnumberFrom->get_text().c_str()); @@ -293,38 +319,48 @@ ExifFilterSettings FilterPanel::getFilter () { efs.isoTo = atoi (isoTo->get_text().c_str()); efs.shutterFrom = ImageMetaData::shutterFromString (shutterFrom->get_text()); efs.shutterTo = ImageMetaData::shutterFromString (shutterTo->get_text()); - - efs.filterFNumber = enaFNumber->get_active (); - efs.filterShutter = enaShutter->get_active (); - efs.filterFocalLen = enaFocalLen->get_active (); - efs.filterISO = enaISO->get_active (); - efs.filterExpComp = enaExpComp->get_active (); - efs.filterCamera = enaCamera->get_active (); - efs.filterLens = enaLens->get_active (); - efs.filterFiletype = enaFiletype->get_active (); - + + efs.filterFNumber = enaFNumber->get_active (); + efs.filterShutter = enaShutter->get_active (); + efs.filterFocalLen = enaFocalLen->get_active (); + efs.filterISO = enaISO->get_active (); + efs.filterExpComp = enaExpComp->get_active (); + efs.filterCamera = enaCamera->get_active (); + efs.filterLens = enaLens->get_active (); + efs.filterFiletype = enaFiletype->get_active (); + std::vector sel = camera->get_selected (); - for (size_t i=0; iget_text (sel[i])); + } sel = expcomp->get_selected (); - for (size_t i=0; iget_text (sel[i])); + } sel = lens->get_selected (); - for (size_t i=0; iget_text (sel[i])); + } sel = filetype->get_selected (); - for (size_t i=0; iget_text (sel[i])); + } return efs; } // Called within GTK UI thread -void FilterPanel::valueChanged () { +void FilterPanel::valueChanged () +{ - if (listener) - listener->exifFilterChanged (); + if (listener) { + listener->exifFilterChanged (); + } } diff --git a/rtgui/filterpanel.h b/rtgui/filterpanel.h index 3d2303b0c..f37695754 100644 --- a/rtgui/filterpanel.h +++ b/rtgui/filterpanel.h @@ -7,7 +7,7 @@ * 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 @@ -22,54 +22,62 @@ #include #include "exiffiltersettings.h" -class FilterPanelListener { +class FilterPanelListener +{ - public: - virtual void exifFilterChanged () {} +public: + virtual void exifFilterChanged () {} }; -class FilterPanel : public Gtk::VBox { +class FilterPanel : public Gtk::VBox +{ - protected: - Gtk::ListViewText* filetype; - Gtk::ListViewText* camera; - Gtk::ListViewText* lens; - Gtk::ListViewText* expcomp; - Gtk::Entry* fnumberFrom; - Gtk::Entry* fnumberTo; - Gtk::Entry* shutterFrom; - Gtk::Entry* shutterTo; - Gtk::Entry* focalFrom; - Gtk::Entry* focalTo; - Gtk::Entry* isoFrom; - Gtk::Entry* isoTo; - Gtk::CheckButton* enabled; - Gtk::CheckButton* enaFNumber; - Gtk::CheckButton* enaShutter; - Gtk::CheckButton* enaFocalLen; - Gtk::CheckButton* enaISO; - Gtk::CheckButton* enaExpComp; - Gtk::CheckButton* enaCamera; - Gtk::CheckButton* enaLens; - Gtk::CheckButton* enaFiletype; +protected: + Gtk::ListViewText* filetype; + Gtk::ListViewText* camera; + Gtk::ListViewText* lens; + Gtk::ListViewText* expcomp; + Gtk::Entry* fnumberFrom; + Gtk::Entry* fnumberTo; + Gtk::Entry* shutterFrom; + Gtk::Entry* shutterTo; + Gtk::Entry* focalFrom; + Gtk::Entry* focalTo; + Gtk::Entry* isoFrom; + Gtk::Entry* isoTo; + Gtk::CheckButton* enabled; + Gtk::CheckButton* enaFNumber; + Gtk::CheckButton* enaShutter; + Gtk::CheckButton* enaFocalLen; + Gtk::CheckButton* enaISO; + Gtk::CheckButton* enaExpComp; + Gtk::CheckButton* enaCamera; + Gtk::CheckButton* enaLens; + Gtk::CheckButton* enaFiletype; - int conns; - sigc::connection sChange[22]; + int conns; + sigc::connection sChange[22]; - ExifFilterSettings curefs; - FilterPanelListener* listener; + ExifFilterSettings curefs; + FilterPanelListener* listener; - public: - FilterPanel (); +public: + FilterPanel (); - void setFilterPanelListener (FilterPanelListener* l) { listener = l; } + void setFilterPanelListener (FilterPanelListener* l) + { + listener = l; + } - void setFilter (ExifFilterSettings& defefs, bool updateLists); - ExifFilterSettings getFilter (); - bool isEnabled (); + void setFilter (ExifFilterSettings& defefs, bool updateLists); + ExifFilterSettings getFilter (); + bool isEnabled (); - void valueChanged (); - void setEnabled(bool enabledState){enabled->set_active(enabledState);} + void valueChanged (); + void setEnabled(bool enabledState) + { + enabled->set_active(enabledState); + } }; #endif diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc index 31dca1bad..516bed44a 100644 --- a/rtgui/flatcurveeditorsubgroup.cc +++ b/rtgui/flatcurveeditorsubgroup.cc @@ -32,513 +32,588 @@ #include "curveeditor.h" #include "flatcurveeditorsubgroup.h" -FlatCurveEditorSubGroup::FlatCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) { +FlatCurveEditorSubGroup::FlatCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) +{ - valLinear = (int)FCT_Linear; - valUnchanged = (int)FCT_Unchanged; - parent = prt; + valLinear = (int)FCT_Linear; + valUnchanged = (int)FCT_Unchanged; + parent = prt; - curveBBoxPos = options.curvebboxpos; + curveBBoxPos = options.curvebboxpos; - // ControlPoints curve - CPointsCurveBox = new Gtk::VBox (); - CPointsCurveBox->set_spacing(4); - Gtk::HBox* CPointsCurveAndButtons = Gtk::manage (new Gtk::HBox ()); - CPointsCurveAndButtons->set_spacing(4); - CPointsCurve = Gtk::manage (new MyFlatCurve ()); - CPointsCurve->set_size_request (GRAPH_SIZE+2*RADIUS+1, GRAPH_SIZE+2*RADIUS+1); - CPointsCurve->setType (FCT_MinMaxCPoints); + // ControlPoints curve + CPointsCurveBox = new Gtk::VBox (); + CPointsCurveBox->set_spacing(4); + Gtk::HBox* CPointsCurveAndButtons = Gtk::manage (new Gtk::HBox ()); + CPointsCurveAndButtons->set_spacing(4); + CPointsCurve = Gtk::manage (new MyFlatCurve ()); + CPointsCurve->set_size_request (GRAPH_SIZE + 2 * RADIUS + 1, GRAPH_SIZE + 2 * RADIUS + 1); + CPointsCurve->setType (FCT_MinMaxCPoints); - Gtk::Box* CPointsbbox; // curvebboxpos 0=above, 1=right, 2=below, 3=left - if (options.curvebboxpos==1 || options.curvebboxpos==3) { - CPointsbbox = Gtk::manage (new Gtk::VBox ()); - } else { - CPointsbbox = Gtk::manage (new Gtk::HBox ()); - } - CPointsbbox->set_spacing(4); + Gtk::Box* CPointsbbox; // curvebboxpos 0=above, 1=right, 2=below, 3=left - pasteCPoints = Gtk::manage (new Gtk::Button ()); - pasteCPoints->add (*Gtk::manage (new RTImage ("edit-paste.png"))); - copyCPoints = Gtk::manage (new Gtk::Button ()); - copyCPoints->add (*Gtk::manage (new RTImage ("edit-copy.png"))); - saveCPoints = Gtk::manage (new Gtk::Button ()); - saveCPoints->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); - loadCPoints = Gtk::manage (new Gtk::Button ()); - loadCPoints->add (*Gtk::manage (new RTImage ("gtk-open.png"))); - editCPoints = Gtk::manage (new Gtk::ToggleButton()); - editPointCPoints = Gtk::manage (new Gtk::ToggleButton ()); - editPointCPoints->add (*Gtk::manage (new RTImage ("gtk-edit.png"))); - editPointCPoints->set_tooltip_text(M("CURVEEDITOR_EDITPOINT_HINT")); - editCPoints->add (*Gtk::manage (new RTImage ("editmodehand.png"))); - editCPoints->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); - editCPoints->hide(); + if (options.curvebboxpos == 1 || options.curvebboxpos == 3) { + CPointsbbox = Gtk::manage (new Gtk::VBox ()); + } else { + CPointsbbox = Gtk::manage (new Gtk::HBox ()); + } - CPointsbbox->pack_end (*pasteCPoints, Gtk::PACK_SHRINK, 0); - CPointsbbox->pack_end (*copyCPoints, Gtk::PACK_SHRINK, 0); - CPointsbbox->pack_end (*saveCPoints, Gtk::PACK_SHRINK, 0); - CPointsbbox->pack_end (*loadCPoints, Gtk::PACK_SHRINK, 0); - CPointsbbox->pack_start(*editPointCPoints, Gtk::PACK_SHRINK, 0); - CPointsbbox->pack_start(*editCPoints, Gtk::PACK_SHRINK, 0); + CPointsbbox->set_spacing(4); - CPointsCurveAndButtons->pack_start (*CPointsCurve, Gtk::PACK_EXPAND_WIDGET, 0); - CPointsCurveAndButtons->pack_start (*CPointsbbox, Gtk::PACK_SHRINK, 0); - CPointsCurveBox->pack_start (*CPointsCurveAndButtons, Gtk::PACK_EXPAND_WIDGET); - if (options.curvebboxpos==0) { - removeIfThere (CPointsCurveAndButtons, CPointsbbox, false); - CPointsCurveBox->pack_start (*CPointsbbox); - CPointsCurveBox->reorder_child(*CPointsbbox, 0); - } else if (options.curvebboxpos==2) { - removeIfThere (CPointsCurveAndButtons, CPointsbbox, false); - CPointsCurveBox->pack_start (*CPointsbbox); - } else if (options.curvebboxpos==3) { - CPointsCurveAndButtons->reorder_child(*CPointsbbox, 0); - } + pasteCPoints = Gtk::manage (new Gtk::Button ()); + pasteCPoints->add (*Gtk::manage (new RTImage ("edit-paste.png"))); + copyCPoints = Gtk::manage (new Gtk::Button ()); + copyCPoints->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + saveCPoints = Gtk::manage (new Gtk::Button ()); + saveCPoints->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); + loadCPoints = Gtk::manage (new Gtk::Button ()); + loadCPoints->add (*Gtk::manage (new RTImage ("gtk-open.png"))); + editCPoints = Gtk::manage (new Gtk::ToggleButton()); + editPointCPoints = Gtk::manage (new Gtk::ToggleButton ()); + editPointCPoints->add (*Gtk::manage (new RTImage ("gtk-edit.png"))); + editPointCPoints->set_tooltip_text(M("CURVEEDITOR_EDITPOINT_HINT")); + editCPoints->add (*Gtk::manage (new RTImage ("editmodehand.png"))); + editCPoints->set_tooltip_text(M("EDIT_PIPETTE_TOOLTIP")); + editCPoints->hide(); - { - std::vector axis; - axis.resize(4); - axis.at(0).setValues(M("CURVEEDITOR_AXIS_IN"), 5, 0.001, 0.01, 0., 1.); - axis.at(1).setValues(M("CURVEEDITOR_AXIS_OUT"), 5, 0.001, 0.01, 0., 1.); - axis.at(2).setValues(M("CURVEEDITOR_AXIS_LEFT_TAN"), 5, 0.01, 0.1, 0., 1.); - axis.at(3).setValues(M("CURVEEDITOR_AXIS_RIGHT_TAN"), 5, 0.01, 0.1, 0., 1.); - CPointsCoordAdjuster = Gtk::manage (new CoordinateAdjuster(CPointsCurve, this, axis)); - CPointsCurveBox->pack_start(*CPointsCoordAdjuster, Gtk::PACK_SHRINK, 0); - if (options.curvebboxpos == 2) - CPointsCurveBox->reorder_child(*CPointsCoordAdjuster, 2); - CPointsCoordAdjuster->show_all(); - } + CPointsbbox->pack_end (*pasteCPoints, Gtk::PACK_SHRINK, 0); + CPointsbbox->pack_end (*copyCPoints, Gtk::PACK_SHRINK, 0); + CPointsbbox->pack_end (*saveCPoints, Gtk::PACK_SHRINK, 0); + CPointsbbox->pack_end (*loadCPoints, Gtk::PACK_SHRINK, 0); + CPointsbbox->pack_start(*editPointCPoints, Gtk::PACK_SHRINK, 0); + CPointsbbox->pack_start(*editCPoints, Gtk::PACK_SHRINK, 0); - CPointsCurveBox->show_all (); - CPointsCoordAdjuster->hide(); + CPointsCurveAndButtons->pack_start (*CPointsCurve, Gtk::PACK_EXPAND_WIDGET, 0); + CPointsCurveAndButtons->pack_start (*CPointsbbox, Gtk::PACK_SHRINK, 0); + CPointsCurveBox->pack_start (*CPointsCurveAndButtons, Gtk::PACK_EXPAND_WIDGET); - saveCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::savePressed) ); - loadCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::loadPressed) ); - copyCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::copyPressed) ); - pasteCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::pastePressed) ); - editPointCPointsConn = editPointCPoints->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &FlatCurveEditorSubGroup::editPointToggled), editPointCPoints) ); - editCPointsConn = editCPoints->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &FlatCurveEditorSubGroup::editToggled), editCPoints) ); + if (options.curvebboxpos == 0) { + removeIfThere (CPointsCurveAndButtons, CPointsbbox, false); + CPointsCurveBox->pack_start (*CPointsbbox); + CPointsCurveBox->reorder_child(*CPointsbbox, 0); + } else if (options.curvebboxpos == 2) { + removeIfThere (CPointsCurveAndButtons, CPointsbbox, false); + CPointsCurveBox->pack_start (*CPointsbbox); + } else if (options.curvebboxpos == 3) { + CPointsCurveAndButtons->reorder_child(*CPointsbbox, 0); + } - saveCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); - loadCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); - copyCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); - pasteCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); + { + std::vector axis; + axis.resize(4); + axis.at(0).setValues(M("CURVEEDITOR_AXIS_IN"), 5, 0.001, 0.01, 0., 1.); + axis.at(1).setValues(M("CURVEEDITOR_AXIS_OUT"), 5, 0.001, 0.01, 0., 1.); + axis.at(2).setValues(M("CURVEEDITOR_AXIS_LEFT_TAN"), 5, 0.01, 0.1, 0., 1.); + axis.at(3).setValues(M("CURVEEDITOR_AXIS_RIGHT_TAN"), 5, 0.01, 0.1, 0., 1.); + CPointsCoordAdjuster = Gtk::manage (new CoordinateAdjuster(CPointsCurve, this, axis)); + CPointsCurveBox->pack_start(*CPointsCoordAdjuster, Gtk::PACK_SHRINK, 0); - CPointsCurve->setCurveListener (parent); // Send the message directly to the parent + if (options.curvebboxpos == 2) { + CPointsCurveBox->reorder_child(*CPointsCoordAdjuster, 2); + } + + CPointsCoordAdjuster->show_all(); + } + + CPointsCurveBox->show_all (); + CPointsCoordAdjuster->hide(); + + saveCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::savePressed) ); + loadCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::loadPressed) ); + copyCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::copyPressed) ); + pasteCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::pastePressed) ); + editPointCPointsConn = editPointCPoints->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &FlatCurveEditorSubGroup::editPointToggled), editPointCPoints) ); + editCPointsConn = editCPoints->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &FlatCurveEditorSubGroup::editToggled), editCPoints) ); + + saveCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE")); + loadCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD")); + copyCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY")); + pasteCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE")); + + CPointsCurve->setCurveListener (parent); // Send the message directly to the parent } -FlatCurveEditorSubGroup::~FlatCurveEditorSubGroup() { +FlatCurveEditorSubGroup::~FlatCurveEditorSubGroup() +{ delete CPointsCurveBox; } /* * Add a new curve to the curves list */ -FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel, bool isPeriodic) { - FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this, isPeriodic); +FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel, bool isPeriodic) +{ + FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this, isPeriodic); - // Initialization of the new curve - storeCurveValues(newCE, getCurveFromGUI(FCT_MinMaxCPoints)); - return newCE; + // Initialization of the new curve + storeCurveValues(newCE, getCurveFromGUI(FCT_MinMaxCPoints)); + return newCE; } -void FlatCurveEditorSubGroup::showCoordinateAdjuster(CoordinateProvider *provider) { - if (provider == CPointsCurve) { - if (!editPointCPoints->get_active()) editPointCPoints->set_active(true); - } +void FlatCurveEditorSubGroup::showCoordinateAdjuster(CoordinateProvider *provider) +{ + if (provider == CPointsCurve) { + if (!editPointCPoints->get_active()) { + editPointCPoints->set_active(true); + } + } } -void FlatCurveEditorSubGroup::stopNumericalAdjustment() { - CPointsCurve->stopNumericalAdjustment(); +void FlatCurveEditorSubGroup::stopNumericalAdjustment() +{ + CPointsCurve->stopNumericalAdjustment(); } /* * Force the resize of the curve editor, if the displayed one is the requested one */ -void FlatCurveEditorSubGroup::refresh(CurveEditor *curveToRefresh) { - if (curveToRefresh != NULL && curveToRefresh == static_cast(parent->displayedCurve)) { - switch(FlatCurveType(curveToRefresh->curveType->getSelected())) { - case (FCT_MinMaxCPoints): - CPointsCurve->refresh(); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } - } +void FlatCurveEditorSubGroup::refresh(CurveEditor *curveToRefresh) +{ + if (curveToRefresh != NULL && curveToRefresh == static_cast(parent->displayedCurve)) { + switch(FlatCurveType(curveToRefresh->curveType->getSelected())) { + case (FCT_MinMaxCPoints): + CPointsCurve->refresh(); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } + } } /* * Switch off the edit button */ -void FlatCurveEditorSubGroup::editModeSwitchedOff () { - // toggling off all edit buttons, even if only one is toggle on - bool prevState = editCPointsConn.block(true); - editCPoints->set_active(false); - CPointsCurve->pipetteMouseOver(NULL, NULL, 0); - CPointsCurve->setDirty(true); - if (!prevState) editCPointsConn.block(false); +void FlatCurveEditorSubGroup::editModeSwitchedOff () +{ + // toggling off all edit buttons, even if only one is toggle on + bool prevState = editCPointsConn.block(true); + editCPoints->set_active(false); + CPointsCurve->pipetteMouseOver(NULL, NULL, 0); + CPointsCurve->setDirty(true); + + if (!prevState) { + editCPointsConn.block(false); + } } -void FlatCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, int modifierKey) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((FlatCurveType)(curveEditor->curveType->getSelected())) { - case (FCT_MinMaxCPoints): - CPointsCurve->pipetteMouseOver(curveEditor, provider, modifierKey); - CPointsCurve->setDirty(true); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void FlatCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, int modifierKey) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((FlatCurveType)(curveEditor->curveType->getSelected())) { + case (FCT_MinMaxCPoints): + CPointsCurve->pipetteMouseOver(curveEditor, provider, modifierKey); + CPointsCurve->setDirty(true); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void FlatCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((FlatCurveType)(curveEditor->curveType->getSelected())) { - case (FCT_MinMaxCPoints): - CPointsCurve->pipetteButton1Pressed(provider, modifierKey); - CPointsCurve->setDirty(true); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void FlatCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((FlatCurveType)(curveEditor->curveType->getSelected())) { + case (FCT_MinMaxCPoints): + CPointsCurve->pipetteButton1Pressed(provider, modifierKey); + CPointsCurve->setDirty(true); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void FlatCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((FlatCurveType)(curveEditor->curveType->getSelected())) { - case (FCT_MinMaxCPoints): - CPointsCurve->pipetteButton1Released(provider); - CPointsCurve->setDirty(true); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void FlatCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((FlatCurveType)(curveEditor->curveType->getSelected())) { + case (FCT_MinMaxCPoints): + CPointsCurve->pipetteButton1Released(provider); + CPointsCurve->setDirty(true); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void FlatCurveEditorSubGroup::pipetteDrag(EditDataProvider *provider, int modifierKey) { - CurveEditor *curveEditor = static_cast(parent->displayedCurve); - switch((FlatCurveType)(curveEditor->curveType->getSelected())) { - case (FCT_MinMaxCPoints): - CPointsCurve->pipetteDrag(provider, modifierKey); - CPointsCurve->setDirty(true); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } +void FlatCurveEditorSubGroup::pipetteDrag(EditDataProvider *provider, int modifierKey) +{ + CurveEditor *curveEditor = static_cast(parent->displayedCurve); + + switch((FlatCurveType)(curveEditor->curveType->getSelected())) { + case (FCT_MinMaxCPoints): + CPointsCurve->pipetteDrag(provider, modifierKey); + CPointsCurve->setDirty(true); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } /* * Switch the editor widgets to the currently edited curve */ -void FlatCurveEditorSubGroup::switchGUI() { +void FlatCurveEditorSubGroup::switchGUI() +{ - removeEditor(); + removeEditor(); - FlatCurveEditor* dCurve = static_cast(parent->displayedCurve); + FlatCurveEditor* dCurve = static_cast(parent->displayedCurve); - if (dCurve) { + if (dCurve) { - // Initializing GUI values + repacking the appropriated widget - //dCurve->typeconn.block(true); + // Initializing GUI values + repacking the appropriated widget + //dCurve->typeconn.block(true); - // first we update the colored bar + // first we update the colored bar - ColorProvider *barColorProvider = dCurve->getLeftBarColorProvider(); - std::vector bgGradient = dCurve->getLeftBarBgGradient(); - if (barColorProvider == NULL && bgGradient.size() == 0) { - // dCurve has no left colored bar, so we delete the object - if (leftBar) { - delete leftBar; - leftBar = NULL; - } - } - else { - // dCurve has a ColorProvider or a background gradient defined, so we create/update the object - if (!leftBar) { - leftBar = new ColoredBar(RTO_Bottom2Top); - } - if (barColorProvider) { - bgGradient.clear(); - leftBar->setColorProvider(barColorProvider, dCurve->getLeftBarCallerId()); - leftBar->setBgGradient (bgGradient); - } - else { - leftBar->setColorProvider(NULL, -1); - leftBar->setBgGradient (bgGradient); - } - } + ColorProvider *barColorProvider = dCurve->getLeftBarColorProvider(); + std::vector bgGradient = dCurve->getLeftBarBgGradient(); - barColorProvider = dCurve->getBottomBarColorProvider(); - bgGradient = dCurve->getBottomBarBgGradient(); - if (barColorProvider == NULL && bgGradient.size() == 0) { - // dCurve has no bottom colored bar, so we delete the object - if (bottomBar) { - delete bottomBar; - bottomBar = NULL; - } - } - else { - // dCurve ave a ColorProvider or a background gradient defined, so we create/update the object - if (!bottomBar) { - bottomBar = new ColoredBar(RTO_Left2Right); - } - if (barColorProvider) { - bgGradient.clear(); - bottomBar->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId()); - bottomBar->setBgGradient (bgGradient); - } - else { - bottomBar->setColorProvider(NULL, -1); - bottomBar->setBgGradient (bgGradient); - } - } + if (barColorProvider == NULL && bgGradient.size() == 0) { + // dCurve has no left colored bar, so we delete the object + if (leftBar) { + delete leftBar; + leftBar = NULL; + } + } else { + // dCurve has a ColorProvider or a background gradient defined, so we create/update the object + if (!leftBar) { + leftBar = new ColoredBar(RTO_Bottom2Top); + } - switch((FlatCurveType)(dCurve->curveType->getSelected())) { - case (FCT_MinMaxCPoints): - CPointsCurve->setPeriodicity(dCurve->periodic); // Setting Periodicity before setting points - CPointsCurve->setPoints (dCurve->controlPointsCurveEd); - CPointsCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId()); - CPointsCurve->setColoredBar(leftBar, bottomBar); - CPointsCurve->forceResize(); - updateEditButton(dCurve, editCPoints, editCPointsConn); - parent->pack_start (*CPointsCurveBox); - CPointsCurveBox->check_resize(); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } + if (barColorProvider) { + bgGradient.clear(); + leftBar->setColorProvider(barColorProvider, dCurve->getLeftBarCallerId()); + leftBar->setBgGradient (bgGradient); + } else { + leftBar->setColorProvider(NULL, -1); + leftBar->setBgGradient (bgGradient); + } + } - //dCurve->typeconn.block(false); - } -} + barColorProvider = dCurve->getBottomBarColorProvider(); + bgGradient = dCurve->getBottomBarBgGradient(); -void FlatCurveEditorSubGroup::savePressed () { + if (barColorProvider == NULL && bgGradient.size() == 0) { + // dCurve has no bottom colored bar, so we delete the object + if (bottomBar) { + delete bottomBar; + bottomBar = NULL; + } + } else { + // dCurve ave a ColorProvider or a background gradient defined, so we create/update the object + if (!bottomBar) { + bottomBar = new ColoredBar(RTO_Left2Right); + } - Glib::ustring fname = outputFile(); - if (fname.size()) { - std::ofstream f (fname.c_str()); - std::vector p; - //std::vector p = customCurve->getPoints (); + if (barColorProvider) { + bgGradient.clear(); + bottomBar->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId()); + bottomBar->setBgGradient (bgGradient); + } else { + bottomBar->setColorProvider(NULL, -1); + bottomBar->setBgGradient (bgGradient); + } + } - switch (parent->displayedCurve->selected) { - case FCT_MinMaxCPoints: // Control points - p = CPointsCurve->getPoints (); - break; - default: - break; - } + switch((FlatCurveType)(dCurve->curveType->getSelected())) { + case (FCT_MinMaxCPoints): + CPointsCurve->setPeriodicity(dCurve->periodic); // Setting Periodicity before setting points + CPointsCurve->setPoints (dCurve->controlPointsCurveEd); + CPointsCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId()); + CPointsCurve->setColoredBar(leftBar, bottomBar); + CPointsCurve->forceResize(); + updateEditButton(dCurve, editCPoints, editCPointsConn); + parent->pack_start (*CPointsCurveBox); + CPointsCurveBox->check_resize(); + break; - int ix = 0; - if (p[ix]==(double)(FCT_Linear)) - f << "Linear" << std::endl; - else if (p[ix]==(double)(FCT_MinMaxCPoints)) - f << "ControlPoints" << std::endl; - ix++; - for (unsigned int i=0; i p; - std::string s; - f >> s; - if (s=="Linear") - p.push_back ((double)(FCT_Linear)); - else if (s=="ControlPoints") - p.push_back ((double)(FCT_MinMaxCPoints)); - else return; - double x; - while (f) { - f >> x; - if (f) - p.push_back (x); - } - if (p[0] == (double)(FCT_MinMaxCPoints)) { - CPointsCurve->setPoints (p); - CPointsCurve->queue_draw (); - CPointsCurve->notifyListener (); - } - } + //dCurve->typeconn.block(false); } } -void FlatCurveEditorSubGroup::copyPressed () { +void FlatCurveEditorSubGroup::savePressed () +{ + + Glib::ustring fname = outputFile(); + + if (fname.size()) { + std::ofstream f (fname.c_str()); + std::vector p; + //std::vector p = customCurve->getPoints (); + + switch (parent->displayedCurve->selected) { + case FCT_MinMaxCPoints: // Control points + p = CPointsCurve->getPoints (); + break; + + default: + break; + } + + int ix = 0; + + if (p[ix] == (double)(FCT_Linear)) { + f << "Linear" << std::endl; + } else if (p[ix] == (double)(FCT_MinMaxCPoints)) { + f << "ControlPoints" << std::endl; + } + + ix++; + + for (unsigned int i = 0; i < p.size() / 2; i++, ix += 2) { + f << p[ix] << ' ' << p[ix + 1] << std::endl; + } + + f.close (); + } +} + +void FlatCurveEditorSubGroup::loadPressed () +{ + + Glib::ustring fname = inputFile(); + + if (fname.size()) { + std::ifstream f (fname.c_str()); + + if (f) { + std::vector p; + std::string s; + f >> s; + + if (s == "Linear") { + p.push_back ((double)(FCT_Linear)); + } else if (s == "ControlPoints") { + p.push_back ((double)(FCT_MinMaxCPoints)); + } else { + return; + } + + double x; + + while (f) { + f >> x; + + if (f) { + p.push_back (x); + } + } + + if (p[0] == (double)(FCT_MinMaxCPoints)) { + CPointsCurve->setPoints (p); + CPointsCurve->queue_draw (); + CPointsCurve->notifyListener (); + } + } + } +} + +void FlatCurveEditorSubGroup::copyPressed () +{ // For compatibility use enum FlatCurveType here - std::vector curve; + std::vector curve; - switch (parent->displayedCurve->selected) { - case FCT_MinMaxCPoints: // custom - curve = CPointsCurve->getPoints (); - clipboard.setFlatCurveData (curve,FCT_MinMaxCPoints); - break; - default: // (DCT_Linear, DCT_Unchanged) - // ... do nothing - break; - } + switch (parent->displayedCurve->selected) { + case FCT_MinMaxCPoints: // custom + curve = CPointsCurve->getPoints (); + clipboard.setFlatCurveData (curve, FCT_MinMaxCPoints); + break; + + default: // (DCT_Linear, DCT_Unchanged) + // ... do nothing + break; + } } -void FlatCurveEditorSubGroup::pastePressed () { +void FlatCurveEditorSubGroup::pastePressed () +{ // For compatibility use enum FlatCurveType here - std::vector curve; - FlatCurveType type; + std::vector curve; + FlatCurveType type; - type = clipboard.hasFlatCurveData(); + type = clipboard.hasFlatCurveData(); - if (type == (FlatCurveType)parent->displayedCurve->selected) { - curve = clipboard.getFlatCurveData (); - switch (type) { - case FCT_MinMaxCPoints: // min/max control points - CPointsCurve->setPoints (curve); - CPointsCurve->queue_draw (); - CPointsCurve->notifyListener (); - break; - default: // (FCT_Linear, FCT_Unchanged) - // ... do nothing - break; - } - } - return; + if (type == (FlatCurveType)parent->displayedCurve->selected) { + curve = clipboard.getFlatCurveData (); + + switch (type) { + case FCT_MinMaxCPoints: // min/max control points + CPointsCurve->setPoints (curve); + CPointsCurve->queue_draw (); + CPointsCurve->notifyListener (); + break; + + default: // (FCT_Linear, FCT_Unchanged) + // ... do nothing + break; + } + } + + return; } -void FlatCurveEditorSubGroup::editPointToggled(Gtk::ToggleButton *button) { - if (button->get_active()) - CPointsCoordAdjuster->show(); - else { - CPointsCurve->stopNumericalAdjustment(); - CPointsCoordAdjuster->hide(); - } +void FlatCurveEditorSubGroup::editPointToggled(Gtk::ToggleButton *button) +{ + if (button->get_active()) { + CPointsCoordAdjuster->show(); + } else { + CPointsCurve->stopNumericalAdjustment(); + CPointsCoordAdjuster->hide(); + } } -void FlatCurveEditorSubGroup::editToggled (Gtk::ToggleButton *button) { - FlatCurveEditor* dCurve = static_cast(parent->displayedCurve); - if (!dCurve) - // should never happen! - return; +void FlatCurveEditorSubGroup::editToggled (Gtk::ToggleButton *button) +{ + FlatCurveEditor* dCurve = static_cast(parent->displayedCurve); - if (button->get_active()) { - dCurve->subscribe(); - CPointsCurve->notifyListener (); + if (!dCurve) + // should never happen! + { + return; + } - } - else { - dCurve->unsubscribe(); - } + if (button->get_active()) { + dCurve->subscribe(); + CPointsCurve->notifyListener (); + + } else { + dCurve->unsubscribe(); + } } /* * Store the curves of the currently displayed type from the widgets to the CurveEditor object */ -void FlatCurveEditorSubGroup::storeDisplayedCurve() { - if (parent->displayedCurve) { - switch (parent->displayedCurve->selected) { - /*case (FCT_Parametric): - storeCurveValues(parent->displayedCurve, getCurveFromGUI(FCT_Parametric)); - break;*/ - case (FCT_MinMaxCPoints): - storeCurveValues(parent->displayedCurve, getCurveFromGUI(FCT_MinMaxCPoints)); - break; - default: - break; - } - } +void FlatCurveEditorSubGroup::storeDisplayedCurve() +{ + if (parent->displayedCurve) { + switch (parent->displayedCurve->selected) { + /*case (FCT_Parametric): + storeCurveValues(parent->displayedCurve, getCurveFromGUI(FCT_Parametric)); + break;*/ + case (FCT_MinMaxCPoints): + storeCurveValues(parent->displayedCurve, getCurveFromGUI(FCT_MinMaxCPoints)); + break; + + default: + break; + } + } } /* * Restore the histogram to all types from the CurveEditor object to the widgets */ -void FlatCurveEditorSubGroup::restoreDisplayedHistogram() { - if (parent->displayedCurve) { - //paramCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); - CPointsCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); - } +void FlatCurveEditorSubGroup::restoreDisplayedHistogram() +{ + if (parent->displayedCurve) { + //paramCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); + CPointsCurve->updateBackgroundHistogram (parent->displayedCurve->histogram); + } } -void FlatCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector& p) { - if (!p.empty()) { - FlatCurveType t = static_cast(p[0]); +void FlatCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector& p) +{ + if (!p.empty()) { + FlatCurveType t = static_cast(p[0]); - switch (t) { - case (FCT_MinMaxCPoints): - static_cast(ce)->controlPointsCurveEd = p; - break; - default: - break; - } - } + switch (t) { + case (FCT_MinMaxCPoints): + static_cast(ce)->controlPointsCurveEd = p; + break; + + default: + break; + } + } } /* * Called to update the parametric curve graph with new slider values */ -const std::vector FlatCurveEditorSubGroup::getCurveFromGUI (int type) { - switch ((FlatCurveType)type) { - case (FCT_MinMaxCPoints): - return CPointsCurve->getPoints (); - default: { - // linear and other solutions - std::vector lcurve (1); - lcurve[0] = (double)(FCT_Linear); - return lcurve; - } - } +const std::vector FlatCurveEditorSubGroup::getCurveFromGUI (int type) +{ + switch ((FlatCurveType)type) { + case (FCT_MinMaxCPoints): + return CPointsCurve->getPoints (); + + default: { + // linear and other solutions + std::vector lcurve (1); + lcurve[0] = (double)(FCT_Linear); + return lcurve; + } + } } /* * Unlink the tree editor widgets from their parent box to hide them */ -void FlatCurveEditorSubGroup::removeEditor () { +void FlatCurveEditorSubGroup::removeEditor () +{ removeIfThere (parent, CPointsCurveBox, false); } -bool FlatCurveEditorSubGroup::curveReset(CurveEditor *ce) { - if (!ce) - return false; +bool FlatCurveEditorSubGroup::curveReset(CurveEditor *ce) +{ + if (!ce) { + return false; + } - FlatCurveEditor *fce = static_cast(ce); + FlatCurveEditor *fce = static_cast(ce); - switch (FlatCurveType(ce->selected)) { - case (FCT_MinMaxCPoints) : // = Control cage - CPointsCurve->reset (fce->controlPointsResetCurve, fce->getIdentityValue()); - return true; - break; - /*case (FCT_Parametric) : - highlights->resetPressed(); - lights->resetPressed(); - darks->resetPressed(); - shadows->resetPressed(); - shcSelector->reset(); - paramCurve->reset (); - return true; - break;*/ - default: - return false; - break; - } - return true; + switch (FlatCurveType(ce->selected)) { + case (FCT_MinMaxCPoints) : // = Control cage + CPointsCurve->reset (fce->controlPointsResetCurve, fce->getIdentityValue()); + return true; + break; + + /*case (FCT_Parametric) : + highlights->resetPressed(); + lights->resetPressed(); + darks->resetPressed(); + shadows->resetPressed(); + shcSelector->reset(); + paramCurve->reset (); + return true; + break;*/ + default: + return false; + break; + } + + return true; } /*void FlatCurveEditorSubGroup::updateBackgroundHistogram (CurveEditor* ce) { - CurveEditor* fce = (CurveEditor*)ce; - if (fce==displayedCurve) { - paramCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL); - customCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL); - NURBSCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL); - } + CurveEditor* fce = (CurveEditor*)ce; + if (fce==displayedCurve) { + paramCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL); + customCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL); + NURBSCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL); + } }*/ diff --git a/rtgui/flatcurveeditorsubgroup.h b/rtgui/flatcurveeditorsubgroup.h index a5b2c9cb5..8cd2a6d9a 100644 --- a/rtgui/flatcurveeditorsubgroup.h +++ b/rtgui/flatcurveeditorsubgroup.h @@ -24,55 +24,56 @@ class FlatCurveEditor; -class FlatCurveEditorSubGroup: public CurveEditorSubGroup { +class FlatCurveEditorSubGroup: public CurveEditorSubGroup +{ - friend class FlatCurveEditor; + friend class FlatCurveEditor; protected: - Gtk::VBox* CPointsCurveBox; + Gtk::VBox* CPointsCurveBox; - MyFlatCurve* CPointsCurve; + MyFlatCurve* CPointsCurve; - CoordinateAdjuster *CPointsCoordAdjuster; + CoordinateAdjuster *CPointsCoordAdjuster; - Gtk::Button* saveCPoints; - Gtk::Button* loadCPoints; - Gtk::Button* copyCPoints; - Gtk::Button* pasteCPoints; - Gtk::ToggleButton* editPointCPoints; - Gtk::ToggleButton* editCPoints; - sigc::connection editCPointsConn, editPointCPointsConn; + Gtk::Button* saveCPoints; + Gtk::Button* loadCPoints; + Gtk::Button* copyCPoints; + Gtk::Button* pasteCPoints; + Gtk::ToggleButton* editPointCPoints; + Gtk::ToggleButton* editCPoints; + sigc::connection editCPointsConn, editPointCPointsConn; public: - FlatCurveEditorSubGroup(CurveEditorGroup* prt, Glib::ustring& curveDir); - virtual ~FlatCurveEditorSubGroup(); + FlatCurveEditorSubGroup(CurveEditorGroup* prt, Glib::ustring& curveDir); + virtual ~FlatCurveEditorSubGroup(); - FlatCurveEditor* addCurve(Glib::ustring curveLabel = "", bool periodic = true); - //virtual void updateBackgroundHistogram (CurveEditor* ce); - void switchGUI(); - void refresh(CurveEditor *curveToRefresh); - void editModeSwitchedOff(); - void pipetteMouseOver(EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); - void pipetteButton1Released(EditDataProvider *provider); - void pipetteDrag(EditDataProvider *provider, int modifierKey); - void showCoordinateAdjuster(CoordinateProvider *provider); - void stopNumericalAdjustment(); + FlatCurveEditor* addCurve(Glib::ustring curveLabel = "", bool periodic = true); + //virtual void updateBackgroundHistogram (CurveEditor* ce); + void switchGUI(); + void refresh(CurveEditor *curveToRefresh); + void editModeSwitchedOff(); + void pipetteMouseOver(EditDataProvider *provider, int modifierKey); + void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + void pipetteButton1Released(EditDataProvider *provider); + void pipetteDrag(EditDataProvider *provider, int modifierKey); + void showCoordinateAdjuster(CoordinateProvider *provider); + void stopNumericalAdjustment(); - bool curveReset (CurveEditor *ce); + bool curveReset (CurveEditor *ce); protected: - void storeCurveValues (CurveEditor* ce, const std::vector& p); - void storeDisplayedCurve (); - void restoreDisplayedHistogram (); - void savePressed (); - void loadPressed (); - void copyPressed (); - void pastePressed (); - void removeEditor (); - const std::vector getCurveFromGUI (int type); - void editPointToggled(Gtk::ToggleButton *button); - void editToggled (Gtk::ToggleButton *button); + void storeCurveValues (CurveEditor* ce, const std::vector& p); + void storeDisplayedCurve (); + void restoreDisplayedHistogram (); + void savePressed (); + void loadPressed (); + void copyPressed (); + void pastePressed (); + void removeEditor (); + const std::vector getCurveFromGUI (int type); + void editPointToggled(Gtk::ToggleButton *button); + void editToggled (Gtk::ToggleButton *button); }; #endif diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 81f3421b6..0d346f8c1 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -28,353 +28,392 @@ using namespace rtengine::procparams; FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_LABEL")) { - hbff = Gtk::manage(new Gtk::HBox()); - hbff->set_spacing(2); - flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); - flatFieldFilePersister.reset(new FileChooserLastFolderPersister(flatFieldFile, options.lastFlatfieldDir)); - ffLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); - flatFieldFileReset = Gtk::manage(new Gtk::Button()); - flatFieldFileReset->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); - hbff->pack_start(*ffLabel, Gtk::PACK_SHRINK, 0); - hbff->pack_start(*flatFieldFile); - hbff->pack_start(*flatFieldFileReset, Gtk::PACK_SHRINK, 0); - flatFieldAutoSelect = Gtk::manage(new Gtk::CheckButton((M("TP_FLATFIELD_AUTOSELECT")))); - ffInfo = Gtk::manage(new Gtk::Label("")); - ffInfo->set_alignment(0,0); //left align - flatFieldBlurRadius = Gtk::manage(new Adjuster (M("TP_FLATFIELD_BLURRADIUS"),0,200,2,32)); - flatFieldBlurRadius->setAdjusterListener (this); - if (flatFieldBlurRadius->delay < 1000) flatFieldBlurRadius->delay = 1000; - flatFieldBlurRadius->show(); + hbff = Gtk::manage(new Gtk::HBox()); + hbff->set_spacing(2); + flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); + flatFieldFilePersister.reset(new FileChooserLastFolderPersister(flatFieldFile, options.lastFlatfieldDir)); + ffLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE"))); + flatFieldFileReset = Gtk::manage(new Gtk::Button()); + flatFieldFileReset->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); + hbff->pack_start(*ffLabel, Gtk::PACK_SHRINK, 0); + hbff->pack_start(*flatFieldFile); + hbff->pack_start(*flatFieldFileReset, Gtk::PACK_SHRINK, 0); + flatFieldAutoSelect = Gtk::manage(new Gtk::CheckButton((M("TP_FLATFIELD_AUTOSELECT")))); + ffInfo = Gtk::manage(new Gtk::Label("")); + ffInfo->set_alignment(0, 0); //left align + flatFieldBlurRadius = Gtk::manage(new Adjuster (M("TP_FLATFIELD_BLURRADIUS"), 0, 200, 2, 32)); + flatFieldBlurRadius->setAdjusterListener (this); - Gtk::HBox* hbffbt = Gtk::manage (new Gtk::HBox ()); - hbffbt->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_FLATFIELD_BLURTYPE") +":"))); - hbffbt->set_spacing(4); - flatFieldBlurType = Gtk::manage (new MyComboBoxText ()); - flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_AREA")); - flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_VERTICAL")); - flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_HORIZONTAL")); - flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_VERTHORIZ")); - flatFieldBlurType->set_active(0); - hbffbt->pack_end (*flatFieldBlurType); + if (flatFieldBlurRadius->delay < 1000) { + flatFieldBlurRadius->delay = 1000; + } - flatFieldClipControl = Gtk::manage (new Adjuster(M("TP_FLATFIELD_CLIPCONTROL"), 0., 100., 1., 0.)); - flatFieldClipControl->setAdjusterListener(this); - flatFieldClipControl->addAutoButton(""); - if (flatFieldClipControl->delay < 1000) flatFieldClipControl->delay = 1000; - flatFieldClipControl->show(); - flatFieldClipControl->set_tooltip_markup (M("TP_FLATFIELD_CLIPCONTROL_TOOLTIP")); + flatFieldBlurRadius->show(); - pack_start( *hbff, Gtk::PACK_SHRINK, 0); - pack_start( *flatFieldAutoSelect, Gtk::PACK_SHRINK, 0); - pack_start( *ffInfo, Gtk::PACK_SHRINK, 0); - pack_start( *hbffbt, Gtk::PACK_SHRINK, 0); - pack_start( *flatFieldBlurRadius, Gtk::PACK_SHRINK, 0); - pack_start( *flatFieldClipControl, Gtk::PACK_SHRINK, 0); + Gtk::HBox* hbffbt = Gtk::manage (new Gtk::HBox ()); + hbffbt->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_FLATFIELD_BLURTYPE") + ":"))); + hbffbt->set_spacing(4); + flatFieldBlurType = Gtk::manage (new MyComboBoxText ()); + flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_AREA")); + flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_VERTICAL")); + flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_HORIZONTAL")); + flatFieldBlurType->append_text(M("TP_FLATFIELD_BT_VERTHORIZ")); + flatFieldBlurType->set_active(0); + hbffbt->pack_end (*flatFieldBlurType); - flatFieldFileconn = flatFieldFile->signal_file_set().connect ( sigc::mem_fun(*this, &FlatField::flatFieldFileChanged), true); - flatFieldFileReset->signal_clicked().connect( sigc::mem_fun(*this, &FlatField::flatFieldFile_Reset), true ); - flatFieldAutoSelectconn = flatFieldAutoSelect->signal_toggled().connect ( sigc::mem_fun(*this, &FlatField::flatFieldAutoSelectChanged), true); - flatFieldBlurTypeconn = flatFieldBlurType->signal_changed().connect( sigc::mem_fun(*this, &FlatField::flatFieldBlurTypeChanged) ); - lastShortcutPath = ""; - - // Set filename filters - b_filter_asCurrent = false; - Gtk::FileFilter *filter_any = Gtk::manage(new Gtk::FileFilter); + flatFieldClipControl = Gtk::manage (new Adjuster(M("TP_FLATFIELD_CLIPCONTROL"), 0., 100., 1., 0.)); + flatFieldClipControl->setAdjusterListener(this); + flatFieldClipControl->addAutoButton(""); + + if (flatFieldClipControl->delay < 1000) { + flatFieldClipControl->delay = 1000; + } + + flatFieldClipControl->show(); + flatFieldClipControl->set_tooltip_markup (M("TP_FLATFIELD_CLIPCONTROL_TOOLTIP")); + + pack_start( *hbff, Gtk::PACK_SHRINK, 0); + pack_start( *flatFieldAutoSelect, Gtk::PACK_SHRINK, 0); + pack_start( *ffInfo, Gtk::PACK_SHRINK, 0); + pack_start( *hbffbt, Gtk::PACK_SHRINK, 0); + pack_start( *flatFieldBlurRadius, Gtk::PACK_SHRINK, 0); + pack_start( *flatFieldClipControl, Gtk::PACK_SHRINK, 0); + + flatFieldFileconn = flatFieldFile->signal_file_set().connect ( sigc::mem_fun(*this, &FlatField::flatFieldFileChanged), true); + flatFieldFileReset->signal_clicked().connect( sigc::mem_fun(*this, &FlatField::flatFieldFile_Reset), true ); + flatFieldAutoSelectconn = flatFieldAutoSelect->signal_toggled().connect ( sigc::mem_fun(*this, &FlatField::flatFieldAutoSelectChanged), true); + flatFieldBlurTypeconn = flatFieldBlurType->signal_changed().connect( sigc::mem_fun(*this, &FlatField::flatFieldBlurTypeChanged) ); + lastShortcutPath = ""; + + // Set filename filters + b_filter_asCurrent = false; + Gtk::FileFilter *filter_any = Gtk::manage(new Gtk::FileFilter); filter_any->add_pattern("*"); filter_any->set_name(M("FILECHOOSER_FILTER_ANY")); flatFieldFile->add_filter (*filter_any); - - // filters for all supported non-raw extensions - for (size_t i=0; iadd_pattern("*." + options.parseExtensions[i]); - filter_ff->add_pattern("*." + options.parseExtensions[i].uppercase()); - filter_ff->set_name(options.parseExtensions[i].uppercase()); - flatFieldFile->add_filter (*filter_ff); - //printf("adding filter %s \n",options.parseExtensions[i].uppercase().c_str()); + + // filters for all supported non-raw extensions + for (size_t i = 0; i < options.parseExtensions.size(); i++) { + if (options.parseExtensionsEnabled[i] && options.parseExtensions[i].uppercase() != "JPG" && options.parseExtensions[i].uppercase() != "JPEG" && options.parseExtensions[i].uppercase() != "PNG" && options.parseExtensions[i].uppercase() != "TIF" && options.parseExtensions[i].uppercase() != "TIFF" ) { + Gtk::FileFilter *filter_ff = Gtk::manage(new Gtk::FileFilter); + filter_ff->add_pattern("*." + options.parseExtensions[i]); + filter_ff->add_pattern("*." + options.parseExtensions[i].uppercase()); + filter_ff->set_name(options.parseExtensions[i].uppercase()); + flatFieldFile->add_filter (*filter_ff); + //printf("adding filter %s \n",options.parseExtensions[i].uppercase().c_str()); } } } void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - flatFieldAutoSelectconn.block (true); - flatFieldBlurTypeconn.block (true); + disableListener (); + flatFieldAutoSelectconn.block (true); + flatFieldBlurTypeconn.block (true); - //flatFieldBlurType - for( size_t i=0; i< procparams::RAWParams::numFlatFileBlurTypes;i++) - if( pp->raw.ff_BlurType == procparams::RAWParams::ff_BlurTypestring[i]){ - flatFieldBlurType->set_active(i); - break; - } + //flatFieldBlurType + for( size_t i = 0; i < procparams::RAWParams::numFlatFileBlurTypes; i++) + if( pp->raw.ff_BlurType == procparams::RAWParams::ff_BlurTypestring[i]) { + flatFieldBlurType->set_active(i); + break; + } - if (multiImage || pp->raw.ff_BlurType == procparams::RAWParams::ff_BlurTypestring[procparams::RAWParams::area_ff]) - flatFieldClipControl->show(); - else - flatFieldClipControl->hide(); + if (multiImage || pp->raw.ff_BlurType == procparams::RAWParams::ff_BlurTypestring[procparams::RAWParams::area_ff]) { + flatFieldClipControl->show(); + } else { + flatFieldClipControl->hide(); + } - flatFieldAutoSelect->set_active (pp->raw.ff_AutoSelect); - flatFieldBlurRadius->setValue (pp->raw.ff_BlurRadius); - flatFieldClipControl->setValue (pp->raw.ff_clipControl); - flatFieldClipControl->setAutoValue (pp->raw.ff_AutoClipControl); + flatFieldAutoSelect->set_active (pp->raw.ff_AutoSelect); + flatFieldBlurRadius->setValue (pp->raw.ff_BlurRadius); + flatFieldClipControl->setValue (pp->raw.ff_clipControl); + flatFieldClipControl->setAutoValue (pp->raw.ff_AutoClipControl); - if(pedited ){ - flatFieldAutoSelect->set_inconsistent (!pedited->raw.ff_AutoSelect); - flatFieldBlurRadius->setEditedState( pedited->raw.ff_BlurRadius ? Edited : UnEdited ); - flatFieldClipControl->setEditedState( pedited->raw.ff_clipControl ? Edited : UnEdited ); - flatFieldClipControl->setAutoInconsistent(multiImage && !pedited->raw.ff_AutoClipControl); - if( !pedited->raw.ff_BlurType ) - flatFieldBlurType->set_active(procparams::RAWParams::numFlatFileBlurTypes); // No name - } - if (safe_file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) - flatFieldFile->set_filename (pp->raw.ff_file); - else - flatFieldFile_Reset(); - hbff->set_sensitive( !pp->raw.ff_AutoSelect ); + if(pedited ) { + flatFieldAutoSelect->set_inconsistent (!pedited->raw.ff_AutoSelect); + flatFieldBlurRadius->setEditedState( pedited->raw.ff_BlurRadius ? Edited : UnEdited ); + flatFieldClipControl->setEditedState( pedited->raw.ff_clipControl ? Edited : UnEdited ); + flatFieldClipControl->setAutoInconsistent(multiImage && !pedited->raw.ff_AutoClipControl); - lastFFAutoSelect = pp->raw.ff_AutoSelect; - lastFFAutoClipCtrl = pp->raw.ff_AutoClipControl; + if( !pedited->raw.ff_BlurType ) { + flatFieldBlurType->set_active(procparams::RAWParams::numFlatFileBlurTypes); // No name + } + } - if( pp->raw.ff_AutoSelect && ffp && !batchMode){ - // retrieve the auto-selected ff filename - rtengine::RawImage *img = ffp->getFF(); - if( img ){ - ffInfo->set_text( Glib::ustring::compose("%1: f/%2", Glib::path_get_basename(img->get_filename()), img->get_aperture()) ); // !!! need to add focallength in mm and format aperture to ##.# - }else{ - ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); - } - } - else ffInfo->set_text(""); + if (safe_file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) { + flatFieldFile->set_filename (pp->raw.ff_file); + } else { + flatFieldFile_Reset(); + } - ffChanged = false; + hbff->set_sensitive( !pp->raw.ff_AutoSelect ); - flatFieldAutoSelectconn.block (false); - flatFieldBlurTypeconn.block (false); - enableListener (); - - // Add filter with the current file extension if the current file is raw - if (ffp && !batchMode){ - - if (b_filter_asCurrent){ - //First, remove last filter_asCurrent if it was set for a raw file - std::vector filters = flatFieldFile->list_filters(); - flatFieldFile->remove_filter(**(filters.end()-1)); - b_filter_asCurrent = false; - } + lastFFAutoSelect = pp->raw.ff_AutoSelect; + lastFFAutoClipCtrl = pp->raw.ff_AutoClipControl; - Glib::ustring fname = Glib::path_get_basename(ffp->GetCurrentImageFilePath()); - Glib::ustring filetype; + if( pp->raw.ff_AutoSelect && ffp && !batchMode) { + // retrieve the auto-selected ff filename + rtengine::RawImage *img = ffp->getFF(); - if (fname!=""){ - // get image filetype, set filter to the same as current image's filetype - std::string::size_type idx; - idx = fname.rfind('.'); - if(idx != std::string::npos){ - filetype = fname.substr(idx+1); - //exclude non-raw - israw = filetype.uppercase()!="JPG" && filetype.uppercase()!="JPEG" && filetype.uppercase()!="PNG" && filetype.uppercase()!="TIF" && filetype.uppercase()!="TIFF"; + if( img ) { + ffInfo->set_text( Glib::ustring::compose("%1: f/%2", Glib::path_get_basename(img->get_filename()), img->get_aperture()) ); // !!! need to add focallength in mm and format aperture to ##.# + } else { + ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); + } + } else { + ffInfo->set_text(""); + } - if (israw) - { - b_filter_asCurrent = true; //prevent re-adding this filter on every pp3 file read - Gtk::FileFilter *filter_asCurrent = Gtk::manage(new Gtk::FileFilter); - filter_asCurrent->add_pattern("*." + filetype); - filter_asCurrent->set_name(M("FILECHOOSER_FILTER_SAME") + " (" + filetype + ")"); - flatFieldFile->add_filter (*filter_asCurrent); - flatFieldFile->set_filter (*filter_asCurrent); - } - } - } - } + ffChanged = false; + + flatFieldAutoSelectconn.block (false); + flatFieldBlurTypeconn.block (false); + enableListener (); + + // Add filter with the current file extension if the current file is raw + if (ffp && !batchMode) { + + if (b_filter_asCurrent) { + //First, remove last filter_asCurrent if it was set for a raw file + std::vector filters = flatFieldFile->list_filters(); + flatFieldFile->remove_filter(**(filters.end() - 1)); + b_filter_asCurrent = false; + } + + Glib::ustring fname = Glib::path_get_basename(ffp->GetCurrentImageFilePath()); + Glib::ustring filetype; + + if (fname != "") { + // get image filetype, set filter to the same as current image's filetype + std::string::size_type idx; + idx = fname.rfind('.'); + + if(idx != std::string::npos) { + filetype = fname.substr(idx + 1); + //exclude non-raw + israw = filetype.uppercase() != "JPG" && filetype.uppercase() != "JPEG" && filetype.uppercase() != "PNG" && filetype.uppercase() != "TIF" && filetype.uppercase() != "TIFF"; + + if (israw) { + b_filter_asCurrent = true; //prevent re-adding this filter on every pp3 file read + Gtk::FileFilter *filter_asCurrent = Gtk::manage(new Gtk::FileFilter); + filter_asCurrent->add_pattern("*." + filetype); + filter_asCurrent->set_name(M("FILECHOOSER_FILTER_SAME") + " (" + filetype + ")"); + flatFieldFile->add_filter (*filter_asCurrent); + flatFieldFile->set_filter (*filter_asCurrent); + } + } + } + } } void FlatField::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.ff_file = flatFieldFile->get_filename(); - pp->raw.ff_AutoSelect = flatFieldAutoSelect->get_active(); - pp->raw.ff_BlurRadius = flatFieldBlurRadius->getIntValue(); - pp->raw.ff_clipControl = flatFieldClipControl->getIntValue(); - pp->raw.ff_AutoClipControl = flatFieldClipControl->getAutoValue(); + pp->raw.ff_file = flatFieldFile->get_filename(); + pp->raw.ff_AutoSelect = flatFieldAutoSelect->get_active(); + pp->raw.ff_BlurRadius = flatFieldBlurRadius->getIntValue(); + pp->raw.ff_clipControl = flatFieldClipControl->getIntValue(); + pp->raw.ff_AutoClipControl = flatFieldClipControl->getAutoValue(); - int currentRow = flatFieldBlurType->get_active_row_number(); - if( currentRow>=0 && currentRow < procparams::RAWParams::numFlatFileBlurTypes) - pp->raw.ff_BlurType = procparams::RAWParams::ff_BlurTypestring[currentRow]; + int currentRow = flatFieldBlurType->get_active_row_number(); - if (pedited) { - pedited->raw.ff_file = ffChanged; - pedited->raw.ff_AutoSelect = !flatFieldAutoSelect->get_inconsistent(); - pedited->raw.ff_BlurRadius = flatFieldBlurRadius->getEditedState (); - pedited->raw.ff_clipControl = flatFieldClipControl->getEditedState (); - pedited->raw.ff_AutoClipControl = !flatFieldClipControl->getAutoInconsistent(); - pedited->raw.ff_BlurType = flatFieldBlurType->get_active_row_number() != procparams::RAWParams::numFlatFileBlurTypes; - } + if( currentRow >= 0 && currentRow < procparams::RAWParams::numFlatFileBlurTypes) { + pp->raw.ff_BlurType = procparams::RAWParams::ff_BlurTypestring[currentRow]; + } + + if (pedited) { + pedited->raw.ff_file = ffChanged; + pedited->raw.ff_AutoSelect = !flatFieldAutoSelect->get_inconsistent(); + pedited->raw.ff_BlurRadius = flatFieldBlurRadius->getEditedState (); + pedited->raw.ff_clipControl = flatFieldClipControl->getEditedState (); + pedited->raw.ff_AutoClipControl = !flatFieldClipControl->getAutoInconsistent(); + pedited->raw.ff_BlurType = flatFieldBlurType->get_active_row_number() != procparams::RAWParams::numFlatFileBlurTypes; + } } void FlatField::adjusterChanged (Adjuster* a, double newval) { - if (listener) { + if (listener) { - Glib::ustring value = a->getTextValue(); + Glib::ustring value = a->getTextValue(); - if (a==flatFieldBlurRadius) - listener->panelChanged (EvFlatFieldBlurRadius, value); - else if (a==flatFieldClipControl) - listener->panelChanged (EvFlatFieldClipControl, value); - } + if (a == flatFieldBlurRadius) { + listener->panelChanged (EvFlatFieldBlurRadius, value); + } else if (a == flatFieldClipControl) { + listener->panelChanged (EvFlatFieldClipControl, value); + } + } } -void FlatField::adjusterAutoToggled (Adjuster* a, bool newval) { +void FlatField::adjusterAutoToggled (Adjuster* a, bool newval) +{ - if (multiImage) { - if (flatFieldClipControl->getAutoInconsistent()) { - flatFieldClipControl->setAutoInconsistent(false); - flatFieldClipControl->setAutoValue(false); - } - else if (lastFFAutoClipCtrl) - flatFieldClipControl->setAutoInconsistent(true); + if (multiImage) { + if (flatFieldClipControl->getAutoInconsistent()) { + flatFieldClipControl->setAutoInconsistent(false); + flatFieldClipControl->setAutoValue(false); + } else if (lastFFAutoClipCtrl) { + flatFieldClipControl->setAutoInconsistent(true); + } - lastFFAutoClipCtrl = flatFieldClipControl->getAutoValue(); + lastFFAutoClipCtrl = flatFieldClipControl->getAutoValue(); - } + } - if (listener) { - if(a==flatFieldClipControl) { - if (flatFieldClipControl->getAutoInconsistent()) - listener->panelChanged (EvFlatFieldAutoClipControl, M("GENERAL_UNCHANGED")); - else if (flatFieldClipControl->getAutoValue()) - listener->panelChanged (EvFlatFieldAutoClipControl, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvFlatFieldAutoClipControl, M("GENERAL_DISABLED")); - } - } + if (listener) { + if(a == flatFieldClipControl) { + if (flatFieldClipControl->getAutoInconsistent()) { + listener->panelChanged (EvFlatFieldAutoClipControl, M("GENERAL_UNCHANGED")); + } else if (flatFieldClipControl->getAutoValue()) { + listener->panelChanged (EvFlatFieldAutoClipControl, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvFlatFieldAutoClipControl, M("GENERAL_DISABLED")); + } + } + } } void FlatField::setBatchMode(bool batchMode) { - ToolPanel::setBatchMode (batchMode); - flatFieldBlurRadius->showEditedCB (); - flatFieldClipControl->showEditedCB (); + ToolPanel::setBatchMode (batchMode); + flatFieldBlurRadius->showEditedCB (); + flatFieldClipControl->showEditedCB (); } -void FlatField::setAdjusterBehavior (bool clipctrladd) { - flatFieldClipControl->setAddMode(clipctrladd); +void FlatField::setAdjusterBehavior (bool clipctrladd) +{ + flatFieldClipControl->setAddMode(clipctrladd); } -void FlatField::trimValues (rtengine::procparams::ProcParams* pp) { - flatFieldClipControl->trimValue(pp->raw.ff_clipControl); +void FlatField::trimValues (rtengine::procparams::ProcParams* pp) +{ + flatFieldClipControl->trimValue(pp->raw.ff_clipControl); } void FlatField::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - flatFieldBlurRadius->setDefault( defParams->raw.ff_BlurRadius); - flatFieldClipControl->setDefault( defParams->raw.ff_clipControl); + flatFieldBlurRadius->setDefault( defParams->raw.ff_BlurRadius); + flatFieldClipControl->setDefault( defParams->raw.ff_clipControl); - if (pedited) { - flatFieldBlurRadius->setDefaultEditedState( pedited->raw.ff_BlurRadius ? Edited : UnEdited); - flatFieldClipControl->setDefaultEditedState( pedited->raw.ff_clipControl ? Edited : UnEdited); - } else { - flatFieldBlurRadius->setDefaultEditedState( Irrelevant ); - flatFieldClipControl->setDefaultEditedState( Irrelevant ); - } + if (pedited) { + flatFieldBlurRadius->setDefaultEditedState( pedited->raw.ff_BlurRadius ? Edited : UnEdited); + flatFieldClipControl->setDefaultEditedState( pedited->raw.ff_clipControl ? Edited : UnEdited); + } else { + flatFieldBlurRadius->setDefaultEditedState( Irrelevant ); + flatFieldClipControl->setDefaultEditedState( Irrelevant ); + } } void FlatField::flatFieldFileChanged() { - ffChanged=true; - if (listener) + ffChanged = true; + + if (listener) { listener->panelChanged (EvFlatFieldFile, Glib::path_get_basename(flatFieldFile->get_filename())); + } } void FlatField::flatFieldFile_Reset() { - ffChanged=true; + ffChanged = true; // caution: I had to make this hack, because set_current_folder() doesn't work correctly! // Because szeva doesn't exist since he was committed to happy hunting ground in Issue 316 // we can use him now for this hack - flatFieldFile->set_filename (options.lastFlatfieldDir + "/szeva"); + flatFieldFile->set_filename (options.lastFlatfieldDir + "/szeva"); // end of the hack - if (!options.lastFlatfieldDir.empty()) - flatFieldFile->set_current_folder(options.lastFlatfieldDir); + if (!options.lastFlatfieldDir.empty()) { + flatFieldFile->set_current_folder(options.lastFlatfieldDir); + } - ffInfo->set_text(""); - if (listener) + ffInfo->set_text(""); + + if (listener) { listener->panelChanged (EvFlatFieldFile, M("GENERAL_NONE") ); + } } void FlatField::flatFieldBlurTypeChanged () { - int curSelection = flatFieldBlurType->get_active_row_number(); + int curSelection = flatFieldBlurType->get_active_row_number(); - Glib::ustring s=""; - if( curSelection>=0 && curSelection < procparams::RAWParams::numFlatFileBlurTypes) - s = flatFieldBlurType->get_active_text(); + Glib::ustring s = ""; - if (multiImage || curSelection == procparams::RAWParams::area_ff) - flatFieldClipControl->show(); - else - flatFieldClipControl->hide(); + if( curSelection >= 0 && curSelection < procparams::RAWParams::numFlatFileBlurTypes) { + s = flatFieldBlurType->get_active_text(); + } - if (listener) + if (multiImage || curSelection == procparams::RAWParams::area_ff) { + flatFieldClipControl->show(); + } else { + flatFieldClipControl->hide(); + } + + if (listener) { listener->panelChanged (EvFlatFieldBlurType, s); + } } void FlatField::flatFieldAutoSelectChanged() { if (batchMode) { if (flatFieldAutoSelect->get_inconsistent()) { - flatFieldAutoSelect->set_inconsistent (false); - flatFieldAutoSelectconn.block (true); - flatFieldAutoSelect->set_active (false); - flatFieldAutoSelectconn.block (false); + flatFieldAutoSelect->set_inconsistent (false); + flatFieldAutoSelectconn.block (true); + flatFieldAutoSelect->set_active (false); + flatFieldAutoSelectconn.block (false); + } else if (lastFFAutoSelect) { + flatFieldAutoSelect->set_inconsistent (true); } - else if (lastFFAutoSelect) - flatFieldAutoSelect->set_inconsistent (true); lastFFAutoSelect = flatFieldAutoSelect->get_active (); } - hbff->set_sensitive( !flatFieldAutoSelect->get_active() ); - if( flatFieldAutoSelect->get_active() && ffp && !batchMode){ - // retrieve the auto-selected ff filename - rtengine::RawImage *img = ffp->getFF(); - if( img ){ - ffInfo->set_text( Glib::ustring::compose("%1: f/%2", Glib::path_get_basename(img->get_filename()), img->get_aperture()) ); // !!! need to add focallength in mm and format aperture to ##.# - }else{ - ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); - } + hbff->set_sensitive( !flatFieldAutoSelect->get_active() ); + + if( flatFieldAutoSelect->get_active() && ffp && !batchMode) { + // retrieve the auto-selected ff filename + rtengine::RawImage *img = ffp->getFF(); + + if( img ) { + ffInfo->set_text( Glib::ustring::compose("%1: f/%2", Glib::path_get_basename(img->get_filename()), img->get_aperture()) ); // !!! need to add focallength in mm and format aperture to ##.# + } else { + ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND"))); + } + } else { + ffInfo->set_text(""); } - else{ffInfo->set_text("");} - if (listener) - listener->panelChanged (EvFlatFieldAutoSelect, flatFieldAutoSelect->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + if (listener) { + listener->panelChanged (EvFlatFieldAutoSelect, flatFieldAutoSelect->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } void FlatField::setShortcutPath(Glib::ustring path) { - if (path == "") return; + if (path == "") { + return; + } + #ifdef WIN32 - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(path)) + + // 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) {} - } - lastShortcutPath = path; - try { - flatFieldFile->add_shortcut_folder(path); - } - catch (Glib::Error &err) {} - } + { + if (lastShortcutPath != "") { + try { + flatFieldFile->remove_shortcut_folder(lastShortcutPath); + } catch (Glib::Error &err) {} + } + + lastShortcutPath = path; + + try { + flatFieldFile->add_shortcut_folder(path); + } catch (Glib::Error &err) {} + } } diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index a37e93d76..c760433ec 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -26,47 +26,49 @@ #include "../rtengine/rawimage.h" #include "guiutils.h" -class FFProvider { - public: +class FFProvider +{ +public: virtual ~FFProvider() {} virtual rtengine::RawImage* getFF() = 0; virtual Glib::ustring GetCurrentImageFilePath() = 0; // add other info here }; -class FlatField : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class FlatField : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - MyFileChooserButton *flatFieldFile; - std::auto_ptr flatFieldFilePersister; - Gtk::Label *ffLabel; - Gtk::Label *ffInfo; - Gtk::Button *flatFieldFileReset; - Gtk::CheckButton* flatFieldAutoSelect; - Adjuster* flatFieldClipControl; - Adjuster* flatFieldBlurRadius; - MyComboBoxText* flatFieldBlurType; - Gtk::HBox *hbff; - bool ffChanged; - bool lastFFAutoSelect; - bool lastFFAutoClipCtrl; - FFProvider *ffp; - sigc::connection flatFieldFileconn, flatFieldAutoSelectconn, flatFieldBlurTypeconn; + MyFileChooserButton *flatFieldFile; + std::auto_ptr flatFieldFilePersister; + Gtk::Label *ffLabel; + Gtk::Label *ffInfo; + Gtk::Button *flatFieldFileReset; + Gtk::CheckButton* flatFieldAutoSelect; + Adjuster* flatFieldClipControl; + Adjuster* flatFieldBlurRadius; + MyComboBoxText* flatFieldBlurType; + Gtk::HBox *hbff; + bool ffChanged; + bool lastFFAutoSelect; + bool lastFFAutoClipCtrl; + FFProvider *ffp; + sigc::connection flatFieldFileconn, flatFieldAutoSelectconn, flatFieldBlurTypeconn; Glib::ustring lastShortcutPath; bool b_filter_asCurrent; bool israw; public: - FlatField (); + FlatField (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void setAdjusterBehavior (bool clipctrladd); void trimValues (rtengine::procparams::ProcParams* pp); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void adjusterChanged (Adjuster* a, double newval); void adjusterAutoToggled (Adjuster* a, bool newval); @@ -75,7 +77,10 @@ public: void flatFieldAutoSelectChanged (); void flatFieldBlurTypeChanged (); void setShortcutPath(Glib::ustring path); - void setFFProvider (FFProvider* p) { ffp = p; }; + void setFFProvider (FFProvider* p) + { + ffp = p; + }; }; #endif diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index b9d8ffe12..6d61dd840 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -11,499 +11,591 @@ using namespace rtengine::procparams; Gradient::Gradient () : FoldableToolPanel(this, "gradient", M("TP_GRADIENT_LABEL"), false, true), EditSubscriber(ET_OBJECTS), lastObject(-1), draggedPointOldAngle(-1000.) { - editHBox = Gtk::manage (new Gtk::HBox()); - edit = Gtk::manage (new Gtk::ToggleButton()); - edit->add (*Gtk::manage (new RTImage ("editmodehand.png"))); - edit->set_tooltip_text(M("EDIT_OBJECT_TOOLTIP")); - editConn = edit->signal_toggled().connect( sigc::mem_fun(*this, &Gradient::editToggled) ); - editHBox->pack_start(*edit, Gtk::PACK_SHRINK, 0); - pack_start (*editHBox, Gtk::PACK_SHRINK, 0); + editHBox = Gtk::manage (new Gtk::HBox()); + edit = Gtk::manage (new Gtk::ToggleButton()); + edit->add (*Gtk::manage (new RTImage ("editmodehand.png"))); + edit->set_tooltip_text(M("EDIT_OBJECT_TOOLTIP")); + editConn = edit->signal_toggled().connect( sigc::mem_fun(*this, &Gradient::editToggled) ); + editHBox->pack_start(*edit, Gtk::PACK_SHRINK, 0); + pack_start (*editHBox, Gtk::PACK_SHRINK, 0); - strength = Gtk::manage (new Adjuster (M("TP_GRADIENT_STRENGTH"), -5, 5, 0.01, 0)); - strength->set_tooltip_text (M("TP_GRADIENT_STRENGTH_TOOLTIP")); - strength->setAdjusterListener (this); + strength = Gtk::manage (new Adjuster (M("TP_GRADIENT_STRENGTH"), -5, 5, 0.01, 0)); + strength->set_tooltip_text (M("TP_GRADIENT_STRENGTH_TOOLTIP")); + strength->setAdjusterListener (this); - degree = Gtk::manage (new Adjuster (M("TP_GRADIENT_DEGREE"), -180, 180, 1, 0)); - degree->set_tooltip_text (M("TP_GRADIENT_DEGREE_TOOLTIP")); - degree->setAdjusterListener (this); + degree = Gtk::manage (new Adjuster (M("TP_GRADIENT_DEGREE"), -180, 180, 1, 0)); + degree->set_tooltip_text (M("TP_GRADIENT_DEGREE_TOOLTIP")); + degree->setAdjusterListener (this); - feather = Gtk::manage (new Adjuster (M("TP_GRADIENT_FEATHER"), 0, 100, 1, 25)); - feather->set_tooltip_text (M("TP_GRADIENT_FEATHER_TOOLTIP")); - feather->setAdjusterListener (this); + feather = Gtk::manage (new Adjuster (M("TP_GRADIENT_FEATHER"), 0, 100, 1, 25)); + feather->set_tooltip_text (M("TP_GRADIENT_FEATHER_TOOLTIP")); + feather->setAdjusterListener (this); - centerX = Gtk::manage (new Adjuster (M("TP_GRADIENT_CENTER_X"), -100, 100, 1, 0)); - centerX->set_tooltip_text (M("TP_GRADIENT_CENTER_X_TOOLTIP")); - centerX->setAdjusterListener (this); + centerX = Gtk::manage (new Adjuster (M("TP_GRADIENT_CENTER_X"), -100, 100, 1, 0)); + centerX->set_tooltip_text (M("TP_GRADIENT_CENTER_X_TOOLTIP")); + centerX->setAdjusterListener (this); - centerY = Gtk::manage (new Adjuster (M("TP_GRADIENT_CENTER_Y"), -100, 100, 1, 0)); - centerY->set_tooltip_text (M("TP_GRADIENT_CENTER_Y_TOOLTIP")); - centerY->setAdjusterListener (this); + centerY = Gtk::manage (new Adjuster (M("TP_GRADIENT_CENTER_Y"), -100, 100, 1, 0)); + centerY->set_tooltip_text (M("TP_GRADIENT_CENTER_Y_TOOLTIP")); + centerY->setAdjusterListener (this); - pack_start (*strength, Gtk::PACK_SHRINK, 0); - pack_start (*degree, Gtk::PACK_SHRINK, 0); - pack_start (*feather, Gtk::PACK_SHRINK, 0); - pack_start (*centerX, Gtk::PACK_SHRINK, 0); - pack_start (*centerY, Gtk::PACK_SHRINK, 0); + pack_start (*strength, Gtk::PACK_SHRINK, 0); + pack_start (*degree, Gtk::PACK_SHRINK, 0); + pack_start (*feather, Gtk::PACK_SHRINK, 0); + pack_start (*centerX, Gtk::PACK_SHRINK, 0); + pack_start (*centerY, Gtk::PACK_SHRINK, 0); - // Instantiating the Editing geometry; positions will be initialized later - Line *hLine, *vLine, *featherLine[2]; - Circle *centerCircle; + // Instantiating the Editing geometry; positions will be initialized later + Line *hLine, *vLine, *featherLine[2]; + Circle *centerCircle; - // Visible geometry - hLine = new Line(); hLine->innerLineWidth=2; - vLine = new Line(); - hLine->datum = vLine->datum = Geometry::IMAGE; + // Visible geometry + hLine = new Line(); + hLine->innerLineWidth = 2; + vLine = new Line(); + hLine->datum = vLine->datum = Geometry::IMAGE; - featherLine[0] = new Line(); featherLine[0]->innerLineWidth=2; - featherLine[1] = new Line(); featherLine[1]->innerLineWidth=2; - featherLine[0]->datum = featherLine[1]->datum = Geometry::IMAGE; + featherLine[0] = new Line(); + featherLine[0]->innerLineWidth = 2; + featherLine[1] = new Line(); + featherLine[1]->innerLineWidth = 2; + featherLine[0]->datum = featherLine[1]->datum = Geometry::IMAGE; - centerCircle = new Circle(); - centerCircle->datum = Geometry::IMAGE; - centerCircle->radiusInImageSpace = false; - centerCircle->radius = 6; - centerCircle->filled = true; + centerCircle = new Circle(); + centerCircle->datum = Geometry::IMAGE; + centerCircle->radiusInImageSpace = false; + centerCircle->radius = 6; + centerCircle->filled = true; - EditSubscriber::visibleGeometry.push_back( hLine ); - EditSubscriber::visibleGeometry.push_back( vLine ); - EditSubscriber::visibleGeometry.push_back( featherLine[0] ); - EditSubscriber::visibleGeometry.push_back( featherLine[1] ); - EditSubscriber::visibleGeometry.push_back( centerCircle ); + EditSubscriber::visibleGeometry.push_back( hLine ); + EditSubscriber::visibleGeometry.push_back( vLine ); + EditSubscriber::visibleGeometry.push_back( featherLine[0] ); + EditSubscriber::visibleGeometry.push_back( featherLine[1] ); + EditSubscriber::visibleGeometry.push_back( centerCircle ); - // MouseOver geometry - hLine = new Line(); hLine->innerLineWidth=2; - vLine = new Line(); - hLine->datum = vLine->datum = Geometry::IMAGE; + // MouseOver geometry + hLine = new Line(); + hLine->innerLineWidth = 2; + vLine = new Line(); + hLine->datum = vLine->datum = Geometry::IMAGE; - featherLine[0] = new Line(); featherLine[0]->innerLineWidth=2; - featherLine[1] = new Line(); featherLine[1]->innerLineWidth=2; - featherLine[0]->datum = featherLine[1]->datum = Geometry::IMAGE; + featherLine[0] = new Line(); + featherLine[0]->innerLineWidth = 2; + featherLine[1] = new Line(); + featherLine[1]->innerLineWidth = 2; + featherLine[0]->datum = featherLine[1]->datum = Geometry::IMAGE; - centerCircle = new Circle(); - centerCircle->datum = Geometry::IMAGE; - centerCircle->radiusInImageSpace = false; - centerCircle->radius = 30; - centerCircle->filled = true; + centerCircle = new Circle(); + centerCircle->datum = Geometry::IMAGE; + centerCircle->radiusInImageSpace = false; + centerCircle->radius = 30; + centerCircle->filled = true; - EditSubscriber::mouseOverGeometry.push_back( hLine ); - EditSubscriber::mouseOverGeometry.push_back( vLine ); - EditSubscriber::mouseOverGeometry.push_back( featherLine[0] ); - EditSubscriber::mouseOverGeometry.push_back( featherLine[1] ); - EditSubscriber::mouseOverGeometry.push_back( centerCircle ); + EditSubscriber::mouseOverGeometry.push_back( hLine ); + EditSubscriber::mouseOverGeometry.push_back( vLine ); + EditSubscriber::mouseOverGeometry.push_back( featherLine[0] ); + EditSubscriber::mouseOverGeometry.push_back( featherLine[1] ); + EditSubscriber::mouseOverGeometry.push_back( centerCircle ); - show_all(); + show_all(); } -Gradient::~Gradient() { - for (std::vector::const_iterator i = visibleGeometry.begin(); i != visibleGeometry.end(); ++i) { - delete *i; - } - for (std::vector::const_iterator i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); ++i) { - delete *i; - } +Gradient::~Gradient() +{ + for (std::vector::const_iterator i = visibleGeometry.begin(); i != visibleGeometry.end(); ++i) { + delete *i; + } + + for (std::vector::const_iterator i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); ++i) { + delete *i; + } } void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener (); - if (pedited) { - degree->setEditedState (pedited->gradient.degree ? Edited : UnEdited); - feather->setEditedState (pedited->gradient.feather ? Edited : UnEdited); - strength->setEditedState (pedited->gradient.strength ? Edited : UnEdited); - centerX->setEditedState (pedited->gradient.centerX ? Edited : UnEdited); - centerY->setEditedState (pedited->gradient.centerY ? Edited : UnEdited); - set_inconsistent (multiImage && !pedited->gradient.enabled); - } + if (pedited) { + degree->setEditedState (pedited->gradient.degree ? Edited : UnEdited); + feather->setEditedState (pedited->gradient.feather ? Edited : UnEdited); + strength->setEditedState (pedited->gradient.strength ? Edited : UnEdited); + centerX->setEditedState (pedited->gradient.centerX ? Edited : UnEdited); + centerY->setEditedState (pedited->gradient.centerY ? Edited : UnEdited); + set_inconsistent (multiImage && !pedited->gradient.enabled); + } - setEnabled(pp->gradient.enabled); - degree->setValue (pp->gradient.degree); - feather->setValue (pp->gradient.feather); - strength->setValue (pp->gradient.strength); - centerX->setValue (pp->gradient.centerX); - centerY->setValue (pp->gradient.centerY); + setEnabled(pp->gradient.enabled); + degree->setValue (pp->gradient.degree); + feather->setValue (pp->gradient.feather); + strength->setValue (pp->gradient.strength); + centerX->setValue (pp->gradient.centerX); + centerY->setValue (pp->gradient.centerY); - updateGeometry (pp->gradient.centerX, pp->gradient.centerY, pp->gradient.feather, pp->gradient.degree); + updateGeometry (pp->gradient.centerX, pp->gradient.centerY, pp->gradient.feather, pp->gradient.degree); - enableListener (); + enableListener (); } -void Gradient::updateGeometry(int centerX_, int centerY_, double feather_, double degree_) { - EditDataProvider* dataProvider = getEditProvider(); - if (dataProvider) { - int imW, imH; - PolarCoord polCoord1, polCoord2; - dataProvider->getImageSize(imW, imH); - double decay = feather_ * sqrt(double(imW)*double(imW)+double(imH)*double(imH)) / 200.; +void Gradient::updateGeometry(int centerX_, int centerY_, double feather_, double degree_) +{ + EditDataProvider* dataProvider = getEditProvider(); - Coord origin(imW/2+centerX_*imW/200.f, imH/2+centerY_*imH/200.f); + if (dataProvider) { + int imW, imH; + PolarCoord polCoord1, polCoord2; + dataProvider->getImageSize(imW, imH); + double decay = feather_ * sqrt(double(imW) * double(imW) + double(imH) * double(imH)) / 200.; - Line *currLine; - Circle *currCircle; - // update horizontal line - currLine = static_cast(visibleGeometry.at(0)); - polCoord1.set(1500.f, float(-degree_+180)); currLine->begin.setFromPolar(polCoord1); currLine->begin += origin; - polCoord1.set(1500.f, float(-degree_ )); currLine->end.setFromPolar (polCoord1); currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(0)); - polCoord1.set(1500.f, float(-degree_+180)); currLine->begin.setFromPolar(polCoord1); currLine->begin += origin; - polCoord1.set(1500.f, float(-degree_ )); currLine->end.setFromPolar (polCoord1); currLine->end += origin; - // update vertical line - currLine = static_cast(visibleGeometry.at(1)); - polCoord1.set( 700.f, float(-degree_+90 )); currLine->begin.setFromPolar(polCoord1); currLine->begin += origin; - polCoord1.set( 700.f, float(-degree_+270)); currLine->end.setFromPolar (polCoord1); currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(1)); - polCoord1.set( 700.f, float(-degree_+90 )); currLine->begin.setFromPolar(polCoord1); currLine->begin += origin; - polCoord1.set( 700.f, float(-degree_+270)); currLine->end.setFromPolar (polCoord1); currLine->end += origin; - // update upper feather line - currLine = static_cast(visibleGeometry.at(2)); - polCoord2.set(decay, float(-degree_+270)); - polCoord1.set(350.f, float(-degree_+180)); currLine->begin.setFromPolar(polCoord1+polCoord2); currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); currLine->end.setFromPolar (polCoord1+polCoord2); currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(2)); - polCoord1.set(350.f, float(-degree_+180)); currLine->begin.setFromPolar(polCoord1+polCoord2); currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); currLine->end.setFromPolar (polCoord1+polCoord2); currLine->end += origin; - // update lower feather line - currLine = static_cast(visibleGeometry.at(3)); - polCoord2.set(decay, float(-degree_+90)); - polCoord1.set(350.f, float(-degree_+180)); currLine->begin.setFromPolar(polCoord1+polCoord2); currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); currLine->end.setFromPolar (polCoord1+polCoord2); currLine->end += origin; - currLine = static_cast(mouseOverGeometry.at(3)); - polCoord1.set(350.f, float(-degree_+180)); currLine->begin.setFromPolar(polCoord1+polCoord2); currLine->begin += origin; - polCoord1.set(350.f, float(-degree_ )); currLine->end.setFromPolar (polCoord1+polCoord2); currLine->end += origin; - // update circle's position - currCircle = static_cast(visibleGeometry.at(4)); - currCircle->center = origin; - currCircle = static_cast(mouseOverGeometry.at(4)); - currCircle->center = origin; - } + Coord origin(imW / 2 + centerX_ * imW / 200.f, imH / 2 + centerY_ * imH / 200.f); + + Line *currLine; + Circle *currCircle; + // update horizontal line + currLine = static_cast(visibleGeometry.at(0)); + polCoord1.set(1500.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set(1500.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(0)); + polCoord1.set(1500.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set(1500.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + // update vertical line + currLine = static_cast(visibleGeometry.at(1)); + polCoord1.set( 700.f, float(-degree_ + 90 )); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set( 700.f, float(-degree_ + 270)); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(1)); + polCoord1.set( 700.f, float(-degree_ + 90 )); + currLine->begin.setFromPolar(polCoord1); + currLine->begin += origin; + polCoord1.set( 700.f, float(-degree_ + 270)); + currLine->end.setFromPolar (polCoord1); + currLine->end += origin; + // update upper feather line + currLine = static_cast(visibleGeometry.at(2)); + polCoord2.set(decay, float(-degree_ + 270)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(2)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + // update lower feather line + currLine = static_cast(visibleGeometry.at(3)); + polCoord2.set(decay, float(-degree_ + 90)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + currLine = static_cast(mouseOverGeometry.at(3)); + polCoord1.set(350.f, float(-degree_ + 180)); + currLine->begin.setFromPolar(polCoord1 + polCoord2); + currLine->begin += origin; + polCoord1.set(350.f, float(-degree_ )); + currLine->end.setFromPolar (polCoord1 + polCoord2); + currLine->end += origin; + // update circle's position + currCircle = static_cast(visibleGeometry.at(4)); + currCircle->center = origin; + currCircle = static_cast(mouseOverGeometry.at(4)); + currCircle->center = origin; + } } void Gradient::write (ProcParams* pp, ParamsEdited* pedited) { - pp->gradient.degree = degree->getValue (); - pp->gradient.feather = feather->getIntValue (); - pp->gradient.strength = strength->getValue (); - pp->gradient.centerX = centerX->getIntValue (); - pp->gradient.centerY = centerY->getIntValue (); - pp->gradient.enabled = getEnabled(); + pp->gradient.degree = degree->getValue (); + pp->gradient.feather = feather->getIntValue (); + pp->gradient.strength = strength->getValue (); + pp->gradient.centerX = centerX->getIntValue (); + pp->gradient.centerY = centerY->getIntValue (); + pp->gradient.enabled = getEnabled(); - if (pedited) { - pedited->gradient.degree = degree->getEditedState (); - pedited->gradient.feather = feather->getEditedState (); - pedited->gradient.strength = strength->getEditedState (); - pedited->gradient.centerX = centerX->getEditedState (); - pedited->gradient.centerY = centerY->getEditedState (); - pedited->gradient.enabled = !get_inconsistent(); - } + if (pedited) { + pedited->gradient.degree = degree->getEditedState (); + pedited->gradient.feather = feather->getEditedState (); + pedited->gradient.strength = strength->getEditedState (); + pedited->gradient.centerX = centerX->getEditedState (); + pedited->gradient.centerY = centerY->getEditedState (); + pedited->gradient.enabled = !get_inconsistent(); + } } void Gradient::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { - degree->setDefault (defParams->gradient.degree); - feather->setDefault (defParams->gradient.feather); - strength->setDefault (defParams->gradient.strength); - centerX->setDefault (defParams->gradient.centerX); - centerY->setDefault (defParams->gradient.centerY); + degree->setDefault (defParams->gradient.degree); + feather->setDefault (defParams->gradient.feather); + strength->setDefault (defParams->gradient.strength); + centerX->setDefault (defParams->gradient.centerX); + centerY->setDefault (defParams->gradient.centerY); - if (pedited) { - degree->setDefaultEditedState (pedited->gradient.degree ? Edited : UnEdited); - feather->setDefaultEditedState (pedited->gradient.feather ? Edited : UnEdited); - strength->setDefaultEditedState (pedited->gradient.strength ? Edited : UnEdited); - centerX->setDefaultEditedState (pedited->gradient.centerX ? Edited : UnEdited); - centerY->setDefaultEditedState (pedited->gradient.centerY ? Edited : UnEdited); - } else { - degree->setDefaultEditedState (Irrelevant); - feather->setDefaultEditedState (Irrelevant); - strength->setDefaultEditedState (Irrelevant); - centerX->setDefaultEditedState (Irrelevant); - centerY->setDefaultEditedState (Irrelevant); - } + if (pedited) { + degree->setDefaultEditedState (pedited->gradient.degree ? Edited : UnEdited); + feather->setDefaultEditedState (pedited->gradient.feather ? Edited : UnEdited); + strength->setDefaultEditedState (pedited->gradient.strength ? Edited : UnEdited); + centerX->setDefaultEditedState (pedited->gradient.centerX ? Edited : UnEdited); + centerY->setDefaultEditedState (pedited->gradient.centerY ? Edited : UnEdited); + } else { + degree->setDefaultEditedState (Irrelevant); + feather->setDefaultEditedState (Irrelevant); + strength->setDefaultEditedState (Irrelevant); + centerX->setDefaultEditedState (Irrelevant); + centerY->setDefaultEditedState (Irrelevant); + } } -void Gradient::adjusterChanged (Adjuster* a, double newval) { +void Gradient::adjusterChanged (Adjuster* a, double newval) +{ - updateGeometry (int(centerX->getValue()), int(centerY->getValue()), feather->getValue(), degree->getValue()); + updateGeometry (int(centerX->getValue()), int(centerY->getValue()), feather->getValue(), degree->getValue()); - if (listener && getEnabled()) { + if (listener && getEnabled()) { - if (a == degree) - listener->panelChanged (EvGradientDegree, degree->getTextValue()); - else if (a == feather) - listener->panelChanged (EvGradientFeather, feather->getTextValue()); - else if (a == strength) - listener->panelChanged (EvGradientStrength, strength->getTextValue()); - else if (a == centerX || a == centerY) - listener->panelChanged (EvGradientCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue())); - } + if (a == degree) { + listener->panelChanged (EvGradientDegree, degree->getTextValue()); + } else if (a == feather) { + listener->panelChanged (EvGradientFeather, feather->getTextValue()); + } else if (a == strength) { + listener->panelChanged (EvGradientStrength, strength->getTextValue()); + } else if (a == centerX || a == centerY) { + listener->panelChanged (EvGradientCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue())); + } + } } -void Gradient::enabledChanged () { +void Gradient::enabledChanged () +{ - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvGradientEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvGradientEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvGradientEnabled, M("GENERAL_DISABLED")); - } + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvGradientEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvGradientEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvGradientEnabled, M("GENERAL_DISABLED")); + } + } } void Gradient::setAdjusterBehavior (bool degreeadd, bool featheradd, bool strengthadd, bool centeradd) { - degree->setAddMode(degreeadd); - feather->setAddMode(featheradd); - strength->setAddMode(strengthadd); - centerX->setAddMode(centeradd); - centerY->setAddMode(centeradd); + degree->setAddMode(degreeadd); + feather->setAddMode(featheradd); + strength->setAddMode(strengthadd); + centerX->setAddMode(centeradd); + centerY->setAddMode(centeradd); } void Gradient::trimValues (rtengine::procparams::ProcParams* pp) { - degree->trimValue(pp->gradient.degree); - feather->trimValue(pp->gradient.feather); - strength->trimValue(pp->gradient.strength); - centerX->trimValue(pp->gradient.centerX); - centerY->trimValue(pp->gradient.centerY); + degree->trimValue(pp->gradient.degree); + feather->trimValue(pp->gradient.feather); + strength->trimValue(pp->gradient.strength); + centerX->trimValue(pp->gradient.centerX); + centerY->trimValue(pp->gradient.centerY); } void Gradient::setBatchMode (bool batchMode) { - editConn.disconnect(); - removeIfThere(this, editHBox, false); - ToolPanel::setBatchMode (batchMode); - degree->showEditedCB (); - feather->showEditedCB (); - strength->showEditedCB (); - centerX->showEditedCB (); - centerY->showEditedCB (); + editConn.disconnect(); + removeIfThere(this, editHBox, false); + ToolPanel::setBatchMode (batchMode); + degree->showEditedCB (); + feather->showEditedCB (); + strength->showEditedCB (); + centerX->showEditedCB (); + centerY->showEditedCB (); } -void Gradient::setEditProvider (EditDataProvider* provider) { - EditSubscriber::setEditProvider(provider); +void Gradient::setEditProvider (EditDataProvider* provider) +{ + EditSubscriber::setEditProvider(provider); } -void Gradient::editToggled () { - if (edit->get_active()) { - subscribe(); - } - else - unsubscribe(); +void Gradient::editToggled () +{ + if (edit->get_active()) { + subscribe(); + } else { + unsubscribe(); + } } -CursorShape Gradient::getCursor(int objectID) { - switch (objectID) { - case (0): - case (1): - return CSMoveRotate; - case (2): - case (3): - { - int angle = degree->getIntValue(); - if (angle<-135 || (angle>=-45 && angle<=45) || angle>135) - return CSMove1DV; - return CSMove1DH; - } - case (4): - return CSMove2D; - default: - return CSOpenHand; - } +CursorShape Gradient::getCursor(int objectID) +{ + switch (objectID) { + case (0): + case (1): + return CSMoveRotate; + + case (2): + case (3): { + int angle = degree->getIntValue(); + + if (angle < -135 || (angle >= -45 && angle <= 45) || angle > 135) { + return CSMove1DV; + } + + return CSMove1DH; + } + + case (4): + return CSMove2D; + + default: + return CSOpenHand; + } } -bool Gradient::mouseOver(int modifierKey) { - EditDataProvider* editProvider = getEditProvider(); - if (editProvider && editProvider->object!=lastObject) { - if (lastObject > -1) { - if (lastObject == 2 || lastObject == 3) { - EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; - EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; - } - else - EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; - } - if (editProvider->object > -1) { - if (editProvider->object == 2 || editProvider->object == 3) { - EditSubscriber::visibleGeometry.at(2)->state = Geometry::PRELIGHT; - EditSubscriber::visibleGeometry.at(3)->state = Geometry::PRELIGHT; - } - else - EditSubscriber::visibleGeometry.at(editProvider->object)->state = Geometry::PRELIGHT; - } - lastObject = editProvider->object; - return true; - } - return false; +bool Gradient::mouseOver(int modifierKey) +{ + EditDataProvider* editProvider = getEditProvider(); + + if (editProvider && editProvider->object != lastObject) { + if (lastObject > -1) { + if (lastObject == 2 || lastObject == 3) { + EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; + EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; + } else { + EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; + } + } + + if (editProvider->object > -1) { + if (editProvider->object == 2 || editProvider->object == 3) { + EditSubscriber::visibleGeometry.at(2)->state = Geometry::PRELIGHT; + EditSubscriber::visibleGeometry.at(3)->state = Geometry::PRELIGHT; + } else { + EditSubscriber::visibleGeometry.at(editProvider->object)->state = Geometry::PRELIGHT; + } + } + + lastObject = editProvider->object; + return true; + } + + return false; } -bool Gradient::button1Pressed(int modifierKey) { - if (!(modifierKey & (GDK_CONTROL_MASK | GDK_CONTROL_MASK))) { - // button press is valid (no modifier key) - PolarCoord pCoord; - EditDataProvider *provider = getEditProvider(); - int imW, imH; - provider->getImageSize(imW, imH); - double halfSizeW = imW/2.; - double halfSizeH = imH/2.; - draggedCenter.set(int(halfSizeW+halfSizeW*(centerX->getValue()/100.)), int(halfSizeH+halfSizeH*(centerY->getValue()/100.))); +bool Gradient::button1Pressed(int modifierKey) +{ + if (!(modifierKey & (GDK_CONTROL_MASK | GDK_CONTROL_MASK))) { + // button press is valid (no modifier key) + PolarCoord pCoord; + EditDataProvider *provider = getEditProvider(); + int imW, imH; + provider->getImageSize(imW, imH); + double halfSizeW = imW / 2.; + double halfSizeH = imH / 2.; + draggedCenter.set(int(halfSizeW + halfSizeW * (centerX->getValue() / 100.)), int(halfSizeH + halfSizeH * (centerY->getValue() / 100.))); - // trick to get the correct angle (clockwise/counter-clockwise) - Coord p1 = draggedCenter; - Coord p2 = provider->posImage; - int p = p1.y; - p1.y = p2.y; - p2.y = p; + // trick to get the correct angle (clockwise/counter-clockwise) + Coord p1 = draggedCenter; + Coord p2 = provider->posImage; + int p = p1.y; + p1.y = p2.y; + p2.y = p; - pCoord.setFromCartesian(p1, p2); - draggedPointOldAngle = pCoord.angle; - //printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle); - draggedPointAdjusterAngle = degree->getValue(); - if (lastObject==2 || lastObject==3) { - // Dragging a line to change the angle - PolarCoord draggedPoint; - Coord currPos; - currPos = provider->posImage; - Coord centerPos = draggedCenter; + pCoord.setFromCartesian(p1, p2); + draggedPointOldAngle = pCoord.angle; + //printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle); + draggedPointAdjusterAngle = degree->getValue(); - double diagonal = sqrt(double(imW)*double(imW)+double(imH)*double(imH)); + if (lastObject == 2 || lastObject == 3) { + // Dragging a line to change the angle + PolarCoord draggedPoint; + Coord currPos; + currPos = provider->posImage; + Coord centerPos = draggedCenter; - // trick to get the correct angle (clockwise/counter-clockwise) - int p = centerPos.y; - centerPos.y = currPos.y; - currPos.y = p; + double diagonal = sqrt(double(imW) * double(imW) + double(imH) * double(imH)); - draggedPoint.setFromCartesian(centerPos, currPos); - // compute the projected value of the dragged point - draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle-degree->getValue())/180.*M_PI); - if (lastObject==3) - draggedFeatherOffset = -draggedFeatherOffset; - draggedFeatherOffset -= (feather->getValue() / 200. * diagonal); - } - return false; - } - else { - // this will let this class ignore further drag events - if (lastObject > -1) { // should theoretically always be true - if (lastObject == 2 || lastObject == 3) { - EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; - EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; - } - else - EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; - } - lastObject = -1; - return true; - } + // trick to get the correct angle (clockwise/counter-clockwise) + int p = centerPos.y; + centerPos.y = currPos.y; + currPos.y = p; + + draggedPoint.setFromCartesian(centerPos, currPos); + // compute the projected value of the dragged point + draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); + + if (lastObject == 3) { + draggedFeatherOffset = -draggedFeatherOffset; + } + + draggedFeatherOffset -= (feather->getValue() / 200. * diagonal); + } + + return false; + } else { + // this will let this class ignore further drag events + if (lastObject > -1) { // should theoretically always be true + if (lastObject == 2 || lastObject == 3) { + EditSubscriber::visibleGeometry.at(2)->state = Geometry::NORMAL; + EditSubscriber::visibleGeometry.at(3)->state = Geometry::NORMAL; + } else { + EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL; + } + } + + lastObject = -1; + return true; + } } -bool Gradient::button1Released() { - draggedPointOldAngle = -1000.; - return true; +bool Gradient::button1Released() +{ + draggedPointOldAngle = -1000.; + return true; } -bool Gradient::drag(int modifierKey) { - // compute the polar coordinate of the mouse position - EditDataProvider *provider = getEditProvider(); - int imW, imH; - provider->getImageSize(imW, imH); - double halfSizeW = imW/2.; - double halfSizeH = imH/2.; +bool Gradient::drag(int modifierKey) +{ + // compute the polar coordinate of the mouse position + EditDataProvider *provider = getEditProvider(); + int imW, imH; + provider->getImageSize(imW, imH); + double halfSizeW = imW / 2.; + double halfSizeH = imH / 2.; - if (lastObject==0 || lastObject==1) { + if (lastObject == 0 || lastObject == 1) { - // Dragging a line to change the angle - PolarCoord draggedPoint; - Coord currPos; - currPos = provider->posImage+provider->deltaImage; - Coord centerPos = draggedCenter; + // Dragging a line to change the angle + PolarCoord draggedPoint; + Coord currPos; + currPos = provider->posImage + provider->deltaImage; + Coord centerPos = draggedCenter; - // trick to get the correct angle (clockwise/counter-clockwise) - int p = centerPos.y; - centerPos.y = currPos.y; - currPos.y = p; + // trick to get the correct angle (clockwise/counter-clockwise) + int p = centerPos.y; + centerPos.y = currPos.y; + currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); - double deltaAngle = draggedPoint.angle - draggedPointOldAngle; - if (deltaAngle>180.) // crossing the boundary (0->360) - deltaAngle -= 360.; - else if (deltaAngle<-180.) // crossing the boundary (360->0) - deltaAngle += 360.; - draggedPointOldAngle = draggedPoint.angle; + draggedPoint.setFromCartesian(centerPos, currPos); + double deltaAngle = draggedPoint.angle - draggedPointOldAngle; - draggedPointAdjusterAngle += deltaAngle; - if (draggedPointAdjusterAngle > 180.) - draggedPointAdjusterAngle = -360. + draggedPointAdjusterAngle; - else if (draggedPointAdjusterAngle < -180.) - draggedPointAdjusterAngle = 360. - draggedPointAdjusterAngle; - //printf("draggedPointOldAngle: %.3f / From %d,%d to %d,%d -> angle = %.3f / ", draggedPointAdjusterAngle, centerPos.x, centerPos.y, currPos.x, currPos.y, draggedPoint.angle); - //printf("currAngle: %.3f = degree: %.3f + deltaAngle: %.3f %s / draggedPointOldAngle: %.3f\n", draggedPointAdjusterAngle, degree->getValue(), deltaAngle, degree->getValue()>180.?">180":degree->getValue()<180.?"<180":"", draggedPointOldAngle); - if (int(draggedPointAdjusterAngle) != degree->getIntValue()) { - degree->setValue(draggedPointAdjusterAngle); - updateGeometry (int(centerX->getValue()), int(centerY->getValue()), feather->getValue(), degree->getValue()); - if (listener) - listener->panelChanged (EvGradientDegree, degree->getTextValue()); - return true; - } - } - else if (lastObject==2 || lastObject==3) { - // Dragging the upper or lower feather bar - PolarCoord draggedPoint; - Coord currPos; - currPos = provider->posImage+provider->deltaImage; - Coord centerPos = draggedCenter; + if (deltaAngle > 180.) { // crossing the boundary (0->360) + deltaAngle -= 360.; + } else if (deltaAngle < -180.) { // crossing the boundary (360->0) + deltaAngle += 360.; + } - double diagonal = sqrt(double(imW)*double(imW)+double(imH)*double(imH)); + draggedPointOldAngle = draggedPoint.angle; - // trick to get the correct angle (clockwise/counter-clockwise) - int p = centerPos.y; - centerPos.y = currPos.y; - currPos.y = p; + draggedPointAdjusterAngle += deltaAngle; - draggedPoint.setFromCartesian(centerPos, currPos); - double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle-degree->getValue())/180.*M_PI); - if (lastObject==2) - // Dragging the upper feather bar - currDraggedFeatherOffset -= draggedFeatherOffset; - else if (lastObject==3) - // Dragging the lower feather bar - currDraggedFeatherOffset = -currDraggedFeatherOffset + draggedFeatherOffset; - currDraggedFeatherOffset = currDraggedFeatherOffset * 200. / diagonal; + if (draggedPointAdjusterAngle > 180.) { + draggedPointAdjusterAngle = -360. + draggedPointAdjusterAngle; + } else if (draggedPointAdjusterAngle < -180.) { + draggedPointAdjusterAngle = 360. - draggedPointAdjusterAngle; + } - if (int(currDraggedFeatherOffset) != feather->getIntValue()) { - feather->setValue(double(int(currDraggedFeatherOffset))); - updateGeometry (centerX->getValue(), centerY->getValue(), feather->getValue(), degree->getValue()); - if (listener) - listener->panelChanged (EvGradientFeather, feather->getTextValue()); - return true; - } - } - else if (lastObject==4) { - // Dragging the circle to change the center - Coord currPos; - draggedCenter += provider->deltaPrevImage; - currPos = draggedCenter; - currPos.clip(imW, imH); - int newCenterX = int((double(currPos.x)-halfSizeW)/halfSizeW*100.); - int newCenterY = int((double(currPos.y)-halfSizeH)/halfSizeH*100.); - if (newCenterX!=centerX->getIntValue() || newCenterY!=centerY->getIntValue()) { - centerX->setValue(newCenterX); - centerY->setValue(newCenterY); - updateGeometry (newCenterX, newCenterY, feather->getValue(), degree->getValue()); - if (listener) - listener->panelChanged (EvGradientCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue())); - return true; - } - } - return false; + //printf("draggedPointOldAngle: %.3f / From %d,%d to %d,%d -> angle = %.3f / ", draggedPointAdjusterAngle, centerPos.x, centerPos.y, currPos.x, currPos.y, draggedPoint.angle); + //printf("currAngle: %.3f = degree: %.3f + deltaAngle: %.3f %s / draggedPointOldAngle: %.3f\n", draggedPointAdjusterAngle, degree->getValue(), deltaAngle, degree->getValue()>180.?">180":degree->getValue()<180.?"<180":"", draggedPointOldAngle); + if (int(draggedPointAdjusterAngle) != degree->getIntValue()) { + degree->setValue(draggedPointAdjusterAngle); + updateGeometry (int(centerX->getValue()), int(centerY->getValue()), feather->getValue(), degree->getValue()); + + if (listener) { + listener->panelChanged (EvGradientDegree, degree->getTextValue()); + } + + return true; + } + } else if (lastObject == 2 || lastObject == 3) { + // Dragging the upper or lower feather bar + PolarCoord draggedPoint; + Coord currPos; + currPos = provider->posImage + provider->deltaImage; + Coord centerPos = draggedCenter; + + double diagonal = sqrt(double(imW) * double(imW) + double(imH) * double(imH)); + + // trick to get the correct angle (clockwise/counter-clockwise) + int p = centerPos.y; + centerPos.y = currPos.y; + currPos.y = p; + + draggedPoint.setFromCartesian(centerPos, currPos); + double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); + + if (lastObject == 2) + // Dragging the upper feather bar + { + currDraggedFeatherOffset -= draggedFeatherOffset; + } else if (lastObject == 3) + // Dragging the lower feather bar + { + currDraggedFeatherOffset = -currDraggedFeatherOffset + draggedFeatherOffset; + } + + currDraggedFeatherOffset = currDraggedFeatherOffset * 200. / diagonal; + + if (int(currDraggedFeatherOffset) != feather->getIntValue()) { + feather->setValue(double(int(currDraggedFeatherOffset))); + updateGeometry (centerX->getValue(), centerY->getValue(), feather->getValue(), degree->getValue()); + + if (listener) { + listener->panelChanged (EvGradientFeather, feather->getTextValue()); + } + + return true; + } + } else if (lastObject == 4) { + // Dragging the circle to change the center + Coord currPos; + draggedCenter += provider->deltaPrevImage; + currPos = draggedCenter; + currPos.clip(imW, imH); + int newCenterX = int((double(currPos.x) - halfSizeW) / halfSizeW * 100.); + int newCenterY = int((double(currPos.y) - halfSizeH) / halfSizeH * 100.); + + if (newCenterX != centerX->getIntValue() || newCenterY != centerY->getIntValue()) { + centerX->setValue(newCenterX); + centerY->setValue(newCenterY); + updateGeometry (newCenterX, newCenterY, feather->getValue(), degree->getValue()); + + if (listener) { + listener->panelChanged (EvGradientCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue())); + } + + return true; + } + } + + return false; } -void Gradient::switchOffEditMode () { - if (edit->get_active()) { - // switching off the toggle button - bool wasBlocked = editConn.block(true); - edit->set_active(false); - if (!wasBlocked) editConn.block(false); - } - EditSubscriber::switchOffEditMode(); // disconnect +void Gradient::switchOffEditMode () +{ + if (edit->get_active()) { + // switching off the toggle button + bool wasBlocked = editConn.block(true); + edit->set_active(false); + + if (!wasBlocked) { + editConn.block(false); + } + } + + EditSubscriber::switchOffEditMode(); // disconnect } diff --git a/rtgui/gradient.h b/rtgui/gradient.h index e27bebe3b..e30dd7728 100644 --- a/rtgui/gradient.h +++ b/rtgui/gradient.h @@ -9,12 +9,13 @@ #include "toolpanel.h" #include "edit.h" -class Gradient : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public EditSubscriber { +class Gradient : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public EditSubscriber +{ - private: +private: int lastObject; - protected: +protected: Gtk::HBox *editHBox; Gtk::ToggleButton* edit; Adjuster* degree; @@ -30,14 +31,14 @@ class Gradient : public ToolParamBlock, public AdjusterListener, public Foldable void editToggled (); - public: +public: Gradient (); ~Gradient (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void updateGeometry (int centerX_, int centerY_, double feather_, double degree_); diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index aec3e19ee..141273179 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -6,7 +6,7 @@ * 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 @@ -40,7 +40,8 @@ Glib::RefPtr MyExpander::disabledPBuf; Glib::RefPtr MyExpander::openedPBuf; Glib::RefPtr MyExpander::closedPBuf; -Glib::ustring escapeHtmlChars(const Glib::ustring &src) { +Glib::ustring escapeHtmlChars(const Glib::ustring &src) +{ // Sources chars to be escaped static const Glib::ustring srcChar("&<>"); @@ -55,7 +56,7 @@ Glib::ustring escapeHtmlChars(const Glib::ustring &src) { Glib::ustring dst(src); // Iterating all chars of the copy of the source string - for (size_t i=0; i list = cont->get_children (); Glib::ListHandle::iterator i = list.begin (); - for (; i!=list.end() && *i!=w; ++i); - if (i!=list.end()) { - if (increference) + + for (; i != list.end() && *i != w; ++i); + + if (i != list.end()) { + if (increference) { w->reference (); + } + cont->remove (*w); return true; - } - else + } else { return false; + } } -void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) { +void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) +{ - if (options.thumbInterp==0) + if (options.thumbInterp == 0) { rtengine::nearestInterp (src, sw, sh, dst, dw, dh); - else if (options.thumbInterp==1) + } else if (options.thumbInterp == 1) { rtengine::bilinearInterp (src, sw, sh, dst, dw, dh); + } } -Glib::ustring removeExtension (const Glib::ustring& filename) { +Glib::ustring removeExtension (const Glib::ustring& filename) +{ Glib::ustring bname = Glib::path_get_basename(filename); size_t lastdot = bname.find_last_of ('.'); size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); - if (lastdot!=bname.npos && (lastwhitespace==bname.npos || lastdot > lastwhitespace)) - return filename.substr (0, filename.size()-(bname.size()-lastdot)); - else + + if (lastdot != bname.npos && (lastwhitespace == bname.npos || lastdot > lastwhitespace)) { + return filename.substr (0, filename.size() - (bname.size() - lastdot)); + } else { return filename; + } } -Glib::ustring getExtension (const Glib::ustring& filename) { +Glib::ustring getExtension (const Glib::ustring& filename) +{ Glib::ustring bname = Glib::path_get_basename(filename); size_t lastdot = bname.find_last_of ('.'); size_t lastwhitespace = bname.find_last_of (" \t\f\v\n\r"); - if (lastdot!=bname.npos && (lastwhitespace==bname.npos || lastdot > lastwhitespace)) - return filename.substr (filename.size()-(bname.size()-lastdot)+1, filename.npos); - else + + if (lastdot != bname.npos && (lastwhitespace == bname.npos || lastdot > lastwhitespace)) { + return filename.substr (filename.size() - (bname.size() - lastdot) + 1, filename.npos); + } else { return ""; + } } -bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) { +bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) +{ bool safe = true; + if (safe_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); safe = (msgd.run () == Gtk::RESPONSE_YES); } + return safe; } -void writeFailed (Gtk::Window& parent, const std::string& filename) { +void writeFailed (Gtk::Window& parent, const std::string& filename) +{ Glib::ustring msg_ = Glib::ustring::compose(M("MAIN_MSG_WRITEFAILED"), filename); Gtk::MessageDialog msgd (parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.run (); } -void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams, bool drawGuide, bool useBgColor, bool fullImageVisible) { +void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams, bool drawGuide, bool useBgColor, bool fullImageVisible) +{ cr->set_line_width (0.); cr->rectangle (imx, imy, imw, imh); cr->clip (); - - double c1x = (cparams.x-startx)*scale; - double c1y = (cparams.y-starty)*scale; - double c2x = (cparams.x+cparams.w-startx)*scale - (fullImageVisible ? 0.0 : 1.0); - double c2y = (cparams.y+cparams.h-starty)*scale - (fullImageVisible ? 0.0 : 1.0); - // crop overlay color, linked with crop windows background - if (options.bgcolor==0 || !useBgColor) - cr->set_source_rgba (options.cutOverlayBrush[0], options.cutOverlayBrush[1], options.cutOverlayBrush[2], options.cutOverlayBrush[3]); - else if (options.bgcolor==1) - cr->set_source_rgb (0,0,0); - else if (options.bgcolor==2) - cr->set_source_rgb (1,1,1); - - cr->rectangle (imx, imy, imw+0.5, round(c1y)+0.5); - cr->rectangle (imx, round(imy+c2y)+0.5, imw+0.5, round(imh-c2y)+0.5); - cr->rectangle (imx, round(imy+c1y)+0.5, round(c1x)+0.5, round(c2y-c1y+1)+0.5); - cr->rectangle (round(imx+c2x)+0.5, round(imy+c1y)+0.5, round(imw-c2x)+0.5, round(c2y-c1y+1)+0.5); + double c1x = (cparams.x - startx) * scale; + double c1y = (cparams.y - starty) * scale; + double c2x = (cparams.x + cparams.w - startx) * scale - (fullImageVisible ? 0.0 : 1.0); + double c2y = (cparams.y + cparams.h - starty) * scale - (fullImageVisible ? 0.0 : 1.0); + + // crop overlay color, linked with crop windows background + if (options.bgcolor == 0 || !useBgColor) { + cr->set_source_rgba (options.cutOverlayBrush[0], options.cutOverlayBrush[1], options.cutOverlayBrush[2], options.cutOverlayBrush[3]); + } else if (options.bgcolor == 1) { + cr->set_source_rgb (0, 0, 0); + } else if (options.bgcolor == 2) { + cr->set_source_rgb (1, 1, 1); + } + + + cr->rectangle (imx, imy, imw + 0.5, round(c1y) + 0.5); + cr->rectangle (imx, round(imy + c2y) + 0.5, imw + 0.5, round(imh - c2y) + 0.5); + cr->rectangle (imx, round(imy + c1y) + 0.5, round(c1x) + 0.5, round(c2y - c1y + 1) + 0.5); + cr->rectangle (round(imx + c2x) + 0.5, round(imy + c1y) + 0.5, round(imw - c2x) + 0.5, round(c2y - c1y + 1) + 0.5); cr->fill (); // rectangle around the cropped area and guides - if (cparams.guide!="None" && drawGuide) { + if (cparams.guide != "None" && drawGuide) { double rectx1 = round(c1x) + imx + 0.5; double recty1 = round(c1y) + imy + 0.5; double rectx2 = round(c2x) + imx + 0.5; double recty2 = round(c2y) + imy + 0.5; if(fullImageVisible) { - rectx2 = min(rectx2, imx+imw-0.5); - recty2 = min(recty2, imy+imh-0.5); + rectx2 = min(rectx2, imx + imw - 0.5); + recty2 = min(recty2, imy + imh - 0.5); } cr->set_line_width (1.0); @@ -190,92 +213,100 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); - - if (cparams.guide!="Rule of diagonals" && cparams.guide!="Golden Triangle 1" && cparams.guide!="Golden Triangle 2") { + + if (cparams.guide != "Rule of diagonals" && cparams.guide != "Golden Triangle 1" && cparams.guide != "Golden Triangle 2") { // draw guide lines std::vector horiz_ratios; std::vector vert_ratios; - - if (cparams.guide=="Rule of thirds") { - horiz_ratios.push_back (1.0/3.0); - horiz_ratios.push_back (2.0/3.0); - vert_ratios.push_back (1.0/3.0); - vert_ratios.push_back (2.0/3.0); - } - else if (!strncmp(cparams.guide.data(),"Harmonic means",14)) { - horiz_ratios.push_back (1.0-0.618); + + if (cparams.guide == "Rule of thirds") { + horiz_ratios.push_back (1.0 / 3.0); + horiz_ratios.push_back (2.0 / 3.0); + vert_ratios.push_back (1.0 / 3.0); + vert_ratios.push_back (2.0 / 3.0); + } else if (!strncmp(cparams.guide.data(), "Harmonic means", 14)) { + horiz_ratios.push_back (1.0 - 0.618); horiz_ratios.push_back (0.618); vert_ratios.push_back (0.618); - vert_ratios.push_back (1.0-0.618); - } - else if (cparams.guide=="Grid") { + vert_ratios.push_back (1.0 - 0.618); + } else if (cparams.guide == "Grid") { // To have even distribution, normalize it a bit - const int longSideNumLines=10; + const int longSideNumLines = 10; - int w=rectx2-rectx1, h=recty2-recty1; - if (w>longSideNumLines && h>longSideNumLines) { - if (w>h) { - for (int i=1;i longSideNumLines && h > longSideNumLines) { + if (w > h) { + for (int i = 1; i < longSideNumLines; i++) { + vert_ratios.push_back ((double)i / longSideNumLines); + } + + int shortSideNumLines = (int)round(h * (double)longSideNumLines / w); + + for (int i = 1; i < shortSideNumLines; i++) { + horiz_ratios.push_back ((double)i / shortSideNumLines); + } } else { - for (int i=1;iset_source_rgba (1.0, 1.0, 1.0, 0.618); - cr->move_to (rectx1, recty1 + round((recty2-recty1) * horiz_ratios[i])); - cr->line_to (rectx2, recty1 + round((recty2-recty1) * horiz_ratios[i])); + cr->move_to (rectx1, recty1 + round((recty2 - recty1) * horiz_ratios[i])); + cr->line_to (rectx2, recty1 + round((recty2 - recty1) * horiz_ratios[i])); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); - cr->move_to (rectx1, recty1 + round((recty2-recty1) * horiz_ratios[i])); - cr->line_to (rectx2, recty1 + round((recty2-recty1) * horiz_ratios[i])); + cr->move_to (rectx1, recty1 + round((recty2 - recty1) * horiz_ratios[i])); + cr->line_to (rectx2, recty1 + round((recty2 - recty1) * horiz_ratios[i])); cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); } + // Verticals - for (size_t i=0; iset_source_rgba (1.0, 1.0, 1.0, 0.618); - cr->move_to (rectx1 + round((rectx2-rectx1) * vert_ratios[i]), recty1); - cr->line_to (rectx1 + round((rectx2-rectx1) * vert_ratios[i]), recty2); + cr->move_to (rectx1 + round((rectx2 - rectx1) * vert_ratios[i]), recty1); + cr->line_to (rectx1 + round((rectx2 - rectx1) * vert_ratios[i]), recty2); cr->stroke (); cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); - cr->move_to (rectx1 + round((rectx2-rectx1) * vert_ratios[i]), recty1); - cr->line_to (rectx1 + round((rectx2-rectx1) * vert_ratios[i]), recty2); + cr->move_to (rectx1 + round((rectx2 - rectx1) * vert_ratios[i]), recty1); + cr->line_to (rectx1 + round((rectx2 - rectx1) * vert_ratios[i]), recty2); cr->stroke (); ds.resize (0); cr->set_dash (ds, 0); - } - } - else if (cparams.guide=="Rule of diagonals") { + } + } else if (cparams.guide == "Rule of diagonals") { double corners_from[4][2]; double corners_to[4][2]; - int mindim = min(rectx2-rectx1, recty2-recty1); + int mindim = min(rectx2 - rectx1, recty2 - recty1); corners_from[0][0] = rectx1; corners_from[0][1] = recty1; corners_to[0][0] = rectx1 + mindim; @@ -292,7 +323,8 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int corners_from[3][1] = recty2; corners_to[3][0] = rectx2 - mindim; corners_to[3][1] = recty2 - mindim; - for (int i=0; i<4; i++) { + + for (int i = 0; i < 4; i++) { cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); cr->move_to (corners_from[i][0], corners_from[i][1]); cr->line_to (corners_to[i][0], corners_to[i][1]); @@ -307,127 +339,138 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int ds.resize (0); cr->set_dash (ds, 0); } - } else if (cparams.guide=="Golden Triangle 1" || cparams.guide=="Golden Triangle 2") { - // main diagonal - if(cparams.guide=="Golden Triangle 2") { - std::swap(rectx1,rectx2); - } - cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); - cr->move_to (rectx1, recty1); - cr->line_to (rectx2, recty2); - cr->stroke (); - cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - std::valarray ds (1); - ds[0] = 4; - cr->set_dash (ds, 0); - cr->move_to (rectx1, recty1); - cr->line_to (rectx2, recty2); - cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + } else if (cparams.guide == "Golden Triangle 1" || cparams.guide == "Golden Triangle 2") { + // main diagonal + if(cparams.guide == "Golden Triangle 2") { + std::swap(rectx1, rectx2); + } - double height = recty2 - recty1; - double width = rectx2 - rectx1; - double d = sqrt(height*height + width*width); - double alpha = asin(width/d); - double beta = asin(height/d); - double a = sin(beta) * height; - double b = sin(alpha) * height; + cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); + cr->move_to (rectx1, recty1); + cr->line_to (rectx2, recty2); + cr->stroke (); + cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); + std::valarray ds (1); + ds[0] = 4; + cr->set_dash (ds, 0); + cr->move_to (rectx1, recty1); + cr->line_to (rectx2, recty2); + cr->stroke (); + ds.resize (0); + cr->set_dash (ds, 0); - double x = (a*b)/height; - double y = height - (b*(d-a))/width; - cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); - cr->move_to (rectx1, recty2); - cr->line_to (rectx1+x, recty1+y); - cr->stroke (); - cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - ds.resize (1); - ds[0] = 4; - cr->set_dash (ds, 0); - cr->move_to (rectx1, recty2); - cr->line_to (rectx1+x, recty1+y); - cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + double height = recty2 - recty1; + double width = rectx2 - rectx1; + double d = sqrt(height * height + width * width); + double alpha = asin(width / d); + double beta = asin(height / d); + double a = sin(beta) * height; + double b = sin(alpha) * height; - x = width - (a*b)/height; - y = (b*(d-a))/width; - cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); - cr->move_to (rectx2, recty1); - cr->line_to (rectx1+x, recty1+y); - cr->stroke (); - cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); - ds.resize (1); - ds[0] = 4; - cr->set_dash (ds, 0); - cr->move_to (rectx2, recty1); - cr->line_to (rectx1+x, recty1+y); - cr->stroke (); - ds.resize (0); - cr->set_dash (ds, 0); + double x = (a * b) / height; + double y = height - (b * (d - a)) / width; + cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); + cr->move_to (rectx1, recty2); + cr->line_to (rectx1 + x, recty1 + y); + cr->stroke (); + cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); + ds.resize (1); + ds[0] = 4; + cr->set_dash (ds, 0); + cr->move_to (rectx1, recty2); + cr->line_to (rectx1 + x, recty1 + y); + cr->stroke (); + ds.resize (0); + cr->set_dash (ds, 0); + + x = width - (a * b) / height; + y = (b * (d - a)) / width; + cr->set_source_rgba (1.0, 1.0, 1.0, 0.618); + cr->move_to (rectx2, recty1); + cr->line_to (rectx1 + x, recty1 + y); + cr->stroke (); + cr->set_source_rgba (0.0, 0.0, 0.0, 0.618); + ds.resize (1); + ds[0] = 4; + cr->set_dash (ds, 0); + cr->move_to (rectx2, recty1); + cr->line_to (rectx1 + x, recty1 + y); + cr->stroke (); + ds.resize (0); + cr->set_dash (ds, 0); } } + cr->reset_clip (); } -bool ExpanderBox::on_expose_event(GdkEventExpose* event) { - bool retVal = Gtk::EventBox::on_expose_event(event); +bool ExpanderBox::on_expose_event(GdkEventExpose* event) +{ + bool retVal = Gtk::EventBox::on_expose_event(event); - if (!options.useSystemTheme) { - Glib::RefPtr window = get_window(); - Glib::RefPtr style = get_style (); - Cairo::RefPtr cr = window->create_cairo_context(); + if (!options.useSystemTheme) { + Glib::RefPtr window = get_window(); + Glib::RefPtr style = get_style (); + Cairo::RefPtr cr = window->create_cairo_context(); - int x_, y_, w_, h_, foo; - window->get_geometry(x_, y_, w_, h_, foo); - double x = 0.; - double y = 0.; - double w = double(w_); - double h = double(h_); + int x_, y_, w_, h_, foo; + window->get_geometry(x_, y_, w_, h_, foo); + double x = 0.; + double y = 0.; + double w = double(w_); + double h = double(h_); - cr->set_antialias (Cairo::ANTIALIAS_NONE); + cr->set_antialias (Cairo::ANTIALIAS_NONE); - // draw a frame - cr->set_line_width (1.0); - Gdk::Color c = style->get_fg (Gtk::STATE_NORMAL); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->move_to(x+0.5, y+0.5); - cr->line_to(x+w, y+0.5); - cr->line_to(x+w, y+h); - cr->line_to(x+0.5, y+h); - cr->line_to(x+0.5, y+0.5); - cr->stroke (); - } - return retVal; + // draw a frame + cr->set_line_width (1.0); + Gdk::Color c = style->get_fg (Gtk::STATE_NORMAL); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->move_to(x + 0.5, y + 0.5); + cr->line_to(x + w, y + 0.5); + cr->line_to(x + w, y + h); + cr->line_to(x + 0.5, y + h); + cr->line_to(x + 0.5, y + 0.5); + cr->stroke (); + } + + return retVal; } -ExpanderBox::ExpanderBox( Gtk::Container *p):pC(p) { - set_name ("ExpanderBox"); - updateStyle(); +ExpanderBox::ExpanderBox( Gtk::Container *p): pC(p) +{ + set_name ("ExpanderBox"); + updateStyle(); } -void ExpanderBox::on_style_changed (const Glib::RefPtr& style) { - updateStyle(); +void ExpanderBox::on_style_changed (const Glib::RefPtr& style) +{ + updateStyle(); } -void ExpanderBox::updateStyle() { - set_border_width(options.slimUI ? 2 : 8); // Outer space around the tool's frame 2:7 +void ExpanderBox::updateStyle() +{ + set_border_width(options.slimUI ? 2 : 8); // Outer space around the tool's frame 2:7 } -void ExpanderBox::show_all() { - // ask childs to show themselves, but not us (remain unchanged) - Gtk::Container::show_all_children(true); +void ExpanderBox::show_all() +{ + // ask childs to show themselves, but not us (remain unchanged) + Gtk::Container::show_all_children(true); } -void ExpanderBox::showBox() { - Gtk::EventBox::show(); +void ExpanderBox::showBox() +{ + Gtk::EventBox::show(); } -void ExpanderBox::hideBox() { - Gtk::EventBox::hide(); +void ExpanderBox::hideBox() +{ + Gtk::EventBox::hide(); } -void MyExpander::init() { +void MyExpander::init() +{ inconsistentPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderInconsistent.png")); enabledPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderEnabled.png")); disabledPBuf = Gdk::Pixbuf::create_from_file(RTImage::findIconAbsolutePath("expanderDisabled.png")); @@ -436,9 +479,9 @@ void MyExpander::init() { } MyExpander::MyExpander(bool useEnabled, Gtk::Widget* titleWidget) : - enabled(false), inconsistent(false), flushEvent(false), expBox(NULL), - child(NULL), headerWidget(NULL), statusImage(NULL), - label(NULL), useEnabled(useEnabled) + enabled(false), inconsistent(false), flushEvent(false), expBox(NULL), + child(NULL), headerWidget(NULL), statusImage(NULL), + label(NULL), useEnabled(useEnabled) { set_spacing(options.slimUI ? 0 : 2); set_name("MyExpander"); @@ -456,11 +499,11 @@ MyExpander::MyExpander(bool useEnabled, Gtk::Widget* titleWidget) : imageEvBox->signal_enter_notify_event().connect( sigc::mem_fun(this, & MyExpander::on_enter_leave_enable), false ); imageEvBox->signal_leave_notify_event().connect( sigc::mem_fun(this, & MyExpander::on_enter_leave_enable), false ); headerHBox->pack_start(*imageEvBox, Gtk::PACK_SHRINK, 0); - } - else { + } else { statusImage = Gtk::manage(new Gtk::Image(openedPBuf)); headerHBox->pack_start(*statusImage, Gtk::PACK_SHRINK, 0); } + statusImage->set_can_focus(false); if (titleWidget) { @@ -483,9 +526,9 @@ MyExpander::MyExpander(bool useEnabled, Gtk::Widget* titleWidget) : } MyExpander::MyExpander(bool useEnabled, Glib::ustring titleLabel) : - enabled(false), inconsistent(false), flushEvent(false), expBox(NULL), - child(NULL), headerWidget(NULL), statusImage(NULL), - label(NULL), useEnabled(useEnabled) + enabled(false), inconsistent(false), flushEvent(false), expBox(NULL), + child(NULL), headerWidget(NULL), statusImage(NULL), + label(NULL), useEnabled(useEnabled) { set_spacing(options.slimUI ? 0 : 2); set_name("MyExpander"); @@ -504,16 +547,19 @@ MyExpander::MyExpander(bool useEnabled, Glib::ustring titleLabel) : imageEvBox->signal_enter_notify_event().connect( sigc::mem_fun(this, & MyExpander::on_enter_leave_enable), false ); imageEvBox->signal_leave_notify_event().connect( sigc::mem_fun(this, & MyExpander::on_enter_leave_enable), false ); headerHBox->pack_start(*imageEvBox, Gtk::PACK_SHRINK, 0); - } - else { + } else { statusImage = Gtk::manage(new Gtk::Image(openedPBuf)); headerHBox->pack_start(*statusImage, Gtk::PACK_SHRINK, 0); } + statusImage->set_can_focus(false); Glib::ustring str("-"); - if (!titleLabel.empty()) + + if (!titleLabel.empty()) { str = titleLabel; + } + label = Gtk::manage(new Gtk::Label()); label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); label->set_markup(Glib::ustring("") + escapeHtmlChars(titleLabel) + Glib::ustring("")); @@ -533,197 +579,235 @@ MyExpander::MyExpander(bool useEnabled, Glib::ustring titleLabel) : titleEvBox->signal_leave_notify_event().connect( sigc::mem_fun(this, & MyExpander::on_enter_leave_title), false); } -bool MyExpander::on_enter_leave_title (GdkEventCrossing* event) { - if (is_sensitive()) { - if (event->type == GDK_ENTER_NOTIFY) { - titleEvBox->set_state(Gtk::STATE_PRELIGHT); - queue_draw(); - } - else if (event->type == GDK_LEAVE_NOTIFY) { - titleEvBox->set_state(Gtk::STATE_NORMAL); - queue_draw(); - } - } - return true; +bool MyExpander::on_enter_leave_title (GdkEventCrossing* event) +{ + if (is_sensitive()) { + if (event->type == GDK_ENTER_NOTIFY) { + titleEvBox->set_state(Gtk::STATE_PRELIGHT); + queue_draw(); + } else if (event->type == GDK_LEAVE_NOTIFY) { + titleEvBox->set_state(Gtk::STATE_NORMAL); + queue_draw(); + } + } + + return true; } -bool MyExpander::on_enter_leave_enable (GdkEventCrossing* event) { - if (is_sensitive()) { - if (event->type == GDK_ENTER_NOTIFY) { - imageEvBox->set_state(Gtk::STATE_PRELIGHT); - queue_draw(); - } - else if (event->type == GDK_LEAVE_NOTIFY) { - imageEvBox->set_state(Gtk::STATE_NORMAL); - queue_draw(); - } - } - return true; +bool MyExpander::on_enter_leave_enable (GdkEventCrossing* event) +{ + if (is_sensitive()) { + if (event->type == GDK_ENTER_NOTIFY) { + imageEvBox->set_state(Gtk::STATE_PRELIGHT); + queue_draw(); + } else if (event->type == GDK_LEAVE_NOTIFY) { + imageEvBox->set_state(Gtk::STATE_NORMAL); + queue_draw(); + } + } + + return true; } -void MyExpander::updateStyle() { - headerHBox->set_spacing(options.slimUI ? 2 : 5); - headerHBox->set_border_width(options.slimUI ? 1 : 2); - set_spacing(0); - set_border_width(options.slimUI ? 0 : 1); - if (expBox) expBox->updateStyle(); +void MyExpander::updateStyle() +{ + headerHBox->set_spacing(options.slimUI ? 2 : 5); + headerHBox->set_border_width(options.slimUI ? 1 : 2); + set_spacing(0); + set_border_width(options.slimUI ? 0 : 1); + + if (expBox) { + expBox->updateStyle(); + } } -void MyExpander::setLabel (Glib::ustring newLabel) { - if (label) - label->set_markup(Glib::ustring("") + escapeHtmlChars(newLabel) + Glib::ustring("")); +void MyExpander::setLabel (Glib::ustring newLabel) +{ + if (label) { + label->set_markup(Glib::ustring("") + escapeHtmlChars(newLabel) + Glib::ustring("")); + } } -void MyExpander::setLabel (Gtk::Widget *newWidget) { - if (headerWidget) { - removeIfThere(headerHBox, headerWidget, false); - headerHBox->pack_start(*newWidget, Gtk::PACK_EXPAND_WIDGET, 0); - } +void MyExpander::setLabel (Gtk::Widget *newWidget) +{ + if (headerWidget) { + removeIfThere(headerHBox, headerWidget, false); + headerHBox->pack_start(*newWidget, Gtk::PACK_EXPAND_WIDGET, 0); + } } -bool MyExpander::get_inconsistent() { - return inconsistent; +bool MyExpander::get_inconsistent() +{ + return inconsistent; } -void MyExpander::set_inconsistent(bool isInconsistent) { - if (inconsistent != isInconsistent) { - inconsistent = isInconsistent; - if (useEnabled) { - if (isInconsistent) - statusImage->set(inconsistentPBuf); - else { - if (enabled) - statusImage->set(enabledPBuf); - else - statusImage->set(disabledPBuf); - } - } +void MyExpander::set_inconsistent(bool isInconsistent) +{ + if (inconsistent != isInconsistent) { + inconsistent = isInconsistent; - } + if (useEnabled) { + if (isInconsistent) { + statusImage->set(inconsistentPBuf); + } else { + if (enabled) { + statusImage->set(enabledPBuf); + } else { + statusImage->set(disabledPBuf); + } + } + } + + } } -bool MyExpander::getUseEnabled() { - return useEnabled; +bool MyExpander::getUseEnabled() +{ + return useEnabled; } -bool MyExpander::getEnabled() { - return enabled; +bool MyExpander::getEnabled() +{ + return enabled; } -void MyExpander::setEnabled(bool isEnabled) { - if (isEnabled != enabled) { - if (useEnabled) { - if (enabled) { - enabled = false; - if (!inconsistent) { - statusImage->set(disabledPBuf); - message.emit(); - } - } - else { - enabled = true; - if (!inconsistent) { - statusImage->set(enabledPBuf); - message.emit(); - } - } - } - } +void MyExpander::setEnabled(bool isEnabled) +{ + if (isEnabled != enabled) { + if (useEnabled) { + if (enabled) { + enabled = false; + + if (!inconsistent) { + statusImage->set(disabledPBuf); + message.emit(); + } + } else { + enabled = true; + + if (!inconsistent) { + statusImage->set(enabledPBuf); + message.emit(); + } + } + } + } } -void MyExpander::setEnabledTooltipMarkup(Glib::ustring tooltipMarkup) { - if (useEnabled) { - statusImage->set_tooltip_markup(tooltipMarkup); - } +void MyExpander::setEnabledTooltipMarkup(Glib::ustring tooltipMarkup) +{ + if (useEnabled) { + statusImage->set_tooltip_markup(tooltipMarkup); + } } -void MyExpander::setEnabledTooltipText(Glib::ustring tooltipText) { - if (useEnabled) { - statusImage->set_tooltip_text(tooltipText); - } +void MyExpander::setEnabledTooltipText(Glib::ustring tooltipText) +{ + if (useEnabled) { + statusImage->set_tooltip_text(tooltipText); + } } -void MyExpander::set_expanded( bool expanded ) { - if (!expBox) - return; +void MyExpander::set_expanded( bool expanded ) +{ + if (!expBox) { + return; + } - bool isVisible = expBox->is_visible(); + bool isVisible = expBox->is_visible(); - if (isVisible == expanded) - return; + if (isVisible == expanded) { + return; + } - if (!useEnabled) { - if (expanded ) - statusImage->set(openedPBuf); - else - statusImage->set(closedPBuf); - } - if (expanded) - expBox->showBox(); - else - expBox->hideBox(); + if (!useEnabled) { + if (expanded ) { + statusImage->set(openedPBuf); + } else { + statusImage->set(closedPBuf); + } + } + + if (expanded) { + expBox->showBox(); + } else { + expBox->hideBox(); + } } -bool MyExpander::get_expanded() { - return expBox ? expBox->get_visible() : false; +bool MyExpander::get_expanded() +{ + return expBox ? expBox->get_visible() : false; } -void MyExpander::add (Gtk::Container& widget) { - child = &widget; - expBox = Gtk::manage (new ExpanderBox (child)); - expBox->add (*child); - pack_start(*expBox, Gtk::PACK_SHRINK, 0); - child->show(); - expBox->hideBox(); +void MyExpander::add (Gtk::Container& widget) +{ + child = &widget; + expBox = Gtk::manage (new ExpanderBox (child)); + expBox->add (*child); + pack_start(*expBox, Gtk::PACK_SHRINK, 0); + child->show(); + expBox->hideBox(); } -bool MyExpander::on_toggle(GdkEventButton* event) { - if (flushEvent) { - flushEvent = false; - return false; - } +bool MyExpander::on_toggle(GdkEventButton* event) +{ + if (flushEvent) { + flushEvent = false; + return false; + } - if (!expBox || event->button != 1) - return false; + if (!expBox || event->button != 1) { + return false; + } - bool isVisible = expBox->is_visible(); - if (!useEnabled) { - if (isVisible) - statusImage->set(closedPBuf); - else - statusImage->set(openedPBuf); - } - if (isVisible) - expBox->hideBox(); - else - expBox->showBox(); - return false; + bool isVisible = expBox->is_visible(); + + if (!useEnabled) { + if (isVisible) { + statusImage->set(closedPBuf); + } else { + statusImage->set(openedPBuf); + } + } + + if (isVisible) { + expBox->hideBox(); + } else { + expBox->showBox(); + } + + return false; } -Gtk::Container* MyExpander::getChild() { - return child; +Gtk::Container* MyExpander::getChild() +{ + return child; } // used to connect a function to the enabled_toggled signal -MyExpander::type_signal_enabled_toggled MyExpander::signal_enabled_toggled() { - return message; +MyExpander::type_signal_enabled_toggled MyExpander::signal_enabled_toggled() +{ + return message; } // internal use ; when the user clicks on the toggle button, it calls this method that will emit an enabled_change event -bool MyExpander::on_enabled_change(GdkEventButton* event) { - if (event->button == 1) { - if (enabled) { - enabled = false; - statusImage->set(disabledPBuf); - } - else { - enabled = true; - statusImage->set(enabledPBuf); - } - message.emit(); - flushEvent = true; - } - return false; +bool MyExpander::on_enabled_change(GdkEventButton* event) +{ + if (event->button == 1) { + if (enabled) { + enabled = false; + statusImage->set(disabledPBuf); + } else { + enabled = true; + statusImage->set(enabledPBuf); + } + + message.emit(); + flushEvent = true; + } + + return false; } /* @@ -733,356 +817,420 @@ bool MyExpander::on_enabled_change(GdkEventButton* event) { * otherwise the mouse wheel will scroll the editor's tabs content. * */ -MyScrolledWindow::MyScrolledWindow () { - set_size_request(-1,30); +MyScrolledWindow::MyScrolledWindow () +{ + set_size_request(-1, 30); } -bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) { - if (!options.hideTPVScrollbar) { - Gtk::ScrolledWindow::on_scroll_event (event); - return true; - } +bool MyScrolledWindow::on_scroll_event (GdkEventScroll* event) +{ + if (!options.hideTPVScrollbar) { + Gtk::ScrolledWindow::on_scroll_event (event); + return true; + } Gtk::Adjustment *adjust = get_vadjustment(); Gtk::VScrollbar *scroll = get_vscrollbar(); + if (adjust && scroll) { - double upper = adjust->get_upper(); - double lower = adjust->get_lower(); - double value = adjust->get_value(); - double step = adjust->get_step_increment(); - double value2 = 0.; - if (event->direction == GDK_SCROLL_DOWN) { - value2 = value+step; - if (value2 > upper) - value2 = upper; - if (value2 != value) { - scroll->set_value(value2); - } - } - else { - value2 = value-step; - if (value2 < lower) - value2 = lower; - if (value2 != value) { - scroll->set_value(value2); - } - } + double upper = adjust->get_upper(); + double lower = adjust->get_lower(); + double value = adjust->get_value(); + double step = adjust->get_step_increment(); + double value2 = 0.; + + if (event->direction == GDK_SCROLL_DOWN) { + value2 = value + step; + + if (value2 > upper) { + value2 = upper; + } + + if (value2 != value) { + scroll->set_value(value2); + } + } else { + value2 = value - step; + + if (value2 < lower) { + value2 = lower; + } + + if (value2 != value) { + scroll->set_value(value2); + } + } } + return true; } -MyComboBoxText::MyComboBoxText () { - set_size_request(40, -1); +MyComboBoxText::MyComboBoxText () +{ + set_size_request(40, -1); } -bool MyComboBoxText::on_scroll_event (GdkEventScroll* event) { +bool MyComboBoxText::on_scroll_event (GdkEventScroll* event) +{ - // If Shift is pressed, the widget is modified - if (event->state & GDK_SHIFT_MASK) { - Gtk::ComboBoxText::on_scroll_event(event); - return true; - } - // ... otherwise the scroll event is sent back to an upper level - return false; + // If Shift is pressed, the widget is modified + if (event->state & GDK_SHIFT_MASK) { + Gtk::ComboBoxText::on_scroll_event(event); + return true; + } + + // ... otherwise the scroll event is sent back to an upper level + return false; } -MyComboBox::MyComboBox () { - set_size_request(40, -1); +MyComboBox::MyComboBox () +{ + set_size_request(40, -1); } -bool MyComboBox::on_scroll_event (GdkEventScroll* event) { +bool MyComboBox::on_scroll_event (GdkEventScroll* event) +{ - // If Shift is pressed, the widget is modified - if (event->state & GDK_SHIFT_MASK) { - Gtk::ComboBox::on_scroll_event(event); - return true; - } - // ... otherwise the scroll event is sent back to an upper level - return false; + // If Shift is pressed, the widget is modified + if (event->state & GDK_SHIFT_MASK) { + Gtk::ComboBox::on_scroll_event(event); + return true; + } + + // ... otherwise the scroll event is sent back to an upper level + return false; } -MySpinButton::MySpinButton () { - Gtk::Border border; - border.bottom = 0; - border.top = 0; - border.left = 3; - border.right = 3; - set_inner_border(border); - set_numeric(true); - set_wrap(false); - set_alignment(Gtk::ALIGN_RIGHT); +MySpinButton::MySpinButton () +{ + Gtk::Border border; + border.bottom = 0; + border.top = 0; + border.left = 3; + border.right = 3; + set_inner_border(border); + set_numeric(true); + set_wrap(false); + set_alignment(Gtk::ALIGN_RIGHT); } -void MySpinButton::updateSize() { - double vMin, vMax; - int maxAbs; - unsigned int digits, digits2; - unsigned int maxLen; +void MySpinButton::updateSize() +{ + double vMin, vMax; + int maxAbs; + unsigned int digits, digits2; + unsigned int maxLen; - get_range(vMin, vMax); + get_range(vMin, vMax); - digits = get_digits(); - maxAbs = (int)(fmax(fabs(vMin), fabs(vMax))+0.000001); - if (maxAbs==0) - digits2 = 1; - else { - digits2 = (int)(log10(double(maxAbs))+0.000001); - digits2++; - } - maxLen = digits+digits2+(vMin<0?1:0)+(digits>0?1:0); - set_max_length(maxLen); - set_width_chars(maxLen); + digits = get_digits(); + maxAbs = (int)(fmax(fabs(vMin), fabs(vMax)) + 0.000001); + + if (maxAbs == 0) { + digits2 = 1; + } else { + digits2 = (int)(log10(double(maxAbs)) + 0.000001); + digits2++; + } + + maxLen = digits + digits2 + (vMin < 0 ? 1 : 0) + (digits > 0 ? 1 : 0); + set_max_length(maxLen); + set_width_chars(maxLen); } -bool MySpinButton::on_key_press_event (GdkEventKey* event) { +bool MySpinButton::on_key_press_event (GdkEventKey* event) +{ double vMin, vMax; get_range(vMin, vMax); - if ( (event->string[0] >= 'a' && event->string[0] <= 'z') - ||(event->string[0] >= 'A' && event->string[0] <= 'Z') - || event->string[0] == '+' || (event->string[0] == '-' && vMin >= 0) - || event->string[0] == '=' || event->string[0] == '_' - ) - return false; - else { + + if ( (event->string[0] >= 'a' && event->string[0] <= 'z') + || (event->string[0] >= 'A' && event->string[0] <= 'Z') + || event->string[0] == '+' || (event->string[0] == '-' && vMin >= 0) + || event->string[0] == '=' || event->string[0] == '_' + ) { + return false; + } else { if(event->string[0] == ',') { event->keyval = GDK_period; event->string[0] = '.'; } - return Gtk::Widget::on_key_press_event(event); + + return Gtk::Widget::on_key_press_event(event); } } -bool MySpinButton::on_scroll_event (GdkEventScroll* event) { - // If Shift is pressed, the widget is modified - if (event->state & GDK_SHIFT_MASK) { - Gtk::SpinButton::on_scroll_event(event); - return true; - } - // ... otherwise the scroll event is sent back to an upper level - return false; +bool MySpinButton::on_scroll_event (GdkEventScroll* event) +{ + // If Shift is pressed, the widget is modified + if (event->state & GDK_SHIFT_MASK) { + Gtk::SpinButton::on_scroll_event(event); + return true; + } + + // ... otherwise the scroll event is sent back to an upper level + return false; } -bool MyHScale::on_scroll_event (GdkEventScroll* event) { +bool MyHScale::on_scroll_event (GdkEventScroll* event) +{ - // If Shift is pressed, the widget is modified - if (event->state & GDK_SHIFT_MASK) { - Gtk::HScale::on_scroll_event(event); - return true; - } - // ... otherwise the scroll event is sent back to an upper level - return false; + // If Shift is pressed, the widget is modified + if (event->state & GDK_SHIFT_MASK) { + Gtk::HScale::on_scroll_event(event); + return true; + } + + // ... otherwise the scroll event is sent back to an upper level + return false; } -bool MyHScale::on_key_press_event (GdkEventKey* event) { +bool MyHScale::on_key_press_event (GdkEventKey* event) +{ - if ( event->string[0] == '+' || event->string[0] == '-' ) - return false; - else - return Gtk::Widget::on_key_press_event(event); + if ( event->string[0] == '+' || event->string[0] == '-' ) { + return false; + } else { + return Gtk::Widget::on_key_press_event(event); + } } -MyFileChooserButton::MyFileChooserButton (const Glib::ustring& title, Gtk::FileChooserAction action) : Gtk::FileChooserButton(title, action) { - set_size_request(20, -1); +MyFileChooserButton::MyFileChooserButton (const Glib::ustring& title, Gtk::FileChooserAction action) : Gtk::FileChooserButton(title, action) +{ + set_size_request(20, -1); } // For an unknown reason (a bug ?), it doesn't work when action = FILE_CHOOSER_ACTION_SELECT_FOLDER ! -bool MyFileChooserButton::on_scroll_event (GdkEventScroll* event) { +bool MyFileChooserButton::on_scroll_event (GdkEventScroll* event) +{ - // If Shift is pressed, the widget is modified - if (event->state & GDK_SHIFT_MASK) { - Gtk::FileChooserButton::on_scroll_event(event); - return true; - } - // ... otherwise the scroll event is sent back to an upper level - return false; + // If Shift is pressed, the widget is modified + if (event->state & GDK_SHIFT_MASK) { + Gtk::FileChooserButton::on_scroll_event(event); + return true; + } + + // ... otherwise the scroll event is sent back to an upper level + return false; } FileChooserLastFolderPersister::FileChooserLastFolderPersister( - Gtk::FileChooser* chooser, Glib::ustring& folderVariable) : - chooser(chooser), folderVariable(folderVariable) { - assert(chooser != NULL); + Gtk::FileChooser* chooser, Glib::ustring& folderVariable) : + chooser(chooser), folderVariable(folderVariable) +{ + assert(chooser != NULL); - selectionChangedConnetion = chooser->signal_selection_changed().connect( - sigc::mem_fun(*this, - &FileChooserLastFolderPersister::selectionChanged)); + selectionChangedConnetion = chooser->signal_selection_changed().connect( + sigc::mem_fun(*this, + &FileChooserLastFolderPersister::selectionChanged)); - if (!folderVariable.empty()) { - chooser->set_current_folder(folderVariable); - } + if (!folderVariable.empty()) { + chooser->set_current_folder(folderVariable); + } } -FileChooserLastFolderPersister::~FileChooserLastFolderPersister() { +FileChooserLastFolderPersister::~FileChooserLastFolderPersister() +{ } -void FileChooserLastFolderPersister::selectionChanged() { +void FileChooserLastFolderPersister::selectionChanged() +{ - if (!chooser->get_current_folder().empty()) { - folderVariable = chooser->get_current_folder(); - } + if (!chooser->get_current_folder().empty()) { + folderVariable = chooser->get_current_folder(); + } } -TextOrIcon::TextOrIcon (Glib::ustring fname, Glib::ustring labelTx, Glib::ustring tooltipTx, TOITypes type) { +TextOrIcon::TextOrIcon (Glib::ustring fname, Glib::ustring labelTx, Glib::ustring tooltipTx, TOITypes type) +{ - imgIcon = 0; - label = 0; - filename = fname; - labelText = labelTx; - tooltipText = tooltipTx; + imgIcon = 0; + label = 0; + filename = fname; + labelText = labelTx; + tooltipText = tooltipTx; - switchTo(type); + switchTo(type); } -TextOrIcon::~TextOrIcon () { - if (imgIcon) delete imgIcon; - if (label) delete label; +TextOrIcon::~TextOrIcon () +{ + if (imgIcon) { + delete imgIcon; + } + + if (label) { + delete label; + } } -void TextOrIcon::switchTo(TOITypes type) { - switch (type) { - case (TOI_ICON): - if (!imgIcon) { - removeIfThere(this, label, false); - delete label; - label = 0; - imgIcon = new RTImage (filename); - pack_start(*imgIcon, Gtk::PACK_SHRINK, 0); - set_tooltip_markup ("" + labelText + "\n" + tooltipText); - } - // do nothing if imgIcon exist, which mean that it is currently being displayed - break; - case(TOI_TEXT): - default: - if (!label) { - removeIfThere(this, imgIcon, false); - delete imgIcon; - imgIcon = 0; - label = new Gtk::Label (labelText, Gtk::ALIGN_CENTER); - pack_start(*label, Gtk::PACK_EXPAND_WIDGET, 0); - set_tooltip_markup (tooltipText); - } - // do nothing if label exist, which mean that it is currently being displayed - break; - } - show_all(); +void TextOrIcon::switchTo(TOITypes type) +{ + switch (type) { + case (TOI_ICON): + if (!imgIcon) { + removeIfThere(this, label, false); + delete label; + label = 0; + imgIcon = new RTImage (filename); + pack_start(*imgIcon, Gtk::PACK_SHRINK, 0); + set_tooltip_markup ("" + labelText + "\n" + tooltipText); + } + + // do nothing if imgIcon exist, which mean that it is currently being displayed + break; + + case(TOI_TEXT): + default: + if (!label) { + removeIfThere(this, imgIcon, false); + delete imgIcon; + imgIcon = 0; + label = new Gtk::Label (labelText, Gtk::ALIGN_CENTER); + pack_start(*label, Gtk::PACK_EXPAND_WIDGET, 0); + set_tooltip_markup (tooltipText); + } + + // do nothing if label exist, which mean that it is currently being displayed + break; + } + + show_all(); } -BackBuffer::BackBuffer() : x(0), y(0), w(0), h(0), offset(0,0), dirty(true) {} +BackBuffer::BackBuffer() : x(0), y(0), w(0), h(0), offset(0, 0), dirty(true) {} -void BackBuffer::setSrcOffset(int x, int y) { - // values will be clamped when used... - offset.x = x; - offset.y = y; +void BackBuffer::setSrcOffset(int x, int y) +{ + // values will be clamped when used... + offset.x = x; + offset.y = y; } // Note: newW & newH must be > 0 -bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize) { - assert(newW && newH); +bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize) +{ + assert(newW && newH); - bool newSize = w!=newW || h!=newH; + bool newSize = w != newW || h != newH; - x = newX; - y = newY; - w = newW; - h = newH; + x = newX; + y = newY; + w = newW; + h = newH; - // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!? - if (updateBackBufferSize && newSize && window) { - // allocate a new Surface - surface.clear(); // ... don't know if this is necessary? - surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h); - dirty = true; - } - return dirty; + // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!? + if (updateBackBufferSize && newSize && window) { + // allocate a new Surface + surface.clear(); // ... don't know if this is necessary? + surface = Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, w, h); + dirty = true; + } + + return dirty; } // Note: newW & newH must be > 0 -bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize) { - assert(!newW && !newH); +bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize) +{ + assert(!newW && !newH); - bool newSize = w!=newW || h!=newH; + bool newSize = w != newW || h != newH; - x = newX; - y = newY; - w = newW; - h = newH; + x = newX; + y = newY; + w = newW; + h = newH; - // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!? - if (updateBackBufferSize && newSize) { - // allocate a new Surface - surface.clear(); // ... don't know if this is necessary? - surface = Cairo::ImageSurface::create(format, w, h); - dirty = true; - } - return dirty; + // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!? + if (updateBackBufferSize && newSize) { + // allocate a new Surface + surface.clear(); // ... don't know if this is necessary? + surface = Cairo::ImageSurface::create(format, w, h); + dirty = true; + } + + return dirty; } /* * Copy the backbuffer to a Gdk::Window */ -void BackBuffer::copySurface(Glib::RefPtr window, GdkRectangle *rectangle) { - if (surface && window) { - // TODO: look out if window can be different on each call, and if not, store a reference to the window - Cairo::RefPtr crSrc = window->create_cairo_context(); - Cairo::RefPtr destSurface = crSrc->get_target(); +void BackBuffer::copySurface(Glib::RefPtr window, GdkRectangle *rectangle) +{ + if (surface && window) { + // TODO: look out if window can be different on each call, and if not, store a reference to the window + Cairo::RefPtr crSrc = window->create_cairo_context(); + Cairo::RefPtr destSurface = crSrc->get_target(); - // compute the source offset - int offsetX = rtengine::LIM(offset.x,0, surface->get_width()); - int offsetY = rtengine::LIM(offset.y,0, surface->get_height()); + // compute the source offset + int offsetX = rtengine::LIM(offset.x, 0, surface->get_width()); + int offsetY = rtengine::LIM(offset.y, 0, surface->get_height()); - // now copy the off-screen Surface to the destination Surface - Cairo::RefPtr crDest = Cairo::Context::create(destSurface); - crDest->set_source(surface, x-offsetX, y-offsetY); - crDest->set_line_width(0.); - if (rectangle) - crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); - else - crDest->rectangle(x, y, w, h); - crDest->fill(); - } + // now copy the off-screen Surface to the destination Surface + Cairo::RefPtr crDest = Cairo::Context::create(destSurface); + crDest->set_source(surface, x - offsetX, y - offsetY); + crDest->set_line_width(0.); + + if (rectangle) { + crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); + } else { + crDest->rectangle(x, y, w, h); + } + + crDest->fill(); + } } /* * Copy the BackBuffer to another BackBuffer */ -void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle) { - if (surface && destBackBuffer) { - // compute the source offset - int offsetX = rtengine::LIM(offset.x,0, surface->get_width()); - int offsetY = rtengine::LIM(offset.y,0, surface->get_height()); +void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle) +{ + if (surface && destBackBuffer) { + // compute the source offset + int offsetX = rtengine::LIM(offset.x, 0, surface->get_width()); + int offsetY = rtengine::LIM(offset.y, 0, surface->get_height()); - // now copy the off-screen Surface to the destination Surface - Cairo::RefPtr crDest = Cairo::Context::create(destBackBuffer->getSurface()); - crDest->set_source(surface, x-offsetX, y-offsetY); - crDest->set_line_width(0.); - if (rectangle) - crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); - else - crDest->rectangle(x, y, w, h); - crDest->fill(); - } + // now copy the off-screen Surface to the destination Surface + Cairo::RefPtr crDest = Cairo::Context::create(destBackBuffer->getSurface()); + crDest->set_source(surface, x - offsetX, y - offsetY); + crDest->set_line_width(0.); + + if (rectangle) { + crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); + } else { + crDest->rectangle(x, y, w, h); + } + + crDest->fill(); + } } /* * Copy the BackBuffer to another Cairo::Surface */ -void BackBuffer::copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle) { - if (surface && destSurface) { - // compute the source offset - int offsetX = rtengine::LIM(offset.x,0, surface->get_width()); - int offsetY = rtengine::LIM(offset.y,0, surface->get_height()); +void BackBuffer::copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle) +{ + if (surface && destSurface) { + // compute the source offset + int offsetX = rtengine::LIM(offset.x, 0, surface->get_width()); + int offsetY = rtengine::LIM(offset.y, 0, surface->get_height()); - // now copy the off-screen Surface to the destination Surface - Cairo::RefPtr crDest = Cairo::Context::create(destSurface); - crDest->set_source(surface, x-offsetX, y-offsetY); - crDest->set_line_width(0.); - if (rectangle) - crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); - else - crDest->rectangle(x, y, w, h); - crDest->fill(); - } + // now copy the off-screen Surface to the destination Surface + Cairo::RefPtr crDest = Cairo::Context::create(destSurface); + crDest->set_source(surface, x - offsetX, y - offsetY); + crDest->set_line_width(0.); + + if (rectangle) { + crDest->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); + } else { + crDest->rectangle(x, y, w, h); + } + + crDest->fill(); + } } diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index 3221ba19b..1e65f2753 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -7,7 +7,7 @@ * 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 @@ -25,7 +25,7 @@ #include Glib::ustring escapeHtmlChars(const Glib::ustring &src); -bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference=true); +bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference = true); void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh); Glib::ustring removeExtension (const Glib::ustring& filename); Glib::ustring getExtension (const Glib::ustring& filename); @@ -33,7 +33,7 @@ bool confirmOverwrite (Gtk::Window& parent, const std::string& filename); void writeFailed (Gtk::Window& parent, const std::string& filename); void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams, bool drawGuide = true, bool useBgColor = true, bool fullImageVisible = true); -/** +/** * @brief Lock GTK for critical section. * * Will unlock on destruction. To use: @@ -48,17 +48,17 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int class GThreadLock { public: - GThreadLock() - { - gdk_threads_enter(); - } - ~GThreadLock() - { - gdk_threads_leave(); - } + GThreadLock() + { + gdk_threads_enter(); + } + ~GThreadLock() + { + gdk_threads_leave(); + } }; -/** +/** * @brief Unlock GTK critical section. * * Will relock on destruction. @@ -66,14 +66,14 @@ public: class GThreadUnLock { public: - GThreadUnLock() - { - gdk_threads_leave(); - } - ~GThreadUnLock() - { - gdk_threads_enter(); - } + GThreadUnLock() + { + gdk_threads_leave(); + } + ~GThreadUnLock() + { + gdk_threads_enter(); + } }; /** @@ -82,24 +82,27 @@ public: class ExpanderBox: public Gtk::EventBox { private: - Gtk::Container *pC; + Gtk::Container *pC; public: - ExpanderBox( Gtk::Container *p); - ~ExpanderBox( ){ delete pC;} + ExpanderBox( Gtk::Container *p); + ~ExpanderBox( ) + { + delete pC; + } - void updateStyle(); + void updateStyle(); - void show() {} - void show_all(); - void hide() {} - void set_visible(bool isVisible=true) {} + void show() {} + void show_all(); + void hide() {} + void set_visible(bool isVisible = true) {} - void showBox(); - void hideBox(); + void showBox(); + void hideBox(); - void on_style_changed (const Glib::RefPtr& style); - bool on_expose_event(GdkEventExpose* event); + void on_style_changed (const Glib::RefPtr& style); + bool on_expose_event(GdkEventExpose* event); }; /** @@ -110,171 +113,187 @@ public: * * Warning: once you've instantiated this class with a text label or a widget label, you won't be able to revert to the other solution. */ -class MyExpander : public Gtk::VBox { +class MyExpander : public Gtk::VBox +{ public: - typedef sigc::signal type_signal_enabled_toggled; + typedef sigc::signal type_signal_enabled_toggled; private: - type_signal_enabled_toggled message; - static Glib::RefPtr inconsistentPBuf; /// "inconsistent" image, displayed when useEnabled is true ; in this case, nothing will tell that an expander is opened/closed - static Glib::RefPtr enabledPBuf; /// "enabled" image, displayed when useEnabled is true ; in this case, nothing will tell that an expander is opened/closed - static Glib::RefPtr disabledPBuf; /// "disabled" image, displayed when useEnabled is true ; in this case, nothing will tell that an expander is opened/closed - static Glib::RefPtr openedPBuf; /// "opened" image, displayed when useEnabled is false - static Glib::RefPtr closedPBuf; /// "closed" image, displayed when useEnabled is false - bool enabled; /// Enabled feature (default to true) - bool inconsistent; /// True if the enabled button is inconsistent - Gtk::EventBox *titleEvBox; /// EventBox of the title, to get a connector from it - Gtk::HBox *headerHBox; - bool flushEvent; /// Flag to control the weird event mechanism of Gtk (please prove me wrong!) - ExpanderBox* expBox; /// Frame that includes the child and control its visibility - Gtk::EventBox *imageEvBox; /// Enable/Disable or Open/Close arrow event box + type_signal_enabled_toggled message; + static Glib::RefPtr inconsistentPBuf; /// "inconsistent" image, displayed when useEnabled is true ; in this case, nothing will tell that an expander is opened/closed + static Glib::RefPtr enabledPBuf; /// "enabled" image, displayed when useEnabled is true ; in this case, nothing will tell that an expander is opened/closed + static Glib::RefPtr disabledPBuf; /// "disabled" image, displayed when useEnabled is true ; in this case, nothing will tell that an expander is opened/closed + static Glib::RefPtr openedPBuf; /// "opened" image, displayed when useEnabled is false + static Glib::RefPtr closedPBuf; /// "closed" image, displayed when useEnabled is false + bool enabled; /// Enabled feature (default to true) + bool inconsistent; /// True if the enabled button is inconsistent + Gtk::EventBox *titleEvBox; /// EventBox of the title, to get a connector from it + Gtk::HBox *headerHBox; + bool flushEvent; /// Flag to control the weird event mechanism of Gtk (please prove me wrong!) + ExpanderBox* expBox; /// Frame that includes the child and control its visibility + Gtk::EventBox *imageEvBox; /// Enable/Disable or Open/Close arrow event box - /// Triggered on opened/closed event - bool on_toggle(GdkEventButton* event); - /// Triggered on enabled/disabled change -> will emit a toggle event to the connected objects - bool on_enabled_change(GdkEventButton* event); - /// Used to handle the colored background for the whole Title - bool on_enter_leave_title (GdkEventCrossing* event); - /// Used to handle the colored background for the Enable button - bool on_enter_leave_enable (GdkEventCrossing* event); - /// Update the style of this widget, depending in the "slim" option - void updateStyle(); + /// Triggered on opened/closed event + bool on_toggle(GdkEventButton* event); + /// Triggered on enabled/disabled change -> will emit a toggle event to the connected objects + bool on_enabled_change(GdkEventButton* event); + /// Used to handle the colored background for the whole Title + bool on_enter_leave_title (GdkEventCrossing* event); + /// Used to handle the colored background for the Enable button + bool on_enter_leave_enable (GdkEventCrossing* event); + /// Update the style of this widget, depending in the "slim" option + void updateStyle(); - void on_style_changed (const Glib::RefPtr& style) { updateStyle(); } + void on_style_changed (const Glib::RefPtr& style) + { + updateStyle(); + } protected: - Gtk::Container* child; /// Gtk::Contained to display below the expander's title - Gtk::Widget* headerWidget; /// Widget to display in the header, next to the arrow image ; can be NULL if the "string" version of the ctor has been used - Gtk::Image* statusImage; /// Image to display the opened/closed status (if useEnabled is false) of the enabled/disabled status (if useEnabled is true) - Gtk::Label* label; /// Text to display in the header, next to the arrow image ; can be NULL if the "widget" version of the ctor has been used - bool useEnabled; /// Set whether to handle an enabled/disabled feature and display the appropriate images + Gtk::Container* child; /// Gtk::Contained to display below the expander's title + Gtk::Widget* headerWidget; /// Widget to display in the header, next to the arrow image ; can be NULL if the "string" version of the ctor has been used + Gtk::Image* statusImage; /// Image to display the opened/closed status (if useEnabled is false) of the enabled/disabled status (if useEnabled is true) + Gtk::Label* label; /// Text to display in the header, next to the arrow image ; can be NULL if the "widget" version of the ctor has been used + bool useEnabled; /// Set whether to handle an enabled/disabled feature and display the appropriate images public: - /** @brief Create a custom expander with a simple header made of a label. - * @param useEnabled Set whether to handle an enabled/disabled toggle button and display the appropriate image - * @param titleLabel A string to display in the header. Warning: you won't be able to switch to a widget label. - */ - MyExpander(bool useEnabled, Glib::ustring titleLabel); + /** @brief Create a custom expander with a simple header made of a label. + * @param useEnabled Set whether to handle an enabled/disabled toggle button and display the appropriate image + * @param titleLabel A string to display in the header. Warning: you won't be able to switch to a widget label. + */ + MyExpander(bool useEnabled, Glib::ustring titleLabel); - /** Create a custom expander with a a custom - and responsive - widget - * @param useEnabled Set whether to handle an enabled/disabled toggle button and display the appropriate image - * @param titleWidget A widget to display in the header. Warning: you won't be able to switch to a string label. - */ - MyExpander(bool useEnabled, Gtk::Widget* titleWidget); + /** Create a custom expander with a a custom - and responsive - widget + * @param useEnabled Set whether to handle an enabled/disabled toggle button and display the appropriate image + * @param titleWidget A widget to display in the header. Warning: you won't be able to switch to a string label. + */ + MyExpander(bool useEnabled, Gtk::Widget* titleWidget); - /// Initialize the class by loading the images - static void init(); + /// Initialize the class by loading the images + static void init(); - Glib::SignalProxy1< bool,GdkEventButton* > signal_button_release_event() { return titleEvBox->signal_button_release_event(); }; - type_signal_enabled_toggled signal_enabled_toggled(); + Glib::SignalProxy1< bool, GdkEventButton* > signal_button_release_event() + { + return titleEvBox->signal_button_release_event(); + }; + type_signal_enabled_toggled signal_enabled_toggled(); - /// Set a new label string. If it has been instantiated with a Gtk::Widget, this method will do nothing - void setLabel (Glib::ustring newLabel); - /// Set a new label string. If it has been instantiated with a Gtk::Widget, this method will do nothing - void setLabel (Gtk::Widget *newWidget); + /// Set a new label string. If it has been instantiated with a Gtk::Widget, this method will do nothing + void setLabel (Glib::ustring newLabel); + /// Set a new label string. If it has been instantiated with a Gtk::Widget, this method will do nothing + void setLabel (Gtk::Widget *newWidget); - /// Get whether the enabled option is set (to true or false) or unset (i.e. undefined) - bool get_inconsistent(); - /// Set whether the enabled option is set (to true or false) or unset (i.e. undefined) - void set_inconsistent(bool isInconsistent); + /// Get whether the enabled option is set (to true or false) or unset (i.e. undefined) + bool get_inconsistent(); + /// Set whether the enabled option is set (to true or false) or unset (i.e. undefined) + void set_inconsistent(bool isInconsistent); - /// Get whether the enabled button is used or not - bool getUseEnabled(); - /// Get whether the enabled button is on or off - bool getEnabled(); - /// If not inconsistent, set the enabled button to true or false and emit the message if the state is different - /// If inconsistent, set the internal value to true or false, but do not update the image and do not emit the message - void setEnabled(bool isEnabled); - /// Adds a Tooltip to the Enabled button, if it exist ; do nothing otherwise - void setEnabledTooltipMarkup(Glib::ustring tooltipMarkup); - void setEnabledTooltipText(Glib::ustring tooltipText); + /// Get whether the enabled button is used or not + bool getUseEnabled(); + /// Get whether the enabled button is on or off + bool getEnabled(); + /// If not inconsistent, set the enabled button to true or false and emit the message if the state is different + /// If inconsistent, set the internal value to true or false, but do not update the image and do not emit the message + void setEnabled(bool isEnabled); + /// Adds a Tooltip to the Enabled button, if it exist ; do nothing otherwise + void setEnabledTooltipMarkup(Glib::ustring tooltipMarkup); + void setEnabledTooltipText(Glib::ustring tooltipText); - /// Get the header widget. It'll send back the Gtk::Label* if it has been instantiated with a simple text - Gtk::Widget* getLabelWidget() const { return headerWidget ? headerWidget : label; } + /// Get the header widget. It'll send back the Gtk::Label* if it has been instantiated with a simple text + Gtk::Widget* getLabelWidget() const + { + return headerWidget ? headerWidget : label; + } - /// Get the widget shown/hidden by the expander - Gtk::Container* getChild(); + /// Get the widget shown/hidden by the expander + Gtk::Container* getChild(); - /// Set the collapsed/expanded state of the expander - void set_expanded( bool expanded ); + /// Set the collapsed/expanded state of the expander + void set_expanded( bool expanded ); - /// Get the collapsed/expanded state of the expander - bool get_expanded(); + /// Get the collapsed/expanded state of the expander + bool get_expanded(); - /// Add a Gtk::Container for the content of the expander - /// Warning: do not manually Show/Hide the widget, because this parameter is handled by the click on the Expander's title - void add (Gtk::Container& widget); + /// Add a Gtk::Container for the content of the expander + /// Warning: do not manually Show/Hide the widget, because this parameter is handled by the click on the Expander's title + void add (Gtk::Container& widget); }; /** * @brief subclass of Gtk::ScrolledWindow in order to handle the scrollwheel */ -class MyScrolledWindow : public Gtk::ScrolledWindow { +class MyScrolledWindow : public Gtk::ScrolledWindow +{ - bool on_scroll_event (GdkEventScroll* event); + bool on_scroll_event (GdkEventScroll* event); public: - MyScrolledWindow(); + MyScrolledWindow(); }; /** * @brief subclass of Gtk::ComboBox in order to handle the scrollwheel */ -class MyComboBox : public Gtk::ComboBox { +class MyComboBox : public Gtk::ComboBox +{ - bool on_scroll_event (GdkEventScroll* event); + bool on_scroll_event (GdkEventScroll* event); public: - MyComboBox (); + MyComboBox (); }; /** * @brief subclass of Gtk::ComboBoxText in order to handle the scrollwheel */ -class MyComboBoxText : public Gtk::ComboBoxText { +class MyComboBoxText : public Gtk::ComboBoxText +{ - bool on_scroll_event (GdkEventScroll* event); + bool on_scroll_event (GdkEventScroll* event); public: - MyComboBoxText (); + MyComboBoxText (); }; /** * @brief subclass of Gtk::SpinButton in order to handle the scrollwheel */ -class MySpinButton : public Gtk::SpinButton { +class MySpinButton : public Gtk::SpinButton +{ protected: - bool on_scroll_event (GdkEventScroll* event); - bool on_key_press_event (GdkEventKey* event); + bool on_scroll_event (GdkEventScroll* event); + bool on_key_press_event (GdkEventKey* event); public: - MySpinButton (); - void updateSize(); + MySpinButton (); + void updateSize(); }; /** * @brief subclass of Gtk::HScale in order to handle the scrollwheel */ -class MyHScale : public Gtk::HScale { +class MyHScale : public Gtk::HScale +{ - bool on_scroll_event (GdkEventScroll* event); - bool on_key_press_event (GdkEventKey* event); + bool on_scroll_event (GdkEventScroll* event); + bool on_key_press_event (GdkEventKey* event); }; /** * @brief subclass of Gtk::FileChooserButton in order to handle the scrollwheel */ -class MyFileChooserButton : public Gtk::FileChooserButton { +class MyFileChooserButton : public Gtk::FileChooserButton +{ protected: - bool on_scroll_event (GdkEventScroll* event); + bool on_scroll_event (GdkEventScroll* event); public: - MyFileChooserButton (const Glib::ustring& title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN); + MyFileChooserButton (const Glib::ustring& title, Gtk::FileChooserAction action = Gtk::FILE_CHOOSER_ACTION_OPEN); }; /** @@ -284,149 +303,197 @@ public: * with the associated folder. The path found in the variable is set in the * dialog instance at constructions time of this object. */ -class FileChooserLastFolderPersister: public Glib::Object { +class FileChooserLastFolderPersister: public Glib::Object +{ public: - /** - * Installs this persister on the provided GtkFileChooser instance and - * applies the current folder found in @p folderVariable for the dialog. - * - * @param chooser file chooser to maintain - * @param folderVariable variable storage to use for this dialog - */ - FileChooserLastFolderPersister(Gtk::FileChooser* chooser, Glib::ustring& folderVariable); + /** + * Installs this persister on the provided GtkFileChooser instance and + * applies the current folder found in @p folderVariable for the dialog. + * + * @param chooser file chooser to maintain + * @param folderVariable variable storage to use for this dialog + */ + FileChooserLastFolderPersister(Gtk::FileChooser* chooser, Glib::ustring& folderVariable); - virtual ~FileChooserLastFolderPersister(); + virtual ~FileChooserLastFolderPersister(); private: - /** - * Signal handler for the GtkFileChooser selection action. - */ - void selectionChanged(); + /** + * Signal handler for the GtkFileChooser selection action. + */ + void selectionChanged(); - Gtk::FileChooser* chooser; - Glib::ustring& folderVariable; - sigc::connection selectionChangedConnetion; + Gtk::FileChooser* chooser; + Glib::ustring& folderVariable; + sigc::connection selectionChangedConnetion; }; typedef enum RTUpdatePolicy { - RTUP_STATIC, - RTUP_DYNAMIC + RTUP_STATIC, + RTUP_DYNAMIC } eUpdatePolicy; typedef enum RTOrientation { - RTO_Left2Right, - RTO_Bottom2Top, - RTO_Right2Left, - RTO_Top2Bottom + RTO_Left2Right, + RTO_Bottom2Top, + RTO_Right2Left, + RTO_Top2Bottom } eRTOrientation; enum TOITypes { - TOI_TEXT, - TOI_ICON + TOI_TEXT, + TOI_ICON }; typedef enum RTNav { - NAV_NONE, - NAV_NEXT, - NAV_PREVIOUS + NAV_NONE, + NAV_NEXT, + NAV_PREVIOUS } eRTNav; /** * @brief Handle the switch between text and image to be displayed in the HBox (to be used in a button/toolpanel) */ -class TextOrIcon : public Gtk::HBox { +class TextOrIcon : public Gtk::HBox +{ protected: - Gtk::Image* imgIcon; - Gtk::Label* label; - Glib::ustring filename; - Glib::ustring labelText; - Glib::ustring tooltipText; + Gtk::Image* imgIcon; + Gtk::Label* label; + Glib::ustring filename; + Glib::ustring labelText; + Glib::ustring tooltipText; public: - TextOrIcon (Glib::ustring filename, Glib::ustring labelTx, Glib::ustring tooltipTx, TOITypes type); - ~TextOrIcon (); + TextOrIcon (Glib::ustring filename, Glib::ustring labelTx, Glib::ustring tooltipTx, TOITypes type); + ~TextOrIcon (); - void switchTo(TOITypes type); + void switchTo(TOITypes type); }; /** * @brief Define a gradient milestone */ -class GradientMilestone { +class GradientMilestone +{ public: - double position; - double r; - double g; - double b; - double a; + double position; + double r; + double g; + double b; + double a; - GradientMilestone(double _p=0., double _r=0., double _g=0., double _b=0., double _a=0.) { - position = _p; r = _r; g = _g; b = _b; a = _a; - } + GradientMilestone(double _p = 0., double _r = 0., double _g = 0., double _b = 0., double _a = 0.) + { + position = _p; + r = _r; + g = _g; + b = _b; + a = _a; + } }; /** * @brief Handle point coordinates */ template -class Point { +class Point +{ public: - T x, y; - Point() { - x = T(0); - y = T(0); - } + T x, y; + Point() + { + x = T(0); + y = T(0); + } - Point(T coordX, T coordY) { - x = coordX; - y = coordY; - } + Point(T coordX, T coordY) + { + x = coordX; + y = coordY; + } - void setCoords(T coordX, T coordY) { - x = coordX; - y = coordY; - } + void setCoords(T coordX, T coordY) + { + x = coordX; + y = coordY; + } }; /** * @brief Handle backbuffers as automatically as possible */ -class BackBuffer { +class BackBuffer +{ protected: - int x, y, w, h; // Rectangle where the colored bar has to be drawn - Point offset; // Offset of the source region to draw, relative to the top left corner - Cairo::RefPtr surface; - bool dirty; // mean that the Surface has to be (re)allocated + int x, y, w, h; // Rectangle where the colored bar has to be drawn + Point offset; // Offset of the source region to draw, relative to the top left corner + Cairo::RefPtr surface; + bool dirty; // mean that the Surface has to be (re)allocated public: - BackBuffer(); + BackBuffer(); - // set the destination drawing rectangle; return true if the dimensions are different - // Note: newW & newH must be > 0 - bool setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize=true); - bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize=true); - void setSrcOffset(int x, int y); + // set the destination drawing rectangle; return true if the dimensions are different + // Note: newW & newH must be > 0 + bool setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize = true); + bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize = true); + void setSrcOffset(int x, int y); - void copySurface(Glib::RefPtr window, GdkRectangle *rectangle=NULL); - void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle=NULL); - void copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle=NULL); + void copySurface(Glib::RefPtr window, GdkRectangle *rectangle = NULL); + void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle = NULL); + void copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle = NULL); - void setDirty(bool isDirty) { dirty = isDirty; if (!dirty && !surface) dirty = true; } - bool isDirty() { return dirty; } - // you have to check if the surface is created thanks to surfaceCreated before starting to draw on it - bool surfaceCreated() { return surface; } - Cairo::RefPtr getSurface() { return surface; } - void setSurface(Cairo::RefPtr surf) { surface = surf; } - void deleteSurface() { if (surface) surface.clear(); dirty=true; } - // will let you get a Cairo::Context for Cairo drawing operations - Cairo::RefPtr getContext() { return Cairo::Context::create(surface); } - int getWidth() { return surface ? surface->get_width() : 0; } - int getHeight() { return surface ? surface->get_height() : 0; } + void setDirty(bool isDirty) + { + dirty = isDirty; + + if (!dirty && !surface) { + dirty = true; + } + } + bool isDirty() + { + return dirty; + } + // you have to check if the surface is created thanks to surfaceCreated before starting to draw on it + bool surfaceCreated() + { + return surface; + } + Cairo::RefPtr getSurface() + { + return surface; + } + void setSurface(Cairo::RefPtr surf) + { + surface = surf; + } + void deleteSurface() + { + if (surface) { + surface.clear(); + } + + dirty = true; + } + // will let you get a Cairo::Context for Cairo drawing operations + Cairo::RefPtr getContext() + { + return Cairo::Context::create(surface); + } + int getWidth() + { + return surface ? surface->get_width() : 0; + } + int getHeight() + { + return surface ? surface->get_height() : 0; + } }; diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 2c9794f1d..e5d3d560e 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -7,7 +7,7 @@ * 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 @@ -36,154 +36,178 @@ extern Options options; // // // HistogramPanel -HistogramPanel::HistogramPanel () { +HistogramPanel::HistogramPanel () +{ - histogramArea = Gtk::manage (new HistogramArea (this)); - histogramRGBArea = Gtk::manage (new HistogramRGBArea ()); - histogramRGBArea->show(); + histogramArea = Gtk::manage (new HistogramArea (this)); + histogramRGBArea = Gtk::manage (new HistogramRGBArea ()); + histogramRGBArea->show(); - gfxVBox = Gtk::manage (new Gtk::VBox (false, 2)); - histogramRGBArea->setParent(gfxVBox); - gfxVBox->pack_start (*histogramArea, Gtk::PACK_EXPAND_WIDGET, 0); - if (options.histogramBar) - gfxVBox->pack_start (*histogramRGBArea, Gtk::PACK_SHRINK, 0); + gfxVBox = Gtk::manage (new Gtk::VBox (false, 2)); + histogramRGBArea->setParent(gfxVBox); + gfxVBox->pack_start (*histogramArea, Gtk::PACK_EXPAND_WIDGET, 0); - redImage = new RTImage ("histRed.png"); - greenImage = new RTImage ("histGreen.png"); - blueImage = new RTImage ("histBlue.png"); - valueImage = new RTImage ("histValue.png"); - chroImage = new RTImage ("histChro.png"); - rawImage = new RTImage ("histRaw.png"); - fullImage = new RTImage ("histFull.png"); - barImage = new RTImage ("histBar.png"); + if (options.histogramBar) { + gfxVBox->pack_start (*histogramRGBArea, Gtk::PACK_SHRINK, 0); + } - redImage_g = new RTImage ("histRedg.png"); - greenImage_g = new RTImage ("histGreeng.png"); - blueImage_g = new RTImage ("histBlueg.png"); - valueImage_g = new RTImage ("histValueg.png"); - chroImage_g = new RTImage ("histChrog.png"); - rawImage_g = new RTImage ("histRawg.png"); - fullImage_g = new RTImage ("histFullg.png"); - barImage_g = new RTImage ("histBarg.png"); + redImage = new RTImage ("histRed.png"); + greenImage = new RTImage ("histGreen.png"); + blueImage = new RTImage ("histBlue.png"); + valueImage = new RTImage ("histValue.png"); + chroImage = new RTImage ("histChro.png"); + rawImage = new RTImage ("histRaw.png"); + fullImage = new RTImage ("histFull.png"); + barImage = new RTImage ("histBar.png"); - showRed = Gtk::manage (new Gtk::ToggleButton ()); - showGreen = Gtk::manage (new Gtk::ToggleButton ()); - showBlue = Gtk::manage (new Gtk::ToggleButton ()); - showValue = Gtk::manage (new Gtk::ToggleButton ()); - showChro = Gtk::manage (new Gtk::ToggleButton ()); - showRAW = Gtk::manage (new Gtk::ToggleButton ()); - showFull = Gtk::manage (new Gtk::ToggleButton ()); - showBAR = Gtk::manage (new Gtk::ToggleButton ()); + redImage_g = new RTImage ("histRedg.png"); + greenImage_g = new RTImage ("histGreeng.png"); + blueImage_g = new RTImage ("histBlueg.png"); + valueImage_g = new RTImage ("histValueg.png"); + chroImage_g = new RTImage ("histChrog.png"); + rawImage_g = new RTImage ("histRawg.png"); + fullImage_g = new RTImage ("histFullg.png"); + barImage_g = new RTImage ("histBarg.png"); - showRed->set_name("histButton"); showRed->set_can_focus(false); - showGreen->set_name("histButton"); showGreen->set_can_focus(false); - showBlue->set_name("histButton"); showBlue->set_can_focus(false); - showValue->set_name("histButton"); showValue->set_can_focus(false); - showChro->set_name("histButton"); showChro->set_can_focus(false); - showRAW->set_name("histButton"); showRAW->set_can_focus(false); - showFull->set_name("fullButton"); showFull->set_can_focus(false); - showBAR->set_name("histButton"); showBAR->set_can_focus(false); + showRed = Gtk::manage (new Gtk::ToggleButton ()); + showGreen = Gtk::manage (new Gtk::ToggleButton ()); + showBlue = Gtk::manage (new Gtk::ToggleButton ()); + showValue = Gtk::manage (new Gtk::ToggleButton ()); + showChro = Gtk::manage (new Gtk::ToggleButton ()); + showRAW = Gtk::manage (new Gtk::ToggleButton ()); + showFull = Gtk::manage (new Gtk::ToggleButton ()); + showBAR = Gtk::manage (new Gtk::ToggleButton ()); - showRed->set_relief (Gtk::RELIEF_NONE); - showGreen->set_relief (Gtk::RELIEF_NONE); - showBlue->set_relief (Gtk::RELIEF_NONE); - showValue->set_relief (Gtk::RELIEF_NONE); - showChro->set_relief (Gtk::RELIEF_NONE); - showRAW->set_relief (Gtk::RELIEF_NONE); - showFull->set_relief (Gtk::RELIEF_NONE); - showBAR->set_relief (Gtk::RELIEF_NONE); + showRed->set_name("histButton"); + showRed->set_can_focus(false); + showGreen->set_name("histButton"); + showGreen->set_can_focus(false); + showBlue->set_name("histButton"); + showBlue->set_can_focus(false); + showValue->set_name("histButton"); + showValue->set_can_focus(false); + showChro->set_name("histButton"); + showChro->set_can_focus(false); + showRAW->set_name("histButton"); + showRAW->set_can_focus(false); + showFull->set_name("fullButton"); + showFull->set_can_focus(false); + showBAR->set_name("histButton"); + showBAR->set_can_focus(false); - showRed->set_tooltip_text (M("HISTOGRAM_TOOLTIP_R")); - showGreen->set_tooltip_text (M("HISTOGRAM_TOOLTIP_G")); - showBlue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_B")); - showValue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_L")); - showChro->set_tooltip_text (M("HISTOGRAM_TOOLTIP_CHRO")); - showRAW->set_tooltip_text (M("HISTOGRAM_TOOLTIP_RAW")); - showFull->set_tooltip_text (M("HISTOGRAM_TOOLTIP_FULL")); - showBAR->set_tooltip_text (M("HISTOGRAM_TOOLTIP_BAR")); + showRed->set_relief (Gtk::RELIEF_NONE); + showGreen->set_relief (Gtk::RELIEF_NONE); + showBlue->set_relief (Gtk::RELIEF_NONE); + showValue->set_relief (Gtk::RELIEF_NONE); + showChro->set_relief (Gtk::RELIEF_NONE); + showRAW->set_relief (Gtk::RELIEF_NONE); + showFull->set_relief (Gtk::RELIEF_NONE); + showBAR->set_relief (Gtk::RELIEF_NONE); - buttonVBox = Gtk::manage (new Gtk::VBox (false, 2)); - showRed->set_active (true); - showGreen->set_active (true); - showBlue->set_active (true); - showValue->set_active (true); - showChro->set_active (false);//unactive by default + showRed->set_tooltip_text (M("HISTOGRAM_TOOLTIP_R")); + showGreen->set_tooltip_text (M("HISTOGRAM_TOOLTIP_G")); + showBlue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_B")); + showValue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_L")); + showChro->set_tooltip_text (M("HISTOGRAM_TOOLTIP_CHRO")); + showRAW->set_tooltip_text (M("HISTOGRAM_TOOLTIP_RAW")); + showFull->set_tooltip_text (M("HISTOGRAM_TOOLTIP_FULL")); + showBAR->set_tooltip_text (M("HISTOGRAM_TOOLTIP_BAR")); - showRAW->set_active (false); - showFull->set_active (!options.histogramFullMode); - showBAR->set_active (options.histogramBar); + buttonVBox = Gtk::manage (new Gtk::VBox (false, 2)); + showRed->set_active (true); + showGreen->set_active (true); + showBlue->set_active (true); + showValue->set_active (true); + showChro->set_active (false);//unactive by default - showRed->set_image (showRed->get_active() ? *redImage : *redImage_g); - showGreen->set_image (showGreen->get_active() ? *greenImage : *greenImage_g); - showBlue->set_image (showBlue->get_active() ? *blueImage : *blueImage_g); - showValue->set_image (showValue->get_active() ? *valueImage : *valueImage_g); - showChro->set_image (showChro->get_active() ? *chroImage : *chroImage_g); - showRAW->set_image (showRAW->get_active() ? *rawImage : *rawImage_g); - showFull->set_image (showFull->get_active() ? *fullImage : *fullImage_g); - showBAR->set_image (showBAR->get_active() ? *barImage : *barImage_g); + showRAW->set_active (false); + showFull->set_active (!options.histogramFullMode); + showBAR->set_active (options.histogramBar); - showRed->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::red_toggled), showRed ); - showGreen->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::green_toggled), showGreen ); - showBlue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::blue_toggled), showBlue ); - showValue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::value_toggled), showValue ); - showChro->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::chro_toggled), showChro ); - showRAW->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::raw_toggled), showRAW ); - showFull->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::full_toggled), showFull ); - showBAR->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::bar_toggled), showBAR ); + showRed->set_image (showRed->get_active() ? *redImage : *redImage_g); + showGreen->set_image (showGreen->get_active() ? *greenImage : *greenImage_g); + showBlue->set_image (showBlue->get_active() ? *blueImage : *blueImage_g); + showValue->set_image (showValue->get_active() ? *valueImage : *valueImage_g); + showChro->set_image (showChro->get_active() ? *chroImage : *chroImage_g); + showRAW->set_image (showRAW->get_active() ? *rawImage : *rawImage_g); + showFull->set_image (showFull->get_active() ? *fullImage : *fullImage_g); + showBAR->set_image (showBAR->get_active() ? *barImage : *barImage_g); - buttonVBox->pack_start (*showRed, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showGreen, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showBlue, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showValue, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showChro, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showRAW, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showFull, Gtk::PACK_SHRINK, 0); - buttonVBox->pack_start (*showBAR, Gtk::PACK_SHRINK, 0); + showRed->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::red_toggled), showRed ); + showGreen->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::green_toggled), showGreen ); + showBlue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::blue_toggled), showBlue ); + showValue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::value_toggled), showValue ); + showChro->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::chro_toggled), showChro ); + showRAW->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::raw_toggled), showRAW ); + showFull->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::full_toggled), showFull ); + showBAR->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::bar_toggled), showBAR ); - // Put the button vbox next to the window's border to be less disturbing - if (options.histogramPosition == 1) { - pack_start (*buttonVBox, Gtk::PACK_SHRINK, 2); - pack_start (*gfxVBox,Gtk::PACK_EXPAND_WIDGET, 2); - } - else { - pack_start (*gfxVBox,Gtk::PACK_EXPAND_WIDGET, 2); - pack_start (*buttonVBox, Gtk::PACK_SHRINK, 2); - } + buttonVBox->pack_start (*showRed, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showGreen, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showBlue, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showValue, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showChro, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showRAW, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showFull, Gtk::PACK_SHRINK, 0); + buttonVBox->pack_start (*showBAR, Gtk::PACK_SHRINK, 0); - show_all (); + // Put the button vbox next to the window's border to be less disturbing + if (options.histogramPosition == 1) { + pack_start (*buttonVBox, Gtk::PACK_SHRINK, 2); + pack_start (*gfxVBox, Gtk::PACK_EXPAND_WIDGET, 2); + } else { + pack_start (*gfxVBox, Gtk::PACK_EXPAND_WIDGET, 2); + pack_start (*buttonVBox, Gtk::PACK_SHRINK, 2); + } - rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) ); + show_all (); + + rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) ); } -HistogramPanel::~HistogramPanel () { - delete redImage; - delete greenImage; - delete blueImage; - delete valueImage; - delete chroImage; - delete rawImage; - delete fullImage; - delete barImage; +HistogramPanel::~HistogramPanel () +{ + delete redImage; + delete greenImage; + delete blueImage; + delete valueImage; + delete chroImage; + delete rawImage; + delete fullImage; + delete barImage; + + delete redImage_g; + delete greenImage_g; + delete blueImage_g; + delete valueImage_g; + delete chroImage_g; + delete rawImage_g; + delete fullImage_g; + delete barImage_g; - delete redImage_g; - delete greenImage_g; - delete blueImage_g; - delete valueImage_g; - delete chroImage_g; - delete rawImage_g; - delete fullImage_g; - delete barImage_g; - } -void HistogramPanel::resized (Gtk::Allocation& req) { +void HistogramPanel::resized (Gtk::Allocation& req) +{ rconn.block (true); - int gHeight = req.get_width()/2; - if (gHeight > 150) gHeight = 150; else if (gHeight < 100) gHeight = 100; - int bHeight = req.get_width()/30; - if (bHeight > 10) bHeight = 10; else if (bHeight < 5 ) bHeight = 5; + int gHeight = req.get_width() / 2; + + if (gHeight > 150) { + gHeight = 150; + } else if (gHeight < 100) { + gHeight = 100; + } + + int bHeight = req.get_width() / 30; + + if (bHeight > 10) { + bHeight = 10; + } else if (bHeight < 5 ) { + bHeight = 5; + } + histogramArea->set_size_request (req.get_width(), gHeight); histogramRGBArea->set_size_request (req.get_width(), bHeight); @@ -192,103 +216,113 @@ void HistogramPanel::resized (Gtk::Allocation& req) { histogramArea->renderHistogram (); histogramArea->queue_draw (); - if (histogramRGBArea->getFreeze()==true) { + if (histogramRGBArea->getFreeze() == true) { histogramRGBArea->updateFreeze(false); // set histogramRGBArea invalid; histogramRGBArea->renderRGBMarks(-1, -1, -1); // re-set freeze to old state histogramRGBArea->updateFreeze(true); histogramRGBArea->queue_draw (); - } - else { + } else { // set histogramRGBArea invalid; histogramRGBArea->renderRGBMarks(-1, -1, -1); histogramRGBArea->queue_draw (); } } -void HistogramPanel::red_toggled () { +void HistogramPanel::red_toggled () +{ showRed->set_image(showRed->get_active() ? *redImage : *redImage_g); rgbv_toggled(); } -void HistogramPanel::green_toggled () { +void HistogramPanel::green_toggled () +{ showGreen->set_image(showGreen->get_active() ? *greenImage : *greenImage_g); rgbv_toggled(); } -void HistogramPanel::blue_toggled () { +void HistogramPanel::blue_toggled () +{ showBlue->set_image(showBlue->get_active() ? *blueImage : *blueImage_g); rgbv_toggled(); } -void HistogramPanel::value_toggled () { - removeIfThere(showValue, valueImage, false); - removeIfThere(showValue, valueImage_g, false); +void HistogramPanel::value_toggled () +{ + removeIfThere(showValue, valueImage, false); + removeIfThere(showValue, valueImage_g, false); showValue->set_image(showValue->get_active() ? *valueImage : *valueImage_g); rgbv_toggled(); } -void HistogramPanel::chro_toggled () { - removeIfThere(showChro, chroImage, false); - removeIfThere(showChro, chroImage_g, false); +void HistogramPanel::chro_toggled () +{ + removeIfThere(showChro, chroImage, false); + removeIfThere(showChro, chroImage_g, false); showChro->set_image(showChro->get_active() ? *chroImage : *chroImage_g); rgbv_toggled(); } -void HistogramPanel::raw_toggled () { - if (showRAW->get_active()) { - showRAW->set_image(*rawImage); - showValue->set_sensitive(false); - showChro->set_sensitive(false); - } - else { - showRAW->set_image(*rawImage_g); - showValue->set_sensitive(true); - showChro->set_sensitive(true); - } +void HistogramPanel::raw_toggled () +{ + if (showRAW->get_active()) { + showRAW->set_image(*rawImage); + showValue->set_sensitive(false); + showChro->set_sensitive(false); + } else { + showRAW->set_image(*rawImage_g); + showValue->set_sensitive(true); + showChro->set_sensitive(true); + } + rgbv_toggled(); } -void HistogramPanel::full_toggled () { +void HistogramPanel::full_toggled () +{ options.histogramFullMode = !showFull->get_active(); showFull->set_image(showFull->get_active() ? *fullImage : *fullImage_g); rgbv_toggled(); } -void HistogramPanel::bar_toggled () { +void HistogramPanel::bar_toggled () +{ showBAR->set_image(showBAR->get_active() ? *barImage : *barImage_g); rgbv_toggled(); } -void HistogramPanel::rgbv_toggled () { - // Update Display - histogramArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showFull->get_active(), showChro->get_active()); - histogramArea->queue_draw (); +void HistogramPanel::rgbv_toggled () +{ + // Update Display + histogramArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showFull->get_active(), showChro->get_active()); + histogramArea->queue_draw (); - histogramRGBArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showBAR->get_active(), showChro->get_active()); - histogramRGBArea->renderRGBMarks (0,0,0); - histogramArea->queue_draw (); + histogramRGBArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showBAR->get_active(), showChro->get_active()); + histogramRGBArea->renderRGBMarks (0, 0, 0); + histogramArea->queue_draw (); } -void HistogramPanel::setHistRGBInvalid () { +void HistogramPanel::setHistRGBInvalid () +{ // do something to un-show vertical bars histogramRGBArea->renderRGBMarks(-1, -1, -1); histogramRGBArea->queue_draw (); } -// "Freeze" is not a button, but a RMB-click, so this is not in the RGBV-Toggle method -void HistogramPanel::toggleFreeze () { - if (histogramRGBArea->getFreeze()==true) { +// "Freeze" is not a button, but a RMB-click, so this is not in the RGBV-Toggle method +void HistogramPanel::toggleFreeze () +{ + if (histogramRGBArea->getFreeze() == true) { histogramRGBArea->updateFreeze(false); - } - else if (histogramRGBArea->getShow()==true) { + } else if (histogramRGBArea->getShow() == true) { histogramRGBArea->updateFreeze(true); } + return; } -void HistogramPanel::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW,int x, int y, int r, int g, int b) { +void HistogramPanel::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) +{ if (!validPos) { // do something to un-show vertical bars histogramRGBArea->renderRGBMarks(-1, -1, -1); histogramRGBArea->queue_draw (); - } - else { + } else { // do something to show vertical bars histogramRGBArea->renderRGBMarks(r, g, b, profile, profileW); histogramRGBArea->queue_draw (); @@ -299,15 +333,18 @@ void HistogramPanel::pointerMoved (bool validPos, Glib::ustring profile, Glib::u * Move the vertical button bar to the right side * only allowed values for align are Gtk::ALIGN_LEFT and Gtk::ALIGN_RIGHT */ -void HistogramPanel::reorder (Gtk::AlignmentEnum align) { - if (align == Gtk::ALIGN_LEFT) - reorder_child(*buttonVBox, 0); - else - reorder_child(*buttonVBox, 1); +void HistogramPanel::reorder (Gtk::AlignmentEnum align) +{ + if (align == Gtk::ALIGN_LEFT) { + reorder_child(*buttonVBox, 0); + } else { + reorder_child(*buttonVBox, 1); + } } // FullModeListener interface: -void HistogramPanel::toggle_button_full () { +void HistogramPanel::toggle_button_full () +{ showFull->set_active (!showFull->get_active ()); showFull->set_image(showFull->get_active() ? *fullImage : *fullImage_g); } @@ -317,248 +354,299 @@ void HistogramPanel::toggle_button_full () { // // HistogramRGBArea HistogramRGBArea::HistogramRGBArea () ://needChroma unactive by default - frozen(false), valid(false), needRed(true), needGreen(true), needBlue(true), needLuma(true), rawMode(false), showMode(options.histogramBar), barDisplayed(options.histogramBar), needChroma(false){ + frozen(false), valid(false), needRed(true), needGreen(true), needBlue(true), needLuma(true), rawMode(false), showMode(options.histogramBar), barDisplayed(options.histogramBar), needChroma(false) +{ - harih = new HistogramRGBAreaIdleHelper; - harih->harea = this; - harih->destroyed = false; - harih->pending = 0; + harih = new HistogramRGBAreaIdleHelper; + harih->harea = this; + harih->destroyed = false; + harih->pending = 0; } -HistogramRGBArea::~HistogramRGBArea () { +HistogramRGBArea::~HistogramRGBArea () +{ - if (harih->pending) - harih->destroyed = true; - else - delete harih; + if (harih->pending) { + harih->destroyed = true; + } else { + delete harih; + } } -bool HistogramRGBArea::getFreeze() { +bool HistogramRGBArea::getFreeze() +{ return(frozen); } -bool HistogramRGBArea::getShow() { +bool HistogramRGBArea::getShow() +{ return(showMode); } -void HistogramRGBArea::updateFreeze (bool f) { +void HistogramRGBArea::updateFreeze (bool f) +{ frozen = f; return; } -void HistogramRGBArea::renderRGBMarks (int r, int g, int b, Glib::ustring profile, Glib::ustring profileW) { +void HistogramRGBArea::renderRGBMarks (int r, int g, int b, Glib::ustring profile, Glib::ustring profileW) +{ - if (!is_realized ()) + if (!is_realized ()) { return; - - if (frozen) { + } + + if (frozen) { return; - } - - // Mostly not necessary, but should be in some case - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected - - Glib::RefPtr window = get_window(); - int winx, winy, winw, winh, wind; - window->get_geometry(winx, winy, winw, winh, wind); - - overlay = Gdk::Pixmap::create (window, winw, winh, -1); - Glib::RefPtr ovrl = Gdk::GC::create(overlay); - - Glib::RefPtr style = get_style (); - - if (!showMode) { - ovrl->set_foreground (style->get_bg (Gtk::STATE_NORMAL)); - overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh); - if (rgbgc_ && overlay) { - window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); } - return; } - else { - ovrl->set_foreground (mgray); - overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh); - if (rgbgc_ && overlay) { - window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); } - } - - Cairo::RefPtr cr = overlay->create_cairo_context(); - cr->set_line_width (1.0); - - if ( r != -1 && g != -1 && b != -1 ) { - if (needRed) { - // Red - cr->set_source_rgb(1.0, 0.0, 0.0); - cr->move_to((int)(r*(winw/256.0)), 0); - cr->line_to((int)(r*(winw/256.0)), winh-0); - cr->stroke(); } - if (needGreen) { - // Green - cr->set_source_rgb(0.0, 1.0, 0.0); - cr->move_to((int)(g*(winw/256.0)), 0); - cr->line_to((int)(g*(winw/256.0)), winh-0); - cr->stroke(); - } - if (needBlue) { - // Blue - cr->set_source_rgb(0.0, 0.0, 1.0); - cr->move_to((int)(b*(winw/256.0)), 0); - cr->line_to((int)(b*(winw/256.0)), winh-0); - cr->stroke(); - } - if(needLuma || needChroma) { - float Lab_L,Lab_a,Lab_b; - rgb2lab( profile, profileW, r,g,b,Lab_L,Lab_a,Lab_b); - if (needLuma) { - // Luma - cr->set_source_rgb(1.0, 1.0, 1.0); - cr->move_to((int)((Lab_L)*(winw/100.0)), 0); - cr->line_to((int)((Lab_L)*(winw/100.0)), winh-0); - cr->stroke(); + + // Mostly not necessary, but should be in some case + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + + Glib::RefPtr window = get_window(); + int winx, winy, winw, winh, wind; + window->get_geometry(winx, winy, winw, winh, wind); + + overlay = Gdk::Pixmap::create (window, winw, winh, -1); + Glib::RefPtr ovrl = Gdk::GC::create(overlay); + + Glib::RefPtr style = get_style (); + + if (!showMode) { + ovrl->set_foreground (style->get_bg (Gtk::STATE_NORMAL)); + overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh); + + if (rgbgc_ && overlay) { + window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); + } + + return; + } else { + ovrl->set_foreground (mgray); + overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh); + + if (rgbgc_ && overlay) { + window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); + } } - if (needChroma) { - // Chroma - float chromaval = sqrt(Lab_a*Lab_a + Lab_b*Lab_b)/1.8; - // float chromaval = sqrt(Lab_a*Lab_a + Lab_b*Lab_b); - cr->set_source_rgb(0.0, 0.0, 0.0); - cr->move_to((int)(chromaval*(winw/100.0)), 0); - cr->line_to((int)(chromaval*(winw/100.0)), winh-0); - cr->stroke(); + + Cairo::RefPtr cr = overlay->create_cairo_context(); + cr->set_line_width (1.0); + + if ( r != -1 && g != -1 && b != -1 ) { + if (needRed) { + // Red + cr->set_source_rgb(1.0, 0.0, 0.0); + cr->move_to((int)(r * (winw / 256.0)), 0); + cr->line_to((int)(r * (winw / 256.0)), winh - 0); + cr->stroke(); + } + + if (needGreen) { + // Green + cr->set_source_rgb(0.0, 1.0, 0.0); + cr->move_to((int)(g * (winw / 256.0)), 0); + cr->line_to((int)(g * (winw / 256.0)), winh - 0); + cr->stroke(); + } + + if (needBlue) { + // Blue + cr->set_source_rgb(0.0, 0.0, 1.0); + cr->move_to((int)(b * (winw / 256.0)), 0); + cr->line_to((int)(b * (winw / 256.0)), winh - 0); + cr->stroke(); + } + + if(needLuma || needChroma) { + float Lab_L, Lab_a, Lab_b; + rgb2lab( profile, profileW, r, g, b, Lab_L, Lab_a, Lab_b); + + if (needLuma) { + // Luma + cr->set_source_rgb(1.0, 1.0, 1.0); + cr->move_to((int)((Lab_L) * (winw / 100.0)), 0); + cr->line_to((int)((Lab_L) * (winw / 100.0)), winh - 0); + cr->stroke(); + } + + if (needChroma) { + // Chroma + float chromaval = sqrt(Lab_a * Lab_a + Lab_b * Lab_b) / 1.8; + // float chromaval = sqrt(Lab_a*Lab_a + Lab_b*Lab_b); + cr->set_source_rgb(0.0, 0.0, 0.0); + cr->move_to((int)(chromaval * (winw / 100.0)), 0); + cr->line_to((int)(chromaval * (winw / 100.0)), winh - 0); + cr->stroke(); + } + } } - } - } } -void HistogramRGBArea::rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b) { - double xyz_rgb[3][3]; - const double ep=216.0/24389.0; - const double ka=24389.0/27.0; +void HistogramRGBArea::rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b) +{ + double xyz_rgb[3][3]; + const double ep = 216.0 / 24389.0; + const double ka = 24389.0 / 27.0; - double var_R = r / 255.0; - double var_G = g / 255.0; - double var_B = b / 255.0; + double var_R = r / 255.0; + double var_G = g / 255.0; + double var_B = b / 255.0; - Glib::ustring profileCalc; - profileCalc="sRGB";//default - if(options.rtSettings.HistogramWorking) profileCalc=profileW;//display working - - else {// if you want display = output space - if (profile=="RT_sRGB" || profile=="RT_sRGB_gBT709" || profile=="RT_sRGB_g10") profileCalc="sRGB"; - if (profile=="ProPhoto" || profile=="RT_Large_gBT709" || profile=="RT_Large_g10" || profile=="RT_Large_gsRGB") profileCalc="ProPhoto"; - if (profile=="AdobeRGB1998" || profile=="RT_Medium_gsRGB") profileCalc="Adobe RGB"; - if (profile=="WideGamutRGB") profileCalc="WideGamut"; - } - if(options.rtSettings.HistogramWorking) {//display working - if (profileW=="sRGB") {//apply sRGB inverse gamma + Glib::ustring profileCalc; + profileCalc = "sRGB"; //default - if ( var_R > 0.04045 ) - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_R = var_R / 12.92; - if ( var_G > 0.04045 ) - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_G = var_G / 12.92; - if ( var_B > 0.04045 ) - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_B = var_B / 12.92; - } - else - if (profileW=="ProPhoto") {// apply inverse gamma 1.8 - var_R = pow ( var_R, 1.8); - var_G = pow ( var_G, 1.8); - var_B = pow ( var_B, 1.8); - } - else {// apply inverse gamma 2.2 - var_R = pow ( var_R, 2.2); - var_G = pow ( var_G, 2.2); - var_B = pow ( var_B, 2.2); - } - } - else {//display outout profile + if(options.rtSettings.HistogramWorking) { + profileCalc = profileW; //display working + } - if (profile=="RT_sRGB" || profile=="RT_Large_gsRGB" || profile=="RT_Medium_gsRGB") {//apply sRGB inverse gamma - if ( var_R > 0.04045 ) - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_R = var_R / 12.92; - if ( var_G > 0.04045 ) - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_G = var_G / 12.92; - if ( var_B > 0.04045 ) - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_B = var_B / 12.92; - } - - else if (profile=="RT_sRGB_gBT709" || profile=="RT_Large_gBT709") {// - if ( var_R > 0.0795 ) - var_R = pow ( ( ( var_R + 0.0954 ) / 1.0954 ), 2.2);else var_R=var_R/4.5; + else {// if you want display = output space + if (profile == "RT_sRGB" || profile == "RT_sRGB_gBT709" || profile == "RT_sRGB_g10") { + profileCalc = "sRGB"; + } - if ( var_G > 0.0795 ) - var_G = pow ( ( ( var_G + 0.0954 ) / 1.0954 ), 2.2);else var_G=var_G/4.5; + if (profile == "ProPhoto" || profile == "RT_Large_gBT709" || profile == "RT_Large_g10" || profile == "RT_Large_gsRGB") { + profileCalc = "ProPhoto"; + } - if ( var_B > 0.0795 ) - var_B = pow ( ( ( var_B + 0.0954 ) / 1.0954 ), 2.2);else var_B=var_B/4.5; - - } - else if (profile=="ProPhoto") {// apply inverse gamma 1.8 - - var_R = pow ( var_R, 1.8); - var_G = pow ( var_G, 1.8); - var_B = pow ( var_B, 1.8); - } - else if (profile=="RT_sRGB_g10" || profile=="RT_Large_g10") {// apply inverse gamma 1.8 - - var_R = pow ( var_R, 1.); - var_G = pow ( var_G, 1.); - var_B = pow ( var_B, 1.); - } - - else {// apply inverse gamma 2.2 - var_R = pow ( var_R, 2.2); - var_G = pow ( var_G, 2.2); - var_B = pow ( var_B, 2.2); - } - } - // TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileW); + if (profile == "AdobeRGB1998" || profile == "RT_Medium_gsRGB") { + profileCalc = "Adobe RGB"; + } + + if (profile == "WideGamutRGB") { + profileCalc = "WideGamut"; + } + } + + if(options.rtSettings.HistogramWorking) {//display working + if (profileW == "sRGB") { //apply sRGB inverse gamma + + if ( var_R > 0.04045 ) { + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_R = var_R / 12.92; + } + + if ( var_G > 0.04045 ) { + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_G = var_G / 12.92; + } + + if ( var_B > 0.04045 ) { + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_B = var_B / 12.92; + } + } else if (profileW == "ProPhoto") { // apply inverse gamma 1.8 + var_R = pow ( var_R, 1.8); + var_G = pow ( var_G, 1.8); + var_B = pow ( var_B, 1.8); + } else { // apply inverse gamma 2.2 + var_R = pow ( var_R, 2.2); + var_G = pow ( var_G, 2.2); + var_B = pow ( var_B, 2.2); + } + } else { //display outout profile + + if (profile == "RT_sRGB" || profile == "RT_Large_gsRGB" || profile == "RT_Medium_gsRGB") { //apply sRGB inverse gamma + if ( var_R > 0.04045 ) { + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_R = var_R / 12.92; + } + + if ( var_G > 0.04045 ) { + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_G = var_G / 12.92; + } + + if ( var_B > 0.04045 ) { + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_B = var_B / 12.92; + } + } + + else if (profile == "RT_sRGB_gBT709" || profile == "RT_Large_gBT709") { // + if ( var_R > 0.0795 ) { + var_R = pow ( ( ( var_R + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_R = var_R / 4.5; + } + + if ( var_G > 0.0795 ) { + var_G = pow ( ( ( var_G + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_G = var_G / 4.5; + } + + if ( var_B > 0.0795 ) { + var_B = pow ( ( ( var_B + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_B = var_B / 4.5; + } + + } else if (profile == "ProPhoto") { // apply inverse gamma 1.8 + + var_R = pow ( var_R, 1.8); + var_G = pow ( var_G, 1.8); + var_B = pow ( var_B, 1.8); + } else if (profile == "RT_sRGB_g10" || profile == "RT_Large_g10") { // apply inverse gamma 1.8 + + var_R = pow ( var_R, 1.); + var_G = pow ( var_G, 1.); + var_B = pow ( var_B, 1.); + } + + else {// apply inverse gamma 2.2 + var_R = pow ( var_R, 2.2); + var_G = pow ( var_G, 2.2); + var_B = pow ( var_B, 2.2); + } + } + + // TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileW); TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileCalc); - for (int m=0; m<3; m++) - for (int n=0; n<3; n++) { - xyz_rgb[m][n] = wprof[m][n]; - } + for (int m = 0; m < 3; m++) + for (int n = 0; n < 3; n++) { + xyz_rgb[m][n] = wprof[m][n]; + } - double varxx,varyy,varzz; - double var_X = ( xyz_rgb[0][0]*var_R + xyz_rgb[0][1]*var_G + xyz_rgb[0][2]*var_B ) / Color::D50x; - double var_Y = ( xyz_rgb[1][0]*var_R + xyz_rgb[1][1]*var_G + xyz_rgb[1][2]*var_B ) ; - double var_Z = ( xyz_rgb[2][0]*var_R + xyz_rgb[2][1]*var_G + xyz_rgb[2][2]*var_B ) / Color::D50z; + double varxx, varyy, varzz; + double var_X = ( xyz_rgb[0][0] * var_R + xyz_rgb[0][1] * var_G + xyz_rgb[0][2] * var_B ) / Color::D50x; + double var_Y = ( xyz_rgb[1][0] * var_R + xyz_rgb[1][1] * var_G + xyz_rgb[1][2] * var_B ) ; + double var_Z = ( xyz_rgb[2][0] * var_R + xyz_rgb[2][1] * var_G + xyz_rgb[2][2] * var_B ) / Color::D50z; - varxx = var_X>ep?cbrt(var_X):( ka * var_X + 16.0) / 116.0 ; - varyy = var_Y>ep?cbrt(var_Y):( ka * var_Y + 16.0) / 116.0 ; - varzz = var_Z>ep?cbrt(var_Z):( ka * var_Z + 16.0) / 116.0 ; - LAB_l = ( 116 * varyy ) - 16; - LAB_a = 500 * ( varxx - varyy ); - LAB_b = 200 * ( varyy - varzz ); + varxx = var_X > ep ? cbrt(var_X) : ( ka * var_X + 16.0) / 116.0 ; + varyy = var_Y > ep ? cbrt(var_Y) : ( ka * var_Y + 16.0) / 116.0 ; + varzz = var_Z > ep ? cbrt(var_Z) : ( ka * var_Z + 16.0) / 116.0 ; + LAB_l = ( 116 * varyy ) - 16; + LAB_a = 500 * ( varxx - varyy ); + LAB_b = 200 * ( varyy - varzz ); } -int histrgbupdate (void* data) { +int histrgbupdate (void* data) +{ HistogramRGBAreaIdleHelper* harih = static_cast(data); if (harih->destroyed) { - if (harih->pending == 1) + if (harih->pending == 1) { delete harih; - else + } else { harih->pending--; + } + return 0; } - - harih->harea->renderRGBMarks(-1,-1,-1); + + harih->harea->renderRGBMarks(-1, -1, -1); harih->harea->queue_draw (); harih->pending--; @@ -566,23 +654,25 @@ int histrgbupdate (void* data) { return 0; } -void HistogramRGBArea::update (int valh, int rh, int gh, int bh) { - +void HistogramRGBArea::update (int valh, int rh, int gh, int bh) +{ + if (valh) { - val=valh; - r=rh; - g=gh; - b=bh; + val = valh; + r = rh; + g = gh; + b = bh; valid = true; - } - else + } else { valid = false; + } harih->pending++; g_idle_add (histrgbupdate, harih); } -void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool bar, bool c) { +void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool bar, bool c) +{ needRed = r; needGreen = g; @@ -590,19 +680,18 @@ void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, needLuma = l; rawMode = raw; showMode = bar; - needChroma = c; + needChroma = c; // Histogram RGB BAR button logic goes here if (bar && !barDisplayed) { // Toggled on, add (show) the widget - parent->pack_start(*this, Gtk::PACK_SHRINK, 0); + parent->pack_start(*this, Gtk::PACK_SHRINK, 0); options.histogramBar = true; barDisplayed = true; - } - else if (!bar && barDisplayed){ + } else if (!bar && barDisplayed) { // Toggled off, remove (hide) the widget - removeIfThere(parent, this, false); + removeIfThere(parent, this, false); options.histogramBar = false; barDisplayed = false; // unfreeze @@ -612,59 +701,64 @@ void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, // Disable (but don't hide it) the bar button when RAW histogram is displayed if (rawMode) { showMode = false; - } + } } -void HistogramRGBArea::on_realize () { +void HistogramRGBArea::on_realize () +{ - Gtk::DrawingArea::on_realize(); - Glib::RefPtr window = get_window(); - rgbgc_ = Gdk::GC::create(window); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK); + Gtk::DrawingArea::on_realize(); + Glib::RefPtr window = get_window(); + rgbgc_ = Gdk::GC::create(window); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK); - Glib::RefPtr rgbcolormap = get_default_colormap(); - black = Gdk::Color ("black"); - red = Gdk::Color ("red"); - green = Gdk::Color ("green"); - blue = Gdk::Color ("blue"); - lgray = Gdk::Color ("gray75"); - mgray = Gdk::Color ("gray50"); - dgray = Gdk::Color ("gray25"); - rgbcolormap->alloc_color(black); - rgbcolormap->alloc_color(white); - rgbcolormap->alloc_color(red); - rgbcolormap->alloc_color(green); - rgbcolormap->alloc_color(blue); - rgbcolormap->alloc_color(lgray); - rgbcolormap->alloc_color(mgray); - rgbcolormap->alloc_color(dgray); + Glib::RefPtr rgbcolormap = get_default_colormap(); + black = Gdk::Color ("black"); + red = Gdk::Color ("red"); + green = Gdk::Color ("green"); + blue = Gdk::Color ("blue"); + lgray = Gdk::Color ("gray75"); + mgray = Gdk::Color ("gray50"); + dgray = Gdk::Color ("gray25"); + rgbcolormap->alloc_color(black); + rgbcolormap->alloc_color(white); + rgbcolormap->alloc_color(red); + rgbcolormap->alloc_color(green); + rgbcolormap->alloc_color(blue); + rgbcolormap->alloc_color(lgray); + rgbcolormap->alloc_color(mgray); + rgbcolormap->alloc_color(dgray); } -bool HistogramRGBArea::on_expose_event(GdkEventExpose* event) { +bool HistogramRGBArea::on_expose_event(GdkEventExpose* event) +{ - Glib::RefPtr window = get_window(); + Glib::RefPtr window = get_window(); - // on_realize & RenderRGBMarks have to be called before - if (rgbgc_ && overlay) { - window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); - } + // on_realize & RenderRGBMarks have to be called before + if (rgbgc_ && overlay) { + window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); + } - return true; + return true; } -bool HistogramRGBArea::on_button_press_event (GdkEventButton* event) { +bool HistogramRGBArea::on_button_press_event (GdkEventButton* event) +{ - if (event->type==GDK_2BUTTON_PRESS && event->button==1) { - // do something. Maybe un-freeze ? - } - return true; + if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { + // do something. Maybe un-freeze ? + } + + return true; } -void HistogramRGBArea::on_style_changed (const Glib::RefPtr& style) { +void HistogramRGBArea::on_style_changed (const Glib::RefPtr& style) +{ - white = get_style()->get_base(Gtk::STATE_NORMAL); - queue_draw (); + white = get_style()->get_base(Gtk::STATE_NORMAL); + queue_draw (); } // @@ -672,7 +766,8 @@ void HistogramRGBArea::on_style_changed (const Glib::RefPtr& style) // // HistogramArea HistogramArea::HistogramArea (FullModeListener *fml) : //needChroma unactive by default - valid(false), fullMode(options.histogramFullMode), myFullModeListener(fml), oldwidth(-1), oldheight(-1), needLuma(true), needRed(true), needGreen(true), needBlue(true), rawMode(false), needChroma(false) { + valid(false), fullMode(options.histogramFullMode), myFullModeListener(fml), oldwidth(-1), oldheight(-1), needLuma(true), needRed(true), needGreen(true), needBlue(true), rawMode(false), needChroma(false) +{ lhist(256); rhist(256); @@ -686,16 +781,19 @@ HistogramArea::HistogramArea (FullModeListener *fml) : //needChroma unactive by haih->pending = 0; } -HistogramArea::~HistogramArea () { +HistogramArea::~HistogramArea () +{ - if (haih->pending) + if (haih->pending) { haih->destroyed = true; - else + } else { delete haih; + } } -void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool full, bool c) { +void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool full, bool c) +{ needRed = r; needGreen = g; @@ -703,24 +801,26 @@ void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, boo needLuma = l; rawMode = raw; fullMode = !full; - needChroma = c; + needChroma = c; renderHistogram (); } -int histupdateUI (void* data) { +int histupdateUI (void* data) +{ HistogramAreaIdleHelper* haih = static_cast(data); if (haih->destroyed) { - if (haih->pending == 1) + if (haih->pending == 1) { delete haih; - else + } else { haih->pending--; + } return 0; } - + haih->harea->renderHistogram (); haih->harea->queue_draw (); @@ -729,259 +829,314 @@ int histupdateUI (void* data) { return 0; } -void HistogramArea::update (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu &histLuma, LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw, LUTu &histChroma) { - +void HistogramArea::update (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu &histLuma, LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw, LUTu &histChroma) +{ + if (histRed) { - lhist=histLuma;chist=histChroma; - rhist=histRed; ghist=histGreen; bhist=histBlue; - rhistRaw=histRedRaw; ghistRaw=histGreenRaw; bhistRaw=histBlueRaw; + lhist = histLuma; + chist = histChroma; + rhist = histRed; + ghist = histGreen; + bhist = histBlue; + rhistRaw = histRedRaw; + ghistRaw = histGreenRaw; + bhistRaw = histBlueRaw; valid = true; - } - else + } else { valid = false; + } haih->pending++; // Can be done outside of the GUI thread g_idle_add (histupdateUI, haih); } -void HistogramArea::renderHistogram () { +void HistogramArea::renderHistogram () +{ - if (!is_realized ()) + if (!is_realized ()) { return; - - Glib::RefPtr window = get_window(); - int winx, winy, winw, winh, wind; - window->get_geometry(winx, winy, winw, winh, wind); - - backBuffer = Gdk::Pixmap::create (window, winw, winh, -1); - - Glib::RefPtr bgc = Gdk::GC::create(backBuffer); - - bgc->set_foreground (white); - backBuffer->draw_rectangle (bgc, true, 0, 0, winw, winh); - - if (valid) { - // For RAW mode use the other hists - LUTu& rh = rawMode ? rhistRaw : rhist; - LUTu& gh = rawMode ? ghistRaw : ghist; - LUTu& bh = rawMode ? bhistRaw : bhist; - - // make double copies of LUT, one for faster access, another one to scale down the raw histos - LUTu rhchanged(256),ghchanged(256),bhchanged(256); - unsigned int lhisttemp[256],chisttemp[256],rhtemp[256],ghtemp[256],bhtemp[256]; - const int scale = (rawMode ? 8 : 1); - for(int i=0;i<256;i++) { - if(needLuma) - lhisttemp[i] = lhist[i]; - if(needChroma) - chisttemp[i] = chist[i]; - if(needRed) - rhchanged[i] = rhtemp[i] = rh[i] / scale; - if(needGreen) - ghchanged[i] = ghtemp[i] = gh[i] / scale; - if(needBlue) - bhchanged[i] = bhtemp[i] = bh[i] / scale; - } - - // compute height of the full histogram (realheight) and - // does not take into account 0 and 255 values - // them are handled separately - - int fullhistheight = 0; - for (int i=1; i<255; i++) { - if (needLuma && lhisttemp[i]>fullhistheight) - fullhistheight = lhisttemp[i]; - if (needChroma && chisttemp[i]>fullhistheight) - fullhistheight = chisttemp[i]; - if (needRed && rhtemp[i]>fullhistheight) - fullhistheight = rhtemp[i]; - if (needGreen && ghtemp[i]>fullhistheight) - fullhistheight = ghtemp[i]; - if (needBlue && bhtemp[i]>fullhistheight) - fullhistheight = bhtemp[i]; } - int realhistheight = fullhistheight; - - // though much faster than before, this still takes a lot of time especially for big files if rawMode is true - if (!fullMode) { - int area = 0; - if(!rawMode) - for (int i=0; ii) || (needChroma && chisttemp[j]>i) || (needRed && rhtemp[j]>i) || (needGreen && ghtemp[j]>i) || (needBlue && bhtemp[j]>i)) - area++; - if ((double)area / (256*(i+1)) < 0.3) { - realhistheight = i; - break; - } - } - else - for (int i=0; ii) || (needGreen && ghtemp[j]>i) || (needBlue && bhtemp[j]>i)) - area++; - if ((double)area / (256*(i+1)) < 0.3) { - realhistheight = i; - break; - } - } - + Glib::RefPtr window = get_window(); + int winx, winy, winw, winh, wind; + window->get_geometry(winx, winy, winw, winh, wind); + + backBuffer = Gdk::Pixmap::create (window, winw, winh, -1); + + Glib::RefPtr bgc = Gdk::GC::create(backBuffer); + + bgc->set_foreground (white); + backBuffer->draw_rectangle (bgc, true, 0, 0, winw, winh); + + if (valid) { + // For RAW mode use the other hists + LUTu& rh = rawMode ? rhistRaw : rhist; + LUTu& gh = rawMode ? ghistRaw : ghist; + LUTu& bh = rawMode ? bhistRaw : bhist; + + // make double copies of LUT, one for faster access, another one to scale down the raw histos + LUTu rhchanged(256), ghchanged(256), bhchanged(256); + unsigned int lhisttemp[256], chisttemp[256], rhtemp[256], ghtemp[256], bhtemp[256]; + const int scale = (rawMode ? 8 : 1); + + for(int i = 0; i < 256; i++) { + if(needLuma) { + lhisttemp[i] = lhist[i]; + } + + if(needChroma) { + chisttemp[i] = chist[i]; + } + + if(needRed) { + rhchanged[i] = rhtemp[i] = rh[i] / scale; + } + + if(needGreen) { + ghchanged[i] = ghtemp[i] = gh[i] / scale; + } + + if(needBlue) { + bhchanged[i] = bhtemp[i] = bh[i] / scale; + } + } + + // compute height of the full histogram (realheight) and + // does not take into account 0 and 255 values + // them are handled separately + + int fullhistheight = 0; + + for (int i = 1; i < 255; i++) { + if (needLuma && lhisttemp[i] > fullhistheight) { + fullhistheight = lhisttemp[i]; + } + + if (needChroma && chisttemp[i] > fullhistheight) { + fullhistheight = chisttemp[i]; + } + + if (needRed && rhtemp[i] > fullhistheight) { + fullhistheight = rhtemp[i]; + } + + if (needGreen && ghtemp[i] > fullhistheight) { + fullhistheight = ghtemp[i]; + } + + if (needBlue && bhtemp[i] > fullhistheight) { + fullhistheight = bhtemp[i]; + } + } + + int realhistheight = fullhistheight; + + // though much faster than before, this still takes a lot of time especially for big files if rawMode is true + if (!fullMode) { + int area = 0; + + if(!rawMode) + for (int i = 0; i < fullhistheight; i++) { + for (int j = 0; j < 256; j++) + if ((needLuma && lhisttemp[j] > i) || (needChroma && chisttemp[j] > i) || (needRed && rhtemp[j] > i) || (needGreen && ghtemp[j] > i) || (needBlue && bhtemp[j] > i)) { + area++; + } + + if ((double)area / (256 * (i + 1)) < 0.3) { + realhistheight = i; + break; + } + } + else + for (int i = 0; i < fullhistheight; i++) { + for (int j = 0; j < 256; j++) + if ((needRed && rhtemp[j] > i) || (needGreen && ghtemp[j] > i) || (needBlue && bhtemp[j] > i)) { + area++; + } + + if ((double)area / (256 * (i + 1)) < 0.3) { + realhistheight = i; + break; + } + } + + } + + if (realhistheight < winh - 2) { + realhistheight = winh - 2; + } + + Cairo::RefPtr cr = backBuffer->create_cairo_context(); + cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); + cr->set_line_width (1.0); + + int ui = 0, oi = 0; + + if (needLuma && !rawMode) { + drawCurve(cr, lhist, realhistheight, winw, winh); + cr->set_source_rgb (0.75, 0.75, 0.75); + cr->fill_preserve (); + cr->set_source_rgb (0.5, 0.5, 0.5); + cr->stroke (); + + drawMarks(cr, lhist, realhistheight, winw, ui, oi); + } + + if (needChroma && !rawMode) { + drawCurve(cr, chist, realhistheight, winw, winh); + cr->set_source_rgb (0.6, 0.6, 0.6); + // cr->fill_preserve (); + // cr->set_source_rgb (0.2, 0.2, 0.1); + cr->stroke (); + + drawMarks(cr, chist, realhistheight, winw, ui, oi); + } + + if (needRed) { + drawCurve(cr, rhchanged, realhistheight, winw, winh); + cr->set_source_rgb (1.0, 0.0, 0.0); + cr->stroke (); + + drawMarks(cr, rhchanged, realhistheight, winw, ui, oi); + } + + if (needGreen) { + drawCurve(cr, ghchanged, realhistheight, winw, winh); + cr->set_source_rgb (0.0, 1.0, 0.0); + cr->stroke (); + + drawMarks(cr, ghchanged, realhistheight, winw, ui, oi); + } + + if (needBlue) { + drawCurve(cr, bhchanged, realhistheight, winw, winh); + cr->set_source_rgb (0.0, 0.0, 1.0); + cr->stroke (); + + drawMarks(cr, bhchanged, realhistheight, winw, ui, oi); + } } - if (realhistheightset_foreground (mgray); + backBuffer->draw_rectangle (bgc, false, 0, 0, winw - 1, winh - 1); - Cairo::RefPtr cr = backBuffer->create_cairo_context(); - cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); - cr->set_line_width (1.0); + bgc->set_line_attributes (1, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER); - int ui = 0, oi = 0; + backBuffer->draw_line (bgc, winw / 4, 0, winw / 4, winh); + backBuffer->draw_line (bgc, 2 * winw / 4, 0, 2 * winw / 4, winh); + backBuffer->draw_line (bgc, 3 * winw / 4, 0, 3 * winw / 4, winh); + backBuffer->draw_line (bgc, 0, winh / 4, winw, winh / 4); + backBuffer->draw_line (bgc, 0, 2 * winh / 4, winw, 2 * winh / 4); + backBuffer->draw_line (bgc, 0, 3 * winh / 4, winw, 3 * winh / 4); - if (needLuma && !rawMode) { - drawCurve(cr, lhist, realhistheight, winw, winh); - cr->set_source_rgb (0.75, 0.75, 0.75); - cr->fill_preserve (); - cr->set_source_rgb (0.5, 0.5, 0.5); - cr->stroke (); + bgc->set_line_attributes (1, Gdk::LINE_SOLID, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER); - drawMarks(cr, lhist, realhistheight, winw, ui, oi); - } - if (needChroma && !rawMode) { - drawCurve(cr, chist, realhistheight, winw, winh); - cr->set_source_rgb (0.6, 0.6, 0.6); - // cr->fill_preserve (); - // cr->set_source_rgb (0.2, 0.2, 0.1); - cr->stroke (); - - drawMarks(cr, chist, realhistheight, winw, ui, oi); - } - if (needRed) { - drawCurve(cr, rhchanged, realhistheight, winw, winh); - cr->set_source_rgb (1.0, 0.0, 0.0); - cr->stroke (); - - drawMarks(cr, rhchanged, realhistheight, winw, ui, oi); - } - if (needGreen) { - drawCurve(cr, ghchanged, realhistheight, winw, winh); - cr->set_source_rgb (0.0, 1.0, 0.0); - cr->stroke (); - - drawMarks(cr, ghchanged, realhistheight, winw, ui, oi); - } - if (needBlue) { - drawCurve(cr, bhchanged, realhistheight, winw, winh); - cr->set_source_rgb (0.0, 0.0, 1.0); - cr->stroke (); - - drawMarks(cr, bhchanged, realhistheight, winw, ui, oi); - } - } - - bgc->set_foreground (mgray); - backBuffer->draw_rectangle (bgc, false, 0, 0, winw-1, winh-1); - - bgc->set_line_attributes (1, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER); - - backBuffer->draw_line (bgc, winw/4, 0, winw/4, winh); - backBuffer->draw_line (bgc, 2*winw/4, 0, 2*winw/4, winh); - backBuffer->draw_line (bgc, 3*winw/4, 0, 3*winw/4, winh); - backBuffer->draw_line (bgc, 0, winh/4, winw, winh/4); - backBuffer->draw_line (bgc, 0, 2*winh/4, winw, 2*winh/4); - backBuffer->draw_line (bgc, 0, 3*winh/4, winw, 3*winh/4); - - bgc->set_line_attributes (1, Gdk::LINE_SOLID, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER); - - oldwidth = winw; - oldheight = winh; + oldwidth = winw; + oldheight = winh; } -void HistogramArea::on_realize () { +void HistogramArea::on_realize () +{ - Gtk::DrawingArea::on_realize(); - Glib::RefPtr window = get_window(); - gc_ = Gdk::GC::create(window); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK); - Glib::RefPtr colormap = get_default_colormap(); + Gtk::DrawingArea::on_realize(); + Glib::RefPtr window = get_window(); + gc_ = Gdk::GC::create(window); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK); + Glib::RefPtr colormap = get_default_colormap(); - black = Gdk::Color ("black"); - red = Gdk::Color ("red"); - green = Gdk::Color ("green"); - blue = Gdk::Color ("blue"); - lgray = Gdk::Color ("gray75"); - mgray = Gdk::Color ("gray50"); - dgray = Gdk::Color ("gray25"); - colormap->alloc_color(black); - colormap->alloc_color(white); - colormap->alloc_color(red); - colormap->alloc_color(green); - colormap->alloc_color(blue); - colormap->alloc_color(lgray); - colormap->alloc_color(mgray); - colormap->alloc_color(dgray); + black = Gdk::Color ("black"); + red = Gdk::Color ("red"); + green = Gdk::Color ("green"); + blue = Gdk::Color ("blue"); + lgray = Gdk::Color ("gray75"); + mgray = Gdk::Color ("gray50"); + dgray = Gdk::Color ("gray25"); + colormap->alloc_color(black); + colormap->alloc_color(white); + colormap->alloc_color(red); + colormap->alloc_color(green); + colormap->alloc_color(blue); + colormap->alloc_color(lgray); + colormap->alloc_color(mgray); + colormap->alloc_color(dgray); } void HistogramArea::drawCurve(Cairo::RefPtr &cr, - LUTu & data, double scale, int hsize, int vsize) + LUTu & data, double scale, int hsize, int vsize) { - cr->move_to (0, vsize-1); + cr->move_to (0, vsize - 1); + for (int i = 0; i < 256; i++) { - double val = data[i] * (double)(vsize-2) / scale; - if (val > vsize - 1) + double val = data[i] * (double)(vsize - 2) / scale; + + if (val > vsize - 1) { val = vsize - 1; - cr->line_to ((i/255.0)*(hsize - 1), vsize - 1 - val); - } + } + + cr->line_to ((i / 255.0) * (hsize - 1), vsize - 1 - val); + } + cr->line_to (hsize - 1, vsize - 1); } void HistogramArea::drawMarks(Cairo::RefPtr &cr, - LUTu & data, double scale, int hsize, int & ui, int & oi) + LUTu & data, double scale, int hsize, int & ui, int & oi) { int s = 8; - + if(data[0] > scale) { - cr->rectangle(0, (ui++)*s, s, s); + cr->rectangle(0, (ui++)*s, s, s); } + if(data[255] > scale) { - cr->rectangle(hsize - s, (oi++)*s, s, s); + cr->rectangle(hsize - s, (oi++)*s, s, s); } + cr->fill(); } -void HistogramArea::on_style_changed (const Glib::RefPtr& style) { +void HistogramArea::on_style_changed (const Glib::RefPtr& style) +{ white = get_style()->get_base(Gtk::STATE_NORMAL); queue_draw (); } -bool HistogramArea::on_expose_event(GdkEventExpose* event) { +bool HistogramArea::on_expose_event(GdkEventExpose* event) +{ Glib::RefPtr window = get_window(); int winx, winy, winw, winh, wind; window->get_geometry(winx, winy, winw, winh, wind); - if (winw!=oldwidth && winh!=oldheight) - renderHistogram (); + if (winw != oldwidth && winh != oldheight) { + renderHistogram (); + } + window->draw_drawable (gc_, backBuffer, 0, 0, 0, 0, -1, -1); return true; } -bool HistogramArea::on_button_press_event (GdkEventButton* event) { +bool HistogramArea::on_button_press_event (GdkEventButton* event) +{ - if (event->type==GDK_2BUTTON_PRESS && event->button==1) { + if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { fullMode = !fullMode; options.histogramFullMode = fullMode; - if (myFullModeListener) + + if (myFullModeListener) { myFullModeListener->toggle_button_full (); + } + renderHistogram (); queue_draw (); } + return true; } diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index 1fd0ec906..16a0747e3 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -7,7 +7,7 @@ * 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 @@ -41,11 +41,12 @@ struct HistogramRGBAreaIdleHelper { int pending; }; -class HistogramRGBArea : public Gtk::DrawingArea { +class HistogramRGBArea : public Gtk::DrawingArea +{ - typedef const double (*TMatrix)[3]; + typedef const double (*TMatrix)[3]; - protected: +protected: Glib::RefPtr rgbgc_; Glib::RefPtr overlay; @@ -80,7 +81,7 @@ class HistogramRGBArea : public Gtk::DrawingArea { HistogramRGBAreaIdleHelper* harih; - public: +public: HistogramRGBArea(); ~HistogramRGBArea(); @@ -89,7 +90,10 @@ class HistogramRGBArea : public Gtk::DrawingArea { void updateFreeze (bool f); bool getFreeze (); bool getShow (); - void setParent (Gtk::VBox* p) { parent = p; }; + void setParent (Gtk::VBox* p) + { + parent = p; + }; void update (int val, int rh, int gh, int bh); void updateOptions (bool r, bool g, bool b, bool l, bool raw, bool show, bool c); @@ -98,20 +102,22 @@ class HistogramRGBArea : public Gtk::DrawingArea { bool on_expose_event(GdkEventExpose* event); bool on_button_press_event (GdkEventButton* event); void on_style_changed (const Glib::RefPtr& style); - private: - void rgb2lab (Glib::ustring profile, Glib::ustring profileW,int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b); +private: + void rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b); // Some ... }; -class FullModeListener { - public: +class FullModeListener +{ +public: virtual void toggle_button_full () {} }; -class HistogramArea : public Gtk::DrawingArea{ +class HistogramArea : public Gtk::DrawingArea +{ - protected: +protected: Glib::RefPtr gc_; Glib::RefPtr backBuffer; @@ -136,9 +142,9 @@ class HistogramArea : public Gtk::DrawingArea{ HistogramAreaIdleHelper* haih; - public: - - HistogramArea(FullModeListener *fml=NULL); +public: + + HistogramArea(FullModeListener *fml = NULL); ~HistogramArea(); void renderHistogram (); @@ -148,20 +154,21 @@ class HistogramArea : public Gtk::DrawingArea{ bool on_expose_event(GdkEventExpose* event); bool on_button_press_event (GdkEventButton* event); void on_style_changed (const Glib::RefPtr& style); - private: +private: void drawCurve(Cairo::RefPtr &cr, - LUTu & data, double scale, int hsize, int vsize); + LUTu & data, double scale, int hsize, int vsize); void drawMarks(Cairo::RefPtr &cr, - LUTu & data, double scale, int hsize, int & ui, int & oi); + LUTu & data, double scale, int hsize, int & ui, int & oi); }; -class HistogramPanel : public Gtk::HBox, public PointerMotionListener, public FullModeListener { +class HistogramPanel : public Gtk::HBox, public PointerMotionListener, public FullModeListener +{ - protected: +protected: - Gtk::VBox* gfxVBox; - Gtk::VBox* buttonVBox; - HistogramArea* histogramArea; + Gtk::VBox* gfxVBox; + Gtk::VBox* buttonVBox; + HistogramArea* histogramArea; HistogramRGBArea* histogramRGBArea; Gtk::ToggleButton* showRed; Gtk::ToggleButton* showGreen; @@ -170,8 +177,8 @@ class HistogramPanel : public Gtk::HBox, public PointerMotionListener, public Fu Gtk::ToggleButton* showRAW; Gtk::ToggleButton* showFull; Gtk::ToggleButton* showBAR; - Gtk::ToggleButton* showChro; - + Gtk::ToggleButton* showChro; + Gtk::Image *redImage; Gtk::Image *greenImage; Gtk::Image *blueImage; @@ -193,17 +200,18 @@ class HistogramPanel : public Gtk::HBox, public PointerMotionListener, public Fu sigc::connection rconn; void setHistInvalid (); - - public: + +public: HistogramPanel (); ~HistogramPanel (); - void histogramChanged (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu &histLuma, LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw, LUTu &histChroma) { + void histogramChanged (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu &histLuma, LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw, LUTu &histChroma) + { histogramArea->update (histRed, histGreen, histBlue, histLuma, histRedRaw, histGreenRaw, histBlueRaw, histChroma); } // pointermotionlistener interface - void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW,int x, int y, int r, int g, int b); + void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b); // added pointermotionlistener interface void toggleFreeze(); // TODO should be protected @@ -216,8 +224,8 @@ class HistogramPanel : public Gtk::HBox, public PointerMotionListener, public Fu void value_toggled (); void raw_toggled (); void full_toggled (); - void chro_toggled (); - void bar_toggled (); + void chro_toggled (); + void bar_toggled (); void rgbv_toggled (); void resized (Gtk::Allocation& req); diff --git a/rtgui/history.cc b/rtgui/history.cc index 0e58ae5b5..57f7549db 100644 --- a/rtgui/history.cc +++ b/rtgui/history.cc @@ -7,7 +7,7 @@ * 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 @@ -26,13 +26,15 @@ using namespace rtengine::procparams; Glib::ustring eventDescrArray[NUMOFEVENTS]; extern Glib::ustring argv0; -History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1) { +History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1) +{ - blistenerLock = false; // sets default that the Before preview will not be locked + blistenerLock = false; // sets default that the Before preview will not be locked // fill history event message array - for (int i=0; iadd (*hscrollw); - + hTreeView = Gtk::manage (new Gtk::TreeView ()); hscrollw->add (*hTreeView); - + historyModel = Gtk::ListStore::create (historyColumns); hTreeView->set_model (historyModel); // hTreeView->set_headers_visible (false); @@ -61,8 +63,8 @@ History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1) hviewcol2->add_attribute (valuecrt->property_markup (), historyColumns.value); valuecrt->set_property ("xalign", 1.0); - hTreeView->append_column (*hviewcol); - hTreeView->append_column (*hviewcol2); + hTreeView->append_column (*hviewcol); + hTreeView->append_column (*hviewcol2); hviewcol2->set_sizing (Gtk::TREE_VIEW_COLUMN_FIXED); @@ -96,21 +98,20 @@ History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1) bmFrame->add (*bmBox); bmBox->pack_start (*bscrollw, Gtk::PACK_EXPAND_WIDGET, 4); bmBox->pack_end (*ahbox, Gtk::PACK_SHRINK, 4); - - if (bookmarkSupport){ + + if (bookmarkSupport) { historyVPaned = Gtk::manage ( new Gtk::VPaned () ); historyVPaned->pack1 (*histFrame, true, true); historyVPaned->pack2 (*bmFrame, false, true); pack_start(*historyVPaned); - } - else{ + } else { pack_start (*histFrame); } - + bTreeView = Gtk::manage (new Gtk::TreeView ()); bscrollw->add (*bTreeView); - + bookmarkModel = Gtk::ListStore::create (bookmarkColumns); bTreeView->set_model (bookmarkModel); bTreeView->set_headers_visible (false); @@ -121,8 +122,8 @@ History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1) addBookmark->signal_clicked().connect( sigc::mem_fun(*this, &History::addBookmarkPressed) ); delBookmark->signal_clicked().connect( sigc::mem_fun(*this, &History::delBookmarkPressed) ); -// hTreeView->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_HORIZONTAL); - hTreeView->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_BOTH); +// hTreeView->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_HORIZONTAL); + hTreeView->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_BOTH); hTreeView->signal_size_allocate().connect( sigc::mem_fun(*this, &History::resized) ); hTreeView->set_enable_search(false); @@ -131,25 +132,32 @@ History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1) show_all_children (); } -void History::initHistory () { +void History::initHistory () +{ historyModel->clear (); bookmarkModel->clear (); } -void History::clearParamChanges () { +void History::clearParamChanges () +{ initHistory (); } -void History::historySelectionChanged () { +void History::historySelectionChanged () +{ Glib::RefPtr selection = hTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); + if (iter) { Gtk::TreeModel::Row row = *iter; - if (row) + + if (row) { bTreeView->get_selection()->unselect_all (); + } + if (row && tpc) { ProcParams pparams = row[historyColumns.params]; ParamsEdited pe(true); @@ -157,24 +165,32 @@ void History::historySelectionChanged () { ParamsEdited paramsEdited = row[historyColumns.paramsEdited]; tpc->profileChange (&pp, EvHistoryBrowsed, row[historyColumns.text], ¶msEdited); } - if (blistener && blistenerLock==false) { + + if (blistener && blistenerLock == false) { Gtk::TreeModel::Path path = historyModel->get_path (iter); path.prev (); iter = historyModel->get_iter (path); - if (blistener && iter) + + if (blistener && iter) { blistener->historyBeforeLineChanged (iter->get_value (historyColumns.params)); + } } } } -void History::bookmarkSelectionChanged () { +void History::bookmarkSelectionChanged () +{ Glib::RefPtr selection = bTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); + if (iter) { Gtk::TreeModel::Row row = *iter; - if (row) + + if (row) { hTreeView->get_selection()->unselect_all (); + } + if (row && tpc) { ProcParams pparams = row[bookmarkColumns.params]; ParamsEdited pe(true); @@ -185,34 +201,45 @@ void History::bookmarkSelectionChanged () { } } -void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { +void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) +{ // to prevent recursion, we filter out the events triggered by the history - if (ev==EvHistoryBrowsed) + if (ev == EvHistoryBrowsed) { return; + } selchangehist.block (true); - if (ev==EvPhotoLoaded) + if (ev == EvPhotoLoaded) { initHistory (); + } + // construct formatted list content Glib::ustring text = Glib::ustring::compose ("%1", eventDescrArray[ev]); Glib::RefPtr selection = hTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); + // remove all rows after the selection if (iter) { iter++; - while (iter) + + while (iter) { iter = historyModel->erase (iter); + } } + // lookup the last remaining item in the list int size = historyModel->children().size (); Gtk::TreeModel::Row row; - if (size>0) - row = historyModel->children()[size-1]; + + if (size > 0) { + row = historyModel->children()[size - 1]; + } + // if there is no last item or its chev!=ev, create a new one - if (size==0 || !row || row[historyColumns.chev]!=ev || ev==EvProfileChanged) { + if (size == 0 || !row || row[historyColumns.chev] != ev || ev == EvProfileChanged) { Gtk::TreeModel::Row newrow = *(historyModel->append()); newrow[historyColumns.realText] = eventDescrArray[ev]; newrow[historyColumns.text] = text; @@ -220,12 +247,16 @@ void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring newrow[historyColumns.chev] = ev; newrow[historyColumns.params] = *params; newrow[historyColumns.paramsEdited] = paramsEdited ? *paramsEdited : defParamsEdited; - if (ev!=EvBookmarkSelected) + + if (ev != EvBookmarkSelected) { selection->select (newrow); - if (blistener && row && blistenerLock==false) + } + + if (blistener && row && blistenerLock == false) { blistener->historyBeforeLineChanged (row[historyColumns.params]); - else if (blistener && size==0 && blistenerLock==false) + } else if (blistener && size == 0 && blistenerLock == false) { blistener->historyBeforeLineChanged (newrow[historyColumns.params]); + } } // else just update it else { @@ -235,21 +266,27 @@ void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring row[historyColumns.chev] = ev; row[historyColumns.params] = *params; row[historyColumns.paramsEdited] = paramsEdited ? *paramsEdited : defParamsEdited; - if (ev!=EvBookmarkSelected) + + if (ev != EvBookmarkSelected) { selection->select (row); + } } - if (ev!=EvBookmarkSelected) + + if (ev != EvBookmarkSelected) { bTreeView->get_selection()->unselect_all (); + } if (!selection->get_selected_rows().empty()) { Gtk::TreeView::Selection::ListHandle_Path selp = selection->get_selected_rows(); hTreeView->scroll_to_row (*selp.begin()); } + selchangehist.block (false); } -void History::addBookmarkWithText (Glib::ustring text) { +void History::addBookmarkWithText (Glib::ustring text) +{ // lookup the selected item in the history Glib::RefPtr selection = hTreeView->get_selection(); @@ -269,13 +306,16 @@ void History::addBookmarkWithText (Glib::ustring text) { newrow[bookmarkColumns.paramsEdited] = paramsEdited; } -void History::addBookmarkPressed () { - - if (hTreeView->get_selection()->get_selected()) +void History::addBookmarkPressed () +{ + + if (hTreeView->get_selection()->get_selected()) { addBookmarkWithText (Glib::ustring::compose ("%1 %2", M("HISTORY_SNAPSHOT"), bmnum++)); + } } -void History::delBookmarkPressed () { +void History::delBookmarkPressed () +{ // lookup the selected item in the bookmark Glib::RefPtr selection = bTreeView->get_selection(); @@ -284,56 +324,68 @@ void History::delBookmarkPressed () { if (!iter) { return; } + // remove selected bookmark bookmarkModel->erase (iter); // select last item in history int size = historyModel->children().size (); - Gtk::TreeModel::Row row = historyModel->children()[size-1]; + Gtk::TreeModel::Row row = historyModel->children()[size - 1]; hTreeView->get_selection()->select (row); } -void History::undo () { +void History::undo () +{ Glib::RefPtr selection = hTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); - if (iter && iter!=historyModel->children().begin()) + if (iter && iter != historyModel->children().begin()) { selection->select (--iter); - else if (!iter) { + } else if (!iter) { int size = historyModel->children().size (); - if (size>1) - selection->select (historyModel->children()[size-2]); + + if (size > 1) { + selection->select (historyModel->children()[size - 2]); + } } } -void History::redo () { +void History::redo () +{ Glib::RefPtr selection = hTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); if (iter) { iter++; - if (iter!=historyModel->children().end()) + + if (iter != historyModel->children().end()) { selection->select (iter); - } - else { + } + } else { int size = historyModel->children().size (); - if (size>1) - selection->select (historyModel->children()[size-2]); + + if (size > 1) { + selection->select (historyModel->children()[size - 2]); + } } } -void History::resized (Gtk::Allocation& req) { +void History::resized (Gtk::Allocation& req) +{ } -bool History::getBeforeLineParams (rtengine::procparams::ProcParams& params) { +bool History::getBeforeLineParams (rtengine::procparams::ProcParams& params) +{ int size = historyModel->children().size (); - if (size==0 || !blistener) + + if (size == 0 || !blistener) { return false; + } Gtk::TreeModel::Row row; - row = historyModel->children()[size==1 ? 0 : size-2]; + row = historyModel->children()[size == 1 ? 0 : size - 2]; params = row[historyColumns.params]; return true; } diff --git a/rtgui/history.h b/rtgui/history.h index 3400b7ad2..1c3e9e0b4 100644 --- a/rtgui/history.h +++ b/rtgui/history.h @@ -7,7 +7,7 @@ * 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 @@ -25,84 +25,107 @@ #include "profilechangelistener.h" #include "paramsedited.h" -class HistoryBeforeLineListener { +class HistoryBeforeLineListener +{ - public: - virtual void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) {} +public: + virtual void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) {} }; -class History : public Gtk::VBox, public PParamsChangeListener { +class History : public Gtk::VBox, public PParamsChangeListener +{ +public: + + class HistoryColumns : public Gtk::TreeModel::ColumnRecord + { public: - - class HistoryColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn realText; - Gtk::TreeModelColumn text; - Gtk::TreeModelColumn value; - Gtk::TreeModelColumn params; - Gtk::TreeModelColumn chev; - Gtk::TreeModelColumn paramsEdited; - HistoryColumns() { add(text); add(realText); add(value); add(chev); add(params); add(paramsEdited); } - }; - HistoryColumns historyColumns; - class BookmarkColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn text; - Gtk::TreeModelColumn params; - Gtk::TreeModelColumn paramsEdited; - BookmarkColumns() { add(text); add(params); add(paramsEdited); } - }; - BookmarkColumns bookmarkColumns; - - protected: - Gtk::VPaned* historyVPaned; - Gtk::ScrolledWindow* hscrollw; - Gtk::TreeView* hTreeView; - Glib::RefPtr historyModel; - - Gtk::ScrolledWindow* bscrollw; - Gtk::TreeView* bTreeView; - Glib::RefPtr bookmarkModel; - - Gtk::Button* addBookmark; - Gtk::Button* delBookmark; - - sigc::connection selchangehist; - sigc::connection selchangebm; - - HistoryBeforeLineListener * blistener; - ProfileChangeListener* tpc; - ParamsEdited defParamsEdited; - int bmnum; - + Gtk::TreeModelColumn realText; + Gtk::TreeModelColumn text; + Gtk::TreeModelColumn value; + Gtk::TreeModelColumn params; + Gtk::TreeModelColumn chev; + Gtk::TreeModelColumn paramsEdited; + HistoryColumns() + { + add(text); + add(realText); + add(value); + add(chev); + add(params); + add(paramsEdited); + } + }; + HistoryColumns historyColumns; + class BookmarkColumns : public Gtk::TreeModel::ColumnRecord + { public: - - History (bool bookmarkSupport = true); + Gtk::TreeModelColumn text; + Gtk::TreeModelColumn params; + Gtk::TreeModelColumn paramsEdited; + BookmarkColumns() + { + add(text); + add(params); + add(paramsEdited); + } + }; + BookmarkColumns bookmarkColumns; - void setProfileChangeListener (ProfileChangeListener* tpc_) { tpc = tpc_; } - void setHistoryBeforeLineListener (HistoryBeforeLineListener* bll) { blistener = bll; } - - // pparamschangelistener interface - void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL); - void clearParamChanges (); +protected: + Gtk::VPaned* historyVPaned; + Gtk::ScrolledWindow* hscrollw; + Gtk::TreeView* hTreeView; + Glib::RefPtr historyModel; - void historySelectionChanged (); - void bookmarkSelectionChanged (); - void initHistory (); + Gtk::ScrolledWindow* bscrollw; + Gtk::TreeView* bTreeView; + Glib::RefPtr bookmarkModel; - bool getBeforeLineParams (rtengine::procparams::ProcParams& params); - - void addBookmarkWithText (Glib::ustring text); - void addBookmarkPressed (); - void delBookmarkPressed (); + Gtk::Button* addBookmark; + Gtk::Button* delBookmark; - void resized (Gtk::Allocation& req); + sigc::connection selchangehist; + sigc::connection selchangebm; - void undo (); - void redo (); + HistoryBeforeLineListener * blistener; + ProfileChangeListener* tpc; + ParamsEdited defParamsEdited; + int bmnum; - bool blistenerLock; +public: + + History (bool bookmarkSupport = true); + + void setProfileChangeListener (ProfileChangeListener* tpc_) + { + tpc = tpc_; + } + void setHistoryBeforeLineListener (HistoryBeforeLineListener* bll) + { + blistener = bll; + } + + // pparamschangelistener interface + void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited = NULL); + void clearParamChanges (); + + void historySelectionChanged (); + void bookmarkSelectionChanged (); + void initHistory (); + + bool getBeforeLineParams (rtengine::procparams::ProcParams& params); + + void addBookmarkWithText (Glib::ustring text); + void addBookmarkPressed (); + void delBookmarkPressed (); + + void resized (Gtk::Allocation& req); + + void undo (); + void redo (); + + bool blistenerLock; }; #endif diff --git a/rtgui/hsvequalizer.cc b/rtgui/hsvequalizer.cc index ccd9ee8e0..e74848cf3 100644 --- a/rtgui/hsvequalizer.cc +++ b/rtgui/hsvequalizer.cc @@ -5,7 +5,7 @@ * 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 @@ -25,54 +25,58 @@ using namespace rtengine::procparams; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -HSVEqualizer::HSVEqualizer () : FoldableToolPanel(this, "hsvequalizer", M("TP_HSVEQUALIZER_LABEL")) { - - std::vector bottomMilestones; - float R, G, B; - // -0.1 rad < Hue < 1.6 rad - for (int i=0; i<7; i++) { - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } +HSVEqualizer::HSVEqualizer () : FoldableToolPanel(this, "hsvequalizer", M("TP_HSVEQUALIZER_LABEL")) +{ - curveEditorG = new CurveEditorGroup (options.lastHsvCurvesDir, M("TP_HSVEQUALIZER_CHANNEL")); - curveEditorG->setCurveListener (this); + std::vector bottomMilestones; + float R, G, B; - hshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_HUE"))); - hshape->setEditID(EUID_HSV_H, BT_SINGLEPLANE_FLOAT); - hshape->setBottomBarBgGradient(bottomMilestones); - //hshape->setLeftBarColorProvider(this); Not working yet - hshape->setCurveColorProvider(this, 1); + // -0.1 rad < Hue < 1.6 rad + for (int i = 0; i < 7; i++) { + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + bottomMilestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } - sshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_SAT"))); - sshape->setEditID(EUID_HSV_S, BT_SINGLEPLANE_FLOAT); - sshape->setBottomBarBgGradient(bottomMilestones); - //sshape->setLeftBarColorProvider(this); Not working yet - sshape->setCurveColorProvider(this, 2); + curveEditorG = new CurveEditorGroup (options.lastHsvCurvesDir, M("TP_HSVEQUALIZER_CHANNEL")); + curveEditorG->setCurveListener (this); - vshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_VAL"))); - vshape->setEditID(EUID_HSV_V, BT_SINGLEPLANE_FLOAT); - vshape->setBottomBarBgGradient(bottomMilestones); - //vshape->setLeftBarColorProvider(this); Not working yet - vshape->setCurveColorProvider(this, 3); + hshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_HUE"))); + hshape->setEditID(EUID_HSV_H, BT_SINGLEPLANE_FLOAT); + hshape->setBottomBarBgGradient(bottomMilestones); + //hshape->setLeftBarColorProvider(this); Not working yet + hshape->setCurveColorProvider(this, 1); - // This will add the reset button at the end of the curveType buttons - curveEditorG->curveListComplete(); + sshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_SAT"))); + sshape->setEditID(EUID_HSV_S, BT_SINGLEPLANE_FLOAT); + sshape->setBottomBarBgGradient(bottomMilestones); + //sshape->setLeftBarColorProvider(this); Not working yet + sshape->setCurveColorProvider(this, 2); - pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); + vshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_VAL"))); + vshape->setEditID(EUID_HSV_V, BT_SINGLEPLANE_FLOAT); + vshape->setBottomBarBgGradient(bottomMilestones); + //vshape->setLeftBarColorProvider(this); Not working yet + vshape->setCurveColorProvider(this, 3); - //curveEditorG->show(); + // This will add the reset button at the end of the curveType buttons + curveEditorG->curveListComplete(); + + pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); + + //curveEditorG->show(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -HSVEqualizer::~HSVEqualizer () { - delete curveEditorG; +HSVEqualizer::~HSVEqualizer () +{ + delete curveEditorG; } -void HSVEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { +void HSVEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -83,27 +87,36 @@ void HSVEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { } hshape->setCurve (pp->hsvequalizer.hcurve); - sshape->setCurve (pp->hsvequalizer.scurve); + sshape->setCurve (pp->hsvequalizer.scurve); vshape->setCurve (pp->hsvequalizer.vcurve); - + enableListener (); } -void HSVEqualizer::setEditProvider (EditDataProvider *provider) { +void HSVEqualizer::setEditProvider (EditDataProvider *provider) +{ hshape->setEditProvider(provider); sshape->setEditProvider(provider); vshape->setEditProvider(provider); } -void HSVEqualizer::autoOpenCurve () { +void HSVEqualizer::autoOpenCurve () +{ // Open up the first curve if selected bool active = hshape->openIfNonlinear(); - if (!active) sshape->openIfNonlinear(); - if (!active) vshape->openIfNonlinear(); + + if (!active) { + sshape->openIfNonlinear(); + } + + if (!active) { + vshape->openIfNonlinear(); + } } -void HSVEqualizer::write (ProcParams* pp, ParamsEdited* pedited) { - +void HSVEqualizer::write (ProcParams* pp, ParamsEdited* pedited) +{ + pp->hsvequalizer.hcurve = hshape->getCurve (); pp->hsvequalizer.scurve = sshape->getCurve (); pp->hsvequalizer.vcurve = vshape->getCurve (); @@ -122,57 +135,66 @@ void HSVEqualizer::write (ProcParams* pp, ParamsEdited* pedited) { * If more than one curve has been added, the curve listener is automatically * set to 'multi=true', and send a pointer of the modified curve in a parameter */ -void HSVEqualizer::curveChanged (CurveEditor* ce) { +void HSVEqualizer::curveChanged (CurveEditor* ce) +{ if (listener) { - if (ce == hshape) - listener->panelChanged (EvHSVEqualizerH, M("HISTORY_CUSTOMCURVE")); - if (ce == sshape) - listener->panelChanged (EvHSVEqualizerS, M("HISTORY_CUSTOMCURVE")); - if (ce == vshape) - listener->panelChanged (EvHSVEqualizerV, M("HISTORY_CUSTOMCURVE")); - } + if (ce == hshape) { + listener->panelChanged (EvHSVEqualizerH, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == sshape) { + listener->panelChanged (EvHSVEqualizerS, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == vshape) { + listener->panelChanged (EvHSVEqualizerV, M("HISTORY_CUSTOMCURVE")); + } + } } -void HSVEqualizer::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) { +void HSVEqualizer::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) +{ - float r, g, b; + float r, g, b; - if (elemType==ColorCaller::CCET_VERTICAL_BAR) - valY = 0.5; + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } - if (callerId == 1) { // Hue = f(Hue) + if (callerId == 1) { // Hue = f(Hue) - float h = float((valY - 0.5) * 2. + valX); - if (h > 1.0f) - h -= 1.0f; - else if (h < 0.0f) - h += 1.0f; - Color::hsv2rgb01(h, 0.5f, 0.5f, r, g, b); - caller->ccRed = double(r); - caller->ccGreen = double(g); - caller->ccBlue = double(b); - } - else if (callerId == 2) { // Saturation = f(Hue) - Color::hsv2rgb01(float(valX), float(valY), 0.5f, r, g, b); - caller->ccRed = double(r); - caller->ccGreen = double(g); - caller->ccBlue = double(b); - } - else if (callerId == 3) { // Value = f(Hue) - Color::hsv2rgb01(float(valX), 0.5f, float(valY), r, g, b); - caller->ccRed = double(r); - caller->ccGreen = double(g); - caller->ccBlue = double(b); - } - else { - printf("Error: no curve displayed!\n"); - } + float h = float((valY - 0.5) * 2. + valX); + + if (h > 1.0f) { + h -= 1.0f; + } else if (h < 0.0f) { + h += 1.0f; + } + + Color::hsv2rgb01(h, 0.5f, 0.5f, r, g, b); + caller->ccRed = double(r); + caller->ccGreen = double(g); + caller->ccBlue = double(b); + } else if (callerId == 2) { // Saturation = f(Hue) + Color::hsv2rgb01(float(valX), float(valY), 0.5f, r, g, b); + caller->ccRed = double(r); + caller->ccGreen = double(g); + caller->ccBlue = double(b); + } else if (callerId == 3) { // Value = f(Hue) + Color::hsv2rgb01(float(valX), 0.5f, float(valY), r, g, b); + caller->ccRed = double(r); + caller->ccGreen = double(g); + caller->ccBlue = double(b); + } else { + printf("Error: no curve displayed!\n"); + } } -void HSVEqualizer::setBatchMode (bool batchMode) { - +void HSVEqualizer::setBatchMode (bool batchMode) +{ + ToolPanel::setBatchMode (batchMode); curveEditorG->setBatchMode (batchMode); diff --git a/rtgui/hsvequalizer.h b/rtgui/hsvequalizer.h index b35bb1337..939cd1904 100644 --- a/rtgui/hsvequalizer.h +++ b/rtgui/hsvequalizer.h @@ -5,7 +5,7 @@ * 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 @@ -16,7 +16,7 @@ * * 2010 Ilya Popov */ - + #ifndef HSVEQUALIZER_H_INCLUDED #define HSVEQUALIZER_H_INCLUDED @@ -34,25 +34,25 @@ class HSVEqualizer : public ToolParamBlock, public AdjusterListener, public Fold protected: - CurveEditorGroup* curveEditorG; - FlatCurveEditor* hshape; - FlatCurveEditor* sshape; - FlatCurveEditor* vshape; + CurveEditorGroup* curveEditorG; + FlatCurveEditor* hshape; + FlatCurveEditor* sshape; + FlatCurveEditor* vshape; public: HSVEqualizer (); virtual ~HSVEqualizer (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void curveChanged (CurveEditor* ce); //void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); void setBatchMode (bool batchMode); void setEditProvider (EditDataProvider *provider); void autoOpenCurve (); virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - + //void adjusterChanged (Adjuster* a, double newval); }; diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index abd044ca8..6e4668ab4 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -7,7 +7,7 @@ * 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 @@ -30,7 +30,8 @@ using namespace rtengine::procparams; extern Options options; -ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(NULL), icmplistener(NULL), lastRefFilename("") { +ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(NULL), icmplistener(NULL), lastRefFilename("") +{ isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = lastBlendCMSMatrix = lastgamfree = false; @@ -66,7 +67,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch icameraICC->set_tooltip_text (M("TP_ICM_INPUTCAMERAICC_TOOLTIP")); iVBox->pack_start (*icameraICC, Gtk::PACK_SHRINK, 2); - ifromfile = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCUSTOM")+":")); + ifromfile = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCUSTOM") + ":")); Gtk::HBox* ffbox = Gtk::manage (new Gtk::HBox ()); ifromfile->set_tooltip_text (M("TP_ICM_INPUTCUSTOM_TOOLTIP")); ffbox->pack_start (*ifromfile, Gtk::PACK_SHRINK); @@ -85,7 +86,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch dcpFrameVBox->set_border_width(4); Gtk::HBox* dcpIllHBox = Gtk::manage (new Gtk::HBox ()); - dcpIllLabel = Gtk::manage (new Gtk::Label (M("TP_ICM_DCPILLUMINANT")+":")); + dcpIllLabel = Gtk::manage (new Gtk::Label (M("TP_ICM_DCPILLUMINANT") + ":")); dcpIllLabel->set_tooltip_text (M("TP_ICM_DCPILLUMINANT_TOOLTIP")); dcpIllLabel->show (); dcpIll = Gtk::manage (new MyComboBoxText ()); @@ -156,8 +157,10 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch wVBox->pack_start (*wnames, Gtk::PACK_SHRINK); std::vector wpnames = rtengine::getWorkingProfiles (); - for (size_t i=0; iappend_text (wpnames[i]); + } wnames->set_active (0); @@ -183,26 +186,30 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch onames->set_active (0); std::vector opnames = iccStore->getOutputProfiles (); - for (size_t i=0; iappend_text (opnames[i]); + } onames->set_active (0); // Output gamma Gtk::HBox* gaHBox = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* galab = Gtk::manage (new Gtk::Label (M("TP_GAMMA_OUTPUT")+":")); + Gtk::Label* galab = Gtk::manage (new Gtk::Label (M("TP_GAMMA_OUTPUT") + ":")); //galab->set_alignment (0.0, 0.5); gaHBox->pack_start (*galab, Gtk::PACK_SHRINK, 4); wgamma = Gtk::manage (new MyComboBoxText ()); gaHBox->pack_start (*wgamma, Gtk::PACK_EXPAND_WIDGET); - oVBox->pack_start(*gaHBox, Gtk::PACK_EXPAND_WIDGET,2); + oVBox->pack_start(*gaHBox, Gtk::PACK_EXPAND_WIDGET, 2); std::vector wpgamma = rtengine::getGamma (); - for (size_t i=0; iappend_text (wpgamma[i]); + } wgamma->set_active (0); @@ -216,19 +223,27 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch freegamma->set_active (false); fgFrame->set_label_widget(*freegamma); - gampos = Gtk::manage(new Adjuster (M("TP_GAMMA_CURV"),1,3.5,0.01,2.22)); + gampos = Gtk::manage(new Adjuster (M("TP_GAMMA_CURV"), 1, 3.5, 0.01, 2.22)); gampos->setAdjusterListener (this); - if (gampos->delay < 1000) gampos->delay = 1000; + + if (gampos->delay < 1000) { + gampos->delay = 1000; + } + gampos->show(); - slpos = Gtk::manage(new Adjuster (M("TP_GAMMA_SLOP"),0,15,0.01,4.5)); + slpos = Gtk::manage(new Adjuster (M("TP_GAMMA_SLOP"), 0, 15, 0.01, 4.5)); slpos->setAdjusterListener (this); - if (slpos->delay < 1000) slpos->delay = 1000; + + if (slpos->delay < 1000) { + slpos->delay = 1000; + } + slpos->show(); fgVBox->pack_start( *gampos, Gtk::PACK_SHRINK);//gamma fgVBox->pack_start( *slpos, Gtk::PACK_SHRINK);//slope fgFrame->add(*fgVBox); - oVBox->pack_start(*fgFrame, Gtk::PACK_EXPAND_WIDGET,2); + oVBox->pack_start(*fgFrame, Gtk::PACK_EXPAND_WIDGET, 2); oFrame->add(*oVBox); pack_start (*oFrame, Gtk::PACK_EXPAND_WIDGET, 4); @@ -288,7 +303,8 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch show_all (); } -void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { +void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) +{ if (isBatchMode) { dcpFrame->set_sensitive(true); @@ -298,6 +314,7 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { ckbApplyHueSatMap->set_sensitive (true); dcpIllLabel->set_sensitive (true); dcpIll->set_sensitive (true); + if (dcpTemperatures[0] != 0 || dcpTemperatures[1] != 0) { int curr_active = dcpIll->get_active_row_number(); ignoreDcpSignal = true; @@ -311,15 +328,18 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { dcpIll->set_active (curr_active); ignoreDcpSignal = false; } + if (dcpIll->get_active_row_number() == -1 && dcpIlluminant == -1) { dcpIll->set_active(0); } else if (dcpIlluminant >= 0 && dcpIlluminant != dcpIll->get_active_row_number()) { dcpIll->set_active(dcpIlluminant); } + dcpIll->set_sensitive (true); dcpIllLabel->set_sensitive (true); return; } + ckbToneCurve->set_sensitive (false); ckbApplyLookTable->set_sensitive (false); ckbApplyBaselineExposureOffset->set_sensitive (false); @@ -327,26 +347,34 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { dcpIllLabel->set_sensitive (false); dcpIll->set_sensitive (false); dcpFrame->set_sensitive(false); + if (ifromfile->get_active() && dcpStore->isValidDCPFileName(dcp_name)) { DCPProfile* dcp = dcpStore->getProfile(dcp_name, false); + if (dcp) { dcpFrame->set_sensitive(true); + if (dcp->getHasToneCurve()) { ckbToneCurve->set_sensitive (true); } + if (dcp->getHasLookTable()) { ckbApplyLookTable->set_sensitive (true); } + if (dcp->getHasBaselineExposureOffset()) { ckbApplyBaselineExposureOffset->set_sensitive (true); } + if (dcp->getHasHueSatMap()) { ckbApplyHueSatMap->set_sensitive (true); } + int i1, i2; double temp1, temp2; bool willInterpolate; dcp->getIlluminants(i1, temp1, i2, temp2, willInterpolate); + if (willInterpolate) { if (dcpTemperatures[0] != temp1 || dcpTemperatures[1] != temp2) { char tempstr1[64], tempstr2[64]; @@ -363,29 +391,33 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { dcpIll->set_active (curr_active); ignoreDcpSignal = false; } + if (dcpIlluminant > 2) { dcpIlluminant = 0; } + if (dcpIll->get_active_row_number() == -1 && dcpIlluminant == -1) { - ignoreDcpSignal = true; + ignoreDcpSignal = true; dcpIll->set_active(0); - ignoreDcpSignal = false; + ignoreDcpSignal = false; } else if (dcpIlluminant >= 0 && dcpIlluminant != dcpIll->get_active_row_number()) { - ignoreDcpSignal = true; + ignoreDcpSignal = true; dcpIll->set_active(dcpIlluminant); ignoreDcpSignal = false; } + dcpIll->set_sensitive (true); dcpIllLabel->set_sensitive (true); } else { if (dcpIll->get_active_row_number() != -1) { - ignoreDcpSignal = true; + ignoreDcpSignal = true; dcpIll->set_active(-1); - ignoreDcpSignal = false; + ignoreDcpSignal = false; } } } } + if (!dcpIllLabel->get_sensitive() && dcpIll->get_active_row_number() != 0) { if (dcpTemperatures[0] != 0 || dcpTemperatures[1] != 0) { int curr_active = dcpIll->get_active_row_number(); @@ -394,8 +426,11 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { dcpIll->append_text (M("TP_ICM_DCPILLUMINANT_INTERPOLATED")); dcpIll->append_text (M("TP_ICM_DCPILLUMINANT") + " 1"); dcpIll->append_text (M("TP_ICM_DCPILLUMINANT") + " 2"); - if (isBatchMode) + + if (isBatchMode) { dcpIll->append_text (M("GENERAL_UNCHANGED")); + } + dcpTemperatures[0] = 0; dcpTemperatures[1] = 0; dcpIll->set_active (curr_active); @@ -404,7 +439,8 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) { } } -void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -416,43 +452,38 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { hsmconn.block(true); blendcmsconn.block(true); - if(pp->icm.input.substr(0,5) != "file:" && !ipDialog->get_filename().empty()) - ipDialog->set_filename(pp->icm.input); + if(pp->icm.input.substr(0, 5) != "file:" && !ipDialog->get_filename().empty()) { + ipDialog->set_filename(pp->icm.input); + } if (pp->icm.input == "(none)") { inone->set_active (true); ckbBlendCMSMatrix->set_sensitive (false); updateDCP(pp->icm.dcpIlluminant, ""); - } - else if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()==Gtk::STATE_INSENSITIVE)) { + } else if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() == Gtk::STATE_INSENSITIVE)) { iembedded->set_active (true); ckbBlendCMSMatrix->set_sensitive (false); updateDCP(pp->icm.dcpIlluminant, ""); - } - else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state()!=Gtk::STATE_INSENSITIVE) { + } else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) { icameraICC->set_active (true); ckbBlendCMSMatrix->set_sensitive (true); updateDCP(pp->icm.dcpIlluminant, ""); - } - else if ((pp->icm.input == "(cameraICC)") && icamera->get_state()!=Gtk::STATE_INSENSITIVE && icameraICC->get_state()==Gtk::STATE_INSENSITIVE) { + } else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() != Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { // this is the case when (cameraICC) is instructed by packaged profiles, but ICC file is not found // therefore falling back UI to explicitly reflect the (camera) option icamera->set_active (true); ckbBlendCMSMatrix->set_sensitive (false); updateDCP(pp->icm.dcpIlluminant, ""); - } - else if ((pp->icm.input == "(cameraICC)") && icamera->get_state()==Gtk::STATE_INSENSITIVE && icameraICC->get_state()==Gtk::STATE_INSENSITIVE) { + } else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() == Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { // If neither (camera) nor (cameraICC) are available, as is the case when loading a non-raw, activate (embedded). iembedded->set_active (true); ckbBlendCMSMatrix->set_sensitive (false); updateDCP(pp->icm.dcpIlluminant, ""); - } - else if ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()!=Gtk::STATE_INSENSITIVE) { + } else if ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) { icamera->set_active (true); ckbBlendCMSMatrix->set_sensitive (false); updateDCP(pp->icm.dcpIlluminant, ""); - } - else { + } else { ifromfile->set_active (true); oldip = pp->icm.input.substr(5); // cut of "file:" ipDialog->set_filename (pp->icm.input.substr(5)); @@ -463,13 +494,15 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { wnames->set_active_text (pp->icm.working); wgamma->set_active_text (pp->icm.gamma); - if (pp->icm.output==ColorManagementParams::NoICMString) + if (pp->icm.output == ColorManagementParams::NoICMString) { onames->set_active_text (M("TP_ICM_NOICM")); - else + } else { onames->set_active_text (pp->icm.output); + } - if (onames->get_active_row_number()==-1) + if (onames->get_active_row_number() == -1) { onames->set_active_text (M("TP_ICM_NOICM")); + } ckbToneCurve->set_active (pp->icm.toneCurve); lastToneCurve = pp->icm.toneCurve; @@ -483,7 +516,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { ckbBlendCMSMatrix->set_active (pp->icm.blendCMSMatrix); lastBlendCMSMatrix = pp->icm.blendCMSMatrix; - onames->set_sensitive(wgamma->get_active_row_number()==0 || freegamma->get_active()); //"default" + onames->set_sensitive(wgamma->get_active_row_number() == 0 || freegamma->get_active()); //"default" wgamma->set_sensitive(!freegamma->get_active()); freegamma->set_active (pp->icm.freegamma); @@ -499,16 +532,24 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { ckbApplyBaselineExposureOffset->set_inconsistent(!pedited->icm.applyBaselineExposureOffset); ckbApplyHueSatMap->set_inconsistent(!pedited->icm.applyHueSatMap); ckbBlendCMSMatrix->set_inconsistent(!pedited->icm.blendCMSMatrix); - if (!pedited->icm.working) + + if (!pedited->icm.working) { wnames->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->icm.output) + } + + if (!pedited->icm.output) { onames->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->icm.dcpIlluminant) + } + + if (!pedited->icm.dcpIlluminant) { dcpIll->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->icm.gamma){ + } + + if (!pedited->icm.gamma) { wgamma->set_active_text(M("GENERAL_UNCHANGED")); wgamma->set_active_text(M("GENERAL_UNCHANGED")); } + gampos->setEditedState (pedited->icm.gampos ? Edited : UnEdited); slpos->setEditedState (pedited->icm.slpos ? Edited : UnEdited); @@ -525,282 +566,314 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) { +void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) +{ - if (inone->get_active()) + if (inone->get_active()) { pp->icm.input = "(none)"; - else if (iembedded->get_active ()) + } else if (iembedded->get_active ()) { pp->icm.input = "(embedded)"; - else if (icamera->get_active ()) + } else if (icamera->get_active ()) { pp->icm.input = "(camera)"; - else if (icameraICC->get_active ()) + } 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)) - pp->icm.input = "file:"+ipDialog->get_filename (); - else - pp->icm.input = ""; // just a directory + } else { + if (safe_file_test (ipDialog->get_filename (), Glib::FILE_TEST_EXISTS) && !safe_file_test (ipDialog->get_filename (), Glib::FILE_TEST_IS_DIR)) { + pp->icm.input = "file:" + ipDialog->get_filename (); + } else { + pp->icm.input = ""; // just a directory + } - Glib::ustring p=Glib::path_get_dirname(ipDialog->get_filename ()); - } + Glib::ustring p = Glib::path_get_dirname(ipDialog->get_filename ()); + } pp->icm.working = wnames->get_active_text (); pp->icm.gamma = wgamma->get_active_text (); pp->icm.dcpIlluminant = dcpIll->get_active_row_number(); - if (pp->icm.dcpIlluminant < 0) - pp->icm.dcpIlluminant = 0; - if (onames->get_active_text()==M("TP_ICM_NOICM")) + if (pp->icm.dcpIlluminant < 0) { + pp->icm.dcpIlluminant = 0; + } + + if (onames->get_active_text() == M("TP_ICM_NOICM")) { pp->icm.output = ColorManagementParams::NoICMString; - else + } else { pp->icm.output = onames->get_active_text(); + } + pp->icm.freegamma = freegamma->get_active(); - if (ifromfile->get_active() && pp->icm.input.substr(0,5) == "file:" && dcpStore->isValidDCPFileName(pp->icm.input.substr(5))) { + if (ifromfile->get_active() && pp->icm.input.substr(0, 5) == "file:" && dcpStore->isValidDCPFileName(pp->icm.input.substr(5))) { DCPProfile* dcp = dcpStore->getProfile(pp->icm.input.substr(5), false); + if (dcp) { if (dcp->getHasToneCurve()) { pp->icm.toneCurve = ckbToneCurve->get_active (); } + if (dcp->getHasLookTable()) { pp->icm.applyLookTable = ckbApplyLookTable->get_active (); } + if (dcp->getHasBaselineExposureOffset()) { pp->icm.applyBaselineExposureOffset = ckbApplyBaselineExposureOffset->get_active (); } + if (dcp->getHasHueSatMap()) { pp->icm.applyHueSatMap = ckbApplyHueSatMap->get_active (); } } } + pp->icm.blendCMSMatrix = ckbBlendCMSMatrix->get_active (); - pp->icm.gampos =(double) gampos->getValue(); - pp->icm.slpos =(double) slpos->getValue(); + pp->icm.gampos = (double) gampos->getValue(); + pp->icm.slpos = (double) slpos->getValue(); if (pedited) { pedited->icm.input = !iunchanged->get_active (); - pedited->icm.working = wnames->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->icm.output = onames->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->icm.dcpIlluminant = dcpIll->get_active_text()!=M("GENERAL_UNCHANGED"); + pedited->icm.working = wnames->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->icm.output = onames->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->icm.dcpIlluminant = dcpIll->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.toneCurve = !ckbToneCurve->get_inconsistent (); pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent (); pedited->icm.applyBaselineExposureOffset = !ckbApplyBaselineExposureOffset->get_inconsistent (); pedited->icm.applyHueSatMap = !ckbApplyHueSatMap->get_inconsistent (); pedited->icm.blendCMSMatrix = !ckbBlendCMSMatrix->get_inconsistent (); - pedited->icm.gamma = wgamma->get_active_text()!=M("GENERAL_UNCHANGED"); - pedited->icm.freegamma =!freegamma->get_inconsistent(); + pedited->icm.gamma = wgamma->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->icm.freegamma = !freegamma->get_inconsistent(); pedited->icm.gampos = gampos->getEditedState (); pedited->icm.slpos = slpos->getEditedState (); } } -void ICMPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ICMPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ gampos->setDefault (defParams->icm.gampos); slpos->setDefault (defParams->icm.slpos); if (pedited) { gampos->setDefaultEditedState (pedited->icm.gampos ? Edited : UnEdited); slpos->setDefaultEditedState (pedited->icm.slpos ? Edited : UnEdited); - } - else { - gampos->setDefaultEditedState (Irrelevant); - slpos->setDefaultEditedState (Irrelevant); + } else { + gampos->setDefaultEditedState (Irrelevant); + slpos->setDefaultEditedState (Irrelevant); } } -void ICMPanel::setAdjusterBehavior (bool gammaadd, bool slopeadd) { +void ICMPanel::setAdjusterBehavior (bool gammaadd, bool slopeadd) +{ gampos->setAddMode (gammaadd); slpos->setAddMode (slopeadd); } -void ICMPanel::adjusterChanged (Adjuster* a, double newval) { +void ICMPanel::adjusterChanged (Adjuster* a, double newval) +{ if (listener && freegamma->get_active()) { Glib::ustring costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), newval); - if (a==gampos) + if (a == gampos) { listener->panelChanged (EvGAMPOS, costr); - else if (a==slpos) + } else if (a == slpos) { listener->panelChanged (EvSLPOS, costr); + } } } -void ICMPanel::wpChanged () { +void ICMPanel::wpChanged () +{ - if (listener) + if (listener) { listener->panelChanged (EvWProfile, wnames->get_active_text ()); + } } -void ICMPanel::gpChanged () { +void ICMPanel::gpChanged () +{ if (listener) { listener->panelChanged (EvGAMMA, wgamma->get_active_text ()); - onames->set_sensitive(wgamma->get_active_row_number()==0); //"default" + onames->set_sensitive(wgamma->get_active_row_number() == 0); //"default" } } -void ICMPanel::dcpIlluminantChanged() { +void ICMPanel::dcpIlluminantChanged() +{ if (listener && !ignoreDcpSignal) { listener->panelChanged (EvDCPIlluminant, dcpIll->get_active_text ()); } } -void ICMPanel::toneCurveChanged() { +void ICMPanel::toneCurveChanged() +{ if (batchMode) { if (ckbToneCurve->get_inconsistent()) { ckbToneCurve->set_inconsistent (false); tcurveconn.block (true); ckbToneCurve->set_active (false); tcurveconn.block (false); - } - else if (lastToneCurve) + } else if (lastToneCurve) { ckbToneCurve->set_inconsistent (true); + } lastToneCurve = ckbToneCurve->get_active (); } - if (listener) + if (listener) { listener->panelChanged (EvDCPToneCurve, ckbToneCurve->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void ICMPanel::applyLookTableChanged() { +void ICMPanel::applyLookTableChanged() +{ if (batchMode) { if (ckbApplyLookTable->get_inconsistent()) { ckbApplyLookTable->set_inconsistent (false); ltableconn.block (true); ckbApplyLookTable->set_active (false); ltableconn.block (false); - } - else if (lastApplyLookTable) + } else if (lastApplyLookTable) { ckbApplyLookTable->set_inconsistent (true); + } lastApplyLookTable = ckbApplyLookTable->get_active (); } - if (listener) + if (listener) { listener->panelChanged (EvDCPApplyLookTable, ckbApplyLookTable->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void ICMPanel::applyBaselineExposureOffsetChanged() { +void ICMPanel::applyBaselineExposureOffsetChanged() +{ if (batchMode) { if (ckbApplyBaselineExposureOffset->get_inconsistent()) { ckbApplyBaselineExposureOffset->set_inconsistent (false); beoconn.block (true); ckbApplyBaselineExposureOffset->set_active (false); beoconn.block (false); - } - else if (lastApplyBaselineExposureOffset) + } else if (lastApplyBaselineExposureOffset) { ckbApplyBaselineExposureOffset->set_inconsistent (true); + } lastApplyBaselineExposureOffset = ckbApplyBaselineExposureOffset->get_active (); } - if (listener) + if (listener) { listener->panelChanged (EvDCPApplyBaselineExposureOffset, ckbApplyBaselineExposureOffset->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void ICMPanel::applyHueSatMapChanged() { +void ICMPanel::applyHueSatMapChanged() +{ if (batchMode) { if (ckbApplyHueSatMap->get_inconsistent()) { ckbApplyHueSatMap->set_inconsistent (false); hsmconn.block (true); ckbApplyHueSatMap->set_active (false); hsmconn.block (false); - } - else if (lastApplyHueSatMap) + } else if (lastApplyHueSatMap) { ckbApplyHueSatMap->set_inconsistent (true); + } lastApplyHueSatMap = ckbApplyHueSatMap->get_active (); } - if (listener) + if (listener) { listener->panelChanged (EvDCPApplyHueSatMap, ckbApplyHueSatMap->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void ICMPanel::ipChanged () { +void ICMPanel::ipChanged () +{ Glib::ustring profname; + if (inone->get_active()) { profname = "(none)"; ckbBlendCMSMatrix->set_sensitive(false); - } - else if (iembedded->get_active ()) { + } else if (iembedded->get_active ()) { profname = "(embedded)"; ckbBlendCMSMatrix->set_sensitive(false); - } - else if (icamera->get_active ()) { + } else if (icamera->get_active ()) { profname = "(camera)"; ckbBlendCMSMatrix->set_sensitive(false); - } - else if (icameraICC->get_active ()) { + } else if (icameraICC->get_active ()) { profname = "(cameraICC)"; ckbBlendCMSMatrix->set_sensitive(true); - } - else { + } else { profname = ipDialog->get_filename (); ckbBlendCMSMatrix->set_sensitive(true); } + updateDCP(-1, profname); - if (listener && profname!=oldip) + if (listener && profname != oldip) { listener->panelChanged (EvIProfile, profname); + } oldip = profname; } -void ICMPanel::blendCMSMatrixChanged() { +void ICMPanel::blendCMSMatrixChanged() +{ if (batchMode) { if (ckbBlendCMSMatrix->get_inconsistent()) { ckbBlendCMSMatrix->set_inconsistent (false); blendcmsconn.block (true); ckbBlendCMSMatrix->set_active (false); blendcmsconn.block (false); - } - else if (lastBlendCMSMatrix) + } else if (lastBlendCMSMatrix) { ckbBlendCMSMatrix->set_inconsistent (true); + } lastBlendCMSMatrix = ckbBlendCMSMatrix->get_active (); } - if (listener) listener->panelChanged (EvBlendCMSMatrix, ckbBlendCMSMatrix->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + if (listener) { + listener->panelChanged (EvBlendCMSMatrix, ckbBlendCMSMatrix->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void ICMPanel::GamChanged() { +void ICMPanel::GamChanged() +{ if (batchMode) { if (freegamma->get_inconsistent()) { freegamma->set_inconsistent (false); gamcsconn.block (true); freegamma->set_active (false); gamcsconn.block (false); - } - else if (lastgamfree) + } else if (lastgamfree) { freegamma->set_inconsistent (true); + } lastgamfree = freegamma->get_active (); } if (listener) { - if (freegamma->get_active()){ + if (freegamma->get_active()) { listener->panelChanged (EvGAMFREE, M("GENERAL_ENABLED")); onames->set_sensitive(!freegamma->get_active());//disabled choice wgamma->set_sensitive(!freegamma->get_active()); - } - else { + } else { listener->panelChanged (EvGAMFREE, M("GENERAL_DISABLED")); - onames->set_sensitive(!freegamma->get_active() && wgamma->get_active_row_number()==0); + onames->set_sensitive(!freegamma->get_active() && wgamma->get_active_row_number() == 0); wgamma->set_sensitive(!freegamma->get_active()); } } } -void ICMPanel::opChanged () { +void ICMPanel::opChanged () +{ - if (listener) + if (listener) { listener->panelChanged (EvOProfile, onames->get_active_text()); + } } -void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) { +void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) +{ disableListener (); @@ -808,23 +881,28 @@ void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) { iembedded->set_active (!raw); icamera->set_sensitive (raw); icameraICC->set_sensitive (raw && (iccStore->getStdProfile(pMeta->getCamera()) != NULL || dcpStore->getStdProfile(pMeta->getCamera()) != NULL)); - iembedded->set_sensitive (!raw); + iembedded->set_sensitive (!raw); enableListener (); } -void ICMPanel::ipSelectionChanged() { +void ICMPanel::ipSelectionChanged() +{ - if (ipDialog->get_filename() == "") + if (ipDialog->get_filename() == "") { return; + } ipChanged(); } -void ICMPanel::saveReferencePressed () { +void ICMPanel::saveReferencePressed () +{ - if (!icmplistener) + if (!icmplistener) { return; + } + Gtk::FileChooserDialog dialog(M("TP_ICM_SAVEREFERENCE"), Gtk::FILE_CHOOSER_ACTION_SAVE); FileChooserLastFolderPersister persister(&dialog, options.lastProfilingReferenceDir); dialog.set_current_name (lastRefFilename); @@ -855,15 +933,20 @@ void ICMPanel::saveReferencePressed () { //dialog.set_do_overwrite_confirmation (true); bool done = false; + do { int result = dialog.run(); + if (result != Gtk::RESPONSE_OK) { done = true; } else { std::string fname = dialog.get_filename(); Glib::ustring ext = getExtension(fname); - if (ext != "tif" && ext != "tiff") + + if (ext != "tif" && ext != "tiff") { fname += ".tif"; + } + if (confirmOverwrite(dialog, fname)) { icmplistener->saveInputICCReference (fname, applyWB.get_active()); lastRefFilename = Glib::path_get_basename (fname); @@ -871,10 +954,12 @@ void ICMPanel::saveReferencePressed () { } } } while (!done); + return; } -void ICMPanel::setBatchMode (bool batchMode) { +void ICMPanel::setBatchMode (bool batchMode) +{ isBatchMode = true; ignoreDcpSignal = false; diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index bbc9c1194..856558dff 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -7,7 +7,7 @@ * 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 @@ -27,98 +27,103 @@ #include "toolpanel.h" #include "../rtengine/imagedata.h" -class ICMPanelListener { +class ICMPanelListener +{ - public: - virtual ~ICMPanelListener() {} - virtual void saveInputICCReference (Glib::ustring fname, bool apply_wb) {} +public: + virtual ~ICMPanelListener() {} + virtual void saveInputICCReference (Glib::ustring fname, bool apply_wb) {} }; -class ICMPanel : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class ICMPanel : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: - Gtk::Frame* dcpFrame; - Adjuster* gampos; - Adjuster* slpos; - bool lastgamfree; - sigc::connection gamcsconn; - //bool freegamma; - bool lastToneCurve; - sigc::connection tcurveconn; - bool lastApplyLookTable; - sigc::connection ltableconn; - bool lastApplyBaselineExposureOffset; - sigc::connection beoconn; - bool lastApplyHueSatMap; - sigc::connection hsmconn; - bool lastBlendCMSMatrix; - bool isBatchMode; - sigc::connection blendcmsconn; +protected: + Gtk::Frame* dcpFrame; + Adjuster* gampos; + Adjuster* slpos; + bool lastgamfree; + sigc::connection gamcsconn; + //bool freegamma; + bool lastToneCurve; + sigc::connection tcurveconn; + bool lastApplyLookTable; + sigc::connection ltableconn; + bool lastApplyBaselineExposureOffset; + sigc::connection beoconn; + bool lastApplyHueSatMap; + sigc::connection hsmconn; + bool lastBlendCMSMatrix; + bool isBatchMode; + sigc::connection blendcmsconn; - private: - Gtk::VBox * iVBox; +private: + Gtk::VBox * iVBox; - Gtk::CheckButton* freegamma; - Gtk::RadioButton* inone; + Gtk::CheckButton* freegamma; + Gtk::RadioButton* inone; - Gtk::RadioButton* iembedded; - Gtk::RadioButton* icamera; - Gtk::RadioButton* icameraICC; - Gtk::RadioButton* ifromfile; - Gtk::Label* dcpIllLabel; - MyComboBoxText* dcpIll; - Gtk::CheckButton* ckbToneCurve; - Gtk::CheckButton* ckbApplyLookTable; - Gtk::CheckButton* ckbApplyBaselineExposureOffset; - Gtk::CheckButton* ckbApplyHueSatMap; - Gtk::CheckButton* ckbBlendCMSMatrix; - MyComboBoxText* wnames; - MyComboBoxText* wgamma; + Gtk::RadioButton* iembedded; + Gtk::RadioButton* icamera; + Gtk::RadioButton* icameraICC; + Gtk::RadioButton* ifromfile; + Gtk::Label* dcpIllLabel; + MyComboBoxText* dcpIll; + Gtk::CheckButton* ckbToneCurve; + Gtk::CheckButton* ckbApplyLookTable; + Gtk::CheckButton* ckbApplyBaselineExposureOffset; + Gtk::CheckButton* ckbApplyHueSatMap; + Gtk::CheckButton* ckbBlendCMSMatrix; + MyComboBoxText* wnames; + MyComboBoxText* wgamma; - MyComboBoxText* onames; - Gtk::RadioButton* ofromdir; - Gtk::RadioButton* ofromfile; - Gtk::RadioButton* iunchanged; - MyFileChooserButton* ipDialog; - std::auto_ptr ipDialogPersister; - Gtk::RadioButton::Group opts; - Gtk::Button* saveRef; - sigc::connection ipc; - Glib::ustring oldip; - ICMPanelListener* icmplistener; + MyComboBoxText* onames; + Gtk::RadioButton* ofromdir; + Gtk::RadioButton* ofromfile; + Gtk::RadioButton* iunchanged; + MyFileChooserButton* ipDialog; + std::auto_ptr ipDialogPersister; + Gtk::RadioButton::Group opts; + Gtk::Button* saveRef; + sigc::connection ipc; + Glib::ustring oldip; + ICMPanelListener* icmplistener; - bool ignoreDcpSignal; - double dcpTemperatures[2]; - bool enableLastICCWorkDirChange; - Glib::ustring lastRefFilename; - void updateDCP(int dcpIlluminant, Glib::ustring dcp_name); - public: - ICMPanel (); + bool ignoreDcpSignal; + double dcpTemperatures[2]; + bool enableLastICCWorkDirChange; + Glib::ustring lastRefFilename; + void updateDCP(int dcpIlluminant, Glib::ustring dcp_name); +public: + ICMPanel (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void adjusterChanged (Adjuster* a, double newval); - void setAdjusterBehavior (bool gammaadd, bool slopeadd); - - void wpChanged (); - void opChanged (); - void ipChanged (); - void gpChanged (); - void GamChanged (); - void ipSelectionChanged (); - void blendCMSMatrixChanged(); - void dcpIlluminantChanged(); - void toneCurveChanged(); - void applyLookTableChanged(); - void applyBaselineExposureOffsetChanged(); - void applyHueSatMapChanged(); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void adjusterChanged (Adjuster* a, double newval); + void setAdjusterBehavior (bool gammaadd, bool slopeadd); - void setRawMeta (bool raw, const rtengine::ImageData* pMeta); - void saveReferencePressed (); + void wpChanged (); + void opChanged (); + void ipChanged (); + void gpChanged (); + void GamChanged (); + void ipSelectionChanged (); + void blendCMSMatrixChanged(); + void dcpIlluminantChanged(); + void toneCurveChanged(); + void applyLookTableChanged(); + void applyBaselineExposureOffsetChanged(); + void applyHueSatMapChanged(); - void setICMPanelListener (ICMPanelListener* ipl) { icmplistener = ipl; } + void setRawMeta (bool raw, const rtengine::ImageData* pMeta); + void saveReferencePressed (); + + void setICMPanelListener (ICMPanelListener* ipl) + { + icmplistener = ipl; + } }; #endif diff --git a/rtgui/ilabel.cc b/rtgui/ilabel.cc index 753eb8346..591564305 100644 --- a/rtgui/ilabel.cc +++ b/rtgui/ilabel.cc @@ -7,7 +7,7 @@ * 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 @@ -20,7 +20,8 @@ ILabel::ILabel (Glib::ustring lab) : label(lab) {} -void ILabel::on_realize() { +void ILabel::on_realize() +{ Gtk::DrawingArea::on_realize(); add_events(Gdk::EXPOSURE_MASK); @@ -29,10 +30,11 @@ void ILabel::on_realize() { fn->set_markup (label); int labw, labh; fn->get_pixel_size (labw, labh); - set_size_request (2+labw,2+labh); + set_size_request (2 + labw, 2 + labh); } -bool ILabel::on_expose_event (GdkEventExpose* event) { +bool ILabel::on_expose_event (GdkEventExpose* event) +{ Glib::RefPtr style = get_style (); Glib::RefPtr window = get_window(); @@ -51,11 +53,12 @@ bool ILabel::on_expose_event (GdkEventExpose* event) { return true; } -void ILabel::on_style_changed (const Glib::RefPtr& style) { +void ILabel::on_style_changed (const Glib::RefPtr& style) +{ Glib::RefPtr fn = create_pango_layout(label); fn->set_markup (label); int labw, labh; fn->get_pixel_size (labw, labh); - set_size_request (2+labw,2+labh); + set_size_request (2 + labw, 2 + labh); } diff --git a/rtgui/ilabel.h b/rtgui/ilabel.h index b4de52342..aef5eb2ed 100644 --- a/rtgui/ilabel.h +++ b/rtgui/ilabel.h @@ -7,7 +7,7 @@ * 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 @@ -21,15 +21,16 @@ #include -class ILabel : public Gtk::DrawingArea { +class ILabel : public Gtk::DrawingArea +{ Glib::ustring label; - public: - ILabel (Glib::ustring lab); - bool on_expose_event(GdkEventExpose* event); - void on_realize(); - void on_style_changed (const Glib::RefPtr& style); +public: + ILabel (Glib::ustring lab); + bool on_expose_event(GdkEventExpose* event); + void on_realize(); + void on_style_changed (const Glib::RefPtr& style); }; #endif diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 5a3820350..b77e90f09 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -7,7 +7,7 @@ * 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 @@ -25,20 +25,21 @@ #include "../rtengine/refreshmap.h" #include "options.h" -ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), firstOpen(true) { +ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), firstOpen(true) +{ infotext = ""; cropgl = NULL; - pmlistener = NULL; - pmhlistener = NULL; + pmlistener = NULL; + pmhlistener = NULL; focusGrabber = NULL; flawnOverWindow = NULL; mainCropWindow = NULL; previewHandler = NULL; - showClippedH = false; - showClippedS = false; + showClippedH = false; + showClippedS = false; listener = NULL; - + zoomPanel = Gtk::manage (new ZoomPanel (this)); indClippedPanel = Gtk::manage (new IndicateClippedPanel (this)); previewModePanel = Gtk::manage (new PreviewModePanel (this)); @@ -52,129 +53,149 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p), firstOpen(true) { iLinkedImageArea = NULL; } -ImageArea::~ImageArea () { +ImageArea::~ImageArea () +{ - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { delete *i; + } + cropWins.clear (); - if (mainCropWindow) + if (mainCropWindow) { delete mainCropWindow; + } } void ImageArea::on_realize() { - Gtk::DrawingArea::on_realize(); + Gtk::DrawingArea::on_realize(); #if defined (__APPLE__) - // Workaround: disabling POINTER_MOTION_HINT_MASK as for gtk 2.24.22 the get_pointer() function is buggy for quartz and modifier mask is not updated correctly. - // This workaround should be removed when bug is fixed in GTK2 or when migrating to GTK3 - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + // Workaround: disabling POINTER_MOTION_HINT_MASK as for gtk 2.24.22 the get_pointer() function is buggy for quartz and modifier mask is not updated correctly. + // This workaround should be removed when bug is fixed in GTK2 or when migrating to GTK3 + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); #else - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); #endif - Cairo::FontOptions cfo; - cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL); - get_pango_context ()->set_cairo_font_options (cfo); + Cairo::FontOptions cfo; + cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL); + get_pango_context ()->set_cairo_font_options (cfo); } -void ImageArea::on_resized (Gtk::Allocation& req) { - if (ipc && get_width()>1) { // sometimes on_resize is called in some init state, causing wrong sizes - if (!mainCropWindow) { - mainCropWindow = new CropWindow (this, ipc, false, false); - mainCropWindow->setDecorated (false); - mainCropWindow->setFitZoomEnabled (true); - mainCropWindow->addCropWindowListener (this); - mainCropWindow->setCropGUIListener (cropgl); - mainCropWindow->setPointerMotionListener (pmlistener); - mainCropWindow->setPointerMotionHListener (pmhlistener); - mainCropWindow->setPosition (0, 0); - mainCropWindow->setSize (get_width(), get_height(), false); // this execute the refresh itself - mainCropWindow->enable(); // start processing ! - } - else { - mainCropWindow->setSize (get_width(), get_height()); - } - parent->syncBeforeAfterViews(); - } +void ImageArea::on_resized (Gtk::Allocation& req) +{ + if (ipc && get_width() > 1) { // sometimes on_resize is called in some init state, causing wrong sizes + if (!mainCropWindow) { + mainCropWindow = new CropWindow (this, ipc, false, false); + mainCropWindow->setDecorated (false); + mainCropWindow->setFitZoomEnabled (true); + mainCropWindow->addCropWindowListener (this); + mainCropWindow->setCropGUIListener (cropgl); + mainCropWindow->setPointerMotionListener (pmlistener); + mainCropWindow->setPointerMotionHListener (pmhlistener); + mainCropWindow->setPosition (0, 0); + mainCropWindow->setSize (get_width(), get_height(), false); // this execute the refresh itself + mainCropWindow->enable(); // start processing ! + } else { + mainCropWindow->setSize (get_width(), get_height()); + } + + parent->syncBeforeAfterViews(); + } } -void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) { - if( !ipc_ ){ +void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) +{ + if( !ipc_ ) { focusGrabber = NULL; std::list::iterator i = cropWins.begin(); - for( ;i!=cropWins.end();i++ ){ - delete *i; + + for( ; i != cropWins.end(); i++ ) { + delete *i; } + cropWins.clear(); mainCropWindow->setObservedCropWin (NULL); } + ipc = ipc_; } -void ImageArea::setPreviewHandler (PreviewHandler* ph) { - - previewHandler = ph; +void ImageArea::setPreviewHandler (PreviewHandler* ph) +{ + + previewHandler = ph; } -void ImageArea::on_style_changed (const Glib::RefPtr& style) { +void ImageArea::on_style_changed (const Glib::RefPtr& style) +{ // TODO: notify all crop windows that the style has been changed queue_draw (); } -void ImageArea::setInfoText (Glib::ustring text) { +void ImageArea::setInfoText (Glib::ustring text) +{ infotext = text; Glib::RefPtr context = get_pango_context () ; Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); - fontd.set_size (9*Pango::SCALE); + fontd.set_size (9 * Pango::SCALE); context->set_font_description (fontd); ilayout = create_pango_layout(""); ilayout->set_markup(text); int iw, ih; - ilayout->get_pixel_size (iw, ih); - ipixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, true, 8, iw+8, ih+8); + ilayout->get_pixel_size (iw, ih); + ipixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, true, 8, iw + 8, ih + 8); ipixbuf->fill (128); } -void ImageArea::infoEnabled (bool e) { +void ImageArea::infoEnabled (bool e) +{ - if (options.showInfo!=e) { - options.showInfo = e; + if (options.showInfo != e) { + options.showInfo = e; queue_draw (); } } -CropWindow* ImageArea::getCropWindow (int x, int y) { - +CropWindow* ImageArea::getCropWindow (int x, int y) +{ + CropWindow* cw = mainCropWindow; - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) - if ((*i)->isInside (x, y)) + + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) + if ((*i)->isInside (x, y)) { return *i; + } + return cw; } -void ImageArea::redraw () { +void ImageArea::redraw () +{ // dirty prevents multiple updates queued up if (!dirty) { dirty = true; queue_draw (); - } + } } -bool ImageArea::on_expose_event(GdkEventExpose* event) { +bool ImageArea::on_expose_event(GdkEventExpose* event) +{ dirty = false; - if (event->count) + if (event->count) { return true; - + } + Glib::RefPtr window = get_window(); Cairo::RefPtr cr = get_window()->create_cairo_context(); @@ -183,99 +204,116 @@ bool ImageArea::on_expose_event(GdkEventExpose* event) { mainCropWindow->expose (cr); } - if (options.showInfo==true && infotext!="") { + if (options.showInfo == true && infotext != "") { int fnw, fnh; ilayout->get_pixel_size (fnw, fnh); - window->draw_pixbuf (get_style()->get_base_gc (Gtk::STATE_NORMAL), ipixbuf, 0, 0, 4, 4, fnw+8, fnh+8, Gdk::RGB_DITHER_NONE, 0, 0); + window->draw_pixbuf (get_style()->get_base_gc (Gtk::STATE_NORMAL), ipixbuf, 0, 0, 4, 4, fnw + 8, fnh + 8, Gdk::RGB_DITHER_NONE, 0, 0); cr->set_source_rgb (1.0, 1.0, 1.0); cr->move_to (8, 8); ilayout->add_to_cairo_context (cr); cr->fill (); } - for (std::list::reverse_iterator i=cropWins.rbegin(); i!=cropWins.rend(); i++) + for (std::list::reverse_iterator i = cropWins.rbegin(); i != cropWins.rend(); i++) { (*i)->expose (cr); + } return true; } -bool ImageArea::on_motion_notify_event (GdkEventMotion* event) { +bool ImageArea::on_motion_notify_event (GdkEventMotion* event) +{ - if (focusGrabber) + if (focusGrabber) { focusGrabber->pointerMoved (event->state, event->x, event->y); - else { + } else { CropWindow* cw = getCropWindow (event->x, event->y); + if (cw) { if (cw != flawnOverWindow) { - if (flawnOverWindow) + if (flawnOverWindow) { flawnOverWindow->flawnOver(false); + } + cw->flawnOver(true); flawnOverWindow = cw; } + cw->pointerMoved (event->state, event->x, event->y); - } - else if (flawnOverWindow) { + } else if (flawnOverWindow) { flawnOverWindow->flawnOver(false); flawnOverWindow = NULL; } } + return true; } -bool ImageArea::on_button_press_event (GdkEventButton* event) { +bool ImageArea::on_button_press_event (GdkEventButton* event) +{ - if (focusGrabber) + if (focusGrabber) { focusGrabber->buttonPress (event->button, event->type, event->state, event->x, event->y); - else { + } else { CropWindow* cw = getCropWindow (event->x, event->y); - if (cw) + + if (cw) { cw->buttonPress (event->button, event->type, event->state, event->x, event->y); + } } + return true; } -bool ImageArea::on_scroll_event (GdkEventScroll* event) { +bool ImageArea::on_scroll_event (GdkEventScroll* event) +{ CropWindow* cw = getCropWindow (event->x, event->y); + if (cw) { - int newCenterX = (int)event->x; - int newCenterY = (int)event->y; - if (event->direction==GDK_SCROLL_UP && !cw->isMaxZoom()) { + int newCenterX = (int)event->x; + int newCenterY = (int)event->y; + + if (event->direction == GDK_SCROLL_UP && !cw->isMaxZoom()) { cw->findCenter (1, newCenterX, newCenterY); cw->zoomIn (true, newCenterX, newCenterY); - } - else if (!cw->isMinZoom()) { + } else if (!cw->isMinZoom()) { cw->findCenter (-1, newCenterX, newCenterY); cw->zoomOut (true, newCenterX, newCenterY); } } + return true; } -bool ImageArea::on_button_release_event (GdkEventButton* event) { +bool ImageArea::on_button_release_event (GdkEventButton* event) +{ - if (focusGrabber) + if (focusGrabber) { focusGrabber->buttonRelease (event->button, event->type, event->state, event->x, event->y); - else { + } else { CropWindow* cw = getCropWindow (event->x, event->y); + if (cw) { cw->buttonRelease (event->button, event->type, event->state, event->x, event->y); } } + return true; } -bool ImageArea::on_leave_notify_event (GdkEventCrossing* event) { +bool ImageArea::on_leave_notify_event (GdkEventCrossing* event) +{ if (flawnOverWindow) { flawnOverWindow->flawnOver(false); flawnOverWindow = NULL; } + if (focusGrabber) { focusGrabber->flawnOver(false); focusGrabber->leaveNotify (event); - } - else { + } else { CropWindow* cw = getCropWindow (event->x, event->y); if (cw) { @@ -283,18 +321,23 @@ bool ImageArea::on_leave_notify_event (GdkEventCrossing* event) { cw->leaveNotify (event); } } + return true; } -void ImageArea::subscribe(EditSubscriber *subscriber) { +void ImageArea::subscribe(EditSubscriber *subscriber) +{ mainCropWindow->cropHandler.setEditSubscriber(subscriber); - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) + + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { (*i)->cropHandler.setEditSubscriber(subscriber); + } EditDataProvider::subscribe(subscriber); - if (listener && listener->getToolBar()) + if (listener && listener->getToolBar()) { listener->getToolBar()->startEditMode (); + } if (subscriber->getEditingType() == ET_OBJECTS) { // In this case, no need to reprocess the image, so we redraw the image to display the geometry @@ -302,50 +345,65 @@ void ImageArea::subscribe(EditSubscriber *subscriber) { } } -void ImageArea::unsubscribe() { +void ImageArea::unsubscribe() +{ bool wasObjectType = false; EditSubscriber* oldSubscriber = EditDataProvider::getCurrSubscriber(); - if (oldSubscriber && oldSubscriber->getEditingType()==ET_OBJECTS) + + if (oldSubscriber && oldSubscriber->getEditingType() == ET_OBJECTS) { wasObjectType = true; + } EditDataProvider::unsubscribe(); // Ask the Crops to free-up edit mode buffers mainCropWindow->cropHandler.setEditSubscriber(NULL); - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) + + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { (*i)->cropHandler.setEditSubscriber(NULL); + } + setToolHand(); - if (listener && listener->getToolBar()) + if (listener && listener->getToolBar()) { listener->getToolBar()->stopEditMode (); + } - if (wasObjectType) + if (wasObjectType) { queue_draw(); + } } -void ImageArea::getImageSize (int &w, int&h) { +void ImageArea::getImageSize (int &w, int&h) +{ if (ipc) { w = ipc->getFullWidth(); h = ipc->getFullHeight(); - } - else + } else { w = h = 0; + } } -void ImageArea::grabFocus (CropWindow* cw) { - +void ImageArea::grabFocus (CropWindow* cw) +{ + focusGrabber = cw; - if (cw && cw!=mainCropWindow) + + if (cw && cw != mainCropWindow) { cropWindowSelected (cw); + } } -void ImageArea::unGrabFocus () { +void ImageArea::unGrabFocus () +{ focusGrabber = NULL; } -void ImageArea::addCropWindow () { - if (!mainCropWindow) - return; // if called but no image is loaded, it would crash +void ImageArea::addCropWindow () +{ + if (!mainCropWindow) { + return; // if called but no image is loaded, it would crash + } CropWindow* cw = new CropWindow (this, ipc, true, true); cw->zoom11(); @@ -354,242 +412,304 @@ void ImageArea::addCropWindow () { cw->setPointerMotionHListener (pmhlistener); int lastWidth = options.detailWindowWidth; int lastHeight = options.detailWindowHeight; - if (lastWidthgetSize(lastWidth,lastHeight); + CropWindow *lastCrop; + lastCrop = cropWins.front(); + + if(lastCrop) { + lastCrop->getSize(lastWidth, lastHeight); + } } cropWins.push_front (cw); // Position the new crop window this way: start from top right going down to bottom. When bottom is reached, continue top left going down...... - int N = cropWins.size()-1; - int cropwidth, cropheight; - - if(lastWidth <= 0) { // this is only the case for very first start of RT 4.1 or when options file is deleted - cropwidth = 200; - cropheight = 200; - } else { - cropwidth = lastWidth; - cropheight = lastHeight; - } + int N = cropWins.size() - 1; + int cropwidth, cropheight; - cw->setSize (cropwidth,cropheight); - int x,y; - int maxRows = get_height()/cropheight; - if(maxRows == 0) - maxRows = 1; + if(lastWidth <= 0) { // this is only the case for very first start of RT 4.1 or when options file is deleted + cropwidth = 200; + cropheight = 200; + } else { + cropwidth = lastWidth; + cropheight = lastHeight; + } - int col = N / maxRows; - if(col % 2) { // from left side - col = col/2; - x = col*cropwidth; - if(x >= get_width() - 50) - x = get_width() - 50; - } - else { // from right side - col /= 2; - col++; - x = get_width() - col * cropwidth; - if(x <= 0) - x = 0; - } + cw->setSize (cropwidth, cropheight); + int x, y; + int maxRows = get_height() / cropheight; - y = cropheight * (N%maxRows); - cw->setPosition (x, y); - cw->enable(); // start processing! + if(maxRows == 0) { + maxRows = 1; + } - int x0,y0,w,h,wc,hc; - mainCropWindow->getCropRectangle(x0,y0,w,h ); - cw->getCropSize(wc,hc); - cw->setCropPosition(x0+w/2-wc/2,y0+h/2-hc/2); - mainCropWindow->setObservedCropWin (cropWins.front()); + int col = N / maxRows; - if(cropWins.size()==1) // after first detail window we already have high quality - ipc->startProcessing(M_HIGHQUAL); + if(col % 2) { // from left side + col = col / 2; + x = col * cropwidth; + + if(x >= get_width() - 50) { + x = get_width() - 50; + } + } else { // from right side + col /= 2; + col++; + x = get_width() - col * cropwidth; + + if(x <= 0) { + x = 0; + } + } + + y = cropheight * (N % maxRows); + cw->setPosition (x, y); + cw->enable(); // start processing! + + int x0, y0, w, h, wc, hc; + mainCropWindow->getCropRectangle(x0, y0, w, h ); + cw->getCropSize(wc, hc); + cw->setCropPosition(x0 + w / 2 - wc / 2, y0 + h / 2 - hc / 2); + mainCropWindow->setObservedCropWin (cropWins.front()); + + if(cropWins.size() == 1) { // after first detail window we already have high quality + ipc->startProcessing(M_HIGHQUAL); + } } -void ImageArea::cropWindowSelected (CropWindow* cw) { +void ImageArea::cropWindowSelected (CropWindow* cw) +{ std::list::iterator i = std::find (cropWins.begin(), cropWins.end(), cw); - if (i!=cropWins.end()) + + if (i != cropWins.end()) { cropWins.erase (i); + } + cropWins.push_front (cw); mainCropWindow->setObservedCropWin (cropWins.front()); } -void ImageArea::cropWindowClosed (CropWindow* cw) { - - focusGrabber = NULL; +void ImageArea::cropWindowClosed (CropWindow* cw) +{ + + focusGrabber = NULL; std::list::iterator i = std::find (cropWins.begin(), cropWins.end(), cw); - if (i!=cropWins.end()) + + if (i != cropWins.end()) { cropWins.erase (i); - if (!cropWins.empty()) + } + + if (!cropWins.empty()) { mainCropWindow->setObservedCropWin (cropWins.front()); - else + } else { mainCropWindow->setObservedCropWin (NULL); - queue_draw (); + } + + queue_draw (); } -void ImageArea::straightenReady (double rotDeg) { +void ImageArea::straightenReady (double rotDeg) +{ - if (listener) - listener->rotateSelectionReady (rotDeg); + if (listener) { + listener->rotateSelectionReady (rotDeg); + } } -void ImageArea::spotWBSelected (int x, int y) { +void ImageArea::spotWBSelected (int x, int y) +{ - if (listener) + if (listener) { listener->spotWBselected (x, y); + } } -void ImageArea::getScrollImageSize (int& w, int& h) { +void ImageArea::getScrollImageSize (int& w, int& h) +{ if (mainCropWindow && ipc) { double z = mainCropWindow->getZoom (); w = ipc->getFullWidth() * z; h = ipc->getFullHeight() * z; - } - else + } else { w = h = 0; + } } -void ImageArea::getScrollPosition (int& x, int& y) { +void ImageArea::getScrollPosition (int& x, int& y) +{ if (mainCropWindow) { int cropX, cropY; mainCropWindow->getCropPosition (cropX, cropY); - x = cropX*mainCropWindow->getZoom (); - y = cropY*mainCropWindow->getZoom (); - } - else + x = cropX * mainCropWindow->getZoom (); + y = cropY * mainCropWindow->getZoom (); + } else { x = y = 0; + } } -void ImageArea::setScrollPosition (int x, int y) { +void ImageArea::setScrollPosition (int x, int y) +{ if (mainCropWindow) { mainCropWindow->delCropWindowListener (this); - mainCropWindow->setCropPosition (x/mainCropWindow->getZoom (), y/mainCropWindow->getZoom ()); + mainCropWindow->setCropPosition (x / mainCropWindow->getZoom (), y / mainCropWindow->getZoom ()); mainCropWindow->addCropWindowListener (this); } } -void ImageArea::cropPositionChanged (CropWindow* cw) { +void ImageArea::cropPositionChanged (CropWindow* cw) +{ syncBeforeAfterViews (); } -void ImageArea::cropWindowSizeChanged (CropWindow* cw) { +void ImageArea::cropWindowSizeChanged (CropWindow* cw) +{ syncBeforeAfterViews (); } -void ImageArea::cropZoomChanged (CropWindow* cw) { +void ImageArea::cropZoomChanged (CropWindow* cw) +{ - if (cw==mainCropWindow) { + if (cw == mainCropWindow) { parent->zoomChanged (); syncBeforeAfterViews (); zoomPanel->refreshZoomLabel (); } } -double ImageArea::getZoom () { - - if (mainCropWindow) - return mainCropWindow->getZoom (); - else - return 1.0; -} - -// Called by imageAreaPanel before/after views -void ImageArea::setZoom (double zoom) { - - if (mainCropWindow) - mainCropWindow->setZoom (zoom); - zoomPanel->refreshZoomLabel (); -} - -void ImageArea::initialImageArrived (CropWindow* cw) { +double ImageArea::getZoom () +{ if (mainCropWindow) { - if(firstOpen || options.prevdemo!=PD_Sidecar || (!options.rememberZoomAndPan) ) { - mainCropWindow->zoomFit (false); - firstOpen = false; - mainCropWindow->cropHandler.getFullImageSize(fullImageWidth,fullImageHeight); - } else { - int w,h; - mainCropWindow->cropHandler.getFullImageSize(w,h); - if(w == fullImageWidth && h == fullImageHeight) { // && mainCropWindow->getZoom() != mainCropWindow->getZoomFitVal()) { - int x,y; - mainCropWindow->getCropPosition(x,y); - mainCropWindow->setCropPosition(x,y, false); - } else { - mainCropWindow->zoomFit (false); - } - fullImageWidth = w; - fullImageHeight = h; - } + return mainCropWindow->getZoom (); + } else { + return 1.0; } } -void ImageArea::syncBeforeAfterViews () { +// Called by imageAreaPanel before/after views +void ImageArea::setZoom (double zoom) +{ + + if (mainCropWindow) { + mainCropWindow->setZoom (zoom); + } + + zoomPanel->refreshZoomLabel (); +} + +void ImageArea::initialImageArrived (CropWindow* cw) +{ + + if (mainCropWindow) { + if(firstOpen || options.prevdemo != PD_Sidecar || (!options.rememberZoomAndPan) ) { + mainCropWindow->zoomFit (false); + firstOpen = false; + mainCropWindow->cropHandler.getFullImageSize(fullImageWidth, fullImageHeight); + } else { + int w, h; + mainCropWindow->cropHandler.getFullImageSize(w, h); + + if(w == fullImageWidth && h == fullImageHeight) { // && mainCropWindow->getZoom() != mainCropWindow->getZoomFitVal()) { + int x, y; + mainCropWindow->getCropPosition(x, y); + mainCropWindow->setCropPosition(x, y, false); + } else { + mainCropWindow->zoomFit (false); + } + + fullImageWidth = w; + fullImageHeight = h; + } + } +} + +void ImageArea::syncBeforeAfterViews () +{ parent->syncBeforeAfterViews (); } -void ImageArea::setCropGUIListener (CropGUIListener* l) { - - cropgl = l; - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) +void ImageArea::setCropGUIListener (CropGUIListener* l) +{ + + cropgl = l; + + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { (*i)->setCropGUIListener (cropgl); - if (mainCropWindow) + } + + if (mainCropWindow) { mainCropWindow->setCropGUIListener (cropgl); + } } -void ImageArea::setPointerMotionListener (PointerMotionListener* pml) { +void ImageArea::setPointerMotionListener (PointerMotionListener* pml) +{ - pmlistener = pml; - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) + pmlistener = pml; + + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { (*i)->setPointerMotionListener (pml); - if (mainCropWindow) + } + + if (mainCropWindow) { mainCropWindow->setPointerMotionListener (pml); + } } -void ImageArea::setPointerMotionHListener (PointerMotionListener* pml) { +void ImageArea::setPointerMotionHListener (PointerMotionListener* pml) +{ - pmhlistener = pml; - for (std::list::iterator i=cropWins.begin(); i!=cropWins.end(); i++) + pmhlistener = pml; + + for (std::list::iterator i = cropWins.begin(); i != cropWins.end(); i++) { (*i)->setPointerMotionHListener (pml); - if (mainCropWindow) + } + + if (mainCropWindow) { mainCropWindow->setPointerMotionHListener (pml); + } } -ToolMode ImageArea::getToolMode () { +ToolMode ImageArea::getToolMode () +{ - if (listener && listener->getToolBar()) - return listener->getToolBar()->getTool (); - else + if (listener && listener->getToolBar()) { + return listener->getToolBar()->getTool (); + } else { return TMHand; + } } -void ImageArea::setToolHand () { - +void ImageArea::setToolHand () +{ + if (listener && listener->getToolBar()) { listener->getToolBar()->setTool (TMHand); } } -int ImageArea::getSpotWBRectSize () { - - if (listener) - return listener->getSpotWBRectSize (); - else +int ImageArea::getSpotWBRectSize () +{ + + if (listener) { + return listener->getSpotWBRectSize (); + } else { return 1; + } } diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index f8e665cca..bd2c19093 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -7,7 +7,7 @@ * 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 @@ -33,11 +33,12 @@ #include "edit.h" class ImageAreaPanel; -class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider { +class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider +{ friend class ZoomPanel; - protected: +protected: Glib::ustring infotext; Glib::RefPtr ilayout; @@ -46,7 +47,7 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi bool showClippedH, showClippedS; ImageAreaPanel* parent; - + std::list cropWins; PreviewHandler* previewHandler; rtengine::StagedImageProcessor* ipc; @@ -61,7 +62,7 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi CropWindow* getCropWindow (int x, int y); bool firstOpen; int fullImageWidth, fullImageHeight; - public: +public: CropWindow* mainCropWindow; CropWindow* flawnOverWindow; ZoomPanel* zoomPanel; @@ -73,8 +74,14 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi ~ImageArea (); void setImProcCoordinator (rtengine::StagedImageProcessor* ipc_); - void setPreviewModePanel(PreviewModePanel* previewModePanel_){previewModePanel = previewModePanel_;}; - void setIndicateClippedPanel(IndicateClippedPanel* indClippedPanel_){indClippedPanel = indClippedPanel_;}; + void setPreviewModePanel(PreviewModePanel* previewModePanel_) + { + previewModePanel = previewModePanel_; + }; + void setIndicateClippedPanel(IndicateClippedPanel* indClippedPanel_) + { + indClippedPanel = indClippedPanel_; + }; void getScrollImageSize (int& w, int& h); void getScrollPosition (int& x, int& y); @@ -99,9 +106,15 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi void setCropGUIListener (CropGUIListener* l); void setPointerMotionListener (PointerMotionListener* pml); void setPointerMotionHListener (PointerMotionListener* pml); - void setImageAreaToolListener (ImageAreaToolListener* l) { listener = l; } + void setImageAreaToolListener (ImageAreaToolListener* l) + { + listener = l; + } void setPreviewHandler (PreviewHandler* ph); - PreviewHandler* getPreviewHandler () { return previewHandler; } + PreviewHandler* getPreviewHandler () + { + return previewHandler; + } void grabFocus (CropWindow* cw); void unGrabFocus (); @@ -116,8 +129,8 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi void redraw (); void zoomFit (); - double getZoom (); - void setZoom (double zoom); + double getZoom (); + void setZoom (double zoom); // EditDataProvider interface void subscribe(EditSubscriber *subscriber); @@ -126,11 +139,14 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi // CropWindowListener interface void cropPositionChanged (CropWindow* cw); - void cropWindowSizeChanged (CropWindow* cw); + void cropWindowSizeChanged (CropWindow* cw); void cropZoomChanged (CropWindow* cw); void initialImageArrived (CropWindow* cw) ; - CropWindow* getMainCropWindow () { return mainCropWindow; } + CropWindow* getMainCropWindow () + { + return mainCropWindow; + } }; diff --git a/rtgui/imageareapanel.cc b/rtgui/imageareapanel.cc index e7c91d5e9..b456de2c7 100644 --- a/rtgui/imageareapanel.cc +++ b/rtgui/imageareapanel.cc @@ -7,7 +7,7 @@ * 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 @@ -18,7 +18,8 @@ */ #include "imageareapanel.h" -ImageAreaPanel::ImageAreaPanel () : before(NULL), after(NULL) { +ImageAreaPanel::ImageAreaPanel () : before(NULL), after(NULL) +{ set_border_width (2); @@ -38,57 +39,65 @@ ImageAreaPanel::ImageAreaPanel () : before(NULL), after(NULL) { } -ImageAreaPanel::~ImageAreaPanel () { +ImageAreaPanel::~ImageAreaPanel () +{ delete imageArea; } -void ImageAreaPanel::syncBeforeAfterViews () { +void ImageAreaPanel::syncBeforeAfterViews () +{ - if (before && this==after) + if (before && this == after) { before->synchronize (); - else if (after && this==before) + } else if (after && this == before) { after->synchronize (); + } queue_draw (); } -void ImageAreaPanel::setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft) { +void ImageAreaPanel::setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft) +{ before = bef; after = aft; syncBeforeAfterViews (); } -void ImageAreaPanel::zoomChanged () { +void ImageAreaPanel::zoomChanged () +{ - if (after && this==before) + if (after && this == before) { after->imageArea->setZoom (imageArea->getZoom ()); - else if (before && this==after) + } else if (before && this == after) { before->imageArea->setZoom (imageArea->getZoom ()); + } } -void ImageAreaPanel::synchronize () { +void ImageAreaPanel::synchronize () +{ - if (after && this==before) { + if (after && this == before) { int imgw, imgh, x, y; after->imageArea->getScrollImageSize (imgw, imgh); after->imageArea->getScrollPosition (x, y); - if (imgw>0 && imgh>0) { + + if (imgw > 0 && imgh > 0) { int bimgw, bimgh; imageArea->getScrollImageSize (bimgw, bimgh); - imageArea->setScrollPosition (x*bimgw/imgw, y*bimgh/imgh); + imageArea->setScrollPosition (x * bimgw / imgw, y * bimgh / imgh); imageArea->queue_draw (); } - } - else if (before && this==after) { + } else if (before && this == after) { int imgw, imgh, x, y; before->imageArea->getScrollImageSize (imgw, imgh); before->imageArea->getScrollPosition (x, y); - if (imgw>0 && imgh>0) { + + if (imgw > 0 && imgh > 0) { int bimgw, bimgh; imageArea->getScrollImageSize (bimgw, bimgh); - imageArea->setScrollPosition (x*bimgw/imgw, y*bimgh/imgh); + imageArea->setScrollPosition (x * bimgw / imgw, y * bimgh / imgh); imageArea->queue_draw (); } } diff --git a/rtgui/imageareapanel.h b/rtgui/imageareapanel.h index 1b62682a1..a0c5c8df2 100644 --- a/rtgui/imageareapanel.h +++ b/rtgui/imageareapanel.h @@ -7,7 +7,7 @@ * 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 @@ -22,24 +22,25 @@ #include "imagearea.h" class ImageArea; -class ImageAreaPanel : public Gtk::VBox { +class ImageAreaPanel : public Gtk::VBox +{ - protected: +protected: - ImageAreaPanel *before, *after; + ImageAreaPanel *before, *after; - void synchronize (); - - public: - ImageArea* imageArea; + void synchronize (); - ImageAreaPanel (); - ~ImageAreaPanel (); +public: + ImageArea* imageArea; - void zoomChanged (); - - void setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft); - void syncBeforeAfterViews(); + ImageAreaPanel (); + ~ImageAreaPanel (); + + void zoomChanged (); + + void setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft); + void syncBeforeAfterViews(); }; #endif diff --git a/rtgui/imageareatoollistener.h b/rtgui/imageareatoollistener.h index cc26c70a8..3f1238810 100644 --- a/rtgui/imageareatoollistener.h +++ b/rtgui/imageareatoollistener.h @@ -7,7 +7,7 @@ * 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 @@ -23,16 +23,26 @@ #include "thumbnail.h" #include "cropguilistener.h" -class ImageAreaToolListener { +class ImageAreaToolListener +{ - public: - virtual void spotWBselected (int x, int y, Thumbnail* thm=NULL) {} - virtual int getSpotWBRectSize () { return 8; } +public: + virtual void spotWBselected (int x, int y, Thumbnail* thm = NULL) {} + virtual int getSpotWBRectSize () + { + return 8; + } virtual void cropSelectionReady () {} - virtual void rotateSelectionReady (double rotate_deg, Thumbnail* thm=NULL) {} - virtual ToolBar* getToolBar () { return NULL; } - virtual void removeWbTool() =0; - virtual CropGUIListener* startCropEditing (Thumbnail* thm=NULL) { return NULL; } + virtual void rotateSelectionReady (double rotate_deg, Thumbnail* thm = NULL) {} + virtual ToolBar* getToolBar () + { + return NULL; + } + virtual void removeWbTool() = 0; + virtual CropGUIListener* startCropEditing (Thumbnail* thm = NULL) + { + return NULL; + } }; #endif diff --git a/rtgui/impulsedenoise.cc b/rtgui/impulsedenoise.cc index 2979d42f2..5aba32d77 100644 --- a/rtgui/impulsedenoise.cc +++ b/rtgui/impulsedenoise.cc @@ -7,7 +7,7 @@ * 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 @@ -24,18 +24,20 @@ using namespace rtengine; using namespace rtengine::procparams; -ImpulseDenoise::ImpulseDenoise () : FoldableToolPanel(this, "impulsedenoise", M("TP_IMPULSEDENOISE_LABEL"), true, true) { +ImpulseDenoise::ImpulseDenoise () : FoldableToolPanel(this, "impulsedenoise", M("TP_IMPULSEDENOISE_LABEL"), true, true) +{ - thresh = Gtk::manage (new Adjuster (M("TP_IMPULSEDENOISE_THRESH"), 0, 100, 1, 50)); + thresh = Gtk::manage (new Adjuster (M("TP_IMPULSEDENOISE_THRESH"), 0, 100, 1, 50)); - pack_start (*thresh); + pack_start (*thresh); - thresh->setAdjusterListener (this); + thresh->setAdjusterListener (this); - show_all_children (); + show_all_children (); } -void ImpulseDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ImpulseDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -51,7 +53,8 @@ void ImpulseDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void ImpulseDenoise::write (ProcParams* pp, ParamsEdited* pedited) { +void ImpulseDenoise::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->impulseDenoise.thresh = thresh->getValue (); pp->impulseDenoise.enabled = getEnabled(); @@ -62,17 +65,20 @@ void ImpulseDenoise::write (ProcParams* pp, ParamsEdited* pedited) { } } -void ImpulseDenoise::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ImpulseDenoise::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ thresh->setDefault (defParams->impulseDenoise.thresh); - if (pedited) + if (pedited) { thresh->setDefaultEditedState (pedited->impulseDenoise.thresh ? Edited : UnEdited); - else + } else { thresh->setDefaultEditedState (Irrelevant); + } } -void ImpulseDenoise::adjusterChanged (Adjuster* a, double newval) { +void ImpulseDenoise::adjusterChanged (Adjuster* a, double newval) +{ if (listener && getEnabled()) { @@ -80,29 +86,34 @@ void ImpulseDenoise::adjusterChanged (Adjuster* a, double newval) { } } -void ImpulseDenoise::enabledChanged () { +void ImpulseDenoise::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvIDNEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvIDNEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvIDNEnabled, M("GENERAL_DISABLED")); + } } } -void ImpulseDenoise::setBatchMode (bool batchMode) { +void ImpulseDenoise::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); thresh->showEditedCB (); } -void ImpulseDenoise::setAdjusterBehavior (bool threshadd) { +void ImpulseDenoise::setAdjusterBehavior (bool threshadd) +{ - thresh->setAddMode(threshadd); + thresh->setAddMode(threshadd); } -void ImpulseDenoise::trimValues (rtengine::procparams::ProcParams* pp) { +void ImpulseDenoise::trimValues (rtengine::procparams::ProcParams* pp) +{ - thresh->trimValue(pp->impulseDenoise.thresh); + thresh->trimValue(pp->impulseDenoise.thresh); } diff --git a/rtgui/impulsedenoise.h b/rtgui/impulsedenoise.h index 7c7cdc48c..8052309c3 100644 --- a/rtgui/impulsedenoise.h +++ b/rtgui/impulsedenoise.h @@ -7,7 +7,7 @@ * 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 @@ -23,19 +23,20 @@ #include "adjuster.h" #include "toolpanel.h" -class ImpulseDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class ImpulseDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* thresh; //Adjuster* edge; - public: +public: ImpulseDenoise (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/indclippedpanel.cc b/rtgui/indclippedpanel.cc index a1da0c9b7..e1f04b279 100644 --- a/rtgui/indclippedpanel.cc +++ b/rtgui/indclippedpanel.cc @@ -6,7 +6,7 @@ * 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 @@ -21,49 +21,62 @@ #include "imagearea.h" #include "rtimage.h" -IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) { +IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) +{ Glib::ustring tt; indclippedh = Gtk::manage (new Gtk::ToggleButton ()); indclippedh->set_relief(Gtk::RELIEF_NONE); - indclippedh->add (*Gtk::manage (new RTImage ("warnhl.png"))); - tt = Glib::ustring::compose("%1\n%2 = %3",M("MAIN_TOOLTIP_INDCLIPPEDH"),M("MAIN_TOOLTIP_THRESHOLD"),options.highlightThreshold); - if (tt.find("<") == Glib::ustring::npos && tt.find(">") == Glib::ustring::npos) indclippedh->set_tooltip_text (tt); - else indclippedh->set_tooltip_markup (tt); + indclippedh->add (*Gtk::manage (new RTImage ("warnhl.png"))); + tt = Glib::ustring::compose("%1\n%2 = %3", M("MAIN_TOOLTIP_INDCLIPPEDH"), M("MAIN_TOOLTIP_THRESHOLD"), options.highlightThreshold); + + if (tt.find("<") == Glib::ustring::npos && tt.find(">") == Glib::ustring::npos) { + indclippedh->set_tooltip_text (tt); + } else { + indclippedh->set_tooltip_markup (tt); + } indclippeds = Gtk::manage (new Gtk::ToggleButton ()); indclippeds->set_relief(Gtk::RELIEF_NONE); indclippeds->add (*Gtk::manage (new RTImage ("warnsh.png"))); - tt = Glib::ustring::compose("%1\n%2 = %3",M("MAIN_TOOLTIP_INDCLIPPEDS"),M("MAIN_TOOLTIP_THRESHOLD"),options.shadowThreshold); - if (tt.find("<") == Glib::ustring::npos && tt.find(">") == Glib::ustring::npos) indclippeds->set_tooltip_text (tt); - else indclippeds->set_tooltip_markup (tt); + tt = Glib::ustring::compose("%1\n%2 = %3", M("MAIN_TOOLTIP_INDCLIPPEDS"), M("MAIN_TOOLTIP_THRESHOLD"), options.shadowThreshold); + + if (tt.find("<") == Glib::ustring::npos && tt.find(">") == Glib::ustring::npos) { + indclippeds->set_tooltip_text (tt); + } else { + indclippeds->set_tooltip_markup (tt); + } indclippedh->set_active (options.showClippedHighlights); indclippeds->set_active (options.showClippedShadows); - + pack_start (*indclippedh, Gtk::PACK_SHRINK, 0); pack_start (*indclippeds, Gtk::PACK_SHRINK, 0); indclippedh->signal_toggled().connect( sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled) ); indclippeds->signal_toggled().connect( sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled) ); - - show_all (); + + show_all (); } // inverts a toggle programmatically -void IndicateClippedPanel::toggleClipped (bool highlights) { - if (highlights) +void IndicateClippedPanel::toggleClipped (bool highlights) +{ + if (highlights) { indclippedh->set_active(!indclippedh->get_active()); - else + } else { indclippeds->set_active(!indclippeds->get_active()); + } } -void IndicateClippedPanel::buttonToggled () { - imageArea->queue_draw (); +void IndicateClippedPanel::buttonToggled () +{ + imageArea->queue_draw (); - // this will redraw the linked Before image area - // which is set when before/after view is enabled - if (imageArea->iLinkedImageArea!=NULL) - imageArea->iLinkedImageArea->queue_draw (); + // this will redraw the linked Before image area + // which is set when before/after view is enabled + if (imageArea->iLinkedImageArea != NULL) { + imageArea->iLinkedImageArea->queue_draw (); + } } diff --git a/rtgui/indclippedpanel.h b/rtgui/indclippedpanel.h index 4c9c6a986..199a9f620 100644 --- a/rtgui/indclippedpanel.h +++ b/rtgui/indclippedpanel.h @@ -6,7 +6,7 @@ * 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 @@ -21,22 +21,29 @@ #include class ImageArea; -class IndicateClippedPanel : public Gtk::HBox { +class IndicateClippedPanel : public Gtk::HBox +{ - protected: - Gtk::ToggleButton* indclippedh; - Gtk::ToggleButton* indclippeds; - ImageArea* imageArea; - - public: - IndicateClippedPanel (ImageArea* ia); +protected: + Gtk::ToggleButton* indclippedh; + Gtk::ToggleButton* indclippeds; + ImageArea* imageArea; - void buttonToggled (); - - void toggleClipped (bool highlights); // inverts a toggle programmatically +public: + IndicateClippedPanel (ImageArea* ia); - bool showClippedShadows () { return indclippeds->get_active (); } - bool showClippedHighlights () { return indclippedh->get_active (); } + void buttonToggled (); + + void toggleClipped (bool highlights); // inverts a toggle programmatically + + bool showClippedShadows () + { + return indclippeds->get_active (); + } + bool showClippedHighlights () + { + return indclippedh->get_active (); + } }; #endif diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index bc2a83de6..53f32dbbc 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -7,7 +7,7 @@ * 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 @@ -27,28 +27,29 @@ 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)) { - imgPath = imagePath; +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)) { + imgPath = imagePath; - // generate thumbnail image - Glib::ustring ext = getExtension (imagePath); - if (ext=="") { - imgPath.clear(); - return; - } + // generate thumbnail image + Glib::ustring ext = getExtension (imagePath); - rtengine::PreviewImage pi(imagePath, ext, rtengine::PreviewImage::PIM_EmbeddedOrRaw); - Cairo::RefPtr imageSurface = pi.getImage(); + if (ext == "") { + imgPath.clear(); + return; + } - if (imageSurface) { - imgBuffer.setSurface(imageSurface); - fromRaw = true; - } - else { - imgPath.clear(); - } - } + rtengine::PreviewImage pi(imagePath, ext, rtengine::PreviewImage::PIM_EmbeddedOrRaw); + Cairo::RefPtr imageSurface = pi.getImage(); + + if (imageSurface) { + imgBuffer.setSurface(imageSurface); + fromRaw = true; + } else { + imgPath.clear(); + } + } } /* @@ -56,207 +57,235 @@ InspectorBuffer::~InspectorBuffer() { } */ -int InspectorBuffer::infoFromImage (const Glib::ustring& fname) { +int InspectorBuffer::infoFromImage (const Glib::ustring& fname) +{ - rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, NULL); - if (!idata) - return 0; + rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, NULL); - int deg = 0; - if (idata->hasExif()) { - if (idata->getOrientation()=="Rotate 90 CW" ) deg = 90; - else if (idata->getOrientation()=="Rotate 180" ) deg = 180; - else if (idata->getOrientation()=="Rotate 270 CW") deg = 270; - } - delete idata; - return deg; + if (!idata) { + return 0; + } + + int deg = 0; + + if (idata->hasExif()) { + if (idata->getOrientation() == "Rotate 90 CW" ) { + deg = 90; + } else if (idata->getOrientation() == "Rotate 180" ) { + deg = 180; + } else if (idata->getOrientation() == "Rotate 270 CW") { + deg = 270; + } + } + + delete idata; + return deg; } Inspector::Inspector () : currImage(NULL), zoom(0.0), active(false) {} -Inspector::~Inspector() { - deleteBuffers(); +Inspector::~Inspector() +{ + deleteBuffers(); } -bool Inspector::on_expose_event (GdkEventExpose* event) { +bool Inspector::on_expose_event (GdkEventExpose* event) +{ - Glib::RefPtr win = get_window(); - if (!win) - return false; + Glib::RefPtr win = get_window(); - if (!active) { - active = true; - } + if (!win) { + return false; + } + + if (!active) { + active = true; + } - // cleanup the region + // cleanup the region - if (currImage && currImage->imgBuffer.surfaceCreated()) { - // this will eventually create/update the off-screen pixmap + if (currImage && currImage->imgBuffer.surfaceCreated()) { + // this will eventually create/update the off-screen pixmap - // compute the displayed area - Coord availableSize; - Coord topLeft; - Coord displayedSize; - Coord dest(0, 0); - win->get_size(availableSize.x, availableSize.y); - int imW = currImage->imgBuffer.getWidth(); - int imH = currImage->imgBuffer.getHeight(); + // compute the displayed area + Coord availableSize; + Coord topLeft; + Coord displayedSize; + Coord dest(0, 0); + win->get_size(availableSize.x, availableSize.y); + int imW = currImage->imgBuffer.getWidth(); + int imH = currImage->imgBuffer.getHeight(); - if (imW < availableSize.x) { - // center the image in the available space along X - topLeft.x = 0; - displayedSize.x = availableSize.x; - dest.x = (availableSize.x - imW) / 2; - } - else { - // partial image display - // double clamp - topLeft.x = center.x + availableSize.x/2; - topLeft.x = rtengine::min(topLeft.x, imW); - topLeft.x -= availableSize.x; - topLeft.x = rtengine::max(topLeft.x, 0); - } + if (imW < availableSize.x) { + // center the image in the available space along X + topLeft.x = 0; + displayedSize.x = availableSize.x; + dest.x = (availableSize.x - imW) / 2; + } else { + // partial image display + // double clamp + topLeft.x = center.x + availableSize.x / 2; + topLeft.x = rtengine::min(topLeft.x, imW); + topLeft.x -= availableSize.x; + topLeft.x = rtengine::max(topLeft.x, 0); + } - if (imH < availableSize.y) { - // center the image in the available space along Y - topLeft.y = 0; - displayedSize.y = availableSize.y; - dest.y = (availableSize.y - imH) / 2; - } - else { - // partial image display - // double clamp - topLeft.y = center.y + availableSize.y/2; - topLeft.y = rtengine::min(topLeft.y, imH); - topLeft.y -= availableSize.y; - topLeft.y = rtengine::max(topLeft.y, 0); - } + if (imH < availableSize.y) { + // center the image in the available space along Y + topLeft.y = 0; + displayedSize.y = availableSize.y; + dest.y = (availableSize.y - imH) / 2; + } else { + // partial image display + // double clamp + topLeft.y = center.y + availableSize.y / 2; + topLeft.y = rtengine::min(topLeft.y, imH); + topLeft.y -= availableSize.y; + topLeft.y = rtengine::max(topLeft.y, 0); + } - //printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y); + //printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y); - // define the destination area - currImage->imgBuffer.setDrawRectangle(win, dest.x, dest.y, rtengine::min(availableSize.x-dest.x, imW), rtengine::min(availableSize.y-dest.y,imH), false); - currImage->imgBuffer.setSrcOffset(topLeft.x, topLeft.y); + // define the destination area + currImage->imgBuffer.setDrawRectangle(win, dest.x, dest.y, rtengine::min(availableSize.x - dest.x, imW), rtengine::min(availableSize.y - dest.y, imH), false); + currImage->imgBuffer.setSrcOffset(topLeft.x, topLeft.y); - if (!currImage->imgBuffer.surfaceCreated()) { - return false; - } + if (!currImage->imgBuffer.surfaceCreated()) { + return false; + } - // Draw! + // Draw! - Gdk::Color c; - Cairo::RefPtr cr = win->create_cairo_context(); - Glib::RefPtr style = get_style(); + Gdk::Color c; + Cairo::RefPtr cr = win->create_cairo_context(); + Glib::RefPtr style = get_style(); - // draw the background - c = style->get_bg (Gtk::STATE_NORMAL); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->set_line_width (0); - cr->rectangle (0, 0, availableSize.x, availableSize.y); - cr->fill (); + // draw the background + c = style->get_bg (Gtk::STATE_NORMAL); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->set_line_width (0); + cr->rectangle (0, 0, availableSize.x, availableSize.y); + cr->fill (); - currImage->imgBuffer.copySurface(win); + currImage->imgBuffer.copySurface(win); - // draw the frame - c = style->get_fg (Gtk::STATE_NORMAL); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->set_line_width (1); - cr->rectangle (0.5, 0.5, availableSize.x-1, availableSize.y-1); - cr->stroke (); - } - return true; + // draw the frame + c = style->get_fg (Gtk::STATE_NORMAL); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->set_line_width (1); + cr->rectangle (0.5, 0.5, availableSize.x - 1, availableSize.y - 1); + cr->stroke (); + } + + return true; } -void Inspector::mouseMove (rtengine::Coord2D pos, int transform) { - if (!active) - return; +void Inspector::mouseMove (rtengine::Coord2D pos, int transform) +{ + if (!active) { + return; + } - if (currImage) - center.set(int(rtengine::LIM01(pos.x)*double(currImage->imgBuffer.getWidth())), int(rtengine::LIM01(pos.y)*double(currImage->imgBuffer.getHeight()))); - else - center.set(0,0); - queue_draw(); + if (currImage) { + center.set(int(rtengine::LIM01(pos.x)*double(currImage->imgBuffer.getWidth())), int(rtengine::LIM01(pos.y)*double(currImage->imgBuffer.getHeight()))); + } else { + center.set(0, 0); + } + + queue_draw(); } -void Inspector::switchImage (const Glib::ustring &fullPath) { - if (!active) - return; +void Inspector::switchImage (const Glib::ustring &fullPath) +{ + if (!active) { + return; + } - // we first check the size of the list, it may have been changed in Preference - if (images.size() > size_t(options.maxInspectorBuffers)) { - // deleting the last entries - for (size_t i=images.size()-1; i>size_t(options.maxInspectorBuffers-1); --i) { - delete images.at(i); - images.at(i) = NULL; - } - // resizing down - images.resize(options.maxInspectorBuffers); - } + // we first check the size of the list, it may have been changed in Preference + if (images.size() > size_t(options.maxInspectorBuffers)) { + // deleting the last entries + for (size_t i = images.size() - 1; i > size_t(options.maxInspectorBuffers - 1); --i) { + delete images.at(i); + images.at(i) = NULL; + } - if (fullPath.empty()) { - currImage = NULL; - queue_draw(); - return; - } - else { - bool found = false; - for (size_t i=0; iimgPath==fullPath) { - currImage = images.at(i); + // resizing down + images.resize(options.maxInspectorBuffers); + } - // rolling the list 1 step to the beginning - for (size_t j=i; jimgPath.empty()) { - images.push_back(iBuffer); - currImage = images.at(images.size()-1); - } - else { - currImage = NULL; - } - } - } + if (fullPath.empty()) { + currImage = NULL; + queue_draw(); + return; + } else { + bool found = false; + + for (size_t i = 0; i < images.size(); ++i) { + if (images.at(i) != NULL && images.at(i)->imgPath == fullPath) { + currImage = images.at(i); + + // rolling the list 1 step to the beginning + for (size_t j = i; j < images.size() - 1; ++j) { + images.at(j) = images.at(j + 1); + } + + images.at(images.size() - 1) = currImage; // move the last used image to the tail + found = true; + break; + } + } + + if (!found) { + if (images.size() == size_t(options.maxInspectorBuffers)) { + // The list is full, delete the first entry + delete images.at(0); + images.erase(images.begin()); + } + + // Loading a new image + InspectorBuffer *iBuffer = new InspectorBuffer(fullPath); + + // and add it to the tail + if (!iBuffer->imgPath.empty()) { + images.push_back(iBuffer); + currImage = images.at(images.size() - 1); + } else { + currImage = NULL; + } + } + } } -void Inspector::deleteBuffers () { - for (size_t i=0; i images; - InspectorBuffer* currImage; - double zoom; - bool active; +private: + Coord center; + std::vector images; + InspectorBuffer* currImage; + double zoom; + bool active; - bool on_expose_event (GdkEventExpose* event); - void deleteBuffers(); + bool on_expose_event (GdkEventExpose* event); + void deleteBuffers(); - public: - Inspector(); - ~Inspector(); +public: + Inspector(); + ~Inspector(); - /** @brief Mouse movement to a new position - * @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image - * @param transform H/V flip and coarse rotation transformation - */ - void mouseMove (rtengine::Coord2D pos, int transform); + /** @brief Mouse movement to a new position + * @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image + * @param transform H/V flip and coarse rotation transformation + */ + void mouseMove (rtengine::Coord2D pos, int transform); - /** @brief A new image is being flown over - * @param fullPath Full path of the image that is being hovered inspect, or an empty string if out of any image. - */ - void switchImage (const Glib::ustring &fullPath); + /** @brief A new image is being flown over + * @param fullPath Full path of the image that is being hovered inspect, or an empty string if out of any image. + */ + void switchImage (const Glib::ustring &fullPath); - /** @brief Set the new coarse rotation transformation - * @param transform A semi-bitfield coarse transformation using #defines from iimage.h - */ - void setTransformation (int transform); + /** @brief Set the new coarse rotation transformation + * @param transform A semi-bitfield coarse transformation using #defines from iimage.h + */ + void setTransformation (int transform); - /** @brief Use this method to flush all image buffer whenever the Inspector panel is hidden - */ - void flushBuffers (); + /** @brief Use this method to flush all image buffer whenever the Inspector panel is hidden + */ + void flushBuffers (); - /** @brief Set the inspector on/off - * @param state true if to activate the Inspector, false to disable it and flush the buffers - */ - void setActive(bool state); + /** @brief Set the inspector on/off + * @param state true if to activate the Inspector, false to disable it and flush the buffers + */ + void setActive(bool state); - /** @brief Get the on/off state - */ - bool isActive() { return active; }; + /** @brief Get the on/off state + */ + bool isActive() + { + return active; + }; }; #endif diff --git a/rtgui/iptcpanel.cc b/rtgui/iptcpanel.cc index d87b69000..301f7fc27 100644 --- a/rtgui/iptcpanel.cc +++ b/rtgui/iptcpanel.cc @@ -7,7 +7,7 @@ * 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 @@ -25,15 +25,16 @@ extern Glib::ustring argv0; using namespace rtengine; using namespace rtengine::procparams; -IPTCPanel::IPTCPanel () { +IPTCPanel::IPTCPanel () +{ set_border_width (2); Gtk::Table* iptc = Gtk::manage( new Gtk::Table (27, 2) ); - + int row = 0; - Gtk::Label* capl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CAPTION")+":") ); + Gtk::Label* capl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CAPTION") + ":") ); captionText = Gtk::TextBuffer::create (); captionView = Gtk::manage( new Gtk::TextView (captionText) ); Gtk::ScrolledWindow* scrolledWindowc = Gtk::manage( new Gtk::ScrolledWindow() ); @@ -42,44 +43,44 @@ IPTCPanel::IPTCPanel () { capl->set_tooltip_text (M("IPTCPANEL_CAPTIONHINT")); captionView->set_tooltip_text (M("IPTCPANEL_CAPTIONHINT")); captionView->set_size_request(32, 80); - iptc->attach (*capl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*scrolledWindowc, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*capl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*scrolledWindowc, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* capwl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CAPTIONWRITER")+":") ); + Gtk::Label* capwl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CAPTIONWRITER") + ":") ); captionWriter = Gtk::manage( new Gtk::Entry () ); capwl->set_tooltip_text (M("IPTCPANEL_CAPTIONWRITERHINT")); captionWriter->set_tooltip_text (M("IPTCPANEL_CAPTIONWRITERHINT")); - iptc->attach (*capwl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*captionWriter, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); - + iptc->attach (*capwl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*captionWriter, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + row++; - Gtk::Label* headl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_HEADLINE")+":") ); + Gtk::Label* headl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_HEADLINE") + ":") ); headline = Gtk::manage( new Gtk::Entry () ); headl->set_tooltip_text (M("IPTCPANEL_HEADLINEHINT")); headline->set_tooltip_text (M("IPTCPANEL_HEADLINEHINT")); - iptc->attach (*headl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*headline, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*headl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*headline, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* instl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_INSTRUCTIONS")+":") ); + Gtk::Label* instl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_INSTRUCTIONS") + ":") ); instructions = Gtk::manage( new Gtk::Entry () ); instl->set_tooltip_text (M("IPTCPANEL_INSTRUCTIONSHINT")); instructions->set_tooltip_text (M("IPTCPANEL_INSTRUCTIONSHINT")); - iptc->attach (*instl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*instructions, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); - + iptc->attach (*instl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*instructions, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + row++; Gtk::HSeparator* hsep1 = Gtk::manage( new Gtk::HSeparator () ); - iptc->attach (*hsep1, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); - + iptc->attach (*hsep1, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + row++; - Gtk::Label* keyl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_KEYWORDS")+":")); + Gtk::Label* keyl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_KEYWORDS") + ":")); keywords = Gtk::manage( new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE) ); keywords->set_headers_visible (false); keywords->set_size_request (50, 80); @@ -101,22 +102,22 @@ IPTCPanel::IPTCPanel () { kwhb->pack_start (*keyword); kwhb->pack_start (*addKW, Gtk::PACK_SHRINK, 2); kwhb->pack_start (*delKW, Gtk::PACK_SHRINK, 2); - iptc->attach (*keyl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*kwhb, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*keyl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*kwhb, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - iptc->attach (*scrolledWindowkw, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*scrolledWindowkw, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; Gtk::HSeparator* hsep2 = Gtk::manage( new Gtk::HSeparator () ); - iptc->attach (*hsep2, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*hsep2, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* catl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CATEGORY")+":") ); + Gtk::Label* catl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CATEGORY") + ":") ); category = Gtk::manage( new Gtk::ComboBoxEntryText () ); category->set_size_request (32, -1); catl->set_tooltip_text (M("IPTCPANEL_CATEGORYHINT")); category->set_tooltip_text (M("IPTCPANEL_CATEGORYHINT")); - Gtk::Label* scl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_SUPPCATEGORIES")+":") ); + Gtk::Label* scl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_SUPPCATEGORIES") + ":") ); suppCategories = Gtk::manage( new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE) ); suppCategories->set_headers_visible (false); suppCategories->set_size_request(50, 80); @@ -138,120 +139,120 @@ IPTCPanel::IPTCPanel () { schb->pack_start (*suppCategory); schb->pack_start (*addSC, Gtk::PACK_SHRINK, 2); schb->pack_start (*delSC, Gtk::PACK_SHRINK, 2); - iptc->attach (*catl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*category, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*catl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*category, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - iptc->attach (*scl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*schb, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*scl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*schb, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - iptc->attach (*scrolledWindowsc, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*scrolledWindowsc, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - + Gtk::HSeparator* hsep3 = Gtk::manage( new Gtk::HSeparator () ); - iptc->attach (*hsep3, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*hsep3, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - - Gtk::Label* authl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_AUTHOR")+":") ); + + Gtk::Label* authl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_AUTHOR") + ":") ); author = Gtk::manage( new Gtk::Entry () ); authl->set_tooltip_text (M("IPTCPANEL_CREDITHINT")); author->set_tooltip_text (M("IPTCPANEL_CREDITHINT")); - iptc->attach (*authl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*author, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*authl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*author, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* aupl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_AUTHORSPOSITION")+":") ); + Gtk::Label* aupl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_AUTHORSPOSITION") + ":") ); authorPos = Gtk::manage( new Gtk::Entry () ); aupl->set_tooltip_text (M("IPTCPANEL_AUTHORSPOSITIONHINT")); authorPos->set_tooltip_text (M("IPTCPANEL_AUTHORSPOSITIONHINT")); - iptc->attach (*aupl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*authorPos, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*aupl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*authorPos, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* credl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CREDIT")+":") ); + Gtk::Label* credl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CREDIT") + ":") ); credit = Gtk::manage( new Gtk::Entry () ); credl->set_tooltip_text (M("IPTCPANEL_CREDITHINT")); credit->set_tooltip_text (M("IPTCPANEL_CREDITHINT")); - iptc->attach (*credl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*credit, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*credl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*credit, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - - Gtk::Label* sourl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_SOURCE")+":") ); + + Gtk::Label* sourl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_SOURCE") + ":") ); source = Gtk::manage( new Gtk::Entry () ); sourl->set_tooltip_text (M("IPTCPANEL_SOURCEHINT")); source->set_tooltip_text (M("IPTCPANEL_SOURCEHINT")); - iptc->attach (*sourl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*source, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*sourl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*source, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* cprl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_COPYRIGHT")+":") ); + Gtk::Label* cprl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_COPYRIGHT") + ":") ); copyright = Gtk::manage( new Gtk::Entry () ); cprl->set_tooltip_text (M("IPTCPANEL_COPYRIGHTHINT")); copyright->set_tooltip_text (M("IPTCPANEL_COPYRIGHTHINT")); - iptc->attach (*cprl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*copyright, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*cprl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*copyright, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; Gtk::HSeparator* hsep4 = Gtk::manage( new Gtk::HSeparator () ); - iptc->attach (*hsep4, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); - + iptc->attach (*hsep4, 0, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + row++; - Gtk::Label* cityl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CITY")+":") ); + Gtk::Label* cityl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CITY") + ":") ); city = Gtk::manage( new Gtk::Entry () ); cityl->set_tooltip_text (M("IPTCPANEL_CITYHINT")); city->set_tooltip_text (M("IPTCPANEL_CITYHINT")); - iptc->attach (*cityl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*city, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*cityl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*city, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - - Gtk::Label* provl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_PROVINCE")+":") ); + + Gtk::Label* provl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_PROVINCE") + ":") ); province = Gtk::manage( new Gtk::Entry () ); provl->set_tooltip_text (M("IPTCPANEL_PROVINCEHINT")); province->set_tooltip_text (M("IPTCPANEL_PROVINCEHINT")); - iptc->attach (*provl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*province, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*provl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*province, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - - Gtk::Label* ctrl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_COUNTRY")+":") ); + + Gtk::Label* ctrl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_COUNTRY") + ":") ); country = Gtk::manage( new Gtk::Entry () ); ctrl->set_tooltip_text (M("IPTCPANEL_COUNTRYHINT")); country->set_tooltip_text (M("IPTCPANEL_COUNTRYHINT")); - iptc->attach (*ctrl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*country, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*ctrl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*country, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - - Gtk::Label* titll = Gtk::manage( new Gtk::Label (M("IPTCPANEL_TITLE")+":") ); + + Gtk::Label* titll = Gtk::manage( new Gtk::Label (M("IPTCPANEL_TITLE") + ":") ); title = Gtk::manage( new Gtk::Entry () ); titll->set_tooltip_text (M("IPTCPANEL_TITLEHINT")); title->set_tooltip_text (M("IPTCPANEL_TITLEHINT")); - iptc->attach (*titll, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*title, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*titll, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*title, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* dcl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_DATECREATED")+":") ); + Gtk::Label* dcl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_DATECREATED") + ":") ); dateCreated = Gtk::manage( new Gtk::Entry () ); dcl->set_tooltip_text (M("IPTCPANEL_DATECREATEDHINT")); dateCreated->set_tooltip_text (M("IPTCPANEL_DATECREATEDHINT")); - iptc->attach (*dcl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*dateCreated, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*dcl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*dateCreated, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; - Gtk::Label* trl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_TRANSREFERENCE")+":") ); + Gtk::Label* trl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_TRANSREFERENCE") + ":") ); transReference = Gtk::manage( new Gtk::Entry () ); trl->set_tooltip_text (M("IPTCPANEL_TRANSREFERENCEHINT")); transReference->set_tooltip_text (M("IPTCPANEL_TRANSREFERENCEHINT")); - iptc->attach (*trl, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); - iptc->attach (*transReference, 1, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); + iptc->attach (*trl, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); + iptc->attach (*transReference, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); row++; @@ -261,11 +262,11 @@ IPTCPanel::IPTCPanel () { scrolledWindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); scrolledWindow->add(*iptc); - + pack_start (*scrolledWindow); - + Gtk::HBox* bbox = Gtk::manage( new Gtk::HBox () ); - + reset = Gtk::manage( new Gtk::Button (M("IPTCPANEL_RESET")) ); reset->set_image (*Gtk::manage(new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); bbox->pack_start (*reset); @@ -273,7 +274,7 @@ IPTCPanel::IPTCPanel () { file = Gtk::manage( new Gtk::Button (M("IPTCPANEL_EMBEDDED")) ); file->set_image (*Gtk::manage(new RTImage ("gtk-open.png"))); bbox->pack_start (*file); - + copy = Gtk::manage( new Gtk::Button () ); copy->set_image (*Gtk::manage(new RTImage ("edit-copy.png"))); bbox->pack_start (*copy, Gtk::PACK_SHRINK, 0); @@ -281,7 +282,7 @@ IPTCPanel::IPTCPanel () { paste = Gtk::manage( new Gtk::Button () ); paste->set_image (*Gtk::manage(new RTImage ("edit-paste.png"))); bbox->pack_start (*paste, Gtk::PACK_SHRINK, 0); - + pack_end (*bbox, Gtk::PACK_SHRINK, 2); Gtk::Tooltips* toolTip = Gtk::manage( new Gtk::Tooltips () ); @@ -289,174 +290,213 @@ IPTCPanel::IPTCPanel () { toolTip->set_tip (*file, M("IPTCPANEL_EMBEDDEDHINT")); toolTip->set_tip (*copy, M("IPTCPANEL_COPYHINT")); toolTip->set_tip (*paste, M("IPTCPANEL_PASTEHINT")); - + reset->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::resetClicked) ); file->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::fileClicked) ); copy->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::copyClicked) ); paste->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::pasteClicked) ); - addKW->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::addKeyWord) ); - delKW->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::delKeyWord) ); - addSC->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::addSuppCategory) ); - delSC->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::delSuppCategory) ); - keyword->get_entry()->signal_activate().connect( sigc::mem_fun(*this, &IPTCPanel::addKeyWord) ); - suppCategory->get_entry()->signal_activate().connect( sigc::mem_fun(*this, &IPTCPanel::addSuppCategory) ); + addKW->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::addKeyWord) ); + delKW->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::delKeyWord) ); + addSC->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::addSuppCategory) ); + delSC->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::delSuppCategory) ); + keyword->get_entry()->signal_activate().connect( sigc::mem_fun(*this, &IPTCPanel::addKeyWord) ); + suppCategory->get_entry()->signal_activate().connect( sigc::mem_fun(*this, &IPTCPanel::addSuppCategory) ); + + conns[0] = captionText->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[1] = captionWriter->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[2] = headline->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[3] = instructions->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[4] = category->get_entry()->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[5] = author->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[6] = authorPos->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[7] = credit->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[8] = source->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[9] = copyright->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[10] = city->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[11] = province->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[12] = country->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[13] = title->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[14] = dateCreated->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + conns[15] = transReference->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); + + category->get_entry()->set_max_length (3); + keyword->get_entry()->set_max_length (64); + captionWriter->set_max_length (32); + instructions->set_max_length (256); + author->set_max_length (32); + authorPos->set_max_length (32); + credit->set_max_length (32); + source->set_max_length (32); + copyright->set_max_length (128); + city->set_max_length (32); + province->set_max_length (32); + country->set_max_length (64); + title->set_max_length (64); + dateCreated->set_max_length (8); + transReference->set_max_length (32); - conns[0] = captionText->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[1] = captionWriter->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[2] = headline->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[3] = instructions->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[4] = category->get_entry()->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[5] = author->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[6] = authorPos->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[7] = credit->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[8] = source->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[9] = copyright->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[10] = city->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[11] = province->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[12] = country->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[13] = title->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[14] = dateCreated->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - conns[15] = transReference->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) ); - - category->get_entry()->set_max_length (3); - keyword->get_entry()->set_max_length (64); - captionWriter->set_max_length (32); - instructions->set_max_length (256); - author->set_max_length (32); - authorPos->set_max_length (32); - credit->set_max_length (32); - source->set_max_length (32); - copyright->set_max_length (128); - city->set_max_length (32); - province->set_max_length (32); - country->set_max_length (64); - title->set_max_length (64); - dateCreated->set_max_length (8); - transReference->set_max_length (32); - show_all (); } -void IPTCPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { +void IPTCPanel::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); changeList.clear(); - if (!pp->iptc.empty()) + + if (!pp->iptc.empty()) { changeList = pp->iptc; - else + } else { changeList = embeddedData; + } + applyChangeList (); enableListener (); } -void IPTCPanel::write (ProcParams* pp, ParamsEdited* pedited) { - +void IPTCPanel::write (ProcParams* pp, ParamsEdited* pedited) +{ + pp->iptc = changeList; } -void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ defChangeList = defParams->iptc; } - -void IPTCPanel::setImageData (const ImageMetaData* id) { - - if (id) + +void IPTCPanel::setImageData (const ImageMetaData* id) +{ + + if (id) { embeddedData = id->getIPTCData (); - else + } else { embeddedData.clear (); + } file->set_sensitive (!embeddedData.empty()); } -void IPTCPanel::notifyListener () { - - if (listener) +void IPTCPanel::notifyListener () +{ + + if (listener) { listener->panelChanged (EvIPTC, M("HISTORY_CHANGED")); + } } -void IPTCPanel::addKeyWord () { +void IPTCPanel::addKeyWord () +{ keyword->get_entry()->select_region (0, keyword->get_entry()->get_text().size()); - for (unsigned int i=0; isize(); i++) - if (keywords->get_text (i) == keyword->get_entry()->get_text()) + for (unsigned int i = 0; i < keywords->size(); i++) + if (keywords->get_text (i) == keyword->get_entry()->get_text()) { return; - + } + keywords->append_text (keyword->get_entry()->get_text()); keyword->prepend_text (keyword->get_entry()->get_text()); std::vector items; - for (Gtk::TreeModel::iterator i = keyword->get_model()->children().begin(); i!=keyword->get_model()->children().end(); i++) { + + for (Gtk::TreeModel::iterator i = keyword->get_model()->children().begin(); i != keyword->get_model()->children().end(); i++) { Glib::ustring s; i->get_value (0, s); items.push_back (s); } + keyword->clear_items (); - for (unsigned int i=0; i<10 && iappend_text (items[i]); + } + keywords->scroll_to_row (keywords->get_model()->get_path(--keywords->get_model()->children().end())); - + updateChangeList (); } -void IPTCPanel::delKeyWord () { +void IPTCPanel::delKeyWord () +{ std::vector selection = keywords->get_selected (); + if (!selection.empty()) { std::vector keep; - for (unsigned int i=0; isize(); i++) - if (std::find (selection.begin(), selection.end(), i) == selection.end()) + + for (unsigned int i = 0; i < keywords->size(); i++) + if (std::find (selection.begin(), selection.end(), i) == selection.end()) { keep.push_back (keywords->get_text (i)); + } + keywords->clear_items (); - for (unsigned int i=0; iappend_text (keep[i]); + } } updateChangeList (); } -void IPTCPanel::addSuppCategory () { +void IPTCPanel::addSuppCategory () +{ - for (unsigned int i=0; isize(); i++) - if (suppCategories->get_text (i) == suppCategory->get_entry()->get_text()) + for (unsigned int i = 0; i < suppCategories->size(); i++) + if (suppCategories->get_text (i) == suppCategory->get_entry()->get_text()) { return; + } suppCategories->append_text (suppCategory->get_entry()->get_text()); suppCategory->prepend_text (suppCategory->get_entry()->get_text()); std::vector items; - for (Gtk::TreeModel::iterator i = suppCategory->get_model()->children().begin(); i!=suppCategory->get_model()->children().end(); i++) { + + for (Gtk::TreeModel::iterator i = suppCategory->get_model()->children().begin(); i != suppCategory->get_model()->children().end(); i++) { Glib::ustring s; i->get_value (0, s); items.push_back (s); } + suppCategory->clear_items (); - for (unsigned int i=0; i<10 && iappend_text (items[i]); + } + suppCategories->scroll_to_row (suppCategories->get_model()->get_path(--suppCategories->get_model()->children().end())); suppCategory->get_entry()->select_region (0, suppCategory->get_entry()->get_text().size()); - updateChangeList (); + updateChangeList (); } -void IPTCPanel::delSuppCategory () { +void IPTCPanel::delSuppCategory () +{ std::vector selection = suppCategories->get_selected (); + if (!selection.empty()) { std::vector keep; - for (unsigned int i=0; isize(); i++) - if (std::find (selection.begin(), selection.end(), i) == selection.end()) + + for (unsigned int i = 0; i < suppCategories->size(); i++) + if (std::find (selection.begin(), selection.end(), i) == selection.end()) { keep.push_back (suppCategories->get_text (i)); + } + suppCategories->clear_items (); - for (unsigned int i=0; iappend_text (keep[i]); + } } updateChangeList (); } -void IPTCPanel::updateChangeList () { +void IPTCPanel::updateChangeList () +{ changeList.clear (); changeList["Caption" ].push_back (captionText->get_text ()); @@ -464,13 +504,15 @@ void IPTCPanel::updateChangeList () { changeList["Headline" ].push_back (headline->get_text ()); changeList["Instructions" ].push_back (instructions->get_text ()); - for (unsigned int i=0; isize(); i++) - changeList["Keywords" ].push_back (keywords->get_text (i)); + for (unsigned int i = 0; i < keywords->size(); i++) { + changeList["Keywords" ].push_back (keywords->get_text (i)); + } changeList["Category" ].push_back (category->get_entry()->get_text ()); - for (unsigned int i=0; isize(); i++) - changeList["SupplementalCategories"].push_back (suppCategories->get_text (i)); + for (unsigned int i = 0; i < suppCategories->size(); i++) { + changeList["SupplementalCategories"].push_back (suppCategories->get_text (i)); + } changeList["Author" ].push_back (author->get_text ()); changeList["AuthorsPosition"].push_back (authorPos->get_text ()); @@ -487,10 +529,12 @@ void IPTCPanel::updateChangeList () { notifyListener (); } -void IPTCPanel::applyChangeList () { +void IPTCPanel::applyChangeList () +{ - for (int i=0; i<16; i++) + for (int i = 0; i < 16; i++) { conns[i].block (true); + } captionText->set_text (""); captionWriter->set_text (""); @@ -512,53 +556,58 @@ void IPTCPanel::applyChangeList () { transReference->set_text (""); keyword->get_entry()->set_text (""); suppCategory->get_entry()->set_text (""); - - for (rtengine::procparams::IPTCPairs::iterator i=changeList.begin(); i!=changeList.end(); i++) { - if (i->first == "Caption" && !i->second.empty()) + + for (rtengine::procparams::IPTCPairs::iterator i = changeList.begin(); i != changeList.end(); i++) { + if (i->first == "Caption" && !i->second.empty()) { captionText->set_text (i->second.at(0)); - else if (i->first == "CaptionWriter" && !i->second.empty()) + } else if (i->first == "CaptionWriter" && !i->second.empty()) { captionWriter->set_text (i->second.at(0)); - else if (i->first == "Headline" && !i->second.empty()) + } else if (i->first == "Headline" && !i->second.empty()) { headline->set_text (i->second.at(0)); - else if (i->first == "Instructions" && !i->second.empty()) + } else if (i->first == "Instructions" && !i->second.empty()) { instructions->set_text (i->second.at(0)); - else if (i->first == "Keywords") - for (unsigned int j=0; jsecond.size(); j++) + } else if (i->first == "Keywords") + for (unsigned int j = 0; j < i->second.size(); j++) { keywords->append_text (i->second.at(j)); - else if (i->first == "Category" && !i->second.empty()) + } + else if (i->first == "Category" && !i->second.empty()) { category->get_entry()->set_text (i->second.at(0)); - else if (i->first == "SupplementalCategories") - for (unsigned int j=0; jsecond.size(); j++) + } else if (i->first == "SupplementalCategories") + for (unsigned int j = 0; j < i->second.size(); j++) { suppCategories->append_text (i->second.at(j)); - else if (i->first == "Author" && !i->second.empty()) + } + else if (i->first == "Author" && !i->second.empty()) { author->set_text (i->second.at(0)); - else if (i->first == "AuthorsPosition" && !i->second.empty()) + } else if (i->first == "AuthorsPosition" && !i->second.empty()) { authorPos->set_text (i->second.at(0)); - else if (i->first == "Credit" && !i->second.empty()) + } else if (i->first == "Credit" && !i->second.empty()) { credit->set_text (i->second.at(0)); - else if (i->first == "Source" && !i->second.empty()) + } else if (i->first == "Source" && !i->second.empty()) { source->set_text (i->second.at(0)); - else if (i->first == "Copyright" && !i->second.empty()) + } else if (i->first == "Copyright" && !i->second.empty()) { copyright->set_text (i->second.at(0)); - else if (i->first == "City" && !i->second.empty()) + } else if (i->first == "City" && !i->second.empty()) { city->set_text (i->second.at(0)); - else if (i->first == "Province" && !i->second.empty()) + } else if (i->first == "Province" && !i->second.empty()) { province->set_text (i->second.at(0)); - else if (i->first == "Country" && !i->second.empty()) + } else if (i->first == "Country" && !i->second.empty()) { country->set_text (i->second.at(0)); - else if (i->first == "Title" && !i->second.empty()) + } else if (i->first == "Title" && !i->second.empty()) { title->set_text (i->second.at(0)); - else if (i->first == "DateCreated" && !i->second.empty()) + } else if (i->first == "DateCreated" && !i->second.empty()) { dateCreated->set_text (i->second.at(0)); - else if (i->first == "TransReference" && !i->second.empty()) + } else if (i->first == "TransReference" && !i->second.empty()) { transReference->set_text (i->second.at(0)); -} + } + } - for (int i=0; i<16; i++) + for (int i = 0; i < 16; i++) { conns[i].block (false); + } } -void IPTCPanel::resetClicked () { +void IPTCPanel::resetClicked () +{ disableListener (); changeList = defChangeList; @@ -567,7 +616,8 @@ void IPTCPanel::resetClicked () { notifyListener (); } -void IPTCPanel::fileClicked () { +void IPTCPanel::fileClicked () +{ disableListener (); changeList = embeddedData; @@ -576,12 +626,14 @@ void IPTCPanel::fileClicked () { notifyListener (); } -void IPTCPanel::copyClicked () { +void IPTCPanel::copyClicked () +{ clipboard.setIPTC (changeList); } -void IPTCPanel::pasteClicked () { +void IPTCPanel::pasteClicked () +{ disableListener (); changeList = clipboard.getIPTC (); diff --git a/rtgui/iptcpanel.h b/rtgui/iptcpanel.h index 128bf3018..ce870d08d 100644 --- a/rtgui/iptcpanel.h +++ b/rtgui/iptcpanel.h @@ -7,7 +7,7 @@ * 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 @@ -23,70 +23,71 @@ #include "toolpanel.h" #include "guiutils.h" -class IPTCPanel : public Gtk::VBox, public ToolPanel { +class IPTCPanel : public Gtk::VBox, public ToolPanel +{ - private: - rtengine::procparams::IPTCPairs changeList; - rtengine::procparams::IPTCPairs defChangeList; - rtengine::procparams::IPTCPairs embeddedData; - - Gtk::TextView* captionView; - Glib::RefPtr captionText; - Gtk::Entry* captionWriter; - Gtk::Entry* headline; - Gtk::Entry* instructions; - Gtk::ComboBoxEntryText* keyword; - Gtk::ListViewText* keywords; - Gtk::Button* addKW; - Gtk::Button* delKW; - Gtk::ComboBoxEntryText* category; - Gtk::ComboBoxEntryText* suppCategory; - Gtk::ListViewText* suppCategories; - Gtk::Button* addSC; - Gtk::Button* delSC; +private: + rtengine::procparams::IPTCPairs changeList; + rtengine::procparams::IPTCPairs defChangeList; + rtengine::procparams::IPTCPairs embeddedData; - Gtk::Entry* author; - Gtk::Entry* authorPos; - Gtk::Entry* credit; - Gtk::Entry* source; - Gtk::Entry* copyright; - Gtk::Entry* city; - Gtk::Entry* province; - Gtk::Entry* country; - Gtk::Entry* title; - Gtk::Entry* dateCreated; - Gtk::Entry* transReference; + Gtk::TextView* captionView; + Glib::RefPtr captionText; + Gtk::Entry* captionWriter; + Gtk::Entry* headline; + Gtk::Entry* instructions; + Gtk::ComboBoxEntryText* keyword; + Gtk::ListViewText* keywords; + Gtk::Button* addKW; + Gtk::Button* delKW; + Gtk::ComboBoxEntryText* category; + Gtk::ComboBoxEntryText* suppCategory; + Gtk::ListViewText* suppCategories; + Gtk::Button* addSC; + Gtk::Button* delSC; - Gtk::Button* reset; - Gtk::Button* file; - Gtk::Button* copy; - Gtk::Button* paste; + Gtk::Entry* author; + Gtk::Entry* authorPos; + Gtk::Entry* credit; + Gtk::Entry* source; + Gtk::Entry* copyright; + Gtk::Entry* city; + Gtk::Entry* province; + Gtk::Entry* country; + Gtk::Entry* title; + Gtk::Entry* dateCreated; + Gtk::Entry* transReference; - sigc::connection conns[16]; - - void applyChangeList (); - void updateChangeList (); - - public: - IPTCPanel (); - - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - - void setImageData (const rtengine::ImageMetaData* id); + Gtk::Button* reset; + Gtk::Button* file; + Gtk::Button* copy; + Gtk::Button* paste; - void notifyListener (); + sigc::connection conns[16]; - void addKeyWord (); - void delKeyWord (); - void addSuppCategory (); - void delSuppCategory (); - - void resetClicked (); - void fileClicked (); - void copyClicked (); - void pasteClicked (); + void applyChangeList (); + void updateChangeList (); + +public: + IPTCPanel (); + + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + + void setImageData (const rtengine::ImageMetaData* id); + + void notifyListener (); + + void addKeyWord (); + void delKeyWord (); + void addSuppCategory (); + void delSuppCategory (); + + void resetClicked (); + void fileClicked (); + void copyClicked (); + void pasteClicked (); }; #endif diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index cd47ca91a..f5b11f0e9 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -7,7 +7,7 @@ * 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 @@ -24,207 +24,212 @@ using namespace rtengine; using namespace rtengine::procparams; -LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL")) { +LCurve::LCurve () : FoldableToolPanel(this, "labcurves", M("TP_LABCURVE_LABEL")) +{ - std::vector milestones; + std::vector milestones; - brightness = Gtk::manage (new Adjuster (M("TP_LABCURVE_BRIGHTNESS"), -100., 100., 1., 0.)); - contrast = Gtk::manage (new Adjuster (M("TP_LABCURVE_CONTRAST"), -100., 100., 1., 0.)); - chromaticity = Gtk::manage (new Adjuster (M("TP_LABCURVE_CHROMATICITY"), -100., 100., 1., 0.)); - chromaticity->set_tooltip_markup(M("TP_LABCURVE_CHROMA_TOOLTIP")); + brightness = Gtk::manage (new Adjuster (M("TP_LABCURVE_BRIGHTNESS"), -100., 100., 1., 0.)); + contrast = Gtk::manage (new Adjuster (M("TP_LABCURVE_CONTRAST"), -100., 100., 1., 0.)); + chromaticity = Gtk::manage (new Adjuster (M("TP_LABCURVE_CHROMATICITY"), -100., 100., 1., 0.)); + chromaticity->set_tooltip_markup(M("TP_LABCURVE_CHROMA_TOOLTIP")); - pack_start (*brightness); - brightness->show (); + pack_start (*brightness); + brightness->show (); - pack_start (*contrast); - contrast->show (); + pack_start (*contrast); + contrast->show (); - pack_start (*chromaticity); - chromaticity->show (); - - brightness->setAdjusterListener (this); - contrast->setAdjusterListener (this); - chromaticity->setAdjusterListener (this); - - //%%%%%%%%%%%%%%%%%% - Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); - hsep2->show (); - pack_start (*hsep2, Gtk::PACK_EXPAND_WIDGET, 4); - - avoidcolorshift = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_AVOIDCOLORSHIFT"))); - avoidcolorshift->set_tooltip_text (M("TP_LABCURVE_AVOIDCOLORSHIFT_TOOLTIP")); - pack_start (*avoidcolorshift, Gtk::PACK_SHRINK, 4); - - lcredsk = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_LCREDSK"))); - lcredsk->set_tooltip_markup (M("TP_LABCURVE_LCREDSK_TIP")); - pack_start (*lcredsk); + pack_start (*chromaticity); + chromaticity->show (); - rstprotection = Gtk::manage ( new Adjuster (M("TP_LABCURVE_RSTPROTECTION"), 0., 100., 0.1, 0.) ); - pack_start (*rstprotection); - rstprotection->show (); - - rstprotection->setAdjusterListener (this); - rstprotection->set_tooltip_text (M("TP_LABCURVE_RSTPRO_TOOLTIP")); - - acconn = avoidcolorshift->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::avoidcolorshift_toggled) ); - lcconn = lcredsk->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::lcredsk_toggled) ); - - //%%%%%%%%%%%%%%%%%%% + brightness->setAdjusterListener (this); + contrast->setAdjusterListener (this); + chromaticity->setAdjusterListener (this); - Gtk::HSeparator *hsep3 = Gtk::manage (new Gtk::HSeparator()); - hsep3->show (); - pack_start (*hsep3, Gtk::PACK_EXPAND_WIDGET, 4); + //%%%%%%%%%%%%%%%%%% + Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); + hsep2->show (); + pack_start (*hsep2, Gtk::PACK_EXPAND_WIDGET, 4); - curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); - curveEditorG->setCurveListener (this); + avoidcolorshift = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_AVOIDCOLORSHIFT"))); + avoidcolorshift->set_tooltip_text (M("TP_LABCURVE_AVOIDCOLORSHIFT_TOOLTIP")); + pack_start (*avoidcolorshift, Gtk::PACK_SHRINK, 4); - lshape = static_cast(curveEditorG->addCurve(CT_Diagonal, "L*")); - lshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LL_TOOLTIP")); - lshape->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT); + lcredsk = Gtk::manage (new Gtk::CheckButton (M("TP_LABCURVE_LCREDSK"))); + lcredsk->set_tooltip_markup (M("TP_LABCURVE_LCREDSK_TIP")); + pack_start (*lcredsk); - ashape = static_cast(curveEditorG->addCurve(CT_Diagonal, "a*")); - ashape->setEditID(EUID_Lab_aCurve, BT_SINGLEPLANE_FLOAT); - - ashape->setRangeLabels( - M("TP_LABCURVE_CURVEEDITOR_A_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_A_RANGE2"), - M("TP_LABCURVE_CURVEEDITOR_A_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_A_RANGE4") - ); - //from green to magenta - milestones.clear(); - milestones.push_back( GradientMilestone(0., 0., 1., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 0., 1.) ); - ashape->setBottomBarBgGradient(milestones); - ashape->setLeftBarBgGradient(milestones); - milestones.clear(); + rstprotection = Gtk::manage ( new Adjuster (M("TP_LABCURVE_RSTPROTECTION"), 0., 100., 0.1, 0.) ); + pack_start (*rstprotection); + rstprotection->show (); - bshape = static_cast(curveEditorG->addCurve(CT_Diagonal, "b*")); - bshape->setRangeLabels( - M("TP_LABCURVE_CURVEEDITOR_B_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_B_RANGE2"), - M("TP_LABCURVE_CURVEEDITOR_B_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_B_RANGE4") - ); - bshape->setEditID(EUID_Lab_bCurve, BT_SINGLEPLANE_FLOAT); - - //from blue to yellow - milestones.clear(); - milestones.push_back( GradientMilestone(0., 0., 0., 1.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 0.) ); - bshape->setBottomBarBgGradient(milestones); - bshape->setLeftBarBgGradient(milestones); - milestones.clear(); + rstprotection->setAdjusterListener (this); + rstprotection->set_tooltip_text (M("TP_LABCURVE_RSTPRO_TOOLTIP")); - curveEditorG->newLine(); // ------------------------------------------------ second line - - lhshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_LABCURVE_CURVEEDITOR_LH"))); - lhshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LH_TOOLTIP")); - lhshape->setCurveColorProvider(this, 4); - lhshape->setEditID(EUID_Lab_LHCurve, BT_SINGLEPLANE_FLOAT); + acconn = avoidcolorshift->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::avoidcolorshift_toggled) ); + lcconn = lcredsk->signal_toggled().connect( sigc::mem_fun(*this, &LCurve::lcredsk_toggled) ); + + //%%%%%%%%%%%%%%%%%%% + + Gtk::HSeparator *hsep3 = Gtk::manage (new Gtk::HSeparator()); + hsep3->show (); + pack_start (*hsep3, Gtk::PACK_EXPAND_WIDGET, 4); + + curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); + curveEditorG->setCurveListener (this); + + lshape = static_cast(curveEditorG->addCurve(CT_Diagonal, "L*")); + lshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LL_TOOLTIP")); + lshape->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT); + + ashape = static_cast(curveEditorG->addCurve(CT_Diagonal, "a*")); + ashape->setEditID(EUID_Lab_aCurve, BT_SINGLEPLANE_FLOAT); + + ashape->setRangeLabels( + M("TP_LABCURVE_CURVEEDITOR_A_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_A_RANGE2"), + M("TP_LABCURVE_CURVEEDITOR_A_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_A_RANGE4") + ); + //from green to magenta + milestones.clear(); + milestones.push_back( GradientMilestone(0., 0., 1., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 0., 1.) ); + ashape->setBottomBarBgGradient(milestones); + ashape->setLeftBarBgGradient(milestones); + milestones.clear(); + + bshape = static_cast(curveEditorG->addCurve(CT_Diagonal, "b*")); + bshape->setRangeLabels( + M("TP_LABCURVE_CURVEEDITOR_B_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_B_RANGE2"), + M("TP_LABCURVE_CURVEEDITOR_B_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_B_RANGE4") + ); + bshape->setEditID(EUID_Lab_bCurve, BT_SINGLEPLANE_FLOAT); + + //from blue to yellow + milestones.clear(); + milestones.push_back( GradientMilestone(0., 0., 0., 1.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 0.) ); + bshape->setBottomBarBgGradient(milestones); + bshape->setLeftBarBgGradient(milestones); + milestones.clear(); + + curveEditorG->newLine(); // ------------------------------------------------ second line + + lhshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_LABCURVE_CURVEEDITOR_LH"))); + lhshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LH_TOOLTIP")); + lhshape->setCurveColorProvider(this, 4); + lhshape->setEditID(EUID_Lab_LHCurve, BT_SINGLEPLANE_FLOAT); - chshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_LABCURVE_CURVEEDITOR_CH"))); - chshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CH_TOOLTIP")); - chshape->setCurveColorProvider(this, 1); - chshape->setEditID(EUID_Lab_CHCurve, BT_SINGLEPLANE_FLOAT); + chshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_LABCURVE_CURVEEDITOR_CH"))); + chshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CH_TOOLTIP")); + chshape->setCurveColorProvider(this, 1); + chshape->setEditID(EUID_Lab_CHCurve, BT_SINGLEPLANE_FLOAT); - hhshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_LABCURVE_CURVEEDITOR_HH"))); - hhshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_HH_TOOLTIP")); - hhshape->setCurveColorProvider(this, 5); - hhshape->setEditID(EUID_Lab_HHCurve, BT_SINGLEPLANE_FLOAT); - - curveEditorG->newLine(); // ------------------------------------------------ 3rd line + hhshape = static_cast(curveEditorG->addCurve(CT_Flat, M("TP_LABCURVE_CURVEEDITOR_HH"))); + hhshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_HH_TOOLTIP")); + hhshape->setCurveColorProvider(this, 5); + hhshape->setEditID(EUID_Lab_HHCurve, BT_SINGLEPLANE_FLOAT); - ccshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_CC"))); - ccshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CC_TOOLTIP")); - ccshape->setEditID(EUID_Lab_CCurve, BT_SINGLEPLANE_FLOAT); - ccshape->setRangeLabels( - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") - ); - - ccshape->setBottomBarColorProvider(this, 2); - ccshape->setLeftBarColorProvider(this, 2); - ccshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); - - lcshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_LC"))); - lcshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LC_TOOLTIP")); - lcshape->setEditID(EUID_Lab_LCCurve, BT_SINGLEPLANE_FLOAT); - - // left and bottom bar uses the same caller id because the will display the same content - lcshape->setBottomBarColorProvider(this, 2); - lcshape->setRangeLabels( - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), - M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") - ); - lcshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); + curveEditorG->newLine(); // ------------------------------------------------ 3rd line - clshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_CL"))); - clshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CL_TOOLTIP")); - clshape->setEditID(EUID_Lab_CLCurve, BT_SINGLEPLANE_FLOAT); - - clshape->setLeftBarColorProvider(this, 2); - clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - - clshape->setBottomBarBgGradient(milestones); - - - // Setting the gradient milestones + ccshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_CC"))); + ccshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CC_TOOLTIP")); + ccshape->setEditID(EUID_Lab_CCurve, BT_SINGLEPLANE_FLOAT); + ccshape->setRangeLabels( + M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), + M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") + ); - // from black to white - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - lshape->setBottomBarBgGradient(milestones); - lshape->setLeftBarBgGradient(milestones); - milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); - lcshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); - - lcshape->setBottomBarBgGradient(milestones); - - milestones.at(0).r = milestones.at(0).g = milestones.at(0).b = 0.1; - milestones.at(1).r = milestones.at(1).g = milestones.at(1).b = 0.8; - lcshape->setLeftBarBgGradient(milestones); + ccshape->setBottomBarColorProvider(this, 2); + ccshape->setLeftBarColorProvider(this, 2); + ccshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); - // whole hue range - milestones.clear(); - for (int i=0; i<7; i++) { - float R, G, B; - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } - chshape->setBottomBarBgGradient(milestones); - lhshape->setBottomBarBgGradient(milestones); - hhshape->setBottomBarBgGradient(milestones); + lcshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_LC"))); + lcshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_LC_TOOLTIP")); + lcshape->setEditID(EUID_Lab_LCCurve, BT_SINGLEPLANE_FLOAT); + + // left and bottom bar uses the same caller id because the will display the same content + lcshape->setBottomBarColorProvider(this, 2); + lcshape->setRangeLabels( + M("TP_LABCURVE_CURVEEDITOR_CC_RANGE1"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE2"), + M("TP_LABCURVE_CURVEEDITOR_CC_RANGE3"), M("TP_LABCURVE_CURVEEDITOR_CC_RANGE4") + ); + lcshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); + + clshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_LABCURVE_CURVEEDITOR_CL"))); + clshape->setTooltip(M("TP_LABCURVE_CURVEEDITOR_CL_TOOLTIP")); + clshape->setEditID(EUID_Lab_CLCurve, BT_SINGLEPLANE_FLOAT); + + clshape->setLeftBarColorProvider(this, 2); + clshape->setRangeDefaultMilestones(0.25, 0.5, 0.75); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + + clshape->setBottomBarBgGradient(milestones); - // This will add the reset button at the end of the curveType buttons - curveEditorG->curveListComplete(); + // Setting the gradient milestones - pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); + // from black to white + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + lshape->setBottomBarBgGradient(milestones); + lshape->setLeftBarBgGradient(milestones); + milestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + lcshape->setRangeDefaultMilestones(0.05, 0.2, 0.58); + + lcshape->setBottomBarBgGradient(milestones); + + milestones.at(0).r = milestones.at(0).g = milestones.at(0).b = 0.1; + milestones.at(1).r = milestones.at(1).g = milestones.at(1).b = 0.8; + lcshape->setLeftBarBgGradient(milestones); + + // whole hue range + milestones.clear(); + + for (int i = 0; i < 7; i++) { + float R, G, B; + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } + + chshape->setBottomBarBgGradient(milestones); + lhshape->setBottomBarBgGradient(milestones); + hhshape->setBottomBarBgGradient(milestones); + + + // This will add the reset button at the end of the curveType buttons + curveEditorG->curveListComplete(); + + pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); } -LCurve::~LCurve () { - delete curveEditorG; +LCurve::~LCurve () +{ + delete curveEditorG; } -void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { +void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); if (pedited) { brightness->setEditedState (pedited->labCurve.brightness ? Edited : UnEdited); contrast->setEditedState (pedited->labCurve.contrast ? Edited : UnEdited); - chromaticity->setEditedState (pedited->labCurve.chromaticity ? Edited : UnEdited); - - //%%%%%%%%%%%%%%%%%%%%%% - rstprotection->setEditedState (pedited->labCurve.rstprotection ? Edited : UnEdited); + chromaticity->setEditedState (pedited->labCurve.chromaticity ? Edited : UnEdited); + + //%%%%%%%%%%%%%%%%%%%%%% + rstprotection->setEditedState (pedited->labCurve.rstprotection ? Edited : UnEdited); avoidcolorshift->set_inconsistent (!pedited->labCurve.avoidcolorshift); - lcredsk->set_inconsistent (!pedited->labCurve.lcredsk); - - //%%%%%%%%%%%%%%%%%%%%%% + lcredsk->set_inconsistent (!pedited->labCurve.lcredsk); + + //%%%%%%%%%%%%%%%%%%%%%% lshape->setUnChanged (!pedited->labCurve.lcurve); ashape->setUnChanged (!pedited->labCurve.acurve); @@ -242,22 +247,22 @@ void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { chromaticity->setValue (pp->labCurve.chromaticity); adjusterChanged(chromaticity, pp->labCurve.chromaticity); // To update the GUI sensitiveness - //%%%%%%%%%%%%%%%%%%%%%% - rstprotection->setValue (pp->labCurve.rstprotection); + //%%%%%%%%%%%%%%%%%%%%%% + rstprotection->setValue (pp->labCurve.rstprotection); bwtconn.block (true); acconn.block (true); - lcconn.block (true); + lcconn.block (true); avoidcolorshift->set_active (pp->labCurve.avoidcolorshift); lcredsk->set_active (pp->labCurve.lcredsk); - + bwtconn.block (false); acconn.block (false); - lcconn.block (false); - + lcconn.block (false); + lastACVal = pp->labCurve.avoidcolorshift; - lastLCVal = pp->labCurve.lcredsk; - //%%%%%%%%%%%%%%%%%%%%%% + lastLCVal = pp->labCurve.lcredsk; + //%%%%%%%%%%%%%%%%%%%%%% lshape->setCurve (pp->labCurve.lcurve); ashape->setCurve (pp->labCurve.acurve); @@ -274,20 +279,46 @@ void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void LCurve::autoOpenCurve () { +void LCurve::autoOpenCurve () +{ // Open up the first curve if selected bool active = lshape->openIfNonlinear(); - if (!active) ashape->openIfNonlinear(); - if (!active) bshape->openIfNonlinear(); - if (!active) ccshape->openIfNonlinear(); - if (!active) chshape->openIfNonlinear(); - if (!active) lhshape->openIfNonlinear(); - if (!active) hhshape->openIfNonlinear(); - if (!active) lcshape->openIfNonlinear(); - if (!active) clshape->openIfNonlinear(); + + if (!active) { + ashape->openIfNonlinear(); + } + + if (!active) { + bshape->openIfNonlinear(); + } + + if (!active) { + ccshape->openIfNonlinear(); + } + + if (!active) { + chshape->openIfNonlinear(); + } + + if (!active) { + lhshape->openIfNonlinear(); + } + + if (!active) { + hhshape->openIfNonlinear(); + } + + if (!active) { + lcshape->openIfNonlinear(); + } + + if (!active) { + clshape->openIfNonlinear(); + } } -void LCurve::setEditProvider (EditDataProvider *provider) { +void LCurve::setEditProvider (EditDataProvider *provider) +{ lshape->setEditProvider(provider); ccshape->setEditProvider(provider); lcshape->setEditProvider(provider); @@ -297,11 +328,12 @@ void LCurve::setEditProvider (EditDataProvider *provider) { hhshape->setEditProvider(provider); ashape->setEditProvider(provider); bshape->setEditProvider(provider); - + } -void LCurve::write (ProcParams* pp, ParamsEdited* pedited) { +void LCurve::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->labCurve.brightness = brightness->getValue (); pp->labCurve.contrast = (int)contrast->getValue (); @@ -348,7 +380,8 @@ void LCurve::write (ProcParams* pp, ParamsEdited* pedited) { } } -void LCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void LCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ brightness->setDefault (defParams->labCurve.brightness); contrast->setDefault (defParams->labCurve.contrast); @@ -358,21 +391,21 @@ void LCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedit if (pedited) { brightness->setDefaultEditedState (pedited->labCurve.brightness ? Edited : UnEdited); contrast->setDefaultEditedState (pedited->labCurve.contrast ? Edited : UnEdited); - chromaticity->setDefaultEditedState (pedited->labCurve.chromaticity ? Edited : UnEdited); + chromaticity->setDefaultEditedState (pedited->labCurve.chromaticity ? Edited : UnEdited); rstprotection->setDefaultEditedState (pedited->labCurve.rstprotection ? Edited : UnEdited); - } - else { + } else { brightness->setDefaultEditedState (Irrelevant); contrast->setDefaultEditedState (Irrelevant); - chromaticity->setDefaultEditedState (Irrelevant); - rstprotection->setDefaultEditedState (Irrelevant); + chromaticity->setDefaultEditedState (Irrelevant); + rstprotection->setDefaultEditedState (Irrelevant); } } //%%%%%%%%%%%%%%%%%%%%%% //Color shift control changed -void LCurve::avoidcolorshift_toggled () { +void LCurve::avoidcolorshift_toggled () +{ if (batchMode) { if (avoidcolorshift->get_inconsistent()) { @@ -380,22 +413,24 @@ void LCurve::avoidcolorshift_toggled () { acconn.block (true); avoidcolorshift->set_active (false); acconn.block (false); - } - else if (lastACVal) + } else if (lastACVal) { avoidcolorshift->set_inconsistent (true); + } lastACVal = avoidcolorshift->get_active (); } if (listener) { - if (avoidcolorshift->get_active ()) + if (avoidcolorshift->get_active ()) { listener->panelChanged (EvLAvoidColorShift, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvLAvoidColorShift, M("GENERAL_DISABLED")); + } } } -void LCurve::lcredsk_toggled () { +void LCurve::lcredsk_toggled () +{ if (batchMode) { if (lcredsk->get_inconsistent()) { @@ -403,21 +438,21 @@ void LCurve::lcredsk_toggled () { lcconn.block (true); lcredsk->set_active (false); lcconn.block (false); - } - else if (lastLCVal) + } else if (lastLCVal) { lcredsk->set_inconsistent (true); + } lastLCVal = lcredsk->get_active (); - } - else { + } else { lcshape->refresh(); } if (listener) { - if (lcredsk->get_active ()) + if (lcredsk->get_active ()) { listener->panelChanged (EvLLCredsk, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvLLCredsk, M("GENERAL_DISABLED")); + } } } @@ -429,151 +464,187 @@ void LCurve::lcredsk_toggled () { * If more than one curve has been added, the curve listener is automatically * set to 'multi=true', and send a pointer of the modified curve in a parameter */ -void LCurve::curveChanged (CurveEditor* ce) { +void LCurve::curveChanged (CurveEditor* ce) +{ if (listener) { - if (ce == lshape) + if (ce == lshape) { listener->panelChanged (EvLLCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == ashape) + } + + if (ce == ashape) { listener->panelChanged (EvLaCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == bshape) + } + + if (ce == bshape) { listener->panelChanged (EvLbCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == ccshape) - listener->panelChanged (EvLCCCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == chshape) + } + + if (ce == ccshape) { + listener->panelChanged (EvLCCCurve, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == chshape) { listener->panelChanged (EvLCHCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == lhshape) + } + + if (ce == lhshape) { listener->panelChanged (EvLLHCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == hhshape) + } + + if (ce == hhshape) { listener->panelChanged (EvLHHCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == lcshape) + } + + if (ce == lcshape) { listener->panelChanged (EvLLCCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == clshape) + } + + if (ce == clshape) { listener->panelChanged (EvLCLCurve, M("HISTORY_CUSTOMCURVE")); + } } } -void LCurve::adjusterChanged (Adjuster* a, double newval) { +void LCurve::adjusterChanged (Adjuster* a, double newval) +{ Glib::ustring costr; - if (a==brightness) - costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); - else if (a==rstprotection) - costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(1), a->getValue()); - else - costr = Glib::ustring::format ((int)a->getValue()); - if (a==brightness) { - if (listener) listener->panelChanged (EvLBrightness, costr); + if (a == brightness) { + costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); + } else if (a == rstprotection) { + costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(1), a->getValue()); + } else { + costr = Glib::ustring::format ((int)a->getValue()); } - else if (a==contrast) { - if (listener) listener->panelChanged (EvLContrast, costr); - } - else if (a==rstprotection) { - if (listener) listener->panelChanged (EvLRSTProtection, costr); - } - else if (a==chromaticity) { + + if (a == brightness) { + if (listener) { + listener->panelChanged (EvLBrightness, costr); + } + } else if (a == contrast) { + if (listener) { + listener->panelChanged (EvLContrast, costr); + } + } else if (a == rstprotection) { + if (listener) { + listener->panelChanged (EvLRSTProtection, costr); + } + } else if (a == chromaticity) { if (multiImage) { //if chromaticity==-100 (lowest value), we enter the B&W mode and avoid color shift and rstprotection has no effect rstprotection->set_sensitive( true ); avoidcolorshift->set_sensitive( true ); lcredsk->set_sensitive( true ); - } - else { + } else { //if chromaticity==-100 (lowest value), we enter the B&W mode and avoid color shift and rstprotection has no effect - rstprotection->set_sensitive( int(newval)> -100 );//no reason for grey rstprotection - avoidcolorshift->set_sensitive( int(newval)> -100 ); - lcredsk->set_sensitive( int(newval)> -100 ); + rstprotection->set_sensitive( int(newval) > -100 ); //no reason for grey rstprotection + avoidcolorshift->set_sensitive( int(newval) > -100 ); + lcredsk->set_sensitive( int(newval) > -100 ); + } + + if (listener) { + listener->panelChanged (EvLSaturation, costr); } - if (listener) listener->panelChanged (EvLSaturation, costr); } } -void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { +void LCurve::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) +{ - float R, G, B; + float R, G, B; - if (elemType==ColorCaller::CCET_VERTICAL_BAR) - valY = 0.5; + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } - if (callerId == 1) { // ch - main curve + if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); - } - else if (callerId == 2) { // cc - bottom bar + Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); + } else if (callerId == 2) { // cc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - // whole hue range - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); - } - else if (callerId == 3) { // lc - bottom bar + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } else if (callerId == 3) { // lc - bottom bar - float value = (1.f - 0.7f) * float(valX) + 0.7f; - if (lcredsk->get_active()) { - // skin range - // -0.1 rad < Hue < 1.6 rad - // Y axis / from 0.92 up to 0.14056 - float hue = (1.14056f - 0.92f) * float(valY) + 0.92f; - if (hue > 1.0f) hue -= 1.0f; - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(hue, float(valX), value, R, G, B); - } - else { - // whole hue range - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); - } - } - else if (callerId == 4) { // LH - bottom bar - Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); - } - else if (callerId == 5) { // HH - bottom bar - float h = float((valY - 0.5) * 0.3 + valX); - if (h > 1.0f) - h -= 1.0f; - else if (h < 0.0f) - h += 1.0f; - Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); - } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + float value = (1.f - 0.7f) * float(valX) + 0.7f; + + if (lcredsk->get_active()) { + // skin range + // -0.1 rad < Hue < 1.6 rad + // Y axis / from 0.92 up to 0.14056 + float hue = (1.14056f - 0.92f) * float(valY) + 0.92f; + + if (hue > 1.0f) { + hue -= 1.0f; + } + + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(hue, float(valX), value, R, G, B); + } else { + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } + } else if (callerId == 4) { // LH - bottom bar + Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); + } else if (callerId == 5) { // HH - bottom bar + float h = float((valY - 0.5) * 0.3 + valX); + + if (h > 1.0f) { + h -= 1.0f; + } else if (h < 0.0f) { + h += 1.0f; + } + + Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); + } + + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); } -void LCurve::setBatchMode (bool batchMode) { +void LCurve::setBatchMode (bool batchMode) +{ - ToolPanel::setBatchMode (batchMode); - brightness->showEditedCB (); - contrast->showEditedCB (); - chromaticity->showEditedCB (); - rstprotection->showEditedCB (); + ToolPanel::setBatchMode (batchMode); + brightness->showEditedCB (); + contrast->showEditedCB (); + chromaticity->showEditedCB (); + rstprotection->showEditedCB (); - curveEditorG->setBatchMode (batchMode); - lcshape->setBottomBarColorProvider(NULL, -1); - lcshape->setLeftBarColorProvider(NULL, -1); + curveEditorG->setBatchMode (batchMode); + lcshape->setBottomBarColorProvider(NULL, -1); + lcshape->setLeftBarColorProvider(NULL, -1); } -void LCurve::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma){ +void LCurve::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) +{ + + lshape->updateBackgroundHistogram (histLCurve); + ccshape->updateBackgroundHistogram (histCCurve); +// clshape->updateBackgroundHistogram (histCLurve); +// lcshape->updateBackgroundHistogram (histLLCurve); - lshape->updateBackgroundHistogram (histLCurve); - ccshape->updateBackgroundHistogram (histCCurve); -// clshape->updateBackgroundHistogram (histCLurve); -// lcshape->updateBackgroundHistogram (histLLCurve); - } -void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd) { +void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd) +{ - brightness->setAddMode(bradd); - contrast->setAddMode(contradd); - chromaticity->setAddMode(satadd); + brightness->setAddMode(bradd); + contrast->setAddMode(contradd); + chromaticity->setAddMode(satadd); } -void LCurve::trimValues (rtengine::procparams::ProcParams* pp) { +void LCurve::trimValues (rtengine::procparams::ProcParams* pp) +{ - brightness->trimValue(pp->labCurve.brightness); - contrast->trimValue(pp->labCurve.contrast); - chromaticity->trimValue(pp->labCurve.chromaticity); + brightness->trimValue(pp->labCurve.brightness); + contrast->trimValue(pp->labCurve.contrast); + chromaticity->trimValue(pp->labCurve.chromaticity); } diff --git a/rtgui/labcurve.h b/rtgui/labcurve.h index 573a6b587..f679fc020 100644 --- a/rtgui/labcurve.h +++ b/rtgui/labcurve.h @@ -7,7 +7,7 @@ * 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 @@ -26,9 +26,10 @@ #include "curveeditorgroup.h" #include "colorprovider.h" -class LCurve : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider { +class LCurve : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider +{ - protected: +protected: CurveEditorGroup* curveEditorG; Adjuster* brightness; Adjuster* contrast; @@ -41,27 +42,27 @@ class LCurve : public ToolParamBlock, public AdjusterListener, public FoldableTo FlatCurveEditor* chshape; FlatCurveEditor* lhshape; FlatCurveEditor* hhshape; - + DiagonalCurveEditor* clshape; //%%%%%%%%%%%%%%%% Gtk::CheckButton* avoidcolorshift; Gtk::CheckButton* lcredsk; - + Adjuster* rstprotection; sigc::connection bwtconn, acconn, lcconn; bool lastACVal, lastLCVal; - + //%%%%%%%%%%%%%%%% - public: +public: LCurve (); ~LCurve (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void autoOpenCurve (); void setEditProvider (EditDataProvider *provider); @@ -70,9 +71,9 @@ class LCurve : public ToolParamBlock, public AdjusterListener, public FoldableTo void curveChanged (CurveEditor* ce); void adjusterChanged (Adjuster* a, double newval); - void avoidcolorshift_toggled (); + void avoidcolorshift_toggled (); void lcredsk_toggled(); - + void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma); virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); diff --git a/rtgui/lensgeom.cc b/rtgui/lensgeom.cc index 168044197..69c4737bc 100644 --- a/rtgui/lensgeom.cc +++ b/rtgui/lensgeom.cc @@ -23,57 +23,65 @@ using namespace rtengine; using namespace rtengine::procparams; -LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGEOM_LABEL")), rlistener(NULL) { +LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGEOM_LABEL")), rlistener(NULL) +{ - fill = Gtk::manage (new Gtk::CheckButton (M("TP_LENSGEOM_FILL"))); - pack_start (*fill); + fill = Gtk::manage (new Gtk::CheckButton (M("TP_LENSGEOM_FILL"))); + pack_start (*fill); - autoCrop = Gtk::manage (new Gtk::Button (M("TP_LENSGEOM_AUTOCROP"))); - autoCrop->set_image (*Gtk::manage (new RTImage ("crop-auto.png"))); - pack_start (*autoCrop, Gtk::PACK_SHRINK, 2); + autoCrop = Gtk::manage (new Gtk::Button (M("TP_LENSGEOM_AUTOCROP"))); + autoCrop->set_image (*Gtk::manage (new RTImage ("crop-auto.png"))); + pack_start (*autoCrop, Gtk::PACK_SHRINK, 2); - packBox = Gtk::manage (new ToolParamBlock ()); - pack_start (*packBox); + packBox = Gtk::manage (new ToolParamBlock ()); + pack_start (*packBox); - autoCrop->signal_pressed().connect( sigc::mem_fun(*this, &LensGeometry::autoCropPressed) ); - fillConn = fill->signal_toggled().connect( sigc::mem_fun(*this, &LensGeometry::fillPressed) ); + autoCrop->signal_pressed().connect( sigc::mem_fun(*this, &LensGeometry::autoCropPressed) ); + fillConn = fill->signal_toggled().connect( sigc::mem_fun(*this, &LensGeometry::fillPressed) ); - fill->set_active (true); - show_all (); + fill->set_active (true); + show_all (); } -void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited) { +void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); - if (pedited) + if (pedited) { fill->set_inconsistent (!pedited->commonTrans.autofill); + } fillConn.block (true); fill->set_active (pp->commonTrans.autofill); fillConn.block (false); - autoCrop->set_sensitive (!pp->commonTrans.autofill); + autoCrop->set_sensitive (!pp->commonTrans.autofill); lastFill = pp->commonTrans.autofill; enableListener (); } -void LensGeometry::write (ProcParams* pp, ParamsEdited* pedited) { +void LensGeometry::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->commonTrans.autofill = fill->get_active (); - if (pedited) + if (pedited) { pedited->commonTrans.autofill = !fill->get_inconsistent(); + } } -void LensGeometry::autoCropPressed () { +void LensGeometry::autoCropPressed () +{ - if (rlistener) + if (rlistener) { rlistener->autoCropRequested (); + } } -void LensGeometry::fillPressed () { +void LensGeometry::fillPressed () +{ if (batchMode) { if (fill->get_inconsistent()) { @@ -81,24 +89,26 @@ void LensGeometry::fillPressed () { fillConn.block (true); fill->set_active (false); fillConn.block (false); - } - else if (lastFill) + } else if (lastFill) { fill->set_inconsistent (true); + } lastFill = fill->get_active (); + } else { + autoCrop->set_sensitive (!fill->get_active()); } - else - autoCrop->set_sensitive (!fill->get_active()); if (listener) { - if (fill->get_active ()) - listener->panelChanged (EvTransAutoFill, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvTransAutoFill, M("GENERAL_DISABLED")); + if (fill->get_active ()) { + listener->panelChanged (EvTransAutoFill, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvTransAutoFill, M("GENERAL_DISABLED")); + } } } -void LensGeometry::setBatchMode (bool batchMode) { +void LensGeometry::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); removeIfThere (this, autoCrop); diff --git a/rtgui/lensgeom.h b/rtgui/lensgeom.h index 84d64e816..f6b41b632 100644 --- a/rtgui/lensgeom.h +++ b/rtgui/lensgeom.h @@ -23,9 +23,10 @@ #include "toolpanel.h" #include "lensgeomlistener.h" -class LensGeometry : public ToolParamBlock, public FoldableToolPanel { +class LensGeometry : public ToolParamBlock, public FoldableToolPanel +{ - protected: +protected: Gtk::Button* autoCrop; LensGeomListener* rlistener; Gtk::CheckButton* fill; @@ -33,19 +34,25 @@ class LensGeometry : public ToolParamBlock, public FoldableToolPanel { sigc::connection fillConn; ToolParamBlock* packBox; - public: +public: LensGeometry (); - Gtk::Box* getPackBox () { return packBox; } + Gtk::Box* getPackBox () + { + return packBox; + } - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void fillPressed (); void autoCropPressed (); - void setLensGeomListener (LensGeomListener* l) { rlistener = l; } + void setLensGeomListener (LensGeomListener* l) + { + rlistener = l; + } }; #endif diff --git a/rtgui/lensgeomlistener.h b/rtgui/lensgeomlistener.h index 6b7f79f98..3f9866e95 100644 --- a/rtgui/lensgeomlistener.h +++ b/rtgui/lensgeomlistener.h @@ -19,12 +19,13 @@ #ifndef _LENSGEOMLISTENER_H_ #define _LENSGEOMLISTENER_H_ -class LensGeomListener { +class LensGeomListener +{ - public: - virtual void straightenRequested ()=0; - virtual void autoCropRequested ()=0; - virtual double autoDistorRequested ()=0; +public: + virtual void straightenRequested () = 0; + virtual void autoCropRequested () = 0; + virtual double autoDistorRequested () = 0; }; #endif diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 68065739a..f85fb79c0 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -42,7 +42,8 @@ LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("T filterLCP.add_pattern("*.LCP"); fcbLCPFile->add_filter(filterLCP); - Glib::ustring defDir=lcpStore->getDefaultCommonDirectory(); + Glib::ustring defDir = lcpStore->getDefaultCommonDirectory(); + if (!defDir.empty()) { #ifdef WIN32 fcbLCPFile->set_show_hidden(true); // ProgramData is hidden on Windows @@ -71,7 +72,7 @@ LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("T ckbUseVign->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseVignChanged) ); ckbUseCA->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseCAChanged) ); - allowFocusDep=true; + allowFocusDep = true; } void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) @@ -83,13 +84,15 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa updateDisabled(true); } else { Glib::ustring fname = fcbLCPFile->get_filename(); - if (!pp->lensProf.lcpFile.empty()) + + if (!pp->lensProf.lcpFile.empty()) { fcbLCPFile->unselect_filename(fname); - else { - Glib::ustring lastFolder = fcbLCPFile->get_current_folder(); - fcbLCPFile->set_filename(""); - fcbLCPFile->set_current_folder(lastFolder); - } + } else { + Glib::ustring lastFolder = fcbLCPFile->get_current_folder(); + fcbLCPFile->set_filename(""); + fcbLCPFile->set_current_folder(lastFolder); + } + updateDisabled(false); } @@ -97,31 +100,34 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa ckbUseVign->set_active (pp->lensProf.useVign && isRaw); ckbUseCA->set_active (pp->lensProf.useCA && isRaw); - lcpFileChanged=useDistChanged=useVignChanged=useCAChanged=false; + lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false; enableListener (); } -void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta) { - if (!raw || pMeta->getFocusDist()<=0) { +void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta) +{ + if (!raw || pMeta->getFocusDist() <= 0) { disableListener(); // CA is very focus layer dependend, otherwise it might even worsen things - allowFocusDep=false; + allowFocusDep = false; ckbUseCA->set_active(false); ckbUseCA->set_sensitive(false); enableListener(); } - isRaw=raw; + + isRaw = raw; } void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - if (lcpStore->isValidLCPFileName(fcbLCPFile->get_filename())) + if (lcpStore->isValidLCPFileName(fcbLCPFile->get_filename())) { pp->lensProf.lcpFile = fcbLCPFile->get_filename(); - else + } else { pp->lensProf.lcpFile = ""; + } pp->lensProf.useDist = ckbUseDist->get_active(); pp->lensProf.useVign = ckbUseVign->get_active(); @@ -137,41 +143,53 @@ void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited void LensProfilePanel::onLCPFileChanged() { - lcpFileChanged=true; + lcpFileChanged = true; updateDisabled(lcpStore->isValidLCPFileName(fcbLCPFile->get_filename())); - if (listener) + if (listener) { listener->panelChanged (EvLCPFile, Glib::path_get_basename(fcbLCPFile->get_filename())); + } } void LensProfilePanel::onLCPFileReset() { - lcpFileChanged=true; + lcpFileChanged = true; fcbLCPFile->unselect_filename(fcbLCPFile->get_filename()); updateDisabled(false); - if (listener) + if (listener) { listener->panelChanged (EvLCPFile, M("GENERAL_NONE")); + } } void LensProfilePanel::onUseDistChanged() { - useDistChanged=true; - if (listener) listener->panelChanged (EvLCPUseDist, ckbUseDist->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + useDistChanged = true; + + if (listener) { + listener->panelChanged (EvLCPUseDist, ckbUseDist->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } void LensProfilePanel::onUseVignChanged() { - useVignChanged=true; - if (listener) listener->panelChanged (EvLCPUseVign, ckbUseVign->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + useVignChanged = true; + + if (listener) { + listener->panelChanged (EvLCPUseVign, ckbUseVign->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } void LensProfilePanel::onUseCAChanged() { - useCAChanged=true; - if (listener) listener->panelChanged (EvLCPUseCA, ckbUseCA->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + useCAChanged = true; + + if (listener) { + listener->panelChanged (EvLCPUseCA, ckbUseCA->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void LensProfilePanel::updateDisabled(bool enable) { +void LensProfilePanel::updateDisabled(bool enable) +{ ckbUseDist->set_sensitive(enable); ckbUseVign->set_sensitive(enable && isRaw); ckbUseCA->set_sensitive(enable && allowFocusDep); diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 8023786d2..0397388d5 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -23,7 +23,8 @@ #include "toolpanel.h" #include "guiutils.h" -class LensProfilePanel : public ToolParamBlock, public FoldableToolPanel { +class LensProfilePanel : public ToolParamBlock, public FoldableToolPanel +{ protected: @@ -32,7 +33,7 @@ protected: Gtk::HBox *hbLCPFile; Gtk::Button *btnReset; Gtk::Label *lLCPFileHead; - bool lcpFileChanged,useDistChanged,useVignChanged,useCAChanged; + bool lcpFileChanged, useDistChanged, useVignChanged, useCAChanged; sigc::connection conLCPFile, conUseDist, conUseVign, conUseCA; void updateDisabled(bool enable); bool allowFocusDep; @@ -42,8 +43,8 @@ public: LensProfilePanel (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setRawMeta (bool raw, const rtengine::ImageMetaData* pMeta); void onLCPFileChanged (); diff --git a/rtgui/lwbutton.cc b/rtgui/lwbutton.cc index ea4bf182f..52b7fd7e8 100644 --- a/rtgui/lwbutton.cc +++ b/rtgui/lwbutton.cc @@ -7,7 +7,7 @@ * 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 @@ -19,52 +19,60 @@ #include "lwbutton.h" #include "guiutils.h" -LWButton::LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring tooltip) - : halign(ha), valign(va), icon(i), state(Normal), listener(NULL), actionCode(aCode), actionData(aData), toolTip(tooltip) { - +LWButton::LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring tooltip) + : halign(ha), valign(va), icon(i), state(Normal), listener(NULL), actionCode(aCode), actionData(aData), toolTip(tooltip) +{ + if (i) { - w = i->get_width () + 2; - h = i->get_height () + 2; + w = i->get_width () + 2; + h = i->get_height () + 2; + } else { + w = h = 2; } - else - w = h = 2; } -void LWButton::getSize (int& minw, int& minh) { +void LWButton::getSize (int& minw, int& minh) +{ minw = w; minh = h; } -void LWButton::setPosition (int x, int y) { +void LWButton::setPosition (int x, int y) +{ xpos = x; ypos = y; } -void LWButton::getPosition (int& x, int& y) { +void LWButton::getPosition (int& x, int& y) +{ x = xpos; y = ypos; } -void LWButton::setIcon (Cairo::RefPtr i) { +void LWButton::setIcon (Cairo::RefPtr i) +{ icon = i; + if (i) { - w = i->get_width () + 2; - h = i->get_height () + 2; + w = i->get_width () + 2; + h = i->get_height () + 2; + } else { + w = h = 2; } - else - w = h = 2; } -Cairo::RefPtr LWButton::getIcon () { +Cairo::RefPtr LWButton::getIcon () +{ return icon; } -void LWButton::setColors (const Gdk::Color& bg, const Gdk::Color& fg) { +void LWButton::setColors (const Gdk::Color& bg, const Gdk::Color& fg) +{ bgr = bg.get_red_p (); bgg = bg.get_green_p (); @@ -74,117 +82,153 @@ void LWButton::setColors (const Gdk::Color& bg, const Gdk::Color& fg) { fgb = fg.get_blue_p (); } -bool LWButton::inside (int x, int y) { +bool LWButton::inside (int x, int y) +{ - return x>xpos && xypos && y xpos && x < xpos + w && y > ypos && y < ypos + h; } -bool LWButton::motionNotify (int x, int y) { +bool LWButton::motionNotify (int x, int y) +{ bool in = inside (x, y); State nstate = state; - if (state==Normal && in) + + if (state == Normal && in) { nstate = Over; - else if (state==Over && !in) + } else if (state == Over && !in) { nstate = Normal; - else if (state==Pressed_In && !in) + } else if (state == Pressed_In && !in) { nstate = Pressed_Out; - else if (state==Pressed_Out && in) + } else if (state == Pressed_Out && in) { nstate = Pressed_In; - - if (state!=nstate) { + } + + if (state != nstate) { state = nstate; - if (listener) + + if (listener) { listener->redrawNeeded (this); + } + return true; } + return in; } -bool LWButton::pressNotify (int x, int y) { +bool LWButton::pressNotify (int x, int y) +{ bool in = inside (x, y); State nstate = state; - if (in && (state==Normal || state==Over || state==Pressed_Out)) + + if (in && (state == Normal || state == Over || state == Pressed_Out)) { nstate = Pressed_In; - else if (!in && state==Pressed_In) + } else if (!in && state == Pressed_In) { nstate = Normal; - - if (state!=nstate) { + } + + if (state != nstate) { state = nstate; - if (listener) + + if (listener) { listener->redrawNeeded (this); + } + return true; } + return in; } -bool LWButton::releaseNotify (int x, int y) { +bool LWButton::releaseNotify (int x, int y) +{ bool in = inside (x, y); State nstate = state; bool action = false; - if (in && (state==Pressed_In || state==Pressed_Out)) { + + if (in && (state == Pressed_In || state == Pressed_Out)) { nstate = Over; action = true; - } - else + } else { nstate = Normal; - + } + bool ret = action; - if (state!=nstate) { + + if (state != nstate) { state = nstate; - if (listener) + + if (listener) { listener->redrawNeeded (this); + } + ret = true; } - - if (action && listener) + + if (action && listener) { listener->buttonPressed (this, actionCode, actionData); + } + return ret; } -void LWButton::redraw (Cairo::RefPtr context) { +void LWButton::redraw (Cairo::RefPtr context) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected context->set_line_width (1.0); context->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); - context->rectangle (xpos+0.5, ypos+0.5, w-1.0, h-1.0); - if (state==Pressed_In) + context->rectangle (xpos + 0.5, ypos + 0.5, w - 1.0, h - 1.0); + + if (state == Pressed_In) { context->set_source_rgb (fgr, fgg, fgb); - else + } else { context->set_source_rgba (bgr, bgg, bgb, 0); + } + context->fill_preserve (); - if (state==Over) + + if (state == Over) { context->set_source_rgb (fgr, fgg, fgb); - else + } else { context->set_source_rgba (bgr, bgg, bgb, 0); + } + context->stroke (); int dilat = 1; - if (state==Pressed_In) + + if (state == Pressed_In) { dilat++; + } if (icon) { - context->set_source (icon, xpos+dilat, ypos+dilat); + context->set_source (icon, xpos + dilat, ypos + dilat); context->paint (); } } -void LWButton::getAlignment (Alignment& ha, Alignment& va) { +void LWButton::getAlignment (Alignment& ha, Alignment& va) +{ ha = halign; va = valign; } -Glib::ustring LWButton::getToolTip (int x, int y) { +Glib::ustring LWButton::getToolTip (int x, int y) +{ - if (inside (x, y)) + if (inside (x, y)) { return toolTip; - else + } else { return ""; + } } -void LWButton::setToolTip (const Glib::ustring& tooltip) { +void LWButton::setToolTip (const Glib::ustring& tooltip) +{ toolTip = tooltip; } diff --git a/rtgui/lwbutton.h b/rtgui/lwbutton.h index b50478abd..2241235a2 100644 --- a/rtgui/lwbutton.h +++ b/rtgui/lwbutton.h @@ -7,7 +7,7 @@ * 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 @@ -22,54 +22,59 @@ #include class LWButton; -class LWButtonListener { +class LWButtonListener +{ - public: - virtual ~LWButtonListener () {} - virtual void buttonPressed (LWButton* button, int actionCode, void* actionData) {} - virtual void redrawNeeded (LWButton* button) {} +public: + virtual ~LWButtonListener () {} + virtual void buttonPressed (LWButton* button, int actionCode, void* actionData) {} + virtual void redrawNeeded (LWButton* button) {} }; -class LWButton { - - public: - enum Alignment {Left, Right, Top, Bottom, Center}; - enum State { Normal, Over, Pressed_In, Pressed_Out}; - - private: - int xpos, ypos, w, h; - Alignment halign, valign; - Cairo::RefPtr icon; - double bgr, bgg, bgb; - double fgr, fgg, fgb; - State state; - LWButtonListener* listener; - int actionCode; - void* actionData; - Glib::ustring toolTip; - - public: - LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha=Left, Alignment va=Center, Glib::ustring tooltip=""); - - void getSize (int& minw, int& minh); - void getAlignment (Alignment& ha, Alignment& va); - void setPosition (int x, int y); - void getPosition (int& x, int& y); - bool inside (int x, int y); - void setIcon (Cairo::RefPtr i); - Cairo::RefPtr getIcon (); - void setColors (const Gdk::Color& bg, const Gdk::Color& fg); - void setToolTip (const Glib::ustring& tooltip); - - bool motionNotify (int x, int y); - bool pressNotify (int x, int y); - bool releaseNotify (int x, int y); +class LWButton +{ - Glib::ustring getToolTip (int x, int y); - - void setButtonListener (LWButtonListener* bl) { listener = bl; } +public: + enum Alignment {Left, Right, Top, Bottom, Center}; + enum State { Normal, Over, Pressed_In, Pressed_Out}; - void redraw (Cairo::RefPtr context); +private: + int xpos, ypos, w, h; + Alignment halign, valign; + Cairo::RefPtr icon; + double bgr, bgg, bgb; + double fgr, fgg, fgb; + State state; + LWButtonListener* listener; + int actionCode; + void* actionData; + Glib::ustring toolTip; + +public: + LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha = Left, Alignment va = Center, Glib::ustring tooltip = ""); + + void getSize (int& minw, int& minh); + void getAlignment (Alignment& ha, Alignment& va); + void setPosition (int x, int y); + void getPosition (int& x, int& y); + bool inside (int x, int y); + void setIcon (Cairo::RefPtr i); + Cairo::RefPtr getIcon (); + void setColors (const Gdk::Color& bg, const Gdk::Color& fg); + void setToolTip (const Glib::ustring& tooltip); + + bool motionNotify (int x, int y); + bool pressNotify (int x, int y); + bool releaseNotify (int x, int y); + + Glib::ustring getToolTip (int x, int y); + + void setButtonListener (LWButtonListener* bl) + { + listener = bl; + } + + void redraw (Cairo::RefPtr context); }; #endif diff --git a/rtgui/lwbuttonset.cc b/rtgui/lwbuttonset.cc index fea24d41c..bfa4684af 100644 --- a/rtgui/lwbuttonset.cc +++ b/rtgui/lwbuttonset.cc @@ -7,7 +7,7 @@ * 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 @@ -18,152 +18,193 @@ */ #include "lwbuttonset.h" -LWButtonSet::LWButtonSet () : aw(0), ah(0) { +LWButtonSet::LWButtonSet () : aw(0), ah(0) +{ } -LWButtonSet::~LWButtonSet () { +LWButtonSet::~LWButtonSet () +{ - for (size_t i=0; igetSize (bw, bh); - w+= bw; - if (bh>h) - h = bh; } } -void LWButtonSet::arrangeButtons (int x, int y, int w, int h) { +void LWButtonSet::add (LWButton* b) +{ + + buttons.push_back (b); +} + +void LWButtonSet::getMinimalDimensions (int& w, int& h) +{ + + w = 0; + h = 0; + + for (size_t i = 0; i < buttons.size(); i++) { + int bw, bh; + buttons[i]->getSize (bw, bh); + w += bw; + + if (bh > h) { + h = bh; + } + } +} + +void LWButtonSet::arrangeButtons (int x, int y, int w, int h) +{ int mw, mh; getMinimalDimensions (mw, mh); - if (w<0) + if (w < 0) { w = mw; - if (h<0) - h = mh; + } - int begx = x; - int endx = x+w-1; - for (size_t i=0; igetSize (bw, bh); buttons[i]->getAlignment (halign, valign); + if (halign == LWButton::Left) { bx = begx; begx += bw; - } - else if (halign == LWButton::Right) { - bx = endx-bw; + } else if (halign == LWButton::Right) { + bx = endx - bw; endx -= bw; } - if (valign == LWButton::Top) + + if (valign == LWButton::Top) { by = y; - else if (valign == LWButton::Bottom) - by = y+h-bh-1; - else if (valign == LWButton::Center) - by = y+(h-bh)/2; + } else if (valign == LWButton::Bottom) { + by = y + h - bh - 1; + } else if (valign == LWButton::Center) { + by = y + (h - bh) / 2; + } + buttons[i]->setPosition (bx, by); } + aw = w; ah = h; ax = x; ay = y; } -void LWButtonSet::move (int nx, int ny) { +void LWButtonSet::move (int nx, int ny) +{ - for (size_t i=0; igetPosition (x, y); - buttons[i]->setPosition (x+nx-ax, y+ny-ay); + buttons[i]->setPosition (x + nx - ax, y + ny - ay); } ax = nx; ay = ny; } -void LWButtonSet::redraw (Cairo::RefPtr context) { +void LWButtonSet::redraw (Cairo::RefPtr context) +{ - for (size_t i=0; iredraw (context); + } } -bool LWButtonSet::motionNotify (int x, int y) { +bool LWButtonSet::motionNotify (int x, int y) +{ bool res = false; - for (size_t i=0; imotionNotify (x, y); res = res || handled; } - + return res; } -bool LWButtonSet::pressNotify (int x, int y) { +bool LWButtonSet::pressNotify (int x, int y) +{ bool res = false; - for (size_t i=0; ipressNotify (x, y); res = res || handled; } + return res; } -bool LWButtonSet::releaseNotify (int x, int y) { +bool LWButtonSet::releaseNotify (int x, int y) +{ bool res = false; - for (size_t i=0; ireleaseNotify (x, y); res = res || handled; } + return res; } -bool LWButtonSet::inside (int x, int y) { +bool LWButtonSet::inside (int x, int y) +{ - for (size_t i=0; iinside (x, y)) + for (size_t i = 0; i < buttons.size(); i++) + if (buttons[i]->inside (x, y)) { return true; + } + return false; } -void LWButtonSet::setButtonListener (LWButtonListener* bl) { +void LWButtonSet::setButtonListener (LWButtonListener* bl) +{ - for (size_t i=0; isetButtonListener (bl); + } } -void LWButtonSet::getAllocatedDimensions (int& w, int& h) { +void LWButtonSet::getAllocatedDimensions (int& w, int& h) +{ w = aw; h = ah; } -void LWButtonSet::setColors (const Gdk::Color& bg, const Gdk::Color& fg) { +void LWButtonSet::setColors (const Gdk::Color& bg, const Gdk::Color& fg) +{ - for (size_t i=0; isetColors (bg, fg); + } } -Glib::ustring LWButtonSet::getToolTip (int x, int y) { +Glib::ustring LWButtonSet::getToolTip (int x, int y) +{ - for (size_t i=0; igetToolTip (x, y); - if (ttip!="") + + if (ttip != "") { return ttip; + } } + return ""; } diff --git a/rtgui/lwbuttonset.h b/rtgui/lwbuttonset.h index 651304c83..3c17e488d 100644 --- a/rtgui/lwbuttonset.h +++ b/rtgui/lwbuttonset.h @@ -7,7 +7,7 @@ * 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 @@ -23,31 +23,32 @@ #include "lwbutton.h" #include -class LWButtonSet { +class LWButtonSet +{ - protected: - std::vector buttons; - int aw, ah, ax, ay; - public: - LWButtonSet (); - ~LWButtonSet (); - - void add (LWButton* b); - - void getMinimalDimensions (int& w, int& h); - void getAllocatedDimensions (int& w, int& h); - void arrangeButtons (int x, int y, int w, int h); - void setColors (const Gdk::Color& bg, const Gdk::Color& fg); - bool motionNotify (int x, int y); - bool pressNotify (int x, int y); - bool releaseNotify (int x, int y); - void move (int nx, int ny); - bool inside (int x, int y); +protected: + std::vector buttons; + int aw, ah, ax, ay; +public: + LWButtonSet (); + ~LWButtonSet (); - Glib::ustring getToolTip (int x, int y); - - void setButtonListener (LWButtonListener* bl); - void redraw (Cairo::RefPtr context); + void add (LWButton* b); + + void getMinimalDimensions (int& w, int& h); + void getAllocatedDimensions (int& w, int& h); + void arrangeButtons (int x, int y, int w, int h); + void setColors (const Gdk::Color& bg, const Gdk::Color& fg); + bool motionNotify (int x, int y); + bool pressNotify (int x, int y); + bool releaseNotify (int x, int y); + void move (int nx, int ny); + bool inside (int x, int y); + + Glib::ustring getToolTip (int x, int y); + + void setButtonListener (LWButtonListener* bl); + void redraw (Cairo::RefPtr context); }; #endif diff --git a/rtgui/main.cc b/rtgui/main.cc index e4e16be74..cc7c3cbe5 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -7,7 +7,7 @@ * 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 @@ -24,9 +24,9 @@ // This file is for your program, I won't touch it again! #ifdef __GNUC__ - #if defined(__FAST_MATH__) - #error Using the -ffast-math CFLAG is known to lead to problems. Disable it to compile RawTherapee. - #endif +#if defined(__FAST_MATH__) +#error Using the -ffast-math CFLAG is known to lead to problems. Disable it to compile RawTherapee. +#endif #endif #include "config.h" @@ -74,15 +74,20 @@ static Glib::RecMutex myGdkRecMutex; static Glib::Threads::RecMutex myGdkRecMutex; #endif -static void myGdkLockEnter() { myGdkRecMutex.lock(); } -static void myGdkLockLeave() { - // Automatic gdk_flush for non main tread - #if AUTO_GDK_FLUSH - if (Glib::Thread::self() != mainThread) { - gdk_flush(); - } - #endif - myGdkRecMutex.unlock(); +static void myGdkLockEnter() +{ + myGdkRecMutex.lock(); +} +static void myGdkLockLeave() +{ + // Automatic gdk_flush for non main tread +#if AUTO_GDK_FLUSH + if (Glib::Thread::self() != mainThread) { + gdk_flush(); + } + +#endif + myGdkRecMutex.unlock(); } /* Process line command options @@ -97,7 +102,7 @@ int processLineParams( int argc, char **argv ); int main(int argc, char **argv) { - setlocale(LC_ALL,""); + setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); // to set decimal point to "." // Uncomment the following line if you want to use the "--g-fatal-warnings" command line flag //gtk_init (&argc, &argv); @@ -111,15 +116,17 @@ int main(int argc, char **argv) char exname[512] = {0}; Glib::ustring exePath; // get the path where the rawtherapee executable is stored - #ifdef WIN32 - WCHAR exnameU[512] = {0}; - GetModuleFileNameW (NULL, exnameU, 512); - WideCharToMultiByte(CP_UTF8,0,exnameU,-1,exname,512,0,0 ); - #else - if (readlink("/proc/self/exe", exname, 512) < 0) { - strncpy(exname, argv[0], 512); - } - #endif +#ifdef WIN32 + WCHAR exnameU[512] = {0}; + GetModuleFileNameW (NULL, exnameU, 512); + WideCharToMultiByte(CP_UTF8, 0, exnameU, -1, exname, 512, 0, 0 ); +#else + + if (readlink("/proc/self/exe", exname, 512) < 0) { + strncpy(exname, argv[0], 512); + } + +#endif exePath = Glib::path_get_dirname(exname); // set paths @@ -128,575 +135,679 @@ int main(int argc, char **argv) } else { argv0 = Glib::build_filename(exePath, DATA_SEARCH_PATH); } + if (Glib::path_is_absolute(CREDITS_SEARCH_PATH)) { creditsPath = CREDITS_SEARCH_PATH; } else { creditsPath = Glib::build_filename(exePath, CREDITS_SEARCH_PATH); } + if (Glib::path_is_absolute(LICENCE_SEARCH_PATH)) { licensePath = LICENCE_SEARCH_PATH; } else { licensePath = Glib::build_filename(exePath, LICENCE_SEARCH_PATH); } + #else argv0 = DATA_SEARCH_PATH; creditsPath = CREDITS_SEARCH_PATH; licensePath = LICENCE_SEARCH_PATH; #endif - - mainThread = Glib::Thread::self(); - if (!Options::load ()) { - Gtk::Main m(&argc, &argv); - Gtk::MessageDialog msgd ("Fatal error!\nThe RT_SETTINGS and/or RT_PATH environment variables are set, but use a relative path. The path must be absolute!", true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - return -2; - } + mainThread = Glib::Thread::self(); - extProgStore->init(); - SoundManager::init(); + if (!Options::load ()) { + Gtk::Main m(&argc, &argv); + Gtk::MessageDialog msgd ("Fatal error!\nThe RT_SETTINGS and/or RT_PATH environment variables are set, but use a relative path. The path must be absolute!", true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + return -2; + } + + extProgStore->init(); + SoundManager::init(); #ifdef WIN32 - bool consoleOpened = false; + 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 ))) { - bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); - bool stderrRedirectedtoFile = (GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == 0x0001); - // no console, if stdout and stderr both are redirected to file - if( !(stdoutRedirectedtoFile && stderrRedirectedtoFile)) { - // check if parameter -w was passed. - // We have to do that in this step, because it controls whether to open a console to show the output of following steps - bool Console = true; - for(int i=1;i 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 ))) { + bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); + bool stderrRedirectedtoFile = (GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == 0x0001); - consoleOpened = true; + // no console, if stdout and stderr both are redirected to file + if( !(stdoutRedirectedtoFile && stderrRedirectedtoFile)) { + // check if parameter -w was passed. + // We have to do that in this step, because it controls whether to open a console to show the output of following steps + bool Console = true; - // printing RT's version in every case, particularly useful for the 'verbose' mode, but also for the batch processing - std::cout << "RawTherapee, version " << VERSION << std::endl; - std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; - } - } - } + for(int i = 1; i < argc; i++) + if(!strcmp(argv[i], "-w")) { + Console = false; + break; + } + + if(Console) { + AllocConsole(); + AttachConsole( GetCurrentProcessId() ) ; + // Don't allow CTRL-C in console to terminate RT + SetConsoleCtrlHandler( NULL, true ); + // Set title of console + char consoletitle[128]; + sprintf(consoletitle, "RawTherapee %s Console", VERSION); + SetConsoleTitle(consoletitle); + // increase size of screen buffer + COORD c; + c.X = 200; + c.Y = 1000; + SetConsoleScreenBufferSize( GetStdHandle( STD_OUTPUT_HANDLE ), c ); + // Disable console-Cursor + CONSOLE_CURSOR_INFO cursorInfo; + cursorInfo.dwSize = 100; + cursorInfo.bVisible = false; + SetConsoleCursorInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &cursorInfo ); + + if(!stdoutRedirectedtoFile) { + freopen( "CON", "w", stdout ) ; + } + + if(!stderrRedirectedtoFile) { + freopen( "CON", "w", stderr ) ; + } + + freopen( "CON", "r", stdin ) ; + + consoleOpened = true; + + // printing RT's version in every case, particularly useful for the 'verbose' mode, but also for the batch processing + std::cout << "RawTherapee, version " << VERSION << std::endl; + std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; + } + } + } + + int ret = processLineParams( argc, argv); + + if( ret <= 0 ) { + if(consoleOpened) { + printf("Press any key to exit RawTherapee\n"); + FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); + getch(); + } + + return ret; + } + } - int ret = processLineParams( argc, argv); - if( ret <= 0 ) { - if(consoleOpened) { - printf("Press any key to exit RawTherapee\n"); - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - getch(); - } - return ret; - } - } #else - if (argc>1 || options.rtSettings.verbose){ - // printing RT's version in all case, particularly useful for the 'verbose' mode, but also for the batch processing - std::cout << "RawTherapee, version " << VERSION << std::endl; - std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; - if (argc>1){ - int ret = processLineParams( argc, argv); - if( ret <= 0 ) - return ret; - } - } + + if (argc > 1 || options.rtSettings.verbose) { + // printing RT's version in all case, particularly useful for the 'verbose' mode, but also for the batch processing + std::cout << "RawTherapee, version " << VERSION << std::endl; + std::cout << "WARNING: closing this window will close RawTherapee!" << std::endl << std::endl; + + if (argc > 1) { + int ret = processLineParams( argc, argv); + + if( ret <= 0 ) { + return ret; + } + } + } + #endif - if( !options.rtSettings.verbose ) - TIFFSetWarningHandler(NULL); // avoid annoying message boxes + if( !options.rtSettings.verbose ) { + TIFFSetWarningHandler(NULL); // avoid annoying message boxes + } #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); + + // 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); + } + #endif - simpleEditor=false; - if( !argv1.empty() ) - if( safe_file_test(argv1, Glib::FILE_TEST_EXISTS) && !safe_file_test(argv1, Glib::FILE_TEST_IS_DIR)) - simpleEditor = true; + simpleEditor = false; - if (!options.useSystemTheme) - { - std::vector rcfiles; - rcfiles.push_back (argv0+"/themes/"+options.theme+".gtkrc"); - if (options.slimUI) - rcfiles.push_back (argv0+"/themes/slim"); - // Set the font face and size - Gtk::RC::parse_string (Glib::ustring::compose( - "style \"clearlooks-default\" { font_name = \"%1\" }", options.font)); - Gtk::RC::set_default_files (rcfiles); - } - Gtk::Main m(&argc, &argv); + if( !argv1.empty() ) + if( safe_file_test(argv1, Glib::FILE_TEST_EXISTS) && !safe_file_test(argv1, Glib::FILE_TEST_IS_DIR)) { + simpleEditor = true; + } - Glib::ustring icon_path = Glib::build_filename(argv0,"images"); - Glib::RefPtr defaultIconTheme = Gtk::IconTheme::get_default(); - defaultIconTheme->append_search_path(icon_path); + if (!options.useSystemTheme) { + std::vector rcfiles; + rcfiles.push_back (argv0 + "/themes/" + options.theme + ".gtkrc"); - RTImage::setPaths(options); - MyExpander::init(); // has to stay AFTER RTImage::setPaths + if (options.slimUI) { + rcfiles.push_back (argv0 + "/themes/slim"); + } + + // Set the font face and size + Gtk::RC::parse_string (Glib::ustring::compose( + "style \"clearlooks-default\" { font_name = \"%1\" }", options.font)); + Gtk::RC::set_default_files (rcfiles); + } + + Gtk::Main m(&argc, &argv); + + Glib::ustring icon_path = Glib::build_filename(argv0, "images"); + Glib::RefPtr defaultIconTheme = Gtk::IconTheme::get_default(); + defaultIconTheme->append_search_path(icon_path); + + RTImage::setPaths(options); + MyExpander::init(); // has to stay AFTER RTImage::setPaths #ifndef WIN32 - // For an unknown reason, gtkmm 2.22 don't know the gtk-button-images property, while it exists in the documentation... - // Anyway, the problem was Linux only - static Glib::RefPtr settings = Gtk::Settings::get_default(); - if (settings) - settings->property_gtk_button_images().set_value(true); - else - printf("Error: no default settings to update!\n"); + // For an unknown reason, gtkmm 2.22 don't know the gtk-button-images property, while it exists in the documentation... + // Anyway, the problem was Linux only + static Glib::RefPtr settings = Gtk::Settings::get_default(); + + if (settings) { + settings->property_gtk_button_images().set_value(true); + } else { + printf("Error: no default settings to update!\n"); + } + #endif - gdk_threads_enter (); - RTWindow *rtWindow = new class RTWindow(); + gdk_threads_enter (); + RTWindow *rtWindow = new class RTWindow(); - // alerting users if the default raw and image profiles are missing - if (options.is_defProfRawMissing()) { - Gtk::MessageDialog msgd (Glib::ustring::compose(M("OPTIONS_DEFRAW_MISSING"), options.defProfRaw), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - } - if (options.is_defProfImgMissing()) { - Gtk::MessageDialog msgd (Glib::ustring::compose(M("OPTIONS_DEFIMG_MISSING"), options.defProfImg), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - } + // alerting users if the default raw and image profiles are missing + if (options.is_defProfRawMissing()) { + Gtk::MessageDialog msgd (Glib::ustring::compose(M("OPTIONS_DEFRAW_MISSING"), options.defProfRaw), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + } - // opening the main window - m.run(*rtWindow); + if (options.is_defProfImgMissing()) { + Gtk::MessageDialog msgd (Glib::ustring::compose(M("OPTIONS_DEFIMG_MISSING"), options.defProfImg), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.run (); + } - gdk_threads_leave (); - delete rtWindow; - rtengine::cleanup(); + // opening the main window + m.run(*rtWindow); + + gdk_threads_leave (); + delete rtWindow; + rtengine::cleanup(); #ifdef WIN32 - if (consoleOpened) { - printf("Press any key to exit RawTherapee\n"); - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - getch(); - } + + if (consoleOpened) { + printf("Press any key to exit RawTherapee\n"); + FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); + getch(); + } + #endif - return 0; + return 0; } -void deleteProcParams(std::vector &pparams) { - for (unsigned int i=0; ideleteInstance(); - delete pparams[i]; - pparams[i] = NULL; - } - return; +void deleteProcParams(std::vector &pparams) +{ + for (unsigned int i = 0; i < pparams.size(); i++) { + pparams[i]->deleteInstance(); + delete pparams[i]; + pparams[i] = NULL; + } + + return; } int processLineParams( int argc, char **argv ) { - rtengine::procparams::PartialProfile *rawParams=NULL, *imgParams=NULL; - std::vector inputFiles; - Glib::ustring outputPath = ""; - std::vector processingParams; - bool outputDirectory=false; - bool overwriteFiles=false; - bool sideProcParams=false; - bool copyParamsFile=false; - bool skipIfNoSidecar=false; - bool useDefault=false; - unsigned int sideCarFilePos = 0; - int compression=92; - int subsampling=3; - int bits=-1; - std::string outputType = ""; - unsigned errors=0; - for( int iArg=1; iArgload ( fname ))) { - processingParams.push_back(currentParams); - } - else { - std::cerr << "Error: \""<< fname <<"\" not found" << std::endl; - deleteProcParams(processingParams); - return -3; - } - } - break; - case 'S': - skipIfNoSidecar=true; - case 's': // Processing params next to file (file extension appended) - sideProcParams = true; - sideCarFilePos = processingParams.size(); - break; - case 'd': - useDefault = true; - break; - case 'Y': - overwriteFiles =true; - break; - case 'j': - if (strlen(argv[iArg]) > 2 && argv[iArg][2] == 's') { - if (strlen(argv[iArg])==3) { - std::cerr << "Error: the -js switch requires a mandatory value!" << std::endl; - deleteProcParams(processingParams); - return -3; - } - // looking for the subsampling parameter - sscanf(&argv[iArg][3],"%d",&subsampling); - if (subsampling < 1 || subsampling > 3) { - std::cerr << "Error: the value accompanying the -js switch has to be in the [1-3] range!" << std::endl; - deleteProcParams(processingParams); - return -3; - } - } - else { - outputType = "jpg"; - sscanf(&argv[iArg][2],"%d",&compression); - if (compression < 0 || compression > 100) { - std::cerr << "Error: the value accompanying the -j switch has to be in the [0-100] range!" << std::endl; - deleteProcParams(processingParams); - return -3; - } - } - break; - case 'b': - sscanf(&argv[iArg][2],"%d",&bits); - if (bits != 8 && bits != 16) - { - std::cerr << "Error: specify -b8 for 8-bit or -b16 for 16-bit output." << std::endl; + rtengine::procparams::PartialProfile *rawParams = NULL, *imgParams = NULL; + std::vector inputFiles; + Glib::ustring outputPath = ""; + std::vector processingParams; + bool outputDirectory = false; + bool overwriteFiles = false; + bool sideProcParams = false; + bool copyParamsFile = false; + bool skipIfNoSidecar = false; + bool useDefault = false; + unsigned int sideCarFilePos = 0; + int compression = 92; + int subsampling = 3; + int bits = -1; + std::string outputType = ""; + unsigned errors = 0; + + for( int iArg = 1; iArg < argc; iArg++) { + if( argv[iArg][0] == '-' ) { + switch( argv[iArg][1] ) { + case 'O': + copyParamsFile = true; + + case 'o': // outputfile or dir + if( iArg + 1 < argc ) { + iArg++; + outputPath = safe_filename_to_utf8 (argv[iArg]); + + if( safe_file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { + outputDirectory = true; + } + } + + break; + + case 'p': // processing parameters for all inputs; all set procparams are required, so + + // 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] ); + + if (fname.at(0) == '-') { + std::cerr << "Error: filename missing next to the -p switch" << std::endl; deleteProcParams(processingParams); return -3; } - break; - case 't': - outputType = "tif"; - compression = ((argv[iArg][2]!='z')?0:1); - break; - case 'n': - outputType = "png"; - compression = -1; - break; - case 'c': // MUST be last option - while( iArg+1 names; - Glib::RefPtr dir = Gio::File::create_for_path ( argv[iArg] ); - safe_build_file_list (dir, names, argv[iArg] ); - 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] ); - } - } - }else{ - inputFiles.push_back( safe_filename_to_utf8 (argv[iArg]) ); - } - } - break; + + rtengine::procparams::PartialProfile* currentParams = new rtengine::procparams::PartialProfile(true); + + if (!(currentParams->load ( fname ))) { + processingParams.push_back(currentParams); + } else { + std::cerr << "Error: \"" << fname << "\" not found" << std::endl; + deleteProcParams(processingParams); + return -3; + } + } + + break; + + case 'S': + skipIfNoSidecar = true; + + case 's': // Processing params next to file (file extension appended) + sideProcParams = true; + sideCarFilePos = processingParams.size(); + break; + + case 'd': + useDefault = true; + break; + + case 'Y': + overwriteFiles = true; + break; + + case 'j': + if (strlen(argv[iArg]) > 2 && argv[iArg][2] == 's') { + if (strlen(argv[iArg]) == 3) { + std::cerr << "Error: the -js switch requires a mandatory value!" << std::endl; + deleteProcParams(processingParams); + return -3; + } + + // looking for the subsampling parameter + sscanf(&argv[iArg][3], "%d", &subsampling); + + if (subsampling < 1 || subsampling > 3) { + std::cerr << "Error: the value accompanying the -js switch has to be in the [1-3] range!" << std::endl; + deleteProcParams(processingParams); + return -3; + } + } else { + outputType = "jpg"; + sscanf(&argv[iArg][2], "%d", &compression); + + if (compression < 0 || compression > 100) { + std::cerr << "Error: the value accompanying the -j switch has to be in the [0-100] range!" << std::endl; + deleteProcParams(processingParams); + return -3; + } + } + + break; + + case 'b': + sscanf(&argv[iArg][2], "%d", &bits); + + if (bits != 8 && bits != 16) { + std::cerr << "Error: specify -b8 for 8-bit or -b16 for 16-bit output." << std::endl; + deleteProcParams(processingParams); + return -3; + } + + break; + + case 't': + outputType = "tif"; + compression = ((argv[iArg][2] != 'z') ? 0 : 1); + break; + + case 'n': + outputType = "png"; + compression = -1; + break; + + case 'c': // MUST be last option + 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; + 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] ); + + 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] ); + } + } + } else { + inputFiles.push_back( safe_filename_to_utf8 (argv[iArg]) ); + } + } + + break; #ifdef WIN32 - case 'w': // This case is handled outside this function - break; + + case 'w': // This case is handled outside this function + break; #endif - case 'h': - case '?': - default: - { - Glib::ustring pparamsExt = paramFileExtension.substr(1); - std::cout << " indicate parameters you can change." << std::endl; - std::cout << "[Square brackets] mean the parameter is not mandatory." << std::endl; - std::cout << "The pipe symbol | indicates a choice of one or the other." << std::endl; - std::cout << "The dash symbol - denotes a range of possible values from one to the other." << std::endl; - cout << std::endl; - std::cout << "Usage:" << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " Start File Browser inside directory." << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " Start Image Editor with file." << std::endl; - std::cout << " " << Glib::path_get_basename(argv[0]) << " -c | Convert files in batch with default parameters." << std::endl << std::endl; + + case 'h': + case '?': + default: { + Glib::ustring pparamsExt = paramFileExtension.substr(1); + std::cout << " indicate parameters you can change." << std::endl; + std::cout << "[Square brackets] mean the parameter is not mandatory." << std::endl; + std::cout << "The pipe symbol | indicates a choice of one or the other." << std::endl; + std::cout << "The dash symbol - denotes a range of possible values from one to the other." << std::endl; + cout << std::endl; + std::cout << "Usage:" << std::endl; + std::cout << " " << Glib::path_get_basename(argv[0]) << " Start File Browser inside directory." << std::endl; + std::cout << " " << Glib::path_get_basename(argv[0]) << " Start Image Editor with file." << std::endl; + std::cout << " " << Glib::path_get_basename(argv[0]) << " -c | Convert files in batch with default parameters." << std::endl << std::endl; #ifdef WIN32 - std::cout << " -w Do not open the Windows console" << std::endl; + std::cout << " -w Do not open the Windows console" << std::endl; #endif - std::cout << "Other options used with -c (-c must be the last option):" << std::endl; - std::cout << Glib::path_get_basename(argv[0]) << " [-o |-O ] [-s|-S] [-p ] [-d] [-j[1-100] [-js<1-3>]|[-b<8|16>] <[-t[z] | [-n]]] [-Y] -c " << std::endl; - std::cout << " -o | Select output file or directory." << std::endl; - std::cout << " -O | Select output file or directory and copy " << pparamsExt << " file into it." << std::endl; - std::cout << " -s Include the " << pparamsExt << " file next to the input file (with the same" << std::endl; - std::cout << " name) to build the image parameters," << std::endl; - std::cout << " e.g. for photo.raw there should be a photo.raw." << pparamsExt << " file in" << std::endl; - std::cout << " the same directory. If the file does not exist, internal" << std::endl; - std::cout << " default (neutral) values (not those in Default." << pparamsExt << ") will be" << std::endl; - std::cout << " used." << std::endl; - std::cout << " -S Like -s but skip if the " << pparamsExt << " file does not exist." << std::endl; - std::cout << " -p Specify " << pparamsExt << " file to be used for all conversions." << std::endl; - std::cout << " You can specify as many -p options as you like (see" << std::endl; - std::cout << " description below)." << std::endl; - std::cout << " -d Use the default raw or non-raw " << pparamsExt << " file as set in" << std::endl; - std::cout << " Preferences > Image Processing > Default Processing Profile" << std::endl; - std::cout << " -j[1-100] Specify output to be JPEG (on by default). Optionally add" << std::endl; - std::cout << " compression 1-100 (default value: 92)." << std::endl; - std::cout << " -js<1-3> Specify the JPEG subsampling parameter, where:" << std::endl; - std::cout << " 1 = Best compression: 2x2, 1x1, 1x1 (4:1:1) - default of the JPEG library" << std::endl; - std::cout << " 2 = Widely used normal ratio: 2x1, 1x1, 1x1 (4:2:2)" << std::endl; - std::cout << " 3 = Best quality: 1x1, 1x1, 1x1 (4:4:4)" << std::endl; - std::cout << " -b<8|16> Specify bit depth per channel (only applies to TIFF and PNG output)." << std::endl; - std::cout << " -t[z] Specify output to be TIFF (16-bit if -b8 is not set)." << std::endl; - std::cout << " Uncompressed by default, or ZIP compression with 'z'" << std::endl; - std::cout << " -n Specify output to be compressed PNG (16-bit if -b8 is not set)." << std::endl; - std::cout << " -Y Overwrite output if present." << std::endl<|-O ] [-s|-S] [-p ] [-d] [-j[1-100] [-js<1-3>]|[-b<8|16>] <[-t[z] | [-n]]] [-Y] -c " << std::endl; + std::cout << " -o | Select output file or directory." << std::endl; + std::cout << " -O | Select output file or directory and copy " << pparamsExt << " file into it." << std::endl; + std::cout << " -s Include the " << pparamsExt << " file next to the input file (with the same" << std::endl; + std::cout << " name) to build the image parameters," << std::endl; + std::cout << " e.g. for photo.raw there should be a photo.raw." << pparamsExt << " file in" << std::endl; + std::cout << " the same directory. If the file does not exist, internal" << std::endl; + std::cout << " default (neutral) values (not those in Default." << pparamsExt << ") will be" << std::endl; + std::cout << " used." << std::endl; + std::cout << " -S Like -s but skip if the " << pparamsExt << " file does not exist." << std::endl; + std::cout << " -p Specify " << pparamsExt << " file to be used for all conversions." << std::endl; + std::cout << " You can specify as many -p options as you like (see" << std::endl; + std::cout << " description below)." << std::endl; + std::cout << " -d Use the default raw or non-raw " << pparamsExt << " file as set in" << std::endl; + std::cout << " Preferences > Image Processing > Default Processing Profile" << std::endl; + std::cout << " -j[1-100] Specify output to be JPEG (on by default). Optionally add" << std::endl; + std::cout << " compression 1-100 (default value: 92)." << std::endl; + std::cout << " -js<1-3> Specify the JPEG subsampling parameter, where:" << std::endl; + std::cout << " 1 = Best compression: 2x2, 1x1, 1x1 (4:1:1) - default of the JPEG library" << std::endl; + std::cout << " 2 = Widely used normal ratio: 2x1, 1x1, 1x1 (4:2:2)" << std::endl; + std::cout << " 3 = Best quality: 1x1, 1x1, 1x1 (4:4:4)" << std::endl; + std::cout << " -b<8|16> Specify bit depth per channel (only applies to TIFF and PNG output)." << std::endl; + std::cout << " -t[z] Specify output to be TIFF (16-bit if -b8 is not set)." << std::endl; + std::cout << " Uncompressed by default, or ZIP compression with 'z'" << std::endl; + std::cout << " -n Specify output to be compressed PNG (16-bit if -b8 is not set)." << std::endl; + std::cout << " -Y Overwrite output if present." << std::endl << std::endl; + std::cout << "Your " << pparamsExt << " files can be incomplete, RawTherapee will set the values as follows:" << std::endl; + std::cout << " 1- A new profile is created using internal default (neutral) values" << std::endl; + std::cout << " (hard-coded into RawTherapee)," << std::endl; + std::cout << " 2- then overridden by those found in the default raw or non-raw " << pparamsExt << " file" << std::endl; + std::cout << " (if -d has been set)," << std::endl; + std::cout << " 3- then overridden by those found in the " << pparamsExt << " files provided by -p, each one" << std::endl; + std::cout << " overriding the previous values," << std::endl; + std::cout << " 4- then overridden by the sidecar file if -s is set and if the file exists;" << std::endl; + std::cout << " the time where the sidecar file is used depends on the position of the -s" << std::endl; + std::cout << " switch in the command line relative to the -p parameters," << std::endl; + std::cout << " e.g. -p first." << pparamsExt << " -p second." << pparamsExt << " -s -p fourth." << pparamsExt << std::endl; + return -1; + } + } + } else { + argv1 = safe_filename_to_utf8 ( argv[iArg] ); - if (useDefault) { - rawParams = new rtengine::procparams::PartialProfile(true, true); - Glib::ustring profPath = options.findProfilePath(options.defProfRaw); - if (options.is_defProfRawMissing() || profPath.empty() || rawParams->load(profPath==DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfRaw.substr(5) + paramFileExtension))) { - std::cerr << "Error: default raw processing profile not found" << std::endl; - rawParams->deleteInstance(); - delete rawParams; - deleteProcParams(processingParams); - return -3; - } - imgParams = new rtengine::procparams::PartialProfile(true); - profPath = options.findProfilePath(options.defProfImg); - if (options.is_defProfImgMissing() || profPath.empty() || imgParams->load(profPath==DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfImg.substr(5) + paramFileExtension))) { - std::cerr << "Error: default non-raw processing profile not found" << std::endl; - imgParams->deleteInstance(); - delete imgParams; - rawParams->deleteInstance(); - delete rawParams; - deleteProcParams(processingParams); - return -3; - } - } + if( outputDirectory ) { + options.savePathFolder = outputPath; + options.saveUsePathTemplate = false; + } else { + options.saveUsePathTemplate = true; - for( size_t iFile=0; iFile< inputFiles.size(); iFile++){ + if (options.savePathTemplate.empty()) + // If the save path template is empty, we use its default value + { + options.savePathTemplate = "%p1/converted/%f"; + } + } - // Has to be reinstanciated at each profile to have a ProcParams object with default values - rtengine::procparams::ProcParams currentParams; + if (outputType == "jpg") { + options.saveFormat.format = outputType; + options.saveFormat.jpegQuality = compression; + options.saveFormat.jpegSubSamp = subsampling; + } else if (outputType == "tif") { + options.saveFormat.format = outputType; + } else if (outputType == "png") { + options.saveFormat.format = outputType; + } - Glib::ustring inputFile = inputFiles[iFile]; - std::cout << "Processing: " << inputFile << std::endl; - - rtengine::InitialImage* ii=NULL; - rtengine::ProcessingJob* job =NULL; - int errorCode; - bool isRaw=false; - - Glib::ustring outputFile; - if( outputType.empty() ) - outputType = "jpg"; - if( outputPath.empty() ){ - Glib::ustring s = inputFile; - Glib::ustring::size_type ext= s.find_last_of('.'); - outputFile = s.substr(0,ext)+ "." + outputType; - }else if( outputDirectory ){ - Glib::ustring s = Glib::path_get_basename( inputFile ); - Glib::ustring::size_type ext= s.find_last_of('.'); - outputFile = outputPath + "/" + s.substr(0,ext) + "." + outputType; - }else{ - Glib::ustring s = outputPath; - Glib::ustring::size_type ext= s.find_last_of('.'); - outputFile = s.substr(0,ext) + "." + outputType; - } - if( inputFile == outputFile){ - std::cerr << "Cannot overwrite: " << inputFile << std::endl; - continue; - } - if( !overwriteFiles && safe_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; - } - - // Load the image - isRaw = true; - Glib::ustring ext = getExtension (inputFile); - if (ext.lowercase()=="jpg" || ext.lowercase()=="jpeg" || ext.lowercase()=="tif" || ext.lowercase()=="tiff" || ext.lowercase()=="png") - isRaw = false; - - ii = rtengine::InitialImage::load ( inputFile, isRaw, &errorCode, NULL ); - if (!ii) { - errors++; - std::cerr << "Error loading file: "<< inputFile << std::endl; - continue; - } - - if (useDefault) { - if (isRaw) { - std::cout << " Merging default raw processing profile" << std::endl; - rawParams->applyTo(¤tParams); - } - else { - std::cout << " Merging default non-raw processing profile" << std::endl; - imgParams->applyTo(¤tParams); - } - } - - bool sideCarFound = false; - unsigned int i=0; - // Iterate the procparams file list in order to build the final ProcParams - do { - if (sideProcParams && i==sideCarFilePos) { - // using the sidecar file - 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 )) - std::cerr << "Warning: sidecar file requested but not found for: "<< sideProcessingParams << std::endl; - else { - sideCarFound = true; - std::cout << " Merging sidecar procparams" << std::endl; - } - } - if( processingParams.size()>i ) { - std::cout << " Merging procparams #" << i << std::endl; - processingParams[i]->applyTo(¤tParams); - } - i++; - } while (i < processingParams.size()+(sideProcParams?1:0)); - - if( sideProcParams && !sideCarFound && skipIfNoSidecar ){ - delete ii; - errors++; - std::cerr << "Error: no sidecar procparams found for: "<< inputFile << std::endl; - continue; - } - - job = rtengine::ProcessingJob::create (ii, currentParams); - if( !job ){ - errors++; - std::cerr << "Error creating processing for: "<< inputFile << std::endl; - ii->decreaseRef(); - continue; - } - - // Process image - rtengine::IImage16* resultImage = rtengine::processImage (job, errorCode, NULL, options.tunnelMetaData); - if( !resultImage ){ - errors++; - std::cerr << "Error processing: "<< inputFile << std::endl; - rtengine::ProcessingJob::destroy( job ); - continue; + break; } - // save image to disk - if( outputType=="jpg" ) - errorCode = resultImage->saveAsJPEG( outputFile, compression, subsampling ); - else if( outputType=="tif" ) - errorCode = resultImage->saveAsTIFF( outputFile, bits, compression==0 ); - else if( outputType=="png" ) - errorCode = resultImage->saveAsPNG( outputFile,compression, bits ); - else - errorCode = resultImage->saveToFile (outputFile); + } - if(errorCode){ - errors++; - std::cerr << "Error saving to: "<< outputFile << std::endl; - }else{ - if( copyParamsFile ){ - Glib::ustring outputProcessingParams = outputFile + paramFileExtension; - currentParams.save( outputProcessingParams ); - } - } + if( !argv1.empty() ) { + return 1; + } - ii->decreaseRef(); - resultImage->free(); - } + if( inputFiles.empty() ) { + return 2; + } - if (imgParams) { imgParams->deleteInstance(); delete imgParams; } - if (rawParams) { rawParams->deleteInstance(); delete rawParams; } - deleteProcParams(processingParams); + if (useDefault) { + rawParams = new rtengine::procparams::PartialProfile(true, true); + Glib::ustring profPath = options.findProfilePath(options.defProfRaw); - return errors>0?-2:0; + if (options.is_defProfRawMissing() || profPath.empty() || rawParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfRaw.substr(5) + paramFileExtension))) { + std::cerr << "Error: default raw processing profile not found" << std::endl; + rawParams->deleteInstance(); + delete rawParams; + deleteProcParams(processingParams); + return -3; + } + + imgParams = new rtengine::procparams::PartialProfile(true); + profPath = options.findProfilePath(options.defProfImg); + + if (options.is_defProfImgMissing() || profPath.empty() || imgParams->load(profPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(profPath, options.defProfImg.substr(5) + paramFileExtension))) { + std::cerr << "Error: default non-raw processing profile not found" << std::endl; + imgParams->deleteInstance(); + delete imgParams; + rawParams->deleteInstance(); + delete rawParams; + deleteProcParams(processingParams); + return -3; + } + } + + for( size_t iFile = 0; iFile < inputFiles.size(); iFile++) { + + // Has to be reinstanciated at each profile to have a ProcParams object with default values + rtengine::procparams::ProcParams currentParams; + + Glib::ustring inputFile = inputFiles[iFile]; + std::cout << "Processing: " << inputFile << std::endl; + + rtengine::InitialImage* ii = NULL; + rtengine::ProcessingJob* job = NULL; + int errorCode; + bool isRaw = false; + + Glib::ustring outputFile; + + if( outputType.empty() ) { + outputType = "jpg"; + } + + if( outputPath.empty() ) { + Glib::ustring s = inputFile; + Glib::ustring::size_type ext = s.find_last_of('.'); + outputFile = s.substr(0, ext) + "." + outputType; + } else if( outputDirectory ) { + Glib::ustring s = Glib::path_get_basename( inputFile ); + Glib::ustring::size_type ext = s.find_last_of('.'); + outputFile = outputPath + "/" + s.substr(0, ext) + "." + outputType; + } else { + Glib::ustring s = outputPath; + Glib::ustring::size_type ext = s.find_last_of('.'); + outputFile = s.substr(0, ext) + "." + outputType; + } + + if( inputFile == outputFile) { + std::cerr << "Cannot overwrite: " << inputFile << std::endl; + continue; + } + + if( !overwriteFiles && safe_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; + } + + // Load the image + isRaw = true; + Glib::ustring ext = getExtension (inputFile); + + if (ext.lowercase() == "jpg" || ext.lowercase() == "jpeg" || ext.lowercase() == "tif" || ext.lowercase() == "tiff" || ext.lowercase() == "png") { + isRaw = false; + } + + ii = rtengine::InitialImage::load ( inputFile, isRaw, &errorCode, NULL ); + + if (!ii) { + errors++; + std::cerr << "Error loading file: " << inputFile << std::endl; + continue; + } + + if (useDefault) { + if (isRaw) { + std::cout << " Merging default raw processing profile" << std::endl; + rawParams->applyTo(¤tParams); + } else { + std::cout << " Merging default non-raw processing profile" << std::endl; + imgParams->applyTo(¤tParams); + } + } + + bool sideCarFound = false; + unsigned int i = 0; + + // Iterate the procparams file list in order to build the final ProcParams + do { + if (sideProcParams && i == sideCarFilePos) { + // using the sidecar file + 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 )) { + std::cerr << "Warning: sidecar file requested but not found for: " << sideProcessingParams << std::endl; + } else { + sideCarFound = true; + std::cout << " Merging sidecar procparams" << std::endl; + } + } + + if( processingParams.size() > i ) { + std::cout << " Merging procparams #" << i << std::endl; + processingParams[i]->applyTo(¤tParams); + } + + i++; + } while (i < processingParams.size() + (sideProcParams ? 1 : 0)); + + if( sideProcParams && !sideCarFound && skipIfNoSidecar ) { + delete ii; + errors++; + std::cerr << "Error: no sidecar procparams found for: " << inputFile << std::endl; + continue; + } + + job = rtengine::ProcessingJob::create (ii, currentParams); + + if( !job ) { + errors++; + std::cerr << "Error creating processing for: " << inputFile << std::endl; + ii->decreaseRef(); + continue; + } + + // Process image + rtengine::IImage16* resultImage = rtengine::processImage (job, errorCode, NULL, options.tunnelMetaData); + + if( !resultImage ) { + errors++; + std::cerr << "Error processing: " << inputFile << std::endl; + rtengine::ProcessingJob::destroy( job ); + continue; + } + + // save image to disk + if( outputType == "jpg" ) { + errorCode = resultImage->saveAsJPEG( outputFile, compression, subsampling ); + } else if( outputType == "tif" ) { + errorCode = resultImage->saveAsTIFF( outputFile, bits, compression == 0 ); + } else if( outputType == "png" ) { + errorCode = resultImage->saveAsPNG( outputFile, compression, bits ); + } else { + errorCode = resultImage->saveToFile (outputFile); + } + + if(errorCode) { + errors++; + std::cerr << "Error saving to: " << outputFile << std::endl; + } else { + if( copyParamsFile ) { + Glib::ustring outputProcessingParams = outputFile + paramFileExtension; + currentParams.save( outputProcessingParams ); + } + } + + ii->decreaseRef(); + resultImage->free(); + } + + if (imgParams) { + imgParams->deleteInstance(); + delete imgParams; + } + + if (rawParams) { + rawParams->deleteInstance(); + delete rawParams; + } + + deleteProcParams(processingParams); + + return errors > 0 ? -2 : 0; } diff --git a/rtgui/mountselectionlistener.h b/rtgui/mountselectionlistener.h index 169d57108..73728dfd9 100644 --- a/rtgui/mountselectionlistener.h +++ b/rtgui/mountselectionlistener.h @@ -7,7 +7,7 @@ * 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 @@ -21,10 +21,11 @@ #include -class MountSelectionListener { +class MountSelectionListener +{ - public: - virtual void mountSelectionChanged (Glib::ustring mountRoot) {} +public: + virtual void mountSelectionChanged (Glib::ustring mountRoot) {} }; #endif diff --git a/rtgui/multilangmgr.cc b/rtgui/multilangmgr.cc index 0a9122a2d..37dcb5e3c 100644 --- a/rtgui/multilangmgr.cc +++ b/rtgui/multilangmgr.cc @@ -7,7 +7,7 @@ * 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 @@ -38,75 +38,95 @@ MultiLangMgr langMgr; -Glib::ustring M (std::string key) { return langMgr.getStr (key); } +Glib::ustring M (std::string key) +{ + return langMgr.getStr (key); +} // fb is fallback manager if the first could not be loaded -bool MultiLangMgr::load (Glib::ustring fname, MultiLangMgr* fb) { +bool MultiLangMgr::load (Glib::ustring fname, MultiLangMgr* fb) +{ FILE *f = safe_g_fopen (fname, "rt"); fallBack = fb; - if (f==NULL) + if (f == NULL) { return false; - + } + transTable.clear (); char* buffer = new char[2048]; - + while (fgets (buffer, 2048, f) != 0) { // find separator int seppos = 0; - while (buffer[seppos]!=0 && buffer[seppos]!=';') + + while (buffer[seppos] != 0 && buffer[seppos] != ';') { seppos++; + } + // no separator found - if (buffer[seppos]==0) + if (buffer[seppos] == 0) { continue; + } + // cut the last \n and \r characters - int endpos = strlen(buffer)-1; - while (buffer[endpos]=='\n' || buffer[endpos]=='\r') + int endpos = strlen(buffer) - 1; + + while (buffer[endpos] == '\n' || buffer[endpos] == '\r') { endpos--; - buffer[endpos+1] = 0; + } + + buffer[endpos + 1] = 0; // replace "\n" to '\n' int j = 0; - for (int i=0; i::iterator r; - for (r=transTable.begin (); r!=transTable.end(); r++) + + for (r = transTable.begin (); r != transTable.end(); r++) { fprintf (f, "%s;%s\n", r->first.c_str(), safe_locale_from_utf8(r->second).c_str()); + } fclose (f); return true; } - -bool MultiLangMgr::isOSLanguageDetectSupported() { + +bool MultiLangMgr::isOSLanguageDetectSupported() +{ #ifdef WIN32 - #ifdef __MINGW64_VERSION_MAJOR +#ifdef __MINGW64_VERSION_MAJOR // Only on Vista or above - return LOBYTE(LOWORD(GetVersion()))>=6; + return LOBYTE(LOWORD(GetVersion())) >= 6; #else return false; #endif @@ -119,7 +139,8 @@ bool MultiLangMgr::isOSLanguageDetectSupported() { // returns Language name mapped from the currently selected OS language -Glib::ustring MultiLangMgr::getOSUserLanguage() { +Glib::ustring MultiLangMgr::getOSUserLanguage() +{ Glib::ustring langName = Glib::ustring("default"); if (isOSLanguageDetectSupported()) { @@ -128,75 +149,158 @@ Glib::ustring MultiLangMgr::getOSUserLanguage() { // When using old versions of MINGW this is not defined #ifdef __MINGW64_VERSION_MAJOR WCHAR langRFCU[64] = {0}; - if (GetUserDefaultLocaleName(langRFCU,64)!=0 && lstrlenW(langRFCU)>=2) { + + if (GetUserDefaultLocaleName(langRFCU, 64) != 0 && lstrlenW(langRFCU) >= 2) { // convert UNICODE16 to GTK char langRFC[64]; - WideCharToMultiByte(CP_UTF8,0,langRFCU,-1,langRFC,64,0,0); - Glib::ustring localRFC=Glib::ustring(langRFC); + WideCharToMultiByte(CP_UTF8, 0, langRFCU, -1, langRFC, 64, 0, 0); + Glib::ustring localRFC = Glib::ustring(langRFC); - langName=TranslateRFC2Language(localRFC); + langName = TranslateRFC2Language(localRFC); } + #endif #elif defined(__linux__) || defined(__APPLE__) char *tmplocale; - tmplocale = setlocale(LC_CTYPE,""); + tmplocale = setlocale(LC_CTYPE, ""); setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - if(tmplocale) + + if(tmplocale) { langName = TranslateRFC2Language(tmplocale); + } + #endif } + return langName; } // Translates RFC standard language code to file name, e.g. "de-DE" to "Deutsch" -Glib::ustring MultiLangMgr::TranslateRFC2Language(Glib::ustring rfcName) { - if (rfcName.length()<2) return Glib::ustring("default"); +Glib::ustring MultiLangMgr::TranslateRFC2Language(Glib::ustring rfcName) +{ + if (rfcName.length() < 2) { + return Glib::ustring("default"); + } - Glib::ustring major=rfcName.substr(0,2).lowercase(); + Glib::ustring major = rfcName.substr(0, 2).lowercase(); Glib::ustring minor; - if (rfcName.length()>=5) { - minor=rfcName.substr(3,2).uppercase(); + + if (rfcName.length() >= 5) { + minor = rfcName.substr(3, 2).uppercase(); } //printf("Lang: %s - %s\n",major.c_str(),minor.c_str()); - if (major=="ca") return "Catala"; - if (major=="zh") - return (minor=="CN" || minor=="SG") ? "Chinese (Simplified)" : "Chinese (Traditional)"; - if (major=="cs") return "Czech"; - if (major=="da") return "Dansk"; - if (major=="de") return "Deutsch"; - if (major=="es") return "Espanol"; - if (major=="eu") return "Euskara"; - if (major=="fr") return "Francais"; - if (major=="el") return "Greek"; - if (major=="he") return "Hebrew"; - if (major=="it") return "Italiano"; - if (major=="ja") return "Japanese"; - if (major=="lv") return "Latvian"; - if (major=="hu") return "Magyar"; - if (major=="nl") return "Nederlands"; - if (major=="nn" || major=="nb") return "Norsk BM"; - if (major=="pl") return "Polish"; - if (major=="pt") return "Portugues (Brasil)"; - if (major=="ru") return "Russian"; - if (major=="sr") return "Serbian (Cyrilic Characters)"; - if (major=="sk") return "Slovak"; - if (major=="fi") return "Suomi"; - if (major=="sv") return "Swedish"; - if (major=="tr") return "Turkish"; + if (major == "ca") { + return "Catala"; + } + + if (major == "zh") { + return (minor == "CN" || minor == "SG") ? "Chinese (Simplified)" : "Chinese (Traditional)"; + } + + if (major == "cs") { + return "Czech"; + } + + if (major == "da") { + return "Dansk"; + } + + if (major == "de") { + return "Deutsch"; + } + + if (major == "es") { + return "Espanol"; + } + + if (major == "eu") { + return "Euskara"; + } + + if (major == "fr") { + return "Francais"; + } + + if (major == "el") { + return "Greek"; + } + + if (major == "he") { + return "Hebrew"; + } + + if (major == "it") { + return "Italiano"; + } + + if (major == "ja") { + return "Japanese"; + } + + if (major == "lv") { + return "Latvian"; + } + + if (major == "hu") { + return "Magyar"; + } + + if (major == "nl") { + return "Nederlands"; + } + + if (major == "nn" || major == "nb") { + return "Norsk BM"; + } + + if (major == "pl") { + return "Polish"; + } + + if (major == "pt") { + return "Portugues (Brasil)"; + } + + if (major == "ru") { + return "Russian"; + } + + if (major == "sr") { + return "Serbian (Cyrilic Characters)"; + } + + if (major == "sk") { + return "Slovak"; + } + + if (major == "fi") { + return "Suomi"; + } + + if (major == "sv") { + return "Swedish"; + } + + if (major == "tr") { + return "Turkish"; + } // Don't split en-US, en-GB, etc. since only default english is constantly updated return "default"; } -Glib::ustring MultiLangMgr::getStr (std::string key) { +Glib::ustring MultiLangMgr::getStr (std::string key) +{ std::map::iterator r = transTable.find (key); - if (r!=transTable.end()) + + if (r != transTable.end()) { return r->second; - else if (fallBack) + } else if (fallBack) { return fallBack->getStr (key); - else + } else { return key; + } } diff --git a/rtgui/multilangmgr.h b/rtgui/multilangmgr.h index 7f14e0fac..e8b1727ce 100644 --- a/rtgui/multilangmgr.h +++ b/rtgui/multilangmgr.h @@ -7,7 +7,7 @@ * 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 @@ -23,17 +23,24 @@ #include #include -class MultiLangMgr { +class MultiLangMgr +{ std::map transTable; MultiLangMgr* fallBack; - + Glib::ustring TranslateRFC2Language(Glib::ustring rfcName); - public: +public: MultiLangMgr () : fallBack (NULL) {} - MultiLangMgr (Glib::ustring fname) : fallBack (NULL) { load (fname); } - MultiLangMgr (Glib::ustring fname, MultiLangMgr* fb) : fallBack (NULL) { load (fname, fb); } + MultiLangMgr (Glib::ustring fname) : fallBack (NULL) + { + load (fname); + } + MultiLangMgr (Glib::ustring fname, MultiLangMgr* fb) : fallBack (NULL) + { + load (fname, fb); + } bool load (Glib::ustring fname, MultiLangMgr* fb = NULL); bool save (Glib::ustring fname); diff --git a/rtgui/mycurve.cc b/rtgui/mycurve.cc index 21eb4df80..55e566ada 100644 --- a/rtgui/mycurve.cc +++ b/rtgui/mycurve.cc @@ -7,7 +7,7 @@ * 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 @@ -21,7 +21,8 @@ #include #include -MyCurve::MyCurve () : pipetteR(-1.f), pipetteG(-1.f), pipetteB(-1.f), pipetteVal(-1.f), listener(NULL) { +MyCurve::MyCurve () : pipetteR(-1.f), pipetteG(-1.f), pipetteB(-1.f), pipetteVal(-1.f), listener(NULL) +{ cursor_type = CSArrow; graphX = get_allocation().get_width() - RADIUS * 2; @@ -42,9 +43,9 @@ MyCurve::MyCurve () : pipetteR(-1.f), pipetteG(-1.f), pipetteB(-1.f), pipetteVal #if defined (__APPLE__) // Workaround: disabling POINTER_MOTION_HINT_MASK as for gtk 2.24.22 the get_pointer() function is buggy for quartz and modifier mask is not updated correctly. // This workaround should be removed when bug is fixed in GTK2 or when migrating to GTK3 - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK); #else - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK); #endif mcih = new MyCurveIdleHelper; @@ -53,91 +54,118 @@ MyCurve::MyCurve () : pipetteR(-1.f), pipetteG(-1.f), pipetteB(-1.f), pipetteVal mcih->pending = 0; } -MyCurve::~MyCurve () { +MyCurve::~MyCurve () +{ - if (mcih->pending) + if (mcih->pending) { mcih->destroyed = true; - else + } else { delete mcih; + } } -int MyCurve::calcDimensions () { - int newRequestedW, newRequestedH; +int MyCurve::calcDimensions () +{ + int newRequestedW, newRequestedH; - newRequestedW = newRequestedH = get_allocation().get_width(); - if (leftBar && !bottomBar) - newRequestedH -= getBarWidth() + CBAR_MARGIN - RADIUS; - if (!leftBar && bottomBar) - newRequestedH += getBarWidth() + CBAR_MARGIN - RADIUS; + newRequestedW = newRequestedH = get_allocation().get_width(); - graphW = newRequestedW - RADIUS - (leftBar ? (getBarWidth()+CBAR_MARGIN) : RADIUS); - graphH = newRequestedH - RADIUS - (bottomBar ? (getBarWidth()+CBAR_MARGIN) : RADIUS); - graphX = newRequestedW - RADIUS - graphW; - graphY = RADIUS + graphH; + if (leftBar && !bottomBar) { + newRequestedH -= getBarWidth() + CBAR_MARGIN - RADIUS; + } - return newRequestedH; + if (!leftBar && bottomBar) { + newRequestedH += getBarWidth() + CBAR_MARGIN - RADIUS; + } + + graphW = newRequestedW - RADIUS - (leftBar ? (getBarWidth() + CBAR_MARGIN) : RADIUS); + graphH = newRequestedH - RADIUS - (bottomBar ? (getBarWidth() + CBAR_MARGIN) : RADIUS); + graphX = newRequestedW - RADIUS - graphW; + graphY = RADIUS + graphH; + + return newRequestedH; } -void MyCurve::setColoredBar (ColoredBar *left, ColoredBar *bottom) { - leftBar = left; - bottomBar = bottom; +void MyCurve::setColoredBar (ColoredBar *left, ColoredBar *bottom) +{ + leftBar = left; + bottomBar = bottom; } -void MyCurve::notifyListener () { +void MyCurve::notifyListener () +{ - if (listener) + if (listener) { listener->curveChanged (); + } } -bool MyCurve::snapCoordinateX(double testedVal, double realVal) { +bool MyCurve::snapCoordinateX(double testedVal, double realVal) +{ - double dist = realVal - testedVal; + double dist = realVal - testedVal; - if (dist < 0.) dist = -dist; - if (dist < snapToMinDistX) { - snapToMinDistX = dist; - snapToValX = testedVal; - return true; - } - return false; + if (dist < 0.) { + dist = -dist; + } + + if (dist < snapToMinDistX) { + snapToMinDistX = dist; + snapToValX = testedVal; + return true; + } + + return false; } -bool MyCurve::snapCoordinateY(double testedVal, double realVal) { +bool MyCurve::snapCoordinateY(double testedVal, double realVal) +{ - double dist = realVal - testedVal; + double dist = realVal - testedVal; - if (dist < 0.) dist = -dist; - if (dist < snapToMinDistY) { - snapToMinDistY = dist; - snapToValY = testedVal; - return true; - } - return false; + if (dist < 0.) { + dist = -dist; + } + + if (dist < snapToMinDistY) { + snapToMinDistY = dist; + snapToValY = testedVal; + return true; + } + + return false; } -float MyCurve::getVal(LUTf &curve, int x) { - if ((graphW-2) == curve.getSize()) { - return curve[x]; - } - else { - return curve.getVal01(float(x)/(graphW-3)); - } +float MyCurve::getVal(LUTf &curve, int x) +{ + if ((graphW - 2) == curve.getSize()) { + return curve[x]; + } else { + return curve.getVal01(float(x) / (graphW - 3)); + } } -void MyCurve::on_style_changed (const Glib::RefPtr& style) { - setDirty(true); +void MyCurve::on_style_changed (const Glib::RefPtr& style) +{ + setDirty(true); queue_draw (); } -void MyCurve::refresh() { - if (leftBar != NULL) - leftBar->setDirty(true); - if (bottomBar != NULL) - bottomBar->setDirty(true); +void MyCurve::refresh() +{ + if (leftBar != NULL) { + leftBar->setDirty(true); + } - setDirty(true); + if (bottomBar != NULL) { + bottomBar->setDirty(true); + } - Glib::RefPtr win = get_window(); - if (win) - win->invalidate(true); + setDirty(true); + + Glib::RefPtr win = get_window(); + + if (win) { + win->invalidate(true); + } } diff --git a/rtgui/mycurve.h b/rtgui/mycurve.h index 5a20ad190..96574e12a 100644 --- a/rtgui/mycurve.h +++ b/rtgui/mycurve.h @@ -7,7 +7,7 @@ * 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 @@ -29,121 +29,144 @@ #include "guiutils.h" #include "options.h" -#define RADIUS 3 /** radius of the control points */ -#define CBAR_WIDTH_STD 13 /** width of the colored bar (border included) for standard themes */ -#define CBAR_WIDTH_SLIM 10 /** width of the colored bar (border included) for slim themes */ -#define CBAR_MARGIN 2 /** spacing between the colored bar and the graph */ -#define SQUARE 2 /** half length of the square shape of the tangent handles */ -#define MIN_DISTANCE 5 /** min distance between control points */ -#define GRAPH_SIZE 200 /** size of the curve editor graphic */ +#define RADIUS 3 /** radius of the control points */ +#define CBAR_WIDTH_STD 13 /** width of the colored bar (border included) for standard themes */ +#define CBAR_WIDTH_SLIM 10 /** width of the colored bar (border included) for slim themes */ +#define CBAR_MARGIN 2 /** spacing between the colored bar and the graph */ +#define SQUARE 2 /** half length of the square shape of the tangent handles */ +#define MIN_DISTANCE 5 /** min distance between control points */ +#define GRAPH_SIZE 200 /** size of the curve editor graphic */ /** @brief Flat or Diagonal curve type For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget */ enum CurveType { - CT_Flat, - CT_Diagonal + CT_Flat, + CT_Diagonal }; /** @brief Tells the type of element that the points snaps to */ enum SnapToType { - ST_None, /// The point is not snapped - ST_Identity, /// Point snapped to the identity curve - ST_Neighbors /// Point snapped to the neighbor points + ST_None, /// The point is not snapped + ST_Identity, /// Point snapped to the identity curve + ST_Neighbors /// Point snapped to the neighbor points }; enum ResizeState { - RS_Pending = 1, /// Resize has to occurs - RS_Done = 2, /// Resize has been done - RS_Force = 4 /// Resize has to occurs even without CONFIGURE event + RS_Pending = 1, /// Resize has to occurs + RS_Done = 2, /// Resize has been done + RS_Force = 4 /// Resize has to occurs even without CONFIGURE event }; class MyCurveIdleHelper; class CurveEditor; -class MyCurve : public Gtk::DrawingArea, public BackBuffer, public ColorCaller, public CoordinateProvider { +class MyCurve : public Gtk::DrawingArea, public BackBuffer, public ColorCaller, public CoordinateProvider +{ - friend class MyCurveIdleHelper; + friend class MyCurveIdleHelper; - protected: - float pipetteR, pipetteG, pipetteB; /// RGB values from the PipetteDataProvider ; if a channel is set to -1.0f, it is not used - float pipetteVal; /// Effective pipette value, i.e. where to create the point; if a point already exist near this value, it'll be used +protected: + float pipetteR, pipetteG, pipetteB; /// RGB values from the PipetteDataProvider ; if a channel is set to -1.0f, it is not used + float pipetteVal; /// Effective pipette value, i.e. where to create the point; if a point already exist near this value, it'll be used - CurveListener* listener; - ColoredBar *leftBar; - ColoredBar *bottomBar; - CursorShape cursor_type; - int graphX, graphY, graphW, graphH; /// position and dimensions of the graphic area, excluding surrounding space for the points of for the colored bar - int prevGraphW, prevGraphH; /// previous inner width and height of the editor - Gdk::ModifierType mod_type; - int cursorX; /// X coordinate in the graph of the cursor - int cursorY; /// Y coordinate in the graph of the cursor - LUTf point; - LUTf upoint; - LUTf lpoint; - bool buttonPressed; - /** - * snapToElmt, which will be used for the Y axis only, must be interpreted like this: - * -100 : no element (default) - * -3 : maximum value - * -2 : identity value - * -1 : minimum value - * [0;1000[ : control point that it's snapped to - * >=1000 : moved control point which snaps to the line made by its previous and next point - */ - int snapToElmt; - bool snapTo; - double snapToMinDistX, snapToMinDistY; - double snapToValX, snapToValY; - MyCurveIdleHelper* mcih; - enum ResizeState sized; - bool curveIsDirty; + CurveListener* listener; + ColoredBar *leftBar; + ColoredBar *bottomBar; + CursorShape cursor_type; + int graphX, graphY, graphW, graphH; /// position and dimensions of the graphic area, excluding surrounding space for the points of for the colored bar + int prevGraphW, prevGraphH; /// previous inner width and height of the editor + Gdk::ModifierType mod_type; + int cursorX; /// X coordinate in the graph of the cursor + int cursorY; /// Y coordinate in the graph of the cursor + LUTf point; + LUTf upoint; + LUTf lpoint; + bool buttonPressed; + /** + * snapToElmt, which will be used for the Y axis only, must be interpreted like this: + * -100 : no element (default) + * -3 : maximum value + * -2 : identity value + * -1 : minimum value + * [0;1000[ : control point that it's snapped to + * >=1000 : moved control point which snaps to the line made by its previous and next point + */ + int snapToElmt; + bool snapTo; + double snapToMinDistX, snapToMinDistY; + double snapToValX, snapToValY; + MyCurveIdleHelper* mcih; + enum ResizeState sized; + bool curveIsDirty; - int edited_point; // > -1 when a point is being numerically edited - std::vector editedPos; + int edited_point; // > -1 when a point is being numerically edited + std::vector editedPos; - virtual std::vector get_vector (int veclen) = 0; - int getGraphMinSize() { return GRAPH_SIZE + RADIUS + 1; } - bool snapCoordinateX(double testedVal, double realVal); - bool snapCoordinateY(double testedVal, double realVal); - float getVal(LUTf &curve, int x); + virtual std::vector get_vector (int veclen) = 0; + int getGraphMinSize() + { + return GRAPH_SIZE + RADIUS + 1; + } + bool snapCoordinateX(double testedVal, double realVal); + bool snapCoordinateY(double testedVal, double realVal); + float getVal(LUTf &curve, int x); - // return value = new requested height - int calcDimensions (); + // return value = new requested height + int calcDimensions (); - public: - MyCurve (); - ~MyCurve (); +public: + MyCurve (); + ~MyCurve (); - void setCurveListener (CurveListener* cl) { listener = cl; } - void setColoredBar (ColoredBar *left, ColoredBar *bottom); - void notifyListener (); - void updateBackgroundHistogram (LUTu & hist) {return;} ; - void forceResize() { sized = RS_Force; } - void refresh(); - void setCurveDirty () { curveIsDirty = true; } - void on_style_changed (const Glib::RefPtr& style); - virtual std::vector getPoints () = 0; - virtual void setPoints (const std::vector& p) = 0; - virtual bool handleEvents (GdkEvent* event) = 0; - virtual void reset (const std::vector &resetCurve, double identityValue=0.5) = 0; + void setCurveListener (CurveListener* cl) + { + listener = cl; + } + void setColoredBar (ColoredBar *left, ColoredBar *bottom); + void notifyListener (); + void updateBackgroundHistogram (LUTu & hist) + { + return; + } ; + void forceResize() + { + sized = RS_Force; + } + void refresh(); + void setCurveDirty () + { + curveIsDirty = true; + } + void on_style_changed (const Glib::RefPtr& style); + virtual std::vector getPoints () = 0; + virtual void setPoints (const std::vector& p) = 0; + virtual bool handleEvents (GdkEvent* event) = 0; + virtual void reset (const std::vector &resetCurve, double identityValue = 0.5) = 0; - virtual void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) =0; - virtual void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) =0; - virtual void pipetteButton1Released(EditDataProvider *provider) =0; - virtual void pipetteDrag(EditDataProvider *provider, int modifierKey) =0; + virtual void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) = 0; + virtual void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) = 0; + virtual void pipetteButton1Released(EditDataProvider *provider) = 0; + virtual void pipetteDrag(EditDataProvider *provider, int modifierKey) = 0; - static int getBarWidth() { return options.slimUI ? CBAR_WIDTH_SLIM : CBAR_WIDTH_STD; } + static int getBarWidth() + { + return options.slimUI ? CBAR_WIDTH_SLIM : CBAR_WIDTH_STD; + } }; -class MyCurveIdleHelper { - public: - MyCurve* myCurve; - bool destroyed; - int pending; +class MyCurveIdleHelper +{ +public: + MyCurve* myCurve; + bool destroyed; + int pending; - void clearPixmap () { myCurve->setDirty(true); } + void clearPixmap () + { + myCurve->setDirty(true); + } }; #endif diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index 070459e7b..98eb6c283 100644 --- a/rtgui/mydiagonalcurve.cc +++ b/rtgui/mydiagonalcurve.cc @@ -7,7 +7,7 @@ * 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 @@ -21,7 +21,8 @@ #include #include -MyDiagonalCurve::MyDiagonalCurve () : activeParam(-1), bghistvalid(false) { +MyDiagonalCurve::MyDiagonalCurve () : activeParam(-1), bghistvalid(false) +{ graphW = get_allocation().get_width() - RADIUS * 2; graphH = get_allocation().get_height() - RADIUS * 2; @@ -46,136 +47,182 @@ MyDiagonalCurve::MyDiagonalCurve () : activeParam(-1), bghistvalid(false) { curve.y.push_back(1.); } -MyDiagonalCurve::~MyDiagonalCurve () { +MyDiagonalCurve::~MyDiagonalCurve () +{ delete [] bghist; } -std::vector MyDiagonalCurve::get_vector (int veclen) { +std::vector MyDiagonalCurve::get_vector (int veclen) +{ std::vector vector; vector.resize (veclen); if (curve.type != DCT_Parametric) { // count active points: - double prev =- 1.0; + double prev = - 1.0; int active = 0; int firstact = -1; + for (int i = 0; i < (int)curve.x.size(); ++i) if (curve.x.at(i) > prev) { - if (firstact < 0) - firstact = i; + if (firstact < 0) { + firstact = i; + } + prev = curve.x.at(i); ++active; } + // handle degenerate case: if (active < 2) { double ry; - if (active > 0) + + if (active > 0) { ry = curve.y.at(firstact); - else + } else { ry = 0.0; - if (ry < 0.0) ry = 0.0; - if (ry > 1.0) ry = 1.0; - for (int x = 0; x < veclen; ++x) + } + + if (ry < 0.0) { + ry = 0.0; + } + + if (ry > 1.0) { + ry = 1.0; + } + + for (int x = 0; x < veclen; ++x) { vector.at(x) = ry; + } + return vector; } } // calculate remaining points std::vector curveDescr = getPoints (); - rtengine::DiagonalCurve rtcurve(curveDescr, veclen*1.2); + rtengine::DiagonalCurve rtcurve(curveDescr, veclen * 1.2); std::vector t; t.resize (veclen); - for (int i = 0; i < veclen; i++) + + for (int i = 0; i < veclen; i++) { t[i] = (double) i / (veclen - 1.0); + } + rtcurve.getVal (t, vector); return vector; } -void MyDiagonalCurve::get_LUT (LUTf &lut) { +void MyDiagonalCurve::get_LUT (LUTf &lut) +{ int size = lut.getSize(); if (curve.type != DCT_Parametric) { // count active points: - double prev =- 1.0; + double prev = - 1.0; int active = 0; int firstact = -1; + for (int i = 0; i < (int)curve.x.size(); ++i) if (curve.x.at(i) > prev) { - if (firstact < 0) - firstact = i; + if (firstact < 0) { + firstact = i; + } + prev = curve.x.at(i); ++active; } + // handle degenerate case: if (active < 2) { double ry; - if (active > 0) + + if (active > 0) { ry = curve.y.at(firstact); - else + } else { ry = 0.0; - if (ry < 0.0) ry = 0.0; - if (ry > 1.0) ry = 1.0; - for (int x = 0; x < size; ++x) + } + + if (ry < 0.0) { + ry = 0.0; + } + + if (ry > 1.0) { + ry = 1.0; + } + + for (int x = 0; x < size; ++x) { lut[x] = ry; + } + return; } } // calculate remaining points std::vector curveDescr = getPoints (); - rtengine::DiagonalCurve rtcurve(curveDescr, lut.getUpperBound()*1.2); + rtengine::DiagonalCurve rtcurve(curveDescr, lut.getUpperBound() * 1.2); double t; double maxVal = double(lut.getUpperBound()); + for (int i = 0; i < size; i++) { t = double(i) / maxVal; lut[i] = rtcurve.getVal (t); } + return; } -void MyDiagonalCurve::interpolate () { +void MyDiagonalCurve::interpolate () +{ prevGraphW = graphW; prevGraphH = graphH; - int nbPoints = rtengine::max(graphW-2,201); + int nbPoints = rtengine::max(graphW - 2, 201); point(nbPoints); get_LUT (point); upoint.reset(); lpoint.reset (); - if (curve.type==DCT_Parametric && activeParam>0) { - double tmp = curve.x.at(activeParam-1); - if (activeParam>=4) { + if (curve.type == DCT_Parametric && activeParam > 0) { + double tmp = curve.x.at(activeParam - 1); + + if (activeParam >= 4) { upoint(nbPoints); lpoint(nbPoints); - curve.x.at(activeParam-1) = 100; + curve.x.at(activeParam - 1) = 100; get_LUT(upoint); - curve.x.at(activeParam-1) = -100; + curve.x.at(activeParam - 1) = -100; get_LUT (lpoint); - curve.x.at(activeParam-1) = tmp; + curve.x.at(activeParam - 1) = tmp; } } curveIsDirty = false; } -void MyDiagonalCurve::draw (int handle) { +void MyDiagonalCurve::draw (int handle) +{ if (!isDirty()) { return; } Glib::RefPtr win = get_window(); - if (!surfaceCreated() || !win) + + if (!surfaceCreated() || !win) { return; + } // re-calculate curve if dimensions changed int currPointSize = point.getUpperBound(); - if (curveIsDirty || /*prevGraphW != graphW || prevGraphH != graphH ||*/ (currPointSize==200 && (graphW-3>200)) || (currPointSize>200 && (graphW-2<=200 || graphW-3!=currPointSize))) + + if (curveIsDirty || /*prevGraphW != graphW || prevGraphH != graphH ||*/ (currPointSize == 200 && (graphW - 3 > 200)) || (currPointSize > 200 && (graphW - 2 <= 200 || graphW - 3 != currPointSize))) { interpolate (); + } + currPointSize = point.getUpperBound(); Gtk::StateType state = !is_sensitive() ? Gtk::STATE_INSENSITIVE : Gtk::STATE_NORMAL; @@ -194,25 +241,30 @@ void MyDiagonalCurve::draw (int handle) { if (bghistvalid) { // find highest bin unsigned int valMax = 0; - for (int i=0; i<256; i++) - if (bghist[i]>valMax) + + for (int i = 0; i < 256; i++) + if (bghist[i] > valMax) { valMax = bghist[i]; + } + // draw histogram cr->set_line_width (1.0); - double stepSize = (graphW-3) / 255.0; - cr->move_to ( double(graphX+1), double(graphY-1) ); + double stepSize = (graphW - 3) / 255.0; + cr->move_to ( double(graphX + 1), double(graphY - 1) ); c = style->get_fg (Gtk::STATE_INSENSITIVE); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - for (int i=0; i<256; i++) { - double val = double(bghist[i]) * double(graphH-2) / double(valMax); + + for (int i = 0; i < 256; i++) { + double val = double(bghist[i]) * double(graphH - 2) / double(valMax); /* if (val>graphH-2) val = graphH-2; */ //if (i>0) - cr->line_to (double(graphX)+1.5+double(i)*stepSize, double(graphY-1)-val); + cr->line_to (double(graphX) + 1.5 + double(i)*stepSize, double(graphY - 1) - val); } - cr->line_to (double(graphX)+1.5+255.*stepSize, double(graphY-1)); + + cr->line_to (double(graphX) + 1.5 + 255.*stepSize, double(graphY - 1)); cr->close_path(); cr->fill (); } @@ -222,26 +274,30 @@ void MyDiagonalCurve::draw (int handle) { c = style->get_dark (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); cr->set_antialias (Cairo::ANTIALIAS_NONE); + for (int i = 0; i <= 10; i++) { // horizontal lines - cr->move_to (double(graphX)+0.5 , double(graphY) - max(0.5, double(graphH*i/10) - 0.5)); - cr->rel_line_to (double(graphW-1) , 0.); + cr->move_to (double(graphX) + 0.5 , double(graphY) - max(0.5, double(graphH * i / 10) - 0.5)); + cr->rel_line_to (double(graphW - 1) , 0.); // vertical lines - cr->move_to (double(graphX) + max(0.5, double(graphW*i/10) - 0.5), double(graphY)); - cr->rel_line_to (0. , double(-graphH+1)); + cr->move_to (double(graphX) + max(0.5, double(graphW * i / 10) - 0.5), double(graphY)); + cr->rel_line_to (0. , double(-graphH + 1)); } + cr->stroke (); // draw f(x)=x line - if (snapToElmt == -2) + if (snapToElmt == -2) { cr->set_source_rgb (1.0, 0.0, 0.0); - else + } else { cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + } + std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); - cr->move_to (double(graphX)+1.5, double(graphY)-1.5); - cr->rel_line_to (double(graphW-3), double(-graphH+3)); + cr->move_to (double(graphX) + 1.5, double(graphY) - 1.5); + cr->rel_line_to (double(graphW - 3), double(-graphH + 3)); cr->stroke (); cr->unset_dash (); @@ -249,52 +305,70 @@ void MyDiagonalCurve::draw (int handle) { cr->set_line_width (1.0); // draw upper and lower bounds - float graphH_ = float(graphH-3); - float graphX_ = float(graphX)+1.5; - float graphY_ = float(graphY)-1.5; - if (curve.type==DCT_Parametric && activeParam>0 && lpoint.getUpperBound()>1 && upoint.getUpperBound()>1) { + float graphH_ = float(graphH - 3); + float graphX_ = float(graphX) + 1.5; + float graphY_ = float(graphY) - 1.5; + + if (curve.type == DCT_Parametric && activeParam > 0 && lpoint.getUpperBound() > 1 && upoint.getUpperBound() > 1) { cr->set_source_rgba (0.0, 0.0, 0.0, 0.15); - cr->move_to (graphX_, getVal(upoint, 0)*-graphH_+graphY_); - for (int i=1; iline_to (float(i)+graphX_, getVal(upoint, i)*-graphH_+graphY_); - for (int i=graphW-3; i>=0; --i) - cr->line_to (float(i)+graphX_, getVal(lpoint, i)*-graphH_+graphY_); + cr->move_to (graphX_, getVal(upoint, 0) * -graphH_ + graphY_); + + for (int i = 1; i < graphW - 2; ++i) { + cr->line_to (float(i) + graphX_, getVal(upoint, i) * -graphH_ + graphY_); + } + + for (int i = graphW - 3; i >= 0; --i) { + cr->line_to (float(i) + graphX_, getVal(lpoint, i) * -graphH_ + graphY_); + } + cr->fill (); } // draw the pipette values if (pipetteR > -1.f || pipetteG > -1.f || pipetteB > -1.f) { - int n=0; - if (pipetteR > -1.f) ++n; - if (pipetteG > -1.f) ++n; - if (pipetteB > -1.f) ++n; + int n = 0; + + if (pipetteR > -1.f) { + ++n; + } + + if (pipetteG > -1.f) { + ++n; + } + + if (pipetteB > -1.f) { + ++n; + } if (n > 1) { if (pipetteR > -1.f) { cr->set_source_rgba (1., 0., 0., 0.5); // WARNING: assuming that red values are stored in pipetteR, which might not be the case! - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteR, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteR, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); } + if (pipetteG > -1.f) { cr->set_source_rgba (0., 1., 0., 0.5); // WARNING: assuming that green values are stored in pipetteG, which might not be the case! - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteG, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteG, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); } + if (pipetteB > -1.f) { cr->set_source_rgba (0., 0., 1., 0.5); // WARNING: assuming that blue values are stored in pipetteB, which might not be the case! - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteB, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteB, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); } } + if (pipetteVal > -1.f) { cr->set_line_width (2.); c = style->get_fg (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteVal, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteVal, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); cr->set_line_width (1.); } @@ -303,7 +377,7 @@ void MyDiagonalCurve::draw (int handle) { c = style->get_fg (state); // draw the cage of the NURBS curve - if (curve.type==DCT_NURBS) { + if (curve.type == DCT_NURBS) { unsigned int nbPoints; std::valarray ch_ds (1); ch_ds[0] = 2; @@ -311,33 +385,40 @@ void MyDiagonalCurve::draw (int handle) { cr->set_line_width (0.75); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); std::vector points = getPoints(); - nbPoints = ((int)points.size()-1)/2; - for (unsigned int i = 1; i < nbPoints; i++) { - int pos = i*2+1; + nbPoints = ((int)points.size() - 1) / 2; - double x1 = double(graphX)+1.5 + double(graphW-3)*points[pos-2]; // project (curve.at(i), 0, 1, graphW); - double y1 = double(graphY)-1.5 - double(graphH-3)*points[pos-1]; // project (curve.y.at(i)i], 0, 1, graphH); - double x2 = double(graphX)+0.5 + double(graphW-3)*points[pos]; // project (curve.at(i), 0, 1, graphW); - double y2 = double(graphY)-1.5 - double(graphH-3)*points[pos+1]; // project (curve.y.at(i), 0, 1, graphH); + for (unsigned int i = 1; i < nbPoints; i++) { + int pos = i * 2 + 1; + + double x1 = double(graphX) + 1.5 + double(graphW - 3) * points[pos - 2]; // project (curve.at(i), 0, 1, graphW); + double y1 = double(graphY) - 1.5 - double(graphH - 3) * points[pos - 1]; // project (curve.y.at(i)i], 0, 1, graphH); + double x2 = double(graphX) + 0.5 + double(graphW - 3) * points[pos]; // project (curve.at(i), 0, 1, graphW); + double y2 = double(graphY) - 1.5 - double(graphH - 3) * points[pos + 1]; // project (curve.y.at(i), 0, 1, graphH); // set the color of the line when the point is snapped to the cage - if (curve.x.size() == nbPoints && snapToElmt >= 1000 && ((i == (snapToElmt-1000)) || (i == (snapToElmt-999)))) + if (curve.x.size() == nbPoints && snapToElmt >= 1000 && ((i == (snapToElmt - 1000)) || (i == (snapToElmt - 999)))) { cr->set_source_rgb (1.0, 0.0, 0.0); - else + } else { cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + } + cr->move_to (x1, y1); cr->line_to (x2, y2); cr->stroke (); } + cr->unset_dash (); cr->set_line_width (1.0); } // draw curve cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->move_to (graphX_, getVal(point, 0)*-graphH_+graphY_); - for (int i=1; iline_to (float(i)+graphX_, getVal(point, i)*-graphH_+graphY_); + cr->move_to (graphX_, getVal(point, 0) * -graphH_ + graphY_); + + for (int i = 1; i < graphW - 2; ++i) { + cr->line_to (float(i) + graphX_, getVal(point, i) * -graphH_ + graphY_); + } + cr->stroke (); // draw the left colored bar @@ -345,13 +426,13 @@ void MyDiagonalCurve::draw (int handle) { // first the background int bWidth = getBarWidth(); BackBuffer *bb = this; - leftBar->setDrawRectangle(win, 1, graphY-graphH+1, bWidth-2, graphH-2); + leftBar->setDrawRectangle(win, 1, graphY - graphH + 1, bWidth - 2, graphH - 2); leftBar->expose(bb); // now the border c = style->get_dark (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->rectangle(0.5, graphY-graphH+0.5, bWidth-1, graphH-1); + cr->rectangle(0.5, graphY - graphH + 0.5, bWidth - 1, graphH - 1); cr->stroke(); } @@ -360,814 +441,958 @@ void MyDiagonalCurve::draw (int handle) { // first the background int bWidth = getBarWidth(); BackBuffer *bb = this; - bottomBar->setDrawRectangle(win, graphX+1, graphY+CBAR_MARGIN+1, graphW-2, bWidth-2); + bottomBar->setDrawRectangle(win, graphX + 1, graphY + CBAR_MARGIN + 1, graphW - 2, bWidth - 2); bottomBar->expose(bb); // now the border c = style->get_dark (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->rectangle(graphX+0.5, graphY+CBAR_MARGIN+0.5, graphW-1, bWidth-1 ); + cr->rectangle(graphX + 0.5, graphY + CBAR_MARGIN + 0.5, graphW - 1, bWidth - 1 ); cr->stroke(); } // draw bullets - if (curve.type!=DCT_Parametric) { + if (curve.type != DCT_Parametric) { c = style->get_fg (state); + for (int i = 0; i < (int)curve.x.size(); ++i) { - if (curve.x.at(i) == -1) continue; + if (curve.x.at(i) == -1) { + continue; + } + if (snapToElmt >= 1000) { - int pt = snapToElmt-1000; - if (i >= (pt-1) && i <= (pt+1)) + int pt = snapToElmt - 1000; + + if (i >= (pt - 1) && i <= (pt + 1)) { cr->set_source_rgb(1.0, 0.0, 0.0); - else + } else { cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - else { - if (i == handle || i == snapToElmt || i == edited_point) + } + } else { + if (i == handle || i == snapToElmt || i == edited_point) { cr->set_source_rgb (1.0, 0.0, 0.0); - else + } else { cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + } } - double x = double(graphX+1) + double((graphW-2) * curve.x.at(i)); // project (curve.x.at(i), 0, 1, graphW); - double y = double(graphY-1) - double((graphH-2) * curve.y.at(i)); // project (curve.y.at(i), 0, 1, graphH); + double x = double(graphX + 1) + double((graphW - 2) * curve.x.at(i)); // project (curve.x.at(i), 0, 1, graphW); + double y = double(graphY - 1) - double((graphH - 2) * curve.y.at(i)); // project (curve.y.at(i), 0, 1, graphH); - cr->arc (x, y, RADIUS+0.5, 0, 2*M_PI); + cr->arc (x, y, RADIUS + 0.5, 0, 2 * M_PI); cr->fill (); if (i == edited_point) { cr->set_line_width(2.); - cr->arc (x, y, RADIUS+3.5, 0, 2*M_PI); + cr->arc (x, y, RADIUS + 3.5, 0, 2 * M_PI); cr->stroke(); cr->set_line_width(1.); } } } + setDirty(false); queue_draw(); } /*void MyDiagonalCurve::graphSizeRequest (Gtk::Requisition* req) { - req->width = getGraphMinSize(); - // The real height request should take care of the presence of the vertical - // scroll bar and its width - req->height = sized ? getGraphMinSize() : get_allocation().get_width(); + req->width = getGraphMinSize(); + // The real height request should take care of the presence of the vertical + // scroll bar and its width + req->height = sized ? getGraphMinSize() : get_allocation().get_width(); }*/ -bool MyDiagonalCurve::handleEvents (GdkEvent* event) { +bool MyDiagonalCurve::handleEvents (GdkEvent* event) +{ - CursorShape new_type = cursor_type; + CursorShape new_type = cursor_type; - bool retval = false; - int num = (int)curve.x.size(); + bool retval = false; + int num = (int)curve.x.size(); - /* graphW and graphH are the size of the graph */ - calcDimensions(); + /* graphW and graphH are the size of the graph */ + calcDimensions(); - if ((graphW < 0) || (graphH < 0)) - return false; + if ((graphW < 0) || (graphH < 0)) { + return false; + } - double minDistanceX = double(MIN_DISTANCE) / double(graphW-1); - double minDistanceY = double(MIN_DISTANCE) / double(graphH-1); + double minDistanceX = double(MIN_DISTANCE) / double(graphW - 1); + double minDistanceY = double(MIN_DISTANCE) / double(graphH - 1); - switch (event->type) { - case Gdk::CONFIGURE: { - // Happen when the the window is resized - if (sized & (RS_Pending | RS_Force)) { - set_size_request(-1, calcDimensions()); - sized = RS_Done; - } - retval = true; - break; - } - case Gdk::EXPOSE: - { - Glib::RefPtr win = get_window(); - if (sized & (RS_Pending | RS_Force)) { - set_size_request(-1, calcDimensions()); - } - sized = RS_Pending; - // setDrawRectangle will allocate the backbuffer Surface - if (setDrawRectangle(win, 0, 0, get_allocation().get_width(), get_allocation().get_height())) { - setDirty(true); - if (prevGraphW > 200 || graphW > 200) - curveIsDirty = true; - } - draw (lit_point); - GdkRectangle *rectangle = &(event->expose.area); - copySurface(win, rectangle); + switch (event->type) { + case Gdk::CONFIGURE: { + // Happen when the the window is resized + if (sized & (RS_Pending | RS_Force)) { + set_size_request(-1, calcDimensions()); + sized = RS_Done; + } - retval = true; - break; - } + retval = true; + break; + } - case Gdk::BUTTON_PRESS: - snapToElmt = -100; - if (curve.type!=DCT_Parametric) { - if (edited_point == -1) { - if (event->button.button == 1) { - std::vector::iterator itx, ity; - buttonPressed = true; - add_modal_grab (); + case Gdk::EXPOSE: { + Glib::RefPtr win = get_window(); - // get the pointer position - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - findClosestPoint(); + if (sized & (RS_Pending | RS_Force)) { + set_size_request(-1, calcDimensions()); + } - new_type = CSMove; - if (distanceX > minDistanceX) { - if (mod_type & GDK_CONTROL_MASK) { - clampedY = point.getVal01(clampedX); - } - /* insert a new control point */ - if (num > 0) { - if (clampedX > curve.x.at(closest_point)) - ++closest_point; - } - itx = curve.x.begin(); - ity = curve.y.begin(); - for (int i=0; ibutton.button == 3) { - if (lit_point>-1 && grab_point==-1) { - if (!coordinateAdjuster->is_visible()) - coordinateAdjuster->showMe(this); + if (prevGraphW > 200 || graphW > 200) { + curveIsDirty = true; + } + } - edited_point = lit_point; - std::vector newBoundaries(2); - unsigned int size = curve.x.size(); - if (edited_point == 0) { newBoundaries.at(0).minVal = 0.; newBoundaries.at(0).maxVal = curve.x.at(1); } - else if (edited_point == size-1) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = 1.; } - else if (curve.x.size() > 2) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = curve.x.at(edited_point+1); } - newBoundaries.at(1).minVal = 0.; newBoundaries.at(1).maxVal = 1.; - editedPos.at(0) = curve.x.at(edited_point); - editedPos.at(1) = curve.y.at(edited_point); - coordinateAdjuster->setPos(editedPos); - coordinateAdjuster->startNumericalAdjustment(newBoundaries); - setDirty(true); - draw (lit_point); - new_type = CSArrow; - retval = true; - } - } - if (buttonPressed) retval = true; - } - else { // if (edited_point > -1) - if (event->button.button == 3) { - // do we edit another point? - if (edited_point>-1 && grab_point==-1) { - /* get the pointer position */ - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - findClosestPoint(); - if (cursorX>=0 && cursorX<=graphW && cursorY>=0 && cursorY<=graphH) { - if (distanceX <= minDistanceX) { - // the cursor is close to an existing point - lit_point = closest_point; - if (lit_point != edited_point) { - edited_point = lit_point; - curveIsDirty = true; - setDirty(true); - draw (lit_point); - std::vector newBoundaries; - newBoundaries.resize(2); - unsigned int size = curve.x.size(); - if (edited_point == 0) { newBoundaries.at(0).minVal = 0.; newBoundaries.at(0).maxVal = curve.x.at(1); } - else if (edited_point == size-1) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = 1.; } - else if (curve.x.size() > 2) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = curve.x.at(edited_point+1); } - newBoundaries.at(1).minVal = 0.; newBoundaries.at(1).maxVal = 1.; - retval = true; - editedPos.at(0) = curve.x.at(edited_point); - editedPos.at(1) = curve.y.at(edited_point); - coordinateAdjuster->switchAdjustedPoint(editedPos, newBoundaries); - } - } - else { - // the cursor is inside the graph but away from existing points - new_type = CSPlus; - curveIsDirty = true; - stopNumericalAdjustment(); - } - } - retval = true; - } - } - } - retval = true; - } - break; + draw (lit_point); + GdkRectangle *rectangle = &(event->expose.area); + copySurface(win, rectangle); - case Gdk::BUTTON_RELEASE: - snapToElmt = -100; - if (curve.type!=DCT_Parametric && edited_point==-1) { - if (buttonPressed && event->button.button == 1) { - std::vector::iterator itx, ity; - int src, dst; - buttonPressed = false; - /* get the pointer position */ - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - findClosestPoint(); + retval = true; + break; + } - remove_modal_grab (); - int previous_lit_point = lit_point; - /* delete inactive points: */ - itx = curve.x.begin(); - ity = curve.y.begin(); - for (src = dst = 0; src < num; ++src) - if (curve.x.at(src) >= 0.0) { - curve.x.at(dst) = curve.x.at(src); - curve.y.at(dst) = curve.y.at(src); - ++dst; - ++itx; - ++ity; - } - if (dst < src) { - curve.x.erase (itx, curve.x.end()); - curve.y.erase (ity, curve.y.end()); - if (curve.x.empty()) { - curve.x.push_back (0); - curve.y.push_back (0); - curveIsDirty = true; - setDirty(true); - draw (lit_point); - } - } - if (distanceX <= minDistanceX) { - new_type = CSMove; - lit_point = closest_point; - } - else { - new_type = CSPlus; - lit_point = -1; - } - if (lit_point != previous_lit_point) { - setDirty(true); - draw (lit_point); - } - grab_point = -1; - retval = true; - notifyListener (); - } - } - break; + case Gdk::BUTTON_PRESS: + snapToElmt = -100; - case Gdk::LEAVE_NOTIFY: - // Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case - // The cursor will have to LEAVE another time after the drag... - if (!buttonPressed) - if (grab_point == -1) { - new_type = CSArrow; - lit_point = -1; - pipetteR = pipetteG = pipetteB = -1.f; - setDirty(true); - draw (lit_point); - } - retval = true; - break; + if (curve.type != DCT_Parametric) { + if (edited_point == -1) { + if (event->button.button == 1) { + std::vector::iterator itx, ity; + buttonPressed = true; + add_modal_grab (); - case Gdk::MOTION_NOTIFY: - snapToElmt = -100; - if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) { + // get the pointer position + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + findClosestPoint(); - snapToMinDistY = snapToMinDistX = 10.; - snapToValY = snapToValX = 0.; - snapToElmt = -100; + new_type = CSMove; - // get the pointer position - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + if (distanceX > minDistanceX) { + if (mod_type & GDK_CONTROL_MASK) { + clampedY = point.getVal01(clampedX); + } - if (grab_point == -1) { - if (edited_point==-1) { - // there's no point currently being moved - int previous_lit_point = lit_point; - findClosestPoint(); - if (cursorX<0 || cursorX>graphW || cursorY<0 || cursorY>graphH) { - // the cursor has left the graph area - new_type = CSArrow; - lit_point = -1; - } - else if (distanceX <= minDistanceX) { - // the cursor is close to an existing point - new_type = CSMove; - lit_point = closest_point; - } - else { - // the cursor is inside the graph but away from existing points - new_type = CSPlus; - lit_point = -1; - } - if (lit_point != previous_lit_point) { - setDirty(true); - draw (lit_point); - if (lit_point > -1) { - editedPos.at(0) = curve.x.at(lit_point); - editedPos.at(1) = curve.y.at(lit_point); - } - coordinateAdjuster->setPos(editedPos); - } - if (lit_point == -1 && new_type == CSPlus) { - editedPos.at(0) = clampedX; - editedPos.at(1) = clampedY; - coordinateAdjuster->setPos(editedPos); - } - } - else { // if (edited_point > -1) - // there's no point currently being moved - int previous_lit_point = lit_point; - findClosestPoint(); - if (distanceX <= minDistanceX) { - // the cursor is close to an existing point - lit_point = closest_point; - } - else { - // the cursor is outside the graph or inside the graph but away from existing points - lit_point = -1; - } - if (lit_point != previous_lit_point) { - setDirty(true); - draw (lit_point); - } - } - } - else { - // a point is being moved + /* insert a new control point */ + if (num > 0) { + if (clampedX > curve.x.at(closest_point)) { + ++closest_point; + } + } - // bounds of the grabbed point - double leftBound = (grab_point == 0 ) ? 0. : curve.x.at(grab_point-1); - double rightBound = (grab_point == num-1) ? 1. : curve.x.at(grab_point+1); - double const bottomBound = 0.; - double const topBound = 1.; + itx = curve.x.begin(); + ity = curve.y.begin(); - double leftDeletionBound = leftBound - minDistanceX; - double rightDeletionBound = rightBound + minDistanceX; - double bottomDeletionBound = bottomBound - minDistanceY; - double topDeletionBound = topBound + minDistanceY; + for (int i = 0; i < closest_point; i++) { + itx++; + ity++; + } - // we memorize the previous position of the point, for optimization purpose - double prevPosX = curve.x.at(grab_point); - double prevPosY = curve.y.at(grab_point); + curve.x.insert (itx, 0); + curve.y.insert (ity, 0); + num++; - // we memorize the previous position of the point, for optimization purpose - ugpX += deltaX; - ugpY += deltaY; + // the graph is refreshed only if a new point is created + curve.x.at(closest_point) = clampedX; + curve.y.at(closest_point) = clampedY; - // the unclamped grabbed point is brought back in the range when snapTo is active - if (snapTo) ugpY = CLAMP(ugpY, 0.0, 1.0); + curveIsDirty = true; + setDirty(true); + draw (closest_point); + notifyListener (); + } - // handling limitations along X axis - if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num-1))) { - curve.x.at(grab_point) = -1.; - } - else if (ugpX <= leftDeletionBound && (grab_point > 0 && grab_point < (num-1))) { - curve.x.at(grab_point) = -1.; - } - else - // nextPosX is in bounds - curve.x.at(grab_point) = CLAMP(ugpX, leftBound, rightBound); + grab_point = closest_point; + lit_point = closest_point; + ugpX = curve.x.at(closest_point); + ugpY = curve.y.at(closest_point); + } else if (event->button.button == 3) { + if (lit_point > -1 && grab_point == -1) { + if (!coordinateAdjuster->is_visible()) { + coordinateAdjuster->showMe(this); + } - // Handling limitations along Y axis - if (ugpY >= topDeletionBound && grab_point != 0 && grab_point != num-1) { - curve.x.at(grab_point) = -1.; - } - else if (ugpY <= bottomDeletionBound && grab_point != 0 && grab_point != num-1) { - curve.x.at(grab_point) = -1.; - } - else { - // snapping point to specific values - if (snapTo && curve.x.at(grab_point) != -1.) { - if (grab_point > 0 && grab_point < (curve.y.size()-1)) { - double prevX = curve.x.at(grab_point-1); - double prevY = curve.y.at(grab_point-1); - double nextX = curve.x.at(grab_point+1); - double nextY = curve.y.at(grab_point+1); + edited_point = lit_point; + std::vector newBoundaries(2); + unsigned int size = curve.x.size(); - double ratio = (curve.x.at(grab_point)-prevX)/(nextX-prevX); - double y = (nextY-prevY) * ratio + prevY; + if (edited_point == 0) { + newBoundaries.at(0).minVal = 0.; + newBoundaries.at(0).maxVal = curve.x.at(1); + } else if (edited_point == size - 1) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = 1.; + } else if (curve.x.size() > 2) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = curve.x.at(edited_point + 1); + } - if (snapCoordinateY(y, ugpY)) snapToElmt = 1000+grab_point; - } - if (grab_point > 0) { - int prevP = grab_point-1; - if (snapCoordinateY(curve.y.at(prevP), ugpY)) snapToElmt = prevP; - } - if (grab_point < (curve.y.size()-1)) { - int nextP = grab_point+1; - if (snapCoordinateY(curve.y.at(nextP), ugpY)) snapToElmt = nextP; - } - if (snapCoordinateY(1.0, ugpY)) snapToElmt = -3; - if (snapCoordinateY(curve.x.at(grab_point), ugpY)) snapToElmt = -2; - if (snapCoordinateY(0.0, ugpY)) snapToElmt = -1; + newBoundaries.at(1).minVal = 0.; + newBoundaries.at(1).maxVal = 1.; + editedPos.at(0) = curve.x.at(edited_point); + editedPos.at(1) = curve.y.at(edited_point); + coordinateAdjuster->setPos(editedPos); + coordinateAdjuster->startNumericalAdjustment(newBoundaries); + setDirty(true); + draw (lit_point); + new_type = CSArrow; + retval = true; + } + } - curve.y.at(grab_point) = snapToValY; - } - else { - // nextPosY is in the bounds - curve.y.at(grab_point) = CLAMP(ugpY, 0.0, 1.0); - } - } + if (buttonPressed) { + retval = true; + } + } else { // if (edited_point > -1) + if (event->button.button == 3) { + // do we edit another point? + if (edited_point > -1 && grab_point == -1) { + /* get the pointer position */ + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + findClosestPoint(); - if (curve.x.at(grab_point) != prevPosX || curve.y.at(grab_point) != prevPosY) { - // we recalculate the curve only if we have to - curveIsDirty = true; - setDirty(true); - draw (lit_point); - notifyListener (); + if (cursorX >= 0 && cursorX <= graphW && cursorY >= 0 && cursorY <= graphH) { + if (distanceX <= minDistanceX) { + // the cursor is close to an existing point + lit_point = closest_point; - if (coordinateAdjuster->is_visible()) { - editedPos.at(0) = curve.x.at(grab_point); - editedPos.at(1) = curve.y.at(grab_point); - coordinateAdjuster->setPos(editedPos); - } - } - } - } + if (lit_point != edited_point) { + edited_point = lit_point; + curveIsDirty = true; + setDirty(true); + draw (lit_point); + std::vector newBoundaries; + newBoundaries.resize(2); + unsigned int size = curve.x.size(); - retval = true; - break; + if (edited_point == 0) { + newBoundaries.at(0).minVal = 0.; + newBoundaries.at(0).maxVal = curve.x.at(1); + } else if (edited_point == size - 1) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = 1.; + } else if (curve.x.size() > 2) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = curve.x.at(edited_point + 1); + } - default: - break; - } - if (new_type != cursor_type) { - cursor_type = new_type; - cursorManager.setCursor(cursor_type); - } - return retval; + newBoundaries.at(1).minVal = 0.; + newBoundaries.at(1).maxVal = 1.; + retval = true; + editedPos.at(0) = curve.x.at(edited_point); + editedPos.at(1) = curve.y.at(edited_point); + coordinateAdjuster->switchAdjustedPoint(editedPos, newBoundaries); + } + } else { + // the cursor is inside the graph but away from existing points + new_type = CSPlus; + curveIsDirty = true; + stopNumericalAdjustment(); + } + } + + retval = true; + } + } + } + + retval = true; + } + + break; + + case Gdk::BUTTON_RELEASE: + snapToElmt = -100; + + if (curve.type != DCT_Parametric && edited_point == -1) { + if (buttonPressed && event->button.button == 1) { + std::vector::iterator itx, ity; + int src, dst; + buttonPressed = false; + /* get the pointer position */ + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + findClosestPoint(); + + remove_modal_grab (); + int previous_lit_point = lit_point; + /* delete inactive points: */ + itx = curve.x.begin(); + ity = curve.y.begin(); + + for (src = dst = 0; src < num; ++src) + if (curve.x.at(src) >= 0.0) { + curve.x.at(dst) = curve.x.at(src); + curve.y.at(dst) = curve.y.at(src); + ++dst; + ++itx; + ++ity; + } + + if (dst < src) { + curve.x.erase (itx, curve.x.end()); + curve.y.erase (ity, curve.y.end()); + + if (curve.x.empty()) { + curve.x.push_back (0); + curve.y.push_back (0); + curveIsDirty = true; + setDirty(true); + draw (lit_point); + } + } + + if (distanceX <= minDistanceX) { + new_type = CSMove; + lit_point = closest_point; + } else { + new_type = CSPlus; + lit_point = -1; + } + + if (lit_point != previous_lit_point) { + setDirty(true); + draw (lit_point); + } + + grab_point = -1; + retval = true; + notifyListener (); + } + } + + break; + + case Gdk::LEAVE_NOTIFY: + + // Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case + // The cursor will have to LEAVE another time after the drag... + if (!buttonPressed) + if (grab_point == -1) { + new_type = CSArrow; + lit_point = -1; + pipetteR = pipetteG = pipetteB = -1.f; + setDirty(true); + draw (lit_point); + } + + retval = true; + break; + + case Gdk::MOTION_NOTIFY: + snapToElmt = -100; + + if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) { + + snapToMinDistY = snapToMinDistX = 10.; + snapToValY = snapToValX = 0.; + snapToElmt = -100; + + // get the pointer position + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + + if (grab_point == -1) { + if (edited_point == -1) { + // there's no point currently being moved + int previous_lit_point = lit_point; + findClosestPoint(); + + if (cursorX < 0 || cursorX > graphW || cursorY < 0 || cursorY > graphH) { + // the cursor has left the graph area + new_type = CSArrow; + lit_point = -1; + } else if (distanceX <= minDistanceX) { + // the cursor is close to an existing point + new_type = CSMove; + lit_point = closest_point; + } else { + // the cursor is inside the graph but away from existing points + new_type = CSPlus; + lit_point = -1; + } + + if (lit_point != previous_lit_point) { + setDirty(true); + draw (lit_point); + + if (lit_point > -1) { + editedPos.at(0) = curve.x.at(lit_point); + editedPos.at(1) = curve.y.at(lit_point); + } + + coordinateAdjuster->setPos(editedPos); + } + + if (lit_point == -1 && new_type == CSPlus) { + editedPos.at(0) = clampedX; + editedPos.at(1) = clampedY; + coordinateAdjuster->setPos(editedPos); + } + } else { // if (edited_point > -1) + // there's no point currently being moved + int previous_lit_point = lit_point; + findClosestPoint(); + + if (distanceX <= minDistanceX) { + // the cursor is close to an existing point + lit_point = closest_point; + } else { + // the cursor is outside the graph or inside the graph but away from existing points + lit_point = -1; + } + + if (lit_point != previous_lit_point) { + setDirty(true); + draw (lit_point); + } + } + } else { + // a point is being moved + + // bounds of the grabbed point + double leftBound = (grab_point == 0 ) ? 0. : curve.x.at(grab_point - 1); + double rightBound = (grab_point == num - 1) ? 1. : curve.x.at(grab_point + 1); + double const bottomBound = 0.; + double const topBound = 1.; + + double leftDeletionBound = leftBound - minDistanceX; + double rightDeletionBound = rightBound + minDistanceX; + double bottomDeletionBound = bottomBound - minDistanceY; + double topDeletionBound = topBound + minDistanceY; + + // we memorize the previous position of the point, for optimization purpose + double prevPosX = curve.x.at(grab_point); + double prevPosY = curve.y.at(grab_point); + + // we memorize the previous position of the point, for optimization purpose + ugpX += deltaX; + ugpY += deltaY; + + // the unclamped grabbed point is brought back in the range when snapTo is active + if (snapTo) { + ugpY = CLAMP(ugpY, 0.0, 1.0); + } + + // handling limitations along X axis + if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num - 1))) { + curve.x.at(grab_point) = -1.; + } else if (ugpX <= leftDeletionBound && (grab_point > 0 && grab_point < (num - 1))) { + curve.x.at(grab_point) = -1.; + } else + // nextPosX is in bounds + { + curve.x.at(grab_point) = CLAMP(ugpX, leftBound, rightBound); + } + + // Handling limitations along Y axis + if (ugpY >= topDeletionBound && grab_point != 0 && grab_point != num - 1) { + curve.x.at(grab_point) = -1.; + } else if (ugpY <= bottomDeletionBound && grab_point != 0 && grab_point != num - 1) { + curve.x.at(grab_point) = -1.; + } else { + // snapping point to specific values + if (snapTo && curve.x.at(grab_point) != -1.) { + if (grab_point > 0 && grab_point < (curve.y.size() - 1)) { + double prevX = curve.x.at(grab_point - 1); + double prevY = curve.y.at(grab_point - 1); + double nextX = curve.x.at(grab_point + 1); + double nextY = curve.y.at(grab_point + 1); + + double ratio = (curve.x.at(grab_point) - prevX) / (nextX - prevX); + double y = (nextY - prevY) * ratio + prevY; + + if (snapCoordinateY(y, ugpY)) { + snapToElmt = 1000 + grab_point; + } + } + + if (grab_point > 0) { + int prevP = grab_point - 1; + + if (snapCoordinateY(curve.y.at(prevP), ugpY)) { + snapToElmt = prevP; + } + } + + if (grab_point < (curve.y.size() - 1)) { + int nextP = grab_point + 1; + + if (snapCoordinateY(curve.y.at(nextP), ugpY)) { + snapToElmt = nextP; + } + } + + if (snapCoordinateY(1.0, ugpY)) { + snapToElmt = -3; + } + + if (snapCoordinateY(curve.x.at(grab_point), ugpY)) { + snapToElmt = -2; + } + + if (snapCoordinateY(0.0, ugpY)) { + snapToElmt = -1; + } + + curve.y.at(grab_point) = snapToValY; + } else { + // nextPosY is in the bounds + curve.y.at(grab_point) = CLAMP(ugpY, 0.0, 1.0); + } + } + + if (curve.x.at(grab_point) != prevPosX || curve.y.at(grab_point) != prevPosY) { + // we recalculate the curve only if we have to + curveIsDirty = true; + setDirty(true); + draw (lit_point); + notifyListener (); + + if (coordinateAdjuster->is_visible()) { + editedPos.at(0) = curve.x.at(grab_point); + editedPos.at(1) = curve.y.at(grab_point); + coordinateAdjuster->setPos(editedPos); + } + } + } + } + + retval = true; + break; + + default: + break; + } + + if (new_type != cursor_type) { + cursor_type = new_type; + cursorManager.setCursor(cursor_type); + } + + return retval; } -CursorShape MyDiagonalCurve::motionNotify(CursorShape type, double minDistanceX, double minDistanceY, int num) { - CursorShape new_type = type; +CursorShape MyDiagonalCurve::motionNotify(CursorShape type, double minDistanceX, double minDistanceY, int num) +{ + CursorShape new_type = type; - return new_type; + return new_type; } -void MyDiagonalCurve::pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) { - if (!provider) { - // occurs when leaving the preview area -> cleanup the curve editor - pipetteR = pipetteG = pipetteB = -1.f; - lit_point = -1; - return; - } +void MyDiagonalCurve::pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) +{ + if (!provider) { + // occurs when leaving the preview area -> cleanup the curve editor + pipetteR = pipetteG = pipetteB = -1.f; + lit_point = -1; + return; + } - pipetteR = provider->pipetteVal[0]; - pipetteG = provider->pipetteVal[1]; - pipetteB = provider->pipetteVal[2]; - pipetteVal = 0.f; - if (listener) { - pipetteVal = listener->blendPipetteValues(ce, pipetteR, pipetteG, pipetteB); - } - else { - int n = 0; - if (pipetteR != -1.f) { - pipetteVal += pipetteR; - ++n; - } - if (pipetteG != -1.f) { - pipetteVal += pipetteG; - ++n; - } - if (pipetteB != -1.f) { - pipetteVal += pipetteB; - ++n; - } - if (n>1) - pipetteVal /= n; - else if (!n) - pipetteVal = -1.f; - } + pipetteR = provider->pipetteVal[0]; + pipetteG = provider->pipetteVal[1]; + pipetteB = provider->pipetteVal[2]; + pipetteVal = 0.f; - /* graphW and graphH are the size of the graph */ - calcDimensions(); + if (listener) { + pipetteVal = listener->blendPipetteValues(ce, pipetteR, pipetteG, pipetteB); + } else { + int n = 0; - if ((graphW < 0) || (graphH < 0)) - return; + if (pipetteR != -1.f) { + pipetteVal += pipetteR; + ++n; + } - double minDistanceX = double(MIN_DISTANCE) / double(graphW-1); + if (pipetteG != -1.f) { + pipetteVal += pipetteG; + ++n; + } - if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) { - // get the pointer position - getCursorPositionFromCurve(pipetteVal); + if (pipetteB != -1.f) { + pipetteVal += pipetteB; + ++n; + } - if (edited_point==-1) { - if (grab_point == -1) { - // there's no point currently being moved - int previous_lit_point = lit_point; - findClosestPoint(); - if (cursorX<0 || cursorX>graphW || cursorY<0 || cursorY>graphH) { - // the cursor has left the graph area - lit_point = -1; - } - else if (distanceX <= minDistanceX) { - lit_point = closest_point; - } - else { - lit_point = -1; - } - if (lit_point != previous_lit_point) { - setDirty(true); - draw (lit_point); - } - } - } - else - draw(lit_point); + if (n > 1) { + pipetteVal /= n; + } else if (!n) { + pipetteVal = -1.f; + } + } - if (edited_point==-1) { - editedPos.at(0) = pipetteVal; - editedPos.at(1) = point.getVal01(pipetteVal); - coordinateAdjuster->setPos(editedPos); - } - } + /* graphW and graphH are the size of the graph */ + calcDimensions(); + + if ((graphW < 0) || (graphH < 0)) { + return; + } + + double minDistanceX = double(MIN_DISTANCE) / double(graphW - 1); + + if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) { + // get the pointer position + getCursorPositionFromCurve(pipetteVal); + + if (edited_point == -1) { + if (grab_point == -1) { + // there's no point currently being moved + int previous_lit_point = lit_point; + findClosestPoint(); + + if (cursorX < 0 || cursorX > graphW || cursorY < 0 || cursorY > graphH) { + // the cursor has left the graph area + lit_point = -1; + } else if (distanceX <= minDistanceX) { + lit_point = closest_point; + } else { + lit_point = -1; + } + + if (lit_point != previous_lit_point) { + setDirty(true); + draw (lit_point); + } + } + } else { + draw(lit_point); + } + + if (edited_point == -1) { + editedPos.at(0) = pipetteVal; + editedPos.at(1) = point.getVal01(pipetteVal); + coordinateAdjuster->setPos(editedPos); + } + } } -void MyDiagonalCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { - if (edited_point>1) - return; +void MyDiagonalCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +{ + if (edited_point > 1) { + return; + } - int num = (int)curve.x.size(); + int num = (int)curve.x.size(); - /* graphW and graphH are the size of the graph */ - calcDimensions(); + /* graphW and graphH are the size of the graph */ + calcDimensions(); - double minDistanceX = double(MIN_DISTANCE) / double(graphW-1); + double minDistanceX = double(MIN_DISTANCE) / double(graphW - 1); - if ((graphW < 0) || (graphH < 0)) - return; + if ((graphW < 0) || (graphH < 0)) { + return; + } - snapToElmt = -100; - if (curve.type!=DCT_Parametric) { - std::vector::iterator itx, ity; - buttonPressed = true; + snapToElmt = -100; - // get the pointer position - getCursorPositionFromCurve(pipetteVal); - findClosestPoint(); + if (curve.type != DCT_Parametric) { + std::vector::iterator itx, ity; + buttonPressed = true; - if (distanceX > minDistanceX) { - /* insert a new control point */ - if (num > 0) { - if (clampedX > curve.x.at(closest_point)) - ++closest_point; - } - itx = curve.x.begin(); - ity = curve.y.begin(); - for (int i=0; i minDistanceX) { + /* insert a new control point */ + if (num > 0) { + if (clampedX > curve.x.at(closest_point)) { + ++closest_point; + } + } - if (lit_point>-1 && grab_point==-1 && coordinateAdjuster->is_visible()) { - std::vector position; - position.resize(2); - position.at(0) = clampedX; - position.at(1) = clampedY; - coordinateAdjuster->setPos(position); - } + itx = curve.x.begin(); + ity = curve.y.begin(); - curveIsDirty = true; - setDirty(true); - draw (lit_point); - notifyListener (); - } - grab_point = closest_point; - lit_point = closest_point; - ugpX = curve.x.at(closest_point); - ugpY = curve.y.at(closest_point); - } + for (int i = 0; i < closest_point; i++) { + itx++; + ity++; + } + + lit_point = closest_point; + curve.x.insert (itx, 0); + curve.y.insert (ity, 0); + + // the graph is refreshed only if a new point is created (snapped to a pixel) + curve.x.at(lit_point) = clampedX; + curve.y.at(lit_point) = clampedY; + + if (lit_point > -1 && grab_point == -1 && coordinateAdjuster->is_visible()) { + std::vector position; + position.resize(2); + position.at(0) = clampedX; + position.at(1) = clampedY; + coordinateAdjuster->setPos(position); + } + + curveIsDirty = true; + setDirty(true); + draw (lit_point); + notifyListener (); + } + + grab_point = closest_point; + lit_point = closest_point; + ugpX = curve.x.at(closest_point); + ugpY = curve.y.at(closest_point); + } } -void MyDiagonalCurve::pipetteButton1Released(EditDataProvider *provider) { - if (edited_point>1) - return; +void MyDiagonalCurve::pipetteButton1Released(EditDataProvider *provider) +{ + if (edited_point > 1) { + return; + } - /* graphW and graphH are the size of the graph */ - calcDimensions(); + /* graphW and graphH are the size of the graph */ + calcDimensions(); - double minDistanceX = double(MIN_DISTANCE) / double(graphW-1); - //double minDistanceY = double(MIN_DISTANCE) / double(graphH-1); + double minDistanceX = double(MIN_DISTANCE) / double(graphW - 1); + //double minDistanceY = double(MIN_DISTANCE) / double(graphH-1); - if ((graphW < 0) || (graphH < 0)) - return; + if ((graphW < 0) || (graphH < 0)) { + return; + } - snapToElmt = -100; - if (curve.type!=DCT_Parametric) { - std::vector::iterator itx, ity; - buttonPressed = false; - /* get the pointer position */ - getCursorPosition(Gdk::EventType(Gdk::BUTTON_RELEASE), false, graphY, 0, Gdk::ModifierType(0)); - findClosestPoint(); + snapToElmt = -100; - int previous_lit_point = lit_point; + if (curve.type != DCT_Parametric) { + std::vector::iterator itx, ity; + buttonPressed = false; + /* get the pointer position */ + getCursorPosition(Gdk::EventType(Gdk::BUTTON_RELEASE), false, graphY, 0, Gdk::ModifierType(0)); + findClosestPoint(); - if (distanceX <= minDistanceX) { - lit_point = closest_point; - } - else { - lit_point = -1; - } - if (lit_point != previous_lit_point) { - setDirty(true); - draw (lit_point); - } - grab_point = -1; - //notifyListener (); - } + int previous_lit_point = lit_point; + + if (distanceX <= minDistanceX) { + lit_point = closest_point; + } else { + lit_point = -1; + } + + if (lit_point != previous_lit_point) { + setDirty(true); + draw (lit_point); + } + + grab_point = -1; + //notifyListener (); + } } -void MyDiagonalCurve::pipetteDrag(EditDataProvider *provider, int modifierKey) { - if (edited_point>-1 || curve.type==DCT_Parametric || graphW<0 || graphH<0) - return; +void MyDiagonalCurve::pipetteDrag(EditDataProvider *provider, int modifierKey) +{ + if (edited_point > -1 || curve.type == DCT_Parametric || graphW < 0 || graphH < 0) { + return; + } - snapToMinDistY = snapToMinDistX = 10.; - snapToValY = snapToValX = 0.; - snapToElmt = -100; + snapToMinDistY = snapToMinDistX = 10.; + snapToValY = snapToValX = 0.; + snapToElmt = -100; - /* graphW and graphH are the size of the graph */ - calcDimensions(); + /* graphW and graphH are the size of the graph */ + calcDimensions(); - getCursorPosition(Gdk::MOTION_NOTIFY, false, cursorX+graphX, graphY-cursorY+provider->deltaPrevScreen.y, Gdk::ModifierType(modifierKey)); + getCursorPosition(Gdk::MOTION_NOTIFY, false, cursorX + graphX, graphY - cursorY + provider->deltaPrevScreen.y, Gdk::ModifierType(modifierKey)); - // we memorize the previous position of the point, for optimization purpose - double prevPosX = curve.x.at(grab_point); - double prevPosY = curve.y.at(grab_point); + // we memorize the previous position of the point, for optimization purpose + double prevPosX = curve.x.at(grab_point); + double prevPosY = curve.y.at(grab_point); - // we memorize the previous position of the point, for optimization purpose - ugpX += deltaX; - ugpY += deltaY; + // we memorize the previous position of the point, for optimization purpose + ugpX += deltaX; + ugpY += deltaY; - // the unclamped grabbed point is brought back in the range - ugpY = CLAMP(ugpY, 0.0, 1.0); + // the unclamped grabbed point is brought back in the range + ugpY = CLAMP(ugpY, 0.0, 1.0); - // snapping point to specific values - if (snapTo && curve.x.at(grab_point) != -1.) { - if (grab_point > 0 && grab_point < (curve.y.size()-1)) { - double prevX = curve.x.at(grab_point-1); - double prevY = curve.y.at(grab_point-1); - double nextX = curve.x.at(grab_point+1); - double nextY = curve.y.at(grab_point+1); + // snapping point to specific values + if (snapTo && curve.x.at(grab_point) != -1.) { + if (grab_point > 0 && grab_point < (curve.y.size() - 1)) { + double prevX = curve.x.at(grab_point - 1); + double prevY = curve.y.at(grab_point - 1); + double nextX = curve.x.at(grab_point + 1); + double nextY = curve.y.at(grab_point + 1); - double ratio = (curve.x.at(grab_point)-prevX)/(nextX-prevX); - double y = (nextY-prevY) * ratio + prevY; + double ratio = (curve.x.at(grab_point) - prevX) / (nextX - prevX); + double y = (nextY - prevY) * ratio + prevY; - if (snapCoordinateY(y, ugpY)) snapToElmt = 1000+grab_point; - } - if (grab_point > 0) { - int prevP = grab_point-1; - if (snapCoordinateY(curve.y.at(prevP), ugpY)) snapToElmt = prevP; - } - if (grab_point < (curve.y.size()-1)) { - int nextP = grab_point+1; - if (snapCoordinateY(curve.y.at(nextP), ugpY)) snapToElmt = nextP; - } - if (snapCoordinateY(1.0, ugpY)) snapToElmt = -3; - if (snapCoordinateY(curve.x.at(grab_point), ugpY)) snapToElmt = -2; - if (snapCoordinateY(0.0, ugpY)) snapToElmt = -1; + if (snapCoordinateY(y, ugpY)) { + snapToElmt = 1000 + grab_point; + } + } - curve.y.at(grab_point) = snapToValY; - } - else { - // nextPosY is in the bounds - curve.y.at(grab_point) = ugpY; - } + if (grab_point > 0) { + int prevP = grab_point - 1; - if (curve.x.at(grab_point) != prevPosX || curve.y.at(grab_point) != prevPosY) { - // we recalculate the curve only if we have to - curveIsDirty = true; - setDirty(true); - draw (lit_point); - notifyListener (); + if (snapCoordinateY(curve.y.at(prevP), ugpY)) { + snapToElmt = prevP; + } + } - if (lit_point>-1 && coordinateAdjuster->is_visible()) { - std::vector position; - position.resize(2); - position.at(0) = curve.x.at(grab_point); - position.at(1) = curve.y.at(grab_point); - coordinateAdjuster->setPos(position); - } + if (grab_point < (curve.y.size() - 1)) { + int nextP = grab_point + 1; - } + if (snapCoordinateY(curve.y.at(nextP), ugpY)) { + snapToElmt = nextP; + } + } + + if (snapCoordinateY(1.0, ugpY)) { + snapToElmt = -3; + } + + if (snapCoordinateY(curve.x.at(grab_point), ugpY)) { + snapToElmt = -2; + } + + if (snapCoordinateY(0.0, ugpY)) { + snapToElmt = -1; + } + + curve.y.at(grab_point) = snapToValY; + } else { + // nextPosY is in the bounds + curve.y.at(grab_point) = ugpY; + } + + if (curve.x.at(grab_point) != prevPosX || curve.y.at(grab_point) != prevPosY) { + // we recalculate the curve only if we have to + curveIsDirty = true; + setDirty(true); + draw (lit_point); + notifyListener (); + + if (lit_point > -1 && coordinateAdjuster->is_visible()) { + std::vector position; + position.resize(2); + position.at(0) = curve.x.at(grab_point); + position.at(1) = curve.y.at(grab_point); + coordinateAdjuster->setPos(position); + } + + } } -void MyDiagonalCurve::getCursorPositionFromCurve(float x) { +void MyDiagonalCurve::getCursorPositionFromCurve(float x) +{ - // the graph is refreshed only if a new point is created (snaped to a pixel) - clampedX = x; - clampedY = point.getVal01(x); + // the graph is refreshed only if a new point is created (snaped to a pixel) + clampedX = x; + clampedY = point.getVal01(x); - cursorX = int(clampedX*float(graphW-3)) + graphX+1.5; - cursorY = graphY - int(clampedY*float(graphH-3)); + cursorX = int(clampedX * float(graphW - 3)) + graphX + 1.5; + cursorY = graphY - int(clampedY * float(graphH - 3)); } // x = cursor position found in the event -void MyDiagonalCurve::getCursorPositionFromCurve(int x) { +void MyDiagonalCurve::getCursorPositionFromCurve(int x) +{ - // the graph is refreshed only if a new point is created (snaped to a pixel) - cursorX = x-graphX; - clampedX = (float(cursorX)-1.5) / float(graphW-3); - clampedY = point.getVal01(clampedX); - cursorY = graphY - int(float(1.-clampedY)*float(graphH-3)); + // the graph is refreshed only if a new point is created (snaped to a pixel) + cursorX = x - graphX; + clampedX = (float(cursorX) - 1.5) / float(graphW - 3); + clampedY = point.getVal01(clampedX); + cursorY = graphY - int(float(1. - clampedY) * float(graphH - 3)); } -void MyDiagonalCurve::getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifierKey) { - int tx, ty; - int prevCursorX, prevCursorY; - double incrementX = 1. / double(graphW); - double incrementY = 1. / double(graphH); +void MyDiagonalCurve::getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifierKey) +{ + int tx, ty; + int prevCursorX, prevCursorY; + double incrementX = 1. / double(graphW); + double incrementY = 1. / double(graphH); - // getting the cursor position - switch (evType) { - case (Gdk::MOTION_NOTIFY) : - if (isHint) { - get_window()->get_pointer (tx, ty, mod_type); - } - else { - tx = evX; - ty = evY; - mod_type = modifierKey; - } - break; - case (Gdk::BUTTON_PRESS) : - case (Gdk::BUTTON_RELEASE) : - tx = evX; - ty = evY; - mod_type = modifierKey; - break; - default : - // The cursor position is not available - return; - break; - } + // getting the cursor position + switch (evType) { + case (Gdk::MOTION_NOTIFY) : + if (isHint) { + get_window()->get_pointer (tx, ty, mod_type); + } else { + tx = evX; + ty = evY; + mod_type = modifierKey; + } - if (grab_point != -1) { - prevCursorX = cursorX; - prevCursorY = cursorY; - } - cursorX = tx - graphX; - cursorY = graphY - ty; + break; - snapTo = ST_None; + case (Gdk::BUTTON_PRESS) : + case (Gdk::BUTTON_RELEASE) : + tx = evX; + ty = evY; + mod_type = modifierKey; + break; - // update deltaX/Y if the user drags a point - if (grab_point != -1) { - // set the dragging factor - int control_key = mod_type & GDK_CONTROL_MASK; - int shift_key = mod_type & GDK_SHIFT_MASK; + default : + // The cursor position is not available + return; + break; + } - // the increment get smaller if modifier key are used, and "snap to" may be enabled - if (control_key) { incrementX *= 0.05; incrementY *= 0.05; } - if (shift_key) { snapTo = true; } + if (grab_point != -1) { + prevCursorX = cursorX; + prevCursorY = cursorY; + } - deltaX = double(cursorX - prevCursorX) * incrementX; - deltaY = double(cursorY - prevCursorY) * incrementY; - } - // otherwise set the position of the new point (modifier keys has no effect here) - else { - double tempCursorX = cursorX * incrementX; - double tempCursorY = cursorY * incrementY; - clampedX = CLAMP (tempCursorX, 0., 1.); // X position of the pointer from the origin of the graph - clampedY = CLAMP (tempCursorY, 0., 1.); // Y position of the pointer from the origin of the graph - } + cursorX = tx - graphX; + cursorY = graphY - ty; + + snapTo = ST_None; + + // update deltaX/Y if the user drags a point + if (grab_point != -1) { + // set the dragging factor + int control_key = mod_type & GDK_CONTROL_MASK; + int shift_key = mod_type & GDK_SHIFT_MASK; + + // the increment get smaller if modifier key are used, and "snap to" may be enabled + if (control_key) { + incrementX *= 0.05; + incrementY *= 0.05; + } + + if (shift_key) { + snapTo = true; + } + + deltaX = double(cursorX - prevCursorX) * incrementX; + deltaY = double(cursorY - prevCursorY) * incrementY; + } + // otherwise set the position of the new point (modifier keys has no effect here) + else { + double tempCursorX = cursorX * incrementX; + double tempCursorY = cursorY * incrementY; + clampedX = CLAMP (tempCursorX, 0., 1.); // X position of the pointer from the origin of the graph + clampedY = CLAMP (tempCursorY, 0., 1.); // Y position of the pointer from the origin of the graph + } } -void MyDiagonalCurve::findClosestPoint() { - distanceX = 10.0; distanceY = 10.0; +void MyDiagonalCurve::findClosestPoint() +{ + distanceX = 10.0; + distanceY = 10.0; closest_point = -1; - if (curve.type!=DCT_Parametric) { + if (curve.type != DCT_Parametric) { for (int i = 0; i < (int)curve.x.size(); i++) { double dX = curve.x.at(i) - clampedX; double dY = curve.y.at(i) - clampedY; double currDistX = dX < 0. ? -dX : dX; //abs (dX); double currDistY = dY < 0. ? -dY : dY; //abs (dY); + if (currDistX < distanceX) { distanceX = currDistX; distanceY = currDistY; closest_point = i; - } - else if (currDistX == distanceX && currDistY < distanceY) { + } else if (currDistX == distanceX && currDistY < distanceY) { // there is more than 1 point for that X coordinate, we select the closest point to the cursor distanceY = currDistY; closest_point = i; @@ -1176,74 +1401,88 @@ void MyDiagonalCurve::findClosestPoint() { } } -std::vector MyDiagonalCurve::getPoints () { +std::vector MyDiagonalCurve::getPoints () +{ std::vector result; - if (curve.type==DCT_Parametric) { + + if (curve.type == DCT_Parametric) { result.push_back ((double)(DCT_Parametric)); - for (int i=0; i<(int)curve.x.size(); i++) { + + for (int i = 0; i < (int)curve.x.size(); i++) { result.push_back (curve.x.at(i)); } - } - else { + } else { // the first value gives the type of the curve - if (curve.type==DCT_Linear) + if (curve.type == DCT_Linear) { result.push_back (double(DCT_Linear)); - else if (curve.type==DCT_Spline) + } else if (curve.type == DCT_Spline) { result.push_back (double(DCT_Spline)); - else if (curve.type==DCT_NURBS) + } else if (curve.type == DCT_NURBS) { result.push_back (double(DCT_NURBS)); + } + // then we push all the points coordinate - for (int i=0; i<(int)curve.x.size(); i++) { - if (curve.x.at(i)>=0) { + for (int i = 0; i < (int)curve.x.size(); i++) { + if (curve.x.at(i) >= 0) { result.push_back (curve.x.at(i)); result.push_back (curve.y.at(i)); } } } + return result; } -void MyDiagonalCurve::setPoints (const std::vector& p) { +void MyDiagonalCurve::setPoints (const std::vector& p) +{ int ix = 0; stopNumericalAdjustment(); DiagonalCurveType t = (DiagonalCurveType)p[ix++]; curve.type = t; - if (t==DCT_Parametric) { + + if (t == DCT_Parametric) { curve.x.clear (); curve.y.clear (); - for (size_t i=1; i -1); + if (chanIdx == 0) { curve.x.at(edited_point) = pos; - } - else if (chanIdx == 1) { + } else if (chanIdx == 1) { curve.y.at(edited_point) = pos; } + curveIsDirty = true; setDirty(true); draw(lit_point); notifyListener (); } -void MyDiagonalCurve::stopNumericalAdjustment() { - if (edited_point>-1) { +void MyDiagonalCurve::stopNumericalAdjustment() +{ + if (edited_point > -1) { edited_point = grab_point = lit_point = -1; coordinateAdjuster->stopNumericalAdjustment(); setDirty(true); @@ -1251,28 +1490,32 @@ void MyDiagonalCurve::stopNumericalAdjustment() { } } -void MyDiagonalCurve::setType (DiagonalCurveType t) { +void MyDiagonalCurve::setType (DiagonalCurveType t) +{ curve.type = t; setDirty(true); } -void MyDiagonalCurve::setActiveParam (int ac) { - +void MyDiagonalCurve::setActiveParam (int ac) +{ + activeParam = ac; setDirty(true); queue_draw (); } -int diagonalmchistupdateUI (void* data) { +int diagonalmchistupdateUI (void* data) +{ MyCurveIdleHelper* mcih = static_cast(data); if (mcih->destroyed) { - if (mcih->pending == 1) + if (mcih->pending == 1) { delete mcih; - else + } else { mcih->pending--; + } return 0; } @@ -1285,16 +1528,20 @@ int diagonalmchistupdateUI (void* data) { return 0; } -void MyDiagonalCurve::updateBackgroundHistogram (LUTu & hist) { +void MyDiagonalCurve::updateBackgroundHistogram (LUTu & hist) +{ if (hist) { //memcpy (bghist, hist, 256*sizeof(unsigned int)); - for (int i=0; i<256; i++) bghist[i]=hist[i]; + for (int i = 0; i < 256; i++) { + bghist[i] = hist[i]; + } + //hist = bghist; bghistvalid = true; - } - else + } else { bghistvalid = false; + } mcih->pending++; // Can be done outside of the GUI thread @@ -1302,7 +1549,8 @@ void MyDiagonalCurve::updateBackgroundHistogram (LUTu & hist) { } -void MyDiagonalCurve::reset(const std::vector &resetCurve, double identityValue) { +void MyDiagonalCurve::reset(const std::vector &resetCurve, double identityValue) +{ stopNumericalAdjustment(); @@ -1324,6 +1572,7 @@ void MyDiagonalCurve::reset(const std::vector &resetCurve, double identi lit_point = -1; curveIsDirty = true; break; + case DCT_Parametric : curve.x.resize(7); curve.y.clear(); @@ -1339,9 +1588,11 @@ void MyDiagonalCurve::reset(const std::vector &resetCurve, double identi lit_point = -1; // not sure that it's necessary curveIsDirty = true; break; + default: break; } + setDirty(true); draw(-1); } diff --git a/rtgui/mydiagonalcurve.h b/rtgui/mydiagonalcurve.h index 881a568d1..033ba9f95 100644 --- a/rtgui/mydiagonalcurve.h +++ b/rtgui/mydiagonalcurve.h @@ -7,7 +7,7 @@ * 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 @@ -29,71 +29,73 @@ // For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget enum DiagonalCurveType { - DCT_Empty = -1, // Also used for identity curves - DCT_Linear, // 0 - DCT_Spline, // 1 - DCT_Parametric, // 2 - DCT_NURBS, // 3 - // Insert new curve type above this line - DCT_Unchanged // Must remain the last of the enum + DCT_Empty = -1, // Also used for identity curves + DCT_Linear, // 0 + DCT_Spline, // 1 + DCT_Parametric, // 2 + DCT_NURBS, // 3 + // Insert new curve type above this line + DCT_Unchanged // Must remain the last of the enum }; -class DiagonalCurveDescr { +class DiagonalCurveDescr +{ - public: - DiagonalCurveType type; - std::vector x, y; // in case of parametric curves the curve parameters are stored in vector x. In other cases these vectors store the coordinates of the bullets. +public: + DiagonalCurveType type; + std::vector x, y; // in case of parametric curves the curve parameters are stored in vector x. In other cases these vectors store the coordinates of the bullets. }; -class MyDiagonalCurve : public MyCurve { +class MyDiagonalCurve : public MyCurve +{ - protected: - DiagonalCurveDescr curve; - int grab_point; // the point that the user is moving by mouse - int closest_point; // the point that is the closest from the cursor - int lit_point; // the point that is lit when the cursor is near it - double clampedX; // clamped grabbed point X coordinates in the [0;1] range - double clampedY; // clamped grabbed point Y coordinates in the [0;1] range - double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY - double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY - double distanceX; // X distance from the cursor to the closest point - double distanceY; // Y distance from the cursor to the closest point - double ugpX; // unclamped grabbed point X coordinate in the graph - double ugpY; // unclamped grabbed point Y coordinate in the graph - int activeParam; - unsigned int* bghist; // histogram values - bool bghistvalid; +protected: + DiagonalCurveDescr curve; + int grab_point; // the point that the user is moving by mouse + int closest_point; // the point that is the closest from the cursor + int lit_point; // the point that is lit when the cursor is near it + double clampedX; // clamped grabbed point X coordinates in the [0;1] range + double clampedY; // clamped grabbed point Y coordinates in the [0;1] range + double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY + double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY + double distanceX; // X distance from the cursor to the closest point + double distanceY; // Y distance from the cursor to the closest point + double ugpX; // unclamped grabbed point X coordinate in the graph + double ugpY; // unclamped grabbed point Y coordinate in the graph + int activeParam; + unsigned int* bghist; // histogram values + bool bghistvalid; - void draw (int handle); - void interpolate (); - void findClosestPoint(); - CursorShape motionNotify(CursorShape type, double minDistanceX, double minDistanceY, int num); - std::vector get_vector (int veclen); - void get_LUT (LUTf &lut); - // Get the cursor position and unclamped position from the curve given an X value ; BEWARE: can be time consuming, use with care - void getCursorPositionFromCurve(float x); - void getCursorPositionFromCurve(int x); - // Get the cursor position and unclamped value depending on cursor's position in the graph - void getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifierKey); + void draw (int handle); + void interpolate (); + void findClosestPoint(); + CursorShape motionNotify(CursorShape type, double minDistanceX, double minDistanceY, int num); + std::vector get_vector (int veclen); + void get_LUT (LUTf &lut); + // Get the cursor position and unclamped position from the curve given an X value ; BEWARE: can be time consuming, use with care + void getCursorPositionFromCurve(float x); + void getCursorPositionFromCurve(int x); + // Get the cursor position and unclamped value depending on cursor's position in the graph + void getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifierKey); - public: - MyDiagonalCurve (); - ~MyDiagonalCurve (); - std::vector getPoints (); - void setPoints (const std::vector& p); - void setType (DiagonalCurveType t); - bool handleEvents (GdkEvent* event); - void setActiveParam (int ac); - void reset (const std::vector &resetCurve, double identityValue=0.5); - void updateBackgroundHistogram (LUTu & hist); +public: + MyDiagonalCurve (); + ~MyDiagonalCurve (); + std::vector getPoints (); + void setPoints (const std::vector& p); + void setType (DiagonalCurveType t); + bool handleEvents (GdkEvent* event); + void setActiveParam (int ac); + void reset (const std::vector &resetCurve, double identityValue = 0.5); + void updateBackgroundHistogram (LUTu & hist); - void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); - void pipetteButton1Released(EditDataProvider *provider); - void pipetteDrag(EditDataProvider *provider, int modifierKey); + void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey); + void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + void pipetteButton1Released(EditDataProvider *provider); + void pipetteDrag(EditDataProvider *provider, int modifierKey); - virtual void setPos(double pos, int chanIdx); - virtual void stopNumericalAdjustment(); + virtual void setPos(double pos, int chanIdx); + virtual void stopNumericalAdjustment(); }; #endif diff --git a/rtgui/myflatcurve.cc b/rtgui/myflatcurve.cc index 77678eb03..474756834 100644 --- a/rtgui/myflatcurve.cc +++ b/rtgui/myflatcurve.cc @@ -7,7 +7,7 @@ * 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 @@ -21,7 +21,8 @@ #include #include -MyFlatCurve::MyFlatCurve () { +MyFlatCurve::MyFlatCurve () +{ graphW = get_allocation().get_width() - RADIUS * 2; graphH = get_allocation().get_height() - RADIUS * 2; @@ -51,20 +52,23 @@ MyFlatCurve::MyFlatCurve () { /*MyFlatCurve::~MyFlatCurve () { }*/ -std::vector MyFlatCurve::get_vector (int veclen) { +std::vector MyFlatCurve::get_vector (int veclen) +{ // Create the output variable std::vector convertedValues; // Get the curve control points std::vector curveDescr = getPoints (); - rtengine::FlatCurve rtcurve(curveDescr, periodic, veclen*1.2 > 5000 ? 5000 : veclen*1.2); + rtengine::FlatCurve rtcurve(curveDescr, periodic, veclen * 1.2 > 5000 ? 5000 : veclen * 1.2); // Create the sample values that will be converted std::vector samples; samples.resize (veclen); - for (int i = 0; i < veclen; i++) + + for (int i = 0; i < veclen; i++) { samples.at(i) = (double) i / (veclen - 1.0); + } // Converting the values rtcurve.getVal (samples, convertedValues); @@ -73,28 +77,32 @@ std::vector MyFlatCurve::get_vector (int veclen) { return convertedValues; } -void MyFlatCurve::get_LUT (LUTf &lut) { +void MyFlatCurve::get_LUT (LUTf &lut) +{ int size = lut.getSize(); // Get the curve control points std::vector curveDescr = getPoints (); - rtengine::FlatCurve rtcurve(curveDescr, periodic, lut.getUpperBound()*1.2 > 5000 ? 5000 : lut.getUpperBound()*1.2); + rtengine::FlatCurve rtcurve(curveDescr, periodic, lut.getUpperBound() * 1.2 > 5000 ? 5000 : lut.getUpperBound() * 1.2); double t; double maxVal = double(lut.getUpperBound()); + for (int i = 0; i < size; i++) { t = double(i) / maxVal; lut[i] = rtcurve.getVal (t); } + return; } -void MyFlatCurve::interpolate () { +void MyFlatCurve::interpolate () +{ prevGraphW = graphW; prevGraphH = graphH; - int nbPoints = graphW-2; + int nbPoints = graphW - 2; point(nbPoints); get_LUT (point); upoint.reset (); @@ -103,22 +111,27 @@ void MyFlatCurve::interpolate () { curveIsDirty = false; } -void MyFlatCurve::draw () { +void MyFlatCurve::draw () +{ if (!isDirty()) { return; } Glib::RefPtr win = get_window(); - if (!surfaceCreated() || !win) + + if (!surfaceCreated() || !win) { return; + } // re-calculate curve if dimensions changed int currPointSize = point.getUpperBound(); - if (curveIsDirty || /*prevGraphW != graphW || prevGraphH != graphH ||*/ (currPointSize==200 && (graphW-3>200)) || (currPointSize>200 && (graphW-2<=200 || graphW-3!=currPointSize))) - interpolate (); - double innerW = double(graphW-2); - double innerH = double(graphH-2); + if (curveIsDirty || /*prevGraphW != graphW || prevGraphH != graphH ||*/ (currPointSize == 200 && (graphW - 3 > 200)) || (currPointSize > 200 && (graphW - 2 <= 200 || graphW - 3 != currPointSize))) { + interpolate (); + } + + double innerW = double(graphW - 2); + double innerH = double(graphH - 2); Gtk::StateType state = !is_sensitive() ? Gtk::STATE_INSENSITIVE : Gtk::STATE_NORMAL; @@ -140,8 +153,8 @@ void MyFlatCurve::draw () { std::valarray ds (1); ds[0] = 4; cr->set_dash (ds, 0); - cr->move_to (double(graphX)+1.5, double(graphY-graphH/2)-0.5); - cr->rel_line_to (double(graphW-3), 0.); + cr->move_to (double(graphX) + 1.5, double(graphY - graphH / 2) - 0.5); + cr->rel_line_to (double(graphW - 3), 0.); cr->stroke (); cr->unset_dash (); @@ -155,13 +168,13 @@ void MyFlatCurve::draw () { // first the background int bWidth = getBarWidth(); BackBuffer *bb = this; - leftBar->setDrawRectangle(win, 1, graphY-graphH+1, bWidth-2, graphH-2); + leftBar->setDrawRectangle(win, 1, graphY - graphH + 1, bWidth - 2, graphH - 2); leftBar->expose(bb); // now the border c = style->get_dark (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->rectangle(0.5, graphY-graphH+0.5, bWidth-1, graphH-1); + cr->rectangle(0.5, graphY - graphH + 0.5, bWidth - 1, graphH - 1); cr->stroke(); } @@ -170,13 +183,13 @@ void MyFlatCurve::draw () { // first the background int bWidth = getBarWidth(); BackBuffer *bb = this; - bottomBar->setDrawRectangle(win, graphX+1, graphY+CBAR_MARGIN+1, graphW-2, bWidth-2); + bottomBar->setDrawRectangle(win, graphX + 1, graphY + CBAR_MARGIN + 1, graphW - 2, bWidth - 2); bottomBar->expose(bb); // now the border c = style->get_dark (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->rectangle(graphX+0.5, graphY+CBAR_MARGIN+0.5, graphW-1, bWidth-1 ); + cr->rectangle(graphX + 0.5, graphY + CBAR_MARGIN + 0.5, graphW - 1, bWidth - 1 ); cr->stroke(); } @@ -186,37 +199,49 @@ void MyFlatCurve::draw () { if (pipetteR > -1.f || pipetteG > -1.f || pipetteB > -1.f) { cr->set_line_width (0.75); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - int n=0; - if (pipetteR > -1.f) ++n; - if (pipetteG > -1.f) ++n; - if (pipetteB > -1.f) ++n; + int n = 0; + + if (pipetteR > -1.f) { + ++n; + } + + if (pipetteG > -1.f) { + ++n; + } + + if (pipetteB > -1.f) { + ++n; + } if (n > 1) { if (pipetteR > -1.f) { cr->set_source_rgba (1., 0., 0., 0.5); // WARNING: assuming that red values are stored in pipetteR, which might not be the case! - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteR, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteR, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); } + if (pipetteG > -1.f) { cr->set_source_rgba (0., 1., 0., 0.5); // WARNING: assuming that green values are stored in pipetteG, which might not be the case! - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteG, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteG, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); } + if (pipetteB > -1.f) { cr->set_source_rgba (0., 0., 1., 0.5); // WARNING: assuming that blue values are stored in pipetteB, which might not be the case! - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteB, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteB, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); } } + if (pipetteVal > -1.f) { cr->set_line_width (2.); c = style->get_fg (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->move_to (double(graphX)+1.5 + double(graphW-3)*pipetteVal, double(graphY)-1.5); - cr->rel_line_to (0, double(-graphH+3)); + cr->move_to (double(graphX) + 1.5 + double(graphW - 3)*pipetteVal, double(graphY) - 1.5); + cr->rel_line_to (0, double(-graphH + 3)); cr->stroke (); cr->set_line_width (1.); } @@ -226,72 +251,76 @@ void MyFlatCurve::draw () { if (colorProvider) { //if (curve.type!=FCT_Parametric) - for (int i=0; i<(int)curve.x.size(); ++i) { + for (int i = 0; i < (int)curve.x.size(); ++i) { - if (curve.x.at(i) != -1.) { - int coloredLineWidth = min( max(75,graphW)/75, 8 ); + if (curve.x.at(i) != -1.) { + int coloredLineWidth = min( max(75, graphW) / 75, 8 ); - cr->set_line_width (coloredLineWidth); - colorProvider->colorForValue(curve.x.at(i), curve.y.at(i), CCET_VERTICAL_BAR, colorCallerId, this); - cr->set_source_rgb (ccRed, ccGreen, ccBlue); + cr->set_line_width (coloredLineWidth); + colorProvider->colorForValue(curve.x.at(i), curve.y.at(i), CCET_VERTICAL_BAR, colorCallerId, this); + cr->set_source_rgb (ccRed, ccGreen, ccBlue); - if ( i==lit_point && (editedHandle&(FCT_EditedHandle_CPointUD|FCT_EditedHandle_CPoint|FCT_EditedHandle_CPointX)) ) { - cr->set_line_width (2*coloredLineWidth); + if ( i == lit_point && (editedHandle & (FCT_EditedHandle_CPointUD | FCT_EditedHandle_CPoint | FCT_EditedHandle_CPointX)) ) { + cr->set_line_width (2 * coloredLineWidth); + } + + cr->move_to (double(graphX) + 1 + innerW * curve.x.at(i), double(graphY - 1)); + cr->rel_line_to (0., -innerH); + cr->stroke (); + cr->set_line_width (coloredLineWidth); + + // draw the lit_point's horizontal line + bool drawHLine = false; + + if (edited_point > -1) { + if (i == edited_point) { + cr->set_line_width (2 * coloredLineWidth); + drawHLine = true; } - cr->move_to (double(graphX)+1 + innerW*curve.x.at(i), double(graphY-1)); - cr->rel_line_to (0., -innerH); - cr->stroke (); - cr->set_line_width (coloredLineWidth); - - // draw the lit_point's horizontal line - bool drawHLine = false; - if (edited_point>-1) { - if (i == edited_point) { - cr->set_line_width (2*coloredLineWidth); + } else if (i == lit_point) { + if ( (area & (FCT_Area_H | FCT_Area_V | FCT_Area_Point)) || editedHandle == FCT_EditedHandle_CPointUD) { + if (editedHandle & (FCT_EditedHandle_CPointUD | FCT_EditedHandle_CPoint | FCT_EditedHandle_CPointY)) { + cr->set_line_width (2 * coloredLineWidth); drawHLine = true; } } - else if (i == lit_point) { - if ( (area&(FCT_Area_H|FCT_Area_V|FCT_Area_Point)) || editedHandle==FCT_EditedHandle_CPointUD) { - if (editedHandle&(FCT_EditedHandle_CPointUD|FCT_EditedHandle_CPoint|FCT_EditedHandle_CPointY)) { - cr->set_line_width (2*coloredLineWidth); - drawHLine = true; - } - } - } - if (drawHLine) { - int point = edited_point>-1 ? edited_point : lit_point; - colorProvider->colorForValue(curve.x.at(i), curve.y.at(i), CCET_HORIZONTAL_BAR, colorCallerId, this); - cr->set_source_rgb (ccRed, ccGreen, ccBlue); + } - cr->move_to (double(graphX+1) , double(graphY-1) - innerH*curve.y.at(point)); - cr->rel_line_to (innerW, 0.); - cr->stroke (); - } + if (drawHLine) { + int point = edited_point > -1 ? edited_point : lit_point; + colorProvider->colorForValue(curve.x.at(i), curve.y.at(i), CCET_HORIZONTAL_BAR, colorCallerId, this); + cr->set_source_rgb (ccRed, ccGreen, ccBlue); + + cr->move_to (double(graphX + 1) , double(graphY - 1) - innerH * curve.y.at(point)); + cr->rel_line_to (innerW, 0.); + cr->stroke (); } } + } + // endif cr->set_line_width (1.0); - } - else { + } else { cr->set_source_rgb (0.5, 0.0, 0.0); - if (edited_point>-1 || ((lit_point>-1) && ((area&(FCT_Area_H|FCT_Area_V|FCT_Area_Point)) || editedHandle==FCT_EditedHandle_CPointUD)) ) { + if (edited_point > -1 || ((lit_point > -1) && ((area & (FCT_Area_H | FCT_Area_V | FCT_Area_Point)) || editedHandle == FCT_EditedHandle_CPointUD)) ) { // draw the lit_point's vertical line - if (edited_point>-1 || (editedHandle&(FCT_EditedHandle_CPointUD|FCT_EditedHandle_CPoint|FCT_EditedHandle_CPointY))) { + if (edited_point > -1 || (editedHandle & (FCT_EditedHandle_CPointUD | FCT_EditedHandle_CPoint | FCT_EditedHandle_CPointY))) { cr->set_line_width (2.0); } - int point = edited_point>-1 ? edited_point : lit_point; - cr->move_to (double(graphX)+1 + innerW*curve.x.at(point), double(graphY-1)); + + int point = edited_point > -1 ? edited_point : lit_point; + cr->move_to (double(graphX) + 1 + innerW * curve.x.at(point), double(graphY - 1)); cr->rel_line_to (0., -innerH); cr->stroke (); cr->set_line_width (1.0); // draw the lit_point's horizontal line - if (editedHandle&(FCT_EditedHandle_CPointUD|FCT_EditedHandle_CPoint|FCT_EditedHandle_CPointY)) { + if (editedHandle & (FCT_EditedHandle_CPointUD | FCT_EditedHandle_CPoint | FCT_EditedHandle_CPointY)) { cr->set_line_width (2.0); } - cr->move_to (double(graphX+1) , double(graphY-1) - innerH*curve.y.at(point)); + + cr->move_to (double(graphX + 1) , double(graphY - 1) - innerH * curve.y.at(point)); cr->rel_line_to (innerW, 0.); cr->stroke (); cr->set_line_width (1.0); @@ -303,13 +332,14 @@ void MyFlatCurve::draw () { // draw the graph's borders: c = style->get_dark (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->rectangle(double(graphX)+0.5, double(graphY)-0.5, double(graphW-1), double(-graphH+1)); + cr->rectangle(double(graphX) + 0.5, double(graphY) - 0.5, double(graphW - 1), double(-graphH + 1)); cr->stroke (); double lineMinLength = 1. / graphW * SQUARE * 0.9; - if (tanHandlesDisplayed && lit_point!=-1 && getHandles(lit_point) && curve.x.at(lit_point)!=-1.) { - double x = double(graphX+1) + innerW*curve.x.at(lit_point); - double y = double(graphY) - innerH*curve.y.at(lit_point); + + if (tanHandlesDisplayed && lit_point != -1 && getHandles(lit_point) && curve.x.at(lit_point) != -1.) { + double x = double(graphX + 1) + innerW * curve.x.at(lit_point); + double y = double(graphY) - innerH * curve.y.at(lit_point); double x2; double square; bool crossingTheFrame; @@ -321,27 +351,33 @@ void MyFlatCurve::draw () { // draw tangential vectors crossingTheFrame = false; + // We display the line only if it's longer than the handle knot half-size... if (leftTanX < -0.00001) { leftTanX += 1.0; crossingTheFrame = true; } - x2 = double(graphX+1) + innerW*leftTanX; + + x2 = double(graphX + 1) + innerW * leftTanX; + if (curve.x.at(lit_point) - leftTanX > lineMinLength || crossingTheFrame) { // The left tangential vector reappear on the right side // draw the line cr->move_to (x, y); + if (crossingTheFrame) { - cr->line_to (double(graphX+1), y); + cr->line_to (double(graphX + 1), y); cr->stroke (); cr->move_to (double(graphX) + innerW, y); } + cr->line_to (x2, y); cr->stroke (); } + // draw tangential knot - square = area == FCT_Area_LeftTan ? SQUARE*2. : SQUARE; - cr->rectangle(x2-square, y-square, 2.*square, 2.*square); + square = area == FCT_Area_LeftTan ? SQUARE * 2. : SQUARE; + cr->rectangle(x2 - square, y - square, 2.*square, 2.*square); cr->fill(); // right handle is blue @@ -351,103 +387,113 @@ void MyFlatCurve::draw () { // draw tangential vectors crossingTheFrame = false; + // We display the line only if it's longer than the handle knot half-size... if (rightTanX > 1.00001) { rightTanX -= 1.0; crossingTheFrame = true; } - x2 = double(graphX+1) +innerW*rightTanX; + + x2 = double(graphX + 1) + innerW * rightTanX; + if (rightTanX - curve.x.at(lit_point) > lineMinLength || crossingTheFrame) { // The left tangential vector reappear on the right side // draw the line cr->move_to (x, y); + if (crossingTheFrame) { cr->line_to (double(graphX) + innerW, y); cr->stroke (); - cr->move_to (double(graphX+1), y); + cr->move_to (double(graphX + 1), y); } + cr->line_to (x2, y); cr->stroke (); } + // draw tangential knot - square = area == FCT_Area_RightTan ? SQUARE*2. : SQUARE; - cr->rectangle(x2-square, y-square, 2.*square, 2.*square); + square = area == FCT_Area_RightTan ? SQUARE * 2. : SQUARE; + cr->rectangle(x2 - square, y - square, 2.*square, 2.*square); cr->fill(); } // draw curve c = style->get_fg (state); cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - float graphH_ = float(graphH-3); - float graphX_ = float(graphX)+1.5; - float graphY_ = float(graphY)-1.5; - cr->move_to (graphX_, getVal(point, 0)*-graphH_+graphY_); - for (int i=1; iline_to (float(i)+graphX_, getVal(point, i)*-graphH_+graphY_); + float graphH_ = float(graphH - 3); + float graphX_ = float(graphX) + 1.5; + float graphY_ = float(graphY) - 1.5; + cr->move_to (graphX_, getVal(point, 0) * -graphH_ + graphY_); + + for (int i = 1; i < graphW - 2; ++i) { + cr->line_to (float(i) + graphX_, getVal(point, i) * -graphH_ + graphY_); + } + cr->stroke (); // draw bullets //if (curve.type!=FCT_Parametric) - for (int i = 0; i < (int)curve.x.size(); ++i) { - if (curve.x.at(i) != -1.) { - if (i == edited_point) + for (int i = 0; i < (int)curve.x.size(); ++i) { + if (curve.x.at(i) != -1.) { + if (i == edited_point) { + cr->set_source_rgb (1.0, 0.0, 0.0); + } else if (i == lit_point) { + if (colorProvider && edited_point == -1) { + colorProvider->colorForValue(curve.x.at(i), curve.y.at(i), CCET_POINT, colorCallerId, this); + cr->set_source_rgb (ccRed, ccGreen, ccBlue); + } else { cr->set_source_rgb (1.0, 0.0, 0.0); - else if (i == lit_point) { - if (colorProvider && edited_point==-1) { - colorProvider->colorForValue(curve.x.at(i), curve.y.at(i), CCET_POINT, colorCallerId, this); - cr->set_source_rgb (ccRed, ccGreen, ccBlue); - } - else - cr->set_source_rgb (1.0, 0.0, 0.0); } - else if (i == snapToElmt || i == edited_point) - cr->set_source_rgb (1.0, 0.0, 0.0); - else if (curve.y.at(i) == 0.5) - cr->set_source_rgb (0.0, 0.5, 0.0); - else - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - - double x = double(graphX+1) + innerW * curve.x.at(i); // project (curve.x.at(i), 0, 1, graphW); - double y = double(graphY-1) - innerH * curve.y.at(i); // project (curve.y.at(i), 0, 1, graphH); - - cr->arc (x, y, (double)RADIUS, 0, 2*M_PI); - cr->fill (); - - if (i == edited_point) { - cr->set_source_rgb (1.0, 0.0, 0.0); - cr->set_line_width(2.); - cr->arc (x, y, RADIUS+3.5, 0, 2*M_PI); - cr->stroke(); - cr->set_line_width(1.); - } - + } else if (i == snapToElmt || i == edited_point) { + cr->set_source_rgb (1.0, 0.0, 0.0); + } else if (curve.y.at(i) == 0.5) { + cr->set_source_rgb (0.0, 0.5, 0.0); + } else { + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); } + + double x = double(graphX + 1) + innerW * curve.x.at(i); // project (curve.x.at(i), 0, 1, graphW); + double y = double(graphY - 1) - innerH * curve.y.at(i); // project (curve.y.at(i), 0, 1, graphH); + + cr->arc (x, y, (double)RADIUS, 0, 2 * M_PI); + cr->fill (); + + if (i == edited_point) { + cr->set_source_rgb (1.0, 0.0, 0.0); + cr->set_line_width(2.); + cr->arc (x, y, RADIUS + 3.5, 0, 2 * M_PI); + cr->stroke(); + cr->set_line_width(1.); + } + } + } + // endif // draw the left and right tangent handles if (tanHandlesDisplayed) { - double halfSquareSizeX = minDistanceX/2.; - double halfSquareSizeY = minDistanceY/2.; + double halfSquareSizeX = minDistanceX / 2.; + double halfSquareSizeY = minDistanceY / 2.; // LEFT handle // yellow cr->set_source_rgb (1.0, 1.0, 0.0); - cr->rectangle(double(graphX+1) + innerW*(leftTanHandle.centerX-halfSquareSizeX), - double(graphY-1) - innerH*(leftTanHandle.centerY+halfSquareSizeY), - innerW*minDistanceX, - innerW*minDistanceY); + cr->rectangle(double(graphX + 1) + innerW * (leftTanHandle.centerX - halfSquareSizeX), + double(graphY - 1) - innerH * (leftTanHandle.centerY + halfSquareSizeY), + innerW * minDistanceX, + innerW * minDistanceY); cr->fill(); // RIGHT handle // blue cr->set_source_rgb (0.0, 0.0, 1.0); - cr->rectangle(double(graphX+1) + innerW*(rightTanHandle.centerX-halfSquareSizeX), - double(graphY-1) - innerH*(rightTanHandle.centerY+halfSquareSizeY), - innerW*minDistanceX, - innerW*minDistanceY); + cr->rectangle(double(graphX + 1) + innerW * (rightTanHandle.centerX - halfSquareSizeX), + double(graphY - 1) - innerH * (rightTanHandle.centerY + halfSquareSizeY), + innerW * minDistanceX, + innerW * minDistanceY); cr->fill(); } @@ -458,1138 +504,1273 @@ void MyFlatCurve::draw () { /* * Return the X1, X2, Y position of the tangential handles. */ -bool MyFlatCurve::getHandles(int n) { - int N = curve.x.size(); - double prevX, nextX; - double x, leftTan, rightTan; +bool MyFlatCurve::getHandles(int n) +{ + int N = curve.x.size(); + double prevX, nextX; + double x, leftTan, rightTan; - if (n == -1) return false; + if (n == -1) { + return false; + } - x = curve.x.at(n); - leftTan = curve.leftTangent.at(n); - rightTan = curve.rightTangent.at(n); + x = curve.x.at(n); + leftTan = curve.leftTangent.at(n); + rightTan = curve.rightTangent.at(n); - if (!n) { - // first point, the left handle is then computed with the last point's right handle - prevX = curve.x.at(N-1)-1.0; - nextX = curve.x.at(n+1); - } - else if (n == N-1) { - // last point, the right handle is then computed with the first point's left handle - prevX = curve.x.at(n-1); - nextX = curve.x.at(0)+1.0; - } - else { - // last point, the right handle is then computed with the first point's left handle - prevX = curve.x.at(n-1); - nextX = curve.x.at(n+1); - } + if (!n) { + // first point, the left handle is then computed with the last point's right handle + prevX = curve.x.at(N - 1) - 1.0; + nextX = curve.x.at(n + 1); + } else if (n == N - 1) { + // last point, the right handle is then computed with the first point's left handle + prevX = curve.x.at(n - 1); + nextX = curve.x.at(0) + 1.0; + } else { + // last point, the right handle is then computed with the first point's left handle + prevX = curve.x.at(n - 1); + nextX = curve.x.at(n + 1); + } - if (leftTan == 0.0) leftTanX = x; - else if (leftTan == 1.0) leftTanX = prevX; - else { - leftTanX = (prevX - x) * leftTan + x; - } + if (leftTan == 0.0) { + leftTanX = x; + } else if (leftTan == 1.0) { + leftTanX = prevX; + } else { + leftTanX = (prevX - x) * leftTan + x; + } - if (rightTan == 0.0) rightTanX = x; - else if (rightTan == 1.0) rightTanX = nextX; - else { - rightTanX = (nextX - x) * rightTan + x; - } - return true; + if (rightTan == 0.0) { + rightTanX = x; + } else if (rightTan == 1.0) { + rightTanX = nextX; + } else { + rightTanX = (nextX - x) * rightTan + x; + } + + return true; } -bool MyFlatCurve::handleEvents (GdkEvent* event) { - - CursorShape new_type = cursor_type; - std::vector::iterator itx, ity, itlt, itrt; - - snapToElmt = -100; - bool retval = false; - int num = (int)curve.x.size(); - - /* graphW and graphH are the size of the graph */ - calcDimensions(); - - if ((graphW < 0) || (graphH < 0)) - return false; - - minDistanceX = double(MIN_DISTANCE) / double(graphW-1); - minDistanceY = double(MIN_DISTANCE) / double(graphH-1); - - switch (event->type) { - case Gdk::CONFIGURE: { - // Happen when the the window is resized - if (sized & (RS_Pending | RS_Force)) { - set_size_request(-1, calcDimensions()); - sized = RS_Done; - } - retval = true; - break; - } - case Gdk::EXPOSE: - { - Glib::RefPtr win = get_window(); - if (sized & (RS_Pending | RS_Force)) { - set_size_request(-1, calcDimensions()); - } - sized = RS_Pending; - // setDrawRectangle will allocate the backbuffer Surface - if (setDrawRectangle(win, 0, 0, get_allocation().get_width(), get_allocation().get_height())) { - setDirty(true); - if (prevGraphW > 200 || graphW > 200) - curveIsDirty = true; - } - draw (); - GdkRectangle *rectangle = &(event->expose.area); - copySurface(win, rectangle); - - retval = true; - break; - } - - case Gdk::BUTTON_PRESS: - if (edited_point==-1) { //curve.type!=FCT_Parametric) { - if (event->button.button == 1) { - buttonPressed = true; - add_modal_grab (); - - // get the pointer position - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - getMouseOverArea(); - - // hide the tangent handles - tanHandlesDisplayed = false; - - // Action on BUTTON_PRESS and no edited point - switch (area) { - - case (FCT_Area_Insertion): - new_type = CSMove; - - /* insert a new control point */ - if (num > 0) { - if (clampedX > curve.x.at(closest_point)) - ++closest_point; - } - itx = curve.x.begin(); - ity = curve.y.begin(); - itlt = curve.leftTangent.begin(); - itrt = curve.rightTangent.begin(); - for (int i=0; ibutton.button == 3) { - /* get the pointer position */ - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - getMouseOverArea(); - if (lit_point>-1 && lit_point!=edited_point) { - if (editedHandle == FCT_EditedHandle_None) { - if (area == FCT_Area_Point || area == FCT_Area_V) { - // the cursor is close to an existing point - if (!coordinateAdjuster->is_visible()) - coordinateAdjuster->showMe(this); - - new_type = CSArrow; - tanHandlesDisplayed = false; - edited_point = lit_point; - setDirty(true); - draw (); - std::vector newBoundaries(4); - unsigned int size = curve.x.size(); - if (edited_point == 0) { newBoundaries.at(0).minVal = 0.; newBoundaries.at(0).maxVal = curve.x.at(1); } - else if (edited_point == size-1) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = 1.; } - else if (curve.x.size() > 2) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = curve.x.at(edited_point+1); } - newBoundaries.at(1).minVal = 0.; newBoundaries.at(1).maxVal = 1.; - newBoundaries.at(2).minVal = 0.; newBoundaries.at(2).maxVal = 1.; - newBoundaries.at(3).minVal = 0.; newBoundaries.at(3).maxVal = 1.; - retval = true; - editedPos.at(0) = curve.x.at(edited_point); - editedPos.at(1) = curve.y.at(edited_point); - editedPos.at(2) = curve.leftTangent.at(edited_point); - editedPos.at(3) = curve.rightTangent.at(edited_point); - coordinateAdjuster->setPos(editedPos); - coordinateAdjuster->startNumericalAdjustment(newBoundaries); - } - } - } - retval = true; - } - if (buttonPressed) retval = true; - } - else { // if (edited_point > -1) - if (event->button.button == 3) { - // do we edit another point? - /* get the pointer position */ - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - getMouseOverArea(); - if (area == FCT_Area_Point || area == FCT_Area_V) { - // the cursor is close to an existing point - if (lit_point != edited_point) { - edited_point = lit_point; - setDirty(true); - draw (); - std::vector newBoundaries(4); - unsigned int size = curve.x.size(); - if (edited_point == 0) { newBoundaries.at(0).minVal = 0.; newBoundaries.at(0).maxVal = curve.x.at(1); } - else if (edited_point == size-1) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = 1.; } - else if (curve.x.size() > 2) { newBoundaries.at(0).minVal = curve.x.at(edited_point-1); newBoundaries.at(0).maxVal = curve.x.at(edited_point+1); } - newBoundaries.at(1).minVal = 0.; newBoundaries.at(1).maxVal = 1.; - newBoundaries.at(2).minVal = 0.; newBoundaries.at(2).maxVal = 1.; - newBoundaries.at(3).minVal = 0.; newBoundaries.at(3).maxVal = 1.; - editedPos.at(0) = curve.x.at(edited_point); - editedPos.at(1) = curve.y.at(edited_point); - editedPos.at(2) = curve.leftTangent.at(edited_point); - editedPos.at(3) = curve.rightTangent.at(edited_point); - coordinateAdjuster->switchAdjustedPoint(editedPos, newBoundaries); - retval = true; - } - } - else if (area == FCT_Area_Insertion) { - // the cursor is inside the graph but away from existing points - new_type = CSPlus; - curveIsDirty = true; - stopNumericalAdjustment(); - } - } - } - break; - - case Gdk::BUTTON_RELEASE: - if (edited_point==-1) { //curve.type!=FCT_Parametric) { - if (buttonPressed && event->button.button == 1) { - int src, dst; - buttonPressed = false; - remove_modal_grab (); - - // Removing any deleted point if we were previously modifying the point position - if (editedHandle & (FCT_EditedHandle_CPoint|FCT_EditedHandle_CPointX|FCT_EditedHandle_CPointY)) { - /* delete inactive points: */ - itx = curve.x.begin(); - ity = curve.y.begin(); - itlt = curve.leftTangent.begin(); - itrt = curve.rightTangent.begin(); - for (src = dst = 0; src < num; ++src) - if (curve.x.at(src) >= 0.0) { - curve.x.at(dst) = curve.x.at(src); - curve.y.at(dst) = curve.y.at(src); - curve.leftTangent.at(dst) = curve.leftTangent.at(src); - curve.rightTangent.at(dst) = curve.rightTangent.at(src); - ++dst; - ++itx; - ++ity; - ++itlt; - ++itrt; - } - if (dst < src) { - - // curve cleanup - curve.x.erase (itx, curve.x.end()); - curve.y.erase (ity, curve.y.end()); - curve.leftTangent.erase (itlt, curve.leftTangent.end()); - curve.rightTangent.erase (itrt, curve.rightTangent.end()); - if (curve.x.empty()) { - curve.x.push_back (0.5); - curve.y.push_back (0.5); - curve.leftTangent.push_back (0.3); - curve.rightTangent.push_back (0.3); - curveIsDirty = true; - } - } - } - - editedHandle = FCT_EditedHandle_None; - lit_point = -1; - - // get the pointer position - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - getMouseOverArea(); - - switch (area) { - - case (FCT_Area_Insertion): - new_type = CSArrow; - break; - - case (FCT_Area_Point): - new_type = CSMove; - break; - - case (FCT_Area_H): - new_type = CSResizeHeight; - break; - - case (FCT_Area_V): - new_type = CSMove; - break; - - case (FCT_Area_LeftTan): - new_type = CSEmpty; - break; - - case (FCT_Area_RightTan): - new_type = CSEmpty; - break; - - default: - break; - } - - setDirty(true); - draw (); - retval = true; - //notifyListener (); - } - } - break; - - case Gdk::MOTION_NOTIFY: - if (curve.type == FCT_Linear || curve.type == FCT_MinMaxCPoints) { - - int previous_lit_point = lit_point; - enum MouseOverAreas prevArea = area; - - snapToMinDistY = snapToMinDistX = 10.; - snapToValY = snapToValX = 0.; - snapToElmt = -100; - - // get the pointer position - getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint!=0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); - getMouseOverArea(); - - if (editedHandle == FCT_EditedHandle_CPointUD) { - double dX = deltaX; - double dY = deltaY; - if (dX < 0.) dX = -dX; - if (dY < 0.) dY = -dY; - if (dX > dY) { - editedHandle = FCT_EditedHandle_CPointX; - area = FCT_Area_V; - new_type = CSResizeWidth; - } - else { - editedHandle = FCT_EditedHandle_CPointY; - area = FCT_Area_H; - new_type = CSResizeHeight; - } - } - - switch (editedHandle) { - - case (FCT_EditedHandle_None): { - - if ((lit_point != -1 && previous_lit_point != lit_point) && (area&(FCT_Area_V|FCT_Area_Point)) && edited_point==-1) { - - bool sameSide = false; - - // display the handles - tanHandlesDisplayed = true; - - if (curve.x.at(lit_point) < 3.*minDistanceX) { - // lit_point too near of the left border -> both handles are displayed on the right of the vertical line - rightTanHandle.centerX = leftTanHandle.centerX = curve.x.at(lit_point) + 2.*minDistanceX; - sameSide = true; - } - else if (curve.x.at(lit_point) > 1.-3.*minDistanceX) { - // lit_point too near of the left border -> both handles are displayed on the right of the vertical line - rightTanHandle.centerX = leftTanHandle.centerX = curve.x.at(lit_point) - 2.*minDistanceX; - sameSide = true; - } - else { - leftTanHandle.centerX = curve.x.at(lit_point) - 2.*minDistanceX; - rightTanHandle.centerX = curve.x.at(lit_point) + 2.*minDistanceX; - } - if (sameSide) { - if (clampedY > 1.-2.*minDistanceY) { - // lit_point too near of the top border - leftTanHandle.centerY = 1. - minDistanceY; - rightTanHandle.centerY = 1. - 3.*minDistanceY; - } - else if (clampedY < 2.*minDistanceY) { - // lit_point too near of the bottom border - leftTanHandle.centerY = 3.*minDistanceY; - rightTanHandle.centerY = minDistanceY; - } - else { - leftTanHandle.centerY = clampedY + minDistanceY; - rightTanHandle.centerY = clampedY - minDistanceY; - } - } - else { - if (clampedY > 1.-minDistanceY) { - rightTanHandle.centerY = leftTanHandle.centerY = 1. - minDistanceY; - } - else if (clampedY < minDistanceY) { - rightTanHandle.centerY = leftTanHandle.centerY = minDistanceY; - } - else { - rightTanHandle.centerY = leftTanHandle.centerY = clampedY; - } - } - } - else if (lit_point == -1 || edited_point>-1) { - tanHandlesDisplayed = false; - } - - - if (edited_point==-1) { - switch (area) { - - case (FCT_Area_Insertion): - new_type = CSPlus; - break; - case (FCT_Area_Point): - //new_type = CSMove; - //break; - case (FCT_Area_V): - new_type = CSMove; - break; - case (FCT_Area_H): - new_type = CSResizeHeight; - break; - case (FCT_Area_LeftTan): - new_type = CSMoveLeft; - break; - case (FCT_Area_RightTan): - new_type = CSMoveRight; - break; - case (FCT_Area_None): - default: - new_type = CSArrow; - break; - } - } - - if ((lit_point != previous_lit_point) || (prevArea != area)) { - setDirty(true); - draw (); - } - - if (coordinateAdjuster->is_visible() && edited_point==-1) { - if (lit_point > -1) { - if (lit_point != previous_lit_point) { - editedPos.at(0) = curve.x.at(lit_point); - editedPos.at(1) = curve.y.at(lit_point); - editedPos.at(2) = curve.leftTangent.at(lit_point); - editedPos.at(3) = curve.rightTangent.at(lit_point); - } - coordinateAdjuster->setPos(editedPos); - } - else if (area == FCT_Area_Insertion) { - editedPos.at(0) = clampedX; - editedPos.at(1) = clampedY; - editedPos.at(2) = 0.; - editedPos.at(3) = 0.; - coordinateAdjuster->setPos(editedPos); - } - else { - editedPos.at(0) = editedPos.at(1) = editedPos.at(2) = editedPos.at(3) = 0; - coordinateAdjuster->setPos(editedPos); - } - } - break; - } - - case (FCT_EditedHandle_CPoint): - movePoint(true, true); - if (coordinateAdjuster->is_visible()) { - editedPos.at(0) = curve.x.at(lit_point); - editedPos.at(1) = curve.y.at(lit_point); - coordinateAdjuster->setPos(editedPos); - } - break; - - case (FCT_EditedHandle_CPointX): - movePoint(true, false); - if (coordinateAdjuster->is_visible()) { - editedPos.at(0) = curve.x.at(lit_point); - coordinateAdjuster->setPos(editedPos); - } - break; - - case (FCT_EditedHandle_CPointY): - movePoint(false, true); - if (coordinateAdjuster->is_visible()) { - editedPos.at(1) = curve.y.at(lit_point); - coordinateAdjuster->setPos(editedPos); - } - break; - - case (FCT_EditedHandle_LeftTan): { - double prevValue = curve.leftTangent.at(lit_point); - - ugpX -= deltaX*3; - ugpX = CLAMP(ugpX, 0., 1.); - if (snapTo) { - // since this handle can only move in one direction, we can reuse the snapCoordinateX mechanism - snapCoordinateX(0.0, ugpX); - snapCoordinateX(0.35, ugpX); - snapCoordinateX(0.5, ugpX); - snapCoordinateX(1.0, ugpX); - curve.leftTangent.at(lit_point) = snapToValX; - } - else { - curve.leftTangent.at(lit_point) = ugpX; - } - - if (curve.leftTangent.at(lit_point) != prevValue) { - curveIsDirty = true; - setDirty(true); - draw (); - notifyListener (); - if (coordinateAdjuster->is_visible()) { - editedPos.at(2) = curve.leftTangent.at(lit_point); - coordinateAdjuster->setPos(editedPos); - } - } - break; - } - - case (FCT_EditedHandle_RightTan): { - double prevValue = curve.rightTangent.at(lit_point); - - ugpX += deltaX*3; - ugpX = CLAMP(ugpX, 0., 1.); - if (snapTo) { - // since this handle can only move in one direction, we can reuse the snapCoordinateX mechanism - snapCoordinateX(0.0, ugpX); - snapCoordinateX(0.35, ugpX); - snapCoordinateX(0.5, ugpX); - snapCoordinateX(1.0, ugpX); - curve.rightTangent.at(lit_point) = snapToValX; - } - else { - curve.rightTangent.at(lit_point) = ugpX; - } - - if (curve.rightTangent.at(lit_point) != prevValue) { - curveIsDirty = true; - setDirty(true); - draw (); - notifyListener (); - editedPos.at(3) = curve.rightTangent.at(lit_point); - coordinateAdjuster->setPos(editedPos); - } - break; - } - - // already processed before the "switch" instruction - //case (FCT_EditedHandle_CPointUD): - - default: - break; - } - - if (edited_point==-1) { - if (lit_point == -1) { - editedPos.at(0) = editedPos.at(1) = editedPos.at(2) = editedPos.at(3) = 0; - } - else if (editedPos.at(0) != curve.x.at(lit_point) - || editedPos.at(1) != curve.y.at(lit_point) - || editedPos.at(2) != curve.leftTangent.at(lit_point) - || editedPos.at(3) != curve.rightTangent.at(lit_point)) - { - editedPos.at(0) = curve.x.at(lit_point); - editedPos.at(1) = curve.y.at(lit_point); - editedPos.at(2) = curve.leftTangent.at(lit_point); - editedPos.at(3) = curve.rightTangent.at(lit_point); - coordinateAdjuster->setPos(editedPos); - } - } - } - - retval = true; - break; - - case Gdk::LEAVE_NOTIFY: - // Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case - // The cursor will have to LEAVE another time after the drag... - if (editedHandle == FCT_EditedHandle_None) { - new_type = CSArrow; - lit_point = -1; - tanHandlesDisplayed = false; - pipetteR = pipetteG = pipetteB = -1.f; - setDirty(true); - draw (); - } - retval = true; - break; - - default: - break; - } - if (new_type != cursor_type) { - cursor_type = new_type; - cursorManager.setCursor(cursor_type); - } - return retval; +bool MyFlatCurve::handleEvents (GdkEvent* event) +{ + + CursorShape new_type = cursor_type; + std::vector::iterator itx, ity, itlt, itrt; + + snapToElmt = -100; + bool retval = false; + int num = (int)curve.x.size(); + + /* graphW and graphH are the size of the graph */ + calcDimensions(); + + if ((graphW < 0) || (graphH < 0)) { + return false; + } + + minDistanceX = double(MIN_DISTANCE) / double(graphW - 1); + minDistanceY = double(MIN_DISTANCE) / double(graphH - 1); + + switch (event->type) { + case Gdk::CONFIGURE: { + // Happen when the the window is resized + if (sized & (RS_Pending | RS_Force)) { + set_size_request(-1, calcDimensions()); + sized = RS_Done; + } + + retval = true; + break; + } + + case Gdk::EXPOSE: { + Glib::RefPtr win = get_window(); + + if (sized & (RS_Pending | RS_Force)) { + set_size_request(-1, calcDimensions()); + } + + sized = RS_Pending; + + // setDrawRectangle will allocate the backbuffer Surface + if (setDrawRectangle(win, 0, 0, get_allocation().get_width(), get_allocation().get_height())) { + setDirty(true); + + if (prevGraphW > 200 || graphW > 200) { + curveIsDirty = true; + } + } + + draw (); + GdkRectangle *rectangle = &(event->expose.area); + copySurface(win, rectangle); + + retval = true; + break; + } + + case Gdk::BUTTON_PRESS: + if (edited_point == -1) { //curve.type!=FCT_Parametric) { + if (event->button.button == 1) { + buttonPressed = true; + add_modal_grab (); + + // get the pointer position + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + getMouseOverArea(); + + // hide the tangent handles + tanHandlesDisplayed = false; + + // Action on BUTTON_PRESS and no edited point + switch (area) { + + case (FCT_Area_Insertion): + new_type = CSMove; + + /* insert a new control point */ + if (num > 0) { + if (clampedX > curve.x.at(closest_point)) { + ++closest_point; + } + } + + itx = curve.x.begin(); + ity = curve.y.begin(); + itlt = curve.leftTangent.begin(); + itrt = curve.rightTangent.begin(); + + for (int i = 0; i < closest_point; i++) { + itx++; + ity++; + itlt++; + itrt++; + } + + curve.x.insert (itx, 0); + curve.y.insert (ity, 0); + curve.leftTangent.insert (itlt, 0); + curve.rightTangent.insert (itrt, 0); + num++; + + if (mod_type & GDK_CONTROL_MASK) { + clampedY = point.getVal01(clampedX); + } + + // the graph is refreshed only if a new point is created + curve.x.at(closest_point) = clampedX; + curve.y.at(closest_point) = clampedY; + curve.leftTangent.at(closest_point) = 0.35; + curve.rightTangent.at(closest_point) = 0.35; + + curveIsDirty = true; + setDirty(true); + draw (); + notifyListener (); + + lit_point = closest_point; + + // point automatically activated + editedHandle = FCT_EditedHandle_CPoint; + ugpX = curve.x.at(lit_point); + ugpY = curve.y.at(lit_point); + break; + + case (FCT_Area_Point): + new_type = CSMove; + editedHandle = FCT_EditedHandle_CPoint; + ugpX = curve.x.at(lit_point); + ugpY = curve.y.at(lit_point); + break; + + case (FCT_Area_H): + case (FCT_Area_V): + new_type = CSMove; + editedHandle = FCT_EditedHandle_CPointUD; + ugpX = curve.x.at(lit_point); + ugpY = curve.y.at(lit_point); + break; + + case (FCT_Area_LeftTan): + new_type = CSEmpty; + editedHandle = FCT_EditedHandle_LeftTan; + ugpX = curve.leftTangent.at(lit_point); + break; + + case (FCT_Area_RightTan): + new_type = CSEmpty; + editedHandle = FCT_EditedHandle_RightTan; + ugpX = curve.rightTangent.at(lit_point); + break; + + default: + break; + } + } else if (event->button.button == 3) { + /* get the pointer position */ + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + getMouseOverArea(); + + if (lit_point > -1 && lit_point != edited_point) { + if (editedHandle == FCT_EditedHandle_None) { + if (area == FCT_Area_Point || area == FCT_Area_V) { + // the cursor is close to an existing point + if (!coordinateAdjuster->is_visible()) { + coordinateAdjuster->showMe(this); + } + + new_type = CSArrow; + tanHandlesDisplayed = false; + edited_point = lit_point; + setDirty(true); + draw (); + std::vector newBoundaries(4); + unsigned int size = curve.x.size(); + + if (edited_point == 0) { + newBoundaries.at(0).minVal = 0.; + newBoundaries.at(0).maxVal = curve.x.at(1); + } else if (edited_point == size - 1) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = 1.; + } else if (curve.x.size() > 2) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = curve.x.at(edited_point + 1); + } + + newBoundaries.at(1).minVal = 0.; + newBoundaries.at(1).maxVal = 1.; + newBoundaries.at(2).minVal = 0.; + newBoundaries.at(2).maxVal = 1.; + newBoundaries.at(3).minVal = 0.; + newBoundaries.at(3).maxVal = 1.; + retval = true; + editedPos.at(0) = curve.x.at(edited_point); + editedPos.at(1) = curve.y.at(edited_point); + editedPos.at(2) = curve.leftTangent.at(edited_point); + editedPos.at(3) = curve.rightTangent.at(edited_point); + coordinateAdjuster->setPos(editedPos); + coordinateAdjuster->startNumericalAdjustment(newBoundaries); + } + } + } + + retval = true; + } + + if (buttonPressed) { + retval = true; + } + } else { // if (edited_point > -1) + if (event->button.button == 3) { + // do we edit another point? + /* get the pointer position */ + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + getMouseOverArea(); + + if (area == FCT_Area_Point || area == FCT_Area_V) { + // the cursor is close to an existing point + if (lit_point != edited_point) { + edited_point = lit_point; + setDirty(true); + draw (); + std::vector newBoundaries(4); + unsigned int size = curve.x.size(); + + if (edited_point == 0) { + newBoundaries.at(0).minVal = 0.; + newBoundaries.at(0).maxVal = curve.x.at(1); + } else if (edited_point == size - 1) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = 1.; + } else if (curve.x.size() > 2) { + newBoundaries.at(0).minVal = curve.x.at(edited_point - 1); + newBoundaries.at(0).maxVal = curve.x.at(edited_point + 1); + } + + newBoundaries.at(1).minVal = 0.; + newBoundaries.at(1).maxVal = 1.; + newBoundaries.at(2).minVal = 0.; + newBoundaries.at(2).maxVal = 1.; + newBoundaries.at(3).minVal = 0.; + newBoundaries.at(3).maxVal = 1.; + editedPos.at(0) = curve.x.at(edited_point); + editedPos.at(1) = curve.y.at(edited_point); + editedPos.at(2) = curve.leftTangent.at(edited_point); + editedPos.at(3) = curve.rightTangent.at(edited_point); + coordinateAdjuster->switchAdjustedPoint(editedPos, newBoundaries); + retval = true; + } + } else if (area == FCT_Area_Insertion) { + // the cursor is inside the graph but away from existing points + new_type = CSPlus; + curveIsDirty = true; + stopNumericalAdjustment(); + } + } + } + + break; + + case Gdk::BUTTON_RELEASE: + if (edited_point == -1) { //curve.type!=FCT_Parametric) { + if (buttonPressed && event->button.button == 1) { + int src, dst; + buttonPressed = false; + remove_modal_grab (); + + // Removing any deleted point if we were previously modifying the point position + if (editedHandle & (FCT_EditedHandle_CPoint | FCT_EditedHandle_CPointX | FCT_EditedHandle_CPointY)) { + /* delete inactive points: */ + itx = curve.x.begin(); + ity = curve.y.begin(); + itlt = curve.leftTangent.begin(); + itrt = curve.rightTangent.begin(); + + for (src = dst = 0; src < num; ++src) + if (curve.x.at(src) >= 0.0) { + curve.x.at(dst) = curve.x.at(src); + curve.y.at(dst) = curve.y.at(src); + curve.leftTangent.at(dst) = curve.leftTangent.at(src); + curve.rightTangent.at(dst) = curve.rightTangent.at(src); + ++dst; + ++itx; + ++ity; + ++itlt; + ++itrt; + } + + if (dst < src) { + + // curve cleanup + curve.x.erase (itx, curve.x.end()); + curve.y.erase (ity, curve.y.end()); + curve.leftTangent.erase (itlt, curve.leftTangent.end()); + curve.rightTangent.erase (itrt, curve.rightTangent.end()); + + if (curve.x.empty()) { + curve.x.push_back (0.5); + curve.y.push_back (0.5); + curve.leftTangent.push_back (0.3); + curve.rightTangent.push_back (0.3); + curveIsDirty = true; + } + } + } + + editedHandle = FCT_EditedHandle_None; + lit_point = -1; + + // get the pointer position + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + getMouseOverArea(); + + switch (area) { + + case (FCT_Area_Insertion): + new_type = CSArrow; + break; + + case (FCT_Area_Point): + new_type = CSMove; + break; + + case (FCT_Area_H): + new_type = CSResizeHeight; + break; + + case (FCT_Area_V): + new_type = CSMove; + break; + + case (FCT_Area_LeftTan): + new_type = CSEmpty; + break; + + case (FCT_Area_RightTan): + new_type = CSEmpty; + break; + + default: + break; + } + + setDirty(true); + draw (); + retval = true; + //notifyListener (); + } + } + + break; + + case Gdk::MOTION_NOTIFY: + if (curve.type == FCT_Linear || curve.type == FCT_MinMaxCPoints) { + + int previous_lit_point = lit_point; + enum MouseOverAreas prevArea = area; + + snapToMinDistY = snapToMinDistX = 10.; + snapToValY = snapToValX = 0.; + snapToElmt = -100; + + // get the pointer position + getCursorPosition(Gdk::EventType(event->type), event->motion.is_hint != 0, int(event->button.x), int(event->button.y), Gdk::ModifierType(event->button.state)); + getMouseOverArea(); + + if (editedHandle == FCT_EditedHandle_CPointUD) { + double dX = deltaX; + double dY = deltaY; + + if (dX < 0.) { + dX = -dX; + } + + if (dY < 0.) { + dY = -dY; + } + + if (dX > dY) { + editedHandle = FCT_EditedHandle_CPointX; + area = FCT_Area_V; + new_type = CSResizeWidth; + } else { + editedHandle = FCT_EditedHandle_CPointY; + area = FCT_Area_H; + new_type = CSResizeHeight; + } + } + + switch (editedHandle) { + + case (FCT_EditedHandle_None): { + + if ((lit_point != -1 && previous_lit_point != lit_point) && (area & (FCT_Area_V | FCT_Area_Point)) && edited_point == -1) { + + bool sameSide = false; + + // display the handles + tanHandlesDisplayed = true; + + if (curve.x.at(lit_point) < 3.*minDistanceX) { + // lit_point too near of the left border -> both handles are displayed on the right of the vertical line + rightTanHandle.centerX = leftTanHandle.centerX = curve.x.at(lit_point) + 2.*minDistanceX; + sameSide = true; + } else if (curve.x.at(lit_point) > 1. - 3.*minDistanceX) { + // lit_point too near of the left border -> both handles are displayed on the right of the vertical line + rightTanHandle.centerX = leftTanHandle.centerX = curve.x.at(lit_point) - 2.*minDistanceX; + sameSide = true; + } else { + leftTanHandle.centerX = curve.x.at(lit_point) - 2.*minDistanceX; + rightTanHandle.centerX = curve.x.at(lit_point) + 2.*minDistanceX; + } + + if (sameSide) { + if (clampedY > 1. - 2.*minDistanceY) { + // lit_point too near of the top border + leftTanHandle.centerY = 1. - minDistanceY; + rightTanHandle.centerY = 1. - 3.*minDistanceY; + } else if (clampedY < 2.*minDistanceY) { + // lit_point too near of the bottom border + leftTanHandle.centerY = 3.*minDistanceY; + rightTanHandle.centerY = minDistanceY; + } else { + leftTanHandle.centerY = clampedY + minDistanceY; + rightTanHandle.centerY = clampedY - minDistanceY; + } + } else { + if (clampedY > 1. - minDistanceY) { + rightTanHandle.centerY = leftTanHandle.centerY = 1. - minDistanceY; + } else if (clampedY < minDistanceY) { + rightTanHandle.centerY = leftTanHandle.centerY = minDistanceY; + } else { + rightTanHandle.centerY = leftTanHandle.centerY = clampedY; + } + } + } else if (lit_point == -1 || edited_point > -1) { + tanHandlesDisplayed = false; + } + + + if (edited_point == -1) { + switch (area) { + + case (FCT_Area_Insertion): + new_type = CSPlus; + break; + + case (FCT_Area_Point): + + //new_type = CSMove; + //break; + case (FCT_Area_V): + new_type = CSMove; + break; + + case (FCT_Area_H): + new_type = CSResizeHeight; + break; + + case (FCT_Area_LeftTan): + new_type = CSMoveLeft; + break; + + case (FCT_Area_RightTan): + new_type = CSMoveRight; + break; + + case (FCT_Area_None): + default: + new_type = CSArrow; + break; + } + } + + if ((lit_point != previous_lit_point) || (prevArea != area)) { + setDirty(true); + draw (); + } + + if (coordinateAdjuster->is_visible() && edited_point == -1) { + if (lit_point > -1) { + if (lit_point != previous_lit_point) { + editedPos.at(0) = curve.x.at(lit_point); + editedPos.at(1) = curve.y.at(lit_point); + editedPos.at(2) = curve.leftTangent.at(lit_point); + editedPos.at(3) = curve.rightTangent.at(lit_point); + } + + coordinateAdjuster->setPos(editedPos); + } else if (area == FCT_Area_Insertion) { + editedPos.at(0) = clampedX; + editedPos.at(1) = clampedY; + editedPos.at(2) = 0.; + editedPos.at(3) = 0.; + coordinateAdjuster->setPos(editedPos); + } else { + editedPos.at(0) = editedPos.at(1) = editedPos.at(2) = editedPos.at(3) = 0; + coordinateAdjuster->setPos(editedPos); + } + } + + break; + } + + case (FCT_EditedHandle_CPoint): + movePoint(true, true); + + if (coordinateAdjuster->is_visible()) { + editedPos.at(0) = curve.x.at(lit_point); + editedPos.at(1) = curve.y.at(lit_point); + coordinateAdjuster->setPos(editedPos); + } + + break; + + case (FCT_EditedHandle_CPointX): + movePoint(true, false); + + if (coordinateAdjuster->is_visible()) { + editedPos.at(0) = curve.x.at(lit_point); + coordinateAdjuster->setPos(editedPos); + } + + break; + + case (FCT_EditedHandle_CPointY): + movePoint(false, true); + + if (coordinateAdjuster->is_visible()) { + editedPos.at(1) = curve.y.at(lit_point); + coordinateAdjuster->setPos(editedPos); + } + + break; + + case (FCT_EditedHandle_LeftTan): { + double prevValue = curve.leftTangent.at(lit_point); + + ugpX -= deltaX * 3; + ugpX = CLAMP(ugpX, 0., 1.); + + if (snapTo) { + // since this handle can only move in one direction, we can reuse the snapCoordinateX mechanism + snapCoordinateX(0.0, ugpX); + snapCoordinateX(0.35, ugpX); + snapCoordinateX(0.5, ugpX); + snapCoordinateX(1.0, ugpX); + curve.leftTangent.at(lit_point) = snapToValX; + } else { + curve.leftTangent.at(lit_point) = ugpX; + } + + if (curve.leftTangent.at(lit_point) != prevValue) { + curveIsDirty = true; + setDirty(true); + draw (); + notifyListener (); + + if (coordinateAdjuster->is_visible()) { + editedPos.at(2) = curve.leftTangent.at(lit_point); + coordinateAdjuster->setPos(editedPos); + } + } + + break; + } + + case (FCT_EditedHandle_RightTan): { + double prevValue = curve.rightTangent.at(lit_point); + + ugpX += deltaX * 3; + ugpX = CLAMP(ugpX, 0., 1.); + + if (snapTo) { + // since this handle can only move in one direction, we can reuse the snapCoordinateX mechanism + snapCoordinateX(0.0, ugpX); + snapCoordinateX(0.35, ugpX); + snapCoordinateX(0.5, ugpX); + snapCoordinateX(1.0, ugpX); + curve.rightTangent.at(lit_point) = snapToValX; + } else { + curve.rightTangent.at(lit_point) = ugpX; + } + + if (curve.rightTangent.at(lit_point) != prevValue) { + curveIsDirty = true; + setDirty(true); + draw (); + notifyListener (); + editedPos.at(3) = curve.rightTangent.at(lit_point); + coordinateAdjuster->setPos(editedPos); + } + + break; + } + + // already processed before the "switch" instruction + //case (FCT_EditedHandle_CPointUD): + + default: + break; + } + + if (edited_point == -1) { + if (lit_point == -1) { + editedPos.at(0) = editedPos.at(1) = editedPos.at(2) = editedPos.at(3) = 0; + } else if (editedPos.at(0) != curve.x.at(lit_point) + || editedPos.at(1) != curve.y.at(lit_point) + || editedPos.at(2) != curve.leftTangent.at(lit_point) + || editedPos.at(3) != curve.rightTangent.at(lit_point)) { + editedPos.at(0) = curve.x.at(lit_point); + editedPos.at(1) = curve.y.at(lit_point); + editedPos.at(2) = curve.leftTangent.at(lit_point); + editedPos.at(3) = curve.rightTangent.at(lit_point); + coordinateAdjuster->setPos(editedPos); + } + } + } + + retval = true; + break; + + case Gdk::LEAVE_NOTIFY: + + // Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case + // The cursor will have to LEAVE another time after the drag... + if (editedHandle == FCT_EditedHandle_None) { + new_type = CSArrow; + lit_point = -1; + tanHandlesDisplayed = false; + pipetteR = pipetteG = pipetteB = -1.f; + setDirty(true); + draw (); + } + + retval = true; + break; + + default: + break; + } + + if (new_type != cursor_type) { + cursor_type = new_type; + cursorManager.setCursor(cursor_type); + } + + return retval; } -void MyFlatCurve::pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) { - if (!provider) { - // occurs when leaving the preview area -> cleanup the curve editor - pipetteR = pipetteG = pipetteB = -1.f; - lit_point = -1; - return; - } +void MyFlatCurve::pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey) +{ + if (!provider) { + // occurs when leaving the preview area -> cleanup the curve editor + pipetteR = pipetteG = pipetteB = -1.f; + lit_point = -1; + return; + } - pipetteR = provider->pipetteVal[0]; - pipetteG = provider->pipetteVal[1]; - pipetteB = provider->pipetteVal[2]; - pipetteVal = 0.f; - if (listener) - pipetteVal = listener->blendPipetteValues(ce, pipetteR, pipetteG, pipetteB); - else { - int n = 0; - if (pipetteR != -1.f) { - pipetteVal += pipetteR; - ++n; - } - if (pipetteG != -1.f) { - pipetteVal += pipetteG; - ++n; - } - if (pipetteB != -1.f) { - pipetteVal += pipetteB; - ++n; - } - if (n>1) - pipetteVal /= n; - else if (!n) - pipetteVal = -1.f; - } + pipetteR = provider->pipetteVal[0]; + pipetteG = provider->pipetteVal[1]; + pipetteB = provider->pipetteVal[2]; + pipetteVal = 0.f; - snapToElmt = -100; + if (listener) { + pipetteVal = listener->blendPipetteValues(ce, pipetteR, pipetteG, pipetteB); + } else { + int n = 0; - /* graphW and graphH are the size of the graph */ - calcDimensions(); + if (pipetteR != -1.f) { + pipetteVal += pipetteR; + ++n; + } - if ((graphW < 0) || (graphH < 0)) - return; + if (pipetteG != -1.f) { + pipetteVal += pipetteG; + ++n; + } - int previous_lit_point = lit_point; + if (pipetteB != -1.f) { + pipetteVal += pipetteB; + ++n; + } - // hide the handles - tanHandlesDisplayed = false; + if (n > 1) { + pipetteVal /= n; + } else if (!n) { + pipetteVal = -1.f; + } + } - // get the pointer position - int px = graphX + int(float(graphW)*pipetteVal); // WARNING: converting pipetteVal from float to int, precision loss here! - getCursorPosition(Gdk::EventType(Gdk::BUTTON_PRESS), false, px, graphY, Gdk::ModifierType(modifierKey)); - if (edited_point==-1) - getMouseOverArea(); + snapToElmt = -100; - if (area==FCT_Area_Point) - area = FCT_Area_V; + /* graphW and graphH are the size of the graph */ + calcDimensions(); - snapToMinDistY = snapToMinDistX = 10.; - snapToValY = snapToValX = 0.; + if ((graphW < 0) || (graphH < 0)) { + return; + } - if (edited_point==-1) { - if (editedHandle==FCT_EditedHandle_None && lit_point != previous_lit_point) { - setDirty(true); - draw (); - } - } - else - draw(); + int previous_lit_point = lit_point; - if (edited_point==-1) { - editedPos.at(0) = pipetteVal; - editedPos.at(1) = point.getVal01(pipetteVal); - coordinateAdjuster->setPos(editedPos); - } + // hide the handles + tanHandlesDisplayed = false; + + // get the pointer position + int px = graphX + int(float(graphW) * pipetteVal); // WARNING: converting pipetteVal from float to int, precision loss here! + getCursorPosition(Gdk::EventType(Gdk::BUTTON_PRESS), false, px, graphY, Gdk::ModifierType(modifierKey)); + + if (edited_point == -1) { + getMouseOverArea(); + } + + if (area == FCT_Area_Point) { + area = FCT_Area_V; + } + + snapToMinDistY = snapToMinDistX = 10.; + snapToValY = snapToValX = 0.; + + if (edited_point == -1) { + if (editedHandle == FCT_EditedHandle_None && lit_point != previous_lit_point) { + setDirty(true); + draw (); + } + } else { + draw(); + } + + if (edited_point == -1) { + editedPos.at(0) = pipetteVal; + editedPos.at(1) = point.getVal01(pipetteVal); + coordinateAdjuster->setPos(editedPos); + } } -void MyFlatCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) { - if (edited_point>-1) - return; +void MyFlatCurve::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey) +{ + if (edited_point > -1) { + return; + } - buttonPressed = true; + buttonPressed = true; - // get the pointer position - int px = graphX + int(float(graphW)*pipetteVal); // WARNING: converting pipetteVal from float to int, precision loss here! - getCursorPosition(Gdk::EventType(Gdk::BUTTON_PRESS), false, px, graphY, Gdk::ModifierType(modifierKey)); - getMouseOverArea(); + // get the pointer position + int px = graphX + int(float(graphW) * pipetteVal); // WARNING: converting pipetteVal from float to int, precision loss here! + getCursorPosition(Gdk::EventType(Gdk::BUTTON_PRESS), false, px, graphY, Gdk::ModifierType(modifierKey)); + getMouseOverArea(); - // hide the tangent handles - tanHandlesDisplayed = false; + // hide the tangent handles + tanHandlesDisplayed = false; - // Action on BUTTON_PRESS and no edited point - switch (area) { + // Action on BUTTON_PRESS and no edited point + switch (area) { - case (FCT_Area_Insertion): - { - rtengine::FlatCurve rtCurve(getPoints(), 200); + case (FCT_Area_Insertion): { + rtengine::FlatCurve rtCurve(getPoints(), 200); - std::vector::iterator itx, ity, itlt, itrt; - int num = (int)curve.x.size(); + std::vector::iterator itx, ity, itlt, itrt; + int num = (int)curve.x.size(); - /* insert a new control point */ - if (num > 0) { - if (clampedX > curve.x.at(closest_point)) - ++closest_point; - } - itx = curve.x.begin(); - ity = curve.y.begin(); - itlt = curve.leftTangent.begin(); - itrt = curve.rightTangent.begin(); - for (int i=0; i 0) { + if (clampedX > curve.x.at(closest_point)) { + ++closest_point; + } + } - // the graph is refreshed only if a new point is created - curve.x.at(closest_point) = clampedX; - curve.y.at(closest_point) = clampedY = rtCurve.getVal(pipetteVal); - curve.leftTangent.at(closest_point) = 0.35; - curve.rightTangent.at(closest_point) = 0.35; + itx = curve.x.begin(); + ity = curve.y.begin(); + itlt = curve.leftTangent.begin(); + itrt = curve.rightTangent.begin(); - curveIsDirty = true; - setDirty(true); - draw (); - notifyListener (); + for (int i = 0; i < closest_point; i++) { + itx++; + ity++; + itlt++; + itrt++; + } - lit_point = closest_point; + curve.x.insert (itx, 0); + curve.y.insert (ity, 0); + curve.leftTangent.insert (itlt, 0); + curve.rightTangent.insert (itrt, 0); + num++; - // point automatically activated - editedHandle = FCT_EditedHandle_CPointY; - ugpX = curve.x.at(lit_point); - ugpY = curve.y.at(lit_point); - break; - } - case (FCT_Area_V): - editedHandle = FCT_EditedHandle_CPointY; - ugpX = curve.x.at(lit_point); - ugpY = curve.y.at(lit_point); - break; - default: - break; - } + // the graph is refreshed only if a new point is created + curve.x.at(closest_point) = clampedX; + curve.y.at(closest_point) = clampedY = rtCurve.getVal(pipetteVal); + curve.leftTangent.at(closest_point) = 0.35; + curve.rightTangent.at(closest_point) = 0.35; + + curveIsDirty = true; + setDirty(true); + draw (); + notifyListener (); + + lit_point = closest_point; + + // point automatically activated + editedHandle = FCT_EditedHandle_CPointY; + ugpX = curve.x.at(lit_point); + ugpY = curve.y.at(lit_point); + break; + } + + case (FCT_Area_V): + editedHandle = FCT_EditedHandle_CPointY; + ugpX = curve.x.at(lit_point); + ugpY = curve.y.at(lit_point); + break; + + default: + break; + } } -void MyFlatCurve::pipetteButton1Released(EditDataProvider *provider) { - if (edited_point>-1) - return; +void MyFlatCurve::pipetteButton1Released(EditDataProvider *provider) +{ + if (edited_point > -1) { + return; + } - buttonPressed = false; - remove_modal_grab (); + buttonPressed = false; + remove_modal_grab (); - editedHandle = FCT_EditedHandle_None; - lit_point = -1; + editedHandle = FCT_EditedHandle_None; + lit_point = -1; - // get the pointer position - int px = graphX + int(float(graphW)*pipetteVal); // WARNING: converting pipetteVal from float to int, precision loss here! - getCursorPosition(Gdk::EventType(Gdk::BUTTON_PRESS), false, px, graphY, Gdk::ModifierType(0)); - getMouseOverArea(); + // get the pointer position + int px = graphX + int(float(graphW) * pipetteVal); // WARNING: converting pipetteVal from float to int, precision loss here! + getCursorPosition(Gdk::EventType(Gdk::BUTTON_PRESS), false, px, graphY, Gdk::ModifierType(0)); + getMouseOverArea(); - setDirty(true); - draw (); - //notifyListener (); + setDirty(true); + draw (); + //notifyListener (); } -void MyFlatCurve::pipetteDrag(EditDataProvider *provider, int modifierKey) { - if (edited_point>-1) - return; +void MyFlatCurve::pipetteDrag(EditDataProvider *provider, int modifierKey) +{ + if (edited_point > -1) { + return; + } - snapToMinDistY = snapToMinDistX = 10.; - snapToValY = snapToValX = 0.; - snapToElmt = -100; + snapToMinDistY = snapToMinDistX = 10.; + snapToValY = snapToValX = 0.; + snapToElmt = -100; - // get the pointer position - getCursorPosition(Gdk::MOTION_NOTIFY, false, cursorX+graphX, graphY+provider->deltaScreen.y, Gdk::ModifierType(modifierKey)); - getMouseOverArea(); + // get the pointer position + getCursorPosition(Gdk::MOTION_NOTIFY, false, cursorX + graphX, graphY + provider->deltaScreen.y, Gdk::ModifierType(modifierKey)); + getMouseOverArea(); - if (editedHandle == FCT_EditedHandle_CPointY) { - movePoint(false, true, true); - } + if (editedHandle == FCT_EditedHandle_CPointY) { + movePoint(false, true, true); + } } -void MyFlatCurve::movePoint(bool moveX, bool moveY, bool pipetteDrag) { +void MyFlatCurve::movePoint(bool moveX, bool moveY, bool pipetteDrag) +{ - // bounds of the grabbed point - double leftBound; - double rightBound; - double const bottomBound = 0.; - double const topBound = 1.; + // bounds of the grabbed point + double leftBound; + double rightBound; + double const bottomBound = 0.; + double const topBound = 1.; - // we memorize the previous position of the point, for optimization purpose - double prevPosX = curve.x.at(lit_point); - double prevPosY = curve.y.at(lit_point); + // we memorize the previous position of the point, for optimization purpose + double prevPosX = curve.x.at(lit_point); + double prevPosY = curve.y.at(lit_point); - int nbPoints = (int)curve.x.size(); + int nbPoints = (int)curve.x.size(); - // left and right bound rely on curve periodicity - leftBound = (lit_point == 0 ) ? (periodic && !snapTo ? curve.x.at(nbPoints-1)-1. : 0.) : curve.x.at(lit_point-1); - rightBound = (lit_point == nbPoints-1) ? (periodic && !snapTo ? curve.x.at(0)+1. : 1.) : curve.x.at(lit_point+1); + // left and right bound rely on curve periodicity + leftBound = (lit_point == 0 ) ? (periodic && !snapTo ? curve.x.at(nbPoints - 1) - 1. : 0.) : curve.x.at(lit_point - 1); + rightBound = (lit_point == nbPoints - 1) ? (periodic && !snapTo ? curve.x.at(0) + 1. : 1.) : curve.x.at(lit_point + 1); - double leftDeletionBound = leftBound - minDistanceX; - double rightDeletionBound = rightBound + minDistanceX; - double bottomDeletionBound = bottomBound - minDistanceY; - double topDeletionBound = topBound + minDistanceY; + double leftDeletionBound = leftBound - minDistanceX; + double rightDeletionBound = rightBound + minDistanceX; + double bottomDeletionBound = bottomBound - minDistanceY; + double topDeletionBound = topBound + minDistanceY; - if (moveX) { - // we memorize the previous position of the point, for optimization purpose - ugpX += deltaX; + if (moveX) { + // we memorize the previous position of the point, for optimization purpose + ugpX += deltaX; - // handling periodicity (the first and last point can reappear at the other side of the X range) - if (periodic) { - if (snapTo) { - if (lit_point==0) { - snapCoordinateX(0.0, ugpX); - curve.x.at(0) = snapToValX; - } - else if (lit_point==(nbPoints-1)) { - snapCoordinateX(1.0, ugpX); - curve.x.at(nbPoints-1) = snapToValX; - } - } - else if (lit_point==0 && ugpX<0.) { - // the first point has to be placed at the tail of the point list - std::vector::iterator itx, ity, itlt, itrt; + // handling periodicity (the first and last point can reappear at the other side of the X range) + if (periodic) { + if (snapTo) { + if (lit_point == 0) { + snapCoordinateX(0.0, ugpX); + curve.x.at(0) = snapToValX; + } else if (lit_point == (nbPoints - 1)) { + snapCoordinateX(1.0, ugpX); + curve.x.at(nbPoints - 1) = snapToValX; + } + } else if (lit_point == 0 && ugpX < 0.) { + // the first point has to be placed at the tail of the point list + std::vector::iterator itx, ity, itlt, itrt; - ugpX += 1.; - leftBound += 1.; - rightBound += 1.; - leftDeletionBound += 1.; - rightDeletionBound += 1.; + ugpX += 1.; + leftBound += 1.; + rightBound += 1.; + leftDeletionBound += 1.; + rightDeletionBound += 1.; - // adding a copy of the first point to the tail of the list - curve.x.push_back(curve.x.at(0)); - curve.y.push_back(curve.y.at(0)); - curve.leftTangent.push_back(curve.leftTangent.at(0)); - curve.rightTangent.push_back(curve.rightTangent.at(0)); + // adding a copy of the first point to the tail of the list + curve.x.push_back(curve.x.at(0)); + curve.y.push_back(curve.y.at(0)); + curve.leftTangent.push_back(curve.leftTangent.at(0)); + curve.rightTangent.push_back(curve.rightTangent.at(0)); - // deleting the first point - itx = curve.x.begin(); - ity = curve.y.begin(); - itlt = curve.leftTangent.begin(); - itrt = curve.rightTangent.begin(); + // deleting the first point + itx = curve.x.begin(); + ity = curve.y.begin(); + itlt = curve.leftTangent.begin(); + itrt = curve.rightTangent.begin(); - curve.x.erase(itx); - curve.y.erase(ity); - curve.leftTangent.erase(itlt); - curve.rightTangent.erase(itrt); + curve.x.erase(itx); + curve.y.erase(ity); + curve.leftTangent.erase(itlt); + curve.rightTangent.erase(itrt); - lit_point = nbPoints-1; - } - else if (lit_point==(nbPoints-1) && ugpX>1.) { - // the last point has to be placed at the head of the point list - std::vector::iterator itx, ity, itlt, itrt; + lit_point = nbPoints - 1; + } else if (lit_point == (nbPoints - 1) && ugpX > 1.) { + // the last point has to be placed at the head of the point list + std::vector::iterator itx, ity, itlt, itrt; - ugpX -= 1.; - leftBound -= 1.; - rightBound -= 1.; - leftDeletionBound -= 1.; - rightDeletionBound -= 1.; + ugpX -= 1.; + leftBound -= 1.; + rightBound -= 1.; + leftDeletionBound -= 1.; + rightDeletionBound -= 1.; - // adding a copy of the last point to the head of the list - itx = curve.x.begin(); - ity = curve.y.begin(); - itlt = curve.leftTangent.begin(); - itrt = curve.rightTangent.begin(); + // adding a copy of the last point to the head of the list + itx = curve.x.begin(); + ity = curve.y.begin(); + itlt = curve.leftTangent.begin(); + itrt = curve.rightTangent.begin(); - curve.x.insert(itx,0); - curve.y.insert(ity,0); - curve.leftTangent.insert(itlt,0); - curve.rightTangent.insert(itrt,0); + curve.x.insert(itx, 0); + curve.y.insert(ity, 0); + curve.leftTangent.insert(itlt, 0); + curve.rightTangent.insert(itrt, 0); - curve.x.at(0) = curve.x.at(nbPoints); - curve.y.at(0) = curve.y.at(nbPoints); - curve.leftTangent.at(0) = curve.leftTangent.at(nbPoints); - curve.rightTangent.at(0) = curve.rightTangent.at(nbPoints); + curve.x.at(0) = curve.x.at(nbPoints); + curve.y.at(0) = curve.y.at(nbPoints); + curve.leftTangent.at(0) = curve.leftTangent.at(nbPoints); + curve.rightTangent.at(0) = curve.rightTangent.at(nbPoints); - // deleting the last point - curve.x.pop_back(); - curve.y.pop_back(); - curve.leftTangent.pop_back(); - curve.rightTangent.pop_back(); + // deleting the last point + curve.x.pop_back(); + curve.y.pop_back(); + curve.leftTangent.pop_back(); + curve.rightTangent.pop_back(); - lit_point = 0; - } - } + lit_point = 0; + } + } - // handling limitations along X axis - if (ugpX >= rightDeletionBound && nbPoints>2 && !snapTo) { - curve.x.at(lit_point) = -1.; - } - else if (ugpX <= leftDeletionBound && nbPoints>2 && !snapTo) { - curve.x.at(lit_point) = -1.; - } - else - // nextPosX is in bounds - curve.x.at(lit_point) = CLAMP(ugpX, leftBound, rightBound); - } + // handling limitations along X axis + if (ugpX >= rightDeletionBound && nbPoints > 2 && !snapTo) { + curve.x.at(lit_point) = -1.; + } else if (ugpX <= leftDeletionBound && nbPoints > 2 && !snapTo) { + curve.x.at(lit_point) = -1.; + } else + // nextPosX is in bounds + { + curve.x.at(lit_point) = CLAMP(ugpX, leftBound, rightBound); + } + } - if (moveY) { + if (moveY) { - // we memorize the previous position of the point, for optimization purpose - ugpY += deltaY; + // we memorize the previous position of the point, for optimization purpose + ugpY += deltaY; - // the points stay in the bounds (and can't be deleted) in pipette drag mode - if (pipetteDrag) - ugpY = CLAMP(ugpY, 0.0, 1.0); + // the points stay in the bounds (and can't be deleted) in pipette drag mode + if (pipetteDrag) { + ugpY = CLAMP(ugpY, 0.0, 1.0); + } - // snapping point to specific values - if (snapTo && curve.x.at(lit_point) != -1) { + // snapping point to specific values + if (snapTo && curve.x.at(lit_point) != -1) { - // the unclamped grabbed point is brought back in the range - ugpY = CLAMP(ugpY, 0.0, 1.0); + // the unclamped grabbed point is brought back in the range + ugpY = CLAMP(ugpY, 0.0, 1.0); - if (lit_point == 0) { - int prevP = curve.y.size()-1; - if (snapCoordinateY(curve.y.at(prevP), ugpY)) snapToElmt = prevP; - } - else { - int prevP = lit_point-1; - if (snapCoordinateY(curve.y.at(prevP), ugpY)) snapToElmt = prevP; - } + if (lit_point == 0) { + int prevP = curve.y.size() - 1; - if (curve.y.size() > 2) { - if (lit_point == (curve.y.size()-1)) { - if (snapCoordinateY(curve.y.at(0), ugpY)) snapToElmt = 0; - } - else { - int nextP = lit_point+1; - if (snapCoordinateY(curve.y.at(nextP), ugpY)) snapToElmt = nextP; - } - } - if (snapCoordinateY(1.0, ugpY)) snapToElmt = -3; - if (snapCoordinateY(0.5, ugpY)) snapToElmt = -2; - if (snapCoordinateY(0.0, ugpY)) snapToElmt = -1; + if (snapCoordinateY(curve.y.at(prevP), ugpY)) { + snapToElmt = prevP; + } + } else { + int prevP = lit_point - 1; - curve.y.at(lit_point) = snapToValY; - } + if (snapCoordinateY(curve.y.at(prevP), ugpY)) { + snapToElmt = prevP; + } + } - // Handling limitations along Y axis - if (ugpY >= topDeletionBound && nbPoints>2) { - if (curve.x.at(lit_point) != -1.) { - deletedPointX = curve.x.at(lit_point); - curve.x.at(lit_point) = -1.; - curve.y.at(lit_point) = ugpY; // This is only to force the redraw of the curve - } - } - else if (ugpY <= bottomDeletionBound && nbPoints>2) { - if (curve.x.at(lit_point) != -1.) { - deletedPointX = curve.x.at(lit_point); - curve.x.at(lit_point) = -1.; - curve.y.at(lit_point) = ugpY; // This is only to force the redraw of the curve - } - } - else { - // nextPosY is in the bounds - if (!snapTo) curve.y.at(lit_point) = CLAMP(ugpY, 0.0, 1.0); - if (!moveX && curve.x.at(lit_point) == -1.) { - // bring back the X value of the point if it reappear - curve.x.at(lit_point) = deletedPointX; - } - } - } + if (curve.y.size() > 2) { + if (lit_point == (curve.y.size() - 1)) { + if (snapCoordinateY(curve.y.at(0), ugpY)) { + snapToElmt = 0; + } + } else { + int nextP = lit_point + 1; - if (curve.x.at(lit_point) != prevPosX || curve.y.at(lit_point) != prevPosY) { - // we recompute the curve only if we have to - curveIsDirty = true; - setDirty(true); - draw (); - notifyListener (); - } + if (snapCoordinateY(curve.y.at(nextP), ugpY)) { + snapToElmt = nextP; + } + } + } + + if (snapCoordinateY(1.0, ugpY)) { + snapToElmt = -3; + } + + if (snapCoordinateY(0.5, ugpY)) { + snapToElmt = -2; + } + + if (snapCoordinateY(0.0, ugpY)) { + snapToElmt = -1; + } + + curve.y.at(lit_point) = snapToValY; + } + + // Handling limitations along Y axis + if (ugpY >= topDeletionBound && nbPoints > 2) { + if (curve.x.at(lit_point) != -1.) { + deletedPointX = curve.x.at(lit_point); + curve.x.at(lit_point) = -1.; + curve.y.at(lit_point) = ugpY; // This is only to force the redraw of the curve + } + } else if (ugpY <= bottomDeletionBound && nbPoints > 2) { + if (curve.x.at(lit_point) != -1.) { + deletedPointX = curve.x.at(lit_point); + curve.x.at(lit_point) = -1.; + curve.y.at(lit_point) = ugpY; // This is only to force the redraw of the curve + } + } else { + // nextPosY is in the bounds + if (!snapTo) { + curve.y.at(lit_point) = CLAMP(ugpY, 0.0, 1.0); + } + + if (!moveX && curve.x.at(lit_point) == -1.) { + // bring back the X value of the point if it reappear + curve.x.at(lit_point) = deletedPointX; + } + } + } + + if (curve.x.at(lit_point) != prevPosX || curve.y.at(lit_point) != prevPosY) { + // we recompute the curve only if we have to + curveIsDirty = true; + setDirty(true); + draw (); + notifyListener (); + } } // Set datas relative to cursor position -void MyFlatCurve::getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifierKey) { - int tx, ty; - int prevCursorX, prevCursorY; - double incrementX = 1. / double(graphW); - double incrementY = 1. / double(graphH); +void MyFlatCurve::getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifierKey) +{ + int tx, ty; + int prevCursorX, prevCursorY; + double incrementX = 1. / double(graphW); + double incrementY = 1. / double(graphH); - switch (evType) { - case (Gdk::MOTION_NOTIFY) : - if (isHint) { - get_window()->get_pointer (tx, ty, mod_type); - } - else { - tx = evX; - ty = evY; - mod_type = modifierKey; - } - break; - case (Gdk::BUTTON_PRESS) : - case (Gdk::BUTTON_RELEASE) : - tx = evX; - ty = evY; - mod_type = modifierKey; - break; - default : - // The cursor position is not available - return; - break; - } + switch (evType) { + case (Gdk::MOTION_NOTIFY) : + if (isHint) { + get_window()->get_pointer (tx, ty, mod_type); + } else { + tx = evX; + ty = evY; + mod_type = modifierKey; + } - if (editedHandle != FCT_EditedHandle_None) { - prevCursorX = cursorX; - prevCursorY = cursorY; - } - cursorX = tx - graphX; - cursorY = graphY - ty; + break; - preciseCursorX = cursorX * incrementX; - preciseCursorY = cursorY * incrementY; + case (Gdk::BUTTON_PRESS) : + case (Gdk::BUTTON_RELEASE) : + tx = evX; + ty = evY; + mod_type = modifierKey; + break; - snapTo = false; + default : + // The cursor position is not available + return; + break; + } - // update deltaX/Y if the user drags a point - if (editedHandle != FCT_EditedHandle_None) { - // set the dragging factor - int control_key = mod_type & GDK_CONTROL_MASK; - int shift_key = mod_type & GDK_SHIFT_MASK; + if (editedHandle != FCT_EditedHandle_None) { + prevCursorX = cursorX; + prevCursorY = cursorY; + } - // the increment get smaller if modifier key are used, and "snap to" may be enabled - if (control_key) { incrementX *= 0.05; incrementY *= 0.05; } - if (shift_key) { snapTo = true; } + cursorX = tx - graphX; + cursorY = graphY - ty; - deltaX = (double)(cursorX - prevCursorX) * incrementX; - deltaY = (double)(cursorY - prevCursorY) * incrementY; - } - // otherwise set the position of the new point (modifier keys has no effect here) - else { - clampedX = CLAMP (preciseCursorX, 0., 1.); // X position of the pointer from the origin of the graph - clampedY = CLAMP (preciseCursorY, 0., 1.); // Y position of the pointer from the origin of the graph - } + preciseCursorX = cursorX * incrementX; + preciseCursorY = cursorY * incrementY; + + snapTo = false; + + // update deltaX/Y if the user drags a point + if (editedHandle != FCT_EditedHandle_None) { + // set the dragging factor + int control_key = mod_type & GDK_CONTROL_MASK; + int shift_key = mod_type & GDK_SHIFT_MASK; + + // the increment get smaller if modifier key are used, and "snap to" may be enabled + if (control_key) { + incrementX *= 0.05; + incrementY *= 0.05; + } + + if (shift_key) { + snapTo = true; + } + + deltaX = (double)(cursorX - prevCursorX) * incrementX; + deltaY = (double)(cursorY - prevCursorY) * incrementY; + } + // otherwise set the position of the new point (modifier keys has no effect here) + else { + clampedX = CLAMP (preciseCursorX, 0., 1.); // X position of the pointer from the origin of the graph + clampedY = CLAMP (preciseCursorY, 0., 1.); // Y position of the pointer from the origin of the graph + } } // Find out the active area under the cursor -void MyFlatCurve::getMouseOverArea () { +void MyFlatCurve::getMouseOverArea () +{ - // When dragging an element, editedHandle keep its value - if (editedHandle == FCT_EditedHandle_None) { // && curve.type!=Parametric + // When dragging an element, editedHandle keep its value + if (editedHandle == FCT_EditedHandle_None) { // && curve.type!=Parametric - double minDist = 1000; // used to find out the point pointed by the cursor (over it) - double minDistX = 1000; // used to find out the closest point - double dX, dY; - double absDX; - double dist; - bool aboveVLine = false; + double minDist = 1000; // used to find out the point pointed by the cursor (over it) + double minDistX = 1000; // used to find out the closest point + double dX, dY; + double absDX; + double dist; + bool aboveVLine = false; - // NB: this function assume that the graph's shape is a square + // NB: this function assume that the graph's shape is a square - // Check if the cursor is over a tangent handle - if (tanHandlesDisplayed) { + // Check if the cursor is over a tangent handle + if (tanHandlesDisplayed) { - if (preciseCursorX>=(leftTanHandle.centerX-minDistanceX) && preciseCursorX<=(leftTanHandle.centerX+minDistanceX+0.00001) - && preciseCursorY>=(leftTanHandle.centerY-minDistanceY) && preciseCursorY<=(leftTanHandle.centerY+minDistanceY)) { - area = FCT_Area_LeftTan; - return; - } - if (preciseCursorX>=(rightTanHandle.centerX-minDistanceX-0.00001) && preciseCursorX<=(rightTanHandle.centerX+minDistanceX) - && preciseCursorY>=(rightTanHandle.centerY-minDistanceY ) && preciseCursorY<=(rightTanHandle.centerY+minDistanceY)) { - area = FCT_Area_RightTan; - return; - } - } + if (preciseCursorX >= (leftTanHandle.centerX - minDistanceX) && preciseCursorX <= (leftTanHandle.centerX + minDistanceX + 0.00001) + && preciseCursorY >= (leftTanHandle.centerY - minDistanceY) && preciseCursorY <= (leftTanHandle.centerY + minDistanceY)) { + area = FCT_Area_LeftTan; + return; + } - area = FCT_Area_None; - closest_point = 0; - lit_point = -1; + if (preciseCursorX >= (rightTanHandle.centerX - minDistanceX - 0.00001) && preciseCursorX <= (rightTanHandle.centerX + minDistanceX) + && preciseCursorY >= (rightTanHandle.centerY - minDistanceY ) && preciseCursorY <= (rightTanHandle.centerY + minDistanceY)) { + area = FCT_Area_RightTan; + return; + } + } - for (int i = 0; i < (int)curve.x.size(); i++) { - if (curve.x.at(i) != -1) { - dX = curve.x.at(i) - preciseCursorX; - absDX = dX>0 ? dX : -dX; - if (absDX < minDistX) { - minDistX = absDX; - closest_point = i; - lit_point = i; - } - if (absDX <= minDistanceX) { - aboveVLine = true; - dY = curve.y.at(i) - preciseCursorY; - dist = sqrt(dX*dX + dY*dY); - if (dist < minDist) { - minDist = dist; - } - } - } - } + area = FCT_Area_None; + closest_point = 0; + lit_point = -1; - if (minDist <= minDistanceX) { - // the cursor is over the point - area = FCT_Area_Point; - } - else if (aboveVLine) { - area = FCT_Area_V; - } - else { - // Check if the cursor is in an insertion area - lit_point = -1; - if (preciseCursorX>=0.0 && preciseCursorX<=1.0 && preciseCursorY>=0.0 && preciseCursorY<=1.0) - area = FCT_Area_Insertion; - } - } + for (int i = 0; i < (int)curve.x.size(); i++) { + if (curve.x.at(i) != -1) { + dX = curve.x.at(i) - preciseCursorX; + absDX = dX > 0 ? dX : -dX; + + if (absDX < minDistX) { + minDistX = absDX; + closest_point = i; + lit_point = i; + } + + if (absDX <= minDistanceX) { + aboveVLine = true; + dY = curve.y.at(i) - preciseCursorY; + dist = sqrt(dX * dX + dY * dY); + + if (dist < minDist) { + minDist = dist; + } + } + } + } + + if (minDist <= minDistanceX) { + // the cursor is over the point + area = FCT_Area_Point; + } else if (aboveVLine) { + area = FCT_Area_V; + } else { + // Check if the cursor is in an insertion area + lit_point = -1; + + if (preciseCursorX >= 0.0 && preciseCursorX <= 1.0 && preciseCursorY >= 0.0 && preciseCursorY <= 1.0) { + area = FCT_Area_Insertion; + } + } + } } -std::vector MyFlatCurve::getPoints () { +std::vector MyFlatCurve::getPoints () +{ std::vector result; + /*if (curve.type==FCT_Parametric) { result.push_back ((double)(Parametric)); for (int i=0; i<(int)curve.x.size(); i++) { @@ -1597,70 +1778,84 @@ std::vector MyFlatCurve::getPoints () { } } else {*/ - // the first value gives the type of the curve - if (curve.type==FCT_Linear) - result.push_back ((double)(FCT_Linear)); - else if (curve.type==FCT_MinMaxCPoints) - result.push_back ((double)(FCT_MinMaxCPoints)); - // then we push all the points coordinate - for (int i=0; i<(int)curve.x.size(); i++) { - if (curve.x.at(i)>=0) { - result.push_back (curve.x.at(i)); - result.push_back (curve.y.at(i)); - result.push_back (curve.leftTangent.at(i)); - result.push_back (curve.rightTangent.at(i)); - } + // the first value gives the type of the curve + if (curve.type == FCT_Linear) { + result.push_back ((double)(FCT_Linear)); + } else if (curve.type == FCT_MinMaxCPoints) { + result.push_back ((double)(FCT_MinMaxCPoints)); + } + + // then we push all the points coordinate + for (int i = 0; i < (int)curve.x.size(); i++) { + if (curve.x.at(i) >= 0) { + result.push_back (curve.x.at(i)); + result.push_back (curve.y.at(i)); + result.push_back (curve.leftTangent.at(i)); + result.push_back (curve.rightTangent.at(i)); } + } + //} return result; } -void MyFlatCurve::setPoints (const std::vector& p) { +void MyFlatCurve::setPoints (const std::vector& p) +{ int ix = 0; stopNumericalAdjustment(); FlatCurveType t = (FlatCurveType)p[ix++]; curve.type = t; - if (t==FCT_MinMaxCPoints) { + + if (t == FCT_MinMaxCPoints) { curve.x.clear (); curve.y.clear (); curve.leftTangent.clear(); curve.rightTangent.clear(); - for (int i=0; i<(int)p.size()/4; i++) { + + for (int i = 0; i < (int)p.size() / 4; i++) { curve.x.push_back (p[ix++]); curve.y.push_back (p[ix++]); curve.leftTangent.push_back (p[ix++]); curve.rightTangent.push_back (p[ix++]); } } + curveIsDirty = true; setDirty(true); queue_draw (); } -void MyFlatCurve::setPos(double pos, int chanIdx) { +void MyFlatCurve::setPos(double pos, int chanIdx) +{ assert (edited_point > -1); + switch (chanIdx) { case (0): curve.x.at(edited_point) = pos; break; + case (1): curve.y.at(edited_point) = pos; break; + case (2): curve.leftTangent.at(edited_point) = pos; break; + case (3): curve.rightTangent.at(edited_point) = pos; break; } + curveIsDirty = true; setDirty(true); draw(); notifyListener (); } -void MyFlatCurve::stopNumericalAdjustment() { - if (edited_point>-1) { +void MyFlatCurve::stopNumericalAdjustment() +{ + if (edited_point > -1) { edited_point = lit_point = -1; area = FCT_Area_None; coordinateAdjuster->stopNumericalAdjustment(); @@ -1669,13 +1864,15 @@ void MyFlatCurve::stopNumericalAdjustment() { } } -void MyFlatCurve::setType (FlatCurveType t) { +void MyFlatCurve::setType (FlatCurveType t) +{ curve.type = t; setDirty(true); } -void MyFlatCurve::reset(const std::vector &resetCurve, double identityValue) { +void MyFlatCurve::reset(const std::vector &resetCurve, double identityValue) +{ calcDimensions(); stopNumericalAdjustment(); @@ -1692,16 +1889,19 @@ void MyFlatCurve::reset(const std::vector &resetCurve, double identityVa lit_point = -1; curveIsDirty = true; break; + //case Parametric : - // Nothing to do (?) + // Nothing to do (?) default: break; } + setDirty(true); draw(); } -void MyFlatCurve::defaultCurve (double iVal) { +void MyFlatCurve::defaultCurve (double iVal) +{ curve.x.resize(6); curve.y.resize(6); @@ -1709,8 +1909,8 @@ void MyFlatCurve::defaultCurve (double iVal) { curve.rightTangent.resize(6); // Point for RGBCMY colors - for (int i=0; i<6; i++) { - curve.x.at(i) = (1./6.)*i; + for (int i = 0; i < 6; i++) { + curve.x.at(i) = (1. / 6.) * i; curve.y.at(i) = iVal; curve.leftTangent.at(i) = 0.35; curve.rightTangent.at(i) = 0.35; diff --git a/rtgui/myflatcurve.h b/rtgui/myflatcurve.h index 6f18f56d1..cd08edf89 100644 --- a/rtgui/myflatcurve.h +++ b/rtgui/myflatcurve.h @@ -7,7 +7,7 @@ * 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 @@ -27,109 +27,115 @@ // For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget enum FlatCurveType { - FCT_Empty = -1, // Also used for identity curves - FCT_Linear, // 0 - FCT_MinMaxCPoints, // 1 - //FCT_Parametric, // 2 - // Insert new curve type above this line - FCT_Unchanged // Must remain the last of the enum + FCT_Empty = -1, // Also used for identity curves + FCT_Linear, // 0 + FCT_MinMaxCPoints, // 1 + //FCT_Parametric, // 2 + // Insert new curve type above this line + FCT_Unchanged // Must remain the last of the enum }; enum MouseOverAreas { - FCT_Area_None = 1<<0, // over a zone that don't have any - FCT_Area_Insertion = 1<<1, // where the user can insert a new point - FCT_Area_Point = 1<<2, // over an existing point - FCT_Area_H = 1<<3, // cursor is on the horizontal line going through the edited control point - FCT_Area_V = 1<<4, // cursor is on the vertical line going through the edited control point - FCT_Area_LeftTan = 1<<5, // in the left tangent edition area - FCT_Area_RightTan = 1<<6 // in the right tangent edition area + FCT_Area_None = 1 << 0, // over a zone that don't have any + FCT_Area_Insertion = 1 << 1, // where the user can insert a new point + FCT_Area_Point = 1 << 2, // over an existing point + FCT_Area_H = 1 << 3, // cursor is on the horizontal line going through the edited control point + FCT_Area_V = 1 << 4, // cursor is on the vertical line going through the edited control point + FCT_Area_LeftTan = 1 << 5, // in the left tangent edition area + FCT_Area_RightTan = 1 << 6 // in the right tangent edition area }; enum EditedHandle { - FCT_EditedHandle_None = 1<<0, - FCT_EditedHandle_CPointUD = 1<<1, // UD stands for Unknown Direction - FCT_EditedHandle_CPoint = 1<<2, - FCT_EditedHandle_CPointX = 1<<3, - FCT_EditedHandle_CPointY = 1<<4, - FCT_EditedHandle_LeftTan = 1<<5, - FCT_EditedHandle_RightTan = 1<<6 + FCT_EditedHandle_None = 1 << 0, + FCT_EditedHandle_CPointUD = 1 << 1, // UD stands for Unknown Direction + FCT_EditedHandle_CPoint = 1 << 2, + FCT_EditedHandle_CPointX = 1 << 3, + FCT_EditedHandle_CPointY = 1 << 4, + FCT_EditedHandle_LeftTan = 1 << 5, + FCT_EditedHandle_RightTan = 1 << 6 }; -class FlatCurveDescr { +class FlatCurveDescr +{ - public: - FlatCurveType type; - std::vector x, // Range: [0.0 - 1.0] - y, // Range: [0.0 - 1.0], default value = 0.5 - leftTangent, // Range: [0.0 - 1.0], where 1.0 = distance from previous to this point - rightTangent; // Range: [0.0 - 1.0], where 1.0 = distance from this to next point +public: + FlatCurveType type; + std::vector x, // Range: [0.0 - 1.0] + y, // Range: [0.0 - 1.0], default value = 0.5 + leftTangent, // Range: [0.0 - 1.0], where 1.0 = distance from previous to this point + rightTangent; // Range: [0.0 - 1.0], where 1.0 = distance from this to next point }; -class HandlePosition { +class HandlePosition +{ - public: - double centerX; - double centerY; +public: + double centerX; + double centerY; }; -class MyFlatCurve : public MyCurve { +class MyFlatCurve : public MyCurve +{ - protected: - FlatCurveDescr curve; - int closest_point; // the point that is the closest from the cursor - int lit_point; // the point that is lit when the cursor is near it - double clampedX; // clamped grabbed point X coordinates in the [0;1] range - double clampedY; // clamped grabbed point Y coordinates in the [0;1] range - double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY - double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY - double distanceX; // X distance from the cursor to the closest point - double distanceY; // Y distance from the cursor to the closest point - double ugpX; // unclamped grabbed point X coordinate in the graph - double ugpY; // unclamped grabbed point Y coordinate in the graph - double leftTanX; // X position of the left tangent handle - double rightTanX; // X position of the right tangent handle - double preciseCursorX; // X coordinate in the graph of the cursor, as a double value - double preciseCursorY; // Y coordinate in the graph of the cursor, as a double value - double minDistanceX; // X minimal distance before point suppression - double minDistanceY; // Y minimal distance before point suppression - double deletedPointX; // Backup of the X value of the edited point, when deleted while being dragged - HandlePosition leftTanHandle; // XY coordinate if the upper left and bottom right corner of the left tangent handle - HandlePosition rightTanHandle; // XY coordinate if the upper left and bottom right corner of the right tangent handle - bool tanHandlesDisplayed; // True if the tangent handles are displayed - bool periodic; // Flat curves are periodic by default - enum EditedHandle editedHandle; - bool draggingElement; - enum MouseOverAreas area; +protected: + FlatCurveDescr curve; + int closest_point; // the point that is the closest from the cursor + int lit_point; // the point that is lit when the cursor is near it + double clampedX; // clamped grabbed point X coordinates in the [0;1] range + double clampedY; // clamped grabbed point Y coordinates in the [0;1] range + double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY + double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY + double distanceX; // X distance from the cursor to the closest point + double distanceY; // Y distance from the cursor to the closest point + double ugpX; // unclamped grabbed point X coordinate in the graph + double ugpY; // unclamped grabbed point Y coordinate in the graph + double leftTanX; // X position of the left tangent handle + double rightTanX; // X position of the right tangent handle + double preciseCursorX; // X coordinate in the graph of the cursor, as a double value + double preciseCursorY; // Y coordinate in the graph of the cursor, as a double value + double minDistanceX; // X minimal distance before point suppression + double minDistanceY; // Y minimal distance before point suppression + double deletedPointX; // Backup of the X value of the edited point, when deleted while being dragged + HandlePosition leftTanHandle; // XY coordinate if the upper left and bottom right corner of the left tangent handle + HandlePosition rightTanHandle; // XY coordinate if the upper left and bottom right corner of the right tangent handle + bool tanHandlesDisplayed; // True if the tangent handles are displayed + bool periodic; // Flat curves are periodic by default + enum EditedHandle editedHandle; + bool draggingElement; + enum MouseOverAreas area; - void draw (); - void movePoint(bool moveX, bool moveY, bool pipetteDrag=false); - void defaultCurve (double iVal=0.5); - void interpolate (); - void getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifier); - void getMouseOverArea (); - bool getHandles(int n); - CursorShape motionNotify(CursorShape type, double minDistanceX, double minDistanceY, int num); - std::vector get_vector (int veclen); - void get_LUT (LUTf &lut); + void draw (); + void movePoint(bool moveX, bool moveY, bool pipetteDrag = false); + void defaultCurve (double iVal = 0.5); + void interpolate (); + void getCursorPosition(Gdk::EventType evType, bool isHint, int evX, int evY, Gdk::ModifierType modifier); + void getMouseOverArea (); + bool getHandles(int n); + CursorShape motionNotify(CursorShape type, double minDistanceX, double minDistanceY, int num); + std::vector get_vector (int veclen); + void get_LUT (LUTf &lut); - public: - MyFlatCurve (); - //~MyFlatCurve (); - std::vector getPoints (); - void setPeriodicity (bool isPeriodic) { periodic = isPeriodic; }; - void setPoints (const std::vector& p); - void setType (FlatCurveType t); - bool handleEvents (GdkEvent* event); - void reset (const std::vector &resetCurve, double identityValue=0.5); - //void updateBackgroundHistogram (unsigned int* hist); +public: + MyFlatCurve (); + //~MyFlatCurve (); + std::vector getPoints (); + void setPeriodicity (bool isPeriodic) + { + periodic = isPeriodic; + }; + void setPoints (const std::vector& p); + void setType (FlatCurveType t); + bool handleEvents (GdkEvent* event); + void reset (const std::vector &resetCurve, double identityValue = 0.5); + //void updateBackgroundHistogram (unsigned int* hist); - void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey); - void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); - void pipetteButton1Released(EditDataProvider *provider); - void pipetteDrag(EditDataProvider *provider, int modifierKey); + void pipetteMouseOver (CurveEditor *ce, EditDataProvider *provider, int modifierKey); + void pipetteButton1Pressed(EditDataProvider *provider, int modifierKey); + void pipetteButton1Released(EditDataProvider *provider); + void pipetteDrag(EditDataProvider *provider, int modifierKey); - void setPos(double pos, int chanIdx); - virtual void stopNumericalAdjustment(); + void setPos(double pos, int chanIdx); + virtual void stopNumericalAdjustment(); }; #endif diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index 1fd44b9d7..4f7e638f2 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -7,7 +7,7 @@ * 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 @@ -28,321 +28,355 @@ using namespace rtengine; -Navigator::Navigator () { +Navigator::Navigator () +{ - set_label (M("MAIN_MSG_NAVIGATOR")); - Gtk::VBox* mbox = Gtk::manage (new Gtk::VBox ()); - previewWindow = Gtk::manage (new PreviewWindow ()); - mbox->pack_start (*previewWindow, Gtk::PACK_SHRINK, 2); - position = Gtk::manage (new Gtk::Label ()); - mbox->pack_start (*position, Gtk::PACK_SHRINK, 2); + set_label (M("MAIN_MSG_NAVIGATOR")); + Gtk::VBox* mbox = Gtk::manage (new Gtk::VBox ()); + previewWindow = Gtk::manage (new PreviewWindow ()); + mbox->pack_start (*previewWindow, Gtk::PACK_SHRINK, 2); + position = Gtk::manage (new Gtk::Label ()); + mbox->pack_start (*position, Gtk::PACK_SHRINK, 2); - //labels - lR = Gtk::manage (new Gtk::Label (M("NAVIGATOR_R"))); - lG = Gtk::manage (new Gtk::Label (M("NAVIGATOR_G"))); - lB = Gtk::manage (new Gtk::Label (M("NAVIGATOR_B"))); - lH = Gtk::manage (new Gtk::Label (M("NAVIGATOR_H"))); - lS = Gtk::manage (new Gtk::Label (M("NAVIGATOR_S"))); - lV = Gtk::manage (new Gtk::Label (M("NAVIGATOR_V"))); - lLAB_A = Gtk::manage (new Gtk::Label (M("NAVIGATOR_LAB_A"))); - lLAB_B = Gtk::manage (new Gtk::Label (M("NAVIGATOR_LAB_B"))); - lLAB_L = Gtk::manage (new Gtk::Label (M("NAVIGATOR_LAB_L"))); + //labels + lR = Gtk::manage (new Gtk::Label (M("NAVIGATOR_R"))); + lG = Gtk::manage (new Gtk::Label (M("NAVIGATOR_G"))); + lB = Gtk::manage (new Gtk::Label (M("NAVIGATOR_B"))); + lH = Gtk::manage (new Gtk::Label (M("NAVIGATOR_H"))); + lS = Gtk::manage (new Gtk::Label (M("NAVIGATOR_S"))); + lV = Gtk::manage (new Gtk::Label (M("NAVIGATOR_V"))); + lLAB_A = Gtk::manage (new Gtk::Label (M("NAVIGATOR_LAB_A"))); + lLAB_B = Gtk::manage (new Gtk::Label (M("NAVIGATOR_LAB_B"))); + lLAB_L = Gtk::manage (new Gtk::Label (M("NAVIGATOR_LAB_L"))); // left-align labels - lR->set_alignment(Gtk::ALIGN_LEFT); - lG->set_alignment(Gtk::ALIGN_LEFT); - lB->set_alignment(Gtk::ALIGN_LEFT); - lH->set_alignment(Gtk::ALIGN_LEFT); - lS->set_alignment(Gtk::ALIGN_LEFT); - lV->set_alignment(Gtk::ALIGN_LEFT); - lLAB_A->set_alignment(Gtk::ALIGN_LEFT); - lLAB_B->set_alignment(Gtk::ALIGN_LEFT); - lLAB_L->set_alignment(Gtk::ALIGN_LEFT); + lR->set_alignment(Gtk::ALIGN_LEFT); + lG->set_alignment(Gtk::ALIGN_LEFT); + lB->set_alignment(Gtk::ALIGN_LEFT); + lH->set_alignment(Gtk::ALIGN_LEFT); + lS->set_alignment(Gtk::ALIGN_LEFT); + lV->set_alignment(Gtk::ALIGN_LEFT); + lLAB_A->set_alignment(Gtk::ALIGN_LEFT); + lLAB_B->set_alignment(Gtk::ALIGN_LEFT); + lLAB_L->set_alignment(Gtk::ALIGN_LEFT); - //values - R = Gtk::manage (new Gtk::Label ()); - G = Gtk::manage (new Gtk::Label ()); - B = Gtk::manage (new Gtk::Label ()); - H = Gtk::manage (new Gtk::Label ()); - S = Gtk::manage (new Gtk::Label ()); - V = Gtk::manage (new Gtk::Label ()); - LAB_A = Gtk::manage (new Gtk::Label ()); - LAB_B = Gtk::manage (new Gtk::Label ()); - LAB_L = Gtk::manage (new Gtk::Label ()); + //values + R = Gtk::manage (new Gtk::Label ()); + G = Gtk::manage (new Gtk::Label ()); + B = Gtk::manage (new Gtk::Label ()); + H = Gtk::manage (new Gtk::Label ()); + S = Gtk::manage (new Gtk::Label ()); + V = Gtk::manage (new Gtk::Label ()); + LAB_A = Gtk::manage (new Gtk::Label ()); + LAB_B = Gtk::manage (new Gtk::Label ()); + LAB_L = Gtk::manage (new Gtk::Label ()); - // right-align values - R->set_alignment(Gtk::ALIGN_RIGHT); - G->set_alignment(Gtk::ALIGN_RIGHT); - B->set_alignment(Gtk::ALIGN_RIGHT); - H->set_alignment(Gtk::ALIGN_RIGHT); - S->set_alignment(Gtk::ALIGN_RIGHT); - V->set_alignment(Gtk::ALIGN_RIGHT); - LAB_A->set_alignment(Gtk::ALIGN_RIGHT); - LAB_B->set_alignment(Gtk::ALIGN_RIGHT); - LAB_L->set_alignment(Gtk::ALIGN_RIGHT); + // right-align values + R->set_alignment(Gtk::ALIGN_RIGHT); + G->set_alignment(Gtk::ALIGN_RIGHT); + B->set_alignment(Gtk::ALIGN_RIGHT); + H->set_alignment(Gtk::ALIGN_RIGHT); + S->set_alignment(Gtk::ALIGN_RIGHT); + V->set_alignment(Gtk::ALIGN_RIGHT); + LAB_A->set_alignment(Gtk::ALIGN_RIGHT); + LAB_B->set_alignment(Gtk::ALIGN_RIGHT); + LAB_L->set_alignment(Gtk::ALIGN_RIGHT); - // set font family and size - Glib::ustring fontname; + // set font family and size + Glib::ustring fontname; #ifdef WIN32 - fontname = "Droid Sans Mono Slashed"; // font file is provided in the source tree in rtdata/fonts to be installed by the windows installer + fontname = "Droid Sans Mono Slashed"; // font file is provided in the source tree in rtdata/fonts to be installed by the windows installer #endif #ifdef __linux__ - fontname = "Monospace"; + fontname = "Monospace"; #endif #ifdef __APPLE__ - fontname="Menlo"; + fontname = "Menlo"; #endif - if (fontname!=""){ - R->modify_font(Pango::FontDescription(fontname)); - G->modify_font(Pango::FontDescription(fontname)); - B->modify_font(Pango::FontDescription(fontname)); - H->modify_font(Pango::FontDescription(fontname)); - S->modify_font(Pango::FontDescription(fontname)); - V->modify_font(Pango::FontDescription(fontname)); - LAB_A->modify_font(Pango::FontDescription(fontname)); - LAB_B->modify_font(Pango::FontDescription(fontname)); - LAB_L->modify_font(Pango::FontDescription(fontname)); + if (fontname != "") { + R->modify_font(Pango::FontDescription(fontname)); + G->modify_font(Pango::FontDescription(fontname)); + B->modify_font(Pango::FontDescription(fontname)); + H->modify_font(Pango::FontDescription(fontname)); + S->modify_font(Pango::FontDescription(fontname)); + V->modify_font(Pango::FontDescription(fontname)); + LAB_A->modify_font(Pango::FontDescription(fontname)); + LAB_B->modify_font(Pango::FontDescription(fontname)); + LAB_L->modify_font(Pango::FontDescription(fontname)); - lR->modify_font(Pango::FontDescription(fontname)); - lG->modify_font(Pango::FontDescription(fontname)); - lB->modify_font(Pango::FontDescription(fontname)); - lH->modify_font(Pango::FontDescription(fontname)); - lS->modify_font(Pango::FontDescription(fontname)); - lV->modify_font(Pango::FontDescription(fontname)); - lLAB_A->modify_font(Pango::FontDescription(fontname)); - lLAB_B->modify_font(Pango::FontDescription(fontname)); - lLAB_L->modify_font(Pango::FontDescription(fontname)); + lR->modify_font(Pango::FontDescription(fontname)); + lG->modify_font(Pango::FontDescription(fontname)); + lB->modify_font(Pango::FontDescription(fontname)); + lH->modify_font(Pango::FontDescription(fontname)); + lS->modify_font(Pango::FontDescription(fontname)); + lV->modify_font(Pango::FontDescription(fontname)); + lLAB_A->modify_font(Pango::FontDescription(fontname)); + lLAB_B->modify_font(Pango::FontDescription(fontname)); + lLAB_L->modify_font(Pango::FontDescription(fontname)); - position->modify_font(Pango::FontDescription(fontname)); - } + position->modify_font(Pango::FontDescription(fontname)); + } // setup the tables - Gtk::Table* table0 = Gtk::manage (new Gtk::Table (1, 3)); //rows, cols The main table container - // let's pack tables1,2-3 into table0 + Gtk::Table* table0 = Gtk::manage (new Gtk::Table (1, 3)); //rows, cols The main table container + // let's pack tables1,2-3 into table0 // RGB Gtk::HBox* hbox1 = Gtk::manage (new Gtk::HBox ()); // container Gtk::Table* table1 = Gtk::manage (new Gtk::Table (3, 2)); - table1->attach (*lR, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table1->attach (*R, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table1->attach (*lR, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table1->attach (*R, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); - table1->attach (*lG, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table1->attach (*G, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table1->attach (*lG, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table1->attach (*G, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); - table1->attach (*lB, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table1->attach (*B, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table1->attach (*lB, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table1->attach (*B, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); hbox1->pack_start (*table1, Gtk::PACK_EXPAND_WIDGET, 4); hbox1->pack_start (*Gtk::manage (new Gtk::VSeparator()), Gtk::PACK_SHRINK, 4); - table0->attach (*hbox1, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table0->attach (*hbox1, 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); // HSV Gtk::HBox* hbox2 = Gtk::manage (new Gtk::HBox ()); // container Gtk::Table* table2 = Gtk::manage (new Gtk::Table (3, 2)); - table2->attach (*lH, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table2->attach (*H, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table2->attach (*lH, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table2->attach (*H, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); - table2->attach (*lS, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table2->attach (*S, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table2->attach (*lS, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table2->attach (*S, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); - table2->attach (*lV, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table2->attach (*V, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table2->attach (*lV, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table2->attach (*V, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); hbox2->pack_start (*table2, Gtk::PACK_EXPAND_WIDGET, 4); hbox2->pack_start (*Gtk::manage (new Gtk::VSeparator()), Gtk::PACK_SHRINK, 4); - table0->attach (*hbox2, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table0->attach (*hbox2, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); // LAB Gtk::HBox* hbox3 = Gtk::manage (new Gtk::HBox ()); // container Gtk::Table* table3 = Gtk::manage (new Gtk::Table (3, 2)); - table3->attach (*lLAB_L, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table3->attach (*LAB_L, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table3->attach (*lLAB_L, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table3->attach (*LAB_L, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); - table3->attach (*lLAB_A, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table3->attach (*LAB_A, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table3->attach (*lLAB_A, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table3->attach (*LAB_A, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); - table3->attach (*lLAB_B, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 4, 0); - table3->attach (*LAB_B, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table3->attach (*lLAB_B, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 4, 0); + table3->attach (*LAB_B, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); hbox3->pack_start (*table3, Gtk::PACK_EXPAND_WIDGET, 4); hbox3->pack_start (*Gtk::manage (new Gtk::HBox()), Gtk::PACK_SHRINK, 2); - table0->attach (*hbox3, 2, 3, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + table0->attach (*hbox3, 2, 3, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 0, 0); table0->set_homogeneous(true); // all cells will be the same size as the largest cell. mbox->pack_start (*table0, Gtk::PACK_EXPAND_WIDGET, 2); - add (*mbox); - - setInvalid (); - show_all (); + add (*mbox); + + setInvalid (); + show_all (); } -void Navigator::setInvalid (int fullWidth, int fullHeight) { - if (fullWidth>0 && fullHeight>0) - position->set_text (Glib::ustring::compose (M("NAVIGATOR_XY_FULL"),fullWidth,fullHeight)); - else +void Navigator::setInvalid (int fullWidth, int fullHeight) +{ + if (fullWidth > 0 && fullHeight > 0) { + position->set_text (Glib::ustring::compose (M("NAVIGATOR_XY_FULL"), fullWidth, fullHeight)); + } else { position->set_text (M("NAVIGATOR_XY_NA")); + } - R->set_text (M("NAVIGATOR_NA")); - G->set_text (M("NAVIGATOR_NA")); - B->set_text (M("NAVIGATOR_NA")); - H->set_text (M("NAVIGATOR_NA")); - S->set_text (M("NAVIGATOR_NA")); - V->set_text (M("NAVIGATOR_NA")); - LAB_A->set_text (M("NAVIGATOR_NA")); - LAB_B->set_text (M("NAVIGATOR_NA")); - LAB_L->set_text (M("NAVIGATOR_NA")); + R->set_text (M("NAVIGATOR_NA")); + G->set_text (M("NAVIGATOR_NA")); + B->set_text (M("NAVIGATOR_NA")); + H->set_text (M("NAVIGATOR_NA")); + S->set_text (M("NAVIGATOR_NA")); + V->set_text (M("NAVIGATOR_NA")); + LAB_A->set_text (M("NAVIGATOR_NA")); + LAB_B->set_text (M("NAVIGATOR_NA")); + LAB_L->set_text (M("NAVIGATOR_NA")); } // if !validPos then x/y contain the full image size -void Navigator::pointerMoved (bool validPos, Glib::ustring profile,Glib::ustring profileW, int x, int y, int r, int g, int b) { +void Navigator::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) +{ - if (!validPos) - setInvalid (x,y); - else { - position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y)); + if (!validPos) { + setInvalid (x, y); + } else { + position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y)); - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), r*100.f/255.f) + Glib::ustring("%")); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), g*100.f/255.f) + Glib::ustring("%")); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), b*100.f/255.f) + Glib::ustring("%")); + R->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), r * 100.f / 255.f) + Glib::ustring("%")); + G->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), g * 100.f / 255.f) + Glib::ustring("%")); + B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), b * 100.f / 255.f) + Glib::ustring("%")); - float h, s, v; - Color::rgb2hsv (r*0xffff/0xff, g*0xffff/0xff, b*0xffff/0xff, h, s, v); - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), h*360.f) + Glib::ustring("\xc2\xb0")); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), s*100.f) + Glib::ustring("%")); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), v*100.f) + Glib::ustring("%")); + float h, s, v; + Color::rgb2hsv (r * 0xffff / 0xff, g * 0xffff / 0xff, b * 0xffff / 0xff, h, s, v); + H->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), h * 360.f) + Glib::ustring("\xc2\xb0")); + S->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), s * 100.f) + Glib::ustring("%")); + V->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), v * 100.f) + Glib::ustring("%")); - float LAB_a, LAB_b, LAB_l; - //rgb2lab (r, g, b, LAB_l, LAB_a, LAB_b); - rgb2lab (profile, profileW, r, g, b, LAB_l, LAB_a, LAB_b); // TODO: Really sure this function works? - LAB_A->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_a)); - LAB_B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_b)); - LAB_L->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_l)); - } + float LAB_a, LAB_b, LAB_l; + //rgb2lab (r, g, b, LAB_l, LAB_a, LAB_b); + rgb2lab (profile, profileW, r, g, b, LAB_l, LAB_a, LAB_b); // TODO: Really sure this function works? + LAB_A->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_a)); + LAB_B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_b)); + LAB_L->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_l)); + } } -void Navigator::rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b) { - double xyz_rgb[3][3]; - const double ep=216.0/24389.0; - const double ka=24389.0/27.0; +void Navigator::rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b) +{ + double xyz_rgb[3][3]; + const double ep = 216.0 / 24389.0; + const double ka = 24389.0 / 27.0; - double var_R = r / 255.0; - double var_G = g / 255.0; - double var_B = b / 255.0; + double var_R = r / 255.0; + double var_G = g / 255.0; + double var_B = b / 255.0; - Glib::ustring profileCalc; - profileCalc="sRGB";//default - if(options.rtSettings.HistogramWorking) profileCalc=profileW;//display working - - else {// if you want display = output space - if (profile=="RT_sRGB" || profile=="RT_sRGB_gBT709" || profile=="RT_sRGB_g10") profileCalc="sRGB"; - if (profile=="ProPhoto" || profile=="RT_Large_gBT709" || profile=="RT_Large_g10" || profile=="RT_Large_gsRGB") profileCalc="ProPhoto"; - if (profile=="AdobeRGB1998" || profile=="RT_Medium_gsRGB") profileCalc="Adobe RGB"; - if (profile=="WideGamutRGB") profileCalc="WideGamut"; - } - if(options.rtSettings.HistogramWorking) {//display working - if (profileW=="sRGB") {//apply sRGB inverse gamma + Glib::ustring profileCalc; + profileCalc = "sRGB"; //default - if ( var_R > 0.04045 ) - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_R = var_R / 12.92; - if ( var_G > 0.04045 ) - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_G = var_G / 12.92; - if ( var_B > 0.04045 ) - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_B = var_B / 12.92; - } - else - if (profileW=="ProPhoto") {// apply inverse gamma 1.8 - var_R = pow ( var_R, 1.8); - var_G = pow ( var_G, 1.8); - var_B = pow ( var_B, 1.8); - } - else {// apply inverse gamma 2.2 - var_R = pow ( var_R, 2.2); - var_G = pow ( var_G, 2.2); - var_B = pow ( var_B, 2.2); - } - } - else {//display outout profile + if(options.rtSettings.HistogramWorking) { + profileCalc = profileW; //display working + } - if (profile=="RT_sRGB" || profile=="RT_Large_gsRGB" || profile=="RT_Medium_gsRGB") {//apply sRGB inverse gamma - if ( var_R > 0.04045 ) - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_R = var_R / 12.92; - if ( var_G > 0.04045 ) - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_G = var_G / 12.92; - if ( var_B > 0.04045 ) - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - else - var_B = var_B / 12.92; - } - - else if (profile=="RT_sRGB_gBT709" || profile=="RT_Large_gBT709") {// - if ( var_R > 0.0795 ) - var_R = pow ( ( ( var_R + 0.0954 ) / 1.0954 ), 2.2);else var_R=var_R/4.5; + else {// if you want display = output space + if (profile == "RT_sRGB" || profile == "RT_sRGB_gBT709" || profile == "RT_sRGB_g10") { + profileCalc = "sRGB"; + } - if ( var_G > 0.0795 ) - var_G = pow ( ( ( var_G + 0.0954 ) / 1.0954 ), 2.2);else var_G=var_G/4.5; + if (profile == "ProPhoto" || profile == "RT_Large_gBT709" || profile == "RT_Large_g10" || profile == "RT_Large_gsRGB") { + profileCalc = "ProPhoto"; + } - if ( var_B > 0.0795 ) - var_B = pow ( ( ( var_B + 0.0954 ) / 1.0954 ), 2.2);else var_B=var_B/4.5; - - } - else if (profile=="ProPhoto") {// apply inverse gamma 1.8 - - var_R = pow ( var_R, 1.8); - var_G = pow ( var_G, 1.8); - var_B = pow ( var_B, 1.8); - } - else if (profile=="RT_sRGB_g10" || profile=="RT_Large_g10") {// apply inverse gamma 1.8 - - var_R = pow ( var_R, 1.); - var_G = pow ( var_G, 1.); - var_B = pow ( var_B, 1.); - } - - else {// apply inverse gamma 2.2 - var_R = pow ( var_R, 2.2); - var_G = pow ( var_G, 2.2); - var_B = pow ( var_B, 2.2); - } - } - // TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileW); + if (profile == "AdobeRGB1998" || profile == "RT_Medium_gsRGB") { + profileCalc = "Adobe RGB"; + } + + if (profile == "WideGamutRGB") { + profileCalc = "WideGamut"; + } + } + + if(options.rtSettings.HistogramWorking) {//display working + if (profileW == "sRGB") { //apply sRGB inverse gamma + + if ( var_R > 0.04045 ) { + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_R = var_R / 12.92; + } + + if ( var_G > 0.04045 ) { + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_G = var_G / 12.92; + } + + if ( var_B > 0.04045 ) { + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_B = var_B / 12.92; + } + } else if (profileW == "ProPhoto") { // apply inverse gamma 1.8 + var_R = pow ( var_R, 1.8); + var_G = pow ( var_G, 1.8); + var_B = pow ( var_B, 1.8); + } else { // apply inverse gamma 2.2 + var_R = pow ( var_R, 2.2); + var_G = pow ( var_G, 2.2); + var_B = pow ( var_B, 2.2); + } + } else { //display outout profile + + if (profile == "RT_sRGB" || profile == "RT_Large_gsRGB" || profile == "RT_Medium_gsRGB") { //apply sRGB inverse gamma + if ( var_R > 0.04045 ) { + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_R = var_R / 12.92; + } + + if ( var_G > 0.04045 ) { + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_G = var_G / 12.92; + } + + if ( var_B > 0.04045 ) { + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_B = var_B / 12.92; + } + } + + else if (profile == "RT_sRGB_gBT709" || profile == "RT_Large_gBT709") { // + if ( var_R > 0.0795 ) { + var_R = pow ( ( ( var_R + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_R = var_R / 4.5; + } + + if ( var_G > 0.0795 ) { + var_G = pow ( ( ( var_G + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_G = var_G / 4.5; + } + + if ( var_B > 0.0795 ) { + var_B = pow ( ( ( var_B + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_B = var_B / 4.5; + } + + } else if (profile == "ProPhoto") { // apply inverse gamma 1.8 + + var_R = pow ( var_R, 1.8); + var_G = pow ( var_G, 1.8); + var_B = pow ( var_B, 1.8); + } else if (profile == "RT_sRGB_g10" || profile == "RT_Large_g10") { // apply inverse gamma 1.8 + + var_R = pow ( var_R, 1.); + var_G = pow ( var_G, 1.); + var_B = pow ( var_B, 1.); + } + + else {// apply inverse gamma 2.2 + var_R = pow ( var_R, 2.2); + var_G = pow ( var_G, 2.2); + var_B = pow ( var_B, 2.2); + } + } + + // TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileW); TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileCalc); - for (int m=0; m<3; m++) - for (int n=0; n<3; n++) { - xyz_rgb[m][n] = wprof[m][n]; - } + for (int m = 0; m < 3; m++) + for (int n = 0; n < 3; n++) { + xyz_rgb[m][n] = wprof[m][n]; + } - double varxx,varyy,varzz; - double var_X = ( xyz_rgb[0][0]*var_R + xyz_rgb[0][1]*var_G + xyz_rgb[0][2]*var_B ) / Color::D50x; - double var_Y = ( xyz_rgb[1][0]*var_R + xyz_rgb[1][1]*var_G + xyz_rgb[1][2]*var_B ) ; - double var_Z = ( xyz_rgb[2][0]*var_R + xyz_rgb[2][1]*var_G + xyz_rgb[2][2]*var_B ) / Color::D50z; + double varxx, varyy, varzz; + double var_X = ( xyz_rgb[0][0] * var_R + xyz_rgb[0][1] * var_G + xyz_rgb[0][2] * var_B ) / Color::D50x; + double var_Y = ( xyz_rgb[1][0] * var_R + xyz_rgb[1][1] * var_G + xyz_rgb[1][2] * var_B ) ; + double var_Z = ( xyz_rgb[2][0] * var_R + xyz_rgb[2][1] * var_G + xyz_rgb[2][2] * var_B ) / Color::D50z; - varxx = var_X>ep?cbrt(var_X):( ka * var_X + 16.0) / 116.0 ; - varyy = var_Y>ep?cbrt(var_Y):( ka * var_Y + 16.0) / 116.0 ; - varzz = var_Z>ep?cbrt(var_Z):( ka * var_Z + 16.0) / 116.0 ; - LAB_l = ( 116 * varyy ) - 16; - LAB_a = 500 * ( varxx - varyy ); - LAB_b = 200 * ( varyy - varzz ); + varxx = var_X > ep ? cbrt(var_X) : ( ka * var_X + 16.0) / 116.0 ; + varyy = var_Y > ep ? cbrt(var_Y) : ( ka * var_Y + 16.0) / 116.0 ; + varzz = var_Z > ep ? cbrt(var_Z) : ( ka * var_Z + 16.0) / 116.0 ; + LAB_l = ( 116 * varyy ) - 16; + LAB_a = 500 * ( varxx - varyy ); + LAB_b = 200 * ( varyy - varzz ); } diff --git a/rtgui/navigator.h b/rtgui/navigator.h index 999e1a3b1..3abf34a2f 100644 --- a/rtgui/navigator.h +++ b/rtgui/navigator.h @@ -7,7 +7,7 @@ * 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 @@ -24,32 +24,33 @@ #include "pointermotionlistener.h" #include "../rtengine/iccstore.h" -class Navigator : public Gtk::Frame, public PointerMotionListener { +class Navigator : public Gtk::Frame, public PointerMotionListener +{ - typedef const double (*TMatrix)[3]; + typedef const double (*TMatrix)[3]; - protected: - Gtk::Label* position; - Gtk::Label *R, *G, *B; - Gtk::Label *H, *S, *V; - Gtk::Label *LAB_A, *LAB_B, *LAB_L; +protected: + Gtk::Label* position; + Gtk::Label *R, *G, *B; + Gtk::Label *H, *S, *V; + Gtk::Label *LAB_A, *LAB_B, *LAB_L; - Gtk::Label *lR, *lG, *lB; - Gtk::Label *lH, *lS, *lV; - Gtk::Label *lLAB_A, *lLAB_B, *lLAB_L; + Gtk::Label *lR, *lG, *lB; + Gtk::Label *lH, *lS, *lV; + Gtk::Label *lLAB_A, *lLAB_B, *lLAB_L; - void rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b); - - void setInvalid (int fullWidth=-1, int fullHeight=-1); + void rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b); - public: - PreviewWindow* previewWindow; + void setInvalid (int fullWidth = -1, int fullHeight = -1); - Navigator (); +public: + PreviewWindow* previewWindow; - // pointermotionlistener interface - // void pointerMoved (bool validPos, int x, int y, int r, int g, int b); - void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW,int x, int y, int r, int g, int b); + Navigator (); + + // pointermotionlistener interface + // void pointerMoved (bool validPos, int x, int y, int r, int g, int b); + void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b); }; diff --git a/rtgui/options.cc b/rtgui/options.cc index 7e62547f9..efdb98732 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -7,7 +7,7 @@ * 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 @@ -52,7 +52,8 @@ Glib::ustring versionString = VERSION; Glib::ustring versionSuffixString = VERSION_SUFFIX; Glib::ustring paramFileExtension = ".pp3"; -Options::Options () { +Options::Options () +{ defProfRawMissing = false; defProfImgMissing = false; @@ -61,31 +62,42 @@ Options::Options () { const char *DefaultLanguage = "English (US)"; -inline bool Options::checkProfilePath(Glib::ustring &path) { - if (path.empty()) +inline bool Options::checkProfilePath(Glib::ustring &path) +{ + if (path.empty()) { return false; + } Glib::ustring p = getUserProfilePath(); - if (!p.empty() && safe_file_test (path+paramFileExtension, Glib::FILE_TEST_EXISTS)) + + if (!p.empty() && safe_file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { return true; + } p = getGlobalProfilePath(); - if (!p.empty() && safe_file_test (path+paramFileExtension, Glib::FILE_TEST_EXISTS)) - return true; - else - return false; -} -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 (!p.empty() && safe_file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { return true; - else { - if (!errString.empty()) printf("%s\n", errString.c_str()); + } else { return false; } } -void Options::updatePaths() { +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)) { + return true; + } else { + if (!errString.empty()) { + printf("%s\n", errString.c_str()); + } + + return false; + } +} + +void Options::updatePaths() +{ Glib::ustring tmpPath; @@ -96,50 +108,59 @@ void Options::updatePaths() { // absolute path if (!checkDirPath (profilePath, "")) { safe_g_mkdir_with_parents (profilePath, 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()); + + 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()); + } } + if (checkDirPath (profilePath, "Error: the specified user's profiles' path doesn't point to a directory or doesn't exist!\n")) { if (multiUser) { userProfilePath = profilePath; tmpPath = Glib::build_filename(argv0, "profiles"); + if(checkDirPath (tmpPath, "Error: the global's profiles' path doesn't point to a directory or doesn't exist!\n")) { - if (userProfilePath != tmpPath) + if (userProfilePath != tmpPath) { globalProfilePath = tmpPath; + } } - } - else { + } else { globalProfilePath = profilePath; } - } - else { + } else { tmpPath = Glib::build_filename(argv0, "profiles"); + if(checkDirPath (tmpPath, "Error: the global's profiles' path doesn't point to a directory or doesn't exist!\n")) { globalProfilePath = tmpPath; } } - } - else { + } else { // relative paths if (multiUser) { tmpPath = Glib::build_filename(rtdir, profilePath); + if (!checkDirPath (tmpPath, "")) { safe_g_mkdir_with_parents (tmpPath, 511); - if (!checkDirPath (tmpPath, "")) + + if (!checkDirPath (tmpPath, "")) { printf("Error: user's profiles' directory \"%s\" creation failed\n", tmpPath.c_str()); + } } + if(checkDirPath (tmpPath, "Error: the specified user's profiles' path doesn't point to a directory!\n")) { - userProfilePath = tmpPath; + userProfilePath = tmpPath; } + tmpPath = Glib::build_filename(argv0, "profiles"); + if(checkDirPath (tmpPath, "Error: the specified user's profiles' path doesn't point to a directory or doesn't exist!\n")) { globalProfilePath = tmpPath; } - } - else { + } else { // common directory // directory name set in options is ignored, we use the default directory name tmpPath = Glib::build_filename(argv0, "profiles"); + if(checkDirPath (tmpPath, "Error: no global profiles' directory found!\n")) { globalProfilePath = tmpPath; } @@ -147,40 +168,63 @@ 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() || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastLabCurvesDir = preferredPath; - if (lastDenoiseCurvesDir.empty() || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_IS_DIR)) + } + + if (lastDenoiseCurvesDir.empty() || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastWaveletCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastVibranceCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (loadSaveProfilePath, Glib::FILE_TEST_EXISTS) || !safe_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() || !safe_file_test (lastBWCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastBWCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastBWCurvesDir = preferredPath; - + } + } -Glib::ustring Options::getPreferredProfilePath() { - if (!userProfilePath.empty()) +Glib::ustring Options::getPreferredProfilePath() +{ + if (!userProfilePath.empty()) { return userProfilePath; - else if (!globalProfilePath.empty()) + } else if (!globalProfilePath.empty()) { return globalProfilePath; - else + } else { return ""; + } } /** @brief Get the absolute path of the given filename or the "Neutral" special value @@ -190,32 +234,39 @@ Glib::ustring Options::getPreferredProfilePath() { *@return Send back the absolute path of the given filename or "Neutral" if "Neutral" has been set to profName. Implementor will have * to test for this particular value. If the absolute path is invalid (e.g. the file doesn't exist), it will return an empty string. */ -Glib::ustring Options::findProfilePath(Glib::ustring &profName) { - if (profName.empty()) +Glib::ustring Options::findProfilePath(Glib::ustring &profName) +{ + if (profName.empty()) { return ""; + } - if (profName == DEFPROFILE_INTERNAL) + if (profName == DEFPROFILE_INTERNAL) { return profName; + } Glib::ustring p = profName.substr(0, 4); - if (p=="${U}") { + + if (p == "${U}") { // the path starts by the User virtual path 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() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { return Glib::path_get_dirname(fullPath); - } - else if (p=="${G}") { + } + } else if (p == "${G}") { // the path starts by the User virtual path 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() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { return Glib::path_get_dirname(fullPath); - } - else { + } + } else { // compatibility case -> convert the path to the new format p = getUserProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName + paramFileExtension); + if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { // update the profile path profName = Glib::build_filename("${U}", profName); @@ -224,16 +275,19 @@ 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)) { profName = Glib::build_filename("${G}", profName); return Glib::path_get_dirname(fullPath); } } + return ""; } -void Options::setDefaults () { +void Options::setDefaults () +{ font = "sans, 8"; windowWidth = 1200; @@ -295,29 +349,29 @@ void Options::setDefaults () { fbShowBasicExif = true; fbShowExpComp = false; fbShowHidden = false; - fbArrangement = 2; // was 0 + fbArrangement = 2; // was 0 multiUser = true; profilePath = "profiles"; - loadSaveProfilePath = ""; // will be corrected in load as otherwise construction fails - version = "0.0.0.0"; // temporary value; will be correctly set in RTWindow::on_realize + loadSaveProfilePath = ""; // will be corrected in load as otherwise construction fails + version = "0.0.0.0"; // temporary value; will be correctly set in RTWindow::on_realize thumbSize = 240; thumbSizeTab = 180; thumbSizeQueue = 160; - sameThumbSize = true; // preferring speed of switch between file browser and single editor tab + sameThumbSize = true; // preferring speed of switch between file browser and single editor tab showHistory = true; - showFilePanelState = 0; // Not used anymore ; was the thumb strip state + showFilePanelState = 0; // Not used anymore ; was the thumb strip state showInfo = true; cropPPI = 600; showClippedHighlights = false; showClippedShadows = false; - highlightThreshold = 253; // was 254 - shadowThreshold = 8; // was 0 + highlightThreshold = 253; // was 254 + shadowThreshold = 8; // was 0 bgcolor = 0; blinkClipped = false; language = DefaultLanguage; - languageAutoDetect= langMgr.isOSLanguageDetectSupported(); + languageAutoDetect = langMgr.isOSLanguageDetectSupported(); lastSaveAsPath = ""; - overwriteOutputFile = false; // if TRUE, existing output JPGs/PNGs are overwritten, instead of adding ..-1.jpg, -2.jpg etc. + overwriteOutputFile = false; // if TRUE, existing output JPGs/PNGs are overwritten, instead of adding ..-1.jpg, -2.jpg etc. theme = "25-Gray-Gray"; slimUI = false; useSystemTheme = false; @@ -326,10 +380,10 @@ void Options::setDefaults () { thumbInterp = 1; autoSuffix = true; forceFormatOpts = true; - saveMethodNum = 0; // 0->immediate, 1->putToQueuHead, 2->putToQueueTail - saveParamsFile = true; // was false, but saving the procparams files next to the file make more sense when reorganizing file tree than in a cache - saveParamsCache = false; // there's no need to save the procparams files in a cache if saveParamsFile is true - paramsLoadLocation = PLL_Input; // was PLL_Cache + saveMethodNum = 0; // 0->immediate, 1->putToQueuHead, 2->putToQueueTail + saveParamsFile = true; // was false, but saving the procparams files next to the file make more sense when reorganizing file tree than in a cache + saveParamsCache = false; // there's no need to save the procparams files in a cache if saveParamsFile is true + paramsLoadLocation = PLL_Input; // was PLL_Cache procQueueEnabled = false; gimpDir = ""; psDir = ""; @@ -353,7 +407,7 @@ void Options::setDefaults () { thumbnailZoomRatios.push_back (1.0); overlayedFileNames = false; filmStripOverlayedFileNames = false; - internalThumbIfUntouched = true; // if TRUE, only fast, internal preview images are taken if the image is not edited yet + internalThumbIfUntouched = true; // if TRUE, only fast, internal preview images are taken if the image is not edited yet showFileNames = true; filmStripShowFileNames = false; tabbedUI = false; @@ -373,7 +427,7 @@ void Options::setDefaults () { #endif filledProfile = false; maxInspectorBuffers = 2; // a rather conservative value for low specced systems... - serializeTiffRead = true; + serializeTiffRead = true; FileBrowserToolbarSingleRow = false; hideTPVScrollbar = false; @@ -432,8 +486,8 @@ void Options::setDefaults () { navGuideBrush[2] = 0.0; navGuideBrush[3] = 1.0; - sndEnable=true; - sndLngEditProcDoneSecs=3.0; + sndEnable = true; + sndLngEditProcDoneSecs = 3.0; #ifdef __linux__ sndBatchQueueDone = "complete"; sndLngEditProcDone = "window-attention"; @@ -441,130 +495,133 @@ void Options::setDefaults () { // Reminder: 0 = SET mode, 1 = ADD mode int babehav[] = { - 0, // ADDSET_TC_EXPCOMP - 0, // ADDSET_TC_BRIGHTNESS - 0, // ADDSET_TC_BLACKLEVEL - 0, // ADDSET_TC_CONTRAST - 0, // ADDSET_SH_HIGHLIGHTS - 0, // ADDSET_SH_SHADOWS - 0, // ADDSET_SH_LOCALCONTRAST - 0, // ADDSET_LC_BRIGHTNESS - 0, // ADDSET_LC_CONTRAST - 0, // ADDSET_SHARP_AMOUNT - 0, // ADDSET_WB_TEMPERATURE - 0, // ADDSET_WB_GREEN - 0, // ADDSET_ROTATE_DEGREE - 0, // ADDSET_DIST_AMOUNT - 0, // ADDSET_PERSPECTIVE - 0, // ADDSET_CA - 0, // ADDSET_VIGN_AMOUNT - 0, // ADDSET_VIGN_RADIUS - 0, // ADDSET_VIGN_STRENGTH - 0, // ADDSET_VIGN_CENTER - 0, // ADDSET_LC_CHROMATICITY - 0, // ADDSET_TC_SATURATION - 0, // ADDSET_TC_HLCOMPAMOUNT - 0, // ADDSET_TC_HLCOMPTHRESH - 0, // ADDSET_TC_SHCOMP - 0, // ADDSET_DIRPYREQ - 0, // ADDSET_DIRPYRDN_LUMA - 0, // ADDSET_DIRPYRDN_LUDET - 0, // ADDSET_DIRPYRDN_CHROMA - 0, // ADDSET_DIRPYRDN_CHROMARED - 0, // ADDSET_DIRPYRDN_CHROMABLUE - 0, // ADDSET_DIRPYRDN_GAMMA - 0, // ADDSET_CHMIXER - 0, // ADDSET_PREPROCESS_GREENEQUIL - 0, // ADDSET_PREPROCESS_LINEDENOISE - 0, // ADDSET_RAWCACORR - 0, // ADDSET_RAWEXPOS_LINEAR - 0, // ADDSET_RAWEXPOS_PRESER - 0, // ADDSET_RAWEXPOS_BLACKS - 0, // ADDSET_SHARPENEDGE_AMOUNT - 0, // ADDSET_SHARPENMICRO_AMOUNT - 0, // ADDSET_SHARPENEDGE_PASS - 0, // ADDSET_SHARPENMICRO_UNIFORMITY - 0, // ADDSET_VIBRANCE_PASTELS - 0, // ADDSET_VIBRANCE_SATURATED - 0, // ADDSET_FREE_OUPUT_GAMMA - 0, // ADDSET_FREE_OUTPUT_SLOPE - 0, // ADDSET_CAT_DEGREE - 0, // ADDSET_CAT_ADAPSCEN - 0, // ADDSET_CAT_ADAPLUM - 0, // ADDSET_CAT_LIGHT - 0, // ADDSET_CAT_RSTPRO - 0, // ADDSET_CAT_BADPIX - 0, // ADDSET_CAT_JLIGHT - 0, // ADDSET_CAT_CHROMA - 0, // ADDSET_CAT_CONTRAST - 0, // ADDSET_CAT_CHROMA_S - 0, // ADDSET_CAT_CHROMA_M - 0, // ADDSET_CAT_HUE - 0, // ADDSET_CAT_BADPIX - 0, // ADDSET_WB_EQUAL - 0, // ADDSET_GRADIENT_DEGREE - 0, // ADDSET_GRADIENT_FEATHER - 0, // ADDSET_GRADIENT_STRENGTH - 0, // ADDSET_GRADIENT_CENTER - 0, // ADDSET_PCVIGNETTE_STRENGTH - 0, // ADDSET_PCVIGNETTE_FEATHER - 0, // ADDSET_PCVIGNETTE_ROUNDNESS - 0, // ADDSET_BLACKWHITE_HUES - 0, // ADDSET_BLACKWHITE_GAMMA - 0, // ADDSET_DIRPYREQ_THRESHOLD - 0, // ADDSET_DIRPYREQ_SKINPROTECT - 0, // ADDSET_COLORTONING_SPLIT - 0, //ADDSET_DIRPYRDN_PASSES - 0, // ADDSET_RAWFFCLIPCONTROL - 0, // ADDSET_FILMSIMULATION_STRENGTH - 0, //ADDSET_WA - 0, //ADDSET_WA_THRESHOLD - 0, //ADDSET_WA_THRESHOLD2 - 0, //ADDSET_WA_THRES - 0, //ADDSET_WA_CHRO - 0, //ADDSET_WA_CHROMA - 0, //ADDSET_WA_CONTRAST - 0, //ADDSET_WA_SKINPROTECT - 0, //ADDSET_WA_RESCHRO - 0, //ADDSET_WA_RESCON - 0, //ADDSET_WA_RESCONH - 0, //ADDSET_WA_THRR - 0, //ADDSET_WA_THRRH - 0, //ADDSET_WA_SKYPROTECT - 0, //ADDSET_WA_EDGRAD - 0, //ADDSET_WA_EDGVAL - 0, //ADDSET_WA_STRENGTH - 0, //ADDSET_WA_EDGEDETECT - 0, //ADDSET_WA_EDGEDETECTTHR - 0, //ADDSET_WA_EDGEDETECTTHR2 - 0, //ADDSET_WA_TMRS - 0, //ADDSET_WA_GAMMA - - }; - baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM); - + 0, // ADDSET_TC_EXPCOMP + 0, // ADDSET_TC_BRIGHTNESS + 0, // ADDSET_TC_BLACKLEVEL + 0, // ADDSET_TC_CONTRAST + 0, // ADDSET_SH_HIGHLIGHTS + 0, // ADDSET_SH_SHADOWS + 0, // ADDSET_SH_LOCALCONTRAST + 0, // ADDSET_LC_BRIGHTNESS + 0, // ADDSET_LC_CONTRAST + 0, // ADDSET_SHARP_AMOUNT + 0, // ADDSET_WB_TEMPERATURE + 0, // ADDSET_WB_GREEN + 0, // ADDSET_ROTATE_DEGREE + 0, // ADDSET_DIST_AMOUNT + 0, // ADDSET_PERSPECTIVE + 0, // ADDSET_CA + 0, // ADDSET_VIGN_AMOUNT + 0, // ADDSET_VIGN_RADIUS + 0, // ADDSET_VIGN_STRENGTH + 0, // ADDSET_VIGN_CENTER + 0, // ADDSET_LC_CHROMATICITY + 0, // ADDSET_TC_SATURATION + 0, // ADDSET_TC_HLCOMPAMOUNT + 0, // ADDSET_TC_HLCOMPTHRESH + 0, // ADDSET_TC_SHCOMP + 0, // ADDSET_DIRPYREQ + 0, // ADDSET_DIRPYRDN_LUMA + 0, // ADDSET_DIRPYRDN_LUDET + 0, // ADDSET_DIRPYRDN_CHROMA + 0, // ADDSET_DIRPYRDN_CHROMARED + 0, // ADDSET_DIRPYRDN_CHROMABLUE + 0, // ADDSET_DIRPYRDN_GAMMA + 0, // ADDSET_CHMIXER + 0, // ADDSET_PREPROCESS_GREENEQUIL + 0, // ADDSET_PREPROCESS_LINEDENOISE + 0, // ADDSET_RAWCACORR + 0, // ADDSET_RAWEXPOS_LINEAR + 0, // ADDSET_RAWEXPOS_PRESER + 0, // ADDSET_RAWEXPOS_BLACKS + 0, // ADDSET_SHARPENEDGE_AMOUNT + 0, // ADDSET_SHARPENMICRO_AMOUNT + 0, // ADDSET_SHARPENEDGE_PASS + 0, // ADDSET_SHARPENMICRO_UNIFORMITY + 0, // ADDSET_VIBRANCE_PASTELS + 0, // ADDSET_VIBRANCE_SATURATED + 0, // ADDSET_FREE_OUPUT_GAMMA + 0, // ADDSET_FREE_OUTPUT_SLOPE + 0, // ADDSET_CAT_DEGREE + 0, // ADDSET_CAT_ADAPSCEN + 0, // ADDSET_CAT_ADAPLUM + 0, // ADDSET_CAT_LIGHT + 0, // ADDSET_CAT_RSTPRO + 0, // ADDSET_CAT_BADPIX + 0, // ADDSET_CAT_JLIGHT + 0, // ADDSET_CAT_CHROMA + 0, // ADDSET_CAT_CONTRAST + 0, // ADDSET_CAT_CHROMA_S + 0, // ADDSET_CAT_CHROMA_M + 0, // ADDSET_CAT_HUE + 0, // ADDSET_CAT_BADPIX + 0, // ADDSET_WB_EQUAL + 0, // ADDSET_GRADIENT_DEGREE + 0, // ADDSET_GRADIENT_FEATHER + 0, // ADDSET_GRADIENT_STRENGTH + 0, // ADDSET_GRADIENT_CENTER + 0, // ADDSET_PCVIGNETTE_STRENGTH + 0, // ADDSET_PCVIGNETTE_FEATHER + 0, // ADDSET_PCVIGNETTE_ROUNDNESS + 0, // ADDSET_BLACKWHITE_HUES + 0, // ADDSET_BLACKWHITE_GAMMA + 0, // ADDSET_DIRPYREQ_THRESHOLD + 0, // ADDSET_DIRPYREQ_SKINPROTECT + 0, // ADDSET_COLORTONING_SPLIT + 0, //ADDSET_DIRPYRDN_PASSES + 0, // ADDSET_RAWFFCLIPCONTROL + 0, // ADDSET_FILMSIMULATION_STRENGTH + 0, //ADDSET_WA + 0, //ADDSET_WA_THRESHOLD + 0, //ADDSET_WA_THRESHOLD2 + 0, //ADDSET_WA_THRES + 0, //ADDSET_WA_CHRO + 0, //ADDSET_WA_CHROMA + 0, //ADDSET_WA_CONTRAST + 0, //ADDSET_WA_SKINPROTECT + 0, //ADDSET_WA_RESCHRO + 0, //ADDSET_WA_RESCON + 0, //ADDSET_WA_RESCONH + 0, //ADDSET_WA_THRR + 0, //ADDSET_WA_THRRH + 0, //ADDSET_WA_SKYPROTECT + 0, //ADDSET_WA_EDGRAD + 0, //ADDSET_WA_EDGVAL + 0, //ADDSET_WA_STRENGTH + 0, //ADDSET_WA_EDGEDETECT + 0, //ADDSET_WA_EDGEDETECTTHR + 0, //ADDSET_WA_EDGEDETECTTHR2 + 0, //ADDSET_WA_TMRS + 0, //ADDSET_WA_GAMMA + + }; + baBehav = std::vector (babehav, babehav + ADDSET_PARAM_NUM); + rtSettings.darkFramesPath = ""; rtSettings.flatFieldsPath = ""; #ifdef WIN32 - const gchar* sysRoot = g_getenv("SystemRoot"); // Returns e.g. "c:\Windows" - if (sysRoot!=NULL) - rtSettings.iccDirectory = Glib::ustring(sysRoot) + Glib::ustring("\\System32\\spool\\drivers\\color"); - else - rtSettings.iccDirectory = "C:\\WINDOWS\\System32\\spool\\drivers\\color"; + const gchar* sysRoot = g_getenv("SystemRoot"); // Returns e.g. "c:\Windows" + + if (sysRoot != NULL) { + rtSettings.iccDirectory = Glib::ustring(sysRoot) + Glib::ustring("\\System32\\spool\\drivers\\color"); + } else { + rtSettings.iccDirectory = "C:\\WINDOWS\\System32\\spool\\drivers\\color"; + } + #elif defined __APPLE__ rtSettings.iccDirectory = "/library/ColorSync/Profiles/Displays"; #else rtSettings.iccDirectory = "/usr/share/color/icc"; #endif rtSettings.colorimetricIntent = 1; - rtSettings.viewingdevice=0; - rtSettings.viewingdevicegrey=3; - rtSettings.viewinggreySc=1; - rtSettings.leveldnv=2; - rtSettings.leveldnti=0; - rtSettings.leveldnaut=0; - rtSettings.leveldnliss=0; - rtSettings.leveldnautsimpl=0; + rtSettings.viewingdevice = 0; + rtSettings.viewingdevicegrey = 3; + rtSettings.viewinggreySc = 1; + rtSettings.leveldnv = 2; + rtSettings.leveldnti = 0; + rtSettings.leveldnaut = 0; + rtSettings.leveldnliss = 0; + rtSettings.leveldnautsimpl = 0; rtSettings.monitorProfile = ""; rtSettings.autoMonitorProfile = false; @@ -584,402 +641,1108 @@ void Options::setDefaults () { rtSettings.artifact_cbdl = 4.; rtSettings.level0_cbdl = 0; rtSettings.level123_cbdl = 30; - rtSettings.bot_left=0; - rtSettings.top_left=10; - rtSettings.top_right=40; - rtSettings.bot_right=75; - rtSettings.ed_detec=3;//between 2 and 10 - rtSettings.ed_detecStr=1.3;//not use - rtSettings.ed_low=15.;//between 5 to 40 - rtSettings.ed_lipinfl=0.8;//between 0.5 to 0.9 - rtSettings.ed_lipampl=1.1;//between 1 and 2 - - + rtSettings.bot_left = 0; + rtSettings.top_left = 10; + rtSettings.top_right = 40; + rtSettings.bot_right = 75; + rtSettings.ed_detec = 3; //between 2 and 10 + rtSettings.ed_detecStr = 1.3; //not use + rtSettings.ed_low = 15.; //between 5 to 40 + rtSettings.ed_lipinfl = 0.8; //between 0.5 to 0.9 + rtSettings.ed_lipampl = 1.1; //between 1 and 2 + + rtSettings.ciecamfloat = true; rtSettings.protectred = 60; rtSettings.protectredh = 0.3; - rtSettings.CRI_color =0; - rtSettings.autocielab=true; - rtSettings.denoiselabgamma=2; + rtSettings.CRI_color = 0; + rtSettings.autocielab = true; + rtSettings.denoiselabgamma = 2; rtSettings.HistogramWorking = false; rtSettings.daubech = false; - + rtSettings.nrauto = 10;//between 2 and 20 rtSettings.nrautomax = 40;//between 5 and 100 rtSettings.nrhigh = 0.45;//between 0.1 and 0.9 rtSettings.nrwavlevel = 1;//integer between 0 and 2 - - // rtSettings.colortoningab =0.7; -//rtSettings.decaction =0.3; -// rtSettings.ciebadpixgauss=false; - rtSettings.rgbcurveslumamode_gamut=true; - lastIccDir = rtSettings.iccDirectory; - lastDarkframeDir = rtSettings.darkFramesPath; - lastFlatfieldDir = rtSettings.flatFieldsPath; -// rtSettings.bw_complementary = true; - // There is no reasonable default for curves. We can still suppose that they will take place - // in a subdirectory of the user's own ProcParams presets, i.e. in a subdirectory - // of the one pointed to by the "profile" field. - // The following fields will then be initialized when "profile" will have its final value, - // at the end of the "updatePaths" method. - lastRgbCurvesDir = ""; - lastLabCurvesDir = ""; - lastDenoiseCurvesDir = ""; - lastWaveletCurvesDir = ""; - lastPFCurvesDir = ""; - lastHsvCurvesDir = ""; - lastToneCurvesDir = ""; - lastVibranceCurvesDir = ""; - lastProfilingReferenceDir = ""; - lastBWCurvesDir = ""; + +// rtSettings.colortoningab =0.7; +//rtSettings.decaction =0.3; +// rtSettings.ciebadpixgauss=false; + rtSettings.rgbcurveslumamode_gamut = true; + lastIccDir = rtSettings.iccDirectory; + lastDarkframeDir = rtSettings.darkFramesPath; + lastFlatfieldDir = rtSettings.flatFieldsPath; +// rtSettings.bw_complementary = true; + // There is no reasonable default for curves. We can still suppose that they will take place + // in a subdirectory of the user's own ProcParams presets, i.e. in a subdirectory + // of the one pointed to by the "profile" field. + // The following fields will then be initialized when "profile" will have its final value, + // at the end of the "updatePaths" method. + lastRgbCurvesDir = ""; + lastLabCurvesDir = ""; + lastDenoiseCurvesDir = ""; + lastWaveletCurvesDir = ""; + lastPFCurvesDir = ""; + lastHsvCurvesDir = ""; + lastToneCurvesDir = ""; + lastVibranceCurvesDir = ""; + lastProfilingReferenceDir = ""; + lastBWCurvesDir = ""; maxRecentFolders = 15; } -Options* Options::copyFrom (Options* other) { - *this = *other; - return this; +Options* Options::copyFrom (Options* other) +{ + *this = *other; + return this; } -void Options::filterOutParsedExtensions () { - parsedExtensions.clear(); - for (unsigned int i=0; i(keyFile.get_integer ("GUI", "SortType")); - if (keyFile.has_key ("GUI", "PreferencesWidth")) preferencesWidth = keyFile.get_integer ("GUI", "PreferencesWidth"); - if (keyFile.has_key ("GUI", "PreferencesHeight")) preferencesHeight = keyFile.get_integer ("GUI", "PreferencesHeight"); - if (keyFile.has_key ("GUI", "SaveAsDialogWidth")) saveAsDialogWidth = keyFile.get_integer ("GUI", "SaveAsDialogWidth"); - if (keyFile.has_key ("GUI", "SaveAsDialogHeight")) saveAsDialogHeight = keyFile.get_integer ("GUI", "SaveAsDialogHeight"); - if (keyFile.has_key ("GUI", "ToolPanelWidth")) toolPanelWidth = keyFile.get_integer ("GUI", "ToolPanelWidth"); - if (keyFile.has_key ("GUI", "BrowserToolPanelWidth")) browserToolPanelWidth = keyFile.get_integer ("GUI", "BrowserToolPanelWidth"); - if (keyFile.has_key ("GUI", "BrowserToolPanelHeight")) browserToolPanelHeight = keyFile.get_integer ("GUI", "BrowserToolPanelHeight"); - if (keyFile.has_key ("GUI", "BrowserToolPanelOpened")) browserToolPanelOpened = keyFile.get_boolean ("GUI", "BrowserToolPanelOpened"); - if (keyFile.has_key ("GUI", "BrowserDirPanelOpened")) browserDirPanelOpened = keyFile.get_boolean ("GUI", "BrowserDirPanelOpened"); - if (keyFile.has_key ("GUI", "EditorFilmStripOpened")) editorFilmStripOpened = keyFile.get_boolean ("GUI", "EditorFilmStripOpened"); - if (keyFile.has_key ("GUI", "HistoryPanelWidth")) historyPanelWidth = keyFile.get_integer ("GUI", "HistoryPanelWidth"); - if (keyFile.has_key ("GUI", "LastPreviewScale")) lastScale = keyFile.get_integer ("GUI", "LastPreviewScale"); - if (keyFile.has_key ("GUI", "PanAccelFactor")) panAccelFactor = keyFile.get_integer ("GUI", "PanAccelFactor"); - if (keyFile.has_key ("GUI", "RememberZoomAndPan")) rememberZoomAndPan = keyFile.get_boolean ("GUI", "RememberZoomAndPan"); - if (keyFile.has_key ("GUI", "LastCropSize")) lastCropSize = keyFile.get_integer ("GUI", "LastCropSize"); - if (keyFile.has_key ("GUI", "ShowHistory")) showHistory = keyFile.get_boolean ("GUI", "ShowHistory"); - if (keyFile.has_key ("GUI", "ShowFilePanelState")) showFilePanelState= keyFile.get_integer ("GUI", "ShowFilePanelState"); - if (keyFile.has_key ("GUI", "ShowInfo")) showInfo = keyFile.get_boolean ("GUI", "ShowInfo"); - if (keyFile.has_key ("GUI", "MainNBVertical")) mainNBVertical = keyFile.get_boolean ("GUI", "MainNBVertical"); - if (keyFile.has_key ("GUI", "ShowClippedHighlights"))showClippedHighlights = keyFile.get_boolean ("GUI", "ShowClippedHighlights"); - if (keyFile.has_key ("GUI", "ShowClippedShadows")) showClippedShadows= keyFile.get_boolean ("GUI", "ShowClippedShadows"); - if (keyFile.has_key ("GUI", "FrameColor")) bgcolor = keyFile.get_integer ("GUI", "FrameColor"); - if (keyFile.has_key ("GUI", "ProcessingQueueEnbled"))procQueueEnabled = keyFile.get_boolean ("GUI", "ProcessingQueueEnbled"); - if (keyFile.has_key ("GUI", "ToolPanelsExpanded")) tpOpen = keyFile.get_integer_list ("GUI", "ToolPanelsExpanded"); - if (keyFile.has_key ("GUI", "MultiDisplayMode")) multiDisplayMode = keyFile.get_integer ("GUI", "MultiDisplayMode"); - //if (keyFile.has_key ("GUI", "CurvePanelsExpanded")) crvOpen = keyFile.get_integer_list ("GUI", "CurvePanelsExpanded"); - if (keyFile.has_key ("GUI", "CutOverlayBrush")) cutOverlayBrush = keyFile.get_double_list ("GUI", "CutOverlayBrush"); - if (keyFile.has_key ("GUI", "NavGuideBrush")) navGuideBrush = keyFile.get_double_list ("GUI", "NavGuideBrush"); - if (keyFile.has_key ("GUI", "HistogramPosition")) histogramPosition = keyFile.get_integer ("GUI", "HistogramPosition"); - if (keyFile.has_key ("GUI", "HistogramBar")) histogramBar = keyFile.get_boolean ("GUI", "HistogramBar"); - if (keyFile.has_key ("GUI", "HistogramFullMode")) histogramFullMode = keyFile.get_boolean ("GUI", "HistogramFullMode"); - if (keyFile.has_key ("GUI", "ShowFilmStripToolBar")) showFilmStripToolBar = keyFile.get_boolean ("GUI", "ShowFilmStripToolBar"); - if (keyFile.has_key ("GUI", "FileBrowserToolbarSingleRow")) FileBrowserToolbarSingleRow = keyFile.get_boolean ("GUI", "FileBrowserToolbarSingleRow"); - if (keyFile.has_key ("GUI", "HideTPVScrollbar")) hideTPVScrollbar = keyFile.get_boolean ("GUI", "HideTPVScrollbar"); - if (keyFile.has_key ("GUI", "UseIconNoText")) UseIconNoText = keyFile.get_boolean ("GUI", "UseIconNoText"); - if (keyFile.has_key ("GUI", "HistogramWorking")) rtSettings.HistogramWorking = keyFile.get_boolean ("GUI", "HistogramWorking"); - if (keyFile.has_key ("GUI", "CurveBBoxPosition")) curvebboxpos = keyFile.get_integer ("GUI", "CurveBBoxPosition"); -} + if (keyFile.has_key ("Output", "JpegQuality")) { + saveFormat.jpegQuality = keyFile.get_integer ("Output", "JpegQuality"); + } -if (keyFile.has_group ("Crop Settings")) { - if (keyFile.has_key ("Crop Settings", "PPI")) cropPPI = keyFile.get_integer ("Crop Settings", "PPI"); -} + if (keyFile.has_key ("Output", "JpegSubSamp")) { + saveFormat.jpegSubSamp = keyFile.get_integer ("Output", "JpegSubSamp"); + } -if (keyFile.has_group ("Color Management")) { - if (keyFile.has_key ("Color Management", "ICCDirectory")) rtSettings.iccDirectory = keyFile.get_string ("Color Management", "ICCDirectory"); - if (keyFile.has_key ("Color Management", "MonitorProfile")) rtSettings.monitorProfile = keyFile.get_string ("Color Management", "MonitorProfile"); - if (keyFile.has_key ("Color Management", "AutoMonitorProfile")) rtSettings.autoMonitorProfile = keyFile.get_boolean ("Color Management", "AutoMonitorProfile"); - if (keyFile.has_key ("Color Management", "Autocielab")) rtSettings.autocielab = keyFile.get_boolean ("Color Management", "Autocielab"); - if (keyFile.has_key ("Color Management", "RGBcurvesLumamode_Gamut")) rtSettings.rgbcurveslumamode_gamut = keyFile.get_boolean ("Color Management", "RGBcurvesLumamode_Gamut"); + if (keyFile.has_key ("Output", "PngCompression")) { + saveFormat.pngCompression = keyFile.get_integer ("Output", "PngCompression"); + } - if (keyFile.has_key ("Color Management", "Intent")) rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent"); - if (keyFile.has_key ("Color Management", "CRI")) rtSettings.CRI_color = keyFile.get_integer("Color Management", "CRI"); - if (keyFile.has_key ("Color Management", "DenoiseLabgamma"))rtSettings.denoiselabgamma = keyFile.get_integer("Color Management", "DenoiseLabgamma"); - if (keyFile.has_key ("Color Management", "view")) rtSettings.viewingdevice = keyFile.get_integer("Color Management", "view"); - if (keyFile.has_key ("Color Management", "grey")) rtSettings.viewingdevicegrey = keyFile.get_integer("Color Management", "grey"); - if (keyFile.has_key ("Color Management", "greySc")) rtSettings.viewinggreySc = keyFile.get_integer("Color Management", "greySc"); - if (keyFile.has_key ("Color Management", "CBDLArtif")) rtSettings.artifact_cbdl = keyFile.get_double("Color Management", "CBDLArtif"); - if (keyFile.has_key ("Color Management", "CBDLlevel0")) rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0"); - if (keyFile.has_key ("Color Management", "CBDLlevel123")) rtSettings.level123_cbdl = keyFile.get_double("Color Management", "CBDLlevel123"); - // if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab"); - // if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction"); + if (keyFile.has_key ("Output", "PngBps")) { + saveFormat.pngBits = keyFile.get_integer ("Output", "PngBps"); + } - if (keyFile.has_key ("Color Management", "WhiteBalanceSpotSize")) whiteBalanceSpotSize = keyFile.get_integer("Color Management", "WhiteBalanceSpotSize"); - if( keyFile.has_key ("Color Management", "GamutICC")) rtSettings.gamutICC = keyFile.get_boolean("Color Management", "GamutICC"); - // if( keyFile.has_key ("Color Management", "BWcomplement")) rtSettings.bw_complementary = keyFile.get_boolean("Color Management", "BWcomplement"); - if( keyFile.has_key ("Color Management", "Ciecamfloat")) rtSettings.ciecamfloat = keyFile.get_boolean("Color Management", "Ciecamfloat"); - if( keyFile.has_key ("Color Management", "AdobeRGB")) rtSettings.adobe = keyFile.get_string("Color Management", "AdobeRGB"); - if( keyFile.has_key ("Color Management", "ProPhoto")) rtSettings.prophoto = keyFile.get_string("Color Management", "ProPhoto"); - if( keyFile.has_key ("Color Management", "ProPhoto10")) rtSettings.prophoto10 = keyFile.get_string("Color Management", "ProPhoto10"); - if( keyFile.has_key ("Color Management", "WideGamut")) rtSettings.widegamut = keyFile.get_string("Color Management", "WideGamut"); - if( keyFile.has_key ("Color Management", "sRGB")) rtSettings.srgb = keyFile.get_string("Color Management", "sRGB"); - if( keyFile.has_key ("Color Management", "sRGB10")) rtSettings.srgb10 = keyFile.get_string("Color Management", "sRGB10"); - if( keyFile.has_key ("Color Management", "Beta")) rtSettings.beta = keyFile.get_string("Color Management", "Beta"); - if( keyFile.has_key ("Color Management", "Best")) rtSettings.best = keyFile.get_string("Color Management", "Best"); - if( keyFile.has_key ("Color Management", "Bruce")) rtSettings.bruce = keyFile.get_string("Color Management", "Bruce"); - if( keyFile.has_key ("Color Management", "GamutLch")) rtSettings.gamutLch = keyFile.get_boolean("Color Management", "GamutLch"); - if( keyFile.has_key ("Color Management", "ProtectRed")) rtSettings.protectred = keyFile.get_integer("Color Management", "ProtectRed"); - if( keyFile.has_key ("Color Management", "ProtectRedH")) rtSettings.protectredh = keyFile.get_double("Color Management", "ProtectRedH"); - if( keyFile.has_key ("Color Management", "Amountchroma")) rtSettings.amchroma = keyFile.get_integer("Color Management", "Amountchroma"); + if (keyFile.has_key ("Output", "TiffBps")) { + saveFormat.tiffBits = keyFile.get_integer ("Output", "TiffBps"); + } + + if (keyFile.has_key ("Output", "TiffUncompressed")) { + saveFormat.tiffUncompressed = keyFile.get_boolean ("Output", "TiffUncompressed"); + } + + if (keyFile.has_key ("Output", "SaveProcParams")) { + saveFormat.saveParams = keyFile.get_boolean ("Output", "SaveProcParams"); + } + + + if (keyFile.has_key ("Output", "FormatBatch")) { + saveFormatBatch.format = keyFile.get_string ("Output", "FormatBatch"); + } + + if (keyFile.has_key ("Output", "JpegQualityBatch")) { + saveFormatBatch.jpegQuality = keyFile.get_integer ("Output", "JpegQualityBatch"); + } + + if (keyFile.has_key ("Output", "JpegSubSampBatch")) { + saveFormatBatch.jpegSubSamp = keyFile.get_integer ("Output", "JpegSubSampBatch"); + } + + if (keyFile.has_key ("Output", "PngCompressionBatch")) { + saveFormatBatch.pngCompression = keyFile.get_integer ("Output", "PngCompressionBatch"); + } + + if (keyFile.has_key ("Output", "PngBpsBatch")) { + saveFormatBatch.pngBits = keyFile.get_integer ("Output", "PngBpsBatch"); + } + + if (keyFile.has_key ("Output", "TiffBpsBatch")) { + saveFormatBatch.tiffBits = keyFile.get_integer ("Output", "TiffBpsBatch"); + } + + if (keyFile.has_key ("Output", "TiffUncompressedBatch")) { + saveFormatBatch.tiffUncompressed = keyFile.get_boolean ("Output", "TiffUncompressedBatch"); + } + + if (keyFile.has_key ("Output", "SaveProcParamsBatch")) { + saveFormatBatch.saveParams = keyFile.get_boolean ("Output", "SaveProcParamsBatch"); + } + + if (keyFile.has_key ("Output", "Path")) { + savePathTemplate = keyFile.get_string ("Output", "Path"); + } + + if (keyFile.has_key ("Output", "PathTemplate")) { + savePathTemplate = keyFile.get_string ("Output", "PathTemplate"); + } + + if (keyFile.has_key ("Output", "PathFolder")) { + savePathFolder = keyFile.get_string ("Output", "PathFolder"); + } + + if (keyFile.has_key ("Output", "AutoSuffix")) { + autoSuffix = keyFile.get_boolean("Output", "AutoSuffix"); + } + + if (keyFile.has_key ("Output", "ForceFormatOpts")) { + forceFormatOpts = keyFile.get_boolean("Output", "ForceFormatOpts"); + } + + if (keyFile.has_key ("Output", "SaveMethodNum")) { + saveMethodNum = keyFile.get_integer("Output", "SaveMethodNum"); + } + + if (keyFile.has_key ("Output", "UsePathTemplate")) { + saveUsePathTemplate = keyFile.get_boolean("Output", "UsePathTemplate"); + } + + if (keyFile.has_key ("Output", "LastSaveAsPath")) { + lastSaveAsPath = keyFile.get_string ("Output", "LastSaveAsPath"); + } + + if (keyFile.has_key ("Output", "OverwriteOutputFile")) { + overwriteOutputFile = keyFile.get_boolean("Output", "OverwriteOutputFile"); + } + + if (keyFile.has_key ("Output", "TunnelMetaData")) { + tunnelMetaData = keyFile.get_boolean("Output", "TunnelMetaData"); + } + } + + if (keyFile.has_group ("Profiles")) { + if (keyFile.has_key ("Profiles", "Directory")) { + profilePath = keyFile.get_string ("Profiles", "Directory"); + } + + if (keyFile.has_key ("Profiles", "UseBundledProfiles")) { + useBundledProfiles = keyFile.get_boolean ("Profiles", "UseBundledProfiles"); + } + + if (keyFile.has_key ("Profiles", "LoadSaveProfilePath")) { + loadSaveProfilePath = keyFile.get_string ("Profiles", "LoadSaveProfilePath"); + } + + if (keyFile.has_key ("Profiles", "RawDefault")) { + defProfRaw = keyFile.get_string ("Profiles", "RawDefault"); + } + + if (keyFile.has_key ("Profiles", "ImgDefault")) { + defProfImg = keyFile.get_string ("Profiles", "ImgDefault"); + } + + if (keyFile.has_key ("Profiles", "FilledProfile")) { + filledProfile = keyFile.get_boolean ("Profiles", "FilledProfile"); + } + + if (keyFile.has_key ("Profiles", "SaveParamsWithFile")) { + saveParamsFile = keyFile.get_boolean ("Profiles", "SaveParamsWithFile"); + } + + if (keyFile.has_key ("Profiles", "SaveParamsToCache")) { + saveParamsCache = keyFile.get_boolean ("Profiles", "SaveParamsToCache"); + } + + if (keyFile.has_key ("Profiles", "LoadParamsFromLocation")) { + paramsLoadLocation = (PPLoadLocation)keyFile.get_integer ("Profiles", "LoadParamsFromLocation"); + } + + if (keyFile.has_key ("Profiles", "CustomProfileBuilder")) { + CPBPath = keyFile.get_string ("Profiles", "CustomProfileBuilder"); // for backward compatibility only + } + + if (keyFile.has_key ("Profiles", "CustomProfileBuilderPath")) { + CPBPath = keyFile.get_string ("Profiles", "CustomProfileBuilderPath"); + } + + if (keyFile.has_key ("Profiles", "CustomProfileBuilderKeys")) { + CPBKeys = (CPBKeyType)keyFile.get_integer ("Profiles", "CustomProfileBuilderKeys"); + } + } + + if (keyFile.has_group ("File Browser")) { + if (keyFile.has_key ("File Browser", "ThumbnailSize")) { + thumbSize = keyFile.get_integer ("File Browser", "ThumbnailSize"); + } + + if (keyFile.has_key ("File Browser", "ThumbnailSizeTab")) { + thumbSizeTab = keyFile.get_integer ("File Browser", "ThumbnailSizeTab"); + } + + if (keyFile.has_key ("File Browser", "ThumbnailSizeQueue")) { + thumbSizeQueue = keyFile.get_integer ("File Browser", "ThumbnailSizeQueue"); + } + + if (keyFile.has_key ("File Browser", "SameThumbSize")) { + sameThumbSize = keyFile.get_integer ("File Browser", "SameThumbSize"); + } + + if (keyFile.has_key ("File Browser", "BrowseOnlyRaw")) { + fbOnlyRaw = keyFile.get_boolean ("File Browser", "BrowseOnlyRaw"); + } + + if (keyFile.has_key ("File Browser", "BrowserShowsDate")) { + fbShowDateTime = keyFile.get_boolean ("File Browser", "BrowserShowsDate"); + } + + if (keyFile.has_key ("File Browser", "BrowserShowsExif")) { + fbShowBasicExif = keyFile.get_boolean ("File Browser", "BrowserShowsExif"); + } + + if (keyFile.has_key ("File Browser", "BrowserShowsExpComp")) { + fbShowExpComp = keyFile.get_boolean ("File Browser", "BrowserShowsExpComp"); + } + + if (keyFile.has_key ("File Browser", "BrowserShowsHidden")) { + fbShowHidden = keyFile.get_boolean ("File Browser", "BrowserShowsHidden"); + } + + if (keyFile.has_key ("File Browser", "MaxPreviewHeight")) { + maxThumbnailHeight = keyFile.get_integer ("File Browser", "MaxPreviewHeight"); + } + + if (keyFile.has_key ("File Browser", "MaxCacheEntries")) { + maxCacheEntries = keyFile.get_integer ("File Browser", "MaxCacheEntries"); + } + + if (keyFile.has_key ("File Browser", "ParseExtensions")) { + parseExtensions = keyFile.get_string_list ("File Browser", "ParseExtensions"); + } + + if (keyFile.has_key ("File Browser", "ParseExtensionsEnabled")) { + parseExtensionsEnabled = keyFile.get_integer_list ("File Browser", "ParseExtensionsEnabled"); + } + + if (keyFile.has_key ("File Browser", "ThumbnailArrangement")) { + fbArrangement = keyFile.get_integer ("File Browser", "ThumbnailArrangement"); + } + + if (keyFile.has_key ("File Browser", "ThumbnailInterpolation")) { + thumbInterp = keyFile.get_integer ("File Browser", "ThumbnailInterpolation"); + } + + if (keyFile.has_key ("File Browser", "LiveThumbnails")) { + liveThumbnails = keyFile.get_boolean ("File Browser", "LiveThumbnails"); + } + + if (keyFile.has_key ("File Browser", "FavoriteDirs")) { + favoriteDirs = keyFile.get_string_list ("File Browser", "FavoriteDirs"); + } + + if (keyFile.has_key ("File Browser", "RenameTemplates")) { + renameTemplates = keyFile.get_string_list ("File Browser", "RenameTemplates"); + } + + if (keyFile.has_key ("File Browser", "RenameUseTemplates")) { + renameUseTemplates = keyFile.get_boolean ("File Browser", "RenameUseTemplates"); + } + + if (keyFile.has_key ("File Browser", "ThumbnailZoomRatios")) { + thumbnailZoomRatios = keyFile.get_double_list ("File Browser", "ThumbnailZoomRatios"); + } + + if (keyFile.has_key ("File Browser", "OverlayedFileNames")) { + overlayedFileNames = keyFile.get_boolean ("File Browser", "OverlayedFileNames"); + } + + if (keyFile.has_key ("File Browser", "FilmStripOverlayedFileNames")) { + filmStripOverlayedFileNames = keyFile.get_boolean ("File Browser", "FilmStripOverlayedFileNames"); + } + + if (keyFile.has_key ("File Browser", "ShowFileNames")) { + showFileNames = keyFile.get_boolean ("File Browser", "ShowFileNames"); + } + + if (keyFile.has_key ("File Browser", "FilmStripShowFileNames")) { + filmStripShowFileNames = keyFile.get_boolean ("File Browser", "FilmStripShowFileNames"); + } + + if (keyFile.has_key ("File Browser", "InternalThumbIfUntouched")) { + internalThumbIfUntouched = keyFile.get_boolean ("File Browser", "InternalThumbIfUntouched"); + } + + if (keyFile.has_key ("File Browser", "menuGroupRank")) { + menuGroupRank = keyFile.get_boolean ("File Browser", "menuGroupRank"); + } + + if (keyFile.has_key ("File Browser", "menuGroupLabel")) { + menuGroupLabel = keyFile.get_boolean ("File Browser", "menuGroupLabel"); + } + + if (keyFile.has_key ("File Browser", "menuGroupFileOperations")) { + menuGroupFileOperations = keyFile.get_boolean ("File Browser", "menuGroupFileOperations"); + } + + if (keyFile.has_key ("File Browser", "menuGroupProfileOperations")) { + menuGroupProfileOperations = keyFile.get_boolean ("File Browser", "menuGroupProfileOperations"); + } + + if (keyFile.has_key ("File Browser", "menuGroupExtProg")) { + menuGroupExtProg = keyFile.get_boolean ("File Browser", "menuGroupExtProg"); + } + + if (keyFile.has_key ("File Browser", "MaxRecentFolders")) { + maxRecentFolders = keyFile.get_integer ("File Browser", "MaxRecentFolders"); + } + + recentFolders.reserve(maxRecentFolders + 10); // reserve some more than maxRecentFolders, because at runtime it stores more than that + + if (keyFile.has_key ("File Browser", "RecentFolders")) { + recentFolders = keyFile.get_string_list ("File Browser", "RecentFolders"); + } + } + + if (keyFile.has_group ("Clipping Indication")) { + if (keyFile.has_key ("Clipping Indication", "HighlightThreshold")) { + highlightThreshold = keyFile.get_integer ("Clipping Indication", "HighlightThreshold"); + } + + if (keyFile.has_key ("Clipping Indication", "ShadowThreshold")) { + shadowThreshold = keyFile.get_integer ("Clipping Indication", "ShadowThreshold"); + } + + if (keyFile.has_key ("Clipping Indication", "BlinkClipped")) { + blinkClipped = keyFile.get_boolean ("Clipping Indication", "BlinkClipped"); + } + } + + if (keyFile.has_group ("Performance")) { + if (keyFile.has_key ("Performance", "RgbDenoiseThreadLimit")) { + rgbDenoiseThreadLimit = keyFile.get_integer ("Performance", "RgbDenoiseThreadLimit"); + } + + if( keyFile.has_key ("Performance", "NRauto")) { + rtSettings.nrauto = keyFile.get_double ("Performance", "NRauto"); + } + + if( keyFile.has_key ("Performance", "NRautomax")) { + rtSettings.nrautomax = keyFile.get_double ("Performance", "NRautomax"); + } + + if( keyFile.has_key ("Performance", "NRhigh")) { + rtSettings.nrhigh = keyFile.get_double ("Performance", "NRhigh"); + } + + if(rtSettings.nrhigh == 0.0) { //avoid crash by division by zero in noise reduction + rtSettings.nrhigh = 0.45; + } + + if( keyFile.has_key ("Performance", "NRWavlevel")) { + rtSettings.nrwavlevel = keyFile.get_integer ("Performance", "NRWavlevel"); + } + + if (keyFile.has_key ("Performance", "LevNR")) { + rtSettings.leveldnv = keyFile.get_integer ("Performance", "LevNR"); + } + + if (keyFile.has_key ("Performance", "LevNRTI")) { + rtSettings.leveldnti = keyFile.get_integer ("Performance", "LevNRTI"); + } + + if (keyFile.has_key ("Performance", "LevNRAUT")) { + rtSettings.leveldnaut = keyFile.get_integer ("Performance", "LevNRAUT"); + } + + if (keyFile.has_key ("Performance", "LevNRLISS")) { + rtSettings.leveldnliss = keyFile.get_integer ("Performance", "LevNRLISS"); + } + + if (keyFile.has_key ("Performance", "SIMPLNRAUT")) { + rtSettings.leveldnautsimpl = keyFile.get_integer ("Performance", "SIMPLNRAUT"); + } + + if (keyFile.has_key ("Performance", "ClutCacheSize")) { + clutCacheSize = keyFile.get_integer ("Performance", "ClutCacheSize"); + } + + if (keyFile.has_key ("Performance", "MaxInspectorBuffers")) { + maxInspectorBuffers = keyFile.get_integer ("Performance", "MaxInspectorBuffers"); + } + + if (keyFile.has_key ("Performance", "PreviewDemosaicFromSidecar")) { + prevdemo = (prevdemo_t)keyFile.get_integer ("Performance", "PreviewDemosaicFromSidecar"); + } + + if (keyFile.has_key ("Performance", "Daubechies")) { + rtSettings.daubech = keyFile.get_boolean ("Performance", "Daubechies"); + } + + if (keyFile.has_key ("Performance", "SerializeTiffRead")) { + serializeTiffRead = keyFile.get_boolean ("Performance", "SerializeTiffRead"); + } + } + + if (keyFile.has_group ("GUI")) { + if (keyFile.has_key ("GUI", "Font")) { + font = keyFile.get_string ("GUI", "Font"); + } + + if (keyFile.has_key ("GUI", "WindowWidth")) { + windowWidth = keyFile.get_integer ("GUI", "WindowWidth"); + } + + if (keyFile.has_key ("GUI", "WindowHeight")) { + windowHeight = keyFile.get_integer ("GUI", "WindowHeight"); + } + + if (keyFile.has_key ("GUI", "WindowX")) { + windowX = keyFile.get_integer ("GUI", "WindowX"); + } + + if (keyFile.has_key ("GUI", "WindowY")) { + windowY = keyFile.get_integer ("GUI", "WindowY"); + } + + if (keyFile.has_key ("GUI", "WindowMaximized")) { + windowMaximized = keyFile.get_boolean ("GUI", "WindowMaximized"); + } + + if (keyFile.has_key ("GUI", "DetailWindowWidth")) { + detailWindowWidth = keyFile.get_integer ("GUI", "DetailWindowWidth"); + } + + if (keyFile.has_key ("GUI", "DetailWindowHeight")) { + detailWindowHeight = keyFile.get_integer ("GUI", "DetailWindowHeight"); + } + + if (keyFile.has_key ("GUI", "DirBrowserWidth")) { + dirBrowserWidth = keyFile.get_integer ("GUI", "DirBrowserWidth"); + } + + if (keyFile.has_key ("GUI", "DirBrowserHeight")) { + dirBrowserHeight = keyFile.get_integer ("GUI", "DirBrowserHeight"); + } + + if (keyFile.has_key ("GUI", "SortType")) { + dirBrowserSortType = static_cast(keyFile.get_integer ("GUI", "SortType")); + } + + if (keyFile.has_key ("GUI", "PreferencesWidth")) { + preferencesWidth = keyFile.get_integer ("GUI", "PreferencesWidth"); + } + + if (keyFile.has_key ("GUI", "PreferencesHeight")) { + preferencesHeight = keyFile.get_integer ("GUI", "PreferencesHeight"); + } + + if (keyFile.has_key ("GUI", "SaveAsDialogWidth")) { + saveAsDialogWidth = keyFile.get_integer ("GUI", "SaveAsDialogWidth"); + } + + if (keyFile.has_key ("GUI", "SaveAsDialogHeight")) { + saveAsDialogHeight = keyFile.get_integer ("GUI", "SaveAsDialogHeight"); + } + + if (keyFile.has_key ("GUI", "ToolPanelWidth")) { + toolPanelWidth = keyFile.get_integer ("GUI", "ToolPanelWidth"); + } + + if (keyFile.has_key ("GUI", "BrowserToolPanelWidth")) { + browserToolPanelWidth = keyFile.get_integer ("GUI", "BrowserToolPanelWidth"); + } + + if (keyFile.has_key ("GUI", "BrowserToolPanelHeight")) { + browserToolPanelHeight = keyFile.get_integer ("GUI", "BrowserToolPanelHeight"); + } + + if (keyFile.has_key ("GUI", "BrowserToolPanelOpened")) { + browserToolPanelOpened = keyFile.get_boolean ("GUI", "BrowserToolPanelOpened"); + } + + if (keyFile.has_key ("GUI", "BrowserDirPanelOpened")) { + browserDirPanelOpened = keyFile.get_boolean ("GUI", "BrowserDirPanelOpened"); + } + + if (keyFile.has_key ("GUI", "EditorFilmStripOpened")) { + editorFilmStripOpened = keyFile.get_boolean ("GUI", "EditorFilmStripOpened"); + } + + if (keyFile.has_key ("GUI", "HistoryPanelWidth")) { + historyPanelWidth = keyFile.get_integer ("GUI", "HistoryPanelWidth"); + } + + if (keyFile.has_key ("GUI", "LastPreviewScale")) { + lastScale = keyFile.get_integer ("GUI", "LastPreviewScale"); + } + + if (keyFile.has_key ("GUI", "PanAccelFactor")) { + panAccelFactor = keyFile.get_integer ("GUI", "PanAccelFactor"); + } + + if (keyFile.has_key ("GUI", "RememberZoomAndPan")) { + rememberZoomAndPan = keyFile.get_boolean ("GUI", "RememberZoomAndPan"); + } + + if (keyFile.has_key ("GUI", "LastCropSize")) { + lastCropSize = keyFile.get_integer ("GUI", "LastCropSize"); + } + + if (keyFile.has_key ("GUI", "ShowHistory")) { + showHistory = keyFile.get_boolean ("GUI", "ShowHistory"); + } + + if (keyFile.has_key ("GUI", "ShowFilePanelState")) { + showFilePanelState = keyFile.get_integer ("GUI", "ShowFilePanelState"); + } + + if (keyFile.has_key ("GUI", "ShowInfo")) { + showInfo = keyFile.get_boolean ("GUI", "ShowInfo"); + } + + if (keyFile.has_key ("GUI", "MainNBVertical")) { + mainNBVertical = keyFile.get_boolean ("GUI", "MainNBVertical"); + } + + if (keyFile.has_key ("GUI", "ShowClippedHighlights")) { + showClippedHighlights = keyFile.get_boolean ("GUI", "ShowClippedHighlights"); + } + + if (keyFile.has_key ("GUI", "ShowClippedShadows")) { + showClippedShadows = keyFile.get_boolean ("GUI", "ShowClippedShadows"); + } + + if (keyFile.has_key ("GUI", "FrameColor")) { + bgcolor = keyFile.get_integer ("GUI", "FrameColor"); + } + + if (keyFile.has_key ("GUI", "ProcessingQueueEnbled")) { + procQueueEnabled = keyFile.get_boolean ("GUI", "ProcessingQueueEnbled"); + } + + if (keyFile.has_key ("GUI", "ToolPanelsExpanded")) { + tpOpen = keyFile.get_integer_list ("GUI", "ToolPanelsExpanded"); + } + + if (keyFile.has_key ("GUI", "MultiDisplayMode")) { + multiDisplayMode = keyFile.get_integer ("GUI", "MultiDisplayMode"); + } + + //if (keyFile.has_key ("GUI", "CurvePanelsExpanded")) crvOpen = keyFile.get_integer_list ("GUI", "CurvePanelsExpanded"); + if (keyFile.has_key ("GUI", "CutOverlayBrush")) { + cutOverlayBrush = keyFile.get_double_list ("GUI", "CutOverlayBrush"); + } + + if (keyFile.has_key ("GUI", "NavGuideBrush")) { + navGuideBrush = keyFile.get_double_list ("GUI", "NavGuideBrush"); + } + + if (keyFile.has_key ("GUI", "HistogramPosition")) { + histogramPosition = keyFile.get_integer ("GUI", "HistogramPosition"); + } + + if (keyFile.has_key ("GUI", "HistogramBar")) { + histogramBar = keyFile.get_boolean ("GUI", "HistogramBar"); + } + + if (keyFile.has_key ("GUI", "HistogramFullMode")) { + histogramFullMode = keyFile.get_boolean ("GUI", "HistogramFullMode"); + } + + if (keyFile.has_key ("GUI", "ShowFilmStripToolBar")) { + showFilmStripToolBar = keyFile.get_boolean ("GUI", "ShowFilmStripToolBar"); + } + + if (keyFile.has_key ("GUI", "FileBrowserToolbarSingleRow")) { + FileBrowserToolbarSingleRow = keyFile.get_boolean ("GUI", "FileBrowserToolbarSingleRow"); + } + + if (keyFile.has_key ("GUI", "HideTPVScrollbar")) { + hideTPVScrollbar = keyFile.get_boolean ("GUI", "HideTPVScrollbar"); + } + + if (keyFile.has_key ("GUI", "UseIconNoText")) { + UseIconNoText = keyFile.get_boolean ("GUI", "UseIconNoText"); + } + + if (keyFile.has_key ("GUI", "HistogramWorking")) { + rtSettings.HistogramWorking = keyFile.get_boolean ("GUI", "HistogramWorking"); + } + + if (keyFile.has_key ("GUI", "CurveBBoxPosition")) { + curvebboxpos = keyFile.get_integer ("GUI", "CurveBBoxPosition"); + } + } + + if (keyFile.has_group ("Crop Settings")) { + if (keyFile.has_key ("Crop Settings", "PPI")) { + cropPPI = keyFile.get_integer ("Crop Settings", "PPI"); + } + } + + if (keyFile.has_group ("Color Management")) { + if (keyFile.has_key ("Color Management", "ICCDirectory")) { + rtSettings.iccDirectory = keyFile.get_string ("Color Management", "ICCDirectory"); + } + + if (keyFile.has_key ("Color Management", "MonitorProfile")) { + rtSettings.monitorProfile = keyFile.get_string ("Color Management", "MonitorProfile"); + } + + if (keyFile.has_key ("Color Management", "AutoMonitorProfile")) { + rtSettings.autoMonitorProfile = keyFile.get_boolean ("Color Management", "AutoMonitorProfile"); + } + + if (keyFile.has_key ("Color Management", "Autocielab")) { + rtSettings.autocielab = keyFile.get_boolean ("Color Management", "Autocielab"); + } + + if (keyFile.has_key ("Color Management", "RGBcurvesLumamode_Gamut")) { + rtSettings.rgbcurveslumamode_gamut = keyFile.get_boolean ("Color Management", "RGBcurvesLumamode_Gamut"); + } + + if (keyFile.has_key ("Color Management", "Intent")) { + rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent"); + } + + if (keyFile.has_key ("Color Management", "CRI")) { + rtSettings.CRI_color = keyFile.get_integer("Color Management", "CRI"); + } + + if (keyFile.has_key ("Color Management", "DenoiseLabgamma")) { + rtSettings.denoiselabgamma = keyFile.get_integer("Color Management", "DenoiseLabgamma"); + } + + if (keyFile.has_key ("Color Management", "view")) { + rtSettings.viewingdevice = keyFile.get_integer("Color Management", "view"); + } + + if (keyFile.has_key ("Color Management", "grey")) { + rtSettings.viewingdevicegrey = keyFile.get_integer("Color Management", "grey"); + } + + if (keyFile.has_key ("Color Management", "greySc")) { + rtSettings.viewinggreySc = keyFile.get_integer("Color Management", "greySc"); + } + + if (keyFile.has_key ("Color Management", "CBDLArtif")) { + rtSettings.artifact_cbdl = keyFile.get_double("Color Management", "CBDLArtif"); + } + + if (keyFile.has_key ("Color Management", "CBDLlevel0")) { + rtSettings.level0_cbdl = keyFile.get_double("Color Management", "CBDLlevel0"); + } + + if (keyFile.has_key ("Color Management", "CBDLlevel123")) { + rtSettings.level123_cbdl = keyFile.get_double("Color Management", "CBDLlevel123"); + } + +// if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab"); +// if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction"); + + if (keyFile.has_key ("Color Management", "WhiteBalanceSpotSize")) { + whiteBalanceSpotSize = keyFile.get_integer("Color Management", "WhiteBalanceSpotSize"); + } + + if( keyFile.has_key ("Color Management", "GamutICC")) { + rtSettings.gamutICC = keyFile.get_boolean("Color Management", "GamutICC"); + } + +// if( keyFile.has_key ("Color Management", "BWcomplement")) rtSettings.bw_complementary = keyFile.get_boolean("Color Management", "BWcomplement"); + if( keyFile.has_key ("Color Management", "Ciecamfloat")) { + rtSettings.ciecamfloat = keyFile.get_boolean("Color Management", "Ciecamfloat"); + } + + if( keyFile.has_key ("Color Management", "AdobeRGB")) { + rtSettings.adobe = keyFile.get_string("Color Management", "AdobeRGB"); + } + + if( keyFile.has_key ("Color Management", "ProPhoto")) { + rtSettings.prophoto = keyFile.get_string("Color Management", "ProPhoto"); + } + + if( keyFile.has_key ("Color Management", "ProPhoto10")) { + rtSettings.prophoto10 = keyFile.get_string("Color Management", "ProPhoto10"); + } + + if( keyFile.has_key ("Color Management", "WideGamut")) { + rtSettings.widegamut = keyFile.get_string("Color Management", "WideGamut"); + } + + if( keyFile.has_key ("Color Management", "sRGB")) { + rtSettings.srgb = keyFile.get_string("Color Management", "sRGB"); + } + + if( keyFile.has_key ("Color Management", "sRGB10")) { + rtSettings.srgb10 = keyFile.get_string("Color Management", "sRGB10"); + } + + if( keyFile.has_key ("Color Management", "Beta")) { + rtSettings.beta = keyFile.get_string("Color Management", "Beta"); + } + + if( keyFile.has_key ("Color Management", "Best")) { + rtSettings.best = keyFile.get_string("Color Management", "Best"); + } + + if( keyFile.has_key ("Color Management", "Bruce")) { + rtSettings.bruce = keyFile.get_string("Color Management", "Bruce"); + } + + if( keyFile.has_key ("Color Management", "GamutLch")) { + rtSettings.gamutLch = keyFile.get_boolean("Color Management", "GamutLch"); + } + + if( keyFile.has_key ("Color Management", "ProtectRed")) { + rtSettings.protectred = keyFile.get_integer("Color Management", "ProtectRed"); + } + + if( keyFile.has_key ("Color Management", "ProtectRedH")) { + rtSettings.protectredh = keyFile.get_double("Color Management", "ProtectRedH"); + } + + if( keyFile.has_key ("Color Management", "Amountchroma")) { + rtSettings.amchroma = keyFile.get_integer("Color Management", "Amountchroma"); + } + + if( keyFile.has_key ("Color Management", "ClutsDirectory")) { + clutsDir = keyFile.get_string("Color Management", "ClutsDirectory"); + } - if( keyFile.has_key ("Color Management", "ClutsDirectory")) clutsDir = keyFile.get_string("Color Management", "ClutsDirectory"); // if( keyFile.has_key ("Color Management", "Ciebadpixgauss")) rtSettings.ciebadpixgauss = keyFile.get_boolean("Color Management", "Ciebadpixgauss"); -} + } -if (keyFile.has_group ("Batch Processing")) { - if (keyFile.has_key ("Batch Processing", "AdjusterBehavior")) baBehav = keyFile.get_integer_list ("Batch Processing", "AdjusterBehavior"); -} + if (keyFile.has_group ("Batch Processing")) { + if (keyFile.has_key ("Batch Processing", "AdjusterBehavior")) { + baBehav = keyFile.get_integer_list ("Batch Processing", "AdjusterBehavior"); + } + } -if (keyFile.has_group ("Sounds")) { - if (keyFile.has_key ("Sounds", "Enable")) sndEnable = keyFile.get_boolean ("Sounds", "Enable"); - if (keyFile.has_key ("Sounds", "BatchQueueDone")) sndBatchQueueDone = keyFile.get_string ("Sounds", "BatchQueueDone"); - if (keyFile.has_key ("Sounds", "LngEditProcDone")) sndLngEditProcDone = keyFile.get_string ("Sounds", "LngEditProcDone"); - if (keyFile.has_key ("Sounds", "LngEditProcDoneSecs")) sndLngEditProcDoneSecs = keyFile.get_double ("Sounds", "LngEditProcDoneSecs"); -} + if (keyFile.has_group ("Sounds")) { + if (keyFile.has_key ("Sounds", "Enable")) { + sndEnable = keyFile.get_boolean ("Sounds", "Enable"); + } -if (keyFile.has_group ("Fast Export")) { - if (keyFile.has_key ("Fast Export", "fastexport_bypass_sharpening" )) fastexport_bypass_sharpening = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sharpening" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_sharpenEdge" )) fastexport_bypass_sharpenEdge = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sharpenEdge" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_sharpenMicro" )) fastexport_bypass_sharpenMicro = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sharpenMicro" ); - //if (keyFile.has_key ("Fast Export", "fastexport_bypass_lumaDenoise" )) fastexport_bypass_lumaDenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_lumaDenoise" ); - //if (keyFile.has_key ("Fast Export", "fastexport_bypass_colorDenoise" )) fastexport_bypass_colorDenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_colorDenoise" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_defringe" )) fastexport_bypass_defringe = keyFile.get_boolean ("Fast Export", "fastexport_bypass_defringe" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_dirpyrDenoise" )) fastexport_bypass_dirpyrDenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_sh_hq" )) fastexport_bypass_sh_hq = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sh_hq" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_dirpyrequalizer" )) fastexport_bypass_dirpyrequalizer = keyFile.get_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_wavelet" )) fastexport_bypass_wavelet = keyFile.get_boolean ("Fast Export", "fastexport_bypass_wavelet" ); - if (keyFile.has_key ("Fast Export", "fastexport_raw_dmethod" )) fastexport_raw_bayer_method = keyFile.get_string ("Fast Export", "fastexport_raw_dmethod" ); - if (keyFile.has_key ("Fast Export", "fastexport_raw_bayer_method" )) fastexport_raw_bayer_method = keyFile.get_string ("Fast Export", "fastexport_raw_bayer_method" ); - //if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_all_enhance" )) fastexport_bypass_raw_bayer_all_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_all_enhance" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_dcb_iterations" )) fastexport_bypass_raw_bayer_dcb_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_dcb_iterations" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" )) fastexport_bypass_raw_bayer_dcb_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_dcb_enhance" )) fastexport_bypass_raw_bayer_dcb_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_dcb_enhance" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" )) fastexport_bypass_raw_bayer_dcb_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_lmmse_iterations" )) fastexport_bypass_raw_bayer_lmmse_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_lmmse_iterations" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations")) fastexport_bypass_raw_bayer_lmmse_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations"); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_linenoise" )) fastexport_bypass_raw_bayer_linenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_linenoise" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" )) fastexport_bypass_raw_bayer_linenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_greenthresh" )) fastexport_bypass_raw_bayer_greenthresh = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_greenthresh" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" )) fastexport_bypass_raw_bayer_greenthresh = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" ); - if (keyFile.has_key ("Fast Export", "fastexport_raw_xtrans_method" )) fastexport_raw_xtrans_method = keyFile.get_string ("Fast Export", "fastexport_raw_xtrans_method" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ccSteps" )) fastexport_bypass_raw_ccSteps = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ca" )) fastexport_bypass_raw_ca = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ca" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_df" )) fastexport_bypass_raw_df = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_df" ); - if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ff" )) fastexport_bypass_raw_ff = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ff" ); - if (keyFile.has_key ("Fast Export", "fastexport_icm_input" )) fastexport_icm_input = keyFile.get_string ("Fast Export", "fastexport_icm_input" ); - if (keyFile.has_key ("Fast Export", "fastexport_icm_working" )) fastexport_icm_working = keyFile.get_string ("Fast Export", "fastexport_icm_working" ); - if (keyFile.has_key ("Fast Export", "fastexport_icm_output" )) fastexport_icm_output = keyFile.get_string ("Fast Export", "fastexport_icm_output" ); - if (keyFile.has_key ("Fast Export", "fastexport_icm_gamma" )) fastexport_icm_gamma = keyFile.get_string ("Fast Export", "fastexport_icm_gamma" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_enabled" )) fastexport_resize_enabled = keyFile.get_boolean ("Fast Export", "fastexport_resize_enabled" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_scale" )) fastexport_resize_scale = keyFile.get_double ("Fast Export", "fastexport_resize_scale" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_appliesTo" )) fastexport_resize_appliesTo = keyFile.get_string ("Fast Export", "fastexport_resize_appliesTo" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_method" )) fastexport_resize_method = keyFile.get_string ("Fast Export", "fastexport_resize_method" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_dataspec" )) fastexport_resize_dataspec = keyFile.get_integer ("Fast Export", "fastexport_resize_dataspec" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_width" )) fastexport_resize_width = keyFile.get_integer ("Fast Export", "fastexport_resize_width" ); - if (keyFile.has_key ("Fast Export", "fastexport_resize_height" )) fastexport_resize_height = keyFile.get_integer ("Fast Export", "fastexport_resize_height" ); -} + if (keyFile.has_key ("Sounds", "BatchQueueDone")) { + sndBatchQueueDone = keyFile.get_string ("Sounds", "BatchQueueDone"); + } -if (keyFile.has_group ("Dialogs")) { - safeDirGet(keyFile, "Dialogs", "LastIccDir", lastIccDir); - safeDirGet(keyFile, "Dialogs", "LastDarkframeDir", lastDarkframeDir); - safeDirGet(keyFile, "Dialogs", "LastFlatfieldDir", lastFlatfieldDir); - safeDirGet(keyFile, "Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastLabCurvesDir", lastLabCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastDenoiseCurvesDir", lastDenoiseCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastWaveletCurvesDir", lastWaveletCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastPFCurvesDir", lastPFCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastBWCurvesDir", lastBWCurvesDir); - - safeDirGet(keyFile, "Dialogs", "LastToneCurvesDir", lastToneCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastVibranceCurvesDir", lastVibranceCurvesDir); - safeDirGet(keyFile, "Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); -} + if (keyFile.has_key ("Sounds", "LngEditProcDone")) { + sndLngEditProcDone = keyFile.get_string ("Sounds", "LngEditProcDone"); + } + + if (keyFile.has_key ("Sounds", "LngEditProcDoneSecs")) { + sndLngEditProcDoneSecs = keyFile.get_double ("Sounds", "LngEditProcDoneSecs"); + } + } + + if (keyFile.has_group ("Fast Export")) { + if (keyFile.has_key ("Fast Export", "fastexport_bypass_sharpening" )) { + fastexport_bypass_sharpening = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sharpening" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_sharpenEdge" )) { + fastexport_bypass_sharpenEdge = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sharpenEdge" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_sharpenMicro" )) { + fastexport_bypass_sharpenMicro = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sharpenMicro" ); + } + + //if (keyFile.has_key ("Fast Export", "fastexport_bypass_lumaDenoise" )) fastexport_bypass_lumaDenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_lumaDenoise" ); + //if (keyFile.has_key ("Fast Export", "fastexport_bypass_colorDenoise" )) fastexport_bypass_colorDenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_colorDenoise" ); + if (keyFile.has_key ("Fast Export", "fastexport_bypass_defringe" )) { + fastexport_bypass_defringe = keyFile.get_boolean ("Fast Export", "fastexport_bypass_defringe" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_dirpyrDenoise" )) { + fastexport_bypass_dirpyrDenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_dirpyrDenoise" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_sh_hq" )) { + fastexport_bypass_sh_hq = keyFile.get_boolean ("Fast Export", "fastexport_bypass_sh_hq" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_dirpyrequalizer" )) { + fastexport_bypass_dirpyrequalizer = keyFile.get_boolean ("Fast Export", "fastexport_bypass_dirpyrequalizer" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_wavelet" )) { + fastexport_bypass_wavelet = keyFile.get_boolean ("Fast Export", "fastexport_bypass_wavelet" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_raw_dmethod" )) { + fastexport_raw_bayer_method = keyFile.get_string ("Fast Export", "fastexport_raw_dmethod" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_raw_bayer_method" )) { + fastexport_raw_bayer_method = keyFile.get_string ("Fast Export", "fastexport_raw_bayer_method" ); + } + + //if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_all_enhance" )) fastexport_bypass_raw_bayer_all_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_all_enhance" ); + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_dcb_iterations" )) { + fastexport_bypass_raw_bayer_dcb_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_dcb_iterations" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" )) { + fastexport_bypass_raw_bayer_dcb_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_iterations" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_dcb_enhance" )) { + fastexport_bypass_raw_bayer_dcb_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_dcb_enhance" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" )) { + fastexport_bypass_raw_bayer_dcb_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_dcb_enhance" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_lmmse_iterations" )) { + fastexport_bypass_raw_bayer_lmmse_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_lmmse_iterations" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations")) { + fastexport_bypass_raw_bayer_lmmse_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_lmmse_iterations"); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_linenoise" )) { + fastexport_bypass_raw_bayer_linenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_linenoise" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" )) { + fastexport_bypass_raw_bayer_linenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_linenoise" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_greenthresh" )) { + fastexport_bypass_raw_bayer_greenthresh = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_greenthresh" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" )) { + fastexport_bypass_raw_bayer_greenthresh = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_bayer_greenthresh" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_raw_xtrans_method" )) { + fastexport_raw_xtrans_method = keyFile.get_string ("Fast Export", "fastexport_raw_xtrans_method" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ccSteps" )) { + fastexport_bypass_raw_ccSteps = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ca" )) { + fastexport_bypass_raw_ca = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ca" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_df" )) { + fastexport_bypass_raw_df = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_df" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ff" )) { + fastexport_bypass_raw_ff = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ff" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_icm_input" )) { + fastexport_icm_input = keyFile.get_string ("Fast Export", "fastexport_icm_input" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_icm_working" )) { + fastexport_icm_working = keyFile.get_string ("Fast Export", "fastexport_icm_working" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_icm_output" )) { + fastexport_icm_output = keyFile.get_string ("Fast Export", "fastexport_icm_output" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_icm_gamma" )) { + fastexport_icm_gamma = keyFile.get_string ("Fast Export", "fastexport_icm_gamma" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_enabled" )) { + fastexport_resize_enabled = keyFile.get_boolean ("Fast Export", "fastexport_resize_enabled" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_scale" )) { + fastexport_resize_scale = keyFile.get_double ("Fast Export", "fastexport_resize_scale" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_appliesTo" )) { + fastexport_resize_appliesTo = keyFile.get_string ("Fast Export", "fastexport_resize_appliesTo" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_method" )) { + fastexport_resize_method = keyFile.get_string ("Fast Export", "fastexport_resize_method" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_dataspec" )) { + fastexport_resize_dataspec = keyFile.get_integer ("Fast Export", "fastexport_resize_dataspec" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_width" )) { + fastexport_resize_width = keyFile.get_integer ("Fast Export", "fastexport_resize_width" ); + } + + if (keyFile.has_key ("Fast Export", "fastexport_resize_height" )) { + fastexport_resize_height = keyFile.get_integer ("Fast Export", "fastexport_resize_height" ); + } + } + + if (keyFile.has_group ("Dialogs")) { + safeDirGet(keyFile, "Dialogs", "LastIccDir", lastIccDir); + safeDirGet(keyFile, "Dialogs", "LastDarkframeDir", lastDarkframeDir); + safeDirGet(keyFile, "Dialogs", "LastFlatfieldDir", lastFlatfieldDir); + safeDirGet(keyFile, "Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastLabCurvesDir", lastLabCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastDenoiseCurvesDir", lastDenoiseCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastWaveletCurvesDir", lastWaveletCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastPFCurvesDir", lastPFCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastBWCurvesDir", lastBWCurvesDir); + + safeDirGet(keyFile, "Dialogs", "LastToneCurvesDir", lastToneCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastVibranceCurvesDir", lastVibranceCurvesDir); + safeDirGet(keyFile, "Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); + } // -------------------------------------------------------------------------------------------------------- @@ -988,14 +1751,14 @@ if (keyFile.has_group ("Dialogs")) { return 0; } - } - catch (Glib::Error &err) { - if (options.rtSettings.verbose) + } catch (Glib::Error &err) { + 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()); - } - catch (...) { - if (options.rtSettings.verbose) + } + } catch (...) { + if (options.rtSettings.verbose) { printf("Options::readFromFile / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); + } } return 1; @@ -1009,23 +1772,28 @@ bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustri destination = keyFile.get_string(section, entryName); return true; } + return false; } -int Options::saveToFile (Glib::ustring fname) { +int Options::saveToFile (Glib::ustring fname) +{ rtengine::SafeKeyFile keyFile; keyFile.set_boolean ("General", "TabbedEditor", tabbedUI); keyFile.set_boolean ("General", "StoreLastProfile", savesParamsAtExit); - if (startupDir==STARTUPDIR_HOME) + + if (startupDir == STARTUPDIR_HOME) { keyFile.set_string ("General", "StartupDirectory", "home"); - else if (startupDir==STARTUPDIR_CURRENT) + } else if (startupDir == STARTUPDIR_CURRENT) { keyFile.set_string ("General", "StartupDirectory", "current"); - else if (startupDir==STARTUPDIR_CUSTOM) + } else if (startupDir == STARTUPDIR_CUSTOM) { keyFile.set_string ("General", "StartupDirectory", "custom"); - else if (startupDir==STARTUPDIR_LAST) + } else if (startupDir == STARTUPDIR_LAST) { keyFile.set_string ("General", "StartupDirectory", "last"); + } + keyFile.set_string ("General", "StartupPath", startupPath); keyFile.set_string ("General", "DateFormat", dateFormat); keyFile.set_integer ("General", "AdjusterDelay", adjusterDelay); @@ -1049,7 +1817,7 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_double ("General", "EDLipinfl", rtSettings.ed_lipinfl); keyFile.set_double ("General", "EDLipampl", rtSettings.ed_lipampl); - + keyFile.set_integer ("External Editor", "EditorKind", editorToSendTo); keyFile.set_string ("External Editor", "GimpDir", gimpDir); keyFile.set_string ("External Editor", "PhotoshopDir", psDir); @@ -1094,8 +1862,11 @@ int Options::saveToFile (Glib::ustring fname) { { std::vector temp; temp.reserve(maxRecentFolders); - for(unsigned int i=0;i using Internal values\n", options.defProfRaw.c_str()); + if (options.rtSettings.verbose) { + printf("Raws' default profile \"%s\" found\n", options.defProfRaw.c_str()); + } + } else { + if (options.rtSettings.verbose) { + printf("Raws' default profile \"%s\" not found or not set -> using Internal values\n", options.defProfRaw.c_str()); + } + options.defProfRaw = DEFPROFILE_INTERNAL; options.defProfRawMissing = true; } } - if (options.defProfImg.empty()) - options.defProfImg = DEFPROFILE_INTERNAL; - else { + if (options.defProfImg.empty()) { + options.defProfImg = DEFPROFILE_INTERNAL; + } else { Glib::ustring tmpFName = options.findProfilePath(options.defProfImg); + if (!tmpFName.empty()) { - if (options.rtSettings.verbose) printf("Images' default profile \"%s\" found\n", options.defProfImg.c_str()); - } - else { - if (options.rtSettings.verbose) printf("Images' default profile \"%s\" not found or not set -> using Internal values\n", options.defProfImg.c_str()); + if (options.rtSettings.verbose) { + printf("Images' default profile \"%s\" found\n", options.defProfImg.c_str()); + } + } else { + if (options.rtSettings.verbose) { + printf("Images' default profile \"%s\" not found or not set -> using Internal values\n", options.defProfImg.c_str()); + } + options.defProfImg = DEFPROFILE_INTERNAL; options.defProfImgMissing = true; } } - //We handle languages using a hierarchy of translations. The top of the hierarchy is default. This includes a default translation for all items - // (most likely using simple English). The next level is the language: for instance, English, French, Chinese, etc. This file should contain a - // generic translation for all items which differ from default. Finally there is the locale. This is region-specific items which differ from the - // language file. These files must be name in the format (), where Language is the name of the language which it inherits from, - // and LC is the local code. Some examples of this would be English (US) (American English), French (FR) (Franch French), French (CA) (Canadian - // French), etc. - // - // Each level will only contain the differences between itself and its parent translation. For instance, English (UK) or English (CA) may - // include the translation "HISTORY_MSG_34;Avoid Colour Clipping" where English would translate it as "HISTORY_MSG_34;Avoid Color Clipping" (note - // the difference in the spelling of 'colour'). - // - // It is important that when naming the translation files, that you stick to the format or (). We depend on that to figure - // out which are the parent translations. Furthermore, there must be a file for each locale () -- you cannot have - // 'French (CA)' unless there is a file 'French'. + //We handle languages using a hierarchy of translations. The top of the hierarchy is default. This includes a default translation for all items + // (most likely using simple English). The next level is the language: for instance, English, French, Chinese, etc. This file should contain a + // generic translation for all items which differ from default. Finally there is the locale. This is region-specific items which differ from the + // language file. These files must be name in the format (), where Language is the name of the language which it inherits from, + // and LC is the local code. Some examples of this would be English (US) (American English), French (FR) (Franch French), French (CA) (Canadian + // French), etc. + // + // Each level will only contain the differences between itself and its parent translation. For instance, English (UK) or English (CA) may + // include the translation "HISTORY_MSG_34;Avoid Colour Clipping" where English would translate it as "HISTORY_MSG_34;Avoid Color Clipping" (note + // the difference in the spelling of 'colour'). + // + // It is important that when naming the translation files, that you stick to the format or (). We depend on that to figure + // out which are the parent translations. Furthermore, there must be a file for each locale () -- you cannot have + // 'French (CA)' unless there is a file 'French'. - Glib::ustring defaultTranslation = argv0 + "/languages/default"; - Glib::ustring languageTranslation = ""; - Glib::ustring localeTranslation = ""; + Glib::ustring defaultTranslation = argv0 + "/languages/default"; + Glib::ustring languageTranslation = ""; + Glib::ustring localeTranslation = ""; - if (options.languageAutoDetect) options.language=langMgr.getOSUserLanguage(); + if (options.languageAutoDetect) { + options.language = langMgr.getOSUserLanguage(); + } - if (!options.language.empty()){ - std::vector langPortions = Glib::Regex::split_simple(" ", options.language); - if (langPortions.size() >= 1){ - languageTranslation = argv0 + "/languages/" + langPortions.at(0); - } - if (langPortions.size() >= 2){ - localeTranslation = argv0 + "/languages/" + options.language; - } - } + if (!options.language.empty()) { + std::vector langPortions = Glib::Regex::split_simple(" ", options.language); - langMgr.load(localeTranslation, new MultiLangMgr(languageTranslation, new MultiLangMgr(defaultTranslation))); + if (langPortions.size() >= 1) { + languageTranslation = argv0 + "/languages/" + langPortions.at(0); + } - rtengine::init (&options.rtSettings, argv0, rtdir); + if (langPortions.size() >= 2) { + localeTranslation = argv0 + "/languages/" + options.language; + } + } - return true; + langMgr.load(localeTranslation, new MultiLangMgr(languageTranslation, new MultiLangMgr(defaultTranslation))); + + rtengine::init (&options.rtSettings, argv0, rtdir); + + return true; } -void Options::save () { +void Options::save () +{ - if (options.multiUser==false) { + if (options.multiUser == false) { options.saveToFile (Glib::build_filename(argv0, "options")); - } - else { + } else { options.saveToFile (Glib::build_filename(rtdir, "options")); } } @@ -1474,29 +2272,34 @@ void Options::save () { /* * return true if fname ends with one of the retained image file extensions */ -bool Options::has_retained_extention (Glib::ustring fname) { +bool Options::has_retained_extention (Glib::ustring fname) +{ - Glib::ustring ext = getExtension(fname).lowercase(); + Glib::ustring ext = getExtension(fname).lowercase(); - if (!ext.empty()) { - // there is an extension to the filename + if (!ext.empty()) { + // there is an extension to the filename - // look out if it has one of the retained extensions - for (unsigned int i=0; i=(int)parseExtensionsEnabled.size() || parseExtensionsEnabled[j]; - return false; +bool Options::is_extention_enabled (Glib::ustring ext) +{ + for (int j = 0; j < (int)parseExtensions.size(); j++) + if (parseExtensions[j].casefold() == ext.casefold()) { + return j >= (int)parseExtensionsEnabled.size() || parseExtensionsEnabled[j]; + } + + return false; } diff --git a/rtgui/options.h b/rtgui/options.h index 804deeb73..753ae01bb 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -7,7 +7,7 @@ * 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 @@ -37,33 +37,36 @@ #define DEFPROFILE_IMG "Neutral" // Profile name to use for internal values' profile #define DEFPROFILE_INTERNAL "Neutral" - -class SaveFormat { - public: - Glib::ustring format; - int pngBits; - int pngCompression; - int jpegQuality; - int jpegSubSamp; // 1=best compression, 3=best quality - int tiffBits; - bool tiffUncompressed; - bool saveParams; - SaveFormat () : format("jpg"), pngBits(8), pngCompression(6), jpegQuality(90), jpegSubSamp(2), tiffBits(8), tiffUncompressed(true), saveParams(true) {}; +class SaveFormat +{ + +public: + Glib::ustring format; + int pngBits; + int pngCompression; + int jpegQuality; + int jpegSubSamp; // 1=best compression, 3=best quality + int tiffBits; + bool tiffUncompressed; + bool saveParams; + SaveFormat () : format("jpg"), pngBits(8), pngCompression(6), jpegQuality(90), jpegSubSamp(2), tiffBits(8), tiffUncompressed(true), saveParams(true) {}; }; -enum ThFileType {FT_Invalid=-1, FT_None=0, FT_Raw=1, FT_Jpeg=2, FT_Tiff=3, FT_Png=4, FT_Custom=5, FT_Tiff16=6, FT_Png16=7, FT_Custom16=8}; -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}; +enum ThFileType {FT_Invalid = -1, FT_None = 0, FT_Raw = 1, FT_Jpeg = 2, FT_Tiff = 3, FT_Png = 4, FT_Custom = 5, FT_Tiff16 = 6, FT_Png16 = 7, FT_Custom16 = 8}; +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; +namespace rtengine +{ +class SafeKeyFile; } -class Options { +class Options +{ - private: +private: bool defProfRawMissing; bool defProfImgMissing; Glib::ustring userProfilePath; @@ -85,11 +88,11 @@ class Options { * @return @c true if @p destination was changed */ bool safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, - const Glib::ustring& entryName, Glib::ustring& destination); + const Glib::ustring& entryName, Glib::ustring& destination); - public: +public: bool savesParamsAtExit; - SaveFormat saveFormat,saveFormatBatch; + SaveFormat saveFormat, saveFormatBatch; Glib::ustring savePathTemplate; Glib::ustring savePathFolder; bool saveUsePathTemplate; @@ -137,7 +140,7 @@ class Options { bool multiUser; static Glib::ustring rtdir; Glib::ustring version; - int thumbSize,thumbSizeTab, thumbSizeQueue; + int thumbSize, thumbSizeTab, thumbSizeQueue; bool sameThumbSize; // Will use only one thumb size for the file browser and the single editor tab, and avoid recomputing them bool showHistory; int showFilePanelState; // 0: normal, 1: maximized, 2: normal, 3: hidden @@ -194,7 +197,7 @@ class Options { bool showFileNames; bool filmStripShowFileNames; bool tabbedUI; - int previewSizeTab,previewSizeBrowser; + int previewSizeTab, previewSizeBrowser; bool rememberZoomAndPan; int multiDisplayMode; // 0=none, 1=Edit panels on other display std::vector cutOverlayBrush; // Red;Green;Blue;Alpha , all ranging 0..1 @@ -284,7 +287,7 @@ class Options { Glib::ustring lastVibranceCurvesDir; Glib::ustring lastProfilingReferenceDir; Glib::ustring lastBWCurvesDir; - + size_t maxRecentFolders; // max. number of recent folders stored in options file std::vector recentFolders; // List containing all recent folders @@ -301,15 +304,33 @@ class Options { // if multiUser=false, send back the global profile path Glib::ustring getPreferredProfilePath(); - Glib::ustring getUserProfilePath() { return userProfilePath; } - Glib::ustring getGlobalProfilePath() { return globalProfilePath; } + Glib::ustring getUserProfilePath() + { + return userProfilePath; + } + Glib::ustring getGlobalProfilePath() + { + return globalProfilePath; + } Glib::ustring findProfilePath(Glib::ustring &profName); bool has_retained_extention (Glib::ustring fname); bool is_extention_enabled(Glib::ustring ext); - bool is_defProfRawMissing() { return defProfRawMissing; } - bool is_defProfImgMissing() { return defProfImgMissing; } - void setDefProfRawMissing(bool value) { defProfRawMissing = value; } - void setDefProfImgMissing(bool value) { defProfImgMissing = value; } + bool is_defProfRawMissing() + { + return defProfRawMissing; + } + bool is_defProfImgMissing() + { + return defProfImgMissing; + } + void setDefProfRawMissing(bool value) + { + defProfRawMissing = value; + } + void setDefProfImgMissing(bool value) + { + defProfImgMissing = value; + } }; extern Options options; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 0359726a1..a597662b7 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -7,7 +7,7 @@ * 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 @@ -21,463 +21,472 @@ #include "options.h" #include "addsetids.h" -ParamsEdited::ParamsEdited (bool value) { +ParamsEdited::ParamsEdited (bool value) +{ set (value); } -void ParamsEdited::set (bool v) { +void ParamsEdited::set (bool v) +{ - general.rank = v; - general.colorlabel = v; - general.intrash = v; - toneCurve.curve = v; - toneCurve.curve2 = v; - toneCurve.curveMode = v; - toneCurve.curveMode2 = v; - toneCurve.brightness = v; - toneCurve.black = v; - toneCurve.contrast = v; - toneCurve.saturation = v; - toneCurve.shcompr = v; - toneCurve.hlcompr = v; - toneCurve.hlcomprthresh = v; - toneCurve.autoexp = v; - toneCurve.clip = v; - toneCurve.expcomp = v; - toneCurve.hrenabled = v; - toneCurve.method = v; - labCurve.lcurve = v; - labCurve.acurve = v; - labCurve.bcurve = v; - labCurve.cccurve = v; - labCurve.chcurve = v; - labCurve.lhcurve = v; - labCurve.hhcurve = v; - labCurve.lccurve = v; - labCurve.clcurve = v; - labCurve.brightness = v; - labCurve.contrast = v; - labCurve.chromaticity = v; - labCurve.avoidcolorshift = v; - labCurve.rstprotection = v; - labCurve.lcredsk = v; - rgbCurves.lumamode = v; - rgbCurves.rcurve = v; - rgbCurves.gcurve = v; - rgbCurves.bcurve = v; - colorToning.enabled = v; - colorToning.autosat = v; - colorToning.opacityCurve = v; - colorToning.colorCurve = v; - colorToning.satprotectionthreshold = v; - colorToning.saturatedopacity = v; - colorToning.strength = v; - colorToning.shadowsColSat = v; - colorToning.hlColSat = v; - colorToning.balance = v; - colorToning.clcurve = v; - colorToning.method = v; - colorToning.twocolor = v; - colorToning.cl2curve = v; - colorToning.redlow = v; - colorToning.greenlow = v; - colorToning.bluelow = v; - colorToning.satlow = v; - colorToning.sathigh = v; - colorToning.redmed = v; - colorToning.greenmed = v; - colorToning.bluemed = v; - colorToning.redhigh = v; - colorToning.greenhigh = v; - colorToning.bluehigh = v; - colorToning.lumamode = v; + general.rank = v; + general.colorlabel = v; + general.intrash = v; + toneCurve.curve = v; + toneCurve.curve2 = v; + toneCurve.curveMode = v; + toneCurve.curveMode2 = v; + toneCurve.brightness = v; + toneCurve.black = v; + toneCurve.contrast = v; + toneCurve.saturation = v; + toneCurve.shcompr = v; + toneCurve.hlcompr = v; + toneCurve.hlcomprthresh = v; + toneCurve.autoexp = v; + toneCurve.clip = v; + toneCurve.expcomp = v; + toneCurve.hrenabled = v; + toneCurve.method = v; + labCurve.lcurve = v; + labCurve.acurve = v; + labCurve.bcurve = v; + labCurve.cccurve = v; + labCurve.chcurve = v; + labCurve.lhcurve = v; + labCurve.hhcurve = v; + labCurve.lccurve = v; + labCurve.clcurve = v; + labCurve.brightness = v; + labCurve.contrast = v; + labCurve.chromaticity = v; + labCurve.avoidcolorshift = v; + labCurve.rstprotection = v; + labCurve.lcredsk = v; + rgbCurves.lumamode = v; + rgbCurves.rcurve = v; + rgbCurves.gcurve = v; + rgbCurves.bcurve = v; + colorToning.enabled = v; + colorToning.autosat = v; + colorToning.opacityCurve = v; + colorToning.colorCurve = v; + colorToning.satprotectionthreshold = v; + colorToning.saturatedopacity = v; + colorToning.strength = v; + colorToning.shadowsColSat = v; + colorToning.hlColSat = v; + colorToning.balance = v; + colorToning.clcurve = v; + colorToning.method = v; + colorToning.twocolor = v; + colorToning.cl2curve = v; + colorToning.redlow = v; + colorToning.greenlow = v; + colorToning.bluelow = v; + colorToning.satlow = v; + colorToning.sathigh = v; + colorToning.redmed = v; + colorToning.greenmed = v; + colorToning.bluemed = v; + colorToning.redhigh = v; + colorToning.greenhigh = v; + colorToning.bluehigh = v; + colorToning.lumamode = v; - sharpening.enabled = v; - sharpening.radius = v; - sharpening.amount = v; - sharpening.threshold = v; - sharpening.edgesonly = v; - sharpening.edges_radius = v; - sharpening.edges_tolerance = v; - sharpening.halocontrol = v; - sharpening.halocontrol_amount = v; - sharpening.method = v; - sharpening.deconvamount = v; - sharpening.deconvradius = v; - sharpening.deconviter = v; - sharpening.deconvdamping = v; - prsharpening.enabled = v; - prsharpening.radius = v; - prsharpening.amount = v; - prsharpening.threshold = v; - prsharpening.edgesonly = v; - prsharpening.edges_radius = v; - prsharpening.edges_tolerance = v; - prsharpening.halocontrol = v; - prsharpening.halocontrol_amount = v; - prsharpening.method = v; - prsharpening.deconvamount = v; - prsharpening.deconvradius = v; - prsharpening.deconviter = v; - prsharpening.deconvdamping = v; - sharpenEdge.enabled = v; - sharpenEdge.passes = v; - sharpenEdge.amount = v; - sharpenEdge.threechannels = v; - sharpenMicro.enabled = v; - sharpenMicro.matrix = v; - sharpenMicro.amount = v; - sharpenMicro.uniformity = v; - vibrance.enabled = v; - vibrance.pastels = v; - vibrance.saturated = v; - vibrance.psthreshold = v; - vibrance.protectskins = v; - vibrance.avoidcolorshift = v; - vibrance.pastsattog = v; - vibrance.skintonescurve = v; - colorappearance.enabled = v; - colorappearance.degree = v; - colorappearance.autodegree = v; - colorappearance.surround = v; - colorappearance.adapscen = v; - colorappearance.autoadapscen = v; - colorappearance.adaplum = v; - colorappearance.badpixsl = v; - colorappearance.wbmodel = v; - colorappearance.algo = v; - - colorappearance.jlight = v; - colorappearance.qbright = v; - colorappearance.chroma = v; - colorappearance.schroma = v; - colorappearance.mchroma = v; - colorappearance.contrast = v; - colorappearance.qcontrast = v; - colorappearance.colorh = v; - colorappearance.rstprotection = v; - colorappearance.surrsource = v; - colorappearance.gamut = v; -// colorappearance.badpix = v; - colorappearance.datacie = v; - colorappearance.tonecie = v; -// colorappearance.sharpcie = v; - colorappearance.curve = v; - colorappearance.curve2 = v; - colorappearance.curve3 = v; + sharpening.enabled = v; + sharpening.radius = v; + sharpening.amount = v; + sharpening.threshold = v; + sharpening.edgesonly = v; + sharpening.edges_radius = v; + sharpening.edges_tolerance = v; + sharpening.halocontrol = v; + sharpening.halocontrol_amount = v; + sharpening.method = v; + sharpening.deconvamount = v; + sharpening.deconvradius = v; + sharpening.deconviter = v; + sharpening.deconvdamping = v; + prsharpening.enabled = v; + prsharpening.radius = v; + prsharpening.amount = v; + prsharpening.threshold = v; + prsharpening.edgesonly = v; + prsharpening.edges_radius = v; + prsharpening.edges_tolerance = v; + prsharpening.halocontrol = v; + prsharpening.halocontrol_amount = v; + prsharpening.method = v; + prsharpening.deconvamount = v; + prsharpening.deconvradius = v; + prsharpening.deconviter = v; + prsharpening.deconvdamping = v; + sharpenEdge.enabled = v; + sharpenEdge.passes = v; + sharpenEdge.amount = v; + sharpenEdge.threechannels = v; + sharpenMicro.enabled = v; + sharpenMicro.matrix = v; + sharpenMicro.amount = v; + sharpenMicro.uniformity = v; + vibrance.enabled = v; + vibrance.pastels = v; + vibrance.saturated = v; + vibrance.psthreshold = v; + vibrance.protectskins = v; + vibrance.avoidcolorshift = v; + vibrance.pastsattog = v; + vibrance.skintonescurve = v; + colorappearance.enabled = v; + colorappearance.degree = v; + colorappearance.autodegree = v; + colorappearance.surround = v; + colorappearance.adapscen = v; + colorappearance.autoadapscen = v; + colorappearance.adaplum = v; + colorappearance.badpixsl = v; + colorappearance.wbmodel = v; + colorappearance.algo = v; + + colorappearance.jlight = v; + colorappearance.qbright = v; + colorappearance.chroma = v; + colorappearance.schroma = v; + colorappearance.mchroma = v; + colorappearance.contrast = v; + colorappearance.qcontrast = v; + colorappearance.colorh = v; + colorappearance.rstprotection = v; + colorappearance.surrsource = v; + colorappearance.gamut = v; +// colorappearance.badpix = v; + colorappearance.datacie = v; + colorappearance.tonecie = v; +// colorappearance.sharpcie = v; + colorappearance.curve = v; + colorappearance.curve2 = v; + colorappearance.curve3 = v; colorappearance.curveMode = v; colorappearance.curveMode2 = v; colorappearance.curveMode3 = v; - - //colorBoost.amount = v; - //colorBoost.avoidclip = v; - //colorBoost.enable_saturationlimiter = v; - //colorBoost.saturationlimit = v; - wb.method = v; - wb.green = v; - wb.temperature = v; - wb.equal = v; - //colorShift.a = v; - //colorShift.b = v; - //lumaDenoise.enabled = v; - //lumaDenoise.radius = v; - //lumaDenoise.edgetolerance = v; - //colorDenoise.enabled = v; - //colorDenoise.amount = v; - defringe.enabled = v; - defringe.radius = v; - defringe.threshold = v; - defringe.huecurve = v; - impulseDenoise.enabled = v; - impulseDenoise.thresh = v; - dirpyrDenoise.enabled = v; - dirpyrDenoise.enhance = v; -// dirpyrDenoise.perform = v; - dirpyrDenoise.lcurve = v; - dirpyrDenoise.cccurve = v; - dirpyrDenoise.median = v; - dirpyrDenoise.autochroma = v; - dirpyrDenoise.luma = v; - dirpyrDenoise.Ldetail = v; - dirpyrDenoise.chroma = v; - dirpyrDenoise.redchro = v; - dirpyrDenoise.bluechro = v; - dirpyrDenoise.gamma = v; - dirpyrDenoise.passes = v; - dirpyrDenoise.dmethod = v; - dirpyrDenoise.Lmethod = v; - dirpyrDenoise.Cmethod = v; - dirpyrDenoise.C2method = v; - dirpyrDenoise.smethod = v; - dirpyrDenoise.medmethod = v; - dirpyrDenoise.methodmed = v; - dirpyrDenoise.rgbmethod = v; - epd.enabled = v; - epd.strength = v; - epd.gamma = v; - epd.edgeStopping = v; - epd.scale = v; - epd.reweightingIterates = v; - sh.enabled = v; - sh.hq = v; - sh.highlights = v; - sh.htonalwidth = v; - sh.shadows = v; - sh.stonalwidth = v; - sh.localcontrast = v; - sh.radius = v; - crop.enabled = v; - crop.x = v; - crop.y = v; - crop.w = v; - crop.h = v; - crop.fixratio = v; - crop.ratio = v; - crop.orientation = v; - crop.guide = v; - coarse.rotate = v; - coarse.hflip = v; - coarse.vflip = v; - commonTrans.autofill = v; - rotate.degree = v; - distortion.amount = v; - lensProf.lcpFile = v; - lensProf.useDist = v; - lensProf.useVign = v; - lensProf.useCA = v; - perspective.horizontal = v; - perspective.vertical = v; - gradient.enabled = v; - gradient.degree = v; - gradient.feather = v; - gradient.strength = v; - gradient.centerX = v; - gradient.centerY = v; - pcvignette.enabled = v; - pcvignette.strength = v; - pcvignette.feather = v; - pcvignette.roundness = v; - cacorrection.red = v; - cacorrection.blue = v; - vignetting.amount = v; - vignetting.radius = v; - vignetting.strength = v; - vignetting.centerX = v; - vignetting.centerY = v; - chmixer.red[0] = v; - chmixer.red[1] = v; - chmixer.red[2] = v; - chmixer.green[0] = v; - chmixer.green[1] = v; - chmixer.green[2] = v; - chmixer.blue[0] = v; - chmixer.blue[1] = v; - chmixer.blue[2] = v; - blackwhite.enabled = v; - blackwhite.enabledcc = v; - blackwhite.mixerRed = v; - blackwhite.mixerOrange = v; - blackwhite.mixerYellow = v; - blackwhite.mixerGreen = v; - blackwhite.mixerCyan = v; - blackwhite.mixerBlue = v; - blackwhite.mixerMagenta = v; - blackwhite.mixerPurple = v; - blackwhite.gammaRed = v; - blackwhite.gammaGreen = v; - blackwhite.gammaBlue = v; - blackwhite.filter = v; - blackwhite.setting = v; - blackwhite.method = v; - blackwhite.luminanceCurve = v; - blackwhite.beforeCurve = v; - blackwhite.beforeCurveMode = v; - blackwhite.afterCurve = v; - blackwhite.afterCurveMode = v; - blackwhite.autoc = v; - blackwhite.algo = v; - - resize.scale = v; - resize.appliesTo = v; - resize.method = v; - resize.dataspec = v; - resize.width = v; - resize.height = v; - resize.enabled = v; - icm.input = v; - icm.toneCurve = v; - icm.applyLookTable = v; - icm.applyBaselineExposureOffset = v; - icm.applyHueSatMap = v; - icm.blendCMSMatrix = v; - icm.dcpIlluminant = v; - icm.working = v; - icm.output = v; - icm.gamma = v; - icm.freegamma = v; - icm.gampos = v; - icm.slpos = v; - raw.bayersensor.method = v; - raw.bayersensor.ccSteps = v; - raw.bayersensor.exBlack0 = v; - raw.bayersensor.exBlack1 = v; - raw.bayersensor.exBlack2 = v; - raw.bayersensor.exBlack3 = v; - raw.bayersensor.exTwoGreen=v; - raw.bayersensor.dcbIterations = v; - raw.bayersensor.dcbEnhance = v; - //raw.bayersensor.allEnhance = v; - raw.bayersensor.lmmseIterations = v; - raw.bayersensor.greenEq = v; - raw.bayersensor.linenoise = v; - raw.xtranssensor.method = v; - raw.xtranssensor.ccSteps = v; - raw.xtranssensor.exBlackRed= v; - raw.xtranssensor.exBlackGreen = v; - raw.xtranssensor.exBlackBlue = v; - raw.caCorrection = v; - raw.caBlue = v; - raw.caRed = v; - raw.hotPixelFilter = v; - raw.deadPixelFilter = v; - raw.hotDeadPixelThresh = v; - raw.darkFrame = v; - raw.dfAuto = v; - raw.ff_file = v; - raw.ff_AutoSelect = v; - raw.ff_BlurRadius = v; - raw.ff_BlurType = v; - raw.ff_AutoClipControl = v; - raw.ff_clipControl = v; - raw.exPos = v; - raw.exPreser = v; - wavelet.enabled = v; - wavelet.strength = v; - wavelet.balance = v; - wavelet.iter = v; - wavelet.median = v; - wavelet.medianlev = v; - wavelet.linkedg = v; - wavelet.cbenab = v; - wavelet.greenhigh = v; - wavelet.greenmed = v; - wavelet.greenlow = v; - wavelet.bluehigh = v; - wavelet.bluemed = v; - wavelet.bluelow = v; - wavelet.lipst = v; - wavelet.Medgreinf = v; - wavelet.avoid = v; - wavelet.tmr = v; - wavelet.Lmethod = v; - wavelet.CLmethod = v; - wavelet.Backmethod = v; - wavelet.Tilesmethod = v; - wavelet.daubcoeffmethod = v; - wavelet.CHmethod = v; - wavelet.CHSLmethod = v; - wavelet.EDmethod = v; - wavelet.NPmethod = v; - wavelet.BAmethod = v; - wavelet.TMmethod = v; - wavelet.HSmethod = v; - wavelet.Dirmethod = v; - wavelet.rescon = v; - wavelet.resconH = v; - wavelet.reschro = v; - wavelet.tmrs = v; - wavelet.gamma = v; - wavelet.sup = v; - wavelet.sky = v; - wavelet.thres = v; - wavelet.threshold = v; - wavelet.threshold2 = v; - wavelet.edgedetect = v; - wavelet.edgedetectthr = v; - wavelet.edgedetectthr2 = v; - wavelet.edgesensi = v; - wavelet.edgeampli = v; - wavelet.chroma = v; - wavelet.chro = v; - wavelet.contrast = v; - wavelet.edgrad = v; - wavelet.edgval = v; - wavelet.edgthresh = v; - wavelet.thr = v; - wavelet.thrH = v; - wavelet.skinprotect = v; - wavelet.hueskin = v; - wavelet.hueskin2 = v; - wavelet.hllev = v; - wavelet.bllev = v; - wavelet.edgcont = v; - wavelet.level0noise = v; - wavelet.level1noise = v; - wavelet.level2noise = v; - wavelet.level3noise = v; - wavelet.ccwcurve = v; - wavelet.opacityCurveRG = v; - wavelet.opacityCurveBY = v; - wavelet.opacityCurveW = v; - wavelet.opacityCurveWL = v; - wavelet.hhcurve = v; - wavelet.Chcurve = v; - wavelet.wavclCurve = v; - - wavelet.pastlev = v; - wavelet.satlev = v; -// wavelet.enacont = v; -// wavelet.enachrom = v; -// wavelet.enaedge = v; -// wavelet.enares = v; - wavelet.expfinal = v; - wavelet.expcontrast = v; - wavelet.expchroma = v; - wavelet.expedge = v; - wavelet.expresid = v; - wavelet.exptoning = v; - wavelet.expnoise = v; - - for(int i = 0; i < 9; i++) { - wavelet.c[i] = v; - } - for(int i = 0; i < 9; i++) { - wavelet.ch[i] = v; - } + //colorBoost.amount = v; + //colorBoost.avoidclip = v; + //colorBoost.enable_saturationlimiter = v; + //colorBoost.saturationlimit = v; + wb.method = v; + wb.green = v; + wb.temperature = v; + wb.equal = v; + //colorShift.a = v; + //colorShift.b = v; + //lumaDenoise.enabled = v; + //lumaDenoise.radius = v; + //lumaDenoise.edgetolerance = v; + //colorDenoise.enabled = v; + //colorDenoise.amount = v; + defringe.enabled = v; + defringe.radius = v; + defringe.threshold = v; + defringe.huecurve = v; + impulseDenoise.enabled = v; + impulseDenoise.thresh = v; + dirpyrDenoise.enabled = v; + dirpyrDenoise.enhance = v; +// dirpyrDenoise.perform = v; + dirpyrDenoise.lcurve = v; + dirpyrDenoise.cccurve = v; + dirpyrDenoise.median = v; + dirpyrDenoise.autochroma = v; + dirpyrDenoise.luma = v; + dirpyrDenoise.Ldetail = v; + dirpyrDenoise.chroma = v; + dirpyrDenoise.redchro = v; + dirpyrDenoise.bluechro = v; + dirpyrDenoise.gamma = v; + dirpyrDenoise.passes = v; + dirpyrDenoise.dmethod = v; + dirpyrDenoise.Lmethod = v; + dirpyrDenoise.Cmethod = v; + dirpyrDenoise.C2method = v; + dirpyrDenoise.smethod = v; + dirpyrDenoise.medmethod = v; + dirpyrDenoise.methodmed = v; + dirpyrDenoise.rgbmethod = v; + epd.enabled = v; + epd.strength = v; + epd.gamma = v; + epd.edgeStopping = v; + epd.scale = v; + epd.reweightingIterates = v; + sh.enabled = v; + sh.hq = v; + sh.highlights = v; + sh.htonalwidth = v; + sh.shadows = v; + sh.stonalwidth = v; + sh.localcontrast = v; + sh.radius = v; + crop.enabled = v; + crop.x = v; + crop.y = v; + crop.w = v; + crop.h = v; + crop.fixratio = v; + crop.ratio = v; + crop.orientation = v; + crop.guide = v; + coarse.rotate = v; + coarse.hflip = v; + coarse.vflip = v; + commonTrans.autofill = v; + rotate.degree = v; + distortion.amount = v; + lensProf.lcpFile = v; + lensProf.useDist = v; + lensProf.useVign = v; + lensProf.useCA = v; + perspective.horizontal = v; + perspective.vertical = v; + gradient.enabled = v; + gradient.degree = v; + gradient.feather = v; + gradient.strength = v; + gradient.centerX = v; + gradient.centerY = v; + pcvignette.enabled = v; + pcvignette.strength = v; + pcvignette.feather = v; + pcvignette.roundness = v; + cacorrection.red = v; + cacorrection.blue = v; + vignetting.amount = v; + vignetting.radius = v; + vignetting.strength = v; + vignetting.centerX = v; + vignetting.centerY = v; + chmixer.red[0] = v; + chmixer.red[1] = v; + chmixer.red[2] = v; + chmixer.green[0] = v; + chmixer.green[1] = v; + chmixer.green[2] = v; + chmixer.blue[0] = v; + chmixer.blue[1] = v; + chmixer.blue[2] = v; + blackwhite.enabled = v; + blackwhite.enabledcc = v; + blackwhite.mixerRed = v; + blackwhite.mixerOrange = v; + blackwhite.mixerYellow = v; + blackwhite.mixerGreen = v; + blackwhite.mixerCyan = v; + blackwhite.mixerBlue = v; + blackwhite.mixerMagenta = v; + blackwhite.mixerPurple = v; + blackwhite.gammaRed = v; + blackwhite.gammaGreen = v; + blackwhite.gammaBlue = v; + blackwhite.filter = v; + blackwhite.setting = v; + blackwhite.method = v; + blackwhite.luminanceCurve = v; + blackwhite.beforeCurve = v; + blackwhite.beforeCurveMode = v; + blackwhite.afterCurve = v; + blackwhite.afterCurveMode = v; + blackwhite.autoc = v; + blackwhite.algo = v; - dirpyrequalizer.enabled = v; - dirpyrequalizer.gamutlab = v; - for(int i = 0; i < 6; i++) { - dirpyrequalizer.mult[i] = v; - } - dirpyrequalizer.threshold = v; - dirpyrequalizer.skinprotect = v; - dirpyrequalizer.hueskin = v; - //dirpyrequalizer.algo = v; - hsvequalizer.hcurve = v; - hsvequalizer.scurve = v; - hsvequalizer.vcurve = v; + + resize.scale = v; + resize.appliesTo = v; + resize.method = v; + resize.dataspec = v; + resize.width = v; + resize.height = v; + resize.enabled = v; + icm.input = v; + icm.toneCurve = v; + icm.applyLookTable = v; + icm.applyBaselineExposureOffset = v; + icm.applyHueSatMap = v; + icm.blendCMSMatrix = v; + icm.dcpIlluminant = v; + icm.working = v; + icm.output = v; + icm.gamma = v; + icm.freegamma = v; + icm.gampos = v; + icm.slpos = v; + raw.bayersensor.method = v; + raw.bayersensor.ccSteps = v; + raw.bayersensor.exBlack0 = v; + raw.bayersensor.exBlack1 = v; + raw.bayersensor.exBlack2 = v; + raw.bayersensor.exBlack3 = v; + raw.bayersensor.exTwoGreen = v; + raw.bayersensor.dcbIterations = v; + raw.bayersensor.dcbEnhance = v; + //raw.bayersensor.allEnhance = v; + raw.bayersensor.lmmseIterations = v; + raw.bayersensor.greenEq = v; + raw.bayersensor.linenoise = v; + raw.xtranssensor.method = v; + raw.xtranssensor.ccSteps = v; + raw.xtranssensor.exBlackRed = v; + raw.xtranssensor.exBlackGreen = v; + raw.xtranssensor.exBlackBlue = v; + raw.caCorrection = v; + raw.caBlue = v; + raw.caRed = v; + raw.hotPixelFilter = v; + raw.deadPixelFilter = v; + raw.hotDeadPixelThresh = v; + raw.darkFrame = v; + raw.dfAuto = v; + raw.ff_file = v; + raw.ff_AutoSelect = v; + raw.ff_BlurRadius = v; + raw.ff_BlurType = v; + raw.ff_AutoClipControl = v; + raw.ff_clipControl = v; + raw.exPos = v; + raw.exPreser = v; + wavelet.enabled = v; + wavelet.strength = v; + wavelet.balance = v; + wavelet.iter = v; + wavelet.median = v; + wavelet.medianlev = v; + wavelet.linkedg = v; + wavelet.cbenab = v; + wavelet.greenhigh = v; + wavelet.greenmed = v; + wavelet.greenlow = v; + wavelet.bluehigh = v; + wavelet.bluemed = v; + wavelet.bluelow = v; + wavelet.lipst = v; + wavelet.Medgreinf = v; + wavelet.avoid = v; + wavelet.tmr = v; + wavelet.Lmethod = v; + wavelet.CLmethod = v; + wavelet.Backmethod = v; + wavelet.Tilesmethod = v; + wavelet.daubcoeffmethod = v; + wavelet.CHmethod = v; + wavelet.CHSLmethod = v; + wavelet.EDmethod = v; + wavelet.NPmethod = v; + wavelet.BAmethod = v; + wavelet.TMmethod = v; + wavelet.HSmethod = v; + wavelet.Dirmethod = v; + wavelet.rescon = v; + wavelet.resconH = v; + wavelet.reschro = v; + wavelet.tmrs = v; + wavelet.gamma = v; + wavelet.sup = v; + wavelet.sky = v; + wavelet.thres = v; + wavelet.threshold = v; + wavelet.threshold2 = v; + wavelet.edgedetect = v; + wavelet.edgedetectthr = v; + wavelet.edgedetectthr2 = v; + wavelet.edgesensi = v; + wavelet.edgeampli = v; + wavelet.chroma = v; + wavelet.chro = v; + wavelet.contrast = v; + wavelet.edgrad = v; + wavelet.edgval = v; + wavelet.edgthresh = v; + wavelet.thr = v; + wavelet.thrH = v; + wavelet.skinprotect = v; + wavelet.hueskin = v; + wavelet.hueskin2 = v; + wavelet.hllev = v; + wavelet.bllev = v; + wavelet.edgcont = v; + wavelet.level0noise = v; + wavelet.level1noise = v; + wavelet.level2noise = v; + wavelet.level3noise = v; + wavelet.ccwcurve = v; + wavelet.opacityCurveRG = v; + wavelet.opacityCurveBY = v; + wavelet.opacityCurveW = v; + wavelet.opacityCurveWL = v; + wavelet.hhcurve = v; + wavelet.Chcurve = v; + wavelet.wavclCurve = v; + + wavelet.pastlev = v; + wavelet.satlev = v; +// wavelet.enacont = v; +// wavelet.enachrom = v; +// wavelet.enaedge = v; +// wavelet.enares = v; + wavelet.expfinal = v; + wavelet.expcontrast = v; + wavelet.expchroma = v; + wavelet.expedge = v; + wavelet.expresid = v; + wavelet.exptoning = v; + wavelet.expnoise = v; + + for(int i = 0; i < 9; i++) { + wavelet.c[i] = v; + } + + for(int i = 0; i < 9; i++) { + wavelet.ch[i] = v; + } + + dirpyrequalizer.enabled = v; + dirpyrequalizer.gamutlab = v; + + for(int i = 0; i < 6; i++) { + dirpyrequalizer.mult[i] = v; + } + + dirpyrequalizer.threshold = v; + dirpyrequalizer.skinprotect = v; + dirpyrequalizer.hueskin = v; + //dirpyrequalizer.algo = v; + hsvequalizer.hcurve = v; + hsvequalizer.scurve = v; + hsvequalizer.vcurve = v; filmSimulation.enabled = v; filmSimulation.clutFilename = v; filmSimulation.strength = v; - exif = v; - iptc = v; + exif = v; + iptc = v; } using namespace rtengine; using namespace rtengine::procparams; -void ParamsEdited::initFrom (const std::vector& src) { +void ParamsEdited::initFrom (const std::vector& src) +{ set (true); - if (src.empty()) + + if (src.empty()) { return; + } const ProcParams& p = src[0]; - for (size_t i=1; i colorappearance.colorh = colorappearance.colorh && p.colorappearance.colorh == other.colorappearance.colorh; colorappearance.surrsource = colorappearance.surrsource && p.colorappearance.surrsource == other.colorappearance.surrsource; colorappearance.gamut = colorappearance.gamut && p.colorappearance.gamut == other.colorappearance.gamut; - // colorappearance.badpix = colorappearance.badpix && p.colorappearance.badpix == other.colorappearance.badpix; +// colorappearance.badpix = colorappearance.badpix && p.colorappearance.badpix == other.colorappearance.badpix; colorappearance.datacie = colorappearance.datacie && p.colorappearance.datacie == other.colorappearance.datacie; colorappearance.tonecie = colorappearance.tonecie && p.colorappearance.tonecie == other.colorappearance.tonecie; - // colorappearance.sharpcie = colorappearance.sharpcie && p.colorappearance.sharpcie == other.colorappearance.sharpcie; + // colorappearance.sharpcie = colorappearance.sharpcie && p.colorappearance.sharpcie == other.colorappearance.sharpcie; colorappearance.curve = colorappearance.curve && p.colorappearance.curve == other.colorappearance.curve; colorappearance.curve3 = colorappearance.curve3 && p.colorappearance.curve3 == other.colorappearance.curve3; colorappearance.curve2 = colorappearance.curve2 && p.colorappearance.curve2 == other.colorappearance.curve2; @@ -644,14 +653,14 @@ void ParamsEdited::initFrom (const std::vector dirpyrDenoise.enhance = dirpyrDenoise.enhance && p.dirpyrDenoise.enhance == other.dirpyrDenoise.enhance; dirpyrDenoise.median = dirpyrDenoise.median && p.dirpyrDenoise.median == other.dirpyrDenoise.median; dirpyrDenoise.autochroma = dirpyrDenoise.autochroma && p.dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma; - // dirpyrDenoise.perform = dirpyrDenoise.perform && p.dirpyrDenoise.perform == other.dirpyrDenoise.perform; +// dirpyrDenoise.perform = dirpyrDenoise.perform && p.dirpyrDenoise.perform == other.dirpyrDenoise.perform; dirpyrDenoise.luma = dirpyrDenoise.luma && p.dirpyrDenoise.luma == other.dirpyrDenoise.luma; dirpyrDenoise.lcurve = dirpyrDenoise.lcurve && p.dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve; dirpyrDenoise.cccurve = dirpyrDenoise.cccurve && p.dirpyrDenoise.cccurve == other.dirpyrDenoise.cccurve; dirpyrDenoise.Ldetail = dirpyrDenoise.Ldetail && p.dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail; dirpyrDenoise.chroma = dirpyrDenoise.chroma && p.dirpyrDenoise.chroma == other.dirpyrDenoise.chroma; dirpyrDenoise.redchro = dirpyrDenoise.redchro && p.dirpyrDenoise.redchro == other.dirpyrDenoise.redchro; - dirpyrDenoise.bluechro = dirpyrDenoise.bluechro && p.dirpyrDenoise.bluechro == other.dirpyrDenoise.bluechro; + dirpyrDenoise.bluechro = dirpyrDenoise.bluechro && p.dirpyrDenoise.bluechro == other.dirpyrDenoise.bluechro; dirpyrDenoise.gamma = dirpyrDenoise.gamma && p.dirpyrDenoise.gamma == other.dirpyrDenoise.gamma; dirpyrDenoise.passes = dirpyrDenoise.passes && p.dirpyrDenoise.passes == other.dirpyrDenoise.passes; dirpyrDenoise.dmethod = dirpyrDenoise.dmethod && p.dirpyrDenoise.dmethod == other.dirpyrDenoise.dmethod; @@ -875,8 +884,8 @@ void ParamsEdited::initFrom (const std::vector wavelet.wavclCurve = wavelet.wavclCurve && p.wavelet.wavclCurve == other.wavelet.wavclCurve; wavelet.hhcurve = wavelet.hhcurve && p.wavelet.hhcurve == other.wavelet.hhcurve; wavelet.Chcurve = wavelet.Chcurve && p.wavelet.Chcurve == other.wavelet.Chcurve; - wavelet.skinprotect = wavelet.skinprotect && p.wavelet.skinprotect == other.wavelet.skinprotect; - // wavelet.enacont = wavelet.enacont && p.wavelet.enacont == other.wavelet.enacont; + wavelet.skinprotect = wavelet.skinprotect && p.wavelet.skinprotect == other.wavelet.skinprotect; + // wavelet.enacont = wavelet.enacont && p.wavelet.enacont == other.wavelet.enacont; wavelet.expcontrast = wavelet.expcontrast && p.wavelet.expcontrast == other.wavelet.expcontrast; wavelet.expchroma = wavelet.expchroma && p.wavelet.expchroma == other.wavelet.expchroma; wavelet.expedge = wavelet.expedge && p.wavelet.expedge == other.wavelet.expedge; @@ -884,22 +893,25 @@ void ParamsEdited::initFrom (const std::vector wavelet.expfinal = wavelet.expfinal && p.wavelet.expfinal == other.wavelet.expfinal; wavelet.exptoning = wavelet.exptoning && p.wavelet.exptoning == other.wavelet.exptoning; wavelet.expnoise = wavelet.expnoise && p.wavelet.expnoise == other.wavelet.expnoise; - + for(int i = 0; i < 9; i++) { wavelet.c[i] = wavelet.c[i] && p.wavelet.c[i] == other.wavelet.c[i]; } + for(int i = 0; i < 9; i++) { wavelet.ch[i] = wavelet.ch[i] && p.wavelet.ch[i] == other.wavelet.ch[i]; } dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; dirpyrequalizer.gamutlab = dirpyrequalizer.gamutlab && p.dirpyrequalizer.gamutlab == other.dirpyrequalizer.gamutlab; + for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i]; } + dirpyrequalizer.threshold = dirpyrequalizer.threshold && p.dirpyrequalizer.threshold == other.dirpyrequalizer.threshold; dirpyrequalizer.skinprotect = dirpyrequalizer.skinprotect && p.dirpyrequalizer.skinprotect == other.dirpyrequalizer.skinprotect; - // dirpyrequalizer.algo = dirpyrequalizer.algo && p.dirpyrequalizer.algo == other.dirpyrequalizer.algo; + // dirpyrequalizer.algo = dirpyrequalizer.algo && p.dirpyrequalizer.algo == other.dirpyrequalizer.algo; dirpyrequalizer.hueskin = dirpyrequalizer.hueskin && p.dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin; hsvequalizer.hcurve = hsvequalizer.hcurve && p.hsvequalizer.hcurve == other.hsvequalizer.hcurve; hsvequalizer.scurve = hsvequalizer.scurve && p.hsvequalizer.scurve == other.hsvequalizer.scurve; @@ -914,482 +926,1648 @@ void ParamsEdited::initFrom (const std::vector } } -void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods, bool forceSet) { +void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods, bool forceSet) +{ - bool dontforceSet = !forceSet; + bool dontforceSet = !forceSet; - if (toneCurve.curve) toEdit.toneCurve.curve = mods.toneCurve.curve; - if (toneCurve.curve2) toEdit.toneCurve.curve2 = mods.toneCurve.curve2; - if (toneCurve.curveMode) toEdit.toneCurve.curveMode = mods.toneCurve.curveMode; - if (toneCurve.curveMode2) toEdit.toneCurve.curveMode2 = mods.toneCurve.curveMode2; - if (toneCurve.brightness) toEdit.toneCurve.brightness = dontforceSet && options.baBehav[ADDSET_TC_BRIGHTNESS] ? toEdit.toneCurve.brightness + mods.toneCurve.brightness : mods.toneCurve.brightness; - if (toneCurve.black) toEdit.toneCurve.black = dontforceSet && options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; - if (toneCurve.contrast) toEdit.toneCurve.contrast = dontforceSet && options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; - if (toneCurve.saturation) toEdit.toneCurve.saturation = dontforceSet && options.baBehav[ADDSET_TC_SATURATION] ? toEdit.toneCurve.saturation + mods.toneCurve.saturation : mods.toneCurve.saturation; - if (toneCurve.shcompr) toEdit.toneCurve.shcompr = dontforceSet && options.baBehav[ADDSET_TC_SHCOMP] ? toEdit.toneCurve.shcompr + mods.toneCurve.shcompr : mods.toneCurve.shcompr; - if (toneCurve.autoexp) toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; - if (toneCurve.clip) toEdit.toneCurve.clip = mods.toneCurve.clip; - if (toneCurve.expcomp) toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; - if (toneCurve.hlcompr) toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr; - if (toneCurve.hlcomprthresh) toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh; - if (toneCurve.hrenabled) toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled; - if (toneCurve.method) toEdit.toneCurve.method = mods.toneCurve.method; - if (labCurve.lcurve) toEdit.labCurve.lcurve = mods.labCurve.lcurve; - if (labCurve.acurve) toEdit.labCurve.acurve = mods.labCurve.acurve; - if (labCurve.bcurve) toEdit.labCurve.bcurve = mods.labCurve.bcurve; - if (labCurve.cccurve) toEdit.labCurve.cccurve = mods.labCurve.cccurve; - if (labCurve.chcurve) toEdit.labCurve.chcurve = mods.labCurve.chcurve; - if (labCurve.lhcurve) toEdit.labCurve.lhcurve = mods.labCurve.lhcurve; - if (labCurve.hhcurve) toEdit.labCurve.hhcurve = mods.labCurve.hhcurve; - if (labCurve.lccurve) toEdit.labCurve.lccurve = mods.labCurve.lccurve; - if (labCurve.clcurve) toEdit.labCurve.clcurve = mods.labCurve.clcurve; - if (labCurve.brightness) toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; - if (labCurve.contrast) toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; - if (labCurve.chromaticity) toEdit.labCurve.chromaticity = dontforceSet && options.baBehav[ADDSET_LC_CHROMATICITY] ? toEdit.labCurve.chromaticity + mods.labCurve.chromaticity : mods.labCurve.chromaticity; - if (labCurve.avoidcolorshift) toEdit.labCurve.avoidcolorshift = mods.labCurve.avoidcolorshift; - if (labCurve.rstprotection) toEdit.labCurve.rstprotection = mods.labCurve.rstprotection; - if (labCurve.lcredsk) toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; + if (toneCurve.curve) { + toEdit.toneCurve.curve = mods.toneCurve.curve; + } - if (rgbCurves.lumamode) toEdit.rgbCurves.lumamode = mods.rgbCurves.lumamode; - if (rgbCurves.rcurve) toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; - if (rgbCurves.gcurve) toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; - if (rgbCurves.bcurve) toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; + if (toneCurve.curve2) { + toEdit.toneCurve.curve2 = mods.toneCurve.curve2; + } - if (colorToning.enabled) toEdit.colorToning.enabled = mods.colorToning.enabled; - if (colorToning.twocolor) toEdit.colorToning.twocolor = mods.colorToning.twocolor; - if (colorToning.opacityCurve) toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; - if (colorToning.colorCurve) toEdit.colorToning.colorCurve = mods.colorToning.colorCurve; - if (colorToning.enabled) toEdit.colorToning.enabled = mods.colorToning.enabled; - if (colorToning.opacityCurve) toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; - if (colorToning.satprotectionthreshold) toEdit.colorToning.satProtectionThreshold = dontforceSet && options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD] ? toEdit.colorToning.satProtectionThreshold + mods.colorToning.satProtectionThreshold : mods.colorToning.satProtectionThreshold; - if (colorToning.autosat) toEdit.colorToning.autosat = mods.colorToning.autosat; - if (colorToning.saturatedopacity) toEdit.colorToning.saturatedOpacity = dontforceSet && options.baBehav[ADDSET_COLORTONING_SATOPACITY] ? toEdit.colorToning.saturatedOpacity + mods.colorToning.saturatedOpacity : mods.colorToning.saturatedOpacity; - if (colorToning.strength) toEdit.colorToning.strength = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRENGTH] ? toEdit.colorToning.strength + mods.colorToning.strength: mods.colorToning.strength; + if (toneCurve.curveMode) { + toEdit.toneCurve.curveMode = mods.toneCurve.curveMode; + } - if (colorToning.shadowsColSat) toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; - if (colorToning.hlColSat) toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; - if (colorToning.balance) toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; - if (colorToning.clcurve) toEdit.colorToning.clcurve = mods.colorToning.clcurve; - if (colorToning.method) toEdit.colorToning.method = mods.colorToning.method; - if (colorToning.cl2curve) toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; - if (colorToning.lumamode) toEdit.colorToning.lumamode = mods.colorToning.lumamode; - if (colorToning.satlow) toEdit.colorToning.satlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.satlow + mods.colorToning.satlow : mods.colorToning.satlow; - if (colorToning.sathigh) toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; - if (colorToning.redlow) toEdit.colorToning.redlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redlow + mods.colorToning.redlow : mods.colorToning.redlow; - if (colorToning.greenlow) toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; - if (colorToning.bluelow) toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; - if (colorToning.redmed) toEdit.colorToning.redmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redmed + mods.colorToning.redmed : mods.colorToning.redmed; - if (colorToning.greenmed) toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; - if (colorToning.bluemed) toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; - if (colorToning.redhigh) toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; - if (colorToning.greenhigh) toEdit.colorToning.greenhigh= dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenhigh + mods.colorToning.greenhigh : mods.colorToning.greenhigh; - if (colorToning.bluehigh) toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; + if (toneCurve.curveMode2) { + toEdit.toneCurve.curveMode2 = mods.toneCurve.curveMode2; + } - if (sharpenEdge.enabled) toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; - if (sharpenEdge.passes) toEdit.sharpenEdge.passes = dontforceSet && options.baBehav[ADDSET_SHARPENEDGE_PASS] ? toEdit.sharpenEdge.passes + mods.sharpenEdge.passes : mods.sharpenEdge.passes; - if (sharpenEdge.amount) toEdit.sharpenEdge.amount = dontforceSet && options.baBehav[ADDSET_SHARPENEDGE_AMOUNT] ? toEdit.sharpenEdge.amount + mods.sharpenEdge.amount : mods.sharpenEdge.amount; - if (sharpenEdge.threechannels) toEdit.sharpenEdge.threechannels = mods.sharpenEdge.threechannels; - if (sharpenMicro.enabled) toEdit.sharpenMicro.enabled = mods.sharpenMicro.enabled; - if (sharpenMicro.matrix) toEdit.sharpenMicro.matrix = mods.sharpenMicro.matrix; - if (sharpenMicro.amount) toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; - if (sharpenMicro.uniformity) toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; - if (sharpening.enabled) toEdit.sharpening.enabled = mods.sharpening.enabled; - if (sharpening.radius) toEdit.sharpening.radius = mods.sharpening.radius; - if (sharpening.amount) toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; - if (sharpening.threshold) toEdit.sharpening.threshold = mods.sharpening.threshold; - if (sharpening.edgesonly) toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; - if (sharpening.edges_radius) toEdit.sharpening.edges_radius = mods.sharpening.edges_radius; - if (sharpening.edges_tolerance) toEdit.sharpening.edges_tolerance = mods.sharpening.edges_tolerance; - if (sharpening.halocontrol) toEdit.sharpening.halocontrol = mods.sharpening.halocontrol; - if (sharpening.halocontrol_amount) toEdit.sharpening.halocontrol_amount = mods.sharpening.halocontrol_amount; - if (sharpening.method) toEdit.sharpening.method = mods.sharpening.method; - if (sharpening.deconvamount) toEdit.sharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; - if (sharpening.deconvradius) toEdit.sharpening.deconvradius = mods.sharpening.deconvradius; - if (sharpening.deconviter) toEdit.sharpening.deconviter = mods.sharpening.deconviter; - if (sharpening.deconvdamping) toEdit.sharpening.deconvdamping = mods.sharpening.deconvdamping; - if (prsharpening.enabled) toEdit.prsharpening.enabled = mods.prsharpening.enabled; - if (prsharpening.radius) toEdit.prsharpening.radius = mods.prsharpening.radius; - if (prsharpening.amount) toEdit.prsharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.amount + mods.prsharpening.amount : mods.prsharpening.amount; - if (prsharpening.threshold) toEdit.prsharpening.threshold = mods.prsharpening.threshold; - if (prsharpening.edgesonly) toEdit.prsharpening.edgesonly = mods.prsharpening.edgesonly; - if (prsharpening.edges_radius) toEdit.prsharpening.edges_radius = mods.prsharpening.edges_radius; - if (prsharpening.edges_tolerance) toEdit.prsharpening.edges_tolerance = mods.prsharpening.edges_tolerance; - if (prsharpening.halocontrol) toEdit.prsharpening.halocontrol = mods.prsharpening.halocontrol; - if (prsharpening.halocontrol_amount) toEdit.prsharpening.halocontrol_amount = mods.prsharpening.halocontrol_amount; - if (prsharpening.method) toEdit.prsharpening.method = mods.prsharpening.method; - if (prsharpening.deconvamount) toEdit.prsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.deconvamount + mods.prsharpening.deconvamount : mods.prsharpening.deconvamount; - if (prsharpening.deconvradius) toEdit.prsharpening.deconvradius = mods.prsharpening.deconvradius; - if (prsharpening.deconviter) toEdit.prsharpening.deconviter = mods.prsharpening.deconviter; - if (prsharpening.deconvdamping) toEdit.prsharpening.deconvdamping = mods.prsharpening.deconvdamping; - if (vibrance.enabled) toEdit.vibrance.enabled = mods.vibrance.enabled; - if (vibrance.pastels) toEdit.vibrance.pastels = dontforceSet && options.baBehav[ADDSET_VIBRANCE_PASTELS] ? toEdit.vibrance.pastels + mods.vibrance.pastels : mods.vibrance.pastels; - if (vibrance.saturated) toEdit.vibrance.saturated = dontforceSet && options.baBehav[ADDSET_VIBRANCE_SATURATED] ? toEdit.vibrance.saturated + mods.vibrance.saturated : mods.vibrance.saturated; - if (vibrance.psthreshold) toEdit.vibrance.psthreshold = mods.vibrance.psthreshold; - if (vibrance.protectskins) toEdit.vibrance.protectskins = mods.vibrance.protectskins; - if (vibrance.avoidcolorshift) toEdit.vibrance.avoidcolorshift = mods.vibrance.avoidcolorshift; - if (vibrance.pastsattog) toEdit.vibrance.pastsattog = mods.vibrance.pastsattog; - if (vibrance.skintonescurve) toEdit.vibrance.skintonescurve = mods.vibrance.skintonescurve; + if (toneCurve.brightness) { + toEdit.toneCurve.brightness = dontforceSet && options.baBehav[ADDSET_TC_BRIGHTNESS] ? toEdit.toneCurve.brightness + mods.toneCurve.brightness : mods.toneCurve.brightness; + } - //if (colorBoost.amount) toEdit.colorBoost.amount = dontforceSet && options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; - //if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; - //if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; - //if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; - if (wb.method) toEdit.wb.method = mods.wb.method; - if (wb.equal) toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; - if (wb.green) toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; - if (wb.temperature) toEdit.wb.temperature = dontforceSet && options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; - //if (colorShift.a) toEdit.colorShift.a = dontforceSet && options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; - //if (colorShift.b) toEdit.colorShift.b = dontforceSet && options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; - //if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; - //if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; - //if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = dontforceSet && options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance; - //if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled; - //if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount; - - if (defringe.enabled) toEdit.defringe.enabled = mods.defringe.enabled; - if (defringe.radius) toEdit.defringe.radius = mods.defringe.radius; - if (defringe.threshold) toEdit.defringe.threshold = mods.defringe.threshold; - if (defringe.huecurve) toEdit.defringe.huecurve = mods.defringe.huecurve; - - if (colorappearance.curve) toEdit.colorappearance.curve = mods.colorappearance.curve; - if (colorappearance.curve2) toEdit.colorappearance.curve2 = mods.colorappearance.curve2; - if (colorappearance.curve3) toEdit.colorappearance.curve3 = mods.colorappearance.curve3; - if (colorappearance.curveMode) toEdit.colorappearance.curveMode = mods.colorappearance.curveMode; - if (colorappearance.curveMode2) toEdit.colorappearance.curveMode2 = mods.colorappearance.curveMode2; - if (colorappearance.curveMode3) toEdit.colorappearance.curveMode3 = mods.colorappearance.curveMode3; + if (toneCurve.black) { + toEdit.toneCurve.black = dontforceSet && options.baBehav[ADDSET_TC_BLACKLEVEL] ? toEdit.toneCurve.black + mods.toneCurve.black : mods.toneCurve.black; + } - if (colorappearance.enabled) toEdit.colorappearance.enabled = mods.colorappearance.enabled; - if (colorappearance.degree) toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree; - if (colorappearance.autodegree) toEdit.colorappearance.autodegree = mods.colorappearance.autodegree; - if (colorappearance.surround) toEdit.colorappearance.surround = mods.colorappearance.surround; - if (colorappearance.autoadapscen) toEdit.colorappearance.autoadapscen = mods.colorappearance.autoadapscen; - if (colorappearance.adapscen) toEdit.colorappearance.adapscen = mods.colorappearance.adapscen; - if (colorappearance.adaplum) toEdit.colorappearance.adaplum = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTVIEWING] ? toEdit.colorappearance.adaplum + mods.colorappearance.adaplum : mods.colorappearance.adaplum; - if (colorappearance.badpixsl) toEdit.colorappearance.badpixsl = dontforceSet && options.baBehav[ADDSET_CAT_BADPIX] ? toEdit.colorappearance.badpixsl + mods.colorappearance.badpixsl : mods.colorappearance.badpixsl; - if (colorappearance.wbmodel) toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel; - if (colorappearance.algo) toEdit.colorappearance.algo = mods.colorappearance.algo; + if (toneCurve.contrast) { + toEdit.toneCurve.contrast = dontforceSet && options.baBehav[ADDSET_TC_CONTRAST] ? toEdit.toneCurve.contrast + mods.toneCurve.contrast : mods.toneCurve.contrast; + } - if (colorappearance.jlight) toEdit.colorappearance.jlight = dontforceSet && options.baBehav[ADDSET_CAT_LIGHT] ? toEdit.colorappearance.jlight + mods.colorappearance.jlight : mods.colorappearance.jlight; - if (colorappearance.qbright) toEdit.colorappearance.qbright = dontforceSet && options.baBehav[ADDSET_CAT_BRIGHT] ? toEdit.colorappearance.qbright + mods.colorappearance.qbright : mods.colorappearance.qbright; - if (colorappearance.chroma) toEdit.colorappearance.chroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA] ? toEdit.colorappearance.chroma + mods.colorappearance.chroma : mods.colorappearance.chroma; - if (colorappearance.schroma) toEdit.colorappearance.schroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_S] ? toEdit.colorappearance.schroma + mods.colorappearance.schroma : mods.colorappearance.schroma; - if (colorappearance.mchroma) toEdit.colorappearance.mchroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_M] ? toEdit.colorappearance.mchroma + mods.colorappearance.mchroma : mods.colorappearance.mchroma; - if (colorappearance.contrast) toEdit.colorappearance.contrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST] ? toEdit.colorappearance.contrast + mods.colorappearance.contrast : mods.colorappearance.contrast; - if (colorappearance.qcontrast) toEdit.colorappearance.qcontrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST_Q] ? toEdit.colorappearance.qcontrast + mods.colorappearance.qcontrast : mods.colorappearance.qcontrast; - if (colorappearance.colorh) toEdit.colorappearance.colorh = dontforceSet && options.baBehav[ADDSET_CAT_HUE] ? toEdit.colorappearance.colorh + mods.colorappearance.colorh : mods.colorappearance.colorh; - if (colorappearance.rstprotection) toEdit.colorappearance.rstprotection= dontforceSet && options.baBehav[ADDSET_CAT_RSTPRO] ? toEdit.colorappearance.rstprotection + mods.colorappearance.rstprotection : mods.colorappearance.rstprotection; - if (colorappearance.surrsource) toEdit.colorappearance.surrsource = mods.colorappearance.surrsource; - if (colorappearance.gamut) toEdit.colorappearance.gamut = mods.colorappearance.gamut; -// if (colorappearance.badpix) toEdit.colorappearance.badpix = mods.colorappearance.badpix; - if (colorappearance.datacie) toEdit.colorappearance.datacie = mods.colorappearance.datacie; - if (colorappearance.tonecie) toEdit.colorappearance.tonecie = mods.colorappearance.tonecie; -// if (colorappearance.sharpcie) toEdit.colorappearance.sharpcie = mods.colorappearance.sharpcie; - if (impulseDenoise.enabled) toEdit.impulseDenoise.enabled = mods.impulseDenoise.enabled; - if (impulseDenoise.thresh) toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh; + if (toneCurve.saturation) { + toEdit.toneCurve.saturation = dontforceSet && options.baBehav[ADDSET_TC_SATURATION] ? toEdit.toneCurve.saturation + mods.toneCurve.saturation : mods.toneCurve.saturation; + } - if (dirpyrDenoise.enabled) toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; - if (dirpyrDenoise.enhance) toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; - if (dirpyrDenoise.median) toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; - if (dirpyrDenoise.autochroma) toEdit.dirpyrDenoise.autochroma = mods.dirpyrDenoise.autochroma; - if (dirpyrDenoise.luma) toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; - if (dirpyrDenoise.lcurve) toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve; - if (dirpyrDenoise.cccurve) toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; - if (dirpyrDenoise.Ldetail) toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail; - if (dirpyrDenoise.chroma) toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma; - if (dirpyrDenoise.redchro) toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro; - if (dirpyrDenoise.bluechro) toEdit.dirpyrDenoise.bluechro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE] ? toEdit.dirpyrDenoise.bluechro + mods.dirpyrDenoise.bluechro : mods.dirpyrDenoise.bluechro; - if (dirpyrDenoise.gamma) toEdit.dirpyrDenoise.gamma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_GAMMA] ? toEdit.dirpyrDenoise.gamma + mods.dirpyrDenoise.gamma : mods.dirpyrDenoise.gamma; - if (dirpyrDenoise.passes) toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes; -// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform; - if (dirpyrDenoise.dmethod) toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod; - if (dirpyrDenoise.Lmethod) toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; - if (dirpyrDenoise.Cmethod) toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; - if (dirpyrDenoise.C2method) toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; - if (dirpyrDenoise.smethod) toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod; - if (dirpyrDenoise.medmethod) toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod; - if (dirpyrDenoise.methodmed) toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed; - if (dirpyrDenoise.rgbmethod) toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod; + if (toneCurve.shcompr) { + toEdit.toneCurve.shcompr = dontforceSet && options.baBehav[ADDSET_TC_SHCOMP] ? toEdit.toneCurve.shcompr + mods.toneCurve.shcompr : mods.toneCurve.shcompr; + } - if (epd.enabled) toEdit.epd.enabled = mods.epd.enabled; - if (epd.strength) toEdit.epd.strength = mods.epd.strength; - if (epd.gamma) toEdit.epd.gamma = mods.epd.gamma; - if (epd.edgeStopping) toEdit.epd.edgeStopping = mods.epd.edgeStopping; - if (epd.scale) toEdit.epd.scale = mods.epd.scale; - if (epd.reweightingIterates) toEdit.epd.reweightingIterates = mods.epd.reweightingIterates; + if (toneCurve.autoexp) { + toEdit.toneCurve.autoexp = mods.toneCurve.autoexp; + } - if (sh.enabled) toEdit.sh.enabled = mods.sh.enabled; - if (sh.hq) toEdit.sh.hq = mods.sh.hq; - if (sh.highlights) toEdit.sh.highlights = dontforceSet && options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; - if (sh.htonalwidth) toEdit.sh.htonalwidth = mods.sh.htonalwidth; - if (sh.shadows) toEdit.sh.shadows = dontforceSet && options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; - if (sh.stonalwidth) toEdit.sh.stonalwidth = mods.sh.stonalwidth; - if (sh.localcontrast) toEdit.sh.localcontrast = dontforceSet && options.baBehav[ADDSET_SH_LOCALCONTRAST] ? toEdit.sh.localcontrast + mods.sh.localcontrast : mods.sh.localcontrast; - if (sh.radius) toEdit.sh.radius = mods.sh.radius; - if (crop.enabled) toEdit.crop.enabled = mods.crop.enabled; - if (crop.x) toEdit.crop.x = mods.crop.x; - if (crop.y) toEdit.crop.y = mods.crop.y; - if (crop.w) toEdit.crop.w = mods.crop.w; - if (crop.h) toEdit.crop.h = mods.crop.h; - if (crop.fixratio) toEdit.crop.fixratio = mods.crop.fixratio; - if (crop.ratio) toEdit.crop.ratio = mods.crop.ratio; - if (crop.orientation) toEdit.crop.orientation = mods.crop.orientation; - if (crop.guide) toEdit.crop.guide = mods.crop.guide; - if (coarse.rotate) toEdit.coarse.rotate = mods.coarse.rotate; - if (coarse.hflip) toEdit.coarse.hflip = mods.coarse.hflip; - if (coarse.vflip) toEdit.coarse.vflip = mods.coarse.vflip; - if (commonTrans.autofill) toEdit.commonTrans.autofill = mods.commonTrans.autofill; - if (rotate.degree) toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; - if (distortion.amount) toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; - if (lensProf.lcpFile) toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; - if (lensProf.useDist) toEdit.lensProf.useDist = mods.lensProf.useDist; - if (lensProf.useVign) toEdit.lensProf.useVign = mods.lensProf.useVign; - if (lensProf.useCA) toEdit.lensProf.useCA = mods.lensProf.useCA; + if (toneCurve.clip) { + toEdit.toneCurve.clip = mods.toneCurve.clip; + } - if (perspective.horizontal) toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal; - if (perspective.vertical) toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; - if (gradient.enabled) toEdit.gradient.enabled = mods.gradient.enabled; - if (gradient.degree) toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree; - if (gradient.feather) toEdit.gradient.feather = mods.gradient.feather; - if (gradient.strength) toEdit.gradient.strength = mods.gradient.strength; - if (gradient.centerX) toEdit.gradient.centerX = mods.gradient.centerX; - if (gradient.centerY) toEdit.gradient.centerY = mods.gradient.centerY; - if (pcvignette.enabled) toEdit.pcvignette.enabled = mods.pcvignette.enabled; - if (pcvignette.strength) toEdit.pcvignette.strength = mods.pcvignette.strength; - if (pcvignette.feather) toEdit.pcvignette.feather = mods.pcvignette.feather; - if (pcvignette.roundness) toEdit.pcvignette.roundness = mods.pcvignette.roundness; - if (cacorrection.red) toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; - if (cacorrection.blue) toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; - if (vignetting.amount) toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; - if (vignetting.radius) toEdit.vignetting.radius = mods.vignetting.radius; - if (vignetting.strength) toEdit.vignetting.strength = mods.vignetting.strength; - if (vignetting.centerX) toEdit.vignetting.centerX = mods.vignetting.centerX; - if (vignetting.centerY) toEdit.vignetting.centerY = mods.vignetting.centerY; - for (int i=0; i<3; i++) { - if (chmixer.red[i]) toEdit.chmixer.red[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.red[i] + mods.chmixer.red[i] : mods.chmixer.red[i]; - if (chmixer.green[i]) toEdit.chmixer.green[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.green[i] + mods.chmixer.green[i] : mods.chmixer.green[i]; - if (chmixer.blue[i]) toEdit.chmixer.blue[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.blue[i] + mods.chmixer.blue[i] : mods.chmixer.blue[i]; - } - if (blackwhite.enabled) toEdit.blackwhite.enabled = mods.blackwhite.enabled; - if (blackwhite.method) toEdit.blackwhite.method = mods.blackwhite.method; - if (blackwhite.luminanceCurve) toEdit.blackwhite.luminanceCurve = mods.blackwhite.luminanceCurve; - if (blackwhite.autoc) toEdit.blackwhite.autoc = mods.blackwhite.autoc; - if (blackwhite.setting) toEdit.blackwhite.setting = mods.blackwhite.setting; - if (blackwhite.enabledcc) toEdit.blackwhite.enabledcc = mods.blackwhite.enabledcc; - if (blackwhite.filter) toEdit.blackwhite.filter = mods.blackwhite.filter; - if (blackwhite.mixerRed) toEdit.blackwhite.mixerRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerRed + mods.blackwhite.mixerRed : mods.blackwhite.mixerRed; - if (blackwhite.mixerOrange) toEdit.blackwhite.mixerOrange = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerOrange + mods.blackwhite.mixerOrange : mods.blackwhite.mixerOrange; - if (blackwhite.mixerYellow) toEdit.blackwhite.mixerYellow = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerYellow + mods.blackwhite.mixerYellow : mods.blackwhite.mixerYellow; - if (blackwhite.mixerGreen) toEdit.blackwhite.mixerGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerGreen + mods.blackwhite.mixerGreen : mods.blackwhite.mixerGreen; - if (blackwhite.mixerCyan) toEdit.blackwhite.mixerCyan = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerCyan + mods.blackwhite.mixerCyan : mods.blackwhite.mixerCyan; - if (blackwhite.mixerBlue) toEdit.blackwhite.mixerBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerBlue + mods.blackwhite.mixerBlue : mods.blackwhite.mixerBlue; - if (blackwhite.mixerMagenta) toEdit.blackwhite.mixerMagenta = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerMagenta + mods.blackwhite.mixerMagenta : mods.blackwhite.mixerMagenta; - if (blackwhite.mixerPurple) toEdit.blackwhite.mixerPurple = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerPurple + mods.blackwhite.mixerPurple : mods.blackwhite.mixerPurple; - if (blackwhite.gammaRed) toEdit.blackwhite.gammaRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaRed + mods.blackwhite.gammaRed : mods.blackwhite.gammaRed; - if (blackwhite.gammaGreen) toEdit.blackwhite.gammaGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaGreen + mods.blackwhite.gammaGreen : mods.blackwhite.gammaGreen; - if (blackwhite.gammaBlue) toEdit.blackwhite.gammaBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaBlue + mods.blackwhite.gammaBlue : mods.blackwhite.gammaBlue; - if (blackwhite.beforeCurve) toEdit.blackwhite.beforeCurve = mods.blackwhite.beforeCurve; - if (blackwhite.beforeCurveMode) toEdit.blackwhite.beforeCurveMode = mods.blackwhite.beforeCurveMode; - if (blackwhite.afterCurve) toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve; - if (blackwhite.afterCurveMode) toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode; - if (blackwhite.algo) toEdit.blackwhite.algo = mods.blackwhite.algo; - - if (resize.scale) toEdit.resize.scale = mods.resize.scale; - if (resize.appliesTo) toEdit.resize.appliesTo = mods.resize.appliesTo; - if (resize.method) toEdit.resize.method = mods.resize.method; - if (resize.dataspec) toEdit.resize.dataspec = mods.resize.dataspec; - if (resize.width) toEdit.resize.width = mods.resize.width; - if (resize.height) toEdit.resize.height = mods.resize.height; - if (resize.enabled) toEdit.resize.enabled = mods.resize.enabled; - if (icm.input) toEdit.icm.input = mods.icm.input; - if (icm.toneCurve) toEdit.icm.toneCurve = mods.icm.toneCurve; - if (icm.applyLookTable) toEdit.icm.applyLookTable = mods.icm.applyLookTable; - if (icm.applyBaselineExposureOffset) toEdit.icm.applyBaselineExposureOffset = mods.icm.applyBaselineExposureOffset; - if (icm.applyHueSatMap) toEdit.icm.applyHueSatMap = mods.icm.applyHueSatMap; - if (icm.blendCMSMatrix) toEdit.icm.blendCMSMatrix = mods.icm.blendCMSMatrix; - if (icm.dcpIlluminant) toEdit.icm.dcpIlluminant = mods.icm.dcpIlluminant; - if (icm.working) toEdit.icm.working = mods.icm.working; - if (icm.output) toEdit.icm.output = mods.icm.output; - //if (icm.gampos) toEdit.icm.gampos = mods.icm.gampos; - //if (icm.slpos) toEdit.icm.slpos = mods.icm.slpos; - if (icm.gampos) toEdit.icm.gampos = dontforceSet && options.baBehav[ADDSET_FREE_OUPUT_GAMMA] ? toEdit.icm.gampos + mods.icm.gampos : mods.icm.gampos; - if (icm.slpos) toEdit.icm.slpos = dontforceSet && options.baBehav[ADDSET_FREE_OUTPUT_SLOPE] ? toEdit.icm.slpos + mods.icm.slpos : mods.icm.slpos; - if (icm.gamma) toEdit.icm.gamma = mods.icm.gamma; - if (icm.freegamma) toEdit.icm.freegamma = mods.icm.freegamma; - if (raw.bayersensor.method) toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; - if (raw.bayersensor.ccSteps) toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; - if (raw.bayersensor.exBlack0) toEdit.raw.bayersensor.black0 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black0 + mods.raw.bayersensor.black0 : mods.raw.bayersensor.black0; - if (raw.bayersensor.exBlack1) toEdit.raw.bayersensor.black1 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black1 + mods.raw.bayersensor.black1 : mods.raw.bayersensor.black1; - if (raw.bayersensor.exBlack2) toEdit.raw.bayersensor.black2 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black2 + mods.raw.bayersensor.black2 : mods.raw.bayersensor.black2; - if (raw.bayersensor.exBlack3) toEdit.raw.bayersensor.black3 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black3 + mods.raw.bayersensor.black3 : mods.raw.bayersensor.black3; - if (raw.bayersensor.exTwoGreen) toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; - if (raw.bayersensor.dcbIterations) toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; - if (raw.bayersensor.dcbEnhance) toEdit.raw.bayersensor.dcb_enhance = mods.raw.bayersensor.dcb_enhance; - if (raw.bayersensor.lmmseIterations) toEdit.raw.bayersensor.lmmse_iterations = mods.raw.bayersensor.lmmse_iterations; - //if (raw.bayersensor.allEnhance) toEdit.raw.bayersensor.all_enhance = mods.raw.bayersensor.all_enhance; - if (raw.bayersensor.greenEq) toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; - if (raw.bayersensor.linenoise) toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise; + if (toneCurve.expcomp) { + toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp; + } - if (raw.xtranssensor.method) toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; - if (raw.xtranssensor.ccSteps) toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; - if (raw.xtranssensor.exBlackRed) toEdit.raw.xtranssensor.blackred = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackred + mods.raw.xtranssensor.blackred : mods.raw.xtranssensor.blackred; - if (raw.xtranssensor.exBlackGreen) toEdit.raw.xtranssensor.blackgreen = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackgreen + mods.raw.xtranssensor.blackgreen : mods.raw.xtranssensor.blackgreen; - if (raw.xtranssensor.exBlackBlue) toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; + if (toneCurve.hlcompr) { + toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr; + } - if (raw.caCorrection) toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; - if (raw.caRed) toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; - if (raw.caBlue) toEdit.raw.cablue = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cablue + mods.raw.cablue : mods.raw.cablue; - if (raw.exPos) toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos; - if (raw.exPreser) toEdit.raw.preser = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_PRESER] ? toEdit.raw.preser + mods.raw.preser : mods.raw.preser; + if (toneCurve.hlcomprthresh) { + toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh; + } - if (raw.hotPixelFilter) toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter; - if (raw.deadPixelFilter) toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter; - if (raw.hotDeadPixelThresh) toEdit.raw.hotdeadpix_thresh = mods.raw.hotdeadpix_thresh; - if (raw.darkFrame) toEdit.raw.dark_frame = mods.raw.dark_frame; - if (raw.dfAuto) toEdit.raw.df_autoselect = mods.raw.df_autoselect; + if (toneCurve.hrenabled) { + toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled; + } - if (raw.ff_file) toEdit.raw.ff_file = mods.raw.ff_file; - if (raw.ff_AutoSelect) toEdit.raw.ff_AutoSelect = mods.raw.ff_AutoSelect; - if (raw.ff_BlurRadius) toEdit.raw.ff_BlurRadius = mods.raw.ff_BlurRadius; - if (raw.ff_BlurType) toEdit.raw.ff_BlurType = mods.raw.ff_BlurType; - if (raw.ff_AutoClipControl) toEdit.raw.ff_AutoClipControl = mods.raw.ff_AutoClipControl; - if (raw.ff_clipControl) toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; - if (wavelet.enabled) toEdit.wavelet.enabled = mods.wavelet.enabled; - if (wavelet.strength) toEdit.wavelet.strength = mods.wavelet.strength; - if (wavelet.balance) toEdit.wavelet.balance = mods.wavelet.balance; - if (wavelet.iter) toEdit.wavelet.iter = mods.wavelet.iter; - if (wavelet.median) toEdit.wavelet.median = mods.wavelet.median; - if (wavelet.medianlev) toEdit.wavelet.medianlev = mods.wavelet.medianlev; - if (wavelet.linkedg) toEdit.wavelet.linkedg = mods.wavelet.linkedg; - if (wavelet.cbenab) toEdit.wavelet.cbenab = mods.wavelet.cbenab; - if (wavelet.greenhigh) toEdit.wavelet.greenhigh = mods.wavelet.greenhigh; - if (wavelet.bluehigh) toEdit.wavelet.bluehigh = mods.wavelet.bluehigh; - if (wavelet.greenmed) toEdit.wavelet.greenmed = mods.wavelet.greenmed; - if (wavelet.bluemed) toEdit.wavelet.bluemed = mods.wavelet.bluemed; - if (wavelet.greenlow) toEdit.wavelet.greenlow = mods.wavelet.greenlow; - if (wavelet.bluelow) toEdit.wavelet.bluelow = mods.wavelet.bluelow; - if (wavelet.lipst) toEdit.wavelet.lipst = mods.wavelet.lipst; - if (wavelet.Medgreinf) toEdit.wavelet.Medgreinf = mods.wavelet.Medgreinf; - if (wavelet.avoid) toEdit.wavelet.avoid = mods.wavelet.avoid; - if (wavelet.tmr) toEdit.wavelet.tmr = mods.wavelet.tmr; - if (wavelet.Lmethod) toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; - if (wavelet.CLmethod) toEdit.wavelet.CLmethod = mods.wavelet.CLmethod; - if (wavelet.Backmethod) toEdit.wavelet.Backmethod = mods.wavelet.Backmethod; - if (wavelet.Tilesmethod) toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; - if (wavelet.daubcoeffmethod) toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; - if (wavelet.CHmethod) toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; - if (wavelet.CHSLmethod) toEdit.wavelet.CHSLmethod = mods.wavelet.CHSLmethod; - if (wavelet.EDmethod) toEdit.wavelet.EDmethod = mods.wavelet.EDmethod; - if (wavelet.NPmethod) toEdit.wavelet.NPmethod = mods.wavelet.NPmethod; - if (wavelet.BAmethod) toEdit.wavelet.BAmethod = mods.wavelet.BAmethod; - if (wavelet.TMmethod) toEdit.wavelet.TMmethod = mods.wavelet.TMmethod; - if (wavelet.HSmethod) toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; - if (wavelet.Dirmethod) toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; - if (wavelet.edgthresh) toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; - if (wavelet.sky) toEdit.wavelet.sky= dontforceSet && options.baBehav[ADDSET_WA_SKYPROTECT] ? toEdit.wavelet.sky + mods.wavelet.sky : mods.wavelet.sky; - if (wavelet.thr)toEdit.wavelet.thr= dontforceSet && options.baBehav[ADDSET_WA_THRR] ? toEdit.wavelet.thr + mods.wavelet.thr : mods.wavelet.thr; - if (wavelet.thrH)toEdit.wavelet.thrH= dontforceSet && options.baBehav[ADDSET_WA_THRRH] ? toEdit.wavelet.thrH + mods.wavelet.thrH : mods.wavelet.thrH; - if (wavelet.sup) toEdit.wavelet.sup = mods.wavelet.sup; - if (wavelet.hllev) toEdit.wavelet.hllev = mods.wavelet.hllev; - if (wavelet.bllev) toEdit.wavelet.bllev = mods.wavelet.bllev; - if (wavelet.edgcont) toEdit.wavelet.edgcont = mods.wavelet.edgcont; - if (wavelet.level0noise) toEdit.wavelet.level0noise = mods.wavelet.level0noise; - if (wavelet.level1noise) toEdit.wavelet.level1noise = mods.wavelet.level1noise; - if (wavelet.level2noise) toEdit.wavelet.level2noise = mods.wavelet.level2noise; - if (wavelet.level3noise) toEdit.wavelet.level3noise = mods.wavelet.level3noise; - if (wavelet.pastlev) toEdit.wavelet.pastlev = mods.wavelet.pastlev; - if (wavelet.satlev) toEdit.wavelet.satlev = mods.wavelet.satlev; - if (wavelet.ccwcurve) toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; - if (wavelet.opacityCurveRG) toEdit.wavelet.opacityCurveRG = mods.wavelet.opacityCurveRG; - if (wavelet.opacityCurveBY) toEdit.wavelet.opacityCurveBY = mods.wavelet.opacityCurveBY; - if (wavelet.opacityCurveW) toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; - if (wavelet.opacityCurveWL) toEdit.wavelet.opacityCurveWL = mods.wavelet.opacityCurveWL; - if (wavelet.hhcurve) toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; - if (wavelet.Chcurve) toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; - if (wavelet.wavclCurve) toEdit.wavelet.wavclCurve = mods.wavelet.wavclCurve; - //if (wavelet.enacont) toEdit.wavelet.enacont = mods.wavelet.enacont; - if (wavelet.expcontrast) toEdit.wavelet.expcontrast = mods.wavelet.expcontrast; - if (wavelet.expchroma) toEdit.wavelet.expchroma = mods.wavelet.expchroma; - if (wavelet.expedge) toEdit.wavelet.expedge = mods.wavelet.expedge; - if (wavelet.expresid) toEdit.wavelet.expresid = mods.wavelet.expresid; - if (wavelet.expfinal) toEdit.wavelet.expfinal = mods.wavelet.expfinal; - if (wavelet.exptoning) toEdit.wavelet.exptoning = mods.wavelet.exptoning; - if (wavelet.expnoise) toEdit.wavelet.expnoise = mods.wavelet.expnoise; - - for(int i = 0; i < 9; i++) { - if(wavelet.c[i]) toEdit.wavelet.c[i] = dontforceSet && options.baBehav[ADDSET_WA] ? toEdit.wavelet.c[i] + mods.wavelet.c[i] : mods.wavelet.c[i]; - } - for(int i = 0; i < 9; i++) { - if(wavelet.ch[i]) toEdit.wavelet.ch[i] = dontforceSet && options.baBehav[ADDSET_WA] ? toEdit.wavelet.ch[i] + mods.wavelet.ch[i] : mods.wavelet.ch[i]; - } - if (wavelet.skinprotect)toEdit.wavelet.skinprotect= dontforceSet && options.baBehav[ADDSET_WA_SKINPROTECT] ? toEdit.wavelet.skinprotect + mods.wavelet.skinprotect : mods.wavelet.skinprotect; - if (wavelet.hueskin) toEdit.wavelet.hueskin = mods.wavelet.hueskin; - if (wavelet.hueskin2) toEdit.wavelet.hueskin2 = mods.wavelet.hueskin2; - if (wavelet.edgesensi) toEdit.wavelet.edgesensi = mods.wavelet.edgesensi; - if (wavelet.edgeampli) toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; - if (wavelet.resconH)toEdit.wavelet.resconH= dontforceSet && options.baBehav[ADDSET_WA_RESCONH] ? toEdit.wavelet.resconH + mods.wavelet.resconH : mods.wavelet.resconH; - if (wavelet.reschro)toEdit.wavelet.reschro= dontforceSet && options.baBehav[ADDSET_WA_RESCHRO] ? toEdit.wavelet.reschro + mods.wavelet.reschro : mods.wavelet.reschro; - if (wavelet.tmrs)toEdit.wavelet.tmrs= dontforceSet && options.baBehav[ADDSET_WA_TMRS] ? toEdit.wavelet.tmrs + mods.wavelet.tmrs : mods.wavelet.tmrs; - if (wavelet.gamma)toEdit.wavelet.gamma= dontforceSet && options.baBehav[ADDSET_WA_GAMMA] ? toEdit.wavelet.gamma + mods.wavelet.gamma : mods.wavelet.gamma; - if (wavelet.rescon)toEdit.wavelet.rescon= dontforceSet && options.baBehav[ADDSET_WA_RESCON] ? toEdit.wavelet.rescon + mods.wavelet.rescon : mods.wavelet.rescon; - if (wavelet.thres)toEdit.wavelet.thres= dontforceSet && options.baBehav[ADDSET_WA_THRES] ? toEdit.wavelet.thres + mods.wavelet.thres : mods.wavelet.thres; - if (wavelet.threshold)toEdit.wavelet.threshold= dontforceSet && options.baBehav[ADDSET_WA_THRESHOLD] ? toEdit.wavelet.threshold + mods.wavelet.threshold : mods.wavelet.threshold; - if (wavelet.threshold2)toEdit.wavelet.threshold2= dontforceSet && options.baBehav[ADDSET_WA_THRESHOLD2] ? toEdit.wavelet.threshold2 + mods.wavelet.threshold2 : mods.wavelet.threshold2; - if (wavelet.edgedetect)toEdit.wavelet.edgedetect= dontforceSet && options.baBehav[ADDSET_WA_EDGEDETECT] ? toEdit.wavelet.edgedetect + mods.wavelet.edgedetect : mods.wavelet.edgedetect; - if (wavelet.edgedetectthr)toEdit.wavelet.edgedetectthr= dontforceSet && options.baBehav[ADDSET_WA_EDGEDETECTTHR] ? toEdit.wavelet.edgedetectthr + mods.wavelet.edgedetectthr : mods.wavelet.edgedetectthr; - if (wavelet.edgedetectthr2)toEdit.wavelet.edgedetectthr2= dontforceSet && options.baBehav[ADDSET_WA_EDGEDETECTTHR2] ? toEdit.wavelet.edgedetectthr2 + mods.wavelet.edgedetectthr2 : mods.wavelet.edgedetectthr2; - if (wavelet.chro)toEdit.wavelet.chro= dontforceSet && options.baBehav[ADDSET_WA_CHRO] ? toEdit.wavelet.chro + mods.wavelet.chro : mods.wavelet.chro; - if (wavelet.chroma)toEdit.wavelet.chroma= dontforceSet && options.baBehav[ADDSET_WA_CHROMA] ? toEdit.wavelet.chroma + mods.wavelet.chroma : mods.wavelet.chroma; - if (wavelet.contrast)toEdit.wavelet.contrast= dontforceSet && options.baBehav[ADDSET_WA_CONTRAST] ? toEdit.wavelet.contrast + mods.wavelet.contrast : mods.wavelet.contrast; - if (wavelet.edgrad)toEdit.wavelet.edgrad= dontforceSet && options.baBehav[ADDSET_WA_EDGRAD] ? toEdit.wavelet.edgrad + mods.wavelet.edgrad : mods.wavelet.edgrad; - if (wavelet.edgval)toEdit.wavelet.edgval= dontforceSet && options.baBehav[ADDSET_WA_EDGVAL] ? toEdit.wavelet.edgval + mods.wavelet.edgval : mods.wavelet.edgval; - if (wavelet.strength)toEdit.wavelet.strength= dontforceSet && options.baBehav[ADDSET_WA_STRENGTH] ? toEdit.wavelet.strength + mods.wavelet.strength : mods.wavelet.strength; + if (toneCurve.method) { + toEdit.toneCurve.method = mods.toneCurve.method; + } + + if (labCurve.lcurve) { + toEdit.labCurve.lcurve = mods.labCurve.lcurve; + } + + if (labCurve.acurve) { + toEdit.labCurve.acurve = mods.labCurve.acurve; + } + + if (labCurve.bcurve) { + toEdit.labCurve.bcurve = mods.labCurve.bcurve; + } + + if (labCurve.cccurve) { + toEdit.labCurve.cccurve = mods.labCurve.cccurve; + } + + if (labCurve.chcurve) { + toEdit.labCurve.chcurve = mods.labCurve.chcurve; + } + + if (labCurve.lhcurve) { + toEdit.labCurve.lhcurve = mods.labCurve.lhcurve; + } + + if (labCurve.hhcurve) { + toEdit.labCurve.hhcurve = mods.labCurve.hhcurve; + } + + if (labCurve.lccurve) { + toEdit.labCurve.lccurve = mods.labCurve.lccurve; + } + + if (labCurve.clcurve) { + toEdit.labCurve.clcurve = mods.labCurve.clcurve; + } + + if (labCurve.brightness) { + toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; + } + + if (labCurve.contrast) { + toEdit.labCurve.contrast = dontforceSet && options.baBehav[ADDSET_LC_CONTRAST] ? toEdit.labCurve.contrast + mods.labCurve.contrast : mods.labCurve.contrast; + } + + if (labCurve.chromaticity) { + toEdit.labCurve.chromaticity = dontforceSet && options.baBehav[ADDSET_LC_CHROMATICITY] ? toEdit.labCurve.chromaticity + mods.labCurve.chromaticity : mods.labCurve.chromaticity; + } + + if (labCurve.avoidcolorshift) { + toEdit.labCurve.avoidcolorshift = mods.labCurve.avoidcolorshift; + } + + if (labCurve.rstprotection) { + toEdit.labCurve.rstprotection = mods.labCurve.rstprotection; + } + + if (labCurve.lcredsk) { + toEdit.labCurve.lcredsk = mods.labCurve.lcredsk; + } + + if (rgbCurves.lumamode) { + toEdit.rgbCurves.lumamode = mods.rgbCurves.lumamode; + } + + if (rgbCurves.rcurve) { + toEdit.rgbCurves.rcurve = mods.rgbCurves.rcurve; + } + + if (rgbCurves.gcurve) { + toEdit.rgbCurves.gcurve = mods.rgbCurves.gcurve; + } + + if (rgbCurves.bcurve) { + toEdit.rgbCurves.bcurve = mods.rgbCurves.bcurve; + } + + if (colorToning.enabled) { + toEdit.colorToning.enabled = mods.colorToning.enabled; + } + + if (colorToning.twocolor) { + toEdit.colorToning.twocolor = mods.colorToning.twocolor; + } + + if (colorToning.opacityCurve) { + toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + } + + if (colorToning.colorCurve) { + toEdit.colorToning.colorCurve = mods.colorToning.colorCurve; + } + + if (colorToning.enabled) { + toEdit.colorToning.enabled = mods.colorToning.enabled; + } + + if (colorToning.opacityCurve) { + toEdit.colorToning.opacityCurve = mods.colorToning.opacityCurve; + } + + if (colorToning.satprotectionthreshold) { + toEdit.colorToning.satProtectionThreshold = dontforceSet && options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD] ? toEdit.colorToning.satProtectionThreshold + mods.colorToning.satProtectionThreshold : mods.colorToning.satProtectionThreshold; + } + + if (colorToning.autosat) { + toEdit.colorToning.autosat = mods.colorToning.autosat; + } + + if (colorToning.saturatedopacity) { + toEdit.colorToning.saturatedOpacity = dontforceSet && options.baBehav[ADDSET_COLORTONING_SATOPACITY] ? toEdit.colorToning.saturatedOpacity + mods.colorToning.saturatedOpacity : mods.colorToning.saturatedOpacity; + } + + if (colorToning.strength) { + toEdit.colorToning.strength = dontforceSet && options.baBehav[ADDSET_COLORTONING_STRENGTH] ? toEdit.colorToning.strength + mods.colorToning.strength : mods.colorToning.strength; + } + + if (colorToning.shadowsColSat) { + toEdit.colorToning.shadowsColSat = mods.colorToning.shadowsColSat; + } + + if (colorToning.hlColSat) { + toEdit.colorToning.hlColSat = mods.colorToning.hlColSat; + } + + if (colorToning.balance) { + toEdit.colorToning.balance = dontforceSet && options.baBehav[ADDSET_COLORTONING_BALANCE] ? toEdit.colorToning.balance + mods.colorToning.balance : mods.colorToning.balance; + } + + if (colorToning.clcurve) { + toEdit.colorToning.clcurve = mods.colorToning.clcurve; + } + + if (colorToning.method) { + toEdit.colorToning.method = mods.colorToning.method; + } + + if (colorToning.cl2curve) { + toEdit.colorToning.cl2curve = mods.colorToning.cl2curve; + } + + if (colorToning.lumamode) { + toEdit.colorToning.lumamode = mods.colorToning.lumamode; + } + + if (colorToning.satlow) { + toEdit.colorToning.satlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.satlow + mods.colorToning.satlow : mods.colorToning.satlow; + } + + if (colorToning.sathigh) { + toEdit.colorToning.sathigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.sathigh + mods.colorToning.sathigh : mods.colorToning.sathigh; + } + + if (colorToning.redlow) { + toEdit.colorToning.redlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redlow + mods.colorToning.redlow : mods.colorToning.redlow; + } + + if (colorToning.greenlow) { + toEdit.colorToning.greenlow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenlow + mods.colorToning.greenlow : mods.colorToning.greenlow; + } + + if (colorToning.bluelow) { + toEdit.colorToning.bluelow = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluelow + mods.colorToning.bluelow : mods.colorToning.bluelow; + } + + if (colorToning.redmed) { + toEdit.colorToning.redmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redmed + mods.colorToning.redmed : mods.colorToning.redmed; + } + + if (colorToning.greenmed) { + toEdit.colorToning.greenmed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenmed + mods.colorToning.greenmed : mods.colorToning.greenmed; + } + + if (colorToning.bluemed) { + toEdit.colorToning.bluemed = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluemed + mods.colorToning.bluemed : mods.colorToning.bluemed; + } + + if (colorToning.redhigh) { + toEdit.colorToning.redhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.redhigh + mods.colorToning.redhigh : mods.colorToning.redhigh; + } + + if (colorToning.greenhigh) { + toEdit.colorToning.greenhigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.greenhigh + mods.colorToning.greenhigh : mods.colorToning.greenhigh; + } + + if (colorToning.bluehigh) { + toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; + } + + if (sharpenEdge.enabled) { + toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; + } + + if (sharpenEdge.passes) { + toEdit.sharpenEdge.passes = dontforceSet && options.baBehav[ADDSET_SHARPENEDGE_PASS] ? toEdit.sharpenEdge.passes + mods.sharpenEdge.passes : mods.sharpenEdge.passes; + } + + if (sharpenEdge.amount) { + toEdit.sharpenEdge.amount = dontforceSet && options.baBehav[ADDSET_SHARPENEDGE_AMOUNT] ? toEdit.sharpenEdge.amount + mods.sharpenEdge.amount : mods.sharpenEdge.amount; + } + + if (sharpenEdge.threechannels) { + toEdit.sharpenEdge.threechannels = mods.sharpenEdge.threechannels; + } + + if (sharpenMicro.enabled) { + toEdit.sharpenMicro.enabled = mods.sharpenMicro.enabled; + } + + if (sharpenMicro.matrix) { + toEdit.sharpenMicro.matrix = mods.sharpenMicro.matrix; + } + + if (sharpenMicro.amount) { + toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; + } + + if (sharpenMicro.uniformity) { + toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; + } + + if (sharpening.enabled) { + toEdit.sharpening.enabled = mods.sharpening.enabled; + } + + if (sharpening.radius) { + toEdit.sharpening.radius = mods.sharpening.radius; + } + + if (sharpening.amount) { + toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; + } + + if (sharpening.threshold) { + toEdit.sharpening.threshold = mods.sharpening.threshold; + } + + if (sharpening.edgesonly) { + toEdit.sharpening.edgesonly = mods.sharpening.edgesonly; + } + + if (sharpening.edges_radius) { + toEdit.sharpening.edges_radius = mods.sharpening.edges_radius; + } + + if (sharpening.edges_tolerance) { + toEdit.sharpening.edges_tolerance = mods.sharpening.edges_tolerance; + } + + if (sharpening.halocontrol) { + toEdit.sharpening.halocontrol = mods.sharpening.halocontrol; + } + + if (sharpening.halocontrol_amount) { + toEdit.sharpening.halocontrol_amount = mods.sharpening.halocontrol_amount; + } + + if (sharpening.method) { + toEdit.sharpening.method = mods.sharpening.method; + } + + if (sharpening.deconvamount) { + toEdit.sharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.deconvamount + mods.sharpening.deconvamount : mods.sharpening.deconvamount; + } + + if (sharpening.deconvradius) { + toEdit.sharpening.deconvradius = mods.sharpening.deconvradius; + } + + if (sharpening.deconviter) { + toEdit.sharpening.deconviter = mods.sharpening.deconviter; + } + + if (sharpening.deconvdamping) { + toEdit.sharpening.deconvdamping = mods.sharpening.deconvdamping; + } + + if (prsharpening.enabled) { + toEdit.prsharpening.enabled = mods.prsharpening.enabled; + } + + if (prsharpening.radius) { + toEdit.prsharpening.radius = mods.prsharpening.radius; + } + + if (prsharpening.amount) { + toEdit.prsharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.amount + mods.prsharpening.amount : mods.prsharpening.amount; + } + + if (prsharpening.threshold) { + toEdit.prsharpening.threshold = mods.prsharpening.threshold; + } + + if (prsharpening.edgesonly) { + toEdit.prsharpening.edgesonly = mods.prsharpening.edgesonly; + } + + if (prsharpening.edges_radius) { + toEdit.prsharpening.edges_radius = mods.prsharpening.edges_radius; + } + + if (prsharpening.edges_tolerance) { + toEdit.prsharpening.edges_tolerance = mods.prsharpening.edges_tolerance; + } + + if (prsharpening.halocontrol) { + toEdit.prsharpening.halocontrol = mods.prsharpening.halocontrol; + } + + if (prsharpening.halocontrol_amount) { + toEdit.prsharpening.halocontrol_amount = mods.prsharpening.halocontrol_amount; + } + + if (prsharpening.method) { + toEdit.prsharpening.method = mods.prsharpening.method; + } + + if (prsharpening.deconvamount) { + toEdit.prsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.prsharpening.deconvamount + mods.prsharpening.deconvamount : mods.prsharpening.deconvamount; + } + + if (prsharpening.deconvradius) { + toEdit.prsharpening.deconvradius = mods.prsharpening.deconvradius; + } + + if (prsharpening.deconviter) { + toEdit.prsharpening.deconviter = mods.prsharpening.deconviter; + } + + if (prsharpening.deconvdamping) { + toEdit.prsharpening.deconvdamping = mods.prsharpening.deconvdamping; + } + + if (vibrance.enabled) { + toEdit.vibrance.enabled = mods.vibrance.enabled; + } + + if (vibrance.pastels) { + toEdit.vibrance.pastels = dontforceSet && options.baBehav[ADDSET_VIBRANCE_PASTELS] ? toEdit.vibrance.pastels + mods.vibrance.pastels : mods.vibrance.pastels; + } + + if (vibrance.saturated) { + toEdit.vibrance.saturated = dontforceSet && options.baBehav[ADDSET_VIBRANCE_SATURATED] ? toEdit.vibrance.saturated + mods.vibrance.saturated : mods.vibrance.saturated; + } + + if (vibrance.psthreshold) { + toEdit.vibrance.psthreshold = mods.vibrance.psthreshold; + } + + if (vibrance.protectskins) { + toEdit.vibrance.protectskins = mods.vibrance.protectskins; + } + + if (vibrance.avoidcolorshift) { + toEdit.vibrance.avoidcolorshift = mods.vibrance.avoidcolorshift; + } + + if (vibrance.pastsattog) { + toEdit.vibrance.pastsattog = mods.vibrance.pastsattog; + } + + if (vibrance.skintonescurve) { + toEdit.vibrance.skintonescurve = mods.vibrance.skintonescurve; + } + + //if (colorBoost.amount) toEdit.colorBoost.amount = dontforceSet && options.baBehav[ADDSET_CBOOST_AMOUNT] ? toEdit.colorBoost.amount + mods.colorBoost.amount : mods.colorBoost.amount; + //if (colorBoost.avoidclip) toEdit.colorBoost.avoidclip = mods.colorBoost.avoidclip; + //if (colorBoost.enable_saturationlimiter)toEdit.colorBoost.enable_saturationlimiter = mods.colorBoost.enable_saturationlimiter; + //if (colorBoost.saturationlimit) toEdit.colorBoost.saturationlimit = mods.colorBoost.saturationlimit; + if (wb.method) { + toEdit.wb.method = mods.wb.method; + } + + if (wb.equal) { + toEdit.wb.equal = dontforceSet && options.baBehav[ADDSET_WB_EQUAL] ? toEdit.wb.equal + mods.wb.equal : mods.wb.equal; + } + + if (wb.green) { + toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green; + } + + if (wb.temperature) { + toEdit.wb.temperature = dontforceSet && options.baBehav[ADDSET_WB_TEMPERATURE] ? toEdit.wb.temperature + mods.wb.temperature : mods.wb.temperature; + } + + //if (colorShift.a) toEdit.colorShift.a = dontforceSet && options.baBehav[ADDSET_CS_BLUEYELLOW] ? toEdit.colorShift.a + mods.colorShift.a : mods.colorShift.a; + //if (colorShift.b) toEdit.colorShift.b = dontforceSet && options.baBehav[ADDSET_CS_GREENMAGENTA] ? toEdit.colorShift.b + mods.colorShift.b : mods.colorShift.b; + //if (lumaDenoise.enabled) toEdit.lumaDenoise.enabled = mods.lumaDenoise.enabled; + //if (lumaDenoise.radius) toEdit.lumaDenoise.radius = mods.lumaDenoise.radius; + //if (lumaDenoise.edgetolerance) toEdit.lumaDenoise.edgetolerance = dontforceSet && options.baBehav[ADDSET_LD_EDGETOLERANCE] ? toEdit.lumaDenoise.edgetolerance + mods.lumaDenoise.edgetolerance : mods.lumaDenoise.edgetolerance; + //if (colorDenoise.enabled) toEdit.colorDenoise.enabled = mods.colorDenoise.enabled; + //if (colorDenoise.amount) toEdit.colorDenoise.amount = mods.colorDenoise.amount; + + if (defringe.enabled) { + toEdit.defringe.enabled = mods.defringe.enabled; + } + + if (defringe.radius) { + toEdit.defringe.radius = mods.defringe.radius; + } + + if (defringe.threshold) { + toEdit.defringe.threshold = mods.defringe.threshold; + } + + if (defringe.huecurve) { + toEdit.defringe.huecurve = mods.defringe.huecurve; + } + + if (colorappearance.curve) { + toEdit.colorappearance.curve = mods.colorappearance.curve; + } + + if (colorappearance.curve2) { + toEdit.colorappearance.curve2 = mods.colorappearance.curve2; + } + + if (colorappearance.curve3) { + toEdit.colorappearance.curve3 = mods.colorappearance.curve3; + } + + if (colorappearance.curveMode) { + toEdit.colorappearance.curveMode = mods.colorappearance.curveMode; + } + + if (colorappearance.curveMode2) { + toEdit.colorappearance.curveMode2 = mods.colorappearance.curveMode2; + } + + if (colorappearance.curveMode3) { + toEdit.colorappearance.curveMode3 = mods.colorappearance.curveMode3; + } + + if (colorappearance.enabled) { + toEdit.colorappearance.enabled = mods.colorappearance.enabled; + } + + if (colorappearance.degree) { + toEdit.colorappearance.degree = dontforceSet && options.baBehav[ADDSET_CAT_DEGREE] ? toEdit.colorappearance.degree + mods.colorappearance.degree : mods.colorappearance.degree; + } + + if (colorappearance.autodegree) { + toEdit.colorappearance.autodegree = mods.colorappearance.autodegree; + } + + if (colorappearance.surround) { + toEdit.colorappearance.surround = mods.colorappearance.surround; + } + + if (colorappearance.autoadapscen) { + toEdit.colorappearance.autoadapscen = mods.colorappearance.autoadapscen; + } + + if (colorappearance.adapscen) { + toEdit.colorappearance.adapscen = mods.colorappearance.adapscen; + } + + if (colorappearance.adaplum) { + toEdit.colorappearance.adaplum = dontforceSet && options.baBehav[ADDSET_CAT_ADAPTVIEWING] ? toEdit.colorappearance.adaplum + mods.colorappearance.adaplum : mods.colorappearance.adaplum; + } + + if (colorappearance.badpixsl) { + toEdit.colorappearance.badpixsl = dontforceSet && options.baBehav[ADDSET_CAT_BADPIX] ? toEdit.colorappearance.badpixsl + mods.colorappearance.badpixsl : mods.colorappearance.badpixsl; + } + + if (colorappearance.wbmodel) { + toEdit.colorappearance.wbmodel = mods.colorappearance.wbmodel; + } + + if (colorappearance.algo) { + toEdit.colorappearance.algo = mods.colorappearance.algo; + } + + if (colorappearance.jlight) { + toEdit.colorappearance.jlight = dontforceSet && options.baBehav[ADDSET_CAT_LIGHT] ? toEdit.colorappearance.jlight + mods.colorappearance.jlight : mods.colorappearance.jlight; + } + + if (colorappearance.qbright) { + toEdit.colorappearance.qbright = dontforceSet && options.baBehav[ADDSET_CAT_BRIGHT] ? toEdit.colorappearance.qbright + mods.colorappearance.qbright : mods.colorappearance.qbright; + } + + if (colorappearance.chroma) { + toEdit.colorappearance.chroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA] ? toEdit.colorappearance.chroma + mods.colorappearance.chroma : mods.colorappearance.chroma; + } + + if (colorappearance.schroma) { + toEdit.colorappearance.schroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_S] ? toEdit.colorappearance.schroma + mods.colorappearance.schroma : mods.colorappearance.schroma; + } + + if (colorappearance.mchroma) { + toEdit.colorappearance.mchroma = dontforceSet && options.baBehav[ADDSET_CAT_CHROMA_M] ? toEdit.colorappearance.mchroma + mods.colorappearance.mchroma : mods.colorappearance.mchroma; + } + + if (colorappearance.contrast) { + toEdit.colorappearance.contrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST] ? toEdit.colorappearance.contrast + mods.colorappearance.contrast : mods.colorappearance.contrast; + } + + if (colorappearance.qcontrast) { + toEdit.colorappearance.qcontrast = dontforceSet && options.baBehav[ADDSET_CAT_CONTRAST_Q] ? toEdit.colorappearance.qcontrast + mods.colorappearance.qcontrast : mods.colorappearance.qcontrast; + } + + if (colorappearance.colorh) { + toEdit.colorappearance.colorh = dontforceSet && options.baBehav[ADDSET_CAT_HUE] ? toEdit.colorappearance.colorh + mods.colorappearance.colorh : mods.colorappearance.colorh; + } + + if (colorappearance.rstprotection) { + toEdit.colorappearance.rstprotection = dontforceSet && options.baBehav[ADDSET_CAT_RSTPRO] ? toEdit.colorappearance.rstprotection + mods.colorappearance.rstprotection : mods.colorappearance.rstprotection; + } + + if (colorappearance.surrsource) { + toEdit.colorappearance.surrsource = mods.colorappearance.surrsource; + } + + if (colorappearance.gamut) { + toEdit.colorappearance.gamut = mods.colorappearance.gamut; + } + +// if (colorappearance.badpix) toEdit.colorappearance.badpix = mods.colorappearance.badpix; + if (colorappearance.datacie) { + toEdit.colorappearance.datacie = mods.colorappearance.datacie; + } + + if (colorappearance.tonecie) { + toEdit.colorappearance.tonecie = mods.colorappearance.tonecie; + } + +// if (colorappearance.sharpcie) toEdit.colorappearance.sharpcie = mods.colorappearance.sharpcie; + if (impulseDenoise.enabled) { + toEdit.impulseDenoise.enabled = mods.impulseDenoise.enabled; + } + + if (impulseDenoise.thresh) { + toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh; + } + + if (dirpyrDenoise.enabled) { + toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; + } + + if (dirpyrDenoise.enhance) { + toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; + } + + if (dirpyrDenoise.median) { + toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; + } + + if (dirpyrDenoise.autochroma) { + toEdit.dirpyrDenoise.autochroma = mods.dirpyrDenoise.autochroma; + } + + if (dirpyrDenoise.luma) { + toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; + } + + if (dirpyrDenoise.lcurve) { + toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve; + } + + if (dirpyrDenoise.cccurve) { + toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; + } + + if (dirpyrDenoise.Ldetail) { + toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail; + } + + if (dirpyrDenoise.chroma) { + toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma; + } + + if (dirpyrDenoise.redchro) { + toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro; + } + + if (dirpyrDenoise.bluechro) { + toEdit.dirpyrDenoise.bluechro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE] ? toEdit.dirpyrDenoise.bluechro + mods.dirpyrDenoise.bluechro : mods.dirpyrDenoise.bluechro; + } + + if (dirpyrDenoise.gamma) { + toEdit.dirpyrDenoise.gamma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_GAMMA] ? toEdit.dirpyrDenoise.gamma + mods.dirpyrDenoise.gamma : mods.dirpyrDenoise.gamma; + } + + if (dirpyrDenoise.passes) { + toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes; + } + +// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform; + if (dirpyrDenoise.dmethod) { + toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod; + } + + if (dirpyrDenoise.Lmethod) { + toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; + } + + if (dirpyrDenoise.Cmethod) { + toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; + } + + if (dirpyrDenoise.C2method) { + toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; + } + + if (dirpyrDenoise.smethod) { + toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod; + } + + if (dirpyrDenoise.medmethod) { + toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod; + } + + if (dirpyrDenoise.methodmed) { + toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed; + } + + if (dirpyrDenoise.rgbmethod) { + toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod; + } + + if (epd.enabled) { + toEdit.epd.enabled = mods.epd.enabled; + } + + if (epd.strength) { + toEdit.epd.strength = mods.epd.strength; + } + + if (epd.gamma) { + toEdit.epd.gamma = mods.epd.gamma; + } + + if (epd.edgeStopping) { + toEdit.epd.edgeStopping = mods.epd.edgeStopping; + } + + if (epd.scale) { + toEdit.epd.scale = mods.epd.scale; + } + + if (epd.reweightingIterates) { + toEdit.epd.reweightingIterates = mods.epd.reweightingIterates; + } + + if (sh.enabled) { + toEdit.sh.enabled = mods.sh.enabled; + } + + if (sh.hq) { + toEdit.sh.hq = mods.sh.hq; + } + + if (sh.highlights) { + toEdit.sh.highlights = dontforceSet && options.baBehav[ADDSET_SH_HIGHLIGHTS] ? toEdit.sh.highlights + mods.sh.highlights : mods.sh.highlights; + } + + if (sh.htonalwidth) { + toEdit.sh.htonalwidth = mods.sh.htonalwidth; + } + + if (sh.shadows) { + toEdit.sh.shadows = dontforceSet && options.baBehav[ADDSET_SH_SHADOWS] ? toEdit.sh.shadows + mods.sh.shadows : mods.sh.shadows; + } + + if (sh.stonalwidth) { + toEdit.sh.stonalwidth = mods.sh.stonalwidth; + } + + if (sh.localcontrast) { + toEdit.sh.localcontrast = dontforceSet && options.baBehav[ADDSET_SH_LOCALCONTRAST] ? toEdit.sh.localcontrast + mods.sh.localcontrast : mods.sh.localcontrast; + } + + if (sh.radius) { + toEdit.sh.radius = mods.sh.radius; + } + + if (crop.enabled) { + toEdit.crop.enabled = mods.crop.enabled; + } + + if (crop.x) { + toEdit.crop.x = mods.crop.x; + } + + if (crop.y) { + toEdit.crop.y = mods.crop.y; + } + + if (crop.w) { + toEdit.crop.w = mods.crop.w; + } + + if (crop.h) { + toEdit.crop.h = mods.crop.h; + } + + if (crop.fixratio) { + toEdit.crop.fixratio = mods.crop.fixratio; + } + + if (crop.ratio) { + toEdit.crop.ratio = mods.crop.ratio; + } + + if (crop.orientation) { + toEdit.crop.orientation = mods.crop.orientation; + } + + if (crop.guide) { + toEdit.crop.guide = mods.crop.guide; + } + + if (coarse.rotate) { + toEdit.coarse.rotate = mods.coarse.rotate; + } + + if (coarse.hflip) { + toEdit.coarse.hflip = mods.coarse.hflip; + } + + if (coarse.vflip) { + toEdit.coarse.vflip = mods.coarse.vflip; + } + + if (commonTrans.autofill) { + toEdit.commonTrans.autofill = mods.commonTrans.autofill; + } + + if (rotate.degree) { + toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree; + } + + if (distortion.amount) { + toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount; + } + + if (lensProf.lcpFile) { + toEdit.lensProf.lcpFile = mods.lensProf.lcpFile; + } + + if (lensProf.useDist) { + toEdit.lensProf.useDist = mods.lensProf.useDist; + } + + if (lensProf.useVign) { + toEdit.lensProf.useVign = mods.lensProf.useVign; + } + + if (lensProf.useCA) { + toEdit.lensProf.useCA = mods.lensProf.useCA; + } + + if (perspective.horizontal) { + toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal; + } + + if (perspective.vertical) { + toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; + } + + if (gradient.enabled) { + toEdit.gradient.enabled = mods.gradient.enabled; + } + + if (gradient.degree) { + toEdit.gradient.degree = dontforceSet && options.baBehav[ADDSET_GRADIENT_DEGREE] ? toEdit.gradient.degree + mods.gradient.degree : mods.gradient.degree; + } + + if (gradient.feather) { + toEdit.gradient.feather = mods.gradient.feather; + } + + if (gradient.strength) { + toEdit.gradient.strength = mods.gradient.strength; + } + + if (gradient.centerX) { + toEdit.gradient.centerX = mods.gradient.centerX; + } + + if (gradient.centerY) { + toEdit.gradient.centerY = mods.gradient.centerY; + } + + if (pcvignette.enabled) { + toEdit.pcvignette.enabled = mods.pcvignette.enabled; + } + + if (pcvignette.strength) { + toEdit.pcvignette.strength = mods.pcvignette.strength; + } + + if (pcvignette.feather) { + toEdit.pcvignette.feather = mods.pcvignette.feather; + } + + if (pcvignette.roundness) { + toEdit.pcvignette.roundness = mods.pcvignette.roundness; + } + + if (cacorrection.red) { + toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red; + } + + if (cacorrection.blue) { + toEdit.cacorrection.blue = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.blue + mods.cacorrection.blue : mods.cacorrection.blue; + } + + if (vignetting.amount) { + toEdit.vignetting.amount = dontforceSet && options.baBehav[ADDSET_VIGN_AMOUNT] ? toEdit.vignetting.amount + mods.vignetting.amount : mods.vignetting.amount; + } + + if (vignetting.radius) { + toEdit.vignetting.radius = mods.vignetting.radius; + } + + if (vignetting.strength) { + toEdit.vignetting.strength = mods.vignetting.strength; + } + + if (vignetting.centerX) { + toEdit.vignetting.centerX = mods.vignetting.centerX; + } + + if (vignetting.centerY) { + toEdit.vignetting.centerY = mods.vignetting.centerY; + } + + for (int i = 0; i < 3; i++) { + if (chmixer.red[i]) { + toEdit.chmixer.red[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.red[i] + mods.chmixer.red[i] : mods.chmixer.red[i]; + } + + if (chmixer.green[i]) { + toEdit.chmixer.green[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.green[i] + mods.chmixer.green[i] : mods.chmixer.green[i]; + } + + if (chmixer.blue[i]) { + toEdit.chmixer.blue[i] = dontforceSet && options.baBehav[ADDSET_CHMIXER] ? toEdit.chmixer.blue[i] + mods.chmixer.blue[i] : mods.chmixer.blue[i]; + } + } + + if (blackwhite.enabled) { + toEdit.blackwhite.enabled = mods.blackwhite.enabled; + } + + if (blackwhite.method) { + toEdit.blackwhite.method = mods.blackwhite.method; + } + + if (blackwhite.luminanceCurve) { + toEdit.blackwhite.luminanceCurve = mods.blackwhite.luminanceCurve; + } + + if (blackwhite.autoc) { + toEdit.blackwhite.autoc = mods.blackwhite.autoc; + } + + if (blackwhite.setting) { + toEdit.blackwhite.setting = mods.blackwhite.setting; + } + + if (blackwhite.enabledcc) { + toEdit.blackwhite.enabledcc = mods.blackwhite.enabledcc; + } + + if (blackwhite.filter) { + toEdit.blackwhite.filter = mods.blackwhite.filter; + } + + if (blackwhite.mixerRed) { + toEdit.blackwhite.mixerRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerRed + mods.blackwhite.mixerRed : mods.blackwhite.mixerRed; + } + + if (blackwhite.mixerOrange) { + toEdit.blackwhite.mixerOrange = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerOrange + mods.blackwhite.mixerOrange : mods.blackwhite.mixerOrange; + } + + if (blackwhite.mixerYellow) { + toEdit.blackwhite.mixerYellow = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerYellow + mods.blackwhite.mixerYellow : mods.blackwhite.mixerYellow; + } + + if (blackwhite.mixerGreen) { + toEdit.blackwhite.mixerGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerGreen + mods.blackwhite.mixerGreen : mods.blackwhite.mixerGreen; + } + + if (blackwhite.mixerCyan) { + toEdit.blackwhite.mixerCyan = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerCyan + mods.blackwhite.mixerCyan : mods.blackwhite.mixerCyan; + } + + if (blackwhite.mixerBlue) { + toEdit.blackwhite.mixerBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerBlue + mods.blackwhite.mixerBlue : mods.blackwhite.mixerBlue; + } + + if (blackwhite.mixerMagenta) { + toEdit.blackwhite.mixerMagenta = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerMagenta + mods.blackwhite.mixerMagenta : mods.blackwhite.mixerMagenta; + } + + if (blackwhite.mixerPurple) { + toEdit.blackwhite.mixerPurple = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_HUES] ? toEdit.blackwhite.mixerPurple + mods.blackwhite.mixerPurple : mods.blackwhite.mixerPurple; + } + + if (blackwhite.gammaRed) { + toEdit.blackwhite.gammaRed = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaRed + mods.blackwhite.gammaRed : mods.blackwhite.gammaRed; + } + + if (blackwhite.gammaGreen) { + toEdit.blackwhite.gammaGreen = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaGreen + mods.blackwhite.gammaGreen : mods.blackwhite.gammaGreen; + } + + if (blackwhite.gammaBlue) { + toEdit.blackwhite.gammaBlue = dontforceSet && options.baBehav[ADDSET_BLACKWHITE_GAMMA] ? toEdit.blackwhite.gammaBlue + mods.blackwhite.gammaBlue : mods.blackwhite.gammaBlue; + } + + if (blackwhite.beforeCurve) { + toEdit.blackwhite.beforeCurve = mods.blackwhite.beforeCurve; + } + + if (blackwhite.beforeCurveMode) { + toEdit.blackwhite.beforeCurveMode = mods.blackwhite.beforeCurveMode; + } + + if (blackwhite.afterCurve) { + toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve; + } + + if (blackwhite.afterCurveMode) { + toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode; + } + + if (blackwhite.algo) { + toEdit.blackwhite.algo = mods.blackwhite.algo; + } + + if (resize.scale) { + toEdit.resize.scale = mods.resize.scale; + } + + if (resize.appliesTo) { + toEdit.resize.appliesTo = mods.resize.appliesTo; + } + + if (resize.method) { + toEdit.resize.method = mods.resize.method; + } + + if (resize.dataspec) { + toEdit.resize.dataspec = mods.resize.dataspec; + } + + if (resize.width) { + toEdit.resize.width = mods.resize.width; + } + + if (resize.height) { + toEdit.resize.height = mods.resize.height; + } + + if (resize.enabled) { + toEdit.resize.enabled = mods.resize.enabled; + } + + if (icm.input) { + toEdit.icm.input = mods.icm.input; + } + + if (icm.toneCurve) { + toEdit.icm.toneCurve = mods.icm.toneCurve; + } + + if (icm.applyLookTable) { + toEdit.icm.applyLookTable = mods.icm.applyLookTable; + } + + if (icm.applyBaselineExposureOffset) { + toEdit.icm.applyBaselineExposureOffset = mods.icm.applyBaselineExposureOffset; + } + + if (icm.applyHueSatMap) { + toEdit.icm.applyHueSatMap = mods.icm.applyHueSatMap; + } + + if (icm.blendCMSMatrix) { + toEdit.icm.blendCMSMatrix = mods.icm.blendCMSMatrix; + } + + if (icm.dcpIlluminant) { + toEdit.icm.dcpIlluminant = mods.icm.dcpIlluminant; + } + + if (icm.working) { + toEdit.icm.working = mods.icm.working; + } + + if (icm.output) { + toEdit.icm.output = mods.icm.output; + } + + //if (icm.gampos) toEdit.icm.gampos = mods.icm.gampos; + //if (icm.slpos) toEdit.icm.slpos = mods.icm.slpos; + if (icm.gampos) { + toEdit.icm.gampos = dontforceSet && options.baBehav[ADDSET_FREE_OUPUT_GAMMA] ? toEdit.icm.gampos + mods.icm.gampos : mods.icm.gampos; + } + + if (icm.slpos) { + toEdit.icm.slpos = dontforceSet && options.baBehav[ADDSET_FREE_OUTPUT_SLOPE] ? toEdit.icm.slpos + mods.icm.slpos : mods.icm.slpos; + } + + if (icm.gamma) { + toEdit.icm.gamma = mods.icm.gamma; + } + + if (icm.freegamma) { + toEdit.icm.freegamma = mods.icm.freegamma; + } + + if (raw.bayersensor.method) { + toEdit.raw.bayersensor.method = mods.raw.bayersensor.method; + } + + if (raw.bayersensor.ccSteps) { + toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps; + } + + if (raw.bayersensor.exBlack0) { + toEdit.raw.bayersensor.black0 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black0 + mods.raw.bayersensor.black0 : mods.raw.bayersensor.black0; + } + + if (raw.bayersensor.exBlack1) { + toEdit.raw.bayersensor.black1 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black1 + mods.raw.bayersensor.black1 : mods.raw.bayersensor.black1; + } + + if (raw.bayersensor.exBlack2) { + toEdit.raw.bayersensor.black2 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black2 + mods.raw.bayersensor.black2 : mods.raw.bayersensor.black2; + } + + if (raw.bayersensor.exBlack3) { + toEdit.raw.bayersensor.black3 = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.bayersensor.black3 + mods.raw.bayersensor.black3 : mods.raw.bayersensor.black3; + } + + if (raw.bayersensor.exTwoGreen) { + toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; + } + + if (raw.bayersensor.dcbIterations) { + toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; + } + + if (raw.bayersensor.dcbEnhance) { + toEdit.raw.bayersensor.dcb_enhance = mods.raw.bayersensor.dcb_enhance; + } + + if (raw.bayersensor.lmmseIterations) { + toEdit.raw.bayersensor.lmmse_iterations = mods.raw.bayersensor.lmmse_iterations; + } + + //if (raw.bayersensor.allEnhance) toEdit.raw.bayersensor.all_enhance = mods.raw.bayersensor.all_enhance; + if (raw.bayersensor.greenEq) { + toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; + } + + if (raw.bayersensor.linenoise) { + toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise; + } + + if (raw.xtranssensor.method) { + toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; + } + + if (raw.xtranssensor.ccSteps) { + toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; + } + + if (raw.xtranssensor.exBlackRed) { + toEdit.raw.xtranssensor.blackred = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackred + mods.raw.xtranssensor.blackred : mods.raw.xtranssensor.blackred; + } + + if (raw.xtranssensor.exBlackGreen) { + toEdit.raw.xtranssensor.blackgreen = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackgreen + mods.raw.xtranssensor.blackgreen : mods.raw.xtranssensor.blackgreen; + } + + if (raw.xtranssensor.exBlackBlue) { + toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; + } + + if (raw.caCorrection) { + toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; + } + + if (raw.caRed) { + toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; + } + + if (raw.caBlue) { + toEdit.raw.cablue = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cablue + mods.raw.cablue : mods.raw.cablue; + } + + if (raw.exPos) { + toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos; + } + + if (raw.exPreser) { + toEdit.raw.preser = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_PRESER] ? toEdit.raw.preser + mods.raw.preser : mods.raw.preser; + } + + if (raw.hotPixelFilter) { + toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter; + } + + if (raw.deadPixelFilter) { + toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter; + } + + if (raw.hotDeadPixelThresh) { + toEdit.raw.hotdeadpix_thresh = mods.raw.hotdeadpix_thresh; + } + + if (raw.darkFrame) { + toEdit.raw.dark_frame = mods.raw.dark_frame; + } + + if (raw.dfAuto) { + toEdit.raw.df_autoselect = mods.raw.df_autoselect; + } + + if (raw.ff_file) { + toEdit.raw.ff_file = mods.raw.ff_file; + } + + if (raw.ff_AutoSelect) { + toEdit.raw.ff_AutoSelect = mods.raw.ff_AutoSelect; + } + + if (raw.ff_BlurRadius) { + toEdit.raw.ff_BlurRadius = mods.raw.ff_BlurRadius; + } + + if (raw.ff_BlurType) { + toEdit.raw.ff_BlurType = mods.raw.ff_BlurType; + } + + if (raw.ff_AutoClipControl) { + toEdit.raw.ff_AutoClipControl = mods.raw.ff_AutoClipControl; + } + + if (raw.ff_clipControl) { + toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; + } + + if (wavelet.enabled) { + toEdit.wavelet.enabled = mods.wavelet.enabled; + } + + if (wavelet.strength) { + toEdit.wavelet.strength = mods.wavelet.strength; + } + + if (wavelet.balance) { + toEdit.wavelet.balance = mods.wavelet.balance; + } + + if (wavelet.iter) { + toEdit.wavelet.iter = mods.wavelet.iter; + } + + if (wavelet.median) { + toEdit.wavelet.median = mods.wavelet.median; + } + + if (wavelet.medianlev) { + toEdit.wavelet.medianlev = mods.wavelet.medianlev; + } + + if (wavelet.linkedg) { + toEdit.wavelet.linkedg = mods.wavelet.linkedg; + } + + if (wavelet.cbenab) { + toEdit.wavelet.cbenab = mods.wavelet.cbenab; + } + + if (wavelet.greenhigh) { + toEdit.wavelet.greenhigh = mods.wavelet.greenhigh; + } + + if (wavelet.bluehigh) { + toEdit.wavelet.bluehigh = mods.wavelet.bluehigh; + } + + if (wavelet.greenmed) { + toEdit.wavelet.greenmed = mods.wavelet.greenmed; + } + + if (wavelet.bluemed) { + toEdit.wavelet.bluemed = mods.wavelet.bluemed; + } + + if (wavelet.greenlow) { + toEdit.wavelet.greenlow = mods.wavelet.greenlow; + } + + if (wavelet.bluelow) { + toEdit.wavelet.bluelow = mods.wavelet.bluelow; + } + + if (wavelet.lipst) { + toEdit.wavelet.lipst = mods.wavelet.lipst; + } + + if (wavelet.Medgreinf) { + toEdit.wavelet.Medgreinf = mods.wavelet.Medgreinf; + } + + if (wavelet.avoid) { + toEdit.wavelet.avoid = mods.wavelet.avoid; + } + + if (wavelet.tmr) { + toEdit.wavelet.tmr = mods.wavelet.tmr; + } + + if (wavelet.Lmethod) { + toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; + } + + if (wavelet.CLmethod) { + toEdit.wavelet.CLmethod = mods.wavelet.CLmethod; + } + + if (wavelet.Backmethod) { + toEdit.wavelet.Backmethod = mods.wavelet.Backmethod; + } + + if (wavelet.Tilesmethod) { + toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; + } + + if (wavelet.daubcoeffmethod) { + toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; + } + + if (wavelet.CHmethod) { + toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; + } + + if (wavelet.CHSLmethod) { + toEdit.wavelet.CHSLmethod = mods.wavelet.CHSLmethod; + } + + if (wavelet.EDmethod) { + toEdit.wavelet.EDmethod = mods.wavelet.EDmethod; + } + + if (wavelet.NPmethod) { + toEdit.wavelet.NPmethod = mods.wavelet.NPmethod; + } + + if (wavelet.BAmethod) { + toEdit.wavelet.BAmethod = mods.wavelet.BAmethod; + } + + if (wavelet.TMmethod) { + toEdit.wavelet.TMmethod = mods.wavelet.TMmethod; + } + + if (wavelet.HSmethod) { + toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; + } + + if (wavelet.Dirmethod) { + toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; + } + + if (wavelet.edgthresh) { + toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; + } + + if (wavelet.sky) { + toEdit.wavelet.sky = dontforceSet && options.baBehav[ADDSET_WA_SKYPROTECT] ? toEdit.wavelet.sky + mods.wavelet.sky : mods.wavelet.sky; + } + + if (wavelet.thr) { + toEdit.wavelet.thr = dontforceSet && options.baBehav[ADDSET_WA_THRR] ? toEdit.wavelet.thr + mods.wavelet.thr : mods.wavelet.thr; + } + + if (wavelet.thrH) { + toEdit.wavelet.thrH = dontforceSet && options.baBehav[ADDSET_WA_THRRH] ? toEdit.wavelet.thrH + mods.wavelet.thrH : mods.wavelet.thrH; + } + + if (wavelet.sup) { + toEdit.wavelet.sup = mods.wavelet.sup; + } + + if (wavelet.hllev) { + toEdit.wavelet.hllev = mods.wavelet.hllev; + } + + if (wavelet.bllev) { + toEdit.wavelet.bllev = mods.wavelet.bllev; + } + + if (wavelet.edgcont) { + toEdit.wavelet.edgcont = mods.wavelet.edgcont; + } + + if (wavelet.level0noise) { + toEdit.wavelet.level0noise = mods.wavelet.level0noise; + } + + if (wavelet.level1noise) { + toEdit.wavelet.level1noise = mods.wavelet.level1noise; + } + + if (wavelet.level2noise) { + toEdit.wavelet.level2noise = mods.wavelet.level2noise; + } + + if (wavelet.level3noise) { + toEdit.wavelet.level3noise = mods.wavelet.level3noise; + } + + if (wavelet.pastlev) { + toEdit.wavelet.pastlev = mods.wavelet.pastlev; + } + + if (wavelet.satlev) { + toEdit.wavelet.satlev = mods.wavelet.satlev; + } + + if (wavelet.ccwcurve) { + toEdit.wavelet.ccwcurve = mods.wavelet.ccwcurve; + } + + if (wavelet.opacityCurveRG) { + toEdit.wavelet.opacityCurveRG = mods.wavelet.opacityCurveRG; + } + + if (wavelet.opacityCurveBY) { + toEdit.wavelet.opacityCurveBY = mods.wavelet.opacityCurveBY; + } + + if (wavelet.opacityCurveW) { + toEdit.wavelet.opacityCurveW = mods.wavelet.opacityCurveW; + } + + if (wavelet.opacityCurveWL) { + toEdit.wavelet.opacityCurveWL = mods.wavelet.opacityCurveWL; + } + + if (wavelet.hhcurve) { + toEdit.wavelet.hhcurve = mods.wavelet.hhcurve; + } + + if (wavelet.Chcurve) { + toEdit.wavelet.Chcurve = mods.wavelet.Chcurve; + } + + if (wavelet.wavclCurve) { + toEdit.wavelet.wavclCurve = mods.wavelet.wavclCurve; + } + + //if (wavelet.enacont) toEdit.wavelet.enacont = mods.wavelet.enacont; + if (wavelet.expcontrast) { + toEdit.wavelet.expcontrast = mods.wavelet.expcontrast; + } + + if (wavelet.expchroma) { + toEdit.wavelet.expchroma = mods.wavelet.expchroma; + } + + if (wavelet.expedge) { + toEdit.wavelet.expedge = mods.wavelet.expedge; + } + + if (wavelet.expresid) { + toEdit.wavelet.expresid = mods.wavelet.expresid; + } + + if (wavelet.expfinal) { + toEdit.wavelet.expfinal = mods.wavelet.expfinal; + } + + if (wavelet.exptoning) { + toEdit.wavelet.exptoning = mods.wavelet.exptoning; + } + + if (wavelet.expnoise) { + toEdit.wavelet.expnoise = mods.wavelet.expnoise; + } + + for(int i = 0; i < 9; i++) { + if(wavelet.c[i]) { + toEdit.wavelet.c[i] = dontforceSet && options.baBehav[ADDSET_WA] ? toEdit.wavelet.c[i] + mods.wavelet.c[i] : mods.wavelet.c[i]; + } + } + + for(int i = 0; i < 9; i++) { + if(wavelet.ch[i]) { + toEdit.wavelet.ch[i] = dontforceSet && options.baBehav[ADDSET_WA] ? toEdit.wavelet.ch[i] + mods.wavelet.ch[i] : mods.wavelet.ch[i]; + } + } + + if (wavelet.skinprotect) { + toEdit.wavelet.skinprotect = dontforceSet && options.baBehav[ADDSET_WA_SKINPROTECT] ? toEdit.wavelet.skinprotect + mods.wavelet.skinprotect : mods.wavelet.skinprotect; + } + + if (wavelet.hueskin) { + toEdit.wavelet.hueskin = mods.wavelet.hueskin; + } + + if (wavelet.hueskin2) { + toEdit.wavelet.hueskin2 = mods.wavelet.hueskin2; + } + + if (wavelet.edgesensi) { + toEdit.wavelet.edgesensi = mods.wavelet.edgesensi; + } + + if (wavelet.edgeampli) { + toEdit.wavelet.edgeampli = mods.wavelet.edgeampli; + } + + if (wavelet.resconH) { + toEdit.wavelet.resconH = dontforceSet && options.baBehav[ADDSET_WA_RESCONH] ? toEdit.wavelet.resconH + mods.wavelet.resconH : mods.wavelet.resconH; + } + + if (wavelet.reschro) { + toEdit.wavelet.reschro = dontforceSet && options.baBehav[ADDSET_WA_RESCHRO] ? toEdit.wavelet.reschro + mods.wavelet.reschro : mods.wavelet.reschro; + } + + if (wavelet.tmrs) { + toEdit.wavelet.tmrs = dontforceSet && options.baBehav[ADDSET_WA_TMRS] ? toEdit.wavelet.tmrs + mods.wavelet.tmrs : mods.wavelet.tmrs; + } + + if (wavelet.gamma) { + toEdit.wavelet.gamma = dontforceSet && options.baBehav[ADDSET_WA_GAMMA] ? toEdit.wavelet.gamma + mods.wavelet.gamma : mods.wavelet.gamma; + } + + if (wavelet.rescon) { + toEdit.wavelet.rescon = dontforceSet && options.baBehav[ADDSET_WA_RESCON] ? toEdit.wavelet.rescon + mods.wavelet.rescon : mods.wavelet.rescon; + } + + if (wavelet.thres) { + toEdit.wavelet.thres = dontforceSet && options.baBehav[ADDSET_WA_THRES] ? toEdit.wavelet.thres + mods.wavelet.thres : mods.wavelet.thres; + } + + if (wavelet.threshold) { + toEdit.wavelet.threshold = dontforceSet && options.baBehav[ADDSET_WA_THRESHOLD] ? toEdit.wavelet.threshold + mods.wavelet.threshold : mods.wavelet.threshold; + } + + if (wavelet.threshold2) { + toEdit.wavelet.threshold2 = dontforceSet && options.baBehav[ADDSET_WA_THRESHOLD2] ? toEdit.wavelet.threshold2 + mods.wavelet.threshold2 : mods.wavelet.threshold2; + } + + if (wavelet.edgedetect) { + toEdit.wavelet.edgedetect = dontforceSet && options.baBehav[ADDSET_WA_EDGEDETECT] ? toEdit.wavelet.edgedetect + mods.wavelet.edgedetect : mods.wavelet.edgedetect; + } + + if (wavelet.edgedetectthr) { + toEdit.wavelet.edgedetectthr = dontforceSet && options.baBehav[ADDSET_WA_EDGEDETECTTHR] ? toEdit.wavelet.edgedetectthr + mods.wavelet.edgedetectthr : mods.wavelet.edgedetectthr; + } + + if (wavelet.edgedetectthr2) { + toEdit.wavelet.edgedetectthr2 = dontforceSet && options.baBehav[ADDSET_WA_EDGEDETECTTHR2] ? toEdit.wavelet.edgedetectthr2 + mods.wavelet.edgedetectthr2 : mods.wavelet.edgedetectthr2; + } + + if (wavelet.chro) { + toEdit.wavelet.chro = dontforceSet && options.baBehav[ADDSET_WA_CHRO] ? toEdit.wavelet.chro + mods.wavelet.chro : mods.wavelet.chro; + } + + if (wavelet.chroma) { + toEdit.wavelet.chroma = dontforceSet && options.baBehav[ADDSET_WA_CHROMA] ? toEdit.wavelet.chroma + mods.wavelet.chroma : mods.wavelet.chroma; + } + + if (wavelet.contrast) { + toEdit.wavelet.contrast = dontforceSet && options.baBehav[ADDSET_WA_CONTRAST] ? toEdit.wavelet.contrast + mods.wavelet.contrast : mods.wavelet.contrast; + } + + if (wavelet.edgrad) { + toEdit.wavelet.edgrad = dontforceSet && options.baBehav[ADDSET_WA_EDGRAD] ? toEdit.wavelet.edgrad + mods.wavelet.edgrad : mods.wavelet.edgrad; + } + + if (wavelet.edgval) { + toEdit.wavelet.edgval = dontforceSet && options.baBehav[ADDSET_WA_EDGVAL] ? toEdit.wavelet.edgval + mods.wavelet.edgval : mods.wavelet.edgval; + } + + if (wavelet.strength) { + toEdit.wavelet.strength = dontforceSet && options.baBehav[ADDSET_WA_STRENGTH] ? toEdit.wavelet.strength + mods.wavelet.strength : mods.wavelet.strength; + } - if (dirpyrequalizer.enabled) toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; - if (dirpyrequalizer.gamutlab) toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; - 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]; - } - if (dirpyrequalizer.threshold) toEdit.dirpyrequalizer.threshold= dontforceSet && options.baBehav[ADDSET_DIRPYREQ_THRESHOLD] ? toEdit.dirpyrequalizer.threshold + mods.dirpyrequalizer.threshold : mods.dirpyrequalizer.threshold; - if (dirpyrequalizer.skinprotect)toEdit.dirpyrequalizer.skinprotect= dontforceSet && options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT] ? toEdit.dirpyrequalizer.skinprotect + mods.dirpyrequalizer.skinprotect : mods.dirpyrequalizer.skinprotect; - if (dirpyrequalizer.hueskin) toEdit.dirpyrequalizer.hueskin = mods.dirpyrequalizer.hueskin; -// if (dirpyrequalizer.algo) toEdit.dirpyrequalizer.algo = mods.dirpyrequalizer.algo; - if (hsvequalizer.hcurve) toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve; - if (hsvequalizer.scurve) toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve; - if (hsvequalizer.vcurve) toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve; + if (dirpyrequalizer.enabled) { + toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; + } - if (filmSimulation.enabled) toEdit.filmSimulation.enabled = mods.filmSimulation.enabled; - if (filmSimulation.clutFilename) toEdit.filmSimulation.clutFilename = mods.filmSimulation.clutFilename; - if (filmSimulation.strength) toEdit.filmSimulation.strength = dontforceSet && options.baBehav[ADDSET_FILMSIMULATION_STRENGTH] ? toEdit.filmSimulation.strength + mods.filmSimulation.strength : mods.filmSimulation.strength; + if (dirpyrequalizer.gamutlab) { + toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; + } + + 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]; + } + } + + if (dirpyrequalizer.threshold) { + toEdit.dirpyrequalizer.threshold = dontforceSet && options.baBehav[ADDSET_DIRPYREQ_THRESHOLD] ? toEdit.dirpyrequalizer.threshold + mods.dirpyrequalizer.threshold : mods.dirpyrequalizer.threshold; + } + + if (dirpyrequalizer.skinprotect) { + toEdit.dirpyrequalizer.skinprotect = dontforceSet && options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT] ? toEdit.dirpyrequalizer.skinprotect + mods.dirpyrequalizer.skinprotect : mods.dirpyrequalizer.skinprotect; + } + + if (dirpyrequalizer.hueskin) { + toEdit.dirpyrequalizer.hueskin = mods.dirpyrequalizer.hueskin; + } + +// if (dirpyrequalizer.algo) toEdit.dirpyrequalizer.algo = mods.dirpyrequalizer.algo; + if (hsvequalizer.hcurve) { + toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve; + } + + if (hsvequalizer.scurve) { + toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve; + } + + if (hsvequalizer.vcurve) { + toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve; + } + + if (filmSimulation.enabled) { + toEdit.filmSimulation.enabled = mods.filmSimulation.enabled; + } + + if (filmSimulation.clutFilename) { + toEdit.filmSimulation.clutFilename = mods.filmSimulation.clutFilename; + } + + if (filmSimulation.strength) { + toEdit.filmSimulation.strength = dontforceSet && options.baBehav[ADDSET_FILMSIMULATION_STRENGTH] ? toEdit.filmSimulation.strength + mods.filmSimulation.strength : mods.filmSimulation.strength; + } - // Exif changes are added to the existing ones - if (exif) - for (procparams::ExifPairs::const_iterator i=mods.exif.begin(); i!=mods.exif.end(); i++) { - toEdit.exif[i->first] = i->second; - } + // Exif changes are added to the existing ones + if (exif) + for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); i++) { + toEdit.exif[i->first] = i->second; + } - // IPTC changes are added to the existing ones - if (iptc) - for (procparams::IPTCPairs::const_iterator i=mods.iptc.begin(); i!=mods.iptc.end(); i++) { - toEdit.iptc[i->first] = i->second; - } + // IPTC changes are added to the existing ones + if (iptc) + for (procparams::IPTCPairs::const_iterator i = mods.iptc.begin(); i != mods.iptc.end(); i++) { + toEdit.iptc[i->first] = i->second; + } } -bool RAWParamsEdited::BayerSensor::isUnchanged() const { - return method && ccSteps && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq - && linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; +bool RAWParamsEdited::BayerSensor::isUnchanged() const +{ + return method && ccSteps && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq + && linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; } -bool RAWParamsEdited::XTransSensor::isUnchanged() const { - return method && ccSteps && exBlackRed && exBlackGreen && exBlackBlue; +bool RAWParamsEdited::XTransSensor::isUnchanged() const +{ + return method && ccSteps && exBlackRed && exBlackGreen && exBlackBlue; } -bool RAWParamsEdited::isUnchanged() const { - return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame - && dfAuto && ff_file && ff_AutoSelect && ff_BlurRadius && ff_BlurType && exPos && exPreser && ff_AutoClipControl && ff_clipControl; +bool RAWParamsEdited::isUnchanged() const +{ + return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame + && dfAuto && ff_file && ff_AutoSelect && ff_BlurRadius && ff_BlurType && exPos && exPreser && ff_AutoClipControl && ff_clipControl; } -bool LensProfParamsEdited::isUnchanged() const { +bool LensProfParamsEdited::isUnchanged() const +{ return lcpFile; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 992de66e8..d1f5124b1 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -7,7 +7,7 @@ * 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 @@ -24,164 +24,174 @@ #include "../rtengine/procparams.h" #include "../rtengine/rtengine.h" -class GeneralParamsEdited { +class GeneralParamsEdited +{ - public: - bool rank; - bool colorlabel; - bool intrash; +public: + bool rank; + bool colorlabel; + bool intrash; }; -class ToneCurveParamsEdited { +class ToneCurveParamsEdited +{ - public: - bool curve; - bool curve2; - bool curveMode; - bool curveMode2; - bool brightness; - bool black; - bool contrast; - bool saturation; - bool shcompr; - bool hlcompr; - bool hlcomprthresh; - bool autoexp; - bool clip; - bool expcomp; - bool hrenabled; - bool method; +public: + bool curve; + bool curve2; + bool curveMode; + bool curveMode2; + bool brightness; + bool black; + bool contrast; + bool saturation; + bool shcompr; + bool hlcompr; + bool hlcomprthresh; + bool autoexp; + bool clip; + bool expcomp; + bool hrenabled; + bool method; }; -class LCurveParamsEdited { - public: - bool brightness; - bool contrast; - bool chromaticity; - bool avoidcolorshift; - bool rstprotection; - bool lcurve; - bool acurve; - bool bcurve; - bool lcredsk; - bool cccurve; - bool chcurve; - bool lhcurve; - bool hhcurve; - bool lccurve; - bool clcurve; +class LCurveParamsEdited +{ +public: + bool brightness; + bool contrast; + bool chromaticity; + bool avoidcolorshift; + bool rstprotection; + bool lcurve; + bool acurve; + bool bcurve; + bool lcredsk; + bool cccurve; + bool chcurve; + bool lhcurve; + bool hhcurve; + bool lccurve; + bool clcurve; - bool enabled; - bool method; + bool enabled; + bool method; }; -class RGBCurvesParamsEdited { +class RGBCurvesParamsEdited +{ - public: - bool lumamode; - bool rcurve; - bool gcurve; - bool bcurve; +public: + bool lumamode; + bool rcurve; + bool gcurve; + bool bcurve; }; -class ColorToningEdited { +class ColorToningEdited +{ - public: - bool enabled; - bool opacityCurve; - bool colorCurve; - bool clcurve; - bool method; - bool autosat; - bool satprotectionthreshold; - bool saturatedopacity; - bool strength; - bool shadowsColSat; - bool hlColSat; - bool balance; - bool twocolor; - bool cl2curve; - bool redlow; - bool greenlow; - bool bluelow; - bool redmed; - bool greenmed; - bool bluemed; - bool redhigh; - bool greenhigh; - bool bluehigh; - bool satlow; - bool sathigh; - bool lumamode; +public: + bool enabled; + bool opacityCurve; + bool colorCurve; + bool clcurve; + bool method; + bool autosat; + bool satprotectionthreshold; + bool saturatedopacity; + bool strength; + bool shadowsColSat; + bool hlColSat; + bool balance; + bool twocolor; + bool cl2curve; + bool redlow; + bool greenlow; + bool bluelow; + bool redmed; + bool greenmed; + bool bluemed; + bool redhigh; + bool greenhigh; + bool bluehigh; + bool satlow; + bool sathigh; + bool lumamode; }; -class SharpenEdgeParamsEdited { +class SharpenEdgeParamsEdited +{ - public : - bool enabled; - bool passes; - bool amount; - bool threechannels; +public : + bool enabled; + bool passes; + bool amount; + bool threechannels; }; -class SharpenMicroParamsEdited { - public : - bool enabled; - bool matrix; - bool amount; - bool uniformity; - +class SharpenMicroParamsEdited +{ +public : + bool enabled; + bool matrix; + bool amount; + bool uniformity; + }; -class SharpeningParamsEdited { +class SharpeningParamsEdited +{ - public: - bool enabled; - bool radius; - bool amount; - bool threshold; - bool edgesonly; - bool edges_radius; - bool edges_tolerance; - bool halocontrol; - bool halocontrol_amount; +public: + bool enabled; + bool radius; + bool amount; + bool threshold; + bool edgesonly; + bool edges_radius; + bool edges_tolerance; + bool halocontrol; + bool halocontrol_amount; - bool method; - bool deconvamount; - bool deconvradius; - bool deconviter; - bool deconvdamping; + bool method; + bool deconvamount; + bool deconvradius; + bool deconviter; + bool deconvdamping; }; -class VibranceParamsEdited { +class VibranceParamsEdited +{ - public: - bool enabled; - bool pastels; - bool saturated; - bool psthreshold; - bool protectskins; - bool avoidcolorshift; - bool pastsattog; - bool skintonescurve; +public: + bool enabled; + bool pastels; + bool saturated; + bool psthreshold; + bool protectskins; + bool avoidcolorshift; + bool pastsattog; + bool skintonescurve; }; /*class ColorBoostParamsEdited { - public: + public: bool amount; bool avoidclip; bool enable_saturationlimiter; bool rstprotection; };*/ -class WBParamsEdited { +class WBParamsEdited +{ - public: - bool method; - bool temperature; - bool green; - bool equal; +public: + bool method; + bool temperature; + bool green; + bool equal; }; /*class ColorShiftParamsEdited { @@ -206,7 +216,8 @@ class WBParamsEdited { bool amount; };*/ -class DefringeParamsEdited { +class DefringeParamsEdited +{ public: bool enabled; @@ -215,14 +226,16 @@ public: bool huecurve; }; -class ImpulseDenoiseParamsEdited { +class ImpulseDenoiseParamsEdited +{ public: bool enabled; bool thresh; }; -class ColorAppearanceParamsEdited { +class ColorAppearanceParamsEdited +{ public: bool curve; @@ -258,13 +271,14 @@ public: // bool sharpcie; }; -class DirPyrDenoiseParamsEdited { +class DirPyrDenoiseParamsEdited +{ public: bool enabled; bool enhance; - bool median; - bool autochroma; + bool median; + bool autochroma; bool Ldetail; bool luma; bool chroma; @@ -273,21 +287,22 @@ public: bool gamma; bool lcurve; bool cccurve; - + // bool perform; - bool dmethod; - bool Lmethod; - bool Cmethod; - bool C2method; - bool smethod; + bool dmethod; + bool Lmethod; + bool Cmethod; + bool C2method; + bool smethod; bool medmethod; bool methodmed; bool rgbmethod; bool passes; - + }; -class EPDParamsEdited{ +class EPDParamsEdited +{ public: bool enabled; bool strength; @@ -298,145 +313,159 @@ public: }; -class SHParamsEdited { +class SHParamsEdited +{ - public: - bool enabled; - bool hq; - bool highlights; - bool htonalwidth; - bool shadows; - bool stonalwidth; - bool localcontrast; - bool radius; +public: + bool enabled; + bool hq; + bool highlights; + bool htonalwidth; + bool shadows; + bool stonalwidth; + bool localcontrast; + bool radius; }; -class CropParamsEdited { +class CropParamsEdited +{ - public: - bool enabled; - bool x; - bool y; - bool w; - bool h; - bool fixratio; - bool ratio; - bool orientation; - bool guide; +public: + bool enabled; + bool x; + bool y; + bool w; + bool h; + bool fixratio; + bool ratio; + bool orientation; + bool guide; }; -class CoarseTransformParamsEdited { +class CoarseTransformParamsEdited +{ - public: - bool rotate; - bool hflip; - bool vflip; +public: + bool rotate; + bool hflip; + bool vflip; }; -class CommonTransformParamsEdited { +class CommonTransformParamsEdited +{ - public: - bool autofill; +public: + bool autofill; }; -class RotateParamsEdited { - - public: - bool degree; +class RotateParamsEdited +{ + +public: + bool degree; }; -class DistortionParamsEdited { +class DistortionParamsEdited +{ - public: - bool amount; +public: + bool amount; }; -class LensProfParamsEdited { - public: - bool lcpFile,useDist,useVign,useCA; +class LensProfParamsEdited +{ +public: + bool lcpFile, useDist, useVign, useCA; - bool isUnchanged() const; + bool isUnchanged() const; }; -class PerspectiveParamsEdited { +class PerspectiveParamsEdited +{ - public: - bool horizontal; - bool vertical; +public: + bool horizontal; + bool vertical; }; -class GradientParamsEdited { +class GradientParamsEdited +{ - public: - bool enabled; - bool degree; - bool feather; - bool strength; - bool centerX; - bool centerY; +public: + bool enabled; + bool degree; + bool feather; + bool strength; + bool centerX; + bool centerY; }; -class PCVignetteParamsEdited { +class PCVignetteParamsEdited +{ - public: - bool enabled; - bool strength; - bool feather; - bool roundness; +public: + bool enabled; + bool strength; + bool feather; + bool roundness; }; -class VignettingParamsEdited { +class VignettingParamsEdited +{ - public: - bool amount; - bool radius; - bool strength; - bool centerX; - bool centerY; +public: + bool amount; + bool radius; + bool strength; + bool centerX; + bool centerY; }; -class ChannelMixerParamsEdited { +class ChannelMixerParamsEdited +{ - public: - bool red[3]; - bool green[3]; - bool blue[3]; +public: + bool red[3]; + bool green[3]; + bool blue[3]; }; -class BlackWhiteParamsEdited { +class BlackWhiteParamsEdited +{ + +public: + bool enabledcc; + bool enabled; + bool method; + bool filter; + bool setting; + bool mixerRed; + bool mixerOrange; + bool mixerYellow; + bool mixerGreen; + bool mixerCyan; + bool mixerBlue; + bool mixerMagenta; + bool mixerPurple; + bool gammaRed; + bool gammaGreen; + bool gammaBlue; + bool luminanceCurve; + bool beforeCurve; + bool beforeCurveMode; + bool afterCurve; + bool afterCurveMode; + bool autoc; + bool algo; - public: - bool enabledcc; - bool enabled; - bool method; - bool filter; - bool setting; - bool mixerRed; - bool mixerOrange; - bool mixerYellow; - bool mixerGreen; - bool mixerCyan; - bool mixerBlue; - bool mixerMagenta; - bool mixerPurple; - bool gammaRed; - bool gammaGreen; - bool gammaBlue; - bool luminanceCurve; - bool beforeCurve; - bool beforeCurveMode; - bool afterCurve; - bool afterCurveMode; - bool autoc; - bool algo; - }; -class CACorrParamsEdited { +class CACorrParamsEdited +{ - public: - bool red; - bool blue; +public: + bool red; + bool blue; }; /* class HRecParamsEdited { @@ -446,266 +475,276 @@ class HRecParamsEdited { bool method; }; */ -class ResizeParamsEdited { +class ResizeParamsEdited +{ - public: - bool scale; - bool appliesTo; - bool method; - bool dataspec; - bool width; - bool height; - bool enabled; +public: + bool scale; + bool appliesTo; + bool method; + bool dataspec; + bool width; + bool height; + bool enabled; }; -class ColorManagementParamsEdited { +class ColorManagementParamsEdited +{ - public: - bool input; - bool toneCurve; - bool applyLookTable; - bool applyBaselineExposureOffset; - bool applyHueSatMap; - bool blendCMSMatrix; - bool dcpIlluminant; - bool working; - bool output; - bool gamma; - bool gampos; - bool slpos; - bool gamfree; - bool freegamma; +public: + bool input; + bool toneCurve; + bool applyLookTable; + bool applyBaselineExposureOffset; + bool applyHueSatMap; + bool blendCMSMatrix; + bool dcpIlluminant; + bool working; + bool output; + bool gamma; + bool gampos; + bool slpos; + bool gamfree; + bool freegamma; }; -class WaveletParamsEdited { +class WaveletParamsEdited +{ + +public: + bool enabled; + bool strength; + bool balance; + bool iter; + bool median; + bool medianlev; + bool linkedg; + bool cbenab; + bool lipst; + bool Medgreinf; + bool avoid; + bool tmr; + bool c[9]; + bool ch[9]; + bool Lmethod; + bool CHmethod; + bool CHSLmethod; + bool EDmethod; + bool BAmethod; + bool NPmethod; + bool TMmethod; + bool HSmethod; + bool CLmethod; + bool Backmethod; + bool Tilesmethod; + bool daubcoeffmethod; + bool Dirmethod; + bool rescon; + bool resconH; + bool reschro; + bool tmrs; + bool gamma; + bool sup; + bool sky; + bool thres; + bool threshold; + bool threshold2; + bool edgedetect; + bool edgedetectthr; + bool edgedetectthr2; + bool edgesensi; + bool edgeampli; + bool chro; + bool chroma; + bool contrast; + bool edgrad; + bool edgval; + bool edgthresh; + bool thr; + bool thrH; + bool skinprotect; + bool hueskin; + bool hueskin2; + bool hllev; + bool bllev; + bool edgcont; + bool level0noise; + bool level1noise; + bool level2noise; + bool level3noise; + bool ccwcurve; + bool opacityCurveBY; + bool opacityCurveRG; + bool opacityCurveW; + bool opacityCurveWL; + bool hhcurve; + bool Chcurve; + bool pastlev; + bool satlev; + bool wavclCurve; + bool greenlow; + bool bluelow; + bool greenmed; + bool bluemed; + bool greenhigh; + bool bluehigh; + bool enacont; + bool expcontrast; + bool expchroma; + bool expedge; + bool expresid; + bool expfinal; + bool exptoning; + bool expnoise; - public: - bool enabled; - bool strength; - bool balance; - bool iter; - bool median; - bool medianlev; - bool linkedg; - bool cbenab; - bool lipst; - bool Medgreinf; - bool avoid; - bool tmr; - bool c[9]; - bool ch[9]; - bool Lmethod; - bool CHmethod; - bool CHSLmethod; - bool EDmethod; - bool BAmethod; - bool NPmethod; - bool TMmethod; - bool HSmethod; - bool CLmethod; - bool Backmethod; - bool Tilesmethod; - bool daubcoeffmethod; - bool Dirmethod; - bool rescon; - bool resconH; - bool reschro; - bool tmrs; - bool gamma; - bool sup; - bool sky; - bool thres; - bool threshold; - bool threshold2; - bool edgedetect; - bool edgedetectthr; - bool edgedetectthr2; - bool edgesensi; - bool edgeampli; - bool chro; - bool chroma; - bool contrast; - bool edgrad; - bool edgval; - bool edgthresh; - bool thr; - bool thrH; - bool skinprotect; - bool hueskin; - bool hueskin2; - bool hllev; - bool bllev; - bool edgcont; - bool level0noise; - bool level1noise; - bool level2noise; - bool level3noise; - bool ccwcurve; - bool opacityCurveBY; - bool opacityCurveRG; - bool opacityCurveW; - bool opacityCurveWL; - bool hhcurve; - bool Chcurve; - bool pastlev; - bool satlev; - bool wavclCurve; - bool greenlow; - bool bluelow; - bool greenmed; - bool bluemed; - bool greenhigh; - bool bluehigh; - bool enacont; - bool expcontrast; - bool expchroma; - bool expedge; - bool expresid; - bool expfinal; - bool exptoning; - bool expnoise; - }; -class DirPyrEqualizerParamsEdited { +class DirPyrEqualizerParamsEdited +{ - public: - bool enabled; - bool gamutlab; - bool mult[6]; - - bool threshold; - bool skinprotect; - bool hueskin; - // bool algo; +public: + bool enabled; + bool gamutlab; + bool mult[6]; + + bool threshold; + bool skinprotect; + bool hueskin; + // bool algo; }; -class HSVEqualizerParamsEdited { +class HSVEqualizerParamsEdited +{ - public: - bool hcurve; - bool scurve; - bool vcurve; +public: + bool hcurve; + bool scurve; + bool vcurve; }; -class FilmSimulationParamsEdited { +class FilmSimulationParamsEdited +{ public: bool enabled; bool clutFilename; bool strength; }; -class RAWParamsEdited { +class RAWParamsEdited +{ + +public: + class BayerSensor + { public: - class BayerSensor { - - public: - bool method; - bool ccSteps; - bool exBlack0; - bool exBlack1; - bool exBlack2; - bool exBlack3; - bool exTwoGreen; - bool dcbIterations; - bool dcbEnhance; - bool lmmseIterations; - //bool allEnhance; - bool greenEq; - bool linenoise; - - bool isUnchanged() const; - }; - - class XTransSensor { - - public: - bool method; - bool ccSteps; - bool exBlackRed; - bool exBlackGreen; - bool exBlackBlue; - - bool isUnchanged() const; - }; - - BayerSensor bayersensor; - XTransSensor xtranssensor; - - bool caCorrection; - bool caRed; - bool caBlue; - bool hotPixelFilter; - bool deadPixelFilter; - bool hotDeadPixelThresh; - bool darkFrame; - bool dfAuto; - bool ff_file; - bool ff_AutoSelect; - bool ff_BlurRadius; - bool ff_BlurType; - bool ff_AutoClipControl; - bool ff_clipControl; - bool exPos; - bool exPreser; + bool method; + bool ccSteps; + bool exBlack0; + bool exBlack1; + bool exBlack2; + bool exBlack3; + bool exTwoGreen; + bool dcbIterations; + bool dcbEnhance; + bool lmmseIterations; + //bool allEnhance; + bool greenEq; + bool linenoise; bool isUnchanged() const; -}; + }; -class ParamsEdited { + class XTransSensor + { public: - GeneralParamsEdited general; - ToneCurveParamsEdited toneCurve; - LCurveParamsEdited labCurve; - RGBCurvesParamsEdited rgbCurves; - ColorToningEdited colorToning; - SharpeningParamsEdited sharpening; - SharpeningParamsEdited prsharpening; - SharpenEdgeParamsEdited sharpenEdge; - SharpenMicroParamsEdited sharpenMicro; - VibranceParamsEdited vibrance; - ColorAppearanceParamsEdited colorappearance; - //ColorBoostParamsEdited colorBoost; - WBParamsEdited wb; - //ColorShiftParamsEdited colorShift; - //LumaDenoiseParamsEdited lumaDenoise; - //ColorDenoiseParamsEdited colorDenoise; - DefringeParamsEdited defringe; - DirPyrDenoiseParamsEdited dirpyrDenoise; - EPDParamsEdited epd; - ImpulseDenoiseParamsEdited impulseDenoise; - SHParamsEdited sh; - CropParamsEdited crop; - CoarseTransformParamsEdited coarse; - CommonTransformParamsEdited commonTrans; - RotateParamsEdited rotate; - DistortionParamsEdited distortion; - LensProfParamsEdited lensProf; - PerspectiveParamsEdited perspective; - GradientParamsEdited gradient; - PCVignetteParamsEdited pcvignette; - CACorrParamsEdited cacorrection; - VignettingParamsEdited vignetting; - ChannelMixerParamsEdited chmixer; - BlackWhiteParamsEdited blackwhite; - ResizeParamsEdited resize; - ColorManagementParamsEdited icm; - RAWParamsEdited raw; - DirPyrEqualizerParamsEdited dirpyrequalizer; - WaveletParamsEdited wavelet; - HSVEqualizerParamsEdited hsvequalizer; - FilmSimulationParamsEdited filmSimulation; - bool exif; - bool iptc; + bool method; + bool ccSteps; + bool exBlackRed; + bool exBlackGreen; + bool exBlackBlue; - ParamsEdited (bool value=false); + bool isUnchanged() const; + }; - void set (bool v); - void initFrom (const std::vector& src); - void combine (rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods, bool forceSet); + BayerSensor bayersensor; + XTransSensor xtranssensor; - bool operator== (const ParamsEdited& other); - bool operator!= (const ParamsEdited& other); + bool caCorrection; + bool caRed; + bool caBlue; + bool hotPixelFilter; + bool deadPixelFilter; + bool hotDeadPixelThresh; + bool darkFrame; + bool dfAuto; + bool ff_file; + bool ff_AutoSelect; + bool ff_BlurRadius; + bool ff_BlurType; + bool ff_AutoClipControl; + bool ff_clipControl; + bool exPos; + bool exPreser; + + bool isUnchanged() const; +}; + +class ParamsEdited +{ + +public: + GeneralParamsEdited general; + ToneCurveParamsEdited toneCurve; + LCurveParamsEdited labCurve; + RGBCurvesParamsEdited rgbCurves; + ColorToningEdited colorToning; + SharpeningParamsEdited sharpening; + SharpeningParamsEdited prsharpening; + SharpenEdgeParamsEdited sharpenEdge; + SharpenMicroParamsEdited sharpenMicro; + VibranceParamsEdited vibrance; + ColorAppearanceParamsEdited colorappearance; + //ColorBoostParamsEdited colorBoost; + WBParamsEdited wb; + //ColorShiftParamsEdited colorShift; + //LumaDenoiseParamsEdited lumaDenoise; + //ColorDenoiseParamsEdited colorDenoise; + DefringeParamsEdited defringe; + DirPyrDenoiseParamsEdited dirpyrDenoise; + EPDParamsEdited epd; + ImpulseDenoiseParamsEdited impulseDenoise; + SHParamsEdited sh; + CropParamsEdited crop; + CoarseTransformParamsEdited coarse; + CommonTransformParamsEdited commonTrans; + RotateParamsEdited rotate; + DistortionParamsEdited distortion; + LensProfParamsEdited lensProf; + PerspectiveParamsEdited perspective; + GradientParamsEdited gradient; + PCVignetteParamsEdited pcvignette; + CACorrParamsEdited cacorrection; + VignettingParamsEdited vignetting; + ChannelMixerParamsEdited chmixer; + BlackWhiteParamsEdited blackwhite; + ResizeParamsEdited resize; + ColorManagementParamsEdited icm; + RAWParamsEdited raw; + DirPyrEqualizerParamsEdited dirpyrequalizer; + WaveletParamsEdited wavelet; + HSVEqualizerParamsEdited hsvequalizer; + FilmSimulationParamsEdited filmSimulation; + bool exif; + bool iptc; + + ParamsEdited (bool value = false); + + void set (bool v); + void initFrom (const std::vector& src); + void combine (rtengine::procparams::ProcParams& toEdit, const rtengine::procparams::ProcParams& mods, bool forceSet); + + bool operator== (const ParamsEdited& other); + bool operator!= (const ParamsEdited& other); }; #endif diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 16b5e3bb7..4fbfe2d93 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -7,7 +7,7 @@ * 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 @@ -20,7 +20,8 @@ #include "multilangmgr.h" #include "paramsedited.h" -PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { +PartialPasteDlg::PartialPasteDlg (Glib::ustring title) +{ set_modal (true); set_title (title); @@ -54,13 +55,13 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { pcvignette = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PCVIGNETTE"))); gradient = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_GRADIENT"))); labcurve = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_LABCURVE"))); - colorappearance= Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORAPP"))); + colorappearance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORAPP"))); // options in detail: sharpen = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_SHARPENING"))); sharpenedge = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_SHARPENEDGE"))); sharpenmicro = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_SHARPENMICRO"))); - impden = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_IMPULSEDENOISE"))); + impden = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_IMPULSEDENOISE"))); dirpyreq = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DIRPYREQUALIZER"))); defringe = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DEFRINGE"))); @@ -74,10 +75,10 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { chmixer = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_CHANNELMIXER"))); blackwhite = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_CHANNELMIXERBW"))); dirpyrden = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DIRPYRDENOISE"))); - hsveq = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_HSVEQUALIZER"))); + hsveq = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_HSVEQUALIZER"))); filmSimulation = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FILMSIMULATION")) ); - rgbcurves = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RGBCURVES"))); - colortoning = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORTONING"))); + rgbcurves = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RGBCURVES"))); + colortoning = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COLORTONING"))); // options in lens: distortion = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DISTORTION"))); @@ -113,7 +114,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { raw_dcb_iterations = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBITERATIONS"))); raw_dcb_enhance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBENHANCE"))); //raw_all_enhance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_ALLENHANCE"))); - raw_lmmse_iterations= Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_LMMSEITERATIONS"))); + raw_lmmse_iterations = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_LMMSEITERATIONS"))); df_file = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DARKFRAMEFILE"))); df_AutoSelect = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DARKFRAMEAUTOSELECT"))); @@ -125,12 +126,14 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { Gtk::VBox* vboxes[8]; Gtk::HSeparator* hseps[8]; - for (int i=0; i<8; i++) { + + for (int i = 0; i < 8; i++) { vboxes[i] = Gtk::manage (new Gtk::VBox ()); vboxes[i]->set_border_width (6); hseps[i] = Gtk::manage (new Gtk::HSeparator ()); hseps[i]->set_name("partialPasteHeaderSep"); } + //BASIC vboxes[0]->pack_start (*basic, Gtk::PACK_SHRINK, 2); vboxes[0]->pack_start (*hseps[0], Gtk::PACK_SHRINK, 2); @@ -192,38 +195,38 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { //RAW vboxes[6]->pack_start (*raw, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*hseps[6], Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_method, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_ccSteps, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_dcb_iterations, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_dcb_enhance, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_lmmse_iterations, Gtk::PACK_SHRINK, 2); - //vboxes[6]->pack_start (*raw_all_enhance, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); - vboxes[6]->pack_start (*raw_linenoise, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_greenthresh, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_hotpix_filt, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_deadpix_filt, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); - vboxes[6]->pack_start (*raw_expos, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_preser, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_black, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); - vboxes[6]->pack_start (*df_file, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*df_AutoSelect, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); - vboxes[6]->pack_start (*ff_file, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*ff_AutoSelect, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*ff_BlurType, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*ff_BlurRadius, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*ff_ClipControl, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); - vboxes[6]->pack_start (*raw_ca_autocorrect, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_cared, Gtk::PACK_SHRINK, 2); - vboxes[6]->pack_start (*raw_cablue, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*hseps[6], Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_method, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_ccSteps, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_dcb_iterations, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_dcb_enhance, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_lmmse_iterations, Gtk::PACK_SHRINK, 2); + //vboxes[6]->pack_start (*raw_all_enhance, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[6]->pack_start (*raw_linenoise, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_greenthresh, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_hotpix_filt, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_deadpix_filt, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[6]->pack_start (*raw_expos, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_preser, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_black, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[6]->pack_start (*df_file, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*df_AutoSelect, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[6]->pack_start (*ff_file, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*ff_AutoSelect, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*ff_BlurType, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*ff_BlurRadius, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*ff_ClipControl, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[6]->pack_start (*raw_ca_autocorrect, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_cared, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_cablue, Gtk::PACK_SHRINK, 2); //META - vboxes[7]->pack_start (*meta, Gtk::PACK_SHRINK, 2); + vboxes[7]->pack_start (*meta, Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*hseps[7], Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*exifch, Gtk::PACK_SHRINK, 2); vboxes[7]->pack_start (*iptc, Gtk::PACK_SHRINK, 2); @@ -236,15 +239,20 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { vbCol2->set_border_width (8); vbCol3->set_border_width (8); - for (int i=0; i<3; i++) + for (int i = 0; i < 3; i++) { vbCol1->pack_start (*vboxes[i], Gtk::PACK_SHRINK, 2); - for (int i=3; i<6; i++) - vbCol2->pack_start (*vboxes[i], Gtk::PACK_SHRINK, 2); - for (int i=6; i<8; i++) - vbCol3->pack_start (*vboxes[i], Gtk::PACK_SHRINK, 2); + } - Gtk::VBox* vbtop = Gtk::manage (new Gtk::VBox ()); - vbtop->pack_start (*everything, Gtk::PACK_SHRINK, 2); + for (int i = 3; i < 6; i++) { + vbCol2->pack_start (*vboxes[i], Gtk::PACK_SHRINK, 2); + } + + for (int i = 6; i < 8; i++) { + vbCol3->pack_start (*vboxes[i], Gtk::PACK_SHRINK, 2); + } + + Gtk::VBox* vbtop = Gtk::manage (new Gtk::VBox ()); + vbtop->pack_start (*everything, Gtk::PACK_SHRINK, 2); vbtop->set_border_width (8); Gtk::Dialog::get_vbox()->pack_start (*vbtop, Gtk::PACK_SHRINK, 2); // TODO replace with get_content_area() with GTK upgrade @@ -273,53 +281,53 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { // This can be improved // there is currently no binding of subsettings to CheckButton 'everything' for its inconsistent status everythingConn = everything->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::everythingToggled)); - basicConn = basic->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::basicToggled)); + basicConn = basic->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::basicToggled)); detailConn = detail->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::detailToggled)); - colorConn = color->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::colorToggled)); - lensConn = lens->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::lensToggled)); - compositionConn = composition->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::compositionToggled)); + colorConn = color->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::colorToggled)); + lensConn = lens->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::lensToggled)); + compositionConn = composition->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::compositionToggled)); metaConn = meta->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::metaToggled)); rawConn = raw->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::rawToggled)); wavConn = wav->signal_toggled().connect (sigc::mem_fun(*this, &PartialPasteDlg::wavToggled)); - wbConn = wb->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); - exposureConn = exposure->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + wbConn = wb->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + exposureConn = exposure->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); shConn = sh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); epdConn = epd->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); pcvignetteConn = pcvignette->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); gradientConn = gradient->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); labcurveConn = labcurve->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); - colorappearanceConn=colorappearance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); + colorappearanceConn = colorappearance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true)); sharpenConn = sharpen->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); gradsharpenConn = sharpenedge->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); microcontrastConn = sharpenmicro->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); - impdenConn = impden->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + impdenConn = impden->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); dirpyrdenConn = dirpyrden->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); - dirpyreqConn = dirpyreq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + dirpyreqConn = dirpyreq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); defringeConn = defringe->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); - waveletConn = wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*wav, &Gtk::CheckButton::set_inconsistent), true)); + waveletConn = wavelet->signal_toggled().connect (sigc::bind (sigc::mem_fun(*wav, &Gtk::CheckButton::set_inconsistent), true)); icmConn = icm->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); - //gamcsconn = gam->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); + //gamcsconn = gam->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); vibranceConn = vibrance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); chmixerConn = chmixer->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); chmixerbwConn = blackwhite->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); - hsveqConn = hsveq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); + hsveqConn = hsveq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); filmSimulationConn = filmSimulation->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); rgbcurvesConn = rgbcurves->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); colortoningConn = colortoning->signal_toggled().connect (sigc::bind (sigc::mem_fun(*color, &Gtk::CheckButton::set_inconsistent), true)); - distortionConn = distortion->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); - cacorrConn = cacorr->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); - vignettingConn = vignetting->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); - lcpConn = lcp->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); + distortionConn = distortion->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); + cacorrConn = cacorr->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); + vignettingConn = vignetting->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); + lcpConn = lcp->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true)); - coarserotConn = coarserot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); - finerotConn = finerot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); - cropConn = crop->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); - resizeConn = resize->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); + coarserotConn = coarserot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); + finerotConn = finerot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); + cropConn = crop->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); + resizeConn = resize->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); perspectiveConn = perspective->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); commonTransConn = commonTrans->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true)); @@ -358,20 +366,21 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { show_all_children (); } -void PartialPasteDlg::everythingToggled () { +void PartialPasteDlg::everythingToggled () +{ - basicConn.block (true); - detailConn.block (true); - colorConn.block (true); - lensConn.block (true); - compositionConn.block (true); - metaConn.block (true); - rawConn.block (true); - wavConn.block (true); + basicConn.block (true); + detailConn.block (true); + colorConn.block (true); + lensConn.block (true); + compositionConn.block (true); + metaConn.block (true); + rawConn.block (true); + wavConn.block (true); - everything->set_inconsistent (false); + everything->set_inconsistent (false); - //toggle group headings + //toggle group headings basic->set_active(everything->get_active()); detail->set_active(everything->get_active()); color->set_active(everything->get_active()); @@ -391,41 +400,42 @@ void PartialPasteDlg::everythingToggled () { PartialPasteDlg::rawToggled (); PartialPasteDlg::wavToggled (); - basicConn.block (false); - detailConn.block (false); - colorConn.block (false); - lensConn.block (false); - compositionConn.block (false); - metaConn.block (false); - rawConn.block (false); - wavConn.block (false); + basicConn.block (false); + detailConn.block (false); + colorConn.block (false); + lensConn.block (false); + compositionConn.block (false); + metaConn.block (false); + rawConn.block (false); + wavConn.block (false); } -void PartialPasteDlg::rawToggled () { +void PartialPasteDlg::rawToggled () +{ - raw_methodConn.block (true); - raw_ccStepsConn.block (true); - raw_dcb_iterationsConn.block (true); - raw_dcb_enhanceConn.block (true); - //raw_all_enhanceConn.block (true); - raw_lmmse_iterationsConn.block (true); - raw_exposConn.block (true); - raw_preserConn.block (true); - raw_blackConn.block (true); - raw_ca_autocorrectConn.block (true); - raw_caredConn.block (true); - raw_cablueConn.block (true); - raw_hotpix_filtConn.block (true); - raw_deadpix_filtConn.block (true); - raw_linenoiseConn.block (true); - raw_greenthreshConn.block (true); - df_fileConn.block (true); - df_AutoSelectConn.block (true); - ff_fileConn.block (true); - ff_AutoSelectConn.block (true); - ff_BlurRadiusConn.block (true); - ff_BlurTypeConn.block (true); - ff_ClipControlConn.block (true); + raw_methodConn.block (true); + raw_ccStepsConn.block (true); + raw_dcb_iterationsConn.block (true); + raw_dcb_enhanceConn.block (true); + //raw_all_enhanceConn.block (true); + raw_lmmse_iterationsConn.block (true); + raw_exposConn.block (true); + raw_preserConn.block (true); + raw_blackConn.block (true); + raw_ca_autocorrectConn.block (true); + raw_caredConn.block (true); + raw_cablueConn.block (true); + raw_hotpix_filtConn.block (true); + raw_deadpix_filtConn.block (true); + raw_linenoiseConn.block (true); + raw_greenthreshConn.block (true); + df_fileConn.block (true); + df_AutoSelectConn.block (true); + ff_fileConn.block (true); + ff_AutoSelectConn.block (true); + ff_BlurRadiusConn.block (true); + ff_BlurTypeConn.block (true); + ff_ClipControlConn.block (true); raw->set_inconsistent (false); @@ -434,7 +444,7 @@ void PartialPasteDlg::rawToggled () { raw_dcb_iterations->set_active (raw->get_active ()); raw_dcb_enhance->set_active (raw->get_active ()); raw_lmmse_iterations->set_active (raw->get_active ()); - //raw_all_enhance->set_active (raw->get_active ()); + //raw_all_enhance->set_active (raw->get_active ()); raw_expos->set_active (raw->get_active ()); raw_preser->set_active (raw->get_active ()); raw_black->set_active (raw->get_active ()); @@ -478,7 +488,8 @@ void PartialPasteDlg::rawToggled () { ff_ClipControlConn.block (false); } -void PartialPasteDlg::basicToggled () { +void PartialPasteDlg::basicToggled () +{ wbConn.block (true); exposureConn.block (true); @@ -510,7 +521,8 @@ void PartialPasteDlg::basicToggled () { colorappearanceConn.block (false); } -void PartialPasteDlg::detailToggled () { +void PartialPasteDlg::detailToggled () +{ sharpenConn.block (true); gradsharpenConn.block(true); @@ -539,7 +551,8 @@ void PartialPasteDlg::detailToggled () { dirpyreqConn.block (false); } -void PartialPasteDlg::wavToggled () { +void PartialPasteDlg::wavToggled () +{ waveletConn.block (true); @@ -549,7 +562,8 @@ void PartialPasteDlg::wavToggled () { waveletConn.block (false); } -void PartialPasteDlg::colorToggled () { +void PartialPasteDlg::colorToggled () +{ icmConn.block (true); //gamcsconn.block (true); @@ -575,7 +589,7 @@ void PartialPasteDlg::colorToggled () { icmConn.block (false); //gamcsconn.block (false); vibranceConn.block (false); - chmixerbwConn.block (false); + chmixerbwConn.block (false); chmixerConn.block (false); hsveqConn.block (false); filmSimulationConn.block (false); @@ -583,7 +597,8 @@ void PartialPasteDlg::colorToggled () { colortoningConn.block (false); } -void PartialPasteDlg::lensToggled () { +void PartialPasteDlg::lensToggled () +{ distortionConn.block (true); cacorrConn.block (true); @@ -603,7 +618,8 @@ void PartialPasteDlg::lensToggled () { lcpConn.block (false); } -void PartialPasteDlg::compositionToggled () { +void PartialPasteDlg::compositionToggled () +{ coarserotConn.block (true); finerotConn.block (true); @@ -629,7 +645,8 @@ void PartialPasteDlg::compositionToggled () { commonTransConn.block (false); } -void PartialPasteDlg::metaToggled () { +void PartialPasteDlg::metaToggled () +{ exifchConn.block (true); iptcConn.block (true); @@ -647,10 +664,12 @@ void PartialPasteDlg::metaToggled () { * Copies the selected items from the source ProcParams+ParamsEdited(optional) * to the destination ProcParams. */ -void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, ParamsEdited* dstPE, const rtengine::procparams::ProcParams* srcPP, const ParamsEdited* srcPE) { +void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, ParamsEdited* dstPE, const rtengine::procparams::ProcParams* srcPP, const ParamsEdited* srcPE) +{ ParamsEdited falsePE; // falsePE is a workaround to set a group of ParamsEdited to false ParamsEdited filterPE(true); // Contains the initial information about the loaded values + if (srcPE) { filterPE = *srcPE; } @@ -660,86 +679,256 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param // Now we filter out the filter depending on the checked items - if (!wb->get_active ()) filterPE.wb = falsePE.wb; - if (!exposure->get_active ()) filterPE.toneCurve = falsePE.toneCurve; - if (!sh->get_active ()) filterPE.sh = falsePE.sh; - if (!epd->get_active ()) filterPE.epd = falsePE.epd; - if (!pcvignette->get_active ()) filterPE.pcvignette = falsePE.pcvignette; - if (!gradient->get_active ()) filterPE.gradient = falsePE.gradient; - if (!labcurve->get_active ()) filterPE.labCurve = falsePE.labCurve; - if (!colorappearance->get_active ()) filterPE.colorappearance= falsePE.colorappearance; + if (!wb->get_active ()) { + filterPE.wb = falsePE.wb; + } - if (!sharpen->get_active ()) filterPE.sharpening = falsePE.sharpening; - if (!sharpenedge->get_active ()) filterPE.sharpenEdge = falsePE.sharpenEdge; - if (!sharpenmicro->get_active()) filterPE.sharpenMicro = falsePE.sharpenMicro; - if (!impden->get_active ()) filterPE.impulseDenoise = falsePE.impulseDenoise; - if (!dirpyreq->get_active ()) filterPE.dirpyrequalizer = falsePE.dirpyrequalizer; - if (!defringe->get_active ()) filterPE.defringe = falsePE.defringe; - if (!dirpyrden->get_active ()) filterPE.dirpyrDenoise = falsePE.dirpyrDenoise; + if (!exposure->get_active ()) { + filterPE.toneCurve = falsePE.toneCurve; + } - if (!wavelet->get_active ()) filterPE.wavelet = falsePE.wavelet; + if (!sh->get_active ()) { + filterPE.sh = falsePE.sh; + } - if (!icm->get_active ()) filterPE.icm = falsePE.icm; - if (!vibrance->get_active ()) filterPE.vibrance = falsePE.vibrance; - if (!chmixer->get_active ()) filterPE.chmixer = falsePE.chmixer; - if (!blackwhite->get_active ()) filterPE.blackwhite = falsePE.blackwhite; - if (!hsveq->get_active ()) filterPE.hsvequalizer = falsePE.hsvequalizer; - if (!filmSimulation->get_active ()) filterPE.filmSimulation = falsePE.filmSimulation; - if (!rgbcurves->get_active ()) filterPE.rgbCurves = falsePE.rgbCurves; - if (!colortoning->get_active ()) filterPE.colorToning = falsePE.colorToning; + if (!epd->get_active ()) { + filterPE.epd = falsePE.epd; + } - if (!distortion->get_active ()) filterPE.distortion = falsePE.distortion; - if (!cacorr->get_active ()) filterPE.cacorrection = falsePE.cacorrection; - if (!vignetting->get_active ()) filterPE.vignetting = falsePE.vignetting; - if (!lcp->get_active ()) filterPE.lensProf = falsePE.lensProf; + if (!pcvignette->get_active ()) { + filterPE.pcvignette = falsePE.pcvignette; + } - if (!coarserot->get_active ()) filterPE.coarse = falsePE.coarse; - if (!finerot->get_active ()) filterPE.rotate = falsePE.rotate; - if (!crop->get_active ()) filterPE.crop = falsePE.crop; - if (!resize->get_active ()) filterPE.resize = falsePE.resize; - if (!perspective->get_active ()) filterPE.perspective = falsePE.perspective; - if (!commonTrans->get_active ()) filterPE.commonTrans = falsePE.commonTrans; + if (!gradient->get_active ()) { + filterPE.gradient = falsePE.gradient; + } - if (!exifch->get_active ()) filterPE.exif = falsePE.exif; - if (!iptc->get_active ()) filterPE.iptc = falsePE.iptc; + if (!labcurve->get_active ()) { + filterPE.labCurve = falsePE.labCurve; + } + + if (!colorappearance->get_active ()) { + filterPE.colorappearance = falsePE.colorappearance; + } + + if (!sharpen->get_active ()) { + filterPE.sharpening = falsePE.sharpening; + } + + if (!sharpenedge->get_active ()) { + filterPE.sharpenEdge = falsePE.sharpenEdge; + } + + if (!sharpenmicro->get_active()) { + filterPE.sharpenMicro = falsePE.sharpenMicro; + } + + if (!impden->get_active ()) { + filterPE.impulseDenoise = falsePE.impulseDenoise; + } + + if (!dirpyreq->get_active ()) { + filterPE.dirpyrequalizer = falsePE.dirpyrequalizer; + } + + if (!defringe->get_active ()) { + filterPE.defringe = falsePE.defringe; + } + + if (!dirpyrden->get_active ()) { + filterPE.dirpyrDenoise = falsePE.dirpyrDenoise; + } + + if (!wavelet->get_active ()) { + filterPE.wavelet = falsePE.wavelet; + } + + if (!icm->get_active ()) { + filterPE.icm = falsePE.icm; + } + + if (!vibrance->get_active ()) { + filterPE.vibrance = falsePE.vibrance; + } + + if (!chmixer->get_active ()) { + filterPE.chmixer = falsePE.chmixer; + } + + if (!blackwhite->get_active ()) { + filterPE.blackwhite = falsePE.blackwhite; + } + + if (!hsveq->get_active ()) { + filterPE.hsvequalizer = falsePE.hsvequalizer; + } + + if (!filmSimulation->get_active ()) { + filterPE.filmSimulation = falsePE.filmSimulation; + } + + if (!rgbcurves->get_active ()) { + filterPE.rgbCurves = falsePE.rgbCurves; + } + + if (!colortoning->get_active ()) { + filterPE.colorToning = falsePE.colorToning; + } + + if (!distortion->get_active ()) { + filterPE.distortion = falsePE.distortion; + } + + if (!cacorr->get_active ()) { + filterPE.cacorrection = falsePE.cacorrection; + } + + if (!vignetting->get_active ()) { + filterPE.vignetting = falsePE.vignetting; + } + + if (!lcp->get_active ()) { + filterPE.lensProf = falsePE.lensProf; + } + + if (!coarserot->get_active ()) { + filterPE.coarse = falsePE.coarse; + } + + if (!finerot->get_active ()) { + filterPE.rotate = falsePE.rotate; + } + + if (!crop->get_active ()) { + filterPE.crop = falsePE.crop; + } + + if (!resize->get_active ()) { + filterPE.resize = falsePE.resize; + } + + if (!perspective->get_active ()) { + filterPE.perspective = falsePE.perspective; + } + + if (!commonTrans->get_active ()) { + filterPE.commonTrans = falsePE.commonTrans; + } + + if (!exifch->get_active ()) { + filterPE.exif = falsePE.exif; + } + + if (!iptc->get_active ()) { + filterPE.iptc = falsePE.iptc; + } + + if (!raw_method->get_active ()) { + filterPE.raw.bayersensor.method = falsePE.raw.bayersensor.method; + filterPE.raw.xtranssensor.method = falsePE.raw.xtranssensor.method; + } + + if (!raw_ccSteps->get_active ()) { + filterPE.raw.bayersensor.ccSteps = falsePE.raw.bayersensor.ccSteps; + filterPE.raw.xtranssensor.ccSteps = falsePE.raw.xtranssensor.ccSteps; + } + + if (!raw_dcb_iterations->get_active ()) { + filterPE.raw.bayersensor.dcbIterations = falsePE.raw.bayersensor.dcbIterations; + } + + if (!raw_dcb_enhance->get_active ()) { + filterPE.raw.bayersensor.dcbEnhance = falsePE.raw.bayersensor.dcbEnhance; + } - if (!raw_method->get_active ()) { filterPE.raw.bayersensor.method = falsePE.raw.bayersensor.method; - filterPE.raw.xtranssensor.method = falsePE.raw.xtranssensor.method; } - if (!raw_ccSteps->get_active ()) { filterPE.raw.bayersensor.ccSteps = falsePE.raw.bayersensor.ccSteps; - filterPE.raw.xtranssensor.ccSteps = falsePE.raw.xtranssensor.ccSteps; } - if (!raw_dcb_iterations->get_active ()) filterPE.raw.bayersensor.dcbIterations = falsePE.raw.bayersensor.dcbIterations; - if (!raw_dcb_enhance->get_active ()) filterPE.raw.bayersensor.dcbEnhance = falsePE.raw.bayersensor.dcbEnhance; //if (!raw_all_enhance->get_active ()) filterPE.raw.bayersensor.allEnhance = falsePE.raw.bayersensor.allEnhance; - if (!raw_lmmse_iterations->get_active ()) filterPE.raw.bayersensor.lmmseIterations = falsePE.raw.bayersensor.lmmseIterations; - if (!raw_black->get_active ()) { filterPE.raw.bayersensor.exBlack0 = falsePE.raw.bayersensor.exBlack0; - filterPE.raw.bayersensor.exBlack1 = falsePE.raw.bayersensor.exBlack1; - filterPE.raw.bayersensor.exBlack2 = falsePE.raw.bayersensor.exBlack2; - filterPE.raw.bayersensor.exBlack3 = falsePE.raw.bayersensor.exBlack3; - filterPE.raw.bayersensor.exTwoGreen = falsePE.raw.bayersensor.exTwoGreen; - filterPE.raw.xtranssensor.exBlackRed = falsePE.raw.xtranssensor.exBlackRed; - filterPE.raw.xtranssensor.exBlackGreen = falsePE.raw.xtranssensor.exBlackGreen; - filterPE.raw.xtranssensor.exBlackBlue = falsePE.raw.xtranssensor.exBlackBlue; } - if (!raw_linenoise->get_active ()) filterPE.raw.bayersensor.linenoise = falsePE.raw.bayersensor.linenoise; - if (!raw_greenthresh->get_active ()) filterPE.raw.bayersensor.greenEq = falsePE.raw.bayersensor.greenEq; - if (!raw_expos->get_active ()) filterPE.raw.exPos = falsePE.raw.exPos; - if (!raw_preser->get_active ()) filterPE.raw.exPreser = falsePE.raw.exPreser; - if (!raw_ca_autocorrect->get_active ()) filterPE.raw.caCorrection = falsePE.raw.caCorrection; - if (!raw_cared->get_active ()) filterPE.raw.caRed = falsePE.raw.caRed; - if (!raw_cablue->get_active ()) filterPE.raw.caBlue = falsePE.raw.caBlue; - if (!raw_hotpix_filt->get_active ()) { filterPE.raw.hotPixelFilter = falsePE.raw.hotPixelFilter; } - if (!raw_deadpix_filt->get_active ()) { filterPE.raw.deadPixelFilter = falsePE.raw.deadPixelFilter; } - if (!raw_deadpix_filt->get_active () && !raw_hotpix_filt->get_active ()) - filterPE.raw.hotDeadPixelThresh = falsePE.raw.hotDeadPixelThresh; - if (!df_file->get_active ()) filterPE.raw.darkFrame = falsePE.raw.darkFrame; - if (!df_AutoSelect->get_active ()) filterPE.raw.dfAuto = falsePE.raw.dfAuto; - if (!ff_file->get_active ()) filterPE.raw.ff_file = falsePE.raw.ff_file; - if (!ff_AutoSelect->get_active ()) filterPE.raw.ff_AutoSelect = falsePE.raw.ff_AutoSelect; - if (!ff_BlurRadius->get_active ()) filterPE.raw.ff_BlurRadius = falsePE.raw.ff_BlurRadius; - if (!ff_BlurType->get_active ()) filterPE.raw.ff_BlurType = falsePE.raw.ff_BlurType; - if (!ff_ClipControl->get_active ()) { filterPE.raw.ff_clipControl = falsePE.raw.ff_clipControl; - filterPE.raw.ff_AutoClipControl = falsePE.raw.ff_AutoClipControl; } + if (!raw_lmmse_iterations->get_active ()) { + filterPE.raw.bayersensor.lmmseIterations = falsePE.raw.bayersensor.lmmseIterations; + } - if (dstPE) *dstPE = filterPE; + if (!raw_black->get_active ()) { + filterPE.raw.bayersensor.exBlack0 = falsePE.raw.bayersensor.exBlack0; + filterPE.raw.bayersensor.exBlack1 = falsePE.raw.bayersensor.exBlack1; + filterPE.raw.bayersensor.exBlack2 = falsePE.raw.bayersensor.exBlack2; + filterPE.raw.bayersensor.exBlack3 = falsePE.raw.bayersensor.exBlack3; + filterPE.raw.bayersensor.exTwoGreen = falsePE.raw.bayersensor.exTwoGreen; + filterPE.raw.xtranssensor.exBlackRed = falsePE.raw.xtranssensor.exBlackRed; + filterPE.raw.xtranssensor.exBlackGreen = falsePE.raw.xtranssensor.exBlackGreen; + filterPE.raw.xtranssensor.exBlackBlue = falsePE.raw.xtranssensor.exBlackBlue; + } + + if (!raw_linenoise->get_active ()) { + filterPE.raw.bayersensor.linenoise = falsePE.raw.bayersensor.linenoise; + } + + if (!raw_greenthresh->get_active ()) { + filterPE.raw.bayersensor.greenEq = falsePE.raw.bayersensor.greenEq; + } + + if (!raw_expos->get_active ()) { + filterPE.raw.exPos = falsePE.raw.exPos; + } + + if (!raw_preser->get_active ()) { + filterPE.raw.exPreser = falsePE.raw.exPreser; + } + + if (!raw_ca_autocorrect->get_active ()) { + filterPE.raw.caCorrection = falsePE.raw.caCorrection; + } + + if (!raw_cared->get_active ()) { + filterPE.raw.caRed = falsePE.raw.caRed; + } + + if (!raw_cablue->get_active ()) { + filterPE.raw.caBlue = falsePE.raw.caBlue; + } + + if (!raw_hotpix_filt->get_active ()) { + filterPE.raw.hotPixelFilter = falsePE.raw.hotPixelFilter; + } + + if (!raw_deadpix_filt->get_active ()) { + filterPE.raw.deadPixelFilter = falsePE.raw.deadPixelFilter; + } + + if (!raw_deadpix_filt->get_active () && !raw_hotpix_filt->get_active ()) { + filterPE.raw.hotDeadPixelThresh = falsePE.raw.hotDeadPixelThresh; + } + + if (!df_file->get_active ()) { + filterPE.raw.darkFrame = falsePE.raw.darkFrame; + } + + if (!df_AutoSelect->get_active ()) { + filterPE.raw.dfAuto = falsePE.raw.dfAuto; + } + + if (!ff_file->get_active ()) { + filterPE.raw.ff_file = falsePE.raw.ff_file; + } + + if (!ff_AutoSelect->get_active ()) { + filterPE.raw.ff_AutoSelect = falsePE.raw.ff_AutoSelect; + } + + if (!ff_BlurRadius->get_active ()) { + filterPE.raw.ff_BlurRadius = falsePE.raw.ff_BlurRadius; + } + + if (!ff_BlurType->get_active ()) { + filterPE.raw.ff_BlurType = falsePE.raw.ff_BlurType; + } + + if (!ff_ClipControl->get_active ()) { + filterPE.raw.ff_clipControl = falsePE.raw.ff_clipControl; + filterPE.raw.ff_AutoClipControl = falsePE.raw.ff_AutoClipControl; + } + + if (dstPE) { + *dstPE = filterPE; + } // Apply the filter! filterPE.combine(*dstPP, *srcPP, true); diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index e337a14a2..697a9b830 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -7,7 +7,7 @@ * 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 @@ -22,128 +22,129 @@ #include #include "../rtengine/rtengine.h" -class PartialPasteDlg : public Gtk::Dialog { +class PartialPasteDlg : public Gtk::Dialog +{ - public: +public: - Gtk::ScrolledWindow *scrolledwindow; + Gtk::ScrolledWindow *scrolledwindow; - Gtk::CheckButton* everything; + Gtk::CheckButton* everything; - // main groups: - Gtk::CheckButton* basic; - Gtk::CheckButton* detail; - Gtk::CheckButton* color; - Gtk::CheckButton* lens; - Gtk::CheckButton* composition; - Gtk::CheckButton* meta; - Gtk::CheckButton* raw; - Gtk::CheckButton* wav; + // main groups: + Gtk::CheckButton* basic; + Gtk::CheckButton* detail; + Gtk::CheckButton* color; + Gtk::CheckButton* lens; + Gtk::CheckButton* composition; + Gtk::CheckButton* meta; + Gtk::CheckButton* raw; + Gtk::CheckButton* wav; - // options in basic: - Gtk::CheckButton* wb; - Gtk::CheckButton* exposure; - Gtk::CheckButton* sh; - Gtk::CheckButton* epd; - Gtk::CheckButton* pcvignette; - Gtk::CheckButton* gradient; - Gtk::CheckButton* labcurve; - Gtk::CheckButton* colorappearance; + // options in basic: + Gtk::CheckButton* wb; + Gtk::CheckButton* exposure; + Gtk::CheckButton* sh; + Gtk::CheckButton* epd; + Gtk::CheckButton* pcvignette; + Gtk::CheckButton* gradient; + Gtk::CheckButton* labcurve; + Gtk::CheckButton* colorappearance; - // options in detail: - Gtk::CheckButton* sharpen; - Gtk::CheckButton* sharpenedge; - Gtk::CheckButton* sharpenmicro; - Gtk::CheckButton* impden; - //Gtk::CheckButton* waveq; - Gtk::CheckButton* dirpyrden; - Gtk::CheckButton* defringe; - Gtk::CheckButton* dirpyreq; + // options in detail: + Gtk::CheckButton* sharpen; + Gtk::CheckButton* sharpenedge; + Gtk::CheckButton* sharpenmicro; + Gtk::CheckButton* impden; + //Gtk::CheckButton* waveq; + Gtk::CheckButton* dirpyrden; + Gtk::CheckButton* defringe; + Gtk::CheckButton* dirpyreq; - // options in wavelet - Gtk::CheckButton* wavelet; + // options in wavelet + Gtk::CheckButton* wavelet; - // options in color: - Gtk::CheckButton* icm; - Gtk::CheckButton* gam; - Gtk::CheckButton* vibrance; - Gtk::CheckButton* chmixer; - Gtk::CheckButton* blackwhite; - Gtk::CheckButton* hsveq; - Gtk::CheckButton* filmSimulation; - Gtk::CheckButton* rgbcurves; - Gtk::CheckButton* colortoning; + // options in color: + Gtk::CheckButton* icm; + Gtk::CheckButton* gam; + Gtk::CheckButton* vibrance; + Gtk::CheckButton* chmixer; + Gtk::CheckButton* blackwhite; + Gtk::CheckButton* hsveq; + Gtk::CheckButton* filmSimulation; + Gtk::CheckButton* rgbcurves; + Gtk::CheckButton* colortoning; - // options in lens: - Gtk::CheckButton* distortion; - Gtk::CheckButton* cacorr; - Gtk::CheckButton* vignetting; - Gtk::CheckButton* lcp; + // options in lens: + Gtk::CheckButton* distortion; + Gtk::CheckButton* cacorr; + Gtk::CheckButton* vignetting; + Gtk::CheckButton* lcp; - // options in composition: - Gtk::CheckButton* coarserot; - Gtk::CheckButton* finerot; - Gtk::CheckButton* crop; - Gtk::CheckButton* resize; - Gtk::CheckButton* perspective; - Gtk::CheckButton* commonTrans; + // options in composition: + Gtk::CheckButton* coarserot; + Gtk::CheckButton* finerot; + Gtk::CheckButton* crop; + Gtk::CheckButton* resize; + Gtk::CheckButton* perspective; + Gtk::CheckButton* commonTrans; - // options in meta: - Gtk::CheckButton* exifch; - Gtk::CheckButton* iptc; + // options in meta: + Gtk::CheckButton* exifch; + Gtk::CheckButton* iptc; - // options in raw: - Gtk::CheckButton* raw_expos; - Gtk::CheckButton* raw_preser; - Gtk::CheckButton* raw_black; - Gtk::CheckButton* raw_ca_autocorrect; - Gtk::CheckButton* raw_cared; - Gtk::CheckButton* raw_cablue; - Gtk::CheckButton* raw_hotpix_filt; - Gtk::CheckButton* raw_deadpix_filt; - Gtk::CheckButton* raw_linenoise; - Gtk::CheckButton* raw_greenthresh; - Gtk::CheckButton* raw_method; - Gtk::CheckButton* raw_ccSteps; - Gtk::CheckButton* raw_dcb_iterations; - Gtk::CheckButton* raw_dcb_enhance; - //Gtk::CheckButton* raw_all_enhance; - Gtk::CheckButton* raw_lmmse_iterations; + // options in raw: + Gtk::CheckButton* raw_expos; + Gtk::CheckButton* raw_preser; + Gtk::CheckButton* raw_black; + Gtk::CheckButton* raw_ca_autocorrect; + Gtk::CheckButton* raw_cared; + Gtk::CheckButton* raw_cablue; + Gtk::CheckButton* raw_hotpix_filt; + Gtk::CheckButton* raw_deadpix_filt; + Gtk::CheckButton* raw_linenoise; + Gtk::CheckButton* raw_greenthresh; + Gtk::CheckButton* raw_method; + Gtk::CheckButton* raw_ccSteps; + Gtk::CheckButton* raw_dcb_iterations; + Gtk::CheckButton* raw_dcb_enhance; + //Gtk::CheckButton* raw_all_enhance; + Gtk::CheckButton* raw_lmmse_iterations; - Gtk::CheckButton* df_file; - Gtk::CheckButton* df_AutoSelect; - Gtk::CheckButton* ff_file; - Gtk::CheckButton* ff_AutoSelect; - Gtk::CheckButton* ff_BlurRadius; - Gtk::CheckButton* ff_BlurType; - Gtk::CheckButton* ff_ClipControl; + Gtk::CheckButton* df_file; + Gtk::CheckButton* df_AutoSelect; + Gtk::CheckButton* ff_file; + Gtk::CheckButton* ff_AutoSelect; + Gtk::CheckButton* ff_BlurRadius; + Gtk::CheckButton* ff_BlurType; + Gtk::CheckButton* ff_ClipControl; - sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, wavConn; + sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, wavConn; - sigc::connection wbConn, exposureConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn; - sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, dirpyreqConn, waveletConn; - sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn, colortoningConn, filmSimulationConn; - sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn; - sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn; - sigc::connection exifchConn, iptcConn, icmConn, gamcsconn; - sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn; - sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; //,raw_all_enhanceConn + sigc::connection wbConn, exposureConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn; + sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, dirpyreqConn, waveletConn; + sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn, colortoningConn, filmSimulationConn; + sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn; + sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn; + sigc::connection exifchConn, iptcConn, icmConn, gamcsconn; + sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn; + sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; //,raw_all_enhanceConn - public: - PartialPasteDlg (Glib::ustring title); +public: + PartialPasteDlg (Glib::ustring title); - void applyPaste (rtengine::procparams::ProcParams* dstPP, ParamsEdited* dstPE, const rtengine::procparams::ProcParams* srcPP, const ParamsEdited* srcPE=NULL); + void applyPaste (rtengine::procparams::ProcParams* dstPP, ParamsEdited* dstPE, const rtengine::procparams::ProcParams* srcPP, const ParamsEdited* srcPE = NULL); - void everythingToggled (); - void basicToggled (); - void detailToggled (); - void colorToggled (); - void lensToggled (); - void compositionToggled (); - void metaToggled (); - void rawToggled (); - void wavToggled (); + void everythingToggled (); + void basicToggled (); + void detailToggled (); + void colorToggled (); + void lensToggled (); + void compositionToggled (); + void metaToggled (); + void rawToggled (); + void wavToggled (); }; #endif diff --git a/rtgui/pcvignette.cc b/rtgui/pcvignette.cc index 67e6ae3c6..735b766c7 100644 --- a/rtgui/pcvignette.cc +++ b/rtgui/pcvignette.cc @@ -8,118 +8,122 @@ using namespace rtengine::procparams; PCVignette::PCVignette () : FoldableToolPanel(this, "pcvignette", M("TP_PCVIGNETTE_LABEL"), false, true) { - strength = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_STRENGTH"), -6, 6, 0.01, 0)); - strength->set_tooltip_text (M("TP_PCVIGNETTE_STRENGTH_TOOLTIP")); - strength->setAdjusterListener (this); + strength = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_STRENGTH"), -6, 6, 0.01, 0)); + strength->set_tooltip_text (M("TP_PCVIGNETTE_STRENGTH_TOOLTIP")); + strength->setAdjusterListener (this); - feather = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_FEATHER"), 0, 100, 1, 50)); - feather->set_tooltip_text (M("TP_PCVIGNETTE_FEATHER_TOOLTIP")); - feather->setAdjusterListener (this); + feather = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_FEATHER"), 0, 100, 1, 50)); + feather->set_tooltip_text (M("TP_PCVIGNETTE_FEATHER_TOOLTIP")); + feather->setAdjusterListener (this); - roundness = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_ROUNDNESS"), 0, 100, 1, 50)); - roundness->set_tooltip_text (M("TP_PCVIGNETTE_ROUNDNESS_TOOLTIP")); - roundness->setAdjusterListener (this); + roundness = Gtk::manage (new Adjuster (M("TP_PCVIGNETTE_ROUNDNESS"), 0, 100, 1, 50)); + roundness->set_tooltip_text (M("TP_PCVIGNETTE_ROUNDNESS_TOOLTIP")); + roundness->setAdjusterListener (this); - pack_start (*strength); - pack_start (*feather); - pack_start (*roundness); + pack_start (*strength); + pack_start (*feather); + pack_start (*roundness); - show_all(); + show_all(); } void PCVignette::read (const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener (); - if (pedited) { - strength->setEditedState (pedited->pcvignette.strength ? Edited : UnEdited); - feather->setEditedState (pedited->pcvignette.feather ? Edited : UnEdited); - roundness->setEditedState (pedited->pcvignette.roundness ? Edited : UnEdited); - set_inconsistent (multiImage && !pedited->pcvignette.enabled); - } + if (pedited) { + strength->setEditedState (pedited->pcvignette.strength ? Edited : UnEdited); + feather->setEditedState (pedited->pcvignette.feather ? Edited : UnEdited); + roundness->setEditedState (pedited->pcvignette.roundness ? Edited : UnEdited); + set_inconsistent (multiImage && !pedited->pcvignette.enabled); + } - setEnabled(pp->pcvignette.enabled); - strength->setValue (pp->pcvignette.strength); - feather->setValue (pp->pcvignette.feather); - roundness->setValue (pp->pcvignette.roundness); + setEnabled(pp->pcvignette.enabled); + strength->setValue (pp->pcvignette.strength); + feather->setValue (pp->pcvignette.feather); + roundness->setValue (pp->pcvignette.roundness); - enableListener (); + enableListener (); } void PCVignette::write (ProcParams* pp, ParamsEdited* pedited) { - pp->pcvignette.strength = strength->getValue (); - pp->pcvignette.feather = feather->getIntValue (); - pp->pcvignette.roundness = roundness->getIntValue (); - pp->pcvignette.enabled = getEnabled(); + pp->pcvignette.strength = strength->getValue (); + pp->pcvignette.feather = feather->getIntValue (); + pp->pcvignette.roundness = roundness->getIntValue (); + pp->pcvignette.enabled = getEnabled(); - if (pedited) { - pedited->pcvignette.strength = strength->getEditedState (); - pedited->pcvignette.feather = feather->getEditedState (); - pedited->pcvignette.roundness = roundness->getEditedState (); - pedited->pcvignette.enabled = !get_inconsistent(); - } + if (pedited) { + pedited->pcvignette.strength = strength->getEditedState (); + pedited->pcvignette.feather = feather->getEditedState (); + pedited->pcvignette.roundness = roundness->getEditedState (); + pedited->pcvignette.enabled = !get_inconsistent(); + } } void PCVignette::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { - strength->setDefault (defParams->pcvignette.strength); - feather->setDefault (defParams->pcvignette.feather); - roundness->setDefault (defParams->pcvignette.roundness); + strength->setDefault (defParams->pcvignette.strength); + feather->setDefault (defParams->pcvignette.feather); + roundness->setDefault (defParams->pcvignette.roundness); - if (pedited) { - strength->setDefaultEditedState (pedited->pcvignette.strength ? Edited : UnEdited); - feather->setDefaultEditedState (pedited->pcvignette.feather ? Edited : UnEdited); - roundness->setDefaultEditedState (pedited->pcvignette.roundness ? Edited : UnEdited); - } else { - strength->setDefaultEditedState (Irrelevant); - feather->setDefaultEditedState (Irrelevant); - roundness->setDefaultEditedState (Irrelevant); - } + if (pedited) { + strength->setDefaultEditedState (pedited->pcvignette.strength ? Edited : UnEdited); + feather->setDefaultEditedState (pedited->pcvignette.feather ? Edited : UnEdited); + roundness->setDefaultEditedState (pedited->pcvignette.roundness ? Edited : UnEdited); + } else { + strength->setDefaultEditedState (Irrelevant); + feather->setDefaultEditedState (Irrelevant); + roundness->setDefaultEditedState (Irrelevant); + } } -void PCVignette::adjusterChanged (Adjuster* a, double newval) { +void PCVignette::adjusterChanged (Adjuster* a, double newval) +{ - if (listener && getEnabled()) { - if (a == strength) - listener->panelChanged (EvPCVignetteStrength, strength->getTextValue()); - else if (a == feather) - listener->panelChanged (EvPCVignetteFeather, feather->getTextValue()); - else if (a == roundness) - listener->panelChanged (EvPCVignetteRoundness, roundness->getTextValue()); - } + if (listener && getEnabled()) { + if (a == strength) { + listener->panelChanged (EvPCVignetteStrength, strength->getTextValue()); + } else if (a == feather) { + listener->panelChanged (EvPCVignetteFeather, feather->getTextValue()); + } else if (a == roundness) { + listener->panelChanged (EvPCVignetteRoundness, roundness->getTextValue()); + } + } } -void PCVignette::enabledChanged () { +void PCVignette::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvPCVignetteEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvPCVignetteEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvPCVignetteEnabled, M("GENERAL_DISABLED")); + } } } void PCVignette::setAdjusterBehavior (bool strengthadd, bool featheradd, bool roundnessadd) { - strength->setAddMode(strengthadd); - feather->setAddMode(featheradd); - roundness->setAddMode(roundnessadd); + strength->setAddMode(strengthadd); + feather->setAddMode(featheradd); + roundness->setAddMode(roundnessadd); } void PCVignette::trimValues (rtengine::procparams::ProcParams* pp) { - strength->trimValue(pp->pcvignette.strength); - feather->trimValue(pp->pcvignette.feather); - roundness->trimValue(pp->pcvignette.roundness); + strength->trimValue(pp->pcvignette.strength); + feather->trimValue(pp->pcvignette.feather); + roundness->trimValue(pp->pcvignette.roundness); } void PCVignette::setBatchMode (bool batchMode) { - ToolPanel::setBatchMode (batchMode); - strength->showEditedCB (); - feather->showEditedCB (); - roundness->showEditedCB (); + ToolPanel::setBatchMode (batchMode); + strength->showEditedCB (); + feather->showEditedCB (); + roundness->showEditedCB (); } diff --git a/rtgui/pcvignette.h b/rtgui/pcvignette.h index c71e5c32a..84e4b0f57 100644 --- a/rtgui/pcvignette.h +++ b/rtgui/pcvignette.h @@ -8,20 +8,21 @@ #include "adjuster.h" #include "toolpanel.h" -class PCVignette : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class PCVignette : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* strength; Adjuster* feather; Adjuster* roundness; - public: +public: PCVignette (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index 1ae6a33ba..c94e9d568 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -22,18 +22,19 @@ using namespace rtengine; using namespace rtengine::procparams; -PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M("TP_PERSPECTIVE_LABEL")) { +PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M("TP_PERSPECTIVE_LABEL")) +{ Gtk::Image* ipersHL = Gtk::manage (new RTImage ("perspective-h1.png")); Gtk::Image* ipersHR = Gtk::manage (new RTImage ("perspective-h2.png")); Gtk::Image* ipersVL = Gtk::manage (new RTImage ("perspective-v1.png")); Gtk::Image* ipersVR = Gtk::manage (new RTImage ("perspective-v2.png")); - horiz = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_HORIZONTAL"), -100, 100, 0.1, 0, ipersHL, ipersHR)); - horiz->setAdjusterListener (this); + horiz = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_HORIZONTAL"), -100, 100, 0.1, 0, ipersHL, ipersHR)); + horiz->setAdjusterListener (this); - vert = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_VERTICAL"), -100, 100, 0.1, 0, ipersVL, ipersVR)); - vert->setAdjusterListener (this); + vert = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_VERTICAL"), -100, 100, 0.1, 0, ipersVL, ipersVR)); + vert->setAdjusterListener (this); pack_start (*horiz); pack_start (*vert); @@ -41,13 +42,14 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" show_all(); } -void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) { +void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); if (pedited) { - horiz->setEditedState (pedited->perspective.horizontal ? Edited : UnEdited); - vert->setEditedState (pedited->perspective.vertical ? Edited : UnEdited); + horiz->setEditedState (pedited->perspective.horizontal ? Edited : UnEdited); + vert->setEditedState (pedited->perspective.vertical ? Edited : UnEdited); } horiz->setValue (pp->perspective.horizontal); @@ -56,7 +58,8 @@ void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) { +void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->perspective.horizontal = horiz->getValue (); pp->perspective.vertical = vert->getValue (); @@ -67,40 +70,45 @@ void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) { } } -void PerspCorrection::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void PerspCorrection::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ - horiz->setDefault (defParams->perspective.horizontal); - vert->setDefault (defParams->perspective.vertical); + horiz->setDefault (defParams->perspective.horizontal); + vert->setDefault (defParams->perspective.vertical); if (pedited) { - horiz->setDefaultEditedState (pedited->perspective.horizontal ? Edited : UnEdited); - vert->setDefaultEditedState (pedited->perspective.vertical ? Edited : UnEdited); - } - else { - horiz->setDefaultEditedState (Irrelevant); - vert->setDefaultEditedState (Irrelevant); + horiz->setDefaultEditedState (pedited->perspective.horizontal ? Edited : UnEdited); + vert->setDefaultEditedState (pedited->perspective.vertical ? Edited : UnEdited); + } else { + horiz->setDefaultEditedState (Irrelevant); + vert->setDefaultEditedState (Irrelevant); } } -void PerspCorrection::adjusterChanged (Adjuster* a, double newval) { +void PerspCorrection::adjusterChanged (Adjuster* a, double newval) +{ - if (listener) + if (listener) { listener->panelChanged (EvPerspCorr, Glib::ustring::compose ("%1=%3\n%2=%4", M("TP_PERSPECTIVE_HORIZONTAL"), M("TP_PERSPECTIVE_VERTICAL"), horiz->getValue(), vert->getValue())); + } } -void PerspCorrection::setAdjusterBehavior (bool badd) { +void PerspCorrection::setAdjusterBehavior (bool badd) +{ - horiz->setAddMode(badd); - vert->setAddMode(badd); + horiz->setAddMode(badd); + vert->setAddMode(badd); } -void PerspCorrection::trimValues (rtengine::procparams::ProcParams* pp) { +void PerspCorrection::trimValues (rtengine::procparams::ProcParams* pp) +{ - horiz->trimValue(pp->perspective.horizontal); - vert->trimValue(pp->perspective.vertical); + horiz->trimValue(pp->perspective.horizontal); + vert->trimValue(pp->perspective.vertical); } -void PerspCorrection::setBatchMode (bool batchMode) { +void PerspCorrection::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); horiz->showEditedCB (); diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 35876e14b..d6a1a97c9 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -23,19 +23,20 @@ #include "adjuster.h" #include "toolpanel.h" -class PerspCorrection : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class PerspCorrection : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* horiz; Adjuster* vert; - public: +public: PerspCorrection (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/placesbrowser.cc b/rtgui/placesbrowser.cc index ba1c27873..6edb3b471 100644 --- a/rtgui/placesbrowser.cc +++ b/rtgui/placesbrowser.cc @@ -7,7 +7,7 @@ * 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 @@ -23,7 +23,8 @@ #include "guiutils.h" #include "rtimage.h" -PlacesBrowser::PlacesBrowser () : listener (NULL) { +PlacesBrowser::PlacesBrowser () : listener (NULL) +{ scrollw = Gtk::manage (new Gtk::ScrolledWindow ()); scrollw->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); @@ -42,7 +43,7 @@ PlacesBrowser::PlacesBrowser () : listener (NULL) { treeView = Gtk::manage (new Gtk::TreeView ()); treeView->unset_flags (Gtk::CAN_FOCUS); scrollw->add (*treeView); - + placesModel = Gtk::ListStore::create (placesColumns); treeView->set_model (placesModel); treeView->set_headers_visible (true); @@ -78,55 +79,67 @@ PlacesBrowser::PlacesBrowser () : listener (NULL) { } // For drive letter comparison -bool compareMountByRoot (Glib::RefPtr a,Glib::RefPtr b) { +bool compareMountByRoot (Glib::RefPtr a, Glib::RefPtr b) +{ return a->get_root()->get_parse_name() < b->get_root()->get_parse_name(); } -void PlacesBrowser::refreshPlacesList () { +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 + if (hfile && hfile->query_exists()) { - try { - 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] = 4; - newrow[placesColumns.rowSeparator] = false; + try { + 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] = 4; + newrow[placesColumns.rowSeparator] = false; + } + } catch (Gio::Error&) { + /* This will be thrown if the path doesn't exist */ } - } catch (Gio::Error&) { /* This will be thrown if the path doesn't exist */ } } // append pictures directory hfile = Gio::File::create_for_path (safe_get_user_picture_dir()); + if (hfile && hfile->query_exists()) { - try { - 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] = 4; - newrow[placesColumns.rowSeparator] = false; + try { + 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] = 4; + newrow[placesColumns.rowSeparator] = false; + } + } catch (Gio::Error&) { + /* This will be thrown if the path doesn't exist */ } - } catch (Gio::Error&) { /* This will be thrown if the path doesn't exist */ } } if (!placesModel->children().empty()) { - Gtk::TreeModel::Row newrow = *(placesModel->append()); - newrow[placesColumns.rowSeparator] = true; + Gtk::TreeModel::Row newrow = *(placesModel->append()); + newrow[placesColumns.rowSeparator] = true; } - + // scan all drives std::vector > drives = vm->get_connected_drives (); - for (size_t j=0; j > volumes = drives[j]->get_volumes (); + if (volumes.empty()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = drives[j]->get_name (); @@ -135,8 +148,10 @@ void PlacesBrowser::refreshPlacesList () { newrow[placesColumns.type] = 3; newrow[placesColumns.rowSeparator] = false; } - for (size_t i=0; i mount = volumes[i]->get_mount (); + if (mount) { // placesed volumes Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = mount->get_name (); @@ -144,8 +159,7 @@ void PlacesBrowser::refreshPlacesList () { newrow[placesColumns.root] = mount->get_root ()->get_parse_name (); newrow[placesColumns.type] = 1; newrow[placesColumns.rowSeparator] = false; - } - else { // unplacesed volumes + } else { // unplacesed volumes Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = volumes[i]->get_name (); newrow[placesColumns.icon] = volumes[i]->get_icon (); @@ -155,12 +169,14 @@ void PlacesBrowser::refreshPlacesList () { } } } - + // volumes not belonging to drives std::vector > volumes = vm->get_volumes (); - for (size_t i=0; iget_drive ()) { Glib::RefPtr mount = volumes[i]->get_mount (); + if (mount) { // placesed volumes Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = mount->get_name (); @@ -168,8 +184,7 @@ void PlacesBrowser::refreshPlacesList () { newrow[placesColumns.root] = mount->get_root ()->get_parse_name (); newrow[placesColumns.type] = 1; newrow[placesColumns.rowSeparator] = false; - } - else { // unplacesed volumes + } else { // unplacesed volumes Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = volumes[i]->get_name (); newrow[placesColumns.icon] = volumes[i]->get_icon (); @@ -186,10 +201,10 @@ void PlacesBrowser::refreshPlacesList () { #ifdef WIN32 // on Windows, it's usual to sort by drive letter, not by name - std::sort (mounts.begin(), mounts.end(), compareMountByRoot); + std::sort (mounts.begin(), mounts.end(), compareMountByRoot); #endif - for (size_t i=0; iget_volume ()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = mounts[i]->get_name (); @@ -199,15 +214,19 @@ void PlacesBrowser::refreshPlacesList () { newrow[placesColumns.rowSeparator] = false; } } + // append favorites if (!placesModel->children().empty()) { - Gtk::TreeModel::Row newrow = *(placesModel->append()); - newrow[placesColumns.rowSeparator] = true; + Gtk::TreeModel::Row newrow = *(placesModel->append()); + newrow[placesColumns.rowSeparator] = true; } - for (size_t i=0; i 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 (); @@ -220,71 +239,84 @@ void PlacesBrowser::refreshPlacesList () { } } -bool PlacesBrowser::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) { +bool PlacesBrowser::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) +{ return iter->get_value (placesColumns.rowSeparator); } -void PlacesBrowser::mountChanged (const Glib::RefPtr& m) { +void PlacesBrowser::mountChanged (const Glib::RefPtr& m) +{ GThreadLock lock; refreshPlacesList (); } -void PlacesBrowser::volumeChanged (const Glib::RefPtr& m) { +void PlacesBrowser::volumeChanged (const Glib::RefPtr& m) +{ GThreadLock lock; refreshPlacesList (); } -void PlacesBrowser::driveChanged (const Glib::RefPtr& m) { +void PlacesBrowser::driveChanged (const Glib::RefPtr& m) +{ GThreadLock lock; refreshPlacesList (); } -void PlacesBrowser::selectionChanged () { +void PlacesBrowser::selectionChanged () +{ Glib::RefPtr selection = treeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); + if (iter) { - if (iter->get_value (placesColumns.type)==2) { + if (iter->get_value (placesColumns.type) == 2) { std::vector > volumes = vm->get_volumes (); - for (size_t i=0; iget_name () == iter->get_value (placesColumns.label)) { volumes[i]->mount (); break; } - } - else if (iter->get_value (placesColumns.type)==3) { + } else if (iter->get_value (placesColumns.type) == 3) { std::vector > drives = vm->get_connected_drives (); - for (size_t i=0; iget_name () == iter->get_value (placesColumns.label)) { drives[i]->poll_for_media (); break; } - } - else if (listener) + } else if (listener) { listener->selectDir (iter->get_value (placesColumns.root)); + } } } -void PlacesBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { +void PlacesBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) +{ lastSelectedDir = dirname; } -void PlacesBrowser::addPressed () { +void PlacesBrowser::addPressed () +{ - if (lastSelectedDir=="") + if (lastSelectedDir == "") { return; + } // check if the dirname is already in the list. If yes, return. - for (size_t i=0; i 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 (); @@ -292,16 +324,19 @@ void PlacesBrowser::addPressed () { } } -void PlacesBrowser::delPressed () { +void PlacesBrowser::delPressed () +{ // lookup the selected item in the bookmark Glib::RefPtr selection = treeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); - if (iter && iter->get_value (placesColumns.type)==5) { + if (iter && iter->get_value (placesColumns.type) == 5) { std::vector::iterator i = std::find (options.favoriteDirs.begin(), options.favoriteDirs.end(), iter->get_value (placesColumns.root)); - if (i != options.favoriteDirs.end()) + + if (i != options.favoriteDirs.end()) { options.favoriteDirs.erase (i); + } } refreshPlacesList (); diff --git a/rtgui/placesbrowser.h b/rtgui/placesbrowser.h index 95a2f9ca5..e8c443345 100644 --- a/rtgui/placesbrowser.h +++ b/rtgui/placesbrowser.h @@ -7,7 +7,7 @@ * 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 @@ -25,42 +25,54 @@ #include "dirselectionlistener.h" #include "multilangmgr.h" -class PlacesBrowser : public Gtk::VBox, public DirSelectionListener { - - class PlacesColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn > icon; - Gtk::TreeModelColumn label; - Gtk::TreeModelColumn root; - Gtk::TreeModelColumn type; - Gtk::TreeModelColumn rowSeparator; - PlacesColumns() { add(icon); add(label); add(root); add(type); add(rowSeparator); } - }; - PlacesColumns placesColumns; - Gtk::ScrolledWindow* scrollw; - Gtk::TreeView* treeView; - Glib::RefPtr placesModel; - Glib::RefPtr vm; - DirBrowserRemoteInterface* listener; - Glib::ustring lastSelectedDir; - Gtk::Button* add; - Gtk::Button* del; +class PlacesBrowser : public Gtk::VBox, public DirSelectionListener +{ + class PlacesColumns : public Gtk::TreeModel::ColumnRecord + { public: - - PlacesBrowser (); - - void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { listener = l; } - void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile=""); - - void refreshPlacesList (); - void mountChanged (const Glib::RefPtr& m); - void volumeChanged (const Glib::RefPtr& v); - void driveChanged (const Glib::RefPtr& d); - bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); - void selectionChanged (); - void addPressed (); - void delPressed (); + Gtk::TreeModelColumn > icon; + Gtk::TreeModelColumn label; + Gtk::TreeModelColumn root; + Gtk::TreeModelColumn type; + Gtk::TreeModelColumn rowSeparator; + PlacesColumns() + { + add(icon); + add(label); + add(root); + add(type); + add(rowSeparator); + } + }; + PlacesColumns placesColumns; + Gtk::ScrolledWindow* scrollw; + Gtk::TreeView* treeView; + Glib::RefPtr placesModel; + Glib::RefPtr vm; + DirBrowserRemoteInterface* listener; + Glib::ustring lastSelectedDir; + Gtk::Button* add; + Gtk::Button* del; + +public: + + PlacesBrowser (); + + void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) + { + listener = l; + } + void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile = ""); + + void refreshPlacesList (); + void mountChanged (const Glib::RefPtr& m); + void volumeChanged (const Glib::RefPtr& v); + void driveChanged (const Glib::RefPtr& d); + bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); + void selectionChanged (); + void addPressed (); + void delPressed (); }; #endif diff --git a/rtgui/pointermotionlistener.h b/rtgui/pointermotionlistener.h index 422b25551..46eb42476 100644 --- a/rtgui/pointermotionlistener.h +++ b/rtgui/pointermotionlistener.h @@ -7,7 +7,7 @@ * 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 @@ -19,12 +19,13 @@ #ifndef _POINTERMOTIONLISTENER_ #define _POINTERMOTIONLISTENER_ -class PointerMotionListener { +class PointerMotionListener +{ - public: -// virtual void pointerMoved (bool validPos, int x, int y, int r, int g, int b) {} - virtual void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW,int x, int y, int r, int g, int b) {} - virtual void toggleFreeze () {} +public: +// virtual void pointerMoved (bool validPos, int x, int y, int r, int g, int b) {} + virtual void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) {} + virtual void toggleFreeze () {} }; #endif diff --git a/rtgui/popupbutton.cc b/rtgui/popupbutton.cc index f3a857bc3..440d7b420 100644 --- a/rtgui/popupbutton.cc +++ b/rtgui/popupbutton.cc @@ -27,13 +27,15 @@ * Creates a button with a contextual menu where you can select an item that the button content will reflect * * Parameters: - * label = label displayed in the button + * label = label displayed in the button */ PopUpButton::PopUpButton (const Glib::ustring& label) : Gtk::Button(), PopUpCommon(this, label) { } -void PopUpButton::show() { - PopUpCommon::show(); +void PopUpButton::show() +{ + PopUpCommon::show(); } -void PopUpButton::set_tooltip_text (const Glib::ustring &text) { - PopUpCommon::set_tooltip_text (text); +void PopUpButton::set_tooltip_text (const Glib::ustring &text) +{ + PopUpCommon::set_tooltip_text (text); } diff --git a/rtgui/popupbutton.h b/rtgui/popupbutton.h index 9361912e2..23a9211a8 100644 --- a/rtgui/popupbutton.h +++ b/rtgui/popupbutton.h @@ -24,12 +24,13 @@ #include #include "popupcommon.h" -class PopUpButton : public Gtk::Button, public PopUpCommon { +class PopUpButton : public Gtk::Button, public PopUpCommon +{ public: - PopUpButton (const Glib::ustring& label = ""); - void show (); - void set_tooltip_text (const Glib::ustring &text); + PopUpButton (const Glib::ustring& label = ""); + void show (); + void set_tooltip_text (const Glib::ustring &text); }; #endif diff --git a/rtgui/popupcommon.cc b/rtgui/popupcommon.cc index b639c5b74..881994589 100644 --- a/rtgui/popupcommon.cc +++ b/rtgui/popupcommon.cc @@ -24,136 +24,169 @@ #include "../rtengine/safegtk.h" #include "rtimage.h" -PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label) { - button = thisButton; - hasMenu = false; - imageContainer = Gtk::manage( new Gtk::HBox(false, 0)); - button->set_relief (Gtk::RELIEF_NORMAL); - button->set_border_width (0); - button->add(*imageContainer); - if (label.size()) { - Gtk::Label* buttonLabel = Gtk::manage ( new Gtk::Label(label + " ") ); - imageContainer->pack_start(*buttonLabel, Gtk::PACK_SHRINK, 0); - } - // Create the global container and put the button in it - buttonGroup = Gtk::manage( new Gtk::HBox(false, 0)); - buttonGroup->pack_start(*button, Gtk::PACK_EXPAND_WIDGET, 0); - // Create the list entry - imageFilenames.clear(); - images.clear(); - sItems.clear(); - items.clear(); - selected = -1; // -1 : means that the button is invalid - menu = 0; - buttonImage = 0; - buttonHint = ""; +PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label) +{ + button = thisButton; + hasMenu = false; + imageContainer = Gtk::manage( new Gtk::HBox(false, 0)); + button->set_relief (Gtk::RELIEF_NORMAL); + button->set_border_width (0); + button->add(*imageContainer); + + if (label.size()) { + Gtk::Label* buttonLabel = Gtk::manage ( new Gtk::Label(label + " ") ); + imageContainer->pack_start(*buttonLabel, Gtk::PACK_SHRINK, 0); + } + + // Create the global container and put the button in it + buttonGroup = Gtk::manage( new Gtk::HBox(false, 0)); + buttonGroup->pack_start(*button, Gtk::PACK_EXPAND_WIDGET, 0); + // Create the list entry + imageFilenames.clear(); + images.clear(); + sItems.clear(); + items.clear(); + selected = -1; // -1 : means that the button is invalid + menu = 0; + buttonImage = 0; + buttonHint = ""; } -PopUpCommon::~PopUpCommon () { - for (std::vector::iterator i = images.begin(); i != images.end(); ++i) - { +PopUpCommon::~PopUpCommon () +{ + for (std::vector::iterator i = images.begin(); i != images.end(); ++i) { delete *i; } - for (std::vector::iterator i = items.begin(); i != items.end(); ++i) - { + + for (std::vector::iterator i = items.begin(); i != items.end(); ++i) { delete *i; } - if (menu) delete menu; - if (buttonImage) delete buttonImage; + + if (menu) { + delete menu; + } + + if (buttonImage) { + delete buttonImage; + } + delete buttonGroup; } -PopUpCommon::type_signal_changed PopUpCommon::signal_changed() { - return message; +PopUpCommon::type_signal_changed PopUpCommon::signal_changed() +{ + return message; } -bool PopUpCommon::addEntry (Glib::ustring fileName, Glib::ustring label) { - bool added = false; - if ( label.size() ) { - imageFilenames.push_back(fileName); - sItems.push_back(label); - // Create the image - RTImage* newImage = new RTImage(fileName); - images.push_back(newImage); - int currPos = (int)images.size(); - // Create the menu item - Gtk::ImageMenuItem* newItem = new Gtk::ImageMenuItem (*newImage, label); - items.push_back(newItem); - if (selected == -1) { - // Create the menu on the first item - menu = new Gtk::Menu (); - // Create the image for the button - buttonImage = new RTImage(fileName); - // Use the first image by default - imageContainer->pack_start(*buttonImage,Gtk::PACK_EXPAND_WIDGET); - selected = 0; - } - // When there is at least 1 choice, we add the arrow button - if (images.size() == 1) { - Gtk::Button* arrowButton = Gtk::manage( new Gtk::Button() ); - RTImage* arrowImage = Gtk::manage( new RTImage("popuparrow.png") ); - arrowButton->add(*arrowImage); //menuSymbol); - arrowButton->set_relief (Gtk::RELIEF_NONE); - arrowButton->set_border_width (0); - buttonGroup->pack_start(*arrowButton,Gtk::PACK_SHRINK, 0); - arrowButton->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &PopUpCommon::showMenu) ); - hasMenu = true; - } - newItem->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &PopUpCommon::entrySelected), currPos-1)); - menu->attach (*newItem, 0, 1, currPos-1, currPos); - // The item has been created - added = true; - } - return added; +bool PopUpCommon::addEntry (Glib::ustring fileName, Glib::ustring label) +{ + bool added = false; + + if ( label.size() ) { + imageFilenames.push_back(fileName); + sItems.push_back(label); + // Create the image + RTImage* newImage = new RTImage(fileName); + images.push_back(newImage); + int currPos = (int)images.size(); + // Create the menu item + Gtk::ImageMenuItem* newItem = new Gtk::ImageMenuItem (*newImage, label); + items.push_back(newItem); + + if (selected == -1) { + // Create the menu on the first item + menu = new Gtk::Menu (); + // Create the image for the button + buttonImage = new RTImage(fileName); + // Use the first image by default + imageContainer->pack_start(*buttonImage, Gtk::PACK_EXPAND_WIDGET); + selected = 0; + } + + // When there is at least 1 choice, we add the arrow button + if (images.size() == 1) { + Gtk::Button* arrowButton = Gtk::manage( new Gtk::Button() ); + RTImage* arrowImage = Gtk::manage( new RTImage("popuparrow.png") ); + arrowButton->add(*arrowImage); //menuSymbol); + arrowButton->set_relief (Gtk::RELIEF_NONE); + arrowButton->set_border_width (0); + buttonGroup->pack_start(*arrowButton, Gtk::PACK_SHRINK, 0); + arrowButton->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &PopUpCommon::showMenu) ); + hasMenu = true; + } + + newItem->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &PopUpCommon::entrySelected), currPos - 1)); + menu->attach (*newItem, 0, 1, currPos - 1, currPos); + // The item has been created + added = true; + } + + return added; } // TODO: 'PopUpCommon::removeEntry' method to be created... -void PopUpCommon::entrySelected (int i) { - if (setSelected((unsigned int)i)) - // Emit a a signal if the selected item has changed - message.emit(selected); +void PopUpCommon::entrySelected (int i) +{ + if (setSelected((unsigned int)i)) + // Emit a a signal if the selected item has changed + { + message.emit(selected); + } } /* * Set the button image with the selected item */ -bool PopUpCommon::setSelected (int entryNum) { - if (entryNum < 0 || entryNum > ((int)images.size()-1) || (int)entryNum == selected) - return false; - else { - // Maybe we could do something better than loading the image file each time the selection is changed !? - buttonImage->changeImage(imageFilenames.at(entryNum)); - selected = entryNum; - setButtonHint(); - return true; - } +bool PopUpCommon::setSelected (int entryNum) +{ + if (entryNum < 0 || entryNum > ((int)images.size() - 1) || (int)entryNum == selected) { + return false; + } else { + // Maybe we could do something better than loading the image file each time the selection is changed !? + buttonImage->changeImage(imageFilenames.at(entryNum)); + selected = entryNum; + setButtonHint(); + return true; + } } -void PopUpCommon::show() { - menu->reposition(); - setButtonHint(); - menu->show_all(); - buttonGroup->show_all(); +void PopUpCommon::show() +{ + menu->reposition(); + setButtonHint(); + menu->show_all(); + buttonGroup->show_all(); } -void PopUpCommon::setButtonHint() { - Glib::ustring hint; - if (!buttonHint.empty()) { - hint = buttonHint; - if (selected > -1) - hint += " "; - } - if (selected > -1) - hint += sItems.at(selected); - button->set_tooltip_markup(hint); +void PopUpCommon::setButtonHint() +{ + Glib::ustring hint; + + if (!buttonHint.empty()) { + hint = buttonHint; + + if (selected > -1) { + hint += " "; + } + } + + if (selected > -1) { + hint += sItems.at(selected); + } + + button->set_tooltip_markup(hint); } -void PopUpCommon::showMenu(GdkEventButton* event) { - if (event->button == 1) menu->popup(event->button, event->time); +void PopUpCommon::showMenu(GdkEventButton* event) +{ + if (event->button == 1) { + menu->popup(event->button, event->time); + } } -void PopUpCommon::set_tooltip_text (const Glib::ustring &text) { - buttonHint = text; - setButtonHint(); +void PopUpCommon::set_tooltip_text (const Glib::ustring &text) +{ + buttonHint = text; + setButtonHint(); } diff --git a/rtgui/popupcommon.h b/rtgui/popupcommon.h index 5bdeedbf0..872beb434 100644 --- a/rtgui/popupcommon.h +++ b/rtgui/popupcommon.h @@ -27,43 +27,47 @@ #include "rtimage.h" -class PopUpCommon { +class PopUpCommon +{ public: - typedef sigc::signal type_signal_changed; - type_signal_changed signal_changed(); - Gtk::HBox* buttonGroup; // this is the widget to be packed + typedef sigc::signal type_signal_changed; + type_signal_changed signal_changed(); + Gtk::HBox* buttonGroup; // this is the widget to be packed - PopUpCommon (Gtk::Button* button, const Glib::ustring& label = ""); - virtual ~PopUpCommon (); - bool addEntry (Glib::ustring fileName, Glib::ustring label); - bool setSelected (int entryNum); - int getSelected () { return selected; } - void setButtonHint(); - void show (); - void set_tooltip_text (const Glib::ustring &text); + PopUpCommon (Gtk::Button* button, const Glib::ustring& label = ""); + virtual ~PopUpCommon (); + bool addEntry (Glib::ustring fileName, Glib::ustring label); + bool setSelected (int entryNum); + int getSelected () + { + return selected; + } + void setButtonHint(); + void show (); + void set_tooltip_text (const Glib::ustring &text); private: - type_signal_changed message; + type_signal_changed message; - /* - TODO: MenuItem::get_label() doesn't return any string, or an empty string !? - That's why we store entries strings in sItems, but it would be nice to get ride of it... - */ - std::vector sItems; - std::vector imageFilenames; - std::vector images; - std::vector items; - Glib::ustring buttonHint; - RTImage* buttonImage; - Gtk::HBox* imageContainer; - Gtk::Menu* menu; - Gtk::Button* button; - int selected; - bool hasMenu; + /* + TODO: MenuItem::get_label() doesn't return any string, or an empty string !? + That's why we store entries strings in sItems, but it would be nice to get ride of it... + */ + std::vector sItems; + std::vector imageFilenames; + std::vector images; + std::vector items; + Glib::ustring buttonHint; + RTImage* buttonImage; + Gtk::HBox* imageContainer; + Gtk::Menu* menu; + Gtk::Button* button; + int selected; + bool hasMenu; - void showMenu(GdkEventButton* event); - void entrySelected (int i); + void showMenu(GdkEventButton* event); + void entrySelected (int i); }; diff --git a/rtgui/popuptogglebutton.cc b/rtgui/popuptogglebutton.cc index 1ede81795..9676a2bea 100644 --- a/rtgui/popuptogglebutton.cc +++ b/rtgui/popuptogglebutton.cc @@ -27,13 +27,15 @@ * Creates a toggle button with a contextual menu where you can select an item that the button content will reflect * * Parameters: - * label = label displayed in the button + * label = label displayed in the button */ PopUpToggleButton::PopUpToggleButton (const Glib::ustring& label) : Gtk::ToggleButton(), PopUpCommon(this, label) { } -void PopUpToggleButton::show() { - PopUpCommon::show(); +void PopUpToggleButton::show() +{ + PopUpCommon::show(); } -void PopUpToggleButton::set_tooltip_text (const Glib::ustring &text) { - PopUpCommon::set_tooltip_text (text); +void PopUpToggleButton::set_tooltip_text (const Glib::ustring &text) +{ + PopUpCommon::set_tooltip_text (text); } diff --git a/rtgui/popuptogglebutton.h b/rtgui/popuptogglebutton.h index c6ee5ab05..58342e66c 100644 --- a/rtgui/popuptogglebutton.h +++ b/rtgui/popuptogglebutton.h @@ -24,12 +24,13 @@ #include "popupbutton.h" #include "popupcommon.h" -class PopUpToggleButton : public Gtk::ToggleButton, public PopUpCommon { +class PopUpToggleButton : public Gtk::ToggleButton, public PopUpCommon +{ public: - PopUpToggleButton (const Glib::ustring& label = ""); - void show (); - void set_tooltip_text (const Glib::ustring &text); + PopUpToggleButton (const Glib::ustring& label = ""); + void show (); + void set_tooltip_text (const Glib::ustring &text); }; #endif diff --git a/rtgui/pparamschangelistener.h b/rtgui/pparamschangelistener.h index 10eff09a5..2fac8e8bd 100644 --- a/rtgui/pparamschangelistener.h +++ b/rtgui/pparamschangelistener.h @@ -7,7 +7,7 @@ * 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 @@ -23,20 +23,22 @@ #include #include "paramsedited.h" -class PParamsChangeListener { +class PParamsChangeListener +{ - public: - virtual ~PParamsChangeListener() {} - virtual void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL) {} - virtual void clearParamChanges () {} +public: + virtual ~PParamsChangeListener() {} + virtual void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited = NULL) {} + virtual void clearParamChanges () {} }; -class BatchPParamsChangeListener { +class BatchPParamsChangeListener +{ - public: - virtual ~BatchPParamsChangeListener() {} - virtual void beginBatchPParamsChange(int numberOfEntries) {} - virtual void endBatchPParamsChange() {} +public: + virtual ~BatchPParamsChangeListener() {} + virtual void beginBatchPParamsChange(int numberOfEntries) {} + virtual void endBatchPParamsChange() {} }; #endif diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 15cfb8afa..dd02b38b9 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -7,7 +7,7 @@ * 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 @@ -34,9 +34,10 @@ extern Options options; extern Glib::ustring argv0; -Preferences::Preferences (RTWindow *rtwindow) : rprofiles(NULL), iprofiles(NULL), parent(rtwindow) { - - splash = NULL; +Preferences::Preferences (RTWindow *rtwindow) : rprofiles(NULL), iprofiles(NULL), parent(rtwindow) +{ + + splash = NULL; set_title (M("MAIN_BUTTON_PREFERENCES")); @@ -83,7 +84,7 @@ Preferences::Preferences (RTWindow *rtwindow) : rprofiles(NULL), iprofiles(NULL nb->append_page (*getGeneralPanel(), M("PREFERENCES_TAB_GENERAL")); nb->append_page (*getProcParamsPanel(), M("PREFERENCES_TAB_IMPROC")); nb->append_page (*getFileBrowserPanel(), M("PREFERENCES_TAB_BROWSER")); - nb->append_page (*getColorManagementPanel(),M("PREFERENCES_TAB_COLORMGR")); + nb->append_page (*getColorManagementPanel(), M("PREFERENCES_TAB_COLORMGR")); nb->append_page (*getBatchProcPanel(), M("PREFERENCES_BATCH_PROCESSING")); nb->append_page (*getPerformancePanel(), M("PREFERENCES_TAB_PERFORMANCE")); // Sounds only on Windows and Linux @@ -101,14 +102,16 @@ Preferences::Preferences (RTWindow *rtwindow) : rprofiles(NULL), iprofiles(NULL } -Preferences::~Preferences () { +Preferences::~Preferences () +{ profileStore.removeListener(this); options.preferencesWidth = get_width(); options.preferencesHeight = get_height(); } -Gtk::Widget* Preferences::getBatchProcPanel () { +Gtk::Widget* Preferences::getBatchProcPanel () +{ Gtk::VBox* mvbpp = Gtk::manage (new Gtk::VBox ()); mvbpp->set_border_width(4); @@ -128,11 +131,11 @@ Gtk::Widget* Preferences::getBatchProcPanel () { behModel = Gtk::TreeStore::create (behavColumns); behTreeView->set_model (behModel); - - behTreeView->append_column (M("PREFERENCES_PROPERTY"), behavColumns.label); - behTreeView->append_column_editable (M("PREFERENCES_ADD"), behavColumns.badd); - behTreeView->append_column_editable (M("PREFERENCES_SET"), behavColumns.bset); - + + behTreeView->append_column (M("PREFERENCES_PROPERTY"), behavColumns.label); + behTreeView->append_column_editable (M("PREFERENCES_ADD"), behavColumns.badd); + behTreeView->append_column_editable (M("PREFERENCES_SET"), behavColumns.bset); + Gtk::CellRendererToggle* cr_add = static_cast (behTreeView->get_column (1)->get_first_cell_renderer()); Gtk::CellRendererToggle* cr_set = static_cast (behTreeView->get_column (2)->get_first_cell_renderer()); @@ -177,7 +180,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi->set_value (behavColumns.label, M("TP_LABCURVE_LABEL")); appendBehavList (mi, M("TP_LABCURVE_BRIGHTNESS"), ADDSET_LC_BRIGHTNESS, false); appendBehavList (mi, M("TP_LABCURVE_CONTRAST"), ADDSET_LC_CONTRAST, false); - appendBehavList (mi, M("TP_LABCURVE_CHROMATICITY"), ADDSET_LC_CHROMATICITY, false); + appendBehavList (mi, M("TP_LABCURVE_CHROMATICITY"), ADDSET_LC_CHROMATICITY, false); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_SHARPENING_LABEL")); @@ -195,14 +198,14 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_DIRPYRDENOISE_LABEL")); - // appendBehavList (mi, M("TP_DIRPYRDENOISE_LUMA")+", "+M("TP_DIRPYRDENOISE_CHROMA"), ADDSET_DIRPYRDN_CHLUM, true); - appendBehavList (mi, M("TP_DIRPYRDENOISE_LUMA"),ADDSET_DIRPYRDN_LUMA, true); - appendBehavList (mi, M("TP_DIRPYRDENOISE_LDETAIL"),ADDSET_DIRPYRDN_LUMDET, true); + // appendBehavList (mi, M("TP_DIRPYRDENOISE_LUMA")+", "+M("TP_DIRPYRDENOISE_CHROMA"), ADDSET_DIRPYRDN_CHLUM, true); + appendBehavList (mi, M("TP_DIRPYRDENOISE_LUMA"), ADDSET_DIRPYRDN_LUMA, true); + appendBehavList (mi, M("TP_DIRPYRDENOISE_LDETAIL"), ADDSET_DIRPYRDN_LUMDET, true); appendBehavList (mi, M("TP_DIRPYRDENOISE_CHROMA"), ADDSET_DIRPYRDN_CHROMA, true); appendBehavList (mi, M("TP_DIRPYRDENOISE_RED"), ADDSET_DIRPYRDN_CHROMARED, true); appendBehavList (mi, M("TP_DIRPYRDENOISE_BLUE"), ADDSET_DIRPYRDN_CHROMABLUE, true); - appendBehavList (mi, M("TP_DIRPYRDENOISE_GAMMA"), ADDSET_DIRPYRDN_GAMMA, true); - appendBehavList (mi, M("TP_DIRPYRDENOISE_PASSES"), ADDSET_DIRPYRDN_PASSES, true); + appendBehavList (mi, M("TP_DIRPYRDENOISE_GAMMA"), ADDSET_DIRPYRDN_GAMMA, true); + appendBehavList (mi, M("TP_DIRPYRDENOISE_PASSES"), ADDSET_DIRPYRDN_PASSES, true); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_WBALANCE_LABEL")); @@ -212,19 +215,19 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_COLORAPP_LABEL")); - appendBehavList (mi, M("TP_COLORAPP_CIECAT_DEGREE"),ADDSET_CAT_DEGREE, true); - appendBehavList (mi, M("TP_COLORAPP_ADAPTSCENE"),ADDSET_CAT_ADAPTSCENE, true); - appendBehavList (mi, M("TP_COLORAPP_LIGHT"),ADDSET_CAT_LIGHT, true); - appendBehavList (mi, M("TP_COLORAPP_BRIGHT"),ADDSET_CAT_BRIGHT, true); - appendBehavList (mi, M("TP_COLORAPP_CHROMA"),ADDSET_CAT_CHROMA, true); - appendBehavList (mi, M("TP_COLORAPP_RSTPRO"),ADDSET_CAT_RSTPRO, true); - appendBehavList (mi, M("TP_COLORAPP_CONTRAST"),ADDSET_CAT_CONTRAST, true); - appendBehavList (mi, M("TP_COLORAPP_CONTRAST_Q"),ADDSET_CAT_CONTRAST_Q, true); - appendBehavList (mi, M("TP_COLORAPP_CHROMA_S"),ADDSET_CAT_CHROMA_S, true); - appendBehavList (mi, M("TP_COLORAPP_CHROMA_M"),ADDSET_CAT_CHROMA_M, true); - appendBehavList (mi, M("TP_COLORAPP_HUE"),ADDSET_CAT_HUE, true); - appendBehavList (mi, M("TP_COLORAPP_ADAPTVIEWING"),ADDSET_CAT_ADAPTVIEWING, true); - appendBehavList (mi, M("TP_COLORAPP_BADPIXSL"),ADDSET_CAT_BADPIX, true); + appendBehavList (mi, M("TP_COLORAPP_CIECAT_DEGREE"), ADDSET_CAT_DEGREE, true); + appendBehavList (mi, M("TP_COLORAPP_ADAPTSCENE"), ADDSET_CAT_ADAPTSCENE, true); + appendBehavList (mi, M("TP_COLORAPP_LIGHT"), ADDSET_CAT_LIGHT, true); + appendBehavList (mi, M("TP_COLORAPP_BRIGHT"), ADDSET_CAT_BRIGHT, true); + appendBehavList (mi, M("TP_COLORAPP_CHROMA"), ADDSET_CAT_CHROMA, true); + appendBehavList (mi, M("TP_COLORAPP_RSTPRO"), ADDSET_CAT_RSTPRO, true); + appendBehavList (mi, M("TP_COLORAPP_CONTRAST"), ADDSET_CAT_CONTRAST, true); + appendBehavList (mi, M("TP_COLORAPP_CONTRAST_Q"), ADDSET_CAT_CONTRAST_Q, true); + appendBehavList (mi, M("TP_COLORAPP_CHROMA_S"), ADDSET_CAT_CHROMA_S, true); + appendBehavList (mi, M("TP_COLORAPP_CHROMA_M"), ADDSET_CAT_CHROMA_M, true); + appendBehavList (mi, M("TP_COLORAPP_HUE"), ADDSET_CAT_HUE, true); + appendBehavList (mi, M("TP_COLORAPP_ADAPTVIEWING"), ADDSET_CAT_ADAPTVIEWING, true); + appendBehavList (mi, M("TP_COLORAPP_BADPIXSL"), ADDSET_CAT_BADPIX, true); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_VIBRANCE_LABEL")); @@ -238,9 +241,9 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_CHMIXER_LABEL")); - appendBehavList (mi, M("TP_CHMIXER_RED")+", "+M("TP_CHMIXER_GREEN")+", "+M("TP_CHMIXER_BLUE"), ADDSET_CHMIXER, false); - - mi = behModel->append (); + appendBehavList (mi, M("TP_CHMIXER_RED") + ", " + M("TP_CHMIXER_GREEN") + ", " + M("TP_CHMIXER_BLUE"), ADDSET_CHMIXER, false); + + mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_BWMIX_LABEL")); appendBehavList (mi, M("TP_BWMIX_MIXC"), ADDSET_BLACKWHITE_HUES, false); appendBehavList (mi, M("TP_BWMIX_GAMMA"), ADDSET_BLACKWHITE_GAMMA, false); @@ -251,11 +254,11 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_COLORTONING_LABEL")); - appendBehavList (mi, M("TP_COLORTONING_SPLITCOCO"),ADDSET_COLORTONING_SPLIT , true); - appendBehavList (mi, M("TP_COLORTONING_SATURATIONTHRESHOLD"),ADDSET_COLORTONING_SATTHRESHOLD , true); - appendBehavList (mi, M("TP_COLORTONING_SATURATEDOPACITY"),ADDSET_COLORTONING_SATOPACITY , true); - appendBehavList (mi, M("TP_COLORTONING_BALANCE"),ADDSET_COLORTONING_BALANCE , true); - appendBehavList (mi, M("TP_COLORTONING_STRENGTH"),ADDSET_COLORTONING_STRENGTH , true); + appendBehavList (mi, M("TP_COLORTONING_SPLITCOCO"), ADDSET_COLORTONING_SPLIT , true); + appendBehavList (mi, M("TP_COLORTONING_SATURATIONTHRESHOLD"), ADDSET_COLORTONING_SATTHRESHOLD , true); + appendBehavList (mi, M("TP_COLORTONING_SATURATEDOPACITY"), ADDSET_COLORTONING_SATOPACITY , true); + appendBehavList (mi, M("TP_COLORTONING_BALANCE"), ADDSET_COLORTONING_BALANCE , true); + appendBehavList (mi, M("TP_COLORTONING_STRENGTH"), ADDSET_COLORTONING_STRENGTH , true); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_ROTATE_LABEL")); @@ -267,14 +270,14 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_PERSPECTIVE_LABEL")); - appendBehavList (mi, M("TP_PERSPECTIVE_HORIZONTAL")+", "+M("TP_PERSPECTIVE_VERTICAL"), ADDSET_PERSPECTIVE, false); + appendBehavList (mi, M("TP_PERSPECTIVE_HORIZONTAL") + ", " + M("TP_PERSPECTIVE_VERTICAL"), ADDSET_PERSPECTIVE, false); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_GRADIENT_LABEL")); appendBehavList (mi, M("TP_GRADIENT_DEGREE"), ADDSET_GRADIENT_DEGREE, false); appendBehavList (mi, M("TP_GRADIENT_FEATHER"), ADDSET_GRADIENT_FEATHER, false); appendBehavList (mi, M("TP_GRADIENT_STRENGTH"), ADDSET_GRADIENT_STRENGTH, false); - appendBehavList (mi, M("TP_GRADIENT_CENTER_X")+", "+M("TP_GRADIENT_CENTER_Y"), ADDSET_GRADIENT_CENTER, false); + appendBehavList (mi, M("TP_GRADIENT_CENTER_X") + ", " + M("TP_GRADIENT_CENTER_Y"), ADDSET_GRADIENT_CENTER, false); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_PCVIGNETTE_LABEL")); @@ -284,14 +287,14 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_CACORRECTION_LABEL")); - appendBehavList (mi, M("TP_CACORRECTION_BLUE")+", "+M("TP_CACORRECTION_RED"), ADDSET_CA, true); + appendBehavList (mi, M("TP_CACORRECTION_BLUE") + ", " + M("TP_CACORRECTION_RED"), ADDSET_CA, true); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_VIGNETTING_LABEL")); appendBehavList (mi, M("TP_VIGNETTING_AMOUNT"), ADDSET_VIGN_AMOUNT, false); appendBehavList (mi, M("TP_VIGNETTING_RADIUS"), ADDSET_VIGN_RADIUS, false); appendBehavList (mi, M("TP_VIGNETTING_STRENGTH"), ADDSET_VIGN_STRENGTH, false); - appendBehavList (mi, M("TP_VIGNETTING_CENTER_X")+", "+M("TP_VIGNETTING_CENTER_Y"), ADDSET_VIGN_CENTER, false); + appendBehavList (mi, M("TP_VIGNETTING_CENTER_X") + ", " + M("TP_VIGNETTING_CENTER_Y"), ADDSET_VIGN_CENTER, false); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_DIRPYREQUALIZER_LABEL")); @@ -302,7 +305,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_WAVELET_LABEL")); appendBehavList (mi, M("TP_WAVELET_LEVELS"), ADDSET_WA_THRES, true); - // appendBehavList (mi, M("TP_WAVELET_CONTRAST"), ADDSET_WA, true); + // appendBehavList (mi, M("TP_WAVELET_CONTRAST"), ADDSET_WA, true); appendBehavList (mi, M("TP_WAVELET_THRESHOLD"), ADDSET_WA_THRESHOLD, true); appendBehavList (mi, M("TP_WAVELET_THRESHOLD2"), ADDSET_WA_THRESHOLD2, true); appendBehavList (mi, M("TP_WAVELET_CHRO"), ADDSET_WA_CHRO, true); @@ -323,7 +326,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () { appendBehavList (mi, M("TP_WAVELET_EDGEDETECT"), ADDSET_WA_EDGEDETECT, true); appendBehavList (mi, M("TP_WAVELET_EDGEDETECTTHR"), ADDSET_WA_EDGEDETECTTHR, true); appendBehavList (mi, M("TP_WAVELET_EDGEDETECTTHR2"), ADDSET_WA_EDGEDETECTTHR2, true); - + mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_PREPROCESS_LABEL")); appendBehavList (mi, M("TP_PREPROCESS_GREENEQUIL"), ADDSET_PREPROCESS_GREENEQUIL, false); @@ -344,7 +347,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () { mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_CHROMATABERR_LABEL")); - appendBehavList (mi, M("TP_RAWCACORR_CARED")+", "+M("TP_RAWCACORR_CABLUE"), ADDSET_RAWCACORR, true); + appendBehavList (mi, M("TP_RAWCACORR_CARED") + ", " + M("TP_RAWCACORR_CABLUE"), ADDSET_RAWCACORR, true); behTreeView->expand_all (); @@ -368,7 +371,8 @@ Gtk::Widget* Preferences::getBatchProcPanel () { return mvbpp; } -void Preferences::appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set) { +void Preferences::appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustring label, int id, bool set) +{ Gtk::TreeModel::iterator ci = behModel->append (parent->children()); ci->set_value (behavColumns.label, label); @@ -378,7 +382,8 @@ void Preferences::appendBehavList (Gtk::TreeModel::iterator& parent, Glib::ustri ci->set_value (behavColumns.addsetid, id); } -void Preferences::behAddRadioToggled (const Glib::ustring& path) { +void Preferences::behAddRadioToggled (const Glib::ustring& path) +{ Gtk::TreeModel::iterator iter = behModel->get_iter (path); //bool set = iter->get_value (behavColumns.bset); @@ -386,7 +391,8 @@ void Preferences::behAddRadioToggled (const Glib::ustring& path) { iter->set_value (behavColumns.badd, true); } -void Preferences::behSetRadioToggled (const Glib::ustring& path) { +void Preferences::behSetRadioToggled (const Glib::ustring& path) +{ Gtk::TreeModel::iterator iter = behModel->get_iter (path); //bool add = iter->get_value (behavColumns.badd); @@ -394,18 +400,19 @@ void Preferences::behSetRadioToggled (const Glib::ustring& path) { iter->set_value (behavColumns.badd, false); } -Gtk::Widget* Preferences::getProcParamsPanel () { +Gtk::Widget* Preferences::getProcParamsPanel () +{ Gtk::VBox* mvbpp = Gtk::manage (new Gtk::VBox ()); Gtk::Frame* fpp = Gtk::manage (new Gtk::Frame (M("PREFERENCES_IMPROCPARAMS"))); Gtk::VBox* vbpp = Gtk::manage (new Gtk::VBox ()); vbpp->set_border_width(4); - Gtk::Label* drlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORRAW")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* drlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORRAW") + ":", Gtk::ALIGN_LEFT)); rprofiles = Gtk::manage (new ProfileStoreComboBox ()); rprofiles->set_size_request(50, -1); rpconn = rprofiles->signal_changed().connect( sigc::mem_fun(*this, &Preferences::forRAWComboChanged) ); - Gtk::Label* drimg = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORIMAGE")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* drimg = Gtk::manage (new Gtk::Label (M("PREFERENCES_FORIMAGE") + ":", Gtk::ALIGN_LEFT)); iprofiles = Gtk::manage (new ProfileStoreComboBox ()); iprofiles->set_size_request(50, -1); ipconn = iprofiles->signal_changed().connect( sigc::mem_fun(*this, &Preferences::forImageComboChanged) ); @@ -423,10 +430,10 @@ Gtk::Widget* Preferences::getProcParamsPanel () { // Custom profile builder box Gtk::Frame* cpfrm = Gtk::manage( new Gtk::Frame (M("PREFERENCES_CUSTPROFBUILD")) ); - Gtk::Label* cplab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDPATH")+":", Gtk::ALIGN_LEFT) ); + Gtk::Label* cplab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDPATH") + ":", Gtk::ALIGN_LEFT) ); txtCustProfBuilderPath = Gtk::manage( new Gtk::Entry () ); txtCustProfBuilderPath->set_tooltip_markup (M("PREFERENCES_CUSTPROFBUILDHINT")); - Gtk::Label* cpltypelab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT")+":", Gtk::ALIGN_LEFT) ); + Gtk::Label* cpltypelab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT") + ":", Gtk::ALIGN_LEFT) ); custProfBuilderLabelType = Gtk::manage (new Gtk::ComboBoxText ()); custProfBuilderLabelType->append_text (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID")); custProfBuilderLabelType->append_text (M("PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME")); @@ -447,7 +454,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () { vbdp->pack_start (*saveParamsFile, Gtk::PACK_SHRINK, 4); saveParamsCache = Gtk::manage (new Gtk::CheckButton (M("PREFERENCES_PROFILESAVECACHE"))); vbdp->pack_start (*saveParamsCache, Gtk::PACK_SHRINK, 4); - Gtk::Label* lplab = Gtk::manage (new Gtk::Label (M("PREFERENCES_PROFILELOADPR")+":")); + Gtk::Label* lplab = Gtk::manage (new Gtk::Label (M("PREFERENCES_PROFILELOADPR") + ":")); loadParamsPreference = Gtk::manage (new Gtk::ComboBoxText ()); loadParamsPreference->append_text (M("PREFERENCES_PROFILEPRCACHE")); loadParamsPreference->append_text (M("PREFERENCES_PROFILEPRFILE")); @@ -462,7 +469,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () { Gtk::Frame* fdf = Gtk::manage (new Gtk::Frame (M("PREFERENCES_DARKFRAME")) ); Gtk::HBox* hb42 = Gtk::manage (new Gtk::HBox ()); darkFrameDir = Gtk::manage(new Gtk::FileChooserButton(M("PREFERENCES_DIRDARKFRAMES"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); - Gtk::Label *dfLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_DIRDARKFRAMES")+":")); + Gtk::Label *dfLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_DIRDARKFRAMES") + ":")); hb42->pack_start(*dfLab , Gtk::PACK_SHRINK, 4 ); hb42->pack_start(*darkFrameDir, Gtk::PACK_EXPAND_WIDGET, 4); dfLabel = Gtk::manage(new Gtk::Label("Found:")); @@ -480,7 +487,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () { Gtk::Frame* fff = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FLATFIELD")) ); Gtk::HBox* hb43 = Gtk::manage (new Gtk::HBox ()); flatFieldDir = Gtk::manage(new Gtk::FileChooserButton(M("PREFERENCES_FLATFIELDSDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); - Gtk::Label *ffLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_FLATFIELDSDIR")+":")); + Gtk::Label *ffLab = Gtk::manage(new Gtk::Label(M("PREFERENCES_FLATFIELDSDIR") + ":")); hb43->pack_start(*ffLab , Gtk::PACK_SHRINK, 4 ); hb43->pack_start(*flatFieldDir); ffLabel = Gtk::manage(new Gtk::Label("Found:")); @@ -517,7 +524,8 @@ Gtk::Widget* Preferences::getProcParamsPanel () { return mvbpp; } -Gtk::Widget* Preferences::getPerformancePanel () { +Gtk::Widget* Preferences::getPerformancePanel () +{ Gtk::VBox* mainContainer = Gtk::manage( new Gtk::VBox () ); mainContainer->set_border_width (4); mainContainer->set_spacing(4); @@ -554,7 +562,7 @@ Gtk::Widget* Preferences::getPerformancePanel () { clutCacheSizeSB->set_increments (1, 5); clutCacheSizeSB->set_max_length(2); // Will this be sufficient? :) #ifdef _OPENMP - clutCacheSizeSB->set_range (1, 2*omp_get_num_procs()); + clutCacheSizeSB->set_range (1, 2 * omp_get_num_procs()); #else clutCacheSizeSB->set_range (1, 8); #endif @@ -599,12 +607,12 @@ Gtk::Widget* Preferences::getPerformancePanel () { threadLimitHB->pack_start (*RGBDTLl, Gtk::PACK_SHRINK, 2); threadLimitHB->pack_end (*rgbDenoiseTreadLimitSB, Gtk::PACK_SHRINK, 2); - Gtk::Label* dnlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVDN")+":", Gtk::ALIGN_LEFT)); - Gtk::Label* dnautlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVAUTDN")+":", Gtk::ALIGN_LEFT)); - Gtk::Label* dnautsimpllab = Gtk::manage (new Gtk::Label (M("PREFERENCES_SIMPLAUT")+":", Gtk::ALIGN_LEFT)); - Gtk::Label* dntilab = Gtk::manage (new Gtk::Label (M("PREFERENCES_TINB")+":", Gtk::ALIGN_LEFT)); - Gtk::Label* dnwavlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_WAVLEV")+":", Gtk::ALIGN_LEFT)); - Gtk::Label* dnlisslab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LISS")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVDN") + ":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnautlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVAUTDN") + ":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnautsimpllab = Gtk::manage (new Gtk::Label (M("PREFERENCES_SIMPLAUT") + ":", Gtk::ALIGN_LEFT)); + Gtk::Label* dntilab = Gtk::manage (new Gtk::Label (M("PREFERENCES_TINB") + ":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnwavlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_WAVLEV") + ":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnlisslab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LISS") + ":", Gtk::ALIGN_LEFT)); dnv = Gtk::manage (new Gtk::ComboBoxText ()); dnv->append_text (M("PREFERENCES_MIN")); @@ -654,7 +662,7 @@ Gtk::Widget* Preferences::getPerformancePanel () { // <--- To be hard-coded and removed once tested cbdaubech = Gtk::manage (new Gtk::CheckButton (M("PREFERENCES_DAUB_LABEL"), Gtk::ALIGN_LEFT)); cbdaubech->set_tooltip_markup (M("PREFERENCES_DAUB_TOOLTIP")); - // vbdenoise->pack_start (*cbdaubech, Gtk::PACK_SHRINK); +// vbdenoise->pack_start (*cbdaubech, Gtk::PACK_SHRINK); // ---> fdenoise->add (*vbdenoise); mainContainer->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4); @@ -662,12 +670,13 @@ Gtk::Widget* Preferences::getPerformancePanel () { return mainContainer; } -Gtk::Widget* Preferences::getColorManagementPanel () { +Gtk::Widget* Preferences::getColorManagementPanel () +{ Gtk::VBox* mvbcm = Gtk::manage (new Gtk::VBox ()); mvbcm->set_border_width (4); - Gtk::Label* intlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_CMETRICINTENT")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* intlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_CMETRICINTENT") + ":", Gtk::ALIGN_LEFT)); intent = Gtk::manage (new Gtk::ComboBoxText ()); intent->append_text (M("PREFERENCES_INTENT_PERCEPTUAL")); intent->append_text (M("PREFERENCES_INTENT_RELATIVE")); @@ -675,7 +684,7 @@ Gtk::Widget* Preferences::getColorManagementPanel () { intent->append_text (M("PREFERENCES_INTENT_ABSOLUTE")); iccDir = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_ICCDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); - Gtk::Label* pdlabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_ICCDIR")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* pdlabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_ICCDIR") + ":", Gtk::ALIGN_LEFT)); Gtk::FileFilter monProfileFilter_colprof; monProfileFilter_colprof.set_name(M("FILECHOOSER_FILTER_COLPROF")); @@ -690,7 +699,7 @@ Gtk::Widget* Preferences::getColorManagementPanel () { monProfile = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_MONITORICC"), Gtk::FILE_CHOOSER_ACTION_OPEN)); monProfile->add_filter (monProfileFilter_colprof); monProfile->add_filter (monProfileFilter_any); - Gtk::Label* mplabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_MONITORICC")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* mplabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_MONITORICC") + ":", Gtk::ALIGN_LEFT)); #if defined(WIN32) // Auto-detection not implemented for Linux, see issue 851 cbAutoMonProfile = Gtk::manage (new Gtk::CheckButton (M("PREFERENCES_AUTOMONPROFILE"))); @@ -717,7 +726,7 @@ Gtk::Widget* Preferences::getColorManagementPanel () { Gtk::VBox* vbdp = Gtk::manage (new Gtk::VBox ()); vbdp->set_border_width (4); - Gtk::Label* viewlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_VIEW")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* viewlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_VIEW") + ":", Gtk::ALIGN_LEFT)); view = Gtk::manage (new Gtk::ComboBoxText ()); view->append_text (M("PREFERENCES_D50")); @@ -729,7 +738,7 @@ Gtk::Widget* Preferences::getColorManagementPanel () { view->append_text (M("PREFERENCES_FLUOF7")); view->append_text (M("PREFERENCES_FLUOF11")); - Gtk::Label* greylab = Gtk::manage (new Gtk::Label (M("PREFERENCES_GREY")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* greylab = Gtk::manage (new Gtk::Label (M("PREFERENCES_GREY") + ":", Gtk::ALIGN_LEFT)); grey = Gtk::manage (new Gtk::ComboBoxText ()); grey->append_text (M("PREFERENCES_GREY05")); grey->append_text (M("PREFERENCES_GREY10")); @@ -739,7 +748,7 @@ Gtk::Widget* Preferences::getColorManagementPanel () { grey->append_text (M("PREFERENCES_GREY30")); grey->append_text (M("PREFERENCES_GREY40")); - Gtk::Label* greySclab = Gtk::manage (new Gtk::Label (M("PREFERENCES_GREYSC")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* greySclab = Gtk::manage (new Gtk::Label (M("PREFERENCES_GREYSC") + ":", Gtk::ALIGN_LEFT)); greySc = Gtk::manage (new Gtk::ComboBoxText ()); greySc->append_text (M("PREFERENCES_GREYSCA")); greySc->append_text (M("PREFERENCES_GREYSC18")); @@ -768,7 +777,8 @@ Gtk::Widget* Preferences::getColorManagementPanel () { return mvbcm; } -Gtk::Widget* Preferences::getGeneralPanel () { +Gtk::Widget* Preferences::getGeneralPanel () +{ Gtk::VBox* mvbsd = Gtk::manage( new Gtk::VBox () ); @@ -777,7 +787,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { vbworkflow->set_border_width (4); Gtk::HBox* hbworkflow = Gtk::manage (new Gtk::HBox (false, 4)); - Gtk::Label* flayoutlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_EDITORLAYOUT")+":")); + Gtk::Label* flayoutlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_EDITORLAYOUT") + ":")); editorLayout = Gtk::manage (new Gtk::ComboBoxText ()); editorLayout->append_text (M("PREFERENCES_SINGLETAB")); editorLayout->append_text (M("PREFERENCES_SINGLETABVERTAB")); @@ -793,7 +803,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { vbworkflow->pack_start (*hbworkflow, Gtk::PACK_SHRINK); Gtk::HBox* curveBBoxPosHB = Gtk::manage (new Gtk::HBox (false, 4)); - Gtk::Label* curveBBoxPosL = Gtk::manage (new Gtk::Label (M("PREFERENCES_CURVEBBOXPOS")+":")); + Gtk::Label* curveBBoxPosL = Gtk::manage (new Gtk::Label (M("PREFERENCES_CURVEBBOXPOS") + ":")); Gtk::Label* curveBBoxPosRestartL = Gtk::manage (new Gtk::Label (Glib::ustring("(") + M("PREFERENCES_APPLNEXTSTARTUP") + ")")); curveBBoxPosC = Gtk::manage (new Gtk::ComboBoxText ()); curveBBoxPosC->append_text (M("PREFERENCES_CURVEBBOXPOS_ABOVE")); @@ -839,12 +849,13 @@ Gtk::Widget* Preferences::getGeneralPanel () { ckbLangAutoDetect = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_LANGAUTODETECT")) ); - Gtk::Label* langlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTLANG")+":") ); + Gtk::Label* langlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTLANG") + ":") ); languages = Gtk::manage( new Gtk::ComboBoxText () ); std::vector langs; parseDir (argv0 + "/languages", langs, ""); - for (size_t i=0; iappend_text (langs[i]); } @@ -870,32 +881,34 @@ Gtk::Widget* Preferences::getGeneralPanel () { Gtk::Label* useNextStart = Gtk::manage( new Gtk::Label (Glib::ustring("(") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); Gtk::Label* cutOverlayLabel = Gtk::manage( new Gtk::Label (M("PREFERENCES_CUTOVERLAYBRUSH") + ":") ); - butCropCol= Gtk::manage( new Gtk::ColorButton() ); + butCropCol = Gtk::manage( new Gtk::ColorButton() ); butCropCol->set_use_alpha(true); Gtk::Label* navGuideLabel = Gtk::manage( new Gtk::Label (M("PREFERENCES_NAVGUIDEBRUSH") + ":") ); - butNavGuideCol= Gtk::manage( new Gtk::ColorButton() ); + butNavGuideCol = Gtk::manage( new Gtk::ColorButton() ); butNavGuideCol->set_use_alpha(true); slimUI = Gtk::manage( new Gtk::CheckButton (M("PREFERENCES_SLIMUI")) ); hbUseSystemTheme->pack_start(*chUseSystemTheme, Gtk::PACK_SHRINK); hbUseSystemTheme->pack_start (*useNextStart, Gtk::PACK_SHRINK, 0); hbUseSystemTheme->pack_end(*slimUI, Gtk::PACK_SHRINK, 0); - vbftheme->pack_start(*hbUseSystemTheme, Gtk::PACK_SHRINK, 0); + vbftheme->pack_start(*hbUseSystemTheme, Gtk::PACK_SHRINK, 0); hbtheme = Gtk::manage( new Gtk::HBox () ); hbtheme->set_spacing (4); - Gtk::Label* themelab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTTHEME")+":") ); + Gtk::Label* themelab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTTHEME") + ":") ); theme = Gtk::manage( new Gtk::ComboBoxText () ); theme->set_active (0); std::vector themes; parseDir (argv0 + "/themes", themes, ".gtkrc"); - for (size_t i=0; iappend_text (themes[i]); - Gtk::Label* fontlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTFONT")+":") ); + for (size_t i = 0; i < themes.size(); i++) { + theme->append_text (themes[i]); + } + + Gtk::Label* fontlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTFONT") + ":") ); fontbutton = Gtk::manage( new Gtk::FontButton ()); fontbutton->set_use_size(true); fontbutton->set_font_name(options.font); @@ -932,7 +945,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { Gtk::HBox* vbhl = Gtk::manage( new Gtk::HBox () ); vbhl->set_spacing(4); - Gtk::Label* hll = Gtk::manage( new Gtk::Label (M("PREFERENCES_HLTHRESHOLD")+": ")); + Gtk::Label* hll = Gtk::manage( new Gtk::Label (M("PREFERENCES_HLTHRESHOLD") + ": ")); hlThresh = Gtk::manage( new Gtk::SpinButton () ); hlThresh->set_digits (0); hlThresh->set_increments (1, 10); @@ -944,7 +957,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { Gtk::HBox* vbsh = Gtk::manage( new Gtk::HBox () ); vbsh->set_spacing (4); - Gtk::Label* shl = Gtk::manage( new Gtk::Label (M("PREFERENCES_SHTHRESHOLD")+": ") ); + Gtk::Label* shl = Gtk::manage( new Gtk::Label (M("PREFERENCES_SHTHRESHOLD") + ": ") ); shThresh = Gtk::manage( new Gtk::SpinButton () ); shThresh->show (); shThresh->set_digits (0); @@ -954,7 +967,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { vbsh->pack_end (*shThresh, Gtk::PACK_SHRINK, 0); vbrl->pack_start (*vbsh, Gtk::PACK_SHRINK, 0); - frl->add (*vbrl); + frl->add (*vbrl); hbcd->pack_start (*frl, true, true, 0); //--- @@ -988,46 +1001,46 @@ Gtk::Widget* Preferences::getGeneralPanel () { Gtk::VBox* dgvb = Gtk::manage( new Gtk::VBox () ); Gtk::HBox* hb7c = Gtk::manage( new Gtk::HBox () ); - edOther = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_EDITORCMDLINE")+":")); - hb7c->pack_start (*edOther, Gtk::PACK_SHRINK,4); + edOther = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_EDITORCMDLINE") + ":")); + hb7c->pack_start (*edOther, Gtk::PACK_SHRINK, 4); editorToSendTo = Gtk::manage( new Gtk::Entry () ); hb7c->pack_start (*editorToSendTo); Gtk::RadioButton::Group ge = edOther->get_group(); - + #ifdef __APPLE__ - Gtk::HBox* hb7 = Gtk::manage( new Gtk::HBox () ); - edGimp = Gtk::manage( new Gtk::RadioButton ("GIMP") ); - hb7->pack_start (*edGimp, Gtk::PACK_SHRINK,4); - dgvb->pack_start (*hb7, Gtk::PACK_SHRINK, 4); - edGimp->set_group (ge); - - Gtk::HBox* hb7b = Gtk::manage( new Gtk::HBox () ); - edPS = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_PSPATH")+":")); - hb7b->pack_start (*edPS, Gtk::PACK_SHRINK,4); - psDir = Gtk::manage( new Gtk::FileChooserButton (M("PREFERENCES_PSPATH"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) ); - hb7b->pack_start (*psDir); - dgvb->pack_start (*hb7b, Gtk::PACK_SHRINK, 4); - edPS->set_group (ge); + Gtk::HBox* hb7 = Gtk::manage( new Gtk::HBox () ); + edGimp = Gtk::manage( new Gtk::RadioButton ("GIMP") ); + hb7->pack_start (*edGimp, Gtk::PACK_SHRINK, 4); + dgvb->pack_start (*hb7, Gtk::PACK_SHRINK, 4); + edGimp->set_group (ge); + + Gtk::HBox* hb7b = Gtk::manage( new Gtk::HBox () ); + edPS = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_PSPATH") + ":")); + hb7b->pack_start (*edPS, Gtk::PACK_SHRINK, 4); + psDir = Gtk::manage( new Gtk::FileChooserButton (M("PREFERENCES_PSPATH"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) ); + hb7b->pack_start (*psDir); + dgvb->pack_start (*hb7b, Gtk::PACK_SHRINK, 4); + edPS->set_group (ge); #elif defined WIN32 - Gtk::HBox* hb7 = Gtk::manage( new Gtk::HBox () ); - edGimp = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_GIMPPATH")+":") ); - hb7->pack_start (*edGimp, Gtk::PACK_SHRINK,4); - gimpDir = Gtk::manage( new Gtk::FileChooserButton (M("PREFERENCES_GIMPPATH"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) ); - hb7->pack_start (*gimpDir); - dgvb->pack_start (*hb7, Gtk::PACK_SHRINK, 4); - edGimp->set_group (ge); - - Gtk::HBox* hb7b = Gtk::manage( new Gtk::HBox ()); - edPS = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_PSPATH")+":") ); - hb7b->pack_start (*edPS, Gtk::PACK_SHRINK,4); - psDir = Gtk::manage( new Gtk::FileChooserButton (M("PREFERENCES_PSPATH"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) ); - hb7b->pack_start (*psDir); - dgvb->pack_start (*hb7b, Gtk::PACK_SHRINK, 4); - edPS->set_group (ge); + Gtk::HBox* hb7 = Gtk::manage( new Gtk::HBox () ); + edGimp = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_GIMPPATH") + ":") ); + hb7->pack_start (*edGimp, Gtk::PACK_SHRINK, 4); + gimpDir = Gtk::manage( new Gtk::FileChooserButton (M("PREFERENCES_GIMPPATH"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) ); + hb7->pack_start (*gimpDir); + dgvb->pack_start (*hb7, Gtk::PACK_SHRINK, 4); + edGimp->set_group (ge); + + Gtk::HBox* hb7b = Gtk::manage( new Gtk::HBox ()); + edPS = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_PSPATH") + ":") ); + hb7b->pack_start (*edPS, Gtk::PACK_SHRINK, 4); + psDir = Gtk::manage( new Gtk::FileChooserButton (M("PREFERENCES_PSPATH"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) ); + hb7b->pack_start (*psDir); + dgvb->pack_start (*hb7b, Gtk::PACK_SHRINK, 4); + edPS->set_group (ge); #else Gtk::HBox* hb7 = Gtk::manage( new Gtk::HBox () ); edGimp = Gtk::manage( new Gtk::RadioButton ("GIMP") ); - hb7->pack_start (*edGimp, Gtk::PACK_SHRINK,4); + hb7->pack_start (*edGimp, Gtk::PACK_SHRINK, 4); dgvb->pack_start (*hb7, Gtk::PACK_SHRINK, 4); edGimp->set_group (ge); #endif @@ -1044,11 +1057,12 @@ Gtk::Widget* Preferences::getGeneralPanel () { sconn = slimUI->signal_clicked().connect( sigc::mem_fun(*this, &Preferences::themeChanged) ); fconn = fontbutton->signal_font_set().connect( sigc::mem_fun(*this, &Preferences::fontChanged) ); usethcon = chUseSystemTheme->signal_clicked ().connect( sigc::mem_fun(*this, &Preferences::useThemeChanged) ); - + return mvbsd; } -Gtk::Widget* Preferences::getFileBrowserPanel () { +Gtk::Widget* Preferences::getFileBrowserPanel () +{ Gtk::VBox* mvbfb = Gtk::manage( new Gtk::VBox () ); mvbfb->set_border_width (4); @@ -1058,7 +1072,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { sdcurrent = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_DIRSOFTWARE")) ); sdlast = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_DIRLAST")) ); sdhome = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_DIRHOME")) ); - sdother = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_DIROTHER")+": ") ); + sdother = Gtk::manage( new Gtk::RadioButton (M("PREFERENCES_DIROTHER") + ": ") ); startupdir = Gtk::manage( new Gtk::Entry () ); Gtk::Button* sdselect = Gtk::manage( new Gtk::Button ("") ); @@ -1070,9 +1084,9 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { sdother->set_group (opts); Gtk::VBox* vbsd = Gtk::manage( new Gtk::VBox () ); - vbsd->pack_start (*sdcurrent, Gtk::PACK_SHRINK,0); - vbsd->pack_start (*sdlast, Gtk::PACK_SHRINK,0); - vbsd->pack_start (*sdhome, Gtk::PACK_SHRINK,0); + vbsd->pack_start (*sdcurrent, Gtk::PACK_SHRINK, 0); + vbsd->pack_start (*sdlast, Gtk::PACK_SHRINK, 0); + vbsd->pack_start (*sdhome, Gtk::PACK_SHRINK, 0); Gtk::HBox* otherbox = Gtk::manage( new Gtk::HBox () ); otherbox->pack_start (*sdother, Gtk::PACK_SHRINK); otherbox->pack_start (*startupdir); @@ -1103,7 +1117,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { vbro->set_border_width (4); vbro->pack_start (*showDateTime, Gtk::PACK_SHRINK, 0); - Gtk::Label* dflab = Gtk::manage( new Gtk::Label (M("PREFERENCES_DATEFORMAT")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dflab = Gtk::manage( new Gtk::Label (M("PREFERENCES_DATEFORMAT") + ":", Gtk::ALIGN_LEFT)); dateformat = Gtk::manage( new Gtk::Entry () ); dateformat->set_tooltip_markup (M("PREFERENCES_DATEFORMATHINT")); dflab->set_tooltip_markup (M("PREFERENCES_DATEFORMATHINT")); @@ -1120,7 +1134,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { vbro->pack_start (*ckbInternalThumbIfUntouched, Gtk::PACK_SHRINK, 0); Gtk::HBox* hbrecent = Gtk::manage( new Gtk::HBox () ); - Gtk::Label* labrecent = Gtk::manage( new Gtk::Label (M("PREFERENCES_MAXRECENTFOLDERS")+":") ); + Gtk::Label* labrecent = Gtk::manage( new Gtk::Label (M("PREFERENCES_MAXRECENTFOLDERS") + ":") ); maxRecentFolders = Gtk::manage( new Gtk::SpinButton () ); hbrecent->pack_start (*labrecent, Gtk::PACK_SHRINK, 4); hbrecent->pack_start (*maxRecentFolders, Gtk::PACK_SHRINK, 4); @@ -1129,7 +1143,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { maxRecentFolders->set_range (1, 25); vbro->pack_start (*hbrecent, Gtk::PACK_SHRINK, 4); - fro->add (*vbro); + fro->add (*vbro); Gtk::Frame* frmnu = Gtk::manage( new Gtk::Frame (M("PREFERENCES_MENUOPTIONS")) ); @@ -1147,14 +1161,14 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { vbmnu->pack_start (*ckbmenuGroupProfileOperations, Gtk::PACK_SHRINK, 0); vbmnu->pack_start (*ckbmenuGroupExtProg, Gtk::PACK_SHRINK, 0); - frmnu->add (*vbmnu); + frmnu->add (*vbmnu); Gtk::Frame* fre = Gtk::manage( new Gtk::Frame (M("PREFERENCES_PARSEDEXT")) ); Gtk::VBox* vbre = Gtk::manage( new Gtk::VBox () ); vbre->set_border_width (4); Gtk::HBox* hb0 = Gtk::manage( new Gtk::HBox () ); - Gtk::Label* elab = Gtk::manage( new Gtk::Label (M("PREFERENCES_PARSEDEXTADD")+":") ); + Gtk::Label* elab = Gtk::manage( new Gtk::Label (M("PREFERENCES_PARSEDEXTADD") + ":") ); hb0->pack_start (*elab, Gtk::PACK_SHRINK, 4); extension = Gtk::manage( new Gtk::Entry () ); extension->set_width_chars(5); @@ -1177,19 +1191,19 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { extensions->set_model (extensionModel); extensions->append_column_editable("Enabled", extensionColumns.enabled); extensions->append_column("Extension", extensionColumns.ext); - extensions->set_headers_visible (false); + extensions->set_headers_visible (false); vbre->pack_start (*hscrollw); vbre->pack_start (*hb0, Gtk::PACK_SHRINK, 4); - fre->add (*vbre); + fre->add (*vbre); Gtk::Frame* frc = Gtk::manage( new Gtk::Frame (M("PREFERENCES_CACHEOPTS")) ); Gtk::VBox* vbc = Gtk::manage( new Gtk::VBox () ); - frc->add (*vbc); + frc->add (*vbc); vbc->set_border_width (4); Gtk::HBox* hb3 = Gtk::manage( new Gtk::HBox () ); - Gtk::Label* chlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CACHETHUMBHEIGHT")+":") ); + Gtk::Label* chlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CACHETHUMBHEIGHT") + ":") ); maxThumbSize = Gtk::manage( new Gtk::SpinButton () ); hb3->pack_start (*chlab, Gtk::PACK_SHRINK, 4); hb3->pack_start (*maxThumbSize, Gtk::PACK_SHRINK, 4); @@ -1200,7 +1214,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { vbc->pack_start (*hb3, Gtk::PACK_SHRINK, 4); Gtk::HBox* hb4 = Gtk::manage( new Gtk::HBox () ); - Gtk::Label* celab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CACHEMAXENTRIES")+":") ); + Gtk::Label* celab = Gtk::manage( new Gtk::Label (M("PREFERENCES_CACHEMAXENTRIES") + ":") ); maxCacheEntries = Gtk::manage( new Gtk::SpinButton () ); hb4->pack_start (*celab, Gtk::PACK_SHRINK, 4); hb4->pack_start (*maxCacheEntries, Gtk::PACK_SHRINK, 4); @@ -1230,7 +1244,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { hb6->set_spacing(4); mvbfb->pack_start (*hb6, Gtk::PACK_SHRINK, 4); - + // mvbfb->pack_start (*fro, Gtk::PACK_SHRINK, 4); // mvbfb->pack_start (*fre); // mvbfb->pack_start (*frc, Gtk::PACK_SHRINK, 4); @@ -1245,7 +1259,8 @@ Gtk::Widget* Preferences::getFileBrowserPanel () { return mvbfb; } -Gtk::Widget* Preferences::getSoundPanel () { +Gtk::Widget* Preferences::getSoundPanel () +{ Gtk::VBox* pSnd = new Gtk::VBox (); ckbSndEnable = Gtk::manage( new Gtk::CheckButton (M("GENERAL_ENABLE"))); @@ -1296,38 +1311,52 @@ Gtk::Widget* Preferences::getSoundPanel () { return pSnd; } -void Preferences::parseDir (Glib::ustring dirname, std::vector& items, Glib::ustring ext) { +void Preferences::parseDir (Glib::ustring dirname, std::vector& items, Glib::ustring ext) +{ - if (dirname.empty()) + if (dirname.empty()) { return; + } // process directory Glib::Dir* dir = NULL; + try { dir = new Glib::Dir (dirname); - } - catch (const Glib::Error& e) { + } catch (const Glib::Error& e) { return; } - for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) { - Glib::ustring fname = Glib::build_filename(dirname, *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) - items.push_back (sname.substr(0,sname.size()-ext.size())); + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { + Glib::ustring fname = Glib::build_filename(dirname, *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) { + items.push_back (sname.substr(0, sname.size() - ext.size())); + } } + std::sort(items.begin(), items.end()); delete dir; } -void Preferences::storePreferences () { +void Preferences::storePreferences () +{ // With the new mechanism, we can't be sure of the availability of the DEFPROFILE_RAW & DEFPROFILE_IMG profiles, // because useBundledProfiles may be false. We're now using DEFPROFILE_INTERNAL instead, which is always available. moptions.defProfRaw = rprofiles->getFullPathFromActiveRow(); - if (moptions.defProfRaw.empty()) moptions.defProfRaw = DEFPROFILE_INTERNAL; + + if (moptions.defProfRaw.empty()) { + moptions.defProfRaw = DEFPROFILE_INTERNAL; + } + moptions.defProfImg = iprofiles->getFullPathFromActiveRow(); - if (moptions.defProfImg.empty()) moptions.defProfImg = DEFPROFILE_INTERNAL; + + if (moptions.defProfImg.empty()) { + moptions.defProfImg = DEFPROFILE_INTERNAL; + } moptions.dateFormat = dateformat->get_text(); moptions.panAccelFactor = (int)panFactor->get_value(); @@ -1348,37 +1377,45 @@ void Preferences::storePreferences () { moptions.slimUI = slimUI->get_active (); moptions.useSystemTheme = chUseSystemTheme->get_active (); - Gdk::Color cropCol=butCropCol->get_color(); - moptions.cutOverlayBrush[0]=cropCol.get_red_p(); - moptions.cutOverlayBrush[1]=cropCol.get_green_p(); - moptions.cutOverlayBrush[2]=cropCol.get_blue_p(); - moptions.cutOverlayBrush[3]=butCropCol->get_alpha()/65535.0; + Gdk::Color cropCol = butCropCol->get_color(); + moptions.cutOverlayBrush[0] = cropCol.get_red_p(); + moptions.cutOverlayBrush[1] = cropCol.get_green_p(); + moptions.cutOverlayBrush[2] = cropCol.get_blue_p(); + moptions.cutOverlayBrush[3] = butCropCol->get_alpha() / 65535.0; - Gdk::Color NavGuideCol=butNavGuideCol->get_color(); - moptions.navGuideBrush[0]=NavGuideCol.get_red_p(); - moptions.navGuideBrush[1]=NavGuideCol.get_green_p(); - moptions.navGuideBrush[2]=NavGuideCol.get_blue_p(); - moptions.navGuideBrush[3]=butNavGuideCol->get_alpha()/65535.0; + Gdk::Color NavGuideCol = butNavGuideCol->get_color(); + moptions.navGuideBrush[0] = NavGuideCol.get_red_p(); + moptions.navGuideBrush[1] = NavGuideCol.get_green_p(); + moptions.navGuideBrush[2] = NavGuideCol.get_blue_p(); + moptions.navGuideBrush[3] = butNavGuideCol->get_alpha() / 65535.0; moptions.font = fontbutton->get_font_name(); -#ifdef WIN32 +#ifdef WIN32 moptions.gimpDir = gimpDir->get_filename (); moptions.psDir = psDir->get_filename (); #elif defined __APPLE__ - moptions.psDir = psDir->get_filename (); + moptions.psDir = psDir->get_filename (); #endif moptions.customEditorProg = editorToSendTo->get_text (); - if (edGimp->get_active ()) + + if (edGimp->get_active ()) { moptions.editorToSendTo = 1; -#ifdef WIN32 - else if (edPS->get_active ()) + } + +#ifdef WIN32 + else if (edPS->get_active ()) { moptions.editorToSendTo = 2; -#elif defined __APPLE__ - else if (edPS->get_active ()) - moptions.editorToSendTo = 2; + } + +#elif defined __APPLE__ + else if (edPS->get_active ()) { + moptions.editorToSendTo = 2; + } + #endif - else if (edOther->get_active ()) + else if (edOther->get_active ()) { moptions.editorToSendTo = 3; + } moptions.CPBPath = txtCustProfBuilderPath->get_text(); moptions.CPBKeys = CPBKeyType(custProfBuilderLabelType->get_active_row_number()); @@ -1392,26 +1429,27 @@ void Preferences::storePreferences () { moptions.rtSettings.viewingdevice = view->get_active_row_number (); moptions.rtSettings.viewingdevicegrey = grey->get_active_row_number (); moptions.rtSettings.viewinggreySc = greySc->get_active_row_number (); - // moptions.rtSettings.autocielab = cbAutocielab->get_active (); - moptions.rtSettings.ciecamfloat = cbciecamfloat->get_active (); - moptions.rtSettings.HistogramWorking = ckbHistogramWorking->get_active (); + // moptions.rtSettings.autocielab = cbAutocielab->get_active (); + moptions.rtSettings.ciecamfloat = cbciecamfloat->get_active (); + moptions.rtSettings.HistogramWorking = ckbHistogramWorking->get_active (); moptions.rtSettings.leveldnv = dnv->get_active_row_number (); moptions.rtSettings.leveldnti = dnti->get_active_row_number (); moptions.rtSettings.leveldnliss = dnliss->get_active_row_number (); moptions.rtSettings.leveldnaut = dnaut->get_active_row_number (); moptions.rtSettings.nrwavlevel = dnwavlev->get_active_row_number (); moptions.rtSettings.leveldnautsimpl = dnautsimpl->get_active_row_number (); - moptions.rtSettings.daubech = cbdaubech->get_active (); + moptions.rtSettings.daubech = cbdaubech->get_active (); moptions.prevdemo = (prevdemo_t)cprevdemo->get_active_row_number (); - moptions.serializeTiffRead = ctiffserialize->get_active(); - if (sdcurrent->get_active ()) + moptions.serializeTiffRead = ctiffserialize->get_active(); + + if (sdcurrent->get_active ()) { moptions.startupDir = STARTUPDIR_CURRENT; - else if (sdhome->get_active ()) + } else if (sdhome->get_active ()) { moptions.startupDir = STARTUPDIR_HOME; - else if (sdlast->get_active ()) + } else if (sdlast->get_active ()) { moptions.startupDir = STARTUPDIR_LAST; - else if (sdother->get_active ()) { + } else if (sdother->get_active ()) { moptions.startupDir = STARTUPDIR_CUSTOM; moptions.startupPath = startupdir->get_text(); } @@ -1419,7 +1457,8 @@ void Preferences::storePreferences () { moptions.parseExtensions.clear (); moptions.parseExtensionsEnabled.clear (); Gtk::TreeNodeChildren c = extensionModel->children (); - for (size_t i=0; iget_filename(); moptions.baBehav.resize (ADDSET_PARAM_NUM); - for (Gtk::TreeIter sections=behModel->children().begin(); sections!=behModel->children().end(); sections++) - for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) - moptions.baBehav[adjs->get_value (behavColumns.addsetid)] = adjs->get_value (behavColumns.badd); - int editorMode=editorLayout->get_active_row_number(); - moptions.tabbedUI = (editorMode>1); - moptions.multiDisplayMode = editorMode==3 ? 1:0; - moptions.mainNBVertical = editorMode==1; + for (Gtk::TreeIter sections = behModel->children().begin(); sections != behModel->children().end(); sections++) + for (Gtk::TreeIter adjs = sections->children().begin(); adjs != sections->children().end(); adjs++) { + moptions.baBehav[adjs->get_value (behavColumns.addsetid)] = adjs->get_value (behavColumns.badd); + } + + int editorMode = editorLayout->get_active_row_number(); + moptions.tabbedUI = (editorMode > 1); + moptions.multiDisplayMode = editorMode == 3 ? 1 : 0; + moptions.mainNBVertical = editorMode == 1; moptions.curvebboxpos = curveBBoxPosC->get_active_row_number(); moptions.histogramPosition = ckbHistogramPositionLeft->get_active() ? 1 : 2; @@ -1475,7 +1516,8 @@ void Preferences::storePreferences () { #endif } -void Preferences::fillPreferences () { +void Preferences::fillPreferences () +{ tconn.block (true); sconn.block (true); @@ -1494,17 +1536,24 @@ void Preferences::fillPreferences () { rememberZoomPanCheckbutton->set_active (moptions.rememberZoomAndPan); ctiffserialize->set_active(moptions.serializeTiffRead); #if !defined(__APPLE__) // monitor profile not supported on apple - if (safe_file_test (moptions.rtSettings.monitorProfile, Glib::FILE_TEST_EXISTS)) + + if (safe_file_test (moptions.rtSettings.monitorProfile, Glib::FILE_TEST_EXISTS)) { monProfile->set_filename (moptions.rtSettings.monitorProfile); - if (moptions.rtSettings.monitorProfile.empty()) + } + + if (moptions.rtSettings.monitorProfile.empty()) { monProfile->set_current_folder (moptions.rtSettings.iccDirectory); + } + #if defined(WIN32) cbAutoMonProfile->set_active(moptions.rtSettings.autoMonitorProfile); #endif #endif - if (Glib::file_test (moptions.rtSettings.iccDirectory, Glib::FILE_TEST_IS_DIR)) + if (Glib::file_test (moptions.rtSettings.iccDirectory, Glib::FILE_TEST_IS_DIR)) { iccDir->set_current_folder (moptions.rtSettings.iccDirectory); + } + intent->set_active (moptions.rtSettings.colorimetricIntent); view->set_active (moptions.rtSettings.viewingdevice); grey->set_active (moptions.rtSettings.viewingdevicegrey); @@ -1517,10 +1566,10 @@ void Preferences::fillPreferences () { dnwavlev->set_active (moptions.rtSettings.nrwavlevel); cprevdemo->set_active (moptions.prevdemo); cbdaubech->set_active (moptions.rtSettings.daubech); - -// cbAutocielab->set_active (moptions.rtSettings.autocielab); - cbciecamfloat->set_active (moptions.rtSettings.ciecamfloat); - ckbHistogramWorking->set_active (moptions.rtSettings.HistogramWorking); + +// cbAutocielab->set_active (moptions.rtSettings.autocielab); + cbciecamfloat->set_active (moptions.rtSettings.ciecamfloat); + ckbHistogramWorking->set_active (moptions.rtSettings.HistogramWorking); languages->set_active_text (moptions.language); ckbLangAutoDetect->set_active (moptions.languageAutoDetect); theme->set_active_text (moptions.theme); @@ -1528,14 +1577,14 @@ void Preferences::fillPreferences () { chUseSystemTheme->set_active(moptions.useSystemTheme); Gdk::Color cropCol; - cropCol.set_rgb_p(moptions.cutOverlayBrush[0],moptions.cutOverlayBrush[1],moptions.cutOverlayBrush[2]); + cropCol.set_rgb_p(moptions.cutOverlayBrush[0], moptions.cutOverlayBrush[1], moptions.cutOverlayBrush[2]); butCropCol->set_color(cropCol); - butCropCol->set_alpha ( (unsigned short)(moptions.cutOverlayBrush[3]*65535.0)); + butCropCol->set_alpha ( (unsigned short)(moptions.cutOverlayBrush[3] * 65535.0)); Gdk::Color NavGuideCol; - NavGuideCol.set_rgb_p(moptions.navGuideBrush[0],moptions.navGuideBrush[1],moptions.navGuideBrush[2]); + NavGuideCol.set_rgb_p(moptions.navGuideBrush[0], moptions.navGuideBrush[1], moptions.navGuideBrush[2]); butNavGuideCol->set_color(NavGuideCol); - butNavGuideCol->set_alpha ( (unsigned short)(moptions.navGuideBrush[3]*65535.0)); + butNavGuideCol->set_alpha ( (unsigned short)(moptions.navGuideBrush[3] * 65535.0)); fontbutton->set_font_name(moptions.font); showDateTime->set_active (moptions.fbShowDateTime); @@ -1550,18 +1599,26 @@ void Preferences::fillPreferences () { hlThresh->set_value (moptions.highlightThreshold); shThresh->set_value (moptions.shadowThreshold); - edGimp->set_active (moptions.editorToSendTo==1); - edOther->set_active (moptions.editorToSendTo==3); -#ifdef WIN32 - edPS->set_active (moptions.editorToSendTo==2); - if (safe_file_test (moptions.gimpDir, Glib::FILE_TEST_IS_DIR)) + edGimp->set_active (moptions.editorToSendTo == 1); + edOther->set_active (moptions.editorToSendTo == 3); +#ifdef WIN32 + edPS->set_active (moptions.editorToSendTo == 2); + + if (safe_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 (safe_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)) - psDir->set_current_folder (moptions.psDir); + edPS->set_active (moptions.editorToSendTo == 2); + + if (safe_file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { + psDir->set_current_folder (moptions.psDir); + } + #endif editorToSendTo->set_text (moptions.customEditorProg); @@ -1569,24 +1626,25 @@ void Preferences::fillPreferences () { custProfBuilderLabelType->set_active(moptions.CPBKeys); - if (moptions.startupDir==STARTUPDIR_CURRENT) + if (moptions.startupDir == STARTUPDIR_CURRENT) { sdcurrent->set_active (); - else if (moptions.startupDir==STARTUPDIR_LAST) + } else if (moptions.startupDir == STARTUPDIR_LAST) { sdlast->set_active (); - else if (moptions.startupDir==STARTUPDIR_HOME) + } else if (moptions.startupDir == STARTUPDIR_HOME) { sdhome->set_active (); - else if (moptions.startupDir==STARTUPDIR_CUSTOM) { + } else if (moptions.startupDir == STARTUPDIR_CUSTOM) { sdother->set_active (); startupdir->set_text (moptions.startupPath); } - + extensionModel->clear (); - for (size_t i=0; iappend()); row[extensionColumns.enabled] = moptions.parseExtensionsEnabled[i]; row[extensionColumns.ext] = moptions.parseExtensions[i]; } - + maxThumbSize->set_value (moptions.maxThumbnailHeight); maxRecentFolders->set_value(moptions.maxRecentFolders); maxCacheEntries->set_value (moptions.maxCacheEntries); @@ -1594,22 +1652,23 @@ void Preferences::fillPreferences () { filmStripOverlayedFileNames->set_active(moptions.filmStripOverlayedFileNames); sameThumbSize->set_active(moptions.sameThumbSize); ckbInternalThumbIfUntouched->set_active(moptions.internalThumbIfUntouched); - + saveParamsFile->set_active (moptions.saveParamsFile); saveParamsCache->set_active (moptions.saveParamsCache); loadParamsPreference->set_active (moptions.paramsLoadLocation); useBundledProfiles->set_active (moptions.useBundledProfiles); - ckbTunnelMetaData->set_active (moptions.tunnelMetaData); + ckbTunnelMetaData->set_active (moptions.tunnelMetaData); - if (!moptions.tabbedUI) + if (!moptions.tabbedUI) { editorLayout->set_active(moptions.mainNBVertical ? 1 : 0); - else + } else { editorLayout->set_active(moptions.multiDisplayMode ? 3 : 2); + } curveBBoxPosC->set_active(moptions.curvebboxpos); - ckbHistogramPositionLeft->set_active(moptions.histogramPosition==1); - // ckbHistogramWorking->set_active(moptions.histogramWorking==1); + ckbHistogramPositionLeft->set_active(moptions.histogramPosition == 1); +// ckbHistogramWorking->set_active(moptions.histogramWorking==1); ckbFileBrowserToolbarSingleRow->set_active(moptions.FileBrowserToolbarSingleRow); ckbShowFilmStripToolBar->set_active(moptions.showFilmStripToolBar); ckbHideTPVScrollbar->set_active(moptions.hideTPVScrollbar); @@ -1621,24 +1680,26 @@ void Preferences::fillPreferences () { darkFrameDir->set_current_folder( moptions.rtSettings.darkFramesPath ); darkFrameChanged (); - + flatFieldDir->set_current_folder( moptions.rtSettings.flatFieldsPath ); flatFieldChanged (); clutsDir->set_current_folder( moptions.clutsDir ); - + addc.block (true); setc.block (true); + if (moptions.baBehav.size() == ADDSET_PARAM_NUM) { - for (size_t i=0; ichildren().begin(); sections!=behModel->children().end(); sections++) - for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) + for (size_t i = 0; i < moptions.baBehav.size(); i++) + for (Gtk::TreeIter sections = behModel->children().begin(); sections != behModel->children().end(); sections++) + for (Gtk::TreeIter adjs = sections->children().begin(); adjs != sections->children().end(); adjs++) if (adjs->get_value (behavColumns.addsetid) == (int)i) { - adjs->set_value (behavColumns.badd, moptions.baBehav[i]==1); - adjs->set_value (behavColumns.bset, moptions.baBehav[i]!=1); + adjs->set_value (behavColumns.badd, moptions.baBehav[i] == 1); + adjs->set_value (behavColumns.bset, moptions.baBehav[i] != 1); break; } } + addc.block (false); setc.block (false); tconn.block (false); @@ -1676,64 +1737,71 @@ void Preferences::savePressed () { */ #if defined(WIN32) -void Preferences::autoMonProfileToggled () { - monProfile->set_sensitive(!cbAutoMonProfile->get_active()); +void Preferences::autoMonProfileToggled () +{ + monProfile->set_sensitive(!cbAutoMonProfile->get_active()); } #endif /* void Preferences::autocielabToggled () { -// cbAutocielab->set_sensitive(cbAutocielab->get_active()); +// cbAutocielab->set_sensitive(cbAutocielab->get_active()); } */ -void Preferences::sndEnableToggled () { - txtSndBatchQueueDone->set_sensitive(ckbSndEnable->get_active()); - txtSndLngEditProcDone->set_sensitive(ckbSndEnable->get_active()); - spbSndLngEditProcDoneSecs->set_sensitive(ckbSndEnable->get_active()); +void Preferences::sndEnableToggled () +{ + txtSndBatchQueueDone->set_sensitive(ckbSndEnable->get_active()); + txtSndLngEditProcDone->set_sensitive(ckbSndEnable->get_active()); + spbSndLngEditProcDoneSecs->set_sensitive(ckbSndEnable->get_active()); } -void Preferences::langAutoDetectToggled () { - languages->set_sensitive(!ckbLangAutoDetect->get_active()); +void Preferences::langAutoDetectToggled () +{ + languages->set_sensitive(!ckbLangAutoDetect->get_active()); } -void Preferences::okPressed () { +void Preferences::okPressed () +{ storePreferences (); workflowUpdate(); - options.copyFrom (&moptions); + options.copyFrom (&moptions); options.filterOutParsedExtensions(); Options::save (); hide (); } -void Preferences::cancelPressed () { +void Preferences::cancelPressed () +{ - bool currentSlimState = options.slimUI; - options.slimUI = oldSlimUI; + bool currentSlimState = options.slimUI; + options.slimUI = oldSlimUI; - // set the initial theme back - if (theme->get_active_text()!=options.theme || options.slimUI!=currentSlimState) { - RTImage::setPaths(options); - RTImage::updateImages(); - switchThemeTo(options.theme, options.slimUI); - } + // set the initial theme back + if (theme->get_active_text() != options.theme || options.slimUI != currentSlimState) { + RTImage::setPaths(options); + RTImage::updateImages(); + switchThemeTo(options.theme, options.slimUI); + } - // set the initial font back - if (fontbutton->get_font_name() != options.font) - switchFontTo(options.font); + // set the initial font back + if (fontbutton->get_font_name() != options.font) { + switchFontTo(options.font); + } - // update the profileStore - if (useBundledProfiles->get_active () != options.useBundledProfiles) { - // we have to rescan with the old value; - bpconn.block(true); - useBundledProfiles->set_active (false); - bundledProfilesChanged(); - bpconn.block(false); - } + // update the profileStore + if (useBundledProfiles->get_active () != options.useBundledProfiles) { + // we have to rescan with the old value; + bpconn.block(true); + useBundledProfiles->set_active (false); + bundledProfilesChanged(); + bpconn.block(false); + } - hide (); + hide (); } -void Preferences::selectStartupDir () { +void Preferences::selectStartupDir () +{ Gtk::FileChooserDialog dialog(M("PREFERENCES_DIRSELECTDLG"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); // dialog.set_transient_for(*this); @@ -1744,11 +1812,13 @@ void Preferences::selectStartupDir () { int result = dialog.run(); - if (result==Gtk::RESPONSE_OK) + if (result == Gtk::RESPONSE_OK) { startupdir->set_text (dialog.get_filename()); + } } -void Preferences::aboutPressed () { +void Preferences::aboutPressed () +{ splash = new Splash (*this); splash->set_transient_for (*this); @@ -1756,275 +1826,317 @@ void Preferences::aboutPressed () { splash->show (); } -void Preferences::themeChanged () { +void Preferences::themeChanged () +{ - moptions.theme = theme->get_active_text (); - moptions.useSystemTheme = chUseSystemTheme->get_active (); - RTImage::setPaths(moptions); - RTImage::updateImages(); - switchThemeTo(theme->get_active_text (), slimUI->get_active()); + moptions.theme = theme->get_active_text (); + moptions.useSystemTheme = chUseSystemTheme->get_active (); + RTImage::setPaths(moptions); + RTImage::updateImages(); + switchThemeTo(theme->get_active_text (), slimUI->get_active()); } -void Preferences::forRAWComboChanged () { - if (!rprofiles) - return; - const ProfileStoreEntry *selectedEntry = rprofiles->getSelectedEntry(); - if (!selectedEntry) - return; +void Preferences::forRAWComboChanged () +{ + if (!rprofiles) { + return; + } - if (selectedEntry->type == PSET_FOLDER) { - rpconn.block(true); - rprofiles->set_active(currRawRow); - rpconn.block(false); - } - else - currRawRow = rprofiles->get_active(); + const ProfileStoreEntry *selectedEntry = rprofiles->getSelectedEntry(); - rprofiles->set_tooltip_text(selectedEntry->label); + if (!selectedEntry) { + return; + } + + if (selectedEntry->type == PSET_FOLDER) { + rpconn.block(true); + rprofiles->set_active(currRawRow); + rpconn.block(false); + } else { + currRawRow = rprofiles->get_active(); + } + + rprofiles->set_tooltip_text(selectedEntry->label); } -void Preferences::forImageComboChanged () { - if (!iprofiles) - return; - const ProfileStoreEntry *selectedEntry = iprofiles->getSelectedEntry(); - if (!selectedEntry) - return; +void Preferences::forImageComboChanged () +{ + if (!iprofiles) { + return; + } - if (selectedEntry->type == PSET_FOLDER) { - ipconn.block(true); - iprofiles->set_active(currImgRow); - ipconn.block(false); - } - else - currImgRow = rprofiles->get_active(); - iprofiles->set_tooltip_text(iprofiles->getSelectedEntry()->label); + const ProfileStoreEntry *selectedEntry = iprofiles->getSelectedEntry(); + + if (!selectedEntry) { + return; + } + + if (selectedEntry->type == PSET_FOLDER) { + ipconn.block(true); + iprofiles->set_active(currImgRow); + ipconn.block(false); + } else { + currImgRow = rprofiles->get_active(); + } + + iprofiles->set_tooltip_text(iprofiles->getSelectedEntry()->label); } -void Preferences::layoutComboChanged () { - editorLayout->set_tooltip_text(editorLayout->get_active_text()); +void Preferences::layoutComboChanged () +{ + editorLayout->set_tooltip_text(editorLayout->get_active_text()); } -void Preferences::bundledProfilesChanged () { - rpconn.block (true); - ipconn.block (true); +void Preferences::bundledProfilesChanged () +{ + rpconn.block (true); + ipconn.block (true); - // parseProfiles does use options.useBundledProfiles, so we temporarily change its value - bool currValue = options.useBundledProfiles; - options.useBundledProfiles = useBundledProfiles->get_active (); + // parseProfiles does use options.useBundledProfiles, so we temporarily change its value + bool currValue = options.useBundledProfiles; + options.useBundledProfiles = useBundledProfiles->get_active (); - // rescan the file's tree - profileStore.parseProfiles(); // This will call Preferences::updateProfileList in return + // rescan the file's tree + profileStore.parseProfiles(); // This will call Preferences::updateProfileList in return - // restoring back the old value - options.useBundledProfiles = currValue; + // restoring back the old value + options.useBundledProfiles = currValue; - ipconn.block (false); - rpconn.block (false); + ipconn.block (false); + rpconn.block (false); } -void Preferences::storeCurrentValue() { - // TODO: Find a way to get and restore the current selection; the following line can't work anymore - storedValueRaw = rprofiles->getFullPathFromActiveRow(); - storedValueImg = iprofiles->getFullPathFromActiveRow(); +void Preferences::storeCurrentValue() +{ + // TODO: Find a way to get and restore the current selection; the following line can't work anymore + storedValueRaw = rprofiles->getFullPathFromActiveRow(); + storedValueImg = iprofiles->getFullPathFromActiveRow(); } -void Preferences::updateProfileList() { - rprofiles->updateProfileList(); - iprofiles->updateProfileList(); +void Preferences::updateProfileList() +{ + rprofiles->updateProfileList(); + iprofiles->updateProfileList(); } -void Preferences::restoreValue() { - if (!rprofiles->setActiveRowFromFullPath(storedValueRaw)) { - moptions.defProfRaw = DEFPROFILE_INTERNAL; - rpconn.block(true); - rprofiles->setInternalEntry(); - rpconn.block(false); - } - currRawRow = rprofiles->get_active(); +void Preferences::restoreValue() +{ + if (!rprofiles->setActiveRowFromFullPath(storedValueRaw)) { + moptions.defProfRaw = DEFPROFILE_INTERNAL; + rpconn.block(true); + rprofiles->setInternalEntry(); + rpconn.block(false); + } - if (!iprofiles->setActiveRowFromFullPath(storedValueImg)) { - moptions.defProfImg = DEFPROFILE_INTERNAL; - ipconn.block(true); - iprofiles->setInternalEntry(); - ipconn.block(false); - } - currImgRow = iprofiles->get_active(); + currRawRow = rprofiles->get_active(); - storedValueRaw = ""; - storedValueImg = ""; + if (!iprofiles->setActiveRowFromFullPath(storedValueImg)) { + moptions.defProfImg = DEFPROFILE_INTERNAL; + ipconn.block(true); + iprofiles->setInternalEntry(); + ipconn.block(false); + } + + currImgRow = iprofiles->get_active(); + + storedValueRaw = ""; + storedValueImg = ""; } -void Preferences::fontChanged () { +void Preferences::fontChanged () +{ - switchFontTo(fontbutton->get_font_name()); + switchFontTo(fontbutton->get_font_name()); } -void Preferences::switchThemeTo(Glib::ustring newTheme, bool slimInterface) { +void Preferences::switchThemeTo(Glib::ustring newTheme, bool slimInterface) +{ - std::vector files; - files.push_back (argv0+"/themes/"+newTheme+".gtkrc"); + std::vector files; + files.push_back (argv0 + "/themes/" + newTheme + ".gtkrc"); - options.slimUI = slimInterface; + options.slimUI = slimInterface; - if (slimInterface) - files.push_back (argv0+"/themes/slim"); - Gtk::RC::set_default_files (files); + if (slimInterface) { + files.push_back (argv0 + "/themes/slim"); + } + + Gtk::RC::set_default_files (files); #ifndef WIN32 - // For an unknown reason, gtkmm 2.22 don't know the gtk-button-images property, while it exists in the documentation... - // Anyway, the problem was Linux only - static Glib::RefPtr settings = Gtk::Settings::get_default(); - if (settings) - settings->property_gtk_button_images().set_value(true); - else - printf("Error: no default settings to update!\n"); + // For an unknown reason, gtkmm 2.22 don't know the gtk-button-images property, while it exists in the documentation... + // Anyway, the problem was Linux only + static Glib::RefPtr settings = Gtk::Settings::get_default(); + + if (settings) { + settings->property_gtk_button_images().set_value(true); + } else { + printf("Error: no default settings to update!\n"); + } + #endif - Gtk::RC::reparse_all (Gtk::Settings::get_default()); - GdkEventClient event = { GDK_CLIENT_EVENT, NULL, TRUE, gdk_atom_intern("_GTK_READ_RCFILES", FALSE), 8 }; - gdk_event_send_clientmessage_toall ((GdkEvent*)&event); + Gtk::RC::reparse_all (Gtk::Settings::get_default()); + GdkEventClient event = { GDK_CLIENT_EVENT, NULL, TRUE, gdk_atom_intern("_GTK_READ_RCFILES", FALSE), 8 }; + gdk_event_send_clientmessage_toall ((GdkEvent*)&event); } -void Preferences::workflowUpdate (){ +void Preferences::workflowUpdate () +{ if(moptions.tabbedUI != options.tabbedUI) { parent->MoveFileBrowserToMain(); parent->CloseOpenEditors(); parent->SetMainCurrent(); - if(moptions.tabbedUI){ + + if(moptions.tabbedUI) { parent->epanel->hide_all(); - parent->set_title_decorated(""); - } - else{ - parent->epanel->show_all(); - parent->set_title_decorated(parent->epanel->getFileName()); + parent->set_title_decorated(""); + } else { + parent->epanel->show_all(); + parent->set_title_decorated(parent->epanel->getFileName()); } } + if(moptions.hideTPVScrollbar != options.hideTPVScrollbar) { - // Update the tool panels - parent->updateTPVScrollbar (moptions.hideTPVScrollbar); + // Update the tool panels + parent->updateTPVScrollbar (moptions.hideTPVScrollbar); } + if(moptions.UseIconNoText != options.UseIconNoText) { - // Update the tool's tab titles - parent->updateTabsUsesIcons(moptions.UseIconNoText); + // Update the tool's tab titles + parent->updateTabsUsesIcons(moptions.UseIconNoText); } + if(moptions.FileBrowserToolbarSingleRow != options.FileBrowserToolbarSingleRow) { - // Update the position of the Query toolbar - parent->updateFBQueryTB(moptions.FileBrowserToolbarSingleRow); + // Update the position of the Query toolbar + parent->updateFBQueryTB(moptions.FileBrowserToolbarSingleRow); } + if(moptions.showFilmStripToolBar != options.showFilmStripToolBar) { - // Update the visibility of FB toolbar - parent->updateFBToolBarVisibility(moptions.showFilmStripToolBar); + // Update the visibility of FB toolbar + parent->updateFBToolBarVisibility(moptions.showFilmStripToolBar); } + if(moptions.histogramPosition != options.histogramPosition) { - // Update the position of the Histogram - parent->updateHistogramPosition(options.histogramPosition, moptions.histogramPosition); + // Update the position of the Histogram + parent->updateHistogramPosition(options.histogramPosition, moptions.histogramPosition); } } -void Preferences::switchFontTo(Glib::ustring newFont) { +void Preferences::switchFontTo(Glib::ustring newFont) +{ - Gtk::RC::parse_string (Glib::ustring::compose( - "style \"clearlooks-default\" { font_name = \"%1\" }", newFont)); - Gtk::RC::reparse_all (Gtk::Settings::get_default()); - GdkEventClient event = { GDK_CLIENT_EVENT, NULL, TRUE, gdk_atom_intern("_GTK_READ_RCFILES", FALSE), 8 }; - gdk_event_send_clientmessage_toall ((GdkEvent*)&event); + Gtk::RC::parse_string (Glib::ustring::compose( + "style \"clearlooks-default\" { font_name = \"%1\" }", newFont)); + Gtk::RC::reparse_all (Gtk::Settings::get_default()); + GdkEventClient event = { GDK_CLIENT_EVENT, NULL, TRUE, gdk_atom_intern("_GTK_READ_RCFILES", FALSE), 8 }; + gdk_event_send_clientmessage_toall ((GdkEvent*)&event); } -void Preferences::useThemeChanged(){ +void Preferences::useThemeChanged() +{ - if(!chUseSystemTheme->get_active()){ + if(!chUseSystemTheme->get_active()) { hbtheme->set_sensitive(true); - fontbutton->set_sensitive(true); - } - else{ + fontbutton->set_sensitive(true); + } else { hbtheme->set_sensitive(false); - fontbutton->set_sensitive(false); + fontbutton->set_sensitive(false); } } -void Preferences::addExtPressed () { +void Preferences::addExtPressed () +{ - Gtk::TreeNodeChildren c = extensionModel->children (); - for (size_t i=0; iget_text ()) - return; + Gtk::TreeNodeChildren c = extensionModel->children (); - Gtk::TreeRow row = *(extensionModel->append()); + for (size_t i = 0; i < c.size(); i++) + if (c[i][extensionColumns.ext] == extension->get_text ()) { + return; + } - row[extensionColumns.enabled] = true; - row[extensionColumns.ext] = extension->get_text (); + Gtk::TreeRow row = *(extensionModel->append()); + + row[extensionColumns.enabled] = true; + row[extensionColumns.ext] = extension->get_text (); } -void Preferences::delExtPressed () { +void Preferences::delExtPressed () +{ - extensionModel->erase (extensions->get_selection()->get_selected ()); + extensionModel->erase (extensions->get_selection()->get_selected ()); } -void Preferences::clearProfilesPressed () { +void Preferences::clearProfilesPressed () +{ cacheMgr->clearProfiles (); } -void Preferences::clearThumbImagesPressed () { +void Preferences::clearThumbImagesPressed () +{ cacheMgr->clearThumbImages (); } -void Preferences::clearAllPressed () { +void Preferences::clearAllPressed () +{ cacheMgr->clearAll (); } void Preferences::darkFrameChanged () { - //Glib::ustring s(darkFrameDir->get_filename()); - Glib::ustring s(darkFrameDir->get_current_folder()); - //if( s.compare( rtengine::dfm.getPathname()) !=0 ){ - rtengine::dfm.init( s ); - updateDFinfos(); - //} + //Glib::ustring s(darkFrameDir->get_filename()); + Glib::ustring s(darkFrameDir->get_current_folder()); + //if( s.compare( rtengine::dfm.getPathname()) !=0 ){ + rtengine::dfm.init( s ); + updateDFinfos(); + //} } void Preferences::flatFieldChanged () { - //Glib::ustring s(flatFieldDir->get_filename()); - Glib::ustring s(flatFieldDir->get_current_folder()); - //if( s.compare( rtengine::ffm.getPathname()) !=0 ){ - rtengine::ffm.init( s ); - updateFFinfos(); - //} + //Glib::ustring s(flatFieldDir->get_filename()); + Glib::ustring s(flatFieldDir->get_current_folder()); + //if( s.compare( rtengine::ffm.getPathname()) !=0 ){ + rtengine::ffm.init( s ); + updateFFinfos(); + //} } void Preferences::updateDFinfos() { - int t1,t2; - rtengine::dfm.getStat(t1,t2); + int t1, t2; + rtengine::dfm.getStat(t1, t2); Glib::ustring s = Glib::ustring::compose("%1: %2 %3, %4 %5", M("PREFERENCES_DARKFRAMEFOUND"), t1, M("PREFERENCES_DARKFRAMESHOTS"), t2, M("PREFERENCES_DARKFRAMETEMPLATES")); dfLabel->set_text(s); } void Preferences::updateFFinfos() { - int t1,t2; - rtengine::ffm.getStat(t1,t2); + int t1, t2; + rtengine::ffm.getStat(t1, t2); Glib::ustring s = Glib::ustring::compose("%1: %2 %3, %4 %5", M("PREFERENCES_FLATFIELDFOUND"), t1, M("PREFERENCES_FLATFIELDSHOTS"), t2, M("PREFERENCES_FLATFIELDTEMPLATES")); ffLabel->set_text(s); } -bool Preferences::splashClosed(GdkEventAny* event) { - delete splash; - splash = NULL; - return true; +bool Preferences::splashClosed(GdkEventAny* event) +{ + delete splash; + splash = NULL; + return true; } -void Preferences::behAddAllPressed () { +void Preferences::behAddAllPressed () +{ if (moptions.baBehav.size() == ADDSET_PARAM_NUM) { - for (size_t i=0; ichildren().begin(); sections!=behModel->children().end(); sections++) - for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) + for (size_t i = 0; i < moptions.baBehav.size(); i++) + for (Gtk::TreeIter sections = behModel->children().begin(); sections != behModel->children().end(); sections++) + for (Gtk::TreeIter adjs = sections->children().begin(); adjs != sections->children().end(); adjs++) if (adjs->get_value (behavColumns.addsetid) == (int)i) { adjs->set_value (behavColumns.badd, true); adjs->set_value (behavColumns.bset, false); @@ -2033,12 +2145,13 @@ void Preferences::behAddAllPressed () { } } -void Preferences::behSetAllPressed () { +void Preferences::behSetAllPressed () +{ if (moptions.baBehav.size() == ADDSET_PARAM_NUM) { - for (size_t i=0; ichildren().begin(); sections!=behModel->children().end(); sections++) - for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) + for (size_t i = 0; i < moptions.baBehav.size(); i++) + for (Gtk::TreeIter sections = behModel->children().begin(); sections != behModel->children().end(); sections++) + for (Gtk::TreeIter adjs = sections->children().begin(); adjs != sections->children().end(); adjs++) if (adjs->get_value (behavColumns.addsetid) == (int)i) { adjs->set_value (behavColumns.badd, false); adjs->set_value (behavColumns.bset, true); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index f1cccc16e..76abd0a19 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -7,7 +7,7 @@ * 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 @@ -25,32 +25,46 @@ #include #include "rtwindow.h" -class Preferences : public Gtk::Dialog, public ProfileStoreListener { +class Preferences : public Gtk::Dialog, public ProfileStoreListener +{ - class ExtensionColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn enabled; - Gtk::TreeModelColumn ext; - ExtensionColumns() { add(enabled); add(ext); } - }; - ExtensionColumns extensionColumns; - Glib::RefPtr extensionModel; + class ExtensionColumns : public Gtk::TreeModel::ColumnRecord + { + public: + Gtk::TreeModelColumn enabled; + Gtk::TreeModelColumn ext; + ExtensionColumns() + { + add(enabled); + add(ext); + } + }; + ExtensionColumns extensionColumns; + Glib::RefPtr extensionModel; - class BehavColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn label; - Gtk::TreeModelColumn badd; - Gtk::TreeModelColumn bset; - Gtk::TreeModelColumn visible; - Gtk::TreeModelColumn addsetid; - BehavColumns() { add(label); add(badd); add(bset); add(visible); add(addsetid); } - }; - Glib::RefPtr behModel; - BehavColumns behavColumns; + class BehavColumns : public Gtk::TreeModel::ColumnRecord + { + public: + Gtk::TreeModelColumn label; + Gtk::TreeModelColumn badd; + Gtk::TreeModelColumn bset; + Gtk::TreeModelColumn visible; + Gtk::TreeModelColumn addsetid; + BehavColumns() + { + add(label); + add(badd); + add(bset); + add(visible); + add(addsetid); + } + }; + Glib::RefPtr behModel; + BehavColumns behavColumns; - protected: +protected: Splash* splash; ProfileStoreComboBox* rprofiles; Gtk::TreeIter currRawRow; // :) @@ -82,14 +96,14 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::FileChooserButton* iccDir; Gtk::FileChooserButton* monProfile; - Gtk::CheckButton* cbAutoMonProfile; - //Gtk::CheckButton* cbAutocielab; - Gtk::CheckButton* cbciecamfloat; - Gtk::CheckButton* cbdaubech; - Gtk::SpinButton* hlThresh; - Gtk::SpinButton* shThresh; + Gtk::CheckButton* cbAutoMonProfile; + //Gtk::CheckButton* cbAutocielab; + Gtk::CheckButton* cbciecamfloat; + Gtk::CheckButton* cbdaubech; + Gtk::SpinButton* hlThresh; + Gtk::SpinButton* shThresh; - Gtk::SpinButton* panFactor; + Gtk::SpinButton* panFactor; Gtk::CheckButton* rememberZoomPanCheckbutton; Gtk::ComboBoxText* intent; @@ -119,7 +133,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::FontButton* fontbutton; Gtk::ColorButton* butCropCol; Gtk::ColorButton* butNavGuideCol; - + Gtk::SpinButton* maxThumbSize; Gtk::SpinButton* maxCacheEntries; Gtk::SpinButton* maxRecentFolders; @@ -154,14 +168,14 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::ComboBoxText* loadParamsPreference; Gtk::ComboBoxText* editorLayout; RTWindow* parent; - + Gtk::CheckButton* ckbSndEnable; Gtk::Entry* txtSndBatchQueueDone; Gtk::Entry* txtSndLngEditProcDone; - Gtk::SpinButton* spbSndLngEditProcDoneSecs; - + Gtk::SpinButton* spbSndLngEditProcDoneSecs; + Gtk::CheckButton* ckbTunnelMetaData; - Gtk::CheckButton* ckbInternalThumbIfUntouched; + Gtk::CheckButton* ckbInternalThumbIfUntouched; Gtk::Entry* txtCustProfBuilderPath; Gtk::ComboBoxText* custProfBuilderLabelType; @@ -210,17 +224,17 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::Widget* getBatchProcPanel (); Gtk::Widget* getPerformancePanel (); Gtk::Widget* getSoundPanel (); - - public: - Preferences (RTWindow *rtwindow); - ~Preferences (); - + +public: + Preferences (RTWindow *rtwindow); + ~Preferences (); + void savePressed (); void loadPressed (); void okPressed (); void cancelPressed (); void aboutPressed (); - void autoMonProfileToggled (); + void autoMonProfileToggled (); void sndEnableToggled (); void langAutoDetectToggled (); void autocielabToggled (); diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index 187946740..5ba3c25c1 100644 --- a/rtgui/preprocess.cc +++ b/rtgui/preprocess.cc @@ -26,102 +26,113 @@ using namespace rtengine::procparams; PreProcess::PreProcess () : FoldableToolPanel(this, "preprocess", M("TP_PREPROCESS_LABEL"), true) { - - Gtk::HBox* hotdeadPixel = Gtk::manage( new Gtk::HBox () ); - hotdeadPixel->set_spacing(4); - hotPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_HOTPIXFILT")))); - deadPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_DEADPIXFILT")))); - - hotPixel->set_tooltip_markup (M("TP_PREPROCESS_HOTPIXFILT_TOOLTIP")); - deadPixel->set_tooltip_markup (M("TP_PREPROCESS_DEADPIXFILT_TOOLTIP")); - - hotdeadPixel->pack_start( *hotPixel, Gtk::PACK_SHRINK); - hotdeadPixel->pack_start( *deadPixel, Gtk::PACK_SHRINK, 0); - pack_start(*hotdeadPixel, Gtk::PACK_SHRINK, 0); - hdThreshold = Gtk::manage (new Adjuster (M("TP_RAW_HD"),20,200,2,100)); - hdThreshold->set_tooltip_markup (M("TP_RAW_HD_TOOLTIP")); - hdThreshold->setAdjusterListener (this); - if (hdThreshold->delay < 1000) hdThreshold->delay = 1000; - hdThreshold->show(); - pack_start( *hdThreshold, Gtk::PACK_SHRINK, 4); -// hotdeadPixel->show(); - hpixelconn = hotPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::hotPixelChanged), true); - dpixelconn = deadPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::deadPixelChanged), true); + Gtk::HBox* hotdeadPixel = Gtk::manage( new Gtk::HBox () ); + hotdeadPixel->set_spacing(4); + hotPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_HOTPIXFILT")))); + deadPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_DEADPIXFILT")))); + + hotPixel->set_tooltip_markup (M("TP_PREPROCESS_HOTPIXFILT_TOOLTIP")); + deadPixel->set_tooltip_markup (M("TP_PREPROCESS_DEADPIXFILT_TOOLTIP")); + + hotdeadPixel->pack_start( *hotPixel, Gtk::PACK_SHRINK); + hotdeadPixel->pack_start( *deadPixel, Gtk::PACK_SHRINK, 0); + pack_start(*hotdeadPixel, Gtk::PACK_SHRINK, 0); + hdThreshold = Gtk::manage (new Adjuster (M("TP_RAW_HD"), 20, 200, 2, 100)); + hdThreshold->set_tooltip_markup (M("TP_RAW_HD_TOOLTIP")); + hdThreshold->setAdjusterListener (this); + + if (hdThreshold->delay < 1000) { + hdThreshold->delay = 1000; + } + + hdThreshold->show(); + pack_start( *hdThreshold, Gtk::PACK_SHRINK, 4); + +// hotdeadPixel->show(); + hpixelconn = hotPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::hotPixelChanged), true); + dpixelconn = deadPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::deadPixelChanged), true); } void PreProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - hpixelconn.block (true); - dpixelconn.block (true); - if(pedited ){ - hotPixel->set_inconsistent (!pedited->raw.hotPixelFilter); - deadPixel->set_inconsistent (!pedited->raw.deadPixelFilter); - } + disableListener (); + hpixelconn.block (true); + dpixelconn.block (true); - lastHot = pp->raw.hotPixelFilter; - lastDead = pp->raw.deadPixelFilter; - hotPixel->set_active (pp->raw.hotPixelFilter); - deadPixel->set_active (pp->raw.deadPixelFilter); - hdThreshold->setValue (pp->raw.hotdeadpix_thresh); - hpixelconn.block (false); - dpixelconn.block (false); - enableListener (); + if(pedited ) { + hotPixel->set_inconsistent (!pedited->raw.hotPixelFilter); + deadPixel->set_inconsistent (!pedited->raw.deadPixelFilter); + } + + lastHot = pp->raw.hotPixelFilter; + lastDead = pp->raw.deadPixelFilter; + hotPixel->set_active (pp->raw.hotPixelFilter); + deadPixel->set_active (pp->raw.deadPixelFilter); + hdThreshold->setValue (pp->raw.hotdeadpix_thresh); + hpixelconn.block (false); + dpixelconn.block (false); + enableListener (); } void PreProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.hotPixelFilter = hotPixel->get_active(); - pp->raw.deadPixelFilter = deadPixel->get_active(); - pp->raw.hotdeadpix_thresh = hdThreshold->getIntValue(); - if (pedited) { - pedited->raw.hotDeadPixelThresh = hdThreshold->getEditedState (); - pedited->raw.hotPixelFilter = !hotPixel->get_inconsistent(); - pedited->raw.deadPixelFilter = !deadPixel->get_inconsistent(); - } + pp->raw.hotPixelFilter = hotPixel->get_active(); + pp->raw.deadPixelFilter = deadPixel->get_active(); + pp->raw.hotdeadpix_thresh = hdThreshold->getIntValue(); + + if (pedited) { + pedited->raw.hotDeadPixelThresh = hdThreshold->getEditedState (); + pedited->raw.hotPixelFilter = !hotPixel->get_inconsistent(); + pedited->raw.deadPixelFilter = !deadPixel->get_inconsistent(); + } } void PreProcess::adjusterChanged (Adjuster* a, double newval) { - if (listener) { - if (a == hdThreshold) - listener->panelChanged (EvPreProcessHotDeadThresh, a->getTextValue() ); - } + if (listener) { + if (a == hdThreshold) { + listener->panelChanged (EvPreProcessHotDeadThresh, a->getTextValue() ); + } + } } void PreProcess::hotPixelChanged () { - if (batchMode) { - if (hotPixel->get_inconsistent()) { - hotPixel->set_inconsistent (false); - hpixelconn.block (true); - hotPixel->set_active (false); - hpixelconn.block (false); - } - else if (lastHot) - hotPixel->set_inconsistent (true); + if (batchMode) { + if (hotPixel->get_inconsistent()) { + hotPixel->set_inconsistent (false); + hpixelconn.block (true); + hotPixel->set_active (false); + hpixelconn.block (false); + } else if (lastHot) { + hotPixel->set_inconsistent (true); + } - lastHot = hotPixel->get_active (); - } - if (listener) - listener->panelChanged (EvPreProcessHotPixel, hotPixel->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + lastHot = hotPixel->get_active (); + } + + if (listener) { + listener->panelChanged (EvPreProcessHotPixel, hotPixel->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } void PreProcess::deadPixelChanged () { - if (batchMode) { - if (deadPixel->get_inconsistent()) { - deadPixel->set_inconsistent (false); - dpixelconn.block (true); - deadPixel->set_active (false); - dpixelconn.block (false); - } - else if (lastDead) - deadPixel->set_inconsistent (true); + if (batchMode) { + if (deadPixel->get_inconsistent()) { + deadPixel->set_inconsistent (false); + dpixelconn.block (true); + deadPixel->set_active (false); + dpixelconn.block (false); + } else if (lastDead) { + deadPixel->set_inconsistent (true); + } - lastDead = deadPixel->get_active (); - } - if (listener) - listener->panelChanged (EvPreProcessDeadPixel, deadPixel->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + lastDead = deadPixel->get_active (); + } + + if (listener) { + listener->panelChanged (EvPreProcessDeadPixel, deadPixel->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } diff --git a/rtgui/preprocess.h b/rtgui/preprocess.h index d99973296..8faf647a4 100644 --- a/rtgui/preprocess.h +++ b/rtgui/preprocess.h @@ -26,21 +26,22 @@ #include "guiutils.h" #include "../rtengine/rawimage.h" -class PreProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class PreProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Gtk::CheckButton* hotPixel; Gtk::CheckButton* deadPixel; - bool lastHot,lastDead; + bool lastHot, lastDead; sigc::connection hpixelconn; sigc::connection dpixelconn; Adjuster* hdThreshold; - public: +public: PreProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); //void setBatchMode (bool batchMode); //void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); diff --git a/rtgui/previewhandler.cc b/rtgui/previewhandler.cc index 42b48b879..e2b635e07 100644 --- a/rtgui/previewhandler.cc +++ b/rtgui/previewhandler.cc @@ -7,7 +7,7 @@ * 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 @@ -23,7 +23,8 @@ using namespace rtengine; using namespace rtengine::procparams; -PreviewHandler::PreviewHandler () : image(NULL), previewScale(1.) { +PreviewHandler::PreviewHandler () : image(NULL), previewScale(1.) +{ pih = new PreviewHandlerIdleHelper; pih->phandler = this; @@ -31,12 +32,14 @@ PreviewHandler::PreviewHandler () : image(NULL), previewScale(1.) { pih->pending = 0; } -PreviewHandler::~PreviewHandler () { +PreviewHandler::~PreviewHandler () +{ - if (pih->pending) + if (pih->pending) { pih->destroyed = true; - else + } else { delete pih; + } } //----------------previewimagelistener functions-------------------- @@ -48,15 +51,18 @@ struct iaimgpar { CropParams cp; }; -int setImageUI (void* data) { +int setImageUI (void* data) +{ iaimgpar* iap = static_cast(data); PreviewHandlerIdleHelper* pih = iap->pih; if (pih->destroyed) { - if (pih->pending == 1) + if (pih->pending == 1) { delete pih; - else + } else { pih->pending--; + } + delete iap; return 0; @@ -67,19 +73,20 @@ int setImageUI (void* data) { oldImg->getMutex().lock (); pih->phandler->image = iap->image; oldImg->getMutex().unlock (); - } - else + } else { pih->phandler->image = iap->image; + } pih->phandler->cropParams = iap->cp; pih->phandler->previewScale = iap->scale; pih->pending--; delete iap; - + return 0; } -void PreviewHandler::setImage (rtengine::IImage8* i, double scale, rtengine::procparams::CropParams cp) { +void PreviewHandler::setImage (rtengine::IImage8* i, double scale, rtengine::procparams::CropParams cp) +{ pih->pending++; @@ -93,27 +100,31 @@ void PreviewHandler::setImage (rtengine::IImage8* i, double scale, rtengine::pro } -int delImageUI (void* data) { +int delImageUI (void* data) +{ iaimgpar* iap = static_cast(data); PreviewHandlerIdleHelper* pih = iap->pih; if (pih->destroyed) { - if (pih->pending == 1) + if (pih->pending == 1) { delete pih; - else + } else { pih->pending--; + } + delete iap; return 0; } - + if (pih->phandler->image) { IImage8* oldImg = pih->phandler->image; oldImg->getMutex().lock (); pih->phandler->image = NULL; oldImg->getMutex().unlock (); - } + } + iap->image->free (); pih->phandler->previewImgMutex.lock (); pih->phandler->previewImg.clear (); @@ -125,7 +136,8 @@ int delImageUI (void* data) { return 0; } -void PreviewHandler::delImage (IImage8* i) { +void PreviewHandler::delImage (IImage8* i) +{ pih->pending++; @@ -136,23 +148,26 @@ void PreviewHandler::delImage (IImage8* i) { g_idle_add (delImageUI, iap); } -int imageReadyUI (void* data) { - +int imageReadyUI (void* data) +{ + iaimgpar* iap = static_cast(data); PreviewHandlerIdleHelper* pih = iap->pih; - + if (pih->destroyed) { - if (pih->pending == 1) + if (pih->pending == 1) { delete pih; - else + } else { pih->pending--; + } + delete iap; return 0; } pih->phandler->previewImgMutex.lock (); - pih->phandler->previewImg = Gdk::Pixbuf::create_from_data (pih->phandler->image->getData(), Gdk::COLORSPACE_RGB, false, 8, pih->phandler->image->getWidth(), pih->phandler->image->getHeight(), 3*pih->phandler->image->getWidth()); + pih->phandler->previewImg = Gdk::Pixbuf::create_from_data (pih->phandler->image->getData(), Gdk::COLORSPACE_RGB, false, 8, pih->phandler->image->getWidth(), pih->phandler->image->getHeight(), 3 * pih->phandler->image->getWidth()); pih->phandler->previewImgMutex.unlock (); pih->phandler->cropParams = iap->cp; pih->phandler->previewImageChanged (); @@ -162,7 +177,8 @@ int imageReadyUI (void* data) { return 0; } -void PreviewHandler::imageReady (CropParams cp) { +void PreviewHandler::imageReady (CropParams cp) +{ pih->pending++; iaimgpar* iap = new iaimgpar; @@ -171,27 +187,41 @@ void PreviewHandler::imageReady (CropParams cp) { g_idle_add (imageReadyUI, iap); } -Glib::RefPtr PreviewHandler::getRoughImage (int x, int y, int w, int h, double zoom) { +Glib::RefPtr PreviewHandler::getRoughImage (int x, int y, int w, int h, double zoom) +{ MyMutex::MyLock lock(previewImgMutex); Glib::RefPtr resPixbuf; if (previewImg) { - double totalZoom = zoom*previewScale; - if (w>previewImg->get_width()*totalZoom) - w = image->getWidth()*totalZoom; - if (h>previewImg->get_height()*totalZoom) - h = image->getHeight()*totalZoom; - int ix = x*zoom; - int iy = y*zoom; - if (ix<0) + double totalZoom = zoom * previewScale; + + if (w > previewImg->get_width()*totalZoom) { + w = image->getWidth() * totalZoom; + } + + if (h > previewImg->get_height()*totalZoom) { + h = image->getHeight() * totalZoom; + } + + int ix = x * zoom; + int iy = y * zoom; + + if (ix < 0) { ix = 0; - if (iy<0) + } + + if (iy < 0) { iy = 0; - if ((ix+w)/totalZoom>previewImg->get_width()) - ix = previewImg->get_width()*totalZoom - w; - if ((iy+h)/totalZoom>previewImg->get_height()) - iy = previewImg->get_height()*totalZoom - h; + } + + if ((ix + w) / totalZoom > previewImg->get_width()) { + ix = previewImg->get_width() * totalZoom - w; + } + + if ((iy + h) / totalZoom > previewImg->get_height()) { + iy = previewImg->get_height() * totalZoom - h; + } resPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, w, h); previewImg->scale (resPixbuf, 0, 0, w, h, -ix, -iy, totalZoom, totalZoom, Gdk::INTERP_NEAREST); @@ -200,17 +230,18 @@ Glib::RefPtr PreviewHandler::getRoughImage (int x, int y, int w, in return resPixbuf; } -Glib::RefPtr PreviewHandler::getRoughImage (int desiredW, int desiredH, double& zoom_) { +Glib::RefPtr PreviewHandler::getRoughImage (int desiredW, int desiredH, double& zoom_) +{ MyMutex::MyLock lock(previewImgMutex); Glib::RefPtr resPixbuf; if (previewImg) { - double zoom1 = (double)max(desiredW,20) / previewImg->get_width(); // too small values lead to extremely increased processing time in scale function, Issue 2783 - double zoom2 = (double)max(desiredH,20) / previewImg->get_height(); // "" - double zoom = zoom1getWidth()*zoom, image->getHeight()*zoom); + double zoom1 = (double)max(desiredW, 20) / previewImg->get_width(); // too small values lead to extremely increased processing time in scale function, Issue 2783 + double zoom2 = (double)max(desiredH, 20) / previewImg->get_height(); // "" + double zoom = zoom1 < zoom2 ? zoom1 : zoom2; + + resPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, image->getWidth() * zoom, image->getHeight() * zoom); previewImg->scale (resPixbuf, 0, 0, previewImg->get_width()*zoom, previewImg->get_height()*zoom, 0, 0, zoom, zoom, Gdk::INTERP_BILINEAR); zoom_ = zoom / previewScale; } @@ -218,8 +249,10 @@ Glib::RefPtr PreviewHandler::getRoughImage (int desiredW, int desir return resPixbuf; } -void PreviewHandler::previewImageChanged () { - - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); i++) +void PreviewHandler::previewImageChanged () +{ + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); i++) { (*i)->previewImageChanged (); + } } diff --git a/rtgui/previewhandler.h b/rtgui/previewhandler.h index 8eaa0b3d7..a0e6ca242 100644 --- a/rtgui/previewhandler.h +++ b/rtgui/previewhandler.h @@ -7,7 +7,7 @@ * 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 @@ -24,11 +24,12 @@ #include #include -class PreviewListener { - - public: - virtual ~PreviewListener () {} - virtual void previewImageChanged () {} +class PreviewListener +{ + +public: + virtual ~PreviewListener () {} + virtual void previewImageChanged () {} }; class PreviewHandler; @@ -38,40 +39,47 @@ struct PreviewHandlerIdleHelper { int pending; }; -class PreviewHandler : public rtengine::PreviewImageListener { +class PreviewHandler : public rtengine::PreviewImageListener +{ friend int setImageUI (void* data); friend int delImageUI (void* data); friend int imageReadyUI (void* data); - protected: - rtengine::IImage8* image; - rtengine::procparams::CropParams cropParams; - double previewScale; - PreviewHandlerIdleHelper* pih; - std::list listeners; - MyMutex previewImgMutex; - Glib::RefPtr previewImg; +protected: + rtengine::IImage8* image; + rtengine::procparams::CropParams cropParams; + double previewScale; + PreviewHandlerIdleHelper* pih; + std::list listeners; + MyMutex previewImgMutex; + Glib::RefPtr previewImg; - public: +public: - PreviewHandler (); - virtual ~PreviewHandler (); + PreviewHandler (); + virtual ~PreviewHandler (); - void addPreviewImageListener (PreviewListener* l) { listeners.push_back (l); } + void addPreviewImageListener (PreviewListener* l) + { + listeners.push_back (l); + } - // previewimagelistener - void setImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cp); - void delImage (rtengine::IImage8* img); - void imageReady (rtengine::procparams::CropParams cp); + // previewimagelistener + void setImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cp); + void delImage (rtengine::IImage8* img); + void imageReady (rtengine::procparams::CropParams cp); - // this function is called when a new preview image arrives from rtengine - void previewImageChanged (); + // this function is called when a new preview image arrives from rtengine + void previewImageChanged (); - // with this function it is possible to ask for a rough approximation of a (possibly zoomed) crop of the image - Glib::RefPtr getRoughImage (int x, int y, int w, int h, double zoom); - Glib::RefPtr getRoughImage (int desiredW, int desiredH, double& zoom); - rtengine::procparams::CropParams getCropParams () { return cropParams; } + // with this function it is possible to ask for a rough approximation of a (possibly zoomed) crop of the image + Glib::RefPtr getRoughImage (int x, int y, int w, int h, double zoom); + Glib::RefPtr getRoughImage (int desiredW, int desiredH, double& zoom); + rtengine::procparams::CropParams getCropParams () + { + return cropParams; + } }; #endif diff --git a/rtgui/previewloader.cc b/rtgui/previewloader.cc index 0942f84ac..3fe1897ba 100644 --- a/rtgui/previewloader.cc +++ b/rtgui/previewloader.cc @@ -7,7 +7,7 @@ * 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 @@ -25,7 +25,7 @@ #ifdef _OPENMP #include -#endif +#endif #define DEBUG(format,args...) //#define DEBUG(format,args...) printf("PreviewLoader::%s: " format "\n", __FUNCTION__, ## args) @@ -33,179 +33,179 @@ class PreviewLoader::Impl { public: - struct Job - { - Job(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderListener* listener): - dir_id_(dir_id), - dir_entry_(dir_entry), - listener_(listener) - {} + struct Job { + Job(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderListener* listener): + dir_id_(dir_id), + dir_entry_(dir_entry), + listener_(listener) + {} - Job(): - dir_id_(0), - listener_(0) - {} + Job(): + dir_id_(0), + listener_(0) + {} - int dir_id_; - Glib::ustring dir_entry_; - PreviewLoaderListener* listener_; - }; -/* Issue 2406 - struct OutputJob - { - bool complete; - int dir_id; - PreviewLoaderListener* listener; - FileBrowserEntry* fdn; - }; -*/ - struct JobCompare - { - bool operator()(const Job& lhs, const Job& rhs) - { - if ( lhs.dir_id_ == rhs.dir_id_ ) - { - return lhs.dir_entry_ < rhs.dir_entry_; - } - return lhs.dir_id_ < rhs.dir_id_; - } - }; + int dir_id_; + Glib::ustring dir_entry_; + PreviewLoaderListener* listener_; + }; + /* Issue 2406 + struct OutputJob + { + bool complete; + int dir_id; + PreviewLoaderListener* listener; + FileBrowserEntry* fdn; + }; + */ + struct JobCompare { + bool operator()(const Job& lhs, const Job& rhs) + { + if ( lhs.dir_id_ == rhs.dir_id_ ) { + return lhs.dir_entry_ < rhs.dir_entry_; + } - typedef std::set JobSet; + return lhs.dir_id_ < rhs.dir_id_; + } + }; - Impl():nConcurrentThreads(0) - { - int threadCount=2; - #ifdef _OPENMP - threadCount=omp_get_num_procs(); - #endif - - threadPool_=new Glib::ThreadPool(threadCount,0); - } + typedef std::set JobSet; - Glib::ThreadPool* threadPool_; - MyMutex mutex_; - JobSet jobs_; - gint nConcurrentThreads; -// Issue 2406 std::vector output_; + Impl(): nConcurrentThreads(0) + { + int threadCount = 2; +#ifdef _OPENMP + threadCount = omp_get_num_procs(); +#endif - void processNextJob() - { - Job j; -// Issue 2406 OutputJob *oj; - { - MyMutex::MyLock lock(mutex_); + threadPool_ = new Glib::ThreadPool(threadCount, 0); + } - // nothing to do; could be jobs have been removed - if ( jobs_.empty() ) - { - DEBUG("processing: nothing to do"); - return; - } + Glib::ThreadPool* threadPool_; + MyMutex mutex_; + JobSet jobs_; + gint nConcurrentThreads; +// Issue 2406 std::vector output_; - // copy and remove front job - j = *jobs_.begin(); - jobs_.erase(jobs_.begin()); - DEBUG("processing %s",j.dir_entry_.c_str()); - DEBUG("%d job(s) remaining",jobs_.size()); -/* Issue 2406 - oj = new OutputJob(); - oj->complete = false; - oj->dir_id = j.dir_id_; - oj->listener = j.listener_; - oj->fdn = 0; - output_.push_back(oj); -*/ - } + void processNextJob() + { + Job j; +// Issue 2406 OutputJob *oj; + { + MyMutex::MyLock lock(mutex_); - g_atomic_int_inc (&nConcurrentThreads); // to detect when last thread in pool has run out + // nothing to do; could be jobs have been removed + if ( jobs_.empty() ) { + DEBUG("processing: nothing to do"); + return; + } - // unlock and do processing; will relock on block exit, then call listener - // if something got -// Issue 2406 FileBrowserEntry* fdn = 0; - try { - Thumbnail* tmb = 0; - { - if (safe_file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) - { - tmb = cacheMgr->getEntry(j.dir_entry_); - } - } - if ( tmb ) - { - j.listener_->previewReady(j.dir_id_,new FileBrowserEntry(tmb,j.dir_entry_)); -// Issue 2406 fdn = new FileBrowserEntry(tmb,j.dir_entry_); - } + // copy and remove front job + j = *jobs_.begin(); + jobs_.erase(jobs_.begin()); + DEBUG("processing %s", j.dir_entry_.c_str()); + DEBUG("%d job(s) remaining", jobs_.size()); + /* Issue 2406 + oj = new OutputJob(); + oj->complete = false; + oj->dir_id = j.dir_id_; + oj->listener = j.listener_; + oj->fdn = 0; + output_.push_back(oj); + */ + } - } catch (Glib::Error &e){} catch(...){} -/* Issue 2406 - { - // the purpose of the output_ vector is to deliver the previewReady() calls in the same - // order as we got the jobs from the jobs_ queue. - MyMutex::MyLock lock(mutex_); - oj->fdn = fdn; - oj->complete = true; - while (output_.size() > 0 && output_.front()->complete) { - oj = output_.front(); - if (oj->fdn) { - oj->listener->previewReady(oj->dir_id,oj->fdn); - } - output_.erase(output_.begin()); - delete oj; - } - } -*/ - bool last = g_atomic_int_dec_and_test (&nConcurrentThreads); + g_atomic_int_inc (&nConcurrentThreads); // to detect when last thread in pool has run out - // signal at end - if (last && jobs_.empty()) j.listener_->previewsFinished(j.dir_id_); - } + // unlock and do processing; will relock on block exit, then call listener + // if something got +// Issue 2406 FileBrowserEntry* fdn = 0; + try { + Thumbnail* tmb = 0; + { + if (safe_file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) { + tmb = cacheMgr->getEntry(j.dir_entry_); + } + } + + if ( tmb ) { + j.listener_->previewReady(j.dir_id_, new FileBrowserEntry(tmb, j.dir_entry_)); +// Issue 2406 fdn = new FileBrowserEntry(tmb,j.dir_entry_); + } + + } catch (Glib::Error &e) {} catch(...) {} + + /* Issue 2406 + { + // the purpose of the output_ vector is to deliver the previewReady() calls in the same + // order as we got the jobs from the jobs_ queue. + MyMutex::MyLock lock(mutex_); + oj->fdn = fdn; + oj->complete = true; + while (output_.size() > 0 && output_.front()->complete) { + oj = output_.front(); + if (oj->fdn) { + oj->listener->previewReady(oj->dir_id,oj->fdn); + } + output_.erase(output_.begin()); + delete oj; + } + } + */ + bool last = g_atomic_int_dec_and_test (&nConcurrentThreads); + + // signal at end + if (last && jobs_.empty()) { + j.listener_->previewsFinished(j.dir_id_); + } + } }; PreviewLoader::PreviewLoader(): - impl_(new Impl()) + impl_(new Impl()) { } PreviewLoader* PreviewLoader::getInstance(void) { - // this will not be deleted... - static PreviewLoader* instance_ = NULL; - if ( instance_ == NULL ) - { + // this will not be deleted... + static PreviewLoader* instance_ = NULL; + + if ( instance_ == NULL ) { static MyMutex smutex_; MyMutex::MyLock lock(smutex_); - if ( instance_ == NULL ) instance_ = new PreviewLoader(); - } + if ( instance_ == NULL ) { + instance_ = new PreviewLoader(); + } + } - return instance_; + return instance_; } void PreviewLoader::add(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderListener* l) { - // somebody listening? - if ( l != 0 ) - { + // somebody listening? + if ( l != 0 ) { { MyMutex::MyLock lock(impl_->mutex_); // create a new job and append to queue - DEBUG("saving job %s",dir_entry.c_str()); - impl_->jobs_.insert(Impl::Job(dir_id,dir_entry,l)); + DEBUG("saving job %s", dir_entry.c_str()); + impl_->jobs_.insert(Impl::Job(dir_id, dir_entry, l)); } - // queue a run request - DEBUG("adding run request %s",dir_entry.c_str()); - impl_->threadPool_->push(sigc::mem_fun(*impl_, &PreviewLoader::Impl::processNextJob)); - } + // queue a run request + DEBUG("adding run request %s", dir_entry.c_str()); + impl_->threadPool_->push(sigc::mem_fun(*impl_, &PreviewLoader::Impl::processNextJob)); + } } -void PreviewLoader::removeAllJobs(void) -{ - DEBUG("stop %d",impl_->nConcurrentThreads); - MyMutex::MyLock lock(impl_->mutex_); - impl_->jobs_.clear(); +void PreviewLoader::removeAllJobs(void) +{ + DEBUG("stop %d", impl_->nConcurrentThreads); + MyMutex::MyLock lock(impl_->mutex_); + impl_->jobs_.clear(); } diff --git a/rtgui/previewloader.h b/rtgui/previewloader.h index 09892825c..762776ae7 100644 --- a/rtgui/previewloader.h +++ b/rtgui/previewloader.h @@ -7,7 +7,7 @@ * 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 @@ -23,67 +23,67 @@ #include #include "filebrowserentry.h" -class PreviewLoaderListener +class PreviewLoaderListener { public: - /** - * @brief a preview is ready - * - * @param dir_id directory ID this is for - * @param fd entry - */ - virtual void previewReady (int dir_id, FileBrowserEntry* fd) {} + /** + * @brief a preview is ready + * + * @param dir_id directory ID this is for + * @param fd entry + */ + virtual void previewReady (int dir_id, FileBrowserEntry* fd) {} - /** - * @brief all previews have finished loading - */ - virtual void previewsFinished (int dir_id_) {} + /** + * @brief all previews have finished loading + */ + virtual void previewsFinished (int dir_id_) {} }; class PreviewLoader { - public: +public: - /** - * @brief Singleton entry point. - * - * @note expects to be called inside gtk thread lock - * - * @return Pointer to thumbnail image updater. - */ - static PreviewLoader* getInstance(void); + /** + * @brief Singleton entry point. + * + * @note expects to be called inside gtk thread lock + * + * @return Pointer to thumbnail image updater. + */ + static PreviewLoader* getInstance(void); - /** - * @brief Add an thumbnail image update request. - * - * Code will add the request to the queue and, if needed, start a pool - * thread to process it. - * - * @param dir_id directory we're looking at - * @param dir_entry entry in it - * @param l listener - */ + /** + * @brief Add an thumbnail image update request. + * + * Code will add the request to the queue and, if needed, start a pool + * thread to process it. + * + * @param dir_id directory we're looking at + * @param dir_entry entry in it + * @param l listener + */ void add(int dir_id, const Glib::ustring& dir_entry, PreviewLoaderListener* l); - /** - * @brief Stop processing and remove all jobs. - * - * Will not return till all jobs have completed. - * - * @note expects to be called inside gtk thread lock - */ + /** + * @brief Stop processing and remove all jobs. + * + * Will not return till all jobs have completed. + * + * @note expects to be called inside gtk thread lock + */ void removeAllJobs(void); - private: +private: PreviewLoader(); - class Impl; - Impl* impl_; + class Impl; + Impl* impl_; }; -/** +/** * @brief Singleton boiler plate. * * To use: \c previewLoader->start() , diff --git a/rtgui/previewmodepanel.cc b/rtgui/previewmodepanel.cc index f135b05db..63989809d 100644 --- a/rtgui/previewmodepanel.cc +++ b/rtgui/previewmodepanel.cc @@ -21,46 +21,47 @@ #include "imagearea.h" #include "rtimage.h" -PreviewModePanel::PreviewModePanel (ImageArea* ia) : imageArea(ia) { +PreviewModePanel::PreviewModePanel (ImageArea* ia) : imageArea(ia) +{ iR = new RTImage ("previewmodeR-on.png"); iG = new RTImage ("previewmodeG-on.png"); iB = new RTImage ("previewmodeB-on.png"); iL = new RTImage ("previewmodeL-on.png"); iF = new RTImage ("previewmodeF-on.png"); - iBC0= new RTImage ("previewmodeBC0-on.png"); - iBC1= new RTImage ("previewmodeBC1-on.png"); - iBC2= new RTImage ("previewmodeBC2-on.png"); + iBC0 = new RTImage ("previewmodeBC0-on.png"); + iBC1 = new RTImage ("previewmodeBC1-on.png"); + iBC2 = new RTImage ("previewmodeBC2-on.png"); igR = new RTImage ("previewmodeR-off.png"); igG = new RTImage ("previewmodeG-off.png"); igB = new RTImage ("previewmodeB-off.png"); igL = new RTImage ("previewmodeL-off.png"); igF = new RTImage ("previewmodeF-off.png"); - igBC0= new RTImage ("previewmodeBC0-off.png"); - igBC1= new RTImage ("previewmodeBC1-off.png"); - igBC2= new RTImage ("previewmodeBC2-off.png"); + igBC0 = new RTImage ("previewmodeBC0-off.png"); + igBC1 = new RTImage ("previewmodeBC1-off.png"); + igBC2 = new RTImage ("previewmodeBC2-off.png"); backColor0 = Gtk::manage (new Gtk::ToggleButton ()); backColor0->set_relief(Gtk::RELIEF_NONE); backColor0->set_tooltip_markup (M("MAIN_TOOLTIP_BACKCOLOR0")); - backColor0->set_image(options.bgcolor==0?*iBC0:*igBC0); + backColor0->set_image(options.bgcolor == 0 ? *iBC0 : *igBC0); backColor1 = Gtk::manage (new Gtk::ToggleButton ()); backColor1->set_relief(Gtk::RELIEF_NONE); backColor1->set_tooltip_markup (M("MAIN_TOOLTIP_BACKCOLOR1")); - backColor1->set_image(options.bgcolor==1?*iBC1:*igBC1); + backColor1->set_image(options.bgcolor == 1 ? *iBC1 : *igBC1); backColor2 = Gtk::manage (new Gtk::ToggleButton ()); backColor2->set_relief(Gtk::RELIEF_NONE); backColor2->set_tooltip_markup (M("MAIN_TOOLTIP_BACKCOLOR2")); - backColor2->set_image(options.bgcolor==2?*iBC2:*igBC2); + backColor2->set_image(options.bgcolor == 2 ? *iBC2 : *igBC2); previewR = Gtk::manage (new Gtk::ToggleButton ()); previewR->set_relief(Gtk::RELIEF_NONE); previewR->set_tooltip_markup (M("MAIN_TOOLTIP_PREVIEWR")); previewR->set_image(*igR); - + previewG = Gtk::manage (new Gtk::ToggleButton ()); previewG->set_relief(Gtk::RELIEF_NONE); previewG->set_tooltip_markup (M("MAIN_TOOLTIP_PREVIEWG")); @@ -87,9 +88,9 @@ PreviewModePanel::PreviewModePanel (ImageArea* ia) : imageArea(ia) { previewL->set_active (false); previewFocusMask->set_active (false); - backColor0->set_active (options.bgcolor==0?true:false); - backColor1->set_active (options.bgcolor==1?true:false); - backColor2->set_active (options.bgcolor==2?true:false); + backColor0->set_active (options.bgcolor == 0 ? true : false); + backColor1->set_active (options.bgcolor == 1 ? true : false); + backColor2->set_active (options.bgcolor == 2 ? true : false); vbbackColor = Gtk::manage (new Gtk::VBox ()); vbbackColor->set_border_width (0); @@ -104,150 +105,206 @@ PreviewModePanel::PreviewModePanel (ImageArea* ia) : imageArea(ia) { pack_start (*previewL, Gtk::PACK_SHRINK, 0); pack_start (*previewFocusMask, Gtk::PACK_SHRINK, 0); - connR = previewR->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled),previewR) ); - connG = previewG->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled),previewG) ); - connB = previewB->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled),previewB) ); - connL = previewL->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled),previewL) ); - connFocusMask = previewFocusMask->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled),previewFocusMask) ); + connR = previewR->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled), previewR) ); + connG = previewG->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled), previewG) ); + connB = previewB->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled), previewB) ); + connL = previewL->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled), previewL) ); + connFocusMask = previewFocusMask->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled), previewFocusMask) ); - connbackColor0 = backColor0->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled_backColor),backColor0) ); - connbackColor1 = backColor1->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled_backColor),backColor1) ); - connbackColor2 = backColor2->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled_backColor),backColor2) ); + connbackColor0 = backColor0->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled_backColor), backColor0) ); + connbackColor1 = backColor1->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled_backColor), backColor1) ); + connbackColor2 = backColor2->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &PreviewModePanel::buttonToggled_backColor), backColor2) ); - //show_all (); + //show_all (); } -PreviewModePanel::~PreviewModePanel (){ - delete iR; - delete iG; - delete iB; - delete iL; - delete iF; - delete iBC0; - delete iBC1; - delete iBC2; - delete igR; - delete igG; - delete igB; - delete igL; - delete igF; - delete igBC0; - delete igBC1; - delete igBC2; +PreviewModePanel::~PreviewModePanel () +{ + delete iR; + delete iG; + delete iB; + delete iL; + delete iF; + delete iBC0; + delete iBC1; + delete iBC2; + delete igR; + delete igG; + delete igB; + delete igL; + delete igF; + delete igBC0; + delete igBC1; + delete igBC2; } //toggle Functions below are for shortcuts -void PreviewModePanel::toggleR () { +void PreviewModePanel::toggleR () +{ previewR->set_active(!previewR->get_active()); } -void PreviewModePanel::toggleG () { +void PreviewModePanel::toggleG () +{ previewG->set_active(!previewG->get_active()); } -void PreviewModePanel::toggleB () { +void PreviewModePanel::toggleB () +{ previewB->set_active(!previewB->get_active()); } -void PreviewModePanel::toggleL () { +void PreviewModePanel::toggleL () +{ previewL->set_active(!previewL->get_active()); } -void PreviewModePanel::toggleFocusMask () { +void PreviewModePanel::toggleFocusMask () +{ previewFocusMask->set_active(!previewFocusMask->get_active()); } -void PreviewModePanel::togglebackColor0 () { - backColor0->set_active(!backColor0->get_active()); +void PreviewModePanel::togglebackColor0 () +{ + backColor0->set_active(!backColor0->get_active()); } -void PreviewModePanel::togglebackColor1 () { - backColor1->set_active(!backColor1->get_active()); +void PreviewModePanel::togglebackColor1 () +{ + backColor1->set_active(!backColor1->get_active()); } -void PreviewModePanel::togglebackColor2 () { - backColor2->set_active(!backColor2->get_active()); +void PreviewModePanel::togglebackColor2 () +{ + backColor2->set_active(!backColor2->get_active()); } -void PreviewModePanel::buttonToggled (Gtk::ToggleButton* tbpreview) { - - connR.block(true); - connG.block(true); - connB.block(true); - connL.block(true); - connFocusMask.block(true); +void PreviewModePanel::buttonToggled (Gtk::ToggleButton* tbpreview) +{ - // control state of the buttons - // only 0 or 1 button at a time can remain pressed - if (tbpreview!=previewR) previewR->set_active(false); - if (tbpreview!=previewG) previewG->set_active(false); - if (tbpreview!=previewB) previewB->set_active(false); - if (tbpreview!=previewL) previewL->set_active(false); - if (tbpreview!=previewFocusMask) previewFocusMask->set_active(false); + connR.block(true); + connG.block(true); + connB.block(true); + connL.block(true); + connFocusMask.block(true); - // set image based on button's state - previewR->set_image(previewR->get_active()?*iR:*igR); - previewG->set_image(previewG->get_active()?*iG:*igG); - previewB->set_image(previewB->get_active()?*iB:*igB); - previewL->set_image(previewL->get_active()?*iL:*igL); - previewFocusMask->set_image(previewFocusMask->get_active()?*iF:*igF); + // control state of the buttons + // only 0 or 1 button at a time can remain pressed + if (tbpreview != previewR) { + previewR->set_active(false); + } - connR.block(false); - connG.block(false); - connB.block(false); - connL.block(false); - connFocusMask.block(false); + if (tbpreview != previewG) { + previewG->set_active(false); + } - imageArea->queue_draw (); + if (tbpreview != previewB) { + previewB->set_active(false); + } - // this will redraw the linked Before image area - // which is set when before/after view is enabled - if (imageArea->iLinkedImageArea!=NULL) - imageArea->iLinkedImageArea->queue_draw (); + if (tbpreview != previewL) { + previewL->set_active(false); + } + + if (tbpreview != previewFocusMask) { + previewFocusMask->set_active(false); + } + + // set image based on button's state + previewR->set_image(previewR->get_active() ? *iR : *igR); + previewG->set_image(previewG->get_active() ? *iG : *igG); + previewB->set_image(previewB->get_active() ? *iB : *igB); + previewL->set_image(previewL->get_active() ? *iL : *igL); + previewFocusMask->set_image(previewFocusMask->get_active() ? *iF : *igF); + + connR.block(false); + connG.block(false); + connB.block(false); + connL.block(false); + connFocusMask.block(false); + + imageArea->queue_draw (); + + // this will redraw the linked Before image area + // which is set when before/after view is enabled + if (imageArea->iLinkedImageArea != NULL) { + imageArea->iLinkedImageArea->queue_draw (); + } } -int PreviewModePanel::GetbackColor(){ - int backColor; - if (backColor0->get_active ()) backColor=0; - if (backColor1->get_active ()) backColor=1; - if (backColor2->get_active ()) backColor=2; +int PreviewModePanel::GetbackColor() +{ + int backColor; - return backColor; + if (backColor0->get_active ()) { + backColor = 0; + } + + if (backColor1->get_active ()) { + backColor = 1; + } + + if (backColor2->get_active ()) { + backColor = 2; + } + + return backColor; } -void PreviewModePanel::togglebackColor(){ - int backColor = GetbackColor(); - if(backColor == 0) - togglebackColor1(); - else if(backColor == 1) - togglebackColor2(); - else - togglebackColor0(); +void PreviewModePanel::togglebackColor() +{ + int backColor = GetbackColor(); + + if(backColor == 0) { + togglebackColor1(); + } else if(backColor == 1) { + togglebackColor2(); + } else { + togglebackColor0(); + } } -void PreviewModePanel::buttonToggled_backColor (Gtk::ToggleButton* tbbackColor) { +void PreviewModePanel::buttonToggled_backColor (Gtk::ToggleButton* tbbackColor) +{ - connbackColor0.block(true); - connbackColor1.block(true); - connbackColor2.block(true); + connbackColor0.block(true); + connbackColor1.block(true); + connbackColor2.block(true); - // control the state of the buttons - // Exactly 1 button at a time must remain pressed - if (tbbackColor==backColor0 && !backColor0->get_active()) backColor0->set_active(true); - if (tbbackColor==backColor1 && !backColor1->get_active()) backColor1->set_active(true); - if (tbbackColor==backColor2 && !backColor2->get_active()) backColor2->set_active(true); + // control the state of the buttons + // Exactly 1 button at a time must remain pressed + if (tbbackColor == backColor0 && !backColor0->get_active()) { + backColor0->set_active(true); + } - if (tbbackColor!=backColor0) backColor0->set_active(false); - if (tbbackColor!=backColor1) backColor1->set_active(false); - if (tbbackColor!=backColor2) backColor2->set_active(false); + if (tbbackColor == backColor1 && !backColor1->get_active()) { + backColor1->set_active(true); + } - // set image based on button's state - backColor0->set_image(backColor0->get_active()?*iBC0:*igBC0); - backColor1->set_image(backColor1->get_active()?*iBC1:*igBC1); - backColor2->set_image(backColor2->get_active()?*iBC2:*igBC2); + if (tbbackColor == backColor2 && !backColor2->get_active()) { + backColor2->set_active(true); + } - connbackColor0.block(false); - connbackColor1.block(false); - connbackColor2.block(false); + if (tbbackColor != backColor0) { + backColor0->set_active(false); + } - //TODO not sure if queue_draw is necessary, but will need to reach to backColor of the Before view - imageArea->queue_draw (); + if (tbbackColor != backColor1) { + backColor1->set_active(false); + } - // this will redraw the linked Before image area - // which is set when before/after view is enabled - if (imageArea->iLinkedImageArea!=NULL) - imageArea->iLinkedImageArea->queue_draw (); + if (tbbackColor != backColor2) { + backColor2->set_active(false); + } + + // set image based on button's state + backColor0->set_image(backColor0->get_active() ? *iBC0 : *igBC0); + backColor1->set_image(backColor1->get_active() ? *iBC1 : *igBC1); + backColor2->set_image(backColor2->get_active() ? *iBC2 : *igBC2); + + connbackColor0.block(false); + connbackColor1.block(false); + connbackColor2.block(false); + + //TODO not sure if queue_draw is necessary, but will need to reach to backColor of the Before view + imageArea->queue_draw (); + + // this will redraw the linked Before image area + // which is set when before/after view is enabled + if (imageArea->iLinkedImageArea != NULL) { + imageArea->iLinkedImageArea->queue_draw (); + } } diff --git a/rtgui/previewmodepanel.h b/rtgui/previewmodepanel.h index 3875ec49e..10906c30f 100644 --- a/rtgui/previewmodepanel.h +++ b/rtgui/previewmodepanel.h @@ -22,54 +22,70 @@ #include "adjuster.h"//dev class ImageArea; -class PreviewModePanel : public Gtk::HBox { +class PreviewModePanel : public Gtk::HBox +{ - protected: - Gtk::ToggleButton* previewR; - Gtk::ToggleButton* previewG; - Gtk::ToggleButton* previewB; - Gtk::ToggleButton* previewL; - Gtk::ToggleButton* previewFocusMask; - Gtk::ToggleButton* backColor0; - Gtk::ToggleButton* backColor1; - Gtk::ToggleButton* backColor2; - Gtk::VBox* vbbackColor; - ImageArea* imageArea; +protected: + Gtk::ToggleButton* previewR; + Gtk::ToggleButton* previewG; + Gtk::ToggleButton* previewB; + Gtk::ToggleButton* previewL; + Gtk::ToggleButton* previewFocusMask; + Gtk::ToggleButton* backColor0; + Gtk::ToggleButton* backColor1; + Gtk::ToggleButton* backColor2; + Gtk::VBox* vbbackColor; + ImageArea* imageArea; - Gtk::Image* iR, *igR; - Gtk::Image* iG, *igG; - Gtk::Image* iB, *igB; - Gtk::Image* iL, *igL; - Gtk::Image* iF, *igF; - Gtk::Image* iBC0, *igBC0; - Gtk::Image* iBC1, *igBC1; - Gtk::Image* iBC2, *igBC2; + Gtk::Image* iR, *igR; + Gtk::Image* iG, *igG; + Gtk::Image* iB, *igB; + Gtk::Image* iL, *igL; + Gtk::Image* iF, *igF; + Gtk::Image* iBC0, *igBC0; + Gtk::Image* iBC1, *igBC1; + Gtk::Image* iBC2, *igBC2; - public: - PreviewModePanel (ImageArea* ia); - ~PreviewModePanel(); +public: + PreviewModePanel (ImageArea* ia); + ~PreviewModePanel(); - void toggleR (); - void toggleG (); - void toggleB (); - void toggleL (); - void toggleFocusMask (); - void togglebackColor0(); - void togglebackColor1(); - void togglebackColor2(); - void togglebackColor(); + void toggleR (); + void toggleG (); + void toggleB (); + void toggleL (); + void toggleFocusMask (); + void togglebackColor0(); + void togglebackColor1(); + void togglebackColor2(); + void togglebackColor(); - sigc::connection connR, connB, connG, connL, connFocusMask, connbackColor0, connbackColor1, connbackColor2; + sigc::connection connR, connB, connG, connL, connFocusMask, connbackColor0, connbackColor1, connbackColor2; - void buttonToggled(Gtk::ToggleButton* tbpreview); - void buttonToggled_backColor(Gtk::ToggleButton* tbbackColor); + void buttonToggled(Gtk::ToggleButton* tbpreview); + void buttonToggled_backColor(Gtk::ToggleButton* tbbackColor); - bool showR () { return previewR->get_active (); } - bool showG () { return previewG->get_active (); } - bool showB () { return previewB->get_active (); } - bool showL () { return previewL->get_active (); } - bool showFocusMask () { return previewFocusMask->get_active (); } - int GetbackColor(); + bool showR () + { + return previewR->get_active (); + } + bool showG () + { + return previewG->get_active (); + } + bool showB () + { + return previewB->get_active (); + } + bool showL () + { + return previewL->get_active (); + } + bool showFocusMask () + { + return previewFocusMask->get_active (); + } + int GetbackColor(); }; diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index 399872307..be932df5f 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -7,7 +7,7 @@ * 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 @@ -21,69 +21,84 @@ #include "imagearea.h" #include "cursormanager.h" -PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL), imageArea(NULL), imgX(0), imgY(0), imgW(0), imgH(0), zoom(0.0), isMoving(false), needsUpdate(false) { +PreviewWindow::PreviewWindow () : previewHandler(NULL), mainCropWin(NULL), imageArea(NULL), imgX(0), imgY(0), imgW(0), imgH(0), zoom(0.0), isMoving(false), needsUpdate(false) +{ rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &PreviewWindow::on_resized) ); } -void PreviewWindow::on_realize () { +void PreviewWindow::on_realize () +{ - Gtk::DrawingArea::on_realize (); - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); + Gtk::DrawingArea::on_realize (); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK); } -void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { +void PreviewWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) +{ if (mainCropWin) { int cropX, cropY, cropW, cropH; mainCropWin->getCropRectangle (cropX, cropY, cropW, cropH); // translate it to screen coordinates - x = imgX + round(cropX*zoom); - y = imgY + round(cropY*zoom); + x = imgX + round(cropX * zoom); + y = imgY + round(cropY * zoom); w = round(cropW * zoom); h = round(cropH * zoom); } } -void PreviewWindow::updatePreviewImage () { +void PreviewWindow::updatePreviewImage () +{ int W = get_width(), H = get_height(); Glib::RefPtr wind = get_window(); + if( ! wind ) { needsUpdate = true; - return; + return; } + backBuffer = Gdk::Pixmap::create (wind, W, H, -1); backBuffer->draw_rectangle (get_style()->get_base_gc(Gtk::STATE_NORMAL), true, 0, 0, W, H); + if (previewHandler) { Glib::RefPtr resPixbuf = previewHandler->getRoughImage (W, H, zoom); + if (resPixbuf) { imgW = resPixbuf->get_width(); imgH = resPixbuf->get_height(); - imgX = (W-imgW)/2; - imgY = (H-imgH)/2; + imgX = (W - imgW) / 2; + imgY = (H - imgH) / 2; backBuffer->draw_pixbuf (get_style()->get_base_gc(Gtk::STATE_NORMAL), resPixbuf, 0, 0, imgX, imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); Cairo::RefPtr cr = backBuffer->create_cairo_context(); - if (previewHandler->getCropParams().enabled) + + if (previewHandler->getCropParams().enabled) { drawCrop (cr, imgX, imgY, imgW, imgH, 0, 0, zoom, previewHandler->getCropParams(), true, false); + } } } } -void PreviewWindow::setPreviewHandler (PreviewHandler* ph) { +void PreviewWindow::setPreviewHandler (PreviewHandler* ph) +{ previewHandler = ph; - if (previewHandler) + + if (previewHandler) { previewHandler->addPreviewImageListener (this); + } } -void PreviewWindow::on_resized (Gtk::Allocation& req) { +void PreviewWindow::on_resized (Gtk::Allocation& req) +{ updatePreviewImage (); queue_draw (); } -bool PreviewWindow::on_expose_event (GdkEventExpose* event) { +bool PreviewWindow::on_expose_event (GdkEventExpose* event) +{ if (backBuffer) { Glib::RefPtr window = get_window(); @@ -93,129 +108,151 @@ bool PreviewWindow::on_expose_event (GdkEventExpose* event) { if (!mainCropWin && imageArea) { mainCropWin = imageArea->getMainCropWindow (); - if (mainCropWin) + + if (mainCropWin) { mainCropWin->addCropWindowListener (this); + } } - if ((get_width()!=bufferW && get_height()!=bufferH) || needsUpdate) { + if ((get_width() != bufferW && get_height() != bufferH) || needsUpdate) { needsUpdate = false; updatePreviewImage (); } + window->draw_drawable (get_style()->get_base_gc(Gtk::STATE_NORMAL), backBuffer, 0, 0, 0, 0, -1, -1); if (mainCropWin && zoom > 0.0) { - if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { - Cairo::RefPtr cr = get_window()->create_cairo_context(); - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - double rectX = x + 0.5; - double rectY = y + 0.5; - double rectW = std::min(w, (int)(imgW - (x-imgX) - 1)); - double rectH = std::min(h, (int)(imgH - (y-imgY) - 1)); + if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { + Cairo::RefPtr cr = get_window()->create_cairo_context(); + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + double rectX = x + 0.5; + double rectY = y + 0.5; + double rectW = std::min(w, (int)(imgW - (x - imgX) - 1)); + double rectH = std::min(h, (int)(imgH - (y - imgY) - 1)); - // draw a black "shadow" line - cr->set_source_rgba (0.0, 0.0, 0.0, 0.65); - cr->set_line_width (1); - cr->rectangle (rectX+1., rectY+1, rectW, rectH); - cr->stroke (); + // draw a black "shadow" line + cr->set_source_rgba (0.0, 0.0, 0.0, 0.65); + cr->set_line_width (1); + cr->rectangle (rectX + 1., rectY + 1, rectW, rectH); + cr->stroke (); - // draw a "frame" line. Color of frame line can be set in preferences - cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1.0, 1.0, 1.0, 1.0); - cr->rectangle (rectX, rectY, rectW, rectH); - cr->stroke (); - } + // draw a "frame" line. Color of frame line can be set in preferences + cr->set_source_rgba(options.navGuideBrush[0], options.navGuideBrush[1], options.navGuideBrush[2], options.navGuideBrush[3]); //( 1.0, 1.0, 1.0, 1.0); + cr->rectangle (rectX, rectY, rectW, rectH); + cr->stroke (); + } } } + return true; } - -void PreviewWindow::previewImageChanged () { + +void PreviewWindow::previewImageChanged () +{ updatePreviewImage (); queue_draw (); } -void PreviewWindow::setImageArea (ImageArea* ia) { +void PreviewWindow::setImageArea (ImageArea* ia) +{ imageArea = ia; mainCropWin = ia->getMainCropWindow (); - if (mainCropWin) + + if (mainCropWin) { mainCropWin->addCropWindowListener (this); + } } -void PreviewWindow::cropPositionChanged (CropWindow* w) { +void PreviewWindow::cropPositionChanged (CropWindow* w) +{ queue_draw (); } -void PreviewWindow::cropWindowSizeChanged (CropWindow* w) { +void PreviewWindow::cropWindowSizeChanged (CropWindow* w) +{ queue_draw (); } -void PreviewWindow::cropZoomChanged (CropWindow* w) { +void PreviewWindow::cropZoomChanged (CropWindow* w) +{ queue_draw (); } -bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) { +bool PreviewWindow::on_motion_notify_event (GdkEventMotion* event) +{ - if (!mainCropWin) - return true; + if (!mainCropWin) { + return true; + } - if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; - bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; + if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; + bool moreInside = event->x > x + 6 && event->x < x + w - 1 - 6 && event->y > y + 6 && event->y < y + h - 1 - 6; - if (isMoving) - mainCropWin->remoteMove ((event->x - press_x)/zoom, (event->y - press_y)/zoom); - else if (inside && !moreInside) - cursorManager.setCursor (get_window(), CSClosedHand); - else - cursorManager.setCursor (get_window(), CSArrow); - } - return true; + if (isMoving) { + mainCropWin->remoteMove ((event->x - press_x) / zoom, (event->y - press_y) / zoom); + } else if (inside && !moreInside) { + cursorManager.setCursor (get_window(), CSClosedHand); + } else { + cursorManager.setCursor (get_window(), CSArrow); + } + } + + return true; } -bool PreviewWindow::on_button_press_event (GdkEventButton* event) { +bool PreviewWindow::on_button_press_event (GdkEventButton* event) +{ - if (!mainCropWin) - return true; + if (!mainCropWin) { + return true; + } - if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { - int x, y, w, h; - getObservedFrameArea (x, y, w, h); - bool inside = event->x > x-6 && event->x < x+w-1+6 && event->y > y-6 && event->y < y+h-1+6; - bool moreInside = event->x > x+6 && event->x < x+w-1-6 && event->y > y+6 && event->y < y+h-1-6; + if(mainCropWin->getZoom() > mainCropWin->cropHandler.getFitZoom()) { + int x, y, w, h; + getObservedFrameArea (x, y, w, h); + bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; + bool moreInside = event->x > x + 6 && event->x < x + w - 1 - 6 && event->y > y + 6 && event->y < y + h - 1 - 6; - if (!isMoving) { - isMoving = true; - if (!inside || moreInside) { - mainCropWin->remoteMove ((event->x - (x+w/2))/zoom, (event->y - (y+h/2))/zoom); - press_x = x+w/2; - press_y = y+h/2; - } - else { - press_x = event->x; - press_y = event->y; - } - cursorManager.setCursor (get_window(), CSClosedHand); - } - } - return true; + if (!isMoving) { + isMoving = true; + + if (!inside || moreInside) { + mainCropWin->remoteMove ((event->x - (x + w / 2)) / zoom, (event->y - (y + h / 2)) / zoom); + press_x = x + w / 2; + press_y = y + h / 2; + } else { + press_x = event->x; + press_y = event->y; + } + + cursorManager.setCursor (get_window(), CSClosedHand); + } + } + + return true; } -bool PreviewWindow::on_button_release_event (GdkEventButton* event) { +bool PreviewWindow::on_button_release_event (GdkEventButton* event) +{ - if (!mainCropWin) - return true; + if (!mainCropWin) { + return true; + } - if (isMoving) { - isMoving = false; + if (isMoving) { + isMoving = false; cursorManager.setCursor (get_window(), CSArrow); - mainCropWin->remoteMoveReady (); - } - return true; + mainCropWin->remoteMoveReady (); + } + + return true; } diff --git a/rtgui/previewwindow.h b/rtgui/previewwindow.h index bedfc3abf..275f4bbe3 100644 --- a/rtgui/previewwindow.h +++ b/rtgui/previewwindow.h @@ -7,7 +7,7 @@ * 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 @@ -23,43 +23,44 @@ #include "previewhandler.h" #include "cropwindow.h" -class PreviewWindow : public Gtk::DrawingArea, public PreviewListener, public CropWindowListener { +class PreviewWindow : public Gtk::DrawingArea, public PreviewListener, public CropWindowListener +{ - private: - Glib::RefPtr backBuffer; - PreviewHandler* previewHandler; - sigc::connection rconn; - CropWindow* mainCropWin; - ImageArea* imageArea; - int imgX, imgY, imgW, imgH; - double zoom; - int press_x, press_y; - bool isMoving; - bool needsUpdate; - - void updatePreviewImage (); - void getObservedFrameArea (int& x, int& y, int& w, int& h); - - public: - PreviewWindow (); - - void setPreviewHandler (PreviewHandler* ph); - void setImageArea (ImageArea* ia); +private: + Glib::RefPtr backBuffer; + PreviewHandler* previewHandler; + sigc::connection rconn; + CropWindow* mainCropWin; + ImageArea* imageArea; + int imgX, imgY, imgW, imgH; + double zoom; + int press_x, press_y; + bool isMoving; + bool needsUpdate; - void on_realize (); - void on_resized (Gtk::Allocation& req); - bool on_expose_event (GdkEventExpose* event); - bool on_motion_notify_event (GdkEventMotion* event); - bool on_button_press_event (GdkEventButton* event); - bool on_button_release_event(GdkEventButton* event); - - // PreviewListener interface - void previewImageChanged (); - - // CropWindowListener interface - void cropPositionChanged (CropWindow* w); - void cropWindowSizeChanged (CropWindow* w); - void cropZoomChanged (CropWindow* w); + void updatePreviewImage (); + void getObservedFrameArea (int& x, int& y, int& w, int& h); + +public: + PreviewWindow (); + + void setPreviewHandler (PreviewHandler* ph); + void setImageArea (ImageArea* ia); + + void on_realize (); + void on_resized (Gtk::Allocation& req); + bool on_expose_event (GdkEventExpose* event); + bool on_motion_notify_event (GdkEventMotion* event); + bool on_button_press_event (GdkEventButton* event); + bool on_button_release_event(GdkEventButton* event); + + // PreviewListener interface + void previewImageChanged (); + + // CropWindowListener interface + void cropPositionChanged (CropWindow* w); + void cropWindowSizeChanged (CropWindow* w); + void cropZoomChanged (CropWindow* w); }; #endif diff --git a/rtgui/procparamchangers.h b/rtgui/procparamchangers.h index 759babefc..aeebae4fb 100644 --- a/rtgui/procparamchangers.h +++ b/rtgui/procparamchangers.h @@ -7,7 +7,7 @@ * 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 diff --git a/rtgui/profilechangelistener.h b/rtgui/profilechangelistener.h index b2673391a..0f6870c2d 100644 --- a/rtgui/profilechangelistener.h +++ b/rtgui/profilechangelistener.h @@ -7,7 +7,7 @@ * 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 @@ -22,20 +22,22 @@ #include "../rtengine/rtengine.h" #include -class ProfileChangeListener { +class ProfileChangeListener +{ - public: - virtual ~ProfileChangeListener() {} - virtual void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited=NULL) {} - virtual void setDefaults (rtengine::procparams::ProcParams* defparams) {} +public: + virtual ~ProfileChangeListener() {} + virtual void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited = NULL) {} + virtual void setDefaults (rtengine::procparams::ProcParams* defparams) {} }; -class BatchProfileChangeListener { +class BatchProfileChangeListener +{ - public: - virtual ~BatchProfileChangeListener() {} - virtual void beginBatchProfileChange(int numberOfEntries) {} - virtual void endBatchProfileChange() {} +public: + virtual ~BatchProfileChangeListener() {} + virtual void beginBatchProfileChange(int numberOfEntries) {} + virtual void endBatchProfileChange() {} }; diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index cb7d1ae40..eb655f424 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -7,7 +7,7 @@ * 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 @@ -30,15 +30,18 @@ using namespace rtengine::procparams; PartialPasteDlg* ProfilePanel::partialProfileDlg; -void ProfilePanel::init () { +void ProfilePanel::init () +{ partialProfileDlg = new PartialPasteDlg("Foo"); } -void ProfilePanel::cleanup () { +void ProfilePanel::cleanup () +{ delete partialProfileDlg; } -ProfilePanel::ProfilePanel (bool readOnly) : storedPProfile(NULL), lastFilename(""), imagePath("") { +ProfilePanel::ProfilePanel (bool readOnly) : storedPProfile(NULL), lastFilename(""), imagePath("") +{ tpc = NULL; @@ -58,26 +61,53 @@ ProfilePanel::ProfilePanel (bool readOnly) : storedPProfile(NULL), lastFilename( // pack_start (*profiles, Gtk::PACK_SHRINK, 4); pack_start (*hbox, Gtk::PACK_SHRINK, 4); - + load = Gtk::manage (new Gtk::Button ()); load->add (*Gtk::manage (new RTImage ("gtk-open.png"))); - if (!readOnly) save = Gtk::manage (new Gtk::Button ()); - if (!readOnly) save->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); - if (!readOnly) copy = Gtk::manage (new Gtk::Button ()); - if (!readOnly) copy->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + + if (!readOnly) { + save = Gtk::manage (new Gtk::Button ()); + } + + if (!readOnly) { + save->add (*Gtk::manage (new RTImage ("gtk-save-large.png"))); + } + + if (!readOnly) { + copy = Gtk::manage (new Gtk::Button ()); + } + + if (!readOnly) { + copy->add (*Gtk::manage (new RTImage ("edit-copy.png"))); + } + paste = Gtk::manage (new Gtk::Button ()); paste->add (*Gtk::manage (new RTImage ("edit-paste.png"))); hbox->pack_start (*fillMode, Gtk::PACK_SHRINK, 1); hbox->pack_start (*profiles); hbox->pack_start (*load, Gtk::PACK_SHRINK, 1); - if (!readOnly) hbox->pack_start (*save, Gtk::PACK_SHRINK, 1); + + if (!readOnly) { + hbox->pack_start (*save, Gtk::PACK_SHRINK, 1); + } + hbox->pack_start (*copy, Gtk::PACK_SHRINK, 1); - if (!readOnly) hbox->pack_start (*paste, Gtk::PACK_SHRINK, 1); + + if (!readOnly) { + hbox->pack_start (*paste, Gtk::PACK_SHRINK, 1); + } load->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::load_clicked) ); - if (!readOnly) save->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::save_clicked) ); - if (!readOnly) copy->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::copy_clicked) ); + + if (!readOnly) { + save->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::save_clicked) ); + } + + if (!readOnly) { + copy->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::copy_clicked) ); + } + paste->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ProfilePanel::paste_clicked) ); custom = NULL; @@ -89,109 +119,153 @@ ProfilePanel::ProfilePanel (bool readOnly) : storedPProfile(NULL), lastFilename( changeconn = profiles->signal_changed().connect( sigc::mem_fun(*this, &ProfilePanel::selection_changed) ); load->set_tooltip_markup (M("PROFILEPANEL_TOOLTIPLOAD")); - if (!readOnly) save->set_tooltip_markup (M("PROFILEPANEL_TOOLTIPSAVE")); - if (!readOnly) copy->set_tooltip_markup (M("PROFILEPANEL_TOOLTIPCOPY")); + + if (!readOnly) { + save->set_tooltip_markup (M("PROFILEPANEL_TOOLTIPSAVE")); + } + + if (!readOnly) { + copy->set_tooltip_markup (M("PROFILEPANEL_TOOLTIPCOPY")); + } + paste->set_tooltip_markup (M("PROFILEPANEL_TOOLTIPPASTE")); - + show_all_children (); } -ProfilePanel::~ProfilePanel () { +ProfilePanel::~ProfilePanel () +{ profileStore.removeListener(this); - if (custom) { custom->deleteInstance(); delete custom; } - if (lastsaved) { lastsaved->deleteInstance(); delete lastsaved; } + + if (custom) { + custom->deleteInstance(); + delete custom; + } + + if (lastsaved) { + lastsaved->deleteInstance(); + delete lastsaved; + } + delete profileFillModeOnImage; delete profileFillModeOffImage; } -bool ProfilePanel::isCustomSelected() { - if (profiles->getCurrentLabel() == Glib::ustring ("(" + M("PROFILEPANEL_PCUSTOM") + ")")) +bool ProfilePanel::isCustomSelected() +{ + if (profiles->getCurrentLabel() == Glib::ustring ("(" + M("PROFILEPANEL_PCUSTOM") + ")")) { return true; + } + return false; } -bool ProfilePanel::isLastSavedSelected() { - if (profiles->getCurrentLabel() == Glib::ustring ("(" + M("PROFILEPANEL_PLASTSAVED") + ")")) +bool ProfilePanel::isLastSavedSelected() +{ + if (profiles->getCurrentLabel() == Glib::ustring ("(" + M("PROFILEPANEL_PLASTSAVED") + ")")) { return true; + } + return false; } -Gtk::TreeIter ProfilePanel::getCustomRow() { +Gtk::TreeIter ProfilePanel::getCustomRow() +{ Gtk::TreeIter row; - if (custom) + + if (custom) { row = profiles->getRowFromLabel(Glib::ustring ("(" + M("PROFILEPANEL_PCUSTOM") + ")")); + } + return row; } -Gtk::TreeIter ProfilePanel::getLastSavedRow() { +Gtk::TreeIter ProfilePanel::getLastSavedRow() +{ Gtk::TreeIter row; + if (lastsaved) { row = profiles->getRowFromLabel(Glib::ustring ("(" + M("PROFILEPANEL_PLASTSAVED") + ")")); } + return row; } -Gtk::TreeIter ProfilePanel::addCustomRow() { +Gtk::TreeIter ProfilePanel::addCustomRow() +{ const ProfileStoreEntry *customPSE = new ProfileStoreEntry(Glib::ustring ("(" + M("PROFILEPANEL_PCUSTOM") + ")"), PSET_FILE, 0, 0); Gtk::TreeIter newEntry = profiles->addRow(customPSE); return newEntry; } -Gtk::TreeIter ProfilePanel::addLastSavedRow() { +Gtk::TreeIter ProfilePanel::addLastSavedRow() +{ const ProfileStoreEntry *lastSavedPSE = new ProfileStoreEntry(Glib::ustring ("(" + M("PROFILEPANEL_PLASTSAVED") + ")"), PSET_FILE, 0, 0); Gtk::TreeIter newEntry = profiles->addRow(lastSavedPSE); return newEntry; } -void ProfilePanel::storeCurrentValue () { +void ProfilePanel::storeCurrentValue () +{ // TODO: Find a way to get and restore the current selection; the following line can't work anymore storedValue = profiles->getFullPathFromActiveRow(); + if (!isCustomSelected() && !isLastSavedSelected()) { // storing the current entry's procparams, if not "Custom" or "LastSaved" // for now, the storedPProfile has default internal values const ProfileStoreEntry *entry = profiles->getSelectedEntry(); const PartialProfile *currProfile; - if (entry && (currProfile = profileStore.getProfile(entry))!=NULL) { + + if (entry && (currProfile = profileStore.getProfile(entry)) != NULL) { // now storedPProfile has the current entry's values storedPProfile = new PartialProfile(currProfile->pparams, currProfile->pedited, true); - } - else + } else { storedPProfile = new PartialProfile(true); + } } } /* Get the ProfileStore's entry list and recreate the combobox entries * If you want want to update the ProfileStore list itself (rescan the dir tree), use its "parseProfiles" method instead */ -void ProfilePanel::updateProfileList () { +void ProfilePanel::updateProfileList () +{ bool ccPrevState = changeconn.block(true); // rescan file tree profiles->updateProfileList(); - if (custom) + if (custom) { addCustomRow(); + } - if (lastsaved) + if (lastsaved) { addLastSavedRow(); + } changeconn.block (ccPrevState); } -void ProfilePanel::restoreValue () { +void ProfilePanel::restoreValue () +{ bool ccPrevState = changeconn.block(true); if (!profiles->setActiveRowFromFullPath(storedValue) && storedPProfile) { - if (custom) delete custom; + if (custom) { + delete custom; + } + custom = new PartialProfile (storedPProfile->pparams, storedPProfile->pedited, true); Gtk::TreeIter custRow = getCustomRow(); - if (custRow) + + if (custRow) { profiles->set_active(custRow); - else + } else { profiles->set_active (addCustomRow()); + } } currRow = profiles->get_active(); @@ -207,10 +281,12 @@ void ProfilePanel::restoreValue () { } } -void ProfilePanel::save_clicked (GdkEventButton* event) { +void ProfilePanel::save_clicked (GdkEventButton* event) +{ - if (event->button != 1) + if (event->button != 1) { return; + } Gtk::FileChooserDialog dialog(M("PROFILEPANEL_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); FileChooserLastFolderPersister persister( &dialog, options.loadSaveProfilePath ); @@ -218,22 +294,23 @@ void ProfilePanel::save_clicked (GdkEventButton* event) { //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 &err) {} + //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 &err) {} //Add response buttons the the dialog: dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); @@ -243,7 +320,7 @@ void ProfilePanel::save_clicked (GdkEventButton* event) { Gtk::FileFilter filter_pp; filter_pp.set_name(M("FILECHOOSER_FILTER_PP")); - filter_pp.add_pattern("*"+paramFileExtension); + filter_pp.add_pattern("*" + paramFileExtension); dialog.add_filter(filter_pp); Gtk::FileFilter filter_any; @@ -254,26 +331,30 @@ void ProfilePanel::save_clicked (GdkEventButton* event) { // dialog.set_do_overwrite_confirmation (true); bool done = false; + do { - if (dialog.run()==Gtk::RESPONSE_OK) { + if (dialog.run() == Gtk::RESPONSE_OK) { std::string fname = dialog.get_filename(); Glib::ustring ext = getExtension (fname); - if (("." + ext) != paramFileExtension) + if (("." + ext) != paramFileExtension) { fname += paramFileExtension; + } - if (!confirmOverwrite (dialog, fname)) + if (!confirmOverwrite (dialog, fname)) { continue; + } lastFilename = Glib::path_get_basename (fname); const PartialProfile* toSave; - if (isCustomSelected()) + + if (isCustomSelected()) { toSave = custom; - else if (isLastSavedSelected()) + } else if (isLastSavedSelected()) { toSave = lastsaved; - else { + } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); toSave = entry ? profileStore.getProfile (profiles->getSelectedEntry()) : NULL; } @@ -284,57 +365,66 @@ void ProfilePanel::save_clicked (GdkEventButton* event) { partialProfileDlg->set_title(M("PROFILEPANEL_SAVEPPASTE")); int i = partialProfileDlg->run(); partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) + + if (i != Gtk::RESPONSE_OK) { return; + } // saving the partial profile PartialProfile ppTemp(true); partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); int retCode = ppTemp.pparams->save (fname, "", true, ppTemp.pedited); ppTemp.deleteInstance(); - if (retCode) + + if (retCode) { writeFailed(dialog, fname); - else { - done=true; + } else { + done = true; bool ccPrevState = changeconn.block(true); profileStore.parseProfiles(); changeconn.block (ccPrevState); } - } - else { + } else { // saving a full profile int retCode = toSave->pparams->save (fname); - if (retCode) + + if (retCode) { writeFailed(dialog, fname); - else { - done=true; + } else { + done = true; bool ccPrevState = changeconn.block(true); profileStore.parseProfiles(); changeconn.block (ccPrevState); } } + } else { + done = true; } - else done = true; + } else { + done = true; } - else done = true; } while (!done); + return; } /* * Copy the actual full profile to the clipboard */ -void ProfilePanel::copy_clicked (GdkEventButton* event) { +void ProfilePanel::copy_clicked (GdkEventButton* event) +{ - if (event->button != 1) + if (event->button != 1) { return; + } const PartialProfile* toSave; - if (isCustomSelected()) + + if (isCustomSelected()) { toSave = custom; - else if (isLastSavedSelected()) - toSave = lastsaved; - else { + } else if (isLastSavedSelected()) { + toSave = lastsaved; + } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); toSave = entry ? profileStore.getProfile (entry) : NULL; } @@ -346,51 +436,56 @@ void ProfilePanel::copy_clicked (GdkEventButton* event) { partialProfileDlg->set_title(M("PROFILEPANEL_COPYPPASTE")); int i = partialProfileDlg->run(); partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) + + if (i != Gtk::RESPONSE_OK) { return; + } // saving a partial profile PartialProfile ppTemp(true); partialProfileDlg->applyPaste (ppTemp.pparams, ppTemp.pedited, toSave->pparams, toSave->pedited); clipboard.setPartialProfile(ppTemp); ppTemp.deleteInstance(); - } - else + } else { clipboard.setProcParams (*toSave->pparams); + } } + return; } /* * Load a potentially partial profile */ -void ProfilePanel::load_clicked (GdkEventButton* event) { +void ProfilePanel::load_clicked (GdkEventButton* event) +{ - if (event->button != 1) + if (event->button != 1) { return; + } Gtk::FileChooserDialog dialog(M("PROFILEPANEL_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN); FileChooserLastFolderPersister persister( &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 &err) {} //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 &err) {} //Add response buttons the the dialog: dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL); @@ -400,7 +495,7 @@ void ProfilePanel::load_clicked (GdkEventButton* event) { Gtk::FileFilter filter_pp; filter_pp.set_name(M("FILECHOOSER_FILTER_PP")); - filter_pp.add_pattern("*"+paramFileExtension); + filter_pp.add_pattern("*" + paramFileExtension); dialog.add_filter(filter_pp); Gtk::FileFilter filter_any; @@ -411,7 +506,7 @@ void ProfilePanel::load_clicked (GdkEventButton* event) { int result = dialog.run(); dialog.hide(); - if (result==Gtk::RESPONSE_OK) { + if (result == Gtk::RESPONSE_OK) { Glib::ustring fname = dialog.get_filename(); if (event->state & Gdk::CONTROL_MASK) { @@ -419,10 +514,14 @@ void ProfilePanel::load_clicked (GdkEventButton* event) { partialProfileDlg->set_title(M("PROFILEPANEL_LOADPPASTE")); int i = partialProfileDlg->run(); partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) + + if (i != Gtk::RESPONSE_OK) { return; + } } + bool customCreated = false; + if (!custom) { custom = new PartialProfile (true); customCreated = true; @@ -431,9 +530,12 @@ void ProfilePanel::load_clicked (GdkEventButton* event) { ProcParams pp; ParamsEdited pe; int err = pp.load (fname, &pe); + if (!err) { - if (!customCreated && fillMode->get_active()) + if (!customCreated && fillMode->get_active()) { custom->pparams->setDefaults(); + } + custom->set(true); bool prevState = changeconn.block(true); @@ -447,66 +549,80 @@ void ProfilePanel::load_clicked (GdkEventButton* event) { if (event->state & Gdk::CONTROL_MASK) // custom.pparams = loadedFile.pparams filtered by ( loadedFile.pedited & partialPaste.pedited ) - partialProfileDlg->applyPaste (custom->pparams, !fillMode->get_active()?custom->pedited:NULL, &pp, &pe); - else { + { + partialProfileDlg->applyPaste (custom->pparams, !fillMode->get_active() ? custom->pedited : NULL, &pp, &pe); + } else { // custom.pparams = loadedFile.pparams filtered by ( loadedFile.pedited ) pe.combine(*custom->pparams, pp, true); - if (!fillMode->get_active()) + + if (!fillMode->get_active()) { *custom->pedited = pe; + } } changeTo (custom, M("PROFILEPANEL_PFILE")); - } - else if (customCreated) { + } else if (customCreated) { // we delete custom custom->deleteInstance(); - delete custom; custom = NULL; + delete custom; + custom = NULL; } } + return; } /* * Paste a full profile from the clipboard */ -void ProfilePanel::paste_clicked (GdkEventButton* event) { +void ProfilePanel::paste_clicked (GdkEventButton* event) +{ - if (event->button != 1) + if (event->button != 1) { return; - if (!clipboard.hasProcParams()) + } + + if (!clipboard.hasProcParams()) { return; + } if (event->state & Gdk::CONTROL_MASK) { partialProfileDlg->set_title(M("PROFILEPANEL_PASTEPPASTE")); int i = partialProfileDlg->run(); partialProfileDlg->hide(); - if (i != Gtk::RESPONSE_OK) + + if (i != Gtk::RESPONSE_OK) { return; + } } bool prevState = changeconn.block(true); if (!custom) { custom = new PartialProfile (true); + if (isLastSavedSelected()) { *custom->pparams = *lastsaved->pparams; - } - else { + } else { const ProfileStoreEntry* entry = profiles->getSelectedEntry(); + if (entry) { const PartialProfile* partProfile = profileStore.getProfile (entry); *custom->pparams = *partProfile->pparams; } } + profiles->set_active (addCustomRow()); currRow = profiles->get_active(); - } - else { - if (fillMode->get_active()) + } else { + if (fillMode->get_active()) { custom->pparams->setDefaults(); + } + profiles->set_active(getCustomRow()); currRow = profiles->get_active(); } + custom->pedited->set(true); changeconn.block(prevState); @@ -515,23 +631,28 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) { // and paramsedited initialized to default in all cases ProcParams pp = clipboard.getProcParams (); + if (clipboard.hasPEdited()) { ParamsEdited pe = clipboard.getParamsEdited(); + if (event->state & Gdk::CONTROL_MASK) // custom.pparams = clipboard.pparams filtered by ( clipboard.pedited & partialPaste.pedited ) - partialProfileDlg->applyPaste (custom->pparams, !fillMode->get_active()?custom->pedited:NULL, &pp, &pe); - else { + { + partialProfileDlg->applyPaste (custom->pparams, !fillMode->get_active() ? custom->pedited : NULL, &pp, &pe); + } else { // custom.pparams = clipboard.pparams filtered by ( clipboard.pedited ) pe.combine(*custom->pparams, pp, true); - if (!fillMode->get_active()) + + if (!fillMode->get_active()) { *custom->pedited = pe; + } } - } - else { + } else { if (event->state & Gdk::CONTROL_MASK) // custom.pparams = clipboard.pparams filtered by ( partialPaste.pedited ) + { partialProfileDlg->applyPaste (custom->pparams, NULL, &pp, NULL); - else { + } else { // custom.pparams = clipboard.pparams non filtered *custom->pparams = pp; } @@ -541,25 +662,30 @@ void ProfilePanel::paste_clicked (GdkEventButton* event) { return; } -void ProfilePanel::changeTo (const PartialProfile* newpp, Glib::ustring profname) { +void ProfilePanel::changeTo (const PartialProfile* newpp, Glib::ustring profname) +{ - if (!newpp) + if (!newpp) { return; + } - if (tpc) - tpc->profileChange (newpp, EvProfileChanged, profname); + if (tpc) { + tpc->profileChange (newpp, EvProfileChanged, profname); + } } -void ProfilePanel::selection_changed () { +void ProfilePanel::selection_changed () +{ if (isCustomSelected()) { - if (!dontupdate) + if (!dontupdate) { changeTo (custom, Glib::ustring ("(" + M("PROFILEPANEL_PCUSTOM") + ")")); - } - else if (isLastSavedSelected()) - changeTo (lastsaved, Glib::ustring ("(" + M("PROFILEPANEL_PLASTSAVED") + ")")); - else { + } + } else if (isLastSavedSelected()) { + changeTo (lastsaved, Glib::ustring ("(" + M("PROFILEPANEL_PLASTSAVED") + ")")); + } else { const ProfileStoreEntry *pse = profiles->getSelectedEntry(); + if (pse->type == PSET_FOLDER) { // this entry is invalid, restoring the old value bool ccPrevState = changeconn.block(true); @@ -567,43 +693,48 @@ void ProfilePanel::selection_changed () { changeconn.block(ccPrevState); dontupdate = false; return; - } - else + } else { currRow = profiles->get_active(); + } const PartialProfile* s = profileStore.getProfile (pse); + if (s) { if (fillMode->get_active() && s->pedited) { ParamsEdited pe(true); PartialProfile s2(s->pparams, &pe, false); - changeTo (&s2, pse->label+"+"); - } - else + changeTo (&s2, pse->label + "+"); + } else { changeTo (s, pse->label); + } } } + dontupdate = false; } -void ProfilePanel::procParamsChanged (rtengine::procparams::ProcParams* p, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) { +void ProfilePanel::procParamsChanged (rtengine::procparams::ProcParams* p, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) +{ // to prevent recursion, filter out the events caused by the profilepanel - if (ev==EvProfileChanged || ev==EvPhotoLoaded) + if (ev == EvProfileChanged || ev == EvPhotoLoaded) { return; + } if (!isCustomSelected()) { dontupdate = true; + if (!custom) { custom = new PartialProfile (true); custom->set(true); profiles->set_active (addCustomRow()); currRow = profiles->get_active(); - } - else { + } else { profiles->set_active(getCustomRow()); currRow = profiles->get_active(); } } + *custom->pparams = *p; } @@ -614,7 +745,8 @@ void ProfilePanel::procParamsChanged (rtengine::procparams::ProcParams* p, rteng * @param profileFullPath full path of the profile; must start by the virtual root (${G} or ${U}, and without suffix * @param lastSaved pointer to the last saved ProcParam; may be NULL */ -void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams* lastSaved) { +void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams* lastSaved) +{ const ProfileStoreEntry *pse = NULL; const PartialProfile *defprofile = NULL; @@ -623,13 +755,16 @@ void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams if (custom) { custom->deleteInstance(); - delete custom; custom = NULL; + delete custom; + custom = NULL; } if (lastsaved) { lastsaved->deleteInstance(); - delete lastsaved; lastsaved = NULL; + delete lastsaved; + lastsaved = NULL; } + if (lastSaved) { ParamsEdited* pe = new ParamsEdited(true); // copying the provided last saved profile to ProfilePanel::lastsaved @@ -640,6 +775,7 @@ void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams updateProfileList(); Gtk::TreeIter lasSavedEntry; + // adding the Last Saved combobox entry, if needed if (lastsaved) { defprofile = lastsaved; @@ -658,43 +794,50 @@ void ProfilePanel::initProfile (const Glib::ustring& profileFullPath, ProcParams currRow = profiles->get_active(); if (lastsaved) { - if (lasSavedEntry) profiles->set_active (lasSavedEntry); + if (lasSavedEntry) { + profiles->set_active (lasSavedEntry); + } + currRow = profiles->get_active(); + if (tpc) { tpc->setDefaults (lastsaved->pparams); tpc->profileChange (lastsaved, EvPhotoLoaded, profiles->getSelectedEntry()->label); } - } - else { + } else { if (pse) { profiles->setActiveRowFromEntry(pse); currRow = profiles->get_active(); } + if (tpc) { tpc->setDefaults (defprofile->pparams); tpc->profileChange (defprofile, EvPhotoLoaded, profiles->getSelectedEntry()->label); } } + changeconn.block (ccPrevState); } -void ProfilePanel::setInitialFileName (const Glib::ustring& filename) { +void ProfilePanel::setInitialFileName (const Glib::ustring& filename) +{ lastFilename = Glib::path_get_basename(filename) + paramFileExtension; imagePath = Glib::path_get_dirname(filename); } -void ProfilePanel::profileFillModeToggled() { +void ProfilePanel::profileFillModeToggled() +{ if (fillMode->get_active()) { // The button is pressed, we'll use the profileFillModeOnImage fillMode->set_image(*profileFillModeOnImage); - } - else { + } else { // The button is released, we'll use the profileFillModeOffImage fillMode->set_image(*profileFillModeOffImage); } } -void ProfilePanel::writeOptions() { +void ProfilePanel::writeOptions() +{ options.filledProfile = fillMode->get_active(); } diff --git a/rtgui/profilepanel.h b/rtgui/profilepanel.h index b8e6b0a77..9bcc79196 100644 --- a/rtgui/profilepanel.h +++ b/rtgui/profilepanel.h @@ -7,7 +7,7 @@ * 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 @@ -29,9 +29,10 @@ #include "guiutils.h" #include "rtimage.h" -class ProfilePanel : public Gtk::VBox, public PParamsChangeListener, public ProfileStoreListener { +class ProfilePanel : public Gtk::VBox, public PParamsChangeListener, public ProfileStoreListener +{ - private: +private: rtengine::procparams::PartialProfile* storedPProfile; Glib::ustring storedValue; @@ -50,7 +51,7 @@ class ProfilePanel : public Gtk::VBox, public PParamsChangeListener, public Prof Gtk::TreeIter addCustomRow (); Gtk::TreeIter addLastSavedRow (); - protected: +protected: static PartialPasteDlg* partialProfileDlg; Gtk::Button* save; @@ -66,12 +67,15 @@ class ProfilePanel : public Gtk::VBox, public PParamsChangeListener, public Prof void changeTo (const rtengine::procparams::PartialProfile* newpp, Glib::ustring profname); - public: +public: - ProfilePanel (bool readOnly=false); + ProfilePanel (bool readOnly = false); virtual ~ProfilePanel (); - void setProfileChangeListener (ProfileChangeListener* ppl) { tpc = ppl; } + void setProfileChangeListener (ProfileChangeListener* ppl) + { + tpc = ppl; + } static void init (); static void cleanup (); @@ -83,7 +87,7 @@ class ProfilePanel : public Gtk::VBox, public PParamsChangeListener, public Prof void setInitialFileName (const Glib::ustring& filename); // PParamsChangeListener interface - void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL); + void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited = NULL); // gui callbacks void save_clicked (GdkEventButton* event); diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc index a2e4b0419..b0da47936 100644 --- a/rtgui/profilestore.cc +++ b/rtgui/profilestore.cc @@ -7,7 +7,7 @@ * 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 @@ -27,27 +27,34 @@ ProfileStore profileStore; using namespace rtengine; using namespace rtengine::procparams; -ProfileStore::ProfileStore () : parseMutex(NULL), storeState(STORESTATE_NOTINITIALIZED), internalDefaultProfile(NULL), internalDefaultEntry(NULL) { +ProfileStore::ProfileStore () : parseMutex(NULL), storeState(STORESTATE_NOTINITIALIZED), internalDefaultProfile(NULL), internalDefaultEntry(NULL) +{ internalDefaultProfile = new AutoPartialProfile(); internalDefaultProfile->set(true); } -bool ProfileStore::init () { - if (storeState == STORESTATE_DELETED) +bool ProfileStore::init () +{ + if (storeState == STORESTATE_DELETED) { return false; + } + if (storeState == STORESTATE_NOTINITIALIZED) { storeState = STORESTATE_BEINGINITIALIZED; parseMutex = new MyMutex(); _parseProfiles (); storeState = STORESTATE_INITIALIZED; } + return true; } -ProfileStore::~ProfileStore () { +ProfileStore::~ProfileStore () +{ - if (storeState == STORESTATE_NOTINITIALIZED) + if (storeState == STORESTATE_NOTINITIALIZED) { return; + } // This lock prevent object's suppression while scanning the directories storeState = STORESTATE_DELETED; @@ -71,28 +78,33 @@ ProfileStore::~ProfileStore () { * This method will scan the directory tree again and update the profile list. When finished, * the listeners will be called in order to update with the new list */ -void ProfileStore::parseProfiles () { +void ProfileStore::parseProfiles () +{ if (!init()) // I don't even know if this situation can occur - return; - - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); ++i) - (*i)->storeCurrentValue(); - { - MyMutex::MyLock lock(*parseMutex); - - _parseProfiles (); + return; } - for (std::list::iterator i=listeners.begin(); i!=listeners.end(); ++i) { + for (std::list::iterator i = listeners.begin(); i != listeners.end(); ++i) { + (*i)->storeCurrentValue(); + } + + { + MyMutex::MyLock lock(*parseMutex); + + _parseProfiles (); + } + + for (std::list::iterator i = listeners.begin(); i != listeners.end(); ++i) { (*i)->updateProfileList(); (*i)->restoreValue(); } } -void ProfileStore::_parseProfiles () { +void ProfileStore::_parseProfiles () +{ // Acquire the GUI, since the tree model can interact with combobox GThreadLock threadLock; @@ -111,6 +123,7 @@ void ProfileStore::_parseProfiles () { Glib::ustring virtualPath("${U}"); Glib::ustring currDir("${U}"); parseDir (p1, virtualPath, currDir, 0, 0, displayLevel0); + if (displayLevel0) { virtualPath = "${G}"; currDir = "${G}"; @@ -121,8 +134,10 @@ void ProfileStore::_parseProfiles () { std::sort(entries.begin(), entries.end(), SortProfiles() ); // entries and partProfiles are empty, but the entry and profiles already exist (they have survived to clearFileList and clearProfileList) - if (!internalDefaultEntry) + if (!internalDefaultEntry) { internalDefaultEntry = new ProfileStoreEntry(Glib::ustring("(") + M("PROFILEPANEL_PINTERNAL") + Glib::ustring(")"), PSET_FILE, 0, 0); + } + entries.push_back(internalDefaultEntry); partProfiles[internalDefaultEntry] = internalDefaultProfile; @@ -130,18 +145,24 @@ void ProfileStore::_parseProfiles () { // Check if the default profiles has been found. if (findEntryFromFullPathU(options.defProfRaw) == NULL) { options.setDefProfRawMissing(true); - if (options.rtSettings.verbose) + + if (options.rtSettings.verbose) { printf("WARNING: Default profile \"%s\" for raw images not found!\n", options.defProfRaw.c_str()); + } } + if (findEntryFromFullPathU(options.defProfImg) == NULL) { options.setDefProfImgMissing(true); - if (options.rtSettings.verbose) + + if (options.rtSettings.verbose) { printf("WARNING: Default profile \"%s\" for standard images not found!\n", options.defProfImg.c_str()); + } } } /// @return Returns true if some files has been found (directories are ignored) -bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0) { +bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0) +{ bool fileFound = false; unsigned int folder = 0; // folder's own Id @@ -151,14 +172,15 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath // add this entry to the folder list folders.push_back(virtualPath); - folder = (unsigned int)(folders.size())-1; + folder = (unsigned int)(folders.size()) - 1; - if (level>0 || displayLevel0) { + if (level > 0 || displayLevel0) { // replace the virtual folder name by a localized text - if (currDir == "${U}") + if (currDir == "${U}") { currDir = M("PROFILEPANEL_MYPROFILES"); - else if (currDir == "${G}") + } else if (currDir == "${G}") { currDir = M("PROFILEPANEL_GLOBALPROFILES"); + } // add this localized text to the file list entries.push_back( new ProfileStoreEntry(currDir, PSET_FOLDER, parentId, folder) ); @@ -167,34 +189,41 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath // walking through the directory Glib::Dir* dir = NULL; dir = new Glib::Dir (realPath); - for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) { + + for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) { currDir = *i; - if (currDir == "." || currDir == "..") + + if (currDir == "." || currDir == "..") { continue; + } Glib::ustring fname = Glib::build_filename(realPath, currDir); + if (safe_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); - } - else { + fileFound = parseDir (rp, vp, currDir, folder, level + 1, 0); + } else { size_t lastdot = currDir.find_last_of ('.'); - if (lastdot!=Glib::ustring::npos && lastdot<=currDir.size()-4 && !currDir.casefold().compare (lastdot, 4, paramFileExtension)) { - // file found - if( options.rtSettings.verbose ) - printf ("Processing file %s...", fname.c_str()); - Glib::ustring name = currDir.substr(0,lastdot); + if (lastdot != Glib::ustring::npos && lastdot <= currDir.size() - 4 && !currDir.casefold().compare (lastdot, 4, paramFileExtension)) { + // file found + if( options.rtSettings.verbose ) { + printf ("Processing file %s...", fname.c_str()); + } + + Glib::ustring name = currDir.substr(0, lastdot); // create the partial profile AutoPartialProfile *pProf = new AutoPartialProfile(); int res = pProf->load (fname); - if (!res && pProf->pparams->ppVersion>=220) { + + if (!res && pProf->pparams->ppVersion >= 220) { fileFound = true; - if( options.rtSettings.verbose ) + if( options.rtSettings.verbose ) { printf ("OK\n"); + } // adding this file to the list ProfileStoreEntry* filePSE = new ProfileStoreEntry(name, PSET_FILE, folder, 0); @@ -203,17 +232,17 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath // map the partial profile partProfiles[filePSE] = pProf; //partProfiles.insert( std::pair (filePSE, pProf) ); - } - else if( options.rtSettings.verbose ) { + } else if( options.rtSettings.verbose ) { printf ("failed!\n"); } } } } + delete dir; } - if (!fileFound && (level>0 || displayLevel0)) { + if (!fileFound && (level > 0 || displayLevel0)) { // no files found in this level, we delete the subdirectory entry folders.pop_back(); entries.pop_back(); @@ -222,12 +251,14 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath return fileFound; } -int ProfileStore::findFolderId(const Glib::ustring &path) { - for (std::vector::iterator i=folders.begin(); i!=folders.end(); i++) { +int ProfileStore::findFolderId(const Glib::ustring &path) +{ + for (std::vector::iterator i = folders.begin(); i != folders.end(); i++) { if (*i == path) { return i - folders.begin(); } } + return -1; } @@ -237,29 +268,36 @@ int ProfileStore::findFolderId(const Glib::ustring &path) { * but have to begin with a virtual location ( ${G} or ${U} ) * Will return null on invalid path or if the entry can't be found */ -const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path) { +const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path) +{ - if (path.empty()) + if (path.empty()) { return NULL; + } - if (path == DEFPROFILE_INTERNAL) + if (path == DEFPROFILE_INTERNAL) { return internalDefaultEntry; + } size_t lastdot = path.find_last_of ('.'); - if (lastdot!=Glib::ustring::npos && lastdot<=path.size()-4 && !path.casefold().compare (lastdot, 4, paramFileExtension)) + + if (lastdot != Glib::ustring::npos && lastdot <= path.size() - 4 && !path.casefold().compare (lastdot, 4, paramFileExtension)) // removing the extension - path = path.substr(0,lastdot); + { + path = path.substr(0, lastdot); + } // dir separator may come from options file and may be \ or /, we convert them to G_DIR_SEPARATOR_S - if (path.size() > 4 && (path[4] == '/' || path[4] == '\\')) - path = path.substr(0,4) + G_DIR_SEPARATOR_S + path.substr(5); + if (path.size() > 4 && (path[4] == '/' || path[4] == '\\')) { + path = path.substr(0, 4) + G_DIR_SEPARATOR_S + path.substr(5); + } // removing the filename Glib::ustring fName = Glib::path_get_basename(path); + if (!fName.empty()) { - path = path.substr(0, path.length()-fName.length()); - } - else { + path = path.substr(0, path.length() - fName.length()); + } else { // path is malformed, returning NULL; return NULL; } @@ -274,52 +312,64 @@ const ProfileStoreEntry* ProfileStore::findEntryFromFullPathU(Glib::ustring path } // 2. find the entry that match the given filename and parentFolderId - for (std::vector::iterator i=entries.begin(); i!=entries.end(); i++) { - if (((*i)->parentFolderId)==parentFolderId && (*i)->label==fName) + for (std::vector::iterator i = entries.begin(); i != entries.end(); i++) { + if (((*i)->parentFolderId) == parentFolderId && (*i)->label == fName) { return *i; + } } + return NULL; } /** Protected version of findEntryFromFullPathU */ -const ProfileStoreEntry* ProfileStore::findEntryFromFullPath(Glib::ustring path) { +const ProfileStoreEntry* ProfileStore::findEntryFromFullPath(Glib::ustring path) +{ MyMutex::MyLock lock(*parseMutex); return findEntryFromFullPathU(path); } -const PartialProfile* ProfileStore::getProfile (Glib::ustring path) { +const PartialProfile* ProfileStore::getProfile (Glib::ustring path) +{ if (!init()) // I don't even know if this situation can occur + { return NULL; + } const ProfileStoreEntry *pse = findEntryFromFullPath(path); - if (!pse) + + if (!pse) { return NULL; + } return getProfile(pse); } -const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry) { +const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry) +{ if (!init()) // I don't even know if this situation can occur + { return NULL; + } MyMutex::MyLock lock(*parseMutex); - if (entry == internalDefaultEntry) + if (entry == internalDefaultEntry) { return internalDefaultProfile; + } std::map::iterator iter = partProfiles.find(entry); + if (iter != partProfiles.end()) { return iter->second; - } - else { + } else { // This shouldn't happen! - #ifndef NDEBUG +#ifndef NDEBUG printf("WARNING! Profile not found!\n"); - #endif +#endif return NULL; } } @@ -329,7 +379,8 @@ const PartialProfile* ProfileStore::getProfile (const ProfileStoreEntry* entry) * This method grants you unique access to the vector list through Mutex locking. * When you're done with the file list, you MUST call the releaseFileList method to release the lock. */ -const std::vector* ProfileStore::getFileList () { +const std::vector* ProfileStore::getFileList () +{ /*if (!init()) { // I don't even know if this situation can occur return NULL; @@ -340,7 +391,8 @@ const std::vector* ProfileStore::getFileList () { return &entries; } -void ProfileStore::releaseFileList() { +void ProfileStore::releaseFileList() +{ parseMutex->unlock(); } @@ -349,16 +401,22 @@ void ProfileStore::releaseFileList() { * If the profile doesn't already exist in the profile list, * it will add it with default internal values, so this method never fails */ -const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) { +const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) +{ if (!init()) // I don't even know if this situation can occur + { return NULL; + } + //Note: the mutex is locked in getProfile, called below const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); - if (!pProf) pProf = internalDefaultProfile; + if (!pProf) { + pProf = internalDefaultProfile; + } return pProf->pparams; } @@ -368,50 +426,70 @@ const ProcParams* ProfileStore::getDefaultProcParams (bool isRaw) { * If it doesn't already exist in the profile list, it will add it with default internal values, * so this method will never fails */ -const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw) { +const PartialProfile* ProfileStore::getDefaultPartialProfile (bool isRaw) +{ if (!init()) // I don't even know if this situation can occur + { return NULL; + } + //Note: the mutex is locked in getProfile, called below const PartialProfile* pProf = getProfile (isRaw ? options.defProfRaw : options.defProfImg); - if (!pProf) pProf = internalDefaultProfile; + if (!pProf) { + pProf = internalDefaultProfile; + } return pProf; } -const Glib::ustring ProfileStore::getPathFromId(int folderId) { - return folders.at(folderId); +const Glib::ustring ProfileStore::getPathFromId(int folderId) +{ + return folders.at(folderId); } -void ProfileStore::clearFileList() { - for (std::vector::iterator i=entries.begin(); i!=entries.end(); ++i) - if (*i != internalDefaultEntry) delete *i; +void ProfileStore::clearFileList() +{ + for (std::vector::iterator i = entries.begin(); i != entries.end(); ++i) + if (*i != internalDefaultEntry) { + delete *i; + } + entries.clear(); } -void ProfileStore::clearProfileList() { - for (std::map::iterator i=partProfiles.begin(); i!=partProfiles.end(); ++i) - if (i->second != internalDefaultProfile) delete i->second; +void ProfileStore::clearProfileList() +{ + for (std::map::iterator i = partProfiles.begin(); i != partProfiles.end(); ++i) + if (i->second != internalDefaultProfile) { + delete i->second; + } + partProfiles.clear(); } -void ProfileStore::addListener(ProfileStoreListener *listener) { +void ProfileStore::addListener(ProfileStoreListener *listener) +{ listeners.push_back(listener); } -void ProfileStore::removeListener(ProfileStoreListener *listener) { +void ProfileStore::removeListener(ProfileStoreListener *listener) +{ listeners.remove(listener); } -void ProfileStore::dumpFolderList() { +void ProfileStore::dumpFolderList() +{ printf("Folder list:\n------------\n"); - for (unsigned int i=0; ilabel = label; this->type = type; parentFolderId = parentFolder; folderId = folder; } -ProfileStoreLabel::ProfileStoreLabel(const ProfileStoreEntry *entry) : Gtk::Label(entry->label), entry(entry) { +ProfileStoreLabel::ProfileStoreLabel(const ProfileStoreEntry *entry) : Gtk::Label(entry->label), entry(entry) +{ set_alignment(0, 0.5); show(); } -ProfileStoreComboBox::ProfileStoreComboBox () { +ProfileStoreComboBox::ProfileStoreComboBox () +{ updateProfileList(); } -Glib::ustring ProfileStoreComboBox::getCurrentLabel() { +Glib::ustring ProfileStoreComboBox::getCurrentLabel() +{ Glib::ustring currLabel; Gtk::TreeModel::iterator currRow = get_active(); @@ -443,31 +525,37 @@ Glib::ustring ProfileStoreComboBox::getCurrentLabel() { const ProfileStoreEntry *currEntry = (*currRow)[methodColumns.profileStoreEntry]; return currEntry->label; } + return currLabel; } -const ProfileStoreEntry* ProfileStoreComboBox::getSelectedEntry() { +const ProfileStoreEntry* ProfileStoreComboBox::getSelectedEntry() +{ Gtk::TreeModel::iterator currRow_ = get_active(); Gtk::TreeModel::Row currRow = *currRow_; - if (currRow) + + if (currRow) { return currRow[methodColumns.profileStoreEntry]; - else + } else { return NULL; + } } /** @brief Recursive method to update the combobox entries */ -void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList) { - for (std::vector::const_iterator i=entryList->begin(); i!=entryList->end(); i++) { +void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, int parentFolderId, bool initial, const std::vector *entryList) +{ + for (std::vector::const_iterator i = entryList->begin(); i != entryList->end(); i++) { if ((*i)->parentFolderId == parentFolderId) { // filtering the entry of the same folder if ((*i)->type == PSET_FOLDER) { Glib::ustring folderPath( profileStore.getPathFromId((*i)->folderId) ); + if (options.useBundledProfiles || ((folderPath != "${G}" ) && (folderPath != "${U}" ))) { // creating the new submenu Gtk::TreeModel::Row newSubMenu; + if (initial) { newSubMenu = *(refTreeModel->append()); - } - else { + } else { newSubMenu = *(refTreeModel->append(parentRow->children())); } @@ -476,17 +564,19 @@ void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, newSubMenu[methodColumns.profileStoreEntry] = *i; refreshProfileList_ (&newSubMenu, (*i)->folderId, false, entryList); - } - else + } else { refreshProfileList_ (parentRow, (*i)->folderId, true, entryList); - } - else { + } + } else { Gtk::TreeModel::Row newItem; + // creating a menu entry - if (initial) + if (initial) { newItem = *(refTreeModel->append()); - else + } else { newItem = *(refTreeModel->append(parentRow->children())); + } + newItem[methodColumns.label] = (*i)->label; newItem[methodColumns.profileStoreEntry] = *i; } @@ -499,7 +589,8 @@ void ProfileStoreComboBox::refreshProfileList_ (Gtk::TreeModel::Row *parentRow, * * This method has to be called by the ProfileStoreListener having a ProfileStoreComboBox. */ -void ProfileStoreComboBox::updateProfileList () { +void ProfileStoreComboBox::updateProfileList () +{ // clear items clear(); @@ -528,64 +619,77 @@ void ProfileStoreComboBox::updateProfileList () { pack_start(methodColumns.label, false); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) { +Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse) +{ Gtk::TreeModel::Row row; Gtk::TreeIter rowInSubLevel; + for(Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { row = *iter; // Hombre: is there a smarter way of knowing if this row has childs? const ProfileStoreEntry *pse_ = row[methodColumns.profileStoreEntry]; + if (pse_->type == PSET_FOLDER) { rowInSubLevel = findRowFromEntry_ (iter->children(), pse); + if (rowInSubLevel) { // entry found return rowInSubLevel; } - } - else if (pse_ == pse) { + } else if (pse_ == pse) { // entry found return iter; } } + return childs.end(); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *pse) { +Gtk::TreeIter ProfileStoreComboBox::findRowFromEntry (const ProfileStoreEntry *pse) +{ Gtk::TreeModel::Children childs = refTreeModel->children(); + if (pse) { Gtk::TreeIter row = findRowFromEntry_ (childs, pse); return row; } + return childs.end(); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name) { +Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath_ (Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name) +{ Gtk::TreeModel::Row row; Gtk::TreeIter rowInSubLevel; + for(Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { row = *iter; // Hombre: is there a smarter way of knowing if this row has childs? const ProfileStoreEntry *pse = row[methodColumns.profileStoreEntry]; + if (pse->type == PSET_FOLDER) { rowInSubLevel = findRowFromFullPath_ (iter->children(), parentFolderId, name); + if (rowInSubLevel) { // entry found return rowInSubLevel; } - } - else if (parentFolderId==pse->parentFolderId && name==pse->label) { + } else if (parentFolderId == pse->parentFolderId && name == pse->label) { // entry found return iter; } } + return childs.end(); } -Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) { +Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) +{ Gtk::TreeIter row; - if (path.empty()) + if (path.empty()) { return row; + } if (path == DEFPROFILE_INTERNAL) { row = findRowFromEntry(profileStore.getInternalDefaultPSE()); @@ -594,10 +698,10 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) { // removing the filename Glib::ustring fName = Glib::path_get_basename(path); + if (!fName.empty()) { - path = path.substr(0, path.length()-fName.length()); - } - else { + path = path.substr(0, path.length() - fName.length()); + } else { // path is malformed; return row; } @@ -606,8 +710,9 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) { int parentFolderId = profileStore.findFolderId(path); // 1. find the path in the folder list - if (parentFolderId != -1) + if (parentFolderId != -1) { row = findRowFromFullPath_ (refTreeModel->children(), parentFolderId, fName); + } return row; } @@ -616,74 +721,94 @@ Gtk::TreeIter ProfileStoreComboBox::findRowFromFullPath (Glib::ustring path) { * @return The absolute full path of the active row entry, or the "Internal" keyword, * or an empty string if the ComboBox is in an invalid state */ -Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() { +Glib::ustring ProfileStoreComboBox::getFullPathFromActiveRow() +{ Glib::ustring path; Gtk::TreeModel::iterator currRowI = get_active(); - if (!currRowI) + + if (!currRowI) { return path; + } Gtk::TreeModel::Row currRow = *currRowI; if (currRow) { const ProfileStoreEntry *currEntry = currRow[methodColumns.profileStoreEntry]; - if (!currEntry) - return path; - if (currEntry == profileStore.getInternalDefaultPSE()) + if (!currEntry) { + return path; + } + + if (currEntry == profileStore.getInternalDefaultPSE()) { return Glib::ustring(DEFPROFILE_INTERNAL); + } path = Glib::build_filename(profileStore.getPathFromId(currEntry->parentFolderId), currEntry->label); } + return path; } -bool ProfileStoreComboBox::setActiveRowFromFullPath(Glib::ustring path) { +bool ProfileStoreComboBox::setActiveRowFromFullPath(Glib::ustring path) +{ if (!path.empty()) { Gtk::TreeIter row = findRowFromFullPath(path); + if (row) { set_active(row); return true; } } + return false; } -bool ProfileStoreComboBox::setActiveRowFromEntry(const ProfileStoreEntry *pse) { +bool ProfileStoreComboBox::setActiveRowFromEntry(const ProfileStoreEntry *pse) +{ if (pse) { Gtk::TreeIter row = findRowFromEntry(pse); + if (row) { set_active(row); return true; } } + return false; } -bool ProfileStoreComboBox::setInternalEntry () { +bool ProfileStoreComboBox::setInternalEntry () +{ return setActiveRowFromEntry(profileStore.getInternalDefaultPSE()); } /** @brief Get the row from the first level of the tree that match the provided name */ -Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel(Glib::ustring name) { +Gtk::TreeIter ProfileStoreComboBox::getRowFromLabel(Glib::ustring name) +{ Gtk::TreeIter row; Gtk::TreeModel::Children childs = refTreeModel->children(); + if (!name.empty()) { Gtk::TreeModel::Row currRow; + for(Gtk::TreeModel::Children::iterator iter = childs.begin(); iter != childs.end(); ++iter) { currRow = *iter; const ProfileStoreEntry *pse = currRow[methodColumns.profileStoreEntry]; + if (pse->label == name) { return currRow; } } } + return childs.end(); //return refTreeModel->get_iter(""); // is this fast? We want to send back a null, anvalid or end() iterator object here } /** @brief Add a new row to the first level of the tree */ -Gtk::TreeIter ProfileStoreComboBox::addRow(const ProfileStoreEntry *profileStoreEntry) { +Gtk::TreeIter ProfileStoreComboBox::addRow(const ProfileStoreEntry *profileStoreEntry) +{ Gtk::TreeIter newEntry = refTreeModel->append(); Gtk::TreeModel::Row row = *newEntry; row[methodColumns.label] = profileStoreEntry->label; diff --git a/rtgui/profilestore.h b/rtgui/profilestore.h index bd9c019fb..2928a01ef 100644 --- a/rtgui/profilestore.h +++ b/rtgui/profilestore.h @@ -7,7 +7,7 @@ * 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 @@ -31,17 +31,18 @@ /** @brief This will implement callback functions for the ProfileStore * */ -class ProfileStoreListener { +class ProfileStoreListener +{ - public: - virtual ~ProfileStoreListener() {} +public: + virtual ~ProfileStoreListener() {} - /** @brief Called whenever the current value has to be stored before update. */ - virtual void storeCurrentValue() {} - /** @brief Called whenever the file list has been updated and the content of the listener has to be updated. */ - virtual void updateProfileList() =0; - /** @brief Called whenever the profile list has changed and the old value have to be restored (if possible). */ - virtual void restoreValue() {} + /** @brief Called whenever the current value has to be stored before update. */ + virtual void storeCurrentValue() {} + /** @brief Called whenever the file list has been updated and the content of the listener has to be updated. */ + virtual void updateProfileList() = 0; + /** @brief Called whenever the profile list has changed and the old value have to be restored (if possible). */ + virtual void restoreValue() {} }; /// @brief ProfileStoreEntry type (folder or file) @@ -56,57 +57,59 @@ typedef enum PSE_TYPE { * * Will be used as key element in the name / PartialProfile mapping */ -class ProfileStoreEntry { +class ProfileStoreEntry +{ - public: +public: - Glib::ustring label; /// Label to be used in menu or combobox = profile's filename - PSEType type; /// either PSET_FOLDER or PSET_FILE - unsigned short parentFolderId; /// index of the element's path in the folder list; id == 0 is reserved - unsigned short folderId; /// index of the folder's own path in the folder list; will be null for file entries + Glib::ustring label; /// Label to be used in menu or combobox = profile's filename + PSEType type; /// either PSET_FOLDER or PSET_FILE + unsigned short parentFolderId; /// index of the element's path in the folder list; id == 0 is reserved + unsigned short folderId; /// index of the folder's own path in the folder list; will be null for file entries - /** @brief Create a new ProfileStoreLabel with null values, that will have to be set later with setValues or the copy operator - */ - ProfileStoreEntry(); + /** @brief Create a new ProfileStoreLabel with null values, that will have to be set later with setValues or the copy operator + */ + ProfileStoreEntry(); - /** @brief Create a new ProfileStoreLabel with values - * @param label Label to be used in menu or combobox; also used as profile's filename - * @param type either PSET_FOLDER or PSET_FILE - * @param parentFolder index of the elements's path in the folder list - * @param folder index of the folder's own path in the folder list - */ - ProfileStoreEntry(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); + /** @brief Create a new ProfileStoreLabel with values + * @param label Label to be used in menu or combobox; also used as profile's filename + * @param type either PSET_FOLDER or PSET_FILE + * @param parentFolder index of the elements's path in the folder list + * @param folder index of the folder's own path in the folder list + */ + ProfileStoreEntry(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); - /** @brief Set the values of the object after its instantiation - * @param label Label to be used in menu or combobox; also used as profile's filename - * @param type either PSET_FOLDER or PSET_FILE - * @param parentFolder index of the elements's path in the folder list - * @param folder index of the folder's own path in the folder list - */ - void setValues(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); + /** @brief Set the values of the object after its instantiation + * @param label Label to be used in menu or combobox; also used as profile's filename + * @param type either PSET_FOLDER or PSET_FILE + * @param parentFolder index of the elements's path in the folder list + * @param folder index of the folder's own path in the folder list + */ + void setValues(Glib::ustring label, PSEType type, unsigned short parentFolder, unsigned short folder); }; /** * @brief subclass of Gtk::Label with extra fields for Combobox and Menu, to link with a ProfileStoreEntry */ -class ProfileStoreLabel : public Gtk::Label { +class ProfileStoreLabel : public Gtk::Label +{ - public: - const ProfileStoreEntry *entry; +public: + const ProfileStoreEntry *entry; #ifndef NDEBUG - ProfileStoreLabel() : Gtk::Label("*** error ***"), entry(NULL) {} + ProfileStoreLabel() : Gtk::Label("*** error ***"), entry(NULL) {} #else - ProfileStoreLabel() : Gtk::Label(""), entry(NULL) {} + ProfileStoreLabel() : Gtk::Label(""), entry(NULL) {} #endif - /** @brief Create a new ProfileStoreLabel - * - * @param entry Pointer to the ProfileStoreEntry object, be it a directory or a file - */ - ProfileStoreLabel(const ProfileStoreEntry *entry); - ProfileStoreLabel (const ProfileStoreLabel &other); + /** @brief Create a new ProfileStoreLabel + * + * @param entry Pointer to the ProfileStoreEntry object, be it a directory or a file + */ + ProfileStoreLabel(const ProfileStoreEntry *entry); + ProfileStoreLabel (const ProfileStoreLabel &other); }; @@ -115,91 +118,102 @@ class ProfileStoreLabel : public Gtk::Label { * This store can be queried by the GUI to display a Tree of the profiles available * in the user's and system's profile directory and subdirectories. */ -class ProfileStore { +class ProfileStore +{ - typedef enum { - STORESTATE_NOTINITIALIZED, - STORESTATE_BEINGINITIALIZED, - STORESTATE_INITIALIZED, - STORESTATE_DELETED - } StoreState; + typedef enum { + STORESTATE_NOTINITIALIZED, + STORESTATE_BEINGINITIALIZED, + STORESTATE_INITIALIZED, + STORESTATE_DELETED + } StoreState; - private: - struct SortProfiles { - bool operator ()(const ProfileStoreEntry* const a1, const ProfileStoreEntry* const a2) { - return a1->parentFolderId == a2->parentFolderId ? a1->label < a2->label : a1->parentFolderId < a2->parentFolderId; - } - }; +private: + struct SortProfiles { + bool operator ()(const ProfileStoreEntry* const a1, const ProfileStoreEntry* const a2) + { + return a1->parentFolderId == a2->parentFolderId ? a1->label < a2->label : a1->parentFolderId < a2->parentFolderId; + } + }; - MyMutex *parseMutex; - StoreState storeState; - rtengine::procparams::AutoPartialProfile *internalDefaultProfile; - ProfileStoreEntry *internalDefaultEntry; + MyMutex *parseMutex; + StoreState storeState; + rtengine::procparams::AutoPartialProfile *internalDefaultProfile; + ProfileStoreEntry *internalDefaultEntry; - /** Alphabetically ordered list of folder and files through Gtk::Label sub-class; - * ready to be used in Menu and Combobox - * The first element (#0) will be a fake path so ProfileStoreEntry can be attached to the root container */ - std::vector folders; + /** Alphabetically ordered list of folder and files through Gtk::Label sub-class; + * ready to be used in Menu and Combobox + * The first element (#0) will be a fake path so ProfileStoreEntry can be attached to the root container */ + std::vector folders; - /** Alphabetically ordered list of folder and files through Gtk::Label derived class; - * ready to be used in Menu and Combobox */ - std::vector entries; + /** Alphabetically ordered list of folder and files through Gtk::Label derived class; + * ready to be used in Menu and Combobox */ + std::vector entries; - /** List of PartialProfiles from the indexed files */ - std::map partProfiles; + /** List of PartialProfiles from the indexed files */ + std::map partProfiles; - /** List of the client of this store */ - std::list listeners; + /** List of the client of this store */ + std::list listeners; - /** @brief Method to recursively parse a profile folder with a level depth arbitrarily limited to 3 - * - * @param realPath current full path of the scanned directory ; e.g.: ~/MyProfiles/ - * @param virtualPath current full path that will be saved in "options" ; must start with either ${U} or ${G}, - * standing for User's and Global's (RT) profile folder, respectively - * @param currDir name of the directory to scan; it's the last element of the virtualPath - * @param parentId path entry of the parent folder - * @param level current level of the directory tree - * @param displayLevel0 if true, level 0 is created in order to have a User's and Bundled profiles separation (i.e. 2 root directories are expected) - * if false, only one root directory is expected - */ - bool parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0); - void _parseProfiles (); - void clearFileList (); - void clearProfileList (); - const ProfileStoreEntry* findEntryFromFullPathU(Glib::ustring path); + /** @brief Method to recursively parse a profile folder with a level depth arbitrarily limited to 3 + * + * @param realPath current full path of the scanned directory ; e.g.: ~/MyProfiles/ + * @param virtualPath current full path that will be saved in "options" ; must start with either ${U} or ${G}, + * standing for User's and Global's (RT) profile folder, respectively + * @param currDir name of the directory to scan; it's the last element of the virtualPath + * @param parentId path entry of the parent folder + * @param level current level of the directory tree + * @param displayLevel0 if true, level 0 is created in order to have a User's and Bundled profiles separation (i.e. 2 root directories are expected) + * if false, only one root directory is expected + */ + bool parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath, Glib::ustring& currDir, unsigned int parentId, unsigned char level, bool displayLevel0); + void _parseProfiles (); + void clearFileList (); + void clearProfileList (); + const ProfileStoreEntry* findEntryFromFullPathU(Glib::ustring path); - public: +public: - ProfileStore(); - ~ProfileStore(); - bool init (); - void parseProfiles (); - int findFolderId(const Glib::ustring &path); - const ProfileStoreEntry* findEntryFromFullPath(Glib::ustring path); - const rtengine::procparams::PartialProfile* getProfile (Glib::ustring path); - const rtengine::procparams::PartialProfile* getProfile (const ProfileStoreEntry* entry); - const std::vector* getFileList (); - void releaseFileList (); - const rtengine::procparams::ProcParams* getDefaultProcParams (bool isRaw); - const rtengine::procparams::PartialProfile* getDefaultPartialProfile (bool isRaw); - const Glib::ustring getPathFromId(int folderId); - const ProfileStoreEntry* getInternalDefaultPSE() { return internalDefaultEntry; } + ProfileStore(); + ~ProfileStore(); + bool init (); + void parseProfiles (); + int findFolderId(const Glib::ustring &path); + const ProfileStoreEntry* findEntryFromFullPath(Glib::ustring path); + const rtengine::procparams::PartialProfile* getProfile (Glib::ustring path); + const rtengine::procparams::PartialProfile* getProfile (const ProfileStoreEntry* entry); + const std::vector* getFileList (); + void releaseFileList (); + const rtengine::procparams::ProcParams* getDefaultProcParams (bool isRaw); + const rtengine::procparams::PartialProfile* getDefaultPartialProfile (bool isRaw); + const Glib::ustring getPathFromId(int folderId); + const ProfileStoreEntry* getInternalDefaultPSE() + { + return internalDefaultEntry; + } - void addListener(ProfileStoreListener *listener); - void removeListener(ProfileStoreListener *listener); + void addListener(ProfileStoreListener *listener); + void removeListener(ProfileStoreListener *listener); - void dumpFolderList(); + void dumpFolderList(); }; -class ProfileStoreComboBox : public MyComboBox { +class ProfileStoreComboBox : public MyComboBox +{ - protected: - class MethodColumns : public Gtk::TreeModel::ColumnRecord { - public: +protected: + class MethodColumns : public Gtk::TreeModel::ColumnRecord + { + public: Gtk::TreeModelColumn label; Gtk::TreeModelColumn profileStoreEntry; - MethodColumns() { add(label); add(profileStoreEntry); } + MethodColumns() + { + add(label); + add(profileStoreEntry); + } }; Glib::RefPtr refTreeModel; @@ -208,7 +222,7 @@ class ProfileStoreComboBox : public MyComboBox { Gtk::TreeIter findRowFromEntry_ (Gtk::TreeModel::Children childs, const ProfileStoreEntry *pse); Gtk::TreeIter findRowFromFullPath_(Gtk::TreeModel::Children childs, int parentFolderId, Glib::ustring &name); - public: +public: ProfileStoreComboBox(); void updateProfileList(); Glib::ustring getCurrentLabel(); diff --git a/rtgui/progressconnector.h b/rtgui/progressconnector.h index 791119aa2..ffa4bee67 100644 --- a/rtgui/progressconnector.h +++ b/rtgui/progressconnector.h @@ -7,7 +7,7 @@ * 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 @@ -26,74 +26,84 @@ #undef THREAD_PRIORITY_NORMAL -class PLDBridge : public rtengine::ProgressListener { +class PLDBridge : public rtengine::ProgressListener +{ - rtengine::ProgressListener* pl; + rtengine::ProgressListener* pl; - public: - PLDBridge ( rtengine::ProgressListener* pb) - : pl(pb) {} +public: + PLDBridge ( rtengine::ProgressListener* pb) + : pl(pb) {} // ProgressListener interface - void setProgress (double p) { + void setProgress (double p) + { GThreadLock lock; pl->setProgress(p); } - void setProgressStr (Glib::ustring str) { + void setProgressStr (Glib::ustring str) + { GThreadLock lock; Glib::ustring progrstr; progrstr = M(str); pl->setProgressStr(progrstr); } - void setProgressState (bool inProcessing){ + void setProgressState (bool inProcessing) + { GThreadLock lock; pl->setProgressState(inProcessing); } - void error (Glib::ustring descr){ + void error (Glib::ustring descr) + { GThreadLock lock; pl->error(descr); } }; template -class ProgressConnector { +class ProgressConnector +{ - sigc::signal0 opStart; - sigc::signal0 opEnd; - T retval; - Glib::Thread *workThread; + sigc::signal0 opStart; + sigc::signal0 opEnd; + T retval; + Glib::Thread *workThread; - static int emitEndSignalUI (void* data) { + static int emitEndSignalUI (void* data) + { - sigc::signal0* opEnd = (sigc::signal0*) data; - int r = opEnd->emit (); - delete opEnd; + sigc::signal0* opEnd = (sigc::signal0*) data; + int r = opEnd->emit (); + delete opEnd; - return r; - } - - void workingThread () { - retval = opStart.emit (); - g_idle_add (ProgressConnector::emitEndSignalUI, new sigc::signal0 (opEnd)); - workThread = 0; + return r; + } + + void workingThread () + { + retval = opStart.emit (); + g_idle_add (ProgressConnector::emitEndSignalUI, new sigc::signal0 (opEnd)); + workThread = 0; + } + +public: + + ProgressConnector (): workThread( 0 ) { } + + void startFunc (const sigc::slot0& startHandler, const sigc::slot0& endHandler ) + { + if( !workThread ) { + opStart.connect (startHandler); + opEnd.connect (endHandler); + workThread = Glib::Thread::create(sigc::mem_fun(*this, &ProgressConnector::workingThread), 0, true, true, Glib::THREAD_PRIORITY_NORMAL); } - - public: - - ProgressConnector ():workThread( 0 ) { } + } - void startFunc (const sigc::slot0& startHandler, const sigc::slot0& endHandler ) { - if( !workThread ){ - opStart.connect (startHandler); - opEnd.connect (endHandler); - workThread = Glib::Thread::create(sigc::mem_fun(*this, &ProgressConnector::workingThread), 0, true, true, Glib::THREAD_PRIORITY_NORMAL); - } - } - - T returnValue(){ - return retval; - } + T returnValue() + { + return retval; + } }; #endif diff --git a/rtgui/prsharpening.cc b/rtgui/prsharpening.cc index 1334ce06f..22a70e8a4 100644 --- a/rtgui/prsharpening.cc +++ b/rtgui/prsharpening.cc @@ -67,7 +67,7 @@ PrSharpening::PrSharpening () : FoldableToolPanel(this, "prsharpening", M("TP_PR amount = Gtk::manage (new Adjuster (M("TP_SHARPENING_AMOUNT"), 1, 1000, 1, 200)); radius = Gtk::manage (new Adjuster (M("TP_SHARPENING_RADIUS"), 0.3, 3, 0.01, 0.5)); threshold = Gtk::manage (new ThresholdAdjuster (M("TP_SHARPENING_THRESHOLD"), 0., 2000., 20., 80., 2000., 1200., 0, false)); - threshold->setAdjusterListener (this); + threshold->setAdjusterListener (this); threshold->setBgGradient(milestones); pack_start(*hsep6a, Gtk::PACK_SHRINK, 2); @@ -437,11 +437,12 @@ void PrSharpening::method_changed () } -void PrSharpening::adjusterChanged (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) { - if (listener && (multiImage||getEnabled()) ) { - if(a==threshold) { - listener->panelChanged (EvPrShrThresh,threshold->getHistoryString()); - } +void PrSharpening::adjusterChanged (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) +{ + if (listener && (multiImage || getEnabled()) ) { + if(a == threshold) { + listener->panelChanged (EvPrShrThresh, threshold->getHistoryString()); + } } } diff --git a/rtgui/quickzoomlistener.h b/rtgui/quickzoomlistener.h index 4cbaad8fc..5857bc259 100644 --- a/rtgui/quickzoomlistener.h +++ b/rtgui/quickzoomlistener.h @@ -7,7 +7,7 @@ * 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 @@ -19,9 +19,10 @@ #ifndef _QZLISTENER_ #define _QZLISTENER_ -class QuickZoomListener { +class QuickZoomListener +{ - public: +public: virtual void increaseZoom () {} virtual void decreaseZoom () {} diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index 60e4121a6..8060f322f 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -32,146 +32,160 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM Gtk::Image* icablueL = Gtk::manage (new RTImage ("ajd-ca-blue1.png")); Gtk::Image* icablueR = Gtk::manage (new RTImage ("ajd-ca-blue2.png")); - caAutocorrect = Gtk::manage(new Gtk::CheckButton((M("TP_RAWCACORR_AUTO")))); - caRed = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CARED"),-4.0,4.0,0.1,0,icaredL,icaredR)); - caRed->setAdjusterListener (this); - if (caRed->delay < 1000) caRed->delay = 1000; - caRed->show(); - caBlue = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CABLUE"),-4.0,4.0,0.1,0,icablueL,icablueR)); - caBlue->setAdjusterListener (this); - if (caBlue->delay < 1000) caBlue->delay = 1000; - caBlue->show(); + caAutocorrect = Gtk::manage(new Gtk::CheckButton((M("TP_RAWCACORR_AUTO")))); + caRed = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CARED"), -4.0, 4.0, 0.1, 0, icaredL, icaredR)); + caRed->setAdjusterListener (this); - pack_start( *caAutocorrect, Gtk::PACK_SHRINK, 4); - pack_start( *caRed, Gtk::PACK_SHRINK, 4); - pack_start( *caBlue, Gtk::PACK_SHRINK, 4); + if (caRed->delay < 1000) { + caRed->delay = 1000; + } - caacsconn = caAutocorrect->signal_toggled().connect ( sigc::mem_fun(*this, &RAWCACorr::caCorrectionChanged), true); + caRed->show(); + caBlue = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CABLUE"), -4.0, 4.0, 0.1, 0, icablueL, icablueR)); + caBlue->setAdjusterListener (this); + + if (caBlue->delay < 1000) { + caBlue->delay = 1000; + } + + caBlue->show(); + + pack_start( *caAutocorrect, Gtk::PACK_SHRINK, 4); + pack_start( *caRed, Gtk::PACK_SHRINK, 4); + pack_start( *caBlue, Gtk::PACK_SHRINK, 4); + + caacsconn = caAutocorrect->signal_toggled().connect ( sigc::mem_fun(*this, &RAWCACorr::caCorrectionChanged), true); } void RAWCACorr::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - caacsconn.block (true); + disableListener (); + caacsconn.block (true); - if(pedited ){ - caAutocorrect->set_inconsistent(!pedited->raw.caCorrection); - caRed->setEditedState( pedited->raw.caRed ? Edited : UnEdited ); - caBlue->setEditedState( pedited->raw.caBlue ? Edited : UnEdited ); - } + if(pedited ) { + caAutocorrect->set_inconsistent(!pedited->raw.caCorrection); + caRed->setEditedState( pedited->raw.caRed ? Edited : UnEdited ); + caBlue->setEditedState( pedited->raw.caBlue ? Edited : UnEdited ); + } - lastCA = pp->raw.ca_autocorrect; + lastCA = 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); + // 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); - caRed->setValue (pp->raw.cared); - caBlue->setValue (pp->raw.cablue); + caAutocorrect->set_active(pp->raw.ca_autocorrect); + caRed->setValue (pp->raw.cared); + caBlue->setValue (pp->raw.cablue); - caacsconn.block (false); - enableListener (); + caacsconn.block (false); + enableListener (); } void RAWCACorr::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.ca_autocorrect = caAutocorrect->get_active(); - pp->raw.cared = caRed->getValue(); - pp->raw.cablue = caBlue->getValue(); + pp->raw.ca_autocorrect = caAutocorrect->get_active(); + pp->raw.cared = caRed->getValue(); + pp->raw.cablue = caBlue->getValue(); - if (pedited) { - pedited->raw.caCorrection = !caAutocorrect->get_inconsistent(); - pedited->raw.caRed = caRed->getEditedState (); - pedited->raw.caBlue = caBlue->getEditedState (); - } + if (pedited) { + pedited->raw.caCorrection = !caAutocorrect->get_inconsistent(); + pedited->raw.caRed = caRed->getEditedState (); + pedited->raw.caBlue = caBlue->getEditedState (); + } } void RAWCACorr::adjusterChanged (Adjuster* a, double newval) { - if (listener) { + if (listener) { - Glib::ustring value = a->getTextValue(); + Glib::ustring value = a->getTextValue(); - if (a == caRed) - listener->panelChanged (EvPreProcessCARed, value ); - else if (a == caBlue) - listener->panelChanged (EvPreProcessCABlue, value ); - } + if (a == caRed) { + listener->panelChanged (EvPreProcessCARed, value ); + } else if (a == caBlue) { + listener->panelChanged (EvPreProcessCABlue, value ); + } + } } void RAWCACorr::setBatchMode(bool batchMode) { - ToolPanel::setBatchMode (batchMode); - caRed->showEditedCB (); - caBlue->showEditedCB (); + ToolPanel::setBatchMode (batchMode); + caRed->showEditedCB (); + caBlue->showEditedCB (); } void RAWCACorr::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - caRed->setDefault( defParams->raw.cared); - caBlue->setDefault( defParams->raw.cablue); + caRed->setDefault( defParams->raw.cared); + caBlue->setDefault( defParams->raw.cablue); - if (pedited) { - caRed->setDefaultEditedState( pedited->raw.caRed ? Edited : UnEdited); - caBlue->setDefaultEditedState( pedited->raw.caBlue ? Edited : UnEdited); - } else { - caRed->setDefaultEditedState( Irrelevant ); - caBlue->setDefaultEditedState( Irrelevant ); - } + if (pedited) { + caRed->setDefaultEditedState( pedited->raw.caRed ? Edited : UnEdited); + caBlue->setDefaultEditedState( pedited->raw.caBlue ? Edited : UnEdited); + } else { + caRed->setDefaultEditedState( Irrelevant ); + caBlue->setDefaultEditedState( Irrelevant ); + } } void RAWCACorr::caCorrectionChanged() { if (batchMode) { if (caAutocorrect->get_inconsistent()) { - caAutocorrect->set_inconsistent (false); - caacsconn.block (true); + caAutocorrect->set_inconsistent (false); + caacsconn.block (true); caAutocorrect->set_active (false); caacsconn.block (false); + } else if (lastCA) { + caAutocorrect->set_inconsistent (true); } - else if (lastCA) - caAutocorrect->set_inconsistent (true); lastCA = caAutocorrect->get_active (); } + /*else { - // For non batch mode, we disable the red and blue slider if caAutocorrect is true - if (caAutocorrect->get_active ()) { - caRed->set_sensitive(false); - caBlue->set_sensitive(false); - } - else { - caRed->set_sensitive(true); - caBlue->set_sensitive(true); - } + // For non batch mode, we disable the red and blue slider if caAutocorrect is true + if (caAutocorrect->get_active ()) { + caRed->set_sensitive(false); + caBlue->set_sensitive(false); + } + else { + caRed->set_sensitive(true); + caBlue->set_sensitive(true); + } }*/ // disable Red and Blue sliders when caAutocorrect is enabled - caRed->set_sensitive(!caAutocorrect->get_active ()); - caBlue->set_sensitive(!caAutocorrect->get_active ()); - if (caAutocorrect->get_active ()){ - // set caRed and caBlue to 0 as RawImageSource::CA_correct_RT uses this as - // a condition for auto-CA correction. Alternative would be to change - // RawImageSource::CA_correct_RT and pass it ca_autocorrect value - caRed->setValue(0); - caBlue->setValue(0); - } + caRed->set_sensitive(!caAutocorrect->get_active ()); + caBlue->set_sensitive(!caAutocorrect->get_active ()); - if (listener) - listener->panelChanged (EvPreProcessAutoCA, caAutocorrect->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + if (caAutocorrect->get_active ()) { + // set caRed and caBlue to 0 as RawImageSource::CA_correct_RT uses this as + // a condition for auto-CA correction. Alternative would be to change + // RawImageSource::CA_correct_RT and pass it ca_autocorrect value + caRed->setValue(0); + caBlue->setValue(0); + } + + if (listener) { + listener->panelChanged (EvPreProcessAutoCA, caAutocorrect->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } -void RAWCACorr::setAdjusterBehavior (bool caadd) { +void RAWCACorr::setAdjusterBehavior (bool caadd) +{ - caRed->setAddMode(caadd); - caBlue->setAddMode(caadd); + caRed->setAddMode(caadd); + caBlue->setAddMode(caadd); } -void RAWCACorr::trimValues (rtengine::procparams::ProcParams* pp) { +void RAWCACorr::trimValues (rtengine::procparams::ProcParams* pp) +{ - caRed->trimValue(pp->raw.cared); - caBlue->trimValue(pp->raw.cablue); + caRed->trimValue(pp->raw.cared); + caBlue->trimValue(pp->raw.cablue); } diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index 6d300c89d..7d41d9547 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -24,23 +24,24 @@ #include "toolpanel.h" #include "../rtengine/rawimage.h" -class RAWCACorr : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class RAWCACorr : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: Gtk::CheckButton* caAutocorrect; - Adjuster* caRed; + Adjuster* caRed; Adjuster* caBlue; - bool lastCA; - sigc::connection caacsconn; + bool lastCA; + sigc::connection caacsconn; public: - RAWCACorr (); + RAWCACorr (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setAdjusterBehavior (bool caadd); void trimValues (rtengine::procparams::ProcParams* pp); diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 0c91bfd77..ad81b9110 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -26,88 +26,99 @@ using namespace rtengine::procparams; RAWExposure::RAWExposure () : FoldableToolPanel(this, "rawexposure", M("TP_EXPOS_WHITEPOINT_LABEL")) { - PexPos = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_LINEAR"),0.1,16.0,0.01,1)); - PexPos->setAdjusterListener (this); - if (PexPos->delay < 1000) PexPos->delay = 1000; - PexPos->show(); - PexPreser = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_PRESER"),0,2.5,0.1,0)); - PexPreser->setAdjusterListener (this); - if (PexPreser->delay < 1000) PexPreser->delay = 1000; - PexPreser->show(); + PexPos = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_LINEAR"), 0.1, 16.0, 0.01, 1)); + PexPos->setAdjusterListener (this); - pack_start( *PexPos, Gtk::PACK_SHRINK, 4);//exposi - // raw highlight exposure setting is obsolete, removing from GUI - //pack_start( *PexPreser, Gtk::PACK_SHRINK, 4); + if (PexPos->delay < 1000) { + PexPos->delay = 1000; + } + + PexPos->show(); + PexPreser = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_PRESER"), 0, 2.5, 0.1, 0)); + PexPreser->setAdjusterListener (this); + + if (PexPreser->delay < 1000) { + PexPreser->delay = 1000; + } + + PexPreser->show(); + + pack_start( *PexPos, Gtk::PACK_SHRINK, 4);//exposi + // raw highlight exposure setting is obsolete, removing from GUI + //pack_start( *PexPreser, Gtk::PACK_SHRINK, 4); } void RAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener (); - if(pedited ){ - PexPos->setEditedState( pedited->raw.exPos ? Edited : UnEdited ); - PexPreser->setEditedState( pedited->raw.exPreser ? Edited : UnEdited ); - } + if(pedited ) { + PexPos->setEditedState( pedited->raw.exPos ? Edited : UnEdited ); + PexPreser->setEditedState( pedited->raw.exPreser ? Edited : UnEdited ); + } - PexPos->setValue (pp->raw.expos); - PexPreser->setValue (pp->raw.preser);//exposi + PexPos->setValue (pp->raw.expos); + PexPreser->setValue (pp->raw.preser);//exposi - enableListener (); + enableListener (); } void RAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.expos = PexPos->getValue(); - pp->raw.preser = PexPreser->getValue();//exposi + pp->raw.expos = PexPos->getValue(); + pp->raw.preser = PexPreser->getValue();//exposi - if (pedited) { - pedited->raw.exPos = PexPos->getEditedState (); - pedited->raw.exPreser = PexPreser->getEditedState ();//exposi - } + if (pedited) { + pedited->raw.exPos = PexPos->getEditedState (); + pedited->raw.exPreser = PexPreser->getEditedState ();//exposi + } } void RAWExposure::adjusterChanged (Adjuster* a, double newval) { - if (listener) { - Glib::ustring value = a->getTextValue(); + if (listener) { + Glib::ustring value = a->getTextValue(); - if (a == PexPos ) - listener->panelChanged (EvPreProcessExpCorrLinear, value ); - else if (a == PexPreser && ABS(PexPos->getValue()-1.0)>0.0001) // update takes long, only do it if it would have an effect - listener->panelChanged (EvPreProcessExpCorrPH, value ); - } + if (a == PexPos ) { + listener->panelChanged (EvPreProcessExpCorrLinear, value ); + } else if (a == PexPreser && ABS(PexPos->getValue() - 1.0) > 0.0001) { // update takes long, only do it if it would have an effect + listener->panelChanged (EvPreProcessExpCorrPH, value ); + } + } } void RAWExposure::setBatchMode(bool batchMode) { - ToolPanel::setBatchMode (batchMode); - PexPos->showEditedCB (); - PexPreser->showEditedCB ();//exposure + ToolPanel::setBatchMode (batchMode); + PexPos->showEditedCB (); + PexPreser->showEditedCB ();//exposure } void RAWExposure::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - PexPos->setDefault( defParams->raw.expos); - PexPreser->setDefault( defParams->raw.preser); + PexPos->setDefault( defParams->raw.expos); + PexPreser->setDefault( defParams->raw.preser); - if (pedited) { - PexPos->setDefaultEditedState( pedited->raw.exPos ? Edited : UnEdited); - PexPreser->setDefaultEditedState( pedited->raw.exPreser ? Edited : UnEdited); - } else { - PexPos->setDefaultEditedState( Irrelevant ); - PexPreser->setDefaultEditedState( Irrelevant ); - } + if (pedited) { + PexPos->setDefaultEditedState( pedited->raw.exPos ? Edited : UnEdited); + PexPreser->setDefaultEditedState( pedited->raw.exPreser ? Edited : UnEdited); + } else { + PexPos->setDefaultEditedState( Irrelevant ); + PexPreser->setDefaultEditedState( Irrelevant ); + } } -void RAWExposure::setAdjusterBehavior (bool pexposadd, bool pexpreseradd) { +void RAWExposure::setAdjusterBehavior (bool pexposadd, bool pexpreseradd) +{ - PexPos->setAddMode(pexposadd); - PexPreser->setAddMode(pexpreseradd); + PexPos->setAddMode(pexposadd); + PexPreser->setAddMode(pexpreseradd); } -void RAWExposure::trimValues (rtengine::procparams::ProcParams* pp) { +void RAWExposure::trimValues (rtengine::procparams::ProcParams* pp) +{ - PexPos->trimValue(pp->raw.expos); - PexPreser->trimValue(pp->raw.preser); + PexPos->trimValue(pp->raw.expos); + PexPreser->trimValue(pp->raw.preser); } diff --git a/rtgui/rawexposure.h b/rtgui/rawexposure.h index 11a158105..72e042892 100644 --- a/rtgui/rawexposure.h +++ b/rtgui/rawexposure.h @@ -24,22 +24,23 @@ #include "toolpanel.h" #include "../rtengine/rawimage.h" -class RAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class RAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - Adjuster* PexPos; - Adjuster* PexPreser; + Adjuster* PexPos; + Adjuster* PexPreser; private: -// Gtk::CheckButton* PextwoGreen; +// Gtk::CheckButton* PextwoGreen; public: - RAWExposure (); + RAWExposure (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void adjusterChanged (Adjuster* a, double newval); void setAdjusterBehavior (bool pexposadd, bool pexpreseradd); void trimValues (rtengine::procparams::ProcParams* pp); diff --git a/rtgui/rawprocess.cc b/rtgui/rawprocess.cc index d98766506..9a4f527ed 100644 --- a/rtgui/rawprocess.cc +++ b/rtgui/rawprocess.cc @@ -24,246 +24,277 @@ using namespace rtengine::procparams; RawProcess::RawProcess () : FoldableToolPanel(this) { - Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); - hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") +": ")),Gtk::PACK_SHRINK, 4); - dmethod = Gtk::manage (new MyComboBoxText ()); - for( size_t i=0; iappend_text(procparams::RAWParams::methodstring[i]); + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + dmethod = Gtk::manage (new MyComboBoxText ()); - dmethod->set_active(0); - hb1->set_tooltip_markup (M("TP_RAW_DMETHOD_TOOLTIP")); + for( size_t i = 0; i < procparams::RAWParams::numMethods; i++) { + dmethod->append_text(procparams::RAWParams::methodstring[i]); + } - hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb1, Gtk::PACK_SHRINK, 4); + dmethod->set_active(0); + hb1->set_tooltip_markup (M("TP_RAW_DMETHOD_TOOLTIP")); - dcbOptions = Gtk::manage (new Gtk::VBox ()); - dcbOptions->set_border_width(4); + hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb1, Gtk::PACK_SHRINK, 4); - dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"),0,5,1,2)); - dcbIterations->setAdjusterListener (this); - if (dcbIterations->delay < 1000) dcbIterations->delay = 1000; - dcbIterations->show(); - dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE"))); - dcbOptions->pack_start(*dcbIterations); - dcbOptions->pack_start(*dcbEnhance); - pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4); + dcbOptions = Gtk::manage (new Gtk::VBox ()); + dcbOptions->set_border_width(4); - lmmseOptions = Gtk::manage (new Gtk::VBox ()); - lmmseOptions->set_border_width(4); + dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"), 0, 5, 1, 2)); + dcbIterations->setAdjusterListener (this); - lmmseIterations = Gtk::manage (new Adjuster (M("TP_RAW_LMMSEITERATIONS"),0,6,1,2)); - lmmseIterations->setAdjusterListener (this); - lmmseIterations->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); + if (dcbIterations->delay < 1000) { + dcbIterations->delay = 1000; + } - if (lmmseIterations->delay < 1000) lmmseIterations->delay = 1000; - lmmseIterations->show(); - lmmseOptions->pack_start(*lmmseIterations); - pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); + dcbIterations->show(); + dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE"))); + dcbOptions->pack_start(*dcbIterations); + dcbOptions->pack_start(*dcbEnhance); + pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4); - pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"),0,5,1,0 )); - ccSteps->setAdjusterListener (this); - if (ccSteps->delay < 1000) ccSteps->delay = 1000; - ccSteps->show(); - pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + lmmseOptions = Gtk::manage (new Gtk::VBox ()); + lmmseOptions->set_border_width(4); - //pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - //allOptions = Gtk::manage (new Gtk::VBox ()); - //allOptions->set_border_width(2); - //allEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_ALLENHANCE"))); - //allOptions->pack_start(*allEnhance); - //pack_start( *allOptions, Gtk::PACK_SHRINK, 4); + lmmseIterations = Gtk::manage (new Adjuster (M("TP_RAW_LMMSEITERATIONS"), 0, 6, 1, 2)); + lmmseIterations->setAdjusterListener (this); + lmmseIterations->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); - methodconn = dmethod->signal_changed().connect( sigc::mem_fun(*this, &RawProcess::methodChanged) ); - dcbEnhconn = dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &RawProcess::dcbEnhanceChanged), true); - //allEnhconn = allEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &RawProcess::allEnhanceChanged), true); + if (lmmseIterations->delay < 1000) { + lmmseIterations->delay = 1000; + } + + lmmseIterations->show(); + lmmseOptions->pack_start(*lmmseIterations); + pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); + + pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); + ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 )); + ccSteps->setAdjusterListener (this); + + if (ccSteps->delay < 1000) { + ccSteps->delay = 1000; + } + + ccSteps->show(); + pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + + //pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); + //allOptions = Gtk::manage (new Gtk::VBox ()); + //allOptions->set_border_width(2); + //allEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_ALLENHANCE"))); + //allOptions->pack_start(*allEnhance); + //pack_start( *allOptions, Gtk::PACK_SHRINK, 4); + + methodconn = dmethod->signal_changed().connect( sigc::mem_fun(*this, &RawProcess::methodChanged) ); + dcbEnhconn = dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &RawProcess::dcbEnhanceChanged), true); + //allEnhconn = allEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &RawProcess::allEnhanceChanged), true); } void RawProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - methodconn.block (true); - dcbEnhconn.block (true); - //allEnhconn.block (true); + disableListener (); + methodconn.block (true); + dcbEnhconn.block (true); + //allEnhconn.block (true); - dmethod->set_active(procparams::RAWParams::numMethods); - for( size_t i=0; i< procparams::RAWParams::numMethods;i++) - if( pp->raw.dmethod == procparams::RAWParams::methodstring[i]){ - dmethod->set_active(i); - oldSelection = i; - break; - } + dmethod->set_active(procparams::RAWParams::numMethods); - if(pedited ){ - ccSteps->setEditedState (pedited->raw.ccSteps ? Edited : UnEdited); - dcbIterations->setEditedState ( pedited->raw.dcbIterations ? Edited : UnEdited); - dcbEnhance->set_inconsistent(!pedited->raw.dcbEnhance); - //allEnhance->set_inconsistent(!pedited->raw.allEnhance); - lmmseIterations->setEditedState ( pedited->raw.lmmseIterations ? Edited : UnEdited); + for( size_t i = 0; i < procparams::RAWParams::numMethods; i++) + if( pp->raw.dmethod == procparams::RAWParams::methodstring[i]) { + dmethod->set_active(i); + oldSelection = i; + break; + } - if( !pedited->raw.dmethod ) - dmethod->set_active(procparams::RAWParams::numMethods); // No name - } + if(pedited ) { + ccSteps->setEditedState (pedited->raw.ccSteps ? Edited : UnEdited); + dcbIterations->setEditedState ( pedited->raw.dcbIterations ? Edited : UnEdited); + dcbEnhance->set_inconsistent(!pedited->raw.dcbEnhance); + //allEnhance->set_inconsistent(!pedited->raw.allEnhance); + lmmseIterations->setEditedState ( pedited->raw.lmmseIterations ? Edited : UnEdited); - //allEnhance->set_active(pp->raw.all_enhance); + if( !pedited->raw.dmethod ) { + dmethod->set_active(procparams::RAWParams::numMethods); // No name + } + } - dcbIterations->setValue (pp->raw.dcb_iterations); - dcbEnhance->set_active(pp->raw.dcb_enhance); - ccSteps->setValue (pp->raw.ccSteps); - if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::dcb] || - dmethod->get_active_row_number() == procparams::RAWParams::numMethods) - dcbOptions->show(); - else - dcbOptions->hide(); + //allEnhance->set_active(pp->raw.all_enhance); - lmmseIterations->setValue (pp->raw.lmmse_iterations); - if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::lmmse] || - dmethod->get_active_row_number() == procparams::RAWParams::numMethods) - lmmseOptions->show(); - else - lmmseOptions->hide(); + dcbIterations->setValue (pp->raw.dcb_iterations); + dcbEnhance->set_active(pp->raw.dcb_enhance); + ccSteps->setValue (pp->raw.ccSteps); - // Flase color suppression is applied to all demozaicing method, so don't hide anything - /*if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::eahd] || - pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::hphd] || - pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::vng4]) - ccSteps->show(); - else - ccSteps->hide();*/ + if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::dcb] || + dmethod->get_active_row_number() == procparams::RAWParams::numMethods) { + dcbOptions->show(); + } else { + dcbOptions->hide(); + } - lastDCBen = pp->raw.dcb_enhance; - //lastALLen = pp->raw.all_enhance; + lmmseIterations->setValue (pp->raw.lmmse_iterations); - methodconn.block (false); - dcbEnhconn.block (false); - //allEnhconn.block (false); - - enableListener (); + if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::lmmse] || + dmethod->get_active_row_number() == procparams::RAWParams::numMethods) { + lmmseOptions->show(); + } else { + lmmseOptions->hide(); + } + + // Flase color suppression is applied to all demozaicing method, so don't hide anything + /*if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::eahd] || + pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::hphd] || + pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::vng4]) + ccSteps->show(); + else + ccSteps->hide();*/ + + lastDCBen = pp->raw.dcb_enhance; + //lastALLen = pp->raw.all_enhance; + + methodconn.block (false); + dcbEnhconn.block (false); + //allEnhconn.block (false); + + enableListener (); } void RawProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.ccSteps = ccSteps->getIntValue(); - pp->raw.dcb_iterations = dcbIterations->getIntValue(); - pp->raw.dcb_enhance = dcbEnhance->get_active(); - //pp->raw.all_enhance = allEnhance->get_active(); - pp->raw.lmmse_iterations = lmmseIterations->getIntValue(); + pp->raw.ccSteps = ccSteps->getIntValue(); + pp->raw.dcb_iterations = dcbIterations->getIntValue(); + pp->raw.dcb_enhance = dcbEnhance->get_active(); + //pp->raw.all_enhance = allEnhance->get_active(); + pp->raw.lmmse_iterations = lmmseIterations->getIntValue(); - int currentRow = dmethod->get_active_row_number(); - if( currentRow>=0 && currentRow < procparams::RAWParams::numMethods) - pp->raw.dmethod = procparams::RAWParams::methodstring[currentRow]; + int currentRow = dmethod->get_active_row_number(); - if (pedited) { - pedited->raw.ccSteps = ccSteps->getEditedState (); - pedited->raw.dmethod = dmethod->get_active_row_number() != procparams::RAWParams::numMethods; - pedited->raw.dcbIterations = dcbIterations->getEditedState (); - pedited->raw.dcbEnhance = !dcbEnhance->get_inconsistent(); - //pedited->raw.allEnhance = !allEnhance->get_inconsistent(); - pedited->raw.lmmseIterations = lmmseIterations->getEditedState (); - - } + if( currentRow >= 0 && currentRow < procparams::RAWParams::numMethods) { + pp->raw.dmethod = procparams::RAWParams::methodstring[currentRow]; + } + + if (pedited) { + pedited->raw.ccSteps = ccSteps->getEditedState (); + pedited->raw.dmethod = dmethod->get_active_row_number() != procparams::RAWParams::numMethods; + pedited->raw.dcbIterations = dcbIterations->getEditedState (); + pedited->raw.dcbEnhance = !dcbEnhance->get_inconsistent(); + //pedited->raw.allEnhance = !allEnhance->get_inconsistent(); + pedited->raw.lmmseIterations = lmmseIterations->getEditedState (); + + } } void RawProcess::setBatchMode(bool batchMode) { - dmethod->append_text (M("GENERAL_UNCHANGED")); - dmethod->set_active(procparams::RAWParams::numMethods); // No name - dcbOptions->hide(); - lmmseOptions->hide(); - ToolPanel::setBatchMode (batchMode); - ccSteps->showEditedCB (); - dcbIterations->showEditedCB (); - lmmseIterations->showEditedCB (); - + dmethod->append_text (M("GENERAL_UNCHANGED")); + dmethod->set_active(procparams::RAWParams::numMethods); // No name + dcbOptions->hide(); + lmmseOptions->hide(); + ToolPanel::setBatchMode (batchMode); + ccSteps->showEditedCB (); + dcbIterations->showEditedCB (); + lmmseIterations->showEditedCB (); + } void RawProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - dcbIterations->setDefault( defParams->raw.dcb_iterations); - lmmseIterations->setDefault( defParams->raw.lmmse_iterations); - ccSteps->setDefault (defParams->raw.ccSteps); - if (pedited) { - dcbIterations->setDefaultEditedState( pedited->raw.dcbIterations ? Edited : UnEdited); - lmmseIterations->setDefaultEditedState( pedited->raw.lmmseIterations ? Edited : UnEdited); - ccSteps->setDefaultEditedState(pedited->raw.ccSteps ? Edited : UnEdited); - }else{ - dcbIterations->setDefaultEditedState( Irrelevant ); - lmmseIterations->setDefaultEditedState( Irrelevant ); - ccSteps->setDefaultEditedState(Irrelevant ); - } + dcbIterations->setDefault( defParams->raw.dcb_iterations); + lmmseIterations->setDefault( defParams->raw.lmmse_iterations); + ccSteps->setDefault (defParams->raw.ccSteps); + + if (pedited) { + dcbIterations->setDefaultEditedState( pedited->raw.dcbIterations ? Edited : UnEdited); + lmmseIterations->setDefaultEditedState( pedited->raw.lmmseIterations ? Edited : UnEdited); + ccSteps->setDefaultEditedState(pedited->raw.ccSteps ? Edited : UnEdited); + } else { + dcbIterations->setDefaultEditedState( Irrelevant ); + lmmseIterations->setDefaultEditedState( Irrelevant ); + ccSteps->setDefaultEditedState(Irrelevant ); + } } void RawProcess::adjusterChanged (Adjuster* a, double newval) { if (listener) { - if (a == dcbIterations) - listener->panelChanged (EvDemosaicDCBIter, a->getTextValue() ); - else if (a == ccSteps) - listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); - else if (a == lmmseIterations) - listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); + if (a == dcbIterations) { + listener->panelChanged (EvDemosaicDCBIter, a->getTextValue() ); + } else if (a == ccSteps) { + listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); + } else if (a == lmmseIterations) { + listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); + } - } + } } void RawProcess::methodChanged () { - int curSelection = dmethod->get_active_row_number(); - if ( curSelection == procparams::RAWParams::dcb){ - dcbOptions->show(); - }else{ - dcbOptions->hide(); - } - if ( curSelection == procparams::RAWParams::lmmse){ - lmmseOptions->show(); - }else{ - lmmseOptions->hide(); - } - - Glib::ustring methodName=""; - bool ppreq = false; - if( curSelection>=0 && curSelection < procparams::RAWParams::numMethods) { - methodName = procparams::RAWParams::methodstring[curSelection]; - if (curSelection == procparams::RAWParams::mono || oldSelection == procparams::RAWParams::mono) { - ppreq = true; - } - } - oldSelection = curSelection; + int curSelection = dmethod->get_active_row_number(); - if (listener) - listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + if ( curSelection == procparams::RAWParams::dcb) { + dcbOptions->show(); + } else { + dcbOptions->hide(); + } + + if ( curSelection == procparams::RAWParams::lmmse) { + lmmseOptions->show(); + } else { + lmmseOptions->hide(); + } + + Glib::ustring methodName = ""; + bool ppreq = false; + + if( curSelection >= 0 && curSelection < procparams::RAWParams::numMethods) { + methodName = procparams::RAWParams::methodstring[curSelection]; + + if (curSelection == procparams::RAWParams::mono || oldSelection == procparams::RAWParams::mono) { + ppreq = true; + } + } + + oldSelection = curSelection; + + if (listener) { + listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + } } void RawProcess::dcbEnhanceChanged () { if (batchMode) { if (dcbEnhance->get_inconsistent()) { - dcbEnhance->set_inconsistent (false); - dcbEnhconn.block (true); - dcbEnhance->set_active (false); - dcbEnhconn.block (false); + dcbEnhance->set_inconsistent (false); + dcbEnhconn.block (true); + dcbEnhance->set_active (false); + dcbEnhconn.block (false); + } else if (lastDCBen) { + dcbEnhance->set_inconsistent (true); } - else if (lastDCBen) - dcbEnhance->set_inconsistent (true); lastDCBen = dcbEnhance->get_active (); } - if (listener) - listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED")); + + if (listener) { + listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } } /*void RawProcess::allEnhanceChanged () { if (batchMode) { if (allEnhance->get_inconsistent()) { - allEnhance->set_inconsistent (false); - allEnhconn.block (true); - allEnhance->set_active (false); - allEnhconn.block (false); + allEnhance->set_inconsistent (false); + allEnhconn.block (true); + allEnhance->set_active (false); + allEnhconn.block (false); } else if (lastALLen) - allEnhance->set_inconsistent (true); + allEnhance->set_inconsistent (true); lastALLen = allEnhance->get_active (); } diff --git a/rtgui/rawprocess.h b/rtgui/rawprocess.h index f3c005219..85c1c9f44 100644 --- a/rtgui/rawprocess.h +++ b/rtgui/rawprocess.h @@ -25,9 +25,10 @@ #include "toolpanel.h" -class RawProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel{ +class RawProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: MyComboBoxText* dmethod; Gtk::Label* methodl; @@ -42,22 +43,22 @@ class RawProcess : public ToolParamBlock, public AdjusterListener, public Foldab bool lastDCBen; int oldSelection; - //bool lastALLen; - sigc::connection methodconn,dcbEnhconn; //,allEnhconn; - public: + //bool lastALLen; + sigc::connection methodconn, dcbEnhconn; //,allEnhconn; +public: RawProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void methodChanged (); void adjusterChanged (Adjuster* a, double newval); void dcbEnhanceChanged(); //void allEnhanceChanged(); - + }; #endif diff --git a/rtgui/recentbrowser.cc b/rtgui/recentbrowser.cc index 8d0abde1c..80d56de4d 100644 --- a/rtgui/recentbrowser.cc +++ b/rtgui/recentbrowser.cc @@ -7,7 +7,7 @@ * 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 @@ -22,13 +22,15 @@ using namespace rtengine; -RecentBrowser::RecentBrowser () : listener (NULL) { +RecentBrowser::RecentBrowser () : listener (NULL) +{ recentDirs = Gtk::manage (new MyComboBoxText ()); Gtk::Frame* frame = Gtk::manage (new Gtk::Frame (M("MAIN_FRAME_RECENT"))); frame->add (*recentDirs); - for(size_t i=0;iappend_text (options.recentFolders[i]); } @@ -39,31 +41,39 @@ RecentBrowser::RecentBrowser () : listener (NULL) { show_all (); } -void RecentBrowser::selectionChanged () { +void RecentBrowser::selectionChanged () +{ Glib::ustring sel = recentDirs->get_active_text (); - if (sel!="" && listener) + + if (sel != "" && listener) { listener->selectDir (sel); + } } -void RecentBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { - +void RecentBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) +{ + size_t numFolders = options.recentFolders.size(); - if(numFolders>0) { // search entry and move to top if it exists + + if(numFolders > 0) { // search entry and move to top if it exists size_t i; - for(i=0;i0) { - if(i 0) { + if(i < numFolders) { + options.recentFolders.erase(options.recentFolders.begin() + i); } - options.recentFolders.insert(options.recentFolders.begin(),dirname); + + options.recentFolders.insert(options.recentFolders.begin(), dirname); } } else { - options.recentFolders.insert(options.recentFolders.begin(),dirname); + options.recentFolders.insert(options.recentFolders.begin(), dirname); } conn.block (true); diff --git a/rtgui/recentbrowser.h b/rtgui/recentbrowser.h index dc309945b..511207fa4 100644 --- a/rtgui/recentbrowser.h +++ b/rtgui/recentbrowser.h @@ -7,7 +7,7 @@ * 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 @@ -25,20 +25,24 @@ #include "multilangmgr.h" #include "guiutils.h" -class RecentBrowser : public Gtk::VBox, public DirSelectionListener { +class RecentBrowser : public Gtk::VBox, public DirSelectionListener +{ - Gtk::ComboBoxText* recentDirs; - sigc::connection conn; - DirBrowserRemoteInterface* listener; + Gtk::ComboBoxText* recentDirs; + sigc::connection conn; + DirBrowserRemoteInterface* listener; - public: - - RecentBrowser (); - - void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { listener = l; } - - void selectionChanged (); - void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile=""); +public: + + RecentBrowser (); + + void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) + { + listener = l; + } + + void selectionChanged (); + void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile = ""); }; #endif diff --git a/rtgui/recentselectionlistener.h b/rtgui/recentselectionlistener.h index f1765cb7c..a06048336 100644 --- a/rtgui/recentselectionlistener.h +++ b/rtgui/recentselectionlistener.h @@ -7,7 +7,7 @@ * 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 @@ -21,10 +21,11 @@ #include -class RecentSelectionListener { +class RecentSelectionListener +{ - public: - virtual void recentSelected (Glib::ustring recentdir) {} +public: + virtual void recentSelected (Glib::ustring recentdir) {} }; #endif diff --git a/rtgui/renamedlg.cc b/rtgui/renamedlg.cc index 97883ce03..a33011f09 100644 --- a/rtgui/renamedlg.cc +++ b/rtgui/renamedlg.cc @@ -7,7 +7,7 @@ * 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 @@ -21,15 +21,16 @@ #include "options.h" #include "rtimage.h" -RenameDialog::RenameDialog (Gtk::Window* parent) - : Gtk::Dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *parent, true, true), p(parent), imageData(NULL) { - +RenameDialog::RenameDialog (Gtk::Window* parent) + : Gtk::Dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *parent, true, true), p(parent), imageData(NULL) +{ + Gtk::Table* names = Gtk::manage (new Gtk::Table (2, 2)); Gtk::Label* onlab = Gtk::manage (new Gtk::Label (M("FILEBROWSER_CURRENT_NAME"))); - Gtk::Label* nnlab = Gtk::manage (new Gtk::Label (M("FILEBROWSER_NEW_NAME"))); + Gtk::Label* nnlab = Gtk::manage (new Gtk::Label (M("FILEBROWSER_NEW_NAME"))); oldName = Gtk::manage (new Gtk::Label ("alma")); newName = Gtk::manage (new Gtk::Entry ()); - + names->attach (*onlab, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2); names->attach (*oldName, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2); names->attach (*nnlab, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 2, 2); @@ -47,53 +48,57 @@ RenameDialog::RenameDialog (Gtk::Window* parent) // tbox->pack_start (*useTmpl, Gtk::PACK_SHRINK, 4); // tbox->pack_start (*templates); - + // get_vbox()->pack_start (*tbox, Gtk::PACK_SHRINK, 4); - + add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); -// Issue 316 +// Issue 316 // all = add_button ("All", RESPONSE_ALL); newName->set_activates_default (true); set_default_response (Gtk::RESPONSE_OK); -// Issue 316 +// Issue 316 // fillTemplateList (); // templates->set_row_separator_func (sigc::mem_fun(*this, &RenameDialog::rowSeparatorFunc)); // templates->signal_changed().connect(sigc::mem_fun(*this, &RenameDialog::tmplSelectionChanged)); // useTmpl->signal_toggled().connect( sigc::mem_fun(*this, &RenameDialog::useTemplToggled) ); - + // useTmpl->set_active (options.renameUseTemplates); show_all_children (); } -void RenameDialog::initName (const Glib::ustring& iname, const CacheImageData* cid) { +void RenameDialog::initName (const Glib::ustring& iname, const CacheImageData* cid) +{ imageData = cid; oldName->set_text (iname); newName->set_text (iname); // Issue 316 -// if (useTmpl->get_active () && isTemplSelected ()) +// if (useTmpl->get_active () && isTemplSelected ()) // newName->set_text (applyTemplate (iname, cid, getActiveTemplate())); newName->select_region (0, newName->get_text().size()); } -Glib::ustring RenameDialog::getNewName () { +Glib::ustring RenameDialog::getNewName () +{ return newName->get_text (); } -void RenameDialog::fillTemplateList () { +void RenameDialog::fillTemplateList () +{ templateModel->clear (); - for (size_t i=0; iappend (); iter->set_value (templateColumns.tmplName, options.renameTemplates[i]); iter->set_value (templateColumns.rowSeparator, false); } + // append separator and the manage... item Gtk::TreeModel::iterator iter = templateModel->append (); iter->set_value (templateColumns.tmplName, Glib::ustring("")); @@ -103,60 +108,73 @@ void RenameDialog::fillTemplateList () { iter->set_value (templateColumns.rowSeparator, false); } -bool RenameDialog::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) { +bool RenameDialog::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) +{ return iter->get_value (templateColumns.rowSeparator); } -void RenameDialog::useTemplToggled () { +void RenameDialog::useTemplToggled () +{ templates->set_sensitive (useTmpl->get_active ()); + if (useTmpl->get_active () && isTemplSelected ()) { all->set_sensitive (true); newName->set_text (applyTemplate (oldName->get_text(), imageData, getActiveTemplate())); - } - else + } else { all->set_sensitive (false); + } + newName->select_region (0, newName->get_text().size()); } -bool RenameDialog::isTemplSelected () { +bool RenameDialog::isTemplSelected () +{ Gtk::TreeModel::iterator iter = templates->get_active(); - return iter && iter->get_value (templateColumns.tmplName)!=M("FILEBROWSER_ADDDELTEMPLATE"); + return iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE"); } -Glib::ustring RenameDialog::getActiveTemplate () { +Glib::ustring RenameDialog::getActiveTemplate () +{ Gtk::TreeModel::iterator iter = templates->get_active(); - if (iter && iter->get_value (templateColumns.tmplName)!=M("FILEBROWSER_ADDDELTEMPLATE")) + + if (iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE")) { return iter->get_value (templateColumns.tmplName); - else + } else { return ""; + } } -void RenameDialog::tmplSelectionChanged () { +void RenameDialog::tmplSelectionChanged () +{ Gtk::TreeModel::iterator iter = templates->get_active(); - if (iter && iter->get_value (templateColumns.tmplName)==M("FILEBROWSER_ADDDELTEMPLATE")) { + + if (iter && iter->get_value (templateColumns.tmplName) == M("FILEBROWSER_ADDDELTEMPLATE")) { RenameTemplateEditor* rte = new RenameTemplateEditor (p); - if (rte->run()==Gtk::RESPONSE_OK) { + + if (rte->run() == Gtk::RESPONSE_OK) { fillTemplateList (); } + delete rte; // show add/del template dialog - } - else + } else { useTemplToggled (); + } } -RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) - : Gtk::Dialog ("Edit rename templates", *parent, true, true) { - +RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) + : Gtk::Dialog ("Edit rename templates", *parent, true, true) +{ + list = Gtk::manage (new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); list->set_headers_visible (false); get_vbox ()->pack_start (*list); - + Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); templ = Gtk::manage (new Gtk::Entry ()); Gtk::Button* add = Gtk::manage (new Gtk::Button ()); @@ -166,7 +184,7 @@ RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) hb->pack_start (*templ); hb->pack_start (*add, Gtk::PACK_SHRINK, 2); hb->pack_start (*del, Gtk::PACK_SHRINK, 2); - + get_vbox ()->pack_start (*hb, Gtk::PACK_SHRINK, 4); add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); @@ -175,45 +193,54 @@ RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) add->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::addPressed) ); del->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::delPressed) ); - + show_all_children (); - + set_size_request (-1, 250); } -void RenameTemplateEditor::refreshTemplateList () { +void RenameTemplateEditor::refreshTemplateList () +{ list->clear_items (); - for (size_t i=0; iappend_text (options.renameTemplates[i]); + } } -void RenameTemplateEditor::addPressed () { +void RenameTemplateEditor::addPressed () +{ - if (templ->get_text()!="") { + if (templ->get_text() != "") { options.renameTemplates.push_back (templ->get_text ()); refreshTemplateList (); templ->set_text(""); } } -void RenameTemplateEditor::delPressed () { +void RenameTemplateEditor::delPressed () +{ std::vector sel = list->get_selected (); - for (size_t i=0; iget_text (sel[i]); std::vector::iterator f = std::find (options.renameTemplates.begin(), options.renameTemplates.end(), toDel); - if (f!=options.renameTemplates.end()) + + if (f != options.renameTemplates.end()) { options.renameTemplates.erase (f); + } } + refreshTemplateList (); } -Glib::ustring RenameDialog::applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ) { +Glib::ustring RenameDialog::applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ) +{ return Glib::ustring ("szeva"); - + } diff --git a/rtgui/renamedlg.h b/rtgui/renamedlg.h index eb4a83b99..a5dec4efa 100644 --- a/rtgui/renamedlg.h +++ b/rtgui/renamedlg.h @@ -7,7 +7,7 @@ * 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 @@ -25,59 +25,66 @@ #define RESPONSE_ALL 100 -class RenameDialog : public Gtk::Dialog { +class RenameDialog : public Gtk::Dialog +{ - protected: - - class TemplateColumns : public Gtk::TreeModel::ColumnRecord { - public: - Gtk::TreeModelColumn tmplName; - Gtk::TreeModelColumn rowSeparator; - TemplateColumns() { add(tmplName); add(rowSeparator); } - }; - TemplateColumns templateColumns; - Glib::RefPtr templateModel; - - Gtk::Window* p; - Gtk::Label* oldName; - Gtk::Entry* newName; - Gtk::CheckButton* useTmpl; - MyComboBox* templates; - Gtk::Button* all; - const CacheImageData* imageData; - - void fillTemplateList (); +protected: + class TemplateColumns : public Gtk::TreeModel::ColumnRecord + { public: - RenameDialog (Gtk::Window* parent); - - void initName (const Glib::ustring& iname, const CacheImageData* cid); - Glib::ustring getNewName (); - - bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); - void tmplSelectionChanged (); - void useTemplToggled (); - - bool isTemplSelected (); - Glib::ustring getActiveTemplate (); - - static Glib::ustring applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ); + Gtk::TreeModelColumn tmplName; + Gtk::TreeModelColumn rowSeparator; + TemplateColumns() + { + add(tmplName); + add(rowSeparator); + } + }; + TemplateColumns templateColumns; + Glib::RefPtr templateModel; + + Gtk::Window* p; + Gtk::Label* oldName; + Gtk::Entry* newName; + Gtk::CheckButton* useTmpl; + MyComboBox* templates; + Gtk::Button* all; + const CacheImageData* imageData; + + void fillTemplateList (); + +public: + RenameDialog (Gtk::Window* parent); + + void initName (const Glib::ustring& iname, const CacheImageData* cid); + Glib::ustring getNewName (); + + bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); + void tmplSelectionChanged (); + void useTemplToggled (); + + bool isTemplSelected (); + Glib::ustring getActiveTemplate (); + + static Glib::ustring applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ); }; -class RenameTemplateEditor : public Gtk::Dialog { +class RenameTemplateEditor : public Gtk::Dialog +{ - protected: - Gtk::ListViewText* list; - Gtk::Entry* templ; +protected: + Gtk::ListViewText* list; + Gtk::Entry* templ; - void refreshTemplateList (); - public: - RenameTemplateEditor (Gtk::Window* parent); - - Glib::ustring getSelectedTemplate (); - - void addPressed (); - void delPressed (); + void refreshTemplateList (); +public: + RenameTemplateEditor (Gtk::Window* parent); + + Glib::ustring getSelectedTemplate (); + + void addPressed (); + void delPressed (); }; #endif diff --git a/rtgui/resize.h b/rtgui/resize.h index 54bfb4e4a..19ddc5843 100644 --- a/rtgui/resize.h +++ b/rtgui/resize.h @@ -7,7 +7,7 @@ * 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 @@ -25,9 +25,10 @@ #include "toolpanel.h" #include "guiutils.h" -class Resize : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::SizeListener { +class Resize : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::SizeListener +{ - protected: +protected: Adjuster* scale; Gtk::VBox* sizeBox; MyComboBoxText* appliesTo; @@ -41,16 +42,19 @@ class Resize : public ToolParamBlock, public AdjusterListener, public FoldableTo bool wDirty, hDirty; ToolParamBlock* packBox; - public: +public: Resize (); ~Resize (); - Gtk::Box* getPackBox () { return packBox; } + Gtk::Box* getPackBox () + { + return packBox; + } - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); @@ -59,17 +63,17 @@ class Resize : public ToolParamBlock, public AdjusterListener, public FoldableTo void appliesToChanged (); void methodChanged (); void specChanged (); - void update (bool isCropped, int cw, int ch, int ow=0, int oh=0); + void update (bool isCropped, int cw, int ch, int ow = 0, int oh = 0); void setGUIFromCrop (bool isCropped, int cw, int ch); void sizeChanged (int w, int h, int ow, int oh); void setDimensions (); void enabledChanged (); - private: +private: void fitBoxScale (); int getComputedWidth (); - int getComputedHeight (); - void notifyBBox (); + int getComputedHeight (); + void notifyBBox (); void updateGUI (); }; diff --git a/rtgui/rgbcurves.cc b/rtgui/rgbcurves.cc index e52ffe83a..565ec0eb5 100644 --- a/rtgui/rgbcurves.cc +++ b/rtgui/rgbcurves.cc @@ -7,7 +7,7 @@ * 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 @@ -21,62 +21,67 @@ using namespace rtengine; using namespace rtengine::procparams; -RGBCurves::RGBCurves () : FoldableToolPanel(this, "rgbcurves", M("TP_RGBCURVES_LABEL")) { +RGBCurves::RGBCurves () : FoldableToolPanel(this, "rgbcurves", M("TP_RGBCURVES_LABEL")) +{ - lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_RGBCURVES_LUMAMODE"))); - lumamode->set_tooltip_markup (M("TP_RGBCURVES_LUMAMODE_TOOLTIP")); - lumamode->set_active (false); - lumamode->show (); - pack_start (*lumamode); + lumamode = Gtk::manage (new Gtk::CheckButton (M("TP_RGBCURVES_LUMAMODE"))); + lumamode->set_tooltip_markup (M("TP_RGBCURVES_LUMAMODE_TOOLTIP")); + lumamode->set_active (false); + lumamode->show (); + pack_start (*lumamode); - Gtk::HSeparator *hsep1 = Gtk::manage (new Gtk::HSeparator()); - hsep1->show (); - pack_start (*hsep1); + Gtk::HSeparator *hsep1 = Gtk::manage (new Gtk::HSeparator()); + hsep1->show (); + pack_start (*hsep1); - lumamodeConn = lumamode->signal_toggled().connect( sigc::mem_fun(*this, &RGBCurves::lumamodeChanged) ); + lumamodeConn = lumamode->signal_toggled().connect( sigc::mem_fun(*this, &RGBCurves::lumamodeChanged) ); - std::vector milestones; + std::vector milestones; - curveEditorG = new CurveEditorGroup (options.lastRgbCurvesDir, M("TP_RGBCURVES_CHANNEL")); - curveEditorG->setCurveListener (this); + curveEditorG = new CurveEditorGroup (options.lastRgbCurvesDir, M("TP_RGBCURVES_CHANNEL")); + curveEditorG->setCurveListener (this); - Rshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_RGBCURVES_RED"))); - Rshape->setEditID(EUID_RGB_R, BT_SINGLEPLANE_FLOAT); - milestones.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) ); - milestones.push_back( GradientMilestone(1.0, 1.0, 0.0, 0.0) ); - Rshape->setBottomBarBgGradient(milestones); - Rshape->setLeftBarBgGradient(milestones); + Rshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_RGBCURVES_RED"))); + Rshape->setEditID(EUID_RGB_R, BT_SINGLEPLANE_FLOAT); + milestones.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) ); + milestones.push_back( GradientMilestone(1.0, 1.0, 0.0, 0.0) ); + Rshape->setBottomBarBgGradient(milestones); + Rshape->setLeftBarBgGradient(milestones); - milestones[1].r = 0.0; milestones[1].g = 1.0; - Gshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_RGBCURVES_GREEN"))); - Gshape->setEditID(EUID_RGB_G, BT_SINGLEPLANE_FLOAT); - Gshape->setBottomBarBgGradient(milestones); - Gshape->setLeftBarBgGradient(milestones); + milestones[1].r = 0.0; + milestones[1].g = 1.0; + Gshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_RGBCURVES_GREEN"))); + Gshape->setEditID(EUID_RGB_G, BT_SINGLEPLANE_FLOAT); + Gshape->setBottomBarBgGradient(milestones); + Gshape->setLeftBarBgGradient(milestones); - milestones[1].g = 0.0; milestones[1].b = 1.0; - Bshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_RGBCURVES_BLUE"))); - Bshape->setEditID(EUID_RGB_B, BT_SINGLEPLANE_FLOAT); - Bshape->setBottomBarBgGradient(milestones); - Bshape->setLeftBarBgGradient(milestones); + milestones[1].g = 0.0; + milestones[1].b = 1.0; + Bshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_RGBCURVES_BLUE"))); + Bshape->setEditID(EUID_RGB_B, BT_SINGLEPLANE_FLOAT); + Bshape->setBottomBarBgGradient(milestones); + Bshape->setLeftBarBgGradient(milestones); - // This will add the reset button at the end of the curveType buttons - curveEditorG->curveListComplete(); + // This will add the reset button at the end of the curveType buttons + curveEditorG->curveListComplete(); + + pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); - pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); - } -RGBCurves::~RGBCurves () { - delete curveEditorG; +RGBCurves::~RGBCurves () +{ + delete curveEditorG; } -void RGBCurves::read (const ProcParams* pp, const ParamsEdited* pedited) { +void RGBCurves::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); if (pedited) { Rshape->setUnChanged (!pedited->rgbCurves.rcurve); - Gshape->setUnChanged (!pedited->rgbCurves.gcurve); + Gshape->setUnChanged (!pedited->rgbCurves.gcurve); Bshape->setUnChanged (!pedited->rgbCurves.bcurve); lumamode->set_inconsistent (!pedited->rgbCurves.lumamode); } @@ -88,35 +93,44 @@ void RGBCurves::read (const ProcParams* pp, const ParamsEdited* pedited) { lastLumamode = pp->rgbCurves.lumamode; Rshape->setCurve (pp->rgbCurves.rcurve); - Gshape->setCurve (pp->rgbCurves.gcurve); + Gshape->setCurve (pp->rgbCurves.gcurve); Bshape->setCurve (pp->rgbCurves.bcurve); enableListener (); } -void RGBCurves::setEditProvider (EditDataProvider *provider) { +void RGBCurves::setEditProvider (EditDataProvider *provider) +{ Rshape->setEditProvider(provider); Gshape->setEditProvider(provider); Bshape->setEditProvider(provider); } -void RGBCurves::autoOpenCurve () { +void RGBCurves::autoOpenCurve () +{ // Open up the first curve if selected bool active = Rshape->openIfNonlinear(); - if (!active) Gshape->openIfNonlinear(); - if (!active) Bshape->openIfNonlinear(); + + if (!active) { + Gshape->openIfNonlinear(); + } + + if (!active) { + Bshape->openIfNonlinear(); + } } -void RGBCurves::write (ProcParams* pp, ParamsEdited* pedited) { +void RGBCurves::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->rgbCurves.rcurve = Rshape->getCurve (); - pp->rgbCurves.gcurve = Gshape->getCurve (); + pp->rgbCurves.gcurve = Gshape->getCurve (); pp->rgbCurves.bcurve = Bshape->getCurve (); pp->rgbCurves.lumamode = lumamode->get_active(); if (pedited) { pedited->rgbCurves.rcurve = !Rshape->isUnChanged (); - pedited->rgbCurves.gcurve = !Gshape->isUnChanged (); + pedited->rgbCurves.gcurve = !Gshape->isUnChanged (); pedited->rgbCurves.bcurve = !Bshape->isUnChanged (); pedited->rgbCurves.lumamode = !lumamode->get_inconsistent(); } @@ -129,52 +143,62 @@ void RGBCurves::write (ProcParams* pp, ParamsEdited* pedited) { * If more than one curve has been added, the curve listener is automatically * set to 'multi=true', and send a pointer of the modified curve in a parameter */ -void RGBCurves::curveChanged (CurveEditor* ce) { +void RGBCurves::curveChanged (CurveEditor* ce) +{ if (listener) { - if (ce == Rshape) - listener->panelChanged (EvRGBrCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == Gshape) - listener->panelChanged (EvRGBgCurve, M("HISTORY_CUSTOMCURVE")); - if (ce == Bshape) - listener->panelChanged (EvRGBbCurve, M("HISTORY_CUSTOMCURVE")); - } + if (ce == Rshape) { + listener->panelChanged (EvRGBrCurve, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == Gshape) { + listener->panelChanged (EvRGBgCurve, M("HISTORY_CUSTOMCURVE")); + } + + if (ce == Bshape) { + listener->panelChanged (EvRGBbCurve, M("HISTORY_CUSTOMCURVE")); + } + } } -void RGBCurves::lumamodeChanged () { +void RGBCurves::lumamodeChanged () +{ if (batchMode) { if (lumamode->get_inconsistent()) { - lumamode->set_inconsistent (false); + lumamode->set_inconsistent (false); lumamodeConn.block (true); lumamode->set_active (false); lumamodeConn.block (false); + } else if (lastLumamode) { + lumamode->set_inconsistent (true); } - else if (lastLumamode) - lumamode->set_inconsistent (true); lastLumamode = lumamode->get_active (); } if (listener) { - if (lumamode->get_active ()) + if (lumamode->get_active ()) { listener->panelChanged (EvRGBrCurveLumamode, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvRGBrCurveLumamode, M("GENERAL_DISABLED")); + } } } -void RGBCurves::setBatchMode (bool batchMode) { +void RGBCurves::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); curveEditorG->setBatchMode (batchMode); } -void RGBCurves::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) { +void RGBCurves::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) +{ - // Rshape->updateBackgroundHistogram (histRed); - // Gshape->updateBackgroundHistogram (histGreen); - // Bshape->updateBackgroundHistogram (histBlue); + // Rshape->updateBackgroundHistogram (histRed); + // Gshape->updateBackgroundHistogram (histGreen); + // Bshape->updateBackgroundHistogram (histBlue); } diff --git a/rtgui/rgbcurves.h b/rtgui/rgbcurves.h index 9d5498705..47a7a1344 100644 --- a/rtgui/rgbcurves.h +++ b/rtgui/rgbcurves.h @@ -7,7 +7,7 @@ * 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 @@ -26,25 +26,26 @@ #include "curveeditorgroup.h" #include "colorprovider.h" -class RGBCurves : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider { +class RGBCurves : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider +{ - protected: - CurveEditorGroup* curveEditorG; - DiagonalCurveEditor* Rshape; - DiagonalCurveEditor* Gshape; - DiagonalCurveEditor* Bshape; +protected: + CurveEditorGroup* curveEditorG; + DiagonalCurveEditor* Rshape; + DiagonalCurveEditor* Gshape; + DiagonalCurveEditor* Bshape; Gtk::CheckButton* lumamode; bool lastLumamode; sigc::connection lumamodeConn; - public: +public: RGBCurves (); ~RGBCurves (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void setEditProvider (EditDataProvider *provider); void autoOpenCurve (); diff --git a/rtgui/rotate.cc b/rtgui/rotate.cc index 973ec3c3a..e688dba62 100644 --- a/rtgui/rotate.cc +++ b/rtgui/rotate.cc @@ -7,7 +7,7 @@ * 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 @@ -24,90 +24,107 @@ using namespace rtengine; using namespace rtengine::procparams; -Rotate::Rotate () : FoldableToolPanel(this, "rotate", M("TP_ROTATE_LABEL")) { +Rotate::Rotate () : FoldableToolPanel(this, "rotate", M("TP_ROTATE_LABEL")) +{ - rlistener = NULL; + rlistener = NULL; - //TODO the action of the rotation slider is counter-intuitive - Gtk::Image* irotateL = Gtk::manage (new RTImage ("rotate-right-2.png")); - Gtk::Image* irotateR = Gtk::manage (new RTImage ("rotate-left-2.png")); + //TODO the action of the rotation slider is counter-intuitive + Gtk::Image* irotateL = Gtk::manage (new RTImage ("rotate-right-2.png")); + Gtk::Image* irotateR = Gtk::manage (new RTImage ("rotate-left-2.png")); - degree = Gtk::manage (new Adjuster (M("TP_ROTATE_DEGREE"), -45, 45, 0.01, 0, irotateL, irotateR)); - degree->setAdjusterListener (this); - pack_start (*degree); + degree = Gtk::manage (new Adjuster (M("TP_ROTATE_DEGREE"), -45, 45, 0.01, 0, irotateL, irotateR)); + degree->setAdjusterListener (this); + pack_start (*degree); - selectStraight = Gtk::manage (new Gtk::Button (M("TP_ROTATE_SELECTLINE"))); - Gtk::Image* selimg = Gtk::manage (new RTImage ("straighten-small.png")); - selectStraight->set_image (*selimg); - pack_start (*selectStraight, Gtk::PACK_SHRINK, 2); + selectStraight = Gtk::manage (new Gtk::Button (M("TP_ROTATE_SELECTLINE"))); + Gtk::Image* selimg = Gtk::manage (new RTImage ("straighten-small.png")); + selectStraight->set_image (*selimg); + pack_start (*selectStraight, Gtk::PACK_SHRINK, 2); - selectStraight->signal_pressed().connect( sigc::mem_fun(*this, &Rotate::selectStraightPressed) ); + selectStraight->signal_pressed().connect( sigc::mem_fun(*this, &Rotate::selectStraightPressed) ); - show_all (); + show_all (); } -void Rotate::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Rotate::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); - if (pedited) + if (pedited) { degree->setEditedState (pedited->rotate.degree ? Edited : UnEdited); + } degree->setValue (pp->rotate.degree); - + enableListener (); } -void Rotate::write (ProcParams* pp, ParamsEdited* pedited) { +void Rotate::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->rotate.degree = degree->getValue (); - if (pedited) + if (pedited) { pedited->rotate.degree = degree->getEditedState (); + } } -void Rotate::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void Rotate::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ degree->setDefault (defParams->rotate.degree); - if (pedited) + if (pedited) { degree->setDefaultEditedState (pedited->rotate.degree ? Edited : UnEdited); - else + } else { degree->setDefaultEditedState (Irrelevant); + } } -void Rotate::adjusterChanged (Adjuster* a, double newval) { +void Rotate::adjusterChanged (Adjuster* a, double newval) +{ - if (listener) + if (listener) { listener->panelChanged (EvROTDegree, Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), degree->getValue())); + } } -void Rotate::straighten (double deg) { +void Rotate::straighten (double deg) +{ - degree->setValue (degree->getValue()+deg); + degree->setValue (degree->getValue() + deg); degree->setEditedState (Edited); - if (listener) + + if (listener) { listener->panelChanged (EvROTDegree, Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), degree->getValue())); + } } -void Rotate::selectStraightPressed () { +void Rotate::selectStraightPressed () +{ - if (rlistener) + if (rlistener) { rlistener->straightenRequested (); + } } -void Rotate::setBatchMode (bool batchMode) { +void Rotate::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); degree->showEditedCB (); } -void Rotate::setAdjusterBehavior (bool rotadd) { +void Rotate::setAdjusterBehavior (bool rotadd) +{ - degree->setAddMode(rotadd); + degree->setAddMode(rotadd); } -void Rotate::trimValues (rtengine::procparams::ProcParams* pp) { +void Rotate::trimValues (rtengine::procparams::ProcParams* pp) +{ - degree->trimValue(pp->rotate.degree); + degree->trimValue(pp->rotate.degree); } diff --git a/rtgui/rotate.h b/rtgui/rotate.h index e096393e6..a67f310d5 100644 --- a/rtgui/rotate.h +++ b/rtgui/rotate.h @@ -7,7 +7,7 @@ * 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 @@ -24,20 +24,21 @@ #include "toolpanel.h" #include "lensgeomlistener.h" -class Rotate : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class Rotate : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* degree; Gtk::Button* selectStraight; LensGeomListener* rlistener; - public: +public: Rotate (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void straighten (double deg); @@ -46,7 +47,10 @@ class Rotate : public ToolParamBlock, public AdjusterListener, public FoldableTo void setAdjusterBehavior (bool rotadd); void trimValues (rtengine::procparams::ProcParams* pp); void selectStraightPressed (); - void setLensGeomListener (LensGeomListener* l) { rlistener = l; } + void setLensGeomListener (LensGeomListener* l) + { + rlistener = l; + } }; #endif diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 2211829a0..6472467e6 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -25,125 +25,145 @@ extern Glib::ustring argv0; extern Options options; 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 +std::map > pixBufMap; // List of image buffers in order to live update them on theme switch and to avoid a lot of file accesses /* * 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() { - Glib::ustring mapKey; - if (rtlFileName.length()) { - if (get_direction() == Gtk::TEXT_DIR_RTL) { - mapKey = rtlFileName; - } else { - mapKey = fileName; - } - } else { - mapKey = fileName; - } - - std::map >::iterator it; +RTImage::RTImage(Glib::ustring fileName, Glib::ustring rtlFileName) : Gtk::Image() +{ + Glib::ustring mapKey; + + if (rtlFileName.length()) { + if (get_direction() == Gtk::TEXT_DIR_RTL) { + mapKey = rtlFileName; + } else { + mapKey = fileName; + } + } else { + mapKey = fileName; + } + + std::map >::iterator it; it = pixBufMap.find(mapKey); + if (it != pixBufMap.end()) { set(it->second); } else { Glib::RefPtr tempPixPuf = Gdk::Pixbuf::create_from_file(findIconAbsolutePath(mapKey)); - pixBufMap.insert(std::pair >(mapKey, tempPixPuf)); + pixBufMap.insert(std::pair >(mapKey, tempPixPuf)); set(tempPixPuf); } } -void RTImage::updateImages() { - std::map >::iterator it; - for (it=pixBufMap.begin(); it!=pixBufMap.end(); ++it) { +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); } } // 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) { - clear(); - std::map >::iterator it; +void RTImage::changeImage(Glib::ustring &newImage) +{ + 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)); + 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 #include "options.h" -class RTImage : public Gtk::Image { +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(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); }; #endif diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 4d55a6db6..e3428dea7 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -7,7 +7,7 @@ * 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 @@ -40,16 +40,19 @@ osx_will_quit_cb (GtkosxApplication *app, gpointer data) gtk_main_quit (); } -bool RTWindow::osxFileOpenEvent(Glib::ustring path) { +bool RTWindow::osxFileOpenEvent(Glib::ustring path) +{ CacheManager* cm = CacheManager::getInstance(); - Thumbnail* thm= cm->getEntry( path ); - if(thm && fpanel){ + Thumbnail* thm = cm->getEntry( path ); + + if(thm && fpanel) { std::vector entries; - entries.push_back(thm); + entries.push_back(thm); fpanel->fileCatalog->openRequested(entries); return true; } + return false; } @@ -57,27 +60,31 @@ static gboolean osx_open_file_cb (GtkosxApplication *app, gchar *path_, gpointer data) { RTWindow *rtWin = (RTWindow *)data; + if (!argv1.empty()) { // skip handling if we have a file argument or else we get double open of same file return false; } + Glib::ustring path = Glib::ustring(path_); - Glib::ustring suffix = path.length() > 4 ? path.substr(path.length()-3) : ""; + Glib::ustring suffix = path.length() > 4 ? path.substr(path.length() - 3) : ""; suffix = suffix.lowercase(); + if (suffix == "pp3") { - path = path.substr(0, path.length()-4); + path = path.substr(0, path.length() - 4); } + return rtWin->osxFileOpenEvent(path); } #endif // __APPLE__ RTWindow::RTWindow () -:mainNB(NULL) -,bpanel(NULL) -,splash(NULL) -,btn_fullscreen(NULL) -,epanel(NULL) -,fpanel(NULL) + : mainNB(NULL) + , bpanel(NULL) + , splash(NULL) + , btn_fullscreen(NULL) + , epanel(NULL) + , fpanel(NULL) { cacheMgr->init (); @@ -88,12 +95,18 @@ RTWindow::RTWindow () Glib::ustring fullPath = RTImage::findIconAbsolutePath(fName); #ifdef GLIBMM_EXCEPTIONS_ENABLED - try { set_default_icon_from_file (fullPath); - } catch(Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); } + + try { + set_default_icon_from_file (fullPath); + } catch(Glib::Exception& ex) { + printf ("%s\n", ex.what().c_str()); + } + #else - { std::auto_ptr error; - set_default_icon_from_file (fullPath, error); - } + { + std::auto_ptr error; + set_default_icon_from_file (fullPath, error); + } #endif //GLIBMM_EXCEPTIONS_ENABLED #if defined(__APPLE__) @@ -113,207 +126,229 @@ RTWindow::RTWindow () gtkosx_application_ready (osxApp); } #endif - versionStr = "RawTherapee "+versionString; - if (!versionSuffixString.empty()) - versionStr += " "+versionSuffixString; + versionStr = "RawTherapee " + versionString; + + if (!versionSuffixString.empty()) { + versionStr += " " + versionSuffixString; + } + set_title_decorated(""); property_allow_shrink() = true; set_default_size(options.windowWidth, options.windowHeight); set_modal(false); set_resizable(true); - if (options.windowMaximized) - maximize(); - else { - unmaximize(); - move(options.windowX,options.windowY); + + if (options.windowMaximized) { + maximize(); + } else { + unmaximize(); + move(options.windowX, options.windowY); } on_delete_has_run = false; is_fullscreen = false; property_destroy_with_parent().set_value(false); signal_window_state_event().connect( sigc::mem_fun(*this, &RTWindow::on_window_state_event) ); - signal_key_press_event().connect( sigc::mem_fun(*this, &RTWindow::keyPressed) ); + signal_key_press_event().connect( sigc::mem_fun(*this, &RTWindow::keyPressed) ); - if(simpleEditor) - { - epanel = Gtk::manage( new EditorPanel (NULL) ); - epanel->setParent (this); - add (*epanel); - show_all (); + if(simpleEditor) { + epanel = Gtk::manage( new EditorPanel (NULL) ); + epanel->setParent (this); + add (*epanel); + show_all (); - pldBridge=NULL; // No progress listener + pldBridge = NULL; // No progress listener - CacheManager* cm = CacheManager::getInstance(); - Thumbnail* thm= cm->getEntry( argv1 ); - if(thm){ - int error; - rtengine::InitialImage *ii= rtengine::InitialImage::load(argv1,thm->getType() == FT_Raw,&error,NULL); - epanel->open( thm, ii ); - } - } else { - mainNB = Gtk::manage (new Gtk::Notebook ()); - mainNB->set_scrollable (true); - mainNB->signal_switch_page().connect_notify( sigc::mem_fun(*this, &RTWindow::on_mainNB_switch_page) ); + CacheManager* cm = CacheManager::getInstance(); + Thumbnail* thm = cm->getEntry( argv1 ); - fpanel = new FilePanel () ; - fpanel->setParent (this); + if(thm) { + int error; + rtengine::InitialImage *ii = rtengine::InitialImage::load(argv1, thm->getType() == FT_Raw, &error, NULL); + epanel->open( thm, ii ); + } + } else { + mainNB = Gtk::manage (new Gtk::Notebook ()); + mainNB->set_scrollable (true); + mainNB->signal_switch_page().connect_notify( sigc::mem_fun(*this, &RTWindow::on_mainNB_switch_page) ); - // decorate tab - if (options.mainNBVertical) { - mainNB->set_tab_pos (Gtk::POS_LEFT); + fpanel = new FilePanel () ; + fpanel->setParent (this); - Gtk::VBox* vbf = Gtk::manage (new Gtk::VBox ()); - vbf->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU))); - Gtk::Label* l= Gtk::manage(new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_FILEBROWSER"))); - l->set_angle (90); - vbf->pack_start (*l); - vbf->set_spacing (2); - vbf->set_tooltip_markup (M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); - vbf->show_all (); - mainNB->append_page (*fpanel, *vbf); - } else { - Gtk::HBox* hbf = Gtk::manage (new Gtk::HBox ()); - hbf->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU))); - hbf->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER")))); - hbf->set_spacing (2); - hbf->set_tooltip_markup (M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); - hbf->show_all (); - mainNB->append_page (*fpanel, *hbf); - } + // decorate tab + if (options.mainNBVertical) { + mainNB->set_tab_pos (Gtk::POS_LEFT); + + Gtk::VBox* vbf = Gtk::manage (new Gtk::VBox ()); + vbf->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU))); + Gtk::Label* l = Gtk::manage(new Gtk::Label (Glib::ustring(" ") + M("MAIN_FRAME_FILEBROWSER"))); + l->set_angle (90); + vbf->pack_start (*l); + vbf->set_spacing (2); + vbf->set_tooltip_markup (M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); + vbf->show_all (); + mainNB->append_page (*fpanel, *vbf); + } else { + Gtk::HBox* hbf = Gtk::manage (new Gtk::HBox ()); + hbf->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU))); + hbf->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_FILEBROWSER")))); + hbf->set_spacing (2); + hbf->set_tooltip_markup (M("MAIN_FRAME_FILEBROWSER_TOOLTIP")); + hbf->show_all (); + mainNB->append_page (*fpanel, *hbf); + } bpanel = Gtk::manage ( new BatchQueuePanel (fpanel->fileCatalog) ); - bpanel->setParent (this); + bpanel->setParent (this); - // decorate tab, the label is unimportant since its updated in batchqueuepanel anyway + // decorate tab, the label is unimportant since its updated in batchqueuepanel anyway Gtk::Label* lbq = Gtk::manage ( new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")) ); - if (options.mainNBVertical) lbq->set_angle(90); - mainNB->append_page (*bpanel, *lbq); - // epanel is only for single tab mode + if (options.mainNBVertical) { + lbq->set_angle(90); + } + + mainNB->append_page (*bpanel, *lbq); + + // epanel is only for single tab mode epanel = Gtk::manage ( new EditorPanel (fpanel) ); - epanel->setParent (this); + epanel->setParent (this); - // decorate tab - if (options.mainNBVertical) { - Gtk::VBox* vbe = Gtk::manage (new Gtk::VBox ()); - vbe->pack_start (*Gtk::manage (new RTImage ("rt-logo.png"))); - Gtk::Label* l=Gtk::manage (new Gtk::Label( Glib::ustring(" ") + M("MAIN_FRAME_EDITOR") )); - //l->set_markup(Glib::ustring("Editor")); Bold difficult to read - l->set_angle (90); - vbe->pack_start (*l); - vbe->set_spacing (2); - vbe->set_tooltip_markup (M("MAIN_FRAME_EDITOR_TOOLTIP")); - vbe->show_all (); - epanel->tbTopPanel_1_visible(true); //show the toggle Top Panel button - mainNB->append_page (*epanel, *vbe); - } else { - Gtk::HBox* hbe = Gtk::manage (new Gtk::HBox ()); - hbe->pack_start (*Gtk::manage (new RTImage ("rt-logo.png"))); - hbe->pack_start (*Gtk::manage (new Gtk::Label( Glib::ustring(" ") + M("MAIN_FRAME_EDITOR") ))); - hbe->set_spacing (2); - hbe->set_tooltip_markup (M("MAIN_FRAME_EDITOR_TOOLTIP")); - hbe->show_all (); - epanel->tbTopPanel_1_visible(true); //show the toggle Top Panel button - mainNB->append_page (*epanel, *hbe); - } + // decorate tab + if (options.mainNBVertical) { + Gtk::VBox* vbe = Gtk::manage (new Gtk::VBox ()); + vbe->pack_start (*Gtk::manage (new RTImage ("rt-logo.png"))); + Gtk::Label* l = Gtk::manage (new Gtk::Label( Glib::ustring(" ") + M("MAIN_FRAME_EDITOR") )); + //l->set_markup(Glib::ustring("Editor")); Bold difficult to read + l->set_angle (90); + vbe->pack_start (*l); + vbe->set_spacing (2); + vbe->set_tooltip_markup (M("MAIN_FRAME_EDITOR_TOOLTIP")); + vbe->show_all (); + epanel->tbTopPanel_1_visible(true); //show the toggle Top Panel button + mainNB->append_page (*epanel, *vbe); + } else { + Gtk::HBox* hbe = Gtk::manage (new Gtk::HBox ()); + hbe->pack_start (*Gtk::manage (new RTImage ("rt-logo.png"))); + hbe->pack_start (*Gtk::manage (new Gtk::Label( Glib::ustring(" ") + M("MAIN_FRAME_EDITOR") ))); + hbe->set_spacing (2); + hbe->set_tooltip_markup (M("MAIN_FRAME_EDITOR_TOOLTIP")); + hbe->show_all (); + epanel->tbTopPanel_1_visible(true); //show the toggle Top Panel button + mainNB->append_page (*epanel, *hbe); + } - mainNB->set_current_page (mainNB->page_num (*fpanel)); + mainNB->set_current_page (mainNB->page_num (*fpanel)); - Gtk::VBox* mainBox = Gtk::manage (new Gtk::VBox ()); - mainBox->pack_start (*mainNB); + Gtk::VBox* mainBox = Gtk::manage (new Gtk::VBox ()); + mainBox->pack_start (*mainNB); - // filling bottom box - iFullscreen = new RTImage ("fullscreen.png"); - iFullscreen_exit = new RTImage ("fullscreen-exit.png"); + // filling bottom box + iFullscreen = new RTImage ("fullscreen.png"); + iFullscreen_exit = new RTImage ("fullscreen-exit.png"); - Gtk::LinkButton* rtWeb = Gtk::manage (new Gtk::LinkButton ("http://rawtherapee.com")); - //Gtk::Button* preferences = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_PREFERENCES")+"...")); - Gtk::Button* preferences = Gtk::manage (new Gtk::Button ()); - preferences->set_image (*Gtk::manage(new RTImage ("gtk-preferences.png"))); - preferences->set_tooltip_markup (M("MAIN_BUTTON_PREFERENCES")); - preferences->signal_clicked().connect( sigc::mem_fun(*this, &RTWindow::showPreferences) ); + Gtk::LinkButton* rtWeb = Gtk::manage (new Gtk::LinkButton ("http://rawtherapee.com")); + //Gtk::Button* preferences = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_PREFERENCES")+"...")); + Gtk::Button* preferences = Gtk::manage (new Gtk::Button ()); + preferences->set_image (*Gtk::manage(new RTImage ("gtk-preferences.png"))); + preferences->set_tooltip_markup (M("MAIN_BUTTON_PREFERENCES")); + preferences->signal_clicked().connect( sigc::mem_fun(*this, &RTWindow::showPreferences) ); - //btn_fullscreen = Gtk::manage( new Gtk::Button(M("MAIN_BUTTON_FULLSCREEN"))); - btn_fullscreen = Gtk::manage( new Gtk::Button()); - btn_fullscreen->set_tooltip_markup (M("MAIN_BUTTON_FULLSCREEN")); - btn_fullscreen->set_image (*iFullscreen); - btn_fullscreen->signal_clicked().connect( sigc::mem_fun(*this, &RTWindow::toggle_fullscreen) ); + //btn_fullscreen = Gtk::manage( new Gtk::Button(M("MAIN_BUTTON_FULLSCREEN"))); + btn_fullscreen = Gtk::manage( new Gtk::Button()); + btn_fullscreen->set_tooltip_markup (M("MAIN_BUTTON_FULLSCREEN")); + btn_fullscreen->set_image (*iFullscreen); + btn_fullscreen->signal_clicked().connect( sigc::mem_fun(*this, &RTWindow::toggle_fullscreen) ); #if GTKMM_MINOR_VERSION >= 20 - if (options.mainNBVertical) { - Gtk::VBox* bottomVBox = Gtk::manage (new Gtk::VBox ()); - bottomVBox->pack_start (prProgBar, Gtk::PACK_SHRINK, 1); - bottomVBox->pack_end (*preferences, Gtk::PACK_SHRINK, 0); - bottomVBox->pack_end (*btn_fullscreen, Gtk::PACK_EXPAND_WIDGET, 1); - prProgBar.set_orientation(Gtk::PROGRESS_BOTTOM_TO_TOP); - mainNB->set_action_widget( bottomVBox,Gtk::PACK_END); - bottomVBox->show_all(); - }else{ - Gtk::HBox* bottomHBox = Gtk::manage (new Gtk::HBox ()); - bottomHBox->pack_end (*btn_fullscreen, Gtk::PACK_SHRINK, 1); - bottomHBox->pack_end (*preferences, Gtk::PACK_SHRINK, 0); - bottomHBox->pack_start (prProgBar, Gtk::PACK_EXPAND_WIDGET, 1); - mainNB->set_action_widget( bottomHBox,Gtk::PACK_END); - bottomHBox->show_all(); - } + + if (options.mainNBVertical) { + Gtk::VBox* bottomVBox = Gtk::manage (new Gtk::VBox ()); + bottomVBox->pack_start (prProgBar, Gtk::PACK_SHRINK, 1); + bottomVBox->pack_end (*preferences, Gtk::PACK_SHRINK, 0); + bottomVBox->pack_end (*btn_fullscreen, Gtk::PACK_EXPAND_WIDGET, 1); + prProgBar.set_orientation(Gtk::PROGRESS_BOTTOM_TO_TOP); + mainNB->set_action_widget( bottomVBox, Gtk::PACK_END); + bottomVBox->show_all(); + } else { + Gtk::HBox* bottomHBox = Gtk::manage (new Gtk::HBox ()); + bottomHBox->pack_end (*btn_fullscreen, Gtk::PACK_SHRINK, 1); + bottomHBox->pack_end (*preferences, Gtk::PACK_SHRINK, 0); + bottomHBox->pack_start (prProgBar, Gtk::PACK_EXPAND_WIDGET, 1); + mainNB->set_action_widget( bottomHBox, Gtk::PACK_END); + bottomHBox->show_all(); + } + #else - Gtk::HBox* bottomBox = Gtk::manage (new Gtk::HBox ()); - bottomBox->pack_end (*btn_fullscreen, Gtk::PACK_SHRINK, 1); - bottomBox->pack_end (*preferences, Gtk::PACK_SHRINK, 0); - bottomBox->pack_start (prProgBar, Gtk::PACK_EXPAND_WIDGET, 1); - mainBox->pack_start (*bottomBox, Gtk::PACK_SHRINK, 1); + Gtk::HBox* bottomBox = Gtk::manage (new Gtk::HBox ()); + bottomBox->pack_end (*btn_fullscreen, Gtk::PACK_SHRINK, 1); + bottomBox->pack_end (*preferences, Gtk::PACK_SHRINK, 0); + bottomBox->pack_start (prProgBar, Gtk::PACK_EXPAND_WIDGET, 1); + mainBox->pack_start (*bottomBox, Gtk::PACK_SHRINK, 1); #endif - pldBridge = new PLDBridge(static_cast(this)); + pldBridge = new PLDBridge(static_cast(this)); - Glib::RefPtr style = Gtk::RcStyle::create (); - style->set_xthickness (0); - style->set_ythickness (0); - rtWeb->modify_style (style); + Glib::RefPtr style = Gtk::RcStyle::create (); + style->set_xthickness (0); + style->set_ythickness (0); + rtWeb->modify_style (style); - add (*mainBox); - show_all (); + add (*mainBox); + show_all (); + } + + if (!isSingleTabMode() && !simpleEditor) { + epanel->hide_all(); } - if (!isSingleTabMode()&& !simpleEditor) epanel->hide_all(); } RTWindow::~RTWindow() { - if(!simpleEditor) + if(!simpleEditor) { delete pldBridge; + } + pldBridge = NULL; #if defined(__APPLE__) g_object_unref (osxApp); #endif - if (fpanel) + + if (fpanel) { delete fpanel; + } } -void RTWindow::findVerNumbers(int* numbers, Glib::ustring versionStr) { - numbers[0] = numbers[1] = numbers[2] = numbers[3] = 0; - int n=0; - for (unsigned int i=0; i= '0' && chr <= '9') { - numbers[n] *= 10; - numbers[n] += (int)(chr - '0'); - } - else { - n++; - if (n>4) { - printf("Error: malformed version string; \"%s\" must follow this format: xx.xx.xx.xx. Admitting it's a developer version...\n", versionStr.c_str()); - // Reseting the already found numbers - numbers[0] = numbers[1] = numbers[2] = numbers[3] = 100; - return; - } - } - } +void RTWindow::findVerNumbers(int* numbers, Glib::ustring versionStr) +{ + numbers[0] = numbers[1] = numbers[2] = numbers[3] = 0; + int n = 0; + + for (unsigned int i = 0; i < versionStr.length(); i++) { + char chr = (char)versionStr.at(i); + + if (chr >= '0' && chr <= '9') { + numbers[n] *= 10; + numbers[n] += (int)(chr - '0'); + } else { + n++; + + if (n > 4) { + printf("Error: malformed version string; \"%s\" must follow this format: xx.xx.xx.xx. Admitting it's a developer version...\n", versionStr.c_str()); + // Reseting the already found numbers + numbers[0] = numbers[1] = numbers[2] = numbers[3] = 100; + return; + } + } + } } -void RTWindow::on_realize () { +void RTWindow::on_realize () +{ Gtk::Window::on_realize (); - if( fpanel ) - fpanel->setAspect(); + if( fpanel ) { + fpanel->setAspect(); + } cursorManager.init (get_window()); @@ -328,74 +363,84 @@ void RTWindow::on_realize () { options.version = versionString; bool showReleaseNotes = false; + // Check if the current version is newer - if (currVerNbr[0] > prevVerNbr[0]) showReleaseNotes = true; - else if (currVerNbr[1] > prevVerNbr[1]) showReleaseNotes = true; - else if (currVerNbr[2] > prevVerNbr[2]) showReleaseNotes = true; + if (currVerNbr[0] > prevVerNbr[0]) { + showReleaseNotes = true; + } else if (currVerNbr[1] > prevVerNbr[1]) { + showReleaseNotes = true; + } else if (currVerNbr[2] > prevVerNbr[2]) { + showReleaseNotes = true; + } if (showReleaseNotes) { - // this is a first run! + // this is a first run! splash = new Splash (*this); splash->set_transient_for (*this); splash->signal_delete_event().connect( sigc::mem_fun(*this, &RTWindow::splashClosed) ); + if (splash->hasReleaseNotes()) { - splash->showReleaseNotes(); - splash->show (); - } - else { - delete splash; - splash = NULL; + splash->showReleaseNotes(); + splash->show (); + } else { + delete splash; + splash = NULL; } } } } -bool RTWindow::on_window_state_event(GdkEventWindowState* event) { +bool RTWindow::on_window_state_event(GdkEventWindowState* event) +{ - if (!event->new_window_state) { - // Window mode - options.windowMaximized = false; - } - else if (event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN|GDK_WINDOW_STATE_ICONIFIED)) { - // Fullscreen mode, save this mode even when window is iconified (minimized) to allow easier restore, not the best solution though... - options.windowMaximized = true; - } - return true; + if (!event->new_window_state) { + // Window mode + options.windowMaximized = false; + } else if (event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN | GDK_WINDOW_STATE_ICONIFIED)) { + // Fullscreen mode, save this mode even when window is iconified (minimized) to allow easier restore, not the best solution though... + options.windowMaximized = true; + } + + return true; } -void RTWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) { - if(!on_delete_has_run) { - if(isEditorPanel(page_num)) { - if (isSingleTabMode() && epanel) - MoveFileBrowserToEditor(); - - EditorPanel *ep = static_cast(mainNB->get_nth_page(page_num)); - ep->setAspect(); - - if (!isSingleTabMode()){ - if (filesEdited.size()>0){ - set_title_decorated(ep->getFileName()); - } - } - } else { - // in single tab mode with command line filename epanel does not exist yet - if (isSingleTabMode() && epanel) { - // Save profile on leaving the editor panel - epanel->saveProfile(); +void RTWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) +{ + if(!on_delete_has_run) { + if(isEditorPanel(page_num)) { + if (isSingleTabMode() && epanel) { + MoveFileBrowserToEditor(); + } - // Moving the FileBrowser only if the user has switched to the FileBrowser tab - if (mainNB->get_nth_page(page_num)==fpanel) - MoveFileBrowserToMain(); - } - } - } + EditorPanel *ep = static_cast(mainNB->get_nth_page(page_num)); + ep->setAspect(); + + if (!isSingleTabMode()) { + if (filesEdited.size() > 0) { + set_title_decorated(ep->getFileName()); + } + } + } else { + // in single tab mode with command line filename epanel does not exist yet + if (isSingleTabMode() && epanel) { + // Save profile on leaving the editor panel + epanel->saveProfile(); + + // Moving the FileBrowser only if the user has switched to the FileBrowser tab + if (mainNB->get_nth_page(page_num) == fpanel) { + MoveFileBrowserToMain(); + } + } + } + } } -void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { - if (options.multiDisplayMode>0) { +void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) +{ + if (options.multiDisplayMode > 0) { EditWindow * wndEdit = EditWindow::getInstance(this); wndEdit->show(); - wndEdit->addEditorPanel(ep,name); + wndEdit->addEditorPanel(ep, name); } else { ep->setParent (this); @@ -411,7 +456,7 @@ void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { // make the button as small as possible Glib::RefPtr style = Gtk::RcStyle::create (); style->set_xthickness (0); - style->set_ythickness (0); + style->set_ythickness (0); closeb->modify_style (style); closeb->signal_clicked().connect( sigc::bind (sigc::mem_fun(*this, &RTWindow::remEditorPanel) , ep)); @@ -432,186 +477,217 @@ void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { } } -void RTWindow::remEditorPanel (EditorPanel* ep) { - if (ep->getIsProcessing()) return; // Will crash if destroyed while loading +void RTWindow::remEditorPanel (EditorPanel* ep) +{ + if (ep->getIsProcessing()) { + return; // Will crash if destroyed while loading + } - if (options.multiDisplayMode>0) { + if (options.multiDisplayMode > 0) { EditWindow * wndEdit = EditWindow::getInstance(this); wndEdit->remEditorPanel(ep); } else { - bool queueHadFocus = (mainNB->get_current_page() == mainNB->page_num (*bpanel)); - epanels.erase (ep->getFileName()); - filesEdited.erase (ep->getFileName ()); - fpanel->refreshEditedState (filesEdited); + bool queueHadFocus = (mainNB->get_current_page() == mainNB->page_num (*bpanel)); + epanels.erase (ep->getFileName()); + filesEdited.erase (ep->getFileName ()); + fpanel->refreshEditedState (filesEdited); - mainNB->remove_page (*ep); + mainNB->remove_page (*ep); + + if (!isEditorPanel(mainNB->get_current_page())) { + if(!queueHadFocus) { + mainNB->set_current_page (mainNB->page_num (*fpanel)); + } + + set_title_decorated(""); + } else { + EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); + set_title_decorated(ep->getFileName()); + } - if (!isEditorPanel(mainNB->get_current_page())){ - if(!queueHadFocus) - mainNB->set_current_page (mainNB->page_num (*fpanel)); - set_title_decorated(""); - } else { - EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); - set_title_decorated(ep->getFileName()); - } // TODO: ask what to do: close & apply, close & apply selection, close & revert, cancel } } -bool RTWindow::selectEditorPanel(const std::string &name) { - if (options.multiDisplayMode>0) { +bool RTWindow::selectEditorPanel(const std::string &name) +{ + if (options.multiDisplayMode > 0) { EditWindow * wndEdit = EditWindow::getInstance(this); + if (wndEdit->selectEditorPanel(name)) { - set_title_decorated(name); - return true; + set_title_decorated(name); + return true; } } else { std::map::iterator iep = epanels.find(name); - if (iep!=epanels.end()) { + if (iep != epanels.end()) { mainNB->set_current_page (mainNB->page_num (*iep->second)); set_title_decorated(name); return true; - } - else{ - //set_title_decorated(name); - //printf("RTWindow::selectEditorPanel - plain set\n"); + } else { + //set_title_decorated(name); + //printf("RTWindow::selectEditorPanel - plain set\n"); } } return false; } -bool RTWindow::keyPressed (GdkEventKey* event) { +bool RTWindow::keyPressed (GdkEventKey* event) +{ - bool ctrl = event->state & GDK_CONTROL_MASK; - //bool shift = event->state & GDK_SHIFT_MASK; + bool ctrl = event->state & GDK_CONTROL_MASK; + //bool shift = event->state & GDK_SHIFT_MASK; - bool try_quit = false; + bool try_quit = false; #if defined(__APPLE__) - bool apple_cmd = event->state & GDK_MOD2_MASK; - if (event->keyval == GDK_q && apple_cmd) - try_quit = true; -#else - if (event->keyval == GDK_q && ctrl) - try_quit = true; -#endif - if (try_quit) { - if (!on_delete_event(0)) { - gtk_main_quit(); - } - } + bool apple_cmd = event->state & GDK_MOD2_MASK; - if(event->keyval == GDK_F11) + if (event->keyval == GDK_q && apple_cmd) { + try_quit = true; + } + +#else + + if (event->keyval == GDK_q && ctrl) { + try_quit = true; + } + +#endif + + if (try_quit) { + if (!on_delete_event(0)) { + gtk_main_quit(); + } + } + + if(event->keyval == GDK_F11) { toggle_fullscreen(); + } if (simpleEditor) - // in simpleEditor mode, there's no other tab that can handle pressed keys, so we can send the event to editor panel then return - return epanel->handleShortcutKey (event);; + // in simpleEditor mode, there's no other tab that can handle pressed keys, so we can send the event to editor panel then return + { + return epanel->handleShortcutKey (event); + }; - if (ctrl) { - switch(event->keyval) { - case GDK_F2: // file browser panel - mainNB->set_current_page (mainNB->page_num (*fpanel)); - return true; - case GDK_F3: // batch queue panel - mainNB->set_current_page (mainNB->page_num (*bpanel)); - return true; - case GDK_F4: //single tab mode, editor panel - if (isSingleTabMode() && epanel) { - mainNB->set_current_page (mainNB->page_num (*epanel)); - } - return true; - case GDK_w: //multi-tab mode, close editor panel - if (!isSingleTabMode() && - mainNB->get_current_page()!=mainNB->page_num(*fpanel) && - mainNB->get_current_page()!=mainNB->page_num(*bpanel)) { - - EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); - remEditorPanel (ep); - return true; - } - } - } + if (ctrl) { + switch(event->keyval) { + case GDK_F2: // file browser panel + mainNB->set_current_page (mainNB->page_num (*fpanel)); + return true; + + case GDK_F3: // batch queue panel + mainNB->set_current_page (mainNB->page_num (*bpanel)); + return true; + + case GDK_F4: //single tab mode, editor panel + if (isSingleTabMode() && epanel) { + mainNB->set_current_page (mainNB->page_num (*epanel)); + } + + return true; + + case GDK_w: //multi-tab mode, close editor panel + if (!isSingleTabMode() && + mainNB->get_current_page() != mainNB->page_num(*fpanel) && + mainNB->get_current_page() != mainNB->page_num(*bpanel)) { + + EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); + remEditorPanel (ep); + return true; + } + } + } if (mainNB->get_current_page() == mainNB->page_num(*fpanel)) { return fpanel->handleShortcutKey (event); - } - else if (mainNB->get_current_page() == mainNB->page_num(*bpanel)) { + } else if (mainNB->get_current_page() == mainNB->page_num(*bpanel)) { return bpanel->handleShortcutKey (event); - } - else { + } else { EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page())); return ep->handleShortcutKey (event); } + return false; } -void RTWindow::addBatchQueueJob (BatchQueueEntry* bqe, bool head) { +void RTWindow::addBatchQueueJob (BatchQueueEntry* bqe, bool head) +{ - std::vector entries; - entries.push_back(bqe); + std::vector entries; + entries.push_back(bqe); bpanel->addBatchQueueJobs (entries, head); fpanel->queue_draw (); } -void RTWindow::addBatchQueueJobs (std::vector &entries) { +void RTWindow::addBatchQueueJobs (std::vector &entries) +{ bpanel->addBatchQueueJobs (entries, false); fpanel->queue_draw (); } -bool RTWindow::on_delete_event(GdkEventAny* event) { +bool RTWindow::on_delete_event(GdkEventAny* event) +{ if (on_delete_has_run) { // on Mac OSX we can get multiple events return false; } + // Check if any editor is still processing, and do NOT quit if so. Otherwise crashes and inconsistent caches - bool isProcessing=false; + bool isProcessing = false; - if (isSingleTabMode() || simpleEditor) - isProcessing=epanel->getIsProcessing(); - else { - int pageCount=mainNB->get_n_pages(); + if (isSingleTabMode() || simpleEditor) { + isProcessing = epanel->getIsProcessing(); + } else { + int pageCount = mainNB->get_n_pages(); - for (int i=0;i(mainNB->get_nth_page(i)))->getIsProcessing(); - } + for (int i = 0; i < pageCount && !isProcessing; i++) { + if(isEditorPanel(i)) { + isProcessing |= (static_cast(mainNB->get_nth_page(i)))->getIsProcessing(); + } + } } - if (isProcessing) - return true; + if (isProcessing) { + return true; + } + + if( fpanel ) { + fpanel->saveOptions (); + } + + if( bpanel ) { + bpanel->saveOptions (); + } - if( fpanel ) - fpanel->saveOptions (); - if( bpanel ) - bpanel->saveOptions (); - if ((isSingleTabMode() || simpleEditor) && epanel->isRealized()) { - epanel->saveProfile(); - epanel->writeOptions (); - } - else { + epanel->saveProfile(); + epanel->writeOptions (); + } else { // Storing the options of the last EditorPanel before Gtk destroys everything // Look at the active panel first, if any, otherwise look at the first one (sorted on the filename) if (epanels.size()) { int page = mainNB->get_current_page(); Gtk::Widget *w = mainNB->get_nth_page(page); bool optionsWritten = false; - for (std::map::iterator i=epanels.begin(); i!=epanels.end(); i++) { + + for (std::map::iterator i = epanels.begin(); i != epanels.end(); i++) { if (i->second == w) { i->second->writeOptions(); optionsWritten = true; } } + if (!optionsWritten) { // fallback solution: save the options of the first editor panel - std::map::iterator i=epanels.begin(); + std::map::iterator i = epanels.begin(); i->second->writeOptions(); } - } + } } cacheMgr->closeCache (); // also makes cleanup if too large @@ -619,9 +695,9 @@ bool RTWindow::on_delete_event(GdkEventAny* event) { ProfilePanel::cleanup(); if (!options.windowMaximized) { - options.windowWidth = get_width(); - options.windowHeight = get_height(); - get_position (options.windowX,options.windowY); + options.windowWidth = get_width(); + options.windowHeight = get_height(); + get_position (options.windowX, options.windowY); } Options::save (); @@ -630,34 +706,42 @@ bool RTWindow::on_delete_event(GdkEventAny* event) { return false; } -void RTWindow::showPreferences () { - Preferences *pref = new Preferences (this); - pref->run (); - delete pref; - - fpanel->optionsChanged (); +void RTWindow::showPreferences () +{ + Preferences *pref = new Preferences (this); + pref->run (); + delete pref; + + fpanel->optionsChanged (); } -void RTWindow::setProgress (double p) { - prProgBar.set_fraction (p); +void RTWindow::setProgress (double p) +{ + prProgBar.set_fraction (p); } -void RTWindow::setProgressStr (Glib::ustring str) { - if (!options.mainNBVertical) - prProgBar.set_text ( str ); +void RTWindow::setProgressStr (Glib::ustring str) +{ + if (!options.mainNBVertical) { + prProgBar.set_text ( str ); + } } -void RTWindow::setProgressState (bool inProcessing) { - if (inProcessing) - prProgBar.show(); - else - prProgBar.hide(); - } - -void RTWindow::toggle_fullscreen () { +void RTWindow::setProgressState (bool inProcessing) +{ + if (inProcessing) { + prProgBar.show(); + } else { + prProgBar.hide(); + } +} + +void RTWindow::toggle_fullscreen () +{ if (is_fullscreen) { unfullscreen(); is_fullscreen = false; + if (btn_fullscreen) { //btn_fullscreen->set_label(M("MAIN_BUTTON_FULLSCREEN")); btn_fullscreen->set_tooltip_markup(M("MAIN_BUTTON_FULLSCREEN")); @@ -666,6 +750,7 @@ void RTWindow::toggle_fullscreen () { } else { fullscreen(); is_fullscreen = true; + if (btn_fullscreen) { //btn_fullscreen->set_label(M("MAIN_BUTTON_UNFULLSCREEN")); btn_fullscreen->set_tooltip_markup(M("MAIN_BUTTON_UNFULLSCREEN")); @@ -674,24 +759,24 @@ void RTWindow::toggle_fullscreen () { } } -void RTWindow::error (Glib::ustring descr){ - prProgBar.set_text ( descr ); +void RTWindow::error (Glib::ustring descr) +{ + prProgBar.set_text ( descr ); } void RTWindow::SetEditorCurrent() { - mainNB->set_current_page (mainNB->page_num (*epanel)); + mainNB->set_current_page (mainNB->page_num (*epanel)); } void RTWindow::SetMainCurrent() { - mainNB->set_current_page (mainNB->page_num (*fpanel)); + mainNB->set_current_page (mainNB->page_num (*fpanel)); } void RTWindow::MoveFileBrowserToMain() { - if( fpanel->ribbonPane->get_children().empty()) - { + if( fpanel->ribbonPane->get_children().empty()) { FileCatalog *fCatalog = fpanel->fileCatalog; epanel->catalogPane->remove(*fCatalog); fpanel->ribbonPane->add(*fCatalog); @@ -703,8 +788,7 @@ void RTWindow::MoveFileBrowserToMain() void RTWindow::MoveFileBrowserToEditor() { - if(epanel->catalogPane->get_children().empty() ) - { + if(epanel->catalogPane->get_children().empty() ) { FileCatalog *fCatalog = fpanel->fileCatalog; fpanel->ribbonPane->remove(*fCatalog); fCatalog->disableInspector(); @@ -717,68 +801,86 @@ void RTWindow::MoveFileBrowserToEditor() } } -void RTWindow::updateTPVScrollbar (bool hide) { - fpanel->updateTPVScrollbar (hide); - epanel->updateTPVScrollbar (hide); +void RTWindow::updateTPVScrollbar (bool hide) +{ + fpanel->updateTPVScrollbar (hide); + epanel->updateTPVScrollbar (hide); - std::map::const_iterator itr; - for(itr = epanels.begin(); itr != epanels.end(); ++itr){ - ((*itr).second)->updateTPVScrollbar (hide); - } + std::map::const_iterator itr; + + for(itr = epanels.begin(); itr != epanels.end(); ++itr) { + ((*itr).second)->updateTPVScrollbar (hide); + } } -void RTWindow::updateTabsUsesIcons (bool useIcons) { - fpanel->updateTabsUsesIcons (useIcons); - epanel->updateTabsUsesIcons (useIcons); +void RTWindow::updateTabsUsesIcons (bool useIcons) +{ + fpanel->updateTabsUsesIcons (useIcons); + epanel->updateTabsUsesIcons (useIcons); - std::map::const_iterator itr; - for(itr = epanels.begin(); itr != epanels.end(); ++itr){ - ((*itr).second)->updateTabsUsesIcons (useIcons); - } + std::map::const_iterator itr; + + for(itr = epanels.begin(); itr != epanels.end(); ++itr) { + ((*itr).second)->updateTabsUsesIcons (useIcons); + } } -void RTWindow::updateFBQueryTB (bool singleRow) { - fpanel->fileCatalog->updateFBQueryTB (singleRow); +void RTWindow::updateFBQueryTB (bool singleRow) +{ + fpanel->fileCatalog->updateFBQueryTB (singleRow); } -void RTWindow::updateFBToolBarVisibility (bool showFilmStripToolBar){ - fpanel->fileCatalog->updateFBToolBarVisibility (showFilmStripToolBar); +void RTWindow::updateFBToolBarVisibility (bool showFilmStripToolBar) +{ + fpanel->fileCatalog->updateFBToolBarVisibility (showFilmStripToolBar); } -void RTWindow::updateHistogramPosition (int oldPosition, int newPosition) { - epanel->updateHistogramPosition (oldPosition, newPosition); +void RTWindow::updateHistogramPosition (int oldPosition, int newPosition) +{ + epanel->updateHistogramPosition (oldPosition, newPosition); - std::map::const_iterator itr; - for(itr = epanels.begin(); itr != epanels.end(); ++itr){ - ((*itr).second)->updateHistogramPosition (oldPosition, newPosition); - } + std::map::const_iterator itr; + + for(itr = epanels.begin(); itr != epanels.end(); ++itr) { + ((*itr).second)->updateHistogramPosition (oldPosition, newPosition); + } } -bool RTWindow::splashClosed(GdkEventAny* event) { - delete splash; - splash = NULL; - return true; +bool RTWindow::splashClosed(GdkEventAny* event) +{ + delete splash; + splash = NULL; + return true; } -void RTWindow::set_title_decorated(Glib::ustring fname){ - Glib::ustring subtitle; - if (!fname.empty()) subtitle= " - " + fname; - set_title(versionStr + subtitle); +void RTWindow::set_title_decorated(Glib::ustring fname) +{ + Glib::ustring subtitle; + + if (!fname.empty()) { + subtitle = " - " + fname; + } + + set_title(versionStr + subtitle); } -void RTWindow::CloseOpenEditors(){ - std::map::const_iterator itr; - itr = epanels.begin(); - while(itr != epanels.end()) { - remEditorPanel((*itr).second); - itr = epanels.begin(); - } +void RTWindow::CloseOpenEditors() +{ + std::map::const_iterator itr; + itr = epanels.begin(); + + while(itr != epanels.end()) { + remEditorPanel((*itr).second); + itr = epanels.begin(); + } } -bool RTWindow::isEditorPanel(Widget* panel) { - return (panel != bpanel) && (panel != fpanel); +bool RTWindow::isEditorPanel(Widget* panel) +{ + return (panel != bpanel) && (panel != fpanel); } -bool RTWindow::isEditorPanel(guint pageNum) { - return isEditorPanel(mainNB->get_nth_page(pageNum)); +bool RTWindow::isEditorPanel(guint pageNum) +{ + return isEditorPanel(mainNB->get_nth_page(pageNum)); } diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index cdd2bf290..70e80de4d 100644 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -6,7 +6,7 @@ * 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 @@ -30,81 +30,91 @@ #include #endif -class RTWindow : public Gtk::Window, public rtengine::ProgressListener{ +class RTWindow : public Gtk::Window, public rtengine::ProgressListener +{ - private: - Gtk::Notebook* mainNB; - BatchQueuePanel* bpanel; - std::set filesEdited; - std::map epanels; +private: + Gtk::Notebook* mainNB; + BatchQueuePanel* bpanel; + std::set filesEdited; + std::map epanels; - Splash* splash; - Gtk::ProgressBar prProgBar; - PLDBridge* pldBridge; - bool is_fullscreen; - bool on_delete_has_run; - Gtk::Button * btn_fullscreen; - - Gtk::Image *iFullscreen, *iFullscreen_exit; + Splash* splash; + Gtk::ProgressBar prProgBar; + PLDBridge* pldBridge; + bool is_fullscreen; + bool on_delete_has_run; + Gtk::Button * btn_fullscreen; - bool isSingleTabMode() { return !options.tabbedUI && !(options.multiDisplayMode>0); }; - void findVerNumbers(int* numbers, Glib::ustring versionStr); + Gtk::Image *iFullscreen, *iFullscreen_exit; - bool on_expose_event_epanel(GdkEventExpose* event); - bool on_expose_event_fpanel(GdkEventExpose* event); - bool splashClosed(GdkEventAny* event); - bool isEditorPanel(Widget* panel); - bool isEditorPanel(guint pageNum); + bool isSingleTabMode() + { + return !options.tabbedUI && !(options.multiDisplayMode > 0); + }; + void findVerNumbers(int* numbers, Glib::ustring versionStr); - Glib::ustring versionStr; + bool on_expose_event_epanel(GdkEventExpose* event); + bool on_expose_event_fpanel(GdkEventExpose* event); + bool splashClosed(GdkEventAny* event); + bool isEditorPanel(Widget* panel); + bool isEditorPanel(guint pageNum); + + Glib::ustring versionStr; #if defined(__APPLE__) - GtkosxApplication *osxApp; + GtkosxApplication *osxApp; #endif - public: - RTWindow (); - ~RTWindow(); +public: + RTWindow (); + ~RTWindow(); #if defined(__APPLE__) - bool osxFileOpenEvent(Glib::ustring path); + bool osxFileOpenEvent(Glib::ustring path); #endif - void addEditorPanel (EditorPanel* ep,const std::string &name); - void remEditorPanel (EditorPanel* ep); - bool selectEditorPanel(const std::string &name); + void addEditorPanel (EditorPanel* ep, const std::string &name); + void remEditorPanel (EditorPanel* ep); + bool selectEditorPanel(const std::string &name); - void addBatchQueueJob (BatchQueueEntry* bqe, bool head=false); - void addBatchQueueJobs (std::vector &entries); + void addBatchQueueJob (BatchQueueEntry* bqe, bool head = false); + void addBatchQueueJobs (std::vector &entries); - bool keyPressed (GdkEventKey* event); - bool on_delete_event(GdkEventAny* event); - bool on_window_state_event(GdkEventWindowState* event); - void on_mainNB_switch_page(GtkNotebookPage* page, guint page_num); + bool keyPressed (GdkEventKey* event); + bool on_delete_event(GdkEventAny* event); + bool on_window_state_event(GdkEventWindowState* event); + void on_mainNB_switch_page(GtkNotebookPage* page, guint page_num); - void showPreferences (); - void on_realize (); - void toggle_fullscreen (); - void setProgress (double p); - void setProgressStr (Glib::ustring str); - void setProgressState (bool inProcessing); - void error (Glib::ustring descr); - rtengine::ProgressListener* getProgressListener () { return pldBridge; } - - EditorPanel* epanel; - FilePanel* fpanel; + void showPreferences (); + void on_realize (); + void toggle_fullscreen (); + void setProgress (double p); + void setProgressStr (Glib::ustring str); + void setProgressState (bool inProcessing); + void error (Glib::ustring descr); + rtengine::ProgressListener* getProgressListener () + { + return pldBridge; + } - void SetEditorCurrent(); - void SetMainCurrent(); - void MoveFileBrowserToEditor(); - void MoveFileBrowserToMain(); + EditorPanel* epanel; + FilePanel* fpanel; - void updateTPVScrollbar (bool hide); - void updateHistogramPosition (int oldPosition, int newPosition); - void updateTabsUsesIcons (bool useIcons); - void updateFBQueryTB (bool singleRow); - void updateFBToolBarVisibility (bool showFilmStripToolBar); - bool getIsFullscreen() { return is_fullscreen; } - void set_title_decorated(Glib::ustring fname); - void CloseOpenEditors(); + void SetEditorCurrent(); + void SetMainCurrent(); + void MoveFileBrowserToEditor(); + void MoveFileBrowserToMain(); + + void updateTPVScrollbar (bool hide); + void updateHistogramPosition (int oldPosition, int newPosition); + void updateTabsUsesIcons (bool useIcons); + void updateFBQueryTB (bool singleRow); + void updateFBToolBarVisibility (bool showFilmStripToolBar); + bool getIsFullscreen() + { + return is_fullscreen; + } + void set_title_decorated(Glib::ustring fname); + void CloseOpenEditors(); }; #endif diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index c387f64f9..47957bc80 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -7,7 +7,7 @@ * 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 @@ -23,15 +23,16 @@ #include "rtimage.h" extern Options options; -SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { +SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) +{ - set_title(M("GENERAL_SAVE")); + set_title(M("GENERAL_SAVE")); Gtk::VBox* vbox = get_vbox (); fchooser = Gtk::manage( new Gtk::FileChooserWidget (Gtk::FILE_CHOOSER_ACTION_SAVE) ); fchooser->set_current_folder (initialDir); - fchooser->signal_file_activated().connect(sigc::mem_fun(*this,&SaveAsDialog::okPressed)); + fchooser->signal_file_activated().connect(sigc::mem_fun(*this, &SaveAsDialog::okPressed)); filter_jpg.set_name(M("SAVEDLG_JPGFILTER")); filter_jpg.add_pattern("*.jpg"); @@ -69,8 +70,9 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { saveMethod[1]->set_group (g); saveMethod[2]->set_group (g); - if (options.saveMethodNum >= 0 && options.saveMethodNum < 3) + if (options.saveMethodNum >= 0 && options.saveMethodNum < 3) { saveMethod[options.saveMethodNum]->set_active (true); + } saveMethod[0]->signal_clicked().connect( sigc::mem_fun(*this, &SaveAsDialog::saveImmediatlyClicked) ); saveMethod[1]->signal_clicked().connect( sigc::mem_fun(*this, &SaveAsDialog::putToQueueClicked) ); @@ -80,10 +82,10 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { // ~~~~~~~~~~~~~~~~~~~~~~~~~~ forceFormatOpts = Gtk::manage( new Gtk::CheckButton (M("SAVEDLG_FORCEFORMATOPTS")) ); forceFormatOpts->set_active(options.forceFormatOpts); - forceFormatOpts->set_sensitive(options.saveMethodNum>0); + forceFormatOpts->set_sensitive(options.saveMethodNum > 0); forceFormatOpts->signal_clicked().connect( sigc::mem_fun(*this, &SaveAsDialog::forceFmtOptsSwitched) ); // update sensitivity of the SaveFormatPanel - formatOpts->set_sensitive(options.saveMethodNum==0 || options.forceFormatOpts); + formatOpts->set_sensitive(options.saveMethodNum == 0 || options.forceFormatOpts); // Unique filename option // ~~~~~~~~~~~~~~~~~~~~~~ @@ -97,7 +99,7 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { ok->set_image (*Gtk::manage(new RTImage ("gtk-apply.png"))); cancel->set_image (*Gtk::manage(new RTImage ("gtk-cancel.png"))); - + ok->set_tooltip_markup (M("TP_SAVEDIALOG_OK_TIP")); ok->signal_clicked().connect( sigc::mem_fun(*this, &SaveAsDialog::okPressed) ); @@ -106,6 +108,7 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { // pack everything // ~~~~~~~~~~~~~~~ Gtk::VBox* vbox_bottomRight = Gtk::manage(new Gtk::VBox ()); + // There is no queue in simple mode, so no need to choose if (!simpleEditor) { vbox_bottomRight->pack_start (*saveMethod[0], Gtk::PACK_SHRINK, 2); @@ -113,6 +116,7 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { vbox_bottomRight->pack_start (*saveMethod[2], Gtk::PACK_SHRINK, 2); vbox_bottomRight->pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 5); } + vbox_bottomRight->pack_start (*forceFormatOpts, Gtk::PACK_SHRINK, 4); vbox_bottomRight->pack_start (*autoSuffix, Gtk::PACK_SHRINK, 4); @@ -133,70 +137,87 @@ SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) { signal_key_press_event().connect( sigc::mem_fun(*this, &SaveAsDialog::keyPressed) ); } -void SaveAsDialog::saveImmediatlyClicked () { +void SaveAsDialog::saveImmediatlyClicked () +{ forceFormatOpts->set_sensitive(false); formatOpts->set_sensitive(true); } -void SaveAsDialog::putToQueueClicked () { +void SaveAsDialog::putToQueueClicked () +{ forceFormatOpts->set_sensitive(true); formatOpts->set_sensitive(forceFormatOpts->get_active()); } -void SaveAsDialog::forceFmtOptsSwitched () { +void SaveAsDialog::forceFmtOptsSwitched () +{ formatOpts->set_sensitive(forceFormatOpts->get_active()); } -bool SaveAsDialog::getForceFormatOpts () { +bool SaveAsDialog::getForceFormatOpts () +{ return forceFormatOpts->get_active(); } -bool SaveAsDialog::getAutoSuffix () { +bool SaveAsDialog::getAutoSuffix () +{ return autoSuffix->get_active(); } -bool SaveAsDialog::getImmediately () { +bool SaveAsDialog::getImmediately () +{ return simpleEditor ? true : saveMethod[0]->get_active (); } -bool SaveAsDialog::getToHeadOfQueue () { +bool SaveAsDialog::getToHeadOfQueue () +{ return saveMethod[1]->get_active (); } -bool SaveAsDialog::getToTailOfQueue () { +bool SaveAsDialog::getToTailOfQueue () +{ return saveMethod[2]->get_active (); } -int SaveAsDialog::getSaveMethodNum () { - if (simpleEditor) +int SaveAsDialog::getSaveMethodNum () +{ + if (simpleEditor) { return 0; + } + for (int i = 0; i < 3; i++) - if (saveMethod[i]->get_active()) + if (saveMethod[i]->get_active()) { return i; + } + return -1; } -Glib::ustring SaveAsDialog::getFileName () { +Glib::ustring SaveAsDialog::getFileName () +{ return fname; } -Glib::ustring SaveAsDialog::getDirectory () { +Glib::ustring SaveAsDialog::getDirectory () +{ return fchooser->get_current_folder (); } -SaveFormat SaveAsDialog::getFormat () { +SaveFormat SaveAsDialog::getFormat () +{ return formatOpts->getFormat (); } -void SaveAsDialog::okPressed () { +void SaveAsDialog::okPressed () +{ fname = fchooser->get_filename(); @@ -217,74 +238,84 @@ void SaveAsDialog::okPressed () { bool extIsJpeg = (extLower == "jpg" || extLower == "jpeg" || extLower == "jpe"); bool extIsTiff = (extLower == "tif" || extLower == "tiff"); bool extIsPng = (extLower == "png"); - if (extIsEmpty || !(extIsJpeg || extIsTiff || extIsPng)) { + + if (extIsEmpty || !(extIsJpeg || extIsTiff || extIsPng)) { // extension is either empty or unfamiliar. fname += Glib::ustring (".") + sf.format; } else if ( !(sf.format == "jpg" && extIsJpeg) - && !(sf.format == "tif" && extIsTiff) - && !(sf.format == "png" && extIsPng ) ) { + && !(sf.format == "tif" && extIsTiff) + && !(sf.format == "png" && extIsPng ) ) { // create dialog to warn user that the filename may have two extensions on the end. Glib::ustring msg_ = Glib::ustring ("") + M("GENERAL_WARNING") + ": " + M("SAVEDLG_WARNFILENAME") + " \"" + Glib::path_get_basename (fname) + "." + sf.format + "\""; Gtk::MessageDialog msgd (*this, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK_CANCEL, true); - if (msgd.run () == Gtk::RESPONSE_OK) + + if (msgd.run () == Gtk::RESPONSE_OK) { fname += Glib::ustring (".") + sf.format; - else + } else { return; + } } response (Gtk::RESPONSE_OK); } -void SaveAsDialog::cancelPressed () { +void SaveAsDialog::cancelPressed () +{ fname = fchooser->get_filename(); response (Gtk::RESPONSE_CANCEL); } -void SaveAsDialog::formatChanged (Glib::ustring f) { +void SaveAsDialog::formatChanged (Glib::ustring f) +{ - if (f=="jpg") + if (f == "jpg") { fchooser->set_filter (filter_jpg); - else if (f=="png") + } else if (f == "png") { fchooser->set_filter (filter_png); - else if (f=="tif") + } else if (f == "tif") { fchooser->set_filter (filter_tif); + } } -void SaveAsDialog::setInitialFileName (Glib::ustring fname) { +void SaveAsDialog::setInitialFileName (Glib::ustring fname) +{ fchooser->set_current_name(fname); } -void SaveAsDialog::setImagePath (Glib::ustring ipath) { +void SaveAsDialog::setImagePath (Glib::ustring ipath) +{ 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); + try { + fchooser->add_shortcut_folder(path); + } catch (Glib::Error &err) {} +} + + +bool SaveAsDialog::keyPressed (GdkEventKey* event) +{ + + bool ctrl = event->state & GDK_CONTROL_MASK; + + if (ctrl) { + switch(event->keyval) { + case GDK_Return: // Ctrl-Enter equivalent to pressing OK button + case GDK_KP_Enter: + SaveAsDialog::okPressed(); + return true; + } } - catch (Glib::Error &err) {} -} - - -bool SaveAsDialog::keyPressed (GdkEventKey* event) { - - bool ctrl = event->state & GDK_CONTROL_MASK; - - if (ctrl){ - switch(event->keyval) { - case GDK_Return: // Ctrl-Enter equivalent to pressing OK button - case GDK_KP_Enter: - SaveAsDialog::okPressed(); - return true; - } - } - return false; + + return false; } diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index 7db08b702..db307e4b8 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -7,7 +7,7 @@ * 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 @@ -24,9 +24,10 @@ #include "saveformatpanel.h" #include "options.h" -class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener { +class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener +{ - protected: +protected: Gtk::FileChooserWidget* fchooser; Gtk::CheckButton* autoSuffix; Gtk::CheckButton* forceFormatOpts; @@ -43,9 +44,9 @@ class SaveAsDialog : public Gtk::Dialog, public FormatChangeListener { void saveImmediatlyClicked (); void putToQueueClicked (); - public: +public: SaveAsDialog (Glib::ustring initialDir); - + Glib::ustring getFileName (); Glib::ustring getDirectory (); SaveFormat getFormat (); diff --git a/rtgui/saveformatpanel.cc b/rtgui/saveformatpanel.cc index e9fba1e2c..2159f6623 100644 --- a/rtgui/saveformatpanel.cc +++ b/rtgui/saveformatpanel.cc @@ -7,7 +7,7 @@ * 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 @@ -20,15 +20,16 @@ #include "multilangmgr.h" #include "guiutils.h" -SaveFormatPanel::SaveFormatPanel () : listener (NULL) { +SaveFormatPanel::SaveFormatPanel () : listener (NULL) +{ jpegqual = new Adjuster (M("SAVEDLG_JPEGQUAL"), 0, 100, 1, 100); jpegqual->setAdjusterListener (this); jpegqual->show (); - + jpegSubSampBox = Gtk::manage (new Gtk::HBox ()); - jpegSubSampHead=Gtk::manage (new Gtk::Label (M("SAVEDLG_SUBSAMP") + Glib::ustring(":")) ); + jpegSubSampHead = Gtk::manage (new Gtk::Label (M("SAVEDLG_SUBSAMP") + Glib::ustring(":")) ); jpegSubSampHead->show (); jpegSubSampBox->pack_start (*jpegSubSampHead, Gtk::PACK_SHRINK, 4); @@ -48,12 +49,12 @@ SaveFormatPanel::SaveFormatPanel () : listener (NULL) { pngcompr->setAdjusterListener (this); pngcompr->show (); tiffuncompressed = new Gtk::CheckButton (M("SAVEDLG_TIFFUNCOMPRESSED")); - tiffuncompressed->signal_toggled().connect( sigc::mem_fun(*this,&SaveFormatPanel::formatChanged)); + tiffuncompressed->signal_toggled().connect( sigc::mem_fun(*this, &SaveFormatPanel::formatChanged)); tiffuncompressed->show(); Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* flab = Gtk::manage (new Gtk::Label (M("SAVEDLG_FILEFORMAT")+":")); - hb1->pack_start (*flab, Gtk::PACK_SHRINK,4); + Gtk::Label* flab = Gtk::manage (new Gtk::Label (M("SAVEDLG_FILEFORMAT") + ":")); + hb1->pack_start (*flab, Gtk::PACK_SHRINK, 4); format = Gtk::manage (new MyComboBoxText ()); format->append_text ("JPEG (8 bit)"); format->append_text ("TIFF (8 bit)"); @@ -70,14 +71,14 @@ SaveFormatPanel::SaveFormatPanel () : listener (NULL) { formatopts->pack_start (*jpegqual, Gtk::PACK_SHRINK, 4); formatopts->pack_start (*jpegSubSampBox, Gtk::PACK_SHRINK, 4); pack_start (*formatopts, Gtk::PACK_SHRINK, 4); - + savespp = Gtk::manage (new Gtk::CheckButton (M("SAVEDLG_SAVESPP"))); - savespp->signal_toggled().connect( sigc::mem_fun(*this,&SaveFormatPanel::formatChanged)); + savespp->signal_toggled().connect( sigc::mem_fun(*this, &SaveFormatPanel::formatChanged)); pack_start (*savespp, Gtk::PACK_SHRINK, 4); show_all (); set_border_width (4); - + fstr[0] = "jpg"; fstr[1] = "tif"; fstr[2] = "tif"; @@ -86,92 +87,112 @@ SaveFormatPanel::SaveFormatPanel () : listener (NULL) { } SaveFormatPanel::~SaveFormatPanel () { - delete jpegqual; - delete pngcompr; - delete tiffuncompressed; + delete jpegqual; + delete pngcompr; + delete tiffuncompressed; } -void SaveFormatPanel::init (SaveFormat &sf) { - +void SaveFormatPanel::init (SaveFormat &sf) +{ + FormatChangeListener* tmp = listener; - listener = NULL; - - if (sf.format=="jpg") + listener = NULL; + + if (sf.format == "jpg") { format->set_active (0); - else if (sf.format=="png" && sf.pngBits==16) + } else if (sf.format == "png" && sf.pngBits == 16) { format->set_active (4); - else if (sf.format=="png" && sf.pngBits==8) + } else if (sf.format == "png" && sf.pngBits == 8) { format->set_active (3); - else if (sf.format=="tif" && sf.tiffBits==16) + } else if (sf.format == "tif" && sf.tiffBits == 16) { format->set_active (2); - else if (sf.format=="tif" && sf.tiffBits==8) + } else if (sf.format == "tif" && sf.tiffBits == 8) { format->set_active (1); - - jpegSubSamp->set_active (sf.jpegSubSamp-1); - + } + + jpegSubSamp->set_active (sf.jpegSubSamp - 1); + pngcompr->setValue (sf.pngCompression); jpegqual->setValue (sf.jpegQuality); savespp->set_active (sf.saveParams); tiffuncompressed->set_active (sf.tiffUncompressed); listener = tmp; } - -SaveFormat SaveFormatPanel::getFormat () { + +SaveFormat SaveFormatPanel::getFormat () +{ SaveFormat sf; int sel = format->get_active_row_number(); sf.format = fstr[sel]; - if (sel==4) + + if (sel == 4) { sf.pngBits = 16; - else + } else { sf.pngBits = 8; - if (sel==2) + } + + if (sel == 2) { sf.tiffBits = 16; - else + } else { sf.tiffBits = 8; + } + sf.pngCompression = (int) pngcompr->getValue (); sf.jpegQuality = (int) jpegqual->getValue (); - sf.jpegSubSamp = jpegSubSamp->get_active_row_number()+1; + sf.jpegSubSamp = jpegSubSamp->get_active_row_number() + 1; sf.tiffUncompressed = tiffuncompressed->get_active(); sf.saveParams = savespp->get_active (); return sf; } - -void SaveFormatPanel::formatChanged () { - if (oformat==0) { +void SaveFormatPanel::formatChanged () +{ + + if (oformat == 0) { removeIfThere (formatopts, jpegqual); removeIfThere (formatopts, jpegSubSampBox); - } else if (oformat==3 || oformat==4) + } else if (oformat == 3 || oformat == 4) { removeIfThere (formatopts, pngcompr); - else if (oformat==1 || oformat==2) - removeIfThere (formatopts, tiffuncompressed); + } else if (oformat == 1 || oformat == 2) { + removeIfThere (formatopts, tiffuncompressed); + } int act = format->get_active_row_number(); - if (act<0 || act>4) + + if (act < 0 || act > 4) { return; - + } + Glib::ustring fr = fstr[act]; - if (fr=="jpg") { - formatopts->pack_start (*jpegqual, Gtk::PACK_SHRINK,4); - formatopts->pack_start (*jpegSubSampBox, Gtk::PACK_SHRINK,4); - } else if (fr=="png") - formatopts->pack_start (*pngcompr, Gtk::PACK_SHRINK,4); - else if (fr=="tif") - formatopts->pack_start (*tiffuncompressed, Gtk::PACK_SHRINK,4); + + if (fr == "jpg") { + formatopts->pack_start (*jpegqual, Gtk::PACK_SHRINK, 4); + formatopts->pack_start (*jpegSubSampBox, Gtk::PACK_SHRINK, 4); + } else if (fr == "png") { + formatopts->pack_start (*pngcompr, Gtk::PACK_SHRINK, 4); + } else if (fr == "tif") { + formatopts->pack_start (*tiffuncompressed, Gtk::PACK_SHRINK, 4); + } oformat = act; - - if (listener) + + if (listener) { listener->formatChanged (fr); + } } -void SaveFormatPanel::adjusterChanged (Adjuster* a, double newval) { +void SaveFormatPanel::adjusterChanged (Adjuster* a, double newval) +{ int act = format->get_active_row_number(); - if (act<0 || act>4) + + if (act < 0 || act > 4) { return; - if (listener) + } + + if (listener) { listener->formatChanged (fstr[act]); + } } diff --git a/rtgui/saveformatpanel.h b/rtgui/saveformatpanel.h index 3f21dea97..e4b4b1b7d 100644 --- a/rtgui/saveformatpanel.h +++ b/rtgui/saveformatpanel.h @@ -7,7 +7,7 @@ * 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 @@ -24,41 +24,46 @@ #include "guiutils.h" #include "options.h" -class FormatChangeListener { +class FormatChangeListener +{ - public: - virtual void formatChanged (Glib::ustring f) {} +public: + virtual void formatChanged (Glib::ustring f) {} }; -class SaveFormatPanel : public Gtk::VBox, public AdjusterListener { +class SaveFormatPanel : public Gtk::VBox, public AdjusterListener +{ - protected: - Adjuster* jpegqual; - Adjuster* pngcompr; - Gtk::CheckButton* tiffuncompressed; - MyComboBoxText* format; - MyComboBoxText* jpegSubSamp; - Gtk::VBox* formatopts; - Gtk::HBox* jpegSubSampBox; - Gtk::Label* jpegSubSampHead; - int oformat; - FormatChangeListener* listener; - Glib::ustring fstr[5]; - Gtk::CheckButton* savespp; - - - public: - - SaveFormatPanel (); - ~SaveFormatPanel (); - void setListener (FormatChangeListener* l) { listener = l; } +protected: + Adjuster* jpegqual; + Adjuster* pngcompr; + Gtk::CheckButton* tiffuncompressed; + MyComboBoxText* format; + MyComboBoxText* jpegSubSamp; + Gtk::VBox* formatopts; + Gtk::HBox* jpegSubSampBox; + Gtk::Label* jpegSubSampHead; + int oformat; + FormatChangeListener* listener; + Glib::ustring fstr[5]; + Gtk::CheckButton* savespp; - void init (SaveFormat& sf); - SaveFormat getFormat (); - - void formatChanged (); - void adjusterChanged (Adjuster* a, double newval); + +public: + + SaveFormatPanel (); + ~SaveFormatPanel (); + void setListener (FormatChangeListener* l) + { + listener = l; + } + + void init (SaveFormat& sf); + SaveFormat getFormat (); + + void formatChanged (); + void adjusterChanged (Adjuster* a, double newval); }; #endif diff --git a/rtgui/sensorbayer.cc b/rtgui/sensorbayer.cc index 759622272..8bd36fe32 100644 --- a/rtgui/sensorbayer.cc +++ b/rtgui/sensorbayer.cc @@ -23,10 +23,11 @@ using namespace rtengine; using namespace rtengine::procparams; -SensorBayer::SensorBayer () : FoldableToolPanel(this, "sensorbayer", M("TP_RAW_SENSOR_BAYER_LABEL")) { +SensorBayer::SensorBayer () : FoldableToolPanel(this, "sensorbayer", M("TP_RAW_SENSOR_BAYER_LABEL")) +{ - packBox = Gtk::manage (new ToolParamBlock ()); - pack_start (*packBox); + packBox = Gtk::manage (new ToolParamBlock ()); + pack_start (*packBox); - show_all (); + show_all (); } diff --git a/rtgui/sensorbayer.h b/rtgui/sensorbayer.h index 419ac26b9..f3c620d88 100644 --- a/rtgui/sensorbayer.h +++ b/rtgui/sensorbayer.h @@ -22,16 +22,20 @@ #include #include "toolpanel.h" -class SensorBayer : public ToolParamBlock, public FoldableToolPanel { +class SensorBayer : public ToolParamBlock, public FoldableToolPanel +{ - protected: +protected: ToolParamBlock* packBox; - public: +public: SensorBayer (); - Gtk::Box* getPackBox () { return packBox; } + Gtk::Box* getPackBox () + { + return packBox; + } }; #endif diff --git a/rtgui/sensorxtrans.cc b/rtgui/sensorxtrans.cc index a06064572..3f93e050a 100644 --- a/rtgui/sensorxtrans.cc +++ b/rtgui/sensorxtrans.cc @@ -23,10 +23,11 @@ using namespace rtengine; using namespace rtengine::procparams; -SensorXTrans::SensorXTrans () : FoldableToolPanel(this, "sensorxtrans", M("TP_RAW_SENSOR_XTRANS_LABEL")) { +SensorXTrans::SensorXTrans () : FoldableToolPanel(this, "sensorxtrans", M("TP_RAW_SENSOR_XTRANS_LABEL")) +{ - packBox = Gtk::manage (new ToolParamBlock ()); - pack_start (*packBox); + packBox = Gtk::manage (new ToolParamBlock ()); + pack_start (*packBox); - show_all (); + show_all (); } diff --git a/rtgui/sensorxtrans.h b/rtgui/sensorxtrans.h index 80318a901..d723d29f7 100644 --- a/rtgui/sensorxtrans.h +++ b/rtgui/sensorxtrans.h @@ -22,16 +22,20 @@ #include #include "toolpanel.h" -class SensorXTrans : public ToolParamBlock, public FoldableToolPanel { +class SensorXTrans : public ToolParamBlock, public FoldableToolPanel +{ - protected: +protected: ToolParamBlock* packBox; - public: +public: SensorXTrans (); - Gtk::Box* getPackBox () { return packBox; } + Gtk::Box* getPackBox () + { + return packBox; + } }; #endif diff --git a/rtgui/shadowshighlights.cc b/rtgui/shadowshighlights.cc index ec672b3aa..39dcf6429 100644 --- a/rtgui/shadowshighlights.cc +++ b/rtgui/shadowshighlights.cc @@ -7,7 +7,7 @@ * 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 @@ -21,47 +21,49 @@ using namespace rtengine; using namespace rtengine::procparams; -ShadowsHighlights::ShadowsHighlights () : FoldableToolPanel(this, "shadowshighlights", M("TP_SHADOWSHLIGHTS_LABEL"), false, true) { +ShadowsHighlights::ShadowsHighlights () : FoldableToolPanel(this, "shadowshighlights", M("TP_SHADOWSHLIGHTS_LABEL"), false, true) +{ - hq = Gtk::manage (new Gtk::CheckButton (M("TP_SHADOWSHLIGHTS_SHARPMASK"))); - hq->set_active (false); - pack_start (*hq); - hqConn = hq->signal_toggled().connect( sigc::mem_fun(*this, &ShadowsHighlights::hqChanged) ); + hq = Gtk::manage (new Gtk::CheckButton (M("TP_SHADOWSHLIGHTS_SHARPMASK"))); + hq->set_active (false); + pack_start (*hq); + hqConn = hq->signal_toggled().connect( sigc::mem_fun(*this, &ShadowsHighlights::hqChanged) ); - pack_start (*Gtk::manage (new Gtk::HSeparator())); - highlights = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0)); - h_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 80)); - pack_start (*highlights); - pack_start (*h_tonalwidth); + pack_start (*Gtk::manage (new Gtk::HSeparator())); + highlights = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0)); + h_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 80)); + pack_start (*highlights); + pack_start (*h_tonalwidth); - pack_start (*Gtk::manage (new Gtk::HSeparator())); + pack_start (*Gtk::manage (new Gtk::HSeparator())); - shadows = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0)); - s_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 80)); - pack_start (*shadows); - pack_start (*s_tonalwidth); + shadows = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0)); + s_tonalwidth = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 80)); + pack_start (*shadows); + pack_start (*s_tonalwidth); - pack_start (*Gtk::manage (new Gtk::HSeparator())); + pack_start (*Gtk::manage (new Gtk::HSeparator())); - lcontrast = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_LOCALCONTR"), 0, 100, 1, 0)); - pack_start (*lcontrast); + lcontrast = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_LOCALCONTR"), 0, 100, 1, 0)); + pack_start (*lcontrast); - pack_start (*Gtk::manage (new Gtk::HSeparator())); + pack_start (*Gtk::manage (new Gtk::HSeparator())); - radius = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 30)); - pack_start (*radius); + radius = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 30)); + pack_start (*radius); - radius->setAdjusterListener (this); - highlights->setAdjusterListener (this); - h_tonalwidth->setAdjusterListener (this); - shadows->setAdjusterListener (this); - s_tonalwidth->setAdjusterListener (this); - lcontrast->setAdjusterListener (this); - - show_all_children (); + radius->setAdjusterListener (this); + highlights->setAdjusterListener (this); + h_tonalwidth->setAdjusterListener (this); + shadows->setAdjusterListener (this); + s_tonalwidth->setAdjusterListener (this); + lcontrast->setAdjusterListener (this); + + show_all_children (); } -void ShadowsHighlights::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ShadowsHighlights::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -94,7 +96,8 @@ void ShadowsHighlights::read (const ProcParams* pp, const ParamsEdited* pedited) enableListener (); } -void ShadowsHighlights::write (ProcParams* pp, ParamsEdited* pedited) { +void ShadowsHighlights::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->sh.radius = (int)radius->getValue (); pp->sh.localcontrast = (int)lcontrast->getValue (); @@ -117,7 +120,8 @@ void ShadowsHighlights::write (ProcParams* pp, ParamsEdited* pedited) { } } -void ShadowsHighlights::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ShadowsHighlights::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ radius->setDefault (defParams->sh.radius); lcontrast->setDefault (defParams->sh.localcontrast); @@ -133,8 +137,7 @@ void ShadowsHighlights::setDefaults (const ProcParams* defParams, const ParamsEd h_tonalwidth->setDefaultEditedState (pedited->sh.htonalwidth ? Edited : UnEdited); shadows->setDefaultEditedState (pedited->sh.shadows ? Edited : UnEdited); s_tonalwidth->setDefaultEditedState (pedited->sh.stonalwidth ? Edited : UnEdited); - } - else { + } else { radius->setDefaultEditedState (Irrelevant); lcontrast->setDefaultEditedState (Irrelevant); highlights->setDefaultEditedState (Irrelevant); @@ -144,40 +147,45 @@ void ShadowsHighlights::setDefaults (const ProcParams* defParams, const ParamsEd } } -void ShadowsHighlights::adjusterChanged (Adjuster* a, double newval) { +void ShadowsHighlights::adjusterChanged (Adjuster* a, double newval) +{ if (listener && getEnabled()) { Glib::ustring costr = Glib::ustring::format ((int)a->getValue()); - if (a==highlights) + if (a == highlights) { listener->panelChanged (EvSHHighlights, costr); - else if (a==h_tonalwidth) + } else if (a == h_tonalwidth) { listener->panelChanged (EvSHHLTonalW, costr); - else if (a==shadows) + } else if (a == shadows) { listener->panelChanged (EvSHShadows, costr); - else if (a==s_tonalwidth) + } else if (a == s_tonalwidth) { listener->panelChanged (EvSHSHTonalW, costr); - else if (a==radius) + } else if (a == radius) { listener->panelChanged (EvSHRadius, costr); - else if (a==lcontrast) + } else if (a == lcontrast) { listener->panelChanged (EvSHLContrast, costr); + } } } -void ShadowsHighlights::enabledChanged () { +void ShadowsHighlights::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvSHEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvSHEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvSHEnabled, M("GENERAL_DISABLED")); + } } } -void ShadowsHighlights::hqChanged () { +void ShadowsHighlights::hqChanged () +{ if (batchMode) { if (hq->get_inconsistent()) { @@ -185,22 +193,24 @@ void ShadowsHighlights::hqChanged () { hqConn.block (true); hq->set_active (false); hqConn.block (false); - } - else if (lastHQ) + } else if (lastHQ) { hq->set_inconsistent (true); + } lastHQ = hq->get_active (); } - + if (listener) { - if (hq->get_active()) + if (hq->get_active()) { listener->panelChanged (EvSHHighQuality, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvSHHighQuality, M("GENERAL_DISABLED")); + } } } -void ShadowsHighlights::setBatchMode (bool batchMode) { +void ShadowsHighlights::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); radius->showEditedCB (); @@ -211,16 +221,18 @@ void ShadowsHighlights::setBatchMode (bool batchMode) { s_tonalwidth->showEditedCB (); } -void ShadowsHighlights::setAdjusterBehavior (bool hadd, bool sadd, bool lcadd) { +void ShadowsHighlights::setAdjusterBehavior (bool hadd, bool sadd, bool lcadd) +{ - highlights->setAddMode(hadd); - shadows->setAddMode(sadd); - lcontrast->setAddMode(lcadd); + highlights->setAddMode(hadd); + shadows->setAddMode(sadd); + lcontrast->setAddMode(lcadd); } -void ShadowsHighlights::trimValues (rtengine::procparams::ProcParams* pp) { +void ShadowsHighlights::trimValues (rtengine::procparams::ProcParams* pp) +{ - highlights->trimValue(pp->sh.highlights); - shadows->trimValue(pp->sh.shadows); - lcontrast->trimValue(pp->sh.localcontrast); + highlights->trimValue(pp->sh.highlights); + shadows->trimValue(pp->sh.shadows); + lcontrast->trimValue(pp->sh.localcontrast); } diff --git a/rtgui/shadowshighlights.h b/rtgui/shadowshighlights.h index 9129d1a8c..60071e58f 100644 --- a/rtgui/shadowshighlights.h +++ b/rtgui/shadowshighlights.h @@ -7,7 +7,7 @@ * 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 @@ -23,9 +23,10 @@ #include "adjuster.h" #include "toolpanel.h" -class ShadowsHighlights : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class ShadowsHighlights : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* highlights; Adjuster* h_tonalwidth; Adjuster* shadows; @@ -36,13 +37,13 @@ class ShadowsHighlights : public ToolParamBlock, public AdjusterListener, public bool lastHQ; sigc::connection hqConn; - public: +public: ShadowsHighlights (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index e3b3a4e21..4f46dfd03 100644 --- a/rtgui/sharpenedge.cc +++ b/rtgui/sharpenedge.cc @@ -26,136 +26,156 @@ using namespace rtengine; using namespace rtengine::procparams; -SharpenEdge::SharpenEdge () : FoldableToolPanel(this, "sharpenedge", M("TP_SHARPENEDGE_LABEL"), true, true) { +SharpenEdge::SharpenEdge () : FoldableToolPanel(this, "sharpenedge", M("TP_SHARPENEDGE_LABEL"), true, true) +{ - passes = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_PASSES"),1,4,1,2)); - passes->setAdjusterListener (this); - if (passes->delay < 1000) passes->delay = 1000; - amount = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_AMOUNT"),0,100,1,50)); - amount->setAdjusterListener (this); - if (amount->delay < 1000) amount->delay = 1000; + passes = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_PASSES"), 1, 4, 1, 2)); + passes->setAdjusterListener (this); - threechannels = Gtk::manage(new Gtk::CheckButton((M("TP_SHARPENEDGE_THREE"))));// L + a + b - threechannels->set_active (false); - pack_start( *passes, Gtk::PACK_SHRINK, 0);//passes - pack_start( *amount, Gtk::PACK_SHRINK, 0);//amount - pack_start( *threechannels, Gtk::PACK_SHRINK, 0);//one or 3 channels Lab + if (passes->delay < 1000) { + passes->delay = 1000; + } - show (); + amount = Gtk::manage(new Adjuster (M("TP_SHARPENEDGE_AMOUNT"), 0, 100, 1, 50)); + amount->setAdjusterListener (this); - chanthreeconn = threechannels->signal_toggled().connect( sigc::mem_fun(*this, &SharpenEdge::chanthree_toggled) ); + if (amount->delay < 1000) { + amount->delay = 1000; + } + + threechannels = Gtk::manage(new Gtk::CheckButton((M("TP_SHARPENEDGE_THREE"))));// L + a + b + threechannels->set_active (false); + pack_start( *passes, Gtk::PACK_SHRINK, 0);//passes + pack_start( *amount, Gtk::PACK_SHRINK, 0);//amount + pack_start( *threechannels, Gtk::PACK_SHRINK, 0);//one or 3 channels Lab + + show (); + + chanthreeconn = threechannels->signal_toggled().connect( sigc::mem_fun(*this, &SharpenEdge::chanthree_toggled) ); } -void SharpenEdge::read(const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); +void SharpenEdge::read(const ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener (); - if(pedited ){ - passes->setEditedState (pedited->sharpenEdge.passes ? Edited : UnEdited); - amount->setEditedState (pedited->sharpenEdge.amount ? Edited : UnEdited); - set_inconsistent (multiImage && !pedited->sharpenEdge.enabled); - threechannels->set_inconsistent (!pedited->sharpenEdge.threechannels); - } + if(pedited ) { + passes->setEditedState (pedited->sharpenEdge.passes ? Edited : UnEdited); + amount->setEditedState (pedited->sharpenEdge.amount ? Edited : UnEdited); + set_inconsistent (multiImage && !pedited->sharpenEdge.enabled); + threechannels->set_inconsistent (!pedited->sharpenEdge.threechannels); + } - setEnabled(pp->sharpenEdge.enabled); + setEnabled(pp->sharpenEdge.enabled); - chanthreeconn.block (true); - threechannels->set_active (pp->sharpenEdge.threechannels); - chanthreeconn.block (false); - lastchanthree = pp->sharpenEdge.threechannels; + chanthreeconn.block (true); + threechannels->set_active (pp->sharpenEdge.threechannels); + chanthreeconn.block (false); + lastchanthree = pp->sharpenEdge.threechannels; - passes->setValue (pp->sharpenEdge.passes); - amount->setValue (pp->sharpenEdge.amount); - - enableListener (); + passes->setValue (pp->sharpenEdge.passes); + amount->setValue (pp->sharpenEdge.amount); + + enableListener (); } -void SharpenEdge::write( ProcParams* pp, ParamsEdited* pedited) { - pp->sharpenEdge.enabled = getEnabled(); - pp->sharpenEdge.passes = (int)passes->getValue(); - pp->sharpenEdge.amount = amount->getValue (); - pp->sharpenEdge.threechannels = threechannels->get_active (); +void SharpenEdge::write( ProcParams* pp, ParamsEdited* pedited) +{ + pp->sharpenEdge.enabled = getEnabled(); + pp->sharpenEdge.passes = (int)passes->getValue(); + pp->sharpenEdge.amount = amount->getValue (); + pp->sharpenEdge.threechannels = threechannels->get_active (); - if (pedited) { - pedited->sharpenEdge.enabled = !get_inconsistent(); - pedited->sharpenEdge.passes = passes->getEditedState (); - pedited->sharpenEdge.amount = amount->getEditedState (); - pedited->sharpenEdge.threechannels = !threechannels->get_inconsistent(); - } + if (pedited) { + pedited->sharpenEdge.enabled = !get_inconsistent(); + pedited->sharpenEdge.passes = passes->getEditedState (); + pedited->sharpenEdge.amount = amount->getEditedState (); + pedited->sharpenEdge.threechannels = !threechannels->get_inconsistent(); + } } -void SharpenEdge::enabledChanged () { - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvSharpenEdgeEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvSharpenEdgeEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvSharpenEdgeEnabled, M("GENERAL_DISABLED")); - } +void SharpenEdge::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvSharpenEdgeEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvSharpenEdgeEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvSharpenEdgeEnabled, M("GENERAL_DISABLED")); + } + } } -void SharpenEdge::chanthree_toggled () { +void SharpenEdge::chanthree_toggled () +{ - if (batchMode) { - if (threechannels->get_inconsistent()) { - threechannels->set_inconsistent (false); - chanthreeconn.block (true); - threechannels->set_active (false); - chanthreeconn.block (false); - } - else if (lastchanthree) - threechannels->set_inconsistent (true); + if (batchMode) { + if (threechannels->get_inconsistent()) { + threechannels->set_inconsistent (false); + chanthreeconn.block (true); + threechannels->set_active (false); + chanthreeconn.block (false); + } else if (lastchanthree) { + threechannels->set_inconsistent (true); + } - lastchanthree = threechannels->get_active (); - } + lastchanthree = threechannels->get_active (); + } - if (listener && getEnabled()) { - if (threechannels->get_active ()) - listener->panelChanged (EvSharpenEdgeThreechannels, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvSharpenEdgeThreechannels, M("GENERAL_DISABLED")); - } + if (listener && getEnabled()) { + if (threechannels->get_active ()) { + listener->panelChanged (EvSharpenEdgeThreechannels, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvSharpenEdgeThreechannels, M("GENERAL_DISABLED")); + } + } } -void SharpenEdge::adjusterChanged (Adjuster* a, double newval) { - if (listener && getEnabled()) { - Glib::ustring value = a->getTextValue(); - - if (a == passes ) - listener->panelChanged (EvSharpenEdgePasses, value ); - else if (a == amount) - listener->panelChanged (EvSharpenEdgeAmount, value ); - } +void SharpenEdge::adjusterChanged (Adjuster* a, double newval) +{ + if (listener && getEnabled()) { + Glib::ustring value = a->getTextValue(); + + if (a == passes ) { + listener->panelChanged (EvSharpenEdgePasses, value ); + } else if (a == amount) { + listener->panelChanged (EvSharpenEdgeAmount, value ); + } + } } -void SharpenEdge::setBatchMode(bool batchMode) { - passes->showEditedCB (); - amount->showEditedCB (); +void SharpenEdge::setBatchMode(bool batchMode) +{ + passes->showEditedCB (); + amount->showEditedCB (); } -void SharpenEdge::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) { - passes->setDefault (defParams->sharpenEdge.passes); - amount->setDefault (defParams->sharpenEdge.amount); +void SharpenEdge::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) +{ + passes->setDefault (defParams->sharpenEdge.passes); + amount->setDefault (defParams->sharpenEdge.amount); - if (pedited) { - passes->setDefaultEditedState (pedited->sharpenEdge.passes ? Edited : UnEdited); - amount->setDefaultEditedState (pedited->sharpenEdge.amount ? Edited : UnEdited); - - } else { - passes->setDefaultEditedState (Irrelevant); - amount->setDefaultEditedState (Irrelevant); - - } + if (pedited) { + passes->setDefaultEditedState (pedited->sharpenEdge.passes ? Edited : UnEdited); + amount->setDefaultEditedState (pedited->sharpenEdge.amount ? Edited : UnEdited); + + } else { + passes->setDefaultEditedState (Irrelevant); + amount->setDefaultEditedState (Irrelevant); + + } } -void SharpenEdge::setAdjusterBehavior (bool amountadd, bool passadd) { - amount->setAddMode (amountadd); - passes->setAddMode (passadd); +void SharpenEdge::setAdjusterBehavior (bool amountadd, bool passadd) +{ + amount->setAddMode (amountadd); + passes->setAddMode (passadd); } -void SharpenEdge::trimValues (ProcParams* pp) { - amount->trimValue (pp->sharpenEdge.amount); - passes->trimValue (pp->sharpenEdge.passes); +void SharpenEdge::trimValues (ProcParams* pp) +{ + amount->trimValue (pp->sharpenEdge.amount); + passes->trimValue (pp->sharpenEdge.passes); } diff --git a/rtgui/sharpenedge.h b/rtgui/sharpenedge.h index 30856a5ff..5c8730038 100644 --- a/rtgui/sharpenedge.h +++ b/rtgui/sharpenedge.h @@ -7,7 +7,7 @@ * 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 @@ -28,31 +28,32 @@ #include "adjuster.h" #include "toolpanel.h" -class SharpenEdge : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class SharpenEdge : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - Adjuster* passes; - Adjuster* amount; - Gtk::CheckButton* threechannels; + Adjuster* passes; + Adjuster* amount; + Gtk::CheckButton* threechannels; - sigc::connection chanthreeconn; - bool lastchanthree; + sigc::connection chanthreeconn; + bool lastchanthree; public: - SharpenEdge (); + SharpenEdge (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void trimValues (rtengine::procparams::ProcParams* pp); - void setAdjusterBehavior (bool amountadd, bool passadd); - void adjusterChanged (Adjuster* a, double newval); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void trimValues (rtengine::procparams::ProcParams* pp); + void setAdjusterBehavior (bool amountadd, bool passadd); + void adjusterChanged (Adjuster* a, double newval); void enabledChanged (); - void chanthree_toggled (); + void chanthree_toggled (); }; diff --git a/rtgui/sharpening.cc b/rtgui/sharpening.cc index 289fa0fca..b312f18b5 100644 --- a/rtgui/sharpening.cc +++ b/rtgui/sharpening.cc @@ -7,7 +7,7 @@ * 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 @@ -22,108 +22,109 @@ using namespace rtengine; using namespace rtengine::procparams; -Sharpening::Sharpening () : FoldableToolPanel(this,"sharpening", M("TP_SHARPENING_LABEL"), true, true) { +Sharpening::Sharpening () : FoldableToolPanel(this, "sharpening", M("TP_SHARPENING_LABEL"), true, true) +{ - std::vector milestones; - milestones.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) ); - milestones.push_back( GradientMilestone(1.0, 1.0, 1.0, 1.0) ); + std::vector milestones; + milestones.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) ); + milestones.push_back( GradientMilestone(1.0, 1.0, 1.0, 1.0) ); - setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); - Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); - hb->set_border_width (4); - hb->show (); - Gtk::Label* ml = Gtk::manage (new Gtk::Label (M("TP_SHARPENING_METHOD")+":")); - ml->show (); - method = Gtk::manage (new MyComboBoxText ()); - method->append_text (M("TP_SHARPENING_USM")); - method->append_text (M("TP_SHARPENING_RLD")); - method->show (); - hb->pack_start(*ml, Gtk::PACK_SHRINK, 4); - hb->pack_start(*method); - pack_start (*hb); - - rld = new Gtk::VBox (); - dradius = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.5, 2.5, 0.01, 0.75)); - damount = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_AMOUNT"), 0.0, 100, 1, 75)); - ddamping = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_DAMPING"), 0, 100, 1, 20)); - diter = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_ITERATIONS"), 5, 100, 1, 30)); - rld->pack_start (*dradius); - rld->pack_start (*damount); - rld->pack_start (*ddamping); - rld->pack_start (*diter); - dradius->show (); - damount->show (); - ddamping->show (); - diter->show (); - rld->show (); - - usm = new Gtk::VBox (); - usm->show (); + Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); + hb->set_border_width (4); + hb->show (); + Gtk::Label* ml = Gtk::manage (new Gtk::Label (M("TP_SHARPENING_METHOD") + ":")); + ml->show (); + method = Gtk::manage (new MyComboBoxText ()); + method->append_text (M("TP_SHARPENING_USM")); + method->append_text (M("TP_SHARPENING_RLD")); + method->show (); + hb->pack_start(*ml, Gtk::PACK_SHRINK, 4); + hb->pack_start(*method); + pack_start (*hb); - - Gtk::HSeparator *hsep6a = Gtk::manage (new Gtk::HSeparator()); - amount = Gtk::manage (new Adjuster (M("TP_SHARPENING_AMOUNT"), 1, 1000, 1, 200)); - radius = Gtk::manage (new Adjuster (M("TP_SHARPENING_RADIUS"), 0.3, 3, 0.01, 0.5)); - threshold = Gtk::manage (new ThresholdAdjuster (M("TP_SHARPENING_THRESHOLD"), 0., 2000., 20., 80., 2000., 1200., 0, false)); - threshold->setAdjusterListener (this); - threshold->setBgGradient(milestones); - pack_start(*hsep6a, Gtk::PACK_SHRINK, 2); + rld = new Gtk::VBox (); + dradius = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.5, 2.5, 0.01, 0.75)); + damount = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_AMOUNT"), 0.0, 100, 1, 75)); + ddamping = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_DAMPING"), 0, 100, 1, 20)); + diter = Gtk::manage (new Adjuster (M("TP_SHARPENING_RLD_ITERATIONS"), 5, 100, 1, 30)); + rld->pack_start (*dradius); + rld->pack_start (*damount); + rld->pack_start (*ddamping); + rld->pack_start (*diter); + dradius->show (); + damount->show (); + ddamping->show (); + diter->show (); + rld->show (); - pack_start (*usm); - - usm->pack_start(*radius); - usm->pack_start(*amount); - usm->pack_start(*threshold); - hsep6a->show (); - radius->show (); - amount->show (); - threshold->show (); + usm = new Gtk::VBox (); + usm->show (); - Gtk::HSeparator *hsep6 = Gtk::manage (new Gtk::HSeparator()); - edgesonly = Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENING_ONLYEDGES"))); - edgesonly->set_active (false); - edgebox = new Gtk::VBox (); - eradius = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.5, 2.5, 0.1, 1.9)); - etolerance = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDTOLERANCE"), 10, 10000, 100, 1000)); - usm->pack_start(*hsep6, Gtk::PACK_SHRINK, 2); - usm->pack_start(*edgesonly); - edgebox->pack_start(*eradius); - edgebox->pack_start(*etolerance); - edgebox->show (); - edgebin = Gtk::manage (new Gtk::VBox ()); - usm->pack_start (*edgebin); - edgebin->show (); - hsep6->show(); - edgesonly->show(); - eradius->show(); - etolerance->show(); - Gtk::HSeparator *hsep6b = Gtk::manage (new Gtk::HSeparator()); - halocontrol = Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENING_HALOCONTROL"))); - halocontrol->set_active (false); - hcbox = new Gtk::VBox (); - hcamount = Gtk::manage (new Adjuster (M("TP_SHARPENING_HCAMOUNT"), 1, 100, 1, 75)); - usm->pack_start(*hsep6b, Gtk::PACK_SHRINK, 2); - usm->pack_start(*halocontrol); - hcbox->pack_start(*hcamount); - hcbox->show (); - hcbin = Gtk::manage (new Gtk::VBox ()); - usm->pack_start (*hcbin); - hcbin->show (); - hsep6b->show (); - halocontrol->show (); - hcamount->show (); + Gtk::HSeparator *hsep6a = Gtk::manage (new Gtk::HSeparator()); + amount = Gtk::manage (new Adjuster (M("TP_SHARPENING_AMOUNT"), 1, 1000, 1, 200)); + radius = Gtk::manage (new Adjuster (M("TP_SHARPENING_RADIUS"), 0.3, 3, 0.01, 0.5)); + threshold = Gtk::manage (new ThresholdAdjuster (M("TP_SHARPENING_THRESHOLD"), 0., 2000., 20., 80., 2000., 1200., 0, false)); + threshold->setAdjusterListener (this); + threshold->setBgGradient(milestones); + pack_start(*hsep6a, Gtk::PACK_SHRINK, 2); + + pack_start (*usm); + + usm->pack_start(*radius); + usm->pack_start(*amount); + usm->pack_start(*threshold); + hsep6a->show (); + radius->show (); + amount->show (); + threshold->show (); + + Gtk::HSeparator *hsep6 = Gtk::manage (new Gtk::HSeparator()); + edgesonly = Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENING_ONLYEDGES"))); + edgesonly->set_active (false); + edgebox = new Gtk::VBox (); + eradius = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDRADIUS"), 0.5, 2.5, 0.1, 1.9)); + etolerance = Gtk::manage (new Adjuster (M("TP_SHARPENING_EDTOLERANCE"), 10, 10000, 100, 1000)); + usm->pack_start(*hsep6, Gtk::PACK_SHRINK, 2); + usm->pack_start(*edgesonly); + edgebox->pack_start(*eradius); + edgebox->pack_start(*etolerance); + edgebox->show (); + edgebin = Gtk::manage (new Gtk::VBox ()); + usm->pack_start (*edgebin); + edgebin->show (); + hsep6->show(); + edgesonly->show(); + eradius->show(); + etolerance->show(); + + Gtk::HSeparator *hsep6b = Gtk::manage (new Gtk::HSeparator()); + halocontrol = Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENING_HALOCONTROL"))); + halocontrol->set_active (false); + hcbox = new Gtk::VBox (); + hcamount = Gtk::manage (new Adjuster (M("TP_SHARPENING_HCAMOUNT"), 1, 100, 1, 75)); + usm->pack_start(*hsep6b, Gtk::PACK_SHRINK, 2); + usm->pack_start(*halocontrol); + hcbox->pack_start(*hcamount); + hcbox->show (); + hcbin = Gtk::manage (new Gtk::VBox ()); + usm->pack_start (*hcbin); + hcbin->show (); + hsep6b->show (); + halocontrol->show (); + hcamount->show (); dradius->setAdjusterListener (this); damount->setAdjusterListener (this); ddamping->setAdjusterListener (this); diter->setAdjusterListener (this); radius->setAdjusterListener (this); - amount->setAdjusterListener (this); - eradius->setAdjusterListener (this); - etolerance->setAdjusterListener (this); - hcamount->setAdjusterListener (this); + amount->setAdjusterListener (this); + eradius->setAdjusterListener (this); + etolerance->setAdjusterListener (this); + hcamount->setAdjusterListener (this); edgebox->reference (); hcbox->reference (); @@ -135,7 +136,8 @@ Sharpening::Sharpening () : FoldableToolPanel(this,"sharpening", M("TP_SHARPENIN method->signal_changed().connect( sigc::mem_fun(*this, &Sharpening::method_changed) ); } -Sharpening::~Sharpening () { +Sharpening::~Sharpening () +{ delete usm; delete rld; @@ -144,37 +146,38 @@ Sharpening::~Sharpening () { } -void Sharpening::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Sharpening::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); if (pedited) { - amount->setEditedState (pedited->sharpening.amount ? Edited : UnEdited); - radius->setEditedState (pedited->sharpening.radius ? Edited : UnEdited); - threshold->setEditedState (pedited->sharpening.threshold ? Edited : UnEdited); - eradius->setEditedState (pedited->sharpening.edges_radius ? Edited : UnEdited); - etolerance->setEditedState (pedited->sharpening.edges_tolerance ? Edited : UnEdited); - hcamount->setEditedState (pedited->sharpening.halocontrol_amount ? Edited : UnEdited); - damount->setEditedState (pedited->sharpening.deconvamount ? Edited : UnEdited); - dradius->setEditedState (pedited->sharpening.deconvradius ? Edited : UnEdited); - diter->setEditedState (pedited->sharpening.deconviter ? Edited : UnEdited); - ddamping->setEditedState (pedited->sharpening.deconvdamping ? Edited : UnEdited); + amount->setEditedState (pedited->sharpening.amount ? Edited : UnEdited); + radius->setEditedState (pedited->sharpening.radius ? Edited : UnEdited); + threshold->setEditedState (pedited->sharpening.threshold ? Edited : UnEdited); + eradius->setEditedState (pedited->sharpening.edges_radius ? Edited : UnEdited); + etolerance->setEditedState (pedited->sharpening.edges_tolerance ? Edited : UnEdited); + hcamount->setEditedState (pedited->sharpening.halocontrol_amount ? Edited : UnEdited); + damount->setEditedState (pedited->sharpening.deconvamount ? Edited : UnEdited); + dradius->setEditedState (pedited->sharpening.deconvradius ? Edited : UnEdited); + diter->setEditedState (pedited->sharpening.deconviter ? Edited : UnEdited); + ddamping->setEditedState (pedited->sharpening.deconvdamping ? Edited : UnEdited); - halocontrol->set_inconsistent (multiImage && !pedited->sharpening.halocontrol); - edgesonly->set_inconsistent (multiImage && !pedited->sharpening.edgesonly); - set_inconsistent (multiImage && !pedited->sharpening.enabled); - } + halocontrol->set_inconsistent (multiImage && !pedited->sharpening.halocontrol); + edgesonly->set_inconsistent (multiImage && !pedited->sharpening.edgesonly); + set_inconsistent (multiImage && !pedited->sharpening.enabled); + } setEnabled (pp->sharpening.enabled); - + eonlyConn.block (true); edgesonly->set_active (pp->sharpening.edgesonly); - eonlyConn.block (false); + eonlyConn.block (false); lastEdgesOnly = pp->sharpening.edgesonly; - + hcConn.block (true); halocontrol->set_active (pp->sharpening.halocontrol); - hcConn.block (false); + hcConn.block (false); lastHaloControl = pp->sharpening.halocontrol; amount->setValue (pp->sharpening.amount); @@ -188,28 +191,35 @@ void Sharpening::read (const ProcParams* pp, const ParamsEdited* pedited) { damount->setValue (pp->sharpening.deconvamount); diter->setValue (pp->sharpening.deconviter); ddamping->setValue (pp->sharpening.deconvdamping); - - if (!batchMode) { - removeIfThere (edgebin, edgebox, false); - if (edgesonly->get_active ()) - edgebin->pack_start (*edgebox); - removeIfThere (hcbin, hcbox, false); - if (halocontrol->get_active ()) - hcbin->pack_start (*hcbox); + if (!batchMode) { + removeIfThere (edgebin, edgebox, false); + + if (edgesonly->get_active ()) { + edgebin->pack_start (*edgebox); + } + + removeIfThere (hcbin, hcbox, false); + + if (halocontrol->get_active ()) { + hcbin->pack_start (*hcbox); + } + + } + + if (pedited && !pedited->sharpening.method) { + method->set_active (2); + } else if (pp->sharpening.method == "usm") { + method->set_active (0); + } else if (pp->sharpening.method == "rld") { + method->set_active (1); + } - } - if (pedited && !pedited->sharpening.method) - method->set_active (2); - else if (pp->sharpening.method=="usm") - method->set_active (0); - else if (pp->sharpening.method=="rld") - method->set_active (1); - enableListener (); } -void Sharpening::write (ProcParams* pp, ParamsEdited* pedited) { +void Sharpening::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->sharpening.amount = (int)amount->getValue(); pp->sharpening.enabled = getEnabled (); @@ -224,31 +234,33 @@ void Sharpening::write (ProcParams* pp, ParamsEdited* pedited) { pp->sharpening.deconviter = (int)diter->getValue (); pp->sharpening.deconvamount = (int)damount->getValue (); pp->sharpening.deconvdamping = (int)ddamping->getValue (); - - if (method->get_active_row_number()==0) + + if (method->get_active_row_number() == 0) { pp->sharpening.method = "usm"; - else if (method->get_active_row_number()==1) + } else if (method->get_active_row_number() == 1) { pp->sharpening.method = "rld"; + } if (pedited) { - pedited->sharpening.amount = amount->getEditedState (); - pedited->sharpening.radius = radius->getEditedState (); - pedited->sharpening.threshold = threshold->getEditedState (); - pedited->sharpening.edges_radius = eradius->getEditedState (); - pedited->sharpening.edges_tolerance = etolerance->getEditedState (); - pedited->sharpening.halocontrol_amount = hcamount->getEditedState (); - pedited->sharpening.deconvamount = damount->getEditedState (); - pedited->sharpening.deconvradius = dradius->getEditedState (); - pedited->sharpening.deconviter = diter->getEditedState (); - pedited->sharpening.deconvdamping = ddamping->getEditedState (); - pedited->sharpening.method = method->get_active_row_number()!=2; - pedited->sharpening.halocontrol = !halocontrol->get_inconsistent(); - pedited->sharpening.edgesonly = !edgesonly->get_inconsistent(); - pedited->sharpening.enabled = !get_inconsistent(); + pedited->sharpening.amount = amount->getEditedState (); + pedited->sharpening.radius = radius->getEditedState (); + pedited->sharpening.threshold = threshold->getEditedState (); + pedited->sharpening.edges_radius = eradius->getEditedState (); + pedited->sharpening.edges_tolerance = etolerance->getEditedState (); + pedited->sharpening.halocontrol_amount = hcamount->getEditedState (); + pedited->sharpening.deconvamount = damount->getEditedState (); + pedited->sharpening.deconvradius = dradius->getEditedState (); + pedited->sharpening.deconviter = diter->getEditedState (); + pedited->sharpening.deconvdamping = ddamping->getEditedState (); + pedited->sharpening.method = method->get_active_row_number() != 2; + pedited->sharpening.halocontrol = !halocontrol->get_inconsistent(); + pedited->sharpening.edgesonly = !edgesonly->get_inconsistent(); + pedited->sharpening.enabled = !get_inconsistent(); } } -void Sharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void Sharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ amount->setDefault (defParams->sharpening.amount); radius->setDefault (defParams->sharpening.radius); @@ -262,85 +274,92 @@ void Sharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* p ddamping->setDefault (defParams->sharpening.deconvdamping); if (pedited) { - amount->setDefaultEditedState (pedited->sharpening.amount ? Edited : UnEdited); - radius->setDefaultEditedState (pedited->sharpening.radius ? Edited : UnEdited); - threshold->setDefaultEditedState (pedited->sharpening.threshold ? Edited : UnEdited); - eradius->setDefaultEditedState (pedited->sharpening.edges_radius ? Edited : UnEdited); - etolerance->setDefaultEditedState (pedited->sharpening.edges_tolerance ? Edited : UnEdited); - hcamount->setDefaultEditedState (pedited->sharpening.halocontrol_amount ? Edited : UnEdited); - damount->setDefaultEditedState (pedited->sharpening.deconvamount ? Edited : UnEdited); - dradius->setDefaultEditedState (pedited->sharpening.deconvradius ? Edited : UnEdited); - diter->setDefaultEditedState (pedited->sharpening.deconviter ? Edited : UnEdited); - ddamping->setDefaultEditedState (pedited->sharpening.deconvdamping ? Edited : UnEdited); - } - else { - amount->setDefaultEditedState (Irrelevant); - radius->setDefaultEditedState (Irrelevant); - threshold->setDefaultEditedState (Irrelevant); - eradius->setDefaultEditedState (Irrelevant); - etolerance->setDefaultEditedState (Irrelevant); - hcamount->setDefaultEditedState (Irrelevant); - damount->setDefaultEditedState (Irrelevant); - dradius->setDefaultEditedState (Irrelevant); - diter->setDefaultEditedState (Irrelevant); - ddamping->setDefaultEditedState (Irrelevant); + amount->setDefaultEditedState (pedited->sharpening.amount ? Edited : UnEdited); + radius->setDefaultEditedState (pedited->sharpening.radius ? Edited : UnEdited); + threshold->setDefaultEditedState (pedited->sharpening.threshold ? Edited : UnEdited); + eradius->setDefaultEditedState (pedited->sharpening.edges_radius ? Edited : UnEdited); + etolerance->setDefaultEditedState (pedited->sharpening.edges_tolerance ? Edited : UnEdited); + hcamount->setDefaultEditedState (pedited->sharpening.halocontrol_amount ? Edited : UnEdited); + damount->setDefaultEditedState (pedited->sharpening.deconvamount ? Edited : UnEdited); + dradius->setDefaultEditedState (pedited->sharpening.deconvradius ? Edited : UnEdited); + diter->setDefaultEditedState (pedited->sharpening.deconviter ? Edited : UnEdited); + ddamping->setDefaultEditedState (pedited->sharpening.deconvdamping ? Edited : UnEdited); + } else { + amount->setDefaultEditedState (Irrelevant); + radius->setDefaultEditedState (Irrelevant); + threshold->setDefaultEditedState (Irrelevant); + eradius->setDefaultEditedState (Irrelevant); + etolerance->setDefaultEditedState (Irrelevant); + hcamount->setDefaultEditedState (Irrelevant); + damount->setDefaultEditedState (Irrelevant); + dradius->setDefaultEditedState (Irrelevant); + diter->setDefaultEditedState (Irrelevant); + ddamping->setDefaultEditedState (Irrelevant); } } -void Sharpening::adjusterChanged (Adjuster* a, double newval) { +void Sharpening::adjusterChanged (Adjuster* a, double newval) +{ - if (listener && (multiImage||getEnabled()) ) { + if (listener && (multiImage || getEnabled()) ) { Glib::ustring costr; - if (a==radius || a==dradius) + + if (a == radius || a == dradius) { costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); - else if (a==eradius) + } else if (a == eradius) { costr = Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue()); - else + } else { costr = Glib::ustring::format ((int)a->getValue()); - - if (a==amount) + } + + if (a == amount) { listener->panelChanged (EvShrAmount, costr); - else if (a==radius) + } else if (a == radius) { listener->panelChanged (EvShrRadius, costr); - else if (a==eradius) + } else if (a == eradius) { listener->panelChanged (EvShrEdgeRadius, costr); - else if (a==etolerance) + } else if (a == etolerance) { listener->panelChanged (EvShrEdgeTolerance, costr); - else if (a==hcamount) + } else if (a == hcamount) { listener->panelChanged (EvShrHaloAmount, costr); - else if (a==dradius) + } else if (a == dradius) { listener->panelChanged (EvShrDRadius, costr); - else if (a==damount) + } else if (a == damount) { listener->panelChanged (EvShrDAmount, costr); - else if (a==ddamping) + } else if (a == ddamping) { listener->panelChanged (EvShrDDamping, costr); - else if (a==diter) + } else if (a == diter) { listener->panelChanged (EvShrDIterations, costr); + } } } -void Sharpening::adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) { - if (listener && (multiImage||getEnabled()) ) { - if(a==threshold) { +void Sharpening::adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) +{ + if (listener && (multiImage || getEnabled()) ) { + if(a == threshold) { listener->panelChanged (EvShrThresh, threshold->getHistoryString()); } } } -void Sharpening::enabledChanged () { +void Sharpening::enabledChanged () +{ if (listener) { - if (get_inconsistent()) + if (get_inconsistent()) { listener->panelChanged (EvShrEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) + } else if (getEnabled()) { listener->panelChanged (EvShrEnabled, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvShrEnabled, M("GENERAL_DISABLED")); + } } } -void Sharpening::edgesonly_toggled () { +void Sharpening::edgesonly_toggled () +{ if (multiImage) { if (edgesonly->get_inconsistent()) { @@ -348,30 +367,34 @@ void Sharpening::edgesonly_toggled () { eonlyConn.block (true); edgesonly->set_active (false); eonlyConn.block (false); - } - else if (lastEdgesOnly) + } else if (lastEdgesOnly) { edgesonly->set_inconsistent (true); + } lastEdgesOnly = edgesonly->get_active (); } if (!batchMode) { removeIfThere (edgebin, edgebox, false); - if (edgesonly->get_active ()) + + if (edgesonly->get_active ()) { edgebin->pack_start (*edgebox); + } } - if (listener && (multiImage||getEnabled()) ) { - if (edgesonly->get_inconsistent()) + if (listener && (multiImage || getEnabled()) ) { + if (edgesonly->get_inconsistent()) { listener->panelChanged (EvShrEdgeOnly, M("GENERAL_INITIALVALUES")); - else if (edgesonly->get_active ()) + } else if (edgesonly->get_active ()) { listener->panelChanged (EvShrEdgeOnly, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvShrEdgeOnly, M("GENERAL_DISABLED")); + } } } -void Sharpening::halocontrol_toggled () { +void Sharpening::halocontrol_toggled () +{ if (multiImage) { if (halocontrol->get_inconsistent()) { @@ -379,45 +402,52 @@ void Sharpening::halocontrol_toggled () { hcConn.block (true); halocontrol->set_active (false); hcConn.block (false); - } - else if (lastHaloControl) + } else if (lastHaloControl) { halocontrol->set_inconsistent (true); + } lastHaloControl = halocontrol->get_active (); } if (!batchMode) { removeIfThere (hcbin, hcbox, false); - if (halocontrol->get_active ()) + + if (halocontrol->get_active ()) { hcbin->pack_start (*hcbox); + } } - if (listener && (multiImage||getEnabled()) ) { - if (halocontrol->get_inconsistent()) + if (listener && (multiImage || getEnabled()) ) { + if (halocontrol->get_inconsistent()) { listener->panelChanged (EvShrHaloControl, M("GENERAL_INITIALVALUES")); - else if (halocontrol->get_active ()) + } else if (halocontrol->get_active ()) { listener->panelChanged (EvShrHaloControl, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvShrHaloControl, M("GENERAL_DISABLED")); + } } } -void Sharpening::method_changed () { +void Sharpening::method_changed () +{ removeIfThere (this, usm, false); removeIfThere (this, rld, false); - if (method->get_active_row_number()==0) + if (method->get_active_row_number() == 0) { pack_start (*usm); - else if (method->get_active_row_number()==1) + } else if (method->get_active_row_number() == 1) { pack_start (*rld); + } - if (listener && (multiImage||getEnabled()) ) + if (listener && (multiImage || getEnabled()) ) { listener->panelChanged (EvShrMethod, method->get_active_text ()); - + } + } -void Sharpening::setBatchMode (bool batchMode) { +void Sharpening::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); @@ -439,13 +469,15 @@ void Sharpening::setBatchMode (bool batchMode) { method->append_text (M("GENERAL_UNCHANGED")); } -void Sharpening::setAdjusterBehavior (bool amountadd) { +void Sharpening::setAdjusterBehavior (bool amountadd) +{ amount->setAddMode(amountadd); damount->setAddMode(amountadd); } -void Sharpening::trimValues (rtengine::procparams::ProcParams* pp) { +void Sharpening::trimValues (rtengine::procparams::ProcParams* pp) +{ amount->trimValue(pp->sharpening.amount); damount->trimValue(pp->sharpening.deconvamount); diff --git a/rtgui/sharpening.h b/rtgui/sharpening.h index be2c01ad0..3020cea7f 100644 --- a/rtgui/sharpening.h +++ b/rtgui/sharpening.h @@ -7,7 +7,7 @@ * 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 @@ -24,9 +24,10 @@ #include "thresholdadjuster.h" #include "toolpanel.h" -class Sharpening : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel { +class Sharpening : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: MyComboBoxText* method; Adjuster* dradius; Adjuster* damount; @@ -52,14 +53,14 @@ class Sharpening : public ToolParamBlock, public ThresholdAdjusterListener, publ bool lastHaloControl; sigc::connection hcConn; - public: +public: Sharpening (); virtual ~Sharpening (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 5fe7b2af0..0c562a351 100644 --- a/rtgui/sharpenmicro.cc +++ b/rtgui/sharpenmicro.cc @@ -26,137 +26,159 @@ using namespace rtengine; using namespace rtengine::procparams; -SharpenMicro::SharpenMicro () : FoldableToolPanel(this, "sharpenmicro", M("TP_SHARPENMICRO_LABEL"), true, true) { +SharpenMicro::SharpenMicro () : FoldableToolPanel(this, "sharpenmicro", M("TP_SHARPENMICRO_LABEL"), true, true) +{ - setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); - amount= Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_AMOUNT"),0,100,1,20)); - amount->setAdjusterListener (this); - if (amount->delay < 1000) amount->delay = 1000; - amount->show(); - uniformity= Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_UNIFORMITY"),0,100,10,50)); + amount = Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_AMOUNT"), 0, 100, 1, 20)); + amount->setAdjusterListener (this); - uniformity->setAdjusterListener (this); - if (uniformity->delay < 1000) uniformity->delay = 1000; - uniformity->show(); - matrix = Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENMICRO_MATRIX"))); - matrix->set_active (true); - pack_start(*matrix, Gtk::PACK_SHRINK, 0); - matrix->show (); + if (amount->delay < 1000) { + amount->delay = 1000; + } - pack_start( *amount, Gtk::PACK_SHRINK, 0); - pack_start( *uniformity, Gtk::PACK_SHRINK, 0); + amount->show(); + uniformity = Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_UNIFORMITY"), 0, 100, 10, 50)); - show (); + uniformity->setAdjusterListener (this); - matrixconn = matrix->signal_toggled().connect( sigc::mem_fun(*this, &SharpenMicro::matrix_toggled) ); + if (uniformity->delay < 1000) { + uniformity->delay = 1000; + } + + uniformity->show(); + matrix = Gtk::manage (new Gtk::CheckButton (M("TP_SHARPENMICRO_MATRIX"))); + matrix->set_active (true); + pack_start(*matrix, Gtk::PACK_SHRINK, 0); + matrix->show (); + + pack_start( *amount, Gtk::PACK_SHRINK, 0); + pack_start( *uniformity, Gtk::PACK_SHRINK, 0); + + show (); + + matrixconn = matrix->signal_toggled().connect( sigc::mem_fun(*this, &SharpenMicro::matrix_toggled) ); } -void SharpenMicro::read(const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); +void SharpenMicro::read(const ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener (); - if(pedited ){ - set_inconsistent (multiImage && !pedited->sharpenMicro.enabled); - matrix->set_inconsistent (!pedited->sharpenMicro.matrix); - amount->setEditedState (pedited->sharpenMicro.amount ? Edited : UnEdited); - uniformity->setEditedState (pedited->sharpenMicro.uniformity ? Edited : UnEdited); - } + if(pedited ) { + set_inconsistent (multiImage && !pedited->sharpenMicro.enabled); + matrix->set_inconsistent (!pedited->sharpenMicro.matrix); + amount->setEditedState (pedited->sharpenMicro.amount ? Edited : UnEdited); + uniformity->setEditedState (pedited->sharpenMicro.uniformity ? Edited : UnEdited); + } - setEnabled(pp->sharpenMicro.enabled); + setEnabled(pp->sharpenMicro.enabled); - matrixconn.block (true); - matrix->set_active (pp->sharpenMicro.matrix); - matrixconn.block (false); - lastmatrix = pp->sharpenMicro.matrix; + matrixconn.block (true); + matrix->set_active (pp->sharpenMicro.matrix); + matrixconn.block (false); + lastmatrix = pp->sharpenMicro.matrix; - amount->setValue (pp->sharpenMicro.amount); - uniformity->setValue (pp->sharpenMicro.uniformity); + amount->setValue (pp->sharpenMicro.amount); + uniformity->setValue (pp->sharpenMicro.uniformity); - enableListener (); + enableListener (); } -void SharpenMicro::write( ProcParams* pp, ParamsEdited* pedited) { - pp->sharpenMicro.enabled = getEnabled(); - pp->sharpenMicro.matrix = matrix->get_active (); - pp->sharpenMicro.amount = amount->getValue (); - pp->sharpenMicro.uniformity = uniformity->getValue (); +void SharpenMicro::write( ProcParams* pp, ParamsEdited* pedited) +{ + pp->sharpenMicro.enabled = getEnabled(); + pp->sharpenMicro.matrix = matrix->get_active (); + pp->sharpenMicro.amount = amount->getValue (); + pp->sharpenMicro.uniformity = uniformity->getValue (); - if (pedited) { - pedited->sharpenMicro.enabled = !get_inconsistent(); - pedited->sharpenMicro.matrix = !matrix->get_inconsistent(); - pedited->sharpenMicro.amount = amount->getEditedState (); - pedited->sharpenMicro.uniformity = uniformity->getEditedState (); - } + if (pedited) { + pedited->sharpenMicro.enabled = !get_inconsistent(); + pedited->sharpenMicro.matrix = !matrix->get_inconsistent(); + pedited->sharpenMicro.amount = amount->getEditedState (); + pedited->sharpenMicro.uniformity = uniformity->getEditedState (); + } } -void SharpenMicro::enabledChanged () { +void SharpenMicro::enabledChanged () +{ - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvSharpenMicroEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvSharpenMicroEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvSharpenMicroEnabled, M("GENERAL_DISABLED")); - } + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvSharpenMicroEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvSharpenMicroEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvSharpenMicroEnabled, M("GENERAL_DISABLED")); + } + } } -void SharpenMicro::matrix_toggled () { - if (batchMode) { - if (matrix->get_inconsistent()) { - matrix->set_inconsistent (false); - matrixconn.block (true); - matrix->set_active (false); - matrixconn.block (false); - } - else if (lastmatrix) - matrix->set_inconsistent (true); +void SharpenMicro::matrix_toggled () +{ + if (batchMode) { + if (matrix->get_inconsistent()) { + matrix->set_inconsistent (false); + matrixconn.block (true); + matrix->set_active (false); + matrixconn.block (false); + } else if (lastmatrix) { + matrix->set_inconsistent (true); + } - lastmatrix = matrix->get_active (); - } + lastmatrix = matrix->get_active (); + } - if (listener && getEnabled()) { - if (matrix->get_active ()) - listener->panelChanged (EvSharpenMicroMatrix, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvSharpenMicroMatrix, M("GENERAL_DISABLED")); - } + if (listener && getEnabled()) { + if (matrix->get_active ()) { + listener->panelChanged (EvSharpenMicroMatrix, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvSharpenMicroMatrix, M("GENERAL_DISABLED")); + } + } } -void SharpenMicro::adjusterChanged (Adjuster* a, double newval) { - if (listener && getEnabled()) { - Glib::ustring value = a->getTextValue(); - if (a == amount) - listener->panelChanged (EvSharpenMicroAmount, value ); - else if (a == uniformity) - listener->panelChanged (EvSharpenMicroUniformity, value ); - } +void SharpenMicro::adjusterChanged (Adjuster* a, double newval) +{ + if (listener && getEnabled()) { + Glib::ustring value = a->getTextValue(); + + if (a == amount) { + listener->panelChanged (EvSharpenMicroAmount, value ); + } else if (a == uniformity) { + listener->panelChanged (EvSharpenMicroUniformity, value ); + } + } } -void SharpenMicro::setBatchMode(bool batchMode) { - amount->showEditedCB (); - uniformity->showEditedCB (); +void SharpenMicro::setBatchMode(bool batchMode) +{ + amount->showEditedCB (); + uniformity->showEditedCB (); } -void SharpenMicro::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) { - amount->setDefault (defParams->sharpenMicro.amount); - uniformity->setDefault (defParams->sharpenMicro.uniformity); +void SharpenMicro::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) +{ + amount->setDefault (defParams->sharpenMicro.amount); + uniformity->setDefault (defParams->sharpenMicro.uniformity); - if (pedited) { - amount->setDefaultEditedState (pedited->sharpenMicro.amount ? Edited : UnEdited); - uniformity->setDefaultEditedState (pedited->sharpenMicro.uniformity ? Edited : UnEdited); - } else { - amount->setDefaultEditedState (Irrelevant); - uniformity->setDefaultEditedState (Irrelevant); - } + if (pedited) { + amount->setDefaultEditedState (pedited->sharpenMicro.amount ? Edited : UnEdited); + uniformity->setDefaultEditedState (pedited->sharpenMicro.uniformity ? Edited : UnEdited); + } else { + amount->setDefaultEditedState (Irrelevant); + uniformity->setDefaultEditedState (Irrelevant); + } } -void SharpenMicro::setAdjusterBehavior (bool amountadd, bool uniformityadd ) { - amount->setAddMode (amountadd); - uniformity->setAddMode (uniformityadd); +void SharpenMicro::setAdjusterBehavior (bool amountadd, bool uniformityadd ) +{ + amount->setAddMode (amountadd); + uniformity->setAddMode (uniformityadd); } -void SharpenMicro::trimValues (ProcParams* pp) { - amount->trimValue (pp->sharpenMicro.amount); - uniformity->trimValue (pp->sharpenMicro.uniformity); +void SharpenMicro::trimValues (ProcParams* pp) +{ + amount->trimValue (pp->sharpenMicro.amount); + uniformity->trimValue (pp->sharpenMicro.uniformity); } diff --git a/rtgui/sharpenmicro.h b/rtgui/sharpenmicro.h index 7cf0f0384..4b45dd5c4 100644 --- a/rtgui/sharpenmicro.h +++ b/rtgui/sharpenmicro.h @@ -7,7 +7,7 @@ * 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 @@ -28,32 +28,33 @@ #include "adjuster.h" #include "toolpanel.h" -class SharpenMicro : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class SharpenMicro : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - Gtk::CheckButton* matrix; - Adjuster* amount; - Adjuster* uniformity; + Gtk::CheckButton* matrix; + Adjuster* amount; + Adjuster* uniformity; - sigc::connection matrixconn; - bool lastmatrix; + sigc::connection matrixconn; + bool lastmatrix; public: - SharpenMicro (); + SharpenMicro (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void trimValues (rtengine::procparams::ProcParams* pp); - void setAdjusterBehavior (bool amountadd, bool uniformityadd ); - void adjusterChanged (Adjuster* a, double newval); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void trimValues (rtengine::procparams::ProcParams* pp); + void setAdjusterBehavior (bool amountadd, bool uniformityadd ); + void adjusterChanged (Adjuster* a, double newval); void enabledChanged (); - void matrix_toggled (); - + void matrix_toggled (); + }; diff --git a/rtgui/shcselector.cc b/rtgui/shcselector.cc index 6b59db316..461eb118f 100644 --- a/rtgui/shcselector.cc +++ b/rtgui/shcselector.cc @@ -7,7 +7,7 @@ * 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 @@ -21,234 +21,276 @@ #include "multilangmgr.h" #include "mycurve.h" -SHCSelector::SHCSelector() : ColoredBar(RTO_Left2Right), movingPosition(-1), cl(NULL) { +SHCSelector::SHCSelector() : ColoredBar(RTO_Left2Right), movingPosition(-1), cl(NULL) +{ positions[0] = defaults[0] = 0.25; positions[1] = defaults[1] = 0.5; positions[2] = defaults[2] = 0.75; - leftMargin = RADIUS; - rightMargin = RADIUS; + leftMargin = RADIUS; + rightMargin = RADIUS; // TODO: This is a hack :) ; change this name to a specific one and create a new entry in all gtkrc theme files - set_name("ThresholdSelector"); - set_can_focus(false); - set_size_request (-1, 12); - set_tooltip_text(M("SHCSELECTOR_TOOLTIP")); + set_name("ThresholdSelector"); + set_can_focus(false); + set_size_request (-1, 12); + set_tooltip_text(M("SHCSELECTOR_TOOLTIP")); } -void SHCSelector::setMargins(int left, int right) { - leftMargin = left; - rightMargin = right; +void SHCSelector::setMargins(int left, int right) +{ + leftMargin = left; + rightMargin = right; } -void SHCSelector::setDefaults (double spos, double cpos, double hpos) { - defaults[0] = spos; - defaults[1] = cpos; - defaults[2] = hpos; +void SHCSelector::setDefaults (double spos, double cpos, double hpos) +{ + defaults[0] = spos; + defaults[1] = cpos; + defaults[2] = hpos; } -void SHCSelector::setPositions (double spos, double cpos, double hpos) { - +void SHCSelector::setPositions (double spos, double cpos, double hpos) +{ + positions[0] = spos; positions[1] = cpos; positions[2] = hpos; - + queue_draw (); } -void SHCSelector::getPositions (double& spos, double& cpos, double& hpos) { +void SHCSelector::getPositions (double& spos, double& cpos, double& hpos) +{ spos = positions[0]; cpos = positions[1]; hpos = positions[2]; } -void SHCSelector::on_realize() { +void SHCSelector::on_realize() +{ - Gtk::DrawingArea::on_realize(); + Gtk::DrawingArea::on_realize(); - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); } -bool SHCSelector::on_expose_event(GdkEventExpose* event) { - - Gdk::Color c; +bool SHCSelector::on_expose_event(GdkEventExpose* event) +{ + + Gdk::Color c; Cairo::RefPtr cr = get_window()->create_cairo_context(); int w = get_width () - leftMargin - rightMargin; int h = get_height (); - wslider = std::max(int(h / 5), 10); - double hwslider = double(wslider)/2.; + wslider = std::max(int(h / 5), 10); + double hwslider = double(wslider) / 2.; - Gtk::StateType state = !is_sensitive() ? Gtk::STATE_INSENSITIVE : Gtk::STATE_NORMAL; - Glib::RefPtr style = get_style(); + Gtk::StateType state = !is_sensitive() ? Gtk::STATE_INSENSITIVE : Gtk::STATE_NORMAL; + Glib::RefPtr style = get_style(); // clear bg - // set the box's colors - cr->set_line_width (1.0); - cr->set_line_cap(Cairo::LINE_CAP_BUTT); - if (is_sensitive() && canGetColors()) { - // gradient background - Glib::RefPtr win = get_window(); - // this will eventually create/update the off-screen pixmap - setDrawRectangle(win, leftMargin+1, 1, w-2, int(float(h)*5.5f/7.f+0.5f)); - // that we're displaying here - ColoredBar::expose(win); - } - else { - // solid background - c = style->get_bg (state); - if (state==Gtk::STATE_INSENSITIVE) - cr->set_source_rgb (c.get_red_p()*0.96, c.get_green_p()*0.96, c.get_blue_p()*0.96); - else - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); + // set the box's colors + cr->set_line_width (1.0); + cr->set_line_cap(Cairo::LINE_CAP_BUTT); - // draw the box's background - cr->rectangle (leftMargin+1, 1, w-2, int(float(h)*5.5f/7.f+0.5f)); - cr->fill(); - } + if (is_sensitive() && canGetColors()) { + // gradient background + Glib::RefPtr win = get_window(); + // this will eventually create/update the off-screen pixmap + setDrawRectangle(win, leftMargin + 1, 1, w - 2, int(float(h) * 5.5f / 7.f + 0.5f)); + // that we're displaying here + ColoredBar::expose(win); + } else { + // solid background + c = style->get_bg (state); - // draw the box's borders - cr->set_line_width (1.); - cr->rectangle (leftMargin+0.5, 0.5, w-1, int(float(h)*5.5f/7.f+0.5f)+1); - c = style->get_bg (state); - if (state==Gtk::STATE_INSENSITIVE) - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); - else - cr->set_source_rgb (c.get_red_p()*0.7, c.get_green_p()*0.7, c.get_blue_p()*0.7); - cr->stroke (); + if (state == Gtk::STATE_INSENSITIVE) { + cr->set_source_rgb (c.get_red_p() * 0.96, c.get_green_p() * 0.96, c.get_blue_p() * 0.96); + } else { + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } + + // draw the box's background + cr->rectangle (leftMargin + 1, 1, w - 2, int(float(h) * 5.5f / 7.f + 0.5f)); + cr->fill(); + } + + // draw the box's borders + cr->set_line_width (1.); + cr->rectangle (leftMargin + 0.5, 0.5, w - 1, int(float(h) * 5.5f / 7.f + 0.5f) + 1); + c = style->get_bg (state); + + if (state == Gtk::STATE_INSENSITIVE) { + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } else { + cr->set_source_rgb (c.get_red_p() * 0.7, c.get_green_p() * 0.7, c.get_blue_p() * 0.7); + } + + cr->stroke (); // draw sliders //cr->set_line_width (1.0); - for (int i=0; i<3; i++) { - cr->move_to (leftMargin+0.5+(w-1)*positions[i]+hwslider, double(h)-0.5); - cr->rel_line_to (0., double(-h/3)); - cr->rel_line_to (-hwslider, double(-h/3)); - cr->rel_line_to (-hwslider, double(h/3)); - cr->rel_line_to (0., double(h/3)); + for (int i = 0; i < 3; i++) { + cr->move_to (leftMargin + 0.5 + (w - 1)*positions[i] + hwslider, double(h) - 0.5); + cr->rel_line_to (0., double(-h / 3)); + cr->rel_line_to (-hwslider, double(-h / 3)); + cr->rel_line_to (-hwslider, double(h / 3)); + cr->rel_line_to (0., double(h / 3)); cr->close_path(); - // normal - c = style->get_bg (is_sensitive() ? Gtk::STATE_ACTIVE : Gtk::STATE_INSENSITIVE); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->fill_preserve (); - c = style->get_bg (state); - if (state==Gtk::STATE_INSENSITIVE) - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); - else - cr->set_source_rgb (c.get_red_p()*0.7, c.get_green_p()*0.7, c.get_blue_p()*0.7); - cr->stroke (); + // normal + c = style->get_bg (is_sensitive() ? Gtk::STATE_ACTIVE : Gtk::STATE_INSENSITIVE); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->fill_preserve (); + c = style->get_bg (state); + + if (state == Gtk::STATE_INSENSITIVE) { + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } else { + cr->set_source_rgb (c.get_red_p() * 0.7, c.get_green_p() * 0.7, c.get_blue_p() * 0.7); + } + + cr->stroke (); } - + // draw text for the slider that is being moved Glib::RefPtr context = get_pango_context () ; cr->set_line_width (0.5); + if (movingPosition >= 0) { int i = movingPosition; int offset; int layout_width, layout_height; Glib::RefPtr layout = create_pango_layout(Glib::ustring::format(std::setprecision(2), positions[i])); layout->get_pixel_size(layout_width, layout_height); - offset = positions[i] > 0.5 ? -layout_width-1-hwslider : 1+hwslider; - c = style->get_bg (state); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + offset = positions[i] > 0.5 ? -layout_width - 1 - hwslider : 1 + hwslider; + c = style->get_bg (state); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->set_line_width(3.); - cr->set_line_join(Cairo::LINE_JOIN_ROUND); - cr->set_line_cap(Cairo::LINE_CAP_ROUND); + cr->set_line_width(3.); + cr->set_line_join(Cairo::LINE_JOIN_ROUND); + cr->set_line_cap(Cairo::LINE_CAP_ROUND); - cr->move_to (leftMargin+w*positions[i]+offset, 0.); - layout->add_to_cairo_context (cr); + cr->move_to (leftMargin + w * positions[i] + offset, 0.); + layout->add_to_cairo_context (cr); cr->stroke_preserve(); - c = style->get_fg (Gtk::STATE_PRELIGHT); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + c = style->get_fg (Gtk::STATE_PRELIGHT); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); cr->fill (); } + return true; } -bool SHCSelector::on_button_press_event (GdkEventButton* event) { - +bool SHCSelector::on_button_press_event (GdkEventButton* event) +{ + // check if a slider is under the cursor - double w = double(get_width ()-leftMargin-rightMargin); + double w = double(get_width () - leftMargin - rightMargin); movingPosition = -1; - for (int i=0; i<3; i++) - if (event->x > double(leftMargin)+w*positions[i]-wslider/2. && event->x < double(leftMargin)+w*positions[i]+wslider/2) { + + for (int i = 0; i < 3; i++) + if (event->x > double(leftMargin) + w * positions[i] - wslider / 2. && event->x < double(leftMargin) + w * positions[i] + wslider / 2) { movingPosition = i; tmpX = event->x; tmpPos = positions[i]; break; } + queue_draw (); return true; } -bool SHCSelector::on_button_release_event (GdkEventButton* event) { - +bool SHCSelector::on_button_release_event (GdkEventButton* event) +{ + if (event->button == 1) { - if (movingPosition >= 0) { - movingPosition = -1; - queue_draw (); - } - } - else if (event->button == 3) { - if (movingPosition >= 0) - movingPosition = -1; - // right mouse button reset the selector to the stored default values - if (reset()) { - // rest has modified the values - if (cl) + if (movingPosition >= 0) { + movingPosition = -1; + queue_draw (); + } + } else if (event->button == 3) { + if (movingPosition >= 0) { + movingPosition = -1; + } + + // right mouse button reset the selector to the stored default values + if (reset()) { + // rest has modified the values + if (cl) { cl->shcChanged (); - } + } + } } + return true; } -bool SHCSelector::on_motion_notify_event (GdkEventMotion* event) { - +bool SHCSelector::on_motion_notify_event (GdkEventMotion* event) +{ + if (movingPosition >= 0) { int w = get_width (); positions[movingPosition] = tmpPos + (event->x - tmpX) / w; - if (positions[movingPosition] < 0) - positions[movingPosition] = 0.0; - if (movingPosition > 0 && positions[movingPosition] < positions[movingPosition-1]+wslider/w) - positions[movingPosition] = positions[movingPosition-1]+wslider/w; - if (positions[movingPosition] > 1.0) - positions[movingPosition] = 1.0; - if (movingPosition < 2 && positions[movingPosition] > positions[movingPosition+1]-wslider/w) - positions[movingPosition] = positions[movingPosition+1]-wslider/w; - if (cl) + if (positions[movingPosition] < 0) { + positions[movingPosition] = 0.0; + } + + if (movingPosition > 0 && positions[movingPosition] < positions[movingPosition - 1] + wslider / w) { + positions[movingPosition] = positions[movingPosition - 1] + wslider / w; + } + + if (positions[movingPosition] > 1.0) { + positions[movingPosition] = 1.0; + } + + if (movingPosition < 2 && positions[movingPosition] > positions[movingPosition + 1] - wslider / w) { + positions[movingPosition] = positions[movingPosition + 1] - wslider / w; + } + + if (cl) { cl->shcChanged (); + } + queue_draw (); } + return true; } -void SHCSelector::styleChanged (const Glib::RefPtr& style) { - +void SHCSelector::styleChanged (const Glib::RefPtr& style) +{ + queue_draw (); } -bool SHCSelector::reset () { // : movingPosition(-1), cl(NULL) { - if ( positions[0] != defaults[0] || - positions[1] != defaults[1] || - positions[2] != defaults[2] - ) { +bool SHCSelector::reset () // : movingPosition(-1), cl(NULL) { +{ + if ( positions[0] != defaults[0] || + positions[1] != defaults[1] || + positions[2] != defaults[2] + ) { - positions[0] = defaults[0]; - positions[1] = defaults[1]; - positions[2] = defaults[2]; - queue_draw (); - return true; - } - return false; + positions[0] = defaults[0]; + positions[1] = defaults[1]; + positions[2] = defaults[2]; + queue_draw (); + return true; + } + + return false; } -void SHCSelector::refresh() { - setDirty(true); - Glib::RefPtr win = get_window(); - if (win) - win->invalidate(true); +void SHCSelector::refresh() +{ + setDirty(true); + Glib::RefPtr win = get_window(); + + if (win) { + win->invalidate(true); + } } diff --git a/rtgui/shcselector.h b/rtgui/shcselector.h index 7096d6d23..b71044f0f 100644 --- a/rtgui/shcselector.h +++ b/rtgui/shcselector.h @@ -7,7 +7,7 @@ * 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 @@ -22,15 +22,17 @@ #include #include "coloredbar.h" -class SHCListener { - public: - virtual ~SHCListener() {} - virtual void shcChanged () {} +class SHCListener +{ +public: + virtual ~SHCListener() {} + virtual void shcChanged () {} }; -class SHCSelector : public Gtk::DrawingArea, public ColoredBar { +class SHCSelector : public Gtk::DrawingArea, public ColoredBar +{ - protected: +protected: int movingPosition; double tmpX, tmpPos; @@ -38,22 +40,25 @@ class SHCSelector : public Gtk::DrawingArea, public ColoredBar { double defaults[3]; double positions[3]; double wslider; - + // left margin, essentially a workaround to take care of an eventual right colored bar (e.g. for curves) int leftMargin; // right margin, essentially a workaround to take care of an eventual right colored bar int rightMargin; - const static int hb = 3; // horizontal border - const static int vb = 2; // vertical border + const static int hb = 3; // horizontal border + const static int vb = 2; // vertical border - SHCListener* cl; + SHCListener* cl; + +public: - public: - SHCSelector(); - void setSHCListener (SHCListener* l) { cl = l;; } + void setSHCListener (SHCListener* l) + { + cl = l;; + } void setMargins(int left, int right); void setDefaults (double spos, double cpos, double hpos); diff --git a/rtgui/soundman.cc b/rtgui/soundman.cc index 9cb3450dc..ff562d030 100644 --- a/rtgui/soundman.cc +++ b/rtgui/soundman.cc @@ -49,17 +49,19 @@ void SoundManager::init() // param is either file name or name of the system event on Windows (e.g. "SystemAsterisk" or "SystemDefault"). void SoundManager::playSoundAsync(const Glib::ustring &sound) { - if (sound.empty() || !options.sndEnable) return; + if (sound.empty() || !options.sndEnable) { + return; + } #ifdef WIN32 - DWORD sndParam=SND_ASYNC | SND_NODEFAULT; + DWORD sndParam = SND_ASYNC | SND_NODEFAULT; - if (sound.find('.')!=Glib::ustring::npos) { + if (sound.find('.') != Glib::ustring::npos) { // contain dot, so it's a filename - sndParam|=SND_FILENAME; + sndParam |= SND_FILENAME; } else { // no dot, so it's a system event - sndParam|=SND_ALIAS; + sndParam |= SND_ALIAS; } wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (sound.c_str(), -1, NULL, NULL, NULL); diff --git a/rtgui/soundman.h b/rtgui/soundman.h index d6d39314f..a778a006a 100644 --- a/rtgui/soundman.h +++ b/rtgui/soundman.h @@ -23,7 +23,8 @@ #include "../rtengine/safegtk.h" -class SoundManager { +class SoundManager +{ public: static void init(); static void playSoundAsync(const Glib::ustring &sound); diff --git a/rtgui/splash.cc b/rtgui/splash.cc index c6473369d..b385ca460 100644 --- a/rtgui/splash.cc +++ b/rtgui/splash.cc @@ -7,7 +7,7 @@ * 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 @@ -27,13 +27,15 @@ extern Glib::ustring licensePath; extern Glib::ustring versionString; extern Glib::ustring versionSuffixString; -SplashImage::SplashImage () { +SplashImage::SplashImage () +{ pixbuf = safe_create_from_file ("splash.png"); set_size_request (pixbuf->get_width(), pixbuf->get_height()); } -void SplashImage::on_realize () { +void SplashImage::on_realize () +{ Gtk::DrawingArea::on_realize(); add_events(Gdk::EXPOSURE_MASK); @@ -43,12 +45,13 @@ void SplashImage::on_realize () { Gdk::Color fontc = Gdk::Color ("white"); colormap->alloc_color (fontc); gc_->set_foreground (fontc); - + } -bool SplashImage::on_expose_event (GdkEventExpose* event) { +bool SplashImage::on_expose_event (GdkEventExpose* event) +{ - Glib::RefPtr window = get_window(); + Glib::RefPtr window = get_window(); pixbuf->render_to_drawable (window, gc_, 0, 0, 0, 0, pixbuf->get_width(), pixbuf->get_height(), Gdk::RGB_DITHER_NONE, 0, 0); Cairo::FontOptions cfo; @@ -57,7 +60,7 @@ bool SplashImage::on_expose_event (GdkEventExpose* event) { context->set_cairo_font_options (cfo); Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_LIGHT); - fontd.set_absolute_size (12*Pango::SCALE); + fontd.set_absolute_size (12 * Pango::SCALE); context->set_font_description (fontd); Gdk::Color *textColor = new Gdk::Color(); textColor->set_rgb(0, 0, 0); @@ -65,8 +68,11 @@ bool SplashImage::on_expose_event (GdkEventExpose* event) { int w, h; Glib::ustring versionStr(versionString); - if (!versionSuffixString.empty()) - versionStr += " "+versionSuffixString; + + if (!versionSuffixString.empty()) { + versionStr += " " + versionSuffixString; + } + version = create_pango_layout (versionStr); version->set_markup("" + versionStr + ""); version->get_pixel_size (w, h); @@ -75,7 +81,8 @@ bool SplashImage::on_expose_event (GdkEventExpose* event) { return true; } -Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, true) { +Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, true) +{ set_border_width (4); @@ -97,121 +104,141 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t splashImage->show (); // 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 (f != NULL) { - char* buffer = new char[1024]; - std::ostringstream ostr; - while (fgets (buffer, 1024, f)) - ostr << buffer; - delete [] buffer; - fclose (f); + std::string buildFileName = Glib::build_filename (creditsPath, "AboutThisBuild.txt"); - Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); - textBuffer->set_text((Glib::ustring)(ostr.str())); + if ( safe_file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = safe_g_fopen (buildFileName, "rt"); - Gtk::ScrolledWindow *buildSW = Gtk::manage (new Gtk::ScrolledWindow()); - Gtk::TextView *buildTV = Gtk::manage (new Gtk::TextView (textBuffer)); - buildTV->set_editable(false); - buildTV->set_left_margin (10); - buildTV->set_right_margin (5); - buildSW->add(*buildTV); - nb->append_page (*buildSW, M("ABOUT_TAB_BUILD")); - } - } + if (f != NULL) { + char* buffer = new char[1024]; + std::ostringstream ostr; + + while (fgets (buffer, 1024, f)) { + ostr << buffer; + } + + delete [] buffer; + fclose (f); + + Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); + textBuffer->set_text((Glib::ustring)(ostr.str())); + + Gtk::ScrolledWindow *buildSW = Gtk::manage (new Gtk::ScrolledWindow()); + Gtk::TextView *buildTV = Gtk::manage (new Gtk::TextView (textBuffer)); + buildTV->set_editable(false); + buildTV->set_left_margin (10); + buildTV->set_right_margin (5); + buildSW->add(*buildTV); + nb->append_page (*buildSW, M("ABOUT_TAB_BUILD")); + } + } // 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 (f != NULL) { - char* buffer = new char[1024]; - std::ostringstream ostr; - while (fgets (buffer, 1024, f)) - ostr << buffer; - delete [] buffer; - fclose (f); + std::string creditsFileName = Glib::build_filename (creditsPath, "AUTHORS.txt"); - Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); - textBuffer->set_text((Glib::ustring)(ostr.str())); + if ( safe_file_test(creditsFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = safe_g_fopen (creditsFileName, "rt"); - Gtk::ScrolledWindow *creditsSW = Gtk::manage (new Gtk::ScrolledWindow()); - Gtk::TextView *creditsTV = Gtk::manage (new Gtk::TextView (textBuffer)); - creditsTV->set_left_margin (10); - creditsTV->set_right_margin (5); - creditsTV->set_wrap_mode(Gtk::WRAP_WORD); - creditsTV->set_editable(false); - creditsSW->add(*creditsTV); - nb->append_page (*creditsSW, M("ABOUT_TAB_CREDITS")); - } - } + if (f != NULL) { + char* buffer = new char[1024]; + std::ostringstream ostr; + + while (fgets (buffer, 1024, f)) { + ostr << buffer; + } + + delete [] buffer; + fclose (f); + + Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); + textBuffer->set_text((Glib::ustring)(ostr.str())); + + Gtk::ScrolledWindow *creditsSW = Gtk::manage (new Gtk::ScrolledWindow()); + Gtk::TextView *creditsTV = Gtk::manage (new Gtk::TextView (textBuffer)); + creditsTV->set_left_margin (10); + creditsTV->set_right_margin (5); + creditsTV->set_wrap_mode(Gtk::WRAP_WORD); + creditsTV->set_editable(false); + creditsSW->add(*creditsTV); + nb->append_page (*creditsSW, M("ABOUT_TAB_CREDITS")); + } + } // 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 (f != NULL) { - char* buffer = new char[1024]; - std::ostringstream ostr; - while (fgets (buffer, 1024, f)) - ostr << buffer; - delete [] buffer; - fclose (f); + std::string licenseFileName = Glib::build_filename (licensePath, "LICENSE.txt"); - Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); - textBuffer->set_text((Glib::ustring)(ostr.str())); + if ( safe_file_test(licenseFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = safe_g_fopen (licenseFileName, "rt"); - Gtk::ScrolledWindow *licenseSW = Gtk::manage (new Gtk::ScrolledWindow()); - Gtk::TextView *licenseTV = Gtk::manage (new Gtk::TextView (textBuffer)); + if (f != NULL) { + char* buffer = new char[1024]; + std::ostringstream ostr; - // set monospace font to enhance readability of formatted text - Pango::FontDescription fdescLicense; - fdescLicense.set_family("monospace"); - fdescLicense.set_absolute_size (11*Pango::SCALE); - licenseTV->modify_font(fdescLicense); + while (fgets (buffer, 1024, f)) { + ostr << buffer; + } - licenseTV->set_left_margin (10); - licenseTV->set_right_margin (5); - licenseTV->set_editable(false); - licenseSW->add(*licenseTV); - nb->append_page (*licenseSW, M("ABOUT_TAB_LICENSE")); - } - } + delete [] buffer; + fclose (f); + + Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); + textBuffer->set_text((Glib::ustring)(ostr.str())); + + Gtk::ScrolledWindow *licenseSW = Gtk::manage (new Gtk::ScrolledWindow()); + Gtk::TextView *licenseTV = Gtk::manage (new Gtk::TextView (textBuffer)); + + // set monospace font to enhance readability of formatted text + Pango::FontDescription fdescLicense; + fdescLicense.set_family("monospace"); + fdescLicense.set_absolute_size (11 * Pango::SCALE); + licenseTV->modify_font(fdescLicense); + + licenseTV->set_left_margin (10); + licenseTV->set_right_margin (5); + licenseTV->set_editable(false); + licenseSW->add(*licenseTV); + nb->append_page (*licenseSW, M("ABOUT_TAB_LICENSE")); + } + } // 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 (f != NULL) { - char* buffer = new char[1024]; - std::ostringstream ostr; - while (fgets (buffer, 1024, f)) - ostr << buffer; - delete [] buffer; - fclose (f); + std::string releaseNotesFileName = Glib::build_filename (creditsPath, "RELEASE_NOTES.txt"); - Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); - textBuffer->set_text((Glib::ustring)(ostr.str())); + if ( safe_file_test(releaseNotesFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = safe_g_fopen (releaseNotesFileName, "rt"); - releaseNotesSW = Gtk::manage (new Gtk::ScrolledWindow()); - Gtk::TextView *releaseNotesTV = Gtk::manage (new Gtk::TextView (textBuffer)); + if (f != NULL) { + char* buffer = new char[1024]; + std::ostringstream ostr; - // set monospace font to enhance readability of formatted text - Pango::FontDescription fdescReleaseNotes; - fdescReleaseNotes.set_family("monospace"); - fdescReleaseNotes.set_absolute_size (11*Pango::SCALE); - releaseNotesTV->modify_font(fdescReleaseNotes); + while (fgets (buffer, 1024, f)) { + ostr << buffer; + } + + delete [] buffer; + fclose (f); + + Glib::RefPtr textBuffer = Gtk::TextBuffer::create(); + textBuffer->set_text((Glib::ustring)(ostr.str())); + + releaseNotesSW = Gtk::manage (new Gtk::ScrolledWindow()); + Gtk::TextView *releaseNotesTV = Gtk::manage (new Gtk::TextView (textBuffer)); + + // set monospace font to enhance readability of formatted text + Pango::FontDescription fdescReleaseNotes; + fdescReleaseNotes.set_family("monospace"); + fdescReleaseNotes.set_absolute_size (11 * Pango::SCALE); + releaseNotesTV->modify_font(fdescReleaseNotes); - releaseNotesTV->set_left_margin (10); - releaseNotesTV->set_right_margin (3); - releaseNotesTV->set_editable(false); - releaseNotesTV->set_wrap_mode(Gtk::WRAP_WORD); - releaseNotesSW->add(*releaseNotesTV); - nb->append_page (*releaseNotesSW, M("ABOUT_TAB_RELEASENOTES")); - } - } + releaseNotesTV->set_left_margin (10); + releaseNotesTV->set_right_margin (3); + releaseNotesTV->set_editable(false); + releaseNotesTV->set_wrap_mode(Gtk::WRAP_WORD); + releaseNotesSW->add(*releaseNotesTV); + nb->append_page (*releaseNotesSW, M("ABOUT_TAB_RELEASENOTES")); + } + } set_position (Gtk::WIN_POS_CENTER); @@ -224,25 +251,32 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t set_keep_above (true); } -Splash::Splash (Gtk::Window& parent, int maxtime) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, true) { +Splash::Splash (Gtk::Window& parent, int maxtime) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, true) +{ splashImage = Gtk::manage(new SplashImage ()); // add (*splashImage); get_vbox()->pack_start (*splashImage); splashImage->show (); - if (maxtime>0) + if (maxtime > 0) { Glib::signal_timeout().connect (sigc::mem_fun(*this, &Splash::on_timer), maxtime); + } + set_position (Gtk::WIN_POS_CENTER); - if (maxtime>0) + + if (maxtime > 0) { set_decorated (false); + } + add_events(Gdk::BUTTON_RELEASE_MASK); set_resizable (false); set_keep_above (true); } -bool Splash::on_timer () { +bool Splash::on_timer () +{ hide (); return false; @@ -257,11 +291,14 @@ bool Splash::on_button_release_event (GdkEventButton* event) { } */ -void Splash::showReleaseNotes() { - if (releaseNotesSW) - nb->set_current_page(nb->page_num(*releaseNotesSW)); +void Splash::showReleaseNotes() +{ + if (releaseNotesSW) { + nb->set_current_page(nb->page_num(*releaseNotesSW)); + } } -void Splash::closePressed() { +void Splash::closePressed() +{ hide(); } diff --git a/rtgui/splash.h b/rtgui/splash.h index 8d54a58c4..5e3d5e1b4 100644 --- a/rtgui/splash.h +++ b/rtgui/splash.h @@ -7,7 +7,7 @@ * 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 @@ -21,32 +21,37 @@ #include -class SplashImage : public Gtk::DrawingArea { +class SplashImage : public Gtk::DrawingArea +{ - private: - Glib::RefPtr gc_; - Glib::RefPtr pixbuf; - Glib::RefPtr version; - - public: - SplashImage (); - void on_realize (); - bool on_expose_event (GdkEventExpose* event); +private: + Glib::RefPtr gc_; + Glib::RefPtr pixbuf; + Glib::RefPtr version; + +public: + SplashImage (); + void on_realize (); + bool on_expose_event (GdkEventExpose* event); }; //class Splash : public Gtk::Window { -class Splash : public Gtk::Dialog { +class Splash : public Gtk::Dialog +{ - private: +private: SplashImage* splashImage; Gtk::Notebook* nb; Gtk::ScrolledWindow* releaseNotesSW; - public: +public: Splash (Gtk::Window& parent, int maxtime); Splash (Gtk::Window& parent); - bool hasReleaseNotes() { return releaseNotesSW != NULL; }; + bool hasReleaseNotes() + { + return releaseNotesSW != NULL; + }; void showReleaseNotes(); bool on_timer (); //virtual bool on_button_release_event (GdkEventButton* event); diff --git a/rtgui/threadutils.h b/rtgui/threadutils.h index 81d2c9917..2ee654c4e 100644 --- a/rtgui/threadutils.h +++ b/rtgui/threadutils.h @@ -31,9 +31,9 @@ #ifdef NDEBUG - // We don't trace mutex - #undef TRACE_MYRWMUTEX - #define TRACE_MYRWMUTEX 0 +// We don't trace mutex +#undef TRACE_MYRWMUTEX +#define TRACE_MYRWMUTEX 0 #endif @@ -59,101 +59,116 @@ */ #ifdef WIN32 -class MyMutex : public Glib::RecMutex { +class MyMutex : public Glib::RecMutex +{ #else -class MyMutex : public Glib::Threads::RecMutex { +class MyMutex : public Glib::Threads::RecMutex +{ #endif #if STRICT_MUTEX || !defined(NDEBUG) private: - bool alreadyLocked; + bool alreadyLocked; #endif public: - class MyLock; + class MyLock; #if STRICT_MUTEX || !defined(NDEBUG) - MyMutex() : alreadyLocked(false) {} + MyMutex() : alreadyLocked(false) {} #else - MyMutex() {} + MyMutex() {} #endif - void lock() { - #ifdef WIN32 - Glib::RecMutex::lock(); - #else - Glib::Threads::RecMutex::lock(); - #endif - #if STRICT_MUTEX || !defined(NDEBUG) - if (alreadyLocked) { - #ifndef NDEBUG - std::cout << "Warning: MyMutex already locked!" << std::endl; // breakpoint - #endif - #if STRICT_MUTEX - #ifndef NDEBUG - #ifdef WIN32 - DebugBreak(); - #else - raise(SIGTRAP); - #endif - #else - raise(SIGINT); - #endif - #endif - } - alreadyLocked = true; - #endif - } + void lock() + { +#ifdef WIN32 + Glib::RecMutex::lock(); +#else + Glib::Threads::RecMutex::lock(); +#endif +#if STRICT_MUTEX || !defined(NDEBUG) - bool trylock() { - #ifdef WIN32 - if (Glib::RecMutex::trylock()) - #else - if (Glib::Threads::RecMutex::trylock()) - #endif - { - #if STRICT_MUTEX || !defined(NDEBUG) - if (alreadyLocked) { - #ifndef NDEBUG - std::cout << "Warning: MyMutex already locked!" << std::endl; // breakpoint - #endif - #if STRICT_MUTEX - #ifndef NDEBUG - #ifdef WIN32 - DebugBreak(); - #else - raise(SIGTRAP); - #endif - #else - raise(SIGINT); - #endif - #endif - } - alreadyLocked = true; - #endif - return true; - } - return false; - } + if (alreadyLocked) { +#ifndef NDEBUG + std::cout << "Warning: MyMutex already locked!" << std::endl; // breakpoint +#endif +#if STRICT_MUTEX +#ifndef NDEBUG +#ifdef WIN32 + DebugBreak(); +#else + raise(SIGTRAP); +#endif +#else + raise(SIGINT); +#endif +#endif + } - // Warning: the base class of MyMutex is RecMutex, but the mutex is said "unlocked" on first occurrence of "unlock", to avoid overhead. - void unlock() { - #if STRICT_MUTEX || !defined(NDEBUG) - alreadyLocked = false; - #endif - #ifdef WIN32 - Glib::RecMutex::unlock(); - #else - Glib::Threads::RecMutex::unlock(); - #endif - } + alreadyLocked = true; +#endif + } + + bool trylock() + { +#ifdef WIN32 + + if (Glib::RecMutex::trylock()) +#else + if (Glib::Threads::RecMutex::trylock()) +#endif + { +#if STRICT_MUTEX || !defined(NDEBUG) + + if (alreadyLocked) { +#ifndef NDEBUG + std::cout << "Warning: MyMutex already locked!" << std::endl; // breakpoint +#endif +#if STRICT_MUTEX +#ifndef NDEBUG +#ifdef WIN32 + DebugBreak(); +#else + raise(SIGTRAP); +#endif +#else + raise(SIGINT); +#endif +#endif + } + + alreadyLocked = true; +#endif + return true; + } + + return false; + } + + // Warning: the base class of MyMutex is RecMutex, but the mutex is said "unlocked" on first occurrence of "unlock", to avoid overhead. + void unlock() + { +#if STRICT_MUTEX || !defined(NDEBUG) + alreadyLocked = false; +#endif +#ifdef WIN32 + Glib::RecMutex::unlock(); +#else + Glib::Threads::RecMutex::unlock(); +#endif + } }; // Class copied from the Glibmm source code, to provide a workaround of the behavior's difference between Linux and Windows -class MyMutex::MyLock { +class MyMutex::MyLock +{ public: - explicit inline MyLock(MyMutex& mutex) : mutex_ (mutex), locked_ (true) { mutex_.lock(); } + explicit inline MyLock(MyMutex& mutex) : mutex_ (mutex), locked_ (true) + { + mutex_.lock(); + } #ifdef WIN32 inline MyLock(MyMutex& mutex, Glib::NotLock) : mutex_ (mutex), locked_ (false) {} inline MyLock(MyMutex& mutex, Glib::TryLock) : mutex_ (mutex), locked_ (mutex.trylock()) {} @@ -161,12 +176,32 @@ public: inline MyLock(MyMutex& mutex, Glib::Threads::NotLock) : mutex_ (mutex), locked_ (false) {} inline MyLock(MyMutex& mutex, Glib::Threads::TryLock) : mutex_ (mutex), locked_ (mutex.trylock()) {} #endif - inline ~MyLock() { if(locked_) mutex_.unlock(); } + inline ~MyLock() + { + if(locked_) { + mutex_.unlock(); + } + } - inline void acquire() { mutex_.lock(); locked_ = true; } - inline bool try_acquire() { locked_ = mutex_.trylock(); return locked_; } - inline void release() { mutex_.unlock(); locked_ = false; } - inline bool locked() const { return locked_; } + inline void acquire() + { + mutex_.lock(); + locked_ = true; + } + inline bool try_acquire() + { + locked_ = mutex_.trylock(); + return locked_; + } + inline void release() + { + mutex_.unlock(); + locked_ = false; + } + inline bool locked() const + { + return locked_; + } private: MyMutex& mutex_; @@ -183,26 +218,27 @@ private: * * It may be slower, but thread safe! */ -class MyRWMutex { +class MyRWMutex +{ public: #ifdef WIN32 - Glib::Mutex handlerMutex; // Having a recursive or non-recursive mutex is not important here, so we can use Glib::Mutex - Glib::Cond access; + Glib::Mutex handlerMutex; // Having a recursive or non-recursive mutex is not important here, so we can use Glib::Mutex + Glib::Cond access; #else - Glib::Threads::Mutex handlerMutex; // Having a recursive or non-recursive mutex is not important here, so we can use Glib::Threads::Mutex - Glib::Threads::Cond access; + Glib::Threads::Mutex handlerMutex; // Having a recursive or non-recursive mutex is not important here, so we can use Glib::Threads::Mutex + Glib::Threads::Cond access; #endif - size_t writerCount; - size_t readerCount; + size_t writerCount; + size_t readerCount; #if TRACE_MYRWMUTEX - Glib::ustring lastWriterFile; - int lastWriterLine; - // Unfortunately, ownerThread may not be the culprit of a deadlock, it can be another concurrent Reader... - void* ownerThread; + Glib::ustring lastWriterFile; + int lastWriterLine; + // Unfortunately, ownerThread may not be the culprit of a deadlock, it can be another concurrent Reader... + void* ownerThread; - MyRWMutex() : writerCount(0), readerCount(0), lastWriterLine(0), ownerThread(NULL) {} + MyRWMutex() : writerCount(0), readerCount(0), lastWriterLine(0), ownerThread(NULL) {} #else - MyRWMutex() : writerCount(0), readerCount(0) {} + MyRWMutex() : writerCount(0), readerCount(0) {} #endif }; @@ -210,394 +246,446 @@ public: * @brief Custom ReaderLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!) * */ -class MyReaderLock { +class MyReaderLock +{ - MyRWMutex& rwMutex; - bool locked; + MyRWMutex& rwMutex; + bool locked; - #if TRACE_MYRWMUTEX - static unsigned int readerLockCounter; - int locknumber; +#if TRACE_MYRWMUTEX + static unsigned int readerLockCounter; + int locknumber; public: - inline MyReaderLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0) - #else + inline MyReaderLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0) +#else public: - inline MyReaderLock(MyRWMutex& mutex) : rwMutex(mutex) - #endif + inline MyReaderLock(MyRWMutex& mutex) : rwMutex(mutex) +#endif - { - // to operate safely - rwMutex.handlerMutex.lock(); + { + // to operate safely + rwMutex.handlerMutex.lock(); - #if TRACE_MYRWMUTEX - locknumber = readerLockCounter++; - void* thread = Glib::Thread::self(); - std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R"; - #endif +#if TRACE_MYRWMUTEX + locknumber = readerLockCounter++; + void* thread = Glib::Thread::self(); + std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R"; +#endif - if (!rwMutex.writerCount) { - // There's no writer operating, we can increment the writer count which will lock writers - ++rwMutex.writerCount; - #if TRACE_MYRWMUTEX - std::cout << " ++ new owner"; - #endif - } - else { - // The writer count is non null, but we can be the owner of the writer lock - // It will be the case if the reader count is non null too. - if (!rwMutex.readerCount) { - // the mutex is in real write mode, we're waiting to see it null - #if TRACE_MYRWMUTEX - std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; - #endif - while (rwMutex.writerCount) - rwMutex.access.wait(rwMutex.handlerMutex); - ++rwMutex.writerCount; - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = file; - rwMutex.lastWriterLine = line; - rwMutex.ownerThread = thread; - std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R ++ new owner"; - #endif - } - } - // then we can increment the reader count - ++rwMutex.readerCount; + if (!rwMutex.writerCount) { + // There's no writer operating, we can increment the writer count which will lock writers + ++rwMutex.writerCount; +#if TRACE_MYRWMUTEX + std::cout << " ++ new owner"; +#endif + } else { + // The writer count is non null, but we can be the owner of the writer lock + // It will be the case if the reader count is non null too. + if (!rwMutex.readerCount) { + // the mutex is in real write mode, we're waiting to see it null +#if TRACE_MYRWMUTEX + std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; +#endif - #if TRACE_MYRWMUTEX - std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; - #endif + while (rwMutex.writerCount) { + rwMutex.access.wait(rwMutex.handlerMutex); + } - rwMutex.handlerMutex.unlock(); + ++rwMutex.writerCount; +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = file; + rwMutex.lastWriterLine = line; + rwMutex.ownerThread = thread; + std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - R ++ new owner"; +#endif + } + } - locked = true; - } - #if TRACE_MYRWMUTEX - // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely - inline void acquire(const char* file, const int line) - #else - // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely - inline void acquire() - #endif - { - #if TRACE_MYRWMUTEX - void* thread = Glib::Thread::self(); - #endif - if (!locked) { - // to operate safely - rwMutex.handlerMutex.lock(); + // then we can increment the reader count + ++rwMutex.readerCount; - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock)"; - #endif +#if TRACE_MYRWMUTEX + std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; +#endif - if (!rwMutex.writerCount) { - // There's no writer operating, we can increment the writer count which will lock writers - ++rwMutex.writerCount; - #if TRACE_MYRWMUTEX - std::cout << " ++ new owner"; - #endif - } - else { - // The writer count is non null, but a reader can be the owner of the writer lock, - // it will be the case if the reader count is non null too. - if (!rwMutex.readerCount) { - // the mutex is in real write mode, we're waiting to see it null - #if TRACE_MYRWMUTEX - std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; - #endif - while (rwMutex.writerCount) - rwMutex.access.wait(rwMutex.handlerMutex); - ++rwMutex.writerCount; - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = file; - rwMutex.lastWriterLine = line; - rwMutex.ownerThread = thread; - std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock) ++ new owner"; - #endif - } - } - // then we can increment the reader count - ++rwMutex.readerCount; + rwMutex.handlerMutex.unlock(); - #if TRACE_MYRWMUTEX - std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; - #endif + locked = true; + } +#if TRACE_MYRWMUTEX + // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely + inline void acquire(const char* file, const int line) +#else + // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely + inline void acquire() +#endif + { +#if TRACE_MYRWMUTEX + void* thread = Glib::Thread::self(); +#endif - rwMutex.handlerMutex.unlock(); + if (!locked) { + // to operate safely + rwMutex.handlerMutex.lock(); - locked = true; - } - #if TRACE_MYRWMUTEX - else std::cout << thread << "/" << locknumber << " / already locked by this object - R (lock)" << std::endl; - #endif - } - inline ~MyReaderLock() { - #if TRACE_MYRWMUTEX - void* thread = Glib::Thread::self(); - #endif - if (locked) { - // to operate safely - rwMutex.handlerMutex.lock(); +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock)"; +#endif - // decrement the writer number first - --rwMutex.readerCount; + if (!rwMutex.writerCount) { + // There's no writer operating, we can increment the writer count which will lock writers + ++rwMutex.writerCount; +#if TRACE_MYRWMUTEX + std::cout << " ++ new owner"; +#endif + } else { + // The writer count is non null, but a reader can be the owner of the writer lock, + // it will be the case if the reader count is non null too. + if (!rwMutex.readerCount) { + // the mutex is in real write mode, we're waiting to see it null +#if TRACE_MYRWMUTEX + std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; +#endif - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << " / unlocking - R - ReaderCount: " << rwMutex.readerCount; - #endif + while (rwMutex.writerCount) { + rwMutex.access.wait(rwMutex.handlerMutex); + } - if (!rwMutex.readerCount) { - // no more reader, so we decrement the writer count - --rwMutex.writerCount; - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = ""; - rwMutex.lastWriterLine = 0; - rwMutex.ownerThread = NULL; - std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount; - #endif - // and signal the next waiting reader/writer that it's free - rwMutex.access.broadcast(); - } - #if TRACE_MYRWMUTEX - std::cout << std::endl; - #endif + ++rwMutex.writerCount; +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = file; + rwMutex.lastWriterLine = line; + rwMutex.ownerThread = thread; + std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - R (lock) ++ new owner"; +#endif + } + } - rwMutex.handlerMutex.unlock(); - } - #if TRACE_MYRWMUTEX - else std::cout << thread << "/" << locknumber << " / already unlocked by this object - R" << std::endl; - #endif - } - #if TRACE_MYRWMUTEX - // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely - inline void release(const char* file, const int line) - #else - // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely - inline void release() - #endif - { - #if TRACE_MYRWMUTEX - void* thread = Glib::Thread::self(); - #endif - if (locked) { - // to operate safely - rwMutex.handlerMutex.lock(); + // then we can increment the reader count + ++rwMutex.readerCount; - // decrement the writer number first - --rwMutex.readerCount; +#if TRACE_MYRWMUTEX + std::cout << " - ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; +#endif - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << " / unlocking - R (release) - ReaderCount: " << rwMutex.readerCount; - #endif + rwMutex.handlerMutex.unlock(); - if (!rwMutex.readerCount) { - // no more reader, so we decrement the writer count - --rwMutex.writerCount; - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = ""; - rwMutex.lastWriterLine = 0; - rwMutex.ownerThread = NULL; - std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount; - #endif - // and signal the next waiting reader/writer that it's free - rwMutex.access.broadcast(); - } - #if TRACE_MYRWMUTEX - std::cout << std::endl; - #endif + locked = true; + } - rwMutex.handlerMutex.unlock(); +#if TRACE_MYRWMUTEX + else { + std::cout << thread << "/" << locknumber << " / already locked by this object - R (lock)" << std::endl; + } - locked = false; - } - #if TRACE_MYRWMUTEX - else std::cout << thread << "/" << locknumber << " / already unlocked - R (release)" << std::endl; - #endif - } +#endif + } + inline ~MyReaderLock() + { +#if TRACE_MYRWMUTEX + void* thread = Glib::Thread::self(); +#endif + + if (locked) { + // to operate safely + rwMutex.handlerMutex.lock(); + + // decrement the writer number first + --rwMutex.readerCount; + +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << " / unlocking - R - ReaderCount: " << rwMutex.readerCount; +#endif + + if (!rwMutex.readerCount) { + // no more reader, so we decrement the writer count + --rwMutex.writerCount; +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = ""; + rwMutex.lastWriterLine = 0; + rwMutex.ownerThread = NULL; + std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount; +#endif + // and signal the next waiting reader/writer that it's free + rwMutex.access.broadcast(); + } + +#if TRACE_MYRWMUTEX + std::cout << std::endl; +#endif + + rwMutex.handlerMutex.unlock(); + } + +#if TRACE_MYRWMUTEX + else { + std::cout << thread << "/" << locknumber << " / already unlocked by this object - R" << std::endl; + } + +#endif + } +#if TRACE_MYRWMUTEX + // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely + inline void release(const char* file, const int line) +#else + // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely + inline void release() +#endif + { +#if TRACE_MYRWMUTEX + void* thread = Glib::Thread::self(); +#endif + + if (locked) { + // to operate safely + rwMutex.handlerMutex.lock(); + + // decrement the writer number first + --rwMutex.readerCount; + +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << " / unlocking - R (release) - ReaderCount: " << rwMutex.readerCount; +#endif + + if (!rwMutex.readerCount) { + // no more reader, so we decrement the writer count + --rwMutex.writerCount; +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = ""; + rwMutex.lastWriterLine = 0; + rwMutex.ownerThread = NULL; + std::cout << " -- new owner possible!" << " >>> ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount; +#endif + // and signal the next waiting reader/writer that it's free + rwMutex.access.broadcast(); + } + +#if TRACE_MYRWMUTEX + std::cout << std::endl; +#endif + + rwMutex.handlerMutex.unlock(); + + locked = false; + } + +#if TRACE_MYRWMUTEX + else { + std::cout << thread << "/" << locknumber << " / already unlocked - R (release)" << std::endl; + } + +#endif + } }; /** * @brief Custom WriterLock with debugging feature, to replace the buggy Glib::RWLock (can have negative reader_count value!) * */ -class MyWriterLock { +class MyWriterLock +{ - MyRWMutex& rwMutex; - bool locked; + MyRWMutex& rwMutex; + bool locked; - #if TRACE_MYRWMUTEX - static unsigned int writerLockCounter; - int locknumber; +#if TRACE_MYRWMUTEX + static unsigned int writerLockCounter; + int locknumber; public: - inline MyWriterLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0) - #else + inline MyWriterLock(MyRWMutex& mutex, const char* name, const char* file, const int line) : rwMutex(mutex), locked(false), locknumber(0) +#else public: - inline MyWriterLock(MyRWMutex& mutex) : rwMutex(mutex) - #endif - { - // to operate safely - rwMutex.handlerMutex.lock(); + inline MyWriterLock(MyRWMutex& mutex) : rwMutex(mutex) +#endif + { + // to operate safely + rwMutex.handlerMutex.lock(); - #if TRACE_MYRWMUTEX - locknumber = writerLockCounter++; - void* thread = Glib::Thread::self(); - std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - W"; - #endif +#if TRACE_MYRWMUTEX + locknumber = writerLockCounter++; + void* thread = Glib::Thread::self(); + std::cout << thread << "/" << locknumber << ":" << name << " / " << file << " : " << line << " - locking - W"; +#endif - if (rwMutex.writerCount) { - // The writer count is non null, so we have to wait for it to be null again - #if TRACE_MYRWMUTEX - std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; - #endif - while (rwMutex.writerCount) - rwMutex.access.wait(rwMutex.handlerMutex); - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W"; - #endif - } - // then we can increment the writer count - ++rwMutex.writerCount; + if (rwMutex.writerCount) { + // The writer count is non null, so we have to wait for it to be null again +#if TRACE_MYRWMUTEX + std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; +#endif - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = file; - rwMutex.lastWriterLine = line; - rwMutex.ownerThread = thread; - std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; - #endif + while (rwMutex.writerCount) { + rwMutex.access.wait(rwMutex.handlerMutex); + } - rwMutex.handlerMutex.unlock(); +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W"; +#endif + } - locked = true; - } - #if TRACE_MYRWMUTEX - // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely - inline void acquire(const char* file, const int line) - #else - // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely - inline void acquire() - #endif - { - #if TRACE_MYRWMUTEX - void* thread = Glib::Thread::self(); - #endif - if (!locked) { - // to operate safely - rwMutex.handlerMutex.lock(); + // then we can increment the writer count + ++rwMutex.writerCount; - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)"; - #endif +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = file; + rwMutex.lastWriterLine = line; + rwMutex.ownerThread = thread; + std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; +#endif - if (rwMutex.writerCount) { - // The writer count is non null, so we have to wait for it to be null again - #if TRACE_MYRWMUTEX - std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; - #endif - while (rwMutex.writerCount) - rwMutex.access.wait(rwMutex.handlerMutex); - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)"; - #endif - } - // then we can increment the reader count - ++rwMutex.writerCount; + rwMutex.handlerMutex.unlock(); - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = file; - rwMutex.lastWriterLine = line; - rwMutex.ownerThread = thread; - std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; - #endif + locked = true; + } +#if TRACE_MYRWMUTEX + // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely + inline void acquire(const char* file, const int line) +#else + // locks the MyRWMutex with Read access if this MyReaderLock has not already locked it, otherwise return safely + inline void acquire() +#endif + { +#if TRACE_MYRWMUTEX + void* thread = Glib::Thread::self(); +#endif - rwMutex.handlerMutex.unlock(); + if (!locked) { + // to operate safely + rwMutex.handlerMutex.lock(); - locked = true; - } - #if TRACE_MYRWMUTEX - else std::cout << thread << "/" << locknumber << " / already locked by this object - W (lock)" << std::endl; - #endif - } - inline ~MyWriterLock() { - #if TRACE_MYRWMUTEX - void* thread = Glib::Thread::self(); - #endif - if (locked) { - // to operate safely - rwMutex.handlerMutex.lock(); +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)"; +#endif - // decrement the writer number first - --rwMutex.writerCount; + if (rwMutex.writerCount) { + // The writer count is non null, so we have to wait for it to be null again +#if TRACE_MYRWMUTEX + std::cout << " waiting..." << std::endl << "Current writer owner: " << rwMutex.lastWriterFile << " : " << rwMutex.lastWriterLine << std::endl; +#endif - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << " / unlocking - W"; - #endif + while (rwMutex.writerCount) { + rwMutex.access.wait(rwMutex.handlerMutex); + } - if (!rwMutex.writerCount) { - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = ""; - rwMutex.lastWriterLine = 0; - rwMutex.ownerThread = NULL; - std::cout << " -- new owner possible!"; - #endif - // The writer count is null again, so we can wake up the next writer or reader - rwMutex.access.broadcast(); - } - #if TRACE_MYRWMUTEX - std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; - #endif +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << ":" << file << " : " << line << " - locking - W (lock)"; +#endif + } - rwMutex.handlerMutex.unlock(); - } - #if TRACE_MYRWMUTEX - else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W" << std::endl; - #endif - } - #if TRACE_MYRWMUTEX - // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely - inline void release(const char* file, const int line) - #else - // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely - inline void release() - #endif - { - #if TRACE_MYRWMUTEX - void* thread = Glib::Thread::self(); - #endif - if (locked) { - // to operate safely - rwMutex.handlerMutex.lock(); + // then we can increment the reader count + ++rwMutex.writerCount; - // decrement the writer number first - --rwMutex.writerCount; +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = file; + rwMutex.lastWriterLine = line; + rwMutex.ownerThread = thread; + std::cout << " ++ new owner <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; +#endif - #if TRACE_MYRWMUTEX - std::cout << thread << "/" << locknumber << " / unlocking - W (release)"; - #endif + rwMutex.handlerMutex.unlock(); - if (!rwMutex.writerCount) { - #if TRACE_MYRWMUTEX - rwMutex.lastWriterFile = ""; - rwMutex.lastWriterLine = 0; - rwMutex.ownerThread = NULL; - std::cout << " -- new owner possible!"; - #endif - // The writer count is null again, so we can wake up the next writer or reader - rwMutex.access.broadcast(); - } - #if TRACE_MYRWMUTEX - std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; - #endif + locked = true; + } - rwMutex.handlerMutex.unlock(); +#if TRACE_MYRWMUTEX + else { + std::cout << thread << "/" << locknumber << " / already locked by this object - W (lock)" << std::endl; + } - locked = false; - } - #if TRACE_MYRWMUTEX - else std::cout << thread << "/" << locknumber << " / already unlocked by this object - W (release)" << std::endl; - #endif - } +#endif + } + inline ~MyWriterLock() + { +#if TRACE_MYRWMUTEX + void* thread = Glib::Thread::self(); +#endif + + if (locked) { + // to operate safely + rwMutex.handlerMutex.lock(); + + // decrement the writer number first + --rwMutex.writerCount; + +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << " / unlocking - W"; +#endif + + if (!rwMutex.writerCount) { +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = ""; + rwMutex.lastWriterLine = 0; + rwMutex.ownerThread = NULL; + std::cout << " -- new owner possible!"; +#endif + // The writer count is null again, so we can wake up the next writer or reader + rwMutex.access.broadcast(); + } + +#if TRACE_MYRWMUTEX + std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; +#endif + + rwMutex.handlerMutex.unlock(); + } + +#if TRACE_MYRWMUTEX + else { + std::cout << thread << "/" << locknumber << " / already unlocked by this object - W" << std::endl; + } + +#endif + } +#if TRACE_MYRWMUTEX + // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely + inline void release(const char* file, const int line) +#else + // releases the MyRWMutex with Write access if this MyWriterLock has already locked it, otherwise return safely + inline void release() +#endif + { +#if TRACE_MYRWMUTEX + void* thread = Glib::Thread::self(); +#endif + + if (locked) { + // to operate safely + rwMutex.handlerMutex.lock(); + + // decrement the writer number first + --rwMutex.writerCount; + +#if TRACE_MYRWMUTEX + std::cout << thread << "/" << locknumber << " / unlocking - W (release)"; +#endif + + if (!rwMutex.writerCount) { +#if TRACE_MYRWMUTEX + rwMutex.lastWriterFile = ""; + rwMutex.lastWriterLine = 0; + rwMutex.ownerThread = NULL; + std::cout << " -- new owner possible!"; +#endif + // The writer count is null again, so we can wake up the next writer or reader + rwMutex.access.broadcast(); + } + +#if TRACE_MYRWMUTEX + std::cout << " <<< ReaderCount: " << rwMutex.readerCount << " - WriterCount: " << rwMutex.writerCount << std::endl; +#endif + + rwMutex.handlerMutex.unlock(); + + locked = false; + } + +#if TRACE_MYRWMUTEX + else { + std::cout << thread << "/" << locknumber << " / already unlocked by this object - W (release)" << std::endl; + } + +#endif + } }; #if TRACE_MYRWMUTEX diff --git a/rtgui/thresholdadjuster.cc b/rtgui/thresholdadjuster.cc index bf99a631c..6f699eed8 100644 --- a/rtgui/thresholdadjuster.cc +++ b/rtgui/thresholdadjuster.cc @@ -7,7 +7,7 @@ * 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 @@ -28,304 +28,347 @@ #define MIN_RESET_BUTTON_HEIGHT 17 ThresholdAdjuster::ThresholdAdjuster (Glib::ustring label, - double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, - double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, - ThresholdCurveProvider* curveProvider, bool editedCheckBox) - : tSelector(minValueBottom, maxValueBottom, defBottom, labelBottom, precisionBottom, minValueTop, maxValueTop, defTop, labelTop, precisionTop, curveProvider) + double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, + double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, + ThresholdCurveProvider* curveProvider, bool editedCheckBox) + : tSelector(minValueBottom, maxValueBottom, defBottom, labelBottom, precisionBottom, minValueTop, maxValueTop, defTop, labelTop, precisionTop, curveProvider) { - initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT] = defBottom; - initialDefaultVal[ThresholdSelector::TS_TOPLEFT] = defTop; - initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT] = 0.; // unused - initialDefaultVal[ThresholdSelector::TS_TOPRIGHT] = 0.; // unused + initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT] = defBottom; + initialDefaultVal[ThresholdSelector::TS_TOPLEFT] = defTop; + initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT] = 0.; // unused + initialDefaultVal[ThresholdSelector::TS_TOPRIGHT] = 0.; // unused - initObject (label, editedCheckBox); + initObject (label, editedCheckBox); } ThresholdAdjuster::ThresholdAdjuster (Glib::ustring label, double minValue, double maxValue, double defBottom, - double defTop, unsigned int precision, bool startAtOne, bool editedCheckBox) - : tSelector(minValue, maxValue, defBottom, defTop, precision, startAtOne) + double defTop, unsigned int precision, bool startAtOne, bool editedCheckBox) + : tSelector(minValue, maxValue, defBottom, defTop, precision, startAtOne) { - initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT] = defBottom; - initialDefaultVal[ThresholdSelector::TS_TOPLEFT] = defTop; - initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT] = maxValue; - initialDefaultVal[ThresholdSelector::TS_TOPRIGHT] = maxValue; + initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT] = defBottom; + initialDefaultVal[ThresholdSelector::TS_TOPLEFT] = defTop; + initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT] = maxValue; + initialDefaultVal[ThresholdSelector::TS_TOPRIGHT] = maxValue; - initObject (label, editedCheckBox); + initObject (label, editedCheckBox); } ThresholdAdjuster::ThresholdAdjuster (Glib::ustring label, double minValue, double maxValue, - double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight, - unsigned int precision, bool startAtOne, bool editedCheckBox) - : tSelector(minValue, maxValue, defBottomLeft, defTopLeft, - defBottomRight, defTopRight, precision, startAtOne) + double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight, + unsigned int precision, bool startAtOne, bool editedCheckBox) + : tSelector(minValue, maxValue, defBottomLeft, defTopLeft, + defBottomRight, defTopRight, precision, startAtOne) { - initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT] = defBottomLeft; - initialDefaultVal[ThresholdSelector::TS_TOPLEFT] = defTopLeft; - initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT] = defBottomRight; - initialDefaultVal[ThresholdSelector::TS_TOPRIGHT] = defTopRight; + initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT] = defBottomLeft; + initialDefaultVal[ThresholdSelector::TS_TOPLEFT] = defTopLeft; + initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT] = defBottomRight; + initialDefaultVal[ThresholdSelector::TS_TOPRIGHT] = defTopRight; - initObject (label, editedCheckBox); + initObject (label, editedCheckBox); } -void ThresholdAdjuster::initObject (Glib::ustring label, bool editedcb) { +void ThresholdAdjuster::initObject (Glib::ustring label, bool editedcb) +{ - adjusterListener = NULL; - afterReset = false; - blocked = false; + adjusterListener = NULL; + afterReset = false; + blocked = false; - addMode = false; + addMode = false; - // TODO: let the user chose the default value of ThresholdAdjuster::delay, for slow machines - delay = options.adjusterDelay; // delay is no more static, so we can set the delay individually (useful for the RAW editor tab) + // TODO: let the user chose the default value of ThresholdAdjuster::delay, for slow machines + delay = options.adjusterDelay; // delay is no more static, so we can set the delay individually (useful for the RAW editor tab) - set_name("ThresholdAdjuster"); + set_name("ThresholdAdjuster"); - hbox = Gtk::manage (new Gtk::HBox ()); + hbox = Gtk::manage (new Gtk::HBox ()); - this->label = Gtk::manage (new Gtk::Label (label, Gtk::ALIGN_LEFT)); + this->label = Gtk::manage (new Gtk::Label (label, Gtk::ALIGN_LEFT)); - if (editedcb) { - editedCheckBox = Gtk::manage (new Gtk::CheckButton ()); - editedChange = editedCheckBox->signal_toggled().connect( sigc::mem_fun(*this, &ThresholdAdjuster::editedToggled) ); - hbox->pack_start (*editedCheckBox); - } - else - editedCheckBox = NULL; + if (editedcb) { + editedCheckBox = Gtk::manage (new Gtk::CheckButton ()); + editedChange = editedCheckBox->signal_toggled().connect( sigc::mem_fun(*this, &ThresholdAdjuster::editedToggled) ); + hbox->pack_start (*editedCheckBox); + } else { + editedCheckBox = NULL; + } - hbox->pack_start (*this->label); + hbox->pack_start (*this->label); - reset = Gtk::manage (new Gtk::Button ()); - reset->add (*Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); - reset->set_relief (Gtk::RELIEF_NONE); - reset->set_border_width (0); - reset->set_tooltip_text (M("ADJUSTER_RESET_TO_DEFAULT")); + reset = Gtk::manage (new Gtk::Button ()); + reset->add (*Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); + reset->set_relief (Gtk::RELIEF_NONE); + reset->set_border_width (0); + reset->set_tooltip_text (M("ADJUSTER_RESET_TO_DEFAULT")); - hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); + hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0); - reset->set_size_request (-1, this->label->get_height() > MIN_RESET_BUTTON_HEIGHT ? this->label->get_height(): MIN_RESET_BUTTON_HEIGHT); + reset->set_size_request (-1, this->label->get_height() > MIN_RESET_BUTTON_HEIGHT ? this->label->get_height() : MIN_RESET_BUTTON_HEIGHT); - pack_start (*hbox, false, false); - pack_start (tSelector, false, false); + pack_start (*hbox, false, false); + pack_start (tSelector, false, false); - editedState = defEditedState = Irrelevant; + editedState = defEditedState = Irrelevant; - selectorChange = tSelector.signal_value_changed().connect( sigc::mem_fun(*this, &ThresholdAdjuster::selectorChanged) ); - reset->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ThresholdAdjuster::resetPressed) ); + selectorChange = tSelector.signal_value_changed().connect( sigc::mem_fun(*this, &ThresholdAdjuster::selectorChanged) ); + reset->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &ThresholdAdjuster::resetPressed) ); - show_all (); + show_all (); } -ThresholdAdjuster::~ThresholdAdjuster () { +ThresholdAdjuster::~ThresholdAdjuster () +{ - selectorChange.disconnect(); - delayConnection.block(true); - adjusterListener = NULL; + selectorChange.disconnect(); + delayConnection.block(true); + adjusterListener = NULL; } -void ThresholdAdjuster::setDefault (double bottom, double top) { +void ThresholdAdjuster::setDefault (double bottom, double top) +{ - selectorChange.block (true); - tSelector.setPositions(shapeValue(bottom), shapeValue(top)); - selectorChange.block (false); + selectorChange.block (true); + tSelector.setPositions(shapeValue(bottom), shapeValue(top)); + selectorChange.block (false); } -void ThresholdAdjuster::setDefault (double bottomLeft, double topLeft, double bottomRight, double topRight) { +void ThresholdAdjuster::setDefault (double bottomLeft, double topLeft, double bottomRight, double topRight) +{ - selectorChange.block (true); - tSelector.setPositions(shapeValue(bottomLeft), shapeValue(topLeft), shapeValue(bottomRight), shapeValue(topRight)); - selectorChange.block (false); + selectorChange.block (true); + tSelector.setPositions(shapeValue(bottomLeft), shapeValue(topLeft), shapeValue(bottomRight), shapeValue(topRight)); + selectorChange.block (false); } -void ThresholdAdjuster::setDefaultEditedState (EditedState eState) { +void ThresholdAdjuster::setDefaultEditedState (EditedState eState) +{ - defEditedState = eState; + defEditedState = eState; } -void ThresholdAdjuster::resetPressed (GdkEventButton* event) { +void ThresholdAdjuster::resetPressed (GdkEventButton* event) +{ - if (editedState!=Irrelevant) { - editedState = defEditedState; - if (editedCheckBox) { - editedChange.block (true); - editedCheckBox->set_active (defEditedState==Edited); - editedChange.block (false); - } - refreshLabelStyle (); - } - afterReset = true; - if ((event != NULL) && (event->state & GDK_CONTROL_MASK) && (event->button == 1)) - // CTRL pressed : resetting to current default value - tSelector.reset(); - else - // no modifier key or addMode=true : resetting to initial default value - tSelector.setPositions(initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT], - initialDefaultVal[ThresholdSelector::TS_TOPLEFT], - initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT], - initialDefaultVal[ThresholdSelector::TS_TOPRIGHT]); + if (editedState != Irrelevant) { + editedState = defEditedState; + + if (editedCheckBox) { + editedChange.block (true); + editedCheckBox->set_active (defEditedState == Edited); + editedChange.block (false); + } + + refreshLabelStyle (); + } + + afterReset = true; + + if ((event != NULL) && (event->state & GDK_CONTROL_MASK) && (event->button == 1)) + // CTRL pressed : resetting to current default value + { + tSelector.reset(); + } else + // no modifier key or addMode=true : resetting to initial default value + tSelector.setPositions(initialDefaultVal[ThresholdSelector::TS_BOTTOMLEFT], + initialDefaultVal[ThresholdSelector::TS_TOPLEFT], + initialDefaultVal[ThresholdSelector::TS_BOTTOMRIGHT], + initialDefaultVal[ThresholdSelector::TS_TOPRIGHT]); } -double ThresholdAdjuster::shapeValue (double a) { +double ThresholdAdjuster::shapeValue (double a) +{ - unsigned int digit = tSelector.getPrecision(); - return round(a*pow(double(10), digit)) / pow(double(10), digit); + unsigned int digit = tSelector.getPrecision(); + return round(a * pow(double(10), digit)) / pow(double(10), digit); } -void ThresholdAdjuster::selectorChanged () { +void ThresholdAdjuster::selectorChanged () +{ - if (delayConnection.connected()) - delayConnection.disconnect (); + if (delayConnection.connected()) { + delayConnection.disconnect (); + } - if (delay==0) { - if (adjusterListener && !blocked) - sendToListener (); - } - else - delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ThresholdAdjuster::notifyListener), delay); + if (delay == 0) { + if (adjusterListener && !blocked) { + sendToListener (); + } + } else { + delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ThresholdAdjuster::notifyListener), delay); + } - if (!afterReset && editedState==UnEdited) { - editedState = Edited; - if (editedCheckBox) { - editedChange.block (true); - editedCheckBox->set_active (true); - editedChange.block (false); - } - refreshLabelStyle (); - } - afterReset = false; + if (!afterReset && editedState == UnEdited) { + editedState = Edited; + + if (editedCheckBox) { + editedChange.block (true); + editedCheckBox->set_active (true); + editedChange.block (false); + } + + refreshLabelStyle (); + } + + afterReset = false; } -void ThresholdAdjuster::setValue (double bottom, double top) { +void ThresholdAdjuster::setValue (double bottom, double top) +{ - selectorChange.block (true); - tSelector.setPositions(bottom, top); - selectorChange.block (false); - afterReset = false; + selectorChange.block (true); + tSelector.setPositions(bottom, top); + selectorChange.block (false); + afterReset = false; } -void ThresholdAdjuster::setValue (double bottomLeft, double topLeft, double bottomRight, double topRight) { +void ThresholdAdjuster::setValue (double bottomLeft, double topLeft, double bottomRight, double topRight) +{ - selectorChange.block (true); - tSelector.setPositions(bottomLeft, topLeft, bottomRight, topRight); - selectorChange.block (false); - afterReset = false; + selectorChange.block (true); + tSelector.setPositions(bottomLeft, topLeft, bottomRight, topRight); + selectorChange.block (false); + afterReset = false; } -void ThresholdAdjuster::getValue (double& bottom, double& top) { - tSelector.getPositions (bottom, top); +void ThresholdAdjuster::getValue (double& bottom, double& top) +{ + tSelector.getPositions (bottom, top); } -void ThresholdAdjuster::getValue (double& bottomLeft, double& topLeft, double& bottomRight, double& topRight) { - tSelector.getPositions (bottomLeft, topLeft, bottomRight, topRight); +void ThresholdAdjuster::getValue (double& bottomLeft, double& topLeft, double& bottomRight, double& topRight) +{ + tSelector.getPositions (bottomLeft, topLeft, bottomRight, topRight); } -void ThresholdAdjuster::getValue (int& bottom, int& top) { - tSelector.getPositions (bottom, top); +void ThresholdAdjuster::getValue (int& bottom, int& top) +{ + tSelector.getPositions (bottom, top); } -void ThresholdAdjuster::getValue (int& bottomLeft, int& topLeft, int& bottomRight, int& topRight) { - tSelector.getPositions (bottomLeft, topLeft, bottomRight, topRight); +void ThresholdAdjuster::getValue (int& bottomLeft, int& topLeft, int& bottomRight, int& topRight) +{ + tSelector.getPositions (bottomLeft, topLeft, bottomRight, topRight); } -void ThresholdAdjuster::getValue (Glib::ustring& bottom, Glib::ustring& top) { - tSelector.getPositions (bottom, top); +void ThresholdAdjuster::getValue (Glib::ustring& bottom, Glib::ustring& top) +{ + tSelector.getPositions (bottom, top); } -void ThresholdAdjuster::getValue (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight) { - tSelector.getPositions (bottomLeft, topLeft, bottomRight, topRight); +void ThresholdAdjuster::getValue (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight) +{ + tSelector.getPositions (bottomLeft, topLeft, bottomRight, topRight); } -bool ThresholdAdjuster::notifyListener () { +bool ThresholdAdjuster::notifyListener () +{ - if (adjusterListener!=NULL && !blocked) { - GThreadLock lock; - sendToListener(); - } - return false; + if (adjusterListener != NULL && !blocked) { + GThreadLock lock; + sendToListener(); + } + + return false; } -void ThresholdAdjuster::setBgCurveProvider (ThresholdCurveProvider* provider) { - tSelector.setBgCurveProvider(provider); +void ThresholdAdjuster::setBgCurveProvider (ThresholdCurveProvider* provider) +{ + tSelector.setBgCurveProvider(provider); } -void ThresholdAdjuster::setEnabled (bool enabled) { +void ThresholdAdjuster::setEnabled (bool enabled) +{ - tSelector.set_sensitive (enabled); + tSelector.set_sensitive (enabled); } -void ThresholdAdjuster::setEditedState (EditedState eState) { +void ThresholdAdjuster::setEditedState (EditedState eState) +{ - if (editedState!=eState) { - if (editedCheckBox) { - editedChange.block (true); - editedCheckBox->set_active (eState==Edited); - editedChange.block (false); - } - editedState = eState; - refreshLabelStyle (); - } + if (editedState != eState) { + if (editedCheckBox) { + editedChange.block (true); + editedCheckBox->set_active (eState == Edited); + editedChange.block (false); + } + + editedState = eState; + refreshLabelStyle (); + } } -EditedState ThresholdAdjuster::getEditedState () { +EditedState ThresholdAdjuster::getEditedState () +{ - if (editedState!=Irrelevant && editedCheckBox) - editedState = editedCheckBox->get_active () ? Edited : UnEdited; - return editedState; + if (editedState != Irrelevant && editedCheckBox) { + editedState = editedCheckBox->get_active () ? Edited : UnEdited; + } + + return editedState; } -void ThresholdAdjuster::showEditedCB () { +void ThresholdAdjuster::showEditedCB () +{ - if (!editedCheckBox) { - editedCheckBox = Gtk::manage(new Gtk::CheckButton ()); - hbox->pack_start (*editedCheckBox, Gtk::PACK_SHRINK, 2); - hbox->reorder_child (*editedCheckBox, 0); - editedChange = editedCheckBox->signal_toggled().connect( sigc::mem_fun(*this, &ThresholdAdjuster::editedToggled) ); - } + if (!editedCheckBox) { + editedCheckBox = Gtk::manage(new Gtk::CheckButton ()); + hbox->pack_start (*editedCheckBox, Gtk::PACK_SHRINK, 2); + hbox->reorder_child (*editedCheckBox, 0); + editedChange = editedCheckBox->signal_toggled().connect( sigc::mem_fun(*this, &ThresholdAdjuster::editedToggled) ); + } } -void ThresholdAdjuster::refreshLabelStyle () { +void ThresholdAdjuster::refreshLabelStyle () +{ -/* Glib::RefPtr style = label->get_style (); - Pango::FontDescription fd = style->get_font (); - fd.set_weight (editedState==Edited ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL); - style->set_font (fd); - label->set_style (style); - label->queue_draw ();*/ + /* Glib::RefPtr style = label->get_style (); + Pango::FontDescription fd = style->get_font (); + fd.set_weight (editedState==Edited ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL); + style->set_font (fd); + label->set_style (style); + label->queue_draw ();*/ } -void ThresholdAdjuster::editedToggled () { - - if (adjusterListener && !blocked) - sendToListener (); +void ThresholdAdjuster::editedToggled () +{ + + if (adjusterListener && !blocked) { + sendToListener (); + } } -void ThresholdAdjuster::sendToListener () { - if (tSelector.getPrecision() > 0) { - // if precision is >0, then we assume that the listener is waiting for doubles - rtengine::procparams::Threshold t = tSelector.getPositions(); - if (tSelector.isDouble()){ - adjusterListener->adjusterChanged (this, t.value[0], t.value[1], t.value[2], t.value[3]); - adjusterListener->adjusterChanged2 (this, t.value[0], t.value[1], t.value[2], t.value[3]); - } - else - adjusterListener->adjusterChanged (this, t.value[0], t.value[1]); - } - else { - // if precision is equal to 0, then we assume that the listener is waiting for integers - rtengine::procparams::Threshold t = tSelector.getPositions(); - if (tSelector.isDouble()){ - adjusterListener->adjusterChanged (this, t.value[0], t.value[1], t.value[2], t.value[3]); - adjusterListener->adjusterChanged2 (this, t.value[0], t.value[1], t.value[2], t.value[3]); - } - else - adjusterListener->adjusterChanged (this, t.value[0], t.value[1]); - } +void ThresholdAdjuster::sendToListener () +{ + if (tSelector.getPrecision() > 0) { + // if precision is >0, then we assume that the listener is waiting for doubles + rtengine::procparams::Threshold t = tSelector.getPositions(); + + if (tSelector.isDouble()) { + adjusterListener->adjusterChanged (this, t.value[0], t.value[1], t.value[2], t.value[3]); + adjusterListener->adjusterChanged2 (this, t.value[0], t.value[1], t.value[2], t.value[3]); + } else { + adjusterListener->adjusterChanged (this, t.value[0], t.value[1]); + } + } else { + // if precision is equal to 0, then we assume that the listener is waiting for integers + rtengine::procparams::Threshold t = tSelector.getPositions(); + + if (tSelector.isDouble()) { + adjusterListener->adjusterChanged (this, t.value[0], t.value[1], t.value[2], t.value[3]); + adjusterListener->adjusterChanged2 (this, t.value[0], t.value[1], t.value[2], t.value[3]); + } else { + adjusterListener->adjusterChanged (this, t.value[0], t.value[1]); + } + } } -void ThresholdAdjuster::set_tooltip_markup(const Glib::ustring& markup) { - tSelector.set_tooltip_markup(markup); +void ThresholdAdjuster::set_tooltip_markup(const Glib::ustring& markup) +{ + tSelector.set_tooltip_markup(markup); } -void ThresholdAdjuster::set_tooltip_text(const Glib::ustring& text) { - tSelector.set_tooltip_text(text); +void ThresholdAdjuster::set_tooltip_text(const Glib::ustring& text) +{ + tSelector.set_tooltip_text(text); } /* For better readability, this method create the history string of the parameter column, @@ -334,15 +377,15 @@ void ThresholdAdjuster::set_tooltip_text(const Glib::ustring& text) { * * If separatedMode==true, the top slider is assumed to be the primary slider, then the bottom slider as the second one */ -Glib::ustring ThresholdAdjuster::getHistoryString () { - if (tSelector.isDouble()) { - Glib::ustring bl, tl, br, tr; - tSelector.getPositions(bl, tl, br, tr); - return Glib::ustring::compose(tSelector.isStartAtOne()?"%2, %1, %3, %4":"%1, %2, %4, %3", bl, tl, br, tr); - } - else { - Glib::ustring b, t; - tSelector.getPositions(b, t); - return Glib::ustring::compose(tSelector.isStartAtOne()||separatedMode?"%2, %1":"%1, %2", b, t); - } +Glib::ustring ThresholdAdjuster::getHistoryString () +{ + if (tSelector.isDouble()) { + Glib::ustring bl, tl, br, tr; + tSelector.getPositions(bl, tl, br, tr); + return Glib::ustring::compose(tSelector.isStartAtOne() ? "%2, %1, %3, %4" : "%1, %2, %4, %3", bl, tl, br, tr); + } else { + Glib::ustring b, t; + tSelector.getPositions(b, t); + return Glib::ustring::compose(tSelector.isStartAtOne() || separatedMode ? "%2, %1" : "%1, %2", b, t); + } } diff --git a/rtgui/thresholdadjuster.h b/rtgui/thresholdadjuster.h index 3967223f1..99e4efd44 100644 --- a/rtgui/thresholdadjuster.h +++ b/rtgui/thresholdadjuster.h @@ -7,7 +7,7 @@ * 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 @@ -29,109 +29,136 @@ class ThresholdAdjuster; /* * TODO: Maybe we could just send back the history string instead of the individual values? */ -class ThresholdAdjusterListener { +class ThresholdAdjusterListener +{ - public: - // to be used by listener that has created a ThresholdAdjuster with with single threshold and precision > 0 +public: + // to be used by listener that has created a ThresholdAdjuster with with single threshold and precision > 0 virtual void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop) {} - // to be used by listener that has created a ThresholdAdjuster with with double threshold and precision > 0 + // to be used by listener that has created a ThresholdAdjuster with with double threshold and precision > 0 virtual void adjusterChanged (ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {} - // to be used by listener that has created a ThresholdAdjuster with with single threshold and precision == 0 + // to be used by listener that has created a ThresholdAdjuster with with single threshold and precision == 0 virtual void adjusterChanged (ThresholdAdjuster* a, int newBottom, int newTop) {} - // to be used by listener that has created a ThresholdAdjuster with with double threshold and precision == 0 + // to be used by listener that has created a ThresholdAdjuster with with double threshold and precision == 0 virtual void adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {} - virtual void adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) {} + virtual void adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) {} }; -class ThresholdAdjuster : public Gtk::VBox { +class ThresholdAdjuster : public Gtk::VBox +{ - protected: - Gtk::HBox* hbox; - Gtk::Label* label; - ThresholdSelector tSelector; - //MySpinButton* spin; - Gtk::Button* reset; - ThresholdAdjusterListener* adjusterListener; - sigc::connection delayConnection; - //sigc::connection spinChange; - sigc::connection selectorChange; - sigc::connection editedChange; - bool listenerReady; - double initialDefaultVal[4]; // default value at construction time - EditedState editedState; - EditedState defEditedState; - Gtk::CheckButton* editedCheckBox; - bool afterReset; - bool blocked; - bool addMode; - bool separatedMode; - int delay; +protected: + Gtk::HBox* hbox; + Gtk::Label* label; + ThresholdSelector tSelector; + //MySpinButton* spin; + Gtk::Button* reset; + ThresholdAdjusterListener* adjusterListener; + sigc::connection delayConnection; + //sigc::connection spinChange; + sigc::connection selectorChange; + sigc::connection editedChange; + bool listenerReady; + double initialDefaultVal[4]; // default value at construction time + EditedState editedState; + EditedState defEditedState; + Gtk::CheckButton* editedCheckBox; + bool afterReset; + bool blocked; + bool addMode; + bool separatedMode; + int delay; - double shapeValue (double a); - void refreshLabelStyle (); - void initObject (Glib::ustring label, bool editedcb); - void sendToListener (); + double shapeValue (double a); + void refreshLabelStyle (); + void initObject (Glib::ustring label, bool editedcb); + void sendToListener (); - public: +public: - // Custom Threshold widget with 2 cursors (Top and Bottom) and a custom curve provided by the instanciator, - // each cursor having his own range, default value and precision - ThresholdAdjuster (Glib::ustring label, - double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, - double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, - ThresholdCurveProvider* curveProvider, bool editedCheckBox=false); - // Simple Threshold widget with 2 linked sliders (0->1 or 1->0) - ThresholdAdjuster (Glib::ustring label, double minValue, double maxValue, double defBottom, - double defTop, unsigned int precision, bool startAtOne, bool editedCheckBox=false); - // Simple Threshold widget with 4 linked sliders by pairs (0->1->0 or 1->0->1) - ThresholdAdjuster (Glib::ustring label, double minValue, double maxValue, double defBottomLeft, - double defTopLeft, double defBottomRight, double defTopRight, unsigned int precision, - bool startAtOne, bool editedCheckBox=false); + // Custom Threshold widget with 2 cursors (Top and Bottom) and a custom curve provided by the instanciator, + // each cursor having his own range, default value and precision + ThresholdAdjuster (Glib::ustring label, + double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, + double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, + ThresholdCurveProvider* curveProvider, bool editedCheckBox = false); + // Simple Threshold widget with 2 linked sliders (0->1 or 1->0) + ThresholdAdjuster (Glib::ustring label, double minValue, double maxValue, double defBottom, + double defTop, unsigned int precision, bool startAtOne, bool editedCheckBox = false); + // Simple Threshold widget with 4 linked sliders by pairs (0->1->0 or 1->0->1) + ThresholdAdjuster (Glib::ustring label, double minValue, double maxValue, double defBottomLeft, + double defTopLeft, double defBottomRight, double defTopRight, unsigned int precision, + bool startAtOne, bool editedCheckBox = false); - virtual ~ThresholdAdjuster (); - void setAdjusterListener (ThresholdAdjusterListener* alistener) { adjusterListener = alistener; } + virtual ~ThresholdAdjuster (); + void setAdjusterListener (ThresholdAdjusterListener* alistener) + { + adjusterListener = alistener; + } - void setBgCurveProvider (ThresholdCurveProvider* provider); - ThresholdSelector* getThresholdSelector() { return &tSelector; }; + void setBgCurveProvider (ThresholdCurveProvider* provider); + ThresholdSelector* getThresholdSelector() + { + return &tSelector; + }; - template - rtengine::procparams::Threshold getValue () { - return tSelector.getPositions(); - } - void getValue (double& bottom, double& top); - void getValue (double& bottomLeft, double& topLeft, double& bottomRight, double& topRight); - void getValue (int& bottom, int& top); - void getValue (int& bottomLeft, int& topLeft, int& bottomRight, int& topRight); - void getValue (Glib::ustring& bottom, Glib::ustring& top); - void getValue (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight); - template - void setValue (const rtengine::procparams::Threshold &tValues) { tSelector.setPositions(tValues); } - void setValue (double bottom, double top); - void setValue (double bottomLeft, double topLeft, double bottomRight, double topRight); - void setEnabled (bool enabled); - template - void setDefault (const rtengine::procparams::Threshold &tresh) { tSelector.setDefaults(tresh); } - void setDefault (double defBottom, double defTop); - void setDefault (double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight); - void setEditedState (EditedState eState); - EditedState getEditedState (); - void setDefaultEditedState (EditedState eState); - void showEditedCB (); - void block(bool isBlocked) { blocked = isBlocked; } - void setBgGradient (const std::vector &milestones) { tSelector.setBgGradient (milestones); } - void setBgColorProvider (ColorProvider *cp, int i) { tSelector.setColorProvider(cp, i); } - void setUpdatePolicy (eUpdatePolicy policy) { tSelector.setUpdatePolicy(policy); } + template + rtengine::procparams::Threshold getValue () + { + return tSelector.getPositions(); + } + void getValue (double& bottom, double& top); + void getValue (double& bottomLeft, double& topLeft, double& bottomRight, double& topRight); + void getValue (int& bottom, int& top); + void getValue (int& bottomLeft, int& topLeft, int& bottomRight, int& topRight); + void getValue (Glib::ustring& bottom, Glib::ustring& top); + void getValue (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight); + template + void setValue (const rtengine::procparams::Threshold &tValues) + { + tSelector.setPositions(tValues); + } + void setValue (double bottom, double top); + void setValue (double bottomLeft, double topLeft, double bottomRight, double topRight); + void setEnabled (bool enabled); + template + void setDefault (const rtengine::procparams::Threshold &tresh) + { + tSelector.setDefaults(tresh); + } + void setDefault (double defBottom, double defTop); + void setDefault (double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight); + void setEditedState (EditedState eState); + EditedState getEditedState (); + void setDefaultEditedState (EditedState eState); + void showEditedCB (); + void block(bool isBlocked) + { + blocked = isBlocked; + } + void setBgGradient (const std::vector &milestones) + { + tSelector.setBgGradient (milestones); + } + void setBgColorProvider (ColorProvider *cp, int i) + { + tSelector.setColorProvider(cp, i); + } + void setUpdatePolicy (eUpdatePolicy policy) + { + tSelector.setUpdatePolicy(policy); + } - //void spinChanged (); - void selectorChanged (); - bool notifyListener (); - void resetPressed (GdkEventButton* event); - void editedToggled (); - Glib::ustring getHistoryString (); - void set_tooltip_markup(const Glib::ustring& markup); - // this set_tooltip_text method is to set_tooltip_markup, and text can contain markups - void set_tooltip_text(const Glib::ustring& text); + //void spinChanged (); + void selectorChanged (); + bool notifyListener (); + void resetPressed (GdkEventButton* event); + void editedToggled (); + Glib::ustring getHistoryString (); + void set_tooltip_markup(const Glib::ustring& markup); + // this set_tooltip_text method is to set_tooltip_markup, and text can contain markups + void set_tooltip_text(const Glib::ustring& text); }; #endif diff --git a/rtgui/thresholdselector.cc b/rtgui/thresholdselector.cc index b87233fe8..80a961292 100644 --- a/rtgui/thresholdselector.cc +++ b/rtgui/thresholdselector.cc @@ -7,7 +7,7 @@ * 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 @@ -23,673 +23,774 @@ #include "mycurve.h" ThresholdSelector::ThresholdSelector(double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, - double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, - ThresholdCurveProvider* curveProvider) - : ColoredBar(RTO_Left2Right) + double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, + ThresholdCurveProvider* curveProvider) + : ColoredBar(RTO_Left2Right) { - positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottom; - positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTop; - positions[TS_BOTTOMRIGHT] = defPos[TS_BOTTOMRIGHT] = 0; // unused - positions[TS_TOPRIGHT] = defPos[TS_TOPRIGHT] = 0; // unused - this->precisionTop = precisionTop; - this->precisionBottom = precisionBottom; - doubleThresh = false; + positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottom; + positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTop; + positions[TS_BOTTOMRIGHT] = defPos[TS_BOTTOMRIGHT] = 0; // unused + positions[TS_TOPRIGHT] = defPos[TS_TOPRIGHT] = 0; // unused + this->precisionTop = precisionTop; + this->precisionBottom = precisionBottom; + doubleThresh = false; - separatedLabelBottom = labelBottom; - separatedLabelTop = labelTop; + separatedLabelBottom = labelBottom; + separatedLabelTop = labelTop; - bgCurveProvider = curveProvider; - separatedSliders = true; - initalEq1 = false; // unused - minValBottom = minValueBottom; - maxValBottom = maxValueBottom; - minValTop = minValueTop; - maxValTop = maxValueTop; + bgCurveProvider = curveProvider; + separatedSliders = true; + initalEq1 = false; // unused + minValBottom = minValueBottom; + maxValBottom = maxValueBottom; + minValTop = minValueTop; + maxValTop = maxValueTop; - initValues (); + initValues (); } ThresholdSelector::ThresholdSelector(double minValue, double maxValue, double defBottom, - double defTop, unsigned int precision, bool startAtOne) - : ColoredBar(RTO_Left2Right) + double defTop, unsigned int precision, bool startAtOne) + : ColoredBar(RTO_Left2Right) { - positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottom; - positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTop; - positions[TS_BOTTOMRIGHT] = defPos[TS_BOTTOMRIGHT] = maxValue; - positions[TS_TOPRIGHT] = defPos[TS_TOPRIGHT] = maxValue; - this->precisionTop = precision; - this->precisionBottom = precision; - doubleThresh = false; + positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottom; + positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTop; + positions[TS_BOTTOMRIGHT] = defPos[TS_BOTTOMRIGHT] = maxValue; + positions[TS_TOPRIGHT] = defPos[TS_TOPRIGHT] = maxValue; + this->precisionTop = precision; + this->precisionBottom = precision; + doubleThresh = false; - separatedLabelBottom = ""; - separatedLabelTop = ""; + separatedLabelBottom = ""; + separatedLabelTop = ""; #ifndef NDEBUG - if (startAtOne) { - assert (defBottom >= defTop); - assert (defTop >= minValue); - assert (defBottom <= maxValue); - } - else { - assert (defTop >= defBottom); - assert (defBottom >= minValue); - assert (defTop <= maxValue); - } - assert(minValue < maxValue); + + if (startAtOne) { + assert (defBottom >= defTop); + assert (defTop >= minValue); + assert (defBottom <= maxValue); + } else { + assert (defTop >= defBottom); + assert (defBottom >= minValue); + assert (defTop <= maxValue); + } + + assert(minValue < maxValue); #endif - bgCurveProvider = NULL; - separatedSliders = false; - initalEq1 = startAtOne; - minValTop = minValBottom = minValue; - maxValTop = maxValBottom = maxValue; + bgCurveProvider = NULL; + separatedSliders = false; + initalEq1 = startAtOne; + minValTop = minValBottom = minValue; + maxValTop = maxValBottom = maxValue; - initValues (); + initValues (); } ThresholdSelector::ThresholdSelector(double minValue, double maxValue, double defBottomLeft, double defTopLeft, - double defBottomRight, double defTopRight, unsigned int precision, bool startAtOne) - : ColoredBar(RTO_Left2Right) + double defBottomRight, double defTopRight, unsigned int precision, bool startAtOne) + : ColoredBar(RTO_Left2Right) { - positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottomLeft; - positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTopLeft; - positions[TS_BOTTOMRIGHT] = defPos[TS_BOTTOMRIGHT] = defBottomRight; - positions[TS_TOPRIGHT] = defPos[TS_TOPRIGHT] = defTopRight; - this->precisionTop = precision; - this->precisionBottom = precision; - doubleThresh = true; + positions[TS_BOTTOMLEFT] = defPos[TS_BOTTOMLEFT] = defBottomLeft; + positions[TS_TOPLEFT] = defPos[TS_TOPLEFT] = defTopLeft; + positions[TS_BOTTOMRIGHT] = defPos[TS_BOTTOMRIGHT] = defBottomRight; + positions[TS_TOPRIGHT] = defPos[TS_TOPRIGHT] = defTopRight; + this->precisionTop = precision; + this->precisionBottom = precision; + doubleThresh = true; - separatedLabelBottom = ""; - separatedLabelTop = ""; + separatedLabelBottom = ""; + separatedLabelTop = ""; #ifndef NDEBUG - if (startAtOne) { - assert (minValue <= defTopLeft); - assert (defTopLeft <= defBottomLeft); - assert (defBottomLeft <= defBottomRight); - assert (defBottomRight <= defTopRight); - assert (defTopRight <= maxValue); - } - else { - assert (minValue <= defBottomLeft); - assert (defBottomLeft <= defTopLeft); - assert (defTopLeft <= defTopRight); - assert (defTopRight <= defBottomRight); - assert (defBottomRight <= maxValue); - } - assert(minValue < maxValue); + + if (startAtOne) { + assert (minValue <= defTopLeft); + assert (defTopLeft <= defBottomLeft); + assert (defBottomLeft <= defBottomRight); + assert (defBottomRight <= defTopRight); + assert (defTopRight <= maxValue); + } else { + assert (minValue <= defBottomLeft); + assert (defBottomLeft <= defTopLeft); + assert (defTopLeft <= defTopRight); + assert (defTopRight <= defBottomRight); + assert (defBottomRight <= maxValue); + } + + assert(minValue < maxValue); #endif - bgCurveProvider = NULL; - separatedSliders = false; - initalEq1 = startAtOne; - minValTop = minValBottom = minValue; - maxValTop = maxValBottom = maxValue; + bgCurveProvider = NULL; + separatedSliders = false; + initalEq1 = startAtOne; + minValTop = minValBottom = minValue; + maxValTop = maxValBottom = maxValue; - initValues (); + initValues (); } -void ThresholdSelector::initValues () { +void ThresholdSelector::initValues () +{ - updatePolicy = RTUP_STATIC; - additionalTTip = ""; - oldLitCursor = litCursor = TS_UNDEFINED; - movedCursor = TS_UNDEFINED; - secondaryMovedCursor = TS_UNDEFINED; - set_size_request (-1, 30); - add_events(Gdk::LEAVE_NOTIFY_MASK); - set_name("ThresholdSelector"); - set_can_focus(false); - set_app_paintable(true); - setDirty(true); - updateTooltip(); + updatePolicy = RTUP_STATIC; + additionalTTip = ""; + oldLitCursor = litCursor = TS_UNDEFINED; + movedCursor = TS_UNDEFINED; + secondaryMovedCursor = TS_UNDEFINED; + set_size_request (-1, 30); + add_events(Gdk::LEAVE_NOTIFY_MASK); + set_name("ThresholdSelector"); + set_can_focus(false); + set_app_paintable(true); + setDirty(true); + updateTooltip(); } /* * Set the position of the sliders without telling it to the listener */ -void ThresholdSelector::setPositions (double bottom, double top) { +void ThresholdSelector::setPositions (double bottom, double top) +{ - setPositions(bottom, top, maxValBottom, maxValTop); - if (updatePolicy==RTUP_DYNAMIC) - setDirty(true); + setPositions(bottom, top, maxValBottom, maxValTop); + + if (updatePolicy == RTUP_DYNAMIC) { + setDirty(true); + } } /* * Set the position of the sliders without telling it to the listener */ -void ThresholdSelector::setPositions (double bottomLeft, double topLeft, double bottomRight, double topRight) { +void ThresholdSelector::setPositions (double bottomLeft, double topLeft, double bottomRight, double topRight) +{ - bool different = ( (positions[TS_TOPLEFT] != topLeft) || (positions[TS_TOPRIGHT] != topRight) || - (positions[TS_BOTTOMLEFT] != bottomLeft) || (positions[TS_BOTTOMRIGHT] != bottomRight) ); - positions[TS_BOTTOMLEFT] = bottomLeft; - positions[TS_TOPLEFT] = topLeft; - positions[TS_BOTTOMRIGHT] = bottomRight; - positions[TS_TOPRIGHT] = topRight; + bool different = ( (positions[TS_TOPLEFT] != topLeft) || (positions[TS_TOPRIGHT] != topRight) || + (positions[TS_BOTTOMLEFT] != bottomLeft) || (positions[TS_BOTTOMRIGHT] != bottomRight) ); + positions[TS_BOTTOMLEFT] = bottomLeft; + positions[TS_TOPLEFT] = topLeft; + positions[TS_BOTTOMRIGHT] = bottomRight; + positions[TS_TOPRIGHT] = topRight; - if (different) { - if (updatePolicy==RTUP_DYNAMIC) - setDirty(true); - sig_val_changed.emit(); - updateTooltip(); - queue_draw (); - } + if (different) { + if (updatePolicy == RTUP_DYNAMIC) { + setDirty(true); + } + + sig_val_changed.emit(); + updateTooltip(); + queue_draw (); + } } -void ThresholdSelector::setDefaults (double bottom, double top) { +void ThresholdSelector::setDefaults (double bottom, double top) +{ - setDefaults(bottom, top, maxValBottom, maxValTop); + setDefaults(bottom, top, maxValBottom, maxValTop); } -void ThresholdSelector::setDefaults (double bottomLeft, double topLeft, double bottomRight, double topRight) { +void ThresholdSelector::setDefaults (double bottomLeft, double topLeft, double bottomRight, double topRight) +{ - defPos[TS_BOTTOMLEFT] = bottomLeft; - defPos[TS_TOPLEFT] = topLeft; - if (doubleThresh) { - defPos[TS_BOTTOMRIGHT] = bottomRight; - defPos[TS_TOPRIGHT] = topRight; - } + defPos[TS_BOTTOMLEFT] = bottomLeft; + defPos[TS_TOPLEFT] = topLeft; + + if (doubleThresh) { + defPos[TS_BOTTOMRIGHT] = bottomRight; + defPos[TS_TOPRIGHT] = topRight; + } } -void ThresholdSelector::on_realize() { +void ThresholdSelector::on_realize() +{ - Gtk::DrawingArea::on_realize(); + Gtk::DrawingArea::on_realize(); - add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); } -bool ThresholdSelector::on_expose_event(GdkEventExpose* event) { +bool ThresholdSelector::on_expose_event(GdkEventExpose* event) +{ - Gdk::Color c; - Glib::RefPtr win = get_window(); - Cairo::RefPtr cr = win->create_cairo_context(); + Gdk::Color c; + Glib::RefPtr win = get_window(); + Cairo::RefPtr cr = win->create_cairo_context(); - double positions01[4]; - int w = get_width (); - int h = get_height (); + double positions01[4]; + int w = get_width (); + int h = get_height (); - wslider = std::max(int(h / 5), 10); - int hwslider = wslider/2; - int iw = w-wslider-2*hb; // inner width (excluding padding for sliders) + wslider = std::max(int(h / 5), 10); + int hwslider = wslider / 2; + int iw = w - wslider - 2 * hb; // inner width (excluding padding for sliders) - positions01[TS_BOTTOMLEFT] = to01(TS_BOTTOMLEFT); - positions01[TS_TOPLEFT] = to01(TS_TOPLEFT); - positions01[TS_BOTTOMRIGHT] = to01(TS_BOTTOMRIGHT); - positions01[TS_TOPRIGHT] = to01(TS_TOPRIGHT); + positions01[TS_BOTTOMLEFT] = to01(TS_BOTTOMLEFT); + positions01[TS_TOPLEFT] = to01(TS_TOPLEFT); + positions01[TS_BOTTOMRIGHT] = to01(TS_BOTTOMRIGHT); + positions01[TS_TOPRIGHT] = to01(TS_TOPRIGHT); - Gtk::StateType state = !is_sensitive() ? Gtk::STATE_INSENSITIVE : Gtk::STATE_NORMAL; - Glib::RefPtr style = get_style(); + Gtk::StateType state = !is_sensitive() ? Gtk::STATE_INSENSITIVE : Gtk::STATE_NORMAL; + Glib::RefPtr style = get_style(); - // set the box's colors - cr->set_line_width (1.0); - cr->set_line_cap(Cairo::LINE_CAP_BUTT); - if (is_sensitive() && canGetColors()) { - // gradient background - Glib::RefPtr win = get_window(); - // this will eventually create/update the off-screen Surface - setDrawRectangle(win, hb+hwslider, int(float(h)*1.5f/7.f+0.5f), iw+1, int(float(h)*4.f/7.f+0.5f)); - // that we're displaying here - ColoredBar::expose(win); - } - else { - // solid background - c = style->get_bg (state); - if (state==Gtk::STATE_INSENSITIVE) - cr->set_source_rgb (c.get_red_p()*0.96, c.get_green_p()*0.96, c.get_blue_p()*0.96); - else - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); + // set the box's colors + cr->set_line_width (1.0); + cr->set_line_cap(Cairo::LINE_CAP_BUTT); - // draw the box's background - cr->rectangle (hb+hwslider-0.5, double(int(float(h)*1.5f/7.f))+0.5, iw+1, double(int(float(h)*4.f/7.f))); - cr->fill(); - } + if (is_sensitive() && canGetColors()) { + // gradient background + Glib::RefPtr win = get_window(); + // this will eventually create/update the off-screen Surface + setDrawRectangle(win, hb + hwslider, int(float(h) * 1.5f / 7.f + 0.5f), iw + 1, int(float(h) * 4.f / 7.f + 0.5f)); + // that we're displaying here + ColoredBar::expose(win); + } else { + // solid background + c = style->get_bg (state); - // draw curve + if (state == Gtk::STATE_INSENSITIVE) { + cr->set_source_rgb (c.get_red_p() * 0.96, c.get_green_p() * 0.96, c.get_blue_p() * 0.96); + } else { + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } - if (bgCurveProvider) { - double yStart = double(int(float(h)*5.5f/7.f))-0.5; - double yEnd = double(int(float(h)*1.5f/7.f))+1.5; + // draw the box's background + cr->rectangle (hb + hwslider - 0.5, double(int(float(h) * 1.5f / 7.f)) + 0.5, iw + 1, double(int(float(h) * 4.f / 7.f))); + cr->fill(); + } - std::vector pts = bgCurveProvider->getCurvePoints(this); // the values sent by the provider are not checked (assumed to be correct) - if (pts.size() >= 4) { - std::vector::iterator i=pts.begin(); - double x = *i; i++; - double y = *i; i++; - cr->move_to (hb+hwslider+iw*x+0.5, (yEnd-yStart)*y+yStart); + // draw curve - for (; iline_to (hb+hwslider+iw*x+0.5, (yEnd-yStart)*y+yStart); - } - } - else { - // Draw a straight line because not enough points has been sent - double yStart = double(int(float(h)*5.5f/7.f))-0.5; - cr->move_to (hb+hwslider+0.5, yStart); - cr->line_to (hb+hwslider+iw+0.5, yStart); - } + if (bgCurveProvider) { + double yStart = double(int(float(h) * 5.5f / 7.f)) - 0.5; + double yEnd = double(int(float(h) * 1.5f / 7.f)) + 1.5; - } - else { - if (!separatedSliders) { - double yStart = initalEq1 ? double(int(float(h)*1.5f/7.f))+1.5 : double(int(float(h)*5.5f/7.f))-0.5; - double yEnd = initalEq1 ? double(int(float(h)*5.5f/7.f))-0.5 : double(int(float(h)*1.5f/7.f))+1.5; - ThreshCursorId p[4]; - if (initalEq1) { p[0] = TS_TOPLEFT; p[1] = TS_BOTTOMLEFT; p[2] = TS_BOTTOMRIGHT; p[3] = TS_TOPRIGHT; } - else { p[0] = TS_BOTTOMLEFT; p[1] = TS_TOPLEFT; p[2] = TS_TOPRIGHT; p[3] = TS_BOTTOMRIGHT; } - if (positions[p[1]] > minValTop) // we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same - cr->move_to (hb+hwslider, yStart); - else - cr->move_to (hb+hwslider, yEnd); - if (positions[p[0]] > minValTop) - cr->line_to (hb+hwslider+iw*positions01[p[0]]+0.5, yStart); - if (positions[p[1]] > minValTop) - cr->line_to (hb+hwslider+iw*positions01[p[1]]+0.5, yEnd); - cr->line_to (hb+hwslider+iw*positions01[p[2]]+0.5, yEnd); - if (doubleThresh && positions[p[2]] < maxValTop) { - cr->line_to (hb+hwslider+iw*positions01[p[3]]+0.5, yStart); - if (positions[p[3]] < maxValTop) - cr->line_to (hb+hwslider+iw+0.5, yStart); - } - } - } - if (is_sensitive() && bgGradient.size()>1) { - // draw surrounding curve - c = style->get_bg (state); - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); - cr->set_line_width (5.0); - cr->stroke_preserve(); - } - // draw curve - if (is_sensitive()) { - c = style->get_fg (movedCursor!=TS_UNDEFINED || litCursor!=TS_UNDEFINED ? Gtk::STATE_PRELIGHT : Gtk::STATE_ACTIVE); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - else { - c = style->get_bg (Gtk::STATE_INSENSITIVE); - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); - } - cr->set_line_width (1.5); - cr->stroke (); + std::vector pts = bgCurveProvider->getCurvePoints(this); // the values sent by the provider are not checked (assumed to be correct) - // draw the box's borders - cr->set_line_width (1.); - cr->rectangle (hb+hwslider-0.5, double(int(float(h)*1.5f/7.f))+0.5, iw+1, double(int(float(h)*4.f/7.f))); - c = style->get_bg (state); - if (state==Gtk::STATE_INSENSITIVE) - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); - else - cr->set_source_rgb (c.get_red_p()*0.7, c.get_green_p()*0.7, c.get_blue_p()*0.7); - cr->stroke (); + if (pts.size() >= 4) { + std::vector::iterator i = pts.begin(); + double x = *i; + i++; + double y = *i; + i++; + cr->move_to (hb + hwslider + iw * x + 0.5, (yEnd - yStart)*y + yStart); - // draw sliders - //if (!(litCursor == TS_UNDEFINED && movedCursor == TS_UNDEFINED)) { - //cr->set_line_width (1.); - for (int i=0; i<(doubleThresh?4:2); i++) { - double posX = hb+hwslider+iw*positions01[i]+0.5; - double arrowY = i==0 || i==2 ? h-(h*2.5/7.-0.5)-vb : h*2.5/7.-0.5+vb; - double baseY = i==0 || i==2 ? h-0.5-vb : 0.5+vb; - double centerY = (arrowY+baseY)/2.; - cr->move_to (posX, arrowY); - cr->line_to (posX+hwslider, centerY); - cr->line_to (posX+hwslider, baseY); - cr->line_to (posX-hwslider, baseY); - cr->line_to (posX-hwslider, centerY); - cr->close_path(); - if (i==movedCursor) { - // moved (selected) - c = style->get_bg (Gtk::STATE_SELECTED); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->fill_preserve (); - //c = style->get_dark (Gtk::STATE_SELECTED); - //cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - c = style->get_bg (state); - cr->set_source_rgb (c.get_red_p()*0.55, c.get_green_p()*0.55, c.get_blue_p()*0.55); - cr->stroke (); - } - else if (i==secondaryMovedCursor || (movedCursor==TS_UNDEFINED && i==litCursor)) { - // prelight - c = style->get_bg (Gtk::STATE_PRELIGHT); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->fill_preserve (); - c = style->get_bg (state); - cr->set_source_rgb (c.get_red_p()*0.55, c.get_green_p()*0.55, c.get_blue_p()*0.55); - cr->stroke (); - } - else { - // normal - c = style->get_bg (is_sensitive() ? Gtk::STATE_ACTIVE : Gtk::STATE_INSENSITIVE); - cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cr->fill_preserve (); - c = style->get_bg (state); - if (state==Gtk::STATE_INSENSITIVE) - cr->set_source_rgb (c.get_red_p()*0.85, c.get_green_p()*0.85, c.get_blue_p()*0.85); - else - cr->set_source_rgb (c.get_red_p()*0.7, c.get_green_p()*0.7, c.get_blue_p()*0.7); - cr->stroke (); - } - } - //} + for (; i < pts.end(); ) { + x = *i; + i++; + y = *i; + i++; + cr->line_to (hb + hwslider + iw * x + 0.5, (yEnd - yStart)*y + yStart); + } + } else { + // Draw a straight line because not enough points has been sent + double yStart = double(int(float(h) * 5.5f / 7.f)) - 0.5; + cr->move_to (hb + hwslider + 0.5, yStart); + cr->line_to (hb + hwslider + iw + 0.5, yStart); + } - return true; + } else { + if (!separatedSliders) { + double yStart = initalEq1 ? double(int(float(h) * 1.5f / 7.f)) + 1.5 : double(int(float(h) * 5.5f / 7.f)) - 0.5; + double yEnd = initalEq1 ? double(int(float(h) * 5.5f / 7.f)) - 0.5 : double(int(float(h) * 1.5f / 7.f)) + 1.5; + ThreshCursorId p[4]; + + if (initalEq1) { + p[0] = TS_TOPLEFT; + p[1] = TS_BOTTOMLEFT; + p[2] = TS_BOTTOMRIGHT; + p[3] = TS_TOPRIGHT; + } else { + p[0] = TS_BOTTOMLEFT; + p[1] = TS_TOPLEFT; + p[2] = TS_TOPRIGHT; + p[3] = TS_BOTTOMRIGHT; + } + + if (positions[p[1]] > minValTop) { // we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same + cr->move_to (hb + hwslider, yStart); + } else { + cr->move_to (hb + hwslider, yEnd); + } + + if (positions[p[0]] > minValTop) { + cr->line_to (hb + hwslider + iw * positions01[p[0]] + 0.5, yStart); + } + + if (positions[p[1]] > minValTop) { + cr->line_to (hb + hwslider + iw * positions01[p[1]] + 0.5, yEnd); + } + + cr->line_to (hb + hwslider + iw * positions01[p[2]] + 0.5, yEnd); + + if (doubleThresh && positions[p[2]] < maxValTop) { + cr->line_to (hb + hwslider + iw * positions01[p[3]] + 0.5, yStart); + + if (positions[p[3]] < maxValTop) { + cr->line_to (hb + hwslider + iw + 0.5, yStart); + } + } + } + } + + if (is_sensitive() && bgGradient.size() > 1) { + // draw surrounding curve + c = style->get_bg (state); + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + cr->set_line_width (5.0); + cr->stroke_preserve(); + } + + // draw curve + if (is_sensitive()) { + c = style->get_fg (movedCursor != TS_UNDEFINED || litCursor != TS_UNDEFINED ? Gtk::STATE_PRELIGHT : Gtk::STATE_ACTIVE); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + } else { + c = style->get_bg (Gtk::STATE_INSENSITIVE); + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } + + cr->set_line_width (1.5); + cr->stroke (); + + // draw the box's borders + cr->set_line_width (1.); + cr->rectangle (hb + hwslider - 0.5, double(int(float(h) * 1.5f / 7.f)) + 0.5, iw + 1, double(int(float(h) * 4.f / 7.f))); + c = style->get_bg (state); + + if (state == Gtk::STATE_INSENSITIVE) { + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } else { + cr->set_source_rgb (c.get_red_p() * 0.7, c.get_green_p() * 0.7, c.get_blue_p() * 0.7); + } + + cr->stroke (); + + // draw sliders + //if (!(litCursor == TS_UNDEFINED && movedCursor == TS_UNDEFINED)) { + //cr->set_line_width (1.); + for (int i = 0; i < (doubleThresh ? 4 : 2); i++) { + double posX = hb + hwslider + iw * positions01[i] + 0.5; + double arrowY = i == 0 || i == 2 ? h - (h * 2.5 / 7. - 0.5) - vb : h * 2.5 / 7. - 0.5 + vb; + double baseY = i == 0 || i == 2 ? h - 0.5 - vb : 0.5 + vb; + double centerY = (arrowY + baseY) / 2.; + cr->move_to (posX, arrowY); + cr->line_to (posX + hwslider, centerY); + cr->line_to (posX + hwslider, baseY); + cr->line_to (posX - hwslider, baseY); + cr->line_to (posX - hwslider, centerY); + cr->close_path(); + + if (i == movedCursor) { + // moved (selected) + c = style->get_bg (Gtk::STATE_SELECTED); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->fill_preserve (); + //c = style->get_dark (Gtk::STATE_SELECTED); + //cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + c = style->get_bg (state); + cr->set_source_rgb (c.get_red_p() * 0.55, c.get_green_p() * 0.55, c.get_blue_p() * 0.55); + cr->stroke (); + } else if (i == secondaryMovedCursor || (movedCursor == TS_UNDEFINED && i == litCursor)) { + // prelight + c = style->get_bg (Gtk::STATE_PRELIGHT); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->fill_preserve (); + c = style->get_bg (state); + cr->set_source_rgb (c.get_red_p() * 0.55, c.get_green_p() * 0.55, c.get_blue_p() * 0.55); + cr->stroke (); + } else { + // normal + c = style->get_bg (is_sensitive() ? Gtk::STATE_ACTIVE : Gtk::STATE_INSENSITIVE); + cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p()); + cr->fill_preserve (); + c = style->get_bg (state); + + if (state == Gtk::STATE_INSENSITIVE) { + cr->set_source_rgb (c.get_red_p() * 0.85, c.get_green_p() * 0.85, c.get_blue_p() * 0.85); + } else { + cr->set_source_rgb (c.get_red_p() * 0.7, c.get_green_p() * 0.7, c.get_blue_p() * 0.7); + } + + cr->stroke (); + } + } + + //} + + return true; } -bool ThresholdSelector::on_button_press_event (GdkEventButton* event) { +bool ThresholdSelector::on_button_press_event (GdkEventButton* event) +{ - if (event->button == 1) { - movedCursor = litCursor; - findSecondaryMovedCursor(event->state); - tmpX = event->x; + if (event->button == 1) { + movedCursor = litCursor; + findSecondaryMovedCursor(event->state); + tmpX = event->x; - queue_draw (); - } - grab_focus(); - return true; + queue_draw (); + } + + grab_focus(); + return true; } -bool ThresholdSelector::on_button_release_event (GdkEventButton* event) { +bool ThresholdSelector::on_button_release_event (GdkEventButton* event) +{ - if (event->button == 1) { - findLitCursor(event->x, event->y); - movedCursor = TS_UNDEFINED; - secondaryMovedCursor = TS_UNDEFINED; - queue_draw (); - } - return true; + if (event->button == 1) { + findLitCursor(event->x, event->y); + movedCursor = TS_UNDEFINED; + secondaryMovedCursor = TS_UNDEFINED; + queue_draw (); + } + + return true; } -bool ThresholdSelector::on_leave_notify_event (GdkEventCrossing* event) { - if (movedCursor == TS_UNDEFINED) { - litCursor = TS_UNDEFINED; - oldLitCursor = TS_UNDEFINED; - queue_draw(); - } - return true; +bool ThresholdSelector::on_leave_notify_event (GdkEventCrossing* event) +{ + if (movedCursor == TS_UNDEFINED) { + litCursor = TS_UNDEFINED; + oldLitCursor = TS_UNDEFINED; + queue_draw(); + } + + return true; } -bool ThresholdSelector::on_motion_notify_event (GdkEventMotion* event) { +bool ThresholdSelector::on_motion_notify_event (GdkEventMotion* event) +{ - int w = get_width (); + int w = get_width (); - findLitCursor(event->x, event->y); + findLitCursor(event->x, event->y); - if (movedCursor != TS_UNDEFINED) { - // user is moving a cursor or two - double minBound, maxBound, dRange; + if (movedCursor != TS_UNDEFINED) { + // user is moving a cursor or two + double minBound, maxBound, dRange; - findSecondaryMovedCursor(event->state); + findSecondaryMovedCursor(event->state); - // computing the boundaries - findBoundaries(minBound, maxBound); + // computing the boundaries + findBoundaries(minBound, maxBound); - if (movedCursor==TS_BOTTOMLEFT || movedCursor==TS_BOTTOMRIGHT) - dRange = maxValBottom-minValBottom; - else - dRange = maxValTop-minValTop; - double dX = ( (event->x-tmpX)*dRange )/( w-2*hb ); - // slow motion if CTRL is pressed - if (event->state & Gdk::CONTROL_MASK) - dX *= 0.05; + if (movedCursor == TS_BOTTOMLEFT || movedCursor == TS_BOTTOMRIGHT) { + dRange = maxValBottom - minValBottom; + } else { + dRange = maxValTop - minValTop; + } - // get the new X value, inside bounds - double newX = positions[movedCursor] + dX; + double dX = ( (event->x - tmpX) * dRange ) / ( w - 2 * hb ); - if (newX > maxBound) newX = maxBound; - else if (newX < minBound) newX = minBound; + // slow motion if CTRL is pressed + if (event->state & Gdk::CONTROL_MASK) { + dX *= 0.05; + } - // compute the effective dX - dX = newX - positions[movedCursor]; - // set the new position of the moved cursor - positions[movedCursor] = newX; + // get the new X value, inside bounds + double newX = positions[movedCursor] + dX; - // apply the decay to the secondary moved cursor, if necessary - if (secondaryMovedCursor != TS_UNDEFINED) { - positions[secondaryMovedCursor] += dX; - } + if (newX > maxBound) { + newX = maxBound; + } else if (newX < minBound) { + newX = minBound; + } - // set the new reference value for the next move - tmpX = event->x; + // compute the effective dX + dX = newX - positions[movedCursor]; + // set the new position of the moved cursor + positions[movedCursor] = newX; - // ask to redraw the background - if (updatePolicy==RTUP_DYNAMIC) - setDirty(true); + // apply the decay to the secondary moved cursor, if necessary + if (secondaryMovedCursor != TS_UNDEFINED) { + positions[secondaryMovedCursor] += dX; + } - // update the tooltip - updateTooltip(); + // set the new reference value for the next move + tmpX = event->x; - sig_val_changed.emit(); + // ask to redraw the background + if (updatePolicy == RTUP_DYNAMIC) { + setDirty(true); + } - queue_draw (); - } - else { - if (litCursor != oldLitCursor) - queue_draw (); - oldLitCursor = litCursor; - } + // update the tooltip + updateTooltip(); + + sig_val_changed.emit(); + + queue_draw (); + } else { + if (litCursor != oldLitCursor) { + queue_draw (); + } + + oldLitCursor = litCursor; + } - return true; + return true; } -void ThresholdSelector::findLitCursor(int posX, int posY) { - int w = get_width (); - int h = get_height (); +void ThresholdSelector::findLitCursor(int posX, int posY) +{ + int w = get_width (); + int h = get_height (); - litCursor = TS_UNDEFINED; - if (posY >=0 && posY <= h/2) { - if (posX > 0 && posX < w) { - litCursor = TS_TOPLEFT; + litCursor = TS_UNDEFINED; - if (doubleThresh) { - // we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same - double cursorX = (posX-hb)*(maxValTop-minValTop)/(w-2*hb)+minValTop; + if (posY >= 0 && posY <= h / 2) { + if (posX > 0 && posX < w) { + litCursor = TS_TOPLEFT; - if (cursorX>positions[TS_TOPRIGHT] || abs(cursorX-positions[TS_TOPRIGHT]) < abs(cursorX-positions[TS_TOPLEFT])) - litCursor = TS_TOPRIGHT; - } - } - } - else if (posY > h/2 && posY < h) { - if (posX > 0 && posX < w) { - litCursor = TS_BOTTOMLEFT; - if (doubleThresh) { - // we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same - double cursorX = (posX-hb)*(maxValTop-minValTop)/(w-2*hb)+minValTop; + if (doubleThresh) { + // we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same + double cursorX = (posX - hb) * (maxValTop - minValTop) / (w - 2 * hb) + minValTop; - if (cursorX>positions[TS_BOTTOMRIGHT] || abs(cursorX-positions[TS_BOTTOMRIGHT]) < abs(cursorX-positions[TS_BOTTOMLEFT])) - litCursor = TS_BOTTOMRIGHT; - } - } - } + if (cursorX > positions[TS_TOPRIGHT] || abs(cursorX - positions[TS_TOPRIGHT]) < abs(cursorX - positions[TS_TOPLEFT])) { + litCursor = TS_TOPRIGHT; + } + } + } + } else if (posY > h / 2 && posY < h) { + if (posX > 0 && posX < w) { + litCursor = TS_BOTTOMLEFT; + + if (doubleThresh) { + // we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same + double cursorX = (posX - hb) * (maxValTop - minValTop) / (w - 2 * hb) + minValTop; + + if (cursorX > positions[TS_BOTTOMRIGHT] || abs(cursorX - positions[TS_BOTTOMRIGHT]) < abs(cursorX - positions[TS_BOTTOMLEFT])) { + litCursor = TS_BOTTOMRIGHT; + } + } + } + } } -void ThresholdSelector::findBoundaries(double &min, double &max) { +void ThresholdSelector::findBoundaries(double &min, double &max) +{ - switch (movedCursor) { - case (TS_BOTTOMLEFT): - if (separatedSliders) { - if (movedCursor == TS_BOTTOMLEFT) { - min = minValBottom; - max = maxValBottom; - } - else if (movedCursor == TS_TOPLEFT) { - min = minValTop; - max = maxValTop; - } - } - else if (initalEq1) { - min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPLEFT] : minValTop+(positions[TS_BOTTOMLEFT]-positions[TS_TOPLEFT]); - max = positions[TS_BOTTOMRIGHT]; - } - else { - min = minValTop; - max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPLEFT] : positions[TS_TOPRIGHT]-(positions[TS_TOPLEFT]-positions[TS_BOTTOMLEFT]); - } - break; - case (TS_TOPLEFT): - if (separatedSliders) { - if (movedCursor == TS_BOTTOMLEFT) { - min = minValBottom; - max = maxValBottom; - } - else if (movedCursor == TS_TOPLEFT) { - min = minValTop; - max = maxValTop; - } - } - else if (initalEq1) { - min = minValTop; - max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMLEFT] : positions[TS_BOTTOMRIGHT]-(positions[TS_BOTTOMLEFT]-positions[TS_TOPLEFT]); - } - else { - min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMLEFT] : minValTop+(positions[TS_TOPLEFT]-positions[TS_BOTTOMLEFT]); - max = positions[TS_TOPRIGHT]; - } - break; - case (TS_BOTTOMRIGHT): - if (initalEq1) { - min = positions[TS_BOTTOMLEFT]; - max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPRIGHT] : maxValTop-(positions[TS_TOPRIGHT]-positions[TS_BOTTOMRIGHT]); - } - else { - min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPRIGHT] : positions[TS_TOPLEFT]+(positions[TS_BOTTOMRIGHT]-positions[TS_TOPRIGHT]); - max = maxValTop; - } - break; - case (TS_TOPRIGHT): - if (initalEq1) { - min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMRIGHT] : positions[TS_BOTTOMLEFT]+(positions[TS_TOPRIGHT]-positions[TS_BOTTOMRIGHT]); - max = maxValTop; - } - else { - min = positions[TS_TOPLEFT]; - max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMRIGHT] : maxValTop-(positions[TS_BOTTOMRIGHT]-positions[TS_TOPRIGHT]); - } - break; - default: - min = minValTop; - max = maxValTop; - break; - } + switch (movedCursor) { + case (TS_BOTTOMLEFT): + if (separatedSliders) { + if (movedCursor == TS_BOTTOMLEFT) { + min = minValBottom; + max = maxValBottom; + } else if (movedCursor == TS_TOPLEFT) { + min = minValTop; + max = maxValTop; + } + } else if (initalEq1) { + min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPLEFT] : minValTop + (positions[TS_BOTTOMLEFT] - positions[TS_TOPLEFT]); + max = positions[TS_BOTTOMRIGHT]; + } else { + min = minValTop; + max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPLEFT] : positions[TS_TOPRIGHT] - (positions[TS_TOPLEFT] - positions[TS_BOTTOMLEFT]); + } + + break; + + case (TS_TOPLEFT): + if (separatedSliders) { + if (movedCursor == TS_BOTTOMLEFT) { + min = minValBottom; + max = maxValBottom; + } else if (movedCursor == TS_TOPLEFT) { + min = minValTop; + max = maxValTop; + } + } else if (initalEq1) { + min = minValTop; + max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMLEFT] : positions[TS_BOTTOMRIGHT] - (positions[TS_BOTTOMLEFT] - positions[TS_TOPLEFT]); + } else { + min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMLEFT] : minValTop + (positions[TS_TOPLEFT] - positions[TS_BOTTOMLEFT]); + max = positions[TS_TOPRIGHT]; + } + + break; + + case (TS_BOTTOMRIGHT): + if (initalEq1) { + min = positions[TS_BOTTOMLEFT]; + max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPRIGHT] : maxValTop - (positions[TS_TOPRIGHT] - positions[TS_BOTTOMRIGHT]); + } else { + min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_TOPRIGHT] : positions[TS_TOPLEFT] + (positions[TS_BOTTOMRIGHT] - positions[TS_TOPRIGHT]); + max = maxValTop; + } + + break; + + case (TS_TOPRIGHT): + if (initalEq1) { + min = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMRIGHT] : positions[TS_BOTTOMLEFT] + (positions[TS_TOPRIGHT] - positions[TS_BOTTOMRIGHT]); + max = maxValTop; + } else { + min = positions[TS_TOPLEFT]; + max = secondaryMovedCursor == TS_UNDEFINED ? positions[TS_BOTTOMRIGHT] : maxValTop - (positions[TS_BOTTOMRIGHT] - positions[TS_TOPRIGHT]); + } + + break; + + default: + min = minValTop; + max = maxValTop; + break; + } } -void ThresholdSelector::findSecondaryMovedCursor(guint state) { - secondaryMovedCursor = TS_UNDEFINED; - if (!separatedSliders && !(state & Gdk::SHIFT_MASK)) { - switch (movedCursor) { - case (TS_BOTTOMLEFT): - secondaryMovedCursor = TS_TOPLEFT; - break; - case (TS_TOPLEFT): - secondaryMovedCursor = TS_BOTTOMLEFT; - break; - case (TS_BOTTOMRIGHT): - secondaryMovedCursor = TS_TOPRIGHT; - break; - case (TS_TOPRIGHT): - secondaryMovedCursor = TS_BOTTOMRIGHT; - break; - default: - secondaryMovedCursor = TS_UNDEFINED; - break; - } - } +void ThresholdSelector::findSecondaryMovedCursor(guint state) +{ + secondaryMovedCursor = TS_UNDEFINED; + + if (!separatedSliders && !(state & Gdk::SHIFT_MASK)) { + switch (movedCursor) { + case (TS_BOTTOMLEFT): + secondaryMovedCursor = TS_TOPLEFT; + break; + + case (TS_TOPLEFT): + secondaryMovedCursor = TS_BOTTOMLEFT; + break; + + case (TS_BOTTOMRIGHT): + secondaryMovedCursor = TS_TOPRIGHT; + break; + + case (TS_TOPRIGHT): + secondaryMovedCursor = TS_BOTTOMRIGHT; + break; + + default: + secondaryMovedCursor = TS_UNDEFINED; + break; + } + } } -void ThresholdSelector::styleChanged (const Glib::RefPtr& style) { +void ThresholdSelector::styleChanged (const Glib::RefPtr& style) +{ - queue_draw (); + queue_draw (); } -void ThresholdSelector::reset () { +void ThresholdSelector::reset () +{ - positions[0] = defPos[0]; - positions[1] = defPos[1]; - positions[2] = defPos[2]; - positions[3] = defPos[3]; + positions[0] = defPos[0]; + positions[1] = defPos[1]; + positions[2] = defPos[2]; + positions[3] = defPos[3]; - if (updatePolicy==RTUP_DYNAMIC) - setDirty(true); + if (updatePolicy == RTUP_DYNAMIC) { + setDirty(true); + } - updateTooltip(); - queue_draw (); + updateTooltip(); + queue_draw (); } -double ThresholdSelector::to01(ThreshCursorId cursorId) { +double ThresholdSelector::to01(ThreshCursorId cursorId) +{ - double rVal; - if (cursorId==TS_BOTTOMLEFT || cursorId==TS_BOTTOMRIGHT) - rVal = (positions[cursorId]-minValBottom)/(maxValBottom-minValBottom); - else - rVal = (positions[cursorId]-minValTop)/(maxValTop-minValTop); - if (rVal < 0.) rVal = 0.; - else if (rVal > 1.) rVal = 1.; - return rVal; + double rVal; + + if (cursorId == TS_BOTTOMLEFT || cursorId == TS_BOTTOMRIGHT) { + rVal = (positions[cursorId] - minValBottom) / (maxValBottom - minValBottom); + } else { + rVal = (positions[cursorId] - minValTop) / (maxValTop - minValTop); + } + + if (rVal < 0.) { + rVal = 0.; + } else if (rVal > 1.) { + rVal = 1.; + } + + return rVal; } -void ThresholdSelector::setBgCurveProvider (ThresholdCurveProvider* provider) { - bgCurveProvider = provider; +void ThresholdSelector::setBgCurveProvider (ThresholdCurveProvider* provider) +{ + bgCurveProvider = provider; } -void ThresholdSelector::setSeparatedSliders(bool separated) { - separatedSliders = separated; +void ThresholdSelector::setSeparatedSliders(bool separated) +{ + separatedSliders = separated; } -bool ThresholdSelector::getSeparatedSliders() { - return separatedSliders; +bool ThresholdSelector::getSeparatedSliders() +{ + return separatedSliders; } -void ThresholdSelector::updateTooltip() { +void ThresholdSelector::updateTooltip() +{ - Glib::ustring tTip; - if (doubleThresh) { - tTip = Glib::ustring::compose("%1: %2 %3: %4\n%5: %6 %7: %8", - M("THRESHOLDSELECTOR_TL"), Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPLEFT]), - M("THRESHOLDSELECTOR_TR"), Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPRIGHT]), - M("THRESHOLDSELECTOR_BL"), Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMLEFT]), - M("THRESHOLDSELECTOR_BR"), Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMRIGHT]) - ); - if (!additionalTTip.empty()) - tTip += Glib::ustring::compose("\n\n%1", additionalTTip); - tTip += Glib::ustring::compose("\n\n%1", M("THRESHOLDSELECTOR_HINT")); - } - else if (separatedSliders) { - tTip = Glib::ustring::compose("%1: %2\n%3: %4", - separatedLabelTop, Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPLEFT]), - separatedLabelBottom, Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMLEFT]) - ); - if (!additionalTTip.empty()) - tTip += Glib::ustring::compose("\n\n%1", additionalTTip); - } - else { - tTip = Glib::ustring::compose("%1: %2\n%3: %4", - M("THRESHOLDSELECTOR_T"), Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPLEFT]), - M("THRESHOLDSELECTOR_B"), Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMLEFT]) - ); - if (!additionalTTip.empty()) - tTip += Glib::ustring::compose("\n\n%1", additionalTTip); - tTip += Glib::ustring::compose("\n\n%1", M("THRESHOLDSELECTOR_HINT")); - } - Gtk::Widget::set_tooltip_markup(tTip); + Glib::ustring tTip; + + if (doubleThresh) { + tTip = Glib::ustring::compose("%1: %2 %3: %4\n%5: %6 %7: %8", + M("THRESHOLDSELECTOR_TL"), Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPLEFT]), + M("THRESHOLDSELECTOR_TR"), Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPRIGHT]), + M("THRESHOLDSELECTOR_BL"), Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMLEFT]), + M("THRESHOLDSELECTOR_BR"), Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMRIGHT]) + ); + + if (!additionalTTip.empty()) { + tTip += Glib::ustring::compose("\n\n%1", additionalTTip); + } + + tTip += Glib::ustring::compose("\n\n%1", M("THRESHOLDSELECTOR_HINT")); + } else if (separatedSliders) { + tTip = Glib::ustring::compose("%1: %2\n%3: %4", + separatedLabelTop, Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPLEFT]), + separatedLabelBottom, Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMLEFT]) + ); + + if (!additionalTTip.empty()) { + tTip += Glib::ustring::compose("\n\n%1", additionalTTip); + } + } else { + tTip = Glib::ustring::compose("%1: %2\n%3: %4", + M("THRESHOLDSELECTOR_T"), Glib::ustring::format(std::fixed, std::setprecision(precisionTop), positions[TS_TOPLEFT]), + M("THRESHOLDSELECTOR_B"), Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), positions[TS_BOTTOMLEFT]) + ); + + if (!additionalTTip.empty()) { + tTip += Glib::ustring::compose("\n\n%1", additionalTTip); + } + + tTip += Glib::ustring::compose("\n\n%1", M("THRESHOLDSELECTOR_HINT")); + } + + Gtk::Widget::set_tooltip_markup(tTip); } -sigc::signal ThresholdSelector::signal_value_changed() { - return sig_val_changed; +sigc::signal ThresholdSelector::signal_value_changed() +{ + return sig_val_changed; } -double ThresholdSelector::shapePositionValue (ThreshCursorId cursorId) { - unsigned int precision = (cursorId==TS_BOTTOMLEFT || cursorId==TS_BOTTOMRIGHT) ? precisionBottom : precisionTop; - return round(positions[cursorId]*pow(double(10), precision)) / pow(double(10), precision); +double ThresholdSelector::shapePositionValue (ThreshCursorId cursorId) +{ + unsigned int precision = (cursorId == TS_BOTTOMLEFT || cursorId == TS_BOTTOMRIGHT) ? precisionBottom : precisionTop; + return round(positions[cursorId] * pow(double(10), precision)) / pow(double(10), precision); } -void ThresholdSelector::set_tooltip_markup(const Glib::ustring& markup) { - additionalTTip = markup; - updateTooltip(); +void ThresholdSelector::set_tooltip_markup(const Glib::ustring& markup) +{ + additionalTTip = markup; + updateTooltip(); } -void ThresholdSelector::set_tooltip_text(const Glib::ustring& text) { - additionalTTip = text; - updateTooltip(); +void ThresholdSelector::set_tooltip_text(const Glib::ustring& text) +{ + additionalTTip = text; + updateTooltip(); } diff --git a/rtgui/thresholdselector.h b/rtgui/thresholdselector.h index f4db16e2e..fabbfb9db 100644 --- a/rtgui/thresholdselector.h +++ b/rtgui/thresholdselector.h @@ -7,7 +7,7 @@ * 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 @@ -29,14 +29,15 @@ class ThresholdSelector; /* * This class let the instanciator to provide the background curve */ -class ThresholdCurveProvider { - public: - virtual ~ThresholdCurveProvider() {}; - /* - * The curve provider has to send back a list of point (at least 2 points) in the [0.0 ; 1.0] range - * for both X and Y axis; X and Y values are streamlined ( X1, Y1, X2, Y2, X3, Y3, ...) - */ - virtual std::vector getCurvePoints(ThresholdSelector* tAdjuster) const = 0; +class ThresholdCurveProvider +{ +public: + virtual ~ThresholdCurveProvider() {}; + /* + * The curve provider has to send back a list of point (at least 2 points) in the [0.0 ; 1.0] range + * for both X and Y axis; X and Y values are streamlined ( X1, Y1, X2, Y2, X3, Y3, ...) + */ + virtual std::vector getCurvePoints(ThresholdSelector* tAdjuster) const = 0; }; /* @@ -59,161 +60,183 @@ class ThresholdCurveProvider { * have to provide through the * */ -class ThresholdSelector : public Gtk::DrawingArea, public ColoredBar { +class ThresholdSelector : public Gtk::DrawingArea, public ColoredBar +{ - public: +public: - enum ThreshCursorId { - TS_UNDEFINED=-1, - TS_BOTTOMLEFT, - TS_TOPLEFT, - TS_BOTTOMRIGHT, - TS_TOPRIGHT - }; + enum ThreshCursorId { + TS_UNDEFINED = -1, + TS_BOTTOMLEFT, + TS_TOPLEFT, + TS_BOTTOMRIGHT, + TS_TOPRIGHT + }; - protected: +protected: - sigc::signal sig_val_changed; + sigc::signal sig_val_changed; - ThresholdCurveProvider* bgCurveProvider; + ThresholdCurveProvider* bgCurveProvider; - Glib::ustring additionalTTip; - Glib::ustring separatedLabelBottom; // Label for the bottom cursor, displayed if separatedSliders==true only - Glib::ustring separatedLabelTop; // Label for the top cursor, displayed if separatedSliders==true only - bool separatedSliders; // If true, the Top and Bottom sliders are totally separate and can be drag through the full range; for simple threshold only! - bool doubleThresh; // If true: there curve is a double threshold (0 to 1 to 0, or 1 to 0 to 1). - bool initalEq1; // If true: the curve start at 1 (top); if false: the curve start at 0 (bottom) - unsigned int precisionTop; // Decimal number if this object has to handle "double" values, for the Top slider - unsigned int precisionBottom; // Decimal number if this object has to handle "double" values, for the Bottom slider - ThreshCursorId litCursor; - ThreshCursorId oldLitCursor; - double boundary1[2], boundary2[2]; - double tmpX, tmpPos; + Glib::ustring additionalTTip; + Glib::ustring separatedLabelBottom; // Label for the bottom cursor, displayed if separatedSliders==true only + Glib::ustring separatedLabelTop; // Label for the top cursor, displayed if separatedSliders==true only + bool separatedSliders; // If true, the Top and Bottom sliders are totally separate and can be drag through the full range; for simple threshold only! + bool doubleThresh; // If true: there curve is a double threshold (0 to 1 to 0, or 1 to 0 to 1). + bool initalEq1; // If true: the curve start at 1 (top); if false: the curve start at 0 (bottom) + unsigned int precisionTop; // Decimal number if this object has to handle "double" values, for the Top slider + unsigned int precisionBottom; // Decimal number if this object has to handle "double" values, for the Bottom slider + ThreshCursorId litCursor; + ThreshCursorId oldLitCursor; + double boundary1[2], boundary2[2]; + double tmpX, tmpPos; - ThreshCursorId movedCursor, secondaryMovedCursor; - double minValTop, maxValTop; - double minValBottom, maxValBottom; - double defPos[4]; - double positions[4]; - unsigned short wslider; - eUpdatePolicy updatePolicy; + ThreshCursorId movedCursor, secondaryMovedCursor; + double minValTop, maxValTop; + double minValBottom, maxValBottom; + double defPos[4]; + double positions[4]; + unsigned short wslider; + eUpdatePolicy updatePolicy; - const static int hb = 3; // horizontal border - const static int vb = 2; // vertical border + const static int hb = 3; // horizontal border + const static int vb = 2; // vertical border - void initValues (); - void findLitCursor(int posX, int posY); - void findSecondaryMovedCursor(guint state); - void findBoundaries(double &min, double &max); - double to01(ThreshCursorId cursorId); - void updateTooltip(); + void initValues (); + void findLitCursor(int posX, int posY); + void findSecondaryMovedCursor(guint state); + void findBoundaries(double &min, double &max); + double to01(ThreshCursorId cursorId); + void updateTooltip(); - public: +public: - sigc::signal signal_value_changed(); + sigc::signal signal_value_changed(); - ThresholdSelector(double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, - double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, - ThresholdCurveProvider* curveProvider); - ThresholdSelector(double minValue, double maxValue, double defBottom, double defTop, unsigned int precision, bool startAtOne); - ThresholdSelector(double minValue, double maxValue, double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight, unsigned int precision, bool startAtOne); + ThresholdSelector(double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom, + double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop, + ThresholdCurveProvider* curveProvider); + ThresholdSelector(double minValue, double maxValue, double defBottom, double defTop, unsigned int precision, bool startAtOne); + ThresholdSelector(double minValue, double maxValue, double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight, unsigned int precision, bool startAtOne); - double shapePositionValue (ThreshCursorId cursorId); - template - void setDefaults (const rtengine::procparams::Threshold &t) { - defPos[TS_BOTTOMLEFT] = double(t.value[0]); // should we use shapeValue() ? - defPos[TS_TOPLEFT] = double(t.value[1]); - if (doubleThresh) { - defPos[TS_BOTTOMRIGHT] = double(t.value[2]); - defPos[TS_TOPRIGHT] = double(t.value[3]); - } - } - void setDefaults (double bottom, double top); - void setDefaults (double bottomLeft, double topLeft, double bottomRight, double topRight); - template - void setPositions (const rtengine::procparams::Threshold &tValues) { - positions[TS_BOTTOMLEFT] = static_cast(tValues.value[TS_BOTTOMLEFT]); - positions[TS_TOPLEFT] = static_cast(tValues.value[TS_TOPLEFT]); - if (tValues.isDouble()) { - positions[TS_BOTTOMRIGHT] = static_cast(tValues.value[TS_BOTTOMRIGHT]); - positions[TS_TOPRIGHT] = static_cast(tValues.value[TS_TOPRIGHT]); - } - updateTooltip(); - queue_draw(); - } - void setPositions (double bottom, double top); - void setPositions (double bottomLeft, double topLeft, double bottomRight, double topRight); + double shapePositionValue (ThreshCursorId cursorId); + template + void setDefaults (const rtengine::procparams::Threshold &t) + { + defPos[TS_BOTTOMLEFT] = double(t.value[0]); // should we use shapeValue() ? + defPos[TS_TOPLEFT] = double(t.value[1]); - template - rtengine::procparams::Threshold getPositions () { - if (doubleThresh) { - rtengine::procparams::Threshold rThresh( - static_cast(shapePositionValue(TS_BOTTOMLEFT)), - static_cast(shapePositionValue(TS_TOPLEFT)), - static_cast(shapePositionValue(TS_BOTTOMRIGHT)), - static_cast(shapePositionValue(TS_TOPRIGHT)), - initalEq1 - ); - return rThresh; - } - else { - rtengine::procparams::Threshold rThresh( - static_cast(shapePositionValue(TS_BOTTOMLEFT)), - static_cast(shapePositionValue(TS_TOPLEFT)), - initalEq1 - ); - return rThresh; - } - } + if (doubleThresh) { + defPos[TS_BOTTOMRIGHT] = double(t.value[2]); + defPos[TS_TOPRIGHT] = double(t.value[3]); + } + } + void setDefaults (double bottom, double top); + void setDefaults (double bottomLeft, double topLeft, double bottomRight, double topRight); + template + void setPositions (const rtengine::procparams::Threshold &tValues) + { + positions[TS_BOTTOMLEFT] = static_cast(tValues.value[TS_BOTTOMLEFT]); + positions[TS_TOPLEFT] = static_cast(tValues.value[TS_TOPLEFT]); - template - void getPositions (T &bottom, T &top) { - bottom = static_cast(shapePositionValue(TS_BOTTOMLEFT)); - top = static_cast(shapePositionValue(TS_TOPLEFT)); - } + if (tValues.isDouble()) { + positions[TS_BOTTOMRIGHT] = static_cast(tValues.value[TS_BOTTOMRIGHT]); + positions[TS_TOPRIGHT] = static_cast(tValues.value[TS_TOPRIGHT]); + } - template - void getPositions (T &bottomLeft, T &topLeft, T &bottomRight, T &topRight) { - bottomLeft = static_cast(shapePositionValue(TS_BOTTOMLEFT)); - topLeft = static_cast(shapePositionValue(TS_TOPLEFT)); - bottomRight = static_cast(shapePositionValue(TS_BOTTOMRIGHT)); - topRight = static_cast(shapePositionValue(TS_TOPRIGHT)); - } + updateTooltip(); + queue_draw(); + } + void setPositions (double bottom, double top); + void setPositions (double bottomLeft, double topLeft, double bottomRight, double topRight); - void setSeparatedSliders(bool separated); - bool getSeparatedSliders(); - void setBgCurveProvider (ThresholdCurveProvider* provider); - bool isStartAtOne() { return initalEq1; } - bool isDouble() { return doubleThresh; } - void on_realize (); - bool on_expose_event(GdkEventExpose* event); - bool on_button_press_event (GdkEventButton* event); - bool on_button_release_event (GdkEventButton* event); - bool on_motion_notify_event (GdkEventMotion* event); - bool on_leave_notify_event (GdkEventCrossing* event); - void styleChanged (const Glib::RefPtr& style); - unsigned int getPrecision () { return precisionTop; } - void reset (); - void setUpdatePolicy (eUpdatePolicy policy) { updatePolicy = policy; } - void set_tooltip_markup(const Glib::ustring& markup); - // this set_tooltip_text method is to set_tooltip_markup, and text can contain markups - void set_tooltip_text(const Glib::ustring& text); + template + rtengine::procparams::Threshold getPositions () + { + if (doubleThresh) { + rtengine::procparams::Threshold rThresh( + static_cast(shapePositionValue(TS_BOTTOMLEFT)), + static_cast(shapePositionValue(TS_TOPLEFT)), + static_cast(shapePositionValue(TS_BOTTOMRIGHT)), + static_cast(shapePositionValue(TS_TOPRIGHT)), + initalEq1 + ); + return rThresh; + } else { + rtengine::procparams::Threshold rThresh( + static_cast(shapePositionValue(TS_BOTTOMLEFT)), + static_cast(shapePositionValue(TS_TOPLEFT)), + initalEq1 + ); + return rThresh; + } + } + + template + void getPositions (T &bottom, T &top) + { + bottom = static_cast(shapePositionValue(TS_BOTTOMLEFT)); + top = static_cast(shapePositionValue(TS_TOPLEFT)); + } + + template + void getPositions (T &bottomLeft, T &topLeft, T &bottomRight, T &topRight) + { + bottomLeft = static_cast(shapePositionValue(TS_BOTTOMLEFT)); + topLeft = static_cast(shapePositionValue(TS_TOPLEFT)); + bottomRight = static_cast(shapePositionValue(TS_BOTTOMRIGHT)); + topRight = static_cast(shapePositionValue(TS_TOPRIGHT)); + } + + void setSeparatedSliders(bool separated); + bool getSeparatedSliders(); + void setBgCurveProvider (ThresholdCurveProvider* provider); + bool isStartAtOne() + { + return initalEq1; + } + bool isDouble() + { + return doubleThresh; + } + void on_realize (); + bool on_expose_event(GdkEventExpose* event); + bool on_button_press_event (GdkEventButton* event); + bool on_button_release_event (GdkEventButton* event); + bool on_motion_notify_event (GdkEventMotion* event); + bool on_leave_notify_event (GdkEventCrossing* event); + void styleChanged (const Glib::RefPtr& style); + unsigned int getPrecision () + { + return precisionTop; + } + void reset (); + void setUpdatePolicy (eUpdatePolicy policy) + { + updatePolicy = policy; + } + void set_tooltip_markup(const Glib::ustring& markup); + // this set_tooltip_text method is to set_tooltip_markup, and text can contain markups + void set_tooltip_text(const Glib::ustring& text); }; template<> -inline void ThresholdSelector::getPositions (Glib::ustring& bottom, Glib::ustring& top) { - bottom = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMLEFT)); - top = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPLEFT)); +inline void ThresholdSelector::getPositions (Glib::ustring& bottom, Glib::ustring& top) +{ + bottom = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMLEFT)); + top = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPLEFT)); } template<> -inline void ThresholdSelector::getPositions (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight) { +inline void ThresholdSelector::getPositions (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight) +{ - bottomLeft = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMLEFT)); - topLeft = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPLEFT)); - bottomRight = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMRIGHT)); - topRight = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPRIGHT)); + bottomLeft = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMLEFT)); + topLeft = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPLEFT)); + bottomRight = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMRIGHT)); + topRight = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPRIGHT)); } #endif diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index 8499ba668..c2ed480f2 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -5,7 +5,7 @@ * 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 @@ -24,10 +24,12 @@ using namespace std; -ThumbBrowserBase::ThumbBrowserBase () - : lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1), inspector(NULL), isInspectorActive(false) { +ThumbBrowserBase::ThumbBrowserBase () + : lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1), inspector(NULL), isInspectorActive(false) +{ location = THLOC_FILEBROWSER; - inW = -1; inH = -1; + inW = -1; + inH = -1; Gtk::HBox* hb1 = Gtk::manage( new Gtk::HBox () ); Gtk::HBox* hb2 = Gtk::manage( new Gtk::HBox () ); @@ -41,12 +43,12 @@ ThumbBrowserBase::ThumbBrowserBase () hb2->pack_start (hscroll); - pack_start (*hb2,Gtk::PACK_SHRINK, 0); + pack_start (*hb2, Gtk::PACK_SHRINK, 0); internal.setParent (this); - + show_all (); - + hscroll.set_update_policy (Gtk::UPDATE_CONTINUOUS); vscroll.set_update_policy (Gtk::UPDATE_CONTINUOUS); @@ -56,14 +58,16 @@ ThumbBrowserBase::ThumbBrowserBase () internal.signal_size_allocate().connect( sigc::mem_fun(*this, &ThumbBrowserBase::internalAreaResized) ); } -void ThumbBrowserBase::scrollChanged () { +void ThumbBrowserBase::scrollChanged () +{ { - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - for (size_t i=0; isetOffset ((int)(hscroll.get_value()), (int)(vscroll.get_value())); + for (size_t i = 0; i < fd.size(); i++) { + fd[i]->setOffset ((int)(hscroll.get_value()), (int)(vscroll.get_value())); + } } internal.setPosition ((int)(hscroll.get_value()), (int)(vscroll.get_value())); @@ -74,337 +78,362 @@ void ThumbBrowserBase::scrollChanged () { } } -void ThumbBrowserBase::scroll (int direction) { +void ThumbBrowserBase::scroll (int direction) +{ // GUI already acquired when here - if (arrangement==TB_Vertical) - vscroll.set_value (vscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_step_increment()); - else - hscroll.set_value (hscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_step_increment()); + if (arrangement == TB_Vertical) { + vscroll.set_value (vscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_step_increment()); + } else { + hscroll.set_value (hscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_step_increment()); + } } -void ThumbBrowserBase::scrollPage (int direction) { +void ThumbBrowserBase::scrollPage (int direction) +{ // GUI already acquired when here - if (arrangement==TB_Vertical) - vscroll.set_value (vscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_page_increment()); - else - hscroll.set_value (hscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_page_increment()); + if (arrangement == TB_Vertical) { + vscroll.set_value (vscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * vscroll.get_adjustment()->get_page_increment()); + } else { + hscroll.set_value (hscroll.get_value() + (direction == GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_page_increment()); + } } -static void scrollToEntry (double& h, double& v, int iw, int ih, ThumbBrowserEntryBase* entry) { +static void scrollToEntry (double& h, double& v, int iw, int ih, ThumbBrowserEntryBase* entry) +{ const int hmin = entry->getX (); const int hmax = hmin + entry->getEffectiveWidth () - iw; const int vmin = entry->getY (); const int vmax = vmin + entry->getEffectiveHeight () - ih; - if (hmin < 0) + if (hmin < 0) { h += hmin; - else if (hmax > 0) + } else if (hmax > 0) { h += hmax; + } - if(vmin < 0) + if(vmin < 0) { v += vmin; - else if (vmax > 0) + } else if (vmax > 0) { v += vmax; + } } -void ThumbBrowserBase::selectPrev (int distance, bool enlarge) { +void ThumbBrowserBase::selectPrev (int distance, bool enlarge) +{ double h, v; getScrollPosition (h, v); { - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - if (!selected.empty ()) { - std::vector::iterator front = std::find (fd.begin (), fd.end (), selected.front ()); - std::vector::iterator back = std::find (fd.begin (), fd.end (), selected.back ()); - std::vector::iterator last = std::find (fd.begin (), fd.end (), lastClicked); + if (!selected.empty ()) { + std::vector::iterator front = std::find (fd.begin (), fd.end (), selected.front ()); + std::vector::iterator back = std::find (fd.begin (), fd.end (), selected.back ()); + std::vector::iterator last = std::find (fd.begin (), fd.end (), lastClicked); - if (front > back) - std::swap(front, back); + if (front > back) { + std::swap(front, back); + } - std::vector::iterator& curr = last == front ? front : back; + std::vector::iterator& curr = last == front ? front : back; - // find next thumbnail at filtered distance before current - for (; curr >= fd.begin (); --curr) { - if (!(*curr)->filtered) { - if (distance-- == 0) { - // clear current selection - for (size_t i=0; iselected = false; - redrawNeeded (selected[i]); - } - selected.clear (); - - // make sure the newly selected thumbnail is visible and make it current - scrollToEntry (h, v, internal.get_width (), internal.get_height (), *curr); - lastClicked = *curr; - - // either enlarge current selection or set new selection - if(enlarge) { - // reverse direction if distance is too large - if(front > back) - std::swap(front, back); - - for (; front <= back; ++front) { - if (!(*front)->filtered) { - (*front)->selected = true; - redrawNeeded (*front); - selected.push_back (*front); - } + // find next thumbnail at filtered distance before current + for (; curr >= fd.begin (); --curr) { + if (!(*curr)->filtered) { + if (distance-- == 0) { + // clear current selection + for (size_t i = 0; i < selected.size (); ++i) { + selected[i]->selected = false; + redrawNeeded (selected[i]); } - } - else { - (*curr)->selected = true; - redrawNeeded (*curr); - selected.push_back (*curr); - } - break; + selected.clear (); + + // make sure the newly selected thumbnail is visible and make it current + scrollToEntry (h, v, internal.get_width (), internal.get_height (), *curr); + lastClicked = *curr; + + // either enlarge current selection or set new selection + if(enlarge) { + // reverse direction if distance is too large + if(front > back) { + std::swap(front, back); + } + + for (; front <= back; ++front) { + if (!(*front)->filtered) { + (*front)->selected = true; + redrawNeeded (*front); + selected.push_back (*front); + } + } + } else { + (*curr)->selected = true; + redrawNeeded (*curr); + selected.push_back (*curr); + } + + break; + } } } } - } - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); } setScrollPosition (h, v); } -void ThumbBrowserBase::selectNext (int distance, bool enlarge) { +void ThumbBrowserBase::selectNext (int distance, bool enlarge) +{ double h, v; getScrollPosition (h, v); { - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - if (!selected.empty ()) { - std::vector::iterator front = std::find (fd.begin (), fd.end (), selected.front ()); - std::vector::iterator back = std::find (fd.begin (), fd.end (), selected.back ()); - std::vector::iterator last = std::find (fd.begin (), fd.end (), lastClicked); + if (!selected.empty ()) { + std::vector::iterator front = std::find (fd.begin (), fd.end (), selected.front ()); + std::vector::iterator back = std::find (fd.begin (), fd.end (), selected.back ()); + std::vector::iterator last = std::find (fd.begin (), fd.end (), lastClicked); - if (front > back) - std::swap(front, back); + if (front > back) { + std::swap(front, back); + } - std::vector::iterator& curr = last == back ? back : front; + std::vector::iterator& curr = last == back ? back : front; - // find next thumbnail at filtered distance after current - for (; curr < fd.end (); ++curr) { - if (!(*curr)->filtered) { - if (distance-- == 0) { - // clear current selection - for (size_t i=0; iselected = false; - redrawNeeded (selected[i]); - } - selected.clear (); - - // make sure the newly selected thumbnail is visible and make it current - scrollToEntry (h, v, internal.get_width (), internal.get_height (), *curr); - lastClicked = *curr; - - // either enlarge current selection or set new selection - if(enlarge) { - // reverse direction if distance is too large - if(front > back) - std::swap(front, back); - - for (; front <= back; ++front) { - if (!(*front)->filtered) { - (*front)->selected = true; - redrawNeeded (*front); - selected.push_back (*front); - } + // find next thumbnail at filtered distance after current + for (; curr < fd.end (); ++curr) { + if (!(*curr)->filtered) { + if (distance-- == 0) { + // clear current selection + for (size_t i = 0; i < selected.size (); ++i) { + selected[i]->selected = false; + redrawNeeded (selected[i]); } - } - else { - (*curr)->selected = true; - redrawNeeded (*curr); - selected.push_back (*curr); - } - break; + selected.clear (); + + // make sure the newly selected thumbnail is visible and make it current + scrollToEntry (h, v, internal.get_width (), internal.get_height (), *curr); + lastClicked = *curr; + + // either enlarge current selection or set new selection + if(enlarge) { + // reverse direction if distance is too large + if(front > back) { + std::swap(front, back); + } + + for (; front <= back; ++front) { + if (!(*front)->filtered) { + (*front)->selected = true; + redrawNeeded (*front); + selected.push_back (*front); + } + } + } else { + (*curr)->selected = true; + redrawNeeded (*curr); + selected.push_back (*curr); + } + + break; + } } } } - } - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); } setScrollPosition (h, v); } -void ThumbBrowserBase::selectFirst (bool enlarge) { +void ThumbBrowserBase::selectFirst (bool enlarge) +{ double h, v; getScrollPosition (h, v); { - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - if (!fd.empty ()) { - // find first unfiltered entry - std::vector::iterator first = fd.begin (); + if (!fd.empty ()) { + // find first unfiltered entry + std::vector::iterator first = fd.begin (); - for (; first < fd.end (); ++first) { - if (!(*first)->filtered) { - break; - } - } - - scrollToEntry (h, v, internal.get_width (), internal.get_height (), *first); - - ThumbBrowserEntryBase* lastEntry = lastClicked; - lastClicked = *first; - - if(selected.empty ()) { - (*first)->selected = true; - redrawNeeded (*first); - selected.push_back (*first); - } - else { - std::vector::iterator back = std::find (fd.begin (), fd.end (), lastEntry ? lastEntry : selected.back ()); - - if (first > back) - std::swap(first, back); - - // clear current selection - for (size_t i=0; iselected = false; - redrawNeeded (selected[i]); - } - selected.clear (); - - // either enlarge current selection or set new selection - for (; first <= back; ++first) { + for (; first < fd.end (); ++first) { if (!(*first)->filtered) { - (*first)->selected = true; - redrawNeeded (*first); - selected.push_back (*first); + break; + } + } + + scrollToEntry (h, v, internal.get_width (), internal.get_height (), *first); + + ThumbBrowserEntryBase* lastEntry = lastClicked; + lastClicked = *first; + + if(selected.empty ()) { + (*first)->selected = true; + redrawNeeded (*first); + selected.push_back (*first); + } else { + std::vector::iterator back = std::find (fd.begin (), fd.end (), lastEntry ? lastEntry : selected.back ()); + + if (first > back) { + std::swap(first, back); } - if (!enlarge) - break; + // clear current selection + for (size_t i = 0; i < selected.size (); ++i) { + selected[i]->selected = false; + redrawNeeded (selected[i]); + } + + selected.clear (); + + // either enlarge current selection or set new selection + for (; first <= back; ++first) { + if (!(*first)->filtered) { + (*first)->selected = true; + redrawNeeded (*first); + selected.push_back (*first); + } + + if (!enlarge) { + break; + } + } } } - } - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); } setScrollPosition (h, v); } -void ThumbBrowserBase::selectLast (bool enlarge) { +void ThumbBrowserBase::selectLast (bool enlarge) +{ double h, v; getScrollPosition (h, v); { - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - if (!fd.empty ()) { - // find last unfiltered entry - std::vector::iterator last = fd.end () - 1; + if (!fd.empty ()) { + // find last unfiltered entry + std::vector::iterator last = fd.end () - 1; - for (; last >= fd.begin (); --last) { - if (!(*last)->filtered) { - break; - } - } - - scrollToEntry (h, v, internal.get_width (), internal.get_height (), *last); - - ThumbBrowserEntryBase* lastEntry = lastClicked; - lastClicked = *last; - - if(selected.empty()) { - (*last)->selected = true; - redrawNeeded (*last); - selected.push_back (*last); - } - else { - std::vector::iterator front = std::find (fd.begin (), fd.end (), lastEntry ? lastEntry : selected.front ()); - - if (last < front) - std::swap(last, front); - - // clear current selection - for (size_t i=0; iselected = false; - redrawNeeded (selected[i]); - } - selected.clear (); - - // either enlarge current selection or set new selection - for (; front <= last; --last) { + for (; last >= fd.begin (); --last) { if (!(*last)->filtered) { - (*last)->selected = true; - redrawNeeded (*last); - selected.push_back (*last); + break; + } + } + + scrollToEntry (h, v, internal.get_width (), internal.get_height (), *last); + + ThumbBrowserEntryBase* lastEntry = lastClicked; + lastClicked = *last; + + if(selected.empty()) { + (*last)->selected = true; + redrawNeeded (*last); + selected.push_back (*last); + } else { + std::vector::iterator front = std::find (fd.begin (), fd.end (), lastEntry ? lastEntry : selected.front ()); + + if (last < front) { + std::swap(last, front); } - if (!enlarge) - break; + // clear current selection + for (size_t i = 0; i < selected.size (); ++i) { + selected[i]->selected = false; + redrawNeeded (selected[i]); + } + + selected.clear (); + + // either enlarge current selection or set new selection + for (; front <= last; --last) { + if (!(*last)->filtered) { + (*last)->selected = true; + redrawNeeded (*last); + selected.push_back (*last); + } + + if (!enlarge) { + break; + } + } + + std::reverse(selected.begin (), selected.end ()); } - - std::reverse(selected.begin (), selected.end ()); } - } - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); } setScrollPosition (h, v); } -void ThumbBrowserBase::resizeThumbnailArea (int w, int h) { +void ThumbBrowserBase::resizeThumbnailArea (int w, int h) +{ inW = w; inH = h; - if (hscroll.get_value() + internal.get_width() > inW) + if (hscroll.get_value() + internal.get_width() > inW) { hscroll.set_value (inW - internal.get_width()); - if (vscroll.get_value() + internal.get_height() > inH) + } + + if (vscroll.get_value() + internal.get_height() > inH) { vscroll.set_value (inH - internal.get_height()); + } configScrollBars (); } -void ThumbBrowserBase::internalAreaResized (Gtk::Allocation& req) { +void ThumbBrowserBase::internalAreaResized (Gtk::Allocation& req) +{ - if (inW>0 && inH>0) { - configScrollBars (); - redraw (); - } + if (inW > 0 && inH > 0) { + configScrollBars (); + redraw (); + } } -void ThumbBrowserBase::configScrollBars () { +void ThumbBrowserBase::configScrollBars () +{ // HOMBRE:DELETE ME? GThreadLock tLock; // Acquire the GUI - if (inW>0 && inH>0) { - + if (inW > 0 && inH > 0) { + int iw = internal.get_width (); int ih = internal.get_height (); @@ -419,40 +448,47 @@ void ThumbBrowserBase::configScrollBars () { hscroll.get_adjustment()->set_page_size (iw); vscroll.get_adjustment()->set_page_size (ih); - if(iw>=inW) + if(iw >= inW) { hscroll.hide(); - else + } else { hscroll.show(); + } - if(ih>=inH) + if(ih >= inH) { vscroll.hide(); - else + } else { vscroll.show(); + } } } -void ThumbBrowserBase::arrangeFiles () { +void ThumbBrowserBase::arrangeFiles () +{ - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif // GUI already locked by ::redraw, the only caller of this method for now. // We could lock it one more time, there's no harm excepted (negligible) speed penalty //GThreadLock lock; int N = fd.size (); + // apply filter - for (int i=0; ifiltered = !checkFilter (fd[i]); + } int rowHeight = 0; + // compute size of the items - for (int i=0; ifiltered && fd[i]->getMinimalHeight() > rowHeight) + for (int i = 0; i < N; i++) + if (!fd[i]->filtered && fd[i]->getMinimalHeight() > rowHeight) { rowHeight = fd[i]->getMinimalHeight (); - - if (arrangement==TB_Horizontal) { + } + + if (arrangement == TB_Horizontal) { numOfCols = 1; int numOfRows = 1; // if (rowHeight>0) { @@ -462,161 +498,207 @@ void ThumbBrowserBase::arrangeFiles () { // } int ct = 0; - int currx = 0; int curry = 0; - while (ctgetMinimalWidth() > maxw) - maxw = fd[ct+i]->getMinimalWidth (); + + for (int i = 0; ct + i < N && i < numOfRows; i++) + if (fd[ct + i]->getMinimalWidth() > maxw) { + maxw = fd[ct + i]->getMinimalWidth (); + } // arrange items in the column curry = 0; - for (int i=0; ctfiltered) + + for (int i = 0; ct < N && i < numOfRows; i++, ct++) { + while (ct < N && fd[ct]->filtered) { fd[ct++]->drawable = false; - if (ctsetPosition (currx, curry, maxw, rowHeight); fd[ct]->drawable = true; curry += rowHeight; } } + currx += maxw; } - #if PROTECT_VECTORS + +#if PROTECT_VECTORS MYREADERLOCK_RELEASE(l); - #endif +#endif // This will require a Writer access - resizeThumbnailArea (currx, numOfRows*rowHeight); - } - else { + resizeThumbnailArea (currx, numOfRows * rowHeight); + } else { int availWidth = internal.get_width(); // initial number of columns numOfCols = 0; int colsWidth = 0; - for (int i=0; ifiltered && colsWidth + fd[i]->getMinimalWidth() <= availWidth) { colsWidth += fd[numOfCols]->getMinimalWidth (); numOfCols++; } - if (numOfCols<1) + + if (numOfCols < 1) { numOfCols = 1; + } + std::vector colWidths; - for (; numOfCols>0; numOfCols--) { + + for (; numOfCols > 0; numOfCols--) { // compute column widths colWidths.resize (numOfCols); - for (int i=0; ifiltered && fd[i]->getMinimalWidth() > colWidths[j%numOfCols]) - colWidths[j%numOfCols] = fd[i]->getMinimalWidth (); - if (!fd[i]->filtered) - j++; } - // if not wider than the space available, arrange it and we are ready - colsWidth = 0; - for (int i=0; ifiltered) - fd[ct++]->drawable = false; - if (ctsetPosition (currx, curry, colWidths[i%numOfCols], rowHeight); - fd[ct]->drawable = true; - currx += colWidths[i%numOfCols]; + + for (int i = 0, j = 0; i < N; i++) { + if (!fd[i]->filtered && fd[i]->getMinimalWidth() > colWidths[j % numOfCols]) { + colWidths[j % numOfCols] = fd[i]->getMinimalWidth (); + } + + if (!fd[i]->filtered) { + j++; } } - if (currx>0) // there were thumbnails placed in the row - curry += rowHeight; + + // if not wider than the space available, arrange it and we are ready + colsWidth = 0; + + for (int i = 0; i < numOfCols; i++) { + colsWidth += colWidths[i]; + } + + if (numOfCols == 1 || colsWidth < availWidth) { + break; + } } - #if PROTECT_VECTORS + + // arrange files + int ct = 0; + int currx = 0; + int curry = 0; + + while (ct < N) { + // arrange items in the row + currx = 0; + + for (int i = 0; ct < N && i < numOfCols; i++, ct++) { + while (ct < N && fd[ct]->filtered) { + fd[ct++]->drawable = false; + } + + if (ct < N) { + fd[ct]->setPosition (currx, curry, colWidths[i % numOfCols], rowHeight); + fd[ct]->drawable = true; + currx += colWidths[i % numOfCols]; + } + } + + if (currx > 0) { // there were thumbnails placed in the row + curry += rowHeight; + } + } + +#if PROTECT_VECTORS MYREADERLOCK_RELEASE(l); - #endif +#endif // This will require a Writer access resizeThumbnailArea (colsWidth, curry); } } -void ThumbBrowserBase::disableInspector() { - if (inspector) +void ThumbBrowserBase::disableInspector() +{ + if (inspector) { inspector->setActive(false); + } } -void ThumbBrowserBase::enableInspector() { - if (inspector) +void ThumbBrowserBase::enableInspector() +{ + if (inspector) { inspector->setActive(true); + } } -void ThumbBrowserBase::Internal::on_realize() { - // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) - Cairo::FontOptions cfo; - cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL); - get_pango_context()->set_cairo_font_options (cfo); +void ThumbBrowserBase::Internal::on_realize() +{ + // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) + Cairo::FontOptions cfo; + cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL); + get_pango_context()->set_cairo_font_options (cfo); - Gtk::DrawingArea::on_realize(); - Glib::RefPtr window = get_window(); - set_flags (Gtk::CAN_FOCUS); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK); - gc_ = Gdk::GC::create(window); - set_has_tooltip (true); - signal_query_tooltip().connect( sigc::mem_fun(*this, &ThumbBrowserBase::Internal::on_query_tooltip) ); + Gtk::DrawingArea::on_realize(); + Glib::RefPtr window = get_window(); + set_flags (Gtk::CAN_FOCUS); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK); + gc_ = Gdk::GC::create(window); + set_has_tooltip (true); + signal_query_tooltip().connect( sigc::mem_fun(*this, &ThumbBrowserBase::Internal::on_query_tooltip) ); } -bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) { +bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) Glib::ustring ttip = ""; { - #if PROTECT_VECTORS - MYREADERLOCK(l, parent->entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, parent->entryRW); +#endif - for (size_t i=0; ifd.size(); i++) - if (parent->fd[i]->drawable && parent->fd[i]->inside (x, y)) { - ttip = parent->fd[i]->getToolTip (x, y); - break; - } + for (size_t i = 0; i < parent->fd.size(); i++) + if (parent->fd[i]->drawable && parent->fd[i]->inside (x, y)) { + ttip = parent->fd[i]->getToolTip (x, y); + break; + } } - if (ttip!="") { + + if (ttip != "") { tooltip->set_markup (ttip); return true; - } - else + } else { return false; + } } -void ThumbBrowserBase::on_style_changed (const Glib::RefPtr& style) { +void ThumbBrowserBase::on_style_changed (const Glib::RefPtr& style) +{ // GUI will be acquired by refreshThumbImages refreshThumbImages (); } -ThumbBrowserBase::Internal::Internal () : ofsX(0), ofsY(0), parent(NULL), dirty(true) { +ThumbBrowserBase::Internal::Internal () : ofsX(0), ofsY(0), parent(NULL), dirty(true) +{ } -void ThumbBrowserBase::Internal::setParent (ThumbBrowserBase* p) { +void ThumbBrowserBase::Internal::setParent (ThumbBrowserBase* p) +{ parent = p; } -void ThumbBrowserBase::Internal::setPosition (int x, int y) { +void ThumbBrowserBase::Internal::setPosition (int x, int y) +{ ofsX = x; ofsY = y; } -bool ThumbBrowserBase::Internal::on_key_press_event (GdkEventKey* event) { +bool ThumbBrowserBase::Internal::on_key_press_event (GdkEventKey* event) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) return parent->keyPressed (event); } -bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) { +bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) grab_focus (); @@ -627,7 +709,7 @@ bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) { GdkRectangle rect; rect.x = 0; - rect.y = 0; + rect.y = 0; window->get_size (rect.width, rect.height); gdk_window_invalidate_rect (window->gobj(), &rect, true); @@ -636,140 +718,161 @@ bool ThumbBrowserBase::Internal::on_button_press_event (GdkEventButton* event) { return true; } -void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh) { +void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh) +{ // GUI already acquired ThumbBrowserEntryBase* fileDescr = NULL; bool handled = false; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif - for (size_t i=0; idrawable) { - if (fd[i]->inside (x, y) && fd[i]->insideWindow (clx, cly, clw, clh)) + if (fd[i]->inside (x, y) && fd[i]->insideWindow (clx, cly, clw, clh)) { fileDescr = fd[i]; + } + bool b = fd[i]->pressNotify (button, type, state, x, y); handled = handled || b; } } - if (handled || (fileDescr && fileDescr->processing)) + if (handled || (fileDescr && fileDescr->processing)) { return; + } { - #if PROTECT_VECTORS - MYWRITERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, entryRW); +#endif - if (selected.size()==1 && type==GDK_2BUTTON_PRESS && button==1) - doubleClicked (selected[0]); - else if (button==1 && type==GDK_BUTTON_PRESS) { - if (fileDescr && (state & GDK_SHIFT_MASK)) { - if (selected.empty()) { - selected.push_back (fileDescr); - fileDescr->selected = true; - lastClicked = fileDescr; - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); - } - else { - // find the start and the end of the selection interval - size_t startx = fd.size()-1; - if (lastClicked) { - for (; startx>0; startx--) - if (fd[startx]==lastClicked) - break; - } - else { - for (; startx>0; startx--) - if (fd[startx]==selected[0]) - break; - } - size_t endx = 0; - for (; endxselected = false; - selected.clear (); - // select thumbnails in the interval - for (size_t i=startx; i<=endx; i++) { - if (!fd[i]->filtered) { - fd[i]->selected = true; - selected.push_back (fd[i]); + if (selected.size() == 1 && type == GDK_2BUTTON_PRESS && button == 1) { + doubleClicked (selected[0]); + } else if (button == 1 && type == GDK_BUTTON_PRESS) { + if (fileDescr && (state & GDK_SHIFT_MASK)) { + if (selected.empty()) { + selected.push_back (fileDescr); + fileDescr->selected = true; + lastClicked = fileDescr; +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); + } else { + // find the start and the end of the selection interval + size_t startx = fd.size() - 1; + + if (lastClicked) { + for (; startx > 0; startx--) + if (fd[startx] == lastClicked) { + break; + } + } else { + for (; startx > 0; startx--) + if (fd[startx] == selected[0]) { + break; + } } + + size_t endx = 0; + + for (; endx < fd.size(); endx++) + if (fd[endx] == fileDescr) { + break; + } + + if (endx < startx) { + int tmp = endx; + endx = startx; + startx = tmp; + } + + // clear current selection + for (size_t i = 0; i < selected.size(); i++) { + selected[i]->selected = false; + } + + selected.clear (); + + // select thumbnails in the interval + for (size_t i = startx; i <= endx; i++) { + if (!fd[i]->filtered) { + fd[i]->selected = true; + selected.push_back (fd[i]); + } + } + + lastClicked = fileDescr; +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); } + } else if (fileDescr && (state & GDK_CONTROL_MASK)) { + std::vector::iterator i = std::find (selected.begin(), selected.end(), fileDescr); + + if (i != selected.end()) { + (*i)->selected = false; + selected.erase (i); + } else { + selected.push_back (fileDescr); + fileDescr->selected = true; + } + lastClicked = fileDescr; - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif +#endif + selectionChanged (); + } else { + for (size_t i = 0; i < selected.size(); i++) { + selected[i]->selected = false; + } + + selected.clear (); + + if (fileDescr) { + selected.push_back (fileDescr); + fileDescr->selected = true; + } + + lastClicked = fileDescr; +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif selectionChanged (); } - } - else if (fileDescr && (state & GDK_CONTROL_MASK)) { - std::vector::iterator i = std::find (selected.begin(), selected.end(), fileDescr); - if (i!=selected.end()) { - (*i)->selected = false; - selected.erase (i); - } - else { - selected.push_back (fileDescr); + } else if (fileDescr && button == 3 && type == GDK_BUTTON_PRESS) { + if (!fileDescr->selected) { + for (size_t i = 0; i < selected.size(); i++) { + selected[i]->selected = false; + } + + selected.clear (); fileDescr->selected = true; - } - lastClicked = fileDescr; - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); - } - else { - for (size_t i=0; iselected = false; - selected.clear (); - if (fileDescr) { selected.push_back (fileDescr); - fileDescr->selected = true; + lastClicked = fileDescr; +#if PROTECT_VECTORS + MYWRITERLOCK_RELEASE(l); +#endif + selectionChanged (); } - lastClicked = fileDescr; - #if PROTECT_VECTORS + +#if PROTECT_VECTORS MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); +#endif + rightClicked (fileDescr); } - } - else if (fileDescr && button==3 && type==GDK_BUTTON_PRESS) { - if (!fileDescr->selected) { - for (size_t i=0; iselected = false; - selected.clear (); - fileDescr->selected = true; - selected.push_back (fileDescr); - lastClicked = fileDescr; - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - selectionChanged (); - } - #if PROTECT_VECTORS - MYWRITERLOCK_RELEASE(l); - #endif - rightClicked (fileDescr); - } } // end of MYWRITERLOCK(l, entryRW); } -bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) { +bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) dirty = false; @@ -785,67 +888,72 @@ bool ThumbBrowserBase::Internal::on_expose_event(GdkEventExpose* event) { context->set_font_description (get_style()->get_font()); { - #if PROTECT_VECTORS - MYWRITERLOCK(l, parent->entryRW); - #endif +#if PROTECT_VECTORS + MYWRITERLOCK(l, parent->entryRW); +#endif - for (size_t i=0; ifd.size() && !dirty; i++) { // if dirty meanwhile, cancel and wait for next redraw - if (!parent->fd[i]->drawable || !parent->fd[i]->insideWindow (0, 0, w, h)) - parent->fd[i]->updatepriority = false; - else { - parent->fd[i]->updatepriority = true; - parent->fd[i]->draw (); + for (size_t i = 0; i < parent->fd.size() && !dirty; i++) { // if dirty meanwhile, cancel and wait for next redraw + if (!parent->fd[i]->drawable || !parent->fd[i]->insideWindow (0, 0, w, h)) { + parent->fd[i]->updatepriority = false; + } else { + parent->fd[i]->updatepriority = true; + parent->fd[i]->draw (); + } } } - } return true; } -bool ThumbBrowserBase::Internal::on_button_release_event (GdkEventButton* event) { +bool ThumbBrowserBase::Internal::on_button_release_event (GdkEventButton* event) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) int w = get_width(); int h = get_height(); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, parent->entryRW); - #endif +#endif - for (size_t i=0; ifd.size(); i++) + for (size_t i = 0; i < parent->fd.size(); i++) if (parent->fd[i]->drawable && parent->fd[i]->insideWindow (0, 0, w, h)) { ThumbBrowserEntryBase* tbe = parent->fd[i]; - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK_RELEASE(l); - #endif +#endif // This will require a Writer access... tbe->releaseNotify (event->button, event->type, event->state, (int)event->x, (int)event->y); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK_ACQUIRE(l); - #endif +#endif } + return true; } -bool ThumbBrowserBase::Internal::on_motion_notify_event (GdkEventMotion* event) { +bool ThumbBrowserBase::Internal::on_motion_notify_event (GdkEventMotion* event) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) int w = get_width(); int h = get_height(); - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, parent->entryRW); - #endif +#endif - for (size_t i=0; ifd.size(); i++) + for (size_t i = 0; i < parent->fd.size(); i++) if (parent->fd[i]->drawable && parent->fd[i]->insideWindow (0, 0, w, h)) { /*#if PROTECT_VECTORS MYREADERLOCK_RELEASE(l); // motionNotify calls the queue, which locks #endif*/ parent->fd[i]->motionNotify ((int)event->x, (int)event->y); } + return true; } -bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) { +bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) +{ // Gtk signals automatically acquire the GUI (i.e. this method is enclosed by gdk_thread_enter and gdk_thread_leave) parent->scroll (event->direction); @@ -853,102 +961,122 @@ bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event) { } -void ThumbBrowserBase::redraw () { +void ThumbBrowserBase::redraw () +{ GThreadLock lock; arrangeFiles (); queue_draw (); } -void ThumbBrowserBase::zoomChanged (bool zoomIn) { +void ThumbBrowserBase::zoomChanged (bool zoomIn) +{ + + int newHeight = 0; + int optThumbSize = getThumbnailHeight(); - int newHeight=0; - int optThumbSize=getThumbnailHeight(); if (zoomIn) - for (size_t i=0; i optThumbSize) + + if (newHeight > optThumbSize) { break; + } } else - for (size_t i=options.thumbnailZoomRatios.size()-1; i>0; i--) { + for (size_t i = options.thumbnailZoomRatios.size() - 1; i > 0; i--) { newHeight = (int)(options.thumbnailZoomRatios[i] * getMaxThumbnailHeight()); - if (newHeight < optThumbSize) + + if (newHeight < optThumbSize) { break; + } } + previewHeight = newHeight; saveThumbnailHeight(newHeight); { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - for (size_t i=0; iresize (previewHeight); + } } redraw (); #ifdef WIN32 gdk_window_process_updates (get_window()->gobj(), true); -#endif +#endif } -void ThumbBrowserBase::refreshThumbImages () { +void ThumbBrowserBase::refreshThumbImages () +{ int previewHeight = getThumbnailHeight(); { - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - for (size_t i=0; iresize (previewHeight); + for (size_t i = 0; i < fd.size(); i++) { + fd[i]->resize (previewHeight); + } } redraw (); } -void ThumbBrowserBase::refreshQuickThumbImages () { - #if PROTECT_VECTORS +void ThumbBrowserBase::refreshQuickThumbImages () +{ +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - for (size_t i=0; irefreshQuickThumbnailImage (); + for (size_t i = 0; i < fd.size(); ++i) { + fd[i]->refreshQuickThumbnailImage (); + } } -void ThumbBrowserBase::refreshEditedState (const std::set& efiles) { +void ThumbBrowserBase::refreshEditedState (const std::set& efiles) +{ editedFiles = efiles; { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - for (size_t i=0; iframed = editedFiles.find (fd[i]->filename)!=editedFiles.end(); + for (size_t i = 0; i < fd.size(); i++) { + fd[i]->framed = editedFiles.find (fd[i]->filename) != editedFiles.end(); + } } queue_draw (); } -void ThumbBrowserBase::setArrangement (Arrangement a) { +void ThumbBrowserBase::setArrangement (Arrangement a) +{ arrangement = a; redraw (); } -void ThumbBrowserBase::enableTabMode(bool enable) { +void ThumbBrowserBase::enableTabMode(bool enable) +{ location = enable ? THLOC_EDITOR : THLOC_FILEBROWSER; arrangement = enable ? ThumbBrowserBase::TB_Horizontal : ThumbBrowserBase::TB_Vertical; - if ((!options.sameThumbSize && (options.thumbSizeTab!=options.thumbSize)) || (options.showFileNames || options.filmStripShowFileNames)) { - #if PROTECT_VECTORS + if ((!options.sameThumbSize && (options.thumbSizeTab != options.thumbSize)) || (options.showFileNames || options.filmStripShowFileNames)) { +#if PROTECT_VECTORS MYWRITERLOCK(l, entryRW); - #endif +#endif - for (size_t i=0; iresize (getThumbnailHeight()); + } } redraw (); @@ -956,61 +1084,66 @@ void ThumbBrowserBase::enableTabMode(bool enable) { // Scroll to selected position if going into ribbon mode or back // Tab mode is horizontal, file browser is vertical { - #if PROTECT_VECTORS - MYREADERLOCK(l, entryRW); - #endif +#if PROTECT_VECTORS + MYREADERLOCK(l, entryRW); +#endif - if (!selected.empty()) { - if (enable) { - double h=selected[0]->getStartX(); - #if PROTECT_VECTORS - MYREADERLOCK_RELEASE(l); - #endif - hscroll.set_value (min(h, hscroll.get_adjustment()->get_upper())); - } else { - double v=selected[0]->getStartY(); - #if PROTECT_VECTORS - MYREADERLOCK_RELEASE(l); - #endif - vscroll.set_value (min(v, vscroll.get_adjustment()->get_upper())); + if (!selected.empty()) { + if (enable) { + double h = selected[0]->getStartX(); +#if PROTECT_VECTORS + MYREADERLOCK_RELEASE(l); +#endif + hscroll.set_value (min(h, hscroll.get_adjustment()->get_upper())); + } else { + double v = selected[0]->getStartY(); +#if PROTECT_VECTORS + MYREADERLOCK_RELEASE(l); +#endif + vscroll.set_value (min(v, vscroll.get_adjustment()->get_upper())); + } } } - } } -void ThumbBrowserBase::initEntry (ThumbBrowserEntryBase* entry) { +void ThumbBrowserBase::initEntry (ThumbBrowserEntryBase* entry) +{ entry->setOffset ((int)(hscroll.get_value()), (int)(vscroll.get_value())); } -void ThumbBrowserBase::getScrollPosition (double& h, double& v) { +void ThumbBrowserBase::getScrollPosition (double& h, double& v) +{ h = hscroll.get_value (); v = vscroll.get_value (); } -void ThumbBrowserBase::setScrollPosition (double h, double v) { - hscroll.set_value (h>hscroll.get_adjustment()->get_upper() ? hscroll.get_adjustment()->get_upper() : h); - vscroll.set_value (v>vscroll.get_adjustment()->get_upper() ? vscroll.get_adjustment()->get_upper() : v); +void ThumbBrowserBase::setScrollPosition (double h, double v) +{ + hscroll.set_value (h > hscroll.get_adjustment()->get_upper() ? hscroll.get_adjustment()->get_upper() : h); + vscroll.set_value (v > vscroll.get_adjustment()->get_upper() ? vscroll.get_adjustment()->get_upper() : v); } // needed for auto-height in single tab -int ThumbBrowserBase::getEffectiveHeight() { - int h=hscroll.get_height() + 2; // have 2 pixels rounding error for scroll bars to appear +int ThumbBrowserBase::getEffectiveHeight() +{ + int h = hscroll.get_height() + 2; // have 2 pixels rounding error for scroll bars to appear - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, entryRW); - #endif +#endif // Filtered items do not change in size, so take a non-filtered - for (size_t i=0;ifiltered) { - h+=fd[i]->getEffectiveHeight(); + h += fd[i]->getEffectiveHeight(); break; } return h; } -void ThumbBrowserBase::redrawNeeded (ThumbBrowserEntryBase* entry) { +void ThumbBrowserBase::redrawNeeded (ThumbBrowserEntryBase* entry) +{ // HOMBRE:DELETE ME? GThreadLock tLock; // Acquire the GUI diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h index 046afda22..bd410292d 100644 --- a/rtgui/thumbbrowserbase.h +++ b/rtgui/thumbbrowserbase.h @@ -7,7 +7,7 @@ * 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 @@ -29,32 +29,40 @@ /* * Class handling the list of ThumbBrowserEntry objects and their position in it's allocated space */ -class ThumbBrowserBase : public Gtk::VBox { +class ThumbBrowserBase : public Gtk::VBox +{ - class Internal : public Gtk::DrawingArea { - - Glib::RefPtr gc_; - int ofsX, ofsY; - ThumbBrowserBase* parent; - bool dirty; - public: - Internal (); - void setParent (ThumbBrowserBase* p); - void on_realize(); - bool on_expose_event(GdkEventExpose* event); - bool on_button_press_event (GdkEventButton* event); - bool on_button_release_event (GdkEventButton* event); - bool on_motion_notify_event (GdkEventMotion* event); - bool on_scroll_event (GdkEventScroll* event); - bool on_key_press_event (GdkEventKey* event); - bool on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); - void setPosition (int x, int y); + class Internal : public Gtk::DrawingArea + { - void setDirty () { dirty = true; } - bool isDirty () { return dirty; } + Glib::RefPtr gc_; + int ofsX, ofsY; + ThumbBrowserBase* parent; + bool dirty; + public: + Internal (); + void setParent (ThumbBrowserBase* p); + void on_realize(); + bool on_expose_event(GdkEventExpose* event); + bool on_button_press_event (GdkEventButton* event); + bool on_button_release_event (GdkEventButton* event); + bool on_motion_notify_event (GdkEventMotion* event); + bool on_scroll_event (GdkEventScroll* event); + bool on_key_press_event (GdkEventKey* event); + bool on_query_tooltip (int x, int y, bool keyboard_tooltip, const Glib::RefPtr& tooltip); + void setPosition (int x, int y); + + void setDirty () + { + dirty = true; + } + bool isDirty () + { + return dirty; + } }; - public: +public: enum eLocation { THLOC_BATCHQUEUE, @@ -62,15 +70,18 @@ class ThumbBrowserBase : public Gtk::VBox { THLOC_EDITOR } location; - protected: - virtual int getMaxThumbnailHeight() const { return options.maxThumbnailHeight; } // Differs between batch and file - virtual void saveThumbnailHeight (int height)=0; - virtual int getThumbnailHeight ()=0; +protected: + virtual int getMaxThumbnailHeight() const + { + return options.maxThumbnailHeight; // Differs between batch and file + } + virtual void saveThumbnailHeight (int height) = 0; + virtual int getThumbnailHeight () = 0; Internal internal; Gtk::HScrollbar hscroll; Gtk::VScrollbar vscroll; - + int inW, inH; Inspector *inspector; @@ -80,11 +91,17 @@ class ThumbBrowserBase : public Gtk::VBox { void resizeThumbnailArea (int w, int h); void internalAreaResized (Gtk::Allocation& req); void buttonPressed (int x, int y, int button, GdkEventType type, int state, int clx, int cly, int clw, int clh); - - public: - void setInspector(Inspector* inspector) { this->inspector = inspector; } - Inspector* getInspector() { return inspector; } +public: + + void setInspector(Inspector* inspector) + { + this->inspector = inspector; + } + Inspector* getInspector() + { + return inspector; + } void disableInspector(); void enableInspector(); enum Arrangement {TB_Horizontal, TB_Vertical}; @@ -98,11 +115,17 @@ class ThumbBrowserBase : public Gtk::VBox { void selectFirst (bool enlarge); void selectLast (bool enlarge); - virtual bool isInTabMode() { return false; } + virtual bool isInTabMode() + { + return false; + } - eLocation getLocation() { return location; } + eLocation getLocation() + { + return location; + } - protected: +protected: int eventTime; @@ -110,7 +133,7 @@ class ThumbBrowserBase : public Gtk::VBox { std::vector fd; std::vector selected; ThumbBrowserEntryBase* lastClicked; - + int previewHeight; int numOfCols; @@ -121,39 +144,57 @@ class ThumbBrowserBase : public Gtk::VBox { void arrangeFiles (); void zoomChanged (bool zoomIn); - public: - +public: + ThumbBrowserBase (); - void zoomIn () { zoomChanged (true); } - void zoomOut () { zoomChanged (false); } + void zoomIn () + { + zoomChanged (true); + } + void zoomOut () + { + zoomChanged (false); + } int getEffectiveHeight (); - - const std::vector& getEntries () { return fd; } + + const std::vector& getEntries () + { + return fd; + } void on_style_changed (const Glib::RefPtr& style); void redraw (); // arrange files and draw area void refreshThumbImages (); // refresh thumbnail sizes, re-generate thumbnail images, arrange and draw void refreshQuickThumbImages (); // refresh thumbnail sizes, re-generate thumbnail images, arrange and draw void refreshEditedState (const std::set& efiles); - + void initEntry (ThumbBrowserEntryBase* entry); void getScrollPosition (double& h, double& v); void setScrollPosition (double h, double v); - + void setArrangement (Arrangement a); void enableTabMode(bool enable); // set both thumb sizes and arrangements - virtual bool checkFilter (ThumbBrowserEntryBase* entry) { return true; } + virtual bool checkFilter (ThumbBrowserEntryBase* entry) + { + return true; + } virtual void rightClicked (ThumbBrowserEntryBase* entry) {} virtual void doubleClicked (ThumbBrowserEntryBase* entry) {} - virtual bool keyPressed (GdkEventKey* event) {return true;} + virtual bool keyPressed (GdkEventKey* event) + { + return true; + } virtual void selectionChanged () {} - + virtual void redrawNeeded (ThumbBrowserEntryBase* entry); virtual void thumbRearrangementNeeded () {} - Gtk::Widget* getDrawingArea () { return &internal; } + Gtk::Widget* getDrawingArea () + { + return &internal; + } }; #endif diff --git a/rtgui/thumbbrowserentry.cc b/rtgui/thumbbrowserentry.cc index 7703e9775..1c491a641 100644 --- a/rtgui/thumbbrowserentry.cc +++ b/rtgui/thumbbrowserentry.cc @@ -7,7 +7,7 @@ * 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 @@ -18,41 +18,52 @@ */ #include -FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) - : ThumbBrowserEntryBase (fname), thumbnail(thm) { - +FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) + : ThumbBrowserEntryBase (fname), thumbnail(thm) +{ + previewOwner = false; italicstyle = thumbnail->getType() != FT_Raw; datetimeline = thumbnail->getDateTimeString (); exifline = thumbnail->getExifString (); } -void ThumbBrowserEntry::obtainThumbnailSize () { +void ThumbBrowserEntry::obtainThumbnailSize () +{ - if (thumbnail) + if (thumbnail) { thumbnail->getThumbnailSize (prew, preh); + } } Glib::RefPtr ThumbBrowserEntry::editedIcon; Glib::RefPtr ThumbBrowserEntry::recentlySavedIcon; Glib::RefPtr ThumbBrowserEntry::enqueuedIcon; -std::vector > ThumbBrowserEntry::getIconsOnImageArea () { +std::vector > ThumbBrowserEntry::getIconsOnImageArea () +{ std::vector > ret; - - if (!thumbnail) + + if (!thumbnail) { return ret; + } - if (thumbnail->hasProcParams() && editedIcon) + if (thumbnail->hasProcParams() && editedIcon) { ret.push_back (editedIcon); - if (thumbnail->isRecentlySaved() && recentlySavedIcon) - ret.push_back (recentlySavedIcon); - if (thumbnail->isEnqueued () && enqueuedIcon) - ret.push_back (enqueuedIcon); + } - return ret; + if (thumbnail->isRecentlySaved() && recentlySavedIcon) { + ret.push_back (recentlySavedIcon); + } + + if (thumbnail->isEnqueued () && enqueuedIcon) { + ret.push_back (enqueuedIcon); + } + + return ret; } -ThumbnailButtonSet* ThumbBrowserEntry::getThumbButtonSet () { +ThumbnailButtonSet* ThumbBrowserEntry::getThumbButtonSet () +{ return (ThumbnailButtonSet*)buttonSet; } diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 59d669c4f..f9f8f9f1e 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -7,7 +7,7 @@ * 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 @@ -21,7 +21,7 @@ #include "options.h" #include "../rtengine/mytime.h" -ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) +ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : fnlabw(0), fnlabh(0), dtlabw(0), dtlabh(0), exlabw(0), exlabh(0), prew(0), preh(0), prex(0), prey(0), upperMargin(6), borderWidth(1), textGap(6), sideMargin(8), lowerMargin(8), preview(NULL), dispname(Glib::path_get_basename (fname)), buttonSet(NULL), width(0), height(0), @@ -31,36 +31,49 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) selected(false), drawable(false), filtered(false), framed(false), processing(false), italicstyle(false), edited(false), recentlysaved(false), updatepriority(false), withFilename(WFNAME_NONE) {} -ThumbBrowserEntryBase::~ThumbBrowserEntryBase () { +ThumbBrowserEntryBase::~ThumbBrowserEntryBase () +{ + + if (preview) { + delete [] preview; + } - if (preview) delete [] preview; delete buttonSet; } -void ThumbBrowserEntryBase::addButtonSet (LWButtonSet* bs) { +void ThumbBrowserEntryBase::addButtonSet (LWButtonSet* bs) +{ buttonSet = bs; } -void ThumbBrowserEntryBase::updateBackBuffer () { +void ThumbBrowserEntryBase::updateBackBuffer () +{ - if (!parent) + if (!parent) { return; + } Gtk::Widget* w = parent->getDrawingArea (); Glib::RefPtr win = w->get_window(); + if (!win) // Nothing to draw on, so we return + { return; + } backBuffer = Gdk::Pixmap::create (win, exp_width, exp_height); // If thumbnail is hidden by a filter drawing to it will crash - int backbuffer_w=0, backbuffer_h=0; + int backbuffer_w = 0, backbuffer_h = 0; backBuffer->get_size(backbuffer_w, backbuffer_h); + // if either with or height is zero then return early - if (backbuffer_w * backbuffer_h == 0) return; + if (backbuffer_w * backbuffer_h == 0) { + return; + } bbSelected = selected; bbFramed = framed; @@ -71,7 +84,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () { Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); Gdk::Color bgn = w->get_style()->get_bg(Gtk::STATE_NORMAL); - Gdk::Color bgs = w->get_style()->get_bg(Gtk::STATE_SELECTED); + Gdk::Color bgs = w->get_style()->get_bg(Gtk::STATE_SELECTED); // clear area, draw frames and background gc_->set_foreground (bgn); @@ -82,6 +95,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () { // calculate height of button set int bsHeight = 0; + if (buttonSet) { int tmp; buttonSet->getAllocatedDimensions (tmp, bsHeight); @@ -91,13 +105,13 @@ void ThumbBrowserEntryBase::updateBackBuffer () { //backBuffer->draw_rectangle (gc_, false, (exp_width-prew)/2, upperMargin+bsHeight, prew+1, preh+1); // draw thumbnail image if (preview) { - prex = borderWidth + (exp_width-prew)/2; - prey = upperMargin+bsHeight+borderWidth; - backBuffer->draw_rgb_image (gc_, prex, prey, prew, preh, Gdk::RGB_DITHER_NONE, preview, prew*3); + prex = borderWidth + (exp_width - prew) / 2; + prey = upperMargin + bsHeight + borderWidth; + backBuffer->draw_rgb_image (gc_, prex, prey, prew, preh, Gdk::RGB_DITHER_NONE, preview, prew * 3); } customBackBufferUpdate (cr); - + // draw icons onto the thumbnail area bbIcons = getIconsOnImageArea (); @@ -109,33 +123,40 @@ void ThumbBrowserEntryBase::updateBackBuffer () { int istartx = prex; int istarty = prey; - if ((parent->getLocation()!=ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && options.overlayedFileNames) - || (parent->getLocation()==ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && options.filmStripOverlayedFileNames)) { + if ((parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && options.overlayedFileNames) + || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && options.filmStripOverlayedFileNames)) { cr->begin_new_path (); - cr->rectangle (istartx, istarty, prew, fnlabh+dtlabh+exlabh+2*iofs_y); - if ((texts.get_red_p()+texts.get_green_p()+texts.get_blue_p())/3 > 0.5) + cr->rectangle (istartx, istarty, prew, fnlabh + dtlabh + exlabh + 2 * iofs_y); + + if ((texts.get_red_p() + texts.get_green_p() + texts.get_blue_p()) / 3 > 0.5) { cr->set_source_rgba (0, 0, 0, 0.5); - else + } else { cr->set_source_rgba (1, 1, 1, 0.5); + } + cr->fill (); } istartx += iofs_x; istarty += iofs_y; - + if (!bbIcons.empty()) { int iwidth = 0; int iheight = 0; - for (size_t i=0; iget_width() + (i>0 ? igap : 0); - if (bbIcons[i]->get_height() > iheight) + + for (size_t i = 0; i < bbIcons.size(); i++) { + iwidth += bbIcons[i]->get_width() + (i > 0 ? igap : 0); + + if (bbIcons[i]->get_height() > iheight) { iheight = bbIcons[i]->get_height(); + } } - if ((parent->getLocation()!=ThumbBrowserBase::THLOC_EDITOR && (!options.showFileNames || !options.overlayedFileNames)) - || (parent->getLocation()==ThumbBrowserBase::THLOC_EDITOR && (!options.filmStripShowFileNames || !options.filmStripOverlayedFileNames))) { + + if ((parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && (!options.showFileNames || !options.overlayedFileNames)) + || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && (!options.filmStripShowFileNames || !options.filmStripOverlayedFileNames))) { // Draw the transparent black background around icons cr->begin_new_path (); - cr->move_to(istartx-igap, istarty); + cr->move_to(istartx - igap, istarty); cr->rel_line_to(igap, -igap); cr->rel_line_to(iwidth, 0); cr->rel_line_to(igap, igap); @@ -147,85 +168,102 @@ void ThumbBrowserEntryBase::updateBackBuffer () { cr->set_source_rgba (0, 0, 0, 0.6); cr->fill (); } - for (size_t i=0; idraw_pixbuf (gc_, bbIcons[i], 0, 0, istartx, istarty, bbIcons[i]->get_width(), bbIcons[i]->get_height(), Gdk::RGB_DITHER_NONE, 0, 0); istartx += bbIcons[i]->get_width() + igap; } } - if ( ( (parent->getLocation()!=ThumbBrowserBase::THLOC_EDITOR && options.showFileNames) - || (parent->getLocation()==ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames)) - && withFilename>WFNAME_NONE) - { - int textposx_fn, textposx_ex, textposx_dt, textposy, textw; - if (! ((parent->getLocation()!=ThumbBrowserBase::THLOC_EDITOR && options.overlayedFileNames) - || (parent->getLocation()==ThumbBrowserBase::THLOC_EDITOR && options.filmStripOverlayedFileNames)) ) - { - textposx_fn = exp_width/2 - fnlabw/2; - if (textposx_fn<0) textposx_fn = 0; - textposx_ex = exp_width/2 - exlabw/2; - if (textposx_ex<0) textposx_ex = 0; - textposx_dt = exp_width/2 - dtlabw/2; - if (textposx_dt<0) textposx_dt = 0; - textposy = upperMargin + bsHeight + 2*borderWidth + preh + borderWidth + textGap; - textw = exp_width - 2*textGap; - gc_->set_foreground (selected ? texts : textn); - } - else { - textposx_fn = istartx; - textposx_ex = istartx; - textposx_dt = istartx; - textposy = istarty; - textw = prew - (istartx - prex); - gc_->set_foreground (texts); - } + if ( ( (parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames) + || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames)) + && withFilename > WFNAME_NONE) { + int textposx_fn, textposx_ex, textposx_dt, textposy, textw; - // draw file name - Glib::RefPtr context = w->get_pango_context () ; - Pango::FontDescription fontd = context->get_font_description (); - fontd.set_weight (Pango::WEIGHT_BOLD); - if (italicstyle) - fontd.set_style (Pango::STYLE_ITALIC); - else - fontd.set_style (Pango::STYLE_NORMAL); + if (! ((parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.overlayedFileNames) + || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripOverlayedFileNames)) ) { + textposx_fn = exp_width / 2 - fnlabw / 2; - context->set_font_description (fontd); - Glib::RefPtr fn = w->create_pango_layout (dispname); - fn->set_width (textw*Pango::SCALE); - fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); - backBuffer->draw_layout(gc_, textposx_fn, textposy, fn); + if (textposx_fn < 0) { + textposx_fn = 0; + } - fontd.set_weight (Pango::WEIGHT_NORMAL); - fontd.set_style (Pango::STYLE_NORMAL); - context->set_font_description (fontd); + textposx_ex = exp_width / 2 - exlabw / 2; - if (withFilename==WFNAME_FULL) { - // draw date/time label - int tpos = fnlabh; - if (options.fbShowDateTime && datetimeline!="") { - fn = w->create_pango_layout (datetimeline); - fn->set_width (textw*Pango::SCALE); - fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); - backBuffer->draw_layout(gc_, textposx_dt, textposy + tpos, fn); - tpos += dtlabh; - } - // draw basic exif info - if (options.fbShowBasicExif && exifline!="") { - fn = w->create_pango_layout (exifline); - fn->set_width (textw*Pango::SCALE); - fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); - backBuffer->draw_layout (gc_, textposx_ex, textposy + tpos, fn); - tpos += exlabh; - } - } - } + if (textposx_ex < 0) { + textposx_ex = 0; + } + + textposx_dt = exp_width / 2 - dtlabw / 2; + + if (textposx_dt < 0) { + textposx_dt = 0; + } + + textposy = upperMargin + bsHeight + 2 * borderWidth + preh + borderWidth + textGap; + textw = exp_width - 2 * textGap; + gc_->set_foreground (selected ? texts : textn); + } else { + textposx_fn = istartx; + textposx_ex = istartx; + textposx_dt = istartx; + textposy = istarty; + textw = prew - (istartx - prex); + gc_->set_foreground (texts); + } + + // draw file name + Glib::RefPtr context = w->get_pango_context () ; + Pango::FontDescription fontd = context->get_font_description (); + fontd.set_weight (Pango::WEIGHT_BOLD); + + if (italicstyle) { + fontd.set_style (Pango::STYLE_ITALIC); + } else { + fontd.set_style (Pango::STYLE_NORMAL); + } + + context->set_font_description (fontd); + Glib::RefPtr fn = w->create_pango_layout (dispname); + fn->set_width (textw * Pango::SCALE); + fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); + backBuffer->draw_layout(gc_, textposx_fn, textposy, fn); + + fontd.set_weight (Pango::WEIGHT_NORMAL); + fontd.set_style (Pango::STYLE_NORMAL); + context->set_font_description (fontd); + + if (withFilename == WFNAME_FULL) { + // draw date/time label + int tpos = fnlabh; + + if (options.fbShowDateTime && datetimeline != "") { + fn = w->create_pango_layout (datetimeline); + fn->set_width (textw * Pango::SCALE); + fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); + backBuffer->draw_layout(gc_, textposx_dt, textposy + tpos, fn); + tpos += dtlabh; + } + + // draw basic exif info + if (options.fbShowBasicExif && exifline != "") { + fn = w->create_pango_layout (exifline); + fn->set_width (textw * Pango::SCALE); + fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); + backBuffer->draw_layout (gc_, textposx_ex, textposy + tpos, fn); + tpos += exlabh; + } + } + } } -void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) { +void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) +{ - if (!parent) + if (!parent) { return; - + } + Gtk::Widget* w = parent->getDrawingArea (); // calculate dimensions of the text based fields @@ -233,9 +271,9 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) { Glib::RefPtr context = w->get_pango_context () ; context->set_font_description (w->get_style()->get_font()); - + // filename: - Pango::FontDescription fontd = context->get_font_description (); + Pango::FontDescription fontd = context->get_font_description (); fontd.set_weight (Pango::WEIGHT_BOLD); context->set_font_description (fontd); Glib::RefPtr fn = w->create_pango_layout(shortname); @@ -245,7 +283,7 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) { infoh = fnlabh; infow = 0; - if (withFilename==WFNAME_FULL) { + if (withFilename == WFNAME_FULL) { // datetime fontd.set_weight (Pango::WEIGHT_NORMAL); context->set_font_description (fontd); @@ -259,160 +297,178 @@ void ThumbBrowserEntryBase::getTextSizes (int& infow, int& infoh) { // add date/tile size: if (options.fbShowDateTime) { infoh += dtlabh; - if (dtlabw + 2*sideMargin > infow) - infow = dtlabw + 2*sideMargin; - } - else { + + if (dtlabw + 2 * sideMargin > infow) { + infow = dtlabw + 2 * sideMargin; + } + } else { dtlabw = dtlabh = 0; } + if (options.fbShowBasicExif) { infoh += exlabh; - if (exlabw + 2*sideMargin > infow) - infow = exlabw + 2*sideMargin; - } - else { + + if (exlabw + 2 * sideMargin > infow) { + infow = exlabw + 2 * sideMargin; + } + } else { exlabw = exlabh = 0; } - } - else { + } else { dtlabw = dtlabh = exlabw = exlabh = 0; } } -void ThumbBrowserEntryBase::resize (int h) { +void ThumbBrowserEntryBase::resize (int h) +{ - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, lockRW); - #endif +#endif height = h; int old_preh = preh, old_width = width; // dimensions of the button set - int bsw=0, bsh=0; - if (buttonSet) + int bsw = 0, bsh = 0; + + if (buttonSet) { buttonSet->getMinimalDimensions (bsw, bsh); + } if (parent->getLocation() == ThumbBrowserBase::THLOC_FILEBROWSER) { - if (options.showFileNames) + if (options.showFileNames) { withFilename = WFNAME_FULL; - else + } else { withFilename = WFNAME_NONE; - } - else if (parent->getLocation() == ThumbBrowserBase::THLOC_BATCHQUEUE) { + } + } else if (parent->getLocation() == ThumbBrowserBase::THLOC_BATCHQUEUE) { withFilename = WFNAME_REDUCED; - } - else { - if (options.filmStripShowFileNames) + } else { + if (options.filmStripShowFileNames) { withFilename = WFNAME_REDUCED; - else + } else { withFilename = WFNAME_NONE; + } } // calculate the height remaining for the thumbnail image - preh = height - upperMargin - 2*borderWidth - lowerMargin - bsh; - int infow=0; - int infoh=0; - if ( (parent->getLocation()!=ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && !options.overlayedFileNames) - || (parent->getLocation()==ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && !options.filmStripOverlayedFileNames)) - { + preh = height - upperMargin - 2 * borderWidth - lowerMargin - bsh; + int infow = 0; + int infoh = 0; + + if ( (parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && !options.overlayedFileNames) + || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && !options.filmStripOverlayedFileNames)) { // dimensions of the info text getTextSizes (infow, infoh); infoh += textGap; //preh -= infoh; height += infoh; } + // Minimum size for thumbs - if (preh<24){ - preh=24; - height = preh + (upperMargin + 2*borderWidth + lowerMargin)+ bsh + infoh; + if (preh < 24) { + preh = 24; + height = preh + (upperMargin + 2 * borderWidth + lowerMargin) + bsh + infoh; } calcThumbnailSize (); // recalculates prew - width = prew + 2*sideMargin + 2*borderWidth; - if ( (parent->getLocation()!=ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && !options.overlayedFileNames) - || (parent->getLocation()==ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && !options.filmStripOverlayedFileNames)) - { - width = prew + 2*sideMargin + 2*borderWidth; - if (widthgetLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames && !options.overlayedFileNames) + || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames && !options.filmStripOverlayedFileNames)) { + width = prew + 2 * sideMargin + 2 * borderWidth; + + if (width < infow + 2 * sideMargin + 2 * borderWidth) { + width = infow + 2 * sideMargin + 2 * borderWidth; + } + } + + if (width < bsw + 2 * sideMargin + 2 * borderWidth) { + width = bsw + 2 * sideMargin + 2 * borderWidth; + } + + if ( preh != old_preh || width != old_width ) { delete [] preview; preview = NULL; refreshThumbnailImage (); + } else { + backBuffer.clear(); // This will force a backBuffer update on queue_draw } - else - backBuffer.clear(); // This will force a backBuffer update on queue_draw drawable = true; } -void ThumbBrowserEntryBase::drawFrame (Cairo::RefPtr cr, const Gdk::Color& bg, const Gdk::Color& fg) { +void ThumbBrowserEntryBase::drawFrame (Cairo::RefPtr cr, const Gdk::Color& bg, const Gdk::Color& fg) +{ int radius = 8; + if (selected || framed) { cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); cr->move_to (radius, 0); - cr->arc (exp_width-1-radius, radius, radius, -M_PI/2, 0); - cr->arc (exp_width-1-radius, exp_height-1-radius, radius, 0, M_PI/2); - cr->arc (radius, exp_height-1-radius, radius, M_PI/2, M_PI); - cr->arc (radius, radius, radius, M_PI, -M_PI/2); + cr->arc (exp_width - 1 - radius, radius, radius, -M_PI / 2, 0); + cr->arc (exp_width - 1 - radius, exp_height - 1 - radius, radius, 0, M_PI / 2); + cr->arc (radius, exp_height - 1 - radius, radius, M_PI / 2, M_PI); + cr->arc (radius, radius, radius, M_PI, -M_PI / 2); cr->close_path (); + if (selected) { cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p()); cr->fill_preserve (); } - cr->set_source_rgb (bg.get_red_p()*2/3, bg.get_green_p()*2/3, bg.get_blue_p()*2/3); + + cr->set_source_rgb (bg.get_red_p() * 2 / 3, bg.get_green_p() * 2 / 3, bg.get_blue_p() * 2 / 3); cr->set_line_width (1.0); cr->stroke (); - + } if (framed) { cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); - cr->move_to (+2+0.5+radius, +2+0.5); - cr->arc (-2+0.5+exp_width-1-radius, +2+0.5+radius, radius, -M_PI/2, 0); - cr->arc (-2+0.5+exp_width-1-radius, -2+0.5+exp_height-1-radius, radius, 0, M_PI/2); - cr->arc (+2+0.5+radius, -2+exp_height-1-radius, radius, M_PI/2, M_PI); - cr->arc (+2+0.5+radius, +2+radius, radius, M_PI, -M_PI/2); + cr->move_to (+2 + 0.5 + radius, +2 + 0.5); + cr->arc (-2 + 0.5 + exp_width - 1 - radius, +2 + 0.5 + radius, radius, -M_PI / 2, 0); + cr->arc (-2 + 0.5 + exp_width - 1 - radius, -2 + 0.5 + exp_height - 1 - radius, radius, 0, M_PI / 2); + cr->arc (+2 + 0.5 + radius, -2 + exp_height - 1 - radius, radius, M_PI / 2, M_PI); + cr->arc (+2 + 0.5 + radius, +2 + radius, radius, M_PI, -M_PI / 2); cr->close_path (); cr->set_source_rgb (fg.get_red_p(), fg.get_green_p(), fg.get_blue_p()); cr->set_line_width (2.0); cr->stroke (); - } + } } -void ThumbBrowserEntryBase::draw () { +void ThumbBrowserEntryBase::draw () +{ - if (!drawable || !parent) + if (!drawable || !parent) { return; + } - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYREADERLOCK(l, lockRW); // No resizes, position moves etc. inbetween - #endif +#endif int bbWidth, bbHeight; - if (backBuffer) - backBuffer->get_size (bbWidth, bbHeight); - if (!backBuffer || selected!=bbSelected || framed!=bbFramed || preview!=bbPreview - || exp_width!=bbWidth || exp_height!=bbHeight || getIconsOnImageArea ()!=bbIcons) + if (backBuffer) { + backBuffer->get_size (bbWidth, bbHeight); + } + + if (!backBuffer || selected != bbSelected || framed != bbFramed || preview != bbPreview + || exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons) { updateBackBuffer (); + } Gtk::Widget* w = parent->getDrawingArea (); Glib::RefPtr gc_ = Gdk::GC::create (w->get_window()); - // Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); - // Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); +// Gdk::Color textn = w->get_style()->get_text(Gtk::STATE_NORMAL); + // Gdk::Color texts = w->get_style()->get_text(Gtk::STATE_SELECTED); Gdk::Color bgn = w->get_style()->get_bg(Gtk::STATE_NORMAL); - Gdk::Color bgs = w->get_style()->get_bg(Gtk::STATE_SELECTED); + Gdk::Color bgs = w->get_style()->get_bg(Gtk::STATE_SELECTED); w->get_window()->draw_drawable (gc_, backBuffer, 0, 0, startx + ofsX, starty + ofsY); @@ -420,7 +476,7 @@ void ThumbBrowserEntryBase::draw () { // drawProgressBar (window, gc_, selected ? texts : textn, selected ? bgs : bgn, ofsX+startx, exp_width, ofsY+starty + upperMargin+bsHeight+borderWidth+preh+borderWidth+textGap+tpos, fnlabh); - // redraw button set above the thumbnail + // redraw button set above the thumbnail if (buttonSet) { buttonSet->setColors (selected ? bgs : bgn, selected ? bgn : bgs); Cairo::RefPtr cc = w->get_window()->create_cairo_context(); @@ -428,82 +484,103 @@ void ThumbBrowserEntryBase::draw () { } } -void ThumbBrowserEntryBase::setPosition (int x, int y, int w, int h) { +void ThumbBrowserEntryBase::setPosition (int x, int y, int w, int h) +{ - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, lockRW); - #endif +#endif exp_width = w; exp_height = h; startx = x; starty = y; - - if (buttonSet) - buttonSet->arrangeButtons (ofsX+x+sideMargin, ofsY+y+upperMargin, w-2*sideMargin, -1); + + if (buttonSet) { + buttonSet->arrangeButtons (ofsX + x + sideMargin, ofsY + y + upperMargin, w - 2 * sideMargin, -1); + } } -void ThumbBrowserEntryBase::setOffset (int x, int y) { +void ThumbBrowserEntryBase::setOffset (int x, int y) +{ - #if PROTECT_VECTORS +#if PROTECT_VECTORS MYWRITERLOCK(l, lockRW); - #endif +#endif ofsX = -x; ofsY = -y; - - if (buttonSet) - buttonSet->move (ofsX+startx+sideMargin, ofsY+starty+upperMargin); + + if (buttonSet) { + buttonSet->move (ofsX + startx + sideMargin, ofsY + starty + upperMargin); + } } -bool ThumbBrowserEntryBase::inside (int x, int y) { +bool ThumbBrowserEntryBase::inside (int x, int y) +{ - return x>ofsX+startx && xofsY+starty && y ofsX + startx && x < ofsX + startx + exp_width && y > ofsY + starty && y < ofsY + starty + exp_height; } -void ThumbBrowserEntryBase::getPosInImgSpace (int x, int y, rtengine::Coord2D &coord) { +void ThumbBrowserEntryBase::getPosInImgSpace (int x, int y, rtengine::Coord2D &coord) +{ coord.x = coord.y = -1.; + if (preview) { - x -= ofsX+startx; - y -= ofsY+starty; - if (x>=prex && x<=prex+prew && y>=prey && y<=prey+preh) { - coord.x = double(x-prex)/double(prew); - coord.y = double(y-prey)/double(preh); + x -= ofsX + startx; + y -= ofsY + starty; + + if (x >= prex && x <= prex + prew && y >= prey && y <= prey + preh) { + coord.x = double(x - prex) / double(prew); + coord.y = double(y - prey) / double(preh); } } } -bool ThumbBrowserEntryBase::insideWindow (int x, int y, int w, int h) { +bool ThumbBrowserEntryBase::insideWindow (int x, int y, int w, int h) +{ - return !(ofsX+startx>x+w || ofsX+startx+exp_widthy+h || ofsY+starty+exp_height x + w || ofsX + startx + exp_width < x || ofsY + starty > y + h || ofsY + starty + exp_height < y); +} -bool ThumbBrowserEntryBase::motionNotify (int x, int y) { +bool ThumbBrowserEntryBase::motionNotify (int x, int y) +{ return buttonSet ? buttonSet->motionNotify (x, y) : false; } -bool ThumbBrowserEntryBase::pressNotify (int button, int type, int bstate, int x, int y) { +bool ThumbBrowserEntryBase::pressNotify (int button, int type, int bstate, int x, int y) +{ return buttonSet ? buttonSet->pressNotify (x, y) : false; } -bool ThumbBrowserEntryBase::releaseNotify (int button, int type, int bstate, int x, int y) { +bool ThumbBrowserEntryBase::releaseNotify (int button, int type, int bstate, int x, int y) +{ return buttonSet ? buttonSet->releaseNotify (x, y) : false; } -Glib::ustring ThumbBrowserEntryBase::getToolTip (int x, int y) { +Glib::ustring ThumbBrowserEntryBase::getToolTip (int x, int y) +{ Glib::ustring tooltip = ""; - - if (buttonSet) tooltip = buttonSet->getToolTip (x, y); + + if (buttonSet) { + tooltip = buttonSet->getToolTip (x, y); + } // if the fileinfo is not shown anyway, make a tooltip with the info - if (withFilename backBuffer; bool bbSelected, bbFramed; guint8* bbPreview; std::vector > bbIcons; - + void drawFrame (Cairo::RefPtr cr, const Gdk::Color& bg, const Gdk::Color& fg); void getTextSizes (int& w, int& h); - + // called during updateBackBuffer for custom overlays virtual void customBackBufferUpdate (Cairo::RefPtr c) {} - - public: - + +public: + Thumbnail* thumbnail; // thumbnail preview properties: @@ -93,7 +94,7 @@ protected: Glib::ustring exifline; Glib::ustring datetimeline; -// misc attributes +// misc attributes bool selected; bool drawable; bool filtered; @@ -104,27 +105,57 @@ protected: bool recentlysaved; bool updatepriority; eWithFilename withFilename; - - ThumbBrowserEntryBase (const Glib::ustring& fname); + + ThumbBrowserEntryBase (const Glib::ustring& fname); virtual ~ThumbBrowserEntryBase (); - - void setParent (ThumbBrowserBase* l) { parent = l; } + + void setParent (ThumbBrowserBase* l) + { + parent = l; + } void updateBackBuffer (); - void resize (int h); + void resize (int h); virtual void draw (); - - void addButtonSet (LWButtonSet* bs); - int getMinimalHeight () { return height; } - int getMinimalWidth () { return width; } - int getEffectiveWidth () const { return exp_width; } - int getEffectiveHeight () const { return exp_height; } - int getPreviewHeight () const { return preh; } - int getStartX () const { return startx; } - int getStartY () const { return starty; } - int getX () const { return ofsX+startx; } - int getY () const { return ofsY+starty; } + void addButtonSet (LWButtonSet* bs); + int getMinimalHeight () + { + return height; + } + int getMinimalWidth () + { + return width; + } + + int getEffectiveWidth () const + { + return exp_width; + } + int getEffectiveHeight () const + { + return exp_height; + } + int getPreviewHeight () const + { + return preh; + } + int getStartX () const + { + return startx; + } + int getStartY () const + { + return starty; + } + int getX () const + { + return ofsX + startx; + } + int getY () const + { + return ofsY + starty; + } bool inside (int x, int y); void getPosInImgSpace (int x, int y, rtengine::Coord2D &coord); @@ -132,16 +163,27 @@ protected: void setPosition (int x, int y, int w, int h); void setOffset (int x, int y); - bool operator< (ThumbBrowserEntryBase& other) { return shortname.casefold()>other.shortname.casefold(); } - + bool operator< (ThumbBrowserEntryBase& other) + { + return shortname.casefold() > other.shortname.casefold(); + } + virtual void refreshThumbnailImage () {} virtual void refreshQuickThumbnailImage () {} virtual void calcThumbnailSize () {} virtual void drawProgressBar (Glib::RefPtr win, Glib::RefPtr gc, const Gdk::Color& foregr, const Gdk::Color& backgr, int x, int w, int y, int h) {} - virtual std::vector > getIconsOnImageArea () { std::vector > r; return r; } - virtual void getIconSize (int& w, int& h) { w=0; h=0; } + virtual std::vector > getIconsOnImageArea () + { + std::vector > r; + return r; + } + virtual void getIconSize (int& w, int& h) + { + w = 0; + h = 0; + } virtual bool motionNotify (int x, int y); virtual bool pressNotify (int button, int type, int bstate, int x, int y); diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index 03ae89da3..3f5861677 100644 --- a/rtgui/thumbimageupdater.cc +++ b/rtgui/thumbimageupdater.cc @@ -7,7 +7,7 @@ * 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 @@ -25,299 +25,278 @@ #ifdef _OPENMP #include -#endif +#endif #define DEBUG(format,args...) //#define DEBUG(format,args...) printf("ThumbImageUpdate::%s: " format "\n", __FUNCTION__, ## args) class -ThumbImageUpdater::Impl + ThumbImageUpdater::Impl { public: - struct Job - { - Job(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, - ThumbImageUpdateListener* listener): - tbe_(tbe), - /*pparams_(pparams), - height_(height), */ - priority_(priority), - upgrade_(upgrade), - listener_(listener) - {} + struct Job { + Job(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, + ThumbImageUpdateListener* listener): + tbe_(tbe), + /*pparams_(pparams), + height_(height), */ + priority_(priority), + upgrade_(upgrade), + listener_(listener) + {} - Job(): - tbe_(0), - priority_(NULL), - upgrade_(false), - listener_(0) - {} + Job(): + tbe_(0), + priority_(NULL), + upgrade_(false), + listener_(0) + {} - ThumbBrowserEntryBase* tbe_; - /*rtengine::procparams::ProcParams pparams_; - int height_;*/ - bool* priority_; - bool upgrade_; - ThumbImageUpdateListener* listener_; - }; + ThumbBrowserEntryBase* tbe_; + /*rtengine::procparams::ProcParams pparams_; + int height_;*/ + bool* priority_; + bool upgrade_; + ThumbImageUpdateListener* listener_; + }; - typedef std::list JobList; + typedef std::list JobList; - Impl(): - active_(0), - inactive_waiting_(false) - { - int threadCount = 1; + Impl(): + active_(0), + inactive_waiting_(false) + { + int threadCount = 1; #if !(__GNUC__ == 4 && __GNUC_MINOR__ == 8 && defined( WIN32 ) && defined(__x86_64__)) - // See Issue 2431 for explanation - #ifdef _OPENMP - threadCount = omp_get_num_procs(); - #endif + // See Issue 2431 for explanation +#ifdef _OPENMP + threadCount = omp_get_num_procs(); +#endif #endif - - threadPool_=new Glib::ThreadPool(threadCount,0); - } - Glib::ThreadPool* threadPool_; + threadPool_ = new Glib::ThreadPool(threadCount, 0); + } - // Need to be a Glib::Threads::Mutex because used in a Glib::Threads::Cond object... - // This is the only exceptions in RT so far, MyMutex is used everywhere else - #ifdef WIN32 - Glib::Mutex mutex_; - #else - Glib::Threads::Mutex mutex_; - #endif + Glib::ThreadPool* threadPool_; - JobList jobs_; + // Need to be a Glib::Threads::Mutex because used in a Glib::Threads::Cond object... + // This is the only exceptions in RT so far, MyMutex is used everywhere else +#ifdef WIN32 + Glib::Mutex mutex_; +#else + Glib::Threads::Mutex mutex_; +#endif - unsigned int active_; + JobList jobs_; - bool inactive_waiting_; + unsigned int active_; - #ifdef WIN32 - Glib::Cond inactive_; - #else - Glib::Threads::Cond inactive_; - #endif + bool inactive_waiting_; - void - processNextJob() - { - Job j; +#ifdef WIN32 + Glib::Cond inactive_; +#else + Glib::Threads::Cond inactive_; +#endif - { - #ifdef WIN32 - Glib::Mutex::Lock lock(mutex_); - #else - Glib::Threads::Mutex::Lock lock(mutex_); - #endif + void + processNextJob() + { + Job j; - // nothing to do; could be jobs have been removed - if ( jobs_.empty() ) - { - DEBUG("processing: nothing to do (%d)",jobs_.empty()); - return; - } + { +#ifdef WIN32 + Glib::Mutex::Lock lock(mutex_); +#else + Glib::Threads::Mutex::Lock lock(mutex_); +#endif - JobList::iterator i; + // nothing to do; could be jobs have been removed + if ( jobs_.empty() ) { + DEBUG("processing: nothing to do (%d)", jobs_.empty()); + return; + } - // see if any priority jobs exist - for ( i = jobs_.begin(); i != jobs_.end(); ++i) - { - if ( *(i->priority_) ) - { - DEBUG("processing(priority) %s",i->tbe_->thumbnail->getFileName().c_str()); - break; - } - } + JobList::iterator i; - // see if any none upgrade jobs exist - if ( i == jobs_.end() ) - { - for ( i = jobs_.begin(); i != jobs_.end(); ++i) - { - if ( !i->upgrade_ ) - { - DEBUG("processing(not-upgrade) %s",i->tbe_->thumbnail->getFileName().c_str()); - break; - } - } - } + // see if any priority jobs exist + for ( i = jobs_.begin(); i != jobs_.end(); ++i) { + if ( *(i->priority_) ) { + DEBUG("processing(priority) %s", i->tbe_->thumbnail->getFileName().c_str()); + break; + } + } - // if none, then use first - if ( i == jobs_.end() ) - { - i = jobs_.begin(); - DEBUG("processing(first) %s",i->tbe_->thumbnail->getFileName().c_str()); - } + // see if any none upgrade jobs exist + if ( i == jobs_.end() ) { + for ( i = jobs_.begin(); i != jobs_.end(); ++i) { + if ( !i->upgrade_ ) { + DEBUG("processing(not-upgrade) %s", i->tbe_->thumbnail->getFileName().c_str()); + break; + } + } + } - // copy found job - j = *i; + // if none, then use first + if ( i == jobs_.end() ) { + i = jobs_.begin(); + DEBUG("processing(first) %s", i->tbe_->thumbnail->getFileName().c_str()); + } - // remove so not run again - jobs_.erase(i); - DEBUG("%d job(s) remaining", int(jobs_.size()) ); + // copy found job + j = *i; - ++active_; - } + // remove so not run again + jobs_.erase(i); + DEBUG("%d job(s) remaining", int(jobs_.size()) ); - // unlock and do processing; will relock on block exit, then call listener - double scale = 1.0; - rtengine::IImage8* img = 0; - Thumbnail* thm=j.tbe_->thumbnail; + ++active_; + } - if ( j.upgrade_ ) - { - if ( thm->isQuick() ) - { - img = thm->upgradeThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale); - } - } - else - { - img = thm->processThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale); - } + // unlock and do processing; will relock on block exit, then call listener + double scale = 1.0; + rtengine::IImage8* img = 0; + Thumbnail* thm = j.tbe_->thumbnail; - if (img) - { - DEBUG("pushing image %s",thm->getFileName().c_str()); - j.listener_->updateImage(img, scale, thm->getProcParams().crop); - } + if ( j.upgrade_ ) { + if ( thm->isQuick() ) { + img = thm->upgradeThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale); + } + } else { + img = thm->processThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale); + } - { - #ifdef WIN32 - Glib::Mutex::Lock lock(mutex_); - #else - Glib::Threads::Mutex::Lock lock(mutex_); - #endif + if (img) { + DEBUG("pushing image %s", thm->getFileName().c_str()); + j.listener_->updateImage(img, scale, thm->getProcParams().crop); + } + + { +#ifdef WIN32 + Glib::Mutex::Lock lock(mutex_); +#else + Glib::Threads::Mutex::Lock lock(mutex_); +#endif - if ( --active_ == 0 && - inactive_waiting_ ) - { - inactive_waiting_ = false; - inactive_.signal(); - } - } - } + if ( --active_ == 0 && + inactive_waiting_ ) { + inactive_waiting_ = false; + inactive_.signal(); + } + } + } }; ThumbImageUpdater* ThumbImageUpdater::getInstance(void) { - // this will not be deleted... - static ThumbImageUpdater* instance_ = 0; - if ( instance_ == 0 ) - { - instance_ = new ThumbImageUpdater(); - } - return instance_; + // this will not be deleted... + static ThumbImageUpdater* instance_ = 0; + + if ( instance_ == 0 ) { + instance_ = new ThumbImageUpdater(); + } + + return instance_; } ThumbImageUpdater::ThumbImageUpdater(): - impl_(new Impl()) + impl_(new Impl()) { } -void -ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, ThumbImageUpdateListener* l) +void +ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, ThumbImageUpdateListener* l) { - // nobody listening? - if ( l == 0 ) - { - return; - } + // nobody listening? + if ( l == 0 ) { + return; + } - #ifdef WIN32 - Glib::Mutex::Lock lock(impl_->mutex_); - #else - Glib::Threads::Mutex::Lock lock(impl_->mutex_); - #endif +#ifdef WIN32 + Glib::Mutex::Lock lock(impl_->mutex_); +#else + Glib::Threads::Mutex::Lock lock(impl_->mutex_); +#endif // look up if an older version is in the queue - Impl::JobList::iterator i(impl_->jobs_.begin()); - for ( ; i != impl_->jobs_.end(); ++i ) - { - if ( i->tbe_ == tbe && - i->listener_ == l && - i->upgrade_ == upgrade ) - { - DEBUG("updating job %s",tbe->shortname.c_str()); - // we have one, update queue entry, will be picked up by thread when processed - /*i->pparams_ = params; - i->height_ = height; */ - i->priority_ = priority; - return; - } - } + Impl::JobList::iterator i(impl_->jobs_.begin()); - // create a new job and append to queue - DEBUG("queing job %s",tbe->shortname.c_str()); - impl_->jobs_.push_back(Impl::Job(tbe,priority,upgrade,l)); + for ( ; i != impl_->jobs_.end(); ++i ) { + if ( i->tbe_ == tbe && + i->listener_ == l && + i->upgrade_ == upgrade ) { + DEBUG("updating job %s", tbe->shortname.c_str()); + // we have one, update queue entry, will be picked up by thread when processed + /*i->pparams_ = params; + i->height_ = height; */ + i->priority_ = priority; + return; + } + } - DEBUG("adding run request %s",tbe->shortname.c_str()); - impl_->threadPool_->push(sigc::mem_fun(*impl_, &ThumbImageUpdater::Impl::processNextJob)); + // create a new job and append to queue + DEBUG("queing job %s", tbe->shortname.c_str()); + impl_->jobs_.push_back(Impl::Job(tbe, priority, upgrade, l)); + + DEBUG("adding run request %s", tbe->shortname.c_str()); + impl_->threadPool_->push(sigc::mem_fun(*impl_, &ThumbImageUpdater::Impl::processNextJob)); } -void +void ThumbImageUpdater::removeJobs(ThumbImageUpdateListener* listener) { - DEBUG("removeJobs(%p)",listener); + DEBUG("removeJobs(%p)", listener); - #ifdef WIN32 - Glib::Mutex::Lock lock(impl_->mutex_); - #else - Glib::Threads::Mutex::Lock lock(impl_->mutex_); - #endif +#ifdef WIN32 + Glib::Mutex::Lock lock(impl_->mutex_); +#else + Glib::Threads::Mutex::Lock lock(impl_->mutex_); +#endif - for( Impl::JobList::iterator i(impl_->jobs_.begin()); i != impl_->jobs_.end(); ) - { - if (i->listener_ == listener) - { - DEBUG("erasing specific job"); - Impl::JobList::iterator e(i++); - impl_->jobs_.erase(e); - } - else - { - ++i; - } - } + for( Impl::JobList::iterator i(impl_->jobs_.begin()); i != impl_->jobs_.end(); ) { + if (i->listener_ == listener) { + DEBUG("erasing specific job"); + Impl::JobList::iterator e(i++); + impl_->jobs_.erase(e); + } else { + ++i; + } + } - while ( impl_->active_ != 0 ) - { - // XXX this is nasty... it would be nicer if we weren't called with - // this lock held - GThreadUnLock unlock; - DEBUG("waiting for running jobs1"); - impl_->inactive_waiting_ = true; - impl_->inactive_.wait(impl_->mutex_); - } + while ( impl_->active_ != 0 ) { + // XXX this is nasty... it would be nicer if we weren't called with + // this lock held + GThreadUnLock unlock; + DEBUG("waiting for running jobs1"); + impl_->inactive_waiting_ = true; + impl_->inactive_.wait(impl_->mutex_); + } } -void -ThumbImageUpdater::removeAllJobs(void) -{ - DEBUG("stop"); +void +ThumbImageUpdater::removeAllJobs(void) +{ + DEBUG("stop"); - #ifdef WIN32 - Glib::Mutex::Lock lock(impl_->mutex_); - #else - Glib::Threads::Mutex::Lock lock(impl_->mutex_); - #endif +#ifdef WIN32 + Glib::Mutex::Lock lock(impl_->mutex_); +#else + Glib::Threads::Mutex::Lock lock(impl_->mutex_); +#endif - impl_->jobs_.clear(); + impl_->jobs_.clear(); - while ( impl_->active_ != 0 ) - { - // XXX this is nasty... it would be nicer if we weren't called with - // this lock held - GThreadUnLock unlock; - DEBUG("waiting for running jobs2"); - impl_->inactive_waiting_ = true; - impl_->inactive_.wait(impl_->mutex_); - } + while ( impl_->active_ != 0 ) { + // XXX this is nasty... it would be nicer if we weren't called with + // this lock held + GThreadUnLock unlock; + DEBUG("waiting for running jobs2"); + impl_->inactive_waiting_ = true; + impl_->inactive_.wait(impl_->mutex_); + } } diff --git a/rtgui/thumbimageupdater.h b/rtgui/thumbimageupdater.h index fa459b1ad..ea9cff6d7 100644 --- a/rtgui/thumbimageupdater.h +++ b/rtgui/thumbimageupdater.h @@ -7,7 +7,7 @@ * 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 @@ -24,73 +24,75 @@ #include "thumbbrowserentrybase.h" #include -class ThumbImageUpdateListener { +class ThumbImageUpdateListener +{ public: - /** - * @brief Called when thumbnail image is update - * - * @param img new thumbnail image - * @param scale scale (??) - * @param cropParams how it was cropped (??) - * - * @note no locks are held when called back - */ - virtual void updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) {} + /** + * @brief Called when thumbnail image is update + * + * @param img new thumbnail image + * @param scale scale (??) + * @param cropParams how it was cropped (??) + * + * @note no locks are held when called back + */ + virtual void updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) {} }; -class ThumbImageUpdater { +class ThumbImageUpdater +{ - public: +public: - /** - * @brief Singleton entry point. - * - * @return Pointer to thumbnail image updater. - */ - static ThumbImageUpdater* getInstance(void); + /** + * @brief Singleton entry point. + * + * @return Pointer to thumbnail image updater. + */ + static ThumbImageUpdater* getInstance(void); - /** - * @brief Add an thumbnail image update request. - * - * Code will add the request to the queue and, if needed, start a pool - * thread to process it. - * - * @param t thumbnail - * @param params processing params (?) - * @param height how big - * @param priority if \c true then run as soon as possible - * @param l listener waiting on update - */ + /** + * @brief Add an thumbnail image update request. + * + * Code will add the request to the queue and, if needed, start a pool + * thread to process it. + * + * @param t thumbnail + * @param params processing params (?) + * @param height how big + * @param priority if \c true then run as soon as possible + * @param l listener waiting on update + */ void add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, ThumbImageUpdateListener* l); - /** - * @brief Remove jobs associated with listener \c l. - * - * Jobs being processed will be finished. Will not return till all jobs for - * \c l have been completed. - * - * @param listener jobs associated with this will be stopped - */ + /** + * @brief Remove jobs associated with listener \c l. + * + * Jobs being processed will be finished. Will not return till all jobs for + * \c l have been completed. + * + * @param listener jobs associated with this will be stopped + */ void removeJobs(ThumbImageUpdateListener* listener); - /** - * @brief Stop processing and remove all jobs. - * - * Will not return till all running jobs have completed. - */ + /** + * @brief Stop processing and remove all jobs. + * + * Will not return till all running jobs have completed. + */ void removeAllJobs(void); - private: +private: - ThumbImageUpdater(); + ThumbImageUpdater(); - class Impl; - Impl* impl_; + class Impl; + Impl* impl_; }; -/** +/** * @brief Singleton boiler plate. * * To use: \c thumbImageUpdater->start() , diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index d81b2fd55..838c852a8 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -6,7 +6,7 @@ * 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 @@ -35,7 +35,7 @@ using namespace rtengine::procparams; Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf) : fname(fname), cfs(*cf), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL), - pparamsValid(false), needsReProcessing(true),imageLoading(false), lastImg(NULL), + pparamsValid(false), needsReProcessing(true), imageLoading(false), lastImg(NULL), lastW(0), lastH(0), lastScale(0), initial_(false) { @@ -45,7 +45,7 @@ Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageDa _loadThumbnail (); generateExifDateTimeStrings (); - if (cfs.rankOld >= 0){ + if (cfs.rankOld >= 0) { // rank and inTrash were found in cache (old style), move them over to pparams // try to load the last saved parameters from the cache or from the paramfile file @@ -63,7 +63,7 @@ Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageDa Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5) : fname(fname), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL), pparamsValid(false), - needsReProcessing(true),imageLoading(false), lastImg(NULL), + needsReProcessing(true), imageLoading(false), lastImg(NULL), initial_(true) { @@ -79,105 +79,116 @@ Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::s tpp = 0; } -void Thumbnail::_generateThumbnailImage () { +void Thumbnail::_generateThumbnailImage () +{ - // delete everything loaded into memory - delete tpp; - tpp = NULL; - delete [] lastImg; - lastImg = NULL; - tw = -1; - th = options.maxThumbnailHeight; - imgRatio = -1.; + // delete everything loaded into memory + delete tpp; + tpp = NULL; + delete [] lastImg; + lastImg = NULL; + tw = -1; + th = options.maxThumbnailHeight; + imgRatio = -1.; - // generate thumbnail image - Glib::ustring ext = getExtension (fname); - if (ext=="") - return; - cfs.supported = false; - cfs.exifValid = false; - cfs.timeValid = false; + // generate thumbnail image + Glib::ustring ext = getExtension (fname); - if (ext.lowercase()=="jpg" || ext.lowercase()=="jpeg") { - infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams.wb.equal); - if (tpp) - cfs.format = FT_Jpeg; - } - else if (ext.lowercase()=="png") { - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams.wb.equal); - if (tpp) - cfs.format = FT_Png; - } - else if (ext.lowercase()=="tif" || ext.lowercase()=="tiff") { - infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams.wb.equal); - if (tpp) - cfs.format = FT_Tiff; - } - else { - // RAW works like this: - // 1. if we are here it's because we aren't in the cache so load the JPG - // image out of the RAW. Mark as "quick". - // 2. if we don't find that then just grab the real image. - bool quick = false; - rtengine::RawMetaDataLocation ri; - if ( initial_ && options.internalThumbIfUntouched) - { - quick = true; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, tw, th, 1, TRUE); - } - if ( tpp == NULL ) - { - quick = false; - tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE); - } - if (tpp) { - cfs.format = FT_Raw; - cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; - infoFromImage (fname, &ri); - } - } + if (ext == "") { + return; + } - if (tpp) - { + cfs.supported = false; + cfs.exifValid = false; + cfs.timeValid = false; + + if (ext.lowercase() == "jpg" || ext.lowercase() == "jpeg") { + infoFromImage (fname); + tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams.wb.equal); + + if (tpp) { + cfs.format = FT_Jpeg; + } + } else if (ext.lowercase() == "png") { + tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams.wb.equal); + + if (tpp) { + cfs.format = FT_Png; + } + } else if (ext.lowercase() == "tif" || ext.lowercase() == "tiff") { + infoFromImage (fname); + tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams.wb.equal); + + if (tpp) { + cfs.format = FT_Tiff; + } + } else { + // RAW works like this: + // 1. if we are here it's because we aren't in the cache so load the JPG + // image out of the RAW. Mark as "quick". + // 2. if we don't find that then just grab the real image. + bool quick = false; + rtengine::RawMetaDataLocation ri; + + if ( initial_ && options.internalThumbIfUntouched) { + quick = true; + tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, tw, th, 1, TRUE); + } + + if ( tpp == NULL ) { + quick = false; + tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE); + } + + if (tpp) { + cfs.format = FT_Raw; + cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; + infoFromImage (fname, &ri); + } + } + + if (tpp) { tpp->getAutoWBMultipliers(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul); _saveThumbnail (); cfs.supported = true; needsReProcessing = true; - cfs.save (getCacheFileName ("data")+".txt"); + cfs.save (getCacheFileName ("data") + ".txt"); generateExifDateTimeStrings (); } } -bool Thumbnail::isSupported () { +bool Thumbnail::isSupported () +{ return cfs.supported; } -const ProcParams& Thumbnail::getProcParams () { +const ProcParams& Thumbnail::getProcParams () +{ MyMutex::MyLock lock(mutex); return getProcParamsU(); } // Unprotected version of getProcParams, when -const ProcParams& Thumbnail::getProcParamsU () { - if (pparamsValid) +const ProcParams& Thumbnail::getProcParamsU () +{ + if (pparamsValid) { return pparams; - else { - pparams = *(profileStore.getDefaultProcParams (getType()==FT_Raw)); - if (pparams.wb.method=="Camera") { + } else { + pparams = *(profileStore.getDefaultProcParams (getType() == FT_Raw)); + + if (pparams.wb.method == "Camera") { double ct; getCamWB (ct, pparams.wb.green); pparams.wb.temperature = ct; - } - else if (pparams.wb.method=="Auto") { + } else if (pparams.wb.method == "Auto") { double ct; getAutoWB (ct, pparams.wb.green, pparams.wb.equal); pparams.wb.temperature = ct; } } + return pparams; // there is no valid pp to return, but we have to return something } @@ -193,36 +204,43 @@ const ProcParams& Thumbnail::getProcParamsU () { * * @return Return a pointer to a ProcPamas structure to be updated if returnParams is true and if everything went fine, NULL otherwise. */ -rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool forceCPB, bool flaggingMode) { +rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool forceCPB, bool flaggingMode) +{ - static int index=0; // Will act as unique identifier during the session + static int index = 0; // Will act as unique identifier during the session // try to load the last saved parameters from the cache or from the paramfile file ProcParams* ldprof = NULL; - Glib::ustring defProf = getType()==FT_Raw ? options.defProfRaw : options.defProfImg; + Glib::ustring defProf = getType() == FT_Raw ? options.defProfRaw : options.defProfImg; - const CacheImageData* cfs=getCacheImageData(); + const CacheImageData* cfs = getCacheImageData(); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); + if (!options.CPBPath.empty() && !defaultPparamsPath.empty() && (!hasProcParams() || forceCPB) && cfs && cfs->exifValid) { // First generate the communication file, with general values and EXIF metadata rtengine::ImageMetaData* imageMetaData; - if (getType()==FT_Raw) { + + if (getType() == FT_Raw) { rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); - } - else + } else { imageMetaData = rtengine::ImageMetaData::fromFile (fname, NULL); + } Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) ); - const rtexif::TagDirectory* exifDir=NULL; + const rtexif::TagDirectory* exifDir = NULL; + if (imageMetaData && (exifDir = imageMetaData->getExifData())) { Glib::ustring outFName; - if (options.paramsLoadLocation==PLL_Input) - outFName = fname+paramFileExtension; - else - outFName = getCacheFileName("profiles")+paramFileExtension; + + if (options.paramsLoadLocation == PLL_Input) { + outFName = fname + paramFileExtension; + } else { + outFName = getCacheFileName("profiles") + paramFileExtension; + } + exifDir->CPBDump(tmpFileName, fname, outFName, defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension), cfs, @@ -232,16 +250,24 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu // For the filename etc. do NOT use streams, since they are not UTF8 safe Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\""); - if (options.rtSettings.verbose) + if (options.rtSettings.verbose) { printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str()); + } + bool success = safe_spawn_command_line_sync (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 (success) { + loadProcParams(); + } - if (safe_file_test(tmpFileName, Glib::FILE_TEST_EXISTS )) safe_g_remove (tmpFileName); + if (safe_file_test(tmpFileName, Glib::FILE_TEST_EXISTS )) { + safe_g_remove (tmpFileName); + } - if (imageMetaData) delete imageMetaData; + if (imageMetaData) { + delete imageMetaData; + } } if (returnParams && hasProcParams()) { @@ -252,9 +278,11 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu return ldprof; } -void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt){ - for (size_t i=0; iprocParamsChanged (this, whoChangedIt); +void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt) +{ + for (size_t i = 0; i < listeners.size(); i++) { + listeners[i]->procParamsChanged (this, whoChangedIt); + } } /* @@ -265,172 +293,199 @@ void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt){ * from the default Raw or Image ProcParams, then with the values from the loaded * ProcParams (sidecar or cache file). */ -void Thumbnail::loadProcParams () { +void Thumbnail::loadProcParams () +{ MyMutex::MyLock lock(mutex); pparamsValid = false; pparams.setDefaults(); - const PartialProfile *defaultPP = profileStore.getDefaultPartialProfile(getType()==FT_Raw); + const PartialProfile *defaultPP = profileStore.getDefaultPartialProfile(getType() == FT_Raw); defaultPP->applyTo(&pparams); - if (options.paramsLoadLocation==PLL_Input) { + if (options.paramsLoadLocation == PLL_Input) { // try to load it from params file next to the image file int ppres = pparams.load (fname + paramFileExtension); - pparamsValid = !ppres && pparams.ppVersion>=220; + pparamsValid = !ppres && pparams.ppVersion >= 220; + // if no success, try to load the cached version of the procparams - if (!pparamsValid) - pparamsValid = !pparams.load (getCacheFileName ("profiles")+paramFileExtension); - } - else { + if (!pparamsValid) { + 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) { int ppres = pparams.load (fname + paramFileExtension); - pparamsValid = !ppres && pparams.ppVersion>=220; + pparamsValid = !ppres && pparams.ppVersion >= 220; } } } -void Thumbnail::clearProcParams (int whoClearedIt) { +void Thumbnail::clearProcParams (int whoClearedIt) +{ -/* Clarification on current "clear profile" functionality: - a. if rank/colorlabel/inTrash are NOT set, - the "clear profile" will delete the pp3 file (as before). + /* Clarification on current "clear profile" functionality: + a. if rank/colorlabel/inTrash are NOT set, + the "clear profile" will delete the pp3 file (as before). - b. if any of the rank/colorlabel/inTrash ARE set, - the "clear profile" will lead to execution of ProcParams::setDefaults - (the CPB is NOT called) to set the params values and will preserve - rank/colorlabel/inTrash in the param file. */ + b. if any of the rank/colorlabel/inTrash ARE set, + the "clear profile" will lead to execution of ProcParams::setDefaults + (the CPB is NOT called) to set the params values and will preserve + rank/colorlabel/inTrash in the param file. */ - { - MyMutex::MyLock lock(mutex); - - // preserve rank, colorlabel and inTrash across clear - int rank = getRank(); - int colorlabel = getColorLabel(); - int inTrash = getStage(); - - - cfs.recentlySaved = false; - pparamsValid = false; - needsReProcessing = true; - - //TODO: run though customprofilebuilder? - // probably not as this is the only option to set param values to default - - // reset the params to defaults - pparams.setDefaults(); - - // and restore rank and inTrash - setRank(rank); - setColorLabel(colorlabel); - setStage(inTrash); - - // params could get validated by rank/inTrash values restored above - if (pparamsValid) { - 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_); - // remove param file located next to the file + MyMutex::MyLock lock(mutex); + + // preserve rank, colorlabel and inTrash across clear + int rank = getRank(); + int colorlabel = getColorLabel(); + int inTrash = getStage(); + + + cfs.recentlySaved = false; + pparamsValid = false; + needsReProcessing = true; + + //TODO: run though customprofilebuilder? + // probably not as this is the only option to set param values to default + + // reset the params to defaults + pparams.setDefaults(); + + // and restore rank and inTrash + setRank(rank); + setColorLabel(colorlabel); + setStage(inTrash); + + // params could get validated by rank/inTrash values restored above + if (pparamsValid) { + 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_); + } + + // 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_); - fname_ = removeExtension(fname) + paramFileExtension; - if (safe_file_test (fname_, Glib::FILE_TEST_EXISTS)) - safe_g_remove (fname_); + fname_ = fname + paramFileExtension; - 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 - // be a bit slow as a new full thumbnail will be generated unnecessarily, but currently there is no way to pre-check - // if the format supports quick thumbs. - initial_ = true; - _generateThumbnailImage(); - initial_ = false; + if (safe_file_test(fname_, Glib::FILE_TEST_EXISTS)) { + safe_g_remove (fname_); + } + + fname_ = removeExtension(fname) + paramFileExtension; + + if (safe_file_test (fname_, Glib::FILE_TEST_EXISTS)) { + safe_g_remove (fname_); + } + + 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 + // be a bit slow as a new full thumbnail will be generated unnecessarily, but currently there is no way to pre-check + // if the format supports quick thumbs. + initial_ = true; + _generateThumbnailImage(); + initial_ = false; + } } - } - } // end of mutex lock + } // end of mutex lock - for (size_t i=0; iprocParamsChanged (this, whoClearedIt); + } } -bool Thumbnail::hasProcParams () { - +bool Thumbnail::hasProcParams () +{ + return pparamsValid; } -void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoChangedIt, bool updateCacheNow) { +void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoChangedIt, bool updateCacheNow) +{ - { - MyMutex::MyLock lock(mutex); + { + MyMutex::MyLock lock(mutex); - if (pparams.sharpening.threshold.isDouble() != pp.sharpening.threshold.isDouble()) - printf("WARNING: Sharpening different!\n"); - if (pparams.vibrance.psthreshold.isDouble() != pp.vibrance.psthreshold.isDouble()) - printf("WARNING: Vibrance different!\n"); + if (pparams.sharpening.threshold.isDouble() != pp.sharpening.threshold.isDouble()) { + printf("WARNING: Sharpening different!\n"); + } - if (pparams!=pp) - cfs.recentlySaved = false; + if (pparams.vibrance.psthreshold.isDouble() != pp.vibrance.psthreshold.isDouble()) { + printf("WARNING: Vibrance different!\n"); + } - // do not update rank, colorlabel and inTrash - int rank = getRank(); - int colorlabel = getColorLabel(); - int inTrash = getStage(); + if (pparams != pp) { + cfs.recentlySaved = false; + } - if (pe) { - pe->combine(pparams, pp, true); - } - else pparams = pp; - pparamsValid = true; - needsReProcessing = true; + // do not update rank, colorlabel and inTrash + int rank = getRank(); + int colorlabel = getColorLabel(); + int inTrash = getStage(); - setRank(rank); - setColorLabel(colorlabel); - setStage(inTrash); + if (pe) { + pe->combine(pparams, pp, true); + } else { + pparams = pp; + } - if (updateCacheNow) - updateCache (); + pparamsValid = true; + needsReProcessing = true; - } // end of mutex lock + setRank(rank); + setColorLabel(colorlabel); + setStage(inTrash); - for (size_t i=0; iprocParamsChanged (this, whoChangedIt); + } } -bool Thumbnail::isRecentlySaved () { - +bool Thumbnail::isRecentlySaved () +{ + return cfs.recentlySaved; } -void Thumbnail::imageDeveloped () { - +void Thumbnail::imageDeveloped () +{ + cfs.recentlySaved = true; - cfs.save (getCacheFileName ("data")+".txt"); - if (options.saveParamsCache) - pparams.save (getCacheFileName ("profiles")+paramFileExtension); + cfs.save (getCacheFileName ("data") + ".txt"); + + if (options.saveParamsCache) { + pparams.save (getCacheFileName ("profiles") + paramFileExtension); + } } -void Thumbnail::imageEnqueued () { +void Thumbnail::imageEnqueued () +{ enqueueNumber++; } -void Thumbnail::imageRemovedFromQueue () { +void Thumbnail::imageRemovedFromQueue () +{ enqueueNumber--; } -bool Thumbnail::isEnqueued () { - +bool Thumbnail::isEnqueued () +{ + return enqueueNumber > 0; } @@ -440,80 +495,94 @@ void Thumbnail::increaseRef () ++ref; } -void Thumbnail::decreaseRef () +void Thumbnail::decreaseRef () { - { - MyMutex::MyLock lock(mutex); - if ( ref == 0 ) - { - return; - } - if ( --ref != 0 ) - { - return; - } - } - cachemgr->closeThumbnail (this); + { + MyMutex::MyLock lock(mutex); + + if ( ref == 0 ) { + return; + } + + if ( --ref != 0 ) { + return; + } + } + cachemgr->closeThumbnail (this); } -void Thumbnail::getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams) { - int tw_ = tw; - int th_ = th; - float imgRatio_ = imgRatio; +void Thumbnail::getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams) +{ + int tw_ = tw; + int th_ = th; + float imgRatio_ = imgRatio; - if (pparams) { - int ppCoarse = pparams->coarse.rotate; - if (ppCoarse >= 180) ppCoarse -= 180; + if (pparams) { + int ppCoarse = pparams->coarse.rotate; - int thisCoarse = this->pparams.coarse.rotate; - if (thisCoarse >= 180) thisCoarse -= 180; + if (ppCoarse >= 180) { + ppCoarse -= 180; + } - if (thisCoarse != ppCoarse) { - // different orientation -> swapping width & height - int tmp = th_; - th_ = tw_; - tw_ = tmp; - if (imgRatio_ >= 0.0001f) - imgRatio_ = 1.f/imgRatio_; - } - } + int thisCoarse = this->pparams.coarse.rotate; - if (imgRatio_ > 0.) - w = (int)(imgRatio_ * (float)h); - else - w = tw_ * h / th_; + if (thisCoarse >= 180) { + thisCoarse -= 180; + } + + if (thisCoarse != ppCoarse) { + // different orientation -> swapping width & height + int tmp = th_; + th_ = tw_; + tw_ = tmp; + + if (imgRatio_ >= 0.0001f) { + imgRatio_ = 1.f / imgRatio_; + } + } + } + + if (imgRatio_ > 0.) { + w = (int)(imgRatio_ * (float)h); + } else { + w = tw_ * h / th_; + } } -void Thumbnail::getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h) { +void Thumbnail::getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h) +{ MyMutex::MyLock lock(mutex); // WARNING: When downscaled, the ratio have loosed a lot of precision, so we can't get back the exact initial dimensions - double fw = lastW*lastScale; - double fh = lastH*lastScale; + double fw = lastW * lastScale; + double fh = lastH * lastScale; - if (pparams.coarse.rotate==90 || pparams.coarse.rotate==270) { - fh = lastW*lastScale; - fw = lastH*lastScale; + if (pparams.coarse.rotate == 90 || pparams.coarse.rotate == 270) { + fh = lastW * lastScale; + fw = lastH * lastScale; } + if (!pparams.resize.enabled) { w = fw; h = fh; - } - else { - w = (int)(fw+0.5); - h = (int)(fh+0.5); + } else { + w = (int)(fw + 0.5); + h = (int)(fh + 0.5); } } -rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) { +rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) +{ MyMutex::MyLock lock(mutex); if ( tpp == 0 ) { _loadThumbnail(); - if ( tpp == 0 ) + + if ( tpp == 0 ) { return 0; + } } rtengine::IImage8* image = 0; @@ -521,73 +590,74 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro if ( cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL ) { // RAW internal thumbnail, no profile yet: just do some rotation etc. image = tpp->quickProcessImage (pparams, h, rtengine::TI_Nearest, scale); - } - else { + } else { // Full thumbnail: apply profile image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); } - tpp->getDimensions(lastW,lastH,lastScale); + tpp->getDimensions(lastW, lastH, lastScale); delete tpp; tpp = 0; return image; } -rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) { +rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) +{ - MyMutex::MyLock lock(mutex); + MyMutex::MyLock lock(mutex); - if ( cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL ) - { - return 0; - } + if ( cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL ) { + return 0; + } - _generateThumbnailImage(); - if ( tpp == 0 ) - { - return 0; - } - - rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist,cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); - tpp->getDimensions(lastW,lastH,lastScale); - - delete tpp; - tpp = 0; - return image; + _generateThumbnailImage(); + + if ( tpp == 0 ) { + return 0; + } + + rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); + tpp->getDimensions(lastW, lastH, lastScale); + + delete tpp; + tpp = 0; + return image; } -void Thumbnail::generateExifDateTimeStrings () { +void Thumbnail::generateExifDateTimeStrings () +{ exifString = ""; dateTimeString = ""; - if (!cfs.exifValid) + if (!cfs.exifValid) { return; + } exifString = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", Glib::ustring(rtengine::ImageData::apertureToString(cfs.fnumber)), Glib::ustring(rtengine::ImageData::shutterToString(cfs.shutter)), M("QINFO_ISO"), cfs.iso, Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), cfs.focalLen)); - if (options.fbShowExpComp && cfs.expcomp!="0.00" && cfs.expcomp!="") // don't show exposure compensation if it is 0.00EV;old cache iles do not have ExpComp, so value will not be displayed. - exifString = Glib::ustring::compose ("%1 %2EV", exifString, cfs.expcomp); // append exposure compensation to exifString + if (options.fbShowExpComp && cfs.expcomp != "0.00" && cfs.expcomp != "") { // don't show exposure compensation if it is 0.00EV;old cache iles do not have ExpComp, so value will not be displayed. + exifString = Glib::ustring::compose ("%1 %2EV", exifString, cfs.expcomp); // append exposure compensation to exifString + } + std::string dateFormat = options.dateFormat; std::ostringstream ostr; bool spec = false; - for (size_t i=0; ihasExif()) { cfs.shutter = idata->getShutterSpeed (); - cfs.fnumber = idata->getFNumber (); + cfs.fnumber = idata->getFNumber (); cfs.focalLen = idata->getFocalLen (); cfs.focalLen35mm = idata->getFocalLen35mm (); cfs.focusDist = idata->getFocusDist (); @@ -654,26 +732,28 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataL cfs.camMake = idata->getMake(); cfs.camModel = idata->getModel(); - if (idata->getOrientation()=="Rotate 90 CW") { + if (idata->getOrientation() == "Rotate 90 CW") { deg = 90; - } - else if (idata->getOrientation()=="Rotate 180") { + } else if (idata->getOrientation() == "Rotate 180") { deg = 180; - } - else if (idata->getOrientation()=="Rotate 270 CW") { + } else if (idata->getOrientation() == "Rotate 270 CW") { deg = 270; } - } - else { + } else { cfs.lens = "Unknown"; cfs.camMake = "Unknown"; cfs.camModel = "Unknown"; } + // get image filetype std::string::size_type idx; idx = fname.rfind('.'); - if(idx != std::string::npos){cfs.filetype = fname.substr(idx+1);} - else {cfs.filetype="";} + + if(idx != std::string::npos) { + cfs.filetype = fname.substr(idx + 1); + } else { + cfs.filetype = ""; + } delete idata; return deg; @@ -687,7 +767,8 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataL * - embedded profile (full thumbnail only) * - LiveThumbData section of the data file */ -void Thumbnail::_loadThumbnail(bool firstTrial) { +void Thumbnail::_loadThumbnail(bool firstTrial) +{ needsReProcessing = true; tw = -1; @@ -697,38 +778,44 @@ 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) + if (succ) { tpp->getAutoWBMultipliers(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul); + } // thumbnail image succ = succ && tpp->readImage (getCacheFileName ("images")); if (!succ && firstTrial) { _generateThumbnailImage (); - if (cfs.supported && firstTrial) - _loadThumbnail (false); - if (tpp==NULL) return; - } - else if (!succ) { + if (cfs.supported && firstTrial) { + _loadThumbnail (false); + } + + if (tpp == NULL) { + return; + } + } else if (!succ) { delete tpp; tpp = NULL; return; } - + if ( cfs.thumbImgType == CacheImageData::FULL_THUMBNAIL ) { // load aehistogram tpp->readAEHistogram (getCacheFileName ("aehistograms")); // load embedded profile - tpp->readEmbProfile (getCacheFileName ("embprofiles")+".icc"); + tpp->readEmbProfile (getCacheFileName ("embprofiles") + ".icc"); tpp->init (); } - - if (!initial_ && tpp) tw = tpp->getImageWidth (getProcParamsU(), th, imgRatio); // this might return 0 if image was just building + + if (!initial_ && tpp) { + tw = tpp->getImageWidth (getProcParamsU(), th, imgRatio); // this might return 0 if image was just building + } } /* @@ -739,7 +826,8 @@ void Thumbnail::_loadThumbnail(bool firstTrial) { * - embedded profile (full thumbnail only) * - LiveThumbData section of the data file */ -void Thumbnail::loadThumbnail (bool firstTrial) { +void Thumbnail::loadThumbnail (bool firstTrial) +{ MyMutex::MyLock lock(mutex); _loadThumbnail(firstTrial); } @@ -752,18 +840,20 @@ void Thumbnail::loadThumbnail (bool firstTrial) { * - embedded profile (full thumbnail only) * - LiveThumbData section of the data file */ -void Thumbnail::_saveThumbnail () { +void Thumbnail::_saveThumbnail () +{ - if (!tpp) + if (!tpp) { return; - - if (safe_g_remove (getCacheFileName ("images")+".rtti") == -1) { - // 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"); } - + + if (safe_g_remove (getCacheFileName ("images") + ".rtti") == -1) { + // 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"); + } + // save thumbnail image tpp->writeImage (getCacheFileName ("images"), 1); @@ -771,10 +861,10 @@ void Thumbnail::_saveThumbnail () { 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"); } /* @@ -785,9 +875,9 @@ void Thumbnail::_saveThumbnail () { * - embedded profile (full thumbnail only) * - LiveThumbData section of the data file */ -void Thumbnail::saveThumbnail () +void Thumbnail::saveThumbnail () { - MyMutex::MyLock lock(mutex); + MyMutex::MyLock lock(mutex); _saveThumbnail(); } @@ -797,20 +887,24 @@ void Thumbnail::saveThumbnail () * - updateCacheImageData==true (default) : write the CacheImageData values in the cache folder, * i.e. some General, DateTime, ExifInfo, File info and ExtraRawInfo, */ -void Thumbnail::updateCache (bool updatePParams, bool updateCacheImageData) { +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"); + + if (updateCacheImageData) { + cfs.save (getCacheFileName ("data") + ".txt"); + } } -Thumbnail::~Thumbnail () { +Thumbnail::~Thumbnail () +{ mutex.lock(); delete [] lastImg; @@ -818,67 +912,78 @@ Thumbnail::~Thumbnail () { mutex.unlock(); } -Glib::ustring Thumbnail::getCacheFileName (Glib::ustring subdir) { +Glib::ustring Thumbnail::getCacheFileName (Glib::ustring subdir) +{ return cachemgr->getCacheFileName (subdir, fname, cfs.md5); } -void Thumbnail::setFileName (const Glib::ustring fn) { - - fname = fn; - cfs.md5 = cachemgr->getMD5 (fname); +void Thumbnail::setFileName (const Glib::ustring fn) +{ + + fname = fn; + cfs.md5 = cachemgr->getMD5 (fname); } -void Thumbnail::addThumbnailListener (ThumbnailListener* tnl) { +void Thumbnail::addThumbnailListener (ThumbnailListener* tnl) +{ increaseRef(); listeners.push_back (tnl); } -void Thumbnail::removeThumbnailListener (ThumbnailListener* tnl) { +void Thumbnail::removeThumbnailListener (ThumbnailListener* tnl) +{ std::vector::iterator f = std::find (listeners.begin(), listeners.end(), tnl); - if (f!=listeners.end()) { + + if (f != listeners.end()) { listeners.erase (f); decreaseRef(); - } + } } -// Calculates the standard filename for the automatically named batch result +// Calculates the standard filename for the automatically named batch result // and opens it in OS default viewer // destination: 1=Batch conf. file; 2=batch out dir; 3=RAW dir // Return: Success? -bool Thumbnail::openDefaultViewer(int destination) { +bool Thumbnail::openDefaultViewer(int destination) +{ -#ifdef WIN32 +#ifdef WIN32 Glib::ustring openFName; - if (destination==1) { - openFName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - if (safe_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); - } else { - printf("%s not found\n",openFName.data()); - return false; - } + if (destination == 1) { + openFName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); + + if (safe_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); + } else { + printf("%s not found\n", openFName.data()); + return false; + } } else { openFName = destination == 3 ? fname - : Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); + : Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); printf("Opening %s\n", openFName.c_str()); if (safe_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]; + 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]; wcscpy(par, org); // In this case the / disturbs - wchar_t* p = par+1; // skip the first backslash - while (*p!=0) { - if (*p==L'/') *p=L'\\'; + wchar_t* p = par + 1; // skip the first backslash + + while (*p != 0) { + if (*p == L'/') { + *p = L'\\'; + } + p++; } @@ -900,9 +1005,9 @@ bool Thumbnail::openDefaultViewer(int destination) { return true; #else - // TODO: Add more OSes here - printf("Automatic opening not supported on this OS\n"); - return false; + // TODO: Add more OSes here + printf("Automatic opening not supported on this OS\n"); + return false; #endif } @@ -911,10 +1016,13 @@ bool Thumbnail::imageLoad(bool loading) { MyMutex::MyLock lock(mutex); bool previous = imageLoading; - if( loading && !previous ){ + + if( loading && !previous ) { imageLoading = true; return true; - }else if( !loading ) + } else if( !loading ) { imageLoading = false; + } + return false; } diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 183f4b195..df3b4549e 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -7,7 +7,7 @@ * 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 @@ -30,120 +30,182 @@ #include "threadutils.h" class CacheManager; -class Thumbnail { +class Thumbnail +{ - MyMutex mutex; + MyMutex mutex; - Glib::ustring fname; // file name corresponding to the thumbnail - CacheImageData cfs; // cache entry corresponding to the thumbnail - CacheManager* cachemgr; // parent - int ref; // variable for reference counting - int enqueueNumber; // the number of instances in the batch queue corresponding to this thumbnail - - // if the thumbnail is in processed mode, this class holds its data: - rtengine::Thumbnail* tpp; - int tw, th; // dimensions of timgdata (it stores tpp->width and tpp->height in processed mode for simplicity) - float imgRatio; // hack to avoid rounding error + Glib::ustring fname; // file name corresponding to the thumbnail + CacheImageData cfs; // cache entry corresponding to the thumbnail + CacheManager* cachemgr; // parent + int ref; // variable for reference counting + int enqueueNumber; // the number of instances in the batch queue corresponding to this thumbnail + + // if the thumbnail is in processed mode, this class holds its data: + rtengine::Thumbnail* tpp; + int tw, th; // dimensions of timgdata (it stores tpp->width and tpp->height in processed mode for simplicity) + float imgRatio; // hack to avoid rounding error // double scale; // portion of the sizes of the processed thumbnail image and the full scale image - rtengine::procparams::ProcParams pparams; - bool pparamsValid; - bool pparamsSet; - bool needsReProcessing; - bool imageLoading; - - // these are the data of the result image of the last getthumbnailimage call (for caching purposes) - unsigned char* lastImg; - int lastW; - int lastH; - double lastScale; + rtengine::procparams::ProcParams pparams; + bool pparamsValid; + bool pparamsSet; + bool needsReProcessing; + bool imageLoading; - // exif & date/time strings - Glib::ustring exifString; - Glib::ustring dateTimeString; - - bool initial_; + // these are the data of the result image of the last getthumbnailimage call (for caching purposes) + unsigned char* lastImg; + int lastW; + int lastH; + double lastScale; - // vector of listeners - std::vector listeners; - - void _loadThumbnail (bool firstTrial=true); - void _saveThumbnail (); - void _generateThumbnailImage (); - int infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml=NULL); - void loadThumbnail (bool firstTrial=true); - void generateExifDateTimeStrings (); + // exif & date/time strings + Glib::ustring exifString; + Glib::ustring dateTimeString; - Glib::ustring getCacheFileName (Glib::ustring subdir); - - public: - Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf); - Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5); - ~Thumbnail (); - - bool hasProcParams (); - const rtengine::procparams::ProcParams& getProcParams (); - const rtengine::procparams::ProcParams& getProcParamsU (); // Unprotected version + bool initial_; - // Use this to create params on demand for update ; if flaggingMode=true, the procparams is created for a file being flagged (inTrash, rank, colorLabel) - rtengine::procparams::ProcParams* createProcParamsForUpdate (bool returnParams, bool forceCPB, bool flaggingMode=false); + // vector of listeners + std::vector listeners; - void setProcParams (const rtengine::procparams::ProcParams& pp, ParamsEdited* pe=NULL, int whoChangedIt=-1, bool updateCacheNow=true); - void clearProcParams (int whoClearedIt=-1); - void loadProcParams (); + void _loadThumbnail (bool firstTrial = true); + void _saveThumbnail (); + void _generateThumbnailImage (); + int infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml = NULL); + void loadThumbnail (bool firstTrial = true); + void generateExifDateTimeStrings (); - void notifylisterners_procParamsChanged(int whoChangedIt); + Glib::ustring getCacheFileName (Glib::ustring subdir); - bool isQuick() { return cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL; } - bool isPParamsValid() { return pparamsValid; } - bool isRecentlySaved (); - void imageDeveloped (); - void imageEnqueued (); - void imageRemovedFromQueue (); - bool isEnqueued (); +public: + Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf); + Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5); + ~Thumbnail (); + + bool hasProcParams (); + const rtengine::procparams::ProcParams& getProcParams (); + const rtengine::procparams::ProcParams& getProcParamsU (); // Unprotected version + + // Use this to create params on demand for update ; if flaggingMode=true, the procparams is created for a file being flagged (inTrash, rank, colorLabel) + rtengine::procparams::ProcParams* createProcParamsForUpdate (bool returnParams, bool forceCPB, bool flaggingMode = false); + + void setProcParams (const rtengine::procparams::ProcParams& pp, ParamsEdited* pe = NULL, int whoChangedIt = -1, bool updateCacheNow = true); + void clearProcParams (int whoClearedIt = -1); + void loadProcParams (); + + void notifylisterners_procParamsChanged(int whoChangedIt); + + bool isQuick() + { + return cfs.thumbImgType == CacheImageData::QUICK_THUMBNAIL; + } + bool isPParamsValid() + { + return pparamsValid; + } + bool isRecentlySaved (); + void imageDeveloped (); + void imageEnqueued (); + void imageRemovedFromQueue (); + bool isEnqueued (); // unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w - rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); - rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); - void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams=NULL); - void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h); + rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); + rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); + void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams = NULL); + void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h); - const Glib::ustring& getExifString (); - const Glib::ustring& getDateTimeString (); - void getCamWB (double& temp, double& green) { if (tpp) tpp->getCamWB (temp, green); else temp = green = -1.0; } - void getAutoWB (double& temp, double& green, double equal); - void getSpotWB (int x, int y, int rect, double& temp, double& green) { if (tpp) tpp->getSpotWB (getProcParams(), x, y, rect, temp, green); else temp = green = -1.0; } - void applyAutoExp (rtengine::procparams::ProcParams& pparams) { if (tpp) tpp->applyAutoExp (pparams); } - - ThFileType getType (); - Glib::ustring getFileName () { return fname; } - void setFileName (const Glib::ustring fn); + const Glib::ustring& getExifString (); + const Glib::ustring& getDateTimeString (); + void getCamWB (double& temp, double& green) + { + if (tpp) { + tpp->getCamWB (temp, green); + } else { + temp = green = -1.0; + } + } + void getAutoWB (double& temp, double& green, double equal); + void getSpotWB (int x, int y, int rect, double& temp, double& green) + { + if (tpp) { + tpp->getSpotWB (getProcParams(), x, y, rect, temp, green); + } else { + temp = green = -1.0; + } + } + void applyAutoExp (rtengine::procparams::ProcParams& pparams) + { + if (tpp) { + tpp->applyAutoExp (pparams); + } + } - bool isSupported (); + ThFileType getType (); + Glib::ustring getFileName () + { + return fname; + } + void setFileName (const Glib::ustring fn); - const CacheImageData* getCacheImageData() { return &cfs; } - std::string getMD5 () { return cfs.md5; } + bool isSupported (); - int getRank () { return pparams.rank; } - void setRank (int rank) { if (pparams.rank != rank) { pparams.rank = rank; pparamsValid = true; } } + const CacheImageData* getCacheImageData() + { + return &cfs; + } + std::string getMD5 () + { + return cfs.md5; + } - int getColorLabel () { return pparams.colorlabel; } - void setColorLabel (int colorlabel) { if (pparams.colorlabel != colorlabel) { pparams.colorlabel = colorlabel; pparamsValid = true; } } + int getRank () + { + return pparams.rank; + } + void setRank (int rank) + { + if (pparams.rank != rank) { + pparams.rank = rank; + pparamsValid = true; + } + } - int getStage () { return pparams.inTrash; } - void setStage (int stage) { if (pparams.inTrash != stage) { pparams.inTrash = stage; pparamsValid = true; } } + int getColorLabel () + { + return pparams.colorlabel; + } + void setColorLabel (int colorlabel) + { + if (pparams.colorlabel != colorlabel) { + pparams.colorlabel = colorlabel; + pparamsValid = true; + } + } - void addThumbnailListener (ThumbnailListener* tnl); - void removeThumbnailListener (ThumbnailListener* tnl); + int getStage () + { + return pparams.inTrash; + } + void setStage (int stage) + { + if (pparams.inTrash != stage) { + pparams.inTrash = stage; + pparamsValid = true; + } + } - void increaseRef (); - void decreaseRef (); - - void updateCache (bool updatePParams = true, bool updateCacheImageData = true); - void saveThumbnail (); + void addThumbnailListener (ThumbnailListener* tnl); + void removeThumbnailListener (ThumbnailListener* tnl); - bool openDefaultViewer(int destination); - bool imageLoad(bool loading); + void increaseRef (); + void decreaseRef (); + + void updateCache (bool updatePParams = true, bool updateCacheImageData = true); + void saveThumbnail (); + + bool openDefaultViewer(int destination); + bool imageLoad(bool loading); }; diff --git a/rtgui/thumbnailbrowser.h b/rtgui/thumbnailbrowser.h index 4b3c27078..c237c2194 100644 --- a/rtgui/thumbnailbrowser.h +++ b/rtgui/thumbnailbrowser.h @@ -7,7 +7,7 @@ * 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 @@ -23,39 +23,43 @@ #include "thumbnail.h" #include "filecatalog.h" -class ThumbBrowserEntry { +class ThumbBrowserEntry +{ public: // set by arrangeFiles(): - int width; // minimal width - int height; // minimal height - int exp_width; // ararnged width - int startx; // x coord. in the widget - int starty; // y coord. in the widget + int width; // minimal width + int height; // minimal height + int exp_width; // ararnged width + int startx; // x coord. in the widget + int starty; // y coord. in the widget // thumbnail preview properties: - int prew; // width of the thumbnail - int preh; // height of the thumbnail - guint8* preview; + int prew; // width of the thumbnail + int preh; // height of the thumbnail + guint8* preview; // file and directory attributes: - Glib::ustring filename; - Glib::ustring shortname; - Glib::ustring dirname; + Glib::ustring filename; + Glib::ustring shortname; + Glib::ustring dirname; // the associated thumbnail instance: - Thumbnail* thumbnail; - - ThumbBrowserEntry (Thumbnail* thm, Glib::ustring fname, Glib::ustring sname, Glib::ustring dname, int h) - : thumbnail(thm), filename(fname), shortname(sname), dirname(dname), preh(h) { - preview = thumbnail ? (guint8*) thumbnail->getThumbnailImage (prew, preh) : NULL; - } - - bool operator< (FileDescr& other) { - return shortname>other.shortname; - } + Thumbnail* thumbnail; + + ThumbBrowserEntry (Thumbnail* thm, Glib::ustring fname, Glib::ustring sname, Glib::ustring dname, int h) + : thumbnail(thm), filename(fname), shortname(sname), dirname(dname), preh(h) + { + preview = thumbnail ? (guint8*) thumbnail->getThumbnailImage (prew, preh) : NULL; + } + + bool operator< (FileDescr& other) + { + return shortname > other.shortname; + } }; -class ThumbBrowser : public Gtk::DrawingArea { - - protected: +class ThumbBrowser : public Gtk::DrawingArea +{ + +protected: int dx, dy, w, h; Glib::RefPtr gc_; @@ -74,19 +78,22 @@ class ThumbBrowser : public Gtk::DrawingArea { void arrangeFiles (int rows); - public: +public: ThumbBrowser (); void addEntry (ThumbBrowserEntry* entry); - void setThumbBrowserListener (ThumbBrowserListener* l) { tbl = l; } + void setThumbBrowserListener (ThumbBrowserListener* l) + { + tbl = l; + } virtual void on_realize(); virtual bool on_expose_event(GdkEventExpose* event); virtual bool on_button_press_event (GdkEventButton* event); virtual bool on_button_release_event (GdkEventButton* event); virtual void previewReady (FileDescr* fdn); - + void resized (Gtk::Allocation& req); void redraw (); void styleChanged (const Glib::RefPtr& style); diff --git a/rtgui/thumbnaillistener.h b/rtgui/thumbnaillistener.h index 1a2bae1aa..3c4200838 100644 --- a/rtgui/thumbnaillistener.h +++ b/rtgui/thumbnaillistener.h @@ -7,7 +7,7 @@ * 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 @@ -22,11 +22,12 @@ #include "thumbnail.h" class Thumbnail; -class ThumbnailListener { +class ThumbnailListener +{ - public: - - virtual void procParamsChanged (Thumbnail* thm, int whoChangedIt) {} +public: + + virtual void procParamsChanged (Thumbnail* thm, int whoChangedIt) {} }; diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index a4a12ae78..770652430 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -7,7 +7,7 @@ * 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 @@ -26,170 +26,173 @@ using namespace rtengine; using namespace rtengine::procparams; -ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LABEL")) { +ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LABEL")) +{ - CurveListener::setMulti(true); + CurveListener::setMulti(true); - std::vector bottomMilestones; - bottomMilestones.push_back( GradientMilestone(0., 0., 0., 0.) ); - bottomMilestones.push_back( GradientMilestone(1., 1., 1., 1.) ); + std::vector bottomMilestones; + bottomMilestones.push_back( GradientMilestone(0., 0., 0., 0.) ); + bottomMilestones.push_back( GradientMilestone(1., 1., 1., 1.) ); //----------- Auto Levels ---------------------------------- - abox = Gtk::manage (new Gtk::HBox ()); - abox->set_border_width (2); - abox->set_spacing (10); + abox = Gtk::manage (new Gtk::HBox ()); + abox->set_border_width (2); + abox->set_spacing (10); - autolevels = Gtk::manage (new Gtk::ToggleButton (M("TP_EXPOSURE_AUTOLEVELS"))); - autolevels->set_tooltip_markup (M("TP_EXPOSURE_AUTOLEVELS_TIP")); - autoconn = autolevels->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::autolevels_toggled) ); + autolevels = Gtk::manage (new Gtk::ToggleButton (M("TP_EXPOSURE_AUTOLEVELS"))); + autolevels->set_tooltip_markup (M("TP_EXPOSURE_AUTOLEVELS_TIP")); + autoconn = autolevels->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::autolevels_toggled) ); - lclip = Gtk::manage (new Gtk::Label (M("TP_EXPOSURE_CLIP"))); - lclip->set_tooltip_text (M("TP_EXPOSURE_CLIP_TIP")); + lclip = Gtk::manage (new Gtk::Label (M("TP_EXPOSURE_CLIP"))); + lclip->set_tooltip_text (M("TP_EXPOSURE_CLIP_TIP")); - sclip = Gtk::manage (new MySpinButton ()); - sclip->set_range (0.0, 0.99); - sclip->set_increments (0.01, 0.10); - sclip->set_value (0.02); - sclip->set_digits (2); - sclip->signal_value_changed().connect( sigc::mem_fun(*this, &ToneCurve::clip_changed) ); + sclip = Gtk::manage (new MySpinButton ()); + sclip->set_range (0.0, 0.99); + sclip->set_increments (0.01, 0.10); + sclip->set_value (0.02); + sclip->set_digits (2); + sclip->signal_value_changed().connect( sigc::mem_fun(*this, &ToneCurve::clip_changed) ); - neutral = Gtk::manage (new Gtk::Button (M("TP_NEUTRAL"))); - neutral->set_tooltip_text (M("TP_NEUTRAL_TIP")); - neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &ToneCurve::neutral_pressed) ); - neutral->show(); + neutral = Gtk::manage (new Gtk::Button (M("TP_NEUTRAL"))); + neutral->set_tooltip_text (M("TP_NEUTRAL_TIP")); + neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &ToneCurve::neutral_pressed) ); + neutral->show(); - abox->pack_start (*autolevels, true, true, 0); - // pack_end is used for these controls as autolevels is replaceable using pack_start in batchmode - abox->pack_end (*neutral, true, true, 0); - abox->pack_end (*sclip, false, false, 0); - abox->pack_end (*lclip, false, false, 0); - pack_start (*abox); + abox->pack_start (*autolevels, true, true, 0); + // pack_end is used for these controls as autolevels is replaceable using pack_start in batchmode + abox->pack_end (*neutral, true, true, 0); + abox->pack_end (*sclip, false, false, 0); + abox->pack_end (*lclip, false, false, 0); + pack_start (*abox); //-------------- Highlight Reconstruction ----------------- - pack_start (*Gtk::manage (new Gtk::HSeparator())); + pack_start (*Gtk::manage (new Gtk::HSeparator())); - hrenabled = Gtk::manage (new Gtk::CheckButton (M("TP_HLREC_LABEL"))); - hrenabled->set_active (false); - hrenabled->set_tooltip_markup (M("TP_HLREC_ENA_TOOLTIP")); - pack_start (*hrenabled); + hrenabled = Gtk::manage (new Gtk::CheckButton (M("TP_HLREC_LABEL"))); + hrenabled->set_active (false); + hrenabled->set_tooltip_markup (M("TP_HLREC_ENA_TOOLTIP")); + pack_start (*hrenabled); - method = Gtk::manage (new MyComboBoxText ()); - method->append_text (M("TP_HLREC_LUMINANCE")); - method->append_text (M("TP_HLREC_CIELAB")); - method->append_text (M("TP_HLREC_COLOR")); - method->append_text (M("TP_HLREC_BLEND")); + method = Gtk::manage (new MyComboBoxText ()); + method->append_text (M("TP_HLREC_LUMINANCE")); + method->append_text (M("TP_HLREC_CIELAB")); + method->append_text (M("TP_HLREC_COLOR")); + method->append_text (M("TP_HLREC_BLEND")); - method->set_active (0); - hlrbox = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_HLREC_METHOD"))); - hlrbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); - hlrbox->pack_start (*method); - pack_start (*hlrbox); + method->set_active (0); + hlrbox = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_HLREC_METHOD"))); + hlrbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); + hlrbox->pack_start (*method); + pack_start (*hlrbox); - enaconn = hrenabled->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::hrenabledChanged) ); - methconn = method->signal_changed().connect ( sigc::mem_fun(*this, &ToneCurve::methodChanged) ); + enaconn = hrenabled->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::hrenabledChanged) ); + methconn = method->signal_changed().connect ( sigc::mem_fun(*this, &ToneCurve::methodChanged) ); - //----------- Exposure Compensation --------------------- - pack_start (*Gtk::manage (new Gtk::HSeparator())); + //----------- Exposure Compensation --------------------- + pack_start (*Gtk::manage (new Gtk::HSeparator())); - expcomp = Gtk::manage (new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 12, 0.05, 0)); - pack_start (*expcomp); + expcomp = Gtk::manage (new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 12, 0.05, 0)); + pack_start (*expcomp); - //----------- Highlight recovery & threshold ------------- - hlcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0)); - pack_start (*hlcompr); - hlcomprthresh = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 33)); - pack_start (*hlcomprthresh); + //----------- Highlight recovery & threshold ------------- + hlcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0)); + pack_start (*hlcompr); + hlcomprthresh = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 33)); + pack_start (*hlcomprthresh); //----------- Black Level & Compression ------------------- - black = Gtk::manage (new Adjuster (M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 50, 0)); - pack_start (*black); - shcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRSHADOWS"), 0, 100, 1, 50)); - pack_start (*shcompr); + black = Gtk::manage (new Adjuster (M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 50, 0)); + pack_start (*black); + shcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRSHADOWS"), 0, 100, 1, 50)); + pack_start (*shcompr); - pack_start (*Gtk::manage (new Gtk::HSeparator())); + pack_start (*Gtk::manage (new Gtk::HSeparator())); //---------Brightness / Contrast ------------------------- - brightness = Gtk::manage (new Adjuster (M("TP_EXPOSURE_BRIGHTNESS"), -100, 100, 1, 0)); - pack_start (*brightness); - contrast = Gtk::manage (new Adjuster (M("TP_EXPOSURE_CONTRAST"), -100, 100, 1, 0)); - pack_start (*contrast); - saturation = Gtk::manage (new Adjuster (M("TP_EXPOSURE_SATURATION"), -100, 100, 1, 0)); - pack_start (*saturation); + brightness = Gtk::manage (new Adjuster (M("TP_EXPOSURE_BRIGHTNESS"), -100, 100, 1, 0)); + pack_start (*brightness); + contrast = Gtk::manage (new Adjuster (M("TP_EXPOSURE_CONTRAST"), -100, 100, 1, 0)); + pack_start (*contrast); + saturation = Gtk::manage (new Adjuster (M("TP_EXPOSURE_SATURATION"), -100, 100, 1, 0)); + pack_start (*saturation); //----------- Curve 1 ------------------------------ - pack_start (*Gtk::manage (new Gtk::HSeparator())); + pack_start (*Gtk::manage (new Gtk::HSeparator())); - toneCurveMode = Gtk::manage (new MyComboBoxText ()); - toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_STANDARD")); - toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_WEIGHTEDSTD")); - toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_FILMLIKE")); - toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_SATANDVALBLENDING")); - toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_LUMINANCE")); - toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_PERCEPTUAL")); - toneCurveMode->set_active (0); - toneCurveMode->set_tooltip_text(M("TP_EXPOSURE_TCMODE_LABEL1")); + toneCurveMode = Gtk::manage (new MyComboBoxText ()); + toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_STANDARD")); + toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_WEIGHTEDSTD")); + toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_FILMLIKE")); + toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_SATANDVALBLENDING")); + toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_LUMINANCE")); + toneCurveMode->append_text (M("TP_EXPOSURE_TCMODE_PERCEPTUAL")); + toneCurveMode->set_active (0); + toneCurveMode->set_tooltip_text(M("TP_EXPOSURE_TCMODE_LABEL1")); - curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_EXPOSURE_CURVEEDITOR1")); - curveEditorG->setCurveListener (this); + curveEditorG = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_EXPOSURE_CURVEEDITOR1")); + curveEditorG->setCurveListener (this); - shape = static_cast(curveEditorG->addCurve(CT_Diagonal, "", toneCurveMode)); - shape->setEditID(EUID_ToneCurve1, BT_IMAGEFLOAT); - shape->setBottomBarBgGradient(bottomMilestones); - shape->setLeftBarBgGradient(bottomMilestones); + shape = static_cast(curveEditorG->addCurve(CT_Diagonal, "", toneCurveMode)); + shape->setEditID(EUID_ToneCurve1, BT_IMAGEFLOAT); + shape->setBottomBarBgGradient(bottomMilestones); + shape->setLeftBarBgGradient(bottomMilestones); - // This will add the reset button at the end of the curveType buttons - curveEditorG->curveListComplete(); + // This will add the reset button at the end of the curveType buttons + curveEditorG->curveListComplete(); - pack_start( *curveEditorG, Gtk::PACK_SHRINK, 2); + pack_start( *curveEditorG, Gtk::PACK_SHRINK, 2); - tcmodeconn = toneCurveMode->signal_changed().connect( sigc::mem_fun(*this, &ToneCurve::curveMode1Changed), true ); + tcmodeconn = toneCurveMode->signal_changed().connect( sigc::mem_fun(*this, &ToneCurve::curveMode1Changed), true ); //----------- Curve 2 ------------------------------ - toneCurveMode2 = Gtk::manage (new MyComboBoxText ()); - toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_STANDARD")); - toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_WEIGHTEDSTD")); - toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_FILMLIKE")); - toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_SATANDVALBLENDING")); - toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_LUMINANCE")); - toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_PERCEPTUAL")); - toneCurveMode2->set_active (0); - toneCurveMode2->set_tooltip_text(M("TP_EXPOSURE_TCMODE_LABEL2")); + toneCurveMode2 = Gtk::manage (new MyComboBoxText ()); + toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_STANDARD")); + toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_WEIGHTEDSTD")); + toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_FILMLIKE")); + toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_SATANDVALBLENDING")); + toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_LUMINANCE")); + toneCurveMode2->append_text (M("TP_EXPOSURE_TCMODE_PERCEPTUAL")); + toneCurveMode2->set_active (0); + toneCurveMode2->set_tooltip_text(M("TP_EXPOSURE_TCMODE_LABEL2")); - curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_EXPOSURE_CURVEEDITOR2")); - curveEditorG2->setCurveListener (this); + curveEditorG2 = new CurveEditorGroup (options.lastToneCurvesDir, M("TP_EXPOSURE_CURVEEDITOR2")); + curveEditorG2->setCurveListener (this); - shape2 = static_cast(curveEditorG2->addCurve(CT_Diagonal, "", toneCurveMode2)); - shape2->setEditID(EUID_ToneCurve2, BT_IMAGEFLOAT); - shape2->setBottomBarBgGradient(bottomMilestones); - shape2->setLeftBarBgGradient(bottomMilestones); + shape2 = static_cast(curveEditorG2->addCurve(CT_Diagonal, "", toneCurveMode2)); + shape2->setEditID(EUID_ToneCurve2, BT_IMAGEFLOAT); + shape2->setBottomBarBgGradient(bottomMilestones); + shape2->setLeftBarBgGradient(bottomMilestones); - // This will add the reset button at the end of the curveType buttons - curveEditorG2->curveListComplete(); - curveEditorG2->setTooltip(M("TP_EXPOSURE_CURVEEDITOR2_TOOLTIP")); + // This will add the reset button at the end of the curveType buttons + curveEditorG2->curveListComplete(); + curveEditorG2->setTooltip(M("TP_EXPOSURE_CURVEEDITOR2_TOOLTIP")); - pack_start( *curveEditorG2, Gtk::PACK_SHRINK, 2); + pack_start( *curveEditorG2, Gtk::PACK_SHRINK, 2); - tcmode2conn = toneCurveMode2->signal_changed().connect( sigc::mem_fun(*this, &ToneCurve::curveMode2Changed), true ); + tcmode2conn = toneCurveMode2->signal_changed().connect( sigc::mem_fun(*this, &ToneCurve::curveMode2Changed), true ); // --------- Set Up Listeners ------------- - expcomp->setAdjusterListener (this); - brightness->setAdjusterListener (this); - black->setAdjusterListener (this); - hlcompr->setAdjusterListener (this); - hlcomprthresh->setAdjusterListener (this); - shcompr->setAdjusterListener (this); - contrast->setAdjusterListener (this); - saturation->setAdjusterListener (this); + expcomp->setAdjusterListener (this); + brightness->setAdjusterListener (this); + black->setAdjusterListener (this); + hlcompr->setAdjusterListener (this); + hlcomprthresh->setAdjusterListener (this); + shcompr->setAdjusterListener (this); + contrast->setAdjusterListener (this); + saturation->setAdjusterListener (this); } -ToneCurve::~ToneCurve () { +ToneCurve::~ToneCurve () +{ delete curveEditorG; delete curveEditorG2; } -void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { +void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -206,7 +209,11 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { hlcompr->setValue (pp->toneCurve.hlcompr); hlcomprthresh->setValue (pp->toneCurve.hlcomprthresh); shcompr->setValue (pp->toneCurve.shcompr); - if (!black->getAddMode()) shcompr->set_sensitive(!((int)black->getValue ()==0)); //at black=0 shcompr value has no effect + + if (!black->getAddMode()) { + shcompr->set_sensitive(!((int)black->getValue () == 0)); //at black=0 shcompr value has no effect + } + brightness->setValue (pp->toneCurve.brightness); contrast->setValue (pp->toneCurve.contrast); saturation->setValue (pp->toneCurve.saturation); @@ -229,36 +236,44 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { clipDirty = pedited->toneCurve.clip; shape->setUnChanged (!pedited->toneCurve.curve); shape2->setUnChanged (!pedited->toneCurve.curve2); + if (!pedited->toneCurve.curveMode) { toneCurveMode->set_active(6); } + if (!pedited->toneCurve.curveMode2) { toneCurveMode2->set_active(6); } } - if (pedited) + + if (pedited) { hrenabled->set_inconsistent (!pedited->toneCurve.hrenabled); + } + enaconn.block (true); hrenabled->set_active (pp->toneCurve.hrenabled); enaconn.block (false); - if (pedited && !pedited->toneCurve.method) + if (pedited && !pedited->toneCurve.method) { method->set_active (4); - else if (pp->toneCurve.method=="Luminance") + } else if (pp->toneCurve.method == "Luminance") { method->set_active (0); - else if (pp->toneCurve.method=="CIELab blending") + } else if (pp->toneCurve.method == "CIELab blending") { method->set_active (1); - else if (pp->toneCurve.method=="Color") + } else if (pp->toneCurve.method == "Color") { method->set_active (2); - else if (pp->toneCurve.method=="Blend") + } else if (pp->toneCurve.method == "Blend") { method->set_active (3); + } if (!batchMode) { - if (hrenabled->get_active()) + if (hrenabled->get_active()) { hlrbox->show(); - else + } else { hlrbox->hide(); + } } + lasthrEnabled = pp->toneCurve.hrenabled; autoconn.block (false); @@ -268,17 +283,20 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void ToneCurve::autoOpenCurve () { +void ToneCurve::autoOpenCurve () +{ shape->openIfNonlinear(); shape2->openIfNonlinear(); } -void ToneCurve::setEditProvider (EditDataProvider *provider) { +void ToneCurve::setEditProvider (EditDataProvider *provider) +{ shape->setEditProvider(provider); shape2->setEditProvider(provider); } -void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) { +void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->toneCurve.autoexp = autolevels->get_active(); pp->toneCurve.clip = sclip->get_value (); @@ -294,20 +312,36 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) { pp->toneCurve.curve2 = shape2->getCurve (); int tcMode = toneCurveMode->get_active_row_number(); - if (tcMode == 0) pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_STD; - else if (tcMode == 1) pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_WEIGHTEDSTD; - else if (tcMode == 2) pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_FILMLIKE; - else if (tcMode == 3) pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_SATANDVALBLENDING; - else if (tcMode == 4) pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_LUMINANCE; - else if (tcMode == 5) pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_PERCEPTUAL; + + if (tcMode == 0) { + pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_STD; + } else if (tcMode == 1) { + pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_WEIGHTEDSTD; + } else if (tcMode == 2) { + pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_FILMLIKE; + } else if (tcMode == 3) { + pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_SATANDVALBLENDING; + } else if (tcMode == 4) { + pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_LUMINANCE; + } else if (tcMode == 5) { + pp->toneCurve.curveMode = ToneCurveParams::TC_MODE_PERCEPTUAL; + } tcMode = toneCurveMode2->get_active_row_number(); - if (tcMode == 0) pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD; - else if (tcMode == 1) pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_WEIGHTEDSTD; - else if (tcMode == 2) pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_FILMLIKE; - else if (tcMode == 3) pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_SATANDVALBLENDING; - else if (tcMode == 4) pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_LUMINANCE; - else if (tcMode == 5) pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_PERCEPTUAL; + + if (tcMode == 0) { + pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD; + } else if (tcMode == 1) { + pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_WEIGHTEDSTD; + } else if (tcMode == 2) { + pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_FILMLIKE; + } else if (tcMode == 3) { + pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_SATANDVALBLENDING; + } else if (tcMode == 4) { + pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_LUMINANCE; + } else if (tcMode == 5) { + pp->toneCurve.curveMode2 = ToneCurveParams::TC_MODE_PERCEPTUAL; + } if (pedited) { pedited->toneCurve.expcomp = expcomp->getEditedState (); @@ -325,23 +359,27 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) { pedited->toneCurve.curveMode = toneCurveMode->get_active_row_number() != 6; pedited->toneCurve.curveMode2 = toneCurveMode2->get_active_row_number() != 6; } + if (pedited) { - pedited->toneCurve.method = method->get_active_row_number()!=4; + pedited->toneCurve.method = method->get_active_row_number() != 4; pedited->toneCurve.hrenabled = !hrenabled->get_inconsistent(); } pp->toneCurve.hrenabled = hrenabled->get_active(); - if (method->get_active_row_number()==0) + + if (method->get_active_row_number() == 0) { pp->toneCurve.method = "Luminance"; - else if (method->get_active_row_number()==1) + } else if (method->get_active_row_number() == 1) { pp->toneCurve.method = "CIELab blending"; - else if (method->get_active_row_number()==2) + } else if (method->get_active_row_number() == 2) { pp->toneCurve.method = "Color"; - else if (method->get_active_row_number()==3) + } else if (method->get_active_row_number() == 3) { pp->toneCurve.method = "Blend"; + } } -void ToneCurve::hrenabledChanged () { +void ToneCurve::hrenabledChanged () +{ if (multiImage) { if (hrenabled->get_inconsistent()) { @@ -349,18 +387,19 @@ void ToneCurve::hrenabledChanged () { enaconn.block (true); hrenabled->set_active (false); enaconn.block (false); - } - else if (lasthrEnabled) + } else if (lasthrEnabled) { hrenabled->set_inconsistent (true); + } lasthrEnabled = hrenabled->get_active (); } if (!batchMode) { - if (hrenabled->get_active()) + if (hrenabled->get_active()) { hlrbox->show(); - else + } else { hlrbox->hide(); + } } if (listener) { @@ -371,20 +410,25 @@ void ToneCurve::hrenabledChanged () { autoconn.block(false); autolevels->set_inconsistent (false); } - if (hrenabled->get_active ()) - listener->panelChanged (EvHREnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvHREnabled, M("GENERAL_DISABLED")); - } -} -void ToneCurve::methodChanged () { - if (listener) { - if (hrenabled->get_active ()) - listener->panelChanged (EvHRMethod, method->get_active_text ()); + if (hrenabled->get_active ()) { + listener->panelChanged (EvHREnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvHREnabled, M("GENERAL_DISABLED")); + } } } -void ToneCurve::setRaw (bool raw) { +void ToneCurve::methodChanged () +{ + + if (listener) { + if (hrenabled->get_active ()) { + listener->panelChanged (EvHRMethod, method->get_active_text ()); + } + } +} +void ToneCurve::setRaw (bool raw) +{ disableListener (); method->set_sensitive (raw); @@ -393,7 +437,8 @@ void ToneCurve::setRaw (bool raw) { } -void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ expcomp->setDefault (defParams->toneCurve.expcomp); brightness->setDefault (defParams->toneCurve.brightness); @@ -413,8 +458,7 @@ void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pe brightness->setDefaultEditedState (pedited->toneCurve.brightness ? Edited : UnEdited); contrast->setDefaultEditedState (pedited->toneCurve.contrast ? Edited : UnEdited); saturation->setDefaultEditedState (pedited->toneCurve.saturation ? Edited : UnEdited); - } - else { + } else { expcomp->setDefaultEditedState (Irrelevant); black->setDefaultEditedState (Irrelevant); hlcompr->setDefaultEditedState (Irrelevant); @@ -426,89 +470,116 @@ void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pe } } -void ToneCurve::curveChanged (CurveEditor* ce) { +void ToneCurve::curveChanged (CurveEditor* ce) +{ if (listener) { - if (ce == shape) + if (ce == shape) { listener->panelChanged (EvToneCurve1, M("HISTORY_CUSTOMCURVE")); - else if (ce == shape2) + } else if (ce == shape2) { listener->panelChanged (EvToneCurve2, M("HISTORY_CUSTOMCURVE")); + } } } -void ToneCurve::curveMode1Changed () { +void ToneCurve::curveMode1Changed () +{ //if (listener) listener->panelChanged (EvToneCurveMode, toneCurveMode->get_active_text()); - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::curveMode1Changed_)); + if (listener) { + Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::curveMode1Changed_)); + } } -bool ToneCurve::curveMode1Changed_ () { - if (listener) listener->panelChanged (EvToneCurveMode1, toneCurveMode->get_active_text()); +bool ToneCurve::curveMode1Changed_ () +{ + if (listener) { + listener->panelChanged (EvToneCurveMode1, toneCurveMode->get_active_text()); + } + return false; } -void ToneCurve::curveMode2Changed () { +void ToneCurve::curveMode2Changed () +{ //if (listener) listener->panelChanged (EvToneCurveMode, toneCurveMode->get_active_text()); - if (listener) Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::curveMode2Changed_)); + if (listener) { + Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::curveMode2Changed_)); + } } -bool ToneCurve::curveMode2Changed_ () { - if (listener) listener->panelChanged (EvToneCurveMode2, toneCurveMode2->get_active_text()); +bool ToneCurve::curveMode2Changed_ () +{ + if (listener) { + listener->panelChanged (EvToneCurveMode2, toneCurveMode2->get_active_text()); + } + return false; } -float ToneCurve::blendPipetteValues(CurveEditor *ce, float chan1, float chan2, float chan3) { +float ToneCurve::blendPipetteValues(CurveEditor *ce, float chan1, float chan2, float chan3) +{ // assuming that all the channels are used... if (ce == shape) { - if (toneCurveMode->get_active_row_number() == 4) - return chan1*0.2126729f + chan2*0.7151521f + chan3*0.0721750f; - } - else if (ce == shape2) { - if (toneCurveMode2->get_active_row_number() == 4) - return chan1*0.2126729f + chan2*0.7151521f + chan3*0.0721750f; + if (toneCurveMode->get_active_row_number() == 4) { + return chan1 * 0.2126729f + chan2 * 0.7151521f + chan3 * 0.0721750f; + } + } else if (ce == shape2) { + if (toneCurveMode2->get_active_row_number() == 4) { + return chan1 * 0.2126729f + chan2 * 0.7151521f + chan3 * 0.0721750f; + } } + return CurveListener::blendPipetteValues(ce, chan1, chan2, chan3); } -void ToneCurve::adjusterChanged (Adjuster* a, double newval) { +void ToneCurve::adjusterChanged (Adjuster* a, double newval) +{ // Switch off auto exposure if user changes sliders manually - if (autolevels->get_active() && (a==expcomp || a==brightness || a==contrast || a==black || a==hlcompr || a==hlcomprthresh)) { + if (autolevels->get_active() && (a == expcomp || a == brightness || a == contrast || a == black || a == hlcompr || a == hlcomprthresh)) { autoconn.block(true); autolevels->set_active (false); autoconn.block(false); autolevels->set_inconsistent (false); } - if (!listener) + if (!listener) { return; + } Glib::ustring costr; - if (a==expcomp) - costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); - else - costr = Glib::ustring::format ((int)a->getValue()); - if (a==expcomp) - listener->panelChanged (EvExpComp, costr); - else if (a==brightness) - listener->panelChanged (EvBrightness, costr); - else if (a==black){ - listener->panelChanged (EvBlack, costr); - if (!black->getAddMode()) shcompr->set_sensitive(!((int)black->getValue ()==0)); //at black=0 shcompr value has no effect + if (a == expcomp) { + costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); + } else { + costr = Glib::ustring::format ((int)a->getValue()); } - else if (a==contrast) + + if (a == expcomp) { + listener->panelChanged (EvExpComp, costr); + } else if (a == brightness) { + listener->panelChanged (EvBrightness, costr); + } else if (a == black) { + listener->panelChanged (EvBlack, costr); + + if (!black->getAddMode()) { + shcompr->set_sensitive(!((int)black->getValue () == 0)); //at black=0 shcompr value has no effect + } + } else if (a == contrast) { listener->panelChanged (EvContrast, costr); - else if (a==saturation) + } else if (a == saturation) { listener->panelChanged (EvSaturation, costr); - else if (a==hlcompr) + } else if (a == hlcompr) { listener->panelChanged (EvHLCompr, costr); - else if (a==hlcomprthresh) + } else if (a == hlcomprthresh) { listener->panelChanged (EvHLComprThreshold, costr); - else if (a==shcompr) + } else if (a == shcompr) { listener->panelChanged (EvSHCompr, costr); + } } -void ToneCurve::neutral_pressed () { +void ToneCurve::neutral_pressed () +{ // This method deselects auto levels and HL reconstruction auto // and sets neutral values to params in exposure panel @@ -519,8 +590,7 @@ void ToneCurve::neutral_pressed () { autoconn.block (false); lastAuto = autolevels->get_active (); - } - else { //!batchMode + } else { //!batchMode autolevels->set_active (false); autolevels->set_inconsistent (false); } @@ -534,15 +604,22 @@ void ToneCurve::neutral_pressed () { enaconn.block (true); hrenabled->set_active (false); enaconn.block (false); - if (!batchMode) + + if (!batchMode) { hlrbox->hide(); - if (!black->getAddMode()) shcompr->set_sensitive(!((int)black->getValue ()==0)); //at black=0 shcompr value has no effect + } + + if (!black->getAddMode()) { + shcompr->set_sensitive(!((int)black->getValue () == 0)); //at black=0 shcompr value has no effect + } + contrast->setValue(0); //saturation->setValue(0); listener->panelChanged (EvNeutralExp, M("GENERAL_ENABLED")); } -void ToneCurve::autolevels_toggled () { +void ToneCurve::autolevels_toggled () +{ if (batchMode) { if (autolevels->get_inconsistent()) { @@ -550,9 +627,9 @@ void ToneCurve::autolevels_toggled () { autoconn.block (true); autolevels->set_active (false); autoconn.block (false); - } - else if (lastAuto) + } else if (lastAuto) { autolevels->set_inconsistent (true); + } lastAuto = autolevels->get_active (); @@ -562,58 +639,80 @@ void ToneCurve::autolevels_toggled () { black->setEditedState (UnEdited); hlcompr->setEditedState (UnEdited); hlcomprthresh->setEditedState (UnEdited); - if (expcomp->getAddMode()) + + if (expcomp->getAddMode()) { expcomp->setValue (0); - if (brightness->getAddMode()) + } + + if (brightness->getAddMode()) { brightness->setValue (0); - if (contrast->getAddMode()) + } + + if (contrast->getAddMode()) { contrast->setValue (0); - if (black->getAddMode()) + } + + if (black->getAddMode()) { black->setValue (0); - if (hlcompr->getAddMode()) + } + + if (hlcompr->getAddMode()) { hlcompr->setValue (0); - if (hlcomprthresh->getAddMode()) + } + + if (hlcomprthresh->getAddMode()) { hlcomprthresh->setValue (0); + } if (listener) { if (!autolevels->get_inconsistent()) { - if (autolevels->get_active ()) + if (autolevels->get_active ()) { listener->panelChanged (EvAutoExp, M("GENERAL_ENABLED")); - else + } else { listener->panelChanged (EvFixedExp, M("GENERAL_DISABLED")); + } } } - } - else if (/* !batchMode && */ listener) { + } else if (/* !batchMode && */ listener) { if (autolevels->get_active()) { listener->panelChanged (EvAutoExp, M("GENERAL_ENABLED")); waitForAutoExp (); - if (!black->getAddMode()) shcompr->set_sensitive(!((int)black->getValue ()==0)); //at black=0 shcompr value has no effect - } - else { + + if (!black->getAddMode()) { + shcompr->set_sensitive(!((int)black->getValue () == 0)); //at black=0 shcompr value has no effect + } + } else { listener->panelChanged (EvFixedExp, M("GENERAL_DISABLED")); } } } -void ToneCurve::clip_changed () { +void ToneCurve::clip_changed () +{ clipDirty = true; - if (autolevels->get_active() && listener) + + if (autolevels->get_active() && listener) { Glib::signal_idle().connect (sigc::mem_fun(*this, &ToneCurve::clip_changed_)); + } } -bool ToneCurve::clip_changed_ () { +bool ToneCurve::clip_changed_ () +{ if (listener) { listener->panelChanged (EvClip, Glib::ustring::format (std::setprecision(5), sclip->get_value())); - if (!batchMode) + + if (!batchMode) { waitForAutoExp (); + } } + return false; } -void ToneCurve::waitForAutoExp () { +void ToneCurve::waitForAutoExp () +{ sclip->set_sensitive (false); expcomp->setEnabled (false); @@ -633,12 +732,14 @@ void ToneCurve::waitForAutoExp () { method->set_sensitive(false); } -int autoExpChangedUI (void* data) { +int autoExpChangedUI (void* data) +{ (static_cast(data))->autoExpComputed_ (); return 0; } -void ToneCurve::autoExpChanged (double expcomp, int bright, int contr, int black, int hlcompr, int hlcomprthresh, bool hlrecons) { +void ToneCurve::autoExpChanged (double expcomp, int bright, int contr, int black, int hlcompr, int hlcomprthresh, bool hlrecons) +{ nextBlack = black; nextExpcomp = expcomp; @@ -650,7 +751,8 @@ void ToneCurve::autoExpChanged (double expcomp, int bright, int contr, int black g_idle_add (autoExpChangedUI, this); } -void ToneCurve::enableAll () { +void ToneCurve::enableAll () +{ sclip->set_sensitive (true); expcomp->setEnabled (true); @@ -669,7 +771,8 @@ void ToneCurve::enableAll () { method->set_sensitive(true); } -bool ToneCurve::autoExpComputed_ () { +bool ToneCurve::autoExpComputed_ () +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected disableListener (); @@ -683,17 +786,24 @@ bool ToneCurve::autoExpComputed_ () { enaconn.block (true); hrenabled->set_active (nextHLRecons); enaconn.block (false); - if (nextHLRecons) + + if (nextHLRecons) { hlrbox->show(); - else if (!batchMode) + } else if (!batchMode) { hlrbox->hide(); - if (!black->getAddMode()) shcompr->set_sensitive(!((int)black->getValue ()==0)); //at black=0 shcompr value has no effect + } + + if (!black->getAddMode()) { + shcompr->set_sensitive(!((int)black->getValue () == 0)); //at black=0 shcompr value has no effect + } + enableListener (); return false; } -void ToneCurve::setBatchMode (bool batchMode) { +void ToneCurve::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); method->append_text (M("GENERAL_UNCHANGED")); @@ -720,7 +830,8 @@ void ToneCurve::setBatchMode (bool batchMode) { curveEditorG2->setBatchMode (batchMode); } -void ToneCurve::setAdjusterBehavior (bool expadd, bool hlcompadd, bool hlcompthreshadd, bool bradd, bool blackadd, bool shcompadd, bool contradd, bool satadd) { +void ToneCurve::setAdjusterBehavior (bool expadd, bool hlcompadd, bool hlcompthreshadd, bool bradd, bool blackadd, bool shcompadd, bool contradd, bool satadd) +{ expcomp->setAddMode(expadd); hlcompr->setAddMode(hlcompadd); @@ -732,7 +843,8 @@ void ToneCurve::setAdjusterBehavior (bool expadd, bool hlcompadd, bool hlcompthr saturation->setAddMode(satadd); } -void ToneCurve::trimValues (rtengine::procparams::ProcParams* pp) { +void ToneCurve::trimValues (rtengine::procparams::ProcParams* pp) +{ expcomp->trimValue(pp->toneCurve.expcomp); hlcompr->trimValue(pp->toneCurve.hlcompr); @@ -744,7 +856,8 @@ void ToneCurve::trimValues (rtengine::procparams::ProcParams* pp) { saturation->trimValue(pp->toneCurve.saturation); } -void ToneCurve::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) { +void ToneCurve::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) +{ shape->updateBackgroundHistogram (histToneCurve); } diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 3a6c7afe3..dae1acea6 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -7,7 +7,7 @@ * 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 @@ -27,16 +27,17 @@ #include "mycurve.h" #include "guiutils.h" -class ToneCurve : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoExpListener,public CurveListener { +class ToneCurve : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoExpListener, public CurveListener +{ - protected: +protected: // from HLRecovery Gtk::CheckButton* hrenabled; MyComboBoxText* method; sigc::connection methconn; sigc::connection enaconn; bool lasthrEnabled; - + Gtk::HBox* abox; Gtk::HBox* hlrbox; @@ -71,14 +72,14 @@ class ToneCurve : public ToolParamBlock, public AdjusterListener, public Foldabl int nextHlcomprthresh; bool nextHLRecons; - public: +public: ToneCurve (); ~ToneCurve (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void setAdjusterBehavior (bool expadd, bool hlcompadd, bool hlcompthreshadd, bool bradd, bool blackadd, bool shcompadd, bool contradd, bool satadd); void trimValues (rtengine::procparams::ProcParams* pp); @@ -104,7 +105,7 @@ class ToneCurve : public ToolParamBlock, public AdjusterListener, public Foldabl void expandCurve (bool isExpanded); bool isCurveExpanded (); void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve,/* LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma); - + void setRaw (bool raw); void hrenabledChanged (); diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index 627670dd9..7a7222299 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -7,7 +7,7 @@ * 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 @@ -20,275 +20,363 @@ #include "multilangmgr.h" #include "guiutils.h" -ToolBar::ToolBar () : listener (NULL) { +ToolBar::ToolBar () : listener (NULL) +{ - editingMode = false; + editingMode = false; - handimg = Gtk::manage (new RTImage ("openhand.png")); - handimg->reference(); - editinghandimg = Gtk::manage (new RTImage ("editmodehand.png")); - editinghandimg->reference(); + handimg = Gtk::manage (new RTImage ("openhand.png")); + handimg->reference(); + editinghandimg = Gtk::manage (new RTImage ("editmodehand.png")); + editinghandimg->reference(); - handTool = Gtk::manage (new Gtk::ToggleButton ()); - handTool->add (*handimg); - handimg->show (); - handTool->set_relief(Gtk::RELIEF_NONE); - handTool->show (); + handTool = Gtk::manage (new Gtk::ToggleButton ()); + handTool->add (*handimg); + handimg->show (); + handTool->set_relief(Gtk::RELIEF_NONE); + handTool->show (); - pack_start (*handTool); + pack_start (*handTool); - wbTool = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* wbimg = Gtk::manage (new RTImage ("gtk-color-picker.png")); - wbTool->add (*wbimg); - wbimg->show (); - wbTool->set_relief(Gtk::RELIEF_NONE); - wbTool->show (); + wbTool = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* wbimg = Gtk::manage (new RTImage ("gtk-color-picker.png")); + wbTool->add (*wbimg); + wbimg->show (); + wbTool->set_relief(Gtk::RELIEF_NONE); + wbTool->show (); - pack_start (*wbTool); + pack_start (*wbTool); - cropTool = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* cropimg = Gtk::manage (new RTImage ("crop.png")); - cropTool->add (*cropimg); - cropimg->show (); - cropTool->set_relief(Gtk::RELIEF_NONE); - cropTool->show (); + cropTool = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* cropimg = Gtk::manage (new RTImage ("crop.png")); + cropTool->add (*cropimg); + cropimg->show (); + cropTool->set_relief(Gtk::RELIEF_NONE); + cropTool->show (); - pack_start (*cropTool); + pack_start (*cropTool); - straTool = Gtk::manage (new Gtk::ToggleButton ()); - Gtk::Image* straimg = Gtk::manage (new RTImage ("straighten.png")); - straTool->add (*straimg); - straimg->show (); - straTool->set_relief(Gtk::RELIEF_NONE); - straTool->show (); + straTool = Gtk::manage (new Gtk::ToggleButton ()); + Gtk::Image* straimg = Gtk::manage (new RTImage ("straighten.png")); + straTool->add (*straimg); + straimg->show (); + straTool->set_relief(Gtk::RELIEF_NONE); + straTool->show (); - pack_start (*straTool); + pack_start (*straTool); - handTool->set_active (true); - current = TMHand; + handTool->set_active (true); + current = TMHand; - handConn = handTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::hand_pressed)); - wbConn = wbTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::wb_pressed)); - cropConn = cropTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::crop_pressed)); - straConn = straTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::stra_pressed)); + handConn = handTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::hand_pressed)); + wbConn = wbTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::wb_pressed)); + cropConn = cropTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::crop_pressed)); + straConn = straTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::stra_pressed)); - handTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_HAND")); - wbTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_WB")); - cropTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_CROP")); - straTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_STRAIGHTEN")); + handTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_HAND")); + wbTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_WB")); + cropTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_CROP")); + straTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_STRAIGHTEN")); } -ToolBar::~ToolBar () { - handimg->unreference(); - editinghandimg->unreference(); +ToolBar::~ToolBar () +{ + handimg->unreference(); + editinghandimg->unreference(); } // // Selects the desired tool without notifying the listener // -void ToolBar::setTool (ToolMode tool) { +void ToolBar::setTool (ToolMode tool) +{ - handConn.block (true); - cropConn.block (true); - if (wbTool) wbConn.block (true); - straConn.block (true); + handConn.block (true); + cropConn.block (true); - bool stopEdit = tool==TMHand && handTool->get_active() && editingMode; + if (wbTool) { + wbConn.block (true); + } - handTool->set_active (false); - if (wbTool) wbTool->set_active (false); - cropTool->set_active (false); - straTool->set_active (false); + straConn.block (true); + + bool stopEdit = tool == TMHand && handTool->get_active() && editingMode; + + handTool->set_active (false); + + if (wbTool) { + wbTool->set_active (false); + } + + cropTool->set_active (false); + straTool->set_active (false); + + if (tool == TMHand) { + handTool->set_active (true); + handTool->grab_focus(); // switch focus to the handTool button + } else if (tool == TMSpotWB) { + if (wbTool) { + wbTool->set_active (true); + } + } else if (tool == TMCropSelect) { + cropTool->set_active (true); + } else if (tool == TMStraighten) { + straTool->set_active (true); + } + + current = tool; + + handConn.block (false); + cropConn.block (false); + + if (wbTool) { + wbConn.block (false); + } + + straConn.block (false); + + if (stopEdit) { + stopEditMode(); + + if (listener) { + listener->editModeSwitchedOff(); + } + } +} + +void ToolBar::startEditMode() +{ + if (!editingMode) { + handTool->set_active(true); // will call hand_pressed, with editingMode=false + editingMode = true; + handTool->set_image(*editinghandimg); + } + +#ifndef NDEBUG + else { + printf("Editing mode already active!\n"); + } + +#endif +} + +void ToolBar::stopEditMode() +{ + if (editingMode) { + editingMode = false; + /* WARNING: Should we toggle the Hand button on? + * This method can be called while another tool is active, e.g. if the user toggle off + * the Subscriber's Edit button. For now, we keep that other tool active. If one want to + * switch to the Hand tool, uncommenting the following line should suffice (not tested). + * + * handTool->set_active(true); + */ + handTool->set_image(*handimg); + } +} + +void ToolBar::hand_pressed () +{ + + handConn.block (true); + cropConn.block (true); + + if (wbTool) { + wbConn.block (true); + } + + straConn.block (true); + + if (current != TMHand) { + if (wbTool) { + wbTool->set_active (false); + } + + cropTool->set_active (false); + straTool->set_active (false); + current = TMHand; + } else { + if (editingMode) { + stopEditMode(); + } + + if (listener) { + listener->editModeSwitchedOff (); + } + } - if (tool==TMHand){ handTool->set_active (true); - handTool->grab_focus(); // switch focus to the handTool button - } - else if (tool==TMSpotWB) { - if (wbTool) wbTool->set_active (true); - } - else if (tool==TMCropSelect) + handConn.block (false); + cropConn.block (false); + + if (wbTool) { + wbConn.block (false); + } + + straConn.block (false); + + if (listener) { + listener->toolSelected (TMHand); + } +} + +void ToolBar::wb_pressed () +{ + + handConn.block (true); + cropConn.block (true); + + if (wbTool) { + wbConn.block (true); + } + + straConn.block (true); + + if (current != TMSpotWB) { + handTool->set_active (false); + cropTool->set_active (false); + straTool->set_active (false); + current = TMSpotWB; + } + + if (wbTool) { + wbTool->set_active (true); + } + + handConn.block (false); + cropConn.block (false); + + if (wbTool) { + wbConn.block (false); + } + + straConn.block (false); + + if (listener) { + listener->toolSelected (TMSpotWB); + } +} + +void ToolBar::crop_pressed () +{ + + handConn.block (true); + cropConn.block (true); + + if (wbTool) { + wbConn.block (true); + } + + straConn.block (true); + + if (current != TMCropSelect) { + handTool->set_active (false); + + if (wbTool) { + wbTool->set_active (false); + } + + straTool->set_active (false); + current = TMCropSelect; + } + cropTool->set_active (true); - else if (tool==TMStraighten) + handConn.block (false); + cropConn.block (false); + wbConn.block (false); + straConn.block (false); + + if (listener) { + listener->toolSelected (TMCropSelect); + } +} + +void ToolBar::stra_pressed () +{ + + handConn.block (true); + cropConn.block (true); + + if (wbTool) { + wbConn.block (true); + } + + straConn.block (true); + + if (current != TMStraighten) { + handTool->set_active (false); + + if (wbTool) { + wbTool->set_active (false); + } + + cropTool->set_active (false); + current = TMStraighten; + } + straTool->set_active (true); + handConn.block (false); + cropConn.block (false); - current = tool; + if (wbTool) { + wbConn.block (false); + } - handConn.block (false); - cropConn.block (false); - if (wbTool) wbConn.block (false); - straConn.block (false); + straConn.block (false); - if (stopEdit) { - stopEditMode(); - if (listener) - listener->editModeSwitchedOff(); - } + if (listener) { + listener->toolSelected (TMStraighten); + } } -void ToolBar::startEditMode() { - if (!editingMode) { - handTool->set_active(true); // will call hand_pressed, with editingMode=false - editingMode = true; - handTool->set_image(*editinghandimg); - } - #ifndef NDEBUG - else - printf("Editing mode already active!\n"); - #endif -} - -void ToolBar::stopEditMode() { - if (editingMode) { - editingMode = false; - /* WARNING: Should we toggle the Hand button on? - * This method can be called while another tool is active, e.g. if the user toggle off - * the Subscriber's Edit button. For now, we keep that other tool active. If one want to - * switch to the Hand tool, uncommenting the following line should suffice (not tested). - * - * handTool->set_active(true); - */ - handTool->set_image(*handimg); - } -} - -void ToolBar::hand_pressed () { - - handConn.block (true); - cropConn.block (true); - if (wbTool) wbConn.block (true); - straConn.block (true); - if (current!=TMHand) { - if (wbTool) wbTool->set_active (false); - cropTool->set_active (false); - straTool->set_active (false); - current = TMHand; - } - else { - if (editingMode) - stopEditMode(); - if (listener) - listener->editModeSwitchedOff (); - } - handTool->set_active (true); - handConn.block (false); - cropConn.block (false); - if (wbTool) wbConn.block (false); - straConn.block (false); - - if (listener) - listener->toolSelected (TMHand); -} - -void ToolBar::wb_pressed () { - - handConn.block (true); - cropConn.block (true); - if (wbTool) wbConn.block (true); - straConn.block (true); - if (current!=TMSpotWB) { - handTool->set_active (false); - cropTool->set_active (false); - straTool->set_active (false); - current = TMSpotWB; - } - if (wbTool) wbTool->set_active (true); - handConn.block (false); - cropConn.block (false); - if (wbTool) wbConn.block (false); - straConn.block (false); - - if (listener) - listener->toolSelected (TMSpotWB); -} - -void ToolBar::crop_pressed () { - - handConn.block (true); - cropConn.block (true); - if (wbTool) wbConn.block (true); - straConn.block (true); - if (current!=TMCropSelect) { - handTool->set_active (false); - if (wbTool) wbTool->set_active (false); - straTool->set_active (false); - current = TMCropSelect; - } - cropTool->set_active (true); - handConn.block (false); - cropConn.block (false); - wbConn.block (false); - straConn.block (false); - - if (listener) - listener->toolSelected (TMCropSelect); -} - -void ToolBar::stra_pressed () { - - handConn.block (true); - cropConn.block (true); - if (wbTool) wbConn.block (true); - straConn.block (true); - if (current!=TMStraighten) { - handTool->set_active (false); - if (wbTool) wbTool->set_active (false); - cropTool->set_active (false); - current = TMStraighten; - } - straTool->set_active (true); - handConn.block (false); - cropConn.block (false); - if (wbTool) wbConn.block (false); - straConn.block (false); - - if (listener) - listener->toolSelected (TMStraighten); -} - -bool ToolBar::handleShortcutKey (GdkEventKey* event) { +bool ToolBar::handleShortcutKey (GdkEventKey* event) +{ bool ctrl = event->state & GDK_CONTROL_MASK; //bool shift = event->state & GDK_SHIFT_MASK; bool alt = event->state & GDK_MOD1_MASK; - + if (!ctrl && !alt) { switch(event->keyval) { - case GDK_w: - case GDK_W: - if(wbTool){ - wb_pressed (); - return true; - } - return false; - case GDK_c: - case GDK_C: - crop_pressed (); - return true; - case GDK_s: - case GDK_S: - stra_pressed (); - return true; - case GDK_h: - case GDK_H: - hand_pressed (); + case GDK_w: + case GDK_W: + if(wbTool) { + wb_pressed (); return true; + } + + return false; + + case GDK_c: + case GDK_C: + crop_pressed (); + return true; + + case GDK_s: + case GDK_S: + stra_pressed (); + return true; + + case GDK_h: + case GDK_H: + hand_pressed (); + return true; } - } - else { + } else { switch (event->keyval) { } } - + return false; } -void ToolBar::removeWbTool() { +void ToolBar::removeWbTool() +{ if (wbTool) { wbConn.disconnect(); removeIfThere(this, wbTool, false); wbTool = NULL; - } + } } diff --git a/rtgui/toolbar.h b/rtgui/toolbar.h index 3ec50d65a..e00520721 100644 --- a/rtgui/toolbar.h +++ b/rtgui/toolbar.h @@ -7,7 +7,7 @@ * 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 @@ -23,9 +23,10 @@ #include "toolenum.h" #include "rtimage.h" -class ToolBarListener { +class ToolBarListener +{ - public: +public: virtual ~ToolBarListener() {} /// Callback when a tool is selected virtual void toolSelected (ToolMode tool) {} @@ -34,12 +35,13 @@ class ToolBarListener { virtual void editModeSwitchedOff () {} }; -class ToolBar : public Gtk::HBox { - private: +class ToolBar : public Gtk::HBox +{ +private: RTImage* handimg; RTImage* editinghandimg; - protected: +protected: Gtk::ToggleButton* handTool; Gtk::ToggleButton* wbTool; Gtk::ToggleButton* cropTool; @@ -52,14 +54,20 @@ class ToolBar : public Gtk::HBox { sigc::connection cropConn; sigc::connection straConn; - public: +public: ToolBar (); ~ToolBar (); void setTool (ToolMode tool); - ToolMode getTool () { return current; } + ToolMode getTool () + { + return current; + } - void setToolBarListener (ToolBarListener* tpl) { listener = tpl; } + void setToolBarListener (ToolBarListener* tpl) + { + listener = tpl; + } void startEditMode(); void stopEditMode(); diff --git a/rtgui/toolenum.h b/rtgui/toolenum.h index b07d63ec3..f06fda376 100644 --- a/rtgui/toolenum.h +++ b/rtgui/toolenum.h @@ -7,7 +7,7 @@ * 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 @@ -19,6 +19,6 @@ #ifndef _TOOLENUM_ #define _TOOLENUM_ -enum ToolMode {TMHand=0, TMSpotWB=1, TMCropSelect=2, TMStraighten=3}; +enum ToolMode {TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3}; #endif diff --git a/rtgui/toolpanel.cc b/rtgui/toolpanel.cc index 9bf9bdd77..fdee3fa79 100644 --- a/rtgui/toolpanel.cc +++ b/rtgui/toolpanel.cc @@ -23,128 +23,145 @@ using namespace rtengine::procparams; -ToolVBox::ToolVBox() { - updateStyle(); +ToolVBox::ToolVBox() +{ + updateStyle(); } -void ToolVBox::updateStyle() { - if (options.slimUI) { - set_spacing(1); // Vertical space between tools - set_border_width(1); // Space separating the tab's frame and the tools - } - else { - set_spacing(2); // Vertical space between tools - set_border_width(1); // Space separating the tab's frame and the tools 3 - } +void ToolVBox::updateStyle() +{ + if (options.slimUI) { + set_spacing(1); // Vertical space between tools + set_border_width(1); // Space separating the tab's frame and the tools + } else { + set_spacing(2); // Vertical space between tools + set_border_width(1); // Space separating the tab's frame and the tools 3 + } } -void ToolVBox::on_style_changed (const Glib::RefPtr& style) { - updateStyle(); +void ToolVBox::on_style_changed (const Glib::RefPtr& style) +{ + updateStyle(); } -ToolParamBlock::ToolParamBlock() { - updateStyle(); +ToolParamBlock::ToolParamBlock() +{ + updateStyle(); } -void ToolParamBlock::updateStyle() { - if (options.slimUI) { - set_spacing(2); // Vertical space between parameters in a single tool - set_border_width(6); // Space separating the parameters of a tool and its surrounding frame 6 - } - else { - set_spacing(4); // Vertical space between parameters in a single tool - set_border_width(8); // Space separating the parameters of a tool and its surrounding frame 8 - } +void ToolParamBlock::updateStyle() +{ + if (options.slimUI) { + set_spacing(2); // Vertical space between parameters in a single tool + set_border_width(6); // Space separating the parameters of a tool and its surrounding frame 6 + } else { + set_spacing(4); // Vertical space between parameters in a single tool + set_border_width(8); // Space separating the parameters of a tool and its surrounding frame 8 + } } -void ToolParamBlock::on_style_changed (const Glib::RefPtr& style) { - updateStyle(); +void ToolParamBlock::on_style_changed (const Glib::RefPtr& style) +{ + updateStyle(); } FoldableToolPanel::FoldableToolPanel(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11, bool useEnabled) : ToolPanel(toolName, need11), parentContainer(NULL), exp(NULL), lastEnabled(true) { - if (!content) - return; + if (!content) { + return; + } -// exp->set_border_width (5); -// exp->set_use_markup (true); - if (need11) { - Gtk::HBox *titleHBox = Gtk::manage(new Gtk::HBox()); +// exp->set_border_width (5); +// exp->set_use_markup (true); + if (need11) { + Gtk::HBox *titleHBox = Gtk::manage(new Gtk::HBox()); - Gtk::Label *label = Gtk::manage(new Gtk::Label()); - label->set_markup(Glib::ustring("") + escapeHtmlChars(UILabel) + Glib::ustring("")); - label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); - titleHBox->pack_start(*label, Gtk::PACK_EXPAND_WIDGET, 0); + Gtk::Label *label = Gtk::manage(new Gtk::Label()); + label->set_markup(Glib::ustring("") + escapeHtmlChars(UILabel) + Glib::ustring("")); + label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); + titleHBox->pack_start(*label, Gtk::PACK_EXPAND_WIDGET, 0); - RTImage *image = Gtk::manage (new RTImage("zoom-100-identifier.png")); - image->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); - titleHBox->pack_end(*image, Gtk::PACK_SHRINK, 0); + RTImage *image = Gtk::manage (new RTImage("zoom-100-identifier.png")); + image->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); + titleHBox->pack_end(*image, Gtk::PACK_SHRINK, 0); - exp = Gtk::manage (new MyExpander (useEnabled, titleHBox)); - } - else { - exp = Gtk::manage (new MyExpander (useEnabled, UILabel)); - } - exp->signal_button_release_event().connect_notify( sigc::mem_fun(this, &FoldableToolPanel::foldThemAll) ); - enaConn = signal_enabled_toggled().connect( sigc::mem_fun(*this, &FoldableToolPanel::enabled_toggled) ); + exp = Gtk::manage (new MyExpander (useEnabled, titleHBox)); + } else { + exp = Gtk::manage (new MyExpander (useEnabled, UILabel)); + } - exp->add (*content); - exp->show (); + exp->signal_button_release_event().connect_notify( sigc::mem_fun(this, &FoldableToolPanel::foldThemAll) ); + enaConn = signal_enabled_toggled().connect( sigc::mem_fun(*this, &FoldableToolPanel::enabled_toggled) ); + + exp->add (*content); + exp->show (); } -void FoldableToolPanel::foldThemAll (GdkEventButton* event) { - if (event->button == 3) { - if (listener) - (static_cast(listener))->foldAllButOne( parentContainer, this); - else - (static_cast(tmp))->foldAllButOne( parentContainer, this); - } +void FoldableToolPanel::foldThemAll (GdkEventButton* event) +{ + if (event->button == 3) { + if (listener) { + (static_cast(listener))->foldAllButOne( parentContainer, this); + } else { + (static_cast(tmp))->foldAllButOne( parentContainer, this); + } + } } -void FoldableToolPanel::enabled_toggled() { - if (multiImage) { - if (exp->get_inconsistent()) { - exp->set_inconsistent (false); - enaConn.block (true); - exp->setEnabled (false); - enaConn.block (false); - } - else if (lastEnabled) - exp->set_inconsistent (true); +void FoldableToolPanel::enabled_toggled() +{ + if (multiImage) { + if (exp->get_inconsistent()) { + exp->set_inconsistent (false); + enaConn.block (true); + exp->setEnabled (false); + enaConn.block (false); + } else if (lastEnabled) { + exp->set_inconsistent (true); + } - lastEnabled = exp->getEnabled(); - } - enabledChanged(); + lastEnabled = exp->getEnabled(); + } + + enabledChanged(); } -bool FoldableToolPanel::get_inconsistent() { - return exp->get_inconsistent(); +bool FoldableToolPanel::get_inconsistent() +{ + return exp->get_inconsistent(); } -void FoldableToolPanel::set_inconsistent(bool isInconsistent) { - exp->set_inconsistent(isInconsistent); +void FoldableToolPanel::set_inconsistent(bool isInconsistent) +{ + exp->set_inconsistent(isInconsistent); } -bool FoldableToolPanel::getEnabled() { - return exp->getEnabled(); +bool FoldableToolPanel::getEnabled() +{ + return exp->getEnabled(); } // do not emit the enabled_toggled event -void FoldableToolPanel::setEnabled(bool isEnabled) { - enaConn.block (true); - exp->setEnabled(isEnabled); - lastEnabled = isEnabled; - enaConn.block (false); +void FoldableToolPanel::setEnabled(bool isEnabled) +{ + enaConn.block (true); + exp->setEnabled(isEnabled); + lastEnabled = isEnabled; + enaConn.block (false); } -void FoldableToolPanel::setEnabledTooltipMarkup(Glib::ustring tooltipMarkup) { - if (exp) - exp->set_tooltip_markup(tooltipMarkup); +void FoldableToolPanel::setEnabledTooltipMarkup(Glib::ustring tooltipMarkup) +{ + if (exp) { + exp->set_tooltip_markup(tooltipMarkup); + } } -void FoldableToolPanel::setEnabledTooltipText(Glib::ustring tooltipText) { - if (exp) - exp->set_tooltip_text(tooltipText); +void FoldableToolPanel::setEnabledTooltipText(Glib::ustring tooltipText) +{ + if (exp) { + exp->set_tooltip_text(tooltipText); + } } diff --git a/rtgui/toolpanel.h b/rtgui/toolpanel.h index cf2dad030..69a8d18ac 100644 --- a/rtgui/toolpanel.h +++ b/rtgui/toolpanel.h @@ -7,7 +7,7 @@ * 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 @@ -31,111 +31,184 @@ class ToolPanel; class FoldableToolPanel; -class ToolPanelListener { +class ToolPanelListener +{ - public: - - virtual ~ToolPanelListener() {} - virtual void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) {} +public: + + virtual ~ToolPanelListener() {} + virtual void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) {} }; /// @brief This class control the space around the group of tools inside a tab, as well as the space separating each tool. */ -class ToolVBox : public Gtk::VBox { - private: - void updateStyle(); +class ToolVBox : public Gtk::VBox +{ +private: + void updateStyle(); - public: - ToolVBox(); - void on_style_changed (const Glib::RefPtr& style); +public: + ToolVBox(); + void on_style_changed (const Glib::RefPtr& style); }; /// @brief This class control the space around a tool's block of parameter. */ -class ToolParamBlock : public Gtk::VBox { - private: - void updateStyle(); +class ToolParamBlock : public Gtk::VBox +{ +private: + void updateStyle(); - public: - ToolParamBlock(); - void on_style_changed (const Glib::RefPtr& style); +public: + ToolParamBlock(); + void on_style_changed (const Glib::RefPtr& style); }; -class ToolPanel { +class ToolPanel +{ - protected: - Glib::ustring toolName; - ToolPanelListener* listener; - ToolPanelListener* tmp; - bool batchMode; // True if the ToolPanel is used in Batch mode - bool multiImage; // True if more than one image are being edited at the same time (also imply that batchMode=true), false otherwise - bool need100Percent; +protected: + Glib::ustring toolName; + ToolPanelListener* listener; + ToolPanelListener* tmp; + bool batchMode; // True if the ToolPanel is used in Batch mode + bool multiImage; // True if more than one image are being edited at the same time (also imply that batchMode=true), false otherwise + bool need100Percent; - public: +public: - ToolPanel (Glib::ustring toolName="", bool need11=false) : toolName(toolName), listener(NULL), tmp(NULL), batchMode(false), multiImage(false), need100Percent(need11) {} - virtual ~ToolPanel() {} + ToolPanel (Glib::ustring toolName = "", bool need11 = false) : toolName(toolName), listener(NULL), tmp(NULL), batchMode(false), multiImage(false), need100Percent(need11) {} + virtual ~ToolPanel() {} - virtual void setParent (Gtk::Box* parent) {} - virtual Gtk::Box* getParent () { return NULL; } - virtual MyExpander* getExpander () { return NULL; } - virtual void setExpanded (bool expanded) {} - virtual bool getExpanded () { return false; } - void setMultiImage (bool m) { multiImage = m; } - void setListener (ToolPanelListener* tpl) { listener = tpl; } - virtual void setEditProvider (EditDataProvider *provider) {} - virtual void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL) {} - virtual void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL) {} - virtual void trimValues (rtengine::procparams::ProcParams* pp) { return; } - virtual void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL) {} - virtual void autoOpenCurve () {} + virtual void setParent (Gtk::Box* parent) {} + virtual Gtk::Box* getParent () + { + return NULL; + } + virtual MyExpander* getExpander () + { + return NULL; + } + virtual void setExpanded (bool expanded) {} + virtual bool getExpanded () + { + return false; + } + void setMultiImage (bool m) + { + multiImage = m; + } + void setListener (ToolPanelListener* tpl) + { + listener = tpl; + } + virtual void setEditProvider (EditDataProvider *provider) {} + virtual void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL) {} + virtual void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL) {} + virtual void trimValues (rtengine::procparams::ProcParams* pp) + { + return; + } + virtual void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL) {} + virtual void autoOpenCurve () {} - /** @brief Disable the event broadcasting mechanism - * - * @return Return the previous state of the broadcast (true: enabled ; false: disabled) - */ - bool disableListener () { if (tmp==NULL) tmp = listener; bool prevState = listener!=NULL; listener = NULL; return prevState; } + /** @brief Disable the event broadcasting mechanism + * + * @return Return the previous state of the broadcast (true: enabled ; false: disabled) + */ + bool disableListener () + { + if (tmp == NULL) { + tmp = listener; + } - /** @brief Enable the event broadcasting mechanism - */ - void enableListener () { if (tmp!=NULL) listener = tmp; tmp = NULL; } + bool prevState = listener != NULL; + listener = NULL; + return prevState; + } - virtual void setBatchMode (bool batchMode) { this->batchMode = batchMode; } + /** @brief Enable the event broadcasting mechanism + */ + void enableListener () + { + if (tmp != NULL) { + listener = tmp; + } + + tmp = NULL; + } + + virtual void setBatchMode (bool batchMode) + { + this->batchMode = batchMode; + } }; -class FoldableToolPanel : public ToolPanel { +class FoldableToolPanel : public ToolPanel +{ - protected: - Gtk::Box* parentContainer; - MyExpander* exp; - bool lastEnabled; - sigc::connection enaConn; - void foldThemAll (GdkEventButton* event); - void enabled_toggled(); +protected: + Gtk::Box* parentContainer; + MyExpander* exp; + bool lastEnabled; + sigc::connection enaConn; + void foldThemAll (GdkEventButton* event); + void enabled_toggled(); - public: +public: - FoldableToolPanel(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11=false, bool useEnabled=false); + FoldableToolPanel(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11 = false, bool useEnabled = false); - MyExpander* getExpander() { return exp; } - void setExpanded (bool expanded) { if (exp) exp->set_expanded( expanded ); } - bool getExpanded () { if (exp) return exp->get_expanded(); return false; } - void setParent (Gtk::Box* parent) { parentContainer = parent; } - Gtk::Box* getParent () { return parentContainer; } + MyExpander* getExpander() + { + return exp; + } + void setExpanded (bool expanded) + { + if (exp) { + exp->set_expanded( expanded ); + } + } + bool getExpanded () + { + if (exp) { + return exp->get_expanded(); + } - virtual void enabledChanged () {} + return false; + } + void setParent (Gtk::Box* parent) + { + parentContainer = parent; + } + Gtk::Box* getParent () + { + return parentContainer; + } - bool getUseEnabled () { if (exp) return exp->getUseEnabled(); else return true; } - bool getEnabled(); // related to the enabled/disabled state - void setEnabled(bool isActive); // related to the enabled/disabled state - void setEnabledTooltipMarkup(Glib::ustring tooltipMarkup); - void setEnabledTooltipText(Glib::ustring tooltipText); - bool get_inconsistent(); // related to the enabled/disabled state - void set_inconsistent(bool isInconsistent); // related to the enabled/disabled state + virtual void enabledChanged () {} - // Functions that want to receive an enabled/disabled event from this class - // will have to receive it from MyExpander directly, we do not create - // a relaying event - MyExpander::type_signal_enabled_toggled signal_enabled_toggled() { return exp->signal_enabled_toggled(); } + bool getUseEnabled () + { + if (exp) { + return exp->getUseEnabled(); + } else { + return true; + } + } + bool getEnabled(); // related to the enabled/disabled state + void setEnabled(bool isActive); // related to the enabled/disabled state + void setEnabledTooltipMarkup(Glib::ustring tooltipMarkup); + void setEnabledTooltipText(Glib::ustring tooltipText); + bool get_inconsistent(); // related to the enabled/disabled state + void set_inconsistent(bool isInconsistent); // related to the enabled/disabled state + + // Functions that want to receive an enabled/disabled event from this class + // will have to receive it from MyExpander directly, we do not create + // a relaying event + MyExpander::type_signal_enabled_toggled signal_enabled_toggled() + { + return exp->signal_enabled_toggled(); + } }; #endif diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 5a21eed25..c77a9cdb5 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -7,7 +7,7 @@ * 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 @@ -28,7 +28,8 @@ using namespace rtengine::procparams; -ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { +ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) +{ exposurePanel = Gtk::manage (new ToolVBox ()); detailsPanel = Gtk::manage (new ToolVBox ()); @@ -36,7 +37,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { transformPanel = Gtk::manage (new ToolVBox ()); rawPanel = Gtk::manage (new ToolVBox ()); waveletPanel = Gtk::manage (new ToolVBox ()); - + coarse = Gtk::manage (new CoarsePanel ()); toneCurve = Gtk::manage (new ToneCurve ()); shadowshighlights = Gtk::manage (new ShadowsHighlights ()); @@ -96,52 +97,98 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { // Best -> low ISO // Medium -> High ISO - addPanel (colorPanel, whitebalance); toolPanels.push_back (whitebalance); - addPanel (exposurePanel, toneCurve); toolPanels.push_back (toneCurve); - addPanel (colorPanel, vibrance); toolPanels.push_back (vibrance); - addPanel (colorPanel, chmixer); toolPanels.push_back (chmixer); // << TODO: Add "Enabled" - addPanel (colorPanel, blackwhite); toolPanels.push_back (blackwhite); - addPanel (exposurePanel, shadowshighlights); toolPanels.push_back (shadowshighlights); - addPanel (detailsPanel, sharpening); toolPanels.push_back (sharpening); - addPanel (detailsPanel, sharpenEdge); toolPanels.push_back (sharpenEdge); - addPanel (detailsPanel, sharpenMicro); toolPanels.push_back (sharpenMicro); - addPanel (colorPanel, hsvequalizer); toolPanels.push_back (hsvequalizer); // << TODO: Add "Enabled" - addPanel (colorPanel, filmSimulation); toolPanels.push_back (filmSimulation); - addPanel (colorPanel, rgbcurves); toolPanels.push_back (rgbcurves); // << TODO: Add "Enabled" - addPanel (colorPanel, colortoning); toolPanels.push_back (colortoning); - addPanel (exposurePanel, epd); toolPanels.push_back (epd); - addPanel (exposurePanel, pcvignette); toolPanels.push_back (pcvignette); - addPanel (exposurePanel, gradient); toolPanels.push_back (gradient); - addPanel (exposurePanel, lcurve); toolPanels.push_back (lcurve); // << TODO: Add "Enabled" ??? - addPanel (exposurePanel, colorappearance); toolPanels.push_back (colorappearance); - addPanel (detailsPanel, impulsedenoise); toolPanels.push_back (impulsedenoise); - addPanel (detailsPanel, dirpyrdenoise); toolPanels.push_back (dirpyrdenoise); - addPanel (detailsPanel, defringe); toolPanels.push_back (defringe); - addPanel (detailsPanel, dirpyrequalizer); toolPanels.push_back (dirpyrequalizer); - addPanel (waveletPanel, wavelet); toolPanels.push_back (wavelet); - addPanel (transformPanel, crop); toolPanels.push_back (crop); - addPanel (transformPanel, resize); toolPanels.push_back (resize); - addPanel (resize->getPackBox(), prsharpening); toolPanels.push_back (prsharpening); - addPanel (transformPanel, lensgeom); toolPanels.push_back (lensgeom); - addPanel (lensgeom->getPackBox(), rotate); toolPanels.push_back (rotate); - addPanel (lensgeom->getPackBox(), perspective); toolPanels.push_back (perspective); - addPanel (lensgeom->getPackBox(), lensProf); toolPanels.push_back (lensProf); - addPanel (lensgeom->getPackBox(), distortion); toolPanels.push_back (distortion); - addPanel (lensgeom->getPackBox(), cacorrection); toolPanels.push_back (cacorrection); - addPanel (lensgeom->getPackBox(), vignetting); toolPanels.push_back (vignetting); - addPanel (colorPanel, icm); toolPanels.push_back (icm); - addPanel (rawPanel, sensorbayer); toolPanels.push_back (sensorbayer); - addPanel (sensorbayer->getPackBox(), bayerprocess); toolPanels.push_back (bayerprocess); - addPanel (sensorbayer->getPackBox(), bayerrawexposure); toolPanels.push_back (bayerrawexposure); - addPanel (sensorbayer->getPackBox(), bayerpreprocess); toolPanels.push_back (bayerpreprocess); - addPanel (sensorbayer->getPackBox(), rawcacorrection); toolPanels.push_back (rawcacorrection); - addPanel (rawPanel, sensorxtrans); toolPanels.push_back (sensorxtrans); - addPanel (sensorxtrans->getPackBox(), xtransprocess); toolPanels.push_back (xtransprocess); - addPanel (sensorxtrans->getPackBox(), xtransrawexposure); toolPanels.push_back (xtransrawexposure); - addPanel (rawPanel, rawexposure); toolPanels.push_back (rawexposure); - addPanel (rawPanel, preprocess); toolPanels.push_back (preprocess); - addPanel (rawPanel, darkframe); toolPanels.push_back (darkframe); - addPanel (rawPanel, flatfield); toolPanels.push_back (flatfield); + addPanel (colorPanel, whitebalance); + toolPanels.push_back (whitebalance); + addPanel (exposurePanel, toneCurve); + toolPanels.push_back (toneCurve); + addPanel (colorPanel, vibrance); + toolPanels.push_back (vibrance); + addPanel (colorPanel, chmixer); + toolPanels.push_back (chmixer); // << TODO: Add "Enabled" + addPanel (colorPanel, blackwhite); + toolPanels.push_back (blackwhite); + addPanel (exposurePanel, shadowshighlights); + toolPanels.push_back (shadowshighlights); + addPanel (detailsPanel, sharpening); + toolPanels.push_back (sharpening); + addPanel (detailsPanel, sharpenEdge); + toolPanels.push_back (sharpenEdge); + addPanel (detailsPanel, sharpenMicro); + toolPanels.push_back (sharpenMicro); + addPanel (colorPanel, hsvequalizer); + toolPanels.push_back (hsvequalizer); // << TODO: Add "Enabled" + addPanel (colorPanel, filmSimulation); + toolPanels.push_back (filmSimulation); + addPanel (colorPanel, rgbcurves); + toolPanels.push_back (rgbcurves); // << TODO: Add "Enabled" + addPanel (colorPanel, colortoning); + toolPanels.push_back (colortoning); + addPanel (exposurePanel, epd); + toolPanels.push_back (epd); + addPanel (exposurePanel, pcvignette); + toolPanels.push_back (pcvignette); + addPanel (exposurePanel, gradient); + toolPanels.push_back (gradient); + addPanel (exposurePanel, lcurve); + toolPanels.push_back (lcurve); // << TODO: Add "Enabled" ??? + addPanel (exposurePanel, colorappearance); + toolPanels.push_back (colorappearance); + addPanel (detailsPanel, impulsedenoise); + toolPanels.push_back (impulsedenoise); + addPanel (detailsPanel, dirpyrdenoise); + toolPanels.push_back (dirpyrdenoise); + addPanel (detailsPanel, defringe); + toolPanels.push_back (defringe); + addPanel (detailsPanel, dirpyrequalizer); + toolPanels.push_back (dirpyrequalizer); + addPanel (waveletPanel, wavelet); + toolPanels.push_back (wavelet); + addPanel (transformPanel, crop); + toolPanels.push_back (crop); + addPanel (transformPanel, resize); + toolPanels.push_back (resize); + addPanel (resize->getPackBox(), prsharpening); + toolPanels.push_back (prsharpening); + addPanel (transformPanel, lensgeom); + toolPanels.push_back (lensgeom); + addPanel (lensgeom->getPackBox(), rotate); + toolPanels.push_back (rotate); + addPanel (lensgeom->getPackBox(), perspective); + toolPanels.push_back (perspective); + addPanel (lensgeom->getPackBox(), lensProf); + toolPanels.push_back (lensProf); + addPanel (lensgeom->getPackBox(), distortion); + toolPanels.push_back (distortion); + addPanel (lensgeom->getPackBox(), cacorrection); + toolPanels.push_back (cacorrection); + addPanel (lensgeom->getPackBox(), vignetting); + toolPanels.push_back (vignetting); + addPanel (colorPanel, icm); + toolPanels.push_back (icm); + addPanel (rawPanel, sensorbayer); + toolPanels.push_back (sensorbayer); + addPanel (sensorbayer->getPackBox(), bayerprocess); + toolPanels.push_back (bayerprocess); + addPanel (sensorbayer->getPackBox(), bayerrawexposure); + toolPanels.push_back (bayerrawexposure); + addPanel (sensorbayer->getPackBox(), bayerpreprocess); + toolPanels.push_back (bayerpreprocess); + addPanel (sensorbayer->getPackBox(), rawcacorrection); + toolPanels.push_back (rawcacorrection); + addPanel (rawPanel, sensorxtrans); + toolPanels.push_back (sensorxtrans); + addPanel (sensorxtrans->getPackBox(), xtransprocess); + toolPanels.push_back (xtransprocess); + addPanel (sensorxtrans->getPackBox(), xtransrawexposure); + toolPanels.push_back (xtransrawexposure); + addPanel (rawPanel, rawexposure); + toolPanels.push_back (rawexposure); + addPanel (rawPanel, preprocess); + toolPanels.push_back (preprocess); + addPanel (rawPanel, darkframe); + toolPanels.push_back (darkframe); + addPanel (rawPanel, flatfield); + toolPanels.push_back (flatfield); toolPanels.push_back (coarse); toolPanels.push_back (exifpanel); @@ -162,37 +209,37 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { updateVScrollbars (options.hideTPVScrollbar); // load panel endings - for (int i=0; i<6; i++) { - vbPanelEnd[i] = Gtk::manage (new Gtk::VBox ()); - imgPanelEnd[i] = Gtk::manage (new RTImage("PanelEnding.png")); - imgPanelEnd[i]->show (); - vbPanelEnd[i]->pack_start (*imgPanelEnd[i],Gtk::PACK_SHRINK); - vbPanelEnd[i]->show_all(); + for (int i = 0; i < 6; i++) { + vbPanelEnd[i] = Gtk::manage (new Gtk::VBox ()); + imgPanelEnd[i] = Gtk::manage (new RTImage("PanelEnding.png")); + imgPanelEnd[i]->show (); + vbPanelEnd[i]->pack_start (*imgPanelEnd[i], Gtk::PACK_SHRINK); + vbPanelEnd[i]->show_all(); } exposurePanelSW->add (*exposurePanel); - exposurePanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK,0); - exposurePanel->pack_start (*vbPanelEnd[0],Gtk::PACK_SHRINK,4); + exposurePanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + exposurePanel->pack_start (*vbPanelEnd[0], Gtk::PACK_SHRINK, 4); detailsPanelSW->add (*detailsPanel); - detailsPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK,0); - detailsPanel->pack_start (*vbPanelEnd[1],Gtk::PACK_SHRINK,4); + detailsPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + detailsPanel->pack_start (*vbPanelEnd[1], Gtk::PACK_SHRINK, 4); colorPanelSW->add (*colorPanel); - colorPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK,0); - colorPanel->pack_start (*vbPanelEnd[2],Gtk::PACK_SHRINK,4); + colorPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + colorPanel->pack_start (*vbPanelEnd[2], Gtk::PACK_SHRINK, 4); waveletPanelSW->add (*waveletPanel); - waveletPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK,0); - waveletPanel->pack_start (*vbPanelEnd[5],Gtk::PACK_SHRINK,0); + waveletPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + waveletPanel->pack_start (*vbPanelEnd[5], Gtk::PACK_SHRINK, 0); transformPanelSW->add (*transformPanel); - transformPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK,0); - transformPanel->pack_start (*vbPanelEnd[3],Gtk::PACK_SHRINK,4); + transformPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + transformPanel->pack_start (*vbPanelEnd[3], Gtk::PACK_SHRINK, 4); rawPanelSW->add (*rawPanel); - rawPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK,0); - rawPanel->pack_start (*vbPanelEnd[4],Gtk::PACK_SHRINK,0); + rawPanel->pack_start (*Gtk::manage(new Gtk::HSeparator), Gtk::PACK_SHRINK, 0); + rawPanel->pack_start (*vbPanelEnd[4], Gtk::PACK_SHRINK, 0); @@ -206,21 +253,22 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { toiR = Gtk::manage (new TextOrIcon ("raw.png" , M("MAIN_TAB_RAW") , M("MAIN_TAB_RAW_TOOLTIP") , type)); toiM = Gtk::manage (new TextOrIcon ("meta.png" , M("MAIN_TAB_METADATA") , M("MAIN_TAB_METADATA_TOOLTIP") , type)); - toolPanelNotebook->append_page (*exposurePanelSW, *toiE); - toolPanelNotebook->append_page (*detailsPanelSW, *toiD); - toolPanelNotebook->append_page (*colorPanelSW, *toiC); - toolPanelNotebook->append_page (*waveletPanelSW, *toiW); - toolPanelNotebook->append_page (*transformPanelSW, *toiT); - toolPanelNotebook->append_page (*rawPanelSW, *toiR); - toolPanelNotebook->append_page (*metadataPanel, *toiM); + toolPanelNotebook->append_page (*exposurePanelSW, *toiE); + toolPanelNotebook->append_page (*detailsPanelSW, *toiD); + toolPanelNotebook->append_page (*colorPanelSW, *toiC); + toolPanelNotebook->append_page (*waveletPanelSW, *toiW); + toolPanelNotebook->append_page (*transformPanelSW, *toiT); + toolPanelNotebook->append_page (*rawPanelSW, *toiR); + toolPanelNotebook->append_page (*metadataPanel, *toiM); toolPanelNotebook->set_current_page (0); toolPanelNotebook->set_scrollable (); toolPanelNotebook->show_all (); - for (size_t i=0; isetListener (this); + } whitebalance->setWBProvider (this); whitebalance->setSpotWBListener (this); @@ -236,7 +284,8 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) { toolBar->setToolBarListener(this); } -void ToolPanelCoordinator::addPanel (Gtk::Box* where, FoldableToolPanel* panel) { +void ToolPanelCoordinator::addPanel (Gtk::Box* where, FoldableToolPanel* panel) +{ // no more separator! /*if (where->children().size()) { @@ -251,7 +300,8 @@ void ToolPanelCoordinator::addPanel (Gtk::Box* where, FoldableToolPanel* panel) where->pack_start(*panel->getExpander(), false, false); } -ToolPanelCoordinator::~ToolPanelCoordinator () { +ToolPanelCoordinator::~ToolPanelCoordinator () +{ closeImage (); @@ -259,41 +309,43 @@ ToolPanelCoordinator::~ToolPanelCoordinator () { delete toolBar; } -void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) { +void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) +{ - if (!ipc) return; + if (!ipc) { + return; + } - int changeFlags=refreshmap[(int)event]; + int changeFlags = refreshmap[(int)event]; ProcParams* params = ipc->beginUpdateParams (); - for (size_t i=0; iwrite (params); + } // Compensate rotation on flip - if (event==rtengine::EvCTHFlip || event==rtengine::EvCTVFlip) { - if (fabs(params->rotate.degree)>0.001) { - params->rotate.degree *= -1; + if (event == rtengine::EvCTHFlip || event == rtengine::EvCTVFlip) { + if (fabs(params->rotate.degree) > 0.001) { + params->rotate.degree *= -1; changeFlags |= refreshmap[(int)rtengine::EvROTDegree]; rotate->read (params); } } // some transformations make the crop change for convenience - if (event==rtengine::EvCTHFlip) { + if (event == rtengine::EvCTHFlip) { crop->hFlipCrop (); crop->write (params); - } - else if (event==rtengine::EvCTVFlip) { + } else if (event == rtengine::EvCTVFlip) { crop->vFlipCrop (); crop->write (params); - } - else if (event==rtengine::EvCTRotate) { + } else if (event == rtengine::EvCTRotate) { crop->rotateCrop (params->coarse.rotate, params->coarse.hflip, params->coarse.vflip); crop->write (params); resize->update (params->crop.enabled, params->crop.w, params->crop.h, ipc->getFullWidth(), ipc->getFullHeight()); resize->write (params); - } - else if (event==rtengine::EvCrop) { + } else if (event == rtengine::EvCrop) { resize->update (params->crop.enabled, params->crop.w, params->crop.h); resize->write (params); } @@ -302,15 +354,20 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib:: hasChanged = true; - for (size_t i=0; iprocParamsChanged (params, event, descr); + } } -void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited) { +void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited) +{ - int fw, fh, tr; + int fw, fh, tr; + + if (!ipc) { + return; + } - if (!ipc) return; ProcParams *params = ipc->beginUpdateParams (); ProcParams *mergedParams = new ProcParams(); @@ -327,11 +384,13 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi nparams->applyTo(mergedParams); // Derive the effective changes, if it's a profile change, to prevent slow RAW rerendering if not necessary - bool filterRawRefresh=false; - if (event!=rtengine::EvPhotoLoaded) { + bool filterRawRefresh = false; + + if (event != rtengine::EvPhotoLoaded) { ParamsEdited pe(true); std::vector lParams(2); - lParams[0]=*params; lParams[1]=*mergedParams; + lParams[0] = *params; + lParams[1] = *mergedParams; pe.initFrom (lParams); filterRawRefresh = pe.raw.isUnchanged() && pe.lensProf.isUnchanged(); @@ -341,9 +400,18 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi delete mergedParams; tr = TR_NONE; - if (params->coarse.rotate==90) tr |= TR_R90; - if (params->coarse.rotate==180) tr |= TR_R180; - if (params->coarse.rotate==270) tr |= TR_R270; + + if (params->coarse.rotate == 90) { + tr |= TR_R90; + } + + if (params->coarse.rotate == 180) { + tr |= TR_R180; + } + + if (params->coarse.rotate == 270) { + tr |= TR_R270; + } // trimming overflowing cropped area rtengine::ImageSource *ii = (rtengine::ImageSource*)ipc->getInitialImage(); @@ -351,44 +419,52 @@ void ToolPanelCoordinator::profileChange (const PartialProfile *nparams, rtengi crop->trim(params, fw, fh); // updating the GUI with updated values - for (unsigned int i=0; iread (params); - if (event==rtengine::EvPhotoLoaded || event==rtengine::EvProfileChanged) + + if (event == rtengine::EvPhotoLoaded || event == rtengine::EvProfileChanged) { toolPanels[i]->autoOpenCurve(); + } } // start the IPC processing if (filterRawRefresh) { ipc->endUpdateParams ( refreshmap[(int)event] & ALLNORAW ); - } else - ipc->endUpdateParams (event); + } else { + ipc->endUpdateParams (event); + } hasChanged = event != rtengine::EvProfileChangeNotification; - for (size_t i=0; iprocParamsChanged (params, event, descr); + } } -void ToolPanelCoordinator::setDefaults (ProcParams* defparams) { +void ToolPanelCoordinator::setDefaults (ProcParams* defparams) +{ if (defparams) - for (size_t i=0; isetDefaults (defparams); + } } -CropGUIListener* ToolPanelCoordinator::getCropGUIListener () { +CropGUIListener* ToolPanelCoordinator::getCropGUIListener () +{ return crop; } -void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool raw) { +void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool raw) +{ ipc = ipc_; toneCurve->disableListener (); toneCurve->enableAll (); toneCurve->enableListener (); - const rtengine::ImageMetaData* pMetaData=ipc->getInitialImage()->getMetaData(); + const rtengine::ImageMetaData* pMetaData = ipc->getInitialImage()->getMetaData(); exifpanel->setImageData (pMetaData); iptcpanel->setImageData (pMetaData); @@ -403,17 +479,19 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setSizeListener (crop); ipc->setSizeListener (resize); } + flatfield->setShortcutPath(Glib::path_get_dirname(ipc->getInitialImage()->getFileName())); - icm->setRawMeta (raw, (const rtengine::ImageData*)pMetaData); - lensProf->setRawMeta (raw, pMetaData); + icm->setRawMeta (raw, (const rtengine::ImageData*)pMetaData); + lensProf->setRawMeta (raw, pMetaData); toneCurve->setRaw (raw); hasChanged = true; } -void ToolPanelCoordinator::closeImage () { +void ToolPanelCoordinator::closeImage () +{ if (ipc) { ipc->stopProcessing (); @@ -421,81 +499,102 @@ void ToolPanelCoordinator::closeImage () { } } -void ToolPanelCoordinator::closeAllTools() { +void ToolPanelCoordinator::closeAllTools() +{ - for (size_t i=0; iset_expanded (false); + } } -void ToolPanelCoordinator::openAllTools() { +void ToolPanelCoordinator::openAllTools() +{ - for (size_t i=0; iset_expanded (true); + } } -void ToolPanelCoordinator::updateToolState() { +void ToolPanelCoordinator::updateToolState() +{ - for (size_t i=0; iset_expanded (options.tpOpen.at(i)); + } - if(options.tpOpen.size()>expList.size()) { + if(options.tpOpen.size() > expList.size()) { size_t sizeWavelet = options.tpOpen.size() - expList.size(); std::vector temp; - for (size_t i=0; iupdateToolState(temp); wavelet->setExpanded(true); } } -void ToolPanelCoordinator::readOptions () { +void ToolPanelCoordinator::readOptions () +{ crop->readOptions (); } -void ToolPanelCoordinator::writeOptions () { +void ToolPanelCoordinator::writeOptions () +{ - crop->writeOptions (); + crop->writeOptions (); options.tpOpen.clear (); - for (size_t i=0; iget_expanded ()); + } + wavelet->writeOptions(options.tpOpen); } -void ToolPanelCoordinator::cropSelectionReady () { +void ToolPanelCoordinator::cropSelectionReady () +{ - toolBar->setTool (TMHand); + toolBar->setTool (TMHand); - if (!ipc) - return; -} - -void ToolPanelCoordinator::rotateSelectionReady (double rotate_deg, Thumbnail* thm) { - - toolBar->setTool (TMHand); - - if (!ipc) - return; - - if (rotate_deg!=0.0) - rotate->straighten (rotate_deg); -} - -void ToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) { - - if (!ipc) + if (!ipc) { return; + } +} + +void ToolPanelCoordinator::rotateSelectionReady (double rotate_deg, Thumbnail* thm) +{ + + toolBar->setTool (TMHand); + + if (!ipc) { + return; + } + + if (rotate_deg != 0.0) { + rotate->straighten (rotate_deg); + } +} + +void ToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) +{ + + if (!ipc) { + return; + } // toolBar->setTool (TOOL_HAND); - int rect=whitebalance->getSize (); - int ww= ipc->getFullWidth(); - int hh= ipc->getFullHeight(); - - if (x-rect>0 && y-rect>0 && x+rectgetSize (); + int ww = ipc->getFullWidth(); + int hh = ipc->getFullHeight(); + + if (x - rect > 0 && y - rect > 0 && x + rect < ww && y + rect < hh) { double temp; double green; ipc->getSpotWB (x, y, rect, temp, green); @@ -506,11 +605,13 @@ void ToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) { -void ToolPanelCoordinator::autoCropRequested () { +void ToolPanelCoordinator::autoCropRequested () +{ - if (!ipc) + if (!ipc) { return; - + } + int x1, y1, x2, y2, w, h; ipc->getAutoCrop (crop->getRatio(), x1, y1, w, h); x2 = x1 + w - 1; @@ -522,153 +623,186 @@ void ToolPanelCoordinator::autoCropRequested () { rtengine::RawImage* ToolPanelCoordinator::getDF() { - if (!ipc) + if (!ipc) { return NULL; - const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); - if(imd){ - int iso = imd->getISOSpeed(); - double shutter = imd->getShutterSpeed(); - std::string maker( imd->getMake() ); - std::string model( imd->getModel() ); - time_t timestamp = imd->getDateTimeAsTS(); - - return rtengine::dfm.searchDarkFrame( maker,model,iso,shutter, timestamp); } + + const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); + + if(imd) { + int iso = imd->getISOSpeed(); + double shutter = imd->getShutterSpeed(); + std::string maker( imd->getMake() ); + std::string model( imd->getModel() ); + time_t timestamp = imd->getDateTimeAsTS(); + + return rtengine::dfm.searchDarkFrame( maker, model, iso, shutter, timestamp); + } + return NULL; } rtengine::RawImage* ToolPanelCoordinator::getFF() { - if (!ipc) + if (!ipc) { return NULL; - const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); - if(imd){ - // int iso = imd->getISOSpeed(); temporarilly removed because unused - // double shutter = imd->getShutterSpeed(); temporarilly removed because unused - double aperture = imd->getFNumber(); - double focallength = imd->getFocalLen(); - std::string maker( imd->getMake() ); - std::string model( imd->getModel() ); - std::string lens( imd->getLens() ); - time_t timestamp = imd->getDateTimeAsTS(); - - return rtengine::ffm.searchFlatField( maker,model,lens,focallength,aperture,timestamp); } + + const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); + + if(imd) { + // int iso = imd->getISOSpeed(); temporarilly removed because unused + // double shutter = imd->getShutterSpeed(); temporarilly removed because unused + double aperture = imd->getFNumber(); + double focallength = imd->getFocalLen(); + std::string maker( imd->getMake() ); + std::string model( imd->getModel() ); + std::string lens( imd->getLens() ); + time_t timestamp = imd->getDateTimeAsTS(); + + return rtengine::ffm.searchFlatField( maker, model, lens, focallength, aperture, timestamp); + } + return NULL; } Glib::ustring ToolPanelCoordinator::GetCurrentImageFilePath() { - if (!ipc){ + if (!ipc) { return ""; } + return ipc->getInitialImage()->getFileName(); } -void ToolPanelCoordinator::straightenRequested () { +void ToolPanelCoordinator::straightenRequested () +{ - if (!ipc) + if (!ipc) { return; + } toolBar->setTool (TMStraighten); } -double ToolPanelCoordinator::autoDistorRequested () { - if (!ipc) +double ToolPanelCoordinator::autoDistorRequested () +{ + if (!ipc) { return 0.0; + } + return rtengine::ImProcFunctions::getAutoDistor (ipc->getInitialImage()->getFileName(), 400); } -void ToolPanelCoordinator::spotWBRequested (int size) { +void ToolPanelCoordinator::spotWBRequested (int size) +{ - if (!ipc) + if (!ipc) { return; + } toolBar->setTool (TMSpotWB); } -void ToolPanelCoordinator::cropSelectRequested () { +void ToolPanelCoordinator::cropSelectRequested () +{ - if (!ipc) + if (!ipc) { return; + } toolBar->setTool (TMCropSelect); } -void ToolPanelCoordinator::saveInputICCReference (Glib::ustring fname, bool apply_wb) { +void ToolPanelCoordinator::saveInputICCReference (Glib::ustring fname, bool apply_wb) +{ - if (ipc) + if (ipc) { ipc->saveInputICCReference (fname, apply_wb); + } } -int ToolPanelCoordinator::getSpotWBRectSize () { +int ToolPanelCoordinator::getSpotWBRectSize () +{ return whitebalance->getSize (); } -void ToolPanelCoordinator::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) { - colorappearance->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM,histRed, histGreen, histBlue, histLuma); - toneCurve->updateCurveBackgroundHistogram (histToneCurve, histLCurve,histCCurve,/* histCLurve, histLLCurve,*/ histLCAM, histCCAM,histRed, histGreen, histBlue, histLuma); - lcurve->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM,histRed, histGreen, histBlue, histLuma); - rgbcurves->updateCurveBackgroundHistogram(histToneCurve, histLCurve, histCCurve,/* histCLurve, histLLCurve, */histLCAM, histCCAM,histRed,histGreen, histBlue, histLuma); +void ToolPanelCoordinator::updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma) +{ + colorappearance->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma); + toneCurve->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve,/* histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma); + lcurve->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma); + rgbcurves->updateCurveBackgroundHistogram(histToneCurve, histLCurve, histCCurve,/* histCLurve, histLLCurve, */histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma); } -void ToolPanelCoordinator::foldAllButOne (Gtk::Box* parent, FoldableToolPanel* openedSection) { +void ToolPanelCoordinator::foldAllButOne (Gtk::Box* parent, FoldableToolPanel* openedSection) +{ - for (size_t i=0; igetParent() != NULL) { ToolPanel* currentTP = toolPanels[i]; + if (currentTP->getParent() == parent) { // Section in the same tab, we unfold it if it's not the one that has been clicked if (currentTP != openedSection) { currentTP->setExpanded(false); - } - else { - if (!currentTP->getExpanded()) + } else { + if (!currentTP->getExpanded()) { currentTP->setExpanded(true); + } } } } } } -bool ToolPanelCoordinator::handleShortcutKey (GdkEventKey* event) { +bool ToolPanelCoordinator::handleShortcutKey (GdkEventKey* event) +{ //bool ctrl = event->state & GDK_CONTROL_MASK; temporarily removed because unused //bool shift = event->state & GDK_SHIFT_MASK; temporarily removed because unused bool alt = event->state & GDK_MOD1_MASK; - if (alt){ - switch(event->keyval) { - case GDK_e: - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*exposurePanelSW)); - return true; - case GDK_d: - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*detailsPanelSW)); - return true; - case GDK_c: - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*colorPanelSW)); - return true; - case GDK_t: - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*transformPanelSW)); - return true; - case GDK_r: - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*rawPanelSW)); - return true; - case GDK_w: - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*waveletPanelSW)); - return true; - case GDK_m: - if (metadataPanel){ - toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*metadataPanel)); - return true; - } - } + if (alt) { + switch(event->keyval) { + case GDK_e: + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*exposurePanelSW)); + return true; + + case GDK_d: + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*detailsPanelSW)); + return true; + + case GDK_c: + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*colorPanelSW)); + return true; + + case GDK_t: + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*transformPanelSW)); + return true; + + case GDK_r: + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*rawPanelSW)); + return true; + + case GDK_w: + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*waveletPanelSW)); + return true; + + case GDK_m: + if (metadataPanel) { + toolPanelNotebook->set_current_page (toolPanelNotebook->page_num(*metadataPanel)); + return true; + } + } } + return false; } -void ToolPanelCoordinator::updateVScrollbars (bool hide) { +void ToolPanelCoordinator::updateVScrollbars (bool hide) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected Gtk::PolicyType policy = hide ? Gtk::POLICY_NEVER : Gtk::POLICY_AUTOMATIC; exposurePanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); @@ -679,7 +813,8 @@ void ToolPanelCoordinator::updateVScrollbars (bool hide) { waveletPanelSW->set_policy (Gtk::POLICY_AUTOMATIC, policy); } -void ToolPanelCoordinator::updateTabsHeader (bool useIcons) { +void ToolPanelCoordinator::updateTabsHeader (bool useIcons) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected TOITypes type = useIcons ? TOI_ICON : TOI_TEXT; @@ -688,52 +823,66 @@ void ToolPanelCoordinator::updateTabsHeader (bool useIcons) { toiC->switchTo(type); toiT->switchTo(type); toiR->switchTo(type); - if (toiM) + + if (toiM) { toiM->switchTo(type); + } } -void ToolPanelCoordinator::updateTPVScrollbar (bool hide) { - updateVScrollbars (hide); +void ToolPanelCoordinator::updateTPVScrollbar (bool hide) +{ + updateVScrollbars (hide); } -void ToolPanelCoordinator::updateTabsUsesIcons (bool useIcons) { - updateTabsHeader (useIcons); +void ToolPanelCoordinator::updateTabsUsesIcons (bool useIcons) +{ + updateTabsHeader (useIcons); } -void ToolPanelCoordinator::toolSelected (ToolMode tool) { +void ToolPanelCoordinator::toolSelected (ToolMode tool) +{ GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected - switch (tool) { - case TMCropSelect: - crop->setExpanded(true); - toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*transformPanelSW)); - break; - case TMSpotWB: - whitebalance->setExpanded(true); - toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*colorPanelSW)); - break; - case TMStraighten: - lensgeom->setExpanded(true); - rotate->setExpanded(true); - toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*transformPanelSW)); - break; - default: - break; - } + + switch (tool) { + case TMCropSelect: + crop->setExpanded(true); + toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*transformPanelSW)); + break; + + case TMSpotWB: + whitebalance->setExpanded(true); + toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*colorPanelSW)); + break; + + case TMStraighten: + lensgeom->setExpanded(true); + rotate->setExpanded(true); + toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(*transformPanelSW)); + break; + + default: + break; + } } -void ToolPanelCoordinator::editModeSwitchedOff () { - if (editDataProvider) { - editDataProvider->switchOffEditMode(); - } +void ToolPanelCoordinator::editModeSwitchedOff () +{ + if (editDataProvider) { + editDataProvider->switchOffEditMode(); + } } -void ToolPanelCoordinator::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) { +void ToolPanelCoordinator::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) +{ flatfield->setShortcutPath(dirname); } -void ToolPanelCoordinator::setEditProvider(EditDataProvider *provider) { - editDataProvider = provider; - for (size_t i=0; isetEditProvider(provider); +void ToolPanelCoordinator::setEditProvider(EditDataProvider *provider) +{ + editDataProvider = provider; + + for (size_t i = 0; i < toolPanels.size(); i++) { + toolPanels.at(i)->setEditProvider(provider); + } } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 2ada0556d..8362a3f37 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -7,7 +7,7 @@ * 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 @@ -82,214 +82,239 @@ class ImageEditorCoordinator; -class ToolPanelCoordinator : public ToolPanelListener, - public ToolBarListener, - public ProfileChangeListener, - public WBProvider, - public DFProvider, - public FFProvider, - public LensGeomListener, - public SpotWBListener, - public CropPanelListener, - public ICMPanelListener, - public DirSelectionListener, - public ImageAreaToolListener { +class ToolPanelCoordinator : public ToolPanelListener, + public ToolBarListener, + public ProfileChangeListener, + public WBProvider, + public DFProvider, + public FFProvider, + public LensGeomListener, + public SpotWBListener, + public CropPanelListener, + public ICMPanelListener, + public DirSelectionListener, + public ImageAreaToolListener +{ - protected: +protected: - WhiteBalance* whitebalance; - Vignetting* vignetting; - Gradient* gradient; - PCVignette* pcvignette; - LensGeometry* lensgeom; - LensProfilePanel* lensProf; - Rotate* rotate; - Distortion* distortion; - PerspCorrection* perspective; - CACorrection* cacorrection; - ColorAppearance* colorappearance; - Vibrance* vibrance; - ChMixer* chmixer; - BlackWhite* blackwhite; - Resize* resize; - PrSharpening* prsharpening; - ICMPanel* icm; - Crop* crop; - ToneCurve* toneCurve; - ShadowsHighlights* shadowshighlights; - Defringe* defringe; - ImpulseDenoise* impulsedenoise; - DirPyrDenoise* dirpyrdenoise; - EdgePreservingDecompositionUI *epd; - Sharpening* sharpening; - SharpenEdge* sharpenEdge; - SharpenMicro* sharpenMicro; - LCurve* lcurve; - RGBCurves* rgbcurves; - ColorToning* colortoning; - Wavelet * wavelet; - DirPyrEqualizer* dirpyrequalizer; - HSVEqualizer* hsvequalizer; - FilmSimulation *filmSimulation; - SensorBayer * sensorbayer; - SensorXTrans * sensorxtrans; - BayerProcess* bayerprocess; - XTransProcess* xtransprocess; - BayerPreProcess* bayerpreprocess; - PreProcess* preprocess; - DarkFrame* darkframe; - FlatField* flatfield; - RAWCACorr* rawcacorrection; - RAWExposure* rawexposure; - BayerRAWExposure* bayerrawexposure; - XTransRAWExposure* xtransrawexposure; + WhiteBalance* whitebalance; + Vignetting* vignetting; + Gradient* gradient; + PCVignette* pcvignette; + LensGeometry* lensgeom; + LensProfilePanel* lensProf; + Rotate* rotate; + Distortion* distortion; + PerspCorrection* perspective; + CACorrection* cacorrection; + ColorAppearance* colorappearance; + Vibrance* vibrance; + ChMixer* chmixer; + BlackWhite* blackwhite; + Resize* resize; + PrSharpening* prsharpening; + ICMPanel* icm; + Crop* crop; + ToneCurve* toneCurve; + ShadowsHighlights* shadowshighlights; + Defringe* defringe; + ImpulseDenoise* impulsedenoise; + DirPyrDenoise* dirpyrdenoise; + EdgePreservingDecompositionUI *epd; + Sharpening* sharpening; + SharpenEdge* sharpenEdge; + SharpenMicro* sharpenMicro; + LCurve* lcurve; + RGBCurves* rgbcurves; + ColorToning* colortoning; + Wavelet * wavelet; + DirPyrEqualizer* dirpyrequalizer; + HSVEqualizer* hsvequalizer; + FilmSimulation *filmSimulation; + SensorBayer * sensorbayer; + SensorXTrans * sensorxtrans; + BayerProcess* bayerprocess; + XTransProcess* xtransprocess; + BayerPreProcess* bayerpreprocess; + PreProcess* preprocess; + DarkFrame* darkframe; + FlatField* flatfield; + RAWCACorr* rawcacorrection; + RAWExposure* rawexposure; + BayerRAWExposure* bayerrawexposure; + XTransRAWExposure* xtransrawexposure; - std::vector paramcListeners; + std::vector paramcListeners; - rtengine::StagedImageProcessor* ipc; + rtengine::StagedImageProcessor* ipc; - std::vector toolPanels; - ToolVBox* exposurePanel; - ToolVBox* detailsPanel; - ToolVBox* colorPanel; - ToolVBox* transformPanel; - ToolVBox* rawPanel; - ToolVBox* waveletPanel; - Gtk::Notebook* metadataPanel; - ExifPanel* exifpanel; - IPTCPanel* iptcpanel; - ToolBar* toolBar; + std::vector toolPanels; + ToolVBox* exposurePanel; + ToolVBox* detailsPanel; + ToolVBox* colorPanel; + ToolVBox* transformPanel; + ToolVBox* rawPanel; + ToolVBox* waveletPanel; + Gtk::Notebook* metadataPanel; + ExifPanel* exifpanel; + IPTCPanel* iptcpanel; + ToolBar* toolBar; - TextOrIcon* toiE; - TextOrIcon* toiD; - TextOrIcon* toiC; - TextOrIcon* toiT; - TextOrIcon* toiR; - TextOrIcon* toiM; - TextOrIcon* toiW; + TextOrIcon* toiE; + TextOrIcon* toiD; + TextOrIcon* toiC; + TextOrIcon* toiT; + TextOrIcon* toiR; + TextOrIcon* toiM; + TextOrIcon* toiW; - Gtk::Label* labelE; - Gtk::Label* labelD; - Gtk::Label* labelC; - Gtk::Label* labelT; - Gtk::Label* labelR; - Gtk::Label* labelM; + Gtk::Label* labelE; + Gtk::Label* labelD; + Gtk::Label* labelC; + Gtk::Label* labelT; + Gtk::Label* labelR; + Gtk::Label* labelM; - Gtk::Image* imgIconE; - Gtk::Image* imgIconD; - Gtk::Image* imgIconC; - Gtk::Image* imgIconT; - Gtk::Image* imgIconR; - Gtk::Image* imgIconM; - Gtk::Image* imgPanelEnd[6]; - Gtk::VBox* vbPanelEnd[6]; + Gtk::Image* imgIconE; + Gtk::Image* imgIconD; + Gtk::Image* imgIconC; + Gtk::Image* imgIconT; + Gtk::Image* imgIconR; + Gtk::Image* imgIconM; + Gtk::Image* imgPanelEnd[6]; + Gtk::VBox* vbPanelEnd[6]; - Gtk::ScrolledWindow* exposurePanelSW; - Gtk::ScrolledWindow* detailsPanelSW; - Gtk::ScrolledWindow* colorPanelSW; - Gtk::ScrolledWindow* transformPanelSW; - Gtk::ScrolledWindow* rawPanelSW; - Gtk::ScrolledWindow* waveletPanelSW; + Gtk::ScrolledWindow* exposurePanelSW; + Gtk::ScrolledWindow* detailsPanelSW; + Gtk::ScrolledWindow* colorPanelSW; + Gtk::ScrolledWindow* transformPanelSW; + Gtk::ScrolledWindow* rawPanelSW; + Gtk::ScrolledWindow* waveletPanelSW; - std::vector expList; - - bool hasChanged; + std::vector expList; - void addPanel (Gtk::Box* where, FoldableToolPanel* panel); - void foldThemAll (GdkEventButton* event); - void updateVScrollbars (bool hide); - void updateTabsHeader (bool useIcons); + bool hasChanged; - private: + void addPanel (Gtk::Box* where, FoldableToolPanel* panel); + void foldThemAll (GdkEventButton* event); + void updateVScrollbars (bool hide); + void updateTabsHeader (bool useIcons); - EditDataProvider *editDataProvider; +private: - public: - - CoarsePanel* coarse; - Gtk::Notebook* toolPanelNotebook; + EditDataProvider *editDataProvider; - ToolPanelCoordinator (); - virtual ~ToolPanelCoordinator (); +public: - bool getChangedState () { return hasChanged; } - void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve,LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma); - void foldAllButOne (Gtk::Box* parent, FoldableToolPanel* openedSection); + CoarsePanel* coarse; + Gtk::Notebook* toolPanelNotebook; - // multiple listeners can be added that are notified on changes (typical: profile panel and the history) - void addPParamsChangeListener (PParamsChangeListener* pp) { paramcListeners.push_back (pp); } - - // toolpanellistener interface - void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr); + ToolPanelCoordinator (); + virtual ~ToolPanelCoordinator (); - // profilechangelistener interface - void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited=NULL); - void setDefaults (rtengine::procparams::ProcParams* defparams); + bool getChangedState () + { + return hasChanged; + } + void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma); + void foldAllButOne (Gtk::Box* parent, FoldableToolPanel* openedSection); - // DirSelectionListener interface - void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile=""); + // multiple listeners can be added that are notified on changes (typical: profile panel and the history) + void addPParamsChangeListener (PParamsChangeListener* pp) + { + paramcListeners.push_back (pp); + } - // to support the GUI: - CropGUIListener* getCropGUIListener (); // through the CropGUIListener the editor area can notify the "crop" ToolPanel when the crop selection changes - - // init the toolpanelcoordinator with an image & close it - void initImage (rtengine::StagedImageProcessor* ipc_, bool israw); - void closeImage (); + // toolpanellistener interface + void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr); - // update the "expanded" state of the Tools - void updateToolState (); - void openAllTools (); - void closeAllTools (); - // read/write the "expanded" state of the expanders & read/write the crop panel settings (ratio, guide type, etc.) - void readOptions (); - void writeOptions (); + // profilechangelistener interface + void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited = NULL); + void setDefaults (rtengine::procparams::ProcParams* defparams); - // wbprovider interface - void getAutoWB (double& temp, double& green, double equal) { - if (ipc) - ipc->getAutoWB (temp, green, equal); + // DirSelectionListener interface + void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile = ""); + + // to support the GUI: + CropGUIListener* getCropGUIListener (); // through the CropGUIListener the editor area can notify the "crop" ToolPanel when the crop selection changes + + // init the toolpanelcoordinator with an image & close it + void initImage (rtengine::StagedImageProcessor* ipc_, bool israw); + void closeImage (); + + // update the "expanded" state of the Tools + void updateToolState (); + void openAllTools (); + void closeAllTools (); + // read/write the "expanded" state of the expanders & read/write the crop panel settings (ratio, guide type, etc.) + void readOptions (); + void writeOptions (); + + // wbprovider interface + void getAutoWB (double& temp, double& green, double equal) + { + if (ipc) { + ipc->getAutoWB (temp, green, equal); } - void getCamWB (double& temp, double& green) { if (ipc) ipc->getCamWB (temp, green); } + } + void getCamWB (double& temp, double& green) + { + if (ipc) { + ipc->getCamWB (temp, green); + } + } - //DFProvider interface - rtengine::RawImage* getDF(); + //DFProvider interface + rtengine::RawImage* getDF(); - //FFProvider interface - rtengine::RawImage* getFF(); - Glib::ustring GetCurrentImageFilePath(); + //FFProvider interface + rtengine::RawImage* getFF(); + Glib::ustring GetCurrentImageFilePath(); - // rotatelistener interface - void straightenRequested (); - void autoCropRequested (); - double autoDistorRequested (); + // rotatelistener interface + void straightenRequested (); + void autoCropRequested (); + double autoDistorRequested (); - // spotwblistener interface - void spotWBRequested (int size); + // spotwblistener interface + void spotWBRequested (int size); - // croppanellistener interface - void cropSelectRequested (); - - // icmpanellistener interface - void saveInputICCReference (Glib::ustring fname, bool apply_wb); - - // imageareatoollistener interface - void spotWBselected (int x, int y, Thumbnail* thm=NULL); - void cropSelectionReady (); - void rotateSelectionReady (double rotate_deg, Thumbnail* thm=NULL); - ToolBar* getToolBar () { return toolBar; } - void removeWbTool() { if (toolBar) toolBar->removeWbTool(); } - int getSpotWBRectSize (); - CropGUIListener* startCropEditing (Thumbnail* thm=NULL) { return crop; } + // croppanellistener interface + void cropSelectRequested (); - void updateTPVScrollbar (bool hide); - void updateTabsUsesIcons (bool useIcons); - bool handleShortcutKey (GdkEventKey* event); + // icmpanellistener interface + void saveInputICCReference (Glib::ustring fname, bool apply_wb); - // ToolBarListener interface - void toolSelected (ToolMode tool); - void editModeSwitchedOff (); + // imageareatoollistener interface + void spotWBselected (int x, int y, Thumbnail* thm = NULL); + void cropSelectionReady (); + void rotateSelectionReady (double rotate_deg, Thumbnail* thm = NULL); + ToolBar* getToolBar () + { + return toolBar; + } + void removeWbTool() + { + if (toolBar) { + toolBar->removeWbTool(); + } + } + int getSpotWBRectSize (); + CropGUIListener* startCropEditing (Thumbnail* thm = NULL) + { + return crop; + } - void setEditProvider(EditDataProvider *provider); + void updateTPVScrollbar (bool hide); + void updateTabsUsesIcons (bool useIcons); + bool handleShortcutKey (GdkEventKey* event); + + // ToolBarListener interface + void toolSelected (ToolMode tool); + void editModeSwitchedOff (); + + void setEditProvider(EditDataProvider *provider); }; #endif diff --git a/rtgui/vibrance.cc b/rtgui/vibrance.cc index 4d67d5aeb..702911edd 100644 --- a/rtgui/vibrance.cc +++ b/rtgui/vibrance.cc @@ -23,343 +23,373 @@ using namespace rtengine; using namespace rtengine::procparams; -Vibrance::Vibrance () : FoldableToolPanel(this, "vibrance", M("TP_VIBRANCE_LABEL"), false, true) { +Vibrance::Vibrance () : FoldableToolPanel(this, "vibrance", M("TP_VIBRANCE_LABEL"), false, true) +{ - std::vector milestones; - float R, G, B; - // -0.1 rad < Hue < 1.6 rad - Color::hsv2rgb01(0.92f, 0.45f, 0.6f, R, G, B); - milestones.push_back( GradientMilestone(0.0, double(R), double(G), double(B)) ); - Color::hsv2rgb01(0.14056f, 0.45f, 0.6f, R, G, B); - milestones.push_back( GradientMilestone(1.0, double(R), double(G), double(B)) ); + std::vector milestones; + float R, G, B; + // -0.1 rad < Hue < 1.6 rad + Color::hsv2rgb01(0.92f, 0.45f, 0.6f, R, G, B); + milestones.push_back( GradientMilestone(0.0, double(R), double(G), double(B)) ); + Color::hsv2rgb01(0.14056f, 0.45f, 0.6f, R, G, B); + milestones.push_back( GradientMilestone(1.0, double(R), double(G), double(B)) ); - saturated = Gtk::manage(new Adjuster (M("TP_VIBRANCE_SATURATED"),-100.,100.,1.,0.)); - saturated->setAdjusterListener (this); - saturated->set_sensitive(false); - //if (saturated->delay < 1000) saturated->delay = 1000; - pack_start( *saturated, Gtk::PACK_SHRINK, 0); + saturated = Gtk::manage(new Adjuster (M("TP_VIBRANCE_SATURATED"), -100., 100., 1., 0.)); + saturated->setAdjusterListener (this); + saturated->set_sensitive(false); + //if (saturated->delay < 1000) saturated->delay = 1000; + pack_start( *saturated, Gtk::PACK_SHRINK, 0); - pastels = Gtk::manage(new Adjuster (M("TP_VIBRANCE_PASTELS"),-100.,100.,1.,0.)); - pastels->setAdjusterListener (this); - //if (pastels->delay < 1000) pastels->delay = 1000; - pack_start( *pastels, Gtk::PACK_SHRINK, 0); + pastels = Gtk::manage(new Adjuster (M("TP_VIBRANCE_PASTELS"), -100., 100., 1., 0.)); + pastels->setAdjusterListener (this); + //if (pastels->delay < 1000) pastels->delay = 1000; + pack_start( *pastels, Gtk::PACK_SHRINK, 0); - psThreshold = Gtk::manage (new ThresholdAdjuster (M("TP_VIBRANCE_PSTHRESHOLD"), -100., 100., 0., M("TP_VIBRANCE_PSTHRESHOLD_WEIGTHING"), 0, 0., 100., 75., M("TP_VIBRANCE_PSTHRESHOLD_SATTHRESH"), 0, this, false)); - psThreshold->setAdjusterListener (this); - psThreshold->set_tooltip_markup(M("TP_VIBRANCE_PSTHRESHOLD_TOOLTIP")); - psThreshold->set_sensitive(false); - //if (psThreshold->delay < 1000) psThreshold->delay = 1000; - pack_start( *psThreshold, Gtk::PACK_SHRINK, 0); + psThreshold = Gtk::manage (new ThresholdAdjuster (M("TP_VIBRANCE_PSTHRESHOLD"), -100., 100., 0., M("TP_VIBRANCE_PSTHRESHOLD_WEIGTHING"), 0, 0., 100., 75., M("TP_VIBRANCE_PSTHRESHOLD_SATTHRESH"), 0, this, false)); + psThreshold->setAdjusterListener (this); + psThreshold->set_tooltip_markup(M("TP_VIBRANCE_PSTHRESHOLD_TOOLTIP")); + psThreshold->set_sensitive(false); + //if (psThreshold->delay < 1000) psThreshold->delay = 1000; + pack_start( *psThreshold, Gtk::PACK_SHRINK, 0); - protectSkins = Gtk::manage (new Gtk::CheckButton (M("TP_VIBRANCE_PROTECTSKINS"))); - protectSkins->set_active (true); - pack_start(*protectSkins, Gtk::PACK_SHRINK, 0); + protectSkins = Gtk::manage (new Gtk::CheckButton (M("TP_VIBRANCE_PROTECTSKINS"))); + protectSkins->set_active (true); + pack_start(*protectSkins, Gtk::PACK_SHRINK, 0); - avoidColorShift = Gtk::manage (new Gtk::CheckButton (M("TP_VIBRANCE_AVOIDCOLORSHIFT"))); - avoidColorShift->set_active (true); - pack_start(*avoidColorShift, Gtk::PACK_SHRINK, 0); + avoidColorShift = Gtk::manage (new Gtk::CheckButton (M("TP_VIBRANCE_AVOIDCOLORSHIFT"))); + avoidColorShift->set_active (true); + pack_start(*avoidColorShift, Gtk::PACK_SHRINK, 0); - pastSatTog = Gtk::manage (new Gtk::CheckButton (M("TP_VIBRANCE_PASTSATTOG"))); - pastSatTog->set_active (true); - pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0); + pastSatTog = Gtk::manage (new Gtk::CheckButton (M("TP_VIBRANCE_PASTSATTOG"))); + pastSatTog->set_active (true); + pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0); - curveEditorGG = new CurveEditorGroup (options.lastVibranceCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL")); - curveEditorGG->setCurveListener (this); + curveEditorGG = new CurveEditorGroup (options.lastVibranceCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL")); + curveEditorGG->setCurveListener (this); - skinTonesCurve = static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES"))); - skinTonesCurve->setTooltip(M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_TOOLTIP")); - skinTonesCurve->setBottomBarBgGradient(milestones); - skinTonesCurve->setLeftBarBgGradient(milestones); - skinTonesCurve->setRangeLabels( - M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE1"), M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE2"), - M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE3"), M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE4") - ); - skinTonesCurve->setRangeDefaultMilestones(0.1, 0.4, 0.85); - curveEditorGG->curveListComplete(); + skinTonesCurve = static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES"))); + skinTonesCurve->setTooltip(M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_TOOLTIP")); + skinTonesCurve->setBottomBarBgGradient(milestones); + skinTonesCurve->setLeftBarBgGradient(milestones); + skinTonesCurve->setRangeLabels( + M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE1"), M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE2"), + M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE3"), M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE4") + ); + skinTonesCurve->setRangeDefaultMilestones(0.1, 0.4, 0.85); + curveEditorGG->curveListComplete(); - pack_start (*curveEditorGG, Gtk::PACK_SHRINK, 4); + pack_start (*curveEditorGG, Gtk::PACK_SHRINK, 4); - show (); + show (); - pskinsconn = protectSkins->signal_toggled().connect( sigc::mem_fun(*this, &Vibrance::protectskins_toggled) ); - ashiftconn = avoidColorShift->signal_toggled().connect( sigc::mem_fun(*this, &Vibrance::avoidcolorshift_toggled) ); - pastsattogconn = pastSatTog->signal_toggled().connect( sigc::mem_fun(*this, &Vibrance::pastsattog_toggled) ); + pskinsconn = protectSkins->signal_toggled().connect( sigc::mem_fun(*this, &Vibrance::protectskins_toggled) ); + ashiftconn = avoidColorShift->signal_toggled().connect( sigc::mem_fun(*this, &Vibrance::avoidcolorshift_toggled) ); + pastsattogconn = pastSatTog->signal_toggled().connect( sigc::mem_fun(*this, &Vibrance::pastsattog_toggled) ); } -Vibrance::~Vibrance () { - delete curveEditorGG; +Vibrance::~Vibrance () +{ + delete curveEditorGG; } -void Vibrance::read(const ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); +void Vibrance::read(const ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener (); - if(pedited ){ - set_inconsistent (multiImage && !pedited->vibrance.enabled); - pastels->setEditedState (pedited->vibrance.pastels ? Edited : UnEdited); - saturated->setEditedState (pedited->vibrance.saturated ? Edited : UnEdited); - psThreshold->setEditedState (pedited->vibrance.psthreshold ? Edited : UnEdited); - protectSkins->set_inconsistent (!pedited->vibrance.protectskins); - avoidColorShift->set_inconsistent (!pedited->vibrance.avoidcolorshift); - pastSatTog->set_inconsistent (!pedited->vibrance.pastsattog); - skinTonesCurve->setUnChanged (!pedited->vibrance.skintonescurve); - } + if(pedited ) { + set_inconsistent (multiImage && !pedited->vibrance.enabled); + pastels->setEditedState (pedited->vibrance.pastels ? Edited : UnEdited); + saturated->setEditedState (pedited->vibrance.saturated ? Edited : UnEdited); + psThreshold->setEditedState (pedited->vibrance.psthreshold ? Edited : UnEdited); + protectSkins->set_inconsistent (!pedited->vibrance.protectskins); + avoidColorShift->set_inconsistent (!pedited->vibrance.avoidcolorshift); + pastSatTog->set_inconsistent (!pedited->vibrance.pastsattog); + skinTonesCurve->setUnChanged (!pedited->vibrance.skintonescurve); + } - setEnabled (pp->vibrance.enabled); + setEnabled (pp->vibrance.enabled); - pskinsconn.block (true); - protectSkins->set_active (pp->vibrance.protectskins); - pskinsconn.block (false); - lastProtectSkins = pp->vibrance.protectskins; + pskinsconn.block (true); + protectSkins->set_active (pp->vibrance.protectskins); + pskinsconn.block (false); + lastProtectSkins = pp->vibrance.protectskins; - ashiftconn.block (true); - avoidColorShift->set_active (pp->vibrance.avoidcolorshift); - ashiftconn.block (false); - lastAvoidColorShift = pp->vibrance.avoidcolorshift; + ashiftconn.block (true); + avoidColorShift->set_active (pp->vibrance.avoidcolorshift); + ashiftconn.block (false); + lastAvoidColorShift = pp->vibrance.avoidcolorshift; - pastsattogconn.block (true); - pastSatTog->set_active (pp->vibrance.pastsattog); - pastsattogconn.block (false); - lastPastSatTog = pp->vibrance.pastsattog; + pastsattogconn.block (true); + pastSatTog->set_active (pp->vibrance.pastsattog); + pastsattogconn.block (false); + lastPastSatTog = pp->vibrance.pastsattog; - pastels->setValue (pp->vibrance.pastels); - psThreshold->setValue (pp->vibrance.psthreshold); + pastels->setValue (pp->vibrance.pastels); + psThreshold->setValue (pp->vibrance.psthreshold); - if (lastPastSatTog) { - // Link both slider, so we set saturated and psThresholds unsensitive - psThreshold->set_sensitive(false); - saturated->set_sensitive(false); - saturated->setValue (pp->vibrance.pastels); // Pastels and Saturated are linked - } - else { - // Separate sliders, so we set saturated and psThresholds sensitive again - psThreshold->set_sensitive(true); - saturated->set_sensitive(true); - saturated->setValue (pp->vibrance.saturated); // Pastels and Saturated are separate - } - skinTonesCurve->setCurve (pp->vibrance.skintonescurve); + if (lastPastSatTog) { + // Link both slider, so we set saturated and psThresholds unsensitive + psThreshold->set_sensitive(false); + saturated->set_sensitive(false); + saturated->setValue (pp->vibrance.pastels); // Pastels and Saturated are linked + } else { + // Separate sliders, so we set saturated and psThresholds sensitive again + psThreshold->set_sensitive(true); + saturated->set_sensitive(true); + saturated->setValue (pp->vibrance.saturated); // Pastels and Saturated are separate + } - enableListener (); + skinTonesCurve->setCurve (pp->vibrance.skintonescurve); + + enableListener (); } -void Vibrance::autoOpenCurve () { - skinTonesCurve->openIfNonlinear(); +void Vibrance::autoOpenCurve () +{ + skinTonesCurve->openIfNonlinear(); } -void Vibrance::write( ProcParams* pp, ParamsEdited* pedited) { - pp->vibrance.enabled = getEnabled (); - pp->vibrance.pastels = pastels->getIntValue(); - pp->vibrance.saturated = pastSatTog->get_active() ? pp->vibrance.pastels : saturated->getIntValue (); - pp->vibrance.psthreshold = psThreshold->getValue (); - pp->vibrance.protectskins = protectSkins->get_active (); - pp->vibrance.avoidcolorshift = avoidColorShift->get_active (); - pp->vibrance.pastsattog = pastSatTog->get_active (); - pp->vibrance.skintonescurve = skinTonesCurve->getCurve (); +void Vibrance::write( ProcParams* pp, ParamsEdited* pedited) +{ + pp->vibrance.enabled = getEnabled (); + pp->vibrance.pastels = pastels->getIntValue(); + pp->vibrance.saturated = pastSatTog->get_active() ? pp->vibrance.pastels : saturated->getIntValue (); + pp->vibrance.psthreshold = psThreshold->getValue (); + pp->vibrance.protectskins = protectSkins->get_active (); + pp->vibrance.avoidcolorshift = avoidColorShift->get_active (); + pp->vibrance.pastsattog = pastSatTog->get_active (); + pp->vibrance.skintonescurve = skinTonesCurve->getCurve (); - if (pedited) { - pedited->vibrance.enabled = !get_inconsistent(); - pedited->vibrance.pastels = pastels->getEditedState (); - pedited->vibrance.saturated = saturated->getEditedState (); - pedited->vibrance.psthreshold = psThreshold->getEditedState (); - pedited->vibrance.protectskins = !protectSkins->get_inconsistent(); - pedited->vibrance.avoidcolorshift = !avoidColorShift->get_inconsistent(); - pedited->vibrance.pastsattog = !pastSatTog->get_inconsistent(); - pedited->vibrance.skintonescurve = !skinTonesCurve->isUnChanged (); - } + if (pedited) { + pedited->vibrance.enabled = !get_inconsistent(); + pedited->vibrance.pastels = pastels->getEditedState (); + pedited->vibrance.saturated = saturated->getEditedState (); + pedited->vibrance.psthreshold = psThreshold->getEditedState (); + pedited->vibrance.protectskins = !protectSkins->get_inconsistent(); + pedited->vibrance.avoidcolorshift = !avoidColorShift->get_inconsistent(); + pedited->vibrance.pastsattog = !pastSatTog->get_inconsistent(); + pedited->vibrance.skintonescurve = !skinTonesCurve->isUnChanged (); + } } -void Vibrance::curveChanged () { +void Vibrance::curveChanged () +{ - if (listener && getEnabled ()) listener->panelChanged (EvVibranceSkinTonesCurve, M("HISTORY_CUSTOMCURVE")); + if (listener && getEnabled ()) { + listener->panelChanged (EvVibranceSkinTonesCurve, M("HISTORY_CUSTOMCURVE")); + } } -void Vibrance::enabledChanged () { - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvVibranceEnabled, M("GENERAL_UNCHANGED")); - if (getEnabled()) - listener->panelChanged (EvVibranceEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvVibranceEnabled, M("GENERAL_DISABLED")); - } +void Vibrance::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvVibranceEnabled, M("GENERAL_UNCHANGED")); + } + + if (getEnabled()) { + listener->panelChanged (EvVibranceEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvVibranceEnabled, M("GENERAL_DISABLED")); + } + } } -void Vibrance::protectskins_toggled () { - if (batchMode) { - if (protectSkins->get_inconsistent()) { - protectSkins->set_inconsistent (false); - pskinsconn.block (true); - protectSkins->set_active (false); - pskinsconn.block (false); - } - else if (lastProtectSkins) - protectSkins->set_inconsistent (true); +void Vibrance::protectskins_toggled () +{ + if (batchMode) { + if (protectSkins->get_inconsistent()) { + protectSkins->set_inconsistent (false); + pskinsconn.block (true); + protectSkins->set_active (false); + pskinsconn.block (false); + } else if (lastProtectSkins) { + protectSkins->set_inconsistent (true); + } - lastProtectSkins = protectSkins->get_active (); - } + lastProtectSkins = protectSkins->get_active (); + } - if (listener && getEnabled()) { - if (protectSkins->get_active ()) - listener->panelChanged (EvVibranceProtectSkins, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvVibranceProtectSkins, M("GENERAL_DISABLED")); - } + if (listener && getEnabled()) { + if (protectSkins->get_active ()) { + listener->panelChanged (EvVibranceProtectSkins, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvVibranceProtectSkins, M("GENERAL_DISABLED")); + } + } } -void Vibrance::avoidcolorshift_toggled () { - if (batchMode) { - if (avoidColorShift->get_inconsistent()) { - avoidColorShift->set_inconsistent (false); - ashiftconn.block (true); - avoidColorShift->set_active (false); - ashiftconn.block (false); - } - else if (lastAvoidColorShift) - avoidColorShift->set_inconsistent (true); +void Vibrance::avoidcolorshift_toggled () +{ + if (batchMode) { + if (avoidColorShift->get_inconsistent()) { + avoidColorShift->set_inconsistent (false); + ashiftconn.block (true); + avoidColorShift->set_active (false); + ashiftconn.block (false); + } else if (lastAvoidColorShift) { + avoidColorShift->set_inconsistent (true); + } - lastAvoidColorShift = avoidColorShift->get_active (); - } + lastAvoidColorShift = avoidColorShift->get_active (); + } - if (listener && getEnabled()) { - if (avoidColorShift->get_active ()) - listener->panelChanged (EvVibranceAvoidColorShift, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvVibranceAvoidColorShift, M("GENERAL_DISABLED")); - } + if (listener && getEnabled()) { + if (avoidColorShift->get_active ()) { + listener->panelChanged (EvVibranceAvoidColorShift, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvVibranceAvoidColorShift, M("GENERAL_DISABLED")); + } + } } -void Vibrance::pastsattog_toggled () { - if (batchMode) { - if (pastSatTog->get_inconsistent()) { - pastSatTog->set_inconsistent (false); - pastsattogconn.block (true); - pastSatTog->set_active (false); - pastsattogconn.block (false); - } - else if (lastPastSatTog) - pastSatTog->set_inconsistent (true); +void Vibrance::pastsattog_toggled () +{ + if (batchMode) { + if (pastSatTog->get_inconsistent()) { + pastSatTog->set_inconsistent (false); + pastsattogconn.block (true); + pastSatTog->set_active (false); + pastsattogconn.block (false); + } else if (lastPastSatTog) { + pastSatTog->set_inconsistent (true); + } - lastPastSatTog = pastSatTog->get_active (); - } + lastPastSatTog = pastSatTog->get_active (); + } - if (pastSatTog->get_active()) { - // Link both slider, so we set saturated and psThresholds unsensitive - psThreshold->set_sensitive(false); - saturated->set_sensitive(false); - saturated->setValue (pastels->getValue()); // Pastels and Saturated are linked - } - else { - // Separate sliders, so we set saturated and psThresholds sensitive again - psThreshold->set_sensitive(true); - saturated->set_sensitive(true); - } + if (pastSatTog->get_active()) { + // Link both slider, so we set saturated and psThresholds unsensitive + psThreshold->set_sensitive(false); + saturated->set_sensitive(false); + saturated->setValue (pastels->getValue()); // Pastels and Saturated are linked + } else { + // Separate sliders, so we set saturated and psThresholds sensitive again + psThreshold->set_sensitive(true); + saturated->set_sensitive(true); + } - if (listener && getEnabled()) { - if (pastSatTog->get_active ()) { - listener->panelChanged (EvVibrancePastSatTog, M("GENERAL_ENABLED")); - } - else - listener->panelChanged (EvVibrancePastSatTog, M("GENERAL_DISABLED")); - } + if (listener && getEnabled()) { + if (pastSatTog->get_active ()) { + listener->panelChanged (EvVibrancePastSatTog, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvVibrancePastSatTog, M("GENERAL_DISABLED")); + } + } } -void Vibrance::adjusterChanged (Adjuster* a, double newval) { - if (a == pastels && pastSatTog->get_active()) - saturated->setValue (newval); +void Vibrance::adjusterChanged (Adjuster* a, double newval) +{ + if (a == pastels && pastSatTog->get_active()) { + saturated->setValue (newval); + } - if (listener && getEnabled()) { - Glib::ustring value = a->getTextValue(); + if (listener && getEnabled()) { + Glib::ustring value = a->getTextValue(); - if (a == pastels ) - listener->panelChanged (EvVibrancePastels, value ); - else if (a == saturated && !pastSatTog->get_active()) - listener->panelChanged (EvVibranceSaturated, value ); - } + if (a == pastels ) { + listener->panelChanged (EvVibrancePastels, value ); + } else if (a == saturated && !pastSatTog->get_active()) { + listener->panelChanged (EvVibranceSaturated, value ); + } + } } -void Vibrance::adjusterChanged (ThresholdAdjuster* a, int newBottom, int newTop) { - if (listener && getEnabled()) { - listener->panelChanged (EvVibrancePastSatThreshold, psThreshold->getHistoryString()); - } +void Vibrance::adjusterChanged (ThresholdAdjuster* a, int newBottom, int newTop) +{ + if (listener && getEnabled()) { + listener->panelChanged (EvVibrancePastSatThreshold, psThreshold->getHistoryString()); + } } -void Vibrance::setBatchMode(bool batchMode) { +void Vibrance::setBatchMode(bool batchMode) +{ ToolPanel::setBatchMode (batchMode); - pastels->showEditedCB (); - saturated->showEditedCB (); - psThreshold->showEditedCB (); + pastels->showEditedCB (); + saturated->showEditedCB (); + psThreshold->showEditedCB (); - curveEditorGG->setBatchMode (batchMode); + curveEditorGG->setBatchMode (batchMode); } -void Vibrance::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) { - pastels->setDefault (defParams->vibrance.pastels); - saturated->setDefault (defParams->vibrance.saturated); - psThreshold->setDefault (defParams->vibrance.psthreshold); +void Vibrance::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) +{ + pastels->setDefault (defParams->vibrance.pastels); + saturated->setDefault (defParams->vibrance.saturated); + psThreshold->setDefault (defParams->vibrance.psthreshold); - if (pedited) { - pastels->setDefaultEditedState (pedited->vibrance.pastels ? Edited : UnEdited); - saturated->setDefaultEditedState (pedited->vibrance.saturated ? Edited : UnEdited); - psThreshold->setDefaultEditedState (pedited->vibrance.psthreshold ? Edited : UnEdited); + if (pedited) { + pastels->setDefaultEditedState (pedited->vibrance.pastels ? Edited : UnEdited); + saturated->setDefaultEditedState (pedited->vibrance.saturated ? Edited : UnEdited); + psThreshold->setDefaultEditedState (pedited->vibrance.psthreshold ? Edited : UnEdited); - } else { - pastels->setDefaultEditedState (Irrelevant); - saturated->setDefaultEditedState (Irrelevant); - psThreshold->setDefaultEditedState (Irrelevant); - } + } else { + pastels->setDefaultEditedState (Irrelevant); + saturated->setDefaultEditedState (Irrelevant); + psThreshold->setDefaultEditedState (Irrelevant); + } } -void Vibrance::setAdjusterBehavior (bool pastelsadd, bool saturatedadd) { - pastels->setAddMode (pastelsadd); - saturated->setAddMode (saturatedadd); +void Vibrance::setAdjusterBehavior (bool pastelsadd, bool saturatedadd) +{ + pastels->setAddMode (pastelsadd); + saturated->setAddMode (saturatedadd); } -void Vibrance::trimValues (ProcParams* pp) { - pastels->trimValue (pp->vibrance.pastels); - saturated->trimValue (pp->vibrance.saturated); +void Vibrance::trimValues (ProcParams* pp) +{ + pastels->trimValue (pp->vibrance.pastels); + saturated->trimValue (pp->vibrance.saturated); } -std::vector Vibrance::getCurvePoints(ThresholdSelector* tAdjuster) const { - std::vector points; - double threshold, transitionWeighting; - tAdjuster->getPositions(transitionWeighting, threshold); // ( range -100;+100, range 0;+100 ) - transitionWeighting /= 100.; // range -1., +1. - threshold /= 100.; // range 0., +1. +std::vector Vibrance::getCurvePoints(ThresholdSelector* tAdjuster) const +{ + std::vector points; + double threshold, transitionWeighting; + tAdjuster->getPositions(transitionWeighting, threshold); // ( range -100;+100, range 0;+100 ) + transitionWeighting /= 100.; // range -1., +1. + threshold /= 100.; // range 0., +1. - // Initial point - points.push_back(0.); points.push_back(0.); + // Initial point + points.push_back(0.); + points.push_back(0.); - double p2 = 3.0*threshold/4.0; // same one than in ipvibrance.cc - double s0 = threshold + (1.0-threshold)/4.0; // same one than in ipvibrance.cc + double p2 = 3.0 * threshold / 4.0; // same one than in ipvibrance.cc + double s0 = threshold + (1.0 - threshold) / 4.0; // same one than in ipvibrance.cc - // point at the beginning of the first linear transition - points.push_back(p2); points.push_back(0.); + // point at the beginning of the first linear transition + points.push_back(p2); + points.push_back(0.); - // Y value of the chroma mean point, calculated to get a straight line between p2 and s0 - double chromaMean = (threshold/4.0) / (s0-p2); - // move chromaMean up or down depending on transitionWeighting - if (transitionWeighting > 0.0) { - // positive values -> give more weight to Saturated - chromaMean = (1.0-chromaMean) * transitionWeighting + chromaMean; - } - else if (transitionWeighting < 0.0) { - // negative values -> give more weight to Pastels - chromaMean = chromaMean * transitionWeighting + chromaMean; - } + // Y value of the chroma mean point, calculated to get a straight line between p2 and s0 + double chromaMean = (threshold / 4.0) / (s0 - p2); - // point at the location of the Top cursor, at the end of the first linear transition and the beginning of the second one - points.push_back(threshold); points.push_back(chromaMean); + // move chromaMean up or down depending on transitionWeighting + if (transitionWeighting > 0.0) { + // positive values -> give more weight to Saturated + chromaMean = (1.0 - chromaMean) * transitionWeighting + chromaMean; + } else if (transitionWeighting < 0.0) { + // negative values -> give more weight to Pastels + chromaMean = chromaMean * transitionWeighting + chromaMean; + } - if (threshold < 1.0) { + // point at the location of the Top cursor, at the end of the first linear transition and the beginning of the second one + points.push_back(threshold); + points.push_back(chromaMean); - // point at the end of the second linear transition - points.push_back(s0); points.push_back(1.0); + if (threshold < 1.0) { - // end point - points.push_back(1.0); points.push_back(1.0); - } + // point at the end of the second linear transition + points.push_back(s0); + points.push_back(1.0); - return points; + // end point + points.push_back(1.0); + points.push_back(1.0); + } + + return points; } diff --git a/rtgui/vibrance.h b/rtgui/vibrance.h index 699912d5c..e8afbbad0 100644 --- a/rtgui/vibrance.h +++ b/rtgui/vibrance.h @@ -27,49 +27,49 @@ #include "toolpanel.h" class Vibrance : public ToolParamBlock, public AdjusterListener, public ThresholdCurveProvider, public ThresholdAdjusterListener, - public FoldableToolPanel, public CurveListener + public FoldableToolPanel, public CurveListener { protected: - CurveEditorGroup* curveEditorGG; + CurveEditorGroup* curveEditorGG; - Adjuster* pastels; - Adjuster* saturated; + Adjuster* pastels; + Adjuster* saturated; ThresholdAdjuster* psThreshold; - Gtk::CheckButton* protectSkins; - Gtk::CheckButton* avoidColorShift; - Gtk::CheckButton* pastSatTog; - DiagonalCurveEditor* skinTonesCurve; + Gtk::CheckButton* protectSkins; + Gtk::CheckButton* avoidColorShift; + Gtk::CheckButton* pastSatTog; + DiagonalCurveEditor* skinTonesCurve; - bool lastProtectSkins; - bool lastAvoidColorShift; - bool lastPastSatTog; + bool lastProtectSkins; + bool lastAvoidColorShift; + bool lastPastSatTog; - sigc::connection pskinsconn; - sigc::connection ashiftconn; - sigc::connection pastsattogconn; + sigc::connection pskinsconn; + sigc::connection ashiftconn; + sigc::connection pastsattogconn; public: - Vibrance (); - ~Vibrance (); + Vibrance (); + ~Vibrance (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void trimValues (rtengine::procparams::ProcParams* pp); - void setAdjusterBehavior (bool pastelsadd, bool saturatedadd); - void adjusterChanged (Adjuster* a, double newval); - void adjusterChanged (ThresholdAdjuster* a, int newBottom, int newTop); - void curveChanged (); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void trimValues (rtengine::procparams::ProcParams* pp); + void setAdjusterBehavior (bool pastelsadd, bool saturatedadd); + void adjusterChanged (Adjuster* a, double newval); + void adjusterChanged (ThresholdAdjuster* a, int newBottom, int newTop); + void curveChanged (); void autoOpenCurve (); void enabledChanged (); - void protectskins_toggled (); - void avoidcolorshift_toggled (); - void pastsattog_toggled (); - std::vector getCurvePoints(ThresholdSelector* tAdjuster) const; + void protectskins_toggled (); + void avoidcolorshift_toggled (); + void pastsattog_toggled (); + std::vector getCurvePoints(ThresholdSelector* tAdjuster) const; }; diff --git a/rtgui/vignetting.cc b/rtgui/vignetting.cc index 1d3e84018..dd8d0a2b1 100644 --- a/rtgui/vignetting.cc +++ b/rtgui/vignetting.cc @@ -7,7 +7,7 @@ * 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 @@ -21,13 +21,14 @@ using namespace rtengine; using namespace rtengine::procparams; -Vignetting::Vignetting () : FoldableToolPanel(this, "vignetting", M("TP_VIGNETTING_LABEL")) { +Vignetting::Vignetting () : FoldableToolPanel(this, "vignetting", M("TP_VIGNETTING_LABEL")) +{ amount = Gtk::manage (new Adjuster (M("TP_VIGNETTING_AMOUNT"), -100, 100, 1, 0)); - amount->setAdjusterListener (this); + amount->setAdjusterListener (this); radius = Gtk::manage (new Adjuster (M("TP_VIGNETTING_RADIUS"), 0, 100, 1, 50)); - radius->setAdjusterListener (this); + radius->setAdjusterListener (this); strength = Gtk::manage (new Adjuster (M("TP_VIGNETTING_STRENGTH"), 1, 100, 1, 1)); strength->setAdjusterListener (this); @@ -47,7 +48,8 @@ Vignetting::Vignetting () : FoldableToolPanel(this, "vignetting", M("TP_VIGNETTI show_all(); } -void Vignetting::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Vignetting::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); @@ -68,7 +70,8 @@ void Vignetting::read (const ProcParams* pp, const ParamsEdited* pedited) { enableListener (); } -void Vignetting::write (ProcParams* pp, ParamsEdited* pedited) { +void Vignetting::write (ProcParams* pp, ParamsEdited* pedited) +{ pp->vignetting.amount = amount->getIntValue (); pp->vignetting.radius = radius->getIntValue (); @@ -76,7 +79,7 @@ void Vignetting::write (ProcParams* pp, ParamsEdited* pedited) { pp->vignetting.centerX = centerX->getIntValue (); pp->vignetting.centerY = centerY->getIntValue (); - if (pedited) { + if (pedited) { pedited->vignetting.amount = amount->getEditedState (); pedited->vignetting.radius = radius->getEditedState (); pedited->vignetting.strength = strength->getEditedState (); @@ -85,7 +88,8 @@ void Vignetting::write (ProcParams* pp, ParamsEdited* pedited) { } } -void Vignetting::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void Vignetting::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ amount->setDefault (defParams->vignetting.amount); radius->setDefault (defParams->vignetting.radius); @@ -99,8 +103,7 @@ void Vignetting::setDefaults (const ProcParams* defParams, const ParamsEdited* p strength->setDefaultEditedState (pedited->vignetting.strength ? Edited : UnEdited); centerX->setDefaultEditedState (pedited->vignetting.centerX ? Edited : UnEdited); centerY->setDefaultEditedState (pedited->vignetting.centerY ? Edited : UnEdited); - } - else { + } else { amount->setDefaultEditedState (Irrelevant); radius->setDefaultEditedState (Irrelevant); strength->setDefaultEditedState (Irrelevant); @@ -109,39 +112,44 @@ void Vignetting::setDefaults (const ProcParams* defParams, const ParamsEdited* p } } -void Vignetting::adjusterChanged (Adjuster* a, double newval) { +void Vignetting::adjusterChanged (Adjuster* a, double newval) +{ if (listener) { - if (a == amount) + if (a == amount) { listener->panelChanged (EvVignettingAmount, amount->getTextValue()); - else if (a == radius) + } else if (a == radius) { listener->panelChanged (EvVignettingRadius, radius->getTextValue()); - else if (a == strength) + } else if (a == strength) { listener->panelChanged (EvVignettingStrenght, strength->getTextValue()); - else if (a == centerX || a == centerY) + } else if (a == centerX || a == centerY) { listener->panelChanged (EvVignettingCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue())); + } } } -void Vignetting::setAdjusterBehavior (bool amountadd, bool radiusadd, bool strengthadd, bool centeradd) { +void Vignetting::setAdjusterBehavior (bool amountadd, bool radiusadd, bool strengthadd, bool centeradd) +{ - amount->setAddMode(amountadd); - radius->setAddMode(radiusadd); - strength->setAddMode(strengthadd); - centerX->setAddMode(centeradd); - centerY->setAddMode(centeradd); + amount->setAddMode(amountadd); + radius->setAddMode(radiusadd); + strength->setAddMode(strengthadd); + centerX->setAddMode(centeradd); + centerY->setAddMode(centeradd); } -void Vignetting::trimValues (rtengine::procparams::ProcParams* pp) { +void Vignetting::trimValues (rtengine::procparams::ProcParams* pp) +{ - amount->trimValue(pp->vignetting.amount); - radius->trimValue(pp->vignetting.radius); - strength->trimValue(pp->vignetting.strength); - centerX->trimValue(pp->vignetting.centerX); - centerY->trimValue(pp->vignetting.centerY); + amount->trimValue(pp->vignetting.amount); + radius->trimValue(pp->vignetting.radius); + strength->trimValue(pp->vignetting.strength); + centerX->trimValue(pp->vignetting.centerX); + centerY->trimValue(pp->vignetting.centerY); } -void Vignetting::setBatchMode (bool batchMode) { +void Vignetting::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); amount->showEditedCB (); diff --git a/rtgui/vignetting.h b/rtgui/vignetting.h index a6c22252f..6909b5af7 100644 --- a/rtgui/vignetting.h +++ b/rtgui/vignetting.h @@ -7,7 +7,7 @@ * 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 @@ -23,22 +23,23 @@ #include "adjuster.h" #include "toolpanel.h" -class Vignetting : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class Vignetting : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: Adjuster* amount; Adjuster* radius; Adjuster* strength; Adjuster* centerX; Adjuster* centerY; - public: +public: Vignetting (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index bb8e26999..4bebb10ad 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -26,2823 +26,3057 @@ using namespace rtengine; using namespace rtengine::procparams; extern Options options; -Wavelet::Wavelet () : FoldableToolPanel(this, "wavelet", M("TP_WAVELET_LABEL"), true, true) { - std::vector milestones; - CurveListener::setMulti(true); - nextnlevel=7.; - float r, g, b; - //from -PI to +PI (radians) convert to hsv and draw bottombar - Color::hsv2rgb01(0.4199, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.0 , r, g, b) ); // hsv: 0.4199 rad: -3.14 - Color::hsv2rgb01(0.5000, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.054 , r, g, b) ); // hsv: 0.5 rad: -2.8 - Color::hsv2rgb01(0.6000, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.1336, r, g, b) ); // hsv: 0.60 rad: -2.3 - Color::hsv2rgb01(0.7500, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.3567, r, g, b) ); // hsv: 0.75 rad: -0.9 - Color::hsv2rgb01(0.8560, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.4363, r, g, b) ); // hsv: 0.856 rad: -0.4 - Color::hsv2rgb01(0.9200, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.4841, r, g, b) ); // hsv: 0.92 rad: -0.1 - Color::hsv2rgb01(0.9300, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.5000, r, g, b) ); // hsv: 0.93 rad: 0 - Color::hsv2rgb01(0.9600, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.5366, r, g, b) ); // hsv: 0.96 rad: 0.25 - Color::hsv2rgb01(1.0000, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.5955, r, g, b) ); // hsv: 1. rad: 0.6 - Color::hsv2rgb01(0.0675, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.6911, r, g, b) ); // hsv: 0.0675 rad: 1.2 - Color::hsv2rgb01(0.0900, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.7229, r, g, b) ); // hsv: 0.09 rad: 1.4 - Color::hsv2rgb01(0.1700, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.7707, r, g, b) ); // hsv: 0.17 rad: 1.7 - Color::hsv2rgb01(0.2650, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.8503, r, g, b) ); // hsv: 0.265 rad: 2.1 - Color::hsv2rgb01(0.3240, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(0.8981, r, g, b) ); // hsv: 0.324 rad: 2.5 - Color::hsv2rgb01(0.4197, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(1. , r, g, b) ); // hsv: 0.419 rad: 3.14 +Wavelet::Wavelet () : FoldableToolPanel(this, "wavelet", M("TP_WAVELET_LABEL"), true, true) +{ + std::vector milestones; + CurveListener::setMulti(true); + nextnlevel = 7.; + float r, g, b; + //from -PI to +PI (radians) convert to hsv and draw bottombar + Color::hsv2rgb01(0.4199, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.0 , r, g, b) ); // hsv: 0.4199 rad: -3.14 + Color::hsv2rgb01(0.5000, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.054 , r, g, b) ); // hsv: 0.5 rad: -2.8 + Color::hsv2rgb01(0.6000, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.1336, r, g, b) ); // hsv: 0.60 rad: -2.3 + Color::hsv2rgb01(0.7500, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.3567, r, g, b) ); // hsv: 0.75 rad: -0.9 + Color::hsv2rgb01(0.8560, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.4363, r, g, b) ); // hsv: 0.856 rad: -0.4 + Color::hsv2rgb01(0.9200, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.4841, r, g, b) ); // hsv: 0.92 rad: -0.1 + Color::hsv2rgb01(0.9300, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.5000, r, g, b) ); // hsv: 0.93 rad: 0 + Color::hsv2rgb01(0.9600, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.5366, r, g, b) ); // hsv: 0.96 rad: 0.25 + Color::hsv2rgb01(1.0000, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.5955, r, g, b) ); // hsv: 1. rad: 0.6 + Color::hsv2rgb01(0.0675, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.6911, r, g, b) ); // hsv: 0.0675 rad: 1.2 + Color::hsv2rgb01(0.0900, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.7229, r, g, b) ); // hsv: 0.09 rad: 1.4 + Color::hsv2rgb01(0.1700, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.7707, r, g, b) ); // hsv: 0.17 rad: 1.7 + Color::hsv2rgb01(0.2650, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.8503, r, g, b) ); // hsv: 0.265 rad: 2.1 + Color::hsv2rgb01(0.3240, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(0.8981, r, g, b) ); // hsv: 0.324 rad: 2.5 + Color::hsv2rgb01(0.4197, 0.5, 0.5, r, g, b); + milestones.push_back( GradientMilestone(1. , r, g, b) ); // hsv: 0.419 rad: 3.14 - std::vector milestones2; - milestones2.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) ); - milestones2.push_back( GradientMilestone(1.0, 1.0, 1.0, 1.0) ); + std::vector milestones2; + milestones2.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) ); + milestones2.push_back( GradientMilestone(1.0, 1.0, 1.0, 1.0) ); - std::vector defaultCurve; + std::vector defaultCurve; - expsettings = new MyExpander (false, M("TP_WAVELET_SETTINGS")); - expsettings->signal_button_release_event().connect_notify( sigc::bind( sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings) ); + expsettings = new MyExpander (false, M("TP_WAVELET_SETTINGS")); + expsettings->signal_button_release_event().connect_notify( sigc::bind( sigc::mem_fun(this, &Wavelet::foldAllButMe), expsettings) ); - expcontrast = new MyExpander (true, M("TP_WAVELET_LEVF")); - expcontrast->signal_button_release_event().connect_notify( sigc::bind( sigc::mem_fun(this, &Wavelet::foldAllButMe), expcontrast) ); - enableContrastConn = expcontrast->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expcontrast) ); + expcontrast = new MyExpander (true, M("TP_WAVELET_LEVF")); + expcontrast->signal_button_release_event().connect_notify( sigc::bind( sigc::mem_fun(this, &Wavelet::foldAllButMe), expcontrast) ); + enableContrastConn = expcontrast->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expcontrast) ); - expchroma = new MyExpander (true, M("TP_WAVELET_LEVCH")); - expchroma->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expchroma) ); - enableChromaConn = expchroma->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expchroma) ); + expchroma = new MyExpander (true, M("TP_WAVELET_LEVCH")); + expchroma->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expchroma) ); + enableChromaConn = expchroma->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expchroma) ); - exptoning = new MyExpander (true,M("TP_WAVELET_TON")); - exptoning->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), exptoning) ); - enableToningConn = exptoning->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), exptoning) ); + exptoning = new MyExpander (true, M("TP_WAVELET_TON")); + exptoning->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), exptoning) ); + enableToningConn = exptoning->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), exptoning) ); - expnoise = new MyExpander (true, M("TP_WAVELET_NOISE")); - expnoise->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expnoise) ); - enableNoiseConn = expnoise->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expnoise) ); + expnoise = new MyExpander (true, M("TP_WAVELET_NOISE")); + expnoise->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expnoise) ); + enableNoiseConn = expnoise->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expnoise) ); - expedge = new MyExpander (true, M("TP_WAVELET_EDGE")); - expedge->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expedge) ); - enableEdgeConn = expedge->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expedge) ); + expedge = new MyExpander (true, M("TP_WAVELET_EDGE")); + expedge->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expedge) ); + enableEdgeConn = expedge->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expedge) ); - expgamut = new MyExpander (false, M("TP_WAVELET_CONTR")); - expgamut->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expgamut) ); + expgamut = new MyExpander (false, M("TP_WAVELET_CONTR")); + expgamut->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expgamut) ); - expresid = new MyExpander (true, M("TP_WAVELET_RESID")); - expresid->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expresid) ); - enableResidConn = expresid->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expresid) ); + expresid = new MyExpander (true, M("TP_WAVELET_RESID")); + expresid->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expresid) ); + enableResidConn = expresid->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expresid) ); - expfinal = new MyExpander (true, M("TP_WAVELET_FINAL")); - expfinal->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expfinal) ); - enableFinalConn = expfinal->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expfinal) ); + expfinal = new MyExpander (true, M("TP_WAVELET_FINAL")); + expfinal->signal_button_release_event().connect_notify( sigc::bind ( sigc::mem_fun(this, &Wavelet::foldAllButMe), expfinal) ); + enableFinalConn = expfinal->signal_enabled_toggled().connect ( sigc::bind( sigc::mem_fun(this, &Wavelet::enableToggled), expfinal) ); // Wavelet Settings - settingsVBox = Gtk::manage (new Gtk::VBox()); - settingsVBox->set_border_width(4); - settingsVBox->set_spacing(2); + settingsVBox = Gtk::manage (new Gtk::VBox()); + settingsVBox->set_border_width(4); + settingsVBox->set_spacing(2); - strength = Gtk::manage (new Adjuster (M("TP_WAVELET_STRENGTH"), 0, 100, 1, 100)); - strength->setAdjusterListener (this); + strength = Gtk::manage (new Adjuster (M("TP_WAVELET_STRENGTH"), 0, 100, 1, 100)); + strength->setAdjusterListener (this); - thres = Gtk::manage (new Adjuster (M("TP_WAVELET_LEVELS"), 4, 9, 1, 7));//3 - thres->set_tooltip_text (M("TP_WAVELET_LEVELS_TOOLTIP")); - thres->setAdjusterListener (this); + thres = Gtk::manage (new Adjuster (M("TP_WAVELET_LEVELS"), 4, 9, 1, 7));//3 + thres->set_tooltip_text (M("TP_WAVELET_LEVELS_TOOLTIP")); + thres->setAdjusterListener (this); - tilesizeHBox = Gtk::manage (new Gtk::HBox()); - tilesizeLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_TILESIZE") + ":")); - //tilesizeLabel->set_alignment(Gtk::ALIGN_START); - Tilesmethod = Gtk::manage (new MyComboBoxText ()); - Tilesmethod->append_text (M("TP_WAVELET_TILESFULL")); - Tilesmethod->append_text (M("TP_WAVELET_TILESBIG")); - Tilesmethod->append_text (M("TP_WAVELET_TILESLIT")); - Tilesmethodconn = Tilesmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::TilesmethodChanged) ); - Tilesmethod->set_tooltip_text (M("TP_WAVELET_TILES_TOOLTIP")); - tilesizeHBox->pack_start(*tilesizeLabel, Gtk::PACK_SHRINK, 4); - tilesizeHBox->pack_start(*Tilesmethod); + tilesizeHBox = Gtk::manage (new Gtk::HBox()); + tilesizeLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_TILESIZE") + ":")); + //tilesizeLabel->set_alignment(Gtk::ALIGN_START); + Tilesmethod = Gtk::manage (new MyComboBoxText ()); + Tilesmethod->append_text (M("TP_WAVELET_TILESFULL")); + Tilesmethod->append_text (M("TP_WAVELET_TILESBIG")); + Tilesmethod->append_text (M("TP_WAVELET_TILESLIT")); + Tilesmethodconn = Tilesmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::TilesmethodChanged) ); + Tilesmethod->set_tooltip_text (M("TP_WAVELET_TILES_TOOLTIP")); + tilesizeHBox->pack_start(*tilesizeLabel, Gtk::PACK_SHRINK, 4); + tilesizeHBox->pack_start(*Tilesmethod); - daubcoeffHBox = Gtk::manage (new Gtk::HBox()); - daubcoeffLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_DAUB") + ":")); - daubcoeffmethod = Gtk::manage (new MyComboBoxText ()); - daubcoeffmethod->set_sensitive(true); - daubcoeffmethod->append_text (M("TP_WAVELET_DAUB2")); - daubcoeffmethod->append_text (M("TP_WAVELET_DAUB4")); - daubcoeffmethod->append_text (M("TP_WAVELET_DAUB6")); - daubcoeffmethod->append_text (M("TP_WAVELET_DAUB10")); - daubcoeffmethod->append_text (M("TP_WAVELET_DAUB14")); - daubcoeffmethodconn = daubcoeffmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::daubcoeffmethodChanged) ); - daubcoeffmethod->set_tooltip_text (M("TP_WAVELET_DAUB_TOOLTIP")); - daubcoeffHBox->pack_start(*daubcoeffLabel, Gtk::PACK_SHRINK, 4); - daubcoeffHBox->pack_start(*daubcoeffmethod); + daubcoeffHBox = Gtk::manage (new Gtk::HBox()); + daubcoeffLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_DAUB") + ":")); + daubcoeffmethod = Gtk::manage (new MyComboBoxText ()); + daubcoeffmethod->set_sensitive(true); + daubcoeffmethod->append_text (M("TP_WAVELET_DAUB2")); + daubcoeffmethod->append_text (M("TP_WAVELET_DAUB4")); + daubcoeffmethod->append_text (M("TP_WAVELET_DAUB6")); + daubcoeffmethod->append_text (M("TP_WAVELET_DAUB10")); + daubcoeffmethod->append_text (M("TP_WAVELET_DAUB14")); + daubcoeffmethodconn = daubcoeffmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::daubcoeffmethodChanged) ); + daubcoeffmethod->set_tooltip_text (M("TP_WAVELET_DAUB_TOOLTIP")); + daubcoeffHBox->pack_start(*daubcoeffLabel, Gtk::PACK_SHRINK, 4); + daubcoeffHBox->pack_start(*daubcoeffmethod); - backgroundHBox = Gtk::manage (new Gtk::HBox()); - Backmethod = Gtk::manage (new MyComboBoxText ()); - Backmethod->append_text (M("TP_WAVELET_B0")); - Backmethod->append_text (M("TP_WAVELET_B1")); - Backmethod->append_text (M("TP_WAVELET_B2")); - Backmethodconn = Backmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::BackmethodChanged) ); - backgroundLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_BACKGROUND") + ":")); - backgroundHBox->pack_start(*backgroundLabel, Gtk::PACK_SHRINK, 4); - backgroundHBox->pack_start(*Backmethod); + backgroundHBox = Gtk::manage (new Gtk::HBox()); + Backmethod = Gtk::manage (new MyComboBoxText ()); + Backmethod->append_text (M("TP_WAVELET_B0")); + Backmethod->append_text (M("TP_WAVELET_B1")); + Backmethod->append_text (M("TP_WAVELET_B2")); + Backmethodconn = Backmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::BackmethodChanged) ); + backgroundLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_BACKGROUND") + ":")); + backgroundHBox->pack_start(*backgroundLabel, Gtk::PACK_SHRINK, 4); + backgroundHBox->pack_start(*Backmethod); - levdirMainHBox = Gtk::manage (new Gtk::HBox()); - CLmethod = Gtk::manage (new MyComboBoxText ()); - CLmethod->append_text (M("TP_WAVELET_LEVDIR_ONE")); - CLmethod->append_text (M("TP_WAVELET_LEVDIR_INF")); - CLmethod->append_text (M("TP_WAVELET_LEVDIR_SUP")); - CLmethod->append_text (M("TP_WAVELET_LEVDIR_ALL")); - CLmethodconn = CLmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CLmethodChanged) ); - levdirMainLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_PROC") + ":")); - levdirMainHBox->pack_start(*levdirMainLabel, Gtk::PACK_SHRINK, 4); - levdirMainHBox->pack_start(*CLmethod); //same + levdirMainHBox = Gtk::manage (new Gtk::HBox()); + CLmethod = Gtk::manage (new MyComboBoxText ()); + CLmethod->append_text (M("TP_WAVELET_LEVDIR_ONE")); + CLmethod->append_text (M("TP_WAVELET_LEVDIR_INF")); + CLmethod->append_text (M("TP_WAVELET_LEVDIR_SUP")); + CLmethod->append_text (M("TP_WAVELET_LEVDIR_ALL")); + CLmethodconn = CLmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CLmethodChanged) ); + levdirMainLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_PROC") + ":")); + levdirMainHBox->pack_start(*levdirMainLabel, Gtk::PACK_SHRINK, 4); + levdirMainHBox->pack_start(*CLmethod); //same - levdirSubHBox = Gtk::manage (new Gtk::HBox()); - Lmethod = Gtk::manage (new MyComboBoxText ()); - Lmethod->set_sensitive(false); - Lmethod->set_sensitive(false); - Lmethod->append_text (M("TP_WAVELET_1")); - Lmethod->append_text (M("TP_WAVELET_2")); - Lmethod->append_text (M("TP_WAVELET_3")); - Lmethod->append_text (M("TP_WAVELET_4")); - Lmethod->append_text (M("TP_WAVELET_5")); - Lmethod->append_text (M("TP_WAVELET_6")); - Lmethod->append_text (M("TP_WAVELET_7")); - Lmethod->append_text (M("TP_WAVELET_8")); - Lmethod->append_text (M("TP_WAVELET_9")); - Lmethod->append_text (M("TP_WAVELET_SUPE")); - Lmethod->append_text (M("TP_WAVELET_RESID")); - Lmethod->set_active(0); - Dirmethod = Gtk::manage (new MyComboBoxText ()); - Dirmethod->set_sensitive(false); - Dirmethod->append_text (M("TP_WAVELET_DONE")); - Dirmethod->append_text (M("TP_WAVELET_DTWO")); - Dirmethod->append_text (M("TP_WAVELET_DTHR")); - Dirmethod->append_text (M("TP_WAVELET_DALL")); - Lmethodconn = Lmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::LmethodChanged) ); - Dirmethodconn = Dirmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::DirmethodChanged) ); - levdirSubHBox->pack_start(*Lmethod); - levdirSubHBox->pack_start(*Dirmethod, Gtk::PACK_EXPAND_WIDGET, 2); // same, but 2 not 4? + levdirSubHBox = Gtk::manage (new Gtk::HBox()); + Lmethod = Gtk::manage (new MyComboBoxText ()); + Lmethod->set_sensitive(false); + Lmethod->set_sensitive(false); + Lmethod->append_text (M("TP_WAVELET_1")); + Lmethod->append_text (M("TP_WAVELET_2")); + Lmethod->append_text (M("TP_WAVELET_3")); + Lmethod->append_text (M("TP_WAVELET_4")); + Lmethod->append_text (M("TP_WAVELET_5")); + Lmethod->append_text (M("TP_WAVELET_6")); + Lmethod->append_text (M("TP_WAVELET_7")); + Lmethod->append_text (M("TP_WAVELET_8")); + Lmethod->append_text (M("TP_WAVELET_9")); + Lmethod->append_text (M("TP_WAVELET_SUPE")); + Lmethod->append_text (M("TP_WAVELET_RESID")); + Lmethod->set_active(0); + Dirmethod = Gtk::manage (new MyComboBoxText ()); + Dirmethod->set_sensitive(false); + Dirmethod->append_text (M("TP_WAVELET_DONE")); + Dirmethod->append_text (M("TP_WAVELET_DTWO")); + Dirmethod->append_text (M("TP_WAVELET_DTHR")); + Dirmethod->append_text (M("TP_WAVELET_DALL")); + Lmethodconn = Lmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::LmethodChanged) ); + Dirmethodconn = Dirmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::DirmethodChanged) ); + levdirSubHBox->pack_start(*Lmethod); + levdirSubHBox->pack_start(*Dirmethod, Gtk::PACK_EXPAND_WIDGET, 2); // same, but 2 not 4? - settingsVBox->pack_start(*strength); - settingsVBox->pack_start(*thres); - settingsVBox->pack_start(*tilesizeHBox); - settingsVBox->pack_start(*daubcoeffHBox); - settingsVBox->pack_start(*backgroundHBox); - settingsVBox->pack_start(*levdirMainHBox); - settingsVBox->pack_start(*levdirSubHBox); + settingsVBox->pack_start(*strength); + settingsVBox->pack_start(*thres); + settingsVBox->pack_start(*tilesizeHBox); + settingsVBox->pack_start(*daubcoeffHBox); + settingsVBox->pack_start(*backgroundHBox); + settingsVBox->pack_start(*levdirMainHBox); + settingsVBox->pack_start(*levdirSubHBox); // Contrast - Gtk::VBox * levBox = Gtk::manage (new Gtk::VBox()); - levBox->set_border_width(4); - levBox->set_spacing(2); - - - Gtk::HBox * buttonBox = Gtk::manage (new Gtk::HBox(true, 10)); - wavLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); - levBox->pack_start(*buttonBox, Gtk::PACK_SHRINK, 2); + Gtk::VBox * levBox = Gtk::manage (new Gtk::VBox()); + levBox->set_border_width(4); + levBox->set_spacing(2); - Gtk::Button * contrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_CONTRAST_MINUS"))); - buttonBox->pack_start(*contrastMinusButton); - contrastMinusPressedConn = contrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::contrastMinusPressed)); - Gtk::Button * neutralButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_NEUTRAL"))); - buttonBox->pack_start(*neutralButton); - neutralPressedConn = neutralButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::neutralPressed)); + Gtk::HBox * buttonBox = Gtk::manage (new Gtk::HBox(true, 10)); + wavLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + levBox->pack_start(*buttonBox, Gtk::PACK_SHRINK, 2); - Gtk::Button * contrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_CONTRAST_PLUS"))); - buttonBox->pack_start(*contrastPlusButton); - contrastPlusPressedConn = contrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::contrastPlusPressed)); + Gtk::Button * contrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_CONTRAST_MINUS"))); + buttonBox->pack_start(*contrastMinusButton); + contrastMinusPressedConn = contrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::contrastMinusPressed)); - buttonBox->show_all_children(); + Gtk::Button * neutralButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_NEUTRAL"))); + buttonBox->pack_start(*neutralButton); + neutralPressedConn = neutralButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::neutralPressed)); - for(int i = 0; i < 9; i++) - { - Glib::ustring ss; - switch( i ){ - case 0: - ss =Glib::ustring::compose( "%1 (%2)",(i+1), M("TP_WAVELET_FINEST"));break; - case 8: - ss =Glib::ustring::compose( "%1 (%2)",(i+1), M("TP_WAVELET_LARGEST"));break; - default: - ss =Glib::ustring::compose( "%1",(i+1)); - } + Gtk::Button * contrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_CONTRAST_PLUS"))); + buttonBox->pack_start(*contrastPlusButton); + contrastPlusPressedConn = contrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::contrastPlusPressed)); - correction[i] = Gtk::manage ( new Adjuster (ss, -100, 350, 1, 0) ); - correction[i]->setAdjusterListener(this); - levBox->pack_start(*correction[i]); - } - sup = Gtk::manage (new Adjuster (M("TP_WAVELET_SUPE"), -100, 350, 1, 0)); - levBox->pack_start(*sup); - sup->setAdjusterListener (this); - wavLabels->show(); - levBox->pack_start (*wavLabels); - - contrastSHFrame = Gtk::manage (new Gtk::Frame (M("TP_WAVELET_APPLYTO"))); - contrastSHVBox = Gtk::manage (new Gtk::VBox); - contrastSHVBox->set_border_width(4); - contrastSHVBox->set_spacing(2); + buttonBox->show_all_children(); - HSmethod = Gtk::manage (new MyComboBoxText ()); - HSmethod->append_text (M("TP_WAVELET_HS1")); - HSmethod->append_text (M("TP_WAVELET_HS2")); - HSmethodconn = HSmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::HSmethodChanged) ); + for(int i = 0; i < 9; i++) { + Glib::ustring ss; - hllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HIGHLIGHT"), 0., 100., 50., 75., 100., 98., 0, false)); - hllev->setAdjusterListener (this); - hllev->setBgGradient(milestones2); - - threshold = Gtk::manage (new Adjuster (M("TP_WAVELET_THRESHOLD"), 1, 9, 1, 5)); - threshold->setAdjusterListener (this); - threshold->set_tooltip_text (M("TP_WAVELET_THRESHOLD_TOOLTIP")); + switch( i ) { + case 0: + ss = Glib::ustring::compose( "%1 (%2)", (i + 1), M("TP_WAVELET_FINEST")); + break; - bllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LOWLIGHT"), 0., 100., 0., 2., 50., 25., 0, false)); - bllev->setAdjusterListener (this); - bllev->setBgGradient(milestones2); - - threshold2 = Gtk::manage (new Adjuster (M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 4)); - threshold2->setAdjusterListener (this); - threshold2->set_tooltip_text (M("TP_WAVELET_THRESHOLD2_TOOLTIP")); + case 8: + ss = Glib::ustring::compose( "%1 (%2)", (i + 1), M("TP_WAVELET_LARGEST")); + break; - contrastSHVBox->pack_start(*HSmethod); //remove 2? - contrastSHVBox->pack_start(*hllev); - contrastSHVBox->pack_start(*threshold); - contrastSHVBox->pack_start(*bllev); - contrastSHVBox->pack_start(*threshold2); - contrastSHFrame->add(*contrastSHVBox); - levBox->pack_start(*contrastSHFrame); + default: + ss = Glib::ustring::compose( "%1", (i + 1)); + } + + correction[i] = Gtk::manage ( new Adjuster (ss, -100, 350, 1, 0) ); + correction[i]->setAdjusterListener(this); + levBox->pack_start(*correction[i]); + } + + sup = Gtk::manage (new Adjuster (M("TP_WAVELET_SUPE"), -100, 350, 1, 0)); + levBox->pack_start(*sup); + sup->setAdjusterListener (this); + wavLabels->show(); + levBox->pack_start (*wavLabels); + + contrastSHFrame = Gtk::manage (new Gtk::Frame (M("TP_WAVELET_APPLYTO"))); + contrastSHVBox = Gtk::manage (new Gtk::VBox); + contrastSHVBox->set_border_width(4); + contrastSHVBox->set_spacing(2); + + HSmethod = Gtk::manage (new MyComboBoxText ()); + HSmethod->append_text (M("TP_WAVELET_HS1")); + HSmethod->append_text (M("TP_WAVELET_HS2")); + HSmethodconn = HSmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::HSmethodChanged) ); + + hllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HIGHLIGHT"), 0., 100., 50., 75., 100., 98., 0, false)); + hllev->setAdjusterListener (this); + hllev->setBgGradient(milestones2); + + threshold = Gtk::manage (new Adjuster (M("TP_WAVELET_THRESHOLD"), 1, 9, 1, 5)); + threshold->setAdjusterListener (this); + threshold->set_tooltip_text (M("TP_WAVELET_THRESHOLD_TOOLTIP")); + + bllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LOWLIGHT"), 0., 100., 0., 2., 50., 25., 0, false)); + bllev->setAdjusterListener (this); + bllev->setBgGradient(milestones2); + + threshold2 = Gtk::manage (new Adjuster (M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 4)); + threshold2->setAdjusterListener (this); + threshold2->set_tooltip_text (M("TP_WAVELET_THRESHOLD2_TOOLTIP")); + + contrastSHVBox->pack_start(*HSmethod); //remove 2? + contrastSHVBox->pack_start(*hllev); + contrastSHVBox->pack_start(*threshold); + contrastSHVBox->pack_start(*bllev); + contrastSHVBox->pack_start(*threshold2); + contrastSHFrame->add(*contrastSHVBox); + levBox->pack_start(*contrastSHFrame); // Chromaticity - Gtk::VBox * chBox = Gtk::manage (new Gtk::VBox()); - chBox->set_border_width(4); - chBox->set_spacing(2); + Gtk::VBox * chBox = Gtk::manage (new Gtk::VBox()); + chBox->set_border_width(4); + chBox->set_spacing(2); - ctboxch = Gtk::manage (new Gtk::HBox ()); - labmch = Gtk::manage (new Gtk::Label (M("TP_WAVELET_CHTYPE")+":")); - ctboxch->pack_start (*labmch, Gtk::PACK_SHRINK, 1); - - CHmethod = Gtk::manage (new MyComboBoxText ()); - CHmethod->append_text (M("TP_WAVELET_CH1")); - CHmethod->append_text (M("TP_WAVELET_CH2")); - CHmethod->append_text (M("TP_WAVELET_CH3")); - CHmethodconn = CHmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CHmethodChanged) ); - ctboxch->pack_start(*CHmethod); - chBox->pack_start(*ctboxch); + ctboxch = Gtk::manage (new Gtk::HBox ()); + labmch = Gtk::manage (new Gtk::Label (M("TP_WAVELET_CHTYPE") + ":")); + ctboxch->pack_start (*labmch, Gtk::PACK_SHRINK, 1); - ctboxCH = Gtk::manage (new Gtk::HBox ()); - labmC = Gtk::manage (new Gtk::Label (M("TP_WAVELET_CTYPE")+":")); - ctboxCH->pack_start (*labmC, Gtk::PACK_SHRINK, 1); - - CHSLmethod = Gtk::manage (new MyComboBoxText ()); - CHSLmethod->append_text (M("TP_WAVELET_CHSL")); - CHSLmethod->append_text (M("TP_WAVELET_CHCU")); - CHSLmethodconn = CHSLmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CHSLmethodChanged) ); - ctboxCH->pack_start(*CHSLmethod); - - Gtk::HSeparator *separatorChromaMethod = Gtk::manage (new Gtk::HSeparator()); - chBox->pack_start(*separatorChromaMethod, Gtk::PACK_SHRINK, 2); - - chroma = Gtk::manage (new Adjuster (M("TP_WAVELET_CHRO"), 1, 9, 1, 5)); - chroma->set_tooltip_text (M("TP_WAVELET_CHRO_TOOLTIP")); - chBox->pack_start(*chroma); - chroma->setAdjusterListener (this); + CHmethod = Gtk::manage (new MyComboBoxText ()); + CHmethod->append_text (M("TP_WAVELET_CH1")); + CHmethod->append_text (M("TP_WAVELET_CH2")); + CHmethod->append_text (M("TP_WAVELET_CH3")); + CHmethodconn = CHmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CHmethodChanged) ); + ctboxch->pack_start(*CHmethod); + chBox->pack_start(*ctboxch); - satlev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_SAT"), 0., 130., 30., 45., 130., 100., 0, false)); - satlev->setAdjusterListener (this); - satlev->setBgGradient(milestones2); + ctboxCH = Gtk::manage (new Gtk::HBox ()); + labmC = Gtk::manage (new Gtk::Label (M("TP_WAVELET_CTYPE") + ":")); + ctboxCH->pack_start (*labmC, Gtk::PACK_SHRINK, 1); - pastlev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_PASTEL"), 0., 70., 0., 2., 30., 20., 0, false)); - pastlev->setAdjusterListener (this); - pastlev->setBgGradient(milestones2); - - chBox->pack_start(*pastlev); - chBox->pack_start(*satlev); + CHSLmethod = Gtk::manage (new MyComboBoxText ()); + CHSLmethod->append_text (M("TP_WAVELET_CHSL")); + CHSLmethod->append_text (M("TP_WAVELET_CHCU")); + CHSLmethodconn = CHSLmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CHSLmethodChanged) ); + ctboxCH->pack_start(*CHSLmethod); - chro = Gtk::manage (new Adjuster (M("TP_WAVELET_CHR"), 0., 100., 1., 0.)); - chro->set_tooltip_text (M("TP_WAVELET_CHR_TOOLTIP")); - chBox->pack_start(*chro); - chro->setAdjusterListener (this); - - Gtk::HBox * buttonchBox = Gtk::manage (new Gtk::HBox(true, 10)); - neutralchButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_NEUTRAL"))); - neutralchPressedConn = neutralchButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::neutralchPressed)); - separatorNeutral = Gtk::manage (new Gtk::HSeparator()); - chBox->pack_start(*separatorNeutral, Gtk::PACK_SHRINK, 2); - buttonchBox->pack_start(*neutralchButton); - buttonchBox->show_all_children(); - chBox->pack_start(*buttonchBox, Gtk::PACK_SHRINK, 2); + Gtk::HSeparator *separatorChromaMethod = Gtk::manage (new Gtk::HSeparator()); + chBox->pack_start(*separatorChromaMethod, Gtk::PACK_SHRINK, 2); - for(int i = 0; i < 9; i++) - { - Glib::ustring ss; - switch( i ){ - case 0: - ss =Glib::ustring::compose( "%1 (%2)",(i+1), M("TP_WAVELET_FINEST"));break; - case 8: - ss =Glib::ustring::compose( "%1 (%2)",(i+1), M("TP_WAVELET_LARGEST"));break; - default: - ss =Glib::ustring::compose( "%1",(i+1)); - } + chroma = Gtk::manage (new Adjuster (M("TP_WAVELET_CHRO"), 1, 9, 1, 5)); + chroma->set_tooltip_text (M("TP_WAVELET_CHRO_TOOLTIP")); + chBox->pack_start(*chroma); + chroma->setAdjusterListener (this); - correctionch[i] = Gtk::manage ( new Adjuster (ss, -100, 100, 1, 0) ); - correctionch[i]->setAdjusterListener(this); - chBox->pack_start(*correctionch[i]); - } + satlev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_SAT"), 0., 130., 30., 45., 130., 100., 0, false)); + satlev->setAdjusterListener (this); + satlev->setBgGradient(milestones2); + + pastlev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_PASTEL"), 0., 70., 0., 2., 30., 20., 0, false)); + pastlev->setAdjusterListener (this); + pastlev->setBgGradient(milestones2); + + chBox->pack_start(*pastlev); + chBox->pack_start(*satlev); + + chro = Gtk::manage (new Adjuster (M("TP_WAVELET_CHR"), 0., 100., 1., 0.)); + chro->set_tooltip_text (M("TP_WAVELET_CHR_TOOLTIP")); + chBox->pack_start(*chro); + chro->setAdjusterListener (this); + + Gtk::HBox * buttonchBox = Gtk::manage (new Gtk::HBox(true, 10)); + neutralchButton = Gtk::manage (new Gtk::Button(M("TP_WAVELET_NEUTRAL"))); + neutralchPressedConn = neutralchButton->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::neutralchPressed)); + separatorNeutral = Gtk::manage (new Gtk::HSeparator()); + chBox->pack_start(*separatorNeutral, Gtk::PACK_SHRINK, 2); + buttonchBox->pack_start(*neutralchButton); + buttonchBox->show_all_children(); + chBox->pack_start(*buttonchBox, Gtk::PACK_SHRINK, 2); + + for(int i = 0; i < 9; i++) { + Glib::ustring ss; + + switch( i ) { + case 0: + ss = Glib::ustring::compose( "%1 (%2)", (i + 1), M("TP_WAVELET_FINEST")); + break; + + case 8: + ss = Glib::ustring::compose( "%1 (%2)", (i + 1), M("TP_WAVELET_LARGEST")); + break; + + default: + ss = Glib::ustring::compose( "%1", (i + 1)); + } + + correctionch[i] = Gtk::manage ( new Adjuster (ss, -100, 100, 1, 0) ); + correctionch[i]->setAdjusterListener(this); + chBox->pack_start(*correctionch[i]); + } // Toning - Gtk::VBox * tonBox = Gtk::manage (new Gtk::VBox()); - tonBox->set_border_width(4); - tonBox->set_spacing(2); + Gtk::VBox * tonBox = Gtk::manage (new Gtk::VBox()); + tonBox->set_border_width(4); + tonBox->set_spacing(2); - opaCurveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_COLORT")); - opaCurveEditorG->setCurveListener (this); + opaCurveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_COLORT")); + opaCurveEditorG->setCurveListener (this); - rtengine::WaveletParams::getDefaultOpacityCurveRG(defaultCurve); - opacityShapeRG = static_cast(opaCurveEditorG->addCurve(CT_Flat, "", NULL, false)); - opacityShapeRG->setIdentityValue(0.); - opacityShapeRG->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + rtengine::WaveletParams::getDefaultOpacityCurveRG(defaultCurve); + opacityShapeRG = static_cast(opaCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + opacityShapeRG->setIdentityValue(0.); + opacityShapeRG->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - opaCurveEditorG->curveListComplete(); - opaCurveEditorG->show(); + opaCurveEditorG->curveListComplete(); + opaCurveEditorG->show(); - tonBox->pack_start( *opaCurveEditorG, Gtk::PACK_SHRINK, 2); + tonBox->pack_start( *opaCurveEditorG, Gtk::PACK_SHRINK, 2); - opacityCurveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITY")); - opacityCurveEditorG->setCurveListener (this); + opacityCurveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITY")); + opacityCurveEditorG->setCurveListener (this); - rtengine::WaveletParams::getDefaultOpacityCurveBY(defaultCurve); - opacityShapeBY = static_cast(opacityCurveEditorG->addCurve(CT_Flat, "", NULL, false)); - opacityShapeBY->setIdentityValue(0.); - opacityShapeBY->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + rtengine::WaveletParams::getDefaultOpacityCurveBY(defaultCurve); + opacityShapeBY = static_cast(opacityCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + opacityShapeBY->setIdentityValue(0.); + opacityShapeBY->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - opacityCurveEditorG->curveListComplete(); - opacityCurveEditorG->show(); + opacityCurveEditorG->curveListComplete(); + opacityCurveEditorG->show(); - tonBox->pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); + tonBox->pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); // Denoise and Refine - Gtk::VBox * noiseBox = Gtk::manage (new Gtk::VBox()); - noiseBox->set_border_width(4); - noiseBox->set_spacing(2); + Gtk::VBox * noiseBox = Gtk::manage (new Gtk::VBox()); + noiseBox->set_border_width(4); + noiseBox->set_spacing(2); - linkedg = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_LINKEDG"))); - linkedg->set_active (true); - linkedgConn = linkedg->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::linkedgToggled) ); - noiseBox->pack_start(*linkedg); + linkedg = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_LINKEDG"))); + linkedg->set_active (true); + linkedgConn = linkedg->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::linkedgToggled) ); + noiseBox->pack_start(*linkedg); - level0noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVZERO"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); - level0noise->setAdjusterListener (this); - level0noise->setUpdatePolicy(RTUP_DYNAMIC); + level0noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVZERO"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); + level0noise->setAdjusterListener (this); + level0noise->setUpdatePolicy(RTUP_DYNAMIC); - level1noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVONE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); - level1noise->setAdjusterListener (this); - level1noise->setUpdatePolicy(RTUP_DYNAMIC); + level1noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVONE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); + level1noise->setAdjusterListener (this); + level1noise->setUpdatePolicy(RTUP_DYNAMIC); - level2noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVTWO"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); - level2noise->setAdjusterListener (this); - level2noise->setUpdatePolicy(RTUP_DYNAMIC); + level2noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVTWO"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); + level2noise->setAdjusterListener (this); + level2noise->setUpdatePolicy(RTUP_DYNAMIC); - level3noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVTHRE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); - level3noise->setAdjusterListener (this); - level3noise->setUpdatePolicy(RTUP_DYNAMIC); + level3noise = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LEVTHRE"), -30., 100., 0., M("TP_WAVELET_STREN"), 1., 0., 100., 0., M("TP_WAVELET_NOIS"), 1., NULL, false)); + level3noise->setAdjusterListener (this); + level3noise->setUpdatePolicy(RTUP_DYNAMIC); - noiseBox->pack_start( *level0noise, Gtk::PACK_SHRINK, 0); - noiseBox->pack_start( *level1noise, Gtk::PACK_SHRINK, 0); - noiseBox->pack_start( *level2noise, Gtk::PACK_SHRINK, 0); - noiseBox->pack_start( *level3noise, Gtk::PACK_SHRINK, 0); + noiseBox->pack_start( *level0noise, Gtk::PACK_SHRINK, 0); + noiseBox->pack_start( *level1noise, Gtk::PACK_SHRINK, 0); + noiseBox->pack_start( *level2noise, Gtk::PACK_SHRINK, 0); + noiseBox->pack_start( *level3noise, Gtk::PACK_SHRINK, 0); // Edge Sharpness - Gtk::VBox * edgBox = Gtk::manage (new Gtk::VBox()); - edgBox->set_border_width(4); - edgBox->set_spacing(2); + Gtk::VBox * edgBox = Gtk::manage (new Gtk::VBox()); + edgBox->set_border_width(4); + edgBox->set_spacing(2); - edgval = Gtk::manage ( new Adjuster (M("TP_WAVELET_EDVAL"), 0, 100, 1, 0) ); - edgval->setAdjusterListener(this); - edgBox->pack_start(*edgval); + edgval = Gtk::manage ( new Adjuster (M("TP_WAVELET_EDVAL"), 0, 100, 1, 0) ); + edgval->setAdjusterListener(this); + edgBox->pack_start(*edgval); - edgrad = Gtk::manage ( new Adjuster (M("TP_WAVELET_EDRAD"), 0, 100, 1, 15) ); - edgrad->setAdjusterListener(this); - edgBox->pack_start(*edgrad); - edgrad->set_tooltip_markup (M("TP_WAVELET_EDRAD_TOOLTIP")); + edgrad = Gtk::manage ( new Adjuster (M("TP_WAVELET_EDRAD"), 0, 100, 1, 15) ); + edgrad->setAdjusterListener(this); + edgBox->pack_start(*edgrad); + edgrad->set_tooltip_markup (M("TP_WAVELET_EDRAD_TOOLTIP")); - edgthresh = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGTHRESH"), -50, 100, 1, 10 )); - edgthresh->setAdjusterListener (this); - edgthresh->set_tooltip_markup (M("TP_WAVELET_EDGTHRESH_TOOLTIP")); - edgBox->pack_start (*edgthresh); + edgthresh = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGTHRESH"), -50, 100, 1, 10 )); + edgthresh->setAdjusterListener (this); + edgthresh->set_tooltip_markup (M("TP_WAVELET_EDGTHRESH_TOOLTIP")); + edgBox->pack_start (*edgthresh); - edbox = Gtk::manage (new Gtk::HBox ()); - labmedgr = Gtk::manage (new Gtk::Label (M("TP_WAVELET_MEDGREINF")+":")); - edbox->pack_start (*labmedgr, Gtk::PACK_SHRINK, 1); + edbox = Gtk::manage (new Gtk::HBox ()); + labmedgr = Gtk::manage (new Gtk::Label (M("TP_WAVELET_MEDGREINF") + ":")); + edbox->pack_start (*labmedgr, Gtk::PACK_SHRINK, 1); - Medgreinf = Gtk::manage (new MyComboBoxText ()); - Medgreinf->append_text (M("TP_WAVELET_RE1")); - Medgreinf->append_text (M("TP_WAVELET_RE2")); - Medgreinf->append_text (M("TP_WAVELET_RE3")); - MedgreinfConn = Medgreinf->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::MedgreinfChanged) ); - Medgreinf->set_tooltip_markup (M("TP_WAVELET_EDGREINF_TOOLTIP")); - edbox->pack_start(*Medgreinf); - edgBox->pack_start(*edbox); + Medgreinf = Gtk::manage (new MyComboBoxText ()); + Medgreinf->append_text (M("TP_WAVELET_RE1")); + Medgreinf->append_text (M("TP_WAVELET_RE2")); + Medgreinf->append_text (M("TP_WAVELET_RE3")); + MedgreinfConn = Medgreinf->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::MedgreinfChanged) ); + Medgreinf->set_tooltip_markup (M("TP_WAVELET_EDGREINF_TOOLTIP")); + edbox->pack_start(*Medgreinf); + edgBox->pack_start(*edbox); - Gtk::HSeparator *separatorlc = Gtk::manage (new Gtk::HSeparator()); - edgBox->pack_start(*separatorlc, Gtk::PACK_SHRINK, 2); + Gtk::HSeparator *separatorlc = Gtk::manage (new Gtk::HSeparator()); + edgBox->pack_start(*separatorlc, Gtk::PACK_SHRINK, 2); - ctboxED = Gtk::manage (new Gtk::HBox ()); - labmED = Gtk::manage (new Gtk::Label (M("TP_WAVELET_EDTYPE")+":")); - ctboxED->pack_start (*labmED, Gtk::PACK_SHRINK, 1); + ctboxED = Gtk::manage (new Gtk::HBox ()); + labmED = Gtk::manage (new Gtk::Label (M("TP_WAVELET_EDTYPE") + ":")); + ctboxED->pack_start (*labmED, Gtk::PACK_SHRINK, 1); - EDmethod = Gtk::manage (new MyComboBoxText ()); - EDmethod->append_text (M("TP_WAVELET_EDSL")); - EDmethod->append_text (M("TP_WAVELET_EDCU")); - EDmethodconn = EDmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::EDmethodChanged) ); - ctboxED->pack_start(*EDmethod); - edgBox->pack_start (*ctboxED); - tr=options.rtSettings.top_right; - br=options.rtSettings.bot_right; - tl=options.rtSettings.top_left; - bl=options.rtSettings.bot_left; + EDmethod = Gtk::manage (new MyComboBoxText ()); + EDmethod->append_text (M("TP_WAVELET_EDSL")); + EDmethod->append_text (M("TP_WAVELET_EDCU")); + EDmethodconn = EDmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::EDmethodChanged) ); + ctboxED->pack_start(*EDmethod); + edgBox->pack_start (*ctboxED); + tr = options.rtSettings.top_right; + br = options.rtSettings.bot_right; + tl = options.rtSettings.top_left; + bl = options.rtSettings.bot_left; - edgcont = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_EDGCONT"), 0., 100., bl, tl, br, tr, 0., false)); - edgcont->setAdjusterListener (this); - edgcont->setBgGradient(milestones2); - edgcont->set_tooltip_markup (M("TP_WAVELET_EDGCONT_TOOLTIP")); + edgcont = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_EDGCONT"), 0., 100., bl, tl, br, tr, 0., false)); + edgcont->setAdjusterListener (this); + edgcont->setBgGradient(milestones2); + edgcont->set_tooltip_markup (M("TP_WAVELET_EDGCONT_TOOLTIP")); - // <-- Edge Sharpness Local Contrast curve - CCWcurveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE")); - CCWcurveEditorG->setCurveListener (this); + // <-- Edge Sharpness Local Contrast curve + CCWcurveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_CCURVE")); + CCWcurveEditorG->setCurveListener (this); - rtengine::WaveletParams::getDefaultCCWCurve(defaultCurve); - ccshape = static_cast(CCWcurveEditorG->addCurve(CT_Flat, "", NULL, false)); + rtengine::WaveletParams::getDefaultCCWCurve(defaultCurve); + ccshape = static_cast(CCWcurveEditorG->addCurve(CT_Flat, "", NULL, false)); - ccshape->setIdentityValue(0.); - ccshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - ccshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CC_TOOLTIP")); + ccshape->setIdentityValue(0.); + ccshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + ccshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CC_TOOLTIP")); - CCWcurveEditorG->curveListComplete(); - CCWcurveEditorG->show(); - // --> + CCWcurveEditorG->curveListComplete(); + CCWcurveEditorG->show(); + // --> - edgBox->pack_start (*edgcont); - edgBox->pack_start(*CCWcurveEditorG, Gtk::PACK_SHRINK, 4); + edgBox->pack_start (*edgcont); + edgBox->pack_start(*CCWcurveEditorG, Gtk::PACK_SHRINK, 4); - medianlev = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_MEDILEV"))); - medianlev->set_active (true); - medianlevConn = medianlev->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::medianlevToggled) ); - medianlev->set_tooltip_text (M("TP_WAVELET_MEDILEV_TOOLTIP")); + medianlev = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_MEDILEV"))); + medianlev->set_active (true); + medianlevConn = medianlev->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::medianlevToggled) ); + medianlev->set_tooltip_text (M("TP_WAVELET_MEDILEV_TOOLTIP")); - Gtk::HSeparator *separatored1 = Gtk::manage (new Gtk::HSeparator()); - edgBox->pack_start(*separatored1, Gtk::PACK_SHRINK, 2); + Gtk::HSeparator *separatored1 = Gtk::manage (new Gtk::HSeparator()); + edgBox->pack_start(*separatored1, Gtk::PACK_SHRINK, 2); - eddebox = Gtk::manage (new Gtk::HBox ()); + eddebox = Gtk::manage (new Gtk::HBox ()); - edgBox->pack_start (*eddebox); - edgBox->pack_start(*medianlev); + edgBox->pack_start (*eddebox); + edgBox->pack_start(*medianlev); - edgedetect = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEDETECT"), 0, 100, 1, 90)); - edgedetect->setAdjusterListener (this); - edgedetect->set_tooltip_text (M("TP_WAVELET_EDGEDETECT_TOOLTIP")); - edgBox->pack_start(*edgedetect); + edgedetect = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEDETECT"), 0, 100, 1, 90)); + edgedetect->setAdjusterListener (this); + edgedetect->set_tooltip_text (M("TP_WAVELET_EDGEDETECT_TOOLTIP")); + edgBox->pack_start(*edgedetect); - edgedetectthr = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEDETECTTHR"), 0, 100, 1, 20)); - edgedetectthr->setAdjusterListener (this); - edgedetectthr->set_tooltip_text (M("TP_WAVELET_EDGEDETECTTHR_TOOLTIP")); - edgBox->pack_start(*edgedetectthr); + edgedetectthr = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEDETECTTHR"), 0, 100, 1, 20)); + edgedetectthr->setAdjusterListener (this); + edgedetectthr->set_tooltip_text (M("TP_WAVELET_EDGEDETECTTHR_TOOLTIP")); + edgBox->pack_start(*edgedetectthr); - edgedetectthr2 = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEDETECTTHR2"), -10, 100, 1, 0)); - edgedetectthr2->setAdjusterListener (this); - edgBox->pack_start(*edgedetectthr2); + edgedetectthr2 = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEDETECTTHR2"), -10, 100, 1, 0)); + edgedetectthr2->setAdjusterListener (this); + edgBox->pack_start(*edgedetectthr2); - separatoredge = Gtk::manage (new Gtk::HSeparator()); + separatoredge = Gtk::manage (new Gtk::HSeparator()); - edgBox->pack_start(*separatoredge, Gtk::PACK_SHRINK, 2); - - lipst = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_LIPST"))); - lipst->set_active (true); - lipstConn = lipst->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::lipstToggled) ); -// lipst->set_tooltip_text (M("TP_WAVELET_LIPST_TOOLTIP")); - edgBox->pack_start(*lipst); - - edgesensi = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGESENSI"), 0, 100, 1, 60)); - edgesensi->setAdjusterListener (this); - edgBox->pack_start(*edgesensi); + edgBox->pack_start(*separatoredge, Gtk::PACK_SHRINK, 2); + + lipst = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_LIPST"))); + lipst->set_active (true); + lipstConn = lipst->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::lipstToggled) ); +// lipst->set_tooltip_text (M("TP_WAVELET_LIPST_TOOLTIP")); + edgBox->pack_start(*lipst); + + edgesensi = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGESENSI"), 0, 100, 1, 60)); + edgesensi->setAdjusterListener (this); + edgBox->pack_start(*edgesensi); - edgeampli = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEAMPLI"), 0, 100, 1, 10)); - edgeampli->setAdjusterListener (this); - edgBox->pack_start(*edgeampli); - + edgeampli = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGEAMPLI"), 0, 100, 1, 10)); + edgeampli->setAdjusterListener (this); + edgBox->pack_start(*edgeampli); - Gtk::VBox * ctboxES = Gtk::manage (new Gtk::VBox()); - ctboxES->set_border_width(4); - ctboxES->set_spacing(2); + Gtk::VBox * ctboxES = Gtk::manage (new Gtk::VBox()); - ctboxNP = Gtk::manage (new Gtk::HBox()); + ctboxES->set_border_width(4); + ctboxES->set_spacing(2); - labmNP = Gtk::manage (new Gtk::Label (M("TP_WAVELET_NPTYPE")+":")); - ctboxNP->pack_start (*labmNP, Gtk::PACK_SHRINK, 1); + ctboxNP = Gtk::manage (new Gtk::HBox()); + + labmNP = Gtk::manage (new Gtk::Label (M("TP_WAVELET_NPTYPE") + ":")); + ctboxNP->pack_start (*labmNP, Gtk::PACK_SHRINK, 1); + + NPmethod = Gtk::manage (new MyComboBoxText ()); + NPmethod->append_text (M("TP_WAVELET_NPNONE")); + NPmethod->append_text (M("TP_WAVELET_NPLOW")); + NPmethod->append_text (M("TP_WAVELET_NPHIGH")); + NPmethodconn = NPmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::NPmethodChanged) ); + NPmethod->set_tooltip_text (M("TP_WAVELET_NPTYPE_TOOLTIP")); + + ctboxNP->pack_start(*NPmethod); + ctboxES->pack_start(*ctboxNP); + + edgBox->pack_start(*ctboxES); - NPmethod = Gtk::manage (new MyComboBoxText ()); - NPmethod->append_text (M("TP_WAVELET_NPNONE")); - NPmethod->append_text (M("TP_WAVELET_NPLOW")); - NPmethod->append_text (M("TP_WAVELET_NPHIGH")); - NPmethodconn = NPmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::NPmethodChanged) ); - NPmethod->set_tooltip_text (M("TP_WAVELET_NPTYPE_TOOLTIP")); - - ctboxNP->pack_start(*NPmethod); - ctboxES->pack_start(*ctboxNP); - - edgBox->pack_start(*ctboxES); - // Gamut - Gtk::VBox * conBox = Gtk::manage (new Gtk::VBox()); - conBox->set_border_width(4); - conBox->set_spacing(2); + Gtk::VBox * conBox = Gtk::manage (new Gtk::VBox()); + conBox->set_border_width(4); + conBox->set_spacing(2); - median = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_MEDI"))); - median->set_active (true); - medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::medianToggled) ); - conBox->pack_start(*median); + median = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_MEDI"))); + median->set_active (true); + medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::medianToggled) ); + conBox->pack_start(*median); - hueskin = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HUESKIN"), -314., 314., -5., 25., 170., 120., 0, false)); - hueskin->set_tooltip_markup (M("TP_WAVELET_HUESKIN_TOOLTIP")); + hueskin = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HUESKIN"), -314., 314., -5., 25., 170., 120., 0, false)); + hueskin->set_tooltip_markup (M("TP_WAVELET_HUESKIN_TOOLTIP")); - hueskin->setBgGradient(milestones); - conBox->pack_start(*hueskin); - hueskin->setAdjusterListener (this); + hueskin->setBgGradient(milestones); + conBox->pack_start(*hueskin); + hueskin->setAdjusterListener (this); - skinprotect = Gtk::manage ( new Adjuster (M("TP_WAVELET_SKIN"), -100, 100, 1, 0.) ); - skinprotect->setAdjusterListener(this); - conBox->pack_start(*skinprotect); - skinprotect->set_tooltip_markup (M("TP_WAVELET_SKIN_TOOLTIP")); + skinprotect = Gtk::manage ( new Adjuster (M("TP_WAVELET_SKIN"), -100, 100, 1, 0.) ); + skinprotect->setAdjusterListener(this); + conBox->pack_start(*skinprotect); + skinprotect->set_tooltip_markup (M("TP_WAVELET_SKIN_TOOLTIP")); - curveEditorGAM = new CurveEditorGroup (options.lastWaveletCurvesDir); - curveEditorGAM->setCurveListener (this); + curveEditorGAM = new CurveEditorGroup (options.lastWaveletCurvesDir); + curveEditorGAM->setCurveListener (this); - Chshape = static_cast(curveEditorGAM->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_CH"))); - Chshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CH_TOOLTIP")); - Chshape->setCurveColorProvider(this, 5); - curveEditorGAM->curveListComplete(); - Chshape->setBottomBarBgGradient(milestones); + Chshape = static_cast(curveEditorGAM->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_CH"))); + Chshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CH_TOOLTIP")); + Chshape->setCurveColorProvider(this, 5); + curveEditorGAM->curveListComplete(); + Chshape->setBottomBarBgGradient(milestones); - conBox->pack_start (*curveEditorGAM, Gtk::PACK_SHRINK, 4); + conBox->pack_start (*curveEditorGAM, Gtk::PACK_SHRINK, 4); - avoid = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_AVOID"))); - avoid->set_active (true); - avoidConn = avoid->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::avoidToggled) ); - conBox->pack_start(*avoid); + avoid = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_AVOID"))); + avoid->set_active (true); + avoidConn = avoid->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::avoidToggled) ); + conBox->pack_start(*avoid); // Residual Image - Gtk::VBox * resBox = Gtk::manage (new Gtk::VBox()); - resBox->set_border_width(4); - resBox->set_spacing(2); + Gtk::VBox * resBox = Gtk::manage (new Gtk::VBox()); + resBox->set_border_width(4); + resBox->set_spacing(2); - rescon = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCON"), -100, 100, 1, 0)); - rescon->setAdjusterListener (this); - resBox->pack_start(*rescon, Gtk::PACK_SHRINK); + rescon = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCON"), -100, 100, 1, 0)); + rescon->setAdjusterListener (this); + resBox->pack_start(*rescon, Gtk::PACK_SHRINK); - thr = Gtk::manage (new Adjuster (M("TP_WAVELET_THR"), 0, 100, 1, 35)); - resBox->pack_start(*thr); - thr->setAdjusterListener (this); + thr = Gtk::manage (new Adjuster (M("TP_WAVELET_THR"), 0, 100, 1, 35)); + resBox->pack_start(*thr); + thr->setAdjusterListener (this); - resconH = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCONH"), -100, 100, 1, 0)); - resconH->setAdjusterListener (this); - resBox->pack_start(*resconH, Gtk::PACK_SHRINK); + resconH = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCONH"), -100, 100, 1, 0)); + resconH->setAdjusterListener (this); + resBox->pack_start(*resconH, Gtk::PACK_SHRINK); - thrH = Gtk::manage (new Adjuster (M("TP_WAVELET_THRH"), 0, 100, 1, 65)); - thrH->setAdjusterListener (this); - resBox->pack_start(*thrH,Gtk::PACK_SHRINK); + thrH = Gtk::manage (new Adjuster (M("TP_WAVELET_THRH"), 0, 100, 1, 65)); + thrH->setAdjusterListener (this); + resBox->pack_start(*thrH, Gtk::PACK_SHRINK); - contrast = Gtk::manage (new Adjuster (M("TP_WAVELET_CONTRA"), -100, 100, 1, 0)); - contrast->set_tooltip_text (M("TP_WAVELET_CONTRA_TOOLTIP")); - contrast->setAdjusterListener (this); - resBox->pack_start(*contrast); //keep the possibility to reinstall - - reschro = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0)); - reschro->setAdjusterListener (this); - resBox->pack_start(*reschro); + contrast = Gtk::manage (new Adjuster (M("TP_WAVELET_CONTRA"), -100, 100, 1, 0)); + contrast->set_tooltip_text (M("TP_WAVELET_CONTRA_TOOLTIP")); + contrast->setAdjusterListener (this); + resBox->pack_start(*contrast); //keep the possibility to reinstall + + reschro = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0)); + reschro->setAdjusterListener (this); + resBox->pack_start(*reschro); - ctboxTM = Gtk::manage (new Gtk::HBox ()); - labmTM = Gtk::manage (new Gtk::Label (M("TP_WAVELET_TMTYPE")+":")); - ctboxTM->pack_start (*labmTM, Gtk::PACK_SHRINK, 1); + ctboxTM = Gtk::manage (new Gtk::HBox ()); + labmTM = Gtk::manage (new Gtk::Label (M("TP_WAVELET_TMTYPE") + ":")); + ctboxTM->pack_start (*labmTM, Gtk::PACK_SHRINK, 1); - Gtk::HSeparator *separatorR0 = Gtk::manage (new Gtk::HSeparator()); - resBox->pack_start(*separatorR0, Gtk::PACK_SHRINK, 2); + Gtk::HSeparator *separatorR0 = Gtk::manage (new Gtk::HSeparator()); + resBox->pack_start(*separatorR0, Gtk::PACK_SHRINK, 2); - TMmethod = Gtk::manage (new MyComboBoxText ()); - TMmethod->append_text (M("TP_WAVELET_COMPCONT")); - TMmethod->append_text (M("TP_WAVELET_COMPTM")); - TMmethodconn = TMmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::TMmethodChanged) ); - ctboxTM->pack_start(*TMmethod); - resBox->pack_start (*ctboxTM); + TMmethod = Gtk::manage (new MyComboBoxText ()); + TMmethod->append_text (M("TP_WAVELET_COMPCONT")); + TMmethod->append_text (M("TP_WAVELET_COMPTM")); + TMmethodconn = TMmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::TMmethodChanged) ); + ctboxTM->pack_start(*TMmethod); + resBox->pack_start (*ctboxTM); - tmrs = Gtk::manage(new Adjuster (M("TP_WAVELET_TMSTRENGTH"), -1.0, 2.0, 0.01, 0.0)); - tmrs->set_tooltip_text (M("TP_WAVELET_TMSTRENGTH_TOOLTIP")); + tmrs = Gtk::manage(new Adjuster (M("TP_WAVELET_TMSTRENGTH"), -1.0, 2.0, 0.01, 0.0)); + tmrs->set_tooltip_text (M("TP_WAVELET_TMSTRENGTH_TOOLTIP")); - resBox->pack_start(*tmrs); - tmrs->setAdjusterListener (this); + resBox->pack_start(*tmrs); + tmrs->setAdjusterListener (this); - gamma = Gtk::manage(new Adjuster (M("TP_WAVELET_COMPGAMMA"), 0.4, 2.0, 0.01, 1.0)); - gamma->set_tooltip_text (M("TP_WAVELET_COMPGAMMA_TOOLTIP")); - resBox->pack_start(*gamma); - gamma->setAdjusterListener (this); + gamma = Gtk::manage(new Adjuster (M("TP_WAVELET_COMPGAMMA"), 0.4, 2.0, 0.01, 1.0)); + gamma->set_tooltip_text (M("TP_WAVELET_COMPGAMMA_TOOLTIP")); + resBox->pack_start(*gamma); + gamma->setAdjusterListener (this); - Gtk::HSeparator *separatorR1 = Gtk::manage (new Gtk::HSeparator()); - resBox->pack_start(*separatorR1, Gtk::PACK_SHRINK, 2); + Gtk::HSeparator *separatorR1 = Gtk::manage (new Gtk::HSeparator()); + resBox->pack_start(*separatorR1, Gtk::PACK_SHRINK, 2); - hueskin2 = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HUESKY"), -314., 314., -260., -250, -130., -140., 0, false)); - hueskin2->set_tooltip_markup (M("TP_WAVELET_HUESKY_TOOLTIP")); - hueskin2->setBgGradient(milestones); - resBox->pack_start(*hueskin2); - hueskin2->setAdjusterListener (this); + hueskin2 = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HUESKY"), -314., 314., -260., -250, -130., -140., 0, false)); + hueskin2->set_tooltip_markup (M("TP_WAVELET_HUESKY_TOOLTIP")); + hueskin2->setBgGradient(milestones); + resBox->pack_start(*hueskin2); + hueskin2->setAdjusterListener (this); - sky = Gtk::manage (new Adjuster (M("TP_WAVELET_SKY"), -100., 100.0, 1., 0.)); - sky->set_tooltip_text (M("TP_WAVELET_SKY_TOOLTIP")); - sky->setAdjusterListener (this); + sky = Gtk::manage (new Adjuster (M("TP_WAVELET_SKY"), -100., 100.0, 1., 0.)); + sky->set_tooltip_text (M("TP_WAVELET_SKY_TOOLTIP")); + sky->setAdjusterListener (this); - resBox->pack_start(*sky); + resBox->pack_start(*sky); - // whole hue range - milestones.clear(); - for (int i=0; i<7; i++) { - float R, G, B; - float x = float(i)*(1.0f/6.0); - Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); - milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); - } + // whole hue range + milestones.clear(); - curveEditorRES = new CurveEditorGroup (options.lastWaveletCurvesDir); - curveEditorRES->setCurveListener (this); + for (int i = 0; i < 7; i++) { + float R, G, B; + float x = float(i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + milestones.push_back( GradientMilestone(double(x), double(R), double(G), double(B)) ); + } - hhshape = static_cast(curveEditorRES->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_HH"))); - hhshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_HH_TOOLTIP")); - hhshape->setCurveColorProvider(this, 5); - curveEditorRES->curveListComplete(); - hhshape->setBottomBarBgGradient(milestones); + curveEditorRES = new CurveEditorGroup (options.lastWaveletCurvesDir); + curveEditorRES->setCurveListener (this); - resBox->pack_start (*curveEditorRES, Gtk::PACK_SHRINK, 4); + hhshape = static_cast(curveEditorRES->addCurve(CT_Flat, M("TP_WAVELET_CURVEEDITOR_HH"))); + hhshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_HH_TOOLTIP")); + hhshape->setCurveColorProvider(this, 5); + curveEditorRES->curveListComplete(); + hhshape->setBottomBarBgGradient(milestones); - // Toning and Color Balance - Gtk::HSeparator *separatorCB = Gtk::manage (new Gtk::HSeparator()); + resBox->pack_start (*curveEditorRES, Gtk::PACK_SHRINK, 4); - Gtk::VBox *chanMixerHLBox = Gtk::manage (new Gtk::VBox()); - Gtk::VBox *chanMixerMidBox = Gtk::manage (new Gtk::VBox()); - Gtk::VBox *chanMixerShadowsBox = Gtk::manage (new Gtk::VBox()); + // Toning and Color Balance + Gtk::HSeparator *separatorCB = Gtk::manage (new Gtk::HSeparator()); - cbenab = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_CBENAB"))); - cbenab->set_active (true); - cbenabConn = cbenab->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::cbenabToggled) ); - cbenab->set_tooltip_text (M("TP_WAVELET_CB_TOOLTIP")); + Gtk::VBox *chanMixerHLBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerMidBox = Gtk::manage (new Gtk::VBox()); + Gtk::VBox *chanMixerShadowsBox = Gtk::manage (new Gtk::VBox()); - Gtk::Image* iblueR = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* iyelL = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* imagL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + cbenab = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_CBENAB"))); + cbenab->set_active (true); + cbenabConn = cbenab->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::cbenabToggled) ); + cbenab->set_tooltip_text (M("TP_WAVELET_CB_TOOLTIP")); - Gtk::Image* iblueRm = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* iyelLm = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* imagLm = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenRm = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* iblueR = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelL = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - Gtk::Image* iblueRh = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* iyelLh = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* imagLh = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenRh = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* iblueRm = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelLm = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagLm = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenRm = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - greenhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., igreenRh, imagLh)); - bluehigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iblueRh, iyelLh)); + Gtk::Image* iblueRh = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* iyelLh = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* imagLh = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenRh = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - greenmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., igreenRm, imagLm)); - bluemed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0. , iblueRm , iyelLm)); + greenhigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., igreenRh, imagLh)); + bluehigh = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iblueRh, iyelLh)); - greenlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., igreenR, imagL)); - bluelow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iblueR , iyelL)); + greenmed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., igreenRm, imagLm)); + bluemed = Gtk::manage (new Adjuster ("", -100., 100., 1., 0. , iblueRm , iyelLm)); - chanMixerHLBox->pack_start (*greenhigh); - chanMixerHLBox->pack_start (*bluehigh); - chanMixerMidBox->pack_start (*greenmed); - chanMixerMidBox->pack_start (*bluemed); - chanMixerShadowsBox->pack_start (*greenlow); - chanMixerShadowsBox->pack_start (*bluelow); + greenlow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., igreenR, imagL)); + bluelow = Gtk::manage (new Adjuster ("", -100., 100., 1., 0., iblueR , iyelL)); - greenlow->setAdjusterListener (this); - bluelow->setAdjusterListener (this); - greenmed->setAdjusterListener (this); - bluemed->setAdjusterListener (this); - greenhigh->setAdjusterListener (this); - bluehigh->setAdjusterListener (this); + chanMixerHLBox->pack_start (*greenhigh); + chanMixerHLBox->pack_start (*bluehigh); + chanMixerMidBox->pack_start (*greenmed); + chanMixerMidBox->pack_start (*bluemed); + chanMixerShadowsBox->pack_start (*greenlow); + chanMixerShadowsBox->pack_start (*bluelow); - resBox->pack_start(*separatorCB, Gtk::PACK_SHRINK); + greenlow->setAdjusterListener (this); + bluelow->setAdjusterListener (this); + greenmed->setAdjusterListener (this); + bluemed->setAdjusterListener (this); + greenhigh->setAdjusterListener (this); + bluehigh->setAdjusterListener (this); - chanMixerHLFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT"))); - chanMixerMidFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_MIDTONES"))); - chanMixerShadowsFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SHADOWS"))); + resBox->pack_start(*separatorCB, Gtk::PACK_SHRINK); - chanMixerHLFrame->add(*chanMixerHLBox); - chanMixerMidFrame->add(*chanMixerMidBox); - chanMixerShadowsFrame->add(*chanMixerShadowsBox); - resBox->pack_start(*cbenab); + chanMixerHLFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_HIGHLIGHT"))); + chanMixerMidFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_MIDTONES"))); + chanMixerShadowsFrame = Gtk::manage (new Gtk::Frame(M("TP_COLORTONING_SHADOWS"))); - resBox->pack_start(*chanMixerHLFrame, Gtk::PACK_SHRINK); - resBox->pack_start(*chanMixerMidFrame, Gtk::PACK_SHRINK); - resBox->pack_start(*chanMixerShadowsFrame, Gtk::PACK_SHRINK); + chanMixerHLFrame->add(*chanMixerHLBox); + chanMixerMidFrame->add(*chanMixerMidBox); + chanMixerShadowsFrame->add(*chanMixerShadowsBox); + resBox->pack_start(*cbenab); - // Reset sliders - neutrHBox = Gtk::manage (new Gtk::HBox ()); - neutrHBox->set_border_width (2); + resBox->pack_start(*chanMixerHLFrame, Gtk::PACK_SHRINK); + resBox->pack_start(*chanMixerMidFrame, Gtk::PACK_SHRINK); + resBox->pack_start(*chanMixerShadowsFrame, Gtk::PACK_SHRINK); - neutral = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRAL"))); - //RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); - //neutral->set_image(*resetImg); - neutral->set_tooltip_text (M("TP_COLORTONING_NEUTRAL_TIP")); - neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::neutral_pressed) ); - neutral->show(); - neutrHBox->pack_start (*neutral, Gtk::PACK_EXPAND_WIDGET); + // Reset sliders + neutrHBox = Gtk::manage (new Gtk::HBox ()); + neutrHBox->set_border_width (2); - resBox->pack_start (*neutrHBox); + neutral = Gtk::manage (new Gtk::Button (M("TP_COLORTONING_NEUTRAL"))); + //RTImage *resetImg = Gtk::manage (new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png")); + //neutral->set_image(*resetImg); + neutral->set_tooltip_text (M("TP_COLORTONING_NEUTRAL_TIP")); + neutralconn = neutral->signal_pressed().connect( sigc::mem_fun(*this, &Wavelet::neutral_pressed) ); + neutral->show(); + neutrHBox->pack_start (*neutral, Gtk::PACK_EXPAND_WIDGET); + + resBox->pack_start (*neutrHBox); // Final Touchup - Gtk::VBox * ctboxBA = Gtk::manage (new Gtk::VBox()); + Gtk::VBox * ctboxBA = Gtk::manage (new Gtk::VBox()); - ctboxBA->set_border_width(4); - ctboxBA->set_spacing(2); + ctboxBA->set_border_width(4); + ctboxBA->set_spacing(2); - //Gtk::HSeparator *separatorfin = Gtk::manage (new Gtk::HSeparator()); - //ctboxBA->pack_start(*separatorfin, Gtk::PACK_SHRINK, 2); - ctboxFI = Gtk::manage (new Gtk::HBox()); + //Gtk::HSeparator *separatorfin = Gtk::manage (new Gtk::HSeparator()); + //ctboxBA->pack_start(*separatorfin, Gtk::PACK_SHRINK, 2); + ctboxFI = Gtk::manage (new Gtk::HBox()); - labmBA = Gtk::manage (new Gtk::Label (M("TP_WAVELET_BATYPE")+":")); - ctboxFI->pack_start (*labmBA, Gtk::PACK_SHRINK, 1); + labmBA = Gtk::manage (new Gtk::Label (M("TP_WAVELET_BATYPE") + ":")); + ctboxFI->pack_start (*labmBA, Gtk::PACK_SHRINK, 1); - BAmethod = Gtk::manage (new MyComboBoxText ()); - BAmethod->append_text (M("TP_WAVELET_BANONE")); - BAmethod->append_text (M("TP_WAVELET_BASLI")); - BAmethod->append_text (M("TP_WAVELET_BACUR")); - BAmethodconn = BAmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::BAmethodChanged) ); - ctboxFI->pack_start(*BAmethod); - ctboxBA->pack_start(*ctboxFI); + BAmethod = Gtk::manage (new MyComboBoxText ()); + BAmethod->append_text (M("TP_WAVELET_BANONE")); + BAmethod->append_text (M("TP_WAVELET_BASLI")); + BAmethod->append_text (M("TP_WAVELET_BACUR")); + BAmethodconn = BAmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::BAmethodChanged) ); + ctboxFI->pack_start(*BAmethod); + ctboxBA->pack_start(*ctboxFI); - balance = Gtk::manage (new Adjuster (M("TP_WAVELET_BALANCE"), -30, 100, 1, 0)); - balance->setAdjusterListener (this); - balance->set_tooltip_text (M("TP_WAVELET_BALANCE_TOOLTIP")); - std::vector milestonesW; + balance = Gtk::manage (new Adjuster (M("TP_WAVELET_BALANCE"), -30, 100, 1, 0)); + balance->setAdjusterListener (this); + balance->set_tooltip_text (M("TP_WAVELET_BALANCE_TOOLTIP")); + std::vector milestonesW; - milestonesW.clear(); - milestonesW.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestonesW.push_back( GradientMilestone(1., 1., 1., 1.) ); + milestonesW.clear(); + milestonesW.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestonesW.push_back( GradientMilestone(1., 1., 1., 1.) ); - opacityCurveEditorW = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYW")); - opacityCurveEditorW->setCurveListener (this); + opacityCurveEditorW = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYW")); + opacityCurveEditorW->setCurveListener (this); - rtengine::WaveletParams::getDefaultOpacityCurveW(defaultCurve); - opacityShape = static_cast(opacityCurveEditorW->addCurve(CT_Flat, "", NULL, false)); - opacityShape->setIdentityValue(0.); - opacityShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - opacityShape->setBottomBarBgGradient(milestonesW); + rtengine::WaveletParams::getDefaultOpacityCurveW(defaultCurve); + opacityShape = static_cast(opacityCurveEditorW->addCurve(CT_Flat, "", NULL, false)); + opacityShape->setIdentityValue(0.); + opacityShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + opacityShape->setBottomBarBgGradient(milestonesW); - // This will add the reset button at the end of the curveType buttons - opacityCurveEditorW->curveListComplete(); - opacityCurveEditorW->show(); + // This will add the reset button at the end of the curveType buttons + opacityCurveEditorW->curveListComplete(); + opacityCurveEditorW->show(); - iter = Gtk::manage (new Adjuster (M("TP_WAVELET_ITER"), -3, 3, 1, 0)); - iter->setAdjusterListener (this); - iter->set_tooltip_text (M("TP_WAVELET_ITER_TOOLTIP")); + iter = Gtk::manage (new Adjuster (M("TP_WAVELET_ITER"), -3, 3, 1, 0)); + iter->setAdjusterListener (this); + iter->set_tooltip_text (M("TP_WAVELET_ITER_TOOLTIP")); - Gtk::HSeparator *separatorbalend = Gtk::manage (new Gtk::HSeparator()); + Gtk::HSeparator *separatorbalend = Gtk::manage (new Gtk::HSeparator()); - opacityCurveEditorWL = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYWL")); - opacityCurveEditorWL->setCurveListener (this); + opacityCurveEditorWL = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_OPACITYWL")); + opacityCurveEditorWL->setCurveListener (this); - rtengine::WaveletParams::getDefaultOpacityCurveWL(defaultCurve); - opacityShapeWL = static_cast(opacityCurveEditorWL->addCurve(CT_Flat, "", NULL, false)); - opacityShapeWL->setIdentityValue(0.); - opacityShapeWL->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - opacityShapeWL->setTooltip(M("TP_WAVELET_OPACITYWL_TOOLTIP")); + rtengine::WaveletParams::getDefaultOpacityCurveWL(defaultCurve); + opacityShapeWL = static_cast(opacityCurveEditorWL->addCurve(CT_Flat, "", NULL, false)); + opacityShapeWL->setIdentityValue(0.); + opacityShapeWL->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + opacityShapeWL->setTooltip(M("TP_WAVELET_OPACITYWL_TOOLTIP")); - // This will add the reset button at the end of the curveType buttons - opacityCurveEditorWL->curveListComplete(); - opacityCurveEditorWL->show(); + // This will add the reset button at the end of the curveType buttons + opacityCurveEditorWL->curveListComplete(); + opacityCurveEditorWL->show(); - curveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir,M("TP_WAVELET_CONTEDIT")); - curveEditorG->setCurveListener (this); + curveEditorG = new CurveEditorGroup (options.lastWaveletCurvesDir, M("TP_WAVELET_CONTEDIT")); + curveEditorG->setCurveListener (this); - clshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_WAVELET_CURVEEDITOR_CL"))); - clshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CL_TOOLTIP")); - std::vector milestones22; + clshape = static_cast(curveEditorG->addCurve(CT_Diagonal, M("TP_WAVELET_CURVEEDITOR_CL"))); + clshape->setTooltip(M("TP_WAVELET_CURVEEDITOR_CL_TOOLTIP")); + std::vector milestones22; - milestones22.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones22.push_back( GradientMilestone(1., 1., 1., 1.) ); - clshape->setBottomBarBgGradient(milestones22); - clshape->setLeftBarBgGradient(milestones22); + milestones22.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones22.push_back( GradientMilestone(1., 1., 1., 1.) ); + clshape->setBottomBarBgGradient(milestones22); + clshape->setLeftBarBgGradient(milestones22); - curveEditorG->curveListComplete(); + curveEditorG->curveListComplete(); - tmr = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_BALCHRO"))); - tmr->set_active (true); - tmr->set_tooltip_text (M("TP_WAVELET_BALCHRO_TOOLTIP")); - tmrConn = tmr->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::tmrToggled) ); + tmr = Gtk::manage (new Gtk::CheckButton (M("TP_WAVELET_BALCHRO"))); + tmr->set_active (true); + tmr->set_tooltip_text (M("TP_WAVELET_BALCHRO_TOOLTIP")); + tmrConn = tmr->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::tmrToggled) ); - Gtk::VBox * finalBox = Gtk::manage (new Gtk::VBox()); - finalBox->set_border_width(4); - finalBox->set_spacing(2); + Gtk::VBox * finalBox = Gtk::manage (new Gtk::VBox()); + finalBox->set_border_width(4); + finalBox->set_spacing(2); - finalBox->pack_start (*ctboxBA); - finalBox->pack_start(*balance); - - finalBox->pack_start( *opacityCurveEditorW, Gtk::PACK_SHRINK, 2); - - finalBox->pack_start(*iter); - - finalBox->pack_start(*tmr); - finalBox->pack_start(*separatorbalend, Gtk::PACK_SHRINK, 2); - finalBox->pack_start( *opacityCurveEditorWL, Gtk::PACK_SHRINK, 2); + finalBox->pack_start (*ctboxBA); + finalBox->pack_start(*balance); - finalBox->pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); + finalBox->pack_start( *opacityCurveEditorW, Gtk::PACK_SHRINK, 2); + + finalBox->pack_start(*iter); + + finalBox->pack_start(*tmr); + finalBox->pack_start(*separatorbalend, Gtk::PACK_SHRINK, 2); + finalBox->pack_start( *opacityCurveEditorWL, Gtk::PACK_SHRINK, 2); + + finalBox->pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4); //----------------------------- - expsettings->add(*settingsVBox); - pack_start (*expsettings); + expsettings->add(*settingsVBox); + pack_start (*expsettings); - expcontrast->add(*levBox); - pack_start (*expcontrast); + expcontrast->add(*levBox); + pack_start (*expcontrast); - expchroma->add(*chBox); - pack_start (*expchroma); + expchroma->add(*chBox); + pack_start (*expchroma); - exptoning->add(*tonBox); - pack_start (*exptoning); + exptoning->add(*tonBox); + pack_start (*exptoning); - expnoise->add(*noiseBox); - pack_start (*expnoise); + expnoise->add(*noiseBox); + pack_start (*expnoise); - expedge->add(*edgBox); - pack_start (*expedge); + expedge->add(*edgBox); + pack_start (*expedge); - expgamut->add(*conBox); - pack_start (*expgamut); + expgamut->add(*conBox); + pack_start (*expgamut); - expresid->add(*resBox); - pack_start(*expresid); + expresid->add(*resBox); + pack_start(*expresid); - expfinal->add(*finalBox); - pack_start(*expfinal); + expfinal->add(*finalBox); + pack_start(*expfinal); } -Wavelet::~Wavelet () { - delete opaCurveEditorG; - delete opacityCurveEditorG; - delete CCWcurveEditorG; - delete curveEditorRES; - delete curveEditorGAM; - delete curveEditorG; - delete opacityCurveEditorW; - delete opacityCurveEditorWL; -} - -int wavUpdateUI (void* data) { - GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected - (static_cast(data))->wavComputed_ (); - return 0; -} - -void Wavelet::wavChanged (double nlevel) +Wavelet::~Wavelet () { - nextnlevel=nlevel; - g_idle_add (wavUpdateUI, this); + delete opaCurveEditorG; + delete opacityCurveEditorG; + delete CCWcurveEditorG; + delete curveEditorRES; + delete curveEditorGAM; + delete curveEditorG; + delete opacityCurveEditorW; + delete opacityCurveEditorWL; } -bool Wavelet::wavComputed_ () { - disableListener (); - enableListener (); - updatewavLabel (); - return false; +int wavUpdateUI (void* data) +{ + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + (static_cast(data))->wavComputed_ (); + return 0; } -void Wavelet::updatewavLabel () { - if (!batchMode) { - float lv; - lv=nextnlevel; - wavLabels->set_text( - Glib::ustring::compose(M("TP_WAVELET_LEVLABEL"), - Glib::ustring::format(std::fixed, std::setprecision(0), lv)) - ); - } + +void Wavelet::wavChanged (double nlevel) +{ + nextnlevel = nlevel; + g_idle_add (wavUpdateUI, this); +} +bool Wavelet::wavComputed_ () +{ + + disableListener (); + enableListener (); + updatewavLabel (); + return false; +} +void Wavelet::updatewavLabel () +{ + if (!batchMode) { + float lv; + lv = nextnlevel; + wavLabels->set_text( + Glib::ustring::compose(M("TP_WAVELET_LEVLABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), lv)) + ); + } } // Will only reset the chanel mixer // WARNING! In mutiImage mode, and for sliders in ADD mode, this will reset the slider to 0, but not to the default value as in SET mode. -void Wavelet::neutral_pressed () { - disableListener(); - greenlow->resetValue(false); - bluelow->resetValue(false); - greenmed->resetValue(false); - bluemed->resetValue(false); - greenhigh->resetValue(false); - bluehigh->resetValue(false); +void Wavelet::neutral_pressed () +{ + disableListener(); + greenlow->resetValue(false); + bluelow->resetValue(false); + greenmed->resetValue(false); + bluemed->resetValue(false); + greenhigh->resetValue(false); + bluehigh->resetValue(false); - enableListener(); - if (listener && getEnabled()) - listener->panelChanged (EvWavNeutral, M("ADJUSTER_RESET_TO_DEFAULT")); + enableListener(); + + if (listener && getEnabled()) { + listener->panelChanged (EvWavNeutral, M("ADJUSTER_RESET_TO_DEFAULT")); + } } -void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { +void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) +{ - /***************************************************************************************************** - * - * Disable listeners and signals - * - *****************************************************************************************************/ + /***************************************************************************************************** + * + * Disable listeners and signals + * + *****************************************************************************************************/ - disableListener (); - Lmethodconn.block(true); - CLmethodconn.block(true); - Backmethodconn.block(true); - Tilesmethodconn.block(true); - daubcoeffmethodconn.block(true); - Dirmethodconn.block(true); - CHmethodconn.block(true); - CHSLmethodconn.block(true); - EDmethodconn.block(true); - NPmethodconn.block(true); - BAmethodconn.block(true); - TMmethodconn.block(true); - HSmethodconn.block(true); - MedgreinfConn.block(true); - cbenabConn.block(true); - enableChromaConn.block(true); - enableContrastConn.block(true); - enableEdgeConn.block(true); - enableFinalConn.block(true); - enableNoiseConn.block(true); - enableResidConn.block(true); - enableToningConn.block(true); + disableListener (); + Lmethodconn.block(true); + CLmethodconn.block(true); + Backmethodconn.block(true); + Tilesmethodconn.block(true); + daubcoeffmethodconn.block(true); + Dirmethodconn.block(true); + CHmethodconn.block(true); + CHSLmethodconn.block(true); + EDmethodconn.block(true); + NPmethodconn.block(true); + BAmethodconn.block(true); + TMmethodconn.block(true); + HSmethodconn.block(true); + MedgreinfConn.block(true); + cbenabConn.block(true); + enableChromaConn.block(true); + enableContrastConn.block(true); + enableEdgeConn.block(true); + enableFinalConn.block(true); + enableNoiseConn.block(true); + enableResidConn.block(true); + enableToningConn.block(true); - /***************************************************************************************************** - * - * Set the GUI reflecting the given ProcParams - * - *****************************************************************************************************/ + /***************************************************************************************************** + * + * Set the GUI reflecting the given ProcParams + * + *****************************************************************************************************/ - //HSmethod->set_active (1); // Note: default values are controlled in rtengine::ProcParams::SetDefaults - if (pp->wavelet.HSmethod=="without") - HSmethod->set_active (0); - else if (pp->wavelet.HSmethod=="with") - HSmethod->set_active (1); + //HSmethod->set_active (1); // Note: default values are controlled in rtengine::ProcParams::SetDefaults + if (pp->wavelet.HSmethod == "without") { + HSmethod->set_active (0); + } else if (pp->wavelet.HSmethod == "with") { + HSmethod->set_active (1); + } - //CHmethod->set_active (1); - if (pp->wavelet.CHmethod=="without") - CHmethod->set_active (0); - else if (pp->wavelet.CHmethod=="with") - CHmethod->set_active (1); - else if (pp->wavelet.CHmethod=="link") - CHmethod->set_active (2); + //CHmethod->set_active (1); + if (pp->wavelet.CHmethod == "without") { + CHmethod->set_active (0); + } else if (pp->wavelet.CHmethod == "with") { + CHmethod->set_active (1); + } else if (pp->wavelet.CHmethod == "link") { + CHmethod->set_active (2); + } - //Medgreinf->set_active (1); - if (pp->wavelet.Medgreinf=="more") - Medgreinf->set_active (0); - else if (pp->wavelet.Medgreinf=="none") - Medgreinf->set_active (1); - else if (pp->wavelet.Medgreinf=="less") - Medgreinf->set_active (2); + //Medgreinf->set_active (1); + if (pp->wavelet.Medgreinf == "more") { + Medgreinf->set_active (0); + } else if (pp->wavelet.Medgreinf == "none") { + Medgreinf->set_active (1); + } else if (pp->wavelet.Medgreinf == "less") { + Medgreinf->set_active (2); + } - //CHSLmethod->set_active (1); - if (pp->wavelet.CHSLmethod=="SL") - CHSLmethod->set_active (0); - else if (pp->wavelet.CHSLmethod=="CU") - CHSLmethod->set_active (1); + //CHSLmethod->set_active (1); + if (pp->wavelet.CHSLmethod == "SL") { + CHSLmethod->set_active (0); + } else if (pp->wavelet.CHSLmethod == "CU") { + CHSLmethod->set_active (1); + } - //EDmethod->set_active (1); - if (pp->wavelet.EDmethod=="SL") - EDmethod->set_active (0); - else if (pp->wavelet.EDmethod=="CU") - EDmethod->set_active (1); + //EDmethod->set_active (1); + if (pp->wavelet.EDmethod == "SL") { + EDmethod->set_active (0); + } else if (pp->wavelet.EDmethod == "CU") { + EDmethod->set_active (1); + } - if (pp->wavelet.NPmethod=="none") - NPmethod->set_active (0); - else if (pp->wavelet.NPmethod=="low") - NPmethod->set_active (1); - else if (pp->wavelet.NPmethod=="high") - NPmethod->set_active (2); - - //BAmethod->set_active (0); - if (pp->wavelet.BAmethod=="none") - BAmethod->set_active (0); - else if (pp->wavelet.BAmethod=="sli") - BAmethod->set_active (1); - else if (pp->wavelet.BAmethod=="cur") - BAmethod->set_active (2); + if (pp->wavelet.NPmethod == "none") { + NPmethod->set_active (0); + } else if (pp->wavelet.NPmethod == "low") { + NPmethod->set_active (1); + } else if (pp->wavelet.NPmethod == "high") { + NPmethod->set_active (2); + } - //TMmethod->set_active (1); - if (pp->wavelet.TMmethod=="cont") - TMmethod->set_active (0); - else if (pp->wavelet.TMmethod=="tm") - TMmethod->set_active (1); -// else if (pp->wavelet.TMmethod=="both") -// TMmethod->set_active (2); + //BAmethod->set_active (0); + if (pp->wavelet.BAmethod == "none") { + BAmethod->set_active (0); + } else if (pp->wavelet.BAmethod == "sli") { + BAmethod->set_active (1); + } else if (pp->wavelet.BAmethod == "cur") { + BAmethod->set_active (2); + } - //Backmethod->set_active (3); - if (pp->wavelet.Backmethod=="black") { - Backmethod->set_active (0); - } - else if (pp->wavelet.Backmethod=="grey") { - Backmethod->set_active (1); - } - else if (pp->wavelet.Backmethod=="resid") { - Backmethod->set_active (2); - } + //TMmethod->set_active (1); + if (pp->wavelet.TMmethod == "cont") { + TMmethod->set_active (0); + } else if (pp->wavelet.TMmethod == "tm") { + TMmethod->set_active (1); + } - //CLmethod->set_active (3); - if (pp->wavelet.CLmethod=="one") { - CLmethod->set_active (0); - } - else if (pp->wavelet.CLmethod=="inf") { - CLmethod->set_active (1); - } - else if (pp->wavelet.CLmethod=="sup") { - CLmethod->set_active (2); - } - else if (pp->wavelet.CLmethod=="all") { - CLmethod->set_active (3); - } +// else if (pp->wavelet.TMmethod=="both") +// TMmethod->set_active (2); - //Tilesmethod->set_active (2); - if (pp->wavelet.Tilesmethod=="full") - Tilesmethod->set_active (0); - else if (pp->wavelet.Tilesmethod=="big") - Tilesmethod->set_active (1); - else if (pp->wavelet.Tilesmethod=="lit") - Tilesmethod->set_active (2); + //Backmethod->set_active (3); + if (pp->wavelet.Backmethod == "black") { + Backmethod->set_active (0); + } else if (pp->wavelet.Backmethod == "grey") { + Backmethod->set_active (1); + } else if (pp->wavelet.Backmethod == "resid") { + Backmethod->set_active (2); + } - //daubcoeffmethod->set_active (4); - if (pp->wavelet.daubcoeffmethod=="2_") - daubcoeffmethod->set_active (0); - else if (pp->wavelet.daubcoeffmethod=="4_") - daubcoeffmethod->set_active (1); - else if (pp->wavelet.daubcoeffmethod=="6_") - daubcoeffmethod->set_active (2); - else if (pp->wavelet.daubcoeffmethod=="10_") - daubcoeffmethod->set_active (3); - else if (pp->wavelet.daubcoeffmethod=="14_") - daubcoeffmethod->set_active (4); + //CLmethod->set_active (3); + if (pp->wavelet.CLmethod == "one") { + CLmethod->set_active (0); + } else if (pp->wavelet.CLmethod == "inf") { + CLmethod->set_active (1); + } else if (pp->wavelet.CLmethod == "sup") { + CLmethod->set_active (2); + } else if (pp->wavelet.CLmethod == "all") { + CLmethod->set_active (3); + } - //Dirmethod->set_active (3); - if (pp->wavelet.Dirmethod=="one") - Dirmethod->set_active (0); - else if (pp->wavelet.Dirmethod=="two") - Dirmethod->set_active (1); - else if (pp->wavelet.Dirmethod=="thr") - Dirmethod->set_active (2); - else if (pp->wavelet.Dirmethod=="all") - Dirmethod->set_active (3); + //Tilesmethod->set_active (2); + if (pp->wavelet.Tilesmethod == "full") { + Tilesmethod->set_active (0); + } else if (pp->wavelet.Tilesmethod == "big") { + Tilesmethod->set_active (1); + } else if (pp->wavelet.Tilesmethod == "lit") { + Tilesmethod->set_active (2); + } - int selectedLevel = atoi(pp->wavelet.Lmethod.data())-1; - Lmethod->set_active (selectedLevel == -1 ? 4 :selectedLevel); + //daubcoeffmethod->set_active (4); + if (pp->wavelet.daubcoeffmethod == "2_") { + daubcoeffmethod->set_active (0); + } else if (pp->wavelet.daubcoeffmethod == "4_") { + daubcoeffmethod->set_active (1); + } else if (pp->wavelet.daubcoeffmethod == "6_") { + daubcoeffmethod->set_active (2); + } else if (pp->wavelet.daubcoeffmethod == "10_") { + daubcoeffmethod->set_active (3); + } else if (pp->wavelet.daubcoeffmethod == "14_") { + daubcoeffmethod->set_active (4); + } - ccshape->setCurve (pp->wavelet.ccwcurve); - opacityShapeRG->setCurve (pp->wavelet.opacityCurveRG); - opacityShapeBY->setCurve (pp->wavelet.opacityCurveBY); - opacityShape->setCurve (pp->wavelet.opacityCurveW); - opacityShapeWL->setCurve (pp->wavelet.opacityCurveWL); - hhshape->setCurve (pp->wavelet.hhcurve); - Chshape->setCurve (pp->wavelet.Chcurve); - clshape->setCurve (pp->wavelet.wavclCurve); - expcontrast->setEnabled (pp->wavelet.expcontrast); - expchroma->setEnabled (pp->wavelet.expchroma); - expedge->setEnabled (pp->wavelet.expedge); - expresid->setEnabled (pp->wavelet.expresid); - expfinal->setEnabled (pp->wavelet.expfinal); - exptoning->setEnabled (pp->wavelet.exptoning); - expnoise->setEnabled (pp->wavelet.expnoise); + //Dirmethod->set_active (3); + if (pp->wavelet.Dirmethod == "one") { + Dirmethod->set_active (0); + } else if (pp->wavelet.Dirmethod == "two") { + Dirmethod->set_active (1); + } else if (pp->wavelet.Dirmethod == "thr") { + Dirmethod->set_active (2); + } else if (pp->wavelet.Dirmethod == "all") { + Dirmethod->set_active (3); + } - setEnabled(pp->wavelet.enabled); - avoidConn.block (true); - avoid->set_active (pp->wavelet.avoid); - avoidConn.block (false); - tmrConn.block (true); - tmr->set_active (pp->wavelet.tmr); - tmrConn.block (false); - medianConn.block (true); - median->set_active (pp->wavelet.median); - medianConn.block (false); - medianlevConn.block (true); - medianlev->set_active (pp->wavelet.medianlev); - medianlevConn.block (false); - linkedgConn.block (true); - linkedg->set_active (pp->wavelet.linkedg); - linkedgConn.block (false); - cbenabConn.block (true); - cbenab->set_active (pp->wavelet.cbenab); - cbenabConn.block (false); + int selectedLevel = atoi(pp->wavelet.Lmethod.data()) - 1; + Lmethod->set_active (selectedLevel == -1 ? 4 : selectedLevel); - lipstConn.block (true); - lipst->set_active (pp->wavelet.lipst); - lipstConn.block (false); - //edgreinfConn.block (true); - //edgreinf->set_active (pp->wavelet.edgreinf); - //edgreinfConn.block (false); - //lastedgreinf = pp->wavelet.edgreinf; - lastmedian = pp->wavelet.median; - lastmedianlev = pp->wavelet.medianlev; - lastlinkedg = pp->wavelet.linkedg; - lastcbenab = pp->wavelet.cbenab; - lastlipst = pp->wavelet.lipst; - lastavoid = pp->wavelet.avoid; - lasttmr = pp->wavelet.tmr; - rescon->setValue (pp->wavelet.rescon); - resconH->setValue (pp->wavelet.resconH); - reschro->setValue (pp->wavelet.reschro); - tmrs->setValue (pp->wavelet.tmrs); - gamma->setValue (pp->wavelet.gamma); - sup->setValue (pp->wavelet.sup); - sky->setValue (pp->wavelet.sky); - thres->setValue (pp->wavelet.thres); - chroma->setValue (pp->wavelet.chroma); - chro->setValue (pp->wavelet.chro); - contrast->setValue (pp->wavelet.contrast); - edgrad->setValue (pp->wavelet.edgrad); - edgval->setValue (pp->wavelet.edgval); - edgthresh->setValue (pp->wavelet.edgthresh); - thr->setValue (pp->wavelet.thr); - thrH->setValue (pp->wavelet.thrH); - skinprotect->setValue(pp->wavelet.skinprotect); - hueskin->setValue(pp->wavelet.hueskin); - hueskin2->setValue(pp->wavelet.hueskin2); - threshold->setValue(pp->wavelet.threshold); - threshold2->setValue(pp->wavelet.threshold2); - edgedetect->setValue(pp->wavelet.edgedetect); - edgedetectthr->setValue(pp->wavelet.edgedetectthr); - edgedetectthr2->setValue(pp->wavelet.edgedetectthr2); - edgesensi->setValue(pp->wavelet.edgesensi); - edgeampli->setValue(pp->wavelet.edgeampli); - hllev->setValue(pp->wavelet.hllev); - bllev->setValue(pp->wavelet.bllev); - pastlev->setValue(pp->wavelet.pastlev); - satlev->setValue(pp->wavelet.satlev); - edgcont->setValue(pp->wavelet.edgcont); + ccshape->setCurve (pp->wavelet.ccwcurve); + opacityShapeRG->setCurve (pp->wavelet.opacityCurveRG); + opacityShapeBY->setCurve (pp->wavelet.opacityCurveBY); + opacityShape->setCurve (pp->wavelet.opacityCurveW); + opacityShapeWL->setCurve (pp->wavelet.opacityCurveWL); + hhshape->setCurve (pp->wavelet.hhcurve); + Chshape->setCurve (pp->wavelet.Chcurve); + clshape->setCurve (pp->wavelet.wavclCurve); + expcontrast->setEnabled (pp->wavelet.expcontrast); + expchroma->setEnabled (pp->wavelet.expchroma); + expedge->setEnabled (pp->wavelet.expedge); + expresid->setEnabled (pp->wavelet.expresid); + expfinal->setEnabled (pp->wavelet.expfinal); + exptoning->setEnabled (pp->wavelet.exptoning); + expnoise->setEnabled (pp->wavelet.expnoise); - greenlow->setValue (pp->wavelet.greenlow); - bluelow->setValue (pp->wavelet.bluelow); - greenmed->setValue (pp->wavelet.greenmed); - bluemed->setValue (pp->wavelet.bluemed); - greenhigh->setValue (pp->wavelet.greenhigh); - bluehigh->setValue (pp->wavelet.bluehigh); + setEnabled(pp->wavelet.enabled); + avoidConn.block (true); + avoid->set_active (pp->wavelet.avoid); + avoidConn.block (false); + tmrConn.block (true); + tmr->set_active (pp->wavelet.tmr); + tmrConn.block (false); + medianConn.block (true); + median->set_active (pp->wavelet.median); + medianConn.block (false); + medianlevConn.block (true); + medianlev->set_active (pp->wavelet.medianlev); + medianlevConn.block (false); + linkedgConn.block (true); + linkedg->set_active (pp->wavelet.linkedg); + linkedgConn.block (false); + cbenabConn.block (true); + cbenab->set_active (pp->wavelet.cbenab); + cbenabConn.block (false); - level0noise->setValue(pp->wavelet.level0noise); - level1noise->setValue(pp->wavelet.level1noise); - level2noise->setValue(pp->wavelet.level2noise); - level3noise->setValue(pp->wavelet.level3noise); - strength->setValue(pp->wavelet.strength); - balance->setValue(pp->wavelet.balance); - iter->setValue(pp->wavelet.iter); - for (int i = 0; i < 9; i++) { - correction[i]->setValue(pp->wavelet.c[i]); - } + lipstConn.block (true); + lipst->set_active (pp->wavelet.lipst); + lipstConn.block (false); + //edgreinfConn.block (true); + //edgreinf->set_active (pp->wavelet.edgreinf); + //edgreinfConn.block (false); + //lastedgreinf = pp->wavelet.edgreinf; + lastmedian = pp->wavelet.median; + lastmedianlev = pp->wavelet.medianlev; + lastlinkedg = pp->wavelet.linkedg; + lastcbenab = pp->wavelet.cbenab; + lastlipst = pp->wavelet.lipst; + lastavoid = pp->wavelet.avoid; + lasttmr = pp->wavelet.tmr; + rescon->setValue (pp->wavelet.rescon); + resconH->setValue (pp->wavelet.resconH); + reschro->setValue (pp->wavelet.reschro); + tmrs->setValue (pp->wavelet.tmrs); + gamma->setValue (pp->wavelet.gamma); + sup->setValue (pp->wavelet.sup); + sky->setValue (pp->wavelet.sky); + thres->setValue (pp->wavelet.thres); + chroma->setValue (pp->wavelet.chroma); + chro->setValue (pp->wavelet.chro); + contrast->setValue (pp->wavelet.contrast); + edgrad->setValue (pp->wavelet.edgrad); + edgval->setValue (pp->wavelet.edgval); + edgthresh->setValue (pp->wavelet.edgthresh); + thr->setValue (pp->wavelet.thr); + thrH->setValue (pp->wavelet.thrH); + skinprotect->setValue(pp->wavelet.skinprotect); + hueskin->setValue(pp->wavelet.hueskin); + hueskin2->setValue(pp->wavelet.hueskin2); + threshold->setValue(pp->wavelet.threshold); + threshold2->setValue(pp->wavelet.threshold2); + edgedetect->setValue(pp->wavelet.edgedetect); + edgedetectthr->setValue(pp->wavelet.edgedetectthr); + edgedetectthr2->setValue(pp->wavelet.edgedetectthr2); + edgesensi->setValue(pp->wavelet.edgesensi); + edgeampli->setValue(pp->wavelet.edgeampli); + hllev->setValue(pp->wavelet.hllev); + bllev->setValue(pp->wavelet.bllev); + pastlev->setValue(pp->wavelet.pastlev); + satlev->setValue(pp->wavelet.satlev); + edgcont->setValue(pp->wavelet.edgcont); - for (int i = 0; i < 9; i++) { - correctionch[i]->setValue(pp->wavelet.ch[i]); - } + greenlow->setValue (pp->wavelet.greenlow); + bluelow->setValue (pp->wavelet.bluelow); + greenmed->setValue (pp->wavelet.greenmed); + bluemed->setValue (pp->wavelet.bluemed); + greenhigh->setValue (pp->wavelet.greenhigh); + bluehigh->setValue (pp->wavelet.bluehigh); - /***************************************************************************************************** - * - * Set the inconsistent state (for combobox, select the "GENERAL_UNCHANGED" entry) - * - *****************************************************************************************************/ + level0noise->setValue(pp->wavelet.level0noise); + level1noise->setValue(pp->wavelet.level1noise); + level2noise->setValue(pp->wavelet.level2noise); + level3noise->setValue(pp->wavelet.level3noise); + strength->setValue(pp->wavelet.strength); + balance->setValue(pp->wavelet.balance); + iter->setValue(pp->wavelet.iter); - if (pedited) { - if (!pedited->wavelet.Lmethod) - Lmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.CLmethod) - CLmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.Backmethod) - Backmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.Tilesmethod) - Tilesmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.daubcoeffmethod) - daubcoeffmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.Dirmethod) - Dirmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.CHmethod) - CHmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.CHSLmethod) - CHSLmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.EDmethod) - EDmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.NPmethod) - NPmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.BAmethod) - BAmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.TMmethod) - TMmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.HSmethod) - HSmethod->set_active_text(M("GENERAL_UNCHANGED")); - if (!pedited->wavelet.Medgreinf) - Medgreinf->set_active_text(M("GENERAL_UNCHANGED")); + for (int i = 0; i < 9; i++) { + correction[i]->setValue(pp->wavelet.c[i]); + } - set_inconsistent (multiImage && !pedited->wavelet.enabled); - ccshape->setUnChanged (!pedited->wavelet.ccwcurve); - expcontrast->set_inconsistent (!pedited->wavelet.expcontrast); - expchroma->set_inconsistent (!pedited->wavelet.expchroma); - expedge->set_inconsistent (!pedited->wavelet.expedge); - expresid->set_inconsistent (!pedited->wavelet.expresid); - expfinal->set_inconsistent (!pedited->wavelet.expfinal); - exptoning->set_inconsistent (!pedited->wavelet.exptoning); - expnoise->set_inconsistent (!pedited->wavelet.expnoise); - opacityShapeRG->setCurve (pp->wavelet.opacityCurveRG); - opacityShapeBY->setCurve (pp->wavelet.opacityCurveBY); - opacityShape->setCurve (pp->wavelet.opacityCurveW); - opacityShapeWL->setCurve (pp->wavelet.opacityCurveWL); - hhshape->setUnChanged (!pedited->wavelet.hhcurve); - Chshape->setUnChanged (!pedited->wavelet.Chcurve); - clshape->setUnChanged (!pedited->wavelet.wavclCurve); - avoid->set_inconsistent (!pedited->wavelet.avoid); - tmr->set_inconsistent (!pedited->wavelet.tmr); - edgthresh->setEditedState (pedited->wavelet.edgthresh ? Edited : UnEdited); - rescon->setEditedState (pedited->wavelet.rescon ? Edited : UnEdited); - resconH->setEditedState (pedited->wavelet.resconH ? Edited : UnEdited); - reschro->setEditedState (pedited->wavelet.reschro ? Edited : UnEdited); - tmrs->setEditedState (pedited->wavelet.tmrs ? Edited : UnEdited); - gamma->setEditedState (pedited->wavelet.gamma ? Edited : UnEdited); - sup->setEditedState (pedited->wavelet.sup ? Edited : UnEdited); - sky->setEditedState (pedited->wavelet.sky ? Edited : UnEdited); - thres->setEditedState (pedited->wavelet.thres ? Edited : UnEdited); - balance->setEditedState (pedited->wavelet.balance ? Edited : UnEdited); - iter->setEditedState (pedited->wavelet.iter ? Edited : UnEdited); - threshold->setEditedState (pedited->wavelet.threshold ? Edited : UnEdited); - threshold2->setEditedState (pedited->wavelet.threshold2 ? Edited : UnEdited); - edgedetect->setEditedState (pedited->wavelet.edgedetect ? Edited : UnEdited); - edgedetectthr->setEditedState (pedited->wavelet.edgedetectthr ? Edited : UnEdited); - edgedetectthr2->setEditedState (pedited->wavelet.edgedetectthr2 ? Edited : UnEdited); - edgesensi->setEditedState (pedited->wavelet.edgesensi ? Edited : UnEdited); - edgeampli->setEditedState (pedited->wavelet.edgeampli ? Edited : UnEdited); - chroma->setEditedState (pedited->wavelet.chroma ? Edited : UnEdited); - chro->setEditedState (pedited->wavelet.chro ? Edited : UnEdited); + for (int i = 0; i < 9; i++) { + correctionch[i]->setValue(pp->wavelet.ch[i]); + } - greenlow->setEditedState (pedited->wavelet.greenlow ? Edited : UnEdited); - bluelow->setEditedState (pedited->wavelet.bluelow ? Edited : UnEdited); - greenmed->setEditedState (pedited->wavelet.greenmed ? Edited : UnEdited); - bluemed->setEditedState (pedited->wavelet.bluemed ? Edited : UnEdited); - greenhigh->setEditedState (pedited->wavelet.greenhigh ? Edited : UnEdited); - bluehigh->setEditedState (pedited->wavelet.bluehigh ? Edited : UnEdited); + /***************************************************************************************************** + * + * Set the inconsistent state (for combobox, select the "GENERAL_UNCHANGED" entry) + * + *****************************************************************************************************/ - median->set_inconsistent (!pedited->wavelet.median); - medianlev->set_inconsistent (!pedited->wavelet.medianlev); - linkedg->set_inconsistent (!pedited->wavelet.linkedg); -// edgreinf->set_inconsistent (!pedited->wavelet.edgreinf); - cbenab->set_inconsistent (!pedited->wavelet.cbenab); - lipst->set_inconsistent (!pedited->wavelet.lipst); - contrast->setEditedState (pedited->wavelet.contrast ? Edited : UnEdited); - edgrad->setEditedState (pedited->wavelet.edgrad ? Edited : UnEdited); - edgval->setEditedState (pedited->wavelet.edgval ? Edited : UnEdited); - thr->setEditedState (pedited->wavelet.thr ? Edited : UnEdited); - thrH->setEditedState (pedited->wavelet.thrH ? Edited : UnEdited); - skinprotect->setEditedState (pedited->wavelet.skinprotect ? Edited : UnEdited); - hueskin->setEditedState (pedited->wavelet.hueskin ? Edited : UnEdited); - hueskin2->setEditedState (pedited->wavelet.hueskin2 ? Edited : UnEdited); - hllev->setEditedState (pedited->wavelet.hllev ? Edited : UnEdited); - bllev->setEditedState (pedited->wavelet.bllev ? Edited : UnEdited); - pastlev->setEditedState (pedited->wavelet.pastlev ? Edited : UnEdited); - satlev->setEditedState (pedited->wavelet.satlev ? Edited : UnEdited); - strength->setEditedState(pedited->wavelet.strength ? Edited : UnEdited); - edgcont->setEditedState (pedited->wavelet.edgcont ? Edited : UnEdited); - level0noise->setEditedState (pedited->wavelet.level0noise ? Edited : UnEdited); - level1noise->setEditedState (pedited->wavelet.level1noise ? Edited : UnEdited); - level2noise->setEditedState (pedited->wavelet.level2noise ? Edited : UnEdited); - level3noise->setEditedState (pedited->wavelet.level3noise ? Edited : UnEdited); + if (pedited) { + if (!pedited->wavelet.Lmethod) { + Lmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - for(int i = 0; i < 9; i++) { - correction[i]->setEditedState (pedited->wavelet.c[i] ? Edited : UnEdited); - } - for(int i = 0; i < 9; i++) { - correctionch[i]->setEditedState (pedited->wavelet.ch[i] ? Edited : UnEdited); - } - } + if (!pedited->wavelet.CLmethod) { + CLmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - /***************************************************************************************************** - * - * Update the GUI, all at once if not in Batch editing (in this case, display EVERYTHING) - * - *****************************************************************************************************/ + if (!pedited->wavelet.Backmethod) { + Backmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - if (!batchMode) { - int y; - y=thres->getValue(); - int z; - for(z=y;z<9;z++) correction[z]->hide(); - for(z=0;zshow(); - if (pp->wavelet.CHSLmethod=="SL") { - for(z=y;z<9;z++) correctionch[z]->hide(); - for(z=0;zshow(); - } + if (!pedited->wavelet.Tilesmethod) { + Tilesmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - //adjusterUpdateUI(tmrs); - HSmethodUpdateUI(); - CHmethodUpdateUI(); - //MedgreinfUpdateUI(); - //CHSLmethodUpdateUI(); - EDmethodUpdateUI(); - NPmethodUpdateUI(); - BAmethodUpdateUI(); - TMmethodUpdateUI(); - //BackmethodUpdateUI(); - CLmethodUpdateUI(); - lipstUpdateUI (); - //TilesmethodUpdateUI(); - //daubcoeffmethodUpdateUI(); - //DirmethodUpdateUI(); - //LmethodUpdateUI(); - enabledUpdateUI (); - medianlevUpdateUI (); - cbenabUpdateUI (); - if(z==9) sup->show(); else sup->hide(); - } + if (!pedited->wavelet.daubcoeffmethod) { + daubcoeffmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - /***************************************************************************************************** - * - * Enable listeners and signals - * - *****************************************************************************************************/ + if (!pedited->wavelet.Dirmethod) { + Dirmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - Lmethodconn.block(false); - CLmethodconn.block(false); - Backmethodconn.block(false); - Tilesmethodconn.block(false); - daubcoeffmethodconn.block(false); - CHmethodconn.block(false); - CHSLmethodconn.block(false); - EDmethodconn.block(false); - NPmethodconn.block(false); - BAmethodconn.block(false); - TMmethodconn.block(false); - HSmethodconn.block(false); - Dirmethodconn.block(false); - MedgreinfConn.block(false); - enableChromaConn.block(false); - enableContrastConn.block(false); - enableEdgeConn.block(false); - enableFinalConn.block(false); - enableNoiseConn.block(false); - enableResidConn.block(false); - enableToningConn.block(false); + if (!pedited->wavelet.CHmethod) { + CHmethod->set_active_text(M("GENERAL_UNCHANGED")); + } - enableListener (); + if (!pedited->wavelet.CHSLmethod) { + CHSLmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.EDmethod) { + EDmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.NPmethod) { + NPmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.BAmethod) { + BAmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.TMmethod) { + TMmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.HSmethod) { + HSmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.Medgreinf) { + Medgreinf->set_active_text(M("GENERAL_UNCHANGED")); + } + + set_inconsistent (multiImage && !pedited->wavelet.enabled); + ccshape->setUnChanged (!pedited->wavelet.ccwcurve); + expcontrast->set_inconsistent (!pedited->wavelet.expcontrast); + expchroma->set_inconsistent (!pedited->wavelet.expchroma); + expedge->set_inconsistent (!pedited->wavelet.expedge); + expresid->set_inconsistent (!pedited->wavelet.expresid); + expfinal->set_inconsistent (!pedited->wavelet.expfinal); + exptoning->set_inconsistent (!pedited->wavelet.exptoning); + expnoise->set_inconsistent (!pedited->wavelet.expnoise); + opacityShapeRG->setCurve (pp->wavelet.opacityCurveRG); + opacityShapeBY->setCurve (pp->wavelet.opacityCurveBY); + opacityShape->setCurve (pp->wavelet.opacityCurveW); + opacityShapeWL->setCurve (pp->wavelet.opacityCurveWL); + hhshape->setUnChanged (!pedited->wavelet.hhcurve); + Chshape->setUnChanged (!pedited->wavelet.Chcurve); + clshape->setUnChanged (!pedited->wavelet.wavclCurve); + avoid->set_inconsistent (!pedited->wavelet.avoid); + tmr->set_inconsistent (!pedited->wavelet.tmr); + edgthresh->setEditedState (pedited->wavelet.edgthresh ? Edited : UnEdited); + rescon->setEditedState (pedited->wavelet.rescon ? Edited : UnEdited); + resconH->setEditedState (pedited->wavelet.resconH ? Edited : UnEdited); + reschro->setEditedState (pedited->wavelet.reschro ? Edited : UnEdited); + tmrs->setEditedState (pedited->wavelet.tmrs ? Edited : UnEdited); + gamma->setEditedState (pedited->wavelet.gamma ? Edited : UnEdited); + sup->setEditedState (pedited->wavelet.sup ? Edited : UnEdited); + sky->setEditedState (pedited->wavelet.sky ? Edited : UnEdited); + thres->setEditedState (pedited->wavelet.thres ? Edited : UnEdited); + balance->setEditedState (pedited->wavelet.balance ? Edited : UnEdited); + iter->setEditedState (pedited->wavelet.iter ? Edited : UnEdited); + threshold->setEditedState (pedited->wavelet.threshold ? Edited : UnEdited); + threshold2->setEditedState (pedited->wavelet.threshold2 ? Edited : UnEdited); + edgedetect->setEditedState (pedited->wavelet.edgedetect ? Edited : UnEdited); + edgedetectthr->setEditedState (pedited->wavelet.edgedetectthr ? Edited : UnEdited); + edgedetectthr2->setEditedState (pedited->wavelet.edgedetectthr2 ? Edited : UnEdited); + edgesensi->setEditedState (pedited->wavelet.edgesensi ? Edited : UnEdited); + edgeampli->setEditedState (pedited->wavelet.edgeampli ? Edited : UnEdited); + chroma->setEditedState (pedited->wavelet.chroma ? Edited : UnEdited); + chro->setEditedState (pedited->wavelet.chro ? Edited : UnEdited); + + greenlow->setEditedState (pedited->wavelet.greenlow ? Edited : UnEdited); + bluelow->setEditedState (pedited->wavelet.bluelow ? Edited : UnEdited); + greenmed->setEditedState (pedited->wavelet.greenmed ? Edited : UnEdited); + bluemed->setEditedState (pedited->wavelet.bluemed ? Edited : UnEdited); + greenhigh->setEditedState (pedited->wavelet.greenhigh ? Edited : UnEdited); + bluehigh->setEditedState (pedited->wavelet.bluehigh ? Edited : UnEdited); + + median->set_inconsistent (!pedited->wavelet.median); + medianlev->set_inconsistent (!pedited->wavelet.medianlev); + linkedg->set_inconsistent (!pedited->wavelet.linkedg); +// edgreinf->set_inconsistent (!pedited->wavelet.edgreinf); + cbenab->set_inconsistent (!pedited->wavelet.cbenab); + lipst->set_inconsistent (!pedited->wavelet.lipst); + contrast->setEditedState (pedited->wavelet.contrast ? Edited : UnEdited); + edgrad->setEditedState (pedited->wavelet.edgrad ? Edited : UnEdited); + edgval->setEditedState (pedited->wavelet.edgval ? Edited : UnEdited); + thr->setEditedState (pedited->wavelet.thr ? Edited : UnEdited); + thrH->setEditedState (pedited->wavelet.thrH ? Edited : UnEdited); + skinprotect->setEditedState (pedited->wavelet.skinprotect ? Edited : UnEdited); + hueskin->setEditedState (pedited->wavelet.hueskin ? Edited : UnEdited); + hueskin2->setEditedState (pedited->wavelet.hueskin2 ? Edited : UnEdited); + hllev->setEditedState (pedited->wavelet.hllev ? Edited : UnEdited); + bllev->setEditedState (pedited->wavelet.bllev ? Edited : UnEdited); + pastlev->setEditedState (pedited->wavelet.pastlev ? Edited : UnEdited); + satlev->setEditedState (pedited->wavelet.satlev ? Edited : UnEdited); + strength->setEditedState(pedited->wavelet.strength ? Edited : UnEdited); + edgcont->setEditedState (pedited->wavelet.edgcont ? Edited : UnEdited); + level0noise->setEditedState (pedited->wavelet.level0noise ? Edited : UnEdited); + level1noise->setEditedState (pedited->wavelet.level1noise ? Edited : UnEdited); + level2noise->setEditedState (pedited->wavelet.level2noise ? Edited : UnEdited); + level3noise->setEditedState (pedited->wavelet.level3noise ? Edited : UnEdited); + + for(int i = 0; i < 9; i++) { + correction[i]->setEditedState (pedited->wavelet.c[i] ? Edited : UnEdited); + } + + for(int i = 0; i < 9; i++) { + correctionch[i]->setEditedState (pedited->wavelet.ch[i] ? Edited : UnEdited); + } + } + + /***************************************************************************************************** + * + * Update the GUI, all at once if not in Batch editing (in this case, display EVERYTHING) + * + *****************************************************************************************************/ + + if (!batchMode) { + int y; + y = thres->getValue(); + int z; + + for(z = y; z < 9; z++) { + correction[z]->hide(); + } + + for(z = 0; z < y; z++) { + correction[z]->show(); + } + + if (pp->wavelet.CHSLmethod == "SL") { + for(z = y; z < 9; z++) { + correctionch[z]->hide(); + } + + for(z = 0; z < y; z++) { + correctionch[z]->show(); + } + } + + //adjusterUpdateUI(tmrs); + HSmethodUpdateUI(); + CHmethodUpdateUI(); + //MedgreinfUpdateUI(); + //CHSLmethodUpdateUI(); + EDmethodUpdateUI(); + NPmethodUpdateUI(); + BAmethodUpdateUI(); + TMmethodUpdateUI(); + //BackmethodUpdateUI(); + CLmethodUpdateUI(); + lipstUpdateUI (); + //TilesmethodUpdateUI(); + //daubcoeffmethodUpdateUI(); + //DirmethodUpdateUI(); + //LmethodUpdateUI(); + enabledUpdateUI (); + medianlevUpdateUI (); + cbenabUpdateUI (); + + if(z == 9) { + sup->show(); + } else { + sup->hide(); + } + } + + /***************************************************************************************************** + * + * Enable listeners and signals + * + *****************************************************************************************************/ + + Lmethodconn.block(false); + CLmethodconn.block(false); + Backmethodconn.block(false); + Tilesmethodconn.block(false); + daubcoeffmethodconn.block(false); + CHmethodconn.block(false); + CHSLmethodconn.block(false); + EDmethodconn.block(false); + NPmethodconn.block(false); + BAmethodconn.block(false); + TMmethodconn.block(false); + HSmethodconn.block(false); + Dirmethodconn.block(false); + MedgreinfConn.block(false); + enableChromaConn.block(false); + enableContrastConn.block(false); + enableEdgeConn.block(false); + enableFinalConn.block(false); + enableNoiseConn.block(false); + enableResidConn.block(false); + enableToningConn.block(false); + + enableListener (); } -void Wavelet::setEditProvider (EditDataProvider *provider) { - ccshape->setEditProvider(provider); - opacityShapeRG->setEditProvider(provider); - opacityShapeBY->setEditProvider(provider); - opacityShape->setEditProvider(provider); - opacityShapeWL->setEditProvider(provider); - hhshape->setEditProvider(provider); - Chshape->setEditProvider(provider); - clshape->setEditProvider(provider); +void Wavelet::setEditProvider (EditDataProvider *provider) +{ + ccshape->setEditProvider(provider); + opacityShapeRG->setEditProvider(provider); + opacityShapeBY->setEditProvider(provider); + opacityShape->setEditProvider(provider); + opacityShapeWL->setEditProvider(provider); + hhshape->setEditProvider(provider); + Chshape->setEditProvider(provider); + clshape->setEditProvider(provider); } -void Wavelet::autoOpenCurve () { - ccshape->openIfNonlinear(); - //opacityShapeRG->openIfNonlinear(); - //opacityShapeBY->openIfNonlinear(); +void Wavelet::autoOpenCurve () +{ + ccshape->openIfNonlinear(); + //opacityShapeRG->openIfNonlinear(); + //opacityShapeBY->openIfNonlinear(); } -void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { +void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) +{ - pp->wavelet.enabled = getEnabled(); - pp->wavelet.avoid = avoid->get_active (); - pp->wavelet.tmr = tmr->get_active (); - pp->wavelet.rescon = rescon->getValue(); - pp->wavelet.resconH = resconH->getValue(); - pp->wavelet.reschro = reschro->getValue(); - pp->wavelet.tmrs = tmrs->getValue(); - pp->wavelet.gamma = gamma->getValue(); - pp->wavelet.sup = sup->getValue(); - pp->wavelet.sky = sky->getValue(); - pp->wavelet.thres = thres->getValue(); - pp->wavelet.chroma = chroma->getValue(); - pp->wavelet.chro = chro->getValue(); - pp->wavelet.median = median->get_active (); - pp->wavelet.medianlev = medianlev->get_active (); - pp->wavelet.linkedg = linkedg->get_active (); -// pp->wavelet.edgreinf = edgreinf->get_active (); - pp->wavelet.cbenab = cbenab->get_active (); - pp->wavelet.lipst = lipst->get_active (); - pp->wavelet.contrast = contrast->getValue(); - pp->wavelet.edgrad = edgrad->getValue(); - pp->wavelet.edgval = edgval->getValue(); - pp->wavelet.edgthresh = edgthresh->getValue(); - pp->wavelet.thr = thr->getValue(); - pp->wavelet.thrH = thrH->getValue(); - pp->wavelet.hueskin = hueskin->getValue (); - pp->wavelet.hueskin2 = hueskin2->getValue (); - pp->wavelet.skinprotect = skinprotect->getValue(); - pp->wavelet.threshold = threshold->getValue(); - pp->wavelet.threshold2 = threshold2->getValue(); - pp->wavelet.edgedetect = edgedetect->getValue(); - pp->wavelet.edgedetectthr = edgedetectthr->getValue(); - pp->wavelet.edgedetectthr2 = edgedetectthr2->getValue(); - pp->wavelet.edgesensi = edgesensi->getValue(); - pp->wavelet.edgeampli = edgeampli->getValue(); - pp->wavelet.hllev = hllev->getValue (); - pp->wavelet.bllev = bllev->getValue (); - pp->wavelet.edgcont = edgcont->getValue (); - pp->wavelet.level0noise = level0noise->getValue (); - pp->wavelet.level1noise = level1noise->getValue (); - pp->wavelet.level2noise = level2noise->getValue (); - pp->wavelet.level3noise = level3noise->getValue (); - pp->wavelet.ccwcurve = ccshape->getCurve (); - pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve (); - pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve (); - pp->wavelet.opacityCurveW = opacityShape->getCurve (); - pp->wavelet.opacityCurveWL = opacityShapeWL->getCurve (); - pp->wavelet.hhcurve = hhshape->getCurve (); - pp->wavelet.Chcurve = Chshape->getCurve (); - pp->wavelet.pastlev = pastlev->getValue (); - pp->wavelet.satlev = satlev->getValue (); - pp->wavelet.strength = (int) strength->getValue(); - pp->wavelet.balance = (int) balance->getValue(); + pp->wavelet.enabled = getEnabled(); + pp->wavelet.avoid = avoid->get_active (); + pp->wavelet.tmr = tmr->get_active (); + pp->wavelet.rescon = rescon->getValue(); + pp->wavelet.resconH = resconH->getValue(); + pp->wavelet.reschro = reschro->getValue(); + pp->wavelet.tmrs = tmrs->getValue(); + pp->wavelet.gamma = gamma->getValue(); + pp->wavelet.sup = sup->getValue(); + pp->wavelet.sky = sky->getValue(); + pp->wavelet.thres = thres->getValue(); + pp->wavelet.chroma = chroma->getValue(); + pp->wavelet.chro = chro->getValue(); + pp->wavelet.median = median->get_active (); + pp->wavelet.medianlev = medianlev->get_active (); + pp->wavelet.linkedg = linkedg->get_active (); +// pp->wavelet.edgreinf = edgreinf->get_active (); + pp->wavelet.cbenab = cbenab->get_active (); + pp->wavelet.lipst = lipst->get_active (); + pp->wavelet.contrast = contrast->getValue(); + pp->wavelet.edgrad = edgrad->getValue(); + pp->wavelet.edgval = edgval->getValue(); + pp->wavelet.edgthresh = edgthresh->getValue(); + pp->wavelet.thr = thr->getValue(); + pp->wavelet.thrH = thrH->getValue(); + pp->wavelet.hueskin = hueskin->getValue (); + pp->wavelet.hueskin2 = hueskin2->getValue (); + pp->wavelet.skinprotect = skinprotect->getValue(); + pp->wavelet.threshold = threshold->getValue(); + pp->wavelet.threshold2 = threshold2->getValue(); + pp->wavelet.edgedetect = edgedetect->getValue(); + pp->wavelet.edgedetectthr = edgedetectthr->getValue(); + pp->wavelet.edgedetectthr2 = edgedetectthr2->getValue(); + pp->wavelet.edgesensi = edgesensi->getValue(); + pp->wavelet.edgeampli = edgeampli->getValue(); + pp->wavelet.hllev = hllev->getValue (); + pp->wavelet.bllev = bllev->getValue (); + pp->wavelet.edgcont = edgcont->getValue (); + pp->wavelet.level0noise = level0noise->getValue (); + pp->wavelet.level1noise = level1noise->getValue (); + pp->wavelet.level2noise = level2noise->getValue (); + pp->wavelet.level3noise = level3noise->getValue (); + pp->wavelet.ccwcurve = ccshape->getCurve (); + pp->wavelet.opacityCurveRG = opacityShapeRG->getCurve (); + pp->wavelet.opacityCurveBY = opacityShapeBY->getCurve (); + pp->wavelet.opacityCurveW = opacityShape->getCurve (); + pp->wavelet.opacityCurveWL = opacityShapeWL->getCurve (); + pp->wavelet.hhcurve = hhshape->getCurve (); + pp->wavelet.Chcurve = Chshape->getCurve (); + pp->wavelet.pastlev = pastlev->getValue (); + pp->wavelet.satlev = satlev->getValue (); + pp->wavelet.strength = (int) strength->getValue(); + pp->wavelet.balance = (int) balance->getValue(); - pp->wavelet.greenlow = greenlow->getValue (); - pp->wavelet.bluelow = bluelow->getValue (); - pp->wavelet.greenmed = greenmed->getValue (); - pp->wavelet.bluemed = bluemed->getValue (); - pp->wavelet.greenhigh = greenhigh->getValue (); - pp->wavelet.bluehigh = bluehigh->getValue (); - pp->wavelet.expcontrast = expcontrast->getEnabled(); - pp->wavelet.expchroma = expchroma->getEnabled(); - pp->wavelet.expedge = expedge->getEnabled(); - pp->wavelet.expresid = expresid->getEnabled(); - pp->wavelet.expfinal = expfinal->getEnabled(); - pp->wavelet.exptoning = exptoning->getEnabled(); - pp->wavelet.expnoise = expnoise->getEnabled(); + pp->wavelet.greenlow = greenlow->getValue (); + pp->wavelet.bluelow = bluelow->getValue (); + pp->wavelet.greenmed = greenmed->getValue (); + pp->wavelet.bluemed = bluemed->getValue (); + pp->wavelet.greenhigh = greenhigh->getValue (); + pp->wavelet.bluehigh = bluehigh->getValue (); + pp->wavelet.expcontrast = expcontrast->getEnabled(); + pp->wavelet.expchroma = expchroma->getEnabled(); + pp->wavelet.expedge = expedge->getEnabled(); + pp->wavelet.expresid = expresid->getEnabled(); + pp->wavelet.expfinal = expfinal->getEnabled(); + pp->wavelet.exptoning = exptoning->getEnabled(); + pp->wavelet.expnoise = expnoise->getEnabled(); - pp->wavelet.iter = (int) iter->getValue(); - pp->wavelet.wavclCurve = clshape->getCurve (); + pp->wavelet.iter = (int) iter->getValue(); + pp->wavelet.wavclCurve = clshape->getCurve (); - for (int i = 0; i < 9; i++) - pp->wavelet.c[i] = (int) correction[i]->getValue(); - for (int i = 0; i < 9; i++) - pp->wavelet.ch[i] = (int) correctionch[i]->getValue(); + for (int i = 0; i < 9; i++) { + pp->wavelet.c[i] = (int) correction[i]->getValue(); + } - if (pedited) { - pedited->wavelet.enabled = !get_inconsistent(); - pedited->wavelet.avoid = !avoid->get_inconsistent(); - pedited->wavelet.tmr = !tmr->get_inconsistent(); - pedited->wavelet.median = !median->get_inconsistent(); - pedited->wavelet.medianlev = !medianlev->get_inconsistent(); - pedited->wavelet.linkedg = !linkedg->get_inconsistent(); - pedited->wavelet.cbenab = !cbenab->get_inconsistent(); - pedited->wavelet.lipst = !lipst->get_inconsistent(); - pedited->wavelet.Medgreinf = Medgreinf->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.Lmethod = Lmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.CLmethod = CLmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.Backmethod = Backmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.Tilesmethod = Tilesmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.daubcoeffmethod = daubcoeffmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.CHmethod = CHmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.CHSLmethod = CHSLmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.EDmethod = EDmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.NPmethod = NPmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.BAmethod = BAmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.TMmethod = TMmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.HSmethod = HSmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.Dirmethod = Dirmethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->wavelet.edgthresh = edgthresh->getEditedState(); - pedited->wavelet.rescon = rescon->getEditedState(); - pedited->wavelet.resconH = resconH->getEditedState(); - pedited->wavelet.reschro = reschro->getEditedState(); - pedited->wavelet.tmrs = tmrs->getEditedState(); - pedited->wavelet.gamma = gamma->getEditedState(); - pedited->wavelet.sup = sup->getEditedState(); - pedited->wavelet.sky = sky->getEditedState(); - pedited->wavelet.thres = thres->getEditedState(); - pedited->wavelet.threshold = threshold->getEditedState(); - pedited->wavelet.threshold2 = threshold2->getEditedState(); - pedited->wavelet.edgedetect = edgedetect->getEditedState(); - pedited->wavelet.edgedetectthr = edgedetectthr->getEditedState(); - pedited->wavelet.edgedetectthr2 = edgedetectthr2->getEditedState(); - pedited->wavelet.edgesensi = edgesensi->getEditedState(); - pedited->wavelet.edgeampli = edgeampli->getEditedState(); - pedited->wavelet.chroma = chroma->getEditedState(); - pedited->wavelet.chro = chro->getEditedState(); - pedited->wavelet.contrast = contrast->getEditedState(); - pedited->wavelet.edgrad = edgrad->getEditedState(); - pedited->wavelet.edgval = edgval->getEditedState(); - pedited->wavelet.thr = thr->getEditedState(); - pedited->wavelet.thrH = thrH->getEditedState(); - pedited->wavelet.hueskin = hueskin->getEditedState (); - pedited->wavelet.hueskin2 = hueskin2->getEditedState (); - pedited->wavelet.skinprotect = skinprotect->getEditedState(); - pedited->wavelet.hllev = hllev->getEditedState (); - pedited->wavelet.ccwcurve = !ccshape->isUnChanged (); - pedited->wavelet.edgcont = edgcont->getEditedState (); - pedited->wavelet.level0noise = level0noise->getEditedState (); - pedited->wavelet.level1noise = level1noise->getEditedState (); - pedited->wavelet.level2noise = level2noise->getEditedState (); - pedited->wavelet.level3noise = level3noise->getEditedState (); - pedited->wavelet.opacityCurveRG = !opacityShapeRG->isUnChanged (); - pedited->wavelet.opacityCurveBY = !opacityShapeBY->isUnChanged (); - pedited->wavelet.opacityCurveW = !opacityShape->isUnChanged (); - pedited->wavelet.opacityCurveWL = !opacityShapeWL->isUnChanged (); - pedited->wavelet.hhcurve = !hhshape->isUnChanged (); - pedited->wavelet.Chcurve = !Chshape->isUnChanged (); - pedited->wavelet.bllev = bllev->getEditedState (); - pedited->wavelet.pastlev = pastlev->getEditedState (); - pedited->wavelet.satlev = satlev->getEditedState (); - pedited->wavelet.strength = strength->getEditedState (); - pedited->wavelet.greenlow = greenlow->getEditedState (); - pedited->wavelet.bluelow = bluelow->getEditedState (); - pedited->wavelet.greenmed = greenmed->getEditedState (); - pedited->wavelet.bluemed = bluemed->getEditedState (); - pedited->wavelet.greenhigh = greenhigh->getEditedState (); - pedited->wavelet.bluehigh = bluehigh->getEditedState (); - pedited->wavelet.balance = balance->getEditedState (); - pedited->wavelet.iter = iter->getEditedState (); - pedited->wavelet.wavclCurve = !clshape->isUnChanged (); - pedited->wavelet.expcontrast = !expcontrast->get_inconsistent(); - pedited->wavelet.expchroma = !expchroma->get_inconsistent(); - pedited->wavelet.expedge = !expedge->get_inconsistent(); - pedited->wavelet.expresid = !expresid->get_inconsistent(); - pedited->wavelet.expfinal = !expfinal->get_inconsistent(); - pedited->wavelet.exptoning = !exptoning->get_inconsistent(); - pedited->wavelet.expnoise = !expnoise->get_inconsistent(); + for (int i = 0; i < 9; i++) { + pp->wavelet.ch[i] = (int) correctionch[i]->getValue(); + } - for(int i = 0; i < 9; i++) - pedited->wavelet.c[i] = correction[i]->getEditedState(); - for(int i = 0; i < 9; i++) - pedited->wavelet.ch[i] = correctionch[i]->getEditedState(); - - } - if (CHmethod->get_active_row_number()==0) - pp->wavelet.CHmethod = "without"; - else if (CHmethod->get_active_row_number()==1) - pp->wavelet.CHmethod = "with"; - else if (CHmethod->get_active_row_number()==2) - pp->wavelet.CHmethod = "link"; + if (pedited) { + pedited->wavelet.enabled = !get_inconsistent(); + pedited->wavelet.avoid = !avoid->get_inconsistent(); + pedited->wavelet.tmr = !tmr->get_inconsistent(); + pedited->wavelet.median = !median->get_inconsistent(); + pedited->wavelet.medianlev = !medianlev->get_inconsistent(); + pedited->wavelet.linkedg = !linkedg->get_inconsistent(); + pedited->wavelet.cbenab = !cbenab->get_inconsistent(); + pedited->wavelet.lipst = !lipst->get_inconsistent(); + pedited->wavelet.Medgreinf = Medgreinf->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.Lmethod = Lmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.CLmethod = CLmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.Backmethod = Backmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.Tilesmethod = Tilesmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.daubcoeffmethod = daubcoeffmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.CHmethod = CHmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.CHSLmethod = CHSLmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.EDmethod = EDmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.NPmethod = NPmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.BAmethod = BAmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.TMmethod = TMmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.HSmethod = HSmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.Dirmethod = Dirmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.edgthresh = edgthresh->getEditedState(); + pedited->wavelet.rescon = rescon->getEditedState(); + pedited->wavelet.resconH = resconH->getEditedState(); + pedited->wavelet.reschro = reschro->getEditedState(); + pedited->wavelet.tmrs = tmrs->getEditedState(); + pedited->wavelet.gamma = gamma->getEditedState(); + pedited->wavelet.sup = sup->getEditedState(); + pedited->wavelet.sky = sky->getEditedState(); + pedited->wavelet.thres = thres->getEditedState(); + pedited->wavelet.threshold = threshold->getEditedState(); + pedited->wavelet.threshold2 = threshold2->getEditedState(); + pedited->wavelet.edgedetect = edgedetect->getEditedState(); + pedited->wavelet.edgedetectthr = edgedetectthr->getEditedState(); + pedited->wavelet.edgedetectthr2 = edgedetectthr2->getEditedState(); + pedited->wavelet.edgesensi = edgesensi->getEditedState(); + pedited->wavelet.edgeampli = edgeampli->getEditedState(); + pedited->wavelet.chroma = chroma->getEditedState(); + pedited->wavelet.chro = chro->getEditedState(); + pedited->wavelet.contrast = contrast->getEditedState(); + pedited->wavelet.edgrad = edgrad->getEditedState(); + pedited->wavelet.edgval = edgval->getEditedState(); + pedited->wavelet.thr = thr->getEditedState(); + pedited->wavelet.thrH = thrH->getEditedState(); + pedited->wavelet.hueskin = hueskin->getEditedState (); + pedited->wavelet.hueskin2 = hueskin2->getEditedState (); + pedited->wavelet.skinprotect = skinprotect->getEditedState(); + pedited->wavelet.hllev = hllev->getEditedState (); + pedited->wavelet.ccwcurve = !ccshape->isUnChanged (); + pedited->wavelet.edgcont = edgcont->getEditedState (); + pedited->wavelet.level0noise = level0noise->getEditedState (); + pedited->wavelet.level1noise = level1noise->getEditedState (); + pedited->wavelet.level2noise = level2noise->getEditedState (); + pedited->wavelet.level3noise = level3noise->getEditedState (); + pedited->wavelet.opacityCurveRG = !opacityShapeRG->isUnChanged (); + pedited->wavelet.opacityCurveBY = !opacityShapeBY->isUnChanged (); + pedited->wavelet.opacityCurveW = !opacityShape->isUnChanged (); + pedited->wavelet.opacityCurveWL = !opacityShapeWL->isUnChanged (); + pedited->wavelet.hhcurve = !hhshape->isUnChanged (); + pedited->wavelet.Chcurve = !Chshape->isUnChanged (); + pedited->wavelet.bllev = bllev->getEditedState (); + pedited->wavelet.pastlev = pastlev->getEditedState (); + pedited->wavelet.satlev = satlev->getEditedState (); + pedited->wavelet.strength = strength->getEditedState (); + pedited->wavelet.greenlow = greenlow->getEditedState (); + pedited->wavelet.bluelow = bluelow->getEditedState (); + pedited->wavelet.greenmed = greenmed->getEditedState (); + pedited->wavelet.bluemed = bluemed->getEditedState (); + pedited->wavelet.greenhigh = greenhigh->getEditedState (); + pedited->wavelet.bluehigh = bluehigh->getEditedState (); + pedited->wavelet.balance = balance->getEditedState (); + pedited->wavelet.iter = iter->getEditedState (); + pedited->wavelet.wavclCurve = !clshape->isUnChanged (); + pedited->wavelet.expcontrast = !expcontrast->get_inconsistent(); + pedited->wavelet.expchroma = !expchroma->get_inconsistent(); + pedited->wavelet.expedge = !expedge->get_inconsistent(); + pedited->wavelet.expresid = !expresid->get_inconsistent(); + pedited->wavelet.expfinal = !expfinal->get_inconsistent(); + pedited->wavelet.exptoning = !exptoning->get_inconsistent(); + pedited->wavelet.expnoise = !expnoise->get_inconsistent(); - if (Medgreinf->get_active_row_number()==0) - pp->wavelet.Medgreinf = "more"; - else if (Medgreinf->get_active_row_number()==1) - pp->wavelet.Medgreinf = "none"; - else if (Medgreinf->get_active_row_number()==2) - pp->wavelet.Medgreinf = "less"; - - if (CHSLmethod->get_active_row_number()==0) - pp->wavelet.CHSLmethod = "SL"; - else if (CHSLmethod->get_active_row_number()==1) - pp->wavelet.CHSLmethod = "CU"; + for(int i = 0; i < 9; i++) { + pedited->wavelet.c[i] = correction[i]->getEditedState(); + } - if (EDmethod->get_active_row_number()==0) - pp->wavelet.EDmethod = "SL"; - else if (EDmethod->get_active_row_number()==1) - pp->wavelet.EDmethod = "CU"; + for(int i = 0; i < 9; i++) { + pedited->wavelet.ch[i] = correctionch[i]->getEditedState(); + } - if (NPmethod->get_active_row_number()==0) - pp->wavelet.NPmethod = "none"; - else if (NPmethod->get_active_row_number()==1) - pp->wavelet.NPmethod = "low"; - else if (NPmethod->get_active_row_number()==2) - pp->wavelet.NPmethod = "high"; - - if (BAmethod->get_active_row_number()==0) - pp->wavelet.BAmethod = "none"; - else if (BAmethod->get_active_row_number()==1) - pp->wavelet.BAmethod = "sli"; - else if (BAmethod->get_active_row_number()==2) - pp->wavelet.BAmethod = "cur"; + } - if (TMmethod->get_active_row_number()==0) - pp->wavelet.TMmethod = "cont"; - else if (TMmethod->get_active_row_number()==1) - pp->wavelet.TMmethod = "tm"; - // else if (TMmethod->get_active_row_number()==2) - // pp->wavelet.TMmethod = "both"; - - if (HSmethod->get_active_row_number()==0) - pp->wavelet.HSmethod = "without"; - else if (HSmethod->get_active_row_number()==1) - pp->wavelet.HSmethod = "with"; - - if (CLmethod->get_active_row_number()==0) - pp->wavelet.CLmethod = "one"; - else if (CLmethod->get_active_row_number()==1) - pp->wavelet.CLmethod = "inf"; - else if (CLmethod->get_active_row_number()==2) - pp->wavelet.CLmethod = "sup"; - else if (CLmethod->get_active_row_number()==3) - pp->wavelet.CLmethod = "all"; + if (CHmethod->get_active_row_number() == 0) { + pp->wavelet.CHmethod = "without"; + } else if (CHmethod->get_active_row_number() == 1) { + pp->wavelet.CHmethod = "with"; + } else if (CHmethod->get_active_row_number() == 2) { + pp->wavelet.CHmethod = "link"; + } - if (Backmethod->get_active_row_number()==0) - pp->wavelet.Backmethod = "black"; - else if (Backmethod->get_active_row_number()==1) - pp->wavelet.Backmethod = "grey"; - else if (Backmethod->get_active_row_number()==2) - pp->wavelet.Backmethod = "resid"; - - if (Tilesmethod->get_active_row_number()==0) - pp->wavelet.Tilesmethod = "full"; - else if (Tilesmethod->get_active_row_number()==1) - pp->wavelet.Tilesmethod = "big"; - else if (Tilesmethod->get_active_row_number()==2) - pp->wavelet.Tilesmethod = "lit"; + if (Medgreinf->get_active_row_number() == 0) { + pp->wavelet.Medgreinf = "more"; + } else if (Medgreinf->get_active_row_number() == 1) { + pp->wavelet.Medgreinf = "none"; + } else if (Medgreinf->get_active_row_number() == 2) { + pp->wavelet.Medgreinf = "less"; + } - if (daubcoeffmethod->get_active_row_number()==0) - pp->wavelet.daubcoeffmethod = "2_"; - else if (daubcoeffmethod->get_active_row_number()==1) - pp->wavelet.daubcoeffmethod = "4_"; - else if (daubcoeffmethod->get_active_row_number()==2) - pp->wavelet.daubcoeffmethod = "6_"; - else if (daubcoeffmethod->get_active_row_number()==3) - pp->wavelet.daubcoeffmethod = "10_"; - else if (daubcoeffmethod->get_active_row_number()==4) - pp->wavelet.daubcoeffmethod = "14_"; - - if (Dirmethod->get_active_row_number()==0) - pp->wavelet.Dirmethod = "one"; - else if (Dirmethod->get_active_row_number()==1) - pp->wavelet.Dirmethod = "two"; - else if (Dirmethod->get_active_row_number()==2) - pp->wavelet.Dirmethod = "thr"; - else if (Dirmethod->get_active_row_number()==3) - pp->wavelet.Dirmethod = "all"; - - char lMethod[3]; // one additional char to avoid buffer overrun if someone increases number of levels > 9 - sprintf(lMethod, "%d", Lmethod->get_active_row_number()+1); - pp->wavelet.Lmethod = lMethod; + if (CHSLmethod->get_active_row_number() == 0) { + pp->wavelet.CHSLmethod = "SL"; + } else if (CHSLmethod->get_active_row_number() == 1) { + pp->wavelet.CHSLmethod = "CU"; + } + + if (EDmethod->get_active_row_number() == 0) { + pp->wavelet.EDmethod = "SL"; + } else if (EDmethod->get_active_row_number() == 1) { + pp->wavelet.EDmethod = "CU"; + } + + if (NPmethod->get_active_row_number() == 0) { + pp->wavelet.NPmethod = "none"; + } else if (NPmethod->get_active_row_number() == 1) { + pp->wavelet.NPmethod = "low"; + } else if (NPmethod->get_active_row_number() == 2) { + pp->wavelet.NPmethod = "high"; + } + + if (BAmethod->get_active_row_number() == 0) { + pp->wavelet.BAmethod = "none"; + } else if (BAmethod->get_active_row_number() == 1) { + pp->wavelet.BAmethod = "sli"; + } else if (BAmethod->get_active_row_number() == 2) { + pp->wavelet.BAmethod = "cur"; + } + + if (TMmethod->get_active_row_number() == 0) { + pp->wavelet.TMmethod = "cont"; + } else if (TMmethod->get_active_row_number() == 1) { + pp->wavelet.TMmethod = "tm"; + } + + // else if (TMmethod->get_active_row_number()==2) + // pp->wavelet.TMmethod = "both"; + + if (HSmethod->get_active_row_number() == 0) { + pp->wavelet.HSmethod = "without"; + } else if (HSmethod->get_active_row_number() == 1) { + pp->wavelet.HSmethod = "with"; + } + + if (CLmethod->get_active_row_number() == 0) { + pp->wavelet.CLmethod = "one"; + } else if (CLmethod->get_active_row_number() == 1) { + pp->wavelet.CLmethod = "inf"; + } else if (CLmethod->get_active_row_number() == 2) { + pp->wavelet.CLmethod = "sup"; + } else if (CLmethod->get_active_row_number() == 3) { + pp->wavelet.CLmethod = "all"; + } + + if (Backmethod->get_active_row_number() == 0) { + pp->wavelet.Backmethod = "black"; + } else if (Backmethod->get_active_row_number() == 1) { + pp->wavelet.Backmethod = "grey"; + } else if (Backmethod->get_active_row_number() == 2) { + pp->wavelet.Backmethod = "resid"; + } + + if (Tilesmethod->get_active_row_number() == 0) { + pp->wavelet.Tilesmethod = "full"; + } else if (Tilesmethod->get_active_row_number() == 1) { + pp->wavelet.Tilesmethod = "big"; + } else if (Tilesmethod->get_active_row_number() == 2) { + pp->wavelet.Tilesmethod = "lit"; + } + + if (daubcoeffmethod->get_active_row_number() == 0) { + pp->wavelet.daubcoeffmethod = "2_"; + } else if (daubcoeffmethod->get_active_row_number() == 1) { + pp->wavelet.daubcoeffmethod = "4_"; + } else if (daubcoeffmethod->get_active_row_number() == 2) { + pp->wavelet.daubcoeffmethod = "6_"; + } else if (daubcoeffmethod->get_active_row_number() == 3) { + pp->wavelet.daubcoeffmethod = "10_"; + } else if (daubcoeffmethod->get_active_row_number() == 4) { + pp->wavelet.daubcoeffmethod = "14_"; + } + + if (Dirmethod->get_active_row_number() == 0) { + pp->wavelet.Dirmethod = "one"; + } else if (Dirmethod->get_active_row_number() == 1) { + pp->wavelet.Dirmethod = "two"; + } else if (Dirmethod->get_active_row_number() == 2) { + pp->wavelet.Dirmethod = "thr"; + } else if (Dirmethod->get_active_row_number() == 3) { + pp->wavelet.Dirmethod = "all"; + } + + char lMethod[3]; // one additional char to avoid buffer overrun if someone increases number of levels > 9 + sprintf(lMethod, "%d", Lmethod->get_active_row_number() + 1); + pp->wavelet.Lmethod = lMethod; } -void Wavelet::curveChanged (CurveEditor* ce) { +void Wavelet::curveChanged (CurveEditor* ce) +{ - if (listener && getEnabled()) { - if (ce == ccshape) - listener->panelChanged (EvWavCCCurve, M("HISTORY_CUSTOMCURVE")); - else if (ce == opacityShapeRG) - listener->panelChanged (EvWavColor, M("HISTORY_CUSTOMCURVE")); - else if (ce == opacityShapeBY) - listener->panelChanged (EvWavOpac, M("HISTORY_CUSTOMCURVE")); - else if (ce == opacityShape) - listener->panelChanged (EvWavopacity, M("HISTORY_CUSTOMCURVE")); - else if (ce == opacityShapeWL) - listener->panelChanged (EvWavopacityWL, M("HISTORY_CUSTOMCURVE")); - else if (ce == hhshape) - listener->panelChanged (EvWavHHCurve, M("HISTORY_CUSTOMCURVE")); - else if (ce == Chshape) - listener->panelChanged (EvWavCHCurve, M("HISTORY_CUSTOMCURVE")); - else if (ce == clshape) - listener->panelChanged (EvWavCLCurve, M("HISTORY_CUSTOMCURVE")); - } + if (listener && getEnabled()) { + if (ce == ccshape) { + listener->panelChanged (EvWavCCCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == opacityShapeRG) { + listener->panelChanged (EvWavColor, M("HISTORY_CUSTOMCURVE")); + } else if (ce == opacityShapeBY) { + listener->panelChanged (EvWavOpac, M("HISTORY_CUSTOMCURVE")); + } else if (ce == opacityShape) { + listener->panelChanged (EvWavopacity, M("HISTORY_CUSTOMCURVE")); + } else if (ce == opacityShapeWL) { + listener->panelChanged (EvWavopacityWL, M("HISTORY_CUSTOMCURVE")); + } else if (ce == hhshape) { + listener->panelChanged (EvWavHHCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == Chshape) { + listener->panelChanged (EvWavCHCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == clshape) { + listener->panelChanged (EvWavCLCurve, M("HISTORY_CUSTOMCURVE")); + } + } } -void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ - for (int i = 0; i < 9; i++) { - correction[i]->setDefault(defParams->wavelet.c[i]); - } - for (int i = 0; i < 9; i++) { - correctionch[i]->setDefault(defParams->wavelet.ch[i]); - } - strength->setDefault(defParams->wavelet.strength ); - balance->setDefault(defParams->wavelet.balance ); - iter->setDefault(defParams->wavelet.iter ); - rescon->setDefault (defParams->wavelet.rescon); - resconH->setDefault (defParams->wavelet.resconH); - reschro->setDefault (defParams->wavelet.reschro); - tmrs->setDefault (defParams->wavelet.tmrs); - gamma->setDefault (defParams->wavelet.gamma); - sup->setDefault (defParams->wavelet.sup); - sky->setDefault (defParams->wavelet.sky); - thres->setDefault (defParams->wavelet.thres); - threshold->setDefault (defParams->wavelet.threshold); - threshold2->setDefault (defParams->wavelet.threshold2); - edgedetect->setDefault (defParams->wavelet.edgedetect); - edgedetectthr->setDefault (defParams->wavelet.edgedetectthr); - edgedetectthr2->setDefault (defParams->wavelet.edgedetectthr2); - edgesensi->setDefault (defParams->wavelet.edgesensi); - edgeampli->setDefault (defParams->wavelet.edgeampli); - chroma->setDefault (defParams->wavelet.chroma); - chro->setDefault (defParams->wavelet.chro); - contrast->setDefault (defParams->wavelet.contrast); - edgrad->setDefault (defParams->wavelet.edgrad); - edgval->setDefault (defParams->wavelet.edgval); - edgthresh->setDefault (defParams->wavelet.edgthresh); - thr->setDefault (defParams->wavelet.thr); - thrH->setDefault (defParams->wavelet.thrH); - hueskin->setDefault (defParams->wavelet.hueskin); - hueskin2->setDefault (defParams->wavelet.hueskin2); - hllev->setDefault (defParams->wavelet.hllev); - bllev->setDefault (defParams->wavelet.bllev); - pastlev->setDefault (defParams->wavelet.pastlev); - satlev->setDefault (defParams->wavelet.satlev); - edgcont->setDefault (defParams->wavelet.edgcont); - level0noise->setDefault (defParams->wavelet.level0noise); - level1noise->setDefault (defParams->wavelet.level1noise); - level2noise->setDefault (defParams->wavelet.level2noise); - level3noise->setDefault (defParams->wavelet.level3noise); + for (int i = 0; i < 9; i++) { + correction[i]->setDefault(defParams->wavelet.c[i]); + } - greenlow->setDefault (defParams->wavelet.greenlow); - bluelow->setDefault (defParams->wavelet.bluelow); - greenmed->setDefault (defParams->wavelet.greenmed); - bluemed->setDefault (defParams->wavelet.bluemed); - greenhigh->setDefault (defParams->wavelet.greenhigh); - bluehigh->setDefault (defParams->wavelet.bluehigh); + for (int i = 0; i < 9; i++) { + correctionch[i]->setDefault(defParams->wavelet.ch[i]); + } - if (pedited) { - greenlow->setDefaultEditedState (pedited->wavelet.greenlow ? Edited : UnEdited); - bluelow->setDefaultEditedState (pedited->wavelet.bluelow ? Edited : UnEdited); - greenmed->setDefaultEditedState (pedited->wavelet.greenmed ? Edited : UnEdited); - bluemed->setDefaultEditedState (pedited->wavelet.bluemed ? Edited : UnEdited); - greenhigh->setDefaultEditedState (pedited->wavelet.greenhigh ? Edited : UnEdited); - bluehigh->setDefaultEditedState (pedited->wavelet.bluehigh ? Edited : UnEdited); + strength->setDefault(defParams->wavelet.strength ); + balance->setDefault(defParams->wavelet.balance ); + iter->setDefault(defParams->wavelet.iter ); + rescon->setDefault (defParams->wavelet.rescon); + resconH->setDefault (defParams->wavelet.resconH); + reschro->setDefault (defParams->wavelet.reschro); + tmrs->setDefault (defParams->wavelet.tmrs); + gamma->setDefault (defParams->wavelet.gamma); + sup->setDefault (defParams->wavelet.sup); + sky->setDefault (defParams->wavelet.sky); + thres->setDefault (defParams->wavelet.thres); + threshold->setDefault (defParams->wavelet.threshold); + threshold2->setDefault (defParams->wavelet.threshold2); + edgedetect->setDefault (defParams->wavelet.edgedetect); + edgedetectthr->setDefault (defParams->wavelet.edgedetectthr); + edgedetectthr2->setDefault (defParams->wavelet.edgedetectthr2); + edgesensi->setDefault (defParams->wavelet.edgesensi); + edgeampli->setDefault (defParams->wavelet.edgeampli); + chroma->setDefault (defParams->wavelet.chroma); + chro->setDefault (defParams->wavelet.chro); + contrast->setDefault (defParams->wavelet.contrast); + edgrad->setDefault (defParams->wavelet.edgrad); + edgval->setDefault (defParams->wavelet.edgval); + edgthresh->setDefault (defParams->wavelet.edgthresh); + thr->setDefault (defParams->wavelet.thr); + thrH->setDefault (defParams->wavelet.thrH); + hueskin->setDefault (defParams->wavelet.hueskin); + hueskin2->setDefault (defParams->wavelet.hueskin2); + hllev->setDefault (defParams->wavelet.hllev); + bllev->setDefault (defParams->wavelet.bllev); + pastlev->setDefault (defParams->wavelet.pastlev); + satlev->setDefault (defParams->wavelet.satlev); + edgcont->setDefault (defParams->wavelet.edgcont); + level0noise->setDefault (defParams->wavelet.level0noise); + level1noise->setDefault (defParams->wavelet.level1noise); + level2noise->setDefault (defParams->wavelet.level2noise); + level3noise->setDefault (defParams->wavelet.level3noise); - rescon->setDefault (defParams->wavelet.rescon); - resconH->setDefault (defParams->wavelet.resconH); - reschro->setDefault (defParams->wavelet.reschro); - tmrs->setDefault (defParams->wavelet.tmrs); - gamma->setDefault (defParams->wavelet.gamma); - sup->setDefault (defParams->wavelet.sup); - sky->setDefaultEditedState(pedited->wavelet.sky ? Edited : UnEdited); - thres->setDefaultEditedState(pedited->wavelet.thres ? Edited : UnEdited); - threshold->setDefaultEditedState(pedited->wavelet.threshold ? Edited : UnEdited); - threshold2->setDefaultEditedState(pedited->wavelet.threshold2 ? Edited : UnEdited); - edgedetect->setDefaultEditedState(pedited->wavelet.edgedetect ? Edited : UnEdited); - edgedetectthr->setDefaultEditedState(pedited->wavelet.edgedetectthr ? Edited : UnEdited); - edgedetectthr2->setDefaultEditedState(pedited->wavelet.edgedetectthr2 ? Edited : UnEdited); - edgesensi->setDefaultEditedState(pedited->wavelet.edgesensi ? Edited : UnEdited); - edgeampli->setDefaultEditedState(pedited->wavelet.edgeampli ? Edited : UnEdited); - chroma->setDefaultEditedState(pedited->wavelet.chroma ? Edited : UnEdited); - chro->setDefaultEditedState(pedited->wavelet.chro ? Edited : UnEdited); - contrast->setDefaultEditedState(pedited->wavelet.contrast ? Edited : UnEdited); - edgrad->setDefaultEditedState(pedited->wavelet.edgrad ? Edited : UnEdited); - edgval->setDefaultEditedState(pedited->wavelet.edgval ? Edited : UnEdited); - edgthresh->setDefault (defParams->wavelet.edgthresh); - thr->setDefaultEditedState(pedited->wavelet.thr ? Edited : UnEdited); - thrH->setDefaultEditedState(pedited->wavelet.thrH ? Edited : UnEdited); - skinprotect->setDefaultEditedState(pedited->wavelet.skinprotect ? Edited : UnEdited); - hueskin->setDefaultEditedState(pedited->wavelet.hueskin ? Edited : UnEdited); - hueskin2->setDefaultEditedState(pedited->wavelet.hueskin2 ? Edited : UnEdited); - hllev->setDefaultEditedState(pedited->wavelet.hllev ? Edited : UnEdited); - bllev->setDefaultEditedState(pedited->wavelet.bllev ? Edited : UnEdited); - pastlev->setDefaultEditedState(pedited->wavelet.pastlev ? Edited : UnEdited); - satlev->setDefaultEditedState(pedited->wavelet.satlev ? Edited : UnEdited); - edgcont->setDefaultEditedState(pedited->wavelet.edgcont ? Edited : UnEdited); - strength->setDefaultEditedState(pedited->wavelet.strength ? Edited : UnEdited); - balance->setDefaultEditedState(pedited->wavelet.balance ? Edited : UnEdited); - iter->setDefaultEditedState(pedited->wavelet.iter ? Edited : UnEdited); - level0noise->setDefaultEditedState(pedited->wavelet.level0noise ? Edited : UnEdited); - level1noise->setDefaultEditedState(pedited->wavelet.level1noise ? Edited : UnEdited); - level2noise->setDefaultEditedState(pedited->wavelet.level2noise ? Edited : UnEdited); - level3noise->setDefaultEditedState(pedited->wavelet.level3noise ? Edited : UnEdited); + greenlow->setDefault (defParams->wavelet.greenlow); + bluelow->setDefault (defParams->wavelet.bluelow); + greenmed->setDefault (defParams->wavelet.greenmed); + bluemed->setDefault (defParams->wavelet.bluemed); + greenhigh->setDefault (defParams->wavelet.greenhigh); + bluehigh->setDefault (defParams->wavelet.bluehigh); - for (int i = 0; i < 9; i++) { - correction[i]->setDefaultEditedState(pedited->wavelet.c[i] ? Edited : UnEdited); - } - for (int i = 0; i < 9; i++) { - correctionch[i]->setDefaultEditedState(pedited->wavelet.ch[i] ? Edited : UnEdited); - } - } - else { - rescon->setDefaultEditedState(Irrelevant); - resconH->setDefaultEditedState(Irrelevant); - reschro->setDefaultEditedState(Irrelevant); - tmrs->setDefaultEditedState(Irrelevant); - gamma->setDefaultEditedState(Irrelevant); - sup->setDefaultEditedState(Irrelevant); - sky->setDefaultEditedState(Irrelevant); - thres->setDefaultEditedState(Irrelevant); - threshold->setDefaultEditedState(Irrelevant); - threshold2->setDefaultEditedState(Irrelevant); - edgedetect->setDefaultEditedState(Irrelevant); - edgedetectthr->setDefaultEditedState(Irrelevant); - edgedetectthr2->setDefaultEditedState(Irrelevant); - edgesensi->setDefaultEditedState(Irrelevant); - edgeampli->setDefaultEditedState(Irrelevant); - chroma->setDefaultEditedState(Irrelevant); - chro->setDefaultEditedState(Irrelevant); - contrast->setDefaultEditedState(Irrelevant); - edgrad->setDefaultEditedState(Irrelevant); - edgval->setDefaultEditedState(Irrelevant); - edgthresh->setDefaultEditedState(Irrelevant); - thr->setDefaultEditedState(Irrelevant); - thrH->setDefaultEditedState(Irrelevant); - skinprotect->setDefaultEditedState(Irrelevant); - hueskin->setDefaultEditedState (Irrelevant); - hueskin2->setDefaultEditedState (Irrelevant); - hllev->setDefaultEditedState (Irrelevant); - bllev->setDefaultEditedState (Irrelevant); - edgcont->setDefaultEditedState (Irrelevant); - level0noise->setDefaultEditedState (Irrelevant); - level1noise->setDefaultEditedState (Irrelevant); - level2noise->setDefaultEditedState (Irrelevant); - level3noise->setDefaultEditedState (Irrelevant); - pastlev->setDefaultEditedState (Irrelevant); - satlev->setDefaultEditedState (Irrelevant); - strength->setDefaultEditedState (Irrelevant); - balance->setDefaultEditedState (Irrelevant); - iter->setDefaultEditedState (Irrelevant); + if (pedited) { + greenlow->setDefaultEditedState (pedited->wavelet.greenlow ? Edited : UnEdited); + bluelow->setDefaultEditedState (pedited->wavelet.bluelow ? Edited : UnEdited); + greenmed->setDefaultEditedState (pedited->wavelet.greenmed ? Edited : UnEdited); + bluemed->setDefaultEditedState (pedited->wavelet.bluemed ? Edited : UnEdited); + greenhigh->setDefaultEditedState (pedited->wavelet.greenhigh ? Edited : UnEdited); + bluehigh->setDefaultEditedState (pedited->wavelet.bluehigh ? Edited : UnEdited); - for (int i = 0; i < 9; i++) - correction[i]->setDefaultEditedState(Irrelevant); - for (int i = 0; i < 9; i++) - correctionch[i]->setDefaultEditedState(Irrelevant); - } + rescon->setDefault (defParams->wavelet.rescon); + resconH->setDefault (defParams->wavelet.resconH); + reschro->setDefault (defParams->wavelet.reschro); + tmrs->setDefault (defParams->wavelet.tmrs); + gamma->setDefault (defParams->wavelet.gamma); + sup->setDefault (defParams->wavelet.sup); + sky->setDefaultEditedState(pedited->wavelet.sky ? Edited : UnEdited); + thres->setDefaultEditedState(pedited->wavelet.thres ? Edited : UnEdited); + threshold->setDefaultEditedState(pedited->wavelet.threshold ? Edited : UnEdited); + threshold2->setDefaultEditedState(pedited->wavelet.threshold2 ? Edited : UnEdited); + edgedetect->setDefaultEditedState(pedited->wavelet.edgedetect ? Edited : UnEdited); + edgedetectthr->setDefaultEditedState(pedited->wavelet.edgedetectthr ? Edited : UnEdited); + edgedetectthr2->setDefaultEditedState(pedited->wavelet.edgedetectthr2 ? Edited : UnEdited); + edgesensi->setDefaultEditedState(pedited->wavelet.edgesensi ? Edited : UnEdited); + edgeampli->setDefaultEditedState(pedited->wavelet.edgeampli ? Edited : UnEdited); + chroma->setDefaultEditedState(pedited->wavelet.chroma ? Edited : UnEdited); + chro->setDefaultEditedState(pedited->wavelet.chro ? Edited : UnEdited); + contrast->setDefaultEditedState(pedited->wavelet.contrast ? Edited : UnEdited); + edgrad->setDefaultEditedState(pedited->wavelet.edgrad ? Edited : UnEdited); + edgval->setDefaultEditedState(pedited->wavelet.edgval ? Edited : UnEdited); + edgthresh->setDefault (defParams->wavelet.edgthresh); + thr->setDefaultEditedState(pedited->wavelet.thr ? Edited : UnEdited); + thrH->setDefaultEditedState(pedited->wavelet.thrH ? Edited : UnEdited); + skinprotect->setDefaultEditedState(pedited->wavelet.skinprotect ? Edited : UnEdited); + hueskin->setDefaultEditedState(pedited->wavelet.hueskin ? Edited : UnEdited); + hueskin2->setDefaultEditedState(pedited->wavelet.hueskin2 ? Edited : UnEdited); + hllev->setDefaultEditedState(pedited->wavelet.hllev ? Edited : UnEdited); + bllev->setDefaultEditedState(pedited->wavelet.bllev ? Edited : UnEdited); + pastlev->setDefaultEditedState(pedited->wavelet.pastlev ? Edited : UnEdited); + satlev->setDefaultEditedState(pedited->wavelet.satlev ? Edited : UnEdited); + edgcont->setDefaultEditedState(pedited->wavelet.edgcont ? Edited : UnEdited); + strength->setDefaultEditedState(pedited->wavelet.strength ? Edited : UnEdited); + balance->setDefaultEditedState(pedited->wavelet.balance ? Edited : UnEdited); + iter->setDefaultEditedState(pedited->wavelet.iter ? Edited : UnEdited); + level0noise->setDefaultEditedState(pedited->wavelet.level0noise ? Edited : UnEdited); + level1noise->setDefaultEditedState(pedited->wavelet.level1noise ? Edited : UnEdited); + level2noise->setDefaultEditedState(pedited->wavelet.level2noise ? Edited : UnEdited); + level3noise->setDefaultEditedState(pedited->wavelet.level3noise ? Edited : UnEdited); + + for (int i = 0; i < 9; i++) { + correction[i]->setDefaultEditedState(pedited->wavelet.c[i] ? Edited : UnEdited); + } + + for (int i = 0; i < 9; i++) { + correctionch[i]->setDefaultEditedState(pedited->wavelet.ch[i] ? Edited : UnEdited); + } + } else { + rescon->setDefaultEditedState(Irrelevant); + resconH->setDefaultEditedState(Irrelevant); + reschro->setDefaultEditedState(Irrelevant); + tmrs->setDefaultEditedState(Irrelevant); + gamma->setDefaultEditedState(Irrelevant); + sup->setDefaultEditedState(Irrelevant); + sky->setDefaultEditedState(Irrelevant); + thres->setDefaultEditedState(Irrelevant); + threshold->setDefaultEditedState(Irrelevant); + threshold2->setDefaultEditedState(Irrelevant); + edgedetect->setDefaultEditedState(Irrelevant); + edgedetectthr->setDefaultEditedState(Irrelevant); + edgedetectthr2->setDefaultEditedState(Irrelevant); + edgesensi->setDefaultEditedState(Irrelevant); + edgeampli->setDefaultEditedState(Irrelevant); + chroma->setDefaultEditedState(Irrelevant); + chro->setDefaultEditedState(Irrelevant); + contrast->setDefaultEditedState(Irrelevant); + edgrad->setDefaultEditedState(Irrelevant); + edgval->setDefaultEditedState(Irrelevant); + edgthresh->setDefaultEditedState(Irrelevant); + thr->setDefaultEditedState(Irrelevant); + thrH->setDefaultEditedState(Irrelevant); + skinprotect->setDefaultEditedState(Irrelevant); + hueskin->setDefaultEditedState (Irrelevant); + hueskin2->setDefaultEditedState (Irrelevant); + hllev->setDefaultEditedState (Irrelevant); + bllev->setDefaultEditedState (Irrelevant); + edgcont->setDefaultEditedState (Irrelevant); + level0noise->setDefaultEditedState (Irrelevant); + level1noise->setDefaultEditedState (Irrelevant); + level2noise->setDefaultEditedState (Irrelevant); + level3noise->setDefaultEditedState (Irrelevant); + pastlev->setDefaultEditedState (Irrelevant); + satlev->setDefaultEditedState (Irrelevant); + strength->setDefaultEditedState (Irrelevant); + balance->setDefaultEditedState (Irrelevant); + iter->setDefaultEditedState (Irrelevant); + + for (int i = 0; i < 9; i++) { + correction[i]->setDefaultEditedState(Irrelevant); + } + + for (int i = 0; i < 9; i++) { + correctionch[i]->setDefaultEditedState(Irrelevant); + } + } } -void Wavelet::adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop) { - if (listener && (multiImage||getEnabled()) ) { - if(a==level0noise) { - listener->panelChanged (EvWavlev0nois, - Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS")+": %1"+"\n"+M("TP_WAVELET_STREN")+": %2"), int(newTop), int(newBottom))); - } - else if(a==level1noise) { - listener->panelChanged (EvWavlev1nois, - Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS")+": %1"+"\n"+M("TP_WAVELET_STREN")+": %2"), int(newTop), int(newBottom))); - } - else if(a==level2noise) { - listener->panelChanged (EvWavlev2nois, - Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS")+": %1"+"\n"+M("TP_WAVELET_STREN")+": %2"), int(newTop), int(newBottom))); - } - else if(a==level3noise) { - listener->panelChanged (EvWavlev3nois, - Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS")+": %1"+"\n"+M("TP_WAVELET_STREN")+": %2"), int(newTop), int(newBottom))); - } - - } +void Wavelet::adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop) +{ + if (listener && (multiImage || getEnabled()) ) { + if(a == level0noise) { + listener->panelChanged (EvWavlev0nois, + Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS") + ": %1" + "\n" + M("TP_WAVELET_STREN") + ": %2"), int(newTop), int(newBottom))); + } else if(a == level1noise) { + listener->panelChanged (EvWavlev1nois, + Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS") + ": %1" + "\n" + M("TP_WAVELET_STREN") + ": %2"), int(newTop), int(newBottom))); + } else if(a == level2noise) { + listener->panelChanged (EvWavlev2nois, + Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS") + ": %1" + "\n" + M("TP_WAVELET_STREN") + ": %2"), int(newTop), int(newBottom))); + } else if(a == level3noise) { + listener->panelChanged (EvWavlev3nois, + Glib::ustring::compose(Glib::ustring(M("TP_WAVELET_NOIS") + ": %1" + "\n" + M("TP_WAVELET_STREN") + ": %2"), int(newTop), int(newBottom))); + } + + } } -void Wavelet::adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) { - if (listener && (multiImage||getEnabled()) ) { - if(a==hueskin) - listener->panelChanged (EvWavHueskin,hueskin->getHistoryString()); - else if(a==hueskin2) - listener->panelChanged (EvWavHueskin2,hueskin2->getHistoryString()); - else if(a==hllev) - listener->panelChanged (EvWavlhl,hllev->getHistoryString()); - else if(a==bllev) - listener->panelChanged (EvWavlbl,bllev->getHistoryString()); - else if(a==pastlev) - listener->panelChanged (EvWavpast,pastlev->getHistoryString()); - else if(a==satlev) - listener->panelChanged (EvWavsat,satlev->getHistoryString()); - else if(a==edgcont) - listener->panelChanged (EvWavedgcont,edgcont->getHistoryString()); - } +void Wavelet::adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) +{ + if (listener && (multiImage || getEnabled()) ) { + if(a == hueskin) { + listener->panelChanged (EvWavHueskin, hueskin->getHistoryString()); + } else if(a == hueskin2) { + listener->panelChanged (EvWavHueskin2, hueskin2->getHistoryString()); + } else if(a == hllev) { + listener->panelChanged (EvWavlhl, hllev->getHistoryString()); + } else if(a == bllev) { + listener->panelChanged (EvWavlbl, bllev->getHistoryString()); + } else if(a == pastlev) { + listener->panelChanged (EvWavpast, pastlev->getHistoryString()); + } else if(a == satlev) { + listener->panelChanged (EvWavsat, satlev->getHistoryString()); + } else if(a == edgcont) { + listener->panelChanged (EvWavedgcont, edgcont->getHistoryString()); + } + } } -void Wavelet::HSmethodUpdateUI() { - if (!batchMode) { - if(HSmethod->get_active_row_number()==0) {//without - hllev->hide(); - bllev->hide(); - threshold->hide(); - threshold2->hide(); - } - else {//with - hllev->show(); - bllev->show(); - threshold->show(); - threshold2->show(); - } - } +void Wavelet::HSmethodUpdateUI() +{ + if (!batchMode) { + if(HSmethod->get_active_row_number() == 0) { //without + hllev->hide(); + bllev->hide(); + threshold->hide(); + threshold2->hide(); + } else { //with + hllev->show(); + bllev->show(); + threshold->show(); + threshold2->show(); + } + } } -void Wavelet::HSmethodChanged() { - HSmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavHSmet, HSmethod->get_active_text ()); - } +void Wavelet::HSmethodChanged() +{ + HSmethodUpdateUI(); + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavHSmet, HSmethod->get_active_text ()); + } } -void Wavelet::CHmethodUpdateUI() { - if (!batchMode) { - if(CHmethod->get_active_row_number()==0) { - CHSLmethod->show(); - pastlev->hide(); - satlev->hide(); - chroma->hide(); - chro->hide(); - labmC->show(); - separatorNeutral->hide(); - neutralchButton->show(); - int y=thres->getValue(); - int z; - for(z=y;z<9;z++) correctionch[z]->hide(); - for(z=0;zshow(); - } else if(CHmethod->get_active_row_number()==1) { - CHSLmethod->show(); - pastlev->show(); - satlev->show(); - chroma->show(); - chro->hide(); - labmC->show(); - separatorNeutral->show(); - neutralchButton->show(); - int y=thres->getValue(); - int z; - for(z=y;z<9;z++) correctionch[z]->hide(); - for(z=0;zshow(); - } else { - chro->show(); - pastlev->hide(); - satlev->hide(); - chroma->hide(); - CHSLmethod->hide(); - labmC->hide(); - separatorNeutral->hide(); - neutralchButton->hide(); - for (int i = 0; i < 9; i++) { - correctionch[i]->hide(); - } - } - } +void Wavelet::CHmethodUpdateUI() +{ + if (!batchMode) { + if(CHmethod->get_active_row_number() == 0) { + CHSLmethod->show(); + pastlev->hide(); + satlev->hide(); + chroma->hide(); + chro->hide(); + labmC->show(); + separatorNeutral->hide(); + neutralchButton->show(); + int y = thres->getValue(); + int z; + + for(z = y; z < 9; z++) { + correctionch[z]->hide(); + } + + for(z = 0; z < y; z++) { + correctionch[z]->show(); + } + } else if(CHmethod->get_active_row_number() == 1) { + CHSLmethod->show(); + pastlev->show(); + satlev->show(); + chroma->show(); + chro->hide(); + labmC->show(); + separatorNeutral->show(); + neutralchButton->show(); + int y = thres->getValue(); + int z; + + for(z = y; z < 9; z++) { + correctionch[z]->hide(); + } + + for(z = 0; z < y; z++) { + correctionch[z]->show(); + } + } else { + chro->show(); + pastlev->hide(); + satlev->hide(); + chroma->hide(); + CHSLmethod->hide(); + labmC->hide(); + separatorNeutral->hide(); + neutralchButton->hide(); + + for (int i = 0; i < 9; i++) { + correctionch[i]->hide(); + } + } + } } -void Wavelet::CHmethodChanged() { - CHmethodUpdateUI(); +void Wavelet::CHmethodChanged() +{ + CHmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavCHmet, CHmethod->get_active_text ()); - } + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavCHmet, CHmethod->get_active_text ()); + } } /* void Wavelet::CHSLmethodChangedUI() { - if (!batchMode) { - if(CHSLmethod->get_active_row_number()==0 && CHmethod->get_active_row_number() != 2) {//SL - //CLVcurveEditorG->hide(); - neutralchButton->show(); - int y=thres->getValue(); - int z; - for(z=y;z<9;z++) correctionch[z]->hide(); - for(z=0;zshow(); - } - else if(CHSLmethod->get_active_row_number()==1) {//CU - //CLVcurveEditorG->show(); - neutralchButton->hide(); - for (int i = 0; i < 9; i++) { - correctionch[i]->hide(); - } - } - } + if (!batchMode) { + if(CHSLmethod->get_active_row_number()==0 && CHmethod->get_active_row_number() != 2) {//SL + //CLVcurveEditorG->hide(); + neutralchButton->show(); + int y=thres->getValue(); + int z; + for(z=y;z<9;z++) correctionch[z]->hide(); + for(z=0;zshow(); + } + else if(CHSLmethod->get_active_row_number()==1) {//CU + //CLVcurveEditorG->show(); + neutralchButton->hide(); + for (int i = 0; i < 9; i++) { + correctionch[i]->hide(); + } + } + } } */ -void Wavelet::CHSLmethodChanged() { -/* - CHSLmethodChangedUI(); - if (listener && (multiImage||enabled->get_active()) ) { - listener->panelChanged (EvWavCHSLmet, CHSLmethod->get_active_text ()); - } -*/ +void Wavelet::CHSLmethodChanged() +{ + /* + CHSLmethodChangedUI(); + if (listener && (multiImage||enabled->get_active()) ) { + listener->panelChanged (EvWavCHSLmet, CHSLmethod->get_active_text ()); + } + */ } -void Wavelet::EDmethodUpdateUI() { - if (!batchMode) { - if(EDmethod->get_active_row_number()==0 ) {//SL - CCWcurveEditorG->hide(); - edgcont->show(); - } - else if(EDmethod->get_active_row_number()==1) {//CU - CCWcurveEditorG->show(); - edgcont->hide(); - } - } +void Wavelet::EDmethodUpdateUI() +{ + if (!batchMode) { + if(EDmethod->get_active_row_number() == 0 ) { //SL + CCWcurveEditorG->hide(); + edgcont->show(); + } else if(EDmethod->get_active_row_number() == 1) { //CU + CCWcurveEditorG->show(); + edgcont->hide(); + } + } } -void Wavelet::EDmethodChanged() { - EDmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) - listener->panelChanged (EvWavEDmet, EDmethod->get_active_text ()); +void Wavelet::EDmethodChanged() +{ + EDmethodUpdateUI(); + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavEDmet, EDmethod->get_active_text ()); + } } -void Wavelet::NPmethodUpdateUI() { - if (!batchMode) { - - } +void Wavelet::NPmethodUpdateUI() +{ + if (!batchMode) { + + } } -void Wavelet::NPmethodChanged() { - NPmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavNPmet, NPmethod->get_active_text ()); - } +void Wavelet::NPmethodChanged() +{ + NPmethodUpdateUI(); + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavNPmet, NPmethod->get_active_text ()); + } } -void Wavelet::BAmethodUpdateUI() { - if (!batchMode) { - if(BAmethod->get_active_row_number()==0 ) {//none - balance->hide(); - opacityCurveEditorW->hide(); - iter->hide(); - - } - else if(BAmethod->get_active_row_number()==1) {//sli - opacityCurveEditorW->hide(); - balance->show(); - iter->show(); - } - else if(BAmethod->get_active_row_number()==2) {//CU - opacityCurveEditorW->show(); - balance->hide(); - iter->show(); - } - } +void Wavelet::BAmethodUpdateUI() +{ + if (!batchMode) { + if(BAmethod->get_active_row_number() == 0 ) { //none + balance->hide(); + opacityCurveEditorW->hide(); + iter->hide(); + + } else if(BAmethod->get_active_row_number() == 1) { //sli + opacityCurveEditorW->hide(); + balance->show(); + iter->show(); + } else if(BAmethod->get_active_row_number() == 2) { //CU + opacityCurveEditorW->show(); + balance->hide(); + iter->show(); + } + } } -void Wavelet::BAmethodChanged() { - BAmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavBAmet, BAmethod->get_active_text ()); - } +void Wavelet::BAmethodChanged() +{ + BAmethodUpdateUI(); + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavBAmet, BAmethod->get_active_text ()); + } } -void Wavelet::TMmethodUpdateUI() { - /* - if (!batchMode) { - if(TMmethod->get_active_row_number()==0 ) {// - tmr->hide(); - } - else { - tmr->show(); - } - } - */ +void Wavelet::TMmethodUpdateUI() +{ + /* + if (!batchMode) { + if(TMmethod->get_active_row_number()==0 ) {// + tmr->hide(); + } + else { + tmr->show(); + } + } + */ } -void Wavelet::TMmethodChanged() { - TMmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavTMmet, TMmethod->get_active_text ()); - } +void Wavelet::TMmethodChanged() +{ + TMmethodUpdateUI(); + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavTMmet, TMmethod->get_active_text ()); + } } /* void Wavelet::BackmethodUpdateUI() { - if (!batchMode) { - } + if (!batchMode) { + } } */ -void Wavelet::BackmethodChanged() { - //BackmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavBackmet, Backmethod->get_active_text ()); - } +void Wavelet::BackmethodChanged() +{ + //BackmethodUpdateUI(); + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavBackmet, Backmethod->get_active_text ()); + } } -void Wavelet::CLmethodUpdateUI() { - if (!batchMode) { - if (CLmethod->get_active_row_number()==0) { - CLmethod->set_active (0); - Lmethod->set_sensitive(true); - Dirmethod->set_sensitive(true); - } - else if (CLmethod->get_active_row_number()==1) { - CLmethod->set_active (1); - Lmethod->set_sensitive(true); - Dirmethod->set_sensitive(true); - } - else if (CLmethod->get_active_row_number()==2) { - CLmethod->set_active (2); - Lmethod->set_sensitive(true); - Dirmethod->set_sensitive(true); - } - else if (CLmethod->get_active_row_number()==3) { - CLmethod->set_active (3); - Lmethod->set_sensitive(false); - Dirmethod->set_sensitive(false); - } - } +void Wavelet::CLmethodUpdateUI() +{ + if (!batchMode) { + if (CLmethod->get_active_row_number() == 0) { + CLmethod->set_active (0); + Lmethod->set_sensitive(true); + Dirmethod->set_sensitive(true); + } else if (CLmethod->get_active_row_number() == 1) { + CLmethod->set_active (1); + Lmethod->set_sensitive(true); + Dirmethod->set_sensitive(true); + } else if (CLmethod->get_active_row_number() == 2) { + CLmethod->set_active (2); + Lmethod->set_sensitive(true); + Dirmethod->set_sensitive(true); + } else if (CLmethod->get_active_row_number() == 3) { + CLmethod->set_active (3); + Lmethod->set_sensitive(false); + Dirmethod->set_sensitive(false); + } + } } -void Wavelet::CLmethodChanged() { - CLmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavCLmet, CLmethod->get_active_text ()); - } +void Wavelet::CLmethodChanged() +{ + CLmethodUpdateUI(); + + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavCLmet, CLmethod->get_active_text ()); + } } /* void Wavelet::TilesmethodUpdateUI() { - if (!batchMode) { - } + if (!batchMode) { + } } */ -void Wavelet::TilesmethodChanged() { - //TilesmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavTilesmet, Tilesmethod->get_active_text ()); - } +void Wavelet::TilesmethodChanged() +{ + //TilesmethodUpdateUI(); + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavTilesmet, Tilesmethod->get_active_text ()); + } } /* void Wavelet::daubcoeffmethodUpdateUI() { - if (!batchMode) { - }} + if (!batchMode) { + }} */ -void Wavelet::daubcoeffmethodChanged() { - //daubcoeffmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavdaubcoeffmet, daubcoeffmethod->get_active_text ()); - } +void Wavelet::daubcoeffmethodChanged() +{ + //daubcoeffmethodUpdateUI(); + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavdaubcoeffmet, daubcoeffmethod->get_active_text ()); + } } /* void Wavelet::MedgreinfUpdateUI() { - if (!batchMode) { - } + if (!batchMode) { + } } */ -void Wavelet::MedgreinfChanged() { - //MedgreinfUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavedgreinf, Medgreinf->get_active_text ()); - } +void Wavelet::MedgreinfChanged() +{ + //MedgreinfUpdateUI(); + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavedgreinf, Medgreinf->get_active_text ()); + } } /* void Wavelet::DirmethodUpdateUI() { - if (!batchMode) { - } + if (!batchMode) { + } } */ -void Wavelet::DirmethodChanged() { - //DirmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavDirmeto, Dirmethod->get_active_text ()); - } +void Wavelet::DirmethodChanged() +{ + //DirmethodUpdateUI(); + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavDirmeto, Dirmethod->get_active_text ()); + } } /* void Wavelet::LmethodUpdateUI() { - if (!batchMode) { - } + if (!batchMode) { + } } */ -void Wavelet::LmethodChanged() { - //LmethodUpdateUI(); - if (listener && (multiImage||getEnabled()) ) { - listener->panelChanged (EvWavLmet, Lmethod->get_active_text ()); - } +void Wavelet::LmethodChanged() +{ + //LmethodUpdateUI(); + if (listener && (multiImage || getEnabled()) ) { + listener->panelChanged (EvWavLmet, Lmethod->get_active_text ()); + } } -void Wavelet::setBatchMode (bool batchMode) { - Lmethod->append_text (M("GENERAL_UNCHANGED")); - CLmethod->append_text (M("GENERAL_UNCHANGED")); - Backmethod->append_text (M("GENERAL_UNCHANGED")); - Tilesmethod->append_text (M("GENERAL_UNCHANGED")); - daubcoeffmethod->append_text (M("GENERAL_UNCHANGED")); - CHmethod->append_text (M("GENERAL_UNCHANGED")); - Medgreinf->append_text (M("GENERAL_UNCHANGED")); - CHSLmethod->append_text (M("GENERAL_UNCHANGED")); - EDmethod->append_text (M("GENERAL_UNCHANGED")); - NPmethod->append_text (M("GENERAL_UNCHANGED")); - BAmethod->append_text (M("GENERAL_UNCHANGED")); - TMmethod->append_text (M("GENERAL_UNCHANGED")); - HSmethod->append_text (M("GENERAL_UNCHANGED")); - Dirmethod->append_text (M("GENERAL_UNCHANGED")); - CCWcurveEditorG->setBatchMode (batchMode); - opaCurveEditorG->setBatchMode (batchMode); - opacityCurveEditorG->setBatchMode (batchMode); - opacityCurveEditorW->setBatchMode (batchMode); - opacityCurveEditorWL->setBatchMode (batchMode); - curveEditorRES->setBatchMode (batchMode); - curveEditorGAM->setBatchMode (batchMode); - rescon->showEditedCB (); - resconH->showEditedCB (); - reschro->showEditedCB (); - tmrs->showEditedCB (); - gamma->showEditedCB (); - sup->showEditedCB (); - sky->showEditedCB (); - thres->showEditedCB (); - threshold->showEditedCB (); - threshold2->showEditedCB (); - edgedetect->showEditedCB (); - edgedetectthr->showEditedCB (); - edgedetectthr2->showEditedCB (); - edgesensi->showEditedCB (); - edgeampli->showEditedCB (); - chroma->showEditedCB (); - chro->showEditedCB (); - contrast->showEditedCB (); - edgrad->showEditedCB (); - edgval->showEditedCB (); - edgthresh->showEditedCB (); - thr->showEditedCB (); - thrH->showEditedCB (); - skinprotect->showEditedCB(); - hueskin->showEditedCB (); - hueskin2->showEditedCB (); - hllev->showEditedCB (); - bllev->showEditedCB (); - pastlev->showEditedCB (); - satlev->showEditedCB (); - edgcont->showEditedCB (); - strength->showEditedCB (); - balance->showEditedCB (); - iter->showEditedCB (); - level0noise->showEditedCB (); - level1noise->showEditedCB (); - level2noise->showEditedCB (); - level3noise->showEditedCB (); +void Wavelet::setBatchMode (bool batchMode) +{ + Lmethod->append_text (M("GENERAL_UNCHANGED")); + CLmethod->append_text (M("GENERAL_UNCHANGED")); + Backmethod->append_text (M("GENERAL_UNCHANGED")); + Tilesmethod->append_text (M("GENERAL_UNCHANGED")); + daubcoeffmethod->append_text (M("GENERAL_UNCHANGED")); + CHmethod->append_text (M("GENERAL_UNCHANGED")); + Medgreinf->append_text (M("GENERAL_UNCHANGED")); + CHSLmethod->append_text (M("GENERAL_UNCHANGED")); + EDmethod->append_text (M("GENERAL_UNCHANGED")); + NPmethod->append_text (M("GENERAL_UNCHANGED")); + BAmethod->append_text (M("GENERAL_UNCHANGED")); + TMmethod->append_text (M("GENERAL_UNCHANGED")); + HSmethod->append_text (M("GENERAL_UNCHANGED")); + Dirmethod->append_text (M("GENERAL_UNCHANGED")); + CCWcurveEditorG->setBatchMode (batchMode); + opaCurveEditorG->setBatchMode (batchMode); + opacityCurveEditorG->setBatchMode (batchMode); + opacityCurveEditorW->setBatchMode (batchMode); + opacityCurveEditorWL->setBatchMode (batchMode); + curveEditorRES->setBatchMode (batchMode); + curveEditorGAM->setBatchMode (batchMode); + rescon->showEditedCB (); + resconH->showEditedCB (); + reschro->showEditedCB (); + tmrs->showEditedCB (); + gamma->showEditedCB (); + sup->showEditedCB (); + sky->showEditedCB (); + thres->showEditedCB (); + threshold->showEditedCB (); + threshold2->showEditedCB (); + edgedetect->showEditedCB (); + edgedetectthr->showEditedCB (); + edgedetectthr2->showEditedCB (); + edgesensi->showEditedCB (); + edgeampli->showEditedCB (); + chroma->showEditedCB (); + chro->showEditedCB (); + contrast->showEditedCB (); + edgrad->showEditedCB (); + edgval->showEditedCB (); + edgthresh->showEditedCB (); + thr->showEditedCB (); + thrH->showEditedCB (); + skinprotect->showEditedCB(); + hueskin->showEditedCB (); + hueskin2->showEditedCB (); + hllev->showEditedCB (); + bllev->showEditedCB (); + pastlev->showEditedCB (); + satlev->showEditedCB (); + edgcont->showEditedCB (); + strength->showEditedCB (); + balance->showEditedCB (); + iter->showEditedCB (); + level0noise->showEditedCB (); + level1noise->showEditedCB (); + level2noise->showEditedCB (); + level3noise->showEditedCB (); - ToolPanel::setBatchMode (batchMode); + ToolPanel::setBatchMode (batchMode); - for (int i = 0; i < 9; i++) { - correction[i]->showEditedCB(); - } - for (int i = 0; i < 9; i++) { - correctionch[i]->showEditedCB(); - } + for (int i = 0; i < 9; i++) { + correction[i]->showEditedCB(); + } + + for (int i = 0; i < 9; i++) { + correctionch[i]->showEditedCB(); + } } -void Wavelet::adjusterUpdateUI (Adjuster* a) { -/* - if (!batchMode) { - if (a == tmrs ) { - float tm; - tm=tmrs->getValue(); - if(tm==0.f) tmr->hide(); - else tmr->show(); - } - else if (a == gamma ) { - float tm; - tm=tmrs->getValue(); - if(tm==0.f) tmr->hide(); - else tmr->show(); - ); - } - } -*/ +void Wavelet::adjusterUpdateUI (Adjuster* a) +{ + /* + if (!batchMode) { + if (a == tmrs ) { + float tm; + tm=tmrs->getValue(); + if(tm==0.f) tmr->hide(); + else tmr->show(); + } + else if (a == gamma ) { + float tm; + tm=tmrs->getValue(); + if(tm==0.f) tmr->hide(); + else tmr->show(); + ); + } + } + */ } -void Wavelet::adjusterChanged (Adjuster* a, double newval) { - if (listener && (multiImage||getEnabled()) ) { - if (a == edgthresh) - listener->panelChanged (EvWavtiles, edgthresh->getTextValue()); - else if (a == rescon ) - listener->panelChanged (EvWavrescon, rescon->getTextValue()); - else if (a == resconH ) - listener->panelChanged (EvWavresconH, resconH->getTextValue()); - else if (a == reschro ) - listener->panelChanged (EvWavreschro, reschro->getTextValue()); - else if (a == tmrs ) { - adjusterUpdateUI(a); - listener->panelChanged (EvWavtmrs, tmrs->getTextValue()); - } - else if (a == gamma ) { - adjusterUpdateUI(a); - listener->panelChanged (EvWavgamma, gamma->getTextValue()); - } - else if (a == sky ) - listener->panelChanged (EvWavsky, sky->getTextValue()); - else if (a == sup ) - listener->panelChanged (EvWavsup, sup->getTextValue()); - else if (a == chroma ) - listener->panelChanged (EvWavchroma, chroma->getTextValue()); - else if (a == chro ) - listener->panelChanged (EvWavchro, chro->getTextValue()); - else if (a == contrast ) - listener->panelChanged (EvWavunif, contrast->getTextValue()); - else if (a == thr ) - listener->panelChanged (EvWavthr, thr->getTextValue()); - else if (a == thrH ) - listener->panelChanged (EvWavthrH, thrH->getTextValue()); - else if (a == threshold ) - listener->panelChanged (EvWavThreshold, threshold->getTextValue()); - else if (a == threshold2 ) - listener->panelChanged (EvWavThreshold2, threshold2->getTextValue()); - else if (a == edgedetect ) - listener->panelChanged (EvWavedgedetect, edgedetect->getTextValue()); - else if (a == edgedetectthr ) - listener->panelChanged (EvWavedgedetectthr, edgedetectthr->getTextValue()); - else if (a == edgedetectthr2 ) - listener->panelChanged (EvWavedgedetectthr2, edgedetectthr2->getTextValue()); - else if (a == edgesensi ) - listener->panelChanged (EvWavedgesensi, edgesensi->getTextValue()); - else if (a == edgeampli ) - listener->panelChanged (EvWavedgeampli, edgeampli->getTextValue()); - else if (a == edgrad ) - listener->panelChanged (EvWavedgrad, edgrad->getTextValue()); - else if (a == edgval ) - listener->panelChanged (EvWavedgval, edgval->getTextValue()); - else if (a == thres ) { - int y=thres->getValue(); - int z; - for(z=y;z<9;z++) correction[z]->hide(); - for(z=0;zshow(); - for(z=y;z<9;z++) correctionch[z]->hide(); - for(z=0;zshow(); - if(z==9) sup->show(); else sup->hide(); +void Wavelet::adjusterChanged (Adjuster* a, double newval) +{ + if (listener && (multiImage || getEnabled()) ) { + if (a == edgthresh) { + listener->panelChanged (EvWavtiles, edgthresh->getTextValue()); + } else if (a == rescon ) { + listener->panelChanged (EvWavrescon, rescon->getTextValue()); + } else if (a == resconH ) { + listener->panelChanged (EvWavresconH, resconH->getTextValue()); + } else if (a == reschro ) { + listener->panelChanged (EvWavreschro, reschro->getTextValue()); + } else if (a == tmrs ) { + adjusterUpdateUI(a); + listener->panelChanged (EvWavtmrs, tmrs->getTextValue()); + } else if (a == gamma ) { + adjusterUpdateUI(a); + listener->panelChanged (EvWavgamma, gamma->getTextValue()); + } else if (a == sky ) { + listener->panelChanged (EvWavsky, sky->getTextValue()); + } else if (a == sup ) { + listener->panelChanged (EvWavsup, sup->getTextValue()); + } else if (a == chroma ) { + listener->panelChanged (EvWavchroma, chroma->getTextValue()); + } else if (a == chro ) { + listener->panelChanged (EvWavchro, chro->getTextValue()); + } else if (a == contrast ) { + listener->panelChanged (EvWavunif, contrast->getTextValue()); + } else if (a == thr ) { + listener->panelChanged (EvWavthr, thr->getTextValue()); + } else if (a == thrH ) { + listener->panelChanged (EvWavthrH, thrH->getTextValue()); + } else if (a == threshold ) { + listener->panelChanged (EvWavThreshold, threshold->getTextValue()); + } else if (a == threshold2 ) { + listener->panelChanged (EvWavThreshold2, threshold2->getTextValue()); + } else if (a == edgedetect ) { + listener->panelChanged (EvWavedgedetect, edgedetect->getTextValue()); + } else if (a == edgedetectthr ) { + listener->panelChanged (EvWavedgedetectthr, edgedetectthr->getTextValue()); + } else if (a == edgedetectthr2 ) { + listener->panelChanged (EvWavedgedetectthr2, edgedetectthr2->getTextValue()); + } else if (a == edgesensi ) { + listener->panelChanged (EvWavedgesensi, edgesensi->getTextValue()); + } else if (a == edgeampli ) { + listener->panelChanged (EvWavedgeampli, edgeampli->getTextValue()); + } else if (a == edgrad ) { + listener->panelChanged (EvWavedgrad, edgrad->getTextValue()); + } else if (a == edgval ) { + listener->panelChanged (EvWavedgval, edgval->getTextValue()); + } else if (a == thres ) { + int y = thres->getValue(); + int z; - listener->panelChanged (EvWavthres, thres->getTextValue()); - } - else if (a == skinprotect) - listener->panelChanged (EvWavSkin, skinprotect->getTextValue()); - else if (a == strength) - listener->panelChanged (EvWavStrength, strength->getTextValue()); - else if (a == balance) - listener->panelChanged (EvWavbalance, balance->getTextValue()); - else if (a == iter) - listener->panelChanged (EvWaviter, iter->getTextValue()); - else if (a == greenhigh ) - listener->panelChanged (EvWavgreenhigh, greenhigh->getTextValue()); - else if (a == bluehigh ) - listener->panelChanged (EvWavbluehigh, bluehigh->getTextValue()); - else if (a == greenmed ) - listener->panelChanged (EvWavgreenmed, greenmed->getTextValue()); - else if (a == bluemed ) - listener->panelChanged (EvWavbluemed, bluemed->getTextValue()); - else if (a == greenlow ) - listener->panelChanged (EvWavgreenlow, greenlow->getTextValue()); - else if (a == bluelow ) - listener->panelChanged (EvWavbluelow, bluelow->getTextValue()); + for(z = y; z < 9; z++) { + correction[z]->hide(); + } - if ((a == correction[0] || a == correction[1] || a == correction[2] || a == correction[3] || a == correction[4] || a == correction[5] || a == correction[6] || a == correction[7] || a == correction[8])) { - listener->panelChanged (EvWavelet, - Glib::ustring::compose("%1, %2, %3, %4, %5, %6, %7, %8, %9", - Glib::ustring::format(std::fixed, std::setprecision(0), correction[0]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[1]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[2]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[3]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[4]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[5]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[6]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[7]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correction[8]->getValue())) - ); - } - else if (a == correctionch[0] || a == correctionch[1] || a == correctionch[2] || a == correctionch[3] || a == correctionch[4] || a == correctionch[5] || a == correctionch[6] || a == correctionch[7] || a == correctionch[8] ) { - listener->panelChanged (EvWaveletch, - Glib::ustring::compose("%1, %2, %3, %4, %5, %6, %7, %8, %9", - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[0]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[1]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[2]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[3]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[4]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[5]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[6]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[7]->getValue()), - Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[8]->getValue())) - ); - } - } + for(z = 0; z < y; z++) { + correction[z]->show(); + } + + for(z = y; z < 9; z++) { + correctionch[z]->hide(); + } + + for(z = 0; z < y; z++) { + correctionch[z]->show(); + } + + if(z == 9) { + sup->show(); + } else { + sup->hide(); + } + + listener->panelChanged (EvWavthres, thres->getTextValue()); + } else if (a == skinprotect) { + listener->panelChanged (EvWavSkin, skinprotect->getTextValue()); + } else if (a == strength) { + listener->panelChanged (EvWavStrength, strength->getTextValue()); + } else if (a == balance) { + listener->panelChanged (EvWavbalance, balance->getTextValue()); + } else if (a == iter) { + listener->panelChanged (EvWaviter, iter->getTextValue()); + } else if (a == greenhigh ) { + listener->panelChanged (EvWavgreenhigh, greenhigh->getTextValue()); + } else if (a == bluehigh ) { + listener->panelChanged (EvWavbluehigh, bluehigh->getTextValue()); + } else if (a == greenmed ) { + listener->panelChanged (EvWavgreenmed, greenmed->getTextValue()); + } else if (a == bluemed ) { + listener->panelChanged (EvWavbluemed, bluemed->getTextValue()); + } else if (a == greenlow ) { + listener->panelChanged (EvWavgreenlow, greenlow->getTextValue()); + } else if (a == bluelow ) { + listener->panelChanged (EvWavbluelow, bluelow->getTextValue()); + } + + if ((a == correction[0] || a == correction[1] || a == correction[2] || a == correction[3] || a == correction[4] || a == correction[5] || a == correction[6] || a == correction[7] || a == correction[8])) { + listener->panelChanged (EvWavelet, + Glib::ustring::compose("%1, %2, %3, %4, %5, %6, %7, %8, %9", + Glib::ustring::format(std::fixed, std::setprecision(0), correction[0]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[1]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[2]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[3]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[4]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[5]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[6]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[7]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correction[8]->getValue())) + ); + } else if (a == correctionch[0] || a == correctionch[1] || a == correctionch[2] || a == correctionch[3] || a == correctionch[4] || a == correctionch[5] || a == correctionch[6] || a == correctionch[7] || a == correctionch[8] ) { + listener->panelChanged (EvWaveletch, + Glib::ustring::compose("%1, %2, %3, %4, %5, %6, %7, %8, %9", + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[0]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[1]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[2]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[3]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[4]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[5]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[6]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[7]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(0), correctionch[8]->getValue())) + ); + } + } } -void Wavelet::enabledUpdateUI () { - if (!batchMode) { - int y=thres->getValue(); - int z; - for(z=y;z<9;z++) correction[z]->hide(); - for(z=0;zshow(); - if(z==9) sup->show(); else sup->hide(); +void Wavelet::enabledUpdateUI () +{ + if (!batchMode) { + int y = thres->getValue(); + int z; -// adjusterUpdateUI(tmrs); - } + for(z = y; z < 9; z++) { + correction[z]->hide(); + } + + for(z = 0; z < y; z++) { + correction[z]->show(); + } + + if(z == 9) { + sup->show(); + } else { + sup->hide(); + } + +// adjusterUpdateUI(tmrs); + } } -void Wavelet::enabledChanged () { - enabledUpdateUI(); - if (listener) { - if (get_inconsistent()) - listener->panelChanged (EvWavEnabled, M("GENERAL_UNCHANGED")); - else if (getEnabled()) - listener->panelChanged (EvWavEnabled, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavEnabled, M("GENERAL_DISABLED")); - } +void Wavelet::enabledChanged () +{ + enabledUpdateUI(); + + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvWavEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvWavEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavEnabled, M("GENERAL_DISABLED")); + } + } } -void Wavelet::medianToggled () { +void Wavelet::medianToggled () +{ - if (multiImage) { - if (median->get_inconsistent()) { - median->set_inconsistent (false); - medianConn.block (true); - median->set_active (false); - medianConn.block (false); - } - else if (lastmedian) - median->set_inconsistent (true); + if (multiImage) { + if (median->get_inconsistent()) { + median->set_inconsistent (false); + medianConn.block (true); + median->set_active (false); + medianConn.block (false); + } else if (lastmedian) { + median->set_inconsistent (true); + } - lastmedian = median->get_active (); - } + lastmedian = median->get_active (); + } - if (listener && (multiImage || getEnabled ())) { - if (median->get_inconsistent()) - listener->panelChanged (EvWavmedian, M("GENERAL_UNCHANGED")); - else if (median->get_active ()) - listener->panelChanged (EvWavmedian, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavmedian, M("GENERAL_DISABLED")); - } + if (listener && (multiImage || getEnabled ())) { + if (median->get_inconsistent()) { + listener->panelChanged (EvWavmedian, M("GENERAL_UNCHANGED")); + } else if (median->get_active ()) { + listener->panelChanged (EvWavmedian, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavmedian, M("GENERAL_DISABLED")); + } + } } -void Wavelet::medianlevUpdateUI () { - if (!batchMode) { - if (medianlev->get_active ()){ - edgedetect->show(); - lipst->show(); - separatoredge->show(); +void Wavelet::medianlevUpdateUI () +{ + if (!batchMode) { + if (medianlev->get_active ()) { + edgedetect->show(); + lipst->show(); + separatoredge->show(); - edgedetectthr->show(); - edgedetectthr2->show(); - // edgesensi->show(); - // edgeampli->show(); - // NPmethod->show(); - // labmNP->show(); - if (lipst->get_active ()) {edgesensi->show();edgeampli->show();NPmethod->show(); labmNP->show();} + edgedetectthr->show(); + edgedetectthr2->show(); - else {edgesensi->hide();edgeampli->hide();NPmethod->hide(); labmNP->hide();} - } - else { - edgedetect->hide(); - lipst->hide(); - edgedetectthr->hide(); - edgedetectthr2->hide(); - edgesensi->hide(); - edgeampli->hide(); - separatoredge->hide(); - NPmethod->hide(); - labmNP->hide(); - - } - } + // edgesensi->show(); + // edgeampli->show(); + // NPmethod->show(); + // labmNP->show(); + if (lipst->get_active ()) { + edgesensi->show(); + edgeampli->show(); + NPmethod->show(); + labmNP->show(); + } + + else { + edgesensi->hide(); + edgeampli->hide(); + NPmethod->hide(); + labmNP->hide(); + } + } else { + edgedetect->hide(); + lipst->hide(); + edgedetectthr->hide(); + edgedetectthr2->hide(); + edgesensi->hide(); + edgeampli->hide(); + separatoredge->hide(); + NPmethod->hide(); + labmNP->hide(); + + } + } } -void Wavelet::medianlevToggled () { +void Wavelet::medianlevToggled () +{ - if (multiImage) { - if (medianlev->get_inconsistent()) { - medianlev->set_inconsistent (false); - medianlevConn.block (true); - medianlev->set_active (false); - medianlevConn.block (false); - } - else if (lastmedianlev) - medianlev->set_inconsistent (true); + if (multiImage) { + if (medianlev->get_inconsistent()) { + medianlev->set_inconsistent (false); + medianlevConn.block (true); + medianlev->set_active (false); + medianlevConn.block (false); + } else if (lastmedianlev) { + medianlev->set_inconsistent (true); + } - lastmedianlev = medianlev->get_active (); - } - medianlevUpdateUI(); + lastmedianlev = medianlev->get_active (); + } - if (listener && (multiImage || getEnabled ())) { - if (medianlev->get_inconsistent()) - listener->panelChanged (EvWavmedianlev, M("GENERAL_UNCHANGED")); - else if (medianlev->get_active () ) - listener->panelChanged (EvWavmedianlev, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavmedianlev, M("GENERAL_DISABLED")); - } + medianlevUpdateUI(); + + if (listener && (multiImage || getEnabled ())) { + if (medianlev->get_inconsistent()) { + listener->panelChanged (EvWavmedianlev, M("GENERAL_UNCHANGED")); + } else if (medianlev->get_active () ) { + listener->panelChanged (EvWavmedianlev, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavmedianlev, M("GENERAL_DISABLED")); + } + } } -void Wavelet::linkedgToggled () { +void Wavelet::linkedgToggled () +{ - if (multiImage) { - if (linkedg->get_inconsistent()) { - linkedg->set_inconsistent (false); - linkedgConn.block (true); - linkedg->set_active (false); - linkedgConn.block (false); - } - else if (lastlinkedg) - linkedg->set_inconsistent (true); + if (multiImage) { + if (linkedg->get_inconsistent()) { + linkedg->set_inconsistent (false); + linkedgConn.block (true); + linkedg->set_active (false); + linkedgConn.block (false); + } else if (lastlinkedg) { + linkedg->set_inconsistent (true); + } - lastlinkedg = linkedg->get_active (); - } + lastlinkedg = linkedg->get_active (); + } - if (listener && (multiImage || getEnabled ())) { - if (linkedg->get_inconsistent()) - listener->panelChanged (EvWavlinkedg, M("GENERAL_UNCHANGED")); - else if (linkedg->get_active () ) - listener->panelChanged (EvWavlinkedg, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavlinkedg, M("GENERAL_DISABLED")); - } + if (listener && (multiImage || getEnabled ())) { + if (linkedg->get_inconsistent()) { + listener->panelChanged (EvWavlinkedg, M("GENERAL_UNCHANGED")); + } else if (linkedg->get_active () ) { + listener->panelChanged (EvWavlinkedg, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavlinkedg, M("GENERAL_DISABLED")); + } + } } -void Wavelet::cbenabUpdateUI () { - if (!batchMode) { - if(cbenab->get_active ()) { - chanMixerHLFrame->show(); - chanMixerMidFrame->show(); - chanMixerShadowsFrame->show(); - neutrHBox->show(); - } - else { - chanMixerHLFrame->hide(); - chanMixerMidFrame->hide(); - chanMixerShadowsFrame->hide(); - neutrHBox->hide(); - } - } +void Wavelet::cbenabUpdateUI () +{ + if (!batchMode) { + if(cbenab->get_active ()) { + chanMixerHLFrame->show(); + chanMixerMidFrame->show(); + chanMixerShadowsFrame->show(); + neutrHBox->show(); + } else { + chanMixerHLFrame->hide(); + chanMixerMidFrame->hide(); + chanMixerShadowsFrame->hide(); + neutrHBox->hide(); + } + } } -void Wavelet::cbenabToggled () { - if (multiImage) { - if (cbenab->get_inconsistent()) { - cbenab->set_inconsistent (false); - cbenabConn.block (true); - cbenab->set_active (false); - cbenabConn.block (false); - } - else if (lastcbenab) - cbenab->set_inconsistent (true); +void Wavelet::cbenabToggled () +{ + if (multiImage) { + if (cbenab->get_inconsistent()) { + cbenab->set_inconsistent (false); + cbenabConn.block (true); + cbenab->set_active (false); + cbenabConn.block (false); + } else if (lastcbenab) { + cbenab->set_inconsistent (true); + } - lastcbenab = cbenab->get_active (); - } - cbenabUpdateUI(); + lastcbenab = cbenab->get_active (); + } - if (listener && (multiImage || getEnabled ())) { - if (cbenab->get_inconsistent() ) - listener->panelChanged (EvWavcbenab, M("GENERAL_UNCHANGED")); - else if (cbenab->get_active () ) - listener->panelChanged (EvWavcbenab, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavcbenab, M("GENERAL_DISABLED")); - } + cbenabUpdateUI(); + + if (listener && (multiImage || getEnabled ())) { + if (cbenab->get_inconsistent() ) { + listener->panelChanged (EvWavcbenab, M("GENERAL_UNCHANGED")); + } else if (cbenab->get_active () ) { + listener->panelChanged (EvWavcbenab, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavcbenab, M("GENERAL_DISABLED")); + } + } } -void Wavelet::lipstUpdateUI () { - if (!batchMode) { - if (lipst->get_active ()) { - NPmethod->show(); - edgesensi->show(); - edgeampli->show(); - labmNP->show(); - } - else { - NPmethod->hide(); - edgesensi->hide(); - edgeampli->hide(); - labmNP->hide(); - - } - } +void Wavelet::lipstUpdateUI () +{ + if (!batchMode) { + if (lipst->get_active ()) { + NPmethod->show(); + edgesensi->show(); + edgeampli->show(); + labmNP->show(); + } else { + NPmethod->hide(); + edgesensi->hide(); + edgeampli->hide(); + labmNP->hide(); + + } + } } -void Wavelet::lipstToggled () { +void Wavelet::lipstToggled () +{ - if (multiImage) { - if (lipst->get_inconsistent()) { - lipst->set_inconsistent (false); - lipstConn.block (true); - lipst->set_active (false); - lipstConn.block (false); - } - else if (lastlipst) - lipst->set_inconsistent (true); + if (multiImage) { + if (lipst->get_inconsistent()) { + lipst->set_inconsistent (false); + lipstConn.block (true); + lipst->set_active (false); + lipstConn.block (false); + } else if (lastlipst) { + lipst->set_inconsistent (true); + } - lastlipst = lipst->get_active (); - } - lipstUpdateUI(); + lastlipst = lipst->get_active (); + } - if (listener && (multiImage || getEnabled ())) { - if (lipst->get_inconsistent()) - listener->panelChanged (EvWavlipst, M("GENERAL_UNCHANGED")); - else if (lipst->get_active ()) - listener->panelChanged (EvWavlipst, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavlipst, M("GENERAL_DISABLED")); - } + lipstUpdateUI(); + + if (listener && (multiImage || getEnabled ())) { + if (lipst->get_inconsistent()) { + listener->panelChanged (EvWavlipst, M("GENERAL_UNCHANGED")); + } else if (lipst->get_active ()) { + listener->panelChanged (EvWavlipst, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavlipst, M("GENERAL_DISABLED")); + } + } } /* void Wavelet::edgreinfToggled () { - if (batchMode) { - if (edgreinf->get_inconsistent()) { - edgreinf->set_inconsistent (false); - edgreinfConn.block (true); - edgreinf->set_active (false); - edgreinfConn.block (false); - } - else if (lastedgreinf) - edgreinf->set_inconsistent (true); + if (batchMode) { + if (edgreinf->get_inconsistent()) { + edgreinf->set_inconsistent (false); + edgreinfConn.block (true); + edgreinf->set_active (false); + edgreinfConn.block (false); + } + else if (lastedgreinf) + edgreinf->set_inconsistent (true); - lastedgreinf = edgreinf->get_active (); - } + lastedgreinf = edgreinf->get_active (); + } - if (listener) { - if (enabled->get_inconsistent ()) - listener->panelChanged (EvWavedgreinf, M("GENERAL_UNCHANGED")); - else if (enabled->get_active ()) - listener->panelChanged (EvWavedgreinf, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavedgreinf, M("GENERAL_DISABLED")); - } + if (listener) { + if (enabled->get_inconsistent ()) + listener->panelChanged (EvWavedgreinf, M("GENERAL_UNCHANGED")); + else if (enabled->get_active ()) + listener->panelChanged (EvWavedgreinf, M("GENERAL_ENABLED")); + else + listener->panelChanged (EvWavedgreinf, M("GENERAL_DISABLED")); + } } */ -void Wavelet::avoidToggled () { +void Wavelet::avoidToggled () +{ - if (multiImage) { - if (avoid->get_inconsistent()) { - avoid->set_inconsistent (false); - avoidConn.block (true); - avoid->set_active (false); - avoidConn.block (false); - } - else if (lastavoid) - avoid->set_inconsistent (true); + if (multiImage) { + if (avoid->get_inconsistent()) { + avoid->set_inconsistent (false); + avoidConn.block (true); + avoid->set_active (false); + avoidConn.block (false); + } else if (lastavoid) { + avoid->set_inconsistent (true); + } - lastavoid = avoid->get_active (); - } - if (listener && (multiImage || getEnabled ())) { - if (avoid->get_inconsistent()) - listener->panelChanged (EvWavavoid, M("GENERAL_UNCHANGED")); - else if (avoid->get_active ()) - listener->panelChanged (EvWavavoid, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavavoid, M("GENERAL_DISABLED")); - } + lastavoid = avoid->get_active (); + } + + if (listener && (multiImage || getEnabled ())) { + if (avoid->get_inconsistent()) { + listener->panelChanged (EvWavavoid, M("GENERAL_UNCHANGED")); + } else if (avoid->get_active ()) { + listener->panelChanged (EvWavavoid, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavavoid, M("GENERAL_DISABLED")); + } + } } -void Wavelet::tmrToggled () { +void Wavelet::tmrToggled () +{ - if (multiImage) { - if (tmr->get_inconsistent()) { - tmr->set_inconsistent (false); - tmrConn.block (true); - tmr->set_active (false); - tmrConn.block (false); - } - else if (lasttmr) - tmr->set_inconsistent (true); + if (multiImage) { + if (tmr->get_inconsistent()) { + tmr->set_inconsistent (false); + tmrConn.block (true); + tmr->set_active (false); + tmrConn.block (false); + } else if (lasttmr) { + tmr->set_inconsistent (true); + } - lasttmr = tmr->get_active (); - } + lasttmr = tmr->get_active (); + } - if (listener && (multiImage || getEnabled ())) { - if (tmr->get_inconsistent()) - listener->panelChanged (EvWavtmr, M("GENERAL_UNCHANGED")); - else if (tmr->get_active ()) - listener->panelChanged (EvWavtmr, M("GENERAL_ENABLED")); - else - listener->panelChanged (EvWavtmr, M("GENERAL_DISABLED")); - } + if (listener && (multiImage || getEnabled ())) { + if (tmr->get_inconsistent()) { + listener->panelChanged (EvWavtmr, M("GENERAL_UNCHANGED")); + } else if (tmr->get_active ()) { + listener->panelChanged (EvWavtmr, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvWavtmr, M("GENERAL_DISABLED")); + } + } } -void Wavelet::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { +void Wavelet::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) +{ - float R, G, B; + float R, G, B; - if (elemType==ColorCaller::CCET_VERTICAL_BAR) - valY = 0.5; + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } - if (callerId == 1) { // ch - main curve + if (callerId == 1) { // ch - main curve - Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); - } -/* else if (callerId == 2) { // cc - bottom bar + Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); + } + /* else if (callerId == 2) { // cc - bottom bar - // float value = (1.f - 0.7f) * float(valX) + 0.7f; - float value = (1.f - 0.7f) * float(valX) + 0.7f; - // whole hue range - // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) - Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); - } - */ - else if (callerId == 4) { // LH - bottom bar - Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); - } - else if (callerId == 5) { // HH - bottom bar - float h = float((valY - 0.5) * 0.3 + valX); - if (h > 1.0f) - h -= 1.0f; - else if (h < 0.0f) - h += 1.0f; - Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); - } - caller->ccRed = double(R); - caller->ccGreen = double(G); - caller->ccBlue = double(B); + // float value = (1.f - 0.7f) * float(valX) + 0.7f; + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } + */ + else if (callerId == 4) { // LH - bottom bar + Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); + } else if (callerId == 5) { // HH - bottom bar + float h = float((valY - 0.5) * 0.3 + valX); + + if (h > 1.0f) { + h -= 1.0f; + } else if (h < 0.0f) { + h += 1.0f; + } + + Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); + } + + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); } -void Wavelet::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd,bool chromaadd, bool contrastadd, bool skinadd, bool reschroadd, bool tmrsadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd, bool edgradadd, bool edgvaladd, bool strengthadd, bool gammaadd, bool edgedetectadd, bool edgedetectthradd ,bool edgedetectthr2add) { +void Wavelet::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd, bool chromaadd, bool contrastadd, bool skinadd, bool reschroadd, bool tmrsadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd, bool edgradadd, bool edgvaladd, bool strengthadd, bool gammaadd, bool edgedetectadd, bool edgedetectthradd , bool edgedetectthr2add) +{ - for (int i=0; i<9; i++) - correction[i]->setAddMode(multiplieradd); - threshold->setAddMode(thresholdadd); - skinprotect->setAddMode(skinadd); - threshold2->setAddMode(threshold2add); - thres->setAddMode(thresadd); - chro->setAddMode(chroadd); - chroma->setAddMode(chromaadd); - contrast->setAddMode(contrastadd); - rescon->setAddMode(resconadd); - resconH->setAddMode(resconHadd); - reschro->setAddMode(reschroadd); - tmrs->setAddMode(tmrsadd); - thr->setAddMode(thradd); - thrH->setAddMode(thrHadd); - sky->setAddMode(skyadd); - edgrad->setAddMode(edgradadd); - edgval->setAddMode(edgvaladd); - strength->setAddMode(strengthadd); - gamma->setAddMode(gammaadd); - edgedetect->setAddMode(edgedetectadd); - edgedetectthr->setAddMode(edgedetectthradd); - edgedetectthr2->setAddMode(edgedetectthr2add); + for (int i = 0; i < 9; i++) { + correction[i]->setAddMode(multiplieradd); + } + + threshold->setAddMode(thresholdadd); + skinprotect->setAddMode(skinadd); + threshold2->setAddMode(threshold2add); + thres->setAddMode(thresadd); + chro->setAddMode(chroadd); + chroma->setAddMode(chromaadd); + contrast->setAddMode(contrastadd); + rescon->setAddMode(resconadd); + resconH->setAddMode(resconHadd); + reschro->setAddMode(reschroadd); + tmrs->setAddMode(tmrsadd); + thr->setAddMode(thradd); + thrH->setAddMode(thrHadd); + sky->setAddMode(skyadd); + edgrad->setAddMode(edgradadd); + edgval->setAddMode(edgvaladd); + strength->setAddMode(strengthadd); + gamma->setAddMode(gammaadd); + edgedetect->setAddMode(edgedetectadd); + edgedetectthr->setAddMode(edgedetectthradd); + edgedetectthr2->setAddMode(edgedetectthr2add); } -void Wavelet::neutralPressed () { - for (int i = 0; i < 9; i++) { - correction[i]->setValue(0); - adjusterChanged(correction[i], 0); - } +void Wavelet::neutralPressed () +{ + for (int i = 0; i < 9; i++) { + correction[i]->setValue(0); + adjusterChanged(correction[i], 0); + } } -void Wavelet::neutralchPressed () { +void Wavelet::neutralchPressed () +{ - for (int i = 0; i < 9; i++) { - correctionch[i]->setValue(0); - adjusterChanged(correctionch[i], 0); - } + for (int i = 0; i < 9; i++) { + correctionch[i]->setValue(0); + adjusterChanged(correctionch[i], 0); + } } -void Wavelet::contrastPlusPressed () { +void Wavelet::contrastPlusPressed () +{ - for (int i = 0; i < 9; i++) { - int inc = 1 * (9 - i); - correction[i]->setValue(correction[i]->getValue() + inc); - adjusterChanged(correction[i], correction[i]->getValue()); - } + for (int i = 0; i < 9; i++) { + int inc = 1 * (9 - i); + correction[i]->setValue(correction[i]->getValue() + inc); + adjusterChanged(correction[i], correction[i]->getValue()); + } } -void Wavelet::contrastMinusPressed () { +void Wavelet::contrastMinusPressed () +{ - for (int i = 0; i < 9; i++) { - int inc = -1 * (9 - i); - correction[i]->setValue(correction[i]->getValue() + inc); - adjusterChanged(correction[i], correction[i]->getValue()); - } + for (int i = 0; i < 9; i++) { + int inc = -1 * (9 - i); + correction[i]->setValue(correction[i]->getValue() + inc); + adjusterChanged(correction[i], correction[i]->getValue()); + } } -void Wavelet::foldAllButMe (GdkEventButton* event, MyExpander *expander) { - if (event->button == 3) { - expsettings->set_expanded(expsettings == expander); - expcontrast->set_expanded(expcontrast == expander); - expchroma->set_expanded(expchroma == expander); - exptoning->set_expanded(exptoning == expander); - expnoise->set_expanded(expnoise == expander); - expedge->set_expanded(expedge == expander); - expgamut->set_expanded(expgamut == expander); - expresid->set_expanded(expresid == expander); - expfinal->set_expanded(expfinal == expander); - } +void Wavelet::foldAllButMe (GdkEventButton* event, MyExpander *expander) +{ + if (event->button == 3) { + expsettings->set_expanded(expsettings == expander); + expcontrast->set_expanded(expcontrast == expander); + expchroma->set_expanded(expchroma == expander); + exptoning->set_expanded(exptoning == expander); + expnoise->set_expanded(expnoise == expander); + expedge->set_expanded(expedge == expander); + expgamut->set_expanded(expgamut == expander); + expresid->set_expanded(expresid == expander); + expfinal->set_expanded(expfinal == expander); + } } -void Wavelet::enableToggled(MyExpander *expander) { - if (listener) { - rtengine::ProcEvent event = NUMOFEVENTS; +void Wavelet::enableToggled(MyExpander *expander) +{ + if (listener) { + rtengine::ProcEvent event = NUMOFEVENTS; - if (expander == expcontrast) - event = EvWavenacont; - else if (expander == expchroma) - event = EvWavenachrom; - else if (expander == exptoning) - event = EvWavenatoning; - else if (expander == expnoise) - event = EvWavenanoise; - else if (expander == expedge) - event = EvWavenaedge; - else if (expander == expresid) - event = EvWavenares; - else if (expander == expfinal) - event = EvWavenafin; - else - // unknown expander, returning ! - return; + if (expander == expcontrast) { + event = EvWavenacont; + } else if (expander == expchroma) { + event = EvWavenachrom; + } else if (expander == exptoning) { + event = EvWavenatoning; + } else if (expander == expnoise) { + event = EvWavenanoise; + } else if (expander == expedge) { + event = EvWavenaedge; + } else if (expander == expresid) { + event = EvWavenares; + } else if (expander == expfinal) { + event = EvWavenafin; + } else + // unknown expander, returning ! + { + return; + } - if (expander->get_inconsistent()) - listener->panelChanged (event, M("GENERAL_UNCHANGED")); - else if (expander->getEnabled()) - listener->panelChanged (event, M("GENERAL_ENABLED")); - else - listener->panelChanged (event, M("GENERAL_DISABLED")); - } + if (expander->get_inconsistent()) { + listener->panelChanged (event, M("GENERAL_UNCHANGED")); + } else if (expander->getEnabled()) { + listener->panelChanged (event, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (event, M("GENERAL_DISABLED")); + } + } } -void Wavelet::writeOptions(std::vector &tpOpen) { - tpOpen.push_back (expsettings->get_expanded ()); - tpOpen.push_back (expcontrast->get_expanded ()); - tpOpen.push_back (expchroma->get_expanded ()); - tpOpen.push_back (exptoning->get_expanded ()); - tpOpen.push_back (expnoise->get_expanded ()); - tpOpen.push_back (expedge->get_expanded ()); - tpOpen.push_back (expgamut->get_expanded ()); - tpOpen.push_back (expresid->get_expanded ()); - tpOpen.push_back (expfinal->get_expanded ()); +void Wavelet::writeOptions(std::vector &tpOpen) +{ + tpOpen.push_back (expsettings->get_expanded ()); + tpOpen.push_back (expcontrast->get_expanded ()); + tpOpen.push_back (expchroma->get_expanded ()); + tpOpen.push_back (exptoning->get_expanded ()); + tpOpen.push_back (expnoise->get_expanded ()); + tpOpen.push_back (expedge->get_expanded ()); + tpOpen.push_back (expgamut->get_expanded ()); + tpOpen.push_back (expresid->get_expanded ()); + tpOpen.push_back (expfinal->get_expanded ()); } -void Wavelet::updateToolState(std::vector &tpOpen) { - if(tpOpen.size() == 9) { - expsettings->set_expanded(tpOpen.at(0)); - expcontrast->set_expanded(tpOpen.at(1)); - expchroma->set_expanded(tpOpen.at(2)); - exptoning->set_expanded(tpOpen.at(3)); - expnoise->set_expanded(tpOpen.at(4)); - expedge->set_expanded(tpOpen.at(5)); - expgamut->set_expanded(tpOpen.at(6)); - expresid->set_expanded(tpOpen.at(7)); - expfinal->set_expanded(tpOpen.at(8)); - } +void Wavelet::updateToolState(std::vector &tpOpen) +{ + if(tpOpen.size() == 9) { + expsettings->set_expanded(tpOpen.at(0)); + expcontrast->set_expanded(tpOpen.at(1)); + expchroma->set_expanded(tpOpen.at(2)); + exptoning->set_expanded(tpOpen.at(3)); + expnoise->set_expanded(tpOpen.at(4)); + expedge->set_expanded(tpOpen.at(5)); + expgamut->set_expanded(tpOpen.at(6)); + expresid->set_expanded(tpOpen.at(7)); + expfinal->set_expanded(tpOpen.at(8)); + } } diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index eee427d18..b0bc967ab 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -5,7 +5,7 @@ * 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 @@ -16,7 +16,7 @@ * * 2014 Jacques Desmis */ - + #ifndef WAVELET_H_INCLUDED #define WAVELET_H_INCLUDED @@ -33,281 +33,281 @@ class Wavelet : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public CurveListener, public ColorProvider, public rtengine::WaveletListener, public FoldableToolPanel { protected: - Glib::RefPtr bgTTips; - Glib::RefPtr srTTips; - Glib::RefPtr bgPixbuf; - Glib::RefPtr srPixbuf; - CurveEditorGroup* curveEditorG; + Glib::RefPtr bgTTips; + Glib::RefPtr srTTips; + Glib::RefPtr bgPixbuf; + Glib::RefPtr srPixbuf; + CurveEditorGroup* curveEditorG; - CurveEditorGroup* CCWcurveEditorG; - CurveEditorGroup* curveEditorRES; - CurveEditorGroup* curveEditorGAM; - Gtk::HSeparator* colorSep; - Gtk::HSeparator* separator3; - Gtk::HSeparator* separatorCB; - Gtk::HSeparator* separatorNeutral; - Gtk::HSeparator* separatoredge; + CurveEditorGroup* CCWcurveEditorG; + CurveEditorGroup* curveEditorRES; + CurveEditorGroup* curveEditorGAM; + Gtk::HSeparator* colorSep; + Gtk::HSeparator* separator3; + Gtk::HSeparator* separatorCB; + Gtk::HSeparator* separatorNeutral; + Gtk::HSeparator* separatoredge; - CurveEditorGroup* opaCurveEditorG; - FlatCurveEditor* opacityShapeRG; - CurveEditorGroup* opacityCurveEditorG; - FlatCurveEditor* opacityShapeBY; - CurveEditorGroup* opacityCurveEditorW; - CurveEditorGroup* opacityCurveEditorWL; - FlatCurveEditor* opacityShape; - FlatCurveEditor* opacityShapeWL; - FlatCurveEditor* hhshape; - FlatCurveEditor* Chshape; - DiagonalCurveEditor* clshape; - Gtk::VBox* chanMixerBox; + CurveEditorGroup* opaCurveEditorG; + FlatCurveEditor* opacityShapeRG; + CurveEditorGroup* opacityCurveEditorG; + FlatCurveEditor* opacityShapeBY; + CurveEditorGroup* opacityCurveEditorW; + CurveEditorGroup* opacityCurveEditorWL; + FlatCurveEditor* opacityShape; + FlatCurveEditor* opacityShapeWL; + FlatCurveEditor* hhshape; + FlatCurveEditor* Chshape; + DiagonalCurveEditor* clshape; + Gtk::VBox* chanMixerBox; - FlatCurveEditor* ccshape; - Gtk::CheckButton * display; - Gtk::CheckButton * displaylevel; - Gtk::CheckButton * displaychro; - Gtk::CheckButton * displaygam; - Gtk::CheckButton * displayres; - Gtk::CheckButton * median; - Gtk::CheckButton * medianlev; - Gtk::CheckButton * linkedg; - Gtk::CheckButton * cbenab; - Gtk::CheckButton * lipst; - Gtk::CheckButton * avoid; - Gtk::CheckButton * tmr; + FlatCurveEditor* ccshape; + Gtk::CheckButton * display; + Gtk::CheckButton * displaylevel; + Gtk::CheckButton * displaychro; + Gtk::CheckButton * displaygam; + Gtk::CheckButton * displayres; + Gtk::CheckButton * median; + Gtk::CheckButton * medianlev; + Gtk::CheckButton * linkedg; + Gtk::CheckButton * cbenab; + Gtk::CheckButton * lipst; + Gtk::CheckButton * avoid; + Gtk::CheckButton * tmr; - Gtk::Button * neutralchButton; - Adjuster* correction[9]; - Adjuster* correctionch[9]; - Adjuster* rescon; - Adjuster* resconH; - Adjuster* reschro; - Adjuster* tmrs; - Adjuster* gamma; - Adjuster* sup; - Adjuster* sky; - Adjuster* thres; - Adjuster* chroma; - Adjuster* chro; - Adjuster* contrast; - Adjuster* thr; - Adjuster* thrH; - Adjuster* skinprotect; - Adjuster* edgrad; - Adjuster* edgval; - Adjuster* edgthresh; - Adjuster* strength; - Adjuster* balance; - Adjuster* iter; - Adjuster* greenlow; - Adjuster* bluelow; - Adjuster* greenmed; - Adjuster* bluemed; - Adjuster* greenhigh; - Adjuster* bluehigh; - - ThresholdAdjuster* hueskin; - ThresholdAdjuster* hueskin2; - ThresholdAdjuster* hllev; - ThresholdAdjuster* bllev; - ThresholdAdjuster* pastlev; - ThresholdAdjuster* satlev; - ThresholdAdjuster* edgcont; - ThresholdAdjuster* level0noise; - ThresholdAdjuster* level1noise; - ThresholdAdjuster* level2noise; - ThresholdAdjuster* level3noise; - - Adjuster* threshold; - Adjuster* threshold2; - Adjuster* edgedetect; - Adjuster* edgedetectthr; - Adjuster* edgedetectthr2; - Adjuster* edgesensi; - Adjuster* edgeampli; - MyComboBoxText* Lmethod; - sigc::connection Lmethodconn; - MyComboBoxText* CHmethod; - sigc::connection CHmethodconn; - MyComboBoxText* CHSLmethod; - sigc::connection CHSLmethodconn; - MyComboBoxText* EDmethod; - sigc::connection EDmethodconn; - MyComboBoxText* BAmethod; - sigc::connection BAmethodconn; - MyComboBoxText* NPmethod; - sigc::connection NPmethodconn; - MyComboBoxText* TMmethod; - sigc::connection TMmethodconn; - MyComboBoxText* HSmethod; - sigc::connection HSmethodconn; - MyComboBoxText* CLmethod; - sigc::connection CLmethodconn; - MyComboBoxText* Backmethod; - sigc::connection Backmethodconn; - MyComboBoxText* Tilesmethod; - sigc::connection Tilesmethodconn; - MyComboBoxText* daubcoeffmethod; - sigc::connection daubcoeffmethodconn; - MyComboBoxText* Dirmethod; - sigc::connection Dirmethodconn; - MyComboBoxText* Medgreinf; - sigc::connection MedgreinfConn; - Gtk::Frame* settingsFrame; - Gtk::Frame* toningFrame; - Gtk::Frame* residualFrame; - Gtk::Frame* dispFrame; - Gtk::Frame* levelFrame; - Gtk::Frame* chromaFrame; - Gtk::Frame* controlFrame; - Gtk::Frame* edgeFrame; - Gtk::Frame* noiseFrame; - Gtk::Frame* contrastSHFrame; - Gtk::Frame* finalFrame; - Gtk::Frame *chanMixerHLFrame; - Gtk::Frame *chanMixerMidFrame; - Gtk::Frame *chanMixerShadowsFrame; - Gtk::Frame *dFrame; + Gtk::Button * neutralchButton; + Adjuster* correction[9]; + Adjuster* correctionch[9]; + Adjuster* rescon; + Adjuster* resconH; + Adjuster* reschro; + Adjuster* tmrs; + Adjuster* gamma; + Adjuster* sup; + Adjuster* sky; + Adjuster* thres; + Adjuster* chroma; + Adjuster* chro; + Adjuster* contrast; + Adjuster* thr; + Adjuster* thrH; + Adjuster* skinprotect; + Adjuster* edgrad; + Adjuster* edgval; + Adjuster* edgthresh; + Adjuster* strength; + Adjuster* balance; + Adjuster* iter; + Adjuster* greenlow; + Adjuster* bluelow; + Adjuster* greenmed; + Adjuster* bluemed; + Adjuster* greenhigh; + Adjuster* bluehigh; - Gtk::Label* colLabel; - Gtk::Label* interLabel; - Gtk::Label* wavLabels; - Gtk::Label* hsmethodLabel; - Gtk::Label* daubcoeffLabel; - Gtk::Label* ColorBalanceLabel; - Gtk::Label* labmC; - Gtk::Label* labmch; - Gtk::Label* labmED; - Gtk::Label* labmTM; - Gtk::Label* labmBA; - Gtk::Label* labmNP; - Gtk::Label* labmedgr; - Gtk::Label* labmednois; - MyExpander* expchroma; - MyExpander* expcontrast; - MyExpander* expedge; - MyExpander* expfinal; - MyExpander* expgamut; - MyExpander* expnoise; - MyExpander* expresid; - MyExpander* expsettings; - MyExpander* exptoning; - Gtk::HBox* ctboxCB; - Gtk::HBox* ctboxCH; - Gtk::HBox* ctboxED; - Gtk::HBox* ctboxTM; - Gtk::HBox* hbresid; - Gtk::HBox* backgroundHBox; - Gtk::HBox* daubcoeffHBox; - Gtk::HBox* hsmethodHBox; - Gtk::HBox* levdirMainHBox; - Gtk::HBox* levdirSubHBox; - Gtk::HBox* tilesizeHBox; - - Gtk::HBox* ctboxFI; - Gtk::HBox* ctboxNP; - Gtk::HBox* ctboxch; - Gtk::HBox* edbox; - Gtk::HBox* ednoisbox; - Gtk::HBox* eddebox; - Gtk::VBox* settingsVBox; - Gtk::VBox* contrastSHVBox; - Gtk::Label* tilesizeLabel; - Gtk::Label* levdirMainLabel; - Gtk::Label* backgroundLabel; - Gtk::Button* neutral; - Gtk::HBox* neutrHBox; + ThresholdAdjuster* hueskin; + ThresholdAdjuster* hueskin2; + ThresholdAdjuster* hllev; + ThresholdAdjuster* bllev; + ThresholdAdjuster* pastlev; + ThresholdAdjuster* satlev; + ThresholdAdjuster* edgcont; + ThresholdAdjuster* level0noise; + ThresholdAdjuster* level1noise; + ThresholdAdjuster* level2noise; + ThresholdAdjuster* level3noise; - sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enableFinalConn; - sigc::connection enableNoiseConn, enableResidConn, enableToningConn; - sigc::connection expConn, medianConn, avoidConn, tmrConn, medianlevConn, linkedgConn, lipstConn, cbenabConn, neutralconn; - sigc::connection neutralPressedConn; - sigc::connection contrastPlusPressedConn; - sigc::connection contrastMinusPressedConn; - sigc::connection neutralchPressedConn; + Adjuster* threshold; + Adjuster* threshold2; + Adjuster* edgedetect; + Adjuster* edgedetectthr; + Adjuster* edgedetectthr2; + Adjuster* edgesensi; + Adjuster* edgeampli; + MyComboBoxText* Lmethod; + sigc::connection Lmethodconn; + MyComboBoxText* CHmethod; + sigc::connection CHmethodconn; + MyComboBoxText* CHSLmethod; + sigc::connection CHSLmethodconn; + MyComboBoxText* EDmethod; + sigc::connection EDmethodconn; + MyComboBoxText* BAmethod; + sigc::connection BAmethodconn; + MyComboBoxText* NPmethod; + sigc::connection NPmethodconn; + MyComboBoxText* TMmethod; + sigc::connection TMmethodconn; + MyComboBoxText* HSmethod; + sigc::connection HSmethodconn; + MyComboBoxText* CLmethod; + sigc::connection CLmethodconn; + MyComboBoxText* Backmethod; + sigc::connection Backmethodconn; + MyComboBoxText* Tilesmethod; + sigc::connection Tilesmethodconn; + MyComboBoxText* daubcoeffmethod; + sigc::connection daubcoeffmethodconn; + MyComboBoxText* Dirmethod; + sigc::connection Dirmethodconn; + MyComboBoxText* Medgreinf; + sigc::connection MedgreinfConn; + Gtk::Frame* settingsFrame; + Gtk::Frame* toningFrame; + Gtk::Frame* residualFrame; + Gtk::Frame* dispFrame; + Gtk::Frame* levelFrame; + Gtk::Frame* chromaFrame; + Gtk::Frame* controlFrame; + Gtk::Frame* edgeFrame; + Gtk::Frame* noiseFrame; + Gtk::Frame* contrastSHFrame; + Gtk::Frame* finalFrame; + Gtk::Frame *chanMixerHLFrame; + Gtk::Frame *chanMixerMidFrame; + Gtk::Frame *chanMixerShadowsFrame; + Gtk::Frame *dFrame; - bool lastdisplay, lastdisplaygam,lastdisplayres,lastdisplaychro, lastdisplaylevel,lastmedian, lastmedianlev, lastlinkedg, lastavoid, lastlipst, lasttmr, lastcbenab; - int nextnlevel; - double tr; - double br; - double tl; - double bl; + Gtk::Label* colLabel; + Gtk::Label* interLabel; + Gtk::Label* wavLabels; + Gtk::Label* hsmethodLabel; + Gtk::Label* daubcoeffLabel; + Gtk::Label* ColorBalanceLabel; + Gtk::Label* labmC; + Gtk::Label* labmch; + Gtk::Label* labmED; + Gtk::Label* labmTM; + Gtk::Label* labmBA; + Gtk::Label* labmNP; + Gtk::Label* labmedgr; + Gtk::Label* labmednois; + MyExpander* expchroma; + MyExpander* expcontrast; + MyExpander* expedge; + MyExpander* expfinal; + MyExpander* expgamut; + MyExpander* expnoise; + MyExpander* expresid; + MyExpander* expsettings; + MyExpander* exptoning; + Gtk::HBox* ctboxCB; + Gtk::HBox* ctboxCH; + Gtk::HBox* ctboxED; + Gtk::HBox* ctboxTM; + Gtk::HBox* hbresid; + Gtk::HBox* backgroundHBox; + Gtk::HBox* daubcoeffHBox; + Gtk::HBox* hsmethodHBox; + Gtk::HBox* levdirMainHBox; + Gtk::HBox* levdirSubHBox; + Gtk::HBox* tilesizeHBox; + + Gtk::HBox* ctboxFI; + Gtk::HBox* ctboxNP; + Gtk::HBox* ctboxch; + Gtk::HBox* edbox; + Gtk::HBox* ednoisbox; + Gtk::HBox* eddebox; + Gtk::VBox* settingsVBox; + Gtk::VBox* contrastSHVBox; + Gtk::Label* tilesizeLabel; + Gtk::Label* levdirMainLabel; + Gtk::Label* backgroundLabel; + Gtk::Button* neutral; + Gtk::HBox* neutrHBox; + + sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enableFinalConn; + sigc::connection enableNoiseConn, enableResidConn, enableToningConn; + sigc::connection expConn, medianConn, avoidConn, tmrConn, medianlevConn, linkedgConn, lipstConn, cbenabConn, neutralconn; + sigc::connection neutralPressedConn; + sigc::connection contrastPlusPressedConn; + sigc::connection contrastMinusPressedConn; + sigc::connection neutralchPressedConn; + + bool lastdisplay, lastdisplaygam, lastdisplayres, lastdisplaychro, lastdisplaylevel, lastmedian, lastmedianlev, lastlinkedg, lastavoid, lastlipst, lasttmr, lastcbenab; + int nextnlevel; + double tr; + double br; + double tl; + double bl; public: - Wavelet (); - virtual ~Wavelet (); + Wavelet (); + virtual ~Wavelet (); - bool wavComputed_ (); - void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); - void adjusterChanged (Adjuster* a, double newval); - void adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR); - void autoOpenCurve (); - void curveChanged (CurveEditor* ce); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd,bool chromaadd, bool contrastadd, bool skinadd, bool reschroadd, bool tmrsadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd, bool edgradadd, bool edgvaladd, bool strengthadd, bool gammaadd, bool edgedetectadd, bool edgedetectthradd, bool edgedetectthr2add); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void setEditProvider (EditDataProvider *provider); - void updateToolState (std::vector &tpOpen); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void writeOptions (std::vector &tpOpen); + bool wavComputed_ (); + void adjusterChanged (ThresholdAdjuster* a, double newBottom, double newTop); + void adjusterChanged (Adjuster* a, double newval); + void adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR); + void autoOpenCurve (); + void curveChanged (CurveEditor* ce); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd, bool chromaadd, bool contrastadd, bool skinadd, bool reschroadd, bool tmrsadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd, bool edgradadd, bool edgvaladd, bool strengthadd, bool gammaadd, bool edgedetectadd, bool edgedetectthradd, bool edgedetectthr2add); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void setEditProvider (EditDataProvider *provider); + void updateToolState (std::vector &tpOpen); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void writeOptions (std::vector &tpOpen); private: - void foldAllButMe (GdkEventButton* event, MyExpander *expander); + void foldAllButMe (GdkEventButton* event, MyExpander *expander); - virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); - void BAmethodChanged (); - void NPmethodChanged (); - void BackmethodChanged (); - void CHSLmethodChanged (); - void CHmethodChanged (); - void CLmethodChanged (); - void DirmethodChanged (); - void EDmethodChanged (); - void HSmethodChanged (); - void LmethodChanged (); - void MedgreinfChanged (); - void TMmethodChanged (); - void TilesmethodChanged (); - void avoidToggled (); - void cbenabToggled (); - void contrastMinusPressed (); - void contrastPlusPressed (); - void daubcoeffmethodChanged (); - void enabledChanged (); - void linkedgToggled (); - void lipstToggled (); - void medianToggled (); - void medianlevToggled (); - void neutralPressed (); - void neutral_pressed (); - void neutralchPressed (); - void tmrToggled (); - void updatewavLabel (); - void wavChanged (double nlevel); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void BAmethodChanged (); + void NPmethodChanged (); + void BackmethodChanged (); + void CHSLmethodChanged (); + void CHmethodChanged (); + void CLmethodChanged (); + void DirmethodChanged (); + void EDmethodChanged (); + void HSmethodChanged (); + void LmethodChanged (); + void MedgreinfChanged (); + void TMmethodChanged (); + void TilesmethodChanged (); + void avoidToggled (); + void cbenabToggled (); + void contrastMinusPressed (); + void contrastPlusPressed (); + void daubcoeffmethodChanged (); + void enabledChanged (); + void linkedgToggled (); + void lipstToggled (); + void medianToggled (); + void medianlevToggled (); + void neutralPressed (); + void neutral_pressed (); + void neutralchPressed (); + void tmrToggled (); + void updatewavLabel (); + void wavChanged (double nlevel); - void HSmethodUpdateUI(); - void CHmethodUpdateUI(); -// void CHSLmethodChangedUI(); - void EDmethodUpdateUI(); - void NPmethodUpdateUI(); - void BAmethodUpdateUI(); - void TMmethodUpdateUI(); -// void BackmethodUpdateUI(); - void CLmethodUpdateUI(); -// void TilesmethodUpdateUI(); -// void daubcoeffmethodUpdateUI(); -// void MedgreinfUpdateUI(); -// void DirmethodUpdateUI(); -// void LmethodUpdateUI(); - void adjusterUpdateUI (Adjuster* a); - void enabledUpdateUI (); - void medianlevUpdateUI (); - void cbenabUpdateUI (); - void lipstUpdateUI (); + void HSmethodUpdateUI(); + void CHmethodUpdateUI(); +// void CHSLmethodChangedUI(); + void EDmethodUpdateUI(); + void NPmethodUpdateUI(); + void BAmethodUpdateUI(); + void TMmethodUpdateUI(); +// void BackmethodUpdateUI(); + void CLmethodUpdateUI(); +// void TilesmethodUpdateUI(); +// void daubcoeffmethodUpdateUI(); +// void MedgreinfUpdateUI(); +// void DirmethodUpdateUI(); +// void LmethodUpdateUI(); + void adjusterUpdateUI (Adjuster* a); + void enabledUpdateUI (); + void medianlevUpdateUI (); + void cbenabUpdateUI (); + void lipstUpdateUI (); - void enableToggled(MyExpander *expander); + void enableToggled(MyExpander *expander); }; #endif diff --git a/rtgui/wbprovider.h b/rtgui/wbprovider.h index e92013c2b..2e46467f9 100644 --- a/rtgui/wbprovider.h +++ b/rtgui/wbprovider.h @@ -7,7 +7,7 @@ * 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 @@ -20,9 +20,10 @@ #define _WBPROVIDER_ -class WBProvider { +class WBProvider +{ - public: +public: virtual ~WBProvider() {} virtual void getAutoWB (double& temp, double& green, double equal) {} virtual void getCamWB (double& temp, double& green) {} diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index e15caa38f..914c59956 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -7,7 +7,7 @@ * 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 @@ -33,14 +33,15 @@ using namespace rtengine; using namespace rtengine::procparams; -Glib::RefPtr WhiteBalance::wbPixbufs[rtengine::procparams::WBT_CUSTOM+1]; +Glib::RefPtr WhiteBalance::wbPixbufs[rtengine::procparams::WBT_CUSTOM + 1]; /* Glib::RefPtr WhiteBalance::wbCameraPB, WhiteBalance::wbAutoPB, WhiteBalance::wbSunPB, WhiteBalance::wbTungstenPB, WhiteBalance::wbCloudyPB, WhiteBalance::wbShadePB, WhiteBalance::wbFluorescentPB, WhiteBalance::wbLampPB, WhiteBalance::wbFlashPB, WhiteBalance::wbLedPB, WhiteBalance::wbCustomPB; */ -void WhiteBalance::init () { +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"); @@ -56,34 +57,46 @@ void WhiteBalance::init () { wbPixbufs[WBT_CUSTOM] = safe_create_from_file("wb-custom.png"); } -void WhiteBalance::cleanup () { - for (unsigned int i=0; i MAXTEMP) temp = MAXTEMP; + + if (temp < MINTEMP) { + temp = MINTEMP; + } + + if (temp > MAXTEMP) { + temp = MAXTEMP; + } + return temp; } -static double wbTemp2Slider(double temp) { +static double wbTemp2Slider(double temp) +{ double sval; + if (temp <= CENTERTEMP) { sval = ((temp - MINTEMP) / (CENTERTEMP - MINTEMP)) * 5000.0; } else { @@ -93,198 +106,252 @@ static double wbTemp2Slider(double temp) { double y1; double k = 0.1; bool add = true; + // the y=f(x) function is a mess to invert, therefore we have this trial-refinement loop instead. // from tests, worst case is about 20 iterations, ie no problem for (;;) { - y1 = x * slope + (1.0 - slope)*pow(x, 4.0); - if (5000 * fabs(y1 - y) < 0.1) break; + y1 = x * slope + (1.0 - slope) * pow(x, 4.0); + + if (5000 * fabs(y1 - y) < 0.1) { + break; + } + if (y1 < y) { - if (!add) k /= 2; + if (!add) { + k /= 2; + } + x += k; add = true; } else { - if (add) k /= 2; + if (add) { + k /= 2; + } + x -= k; add = false; } } + sval = 5000.0 + x * 5000.0; } - if (sval < 0) sval = 0; - if (sval > 10000) sval = 10000; + + if (sval < 0) { + sval = 0; + } + + if (sval > 10000) { + sval = 10000; + } + return sval; } -WhiteBalance::WhiteBalance () : FoldableToolPanel(this, "whitebalance", M("TP_WBALANCE_LABEL")), wbp(NULL), wblistener(NULL) { +WhiteBalance::WhiteBalance () : FoldableToolPanel(this, "whitebalance", M("TP_WBALANCE_LABEL")), wbp(NULL), wblistener(NULL) +{ - Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox ()); - hbox->show (); - Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_WBALANCE_METHOD"))); - lab->show (); + Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox ()); + hbox->show (); + Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_WBALANCE_METHOD"))); + lab->show (); - // Create the Tree model - refTreeModel = Gtk::TreeStore::create(methodColumns); - // Create the Combobox - method = Gtk::manage (new MyComboBox ()); - // Assign the model to the Combobox - method->set_model(refTreeModel); + // Create the Tree model + refTreeModel = Gtk::TreeStore::create(methodColumns); + // Create the Combobox + method = Gtk::manage (new MyComboBox ()); + // Assign the model to the Combobox + method->set_model(refTreeModel); - enum WBTypes oldType = WBParams::wbEntries[0]->type; - enum WBTypes currType; - Gtk::TreeModel::Row row, childrow; - for (unsigned int i=0; itype)) { - // New entry type - if (currType == WBT_FLUORESCENT) { - // Creating the Fluorescent subcategory header - row = *(refTreeModel->append()); - row[methodColumns.colIcon] = wbPixbufs[currType]; - row[methodColumns.colLabel] = M("TP_WBALANCE_FLUO_HEADER"); - row[methodColumns.colId] = i+100; - } - if (currType == WBT_WATER) { - // Creating the under water subcategory header - row = *(refTreeModel->append()); - row[methodColumns.colIcon] = wbPixbufs[currType]; - row[methodColumns.colLabel] = M("TP_WBALANCE_WATER_HEADER"); - row[methodColumns.colId] = i+100; - } - if (currType == WBT_LAMP) { - // Creating the Lamp subcategory header - row = *(refTreeModel->append()); - row[methodColumns.colIcon] = wbPixbufs[currType]; - row[methodColumns.colLabel] = M("TP_WBALANCE_LAMP_HEADER"); - row[methodColumns.colId] = i+100; - } - if (currType == WBT_LED) { - // Creating the LED subcategory header - row = *(refTreeModel->append()); - row[methodColumns.colIcon] = wbPixbufs[currType]; - row[methodColumns.colLabel] = M("TP_WBALANCE_LED_HEADER"); - row[methodColumns.colId] = i+100; - } - if (currType == WBT_FLASH) { - // Creating the Flash subcategory header - row = *(refTreeModel->append()); - row[methodColumns.colIcon] = wbPixbufs[currType]; - row[methodColumns.colLabel] = M("TP_WBALANCE_FLASH_HEADER"); - row[methodColumns.colId] = i+100; - } - } - if (currType == WBT_FLUORESCENT - || currType == WBT_LAMP - || currType == WBT_WATER - || currType == WBT_FLASH - || currType == WBT_LED - ) { - childrow = *(refTreeModel->append(row.children())); - childrow[methodColumns.colIcon] = wbPixbufs[currType]; - childrow[methodColumns.colLabel] = WBParams::wbEntries[i]->GUILabel; - childrow[methodColumns.colId] = i; - } - else { - row = *(refTreeModel->append()); - row[methodColumns.colIcon] = wbPixbufs[currType]; - row[methodColumns.colLabel] = WBParams::wbEntries[i]->GUILabel; - row[methodColumns.colId] = i; - } - oldType = currType; + enum WBTypes oldType = WBParams::wbEntries[0]->type; + enum WBTypes currType; + Gtk::TreeModel::Row row, childrow; - custom_green = 1.0; - custom_equal = 1.0; - } + for (unsigned int i = 0; i < WBParams::wbEntries.size(); i++) { + if (oldType != (currType = WBParams::wbEntries[i]->type)) { + // New entry type + if (currType == WBT_FLUORESCENT) { + // Creating the Fluorescent subcategory header + row = *(refTreeModel->append()); + row[methodColumns.colIcon] = wbPixbufs[currType]; + row[methodColumns.colLabel] = M("TP_WBALANCE_FLUO_HEADER"); + row[methodColumns.colId] = i + 100; + } - //Add the model columns to the Combo (which is a kind of view), - //rendering them in the default way: - method->pack_start(methodColumns.colIcon, false); - method->pack_start(methodColumns.colLabel, true); + if (currType == WBT_WATER) { + // Creating the under water subcategory header + row = *(refTreeModel->append()); + row[methodColumns.colIcon] = wbPixbufs[currType]; + row[methodColumns.colLabel] = M("TP_WBALANCE_WATER_HEADER"); + row[methodColumns.colId] = i + 100; + } - method->set_active (0); // Camera - method->show (); - hbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); - hbox->pack_start (*method); - pack_start (*hbox, Gtk::PACK_SHRINK, 4); - opt = 0; + if (currType == WBT_LAMP) { + // Creating the Lamp subcategory header + row = *(refTreeModel->append()); + row[methodColumns.colIcon] = wbPixbufs[currType]; + row[methodColumns.colLabel] = M("TP_WBALANCE_LAMP_HEADER"); + row[methodColumns.colId] = i + 100; + } - Gtk::HBox* spotbox = Gtk::manage (new Gtk::HBox ()); - spotbox->show (); + if (currType == WBT_LED) { + // Creating the LED subcategory header + row = *(refTreeModel->append()); + row[methodColumns.colIcon] = wbPixbufs[currType]; + row[methodColumns.colLabel] = M("TP_WBALANCE_LED_HEADER"); + row[methodColumns.colId] = i + 100; + } - spotbutton = Gtk::manage (new Gtk::Button (M("TP_WBALANCE_SPOTWB"))); - Gtk::Image* spotimg = Gtk::manage (new RTImage ("gtk-color-picker-small.png")); - spotimg->show (); - spotbutton->set_image (*spotimg); - spotbutton->show (); + if (currType == WBT_FLASH) { + // Creating the Flash subcategory header + row = *(refTreeModel->append()); + row[methodColumns.colIcon] = wbPixbufs[currType]; + row[methodColumns.colLabel] = M("TP_WBALANCE_FLASH_HEADER"); + row[methodColumns.colId] = i + 100; + } + } - spotbox->pack_start (*spotbutton); + if (currType == WBT_FLUORESCENT + || currType == WBT_LAMP + || currType == WBT_WATER + || currType == WBT_FLASH + || currType == WBT_LED + ) { + childrow = *(refTreeModel->append(row.children())); + childrow[methodColumns.colIcon] = wbPixbufs[currType]; + childrow[methodColumns.colLabel] = WBParams::wbEntries[i]->GUILabel; + childrow[methodColumns.colId] = i; + } else { + row = *(refTreeModel->append()); + row[methodColumns.colIcon] = wbPixbufs[currType]; + row[methodColumns.colLabel] = WBParams::wbEntries[i]->GUILabel; + row[methodColumns.colId] = i; + } - Gtk::Label* slab = Gtk::manage (new Gtk::Label (M("TP_WBALANCE_SIZE"))); - slab->show (); + oldType = currType; - spotsize = Gtk::manage (new MyComboBoxText ()); - spotsize->show (); - spotsize->append_text ("2"); if (options.whiteBalanceSpotSize==2) spotsize->set_active(0); - spotsize->append_text ("4"); if (options.whiteBalanceSpotSize==4) spotsize->set_active(1); - spotsize->append_text ("8"); if (options.whiteBalanceSpotSize==8) spotsize->set_active(2); - spotsize->append_text ("16"); if (options.whiteBalanceSpotSize==16) spotsize->set_active(3); - spotsize->append_text ("32"); if (options.whiteBalanceSpotSize==32) spotsize->set_active(4); + custom_green = 1.0; + custom_equal = 1.0; + } - spotbox->pack_end (*spotsize, Gtk::PACK_EXPAND_WIDGET, 4); - spotbox->pack_end (*slab, Gtk::PACK_SHRINK, 4); + //Add the model columns to the Combo (which is a kind of view), + //rendering them in the default way: + method->pack_start(methodColumns.colIcon, false); + method->pack_start(methodColumns.colLabel, true); - pack_start (*spotbox, Gtk::PACK_SHRINK, 4); + method->set_active (0); // Camera + method->show (); + hbox->pack_start (*lab, Gtk::PACK_SHRINK, 4); + hbox->pack_start (*method); + pack_start (*hbox, Gtk::PACK_SHRINK, 4); + opt = 0; - Gtk::Image* itempL = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); - Gtk::Image* itempR = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); - Gtk::Image* igreenL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); - Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); - Gtk::Image* iblueredL = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); - Gtk::Image* iblueredR = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + Gtk::HBox* spotbox = Gtk::manage (new Gtk::HBox ()); + spotbox->show (); - temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, CENTERTEMP, itempL, itempR, &wbSlider2Temp, &wbTemp2Slider)); - green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0, igreenL, igreenR)); - equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0, iblueredL, iblueredR)); - cache_customTemp (0); - cache_customGreen (0); - cache_customEqual (0); - equal->set_tooltip_markup (M("TP_WBALANCE_EQBLUERED_TOOLTIP")); - temp->show (); - green->show (); - equal->show (); + spotbutton = Gtk::manage (new Gtk::Button (M("TP_WBALANCE_SPOTWB"))); + Gtk::Image* spotimg = Gtk::manage (new RTImage ("gtk-color-picker-small.png")); + spotimg->show (); + spotbutton->set_image (*spotimg); + spotbutton->show (); - /* Gtk::HBox* boxgreen = Gtk::manage (new Gtk::HBox ()); - boxgreen->show (); + spotbox->pack_start (*spotbutton); - boxgreen->pack_start(*igreenL); - boxgreen->pack_start(*green); - boxgreen->pack_start(*igreenR);*/ + Gtk::Label* slab = Gtk::manage (new Gtk::Label (M("TP_WBALANCE_SIZE"))); + slab->show (); - pack_start (*temp); - //pack_start (*boxgreen); - pack_start (*green); - pack_start (*equal); + spotsize = Gtk::manage (new MyComboBoxText ()); + spotsize->show (); + spotsize->append_text ("2"); - temp->setAdjusterListener (this); - green->setAdjusterListener (this); - equal->setAdjusterListener (this); + if (options.whiteBalanceSpotSize == 2) { + spotsize->set_active(0); + } - spotbutton->signal_pressed().connect( sigc::mem_fun(*this, &WhiteBalance::spotPressed) ); - methconn = method->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::optChanged) ); - spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); + spotsize->append_text ("4"); + + if (options.whiteBalanceSpotSize == 4) { + spotsize->set_active(1); + } + + spotsize->append_text ("8"); + + if (options.whiteBalanceSpotSize == 8) { + spotsize->set_active(2); + } + + spotsize->append_text ("16"); + + if (options.whiteBalanceSpotSize == 16) { + spotsize->set_active(3); + } + + spotsize->append_text ("32"); + + if (options.whiteBalanceSpotSize == 32) { + spotsize->set_active(4); + } + + spotbox->pack_end (*spotsize, Gtk::PACK_EXPAND_WIDGET, 4); + spotbox->pack_end (*slab, Gtk::PACK_SHRINK, 4); + + pack_start (*spotbox, Gtk::PACK_SHRINK, 4); + + Gtk::Image* itempL = Gtk::manage (new RTImage ("ajd-wb-temp1.png")); + Gtk::Image* itempR = Gtk::manage (new RTImage ("ajd-wb-temp2.png")); + Gtk::Image* igreenL = Gtk::manage (new RTImage ("ajd-wb-green1.png")); + Gtk::Image* igreenR = Gtk::manage (new RTImage ("ajd-wb-green2.png")); + Gtk::Image* iblueredL = Gtk::manage (new RTImage ("ajd-wb-bluered1.png")); + Gtk::Image* iblueredR = Gtk::manage (new RTImage ("ajd-wb-bluered2.png")); + + temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, CENTERTEMP, itempL, itempR, &wbSlider2Temp, &wbTemp2Slider)); + green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0, igreenL, igreenR)); + equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0, iblueredL, iblueredR)); + cache_customTemp (0); + cache_customGreen (0); + cache_customEqual (0); + equal->set_tooltip_markup (M("TP_WBALANCE_EQBLUERED_TOOLTIP")); + temp->show (); + green->show (); + equal->show (); + + /* Gtk::HBox* boxgreen = Gtk::manage (new Gtk::HBox ()); + boxgreen->show (); + + boxgreen->pack_start(*igreenL); + boxgreen->pack_start(*green); + boxgreen->pack_start(*igreenR);*/ + + pack_start (*temp); + //pack_start (*boxgreen); + pack_start (*green); + pack_start (*equal); + + temp->setAdjusterListener (this); + green->setAdjusterListener (this); + equal->setAdjusterListener (this); + + spotbutton->signal_pressed().connect( sigc::mem_fun(*this, &WhiteBalance::spotPressed) ); + methconn = method->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::optChanged) ); + spotsize->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::spotSizeChanged) ); } -void WhiteBalance::adjusterChanged (Adjuster* a, double newval) { +void WhiteBalance::adjusterChanged (Adjuster* a, double newval) +{ int tVal = (int)temp->getValue(); double gVal = green->getValue(); double eVal = equal->getValue(); Gtk::TreeModel::Row row = getActiveMethod(); - if (row == refTreeModel->children().end()) return; + + if (row == refTreeModel->children().end()) { + return; + } Glib::ustring colLabel = row[methodColumns.colLabel]; WBEntry* ppMethod = findWBEntry (row[methodColumns.colLabel], WBLT_GUI); WBEntry* wbCustom = findWBEntry ("Custom", WBLT_PP); - if (!ppMethod || (ppMethod->ppLabel!=wbCustom->ppLabel && !(a==equal && ppMethod->type==WBT_AUTO)) ) { + if (!ppMethod || (ppMethod->ppLabel != wbCustom->ppLabel && !(a == equal && ppMethod->type == WBT_AUTO)) ) { methconn.block(true); opt = setActiveMethod(wbCustom->GUILabel); cache_customWB (tVal, gVal); @@ -293,40 +360,53 @@ void WhiteBalance::adjusterChanged (Adjuster* a, double newval) { } //cache custom WB setting to allow its recall - if (a==temp) + if (a == temp) { cache_customTemp (tVal); - else if (a==green) + } else if (a == green) { cache_customGreen (gVal); - else if (a==equal) { + } else if (a == equal) { cache_customEqual (eVal); + // Recomputing AutoWB if it's the current method - if (wbp && ppMethod->type==WBT_AUTO) { - double ctemp=-1.0; double cgreen=-1.0; + if (wbp && ppMethod->type == WBT_AUTO) { + double ctemp = -1.0; + double cgreen = -1.0; wbp->getAutoWB (ctemp, cgreen, eVal); if (ctemp != -1.0) { // Set the automatics temperature value only if in SET mode - if (temp->getEditedState() && !temp->getAddMode() ) temp->setValue (ctemp); + if (temp->getEditedState() && !temp->getAddMode() ) { + temp->setValue (ctemp); + } + // Set the automatics green value only if in SET mode - if (green->getEditedState() && !green->getAddMode()) green->setValue (cgreen); + if (green->getEditedState() && !green->getAddMode()) { + green->setValue (cgreen); + } } } } if (listener) { - if (a==temp) + if (a == temp) { listener->panelChanged (EvWBTemp, Glib::ustring::format ((int)a->getValue())); - else if (a==green) + } else if (a == green) { listener->panelChanged (EvWBGreen, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), a->getValue())); - else if (a==equal) + } else if (a == equal) { listener->panelChanged (EvWBequal, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), a->getValue())); + } } } -void WhiteBalance::optChanged () { +void WhiteBalance::optChanged () +{ Gtk::TreeModel::Row row = getActiveMethod(); - if (row == refTreeModel->children().end()) return; + + if (row == refTreeModel->children().end()) { + return; + } + if (row[methodColumns.colId] >= 100) { // "Header" solutions are trapped ; the combo is then set to the previous value bool prevState = methconn.block(true); @@ -343,8 +423,7 @@ void WhiteBalance::optChanged () { temp->setEditedState (UnEdited); green->setEditedState (UnEdited); equal->setEditedState (UnEdited); - } - else { + } else { int methodId = findWBEntryId (row[methodColumns.colLabel], WBLT_GUI); WBEntry* currMethod = WBParams::wbEntries[methodId]; @@ -356,13 +435,16 @@ void WhiteBalance::optChanged () { temp->setValue (temp->getAddMode() ? 0.0 : (int)ctemp); green->setValue (green->getAddMode() ? 0.0 : cgreen); equal->setValue (equal->getAddMode() ? 0.0 : 1.0); + if (batchMode) { temp->setEditedState (UnEdited); green->setEditedState (UnEdited); equal->setEditedState (UnEdited); } } + break; + case WBT_AUTO: if (wbp) { if (batchMode) { @@ -370,18 +452,22 @@ void WhiteBalance::optChanged () { green->setEditedState (UnEdited); // equal remain as is } + if (!batchMode || equal->getEditedState()) { double ctemp, cgreen; wbp->getAutoWB (ctemp, cgreen, equal->getValue()); + if (ctemp != -1.0) { temp->setValue (temp->getAddMode() ? 0.0 : (int)ctemp); green->setValue (green->getAddMode() ? 0.0 : cgreen); } } } + break; + case WBT_CUSTOM: - if (custom_temp>0){ + if (custom_temp > 0) { temp->setValue (temp->getAddMode() ? 0.0 : custom_temp); green->setValue (green->getAddMode() ? 0.0 : custom_green); equal->setValue (equal->getAddMode() ? 0.0 : custom_equal); @@ -390,12 +476,15 @@ void WhiteBalance::optChanged () { cache_customGreen (green->getValue()); cache_customEqual (equal->getValue()); } + if (batchMode) { temp->setEditedState (Edited); green->setEditedState (Edited); equal->setEditedState (Edited); } + break; + /* All other solution are the default cases case WBT_DAYLIGHT: case WBT_CLOUDY: @@ -410,34 +499,42 @@ void WhiteBalance::optChanged () { temp->setValue ( temp->getAddMode() ? 0.0 : (double)(currMethod->temperature)); green->setValue (green->getAddMode() ? 0.0 : (double)(currMethod->green)); equal->setValue (equal->getAddMode() ? 0.0 : (double)(currMethod->equal)); + if (batchMode) { temp->setEditedState (Edited); green->setEditedState (Edited); equal->setEditedState (Edited); } + break; } } - if (listener) + if (listener) { listener->panelChanged (EvWBMethod, row[methodColumns.colLabel]); + } } } -void WhiteBalance::spotPressed () { +void WhiteBalance::spotPressed () +{ - if (wblistener) - wblistener->spotWBRequested (getSize()); + if (wblistener) { + wblistener->spotWBRequested (getSize()); + } } -void WhiteBalance::spotSizeChanged () { - options.whiteBalanceSpotSize=getSize(); +void WhiteBalance::spotSizeChanged () +{ + options.whiteBalanceSpotSize = getSize(); - if (wblistener) - wblistener->spotWBRequested (getSize()); + if (wblistener) { + wblistener->spotWBRequested (getSize()); + } } -void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) { +void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) +{ disableListener (); methconn.block (true); @@ -449,14 +546,15 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) { green->setEditedState (UnEdited); equal->setEditedState (pedited->wb.equal ? Edited : UnEdited); } - + if (pedited && !pedited->wb.method) { opt = setActiveMethod(M("GENERAL_UNCHANGED")); - } - else { + } else { WBEntry* wbValues = findWBEntry(pp->wb.method, WBLT_PP); - if (!wbValues) + + if (!wbValues) { wbValues = findWBEntry("Camera", WBLT_PP); + } opt = setActiveMethod(wbValues->GUILabel); @@ -469,15 +567,19 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) { cache_customTemp (pp->wb.temperature); cache_customGreen (pp->wb.green); cache_customEqual (pp->wb.equal); - if (pedited) { + + if (pedited) { // The user may have changed the temperature and green value temp->setEditedState (pedited->wb.temperature ? Edited : UnEdited); green->setEditedState (pedited->wb.green ? Edited : UnEdited); } + break; + case WBT_CAMERA: if (wbp) { - double ctemp = -1.0; double cgreen = -1.0; + double ctemp = -1.0; + double cgreen = -1.0; wbp->getCamWB (ctemp, cgreen); if (ctemp != -1.0) { @@ -492,34 +594,51 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) { equal->setValue (equal->getAddMode() ? 0.0 : pp->wb.equal); } } + break; + case WBT_AUTO: // the equalizer's value is restored for the AutoWB equal->setValue (equal->getAddMode() ? 0.0 : pp->wb.equal); // set default values first if in ADD mode, otherwise keep the current ones - if (temp->getAddMode() ) temp->setValue (0.0); - if (green->getAddMode()) green->setValue (0.0); + if (temp->getAddMode() ) { + temp->setValue (0.0); + } + + if (green->getAddMode()) { + green->setValue (0.0); + } // then check for the correct ones, if possible if (wbp) { - double ctemp=-1.0; double cgreen=-1.0; + double ctemp = -1.0; + double cgreen = -1.0; wbp->getAutoWB (ctemp, cgreen, pp->wb.equal); if (ctemp != -1.0) { // Set the automatics temperature if in SET mode if (!pedited || (pedited->wb.temperature && !temp->getAddMode()) ) { temp->setValue (ctemp); - if (pedited) temp->setEditedState (Edited); + + if (pedited) { + temp->setEditedState (Edited); + } } + // Set the automatics green value if in SET mode if (!pedited || (pedited->wb.green && !green->getAddMode())) { green->setValue (cgreen); - if (pedited) green->setEditedState (Edited); + + if (pedited) { + green->setEditedState (Edited); + } } } } + break; + /* All those types are the "default" case: case WBT_DAYLIGHT: @@ -543,78 +662,86 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited) { green->setEditedState (pedited->wb.green ? Edited : UnEdited); equal->setEditedState (pedited->wb.equal ? Edited : UnEdited); } + //cache_customGreen (pp->wb.green); break; } } + methconn.block (false); enableListener (); } -void WhiteBalance::write (ProcParams* pp, ParamsEdited* pedited) { - +void WhiteBalance::write (ProcParams* pp, ParamsEdited* pedited) +{ + Gtk::TreeModel::Row row = getActiveMethod(); if (pedited) { pedited->wb.temperature = temp->getEditedState (); pedited->wb.green = green->getEditedState (); pedited->wb.equal = equal->getEditedState (); - pedited->wb.method = row[methodColumns.colLabel]!=M("GENERAL_UNCHANGED"); + pedited->wb.method = row[methodColumns.colLabel] != M("GENERAL_UNCHANGED"); } WBEntry* ppMethod = findWBEntry (row[methodColumns.colLabel], WBLT_GUI); - if (ppMethod) + if (ppMethod) { pp->wb.method = ppMethod->ppLabel; + } + pp->wb.temperature = temp->getIntValue (); pp->wb.green = green->getValue (); pp->wb.equal = equal->getValue (); } -void WhiteBalance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { +void WhiteBalance::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ equal->setDefault (defParams->wb.equal); if (wbp && defParams->wb.method == "Camera") { - double ctemp; double cgreen; + double ctemp; + double cgreen; wbp->getCamWB (ctemp, cgreen); + // FIXME: Seems to be always -1.0, called too early? Broken! if (ctemp != -1.0) { temp->setDefault (temp->getAddMode() ? 0 : (int)ctemp); green->setDefault (green->getAddMode() ? 0 : cgreen); } - } - else if (wbp && defParams->wb.method == "Auto") { + } else if (wbp && defParams->wb.method == "Auto") { // this setDefaults method is called too early ; the wbp has been set, // but wbp is not ready to provide! - double ctemp; double cgreen; + double ctemp; + double cgreen; wbp->getAutoWB (ctemp, cgreen, defParams->wb.equal); + if (ctemp != -1.0) { temp->setDefault (temp->getAddMode() ? 0 : (int)ctemp); green->setDefault (green->getAddMode() ? 0 : cgreen); - } - else { + } else { // 6504 & 1.0 = same values as in ProcParams::setDefaults temp->setDefault (temp->getAddMode() ? 0 : 6504); green->setDefault (green->getAddMode() ? 0 : 1.0); } - } - else { + } else { temp->setDefault (defParams->wb.temperature); green->setDefault (defParams->wb.green); } + if (pedited) { temp->setDefaultEditedState (pedited->wb.temperature ? Edited : UnEdited); green->setDefaultEditedState (pedited->wb.green ? Edited : UnEdited); equal->setDefaultEditedState (pedited->wb.equal ? Edited : UnEdited); - } - else { + } else { temp->setDefaultEditedState (Irrelevant); green->setDefaultEditedState (Irrelevant); equal->setDefaultEditedState (Irrelevant); } } -void WhiteBalance::setBatchMode (bool batchMode) { +void WhiteBalance::setBatchMode (bool batchMode) +{ ToolPanel::setBatchMode (batchMode); temp->showEditedCB (); @@ -626,101 +753,127 @@ void WhiteBalance::setBatchMode (bool batchMode) { } -int WhiteBalance::getSize () { +int WhiteBalance::getSize () +{ return atoi(spotsize->get_active_text().c_str()); } -void WhiteBalance::setWB (int vtemp, double vgreen) { +void WhiteBalance::setWB (int vtemp, double vgreen) +{ methconn.block(true); WBEntry *wbValues = findWBEntry("Custom", WBLT_PP); temp->setValue (vtemp); green->setValue (vgreen); opt = setActiveMethod(wbValues->GUILabel); - cache_customWB (vtemp,vgreen); // sequence in which this call is made is important; must be before "method->set_active (2);" + cache_customWB (vtemp, vgreen); // sequence in which this call is made is important; must be before "method->set_active (2);" cache_customEqual(equal->getValue()); temp->setEditedState (Edited); green->setEditedState (Edited); methconn.block(false); - if (listener) + if (listener) { listener->panelChanged (EvWBTemp, Glib::ustring::compose("%1, %2", (int)temp->getValue(), Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), green->getValue()))); + } } -void WhiteBalance::setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd) { +void WhiteBalance::setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd) +{ - temp->setAddMode(tempadd); - green->setAddMode(greenadd); - equal->setAddMode(equaladd); + temp->setAddMode(tempadd); + green->setAddMode(greenadd); + equal->setAddMode(equaladd); } -void WhiteBalance::trimValues (rtengine::procparams::ProcParams* pp) { +void WhiteBalance::trimValues (rtengine::procparams::ProcParams* pp) +{ - temp->trimValue(pp->wb.temperature); - green->trimValue(pp->wb.green); - equal->trimValue(pp->wb.equal); + temp->trimValue(pp->wb.temperature); + green->trimValue(pp->wb.green); + equal->trimValue(pp->wb.equal); } -inline void WhiteBalance::cache_customTemp(int temp) { +inline void WhiteBalance::cache_customTemp(int temp) +{ custom_temp = temp; } -void WhiteBalance::cache_customGreen(double green) { +void WhiteBalance::cache_customGreen(double green) +{ custom_green = green; } -void WhiteBalance::cache_customEqual(double equal) { +void WhiteBalance::cache_customEqual(double equal) +{ custom_equal = equal; } -void WhiteBalance::cache_customWB(int temp, double green) { +void WhiteBalance::cache_customWB(int temp, double green) +{ cache_customTemp (temp); cache_customGreen (green); } -int WhiteBalance::findWBEntryId (Glib::ustring label, enum WB_LabelType lblType) { - for (unsigned int i=0; iGUILabel : WBParams::wbEntries[i]->ppLabel)) +int WhiteBalance::findWBEntryId (Glib::ustring label, enum WB_LabelType lblType) +{ + for (unsigned int i = 0; i < WBParams::wbEntries.size(); i++) { + if (label == (lblType == WBLT_GUI ? WBParams::wbEntries[i]->GUILabel : WBParams::wbEntries[i]->ppLabel)) { return i; + } } + return -1; } -WBEntry* WhiteBalance::findWBEntry (Glib::ustring label, enum WB_LabelType lblType) { - for (unsigned int i=0; iGUILabel : WBParams::wbEntries[i]->ppLabel)) +WBEntry* WhiteBalance::findWBEntry (Glib::ustring label, enum WB_LabelType lblType) +{ + for (unsigned int i = 0; i < WBParams::wbEntries.size(); i++) { + if (label == (lblType == WBLT_GUI ? WBParams::wbEntries[i]->GUILabel : WBParams::wbEntries[i]->ppLabel)) { return WBParams::wbEntries[i]; + } } + return NULL; } -int WhiteBalance::_setActiveMethod(Glib::ustring &label, Gtk::TreeModel::Children &children) { +int WhiteBalance::_setActiveMethod(Glib::ustring &label, Gtk::TreeModel::Children &children) +{ int found = -1; - for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end() && found==-1; ++iter) { - Gtk::TreeModel::Row row = *iter; - if (row[methodColumns.colLabel] == label) { - method->set_active(iter); - found = method->get_active_row_number(); - } - if (found !=-1) - return found; - Gtk::TreeModel::Children childs = row.children(); - if (childs.size()) { - found = _setActiveMethod(label, childs); - if (found !=-1) - return found; - } + for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end() && found == -1; ++iter) { + Gtk::TreeModel::Row row = *iter; + + if (row[methodColumns.colLabel] == label) { + method->set_active(iter); + found = method->get_active_row_number(); + } + + if (found != -1) { + return found; + } + + Gtk::TreeModel::Children childs = row.children(); + + if (childs.size()) { + found = _setActiveMethod(label, childs); + + if (found != -1) { + return found; + } + } } + // Entry not found return -1; } -int WhiteBalance::setActiveMethod(Glib::ustring label) { +int WhiteBalance::setActiveMethod(Glib::ustring label) +{ Gtk::TreeModel::Children children = refTreeModel->children(); return _setActiveMethod(label, children); } -inline Gtk::TreeRow WhiteBalance::getActiveMethod () { +inline Gtk::TreeRow WhiteBalance::getActiveMethod () +{ return *(method->get_active()); } diff --git a/rtgui/whitebalance.h b/rtgui/whitebalance.h index 39ad5ffe2..3ebd503bc 100644 --- a/rtgui/whitebalance.h +++ b/rtgui/whitebalance.h @@ -7,7 +7,7 @@ * 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 @@ -26,29 +26,37 @@ #include "wbprovider.h" #include "../rtengine/procparams.h" -class SpotWBListener { +class SpotWBListener +{ - public: - virtual void spotWBRequested (int size) {} +public: + virtual void spotWBRequested (int size) {} }; -class WhiteBalance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class WhiteBalance : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ enum WB_LabelType { WBLT_GUI, WBLT_PP }; - protected: - class MethodColumns : public Gtk::TreeModel::ColumnRecord { - public: +protected: + class MethodColumns : public Gtk::TreeModel::ColumnRecord + { + public: Gtk::TreeModelColumn< Glib::RefPtr > colIcon; Gtk::TreeModelColumn colLabel; Gtk::TreeModelColumn colId; - MethodColumns() { add(colIcon); add(colLabel); add(colId); } + MethodColumns() + { + add(colIcon); + add(colLabel); + add(colId); + } }; - static Glib::RefPtr wbPixbufs[rtengine::procparams::WBT_CUSTOM+1]; + static Glib::RefPtr wbPixbufs[rtengine::procparams::WBT_CUSTOM + 1]; Glib::RefPtr refTreeModel; MethodColumns methodColumns; MyComboBox* method; @@ -76,30 +84,36 @@ class WhiteBalance : public ToolParamBlock, public AdjusterListener, public Fold int _setActiveMethod (Glib::ustring &label, Gtk::TreeModel::Children &children); Gtk::TreeModel::Row getActiveMethod (); - int findWBEntryId (Glib::ustring label, enum WB_LabelType lblType=WBLT_GUI); - rtengine::procparams::WBEntry* findWBEntry (Glib::ustring label, enum WB_LabelType lblType=WBLT_GUI); + int findWBEntryId (Glib::ustring label, enum WB_LabelType lblType = WBLT_GUI); + rtengine::procparams::WBEntry* findWBEntry (Glib::ustring label, enum WB_LabelType lblType = WBLT_GUI); - public: +public: WhiteBalance (); ~WhiteBalance () {}; static void init (); static void cleanup (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - + void optChanged (); void spotPressed (); void spotSizeChanged (); void adjusterChanged (Adjuster* a, double newval); - int getSize (); - void setWBProvider (WBProvider* p) { wbp = p; } - void setSpotWBListener (SpotWBListener* l) { wblistener = l; } + int getSize (); + void setWBProvider (WBProvider* p) + { + wbp = p; + } + void setSpotWBListener (SpotWBListener* l) + { + wblistener = l; + } void setWB (int temp, double green); - + void setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd); void trimValues (rtengine::procparams::ProcParams* pp); }; diff --git a/rtgui/windirmonitor.cc b/rtgui/windirmonitor.cc index 66dbefd3b..1888d9405 100644 --- a/rtgui/windirmonitor.cc +++ b/rtgui/windirmonitor.cc @@ -7,7 +7,7 @@ * 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 @@ -19,59 +19,65 @@ #include "windirmonitor.h" #include "options.h" -static void CALLBACK current_directory_monitor_callback (DWORD error, DWORD nBytes, LPOVERLAPPED lpOverlapped) { +static void CALLBACK current_directory_monitor_callback (DWORD error, DWORD nBytes, LPOVERLAPPED lpOverlapped) +{ DWORD dwOffset = 0; FILE_NOTIFY_INFORMATION* pInfo = NULL; WinDirMonitor::MonitorData* monData = (WinDirMonitor::MonitorData*)lpOverlapped; + if (!nBytes) { delete monData; return; } bool notify = false; + // Analysis of the modifications. Let only parsed file extensions emit a notify, not PP3 changes do { // Get a pointer to the first change record... pInfo = (FILE_NOTIFY_INFORMATION*) &monData->file_notify_buffer[dwOffset]; - char fnameC[(MAX_PATH+1)*2] = {0}; - int strLen = WideCharToMultiByte(CP_UTF8,0,pInfo->FileName,pInfo->FileNameLength/sizeof(WCHAR),fnameC,sizeof(fnameC),0,0); + char fnameC[(MAX_PATH + 1) * 2] = {0}; + int strLen = WideCharToMultiByte(CP_UTF8, 0, pInfo->FileName, pInfo->FileNameLength / sizeof(WCHAR), fnameC, sizeof(fnameC), 0, 0); fnameC[strLen] = 0; Glib::ustring fname = fnameC; - if (options.has_retained_extention(fname)) + if (options.has_retained_extention(fname)) { notify = true; + } // More than one change may happen at the same time. Load the next change and continue... dwOffset += pInfo->NextEntryOffset; } while (!notify && pInfo->NextEntryOffset != 0); - // ReadDirectoryChangesW sometimes emits multiple events per change (one for each change type) - // To make sure it's not flooding update, this gets filtered. - DWORD curTick = GetTickCount(); - if (notify && monData->listener && (curTick-monData->lastTimeUpdateTick)>500) { + // ReadDirectoryChangesW sometimes emits multiple events per change (one for each change type) + // To make sure it's not flooding update, this gets filtered. + DWORD curTick = GetTickCount(); + + if (notify && monData->listener && (curTick - monData->lastTimeUpdateTick) > 500) { monData->lastTimeUpdateTick = curTick; monData->listener->winDirChanged (); - } + } ReadDirectoryChangesW (monData->hDirectory, - monData->file_notify_buffer, - monData->buffer_allocated_bytes, - FALSE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_LAST_WRITE, - &monData->buffer_filled_bytes, - &monData->overlapped, - current_directory_monitor_callback); + monData->file_notify_buffer, + monData->buffer_allocated_bytes, + FALSE, + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_LAST_WRITE, + &monData->buffer_filled_bytes, + &monData->overlapped, + current_directory_monitor_callback); } -WinDirMonitor::WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* listener) : monData(NULL) { +WinDirMonitor::WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* listener) : monData(NULL) +{ wchar_t* wdirname = (wchar_t*)g_utf8_to_utf16 (dirName.c_str(), -1, NULL, NULL, NULL); - HANDLE hDirectory = CreateFileW (wdirname, FILE_LIST_DIRECTORY,FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); + HANDLE hDirectory = CreateFileW (wdirname, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); g_free (wdirname); - + if (hDirectory != INVALID_HANDLE_VALUE) { monData = new MonitorData (); @@ -80,22 +86,24 @@ WinDirMonitor::WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* liste monData->file_notify_buffer = new char [monData->buffer_allocated_bytes]; monData->hDirectory = hDirectory; monData->lastTimeUpdateTick = GetTickCount(); - + ReadDirectoryChangesW (monData->hDirectory, - monData->file_notify_buffer, - monData->buffer_allocated_bytes, - FALSE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_LAST_WRITE, - &monData->buffer_filled_bytes, - &monData->overlapped, - current_directory_monitor_callback); + monData->file_notify_buffer, + monData->buffer_allocated_bytes, + FALSE, + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_LAST_WRITE, + &monData->buffer_filled_bytes, + &monData->overlapped, + current_directory_monitor_callback); } } -WinDirMonitor::~WinDirMonitor () { +WinDirMonitor::~WinDirMonitor () +{ - if (monData && monData->hDirectory != INVALID_HANDLE_VALUE) + if (monData && monData->hDirectory != INVALID_HANDLE_VALUE) { CloseHandle (monData->hDirectory); + } } diff --git a/rtgui/windirmonitor.h b/rtgui/windirmonitor.h index ddef88135..c3278c931 100644 --- a/rtgui/windirmonitor.h +++ b/rtgui/windirmonitor.h @@ -7,7 +7,7 @@ * 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 @@ -22,32 +22,34 @@ #include #include -class WinDirChangeListener { +class WinDirChangeListener +{ - public: - virtual void winDirChanged () {} +public: + virtual void winDirChanged () {} }; -class WinDirMonitor : public Glib::Object { +class WinDirMonitor : public Glib::Object +{ - public: - struct MonitorData { - OVERLAPPED overlapped; - DWORD buffer_allocated_bytes; - char *file_notify_buffer; - DWORD buffer_filled_bytes; - HANDLE hDirectory; - WinDirChangeListener* listener; - int bigyo; - DWORD lastTimeUpdateTick; // for filtering multiple updates events - }; - - private: - MonitorData* monData; - - public: - WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* listener); - ~WinDirMonitor (); +public: + struct MonitorData { + OVERLAPPED overlapped; + DWORD buffer_allocated_bytes; + char *file_notify_buffer; + DWORD buffer_filled_bytes; + HANDLE hDirectory; + WinDirChangeListener* listener; + int bigyo; + DWORD lastTimeUpdateTick; // for filtering multiple updates events + }; + +private: + MonitorData* monData; + +public: + WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* listener); + ~WinDirMonitor (); }; #endif diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 2b028e657..f6c82a55a 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -24,109 +24,126 @@ using namespace rtengine::procparams; XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP_RAW_LABEL"), true) { - Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); - hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") +": ")),Gtk::PACK_SHRINK, 4); - method = Gtk::manage (new MyComboBoxText ()); - for( size_t i=0; iappend_text(procparams::RAWParams::XTransSensor::methodstring[i]); + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + method = Gtk::manage (new MyComboBoxText ()); - method->set_active(0); - hb1->set_tooltip_markup (M("TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP")); + for( size_t i = 0; i < procparams::RAWParams::XTransSensor::numMethods; i++) { + method->append_text(procparams::RAWParams::XTransSensor::methodstring[i]); + } - hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); - pack_start( *hb1, Gtk::PACK_SHRINK, 4); + method->set_active(0); + hb1->set_tooltip_markup (M("TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP")); - pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); - ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"),0,5,1,0 )); - ccSteps->setAdjusterListener (this); - if (ccSteps->delay < 1000) ccSteps->delay = 1000; - ccSteps->show(); - pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb1, Gtk::PACK_SHRINK, 4); - methodconn = method->signal_changed().connect( sigc::mem_fun(*this, &XTransProcess::methodChanged) ); + pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); + ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 )); + ccSteps->setAdjusterListener (this); + + if (ccSteps->delay < 1000) { + ccSteps->delay = 1000; + } + + ccSteps->show(); + pack_start( *ccSteps, Gtk::PACK_SHRINK, 4); + + methodconn = method->signal_changed().connect( sigc::mem_fun(*this, &XTransProcess::methodChanged) ); } void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); - methodconn.block (true); + disableListener (); + methodconn.block (true); - method->set_active(procparams::RAWParams::XTransSensor::numMethods); - for( size_t i=0; i< procparams::RAWParams::XTransSensor::numMethods; i++) - if( pp->raw.xtranssensor.method == procparams::RAWParams::XTransSensor::methodstring[i]) { - method->set_active(i); - oldSelection = i; - break; - } + method->set_active(procparams::RAWParams::XTransSensor::numMethods); - if(pedited ){ - ccSteps->setEditedState (pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); - if( !pedited->raw.xtranssensor.method ) - method->set_active(procparams::RAWParams::XTransSensor::numMethods); // No name - } + for( size_t i = 0; i < procparams::RAWParams::XTransSensor::numMethods; i++) + if( pp->raw.xtranssensor.method == procparams::RAWParams::XTransSensor::methodstring[i]) { + method->set_active(i); + oldSelection = i; + break; + } - ccSteps->setValue (pp->raw.xtranssensor.ccSteps); + if(pedited ) { + ccSteps->setEditedState (pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); - methodconn.block (false); + if( !pedited->raw.xtranssensor.method ) { + method->set_active(procparams::RAWParams::XTransSensor::numMethods); // No name + } + } - enableListener (); + ccSteps->setValue (pp->raw.xtranssensor.ccSteps); + + methodconn.block (false); + + enableListener (); } void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.xtranssensor.ccSteps = ccSteps->getIntValue(); + pp->raw.xtranssensor.ccSteps = ccSteps->getIntValue(); - int currentRow = method->get_active_row_number(); - if( currentRow>=0 && currentRow < procparams::RAWParams::XTransSensor::numMethods) - pp->raw.xtranssensor.method = procparams::RAWParams::XTransSensor::methodstring[currentRow]; + int currentRow = method->get_active_row_number(); - if (pedited) { - pedited->raw.xtranssensor.method = method->get_active_row_number() != procparams::RAWParams::XTransSensor::numMethods; - pedited->raw.xtranssensor.ccSteps = ccSteps->getEditedState (); - } + if( currentRow >= 0 && currentRow < procparams::RAWParams::XTransSensor::numMethods) { + pp->raw.xtranssensor.method = procparams::RAWParams::XTransSensor::methodstring[currentRow]; + } + + if (pedited) { + pedited->raw.xtranssensor.method = method->get_active_row_number() != procparams::RAWParams::XTransSensor::numMethods; + pedited->raw.xtranssensor.ccSteps = ccSteps->getEditedState (); + } } void XTransProcess::setBatchMode(bool batchMode) { - method->append_text (M("GENERAL_UNCHANGED")); - method->set_active(procparams::RAWParams::XTransSensor::numMethods); // No name - ToolPanel::setBatchMode (batchMode); - ccSteps->showEditedCB (); + method->append_text (M("GENERAL_UNCHANGED")); + method->set_active(procparams::RAWParams::XTransSensor::numMethods); // No name + ToolPanel::setBatchMode (batchMode); + ccSteps->showEditedCB (); } void XTransProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - ccSteps->setDefault (defParams->raw.xtranssensor.ccSteps); - if (pedited) { - ccSteps->setDefaultEditedState(pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); - }else{ - ccSteps->setDefaultEditedState(Irrelevant ); - } + ccSteps->setDefault (defParams->raw.xtranssensor.ccSteps); + + if (pedited) { + ccSteps->setDefaultEditedState(pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); + } else { + ccSteps->setDefaultEditedState(Irrelevant ); + } } void XTransProcess::adjusterChanged (Adjuster* a, double newval) { - if (listener) { - if (a == ccSteps) - listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); - } + if (listener) { + if (a == ccSteps) { + listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); + } + } } void XTransProcess::methodChanged () { - int curSelection = method->get_active_row_number(); + int curSelection = method->get_active_row_number(); - Glib::ustring methodName=""; - bool ppreq = false; - if( curSelection>=0 && curSelection < procparams::RAWParams::XTransSensor::numMethods) { - methodName = procparams::RAWParams::XTransSensor::methodstring[curSelection]; - if (curSelection == procparams::RAWParams::XTransSensor::mono || oldSelection == procparams::RAWParams::XTransSensor::mono) { - ppreq = true; - } - } - oldSelection = curSelection; + Glib::ustring methodName = ""; + bool ppreq = false; - if (listener) - listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + if( curSelection >= 0 && curSelection < procparams::RAWParams::XTransSensor::numMethods) { + methodName = procparams::RAWParams::XTransSensor::methodstring[curSelection]; + + if (curSelection == procparams::RAWParams::XTransSensor::mono || oldSelection == procparams::RAWParams::XTransSensor::mono) { + ppreq = true; + } + } + + oldSelection = curSelection; + + if (listener) { + listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + } } diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index 4ee468a27..eebec2f85 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -25,9 +25,10 @@ #include "toolpanel.h" -class XTransProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel{ +class XTransProcess : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ - protected: +protected: MyComboBoxText* method; Adjuster* ccSteps; @@ -35,14 +36,14 @@ class XTransProcess : public ToolParamBlock, public AdjusterListener, public Fol int oldSelection; sigc::connection methodconn; - public: +public: XTransProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); void methodChanged (); void adjusterChanged (Adjuster* a, double newval); diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index fa86a4014..7117b78e3 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -26,106 +26,122 @@ using namespace rtengine::procparams; XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, "xtransrawexposure", M("TP_EXPOS_BLACKPOINT_LABEL")) { - PexBlackRed = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_RED"),-2048,2048,0.1,0));//black level - PexBlackRed->setAdjusterListener (this); - if (PexBlackRed->delay < 1000) PexBlackRed->delay = 1000; - PexBlackRed->show(); - PexBlackGreen = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_GREEN"),-2048,2048,0.1,0));//black level - PexBlackGreen->setAdjusterListener (this); - if (PexBlackGreen->delay < 1000) PexBlackGreen->delay = 1000; - PexBlackGreen->show(); - PexBlackBlue = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_BLUE"),-2048,2048,0.1,0));//black level - PexBlackBlue->setAdjusterListener (this); - if (PexBlackBlue->delay < 1000) PexBlackBlue->delay = 1000; - PexBlackBlue->show(); + PexBlackRed = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_RED"), -2048, 2048, 0.1, 0)); //black level + PexBlackRed->setAdjusterListener (this); - pack_start( *PexBlackRed, Gtk::PACK_SHRINK, 0);//black - pack_start( *PexBlackGreen, Gtk::PACK_SHRINK, 0);//black - pack_start( *PexBlackBlue, Gtk::PACK_SHRINK, 0);//black + if (PexBlackRed->delay < 1000) { + PexBlackRed->delay = 1000; + } + + PexBlackRed->show(); + PexBlackGreen = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_GREEN"), -2048, 2048, 0.1, 0)); //black level + PexBlackGreen->setAdjusterListener (this); + + if (PexBlackGreen->delay < 1000) { + PexBlackGreen->delay = 1000; + } + + PexBlackGreen->show(); + PexBlackBlue = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_BLUE"), -2048, 2048, 0.1, 0)); //black level + PexBlackBlue->setAdjusterListener (this); + + if (PexBlackBlue->delay < 1000) { + PexBlackBlue->delay = 1000; + } + + PexBlackBlue->show(); + + pack_start( *PexBlackRed, Gtk::PACK_SHRINK, 0);//black + pack_start( *PexBlackGreen, Gtk::PACK_SHRINK, 0);//black + pack_start( *PexBlackBlue, Gtk::PACK_SHRINK, 0);//black } void XTransRAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { - disableListener (); + disableListener (); - if(pedited ){ - PexBlackRed->setEditedState( pedited->raw.xtranssensor.exBlackRed ? Edited : UnEdited ); - PexBlackGreen->setEditedState( pedited->raw.xtranssensor.exBlackGreen ? Edited : UnEdited ); - PexBlackBlue->setEditedState( pedited->raw.xtranssensor.exBlackBlue ? Edited : UnEdited ); - } + if(pedited ) { + PexBlackRed->setEditedState( pedited->raw.xtranssensor.exBlackRed ? Edited : UnEdited ); + PexBlackGreen->setEditedState( pedited->raw.xtranssensor.exBlackGreen ? Edited : UnEdited ); + PexBlackBlue->setEditedState( pedited->raw.xtranssensor.exBlackBlue ? Edited : UnEdited ); + } - PexBlackRed->setValue (pp->raw.xtranssensor.blackred);//black - PexBlackGreen->setValue (pp->raw.xtranssensor.blackgreen);//black - PexBlackBlue->setValue (pp->raw.xtranssensor.blackblue);//black + PexBlackRed->setValue (pp->raw.xtranssensor.blackred);//black + PexBlackGreen->setValue (pp->raw.xtranssensor.blackgreen);//black + PexBlackBlue->setValue (pp->raw.xtranssensor.blackblue);//black - enableListener (); + enableListener (); } void XTransRAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { - pp->raw.xtranssensor.blackred = PexBlackRed->getValue();// black - pp->raw.xtranssensor.blackgreen = PexBlackGreen->getValue();// black - pp->raw.xtranssensor.blackblue = PexBlackBlue->getValue();// black + pp->raw.xtranssensor.blackred = PexBlackRed->getValue();// black + pp->raw.xtranssensor.blackgreen = PexBlackGreen->getValue();// black + pp->raw.xtranssensor.blackblue = PexBlackBlue->getValue();// black - if (pedited) { - pedited->raw.xtranssensor.exBlackRed = PexBlackRed->getEditedState ();//black - pedited->raw.xtranssensor.exBlackGreen = PexBlackGreen->getEditedState ();//black - pedited->raw.xtranssensor.exBlackBlue = PexBlackBlue->getEditedState ();//black - } + if (pedited) { + pedited->raw.xtranssensor.exBlackRed = PexBlackRed->getEditedState ();//black + pedited->raw.xtranssensor.exBlackGreen = PexBlackGreen->getEditedState ();//black + pedited->raw.xtranssensor.exBlackBlue = PexBlackBlue->getEditedState ();//black + } } void XTransRAWExposure::adjusterChanged (Adjuster* a, double newval) { - if (listener) { - Glib::ustring value = a->getTextValue(); - if (a == PexBlackRed) - listener->panelChanged (EvPreProcessExpBlackRed, value); - else if (a == PexBlackGreen) - listener->panelChanged (EvPreProcessExpBlackGreen, value); - else if (a == PexBlackBlue) - listener->panelChanged (EvPreProcessExpBlackBlue, value); - } + if (listener) { + Glib::ustring value = a->getTextValue(); + + if (a == PexBlackRed) { + listener->panelChanged (EvPreProcessExpBlackRed, value); + } else if (a == PexBlackGreen) { + listener->panelChanged (EvPreProcessExpBlackGreen, value); + } else if (a == PexBlackBlue) { + listener->panelChanged (EvPreProcessExpBlackBlue, value); + } + } } void XTransRAWExposure::setBatchMode(bool batchMode) { - ToolPanel::setBatchMode (batchMode); - PexBlackRed->showEditedCB ();//black - PexBlackGreen->showEditedCB ();//black - PexBlackBlue->showEditedCB ();//black - + ToolPanel::setBatchMode (batchMode); + PexBlackRed->showEditedCB ();//black + PexBlackGreen->showEditedCB ();//black + PexBlackBlue->showEditedCB ();//black + } void XTransRAWExposure::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { - PexBlackRed->setDefault( defParams->raw.xtranssensor.blackred); - PexBlackGreen->setDefault( defParams->raw.xtranssensor.blackgreen); - PexBlackBlue->setDefault( defParams->raw.xtranssensor.blackblue); + PexBlackRed->setDefault( defParams->raw.xtranssensor.blackred); + PexBlackGreen->setDefault( defParams->raw.xtranssensor.blackgreen); + PexBlackBlue->setDefault( defParams->raw.xtranssensor.blackblue); - if (pedited) { - PexBlackRed->setDefaultEditedState( pedited->raw.xtranssensor.exBlackRed ? Edited : UnEdited); - PexBlackGreen->setDefaultEditedState( pedited->raw.xtranssensor.exBlackGreen ? Edited : UnEdited); - PexBlackBlue->setDefaultEditedState( pedited->raw.xtranssensor.exBlackBlue ? Edited : UnEdited); - - } else { - PexBlackRed->setDefaultEditedState( Irrelevant ); - PexBlackGreen->setDefaultEditedState( Irrelevant ); - PexBlackBlue->setDefaultEditedState( Irrelevant ); - - } + if (pedited) { + PexBlackRed->setDefaultEditedState( pedited->raw.xtranssensor.exBlackRed ? Edited : UnEdited); + PexBlackGreen->setDefaultEditedState( pedited->raw.xtranssensor.exBlackGreen ? Edited : UnEdited); + PexBlackBlue->setDefaultEditedState( pedited->raw.xtranssensor.exBlackBlue ? Edited : UnEdited); + + } else { + PexBlackRed->setDefaultEditedState( Irrelevant ); + PexBlackGreen->setDefaultEditedState( Irrelevant ); + PexBlackBlue->setDefaultEditedState( Irrelevant ); + + } } -void XTransRAWExposure::setAdjusterBehavior (bool pexblackadd) { +void XTransRAWExposure::setAdjusterBehavior (bool pexblackadd) +{ - PexBlackRed->setAddMode(pexblackadd); - PexBlackGreen->setAddMode(pexblackadd); - PexBlackBlue->setAddMode(pexblackadd); + PexBlackRed->setAddMode(pexblackadd); + PexBlackGreen->setAddMode(pexblackadd); + PexBlackBlue->setAddMode(pexblackadd); } -void XTransRAWExposure::trimValues (rtengine::procparams::ProcParams* pp) { +void XTransRAWExposure::trimValues (rtengine::procparams::ProcParams* pp) +{ - PexBlackRed->trimValue(pp->raw.xtranssensor.blackred); - PexBlackGreen->trimValue(pp->raw.xtranssensor.blackgreen); - PexBlackBlue->trimValue(pp->raw.xtranssensor.blackblue); + PexBlackRed->trimValue(pp->raw.xtranssensor.blackred); + PexBlackGreen->trimValue(pp->raw.xtranssensor.blackgreen); + PexBlackBlue->trimValue(pp->raw.xtranssensor.blackblue); } diff --git a/rtgui/xtransrawexposure.h b/rtgui/xtransrawexposure.h index c4708768b..1a92146d3 100644 --- a/rtgui/xtransrawexposure.h +++ b/rtgui/xtransrawexposure.h @@ -24,26 +24,27 @@ #include "toolpanel.h" #include "../rtengine/rawimage.h" -class XTransRAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel { +class XTransRAWExposure : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ protected: - Adjuster* PexBlackRed; - Adjuster* PexBlackGreen; - Adjuster* PexBlackBlue; + Adjuster* PexBlackRed; + Adjuster* PexBlackGreen; + Adjuster* PexBlackBlue; private: -// Gtk::CheckButton* PextwoGreen; +// Gtk::CheckButton* PextwoGreen; public: - XTransRAWExposure (); + XTransRAWExposure (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); - void adjusterChanged (Adjuster* a, double newval); - void setAdjusterBehavior (bool pexblackadd); - void trimValues (rtengine::procparams::ProcParams* pp); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); + void setBatchMode (bool batchMode); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = NULL); + void adjusterChanged (Adjuster* a, double newval); + void setAdjusterBehavior (bool pexblackadd); + void trimValues (rtengine::procparams::ProcParams* pp); }; #endif diff --git a/rtgui/zoompanel.cc b/rtgui/zoompanel.cc index 3596cc588..8f5101282 100644 --- a/rtgui/zoompanel.cc +++ b/rtgui/zoompanel.cc @@ -7,7 +7,7 @@ * 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 @@ -21,20 +21,21 @@ #include "imagearea.h" #include "rtimage.h" -ZoomPanel::ZoomPanel (ImageArea* iarea) : iarea(iarea) { +ZoomPanel::ZoomPanel (ImageArea* iarea) : iarea(iarea) +{ set_border_width (0); Gtk::Image* imageOut = Gtk::manage (new RTImage ("gtk-zoom-out.png")); - imageOut->set_padding(0,0); + imageOut->set_padding(0, 0); Gtk::Image* imageIn = Gtk::manage (new RTImage ("gtk-zoom-in.png")); - imageIn->set_padding(0,0); - Gtk::Image* image11 =Gtk::manage ( new RTImage ("gtk-zoom-100.png")); - image11->set_padding(0,0); + imageIn->set_padding(0, 0); + Gtk::Image* image11 = Gtk::manage ( new RTImage ("gtk-zoom-100.png")); + image11->set_padding(0, 0); Gtk::Image* imageFit = Gtk::manage (new RTImage ("gtk-zoom-fit.png")); - imageFit->set_padding(0,0); + imageFit->set_padding(0, 0); Gtk::Image* imageFitCrop = Gtk::manage (new RTImage ("gtk-zoom-crop.png")); - imageFit->set_padding(0,0); + imageFit->set_padding(0, 0); zoomOut = Gtk::manage (new Gtk::Button()); zoomOut->add (*imageOut); @@ -62,7 +63,7 @@ ZoomPanel::ZoomPanel (ImageArea* iarea) : iarea(iarea) { pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4); Gtk::Image* imageCrop = Gtk::manage (new RTImage ("new-detail-window.png")); - imageCrop->set_padding(0,0); + imageCrop->set_padding(0, 0); newCrop = Gtk::manage (new Gtk::Button()); newCrop->add (*imageCrop); newCrop->set_relief(Gtk::RELIEF_NONE); @@ -87,49 +88,62 @@ ZoomPanel::ZoomPanel (ImageArea* iarea) : iarea(iarea) { zoomLabel->set_text (M("ZOOMPANEL_100")); } -void ZoomPanel::zoomInClicked () { - - if (iarea->mainCropWindow) - iarea->mainCropWindow->zoomIn (); -} - -void ZoomPanel::zoomOutClicked () { - - if (iarea->mainCropWindow) - iarea->mainCropWindow->zoomOut (); -} - -void ZoomPanel::zoomFitClicked () { - - if (iarea->mainCropWindow) - iarea->mainCropWindow->zoomFit (); -} - -void ZoomPanel::zoomFitCropClicked () { - - if (iarea->mainCropWindow) - iarea->mainCropWindow->zoomFitCrop (); -} - -void ZoomPanel::zoom11Clicked () { - - if (iarea->mainCropWindow) - iarea->mainCropWindow->zoom11 (); -} - -void ZoomPanel::refreshZoomLabel () { +void ZoomPanel::zoomInClicked () +{ if (iarea->mainCropWindow) { - int z = (int)(iarea->mainCropWindow->getZoom () * 100); - if (z<100) { - zoomLabel->set_text (Glib::ustring::compose(" %1%%", z)); - } else { - zoomLabel->set_text (Glib::ustring::compose("%1%%", z)); - } + iarea->mainCropWindow->zoomIn (); } } -void ZoomPanel::newCropClicked () { - +void ZoomPanel::zoomOutClicked () +{ + + if (iarea->mainCropWindow) { + iarea->mainCropWindow->zoomOut (); + } +} + +void ZoomPanel::zoomFitClicked () +{ + + if (iarea->mainCropWindow) { + iarea->mainCropWindow->zoomFit (); + } +} + +void ZoomPanel::zoomFitCropClicked () +{ + + if (iarea->mainCropWindow) { + iarea->mainCropWindow->zoomFitCrop (); + } +} + +void ZoomPanel::zoom11Clicked () +{ + + if (iarea->mainCropWindow) { + iarea->mainCropWindow->zoom11 (); + } +} + +void ZoomPanel::refreshZoomLabel () +{ + + if (iarea->mainCropWindow) { + int z = (int)(iarea->mainCropWindow->getZoom () * 100); + + if (z < 100) { + zoomLabel->set_text (Glib::ustring::compose(" %1%%", z)); + } else { + zoomLabel->set_text (Glib::ustring::compose("%1%%", z)); + } + } +} + +void ZoomPanel::newCropClicked () +{ + iarea->addCropWindow (); } diff --git a/rtgui/zoompanel.h b/rtgui/zoompanel.h index cbc46b52b..aa4d9177f 100644 --- a/rtgui/zoompanel.h +++ b/rtgui/zoompanel.h @@ -7,7 +7,7 @@ * 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 @@ -22,9 +22,10 @@ #include class ImageArea; -class ZoomPanel : public Gtk::HBox { +class ZoomPanel : public Gtk::HBox +{ - protected: +protected: Gtk::Button* zoomOut; Gtk::Button* zoomIn; @@ -35,7 +36,7 @@ class ZoomPanel : public Gtk::HBox { Gtk::Label* zoomLabel; ImageArea* iarea; - public: +public: ZoomPanel (ImageArea* iarea);