diff --git a/CMakeLists.txt b/CMakeLists.txt index b3f00e2cd..57b875e6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -356,10 +356,6 @@ if(USE_CLANG) endif (LDGOLD_CMD STREQUAL LDGOLD_CMD-NOTFOUND) endif(USE_CLANG) -if (UNIX) - install (PROGRAMS rtstart DESTINATION ${BINDIR}) -endif (UNIX) - install (FILES AUTHORS.txt DESTINATION ${CREDITSDIR}) install (FILES LICENSE.txt DESTINATION ${LICENCEDIR}) install (FILES AboutThisBuild.txt DESTINATION ${CREDITSDIR}) diff --git a/rtengine/EdgePreservingDecomposition.cc b/rtengine/EdgePreservingDecomposition.cc index d1c24977e..04b97f448 100644 --- a/rtengine/EdgePreservingDecomposition.cc +++ b/rtengine/EdgePreservingDecomposition.cc @@ -440,8 +440,8 @@ float *EdgePreservingDecomposition::CompressDynamicRange(float *Source, float Sc //We're working with luminance, which does better logarithmic. unsigned int i; - //for(i = 0; i != n; i++) - // Source[i] = logf(Source[i] + eps); + for(i = 0; i != n; i++) + Source[i] = logf(Source[i] + eps); //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); @@ -452,7 +452,7 @@ float *EdgePreservingDecomposition::CompressDynamicRange(float *Source, float Sc float ce = expf(Source[i] + u[i]*(CompressionExponent - 1.0f)) - eps; float ue = expf(u[i]) - eps; Source[i] = expf(Source[i]) - eps; - Compressed[i] = u[i];//ce + DetailBoost*(Source[i] - ue); + Compressed[i] = ce + DetailBoost*(Source[i] - ue); } if(Compressed != u) delete[] u; diff --git a/rtengine/FTblockDNchroma.cc b/rtengine/FTblockDNchroma.cc index 7f866b109..a69eb4191 100644 --- a/rtengine/FTblockDNchroma.cc +++ b/rtengine/FTblockDNchroma.cc @@ -27,7 +27,7 @@ #include //#include "bilateral2.h" -//#include "gauss.h" +#include "gauss.h" #include "rtengine.h" #include "improcfun.h" @@ -40,8 +40,6 @@ #include #endif - -#include "EdgePreserveLab.h" #include "cplx_wavelet_dec.h" @@ -52,9 +50,10 @@ //#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) //#define CLIP(x) LIM(x,0,65535) -#define TS 256 // Tile size -#define offset (TS/4) // shift between tiles +#define TS 64 // Tile size +#define offset 25 // shift between tiles #define fTS ((TS/2+1)) // second dimension of Fourier tiles +#define blkrad 0 // radius of block averaging //#define eps 0.01f/(TS*TS) //tolerance namespace rtengine { @@ -97,15 +96,20 @@ namespace rtengine { //srand((unsigned)time(0));//test with random data + //int max; + //float median = MadMax(src->data, max, src->width*src->height); + //gain = sqrt(MAX(1.0f,(0.15f*65535.0f/median))*(65535.0f/max));//'gain' is public float allocated in improcfun.h; + const float gain = pow (2.0, dnparams.expcomp); + #ifdef _OPENMP #pragma omp parallel for #endif for (int i=0; iheight; i++) for (int j=0; jwidth; j++) { - float X = src->r[i][j];//xyz_prophoto[0][0]*src->r[i][j] + xyz_prophoto[0][1]*src->g[i][j] + xyz_prophoto[0][2]*src->b[i][j]; - float Y = src->g[i][j];//xyz_prophoto[1][0]*src->r[i][j] + xyz_prophoto[1][1]*src->g[i][j] + xyz_prophoto[1][2]*src->b[i][j]; - float Z = src->b[i][j];//xyz_prophoto[2][0]*src->r[i][j] + xyz_prophoto[2][1]*src->g[i][j] + xyz_prophoto[2][2]*src->b[i][j]; + float X = gain*src->r[i][j];//xyz_prophoto[0][0]*src->r[i][j] + xyz_prophoto[0][1]*src->g[i][j] + xyz_prophoto[0][2]*src->b[i][j]; + float Y = gain*src->g[i][j];//xyz_prophoto[1][0]*src->r[i][j] + xyz_prophoto[1][1]*src->g[i][j] + xyz_prophoto[1][2]*src->b[i][j]; + float Z = gain*src->b[i][j];//xyz_prophoto[2][0]*src->r[i][j] + xyz_prophoto[2][1]*src->g[i][j] + xyz_prophoto[2][2]*src->b[i][j]; X = X<65535.0f ? gamcurve[X] : (gamma((double)X/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); Y = Y<65535.0f ? gamcurve[Y] : (gamma((double)Y/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f); @@ -143,6 +147,8 @@ namespace rtengine { igamcurve[i] = (gamma((float)i/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); } + const float gain = pow (2.0, dnparams.expcomp); + #ifdef _OPENMP #pragma omp parallel for #endif @@ -161,9 +167,9 @@ namespace rtengine { //Y = 65535.0f*(0.05+0.1*((float)rand()/(float)RAND_MAX));//test with random data - dst->r[i][j] = X;//prophoto_xyz[0][0]*X + prophoto_xyz[0][1]*Y + prophoto_xyz[0][2]*Z; - dst->g[i][j] = Y;//prophoto_xyz[1][0]*X + prophoto_xyz[1][1]*Y + prophoto_xyz[1][2]*Z; - dst->b[i][j] = Z;//prophoto_xyz[2][0]*X + prophoto_xyz[2][1]*Y + prophoto_xyz[2][2]*Z; + dst->r[i][j] = X/gain;//prophoto_xyz[0][0]*X + prophoto_xyz[0][1]*Y + prophoto_xyz[0][2]*Z; + dst->g[i][j] = Y/gain;//prophoto_xyz[1][0]*X + prophoto_xyz[1][1]*Y + prophoto_xyz[1][2]*Z; + dst->b[i][j] = Z/gain;//prophoto_xyz[2][0]*X + prophoto_xyz[2][1]*Y + prophoto_xyz[2][2]*Z; } } @@ -178,7 +184,7 @@ namespace rtengine { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /*if (plistener) { - plistener->setProgressStr ("Block FT Luma Denoise..."); + plistener->setProgressStr ("Denoise..."); plistener->setProgress (0.0); }*/ @@ -200,43 +206,34 @@ namespace rtengine { return; } - const int blkrad=1; - float noisevar_L = SQR(dnparams.luma * TS * 10.0f); - float noisevar_ab = SQR(dnparams.chroma * TS * 100.0f); - - //int dxr=Roffset&1, dyr=(Roffset&2)/2, dxb=(1-dxr), dyb=(1-dyr); - //int rdx, rdy, bdx, bdy; + //const int blkrad=2; + float noisevar_L = SQR((100-dnparams.luma) * TS * 100.0f); + float noisevar_ab = SQR(dnparams.chroma * TS * 150.0f); // calculation for tiling 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 - - //const float eps = 1.0f; - + array2D tilemask_in(TS,TS); array2D tilemask_out(TS,TS); array2D totwt(width,height,ARRAY2D_CLEAR_DATA); + + const int border = MAX(2,TS/16); for (int i=0; iTS/2 ? i-TS : i)); - float vmask = (i1<8 ? SQR(sin(M_PI*i1/16.0f)) : 1.0f); - float vmask2 = (i1<32 ? SQR(sin(M_PI*i1/64.0f)) : 1.0f); + float i1 = abs((i>TS/2 ? i-TS+1 : i)); + float vmask = (i1TS/2 ? j-TS : j)); - //tilemask_in[i][j] = vmask * (j1<4 ? SQR(sin(M_PI*(float)j1/8.0f)) : 1.0f); - tilemask_in[i][j] = (exp(-(SQR(i-TS/2-0.5f)+SQR(j-TS/2-0.5f))/(2*SQR(TS/4.0f))) * \ - vmask * (j1<8 ? SQR(sin(M_PI*(float)j1/16.0f)) : 1.0f)); + float j1 = abs((j>TS/2 ? j-TS+1 : j)); + tilemask_in[i][j] = (vmask * (j1 Ldn(width,height); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // transform RGB input to ersatz Lab RGB_InputTransf(src, labin, dnparams, defringe); + memcpy (labdn->data, labin->data, 3*width*height*sizeof(float)); + //dirpyr_ab(labin, labdn, dnparams);//use dirpyr here if using it to blur ab channels only + //dirpyrLab_denoise(labin, labdn, dnparams);//use dirpyr here if using it to blur ab channels only + + impulse_nr (labdn, 50.0f/20.0f); + int datalen = labin->W * labin->H; wavelet_decomposition Ldecomp(labin->data, labin->W, labin->H, 5/*maxlevels*/, 0/*subsampling*/ ); @@ -259,50 +263,39 @@ namespace rtengine { wavelet_decomposition bdecomp(labin->data+2*datalen, labin->W, labin->H, 5, 1 );//last args are maxlevels, subsampling float noisevarL = SQR(dnparams.Lamt/25.0f);//TODO: clean up naming confusion about params - float noisevarab = SQR(dnparams.chroma/25.0f); + float noisevarab = SQR(dnparams.chroma/10.0f); - //WaveletDenoise(Ldecomp, SQR((float)dnparams.Lamt/25.0f)); - WaveletDenoiseAll(Ldecomp, adecomp, bdecomp, noisevarL, noisevarab); - - Ldecomp.reconstruct(labblur->data); - adecomp.reconstruct(labblur->data+datalen); - bdecomp.reconstruct(labblur->data+2*datalen); + WaveletDenoiseAll_BiShrink(Ldecomp, adecomp, bdecomp, noisevarL, noisevarab); + Ldecomp.reconstruct(labdn->data); + adecomp.reconstruct(labdn->data+datalen); + bdecomp.reconstruct(labdn->data+2*datalen); - //impulse_nr (dst, 50.0f/20.0f); + impulse_nr (labdn, 50.0f/20.0f); //PF_correct_RT(dst, dst, defringe.radius, defringe.threshold); - - //dirpyr_ab(labin, labblur, dnparams);//use dirpyr here if using it to blur ab channels only - //dirpyrLab_denoise(labin, labblur, dnparams);//use dirpyr here if using it to blur ab channels only + //dirpyr_ab(labin, labdn, dnparams);//use dirpyr here if using it to blur ab channels only + //dirpyrLab_denoise(labin, labdn, dnparams);//use dirpyr here if using it to blur ab channels only - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // initialize FT and output data structures - LabImage * labdn = new LabImage(width,height); - for (int i=0; i<3*labdn->W*labdn->H; i++) { + + float * Ldnptr = Ldn; + memcpy (Ldnptr, labdn->data, width*height*sizeof(float)); + for (int i=0; iW*labdn->H; i++) { labdn->data[i] = 0.0f; } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // allocate FT data structures + float ** Lblox = new float *[8] ; - float ** RLblox = new float *[8] ; - float ** BLblox = new float *[8] ; - fftwf_complex ** fLblox = new fftwf_complex *[8] ; //for FT - //float ** fLblox = new float *[8] ; //for DCT - - fftwf_complex ** fRLblox = new fftwf_complex *[8] ; - fftwf_complex ** fBLblox = new fftwf_complex *[8] ; + float ** fLblox = new float *[8] ; //for DCT for( int i = 0 ; i < 8 ; i++ ) { Lblox[i] = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); - //RLblox[i] = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); - //BLblox[i] = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); + fLblox[i] = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); //for DCT - fLblox[i] = (fftwf_complex *) fftwf_malloc (numblox_W*TS*fTS * sizeof (fftwf_complex)); //for FT - //fLblox[i] = (float *) fftwf_malloc (numblox_W*TS*TS * sizeof (float)); //for DCT - - //fRLblox[i] = (fftwf_complex *) fftwf_malloc (numblox_W*TS*fTS * sizeof (fftwf_complex)); - //fBLblox[i] = (fftwf_complex *) fftwf_malloc (numblox_W*TS*fTS * sizeof (fftwf_complex)); } //make a plan for FFTW @@ -310,20 +303,13 @@ namespace rtengine { int nfwd[2]={TS,TS}; - //for FT: - plan_forward_blox = fftwf_plan_many_dft_r2c(2, nfwd, numblox_W, Lblox[0], NULL, 1, TS*TS, \ - fLblox[0], NULL, 1, TS*fTS, FFTW_ESTIMATE ); - plan_backward_blox = fftwf_plan_many_dft_c2r(2, nfwd, numblox_W, fLblox[0], NULL, 1, TS*fTS, \ - Lblox[0], NULL, 1, TS*TS, FFTW_ESTIMATE ); //for DCT: - //const fftw_r2r_kind fwdkind[2] = {FFTW_REDFT10, FFTW_REDFT10}; - //const fftw_r2r_kind bwdkind[2] = {FFTW_REDFT01, FFTW_REDFT01}; + 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[0], NULL, 1, TS*TS, \ - fLblox[0], NULL, 1, TS*TS, fwdkind, FFTW_ESTIMATE ); - //plan_backward_blox = fftwf_plan_many_r2r(2, nfwd, numblox_W, fLblox[0], NULL, 1, TS*TS, \ - Lblox[0], NULL, 1, TS*TS, bwdkind, FFTW_ESTIMATE ); + plan_forward_blox = fftwf_plan_many_r2r(2, nfwd, numblox_W, Lblox[0], NULL, 1, TS*TS, fLblox[0], NULL, 1, TS*TS, fwdkind, FFTW_ESTIMATE ); + plan_backward_blox = fftwf_plan_many_r2r(2, nfwd, numblox_W, fLblox[0], NULL, 1, TS*TS, Lblox[0], NULL, 1, TS*TS, bwdkind, FFTW_ESTIMATE ); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -335,113 +321,53 @@ namespace rtengine { int vblkmod = vblk%8; int top = (vblk-blkrad)*offset; - - for (int hblk=0; hblk=height) { + rr = MAX(0,2*height-2-row); + } - // load Lab high pass data + for (int j=0; jW; j++) { + datarow[j] = (labin->L[rr][j]-Ldn[rr][j]); + } - for (int i=imin; iL[top+i][left+j]-labblur->L[top+i][left+j]);// luma data - //RLblox[vblkmod][(indx + i)*TS+j] = tilemask_in[i][j]*(labin->a[top+i][left+j]-labblur->a[top+i][left+j]);// high pass chroma data - //BLblox[vblkmod][(indx + i)*TS+j] = tilemask_in[i][j]*(labin->b[top+i][left+j]-labblur->b[top+i][left+j]);// high pass chroma data - - totwt[top+i][left+j] += tilemask_in[i][j]*tilemask_out[i][j]; - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //pad the image to size TS on both sides - - if (imin>0) { - for (int i=0; iL[2*imin-i-1][left+j]-labblur->L[2*imin-i-1][left+j]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[2*imin-i-1][left+j]-labblur->a[2*imin-i-1][left+j]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[2*imin-i-1][left+j]-labblur->b[2*imin-i-1][left+j]); + Lblox[vblkmod][(indx + i)*TS+j] = tilemask_in[i][j]*datarow[left+j];// luma data + if (top+i>=0 && top+i=0 && left+j0) { - for (int i=0; iL[2*imin-i-1][2*jmin-j-1]-labblur->L[2*imin-i-1][2*jmin-j-1]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[2*imin-i-1][2*jmin-j-1]-labblur->a[2*imin-i-1][2*jmin-j-1]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[2*imin-i-1][2*jmin-j-1]-labblur->b[2*imin-i-1][2*jmin-j-1]); - } } } - - if (imaxL[height+imax-i-1][left+j]-labblur->L[height+imax-i-1][left+j]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[height+imax-i-1][left+j]-labblur->a[height+imax-i-1][left+j]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[height+imax-i-1][left+j]-labblur->b[height+imax-i-1][left+j]); - } - if (jmaxL[height+imax-i-1][width+jmax-j-1]-labblur->L[height+imax-i-1][width+jmax-j-1]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[height+imax-i-1][width+jmax-j-1]-labblur->a[height+imax-i-1][width+jmax-j-1]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[height+imax-i-1][width+jmax-j-1]-labblur->b[height+imax-i-1][width+jmax-j-1]); - } - } - } - - if (jmin>0) { - for (int j=0; jL[top+i][2*jmin-j-1]-labblur->L[top+i][2*jmin-j-1]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[top+i][2*jmin-j-1]-labblur->a[top+i][2*jmin-j-1]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[top+i][2*jmin-j-1]-labblur->b[top+i][2*jmin-j-1]); - } - if (imaxL[height+imax-i-1][2*jmin-j-1]-labblur->L[height+imax-i-1][2*jmin-j-1]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[height+imax-i-1][2*jmin-j-1]-labblur->a[height+imax-i-1][2*jmin-j-1]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[height+imax-i-1][2*jmin-j-1]-labblur->b[height+imax-i-1][2*jmin-j-1]); - } - } - } - - - if (jmaxL[top+i][width+jmax-j-1]-labblur->L[top+i][width+jmax-j-1]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[top+i][width+jmax-j-1]-labblur->a[top+i][width+jmax-j-1]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[top+i][width+jmax-j-1]-labblur->b[top+i][width+jmax-j-1]); - } - if (imin>0) { - for (int i=0; iL[2*imin-i-1][width+jmax-j-1]-labblur->L[2*imin-i-1][width+jmax-j-1]); - //RLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->a[2*imin-i-1][width+jmax-j-1]-labblur->a[2*imin-i-1][width+jmax-j-1]); - //BLblox[vblkmod][(indx + i)*TS+j]=tilemask_in[i][j]*(labin->b[2*imin-i-1][width+jmax-j-1]-labblur->b[2*imin-i-1][width+jmax-j-1]); - } - } - } - //end of tile padding - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //Lblox[vblkmod][(indx + TS/2)*TS+TS/2]=32768.0f;//testing: locate block centers - }//end of filling block row + delete[] buffer; + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //fftwf_print_plan (plan_forward_blox); - fftwf_execute_dft_r2c(plan_forward_blox,Lblox[vblkmod],fLblox[vblkmod]); // FT an entire row of tiles - //fftwf_execute_r2r(plan_forward_blox,Lblox[vblkmod],fLblox[vblkmod]); // DCT an entire row of tiles + fftwf_execute_r2r(plan_forward_blox,Lblox[vblkmod],fLblox[vblkmod]); // DCT an entire row of tiles + - //fftwf_execute_dft_r2c(plan_forward_blox,RLblox[vblkmod],fRLblox[vblkmod]);// FT an entire row of tiles - //fftwf_execute_dft_r2c(plan_forward_blox,BLblox[vblkmod],fBLblox[vblkmod]);// FT an entire row of tiles + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if (vblkL[i][j]/totwt[i][j];//note that labdn initially stores the denoised hipass data - labdn->L[i][j] = labblur->L[i][j] + hpdn; - //labdn->L[i][j] = -(hporig)+0.25; + labdn->L[i][j] = Ldn[i][j] + hpdn; - //hpdn = labdn->a[i][j]/totwt[i][j]; - //labdn->a[i][j] = labblur->a[i][j] + hpdn; - - //hpdn = labdn->b[i][j]/totwt[i][j]; - //labdn->b[i][j] = labblur->b[i][j] + hpdn; - - labdn->a[i][j] = labblur->a[i][j]; - labdn->b[i][j] = labblur->b[i][j]; } } - //dirpyr_ab(labdn, labdn, dnparams);//use dirpyr here if using it to blur ab channels only - - //dirpyrdenoise(labdn);//denoise ab channels using ImProcFns denoise (stripped to ab channels only) - - //Wavelet denoise of ab channels - //int numpix = labdn->W*labdn->H; - //cplx_wavelet_decomposition adecomp(labdn->data+numpix, labdn->W, labdn->H, 5 );//last arg is num levels - //WaveletDenoise(adecomp, SQR((float)dnparams.chroma*100.0f)); - //adecomp.reconstruct(labdn->data+numpix); - //cplx_wavelet_decomposition bdecomp(labdn->data+2*numpix, labdn->W, labdn->H, 5 );//last arg is num levels - //WaveletDenoise(bdecomp, SQR((float)dnparams.chroma*100.0f)); - //bdecomp.reconstruct(labdn->data+2*numpix); + //dirpyrLab_denoise(labdn, labdn, dnparams);//use dirpyr here if using it to blur ab channels only //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // transform denoised "Lab" to output RGB @@ -570,116 +456,31 @@ namespace rtengine { delete labin; delete labdn; - delete labblur; - }//end of main RB_denoise + }//end of main RGB_denoise + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - void ImProcFunctions::RGBtile_denoise (fftwf_complex ** fLblox, fftwf_complex ** fRLblox, fftwf_complex ** fBLblox, \ - int vblproc, int hblproc, int blkrad, int numblox_H, int numblox_W, \ - float noisevar_L, float noisevar_ab ) //for FT - //void ImProcFunctions::RGBtile_denoise (float ** fLblox, fftwf_complex ** fRLblox, fftwf_complex ** fBLblox, \ - int vblproc, int hblproc, int blkrad, int numblox_H, int numblox_W, \ - float noisevar_L, float noisevar_ab ) //for DCT + void ImProcFunctions::RGBtile_denoise (float ** fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, \ + float noisevar_L, float noisevar_ab ) //for DCT { int vblprocmod=vblproc%8; - const float eps = 0.01f/(TS*TS); //tolerance - const float cutoffsq = 8.0f;//frequency cutoff + float * nbrwt = new float[TS*TS]; //for DCT + int blkstart = hblproc*TS*TS; - float RLblockvar=eps, BLblockvar=eps, Lblockvar=eps; + boxabsblur(fLblox[vblprocmod]+blkstart, nbrwt, 3, 3, TS, TS);//blur neighbor weights for more robust estimation //for DCT - for (int i=TS/4; i<3*TS/4; i++) - for (int j=TS/4; jL[top+i][left+j] += tilemask_out[i][j]*bloxrow_L[(indx + i)*TS+j]/(TS*TS); - //labdn->a[top+i][left+j] += tilemask_out[i][j]*bloxrow_a[(indx + i)*TS+j]/(TS*TS); - //labdn->b[top+i][left+j] += tilemask_out[i][j]*bloxrow_b[(indx + i)*TS+j]/(TS*TS); + labdn->L[top+i][left+j] += tilemask_out[i][j]*bloxrow_L[(indx + i)*TS+j]*DCTnorm; //for DCT } } @@ -723,143 +523,145 @@ namespace rtengine { #undef offset //#undef eps -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //experimental dirpyr low-pass filter -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//experimental dirpyr low-pass filter - -void ImProcFunctions::dirpyr_ab(LabImage * data_fine, LabImage * data_coarse, const procparams::DirPyrDenoiseParams & dnparams) -{ - int W = data_fine->W; - int H = data_fine->H; - float thresh_L = 10.0f*dnparams.luma; - float threshsq_L = SQR(thresh_L); - float thresh_ab = 10.0f*dnparams.chroma; - float threshsq_ab = SQR(thresh_ab); - LUTf rangefn_L(0x10000); - LUTf rangefn_ab(0x10000); - - LabImage * dirpyrlo[2]; - - //set up range functions - - for (int i=0; i<0x10000; i++) { - rangefn_L[i] = exp(-((float)i) / (1.0+thresh_L)) ;// * (1.0+thresh_L)/(((float)i) + thresh_L+1.0); - rangefn_ab[i] = exp(-SQR((float)i) / (1.0+threshsq_ab)) ;// * (1.0+thresh_ab)/(((float)i) + thresh_ab+1.0); - } - dirpyrlo[0] = new LabImage (W, H); - dirpyrlo[1] = new LabImage (W, H); - - //int scale[4]={1,3,5,9/*1*/}; - int scale[5]={1,2,4,7,13/*1*/}; - - int level=0; - int indx=0; - dirpyr_ablevel(data_fine, dirpyrlo[indx], W, H, rangefn_L,rangefn_ab, 0, scale[level] ); - level += 1; - indx = 1-indx; - while (level<3) { - dirpyr_ablevel(dirpyrlo[1-indx], dirpyrlo[indx], W, H, rangefn_L,rangefn_ab, level, scale[level] ); + void ImProcFunctions::dirpyr_ab(LabImage * data_fine, LabImage * data_coarse, const procparams::DirPyrDenoiseParams & dnparams) + { + int W = data_fine->W; + int H = data_fine->H; + float thresh_L = 10.0f*dnparams.luma; + float threshsq_L = SQR(thresh_L); + float thresh_ab = 10.0f*dnparams.chroma; + float threshsq_ab = SQR(thresh_ab); + LUTf rangefn_L(0x10000); + LUTf rangefn_ab(0x10000); + + LabImage * dirpyrlo[2]; + + //set up range functions + + for (int i=0; i<0x10000; i++) { + rangefn_L[i] = exp(-((float)i) / (1.0+thresh_L)) ;// * (1.0+thresh_L)/(((float)i) + thresh_L+1.0); + rangefn_ab[i] = exp(-SQR((float)i) / (1.0+threshsq_ab)) ;// * (1.0+thresh_ab)/(((float)i) + thresh_ab+1.0); + } + dirpyrlo[0] = new LabImage (W, H); + dirpyrlo[1] = new LabImage (W, H); + + //int scale[4]={1,3,5,9/*1*/}; + int scale[5]={1,2,4,7,13/*1*/}; + + int level=0; + int indx=0; + dirpyr_ablevel(data_fine, dirpyrlo[indx], W, H, rangefn_L,rangefn_ab, 0, scale[level] ); level += 1; indx = 1-indx; + while (level<3) { + dirpyr_ablevel(dirpyrlo[1-indx], dirpyrlo[indx], W, H, rangefn_L,rangefn_ab, level, scale[level] ); + level += 1; + indx = 1-indx; + } + + dirpyr_ablevel(dirpyrlo[1-indx], data_coarse, W, H, rangefn_L,rangefn_ab, level, scale[level] ); + + //delete dirpyrlo[0];//TODO: this seems to disable the NR ??? + //delete dirpyrlo[1]; } - dirpyr_ablevel(dirpyrlo[1-indx], data_coarse, W, H, rangefn_L,rangefn_ab, level, scale[level] ); - - //delete dirpyrlo[0];//TODO: this seems to disable the NR ??? - //delete dirpyrlo[1]; -} - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void ImProcFunctions::dirpyr_ablevel(LabImage * data_fine, LabImage * data_coarse, int width, int height, LUTf & rangefn_L, LUTf & rangefn_ab, int level, int scale) -{ - //scale is spacing of directional averaging weights - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // calculate weights, compute directionally weighted average - - //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, 2, 4, 2, 1}, {2, 4, 8, 4, 2}, {4, 8, 16, 8, 4}, {2, 4, 8, 4, 2}, {1, 2, 4, 2, 1}}; - float domker[5][5] = {{0.129923f, 0.279288f, 0.360448f, 0.279288f, 0.129923f}, \ - {0.279288f, 0.600373f, 0.774837f, 0.600373f, 0.279288f}, \ - {0.360448f, 0.774837f, 1.0f, 0.774837f, 0.360448f}, \ - {0.279288f, 0.600373f, 0.774837f, 0.600373f, 0.279288f}, \ - {0.129923f, 0.279288f, 0.360448f, 0.279288f, 0.129923f}};//Gaussian with sigma=1.4 - - - int scalewin = 2*scale; + void ImProcFunctions::dirpyr_ablevel(LabImage * data_fine, LabImage * data_coarse, int width, int height, LUTf & rangefn_L, LUTf & rangefn_ab, int level, int scale) + { + //scale is spacing of directional averaging weights + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // calculate weights, compute directionally weighted average + + //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, 2, 4, 2, 1}, {2, 4, 8, 4, 2}, {4, 8, 16, 8, 4}, {2, 4, 8, 4, 2}, {1, 2, 4, 2, 1}}; + float domker[5][5] = {{0.129923f, 0.279288f, 0.360448f, 0.279288f, 0.129923f}, \ + {0.279288f, 0.600373f, 0.774837f, 0.600373f, 0.279288f}, \ + {0.360448f, 0.774837f, 1.0f, 0.774837f, 0.360448f}, \ + {0.279288f, 0.600373f, 0.774837f, 0.600373f, 0.279288f}, \ + {0.129923f, 0.279288f, 0.360448f, 0.279288f, 0.129923f}};//Gaussian with sigma=1.4 + + + int scalewin = 2*scale; + #ifdef _OPENMP #pragma omp parallel for #endif - for(int i = 0; i < height; i++) { - for(int j = 0; j < width; j++) - { - float valL=0, vala=0, valb=0; - float norm_L=0, norm_ab=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) { - //it seems that weighting the blur by L (gamma=3) works better - //than using the variable gamma source - //float desat = 1-rangefn_ab[data_fine->L[i][j]+abs(data_fine->a[i][j])+abs(data_fine->b[i][j])]; - - float nbrdiff_L = fabs(data_fine->L[inbr][jnbr]-data_fine->L[i][j])/level; - float nbrdiff_ab = (fabs(data_fine->a[inbr][jnbr]-data_fine->a[i][j]) + \ - fabs(data_fine->b[inbr][jnbr]-data_fine->b[i][j])); - float dirwt_L = ( domker[(inbr-i)/scale+2][(jnbr-j)/scale+2] * rangefn_L[nbrdiff_L] ); - float dirwt_ab = ( /*domker[(inbr-i)/scale+2][(jnbr-j)/scale+2] */ rangefn_ab[nbrdiff_ab] ); - //valL += dirwt_L *data_fine->L[inbr][jnbr]; - vala += dirwt_L*dirwt_ab*data_fine->a[inbr][jnbr]; - valb += dirwt_L*dirwt_ab*data_fine->b[inbr][jnbr]; - //norm_L += dirwt_L; - norm_ab += dirwt_L*dirwt_ab; - - } - } - - //data_coarse->L[i][j] = valL/norm_L; // low pass filter - data_coarse->L[i][j] = data_fine->L[i][j]; - data_coarse->a[i][j] = vala/norm_ab; // low pass filter - data_coarse->b[i][j] = valb/norm_ab; // low pass filter - - /*if (level!=3) { - data_coarse->L[i][j] = valL/norm_L; // low pass filter - } else { + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) + { float valL=0, vala=0, valb=0; - float norm=0; - for(int inbr=MAX(0,(i-2)); inbr<=MIN(height-1,(i+2)); inbr++) { - for (int jnbr=MAX(0,(j-2)); jnbr<=MIN(width-1,(j+2)); jnbr++) { - //it seems that weighting the blur by Lab luminance (~gamma=3) - //works better than using the variable gamma source - float nbrdiff = (fabs(data_fine->L[inbr][jnbr]-data_fine->L[i][j]) + \ - fabs(data_fine->a[inbr][jnbr]-data_fine->a[i][j]) + \ - fabs(data_fine->b[inbr][jnbr]-data_fine->b[i][j]))/(level); - float dirwt = ( domker[(inbr-i)/scale+2][(jnbr-j)+2] * rangefn_L[nbrdiff] ); - valL += dirwt*data_fine->L[inbr][jnbr]; - vala += dirwt*data_fine->a[inbr][jnbr]; - valb += dirwt*data_fine->b[inbr][jnbr]; - norm += dirwt; + float norm_L=0, norm_ab=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) { + //it seems that weighting the blur by L (gamma=3) works better + //than using the variable gamma source + //float desat = 1-rangefn_ab[data_fine->L[i][j]+abs(data_fine->a[i][j])+abs(data_fine->b[i][j])]; + + float nbrdiff_L = fabs(data_fine->L[inbr][jnbr]-data_fine->L[i][j])/level; + float nbrdiff_ab = (fabs(data_fine->a[inbr][jnbr]-data_fine->a[i][j]) + \ + fabs(data_fine->b[inbr][jnbr]-data_fine->b[i][j])); + float dirwt_L = ( domker[(inbr-i)/scale+2][(jnbr-j)/scale+2] * rangefn_L[nbrdiff_L] ); + float dirwt_ab = ( /*domker[(inbr-i)/scale+2][(jnbr-j)/scale+2] */ rangefn_ab[nbrdiff_ab] ); + //valL += dirwt_L *data_fine->L[inbr][jnbr]; + vala += dirwt_L*dirwt_ab*data_fine->a[inbr][jnbr]; + valb += dirwt_L*dirwt_ab*data_fine->b[inbr][jnbr]; + //norm_L += dirwt_L; + norm_ab += dirwt_L*dirwt_ab; } } - data_coarse->L[i][j] = data_fine->L[i][j];//valL/norm; - data_coarse->a[i][j] = vala/norm; - data_coarse->b[i][j] = valb/norm; - }*/ - + + //data_coarse->L[i][j] = valL/norm_L; // low pass filter + data_coarse->L[i][j] = data_fine->L[i][j]; + data_coarse->a[i][j] = vala/norm_ab; // low pass filter + data_coarse->b[i][j] = valb/norm_ab; // low pass filter + + /*if (level!=3) { + data_coarse->L[i][j] = valL/norm_L; // low pass filter + } else { + float valL=0, vala=0, valb=0; + float norm=0; + for(int inbr=MAX(0,(i-2)); inbr<=MIN(height-1,(i+2)); inbr++) { + for (int jnbr=MAX(0,(j-2)); jnbr<=MIN(width-1,(j+2)); jnbr++) { + //it seems that weighting the blur by Lab luminance (~gamma=3) + //works better than using the variable gamma source + float nbrdiff = (fabs(data_fine->L[inbr][jnbr]-data_fine->L[i][j]) + \ + fabs(data_fine->a[inbr][jnbr]-data_fine->a[i][j]) + \ + fabs(data_fine->b[inbr][jnbr]-data_fine->b[i][j]))/(level); + float dirwt = ( domker[(inbr-i)/scale+2][(jnbr-j)+2] * rangefn_L[nbrdiff] ); + valL += dirwt*data_fine->L[inbr][jnbr]; + vala += dirwt*data_fine->a[inbr][jnbr]; + valb += dirwt*data_fine->b[inbr][jnbr]; + norm += dirwt; + + } + } + data_coarse->L[i][j] = data_fine->L[i][j];//valL/norm; + data_coarse->a[i][j] = vala/norm; + data_coarse->b[i][j] = valb/norm; + }*/ + + } } + } -} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* void ImProcFunctions::FixImpulse_ab(LabImage * src, LabImage * dst, double radius, int thresh) { @@ -1008,7 +810,7 @@ void ImProcFunctions::FixImpulse_ab(LabImage * src, LabImage * dst, double radiu ParentPadding = 0; } - float threshsq = noisevar;//*SQR(UniversalThresh(WaveletCoeffs.level_coeffs(lvl)[3], Wlvl*Hlvl)); + float threshsq = noisevar;//*SQR(MadMax(WaveletCoeffs.level_coeffs(lvl)[3], max, Wlvl*Hlvl)); Shrink(WavCoeffs, Wlvl, Hlvl, lvl, threshsq/*noisevar*/); } @@ -1058,9 +860,11 @@ void ImProcFunctions::FixImpulse_ab(LabImage * src, LabImage * dst, double radiu //simple wavelet shrinkage float * sigma = new float[W*H]; const float eps = 0.01f; + int max; + printf("level=%d ",level); for (int dir=1; dir<4; dir++) { - float mad = SQR(UniversalThresh(WavCoeffs[dir], W*H));//*6*/(level+1); + float mad = SQR(MadMax(WavCoeffs[dir], max, W*H));//*6*/(level+1); printf(" dir=%d mad=%f ",dir,sqrt(mad)); for (int i=0; i2*thresh_a ? 1 : (coeff_a2*thresh_b ? 1 : (coeff_b2*thresh_a ? 1 : (coeff_a2*thresh_b ? 1 : (coeff_b2*thresh_L ? 1 : (coeff_L2*thresh_L ? 1 : (coeff_L=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)); + printf("\n level=%d \n",lvl); for (int dir=1; dir<4; dir++) { - float mad_L = madL[lvl][dir-1];//SQR(UniversalThresh(WavCoeffs_L[dir], W_L*H_L));// *6/(level+1); - float mad_a = mada[lvl][dir-1];//SQR(UniversalThresh(WavCoeffs_a[dir], W_ab*H_ab));// *6/(level+1); - float mad_b = madb[lvl][dir-1];//SQR(UniversalThresh(WavCoeffs_b[dir], W_ab*H_ab));// *6/(level+1); + float mad_L = madL[lvl][dir-1]; + float mad_a = noisevar_ab*mada[lvl][dir-1]; + float mad_b = noisevar_ab*madb[lvl][dir-1]; + //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 thresh_L = sqrt(mad_L*noisevar_L); - float thresh_a = sqrt(mad_a*noisevar_ab); - float thresh_b = sqrt(mad_b*noisevar_ab); + //float skip_ab_ratio = WaveletCoeffs_a.level_stride(lvl+1)/skip_ab; + float skip_L_ratio = WaveletCoeffs_L.level_stride(lvl+1)/skip_L; - float skip_ab_ratio = WaveletCoeffs_a.level_stride(lvl+1)/skip_ab; - - printf(" dir=%d mad_L=%f mad_a=%f mad_b=%f \n",dir,sqrt(mad_L),sqrt(mad_a),sqrt(mad_b)); + printf(" dir=%d mad_L=%f mad_a=%f mad_b=%f \n",dir,sqrt(mad_L),sqrt(mad_a),sqrt(mad_b)); for (int i=0; i2*thresh_a ? 1 : (coeff_a2*thresh_b ? 1 : (coeff_b2 ? 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))); + WavCoeffs_a[dir][coeffloc_ab] *= SQR(1-exp(-(mag_a/mad_a)-(mag_L/(9*mad_L)))); + WavCoeffs_b[dir][coeffloc_ab] *= SQR(1-exp(-(mag_b/mad_b)-(mag_L/(9*mad_L)))); + } - } + }//now chrominance coefficients are denoised - for (int i=0; i2*thresh_L ? 1 : (coeff_L (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 - for (int i=0; i2*thresh_L ? 1 : (coeff_L (b) ? (a) : (b)) // classical filtering if the support window is small: @@ -461,4 +463,157 @@ template void boxsqblur (T* src, A* dst, int radx, int rady, i //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +template 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 boxabsblur (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) { + for (int row=0; row template - void wavelet_level::decompose_level(E *src, float *filterV, float *filterH, int taps, int offset, int skip) { + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + /* + template + void wavelet_level::AnalysisFilterLeGall (T * srcbuffer, T * dstLo, T * dstHi, int pitch, int srclen) { - T *tmpLo = new T[m_w*m_h2]; - T *tmpHi = new T[m_w*m_h2]; + // Basic convolution code + // Applies a LeGall (CDF 5/3) filter + - T *buffer = new T[MAX(m_w,m_h)]; - - /* filter along columns */ - for (int j=0; j template - void wavelet_level::reconstruct_level(E *dst, float *filterV, float *filterH, int taps, int offset, int skip) { - - T *tmpLo = new T[m_w*m_h2]; - T *tmpHi = new T[m_w*m_h2]; - - int buflen = MAX(m_w2,m_h2); - float *bufferLo = new float[buflen]; - float *bufferHi = new float[buflen]; - - /* filter along rows */ - for (int i=0; i + void wavelet_level::SynthesisFilterLeGall (T * srcLo, T * srcHi, T * dst, T *bufferLo, T *bufferHi, int pitch, int dstlen) { + + // Basic convolution code + //Applies a LeGall (CDF 5/3) filter + + + int srclen = (dstlen==m_w ? m_w2 : m_h2);//length of row/col in src (coarser level) + + for (size_t i=0, j=0; i template + void wavelet_level::decompose_level(E *src, float *filterV, float *filterH, int taps, int offset, int skip) { + + T *tmpLo = new T[m_w*m_h2]; + T *tmpHi = new T[m_w*m_h2]; + + T *buffer = new T[MAX(m_w,m_h)]; + + /* filter along columns */ + for (int j=0; j template + void wavelet_level::reconstruct_level(E *dst, float *filterV, float *filterH, int taps, int offset, int skip) { + + T *tmpLo = new T[m_w*m_h2]; + T *tmpHi = new T[m_w*m_h2]; + + int buflen = MAX(m_w2,m_h2); + float *bufferLo = new float[buflen]; + float *bufferHi = new float[buflen]; + + /* filter along rows */ + for (int i=0; iupdate (baseCrop, shradius, parent->ipf.lumimul, params.sh.hq, skip); cshmap->forceStat (parent->shmap->max, parent->shmap->min, parent->shmap->avg); } - - // shadows & highlights & tone curve & convert to cielab - /*int xref,yref; - xref=000;yref=000; - if (colortest && cropw>115 && croph>115) - for(int j=1;j<5;j++){ - xref+=j*30;yref+=j*30; - if (settings->verbose) printf("before rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f gamma=%f \n",xref,yref,skip, \ - baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256,\ - baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, \ - baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256, - parent->imgsrc->getGamma()); - }*/ if (todo & M_RGBCURVE) parent->ipf.rgbProc (baseCrop, laboCrop, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap, \ params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve ); - /*xref=000;yref=000; - if (colortest && cropw>115 && croph>115) - for(int j=1;j<5;j++){ - xref+=j*30;yref+=j*30; - if (settings->verbose) { - printf("after rgbProc RGB Xr%i Yr%i Skip=%d R=%f G=%f B=%f \n",xref,yref,skip, \ - baseCrop->r[(int)(xref/skip)][(int)(yref/skip)]/256,\ - baseCrop->g[(int)(xref/skip)][(int)(yref/skip)]/256, \ - baseCrop->b[(int)(xref/skip)][(int)(yref/skip)]/256); - printf("after rgbProc Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, - laboCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, \ - laboCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, \ - laboCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); - } - }*/ // apply luminance operations 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.EPDToneMap(labnCrop, 5, 1); //Go with much fewer than normal iterates for fast redisplay. + parent->ipf.EPDToneMap(labnCrop, 5, 1); //Go with much fewer than normal iterates for fast redisplay. parent->ipf.luminanceCurve (labnCrop, labnCrop, parent->lumacurve); parent->ipf.chrominanceCurve (labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve); @@ -200,37 +172,7 @@ void Crop::update (int todo) { //parent->ipf.lab2rgb (laboCrop, cropImg); //cropImg = baseCrop->to8(); - /* - // int xref,yref; - xref=000;yref=000; - if (colortest && cropw>115 && croph>115) - for(int j=1;j<5;j++){ - xref+=j*30;yref+=j*30; - int rlin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))]/255.0) * 255.0); - int glin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1]/255.0) * 255.0); - int blin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2]/255.0) * 255.0); - printf("after lab2rgb RGB lab2 Xr%i Yr%i Skip=%d R=%d G=%d B=%d \n",xref,yref,skip, \ - rlin,glin,blin); - //cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))], \ - //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1)], \ - //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2)]); - //printf("after lab2rgb Lab lab2 Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); - printf("after lab2rgb Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, \ - labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327, \ - labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327, \ - labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327); - } - */ - /* - if (colortest && cropImg->height>115 && cropImg->width>115) {//for testing - xref=000;yref=000; - printf("dcrop final R= %d G= %d B= %d \n", \ - cropImg->data[3*xref/(skip)*(cropImg->width+1)], \ - cropImg->data[3*xref/(skip)*(cropImg->width+1)+1], \ - cropImg->data[3*xref/(skip)*(cropImg->width+1)+2]); - } - */ if (cropImageListener) { // this in output space held in parallel to allow analysis like shadow/highlight Glib::ustring outProfile=params.icm.output; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index b8b71a960..082c4d805 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -181,13 +181,18 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { PreviewProps pp (0, 0, fw, fh, scale); setScale (scale); imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw); + + LUTu aehist; int aehistcompr; + double clip; + int brightness, contrast, black, hlcompr, hlcomprthresh; + + imgsrc->getAutoExpHistogram (aehist, aehistcompr); + ipf.getAutoExp (aehist, aehistcompr, clip, params.dirpyrDenoise.expcomp, brightness, contrast, black, hlcompr, hlcomprthresh); if (todo & M_LINDENOISE) { printf("denoising!\n"); // @Emil: put your luminance denoise tool here ; of course, at this stage, you only have an ImageFloat, no LabImage yet... if (scale==1 && params.dirpyrDenoise.enabled) { - //array2D Ldn(fw,fh); - //ipf.L_denoise(orig_prev, oprevl, params.dirpyrDenoise); ipf.RGB_denoise(orig_prev, orig_prev, params.dirpyrDenoise, params.defringe); } ImageMatrices* imatrices = imgsrc->getImageMatrices (); @@ -226,8 +231,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { if (params.toneCurve.autoexp) { 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); + ipf.getAutoExp (aehist, aehistcompr, params.toneCurve.clip, params.toneCurve.expcomp, 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); @@ -285,7 +290,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { if (todo & (M_LUMINANCE+M_COLOR) ) { nprevl->CopyFrom(oprevl); - //ipf.EPDToneMap(nprevl,0,scale); + ipf.EPDToneMap(nprevl,0,scale); progress ("Applying Luminance Curve...",100*readyphase/numofphases); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index faf602c4f..0bf6daadb 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -559,87 +559,15 @@ void ImProcFunctions::colorCurve (LabImage* lold, LabImage* lnew) { void ImProcFunctions::impulsedenoise (LabImage* lab) { if (params->impulseDenoise.enabled && lab->W>=8 && lab->H>=8) - { - //impulse_nr (lab, (float)params->impulseDenoise.thresh/10.0 );//20 is normal - int datalen = lab->W*lab->H; - for (int i=0; idata[i] *= lab->data[i]/32768.0f; - lab->data[i] = pow(lab->data[i]/32768.0f,3.0)*32768.0f; - //lab->data[i] = 5000; - } - //lab->data[100*lab->W+100] = 20000; - wavelet_decomposition Ldecomp(lab->data, lab->W, lab->H, 5/*maxlevel*/, 1/*subsampling*/ ); - wavelet_decomposition adecomp(lab->data+datalen, lab->W, lab->H, 5, 1 );//last args are maxlevels, subsampling - wavelet_decomposition bdecomp(lab->data+2*datalen, lab->W, lab->H, 5, 1 );//last args are maxlevels, subsampling - - float noisevar_L = SQR((float)params->impulseDenoise.thresh/25.0f); - float noisevar_ab = SQR((float)params->defringe.threshold / 25.0f); - - //WaveletDenoise(Ldecomp, SQR((float)params->impulseDenoise.thresh/25.0f)); - WaveletDenoiseAll(Ldecomp, adecomp, bdecomp, noisevar_L, noisevar_ab); - - LabImage* labtmp = new LabImage (lab->W,lab->H); - int lvl = (params->impulseDenoise.thresh>>4)&7; - int branch = (params->impulseDenoise.thresh>>2)&1;//2*re_im + dir - int subband = params->impulseDenoise.thresh&3;//orientation for detail subbands - float noisevar = SQR((float)params->defringe.threshold * 10.0f); - /*for (int i=0; iW*lab->H; i++) { - //float recoeff = Ldecomp.level_coeffs(lvl,branch)[subband][i]/(2<data[i] = sqrt(SQR(recoeff)+SQR(imcoeff)) * (subband != 0 ? 2*shrink : 0.707); - lab->data[i] = Ldecomp.level_coeffs(lvl,branch)[subband][i] + (subband != 0 ? 10000 : 0); - - }*/ - //for (int i=0; iW*lab->H; i++) { - // Ldecomp.level_coeffs(4)[0][i] = 0; - //} - Ldecomp.reconstruct(labtmp->data); - adecomp.reconstruct(labtmp->data+datalen); - bdecomp.reconstruct(labtmp->data+2*datalen); - - //double radius = (int)(params->impulseDenoise.thresh/10) ; - //boxvar(lab->data, lab->data, radius, radius, lab->W, lab->H); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - /*int w=lab->W; - int h=lab->H; - for(int y = 0; y != h-1; y++){ - float *rg = &lab->data[w*y]; - for(int x = 0; x != w-1; x++){ - 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]))); - lab->data[w*y+x] = gx+gy;//sqrt(lab->data[i]/32768.0f)*32768.0f; - } - }*/ - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //double radius = (double)params->impulseDenoise.thresh/40.0 ; - //AlignedBuffer* buffer = new AlignedBuffer (MAX(lab->W,lab->H)); - //gaussDerivH (lab->L, lab->L, buffer, lab->W, lab->H, radius, false/*multiThread*/); - //gaussVertical(lab->L, lab->L, buffer, lab->W, lab->H, radius, false/*multiThread*/); - //delete buffer; - - //impulse_nr (labtmp, 50.0f/20.0f); - - for (int i=0; idata[i] = 4*(labtmp->data[i+datalen]-lab->data[i+datalen])+10000; - //lab->data[i] = sqrt(MAX(0,labtmp->data[i]/32768.0f))*32768.0f; - } - delete labtmp; - - //impulse_nr (lab, 50.0f/20.0f); - - } + impulse_nr (lab, (float)params->impulseDenoise.thresh/20.0 ); } void ImProcFunctions::defringe (LabImage* lab) { - //if (params->defringe.enabled && lab->W>=8 && lab->H>=8) + if (params->defringe.enabled && lab->W>=8 && lab->H>=8) - //PF_correct_RT(lab, lab, params->defringe.radius, params->defringe.threshold); + PF_correct_RT(lab, lab, params->defringe.radius, params->defringe.threshold); } void ImProcFunctions::dirpyrdenoise (LabImage* lab) { @@ -714,8 +642,8 @@ fclose(f);*/ } - 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 clip, double& expcomp, + int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh) { float scale = 65536.0; float midgray=0.15;//0.18445f;//middle gray in linear gamma = 0.18445*65535 @@ -818,7 +746,7 @@ fclose(f);*/ float gain = exp(expcomp*log(2)); - gain = /*(median/ave)*/sqrt(gain*scale/rawmax); + gain = sqrt(gain*scale/rawmax); black = shc*gain; expcomp = log(gain)/log(2.0);//convert to stops diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 072d91797..b4c5102a6 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -142,23 +142,12 @@ namespace rtengine { int pitch, int scale, const int luma, const int chroma/*, LUTf & Lcurve, LUTf & abcurve*/ ); // FT denoise - //void L_denoise(Imagefloat * src, LabImage * dst, const procparams::DirPyrDenoiseParams & dnparams);//Emil's FT denoise - //void tile_denoise (fftwf_complex ** fLblox, int vblproc, int hblproc, \ - int blkrad, int numblox_H, int numblox_W, float noisevar ); void RGB_InputTransf(Imagefloat * src, LabImage * dst, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe); void RGB_OutputTransf(LabImage * src, Imagefloat * dst, const procparams::DirPyrDenoiseParams & dnparams); void output_tile_row (float *Lbloxrow, float ** Lhipassdn, float ** tilemask, int height, int width, int top, int blkrad ); void RGB_denoise(Imagefloat * src, Imagefloat * dst, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe); - void RGBtile_denoise (fftwf_complex ** fLblox, fftwf_complex ** fRLblox, fftwf_complex ** fBLblox, \ - int vblproc, int hblproc, int blkrad, int numblox_H, int numblox_W, float noisevar_L, float noisevar_ab ); //for FT - //void RGBtile_denoise (float ** fLblox, fftwf_complex ** fRLblox, fftwf_complex ** fBLblox, \ - int vblproc, int hblproc, int blkrad, int numblox_H, int numblox_W, float noisevar_L, float noisevar_ab ); //for DCT - void RGBoutput_tile_row (float *Lbloxrow, float *RLbloxrow, float *BLbloxrow, LabImage * labdn, \ - float ** tilemask_out, int height, int width, int top, int blkrad ); - void dirpyr_ab(LabImage * data_fine, LabImage * data_coarse, const procparams::DirPyrDenoiseParams & dnparams); - void dirpyr_ablevel(LabImage * data_fine, LabImage * data_coarse, int width, int height, \ - LUTf &rangefn_L, LUTf &rangefn_ab, int level, int scale); - void ImStats(float* src, float* dst, int H, int W, int box ); + void RGBtile_denoise (float ** fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_L, float noisevar_ab ); //for DCT + void RGBoutput_tile_row (float *Lbloxrow, LabImage * labdn, float ** tilemask_out, int height, int width, int top ); void WaveletDenoise(cplx_wavelet_decomposition &DualTreeCoeffs, float noisevar ); void WaveletDenoise(wavelet_decomposition &WaveletCoeffs, float noisevar ); void WaveletDenoiseAll(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, @@ -170,7 +159,11 @@ namespace rtengine { void Shrink(float ** WavCoeffs, int W, int H, int level, float noisevar); void ShrinkAll(float ** WavCoeffs_L, float ** WavCoeffs_a, float ** WavCoeffs_b, int level, \ int W_L, int H_L, int W_ab, int H_ab, int skip_L, int skip_ab, float noisevar_L, float noisevar_ab); - float UniversalThresh(float * HH_Coeffs, int datalen); + float MadMax(float * HH_Coeffs, int &max, int datalen); + void dirpyr_ab(LabImage * data_fine, LabImage * data_coarse, const procparams::DirPyrDenoiseParams & dnparams); + void dirpyr_ablevel(LabImage * data_fine, LabImage * data_coarse, int width, int height, LUTf & rangefn_L, LUTf & rangefn_ab, int level, int scale); + + //float gain; // pyramid equalizer void dirpyr_equalizer (float ** src, float ** dst, int srcwidth, int srcheight, const double * mult );//Emil's directional pyramid equalizer @@ -186,7 +179,7 @@ namespace rtengine { 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); bool transCoord (int W, int H, std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1); - void getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh); + void getAutoExp (LUTu & histogram, int histcompr, 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); }; diff --git a/rtengine/impulse_denoise.h b/rtengine/impulse_denoise.h index 52ad84593..c2a2bc103 100644 --- a/rtengine/impulse_denoise.h +++ b/rtengine/impulse_denoise.h @@ -41,11 +41,11 @@ void ImProcFunctions::impulse_nr (LabImage* lab, double thresh) { // buffer for the lowpass image float ** lpf = new float *[height]; // buffer for the highpass image - float ** impish = new float *[height]; + char ** impish = new char *[height]; for (int i=0; i lumcurve = dirpyrDenoise.lumcurve; - Glib::ArrayHandle chromcurve = dirpyrDenoise.chromcurve; - keyFile.set_double_list("Directional Pyramid Denoising", "LumCurve", lumcurve); - keyFile.set_double_list("Directional Pyramid Denoising", "ChromCurve", chromcurve); //Save edgePreservingDecompositionUI. keyFile.set_boolean ("EPD", "Enabled", edgePreservingDecompositionUI.enabled); @@ -828,8 +821,6 @@ if (keyFile.has_group ("Directional Pyramid Denoising")) { if (keyFile.has_key ("Directional Pyramid Denoising", "Luma")) dirpyrDenoise.luma = keyFile.get_integer ("Directional Pyramid Denoising", "Luma"); if (keyFile.has_key ("Directional Pyramid Denoising", "Chroma")) dirpyrDenoise.chroma = keyFile.get_integer ("Directional Pyramid Denoising", "Chroma"); if (keyFile.has_key ("Directional Pyramid Denoising", "Gamma")) dirpyrDenoise.gamma = keyFile.get_double ("Directional Pyramid Denoising", "Gamma"); - if (keyFile.has_key ("Directional Pyramid Denoising", "LumCurve")) dirpyrDenoise.lumcurve = keyFile.get_double_list ("Directional Pyramid Denoising", "LumCurve"); - if (keyFile.has_key ("Directional Pyramid Denoising", "ChromCurve")) dirpyrDenoise.chromcurve = keyFile.get_double_list ("Directional Pyramid Denoising", "ChromCurve"); } //Load EPD. @@ -1139,8 +1130,6 @@ bool ProcParams::operator== (const ProcParams& other) { && dirpyrDenoise.luma == other.dirpyrDenoise.luma && dirpyrDenoise.chroma == other.dirpyrDenoise.chroma && dirpyrDenoise.gamma == other.dirpyrDenoise.gamma - && dirpyrDenoise.lumcurve == other.dirpyrDenoise.lumcurve - && dirpyrDenoise.chromcurve == other.dirpyrDenoise.chromcurve && edgePreservingDecompositionUI.enabled == other.edgePreservingDecompositionUI.enabled && edgePreservingDecompositionUI.Strength == other.edgePreservingDecompositionUI.Strength && edgePreservingDecompositionUI.EdgeStopping == other.edgePreservingDecompositionUI.EdgeStopping diff --git a/rtengine/procparams.h b/rtengine/procparams.h index a98a53e63..95335e806 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -244,8 +244,7 @@ class ColorDenoiseParams { int luma; int chroma; float gamma; - std::vector lumcurve; - std::vector chromcurve; + double expcomp; }; //EPD related parameters. diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index b48174cf7..e0d4c1b93 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -731,7 +731,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei 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, 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); } @@ -855,7 +855,7 @@ 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, \ + ipf.getAutoExp (aeHistogram, aeHistCompression, params.toneCurve.clip, params.toneCurve.expcomp, \ params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh); } } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index e94818ce4..5791a53d3 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -154,7 +154,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p printf("silpleprocess calling autoexp\n"); LUTu aehist; int aehistcompr; imgsrc->getAutoExpHistogram (aehist, aehistcompr); - ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, expcomp, bright, contr, black, hlcompr,hlcomprthresh); + ipf.getAutoExp (aehist, aehistcompr, 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