From 31791b268fa462862461bfcf7ccc63c1fb52fc96 Mon Sep 17 00:00:00 2001 From: Emil Martinec Date: Sat, 9 Apr 2011 08:25:02 -0500 Subject: [PATCH] Speedup for high quality S/H. --- rtengine/dcrop.cc | 9 +-- rtengine/dcrop.h | 4 +- rtengine/improccoordinator.cc | 10 +-- rtengine/improccoordinator.h | 2 +- rtengine/improcfun.cc | 14 ++-- rtengine/rtthumbnail.cc | 5 +- rtengine/shmap.cc | 126 +++++++++++++++++++++++++++++++++- rtengine/shmap.h | 4 +- rtengine/simpleprocess.cc | 11 +-- 9 files changed, 157 insertions(+), 28 deletions(-) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 9e265904b..6f5736c98 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -131,8 +131,9 @@ void Crop::update (int todo) { // blurmap for shadow & highlights if ((todo & M_BLURMAP) && params.sh.enabled) { double radius = sqrt (double(SKIPS(parent->fw,skip)*SKIPS(parent->fw,skip)+SKIPS(parent->fh,skip)*SKIPS(parent->fh,skip))) / 2.0; - double shradius = radius / 1800.0 * params.sh.radius; - cshmap->update (baseCrop, (float**)cbuffer, shradius, parent->ipf.lumimul, params.sh.hq); + double shradius = params.sh.radius; + if (!params.sh.hq) shradius *= radius / 1800.0; + cshmap->update (baseCrop, cbuffer, shradius, parent->ipf.lumimul, params.sh.hq, skip); cshmap->forceStat (parent->shmap->max, parent->shmap->min, parent->shmap->avg); } @@ -348,8 +349,8 @@ if (settings->verbose) printf ("setcropsizes before lock\n"); cshmap = new SHMap (cropw, croph, true); - cbuffer = new int*[croph]; - cbuf_real= new int[(croph+2)*cropw]; + cbuffer = new float*[croph]; + cbuf_real= new float[(croph+2)*cropw]; for (int i=0; iupdate (oprevi, (float**)buffer, shradius, ipf.lumimul, params.sh.hq); + double shradius = params.sh.radius; + if (!params.sh.hq) shradius *= radius / 1800.0; + shmap->update (oprevi, buffer, shradius, ipf.lumimul, params.sh.hq, scale); + } readyphase++; @@ -341,9 +343,9 @@ if (settings->verbose) printf ("setscale before lock\n"); workimg = new Image8 (pW, pH); shmap = new SHMap (pW, pH, true); - buffer = new int*[pH]; + buffer = new float*[pH]; for (int i=0; imap[i][j]; + double mapval = 1.0 + shmap->map[i][j]; double factor = 1.0; if (processSH) { @@ -314,14 +314,14 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, LUTf & hltone } if (processLCE) { double sub = lceamount*(mapval-factor*(r*lumimul[0] + g*lumimul[1] + b*lumimul[2])); - r = (factor*r-sub); - g = (factor*g-sub); - b = (factor*b-sub); + r = CLIP(factor*r-sub); + g = CLIP(factor*g-sub); + b = CLIP(factor*b-sub); } else { - r = (factor*r); - g = (factor*g); - b = (factor*b); + r = CLIP(factor*r); + g = CLIP(factor*g); + b = CLIP(factor*b); } } diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 214c64ae9..4a40e0254 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -697,8 +697,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei } shmap = new SHMap (fw, fh, false); double radius = sqrt (double(fw*fw+fh*fh)) / 2.0; - double shradius = radius / 1800.0 * params.sh.radius; - shmap->update (baseImg, buffer, shradius, ipf.lumimul, params.sh.hq); + double shradius = params.sh.radius; + if (!params.sh.hq) shradius *= radius / 1800.0; + shmap->update (baseImg, buffer, shradius, ipf.lumimul, params.sh.hq, 16); if (buffer) { for (int i=0; i #include +#include //for dirpyr + + +#undef MAXVAL +#undef CLIP +#undef MAX +#undef MIN +#undef SQR + #undef THREAD_PRIORITY_NORMAL #define MAXVAL 0xffff #define CLIP(a) ((a)>0?((a)(b)?(b):(a)) namespace rtengine { @@ -43,7 +56,7 @@ SHMap::~SHMap () { delete [] map; } -void SHMap::update (Imagefloat* img, float** buffer, double radius, double lumi[3], bool hq) { +void SHMap::update (Imagefloat* img, float** buffer, double radius, double lumi[3], bool hq, int skip) { // fill with luminance for (int i=0; i (map, buffer, W, H, 8000, radius, 0, H); #endif +*/ + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //experimental dirpyr shmap + + float thresh = 100*radius;//1000; + LUTf rangefn(0x10000); + float ** dirpyrlo[2]; + + int intfactor = 1024;//16384; + + //set up range functions + + for (int i=0; i<0x10000; i++) { + //rangefn[i] = (int)(((thresh)/((double)(i) + (thresh)))*intfactor); + rangefn[i] = (int)(exp(-(MIN(10,((float)i*i) / (thresh*thresh))))*intfactor); + //if (rangefn[i]<0 || rangefn[i]>intfactor) + //printf("i=%d rangefn=%d arg=%f \n",i,rangefn[i], float(i*i) / (thresh*thresh)); + } + dirpyrlo[0] = allocArray (W, H); + dirpyrlo[1] = allocArray (W, H); + + int scale=1; + int level=0; + int indx=0; + dirpyr_shmap(map, dirpyrlo[indx], W, H, rangefn, 0, scale ); + scale *= 2; + level += 1; + indx = 1-indx; + while (skip*scale<16) { + dirpyr_shmap(dirpyrlo[1-indx], dirpyrlo[indx], W, H, rangefn, level, scale ); + scale *= 2; + level += 1; + indx = 1-indx; + } + /*dirpyr_shmap(dirpyrlo[0], dirpyrlo[1], W, H, rangefn, 1, scale ); + scale = 4; + dirpyr_shmap(dirpyrlo[1], dirpyrlo[0], W, H, rangefn, 2, scale ); + scale = 8; + dirpyr_shmap(dirpyrlo[0], dirpyrlo[1], W, H, rangefn, 3, scale ); + scale = 16; + dirpyr_shmap(dirpyrlo[1], map, W, H, rangefn, 3, scale );*/ + + dirpyr_shmap(dirpyrlo[1-indx], map, W, H, rangefn, level, scale ); + + + freeArray(dirpyrlo[0], H); + freeArray(dirpyrlo[1], H); + + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/* // anti-alias filtering the result #ifdef _OPENMP #pragma omp for @@ -90,6 +155,8 @@ void SHMap::update (Imagefloat* img, float** buffer, double radius, double lumi[ map[i][j] = (buffer[i-1][j-1]+buffer[i-1][j]+buffer[i-1][j+1]+buffer[i][j-1]+buffer[i][j]+buffer[i][j+1]+buffer[i+1][j-1]+buffer[i+1][j]+buffer[i+1][j+1])/9; else map[i][j] = buffer[i][j]; +*/ + } } // end parallel enclosure // update average, minimum, maximum @@ -115,5 +182,60 @@ void SHMap::forceStat (float max_, float min_, float avg_) { max = max_; min = min_; avg = avg_; -}} +} + +void SHMap::dirpyr_shmap(float ** data_fine, float ** data_coarse, int width, int height, LUTf & rangefn, int level, int scale) +{ + //scale is spacing of directional averaging weights + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // calculate weights, compute directionally weighted average + + int halfwin=2; + 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}}; + + //generate domain kernel + if (level<2) { + halfwin = 1; + domker[1][1]=domker[1][2]=domker[2][1]=domker[2][2]=1; + } + + + int scalewin = halfwin*scale; + +#ifdef _OPENMP +#pragma omp parallel for +#endif + for(int i = 0; i < height; i++) { + for(int j = 0; j < width; j++) + { + float val=0; + float norm=0; + + for(int inbr=(i-scalewin); inbr<=(i+scalewin); inbr+=scale) { + if (inbr<0 || inbr>height-1) continue; + for (int jnbr=(j-scalewin); jnbr<=(j+scalewin); jnbr+=scale) { + if (jnbr<0 || jnbr>width-1) continue; + float dirwt = ( domker[(inbr-i)/scale+halfwin][(jnbr-j)/scale+halfwin] * rangefn[abs(data_fine[inbr][jnbr]-data_fine[i][j])] ); + val += dirwt*data_fine[inbr][jnbr]; + norm += dirwt; + /*if (val<0 || norm<0) { + printf("val=%f norm=%f \n",val,norm); + printf("i=%d j=%d inbr=%d jnbr=%d domker=%d val=%d nbrval=%d rangefn=%d \n",i,j,inbr,jnbr, \ + domker[(inbr-i)/scale+halfwin][(jnbr-j)/scale+halfwin], \ + data_fine[i][j], data_fine[inbr][jnbr], \ + rangefn[abs(data_fine[inbr][jnbr]-data_fine[i][j])]); + }*/ + } + } + data_coarse[i][j]=CLIP((int)(val/norm));//low pass filter + if (val<=0 || norm<=0) + printf("val=%f norm=%f \n",val,norm); + } + } + +} + + +}//end of SHMap diff --git a/rtengine/shmap.h b/rtengine/shmap.h index 5f2f98a65..b9189af42 100644 --- a/rtengine/shmap.h +++ b/rtengine/shmap.h @@ -35,8 +35,10 @@ class SHMap { SHMap (int w, int h, bool multiThread); ~SHMap (); - void update (Imagefloat* img, float** buffer, double radius, double lumi[3], bool hq); + void update (Imagefloat* img, float** buffer, double radius, double lumi[3], bool hq, int skip); void forceStat (float max_, float min_, float avg_); + void dirpyr_shmap (float ** data_fine, float ** data_coarse, + int width, int height, LUTf & rangefn, int level, int scale); }; }; #endif diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index d305b9428..b6e3df7e3 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -122,16 +122,17 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } // update blurmap - int** buffer = new int*[fh]; + float** buffer = new float*[fh]; for (int i=0; iupdate (baseImg, (float**)buffer, shradius, ipf.lumimul, params.sh.hq); + double shradius = params.sh.radius; + if (!params.sh.hq) shradius *= radius / 1800.0; + shmap->update (baseImg, buffer, shradius, ipf.lumimul, params.sh.hq, 1); } // RGB processing //!!!// auto exposure!!! @@ -190,7 +191,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p //ipf.waveletEqualizer (labView, true, true); // directional pyramid equalizer - ipf.dirpyrequalizer (labView); + ipf.dirpyrequalizer (labView);//TODO: this is the luminance tonecurve, not the RGB one for (int i=0; i