Speedup for Parametric Curves, Issue 2021

This commit is contained in:
Ingo
2013-11-08 23:49:03 +01:00
parent d67469f3f6
commit e6d6dcea61
3 changed files with 36 additions and 46 deletions

View File

@@ -61,8 +61,8 @@ class CurveFactory {
return 0.0;
double k = sqrt ((m1-1.0)*(m1-m2)/2) / (1.0-m2);
double l = (m1-m2) / (1.0-m2) + k;
double lx = log(x);
return m2*x + (1.0-m2)*(2.0 - exp(k*lx))*exp(l*lx);
double lx = xlog(x);
return m2*x + (1.0-m2)*(2.0 - xexp(k*lx))*xexp(l*lx);
}
// basic concave function between (0,0) and (1,1). m1 and m2 controls the slope at the start and end point
static inline double baseu (double x, double m1, double m2) {
@@ -220,6 +220,12 @@ class Curve {
int ppn; // targeted polyline point number
double* x;
double* y;
// begin of variables used in Parametric curves only
double mc;
double mfc;
double msc;
double mhc;
// end of variables used in Parametric curves only
std::vector<double> poly_x; // X points of the faceted curve
std::vector<double> poly_y; // Y points of the faceted curve
std::vector<HashEntry> hash;

View File

@@ -80,6 +80,11 @@ DiagonalCurve::DiagonalCurve (const std::vector<double>& p, int poly_pn) {
x[8] = 1.0;
else
x[8] = p[8]/100.0;
mc = -xlog(2.0)/xlog(x[2]);
double mbase = pfull (0.5, x[8], x[6], x[5]);
mfc = mbase<=1e-14 ? 0.0 : xexp(xlog(mbase)/mc); // value of the curve at the center point
msc = -xlog(2.0)/xlog(x[1]/x[2]);
mhc = -xlog(2.0)/xlog((x[3]-x[2])/(1-x[2]));
}
}
if (identity) {
@@ -221,28 +226,21 @@ double DiagonalCurve::getVal (double t) const {
case DCT_Parametric : {
if (t<=1e-14)
return 0.0;
double c = -log(2.0)/log(x[2]);
double tv = exp(c*log(t));
double tv = xexp(mc*xlog(t));
double base = pfull (tv, x[8], x[6], x[5]);
double stretched = base<=1e-14 ? 0.0 : exp(log(base)/c);
double stretched = base<=1e-14 ? 0.0 : xexp(xlog(base)/mc);
base = pfull (0.5, x[8], x[6], x[5]);
double fc = base<=1e-14 ? 0.0 : exp(log(base)/c); // value of the curve at the center point
if (t<x[2]) {
// add shadows effect:
double sc = -log(2.0)/log(x[1]/x[2]);
double stv = exp(sc*log(stretched/fc));
double stv = xexp(msc*xlog(stretched/mfc));
double sbase = pfull (stv, x[8], x[7], 0.5);
double sstretched = fc*(sbase<=1e-14 ? 0.0 : exp(log(sbase)/sc));
return sstretched;
return mfc*(sbase<=1e-14 ? 0.0 : xexp(xlog(sbase)/msc));
}
else {
// add highlights effect:
double hc = -log(2.0)/log((x[3]-x[2])/(1-x[2]));
double htv = exp(hc*log((stretched-fc)/(1-fc)));
double htv = xexp(mhc*xlog((stretched-mfc)/(1-mfc)));
double hbase = pfull (htv, x[8], 0.5, x[4]);
double hstretched = fc + (1-fc)*(hbase<=1e-14 ? 0.0 : exp(log(hbase)/hc));
return hstretched;
return mfc + (1-mfc)*(hbase<=1e-14 ? 0.0 : xexp(xlog(hbase)/mhc));
}
break;
}

View File

@@ -44,43 +44,27 @@ using namespace procparams;
extern const Settings* settings;
void fillCurveArrayVib(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed) {
if (needed && diagCurve) {
LUTf lutCurve (65536);
void fillCurveArrayVib(DiagonalCurve* diagCurve, LUTf &outCurve, bool needed) {
for (int i=0; i<=0xffff; i+= i<0xffff-skip ? skip : 1 ) {
if (needed && diagCurve) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int i=0; i<=0xffff; i++ ) {
// change to [0,1] range
// apply custom/parametric/NURBS curve, if any
// and store result in a temporary array
lutCurve[i] = diagCurve->getVal( double(i)/65535.0 );
}
// if skip>1, let apply linear interpolation in the skipped points of the curve
if (skip > 1) {
int prev = 0;
for (int i=1; i<=0xffff-skip; i++) {
int iMod = i%skip;
if (!iMod) {
prev+=skip;
continue;
}
lutCurve[i] = ( lutCurve[prev] * (skip-iMod) + lutCurve[prev+skip]*iMod ) / skip;
}
}
for (int i=0; i<=0xffff; i++) {
outCurve[i] = (65535.0f * lutCurve[i]);
}
outCurve[i] = 65535.f*diagCurve->getVal( double(i)/65535.0 );
}
}
else {
for (int i=0; i<=0xffff; i++) {
outCurve[i] = float(i);
}
}
}
}
/*
* Vibrance correction
* copyright (c)2011 Jacques Desmis <jdesmis@gmail.com> and Jean-Christophe Frisch <natureh@free.fr>
@@ -88,10 +72,12 @@ void fillCurveArrayVib(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool
*/
void ImProcFunctions::vibrance (LabImage* lab) {
int skip=1; //scale==1 ? 1 : 16;
if (!params->vibrance.enabled)
return;
// int skip=1; //scale==1 ? 1 : 16;
bool skinCurveIsSet=false;
DiagonalCurve* dcurve = NULL;
dcurve = new DiagonalCurve (params->vibrance.skintonescurve, CURVES_MIN_POLY_POINTS/skip);
dcurve = new DiagonalCurve (params->vibrance.skintonescurve, CURVES_MIN_POLY_POINTS);
if (dcurve) {
if (!dcurve->isIdentity()) {
skinCurveIsSet = true;
@@ -102,11 +88,11 @@ void ImProcFunctions::vibrance (LabImage* lab) {
}
}
if (!params->vibrance.enabled || (!skinCurveIsSet && !params->vibrance.pastels && !params->vibrance.saturated)) {
if (!skinCurveIsSet && !params->vibrance.pastels && !params->vibrance.saturated) {
if (dcurve) {
delete dcurve;
dcurve = NULL;
}
}
return;
}
@@ -121,8 +107,8 @@ void ImProcFunctions::vibrance (LabImage* lab) {
// skin hue curve
// I use diagonal because I think it's better
LUTf skin_curve (65536,0);
fillCurveArrayVib(dcurve, skin_curve, skip, skinCurveIsSet);
if(skinCurveIsSet)
fillCurveArrayVib(dcurve, skin_curve, skinCurveIsSet);
if (dcurve) {
delete dcurve;
dcurve = NULL;