Speedup for high quality S/H.

This commit is contained in:
Emil Martinec
2011-04-09 08:25:02 -05:00
parent 04b4745718
commit 31791b268f
9 changed files with 157 additions and 28 deletions

View File

@@ -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; i<croph; i++)
cbuffer[i] = cbuf_real+cropw*i+cropw;

View File

@@ -43,8 +43,8 @@ class Crop : public DetailedCrop {
Image8 *cropImgtrue;
int** cbuffer;
int * cbuf_real;
float** cbuffer;
float * cbuf_real;
SHMap* cshmap;
bool updating, needsNext;

View File

@@ -164,8 +164,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
progress ("Preparing shadow/highlight map...",100*readyphase/numofphases);
if ((todo & M_BLURMAP) && params.sh.enabled) {
double radius = sqrt (double(pW*pW+pH*pH)) / 2.0;
double shradius = radius / 1800.0 * params.sh.radius;
shmap->update (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; i<pH; i++)
buffer[i] = new int[pW];
buffer[i] = new float[pW];
allocated = true;
}

View File

@@ -50,7 +50,7 @@ class ImProcCoordinator : public StagedImageProcessor {
ImageSource* imgsrc;
int** buffer;
float** buffer;
SHMap* shmap;

View File

@@ -303,7 +303,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, LUTf & hltone
}
if (processSH || processLCE) {
double mapval = shmap->map[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);
}
}

View File

@@ -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<fh; i++)
delete [] buffer[i];

View File

@@ -21,9 +21,22 @@
#include <bilateral2.h>
#include <rtengine.h>
#include <rawimagesource.h>//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)<MAXVAL?(a):MAXVAL):0)
#define SQR(x) ((x)*(x))
#define MAX(a,b) ((a)<(b)?(b):(a))
#define MIN(a,b) ((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<H; i++)
@@ -63,6 +76,7 @@ void SHMap::update (Imagefloat* img, float** buffer, double radius, double lumi[
delete buffer;
}
else {
/*
#if 0
// the new OpenMP method does not need thread number specific code.
// #ifdef _OPENMP
@@ -80,6 +94,57 @@ void SHMap::update (Imagefloat* img, float** buffer, double radius, double lumi[
#else
bilateral<float> (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<float> (W, H);
dirpyrlo[1] = allocArray<float> (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<float>(dirpyrlo[0], H);
freeArray<float>(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

View File

@@ -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

View File

@@ -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; i<fh; i++)
buffer[i] = new int[fw];
buffer[i] = new float[fw];
SHMap* shmap = NULL;
if (params.sh.enabled) {
shmap = new SHMap (fw, fh, true);
double radius = sqrt (double(fw*fw+fh*fh)) / 2.0;
double shradius = radius / 1800.0 * params.sh.radius;
shmap->update (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<fh; i++)
delete [] buffer[i];