diff --git a/COMPILE.txt b/COMPILE.txt index c2af3429f..b21695d6e 100644 --- a/COMPILE.txt +++ b/COMPILE.txt @@ -285,6 +285,38 @@ WINDOWS FFTW: - Instructions: http://www.fftw.org/install/windows.html + - Specific instructions more suitable for RawTherapee purposes: + + 1. Download the official fftw64 DLL package from http://www.fftw.org/download.html, + unpack it somewhere you can reach it with MSYS + (Hint: in MSYS console to change directory to 'C:/DirName' execute 'cd /C/DirName') + + 2. in MSYS command line, execute: + dlltool --def libfftw3f-3.def --dllname libfftw3f-3.dll --output-lib libfftw3f-3.a + dlltool --def libfftw3l-3.def --dllname libfftw3l-3.dll --output-lib libfftw3l-3.a + dlltool --def libfftw3-3.def --dllname libfftw3-3.dll --output-lib libfftw3-3.a + + This will generate generate 'libfftw3f-3.a.a' file + + 3. copy files: + libfftw3f-3.dll -> MinGW64/bin + libfftw3l-3.dll -> MinGW64/bin + libfftw3-3.dll -> MinGW64/bin + libfftw3f-3.a.a -> MinGW64/lib + fftw3.f.h -> MinGW64/include + + 4. Create a new textfile MinGW64/lib/pkgconfig/fftw3f.pc with the following contents: + + prefix=/mingw64 + exec_prefix=${prefix} + libdir=${exec_prefix}/lib + includedir=${prefix}/include + + Name: fftw3f + Description: FFTW3 Float + Version: 3.3 + Libs: -L${libdir} -lfftw3f-3 -lm + Cflags: -I${includedir} IMPORTANT: @@ -356,6 +388,24 @@ WINDOWS - You'll find the compiled program in the subdirectory named like the value of CMAKE_BUILD_TYPE ("Release" in this example). + METHOD 3: + Here is a sample batch file to compile RawTherapee in Windows + Adjust directory names to match your setup + + set GTKMM_BASEPATH=C:\gtkmm64 + set GTKMM64_BASEPATH=C:\gtkmm64 + set MINGW_BASEPATH=C:\MinGW64 + set PATH=%PATH%;C:\gtkmm64\bin;C:\MinGW64\bin;C:\CMake\bin;C:\DevTools\XMPToolkit\bin + set PKG_CONFIG_PATH=C:\MinGW64\lib\pkgconfig;c:\gtkmm64\lib\pkgconfig + + set RT_SOURCECODE_PATH=C:\Users\YOURNAME\workspace\rawtherapee_default + set RT_BUILD_PATH=C:\Users\YOURNAME\rt_builds\rt_default_release + cd %RT_BUILD_PATH% + + cmake -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" -DPROC_TARGET_NUMBER:STRING=2 -C%RT_SOURCECODE_PATH%\Win32CMakeOptions-Sample.txt %RT_SOURCECODE_PATH% + mingw32-make -j12 install + pause + LINUX ----- diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 2adfcaf3a..e00a107d0 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -918,14 +918,15 @@ TP_COLORAPP_CONTRAST_Q;Contraste (Q) TP_COLORAPP_CONTRAST_Q_TOOLTIP;Contraste dans CIECAM02 pour le curseur (Q); est différent du contraste Lab et RVB TP_COLORAPP_CONTRAST_TOOLTIP;Contraste dans CIECAM02 pour le curseur (J); est différent du contraste Lab et RVB TP_COLORAPP_CURVEEDITOR1;Courbe tonale 1 -TP_COLORAPP_CURVEEDITOR1_TOOLTIP;Histogramme affiche L (lab) avant CIECAM.\n On peut voir le résultat dans la fenêtre histogramme.\n Histogramme de J/Q avant/après si la cas à cocher "Données CIECAM" est activée.\n (J,Q) ne sont pas affichés dans le panneau histogramme +TP_COLORAPP_CURVEEDITOR1_TOOLTIP;Histogramme affiche L (lab) avant CIECAM02.\nOn peut voir le résultat dans la fenêtre histogramme.\n Histogramme de J/Q avant/après si la cas à cocher "Données CIECAM" est activée.\n (J,Q) ne sont pas affichés dans le panneau histogramme TP_COLORAPP_CURVEEDITOR2;Courbe tonale 2 TP_COLORAPP_CURVEEDITOR2_TOOLTIP;usage similaire aux courbes tonales exposition TP_COLORAPP_CURVEEDITOR3;Courbes chroma TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Vous pouvez choisir entre chroma -saturation- niveau couleurs.\n Histogramme affiche la chromaticité Lab avant CIECAM.\n On peut voir le résultat final dans la fenêtre histogramme.\n Histogramme de C,s,M avant/après si la cas à cocher "Données CIECAM" est activée.\n (C,s,M) ne sont pas affichés dans le panneau histogramme TP_COLORAPP_DATACIE;Histogrammes post CIECAM -TP_COLORAPP_DATACIE_TOOLTIP;Quand activé, les histogrammes de fond des courbes CIECAM montrent des valeurs/amplitudes approximatives de J/Q, ou de C:s/M après les ajustements CIECAM.\nCette sélection n'a pas d'incidence sur l'histogramme général.\n\nQuand désactivé, les histogrammes de fond des courbes CIECAM affichent les valeurs Lab avant les ajustements CIECAM -TP_COLORAPP_DEGREE_TOOLTIP;Niveau d'adaptation chromatique CIE CAT 2002\nSi vous sélectionnez " Automatic ", RT essaiera de trouver la meilleure valeur +TP_COLORAPP_DATACIE_TOOLTIP;Quand activé, les histogrammes de fond des courbes CIECAM02 montrent des valeurs/amplitudes approximatives de J/Q, ou de C:s/M après les ajustements CIECAM.\nCette sélection n'a pas d'incidence sur l'histogramme général.\n\nQuand désactivé, les histogrammes de fond des courbes CIECAM affichent les valeurs Lab avant les ajustements CIECAM +TP_COLORAPP_DEGREE_TOOLTIP;Niveau d'adaptation chromatique CIE CAT 2002 +TP_COLORAPP_DEGREE_AUTO_TOOLTIP;Si la case est cochée (recommandé), RT calcule une valeur optimale, qui est utilisé par CAT02, mais aussi pour l'ensemble de CIECAM02.\nVous pouvez décocher la case et changer la valeur du curseur; (les valeurs supérieures à 65 sont recommandées) TP_COLORAPP_EQUAL;Préservé TP_COLORAPP_GAMUT;Contrôle du gamut (Lab) TP_COLORAPP_GAMUT_TOOLTIP;Permet le controle du gamut en mode Lab diff --git a/rtdata/languages/default b/rtdata/languages/default index 0f04c4c9f..1a12e987e 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -925,7 +925,8 @@ TP_COLORAPP_CURVEEDITOR3;Color curve TP_COLORAPP_CURVEEDITOR3_TOOLTIP;Adjust either chroma, saturation or colorfulness.\n\nShows the histogram of chromaticity (Lab) before CIECAM02.\nIf the "Show CIECAM02 output histograms in curves" checkbox is enabled, shows the histogram of C, s or M after CIECAM02.\n\nC, s and M are not shown in the main histogram panel.\nFor final output refer to the main histogram panel TP_COLORAPP_DATACIE;Show CIECAM02 output histograms in curves TP_COLORAPP_DATACIE_TOOLTIP;When enabled, histograms in CIECAM02 curves show approximate values/ranges for J or Q, and C, s or M after the CIECAM02 adjustments.\nThis selection does not impact the main histogram panel.\n\nWhen disabled, histograms in CIECAM02 curves show Lab values before CIECAM02 adjustments -TP_COLORAPP_DEGREE_TOOLTIP;Amount of CIE Chromatic Adaptation Transform 2002\nIf you check the "Automatic" box (to the right), RT will try to find the best value +TP_COLORAPP_DEGREE_TOOLTIP;Amount of CIE Chromatic Adaptation Transform 2002 +TP_COLORAPP_DEGREE_AUTO_TOOLTIP;If the check-box is checked (recommended), RT calculates an optimum value, which is then used by CAT02, and also for the entire CIECAM02.\nTo set the value manually, uncheck the check-box first (values above 65 are recommended) TP_COLORAPP_EQUAL;Equal TP_COLORAPP_GAMUT;Gamut control (Lab) TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in Lab mode diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index ee7817d23..dc922b5ff 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -59,87 +59,87 @@ #define epsilon 0.001f/(TS*TS) //tolerance namespace rtengine { - + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* - Structure of the algorithm: - - 1. Compute an initial denoise of the image via undecimated wavelet transform + 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 + 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. - + */ - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - - + + + + + void ImProcFunctions::RGB_denoise(Imagefloat * src, Imagefloat * dst, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe) - { - + { + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + /*if (plistener) { plistener->setProgressStr ("Denoise..."); plistener->setProgress (0.0); }*/ - + volatile double progress = 0.0; - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + const short int imheight=src->height, imwidth=src->width; - + if (dnparams.luma==0 && dnparams.chroma==0) { //nothing to do; copy src to dst memcpy(dst->data,src->data,dst->width*dst->height*3*sizeof(float)); return; } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // gamma transform for input data float gam = dnparams.gamma; float gamthresh = 0.001; float gamslope = exp(log((double)gamthresh)/gam)/gamthresh; - + LUTf gamcurve(65536,0); - + for (int i=0; i<65536; i++) { gamcurve[i] = (Color::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) * 32768.0f; } - + // inverse gamma transform for output data float igam = 1/gam; float igamthresh = gamthresh*gamslope; float igamslope = 1/gamslope; - + LUTf igamcurve(65536,0); - + for (int i=0; i<65536; i++) { igamcurve[i] = (Color::gamma((float)i/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - + + //srand((unsigned)time(0));//test with random data - + const float gain = pow (2.0, dnparams.expcomp); - + float noisevar_Ldetail = SQR((SQR(100-dnparams.Ldetail) + 50*(100-dnparams.Ldetail)) * TS * 0.5f); - - + + array2D tilemask_in(TS,TS); array2D tilemask_out(TS,TS); - + const int border = MAX(2,TS/16); - + #ifdef _OPENMP #pragma omp parallel for #endif @@ -150,25 +150,25 @@ namespace rtengine { for (int j=0; jTS/2 ? j-TS+1 : j)); tilemask_in[i][j] = (vmask * (j1data[n] = 0; - + const int tilesize = 1024; const int overlap = 128; - + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - + if (imwidth 0) numthreads = MIN(numthreads,options.RgbDenoiseThreadLimit); +#pragma omp parallel num_threads(numthreads) +#endif + { + //DCT block data storage + float * Lblox; + float * fLblox; +#ifdef _OPENMP +#pragma omp critical +#endif + { + Lblox = fftwf_alloc_real(max_numblox_W*TS*TS); + fLblox = fftwf_alloc_real(max_numblox_W*TS*TS); + } +#ifdef _OPENMP +#pragma omp for schedule(dynamic) collapse(2) +#endif for (int tiletop=0; tiletop Lin(width,height,ARRAY2D_CLEAR_DATA); + array2D Lin(width,height); //wavelet denoised image LabImage * labdn = new LabImage(width,height); //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 - +// + //#ifdef _OPENMP //#pragma omp parallel for //#endif @@ -220,145 +272,142 @@ namespace rtengine { int i1 = i - tiletop; for (int j=tileleft/*, j1=0*/; jr(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->L[i1][j1] = Y; labdn->a[i1][j1] = (X-Y); labdn->b[i1][j1] = (Y-Z); - - Ldetail[i1][j1] = 0; + +// Ldetail[i1][j1] = 0; Lin[i1][j1] = Y; - totwt[i1][j1] = 0; +// totwt[i1][j1] = 0; } - } + } } else {//image is not raw; use Lab parametrization for (int i=tiletop/*, i1=0*/; ir(i,j) ]; float gtmp = Color::igammatab_srgb[ src->g(i,j) ]; float btmp = Color::igammatab_srgb[ src->b(i,j) ]; - + //perhaps use LCH or YCrCb ??? float X = xyz_sRGB[0][0]*rtmp + xyz_sRGB[0][1]*gtmp + xyz_sRGB[0][2]*btmp; float Y = xyz_sRGB[1][0]*rtmp + xyz_sRGB[1][1]*gtmp + xyz_sRGB[1][2]*btmp; float Z = xyz_sRGB[2][0]*rtmp + xyz_sRGB[2][1]*gtmp + xyz_sRGB[2][2]*btmp; - + 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->L[i1][j1] = Y; labdn->a[i1][j1] = (X-Y); labdn->b[i1][j1] = (Y-Z); - - Ldetail[i1][j1] = 0; + +// Ldetail[i1][j1] = 0; Lin[i1][j1] = Y; - totwt[i1][j1] = 0; +// totwt[i1][j1] = 0; } } } - - + + //initial impulse denoise if (dnparams.luma>0.01) { impulse_nr (labdn, MIN(50.0f,dnparams.luma)/20.0f); } - + 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 + //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. - wavelet_decomposition Ldecomp(labdn->data, labdn->W, labdn->H, 5/*maxlevels*/, 0/*subsampling*/ ); - wavelet_decomposition adecomp(labdn->data+datalen, labdn->W, labdn->H, 5, 1 ); - wavelet_decomposition bdecomp(labdn->data+2*datalen, labdn->W, labdn->H, 5, 1 ); - + float noisevarL = SQR((dnparams.luma/125.0f)*(1+ dnparams.luma/25.0f)); + float noisevarab = SQR(dnparams.chroma/10.0f); - + { // enclosing this code in a block frees about 120 MB before allocating 20 MB after this block (measured with D700 NEF) + wavelet_decomposition* Ldecomp; + wavelet_decomposition* adecomp; + wavelet_decomposition* bdecomp; + + Ldecomp = new wavelet_decomposition (labdn->data, labdn->W, labdn->H, 5/*maxlevels*/, 0/*subsampling*/ ); + adecomp = new wavelet_decomposition (labdn->data+datalen, labdn->W, labdn->H, 5, 1 ); + bdecomp = new wavelet_decomposition (labdn->data+2*datalen, labdn->W, labdn->H, 5, 1 ); + //WaveletDenoiseAll_BiShrink(Ldecomp, adecomp, bdecomp, noisevarL, noisevarab); - WaveletDenoiseAll(Ldecomp, adecomp, bdecomp, noisevarL, noisevarab); - - Ldecomp.reconstruct(labdn->data); - adecomp.reconstruct(labdn->data+datalen); - bdecomp.reconstruct(labdn->data+2*datalen); - + WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarab); + + Ldecomp->reconstruct(labdn->data); + delete Ldecomp; + adecomp->reconstruct(labdn->data+datalen); + delete adecomp; + bdecomp->reconstruct(labdn->data+2*datalen); + delete bdecomp; + } + //TODO: at this point wavelet coefficients storage can be freed - + //Issue 1680: Done now + //second impulse denoise if (dnparams.luma>0.01) { impulse_nr (labdn, MIN(50.0f,dnparams.luma)/20.0f); - } + } //PF_correct_RT(dst, dst, defringe.radius, defringe.threshold); - + //wavelet denoised L channel array2D Lwavdn(width,height); float * Lwavdnptr = Lwavdn; memcpy (Lwavdnptr, labdn->data, width*height*sizeof(float)); - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // now do detail recovery using block DCT to detect + // now do detail recovery using block DCT to detect // patterns missed by wavelet denoise // blocks are not the same thing as tiles! - - - // allocate DCT data structures - + + + // 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; + //const int nrtiles = numblox_W*numblox_H; // end of tiling calc - - //DCT block data storage - float * Lblox = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); - float * fLblox = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); - - - //make a plan for FFTW - fftwf_plan plan_forward_blox, plan_backward_blox; - - int nfwd[2]={TS,TS}; - - //for DCT: - const fftw_r2r_kind fwdkind[2] = {FFTW_REDFT10, FFTW_REDFT10}; - const fftw_r2r_kind bwdkind[2] = {FFTW_REDFT01, FFTW_REDFT01}; - - plan_forward_blox = fftwf_plan_many_r2r(2, nfwd, numblox_W, Lblox, NULL, 1, TS*TS, fLblox, NULL, 1, TS*TS, fwdkind, FFTW_ESTIMATE ); - plan_backward_blox = fftwf_plan_many_r2r(2, nfwd, numblox_W, fLblox, NULL, 1, TS*TS, Lblox, NULL, 1, TS*TS, bwdkind, FFTW_ESTIMATE ); - + { + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Main detail recovery algorithm: Block loop - //OpenMP here - //adding omp here leads to artifacts + //OpenMP here + //adding omp here leads to artifacts + AlignedBufferMP buffer(width + TS + 2*blkrad*offset); for (int vblk=0; vblk* pBuf = buffer.acquire(); +// float * buffer = new float [width + TS + 2*blkrad*offset]; + float * datarow = (float*)pBuf->data +blkrad*offset; + //#ifdef _OPENMP //#pragma omp parallel for //#endif //TODO: implement using AlignedBufferMP +// #pragma omp parallel for for (int i=0/*, row=top*/; i=height) { rr = MAX(0,2*height-2-row); - } - + } + for (int j=0; jW; j++) { datarow[j] = (Lin[rr][j]-Lwavdn[rr][j]); } - + for (int j=-blkrad*offset; j<0; j++) { datarow[j] = datarow[MIN(-j,width-1)]; } for (int j=width; j=0 && top+i=0 && left+jL[i][j] = Lwavdn[i][j] + hpdn; - + } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // transform denoised "Lab" to output RGB - + //calculate mask for feathering output tile overlaps float * Vmask = new float [height+1]; float * Hmask = new float [width+1]; - + for (int i=0; i0) Hmask[i] = mask; if (tilerightL[i1][j1]; X = (labdn->a[i1][j1]) + Y; 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); - + float factor = Vmask[i1]*Hmask[j1]/gain; - + dsttmp->r(i,j) += factor*X; dsttmp->g(i,j) += factor*Y; dsttmp->b(i,j) += factor*Z; - + } } } else { #ifdef _OPENMP -#pragma omp parallel for +//#pragma omp parallel for #endif for (int i=tiletop; iL[i1][j1]; X = (labdn->a[i1][j1]) + Y; 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); - + float factor = Vmask[i1]*Hmask[j1]; - + float rtmp = sRGB_xyz[0][0]*X + sRGB_xyz[0][1]*Y + sRGB_xyz[0][2]*Z; float gtmp = sRGB_xyz[1][0]*X + sRGB_xyz[1][1]*Y + sRGB_xyz[1][2]*Z; float btmp = sRGB_xyz[2][0]*X + sRGB_xyz[2][1]*Y + sRGB_xyz[2][2]*Z; - + dsttmp->r(i,j) += factor*rtmp; dsttmp->g(i,j) += factor*gtmp; dsttmp->b(i,j) += factor*btmp; - + } } } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + delete labdn; delete[] Vmask; delete[] Hmask; - + }//end of tile row }//end of tile loop - +#ifdef _OPENMP +#pragma omp critical +#endif +{ + fftwf_free ( Lblox); + fftwf_free ( fLblox); +} + + } //copy denoised image to output memcpy (dst->data, dsttmp->data, 3*dst->width*dst->height*sizeof(float)); - + if (!isRAW) {//restore original image gamma #ifdef _OPENMP #pragma omp parallel for @@ -546,140 +596,146 @@ namespace rtengine { dst->data[i] = Color::gammatab_srgb[ dst->data[i] ]; } } - + delete dsttmp; - + + // 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(); + }//end of main RGB_denoise //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - void ImProcFunctions::RGBtile_denoise (float * fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_Ldetail ) //for DCT - { - float * nbrwt = new float[TS*TS]; //for DCT - - int blkstart = hblproc*TS*TS; - - boxabsblur(fLblox+blkstart, nbrwt, 3, 3, TS, TS);//blur neighbor weights for more robust estimation //for DCT + + + void ImProcFunctions::RGBtile_denoise (float * fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_Ldetail ) //for DCT + { + float * nbrwt = new float[TS*TS]; //for DCT + int blkstart = hblproc*TS*TS; + + boxabsblur(fLblox+blkstart, nbrwt, 3, 3, TS, TS);//blur neighbor weights for more robust estimation //for DCT +#pragma omp parallel for for (int n=0; n=0; lvl--) {//for levels less than max, use level diff to make edge mask //for (int lvl=0; lvl edge(Wlvl_L,Hlvl_L); - AlignedBuffer* buffer = new AlignedBuffer (MAX(Wlvl_L,Hlvl_L)); - + AlignedBufferMP* buffer = new AlignedBufferMP (MAX(Wlvl_L,Hlvl_L)); + //printf("\n level=%d \n",lvl); - + for (int dir=1; dir<4; dir++) { float mad_L = madL[lvl][dir-1]; float mad_a = noisevar_ab*mada[lvl][dir-1]; @@ -730,136 +786,138 @@ namespace rtengine { //float mad_Lpar = madL[lvl+1][dir-1]; //float mad_apar = mada[lvl+1][dir-1]; //float mad_bpar = mada[lvl+1][dir-1]; - + //float skip_ab_ratio = WaveletCoeffs_a.level_stride(lvl+1)/skip_ab; float skip_L_ratio = WaveletCoeffs_L.level_stride(lvl+1)/skip_L; - + if (noisevar_ab>0.01) { - + //printf(" dir=%d mad_L=%f mad_a=%f mad_b=%f \n",dir,sqrt(mad_L),sqrt(mad_a),sqrt(mad_b)); - -//OpenMP here + +//OpenMP here for (int i=0; i2 ? 1 : (coeff_a<1 ? 0 : (coeff_a - 1))); //WavCoeffs_b[dir][coeffloc_ab] *= edgefactor*(coeff_b>2 ? 1 : (coeff_b<1 ? 0 : (coeff_b - 1))); - + //float satfactor_a = mad_a/(mad_a+0.5*SQR(WavCoeffs_a[0][coeffloc_ab])); //float satfactor_b = mad_b/(mad_b+0.5*SQR(WavCoeffs_b[0][coeffloc_ab])); - + WavCoeffs_a[dir][coeffloc_ab] *= SQR(1-exp(-(mag_a/mad_a)-(mag_L/(9*mad_L)))/*satfactor_a*/); WavCoeffs_b[dir][coeffloc_ab] *= SQR(1-exp(-(mag_b/mad_b)-(mag_L/(9*mad_L)))/*satfactor_b*/); - + } }//now chrominance coefficients are denoised } - + if (noisevar_L>0.01) { mad_L *= noisevar_L*5/(lvl+1); -//OpenMP here - for (int i=0; i (edge, edge, buffer, Wlvl_L, Hlvl_L, 1<<(lvl+1), false /*multiThread*/); //gaussVertical (edge, edge, buffer, Wlvl_L, Hlvl_L, 1<<(lvl+1), false); - + boxblur(sfave, sfave, lvl+2, lvl+2, Wlvl_L, Hlvl_L);//increase smoothness by locally averaging shrinkage -//OpenMP here - for (int i=0; i0.01) { //OpenMP here #ifdef _OPENMP #pragma omp parallel for -#endif +#endif for (int i=0; i2*thresh_a ? 1 : (coeff_a2*thresh_b ? 1 : (coeff_b0.01) { -//OpenMP here +//OpenMP here #ifdef _OPENMP #pragma omp parallel for #endif @@ -944,28 +1002,28 @@ namespace rtengine { float mag = SQR(WavCoeffs_L[dir][i]); float shrinkfactor = mag/(mag+mad_L*exp(-mag/(9*mad_L))+eps); - + //WavCoeffs_L[dir][i] *= shrinkfactor; sfave[i] = shrinkfactor; } -//OpenMP here +//OpenMP here boxblur(sfave, sfave, level+2, level+2, W_L, H_L);//increase smoothness by locally averaging shrinkage #ifdef _OPENMP #pragma omp parallel for #endif for (int i=0; iW, height=src->H; //temporary array to store chromaticity int (*fringe); fringe = (int (*)) calloc ((height)*(width), sizeof *fringe); - - LabImage * tmp1; + + LabImage * tmp1; tmp1 = new LabImage(width, height); - + #ifdef _OPENMP #pragma omp parallel #endif @@ -63,14 +63,14 @@ void ImProcFunctions::PF_correct_RT(LabImage * src, LabImage * dst, double radiu gaussVertical (tmp1->a, tmp1->a, buffer, src->W, src->H, radius); gaussVertical (tmp1->b, tmp1->b, buffer, src->W, src->H, radius); - gaussHorizontal (src->L, tmp1->L, buffer, src->W, src->H, radius); - gaussVertical (tmp1->L, tmp1->L, buffer, src->W, src->H, radius); +// gaussHorizontal (src->L, tmp1->L, buffer, src->W, src->H, radius); +// gaussVertical (tmp1->L, tmp1->L, buffer, src->W, src->H, radius); } - -//#ifdef _OPENMP -//#pragma omp parallel for -//#endif - float chromave=0; + +float chromave=0; +#ifdef _OPENMP +#pragma omp parallel for reduction(+:chromave) +#endif for(int i = 0; i < height; i++ ) { for(int j = 0; j < width; j++) { float chroma = SQR(src->a[i][j]-tmp1->a[i][j])+SQR(src->b[i][j]-tmp1->b[i][j]); @@ -78,12 +78,18 @@ void ImProcFunctions::PF_correct_RT(LabImage * src, LabImage * dst, double radiu fringe[i*width+j]=chroma; } } - chromave /= (height*width); -// printf("Chro %f \n",chromave); + chromave /= (height*width); + float threshfactor = (thresh*chromave)/33.f; // Calculated once to eliminate mult inside the next loop +// printf("Chro %f \n",chromave); + +// Issue 1674: +// often, CA isn't evenly distributed, e.g. a lot in contrasty regions and none in the sky. +// so it's better to schedule dynamic and let every thread only process 16 rows, to avoid running big threads out of work +// Measured it and in fact gives better performance than without schedule(dynamic,16). Of course, there could be a better +// choice for the chunk_size than 16 #ifdef _OPENMP -#pragma omp parallel for +#pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++ ) { for(int j = 0; j < width; j++) { tmp1->a[i][j] = src->a[i][j]; @@ -91,7 +97,7 @@ void ImProcFunctions::PF_correct_RT(LabImage * src, LabImage * dst, double radiu //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 (33.f*fringe[i*width+j]>thresh*chromave) { + if (fringe[i*width+j]>threshfactor) { float atot=0.f; float btot=0.f; float norm=0.f; @@ -113,7 +119,7 @@ void ImProcFunctions::PF_correct_RT(LabImage * src, LabImage * dst, double radiu #ifdef _OPENMP #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]; @@ -121,28 +127,30 @@ void ImProcFunctions::PF_correct_RT(LabImage * src, LabImage * dst, double radiu dst->b[i][j] = tmp1->b[i][j]; } } - + delete tmp1; free(fringe); } -void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double radius, int thresh) { +void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double radius, int thresh) { int halfwin = ceil(2*radius)+1; - + #include "rt_math.h" - + // local variables int width=src->W, height=src->H; float piid=3.14159265f/180.f; //temporary array to store chromaticity int (*fringe); fringe = (int (*)) calloc ((height)*(width), sizeof *fringe); - + float** sraa; sraa = new float*[height]; for (int i=0; iC_p[i][j]*cos(piid*src->h_p[i][j]); @@ -156,8 +164,10 @@ void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double ra srbb = new float*[height]; for (int i=0; iC_p[i][j]*sin(piid*src->h_p[i][j]); @@ -172,7 +182,7 @@ void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double ra for (int i=0; i (tmbb, tmbb, buffer, src->W, src->H, radius); // gaussHorizontal (src->sh_p, tmL, buffer, src->W, src->H, radius); // gaussVertical (tmL, tmL, buffer, src->W, src->H, radius); - + } - -//#ifdef _OPENMP -//#pragma omp parallel for -//#endif - float chromave=0; + +float chromave=0; +#ifdef _OPENMP +#pragma omp parallel for reduction(+:chromave) +#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]); @@ -198,22 +208,27 @@ void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double ra fringe[i*width+j]=chroma; } } - chromave /= (height*width); + chromave /= (height*width); + float threshfactor = (thresh*chromave)/33.f; // Calculated once to eliminate mult inside the next loop // printf("Chromave CAM %f \n",chromave); +// Issue 1674: +// often, CA isn't evenly distributed, e.g. a lot in contrasty regions and none in the sky. +// so it's better to schedule dynamic and let every thread only process 16 rows, to avoid running big threads out of work +// Measured it and in fact gives better performance than without schedule(dynamic,16). Of course, there could be a better +// choice for the chunk_size than 16 #ifdef _OPENMP -#pragma omp parallel for +#pragma omp parallel for schedule(dynamic,16) #endif - for(int i = 0; i < height; i++ ) { for(int j = 0; j < width; j++) { tmaa[i][j] = sraa[i][j]; tmbb[i][j] = srbb[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 (33.f*fringe[i*width+j]>thresh*chromave) { + if (fringe[i*width+j]>threshfactor) { float atot=0.f; float btot=0.f; float norm=0.f; @@ -235,7 +250,7 @@ void ImProcFunctions::PF_correct_RTcam(CieImage * src, CieImage * dst, double ra #ifdef _OPENMP #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]; diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index 5c4f3f7a8..8f022b4f7 100644 --- a/rtengine/amaze_demosaic_RT.cc +++ b/rtengine/amaze_demosaic_RT.cc @@ -30,17 +30,17 @@ using namespace rtengine; -void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { +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) int width=winw, height=winh; - - + + const float clip_pt = 1/initialGain; #define TS 512 // Tile size; the image is processed in square tiles to lower memory requirements and facilitate multi-threading - + // local variables @@ -69,7 +69,15 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { static const float gquinc[4] = {0.169917f, 0.108947f, 0.069855f, 0.0287182f}; volatile double progress = 0.0; - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +// Issue 1676 +// Moved from inside the parallel section + if (plistener) { + plistener->setProgressStr ("AMaZE Demosaicing..."); + plistener->setProgress (0.0); + } + #pragma omp parallel { //position of top/left corner of the tile @@ -159,7 +167,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { delm = (float (*)) (buffer + 18*sizeof(float)*TS*TS); rbint = (float (*)) (buffer + 19*sizeof(float)*TS*TS); Dgrbh2 = (float (*)) (buffer + 20*sizeof(float)*TS*TS); - Dgrbv2 = (float (*)) (buffer + 21*sizeof(float)*TS*TS); + Dgrbv2 = (float (*)) (buffer + 21*sizeof(float)*TS*TS); dgintv = (float (*)) (buffer + 22*sizeof(float)*TS*TS); dginth = (float (*)) (buffer + 23*sizeof(float)*TS*TS); Dgrbp1 = (float (*)) (buffer + 24*sizeof(float)*TS*TS); @@ -194,10 +202,6 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - if (plistener) { - plistener->setProgressStr ("AMaZE Demosaicing..."); - plistener->setProgress (0.0); - } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -211,8 +215,11 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { // 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 -#pragma omp for schedule(dynamic) nowait + //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) { //location of tile bottom edge @@ -224,7 +231,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { //tile height (=TS except for bottom edge of image) int cc1 = right - left; - //tile vars + //tile vars //counters for pixel location in the image int row, col; //min and max row/column in the tile @@ -286,13 +293,13 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { float rbvarp, rbvarm; - + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // rgb from input CFA data - // rgb values should be floating point number between 0 and 1 - // after white balance multipliers are applied + // 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 @@ -300,7 +307,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { if (left(winy+height)) {rrmax=winy+height-top;} else {rrmax=rr1;} if (right>(winx+width)) {ccmax=winx+width-left;} else {ccmax=cc1;} - + for (rr=rrmin; rr < rrmax; rr++) for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { col = cc+left; @@ -315,7 +322,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //fill borders if (rrmin>0) { - for (rr=0; rr<16; rr++) + for (rr=0; rr<16; rr++) for (cc=ccmin; cc0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr<16; rr++) + for (rr=0; rr<16; rr++) for (cc=0; cc<16; cc++) { c=FC(rr,cc); rgb[(rr)*TS+cc][c] = (rawData[winy+32-rr][winx+32-cc])/65535.0f; @@ -360,7 +367,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { } } if (rrmax0 && ccmax0) { - for (rr=0; rr<16; rr++) + for (rr=0; rr<16; rr++) for (cc=0; cc<16; cc++) { c=FC(rr,cc); rgb[(rrmax+rr)*TS+cc][c] = (rawData[(winy+height-rr-2)][(winx+32-cc)])/65535.0f; @@ -392,31 +399,31 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { for (rr=1; rr < rr1-1; rr++) for (cc=1, indx=(rr)*TS+cc; cc < cc1-1; cc++, indx++) { - + delh[indx] = fabs(cfa[indx+1]-cfa[indx-1]); delv[indx] = fabs(cfa[indx+v1]-cfa[indx-v1]); delhsq[indx] = SQR(delh[indx]); delvsq[indx] = SQR(delv[indx]); delp[indx] = fabs(cfa[indx+p1]-cfa[indx-p1]); delm[indx] = fabs(cfa[indx+m1]-cfa[indx-m1]); - + } for (rr=2; rr < rr1-2; rr++) for (cc=2,indx=(rr)*TS+cc; cc < cc1-2; cc++, indx++) { - + dirwts[indx][0] = eps+delv[indx+v1]+delv[indx-v1]+delv[indx];//+fabs(cfa[indx+v2]-cfa[indx-v2]); //vert directional averaging weights dirwts[indx][1] = eps+delh[indx+1]+delh[indx-1]+delh[indx];//+fabs(cfa[indx+2]-cfa[indx-2]); //horizontal weights - + if (FC(rr,cc)&1) { //for later use in diagonal interpolation //Dgrbp1[indx]=2*cfa[indx]-(cfa[indx-p1]+cfa[indx+p1]); //Dgrbm1[indx]=2*cfa[indx]-(cfa[indx-m1]+cfa[indx+m1]); Dgrbpsq1[indx]=(SQR(cfa[indx]-cfa[indx-p1])+SQR(cfa[indx]-cfa[indx+p1])); Dgrbmsq1[indx]=(SQR(cfa[indx]-cfa[indx-m1])+SQR(cfa[indx]-cfa[indx+m1])); - } + } } //t2_init += clock()-t1_init; @@ -452,7 +459,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { if (fabs(1.0f-crd) 0.8*clip_pt || Gintvha > 0.8*clip_pt || Ginthha > 0.8*clip_pt) { //use HA if highlights are (nearly) clipped guar=guha; gdar=gdha; glar=glha; grar=grha; @@ -476,7 +483,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { //differences of interpolations in opposite directions dgintv[indx]=min(SQR(guha-gdha),SQR(guar-gdar)); dginth[indx]=min(SQR(glha-grha),SQR(glar-grar)); - + } //t2_vcdhcd += clock() - t1_vcdhcd; @@ -493,7 +500,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { //choose the smallest variance; this yields a smoother interpolation if (hcdaltvar 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 @@ -548,7 +555,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { //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]); } @@ -556,20 +563,20 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { for (cc=6+(FC(rr,2)&1),indx=rr*TS+cc; cc0 && fabs(0.5-diffwt)0.5) Dgrb[indx][0]=vcd[indx]; @@ -722,7 +729,7 @@ void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) { for (cc=8+(FC(rr,2)&1),indx=rr*TS+cc; ccverbose) printf("Source double d=%f aw=%f fl=%f wh=%f\n",d,aw,fl,wh); +#endif +} +void ColorTemp::initcam1float(float gamu, float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, + 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; + 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 ); + pfl = pow_F( fl, 0.25f ); +#ifdef _DEBUG + if (settings->verbose) printf("Source float d=%f aw=%f fl=%f wh=%f\n",d,aw,fl,wh); +#endif + +} + +void ColorTemp::initcam2(double gamu, double yb, double f, double la, double xw, double yw, double zw, double &n, double &d, double &nbb, double &ncb, + double &cz, double &aw, double &fl) +{ + n = yb / yw; + d = d_factor( f, la ); + 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 ); +#ifdef _DEBUG + if (settings->verbose) printf("Viewing double d=%f aw=%f fl=%f n=%f\n",d,aw,fl,n); +#endif +} + +void ColorTemp::initcam2float(float gamu, float yb, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, + float &cz, float &aw, float &fl) +{ + n = yb / yw; + d = d_factorfloat( f, la ); + 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 ); +#ifdef _DEBUG + if (settings->verbose) printf("Viewing float d=%f aw=%f fl=%f n=%f\n",d,aw,fl,n); +#endif + +} + + + +void ColorTemp::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) +{ + double r, g, b; + double rw, gw, bw; + double rc, gc, bc; + double rp, gp, bp; + double rpa, gpa, bpa; + double a, ca, cb; + double e, t; + double myh, myj, myc, myq, mym, mys; + 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)); gc = g * (((yw * d) / gw) + (1.0 - d)); bc = b * (((yw * d) / bw) + (1.0 - d)); @@ -1997,38 +2043,23 @@ void ColorTemp::xyz2jchqms_ciecam02( double &J, double &C, double &h, double &Q, } + void ColorTemp::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, bool doneinit, int gamu) -{ + float yb, float la, float f, float c, float nc, float pilotd, int gamu, float n, float nbb, float ncb, float pfl, float cz, float d) + + { float r, g, b; float rw, gw, bw; float rc, gc, bc; float rp, gp, bp; float rpa, gpa, bpa; float a, ca, cb; - float d; - float n, nbb, ncb; float e, t; - float cz; float myh, myj, myc, myq, mym, mys; - float pfl; gamu=1; xyz_to_cat02float( r, g, b, x, y, z, gamu ); xyz_to_cat02float( rw, gw, bw, xw, yw, zw, gamu ); - - if(doneinit){//if one day, we have a pipette... - n = yb / yw; - 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 ); - pfl = pow_F( fl, 0.25f ); - doneinit=false; - } - rc = r * (((yw * d) / rw) + (1.0 - d)); gc = g * (((yw * d) / gw) + (1.0 - d)); bc = b * (((yw * d) / bw) + (1.0 - d)); @@ -2089,33 +2120,19 @@ void ColorTemp::xyz2jchqms_ciecam02float( float &J, float &C, float &h, float &Q } - void ColorTemp::jch2xyz_ciecam02( double &x, double &y, double &z, double J, double C, double h, double xw, double yw, double zw, double yb, double la, - double f, double c, double nc , bool doneinit2, int gamu) + double f, double c, double nc , int gamu, double n, double nbb, double ncb, double fl, double cz, double d, double aw ) { double r, g, b; double rc, gc, bc; double rp, gp, bp; double rpa, gpa, bpa; double rw, gw, bw; - double fl, d; - double n, nbb, ncb; double a, ca, cb; - double aw; double e, t; - double cz; gamu=1; ColorTemp::xyz_to_cat02( rw, gw, bw, xw, yw, zw, gamu ); - if(doneinit2){ - n = yb / yw; - d = d_factor( f, la ); - 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 ); - doneinit2=false; - } 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; t = pow( C / (sqrt( J / 100) * pow( 1.64 - pow( 0.29, n ), 0.73 )), 10.0 / 9.0 ); @@ -2139,30 +2156,18 @@ void ColorTemp::jch2xyz_ciecam02( double &x, double &y, double &z, double J, dou void ColorTemp::jch2xyz_ciecam02float( float &x, float &y, float &z, float J, float C, float h, float xw, float yw, float zw, float yb, float la, - float f, float c, float nc , bool doneinit2, int gamu) + float f, float c, float nc , int gamu, float n, float nbb, float ncb, float fl, float cz, float d, float aw) + { float r, g, b; float rc, gc, bc; float rp, gp, bp; float rpa, gpa, bpa; float rw, gw, bw; - float fl, d; - float n, nbb, ncb; float a, ca, cb; - float aw; float e, t; - float cz; gamu=1; ColorTemp::xyz_to_cat02float( rw, gw, bw, xw, yw, zw, gamu ); - if(doneinit2){ - n = yb / yw; - d = d_factorfloat( f, la ); - 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 ); - doneinit2=false; - } e = ((12500.0f / 13.0f) * nc * ncb) * (cos( ((h * M_PI) / 180.0f) + 2.0f ) + 3.8f); a = pow_F( J / 100.0f, 1.0f / (c * cz) ) * aw; t = pow_F( C / (sqrt( J / 100.f) * pow_F( 1.64f - pow_F( 0.29f, n ), 0.73f )), 10.0f / 9.0f ); diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index e82acc412..cbe8204ab 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -298,30 +298,42 @@ class ColorTemp { double J, double C, double h, double xw, double yw, double zw, double yb, double la, - double f, double c, double nc, bool doneinit2, int gamu ); + double f, double c, double nc, int gamu, double n, double nbb, double ncb, double fl, double cz, double d, double aw); static void jch2xyz_ciecam02float( float &x, float &y, float &z, float J, float C, float h, float xw, float yw, float zw, float yb, float la, - float f, float c, float nc, bool doneinit2, int gamu ); + float f, float c, float nc,int gamu,float n, float nbb, float ncb, float fl, float cz, float d, float aw ); /** * Forward transform from XYZ to CIECAM02 JCh. */ + static void initcam1(double gamu, double yb, double pilotd, double f, double la, double xw, double yw, double zw, double &n, double &d, double &nbb, double &ncb, + double &cz, double &aw, double &wh, double &pfl, double &fl, double &c); + + static void initcam2(double gamu, double yb, double f, double la, double xw, double yw, double zw, double &n, double &d, double &nbb, double &ncb, + double &cz, double &aw, double &fl); + + static void initcam1float(float gamu, float yb, float pilotd, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, + float &cz, float &aw, float &wh, float &pfl, float &fl, float &c); + + static void initcam2float(float gamu, float yb, float f, float la, float xw, float yw, float zw, float &n, float &d, float &nbb, float &ncb, + 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 x, double y, double z, double xw, double yw, double zw, double yb, double la, - double f, double c, double nc, double pilotd, bool doneinit1, int gamu ); + 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 x, float y, float z, float xw, float yw, float zw, float yb, float la, - float f, float c, float nc, float pilotd, bool doneinit1, int gamu ); + float f, float c, float nc, float pilotd, int gamu, float n, float nbb, float ncb, float pfl, float cz, float d ); }; diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index e894eecbe..1af138719 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -202,9 +202,12 @@ void Crop::update (int todo) { } int begh = 0, endh = labnCrop->H; bool execsharp=false; + float d; + double dd; if(skip==1) execsharp=true; - if(settings->ciecamfloat) parent->ipf.ciecam_02float (cieCrop,begh, endh, 1,labnCrop, ¶ms,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp); - else parent->ipf.ciecam_02 (cieCrop,begh, endh, 1,labnCrop, ¶ms,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp); + if(settings->ciecamfloat) {parent->ipf.ciecam_02float (cieCrop,begh, endh, 1,labnCrop, ¶ms,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, d); + } + else {parent->ipf.ciecam_02 (cieCrop,begh, endh, 1,labnCrop, ¶ms,parent->customColCurve1,parent->customColCurve2,parent->customColCurve3, dummy, dummy, 5, 1,(float**)cbuffer, execsharp, dd);} } // switch back to rgb parent->ipf.lab2monitorRgb (labnCrop, cropImg); diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index f61c61b9f..344226f72 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -55,6 +55,7 @@ class Crop : public DetailedCrop { bool cropAllocated; DetailedCropListener* cropImageListener; + Glib::Mutex cropMutex; ImProcCoordinator* parent; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index a958806df..1c8321a19 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -70,7 +70,7 @@ ImProcCoordinator::ImProcCoordinator () bcurvehist(256), bcurvehistCropped(256), bbeforehist(256), pW(-1), pH(-1), - plistener(NULL), imageListener(NULL), aeListener(NULL), hListener(NULL), + plistener(NULL), imageListener(NULL), aeListener(NULL), hListener(NULL),acListener(NULL), resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false) {} @@ -423,12 +423,18 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { int Iterates=0; int begh=0; int endh=pH; - + float d; + double dd; float **buffer = new float*[pH]; for (int i=0; iciecamfloat) ipf.ciecam_02float (ncie, begh, endh, pW, nprevl, ¶ms, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, true); - else ipf.ciecam_02 (ncie, begh, endh, pW, nprevl, ¶ms, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, true); + + if(settings->ciecamfloat){ipf.ciecam_02float (ncie, begh, endh, pW, nprevl, ¶ms, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, true, d); + if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*(double)d); + } + else {ipf.ciecam_02 (ncie, begh, endh, pW, nprevl, ¶ms, customColCurve1,customColCurve2,customColCurve3, histLCAM, histCCAM, 5, 1, (float**)buffer, true, dd); + if(params.colorappearance.autodegree && acListener && params.colorappearance.enabled) acListener->autoCamChanged(100.*dd); + } for (int i=0; i sizeListeners; @@ -184,6 +185,7 @@ class ImProcCoordinator : public StagedImageProcessor { 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 saveInputICCReference (const Glib::ustring& fname); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 8c16d091e..99c179cd5 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -40,6 +40,8 @@ #include "boxblur.h" #include "rt_math.h" #include "EdgePreservingDecomposition.h" +#include "improccoordinator.h" + #ifdef _OPENMP #include #endif @@ -62,10 +64,8 @@ namespace rtengine { extern const Settings* settings; - LUTf ImProcFunctions::cachef ; LUTf ImProcFunctions::gamma2curve = 0; - void ImProcFunctions::initCache () { int maxindex = 65536; @@ -237,7 +237,7 @@ void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* par } // Copyright (c) 2012 Jacques Desmis -void ImProcFunctions::ciecam_02 (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2,const ColorAppearance & customColCurve3, LUTu & histLCAM, LUTu & histCCAM, int Iterates, int scale, float** buffer, bool execsharp) +void ImProcFunctions::ciecam_02 (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2,const ColorAppearance & customColCurve3, LUTu & histLCAM, LUTu & histCCAM, int Iterates, int scale, float** buffer, bool execsharp, double &d) { if(params->colorappearance.enabled) { @@ -283,7 +283,7 @@ if(params->colorappearance.enabled) { Yw=1.0; double Xw, Zw; double f,c,nc,yb,la,xw,yw,zw,f2,c2,nc2,yb2,la2; - double z,fl,n,nbb,ncb,d,aw; + double z,fl,n,nbb,ncb,aw; double xwd,ywd,zwd; int alg=0; float sum=0.f; @@ -409,10 +409,16 @@ if(params->colorappearance.enabled) { // 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 - bool doneinit=true; - bool doneinit2=true; + double cz,wh, pfl; + ColorTemp::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; + ColorTemp::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, doneinit,doneinit2, nc2,f2,c2, alg, gamu, highlight, rstprotection, pW) +#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, gamu, highlight, rstprotection, pW) #endif { //matrix for current working space TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); @@ -437,7 +443,9 @@ if(params->colorappearance.enabled) { 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, aw, fl, wh; + double J, C, h, Q, M, s; + double Jp,Cpr; double Jpro,Cpro, hpro, Qpro, Mpro, spro; bool t1L=false; @@ -447,7 +455,7 @@ if(params->colorappearance.enabled) { int c1C=0; 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; @@ -457,7 +465,7 @@ if(params->colorappearance.enabled) { x, y, z, xw1, yw1, zw1, yb, la, - f, c, nc, pilot, doneinit, gamu ); + f, c, nc, pilot, gamu , n, nbb, ncb, pfl, cz, d ); Jpro=J; Cpro=C; hpro=h; @@ -698,12 +706,13 @@ if(params->colorappearance.enabled) { } } double xx,yy,zz; + //double nj, nbbj, ncbj, flj, czj, dj, awj; //process normal==> viewing ColorTemp::jch2xyz_ciecam02( xx, yy, zz, J, C, h, xw2, yw2, zw2, yb2, la2, - f2, c2, nc2, doneinit2, gamu); + 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; @@ -814,7 +823,7 @@ if((params->colorappearance.tonecie || (params->colorappearance.tonecie && param #ifndef _DEBUG -#pragma omp parallel default(shared) firstprivate(lab,xw2,yw2,zw2,chr,yb,la2,yb2, height,width,begh, endh,doneinit2, nc2,f2,c2, gamu, highlight,pW) +#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); @@ -867,11 +876,12 @@ if((params->colorappearance.tonecie || (params->colorappearance.tonecie && param } } //end histograms + // double nd, nbbd, ncbd, fld, czd, dd, awd; ColorTemp::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, doneinit2, gamu); + 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; @@ -941,11 +951,10 @@ if((params->colorappearance.tonecie || (params->colorappearance.tonecie && param // Copyright (c) 2012 Jacques Desmis -void ImProcFunctions::ciecam_02float (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2,const ColorAppearance & customColCurve3, LUTu & histLCAM, LUTu & histCCAM, int Iterates, int scale, float** buffer, bool execsharp) +void ImProcFunctions::ciecam_02float (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2,const ColorAppearance & customColCurve3, LUTu & histLCAM, LUTu & histCCAM, int Iterates, int scale, float** buffer, bool execsharp, float &d) { if(params->colorappearance.enabled) { //printf("ciecam float\n"); - #ifdef _DEBUG MyTime t1e,t2e; t1e.set(); @@ -987,8 +996,8 @@ if(params->colorappearance.enabled) { float Yw; Yw=1.0; double Xw, Zw; - float f,c,nc,yb,la,xw,yw,zw,f2,c2,nc2,yb2,la2; - float z,fl,n,nbb,ncb,d,aw; + float f,nc,yb,la,c,xw,yw,zw,f2,c2,nc2,yb2,la2; + float z,fl,n,nbb,ncb,aw;//d float xwd,ywd,zwd; int alg=0; float sum=0.f; @@ -1114,10 +1123,14 @@ if(params->colorappearance.enabled) { // 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 - bool doneinit=true; - bool doneinit2=true; + float cz,wh, pfl; + ColorTemp::initcam1float(gamu, yb, pilot, f, la,xw, yw, zw, n, d, nbb, ncb,cz, aw, wh, pfl, fl, c); + float nj,dj,nbbj,ncbj,czj,awj,flj; + ColorTemp::initcam2float(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, doneinit,doneinit2, nc2,f2,c2, alg, gamu, highlight, rstprotection, pW) +#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, gamu, highlight, rstprotection, pW,nj, nbbj, ncbj, flj, czj, dj, awj, n, nbb, ncb, pfl, cz) #endif { //matrix for current working space TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); @@ -1142,7 +1155,8 @@ if(params->colorappearance.enabled) { float epsil=0.0001; //convert Lab => XYZ Color::Lab2XYZ(L, a, b, x1, y1, z1); - float J, C, h, Q, M, s, aw, fl, wh; + // float J, C, h, Q, M, s, aw, fl, wh; + float J, C, h, Q, M, s; float Jp,Cpr; float Jpro,Cpro, hpro, Qpro, Mpro, spro; bool t1L=false; @@ -1152,7 +1166,8 @@ if(params->colorappearance.enabled) { int c1C=0; int c1s=0; int c1co=0; - + // float n,nbb,ncb,pfl,cz,d; + x=(float)x1/655.35f; y=(float)y1/655.35f; z=(float)z1/655.35f; @@ -1162,7 +1177,7 @@ if(params->colorappearance.enabled) { x, y, z, xw1, yw1, zw1, yb, la, - f, c, nc, pilot, doneinit, gamu ); + f, c, nc, pilot, gamu, n, nbb, ncb, pfl, cz, d); Jpro=J; Cpro=C; hpro=h; @@ -1404,11 +1419,13 @@ if(params->colorappearance.enabled) { } float xx,yy,zz; //process normal==> viewing + //float nj, nbbj, ncbj, flj, czj, dj, awj; + ColorTemp::jch2xyz_ciecam02float( xx, yy, zz, J, C, h, xw2, yw2, zw2, yb2, la2, - f2, c2, nc2, doneinit2, gamu); + f2, c2, nc2, gamu, nj, nbbj, ncbj, flj, czj, dj, awj); x=(float)xx*655.35f; y=(float)yy*655.35f; z=(float)zz*655.35f; @@ -1521,7 +1538,7 @@ if((params->colorappearance.tonecie && (params->edgePreservingDecompositionUI.en #ifndef _DEBUG -#pragma omp parallel default(shared) firstprivate(lab,xw2,yw2,zw2,chr,yb,la2,yb2, height,width,begh, endh,doneinit2, nc2,f2,c2, gamu, highlight,pW) +#pragma omp parallel default(shared) firstprivate(lab,xw2,yw2,zw2,chr,yb,la2,yb2, height,width,begh, endh, nc2,f2,c2, gamu, highlight,pW,nj, nbbj, ncbj, flj, czj, dj, awj) #endif { TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); @@ -1574,11 +1591,12 @@ if((params->colorappearance.tonecie && (params->edgePreservingDecompositionUI.en } } //end histograms + ColorTemp::jch2xyz_ciecam02float( 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, doneinit2, gamu); + f2, c2, nc2, gamu, nj, nbbj, ncbj, flj, czj, dj, awj); x=(float)xx*655.35f; y=(float)yy*655.35f; z=(float)zz*655.35f; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 92ef0c675..060091117 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -69,6 +69,7 @@ class ImProcFunctions { public: + bool iGamma; // true if inverse gamma has to be applied in rgbProc double g; @@ -82,7 +83,7 @@ class ImProcFunctions { ImProcFunctions (const ProcParams* iparams, bool imultiThread=true) : monitorTransform(NULL), params(iparams), scale(1), multiThread(imultiThread), iGamma(true), g(0.0) {} ~ImProcFunctions (); - + void setScale (double iscale); bool needsTransform (); @@ -94,8 +95,8 @@ class ImProcFunctions { SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, double expcomp, int hlcompr, int hlcomprthresh); void luminanceCurve (LabImage* lold, LabImage* lnew, LUTf &curve); - void ciecam_02float (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM,int Iterates, int scale, float** buffer, bool execsharp ); - void ciecam_02 (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM,int Iterates, int scale, float** buffer, bool execsharp ); + void ciecam_02float (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM,int Iterates, int scale, float** buffer, bool execsharp, float &d); + void ciecam_02 (CieImage* ncie, int begh, int endh, int pW, LabImage* lab, const ProcParams* params , const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, LUTu &histLCAM, LUTu &histCCAM,int Iterates, int scale, float** buffer, bool execsharp, double &d); void chromiLuminanceCurve (int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve,LUTf & satclcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, LUTu &histCCurve); void vibrance (LabImage* lab);//Jacques' vibrance void colorCurve (LabImage* lold, LabImage* lnew); diff --git a/rtengine/impulse_denoise.h b/rtengine/impulse_denoise.h index 0ae7e5b58..4d911201c 100644 --- a/rtengine/impulse_denoise.h +++ b/rtengine/impulse_denoise.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 widthITheightOUT ANY widthARRANTY; without even the implied warranty of * MERCheightANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -15,7 +15,7 @@ * along with RawTherapee. If not, see . * * 2010 Emil Martinec - * + * */ #include #include "rt_math.h" @@ -29,17 +29,17 @@ using namespace std; namespace rtengine { void ImProcFunctions::impulse_nr (LabImage* lab, double thresh) { - - + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // impulse noise removal // local variables - + int width = lab->W; int height = lab->H; - + float hpfabs, hfnbrave; - + // buffer for the lowpass image float ** lpf = new float *[height]; // buffer for the highpass image @@ -51,45 +51,57 @@ void ImProcFunctions::impulse_nr (LabImage* lab, double thresh) { //memset (impish[i], 0, width*sizeof(unsigned short)); } - + //The cleaning algorithm starts here - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // modified bilateral filter for lowpass image, omitting input pixel; or Gaussian blur - + static float eps = 1.0; float wtdsum[3], dirwt, norm; - int i1, j1; - + int i1, j1; + //rangeblur (lab->L, lpf, impish /*used as buffer here*/, width, height, thresh, false); - #ifdef _OPENMP - #pragma omp parallel - #endif +#ifdef _OPENMP +#pragma omp parallel +#endif { 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)); } - + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - + 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 for private(hpfabs, hfnbrave,i1,j1) +#endif for (int i=0; i < height; i++) for (int j=0; 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=max(0,j-2); j1<=min(j+2,width-1); j1++ ) { hfnbrave += fabs(lab->L[i1][j1]-lpf[i1][j1]); } - hfnbrave = (hfnbrave-hpfabs)/24; - hpfabs>(hfnbrave*impthr) ? impish[i][j]=1 : impish[i][j]=0; - + impish[i][j] = (hpfabs>((hfnbrave-hpfabs)*impthrDiv24)); + }//now impulsive values have been identified - + +// 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 +// Measured it and in fact gives better performance than without schedule(dynamic,16). Of course, there could be a better +// choice for the chunk_size than 16 +// race conditions are avoided by the array impish +#ifdef _OPENMP + #pragma omp parallel for private(wtdsum,norm,dirwt,i1,j1) schedule(dynamic,16) +#endif for (int i=0; i < height; i++) for (int j=0; j < width; j++) { if (!impish[i][j]) continue; @@ -110,17 +122,17 @@ void ImProcFunctions::impulse_nr (LabImage* lab, double thresh) { 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; iwidth / fh; else @@ -820,7 +821,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei myscale = 1.0 / myscale; - // apply crop +/* // apply crop if (params.crop.enabled) { int ix = 0; for (int i=0; iciecamfloat) ipf.ciecam_02float (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true); - else ipf.ciecam_02 (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true); + if(settings->ciecamfloat) ipf.ciecam_02float (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true, d); + else ipf.ciecam_02 (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true, dd); for (int i=0; iciecamfloat) ipf.ciecam_02float (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true); -else ipf.ciecam_02 (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true); +if(settings->ciecamfloat) ipf.ciecam_02float (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true, d); +else ipf.ciecam_02 (cieView, begh, endh,1, labView, ¶ms,customColCurve1,customColCurve2,customColCurve3, dummy, dummy, 5, 1, (float**)buffer, true, dd); for (int i=0; iadd (*Gtk::manage (new RTImage ("processing.png"))); automatic->set_border_width (0); - automatic->set_tooltip_text (M("GENERAL_AUTO")); + automatic->set_tooltip_markup(tooltip.length() ? Glib::ustring::compose("%1\n\n%2", M("GENERAL_AUTO"), tooltip) : M("GENERAL_AUTO")); autoChange = automatic->signal_toggled().connect( sigc::mem_fun(*this, &Adjuster::autoToggled) ); hbox->pack_end (*automatic, Gtk::PACK_SHRINK, 0); diff --git a/rtgui/adjuster.h b/rtgui/adjuster.h index 2390d6764..2f1c77e76 100644 --- a/rtgui/adjuster.h +++ b/rtgui/adjuster.h @@ -80,7 +80,7 @@ class Adjuster : public Gtk::VBox { virtual ~Adjuster (); // Add an "Automatic" checkbox next to the reset button. - void addAutoButton(); + 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 diff --git a/rtgui/colorappearance.cc b/rtgui/colorappearance.cc index 58fd51a67..4cd1b1b4a 100644 --- a/rtgui/colorappearance.cc +++ b/rtgui/colorappearance.cc @@ -57,7 +57,7 @@ ColorAppearance::ColorAppearance () : Gtk::VBox(), FoldableToolPanel(this) { 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(); + degree->addAutoButton(M("TP_COLORAPP_DEGREE_AUTO_TOOLTIP")); degree->set_tooltip_markup (M("TP_COLORAPP_DEGREE_TOOLTIP")); p1VBox->pack_start (*degree); @@ -78,7 +78,7 @@ ColorAppearance::ColorAppearance () : Gtk::VBox(), FoldableToolPanel(this) { wbmHBox->pack_start (*wbmodel); p1VBox->pack_start (*wbmHBox); - adapscen = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTSCENE"), 1, 4000., 1., 2000.)); + adapscen = Gtk::manage (new Adjuster (M("TP_COLORAPP_ADAPTSCENE"), 0.1, 4000., 0.1, 2000.)); if (adapscen->delay < 1000) adapscen->delay = 1000; adapscen->throwOnButtonRelease(); adapscen->set_tooltip_markup (M("TP_COLORAPP_ADAPTSCENE_TOOLTIP")); @@ -830,6 +830,27 @@ void ColorAppearance::setDefaults (const ProcParams* defParams, const ParamsEdit } } +int autoCamChangedUI (void* data) { + (static_cast(data))->autoCamComputed_ (); + return 0; +} +void ColorAppearance::autoCamChanged (double ccam) +{ + nextCcam = ccam; + g_idle_add (autoCamChangedUI, this); + // Glib::signal_idle().connect (sigc::mem_fun(*this, &ColorAppearance::autoCamComputed_)); +} + +bool ColorAppearance::autoCamComputed_ () { + + disableListener (); +// degree->setEnabled (true); + degree->setValue (nextCcam); + enableListener (); + + return false; +} + void ColorAppearance::colorForValue (double valX, double valY, int callerId, ColorCaller *caller) { @@ -891,6 +912,7 @@ void ColorAppearance::adjusterAutoToggled (Adjuster* a, bool newval) { } if (listener && (multiImage||enabled->get_active()) ) { + if(a==degree) { if (degree->getAutoInconsistent()) listener->panelChanged (EvCATAutoDegree, M("GENERAL_UNCHANGED")); @@ -926,7 +948,8 @@ void ColorAppearance::enabledChanged () { toneCurveMode->set_sensitive (true); } else - listener->panelChanged (EvCATEnabled, M("GENERAL_DISABLED")); + {listener->panelChanged (EvCATEnabled, M("GENERAL_DISABLED")); + } } } diff --git a/rtgui/colorappearance.h b/rtgui/colorappearance.h index 0b69002a0..8767f2853 100644 --- a/rtgui/colorappearance.h +++ b/rtgui/colorappearance.h @@ -28,7 +28,7 @@ #include "guiutils.h" #include "colorprovider.h" -class ColorAppearance : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider { +class ColorAppearance : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoCamListener, public CurveListener, public ColorProvider { protected: Glib::RefPtr bgTTips; @@ -76,7 +76,7 @@ class ColorAppearance : public Gtk::VBox, public AdjusterListener, public Foldab DiagonalCurveEditor* shape; DiagonalCurveEditor* shape2; DiagonalCurveEditor* shape3; - + double nextCcam; bool lastEnabled; bool lastAutoDegree; sigc::connection enaConn; @@ -109,6 +109,8 @@ class ColorAppearance : public Gtk::VBox, public AdjusterListener, public Foldab void datacie_toggled (); void tonecie_toggled (); // void sharpcie_toggled (); + void autoCamChanged (double ccam); + bool autoCamComputed_ (); void curveChanged (CurveEditor* ce); void curveMode1Changed (); diff --git a/rtgui/multilangmgr.cc b/rtgui/multilangmgr.cc index 0b44abe39..7c6185356 100644 --- a/rtgui/multilangmgr.cc +++ b/rtgui/multilangmgr.cc @@ -102,6 +102,8 @@ bool MultiLangMgr::isOSLanguageDetectSupported() { #else return false; #endif +#elif __linux__ || __APPLE__ + return true; #else return false; #endif @@ -114,7 +116,6 @@ Glib::ustring MultiLangMgr::getOSUserLanguage() { if (isOSLanguageDetectSupported()) { - // TODO: Add support for other OS here #ifdef WIN32 // When using old versions of MINGW this is not defined #ifdef __MINGW64_VERSION_MAJOR @@ -128,8 +129,10 @@ Glib::ustring MultiLangMgr::getOSUserLanguage() { langName=TranslateRFC2Language(localRFC); } #endif +#elif __linux__ || __APPLE__ + langName = TranslateRFC2Language(std::setlocale(LC_CTYPE,"")); #endif - } else printf("Automatic language detection not supported on your OS\n"); + } return langName; } diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 41ff8a6b7..9631980a2 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -357,6 +357,8 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool if (ipc) { ipc->setAutoExpListener (toneCurve); + ipc->setAutoCamListener (colorappearance); + ipc->setSizeListener (crop); ipc->setSizeListener (resize); } diff --git a/tools/generateSourceTarball b/tools/generateSourceTarball index 6885b19a5..f53d05b38 100755 --- a/tools/generateSourceTarball +++ b/tools/generateSourceTarball @@ -5,9 +5,10 @@ if [[ ! "$1" ]]; then exit fi -hg update "$1" tools/generateReleaseInfo -hg archive -X ".hg*" -X "rtgui/config.h" -X "rtgui/version.h" -X "rtdata/rawtherapee.desktop" rawtherapee-"$1".tar +mkdir rawtherapee-"$1" +mv ReleaseInfo.cmake rawtherapee-"$1" +hg archive -r "$1" -X ".hg*" -X "rtgui/config.h" -X "rtgui/version.h" -X "rtdata/rawtherapee.desktop" rawtherapee-"$1".tar +tar -rf rawtherapee-"$1".tar rawtherapee-"$1"/ReleaseInfo.cmake xz -z -9e rawtherapee-"$1".tar -hg update -rm ReleaseInfo.cmake +rm -r rawtherapee-"$1"