Further patches to exposure and tone curve. Histogram now stays fixed in tone curve, but all sliders up to and including brightness/contrast are applied before tone curve histogram is calculated and displayed. Bug in tone curve interaction with highlight reconstruction is fixed.
This commit is contained in:
parent
aa666fd19c
commit
c296961a56
@ -586,7 +586,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
|
||||
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
/*
|
||||
void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double shcompr, double br, double contr, double defmul, double gamma_, bool igamma, const std::vector<double>& curvePoints, unsigned int* histogram, float* hlCurve, float* shCurve, int* outCurve, unsigned int* outBeforeCCurveHistogram, int skip) {
|
||||
|
||||
double def_mul = pow (2.0, defmul);
|
||||
@ -769,9 +769,192 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
|
||||
outCurve[i] = (int) (65535.0 * dcurve[i]);
|
||||
delete [] dcurve;
|
||||
}
|
||||
*/
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, double shcompr, double br, double contr, double defmul, double gamma_, bool igamma, const std::vector<double>& curvePoints, unsigned int* histogram, float* hlCurve, float* shCurve, int* outCurve, unsigned int* outBeforeCCurveHistogram, int skip) {
|
||||
|
||||
double def_mul = pow (2.0, defmul);
|
||||
|
||||
printf ("def_mul= %f ecomp= %f black= %f hlcompr= %f shcompr= %f br= %f contr= %f defmul= %f gamma= %f, skip= %d \n",def_mul,ecomp,black,hlcompr,shcompr,br,contr,defmul,gamma_,skip);
|
||||
|
||||
// compute parameters of the gamma curve
|
||||
double start = exp(gamma_*log( -0.099 / ((1.0/gamma_-1.0)*1.099 )));
|
||||
double slope = 1.099 * pow (start, 1.0/gamma_-1) - 0.099/start;
|
||||
double mul = 1.099;
|
||||
double add = 0.099;
|
||||
|
||||
// a: slope of the curve, black: starting point at the x axis
|
||||
double a = pow (2.0, ecomp);
|
||||
|
||||
// curve without contrast
|
||||
double* dcurve = new double[65536];
|
||||
|
||||
// check if contrast curve is needed
|
||||
bool needcontrast = contr>0.00001 || contr<-0.00001;
|
||||
|
||||
// check if inverse gamma is needed at the end
|
||||
bool needigamma = igamma && gamma_>0;
|
||||
|
||||
// create a curve if needed
|
||||
Curve* tcurve = NULL;
|
||||
if (curvePoints.size()>0 && curvePoints[0]!=0)
|
||||
tcurve = new Curve (curvePoints, CURVES_MIN_POLY_POINTS/skip);
|
||||
|
||||
// clear array that stores histogram valid before applying the custom curve
|
||||
if (outBeforeCCurveHistogram)
|
||||
memset (outBeforeCCurveHistogram, 0, 256*sizeof(int));
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
std::vector<double> brightcurvePoints;
|
||||
brightcurvePoints.push_back((double)((CurveType)NURBS));
|
||||
|
||||
brightcurvePoints.push_back(0); //black point. Value in [0 ; 1] range
|
||||
brightcurvePoints.push_back(0); //black point. Value in [0 ; 1] range
|
||||
|
||||
if(br>0) {
|
||||
brightcurvePoints.push_back(0.1); //toe point
|
||||
brightcurvePoints.push_back(0.1+br/150.0); //value at toe point
|
||||
|
||||
brightcurvePoints.push_back(0.7); //shoulder point
|
||||
brightcurvePoints.push_back(MIN(1.0,0.7+br/300.0)); //value at shoulder point
|
||||
} else {
|
||||
brightcurvePoints.push_back(0.1-br/150.0); //toe point
|
||||
brightcurvePoints.push_back(0.1); //value at toe point
|
||||
|
||||
brightcurvePoints.push_back(MIN(1.0,0.7-br/300.0)); //shoulder point
|
||||
brightcurvePoints.push_back(0.7); //value at shoulder point
|
||||
}
|
||||
brightcurvePoints.push_back(1); // white point
|
||||
brightcurvePoints.push_back(1); // value at white point
|
||||
|
||||
Curve* brightcurve = NULL;
|
||||
brightcurve = new Curve (brightcurvePoints, CURVES_MIN_POLY_POINTS/skip); // Actually, CURVES_MIN_POLY_POINTS = 1000,
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
for (int i=0; i<=0xffff; i++) {
|
||||
|
||||
// change to [0,1] range
|
||||
double val = (double)i / 65535.0;
|
||||
|
||||
// apply default multiplier (that is >1 if highlight recovery is on)
|
||||
// val *= def_mul;
|
||||
|
||||
// apply base curve, thus, exposure compensation and black point with shadow and highlight protection
|
||||
val = basecurve (val*def_mul, a, 0, def_mul, hlcompr/100.0, 0);
|
||||
//val = basecurve (val*def_mul, a, black, def_mul, hlcompr/100.0, 1.5*shcompr/100.0);
|
||||
|
||||
hlCurve[i] = (65535.0 * CLIPD(val));
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// change to [0,1] range
|
||||
val = (double)i / 65535.0;
|
||||
|
||||
val = basecurve (val, 1, black, 1, 0, 1.5*shcompr/100.0);
|
||||
|
||||
shCurve[i] = (65535.0 * CLIPD(val));
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// change to [0,1] range
|
||||
val = (double)i / 65535.0;
|
||||
|
||||
// gamma correction
|
||||
if (gamma_>0)
|
||||
val = gamma (val, gamma_, start, slope, mul, add);
|
||||
|
||||
// apply brightness curve
|
||||
//val = brightness (val, br/100.0);
|
||||
val = brightcurve->getVal (val);
|
||||
|
||||
// store result in a temporary array
|
||||
dcurve[i] = CLIPD(val);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
if (needcontrast) {
|
||||
// compute mean luminance of the image with the curve applied
|
||||
int sum = 0;
|
||||
double avg = 0;
|
||||
//double sqavg = 0;
|
||||
for (int i=0; i<=0xffff; i++) {
|
||||
avg += dcurve[(int)shCurve[(int)hlCurve[i]]] * histogram[i];
|
||||
//sqavg += dcurve[i]*dcurve[i] * histogram[i];
|
||||
sum += histogram[i];
|
||||
}
|
||||
avg /= sum;
|
||||
//sqavg /= sum;
|
||||
//double stddev = sqrt(sqavg-avg*avg);
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
std::vector<double> contrastcurvePoints;
|
||||
contrastcurvePoints.push_back((double)((CurveType)NURBS));
|
||||
|
||||
contrastcurvePoints.push_back(0); //black point. Value in [0 ; 1] range
|
||||
contrastcurvePoints.push_back(0); //black point. Value in [0 ; 1] range
|
||||
|
||||
contrastcurvePoints.push_back(avg-avg*(0.6-contr/250.0)); //toe point
|
||||
contrastcurvePoints.push_back(avg-avg*(0.6+contr/250.0)); //value at toe point
|
||||
|
||||
contrastcurvePoints.push_back(avg+(1-avg)*(0.6-contr/250.0)); //shoulder point
|
||||
contrastcurvePoints.push_back(avg+(1-avg)*(0.6+contr/250.0)); //value at shoulder point
|
||||
|
||||
contrastcurvePoints.push_back(1); // white point
|
||||
contrastcurvePoints.push_back(1); // value at white point
|
||||
|
||||
Curve* contrastcurve = NULL;
|
||||
contrastcurve = new Curve (contrastcurvePoints, CURVES_MIN_POLY_POINTS/skip); // Actually, CURVES_MIN_POLY_POINTS = 1000,
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
// apply contrast enhancement
|
||||
for (int i=0; i<=0xffff; i++) {
|
||||
//double val = centercontrast (dcurve[i], contr_b, avg);
|
||||
dcurve[i] = contrastcurve->getVal (dcurve[i]);
|
||||
}
|
||||
delete contrastcurve;
|
||||
}
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
for (int i=0; i<=0xffff; i++) {
|
||||
float val;
|
||||
|
||||
// apply custom/parametric/NURBS curve, if any
|
||||
if (tcurve) {
|
||||
if (outBeforeCCurveHistogram) {
|
||||
float hval = dcurve[(int)shCurve[(int)(hlCurve[i])]];
|
||||
//if (needigamma)
|
||||
// hval = igamma2 (hval);
|
||||
int hi = (int)(255.0*CLIPD(hval));
|
||||
outBeforeCCurveHistogram[hi]+=histogram[i] ;
|
||||
}
|
||||
val = tcurve->getVal (dcurve[i]);
|
||||
} else {
|
||||
val = (dcurve[i]);
|
||||
}
|
||||
|
||||
// if inverse gamma is needed, do it (standard sRGB inverse gamma is applied)
|
||||
if (needigamma)
|
||||
val = igamma2 (val);
|
||||
|
||||
outCurve[i] = (int) (65535.0 * val + 0.5);
|
||||
}
|
||||
|
||||
|
||||
delete [] dcurve;
|
||||
delete tcurve;
|
||||
delete brightcurve;
|
||||
if (outBeforeCCurveHistogram) {
|
||||
//for (int i=0; i<256; i++) printf("i= %d bchist= %d \n",i,outBeforeCCurveHistogram[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
@ -104,7 +104,7 @@ class CurveFactory {
|
||||
return y*clower2(x/m, slope*m/y, 2.0-sr);
|
||||
} else {
|
||||
double slope = a/(1-b);
|
||||
double m = a*D>1 ? b/a+(0.25+0.75*(1-1/D))/slope : b+(1-b)/4;
|
||||
double m = a*D>1 ? b/a+(0.25)/slope : b+(1-b)/4;
|
||||
double y = a*D>1 ? 0.25 : (m-b/a)*slope;
|
||||
if (x<=m)
|
||||
return b==0 ? x*slope : clower (x/m, slope*m/y, sr) * y;
|
||||
|
@ -376,14 +376,9 @@ void ImProcCoordinator::updateHistograms (int x1, int y1, int x2, int y2) {
|
||||
memset (ghist, 0, 256*sizeof(int));
|
||||
memset (bhist, 0, 256*sizeof(int));
|
||||
|
||||
memset (bcrgbhist, 0, 256*sizeof(int));
|
||||
memset (bcLhist, 0, 256*sizeof(int));
|
||||
|
||||
for (int i=y1; i<y2; i++) {
|
||||
int ofs = (i*pW + x1)*3;
|
||||
for (int j=x1; j<x2; j++) {
|
||||
int Y = CLIPTO((299*previmg->data[ofs]+587*previmg->data[ofs+1]+114*previmg->data[ofs+2]),0,255000)/1000;
|
||||
bcrgbhist[Y]++;
|
||||
rhist[previmg->data[ofs++]]++;
|
||||
ghist[previmg->data[ofs++]]++;
|
||||
bhist[previmg->data[ofs++]]++;
|
||||
@ -394,7 +389,6 @@ void ImProcCoordinator::updateHistograms (int x1, int y1, int x2, int y2) {
|
||||
for (int i=y1; i<y2; i++)
|
||||
for (int j=x1; j<x2; j++) {
|
||||
Lhist[nprevl->L[i][j]/256]++;
|
||||
bcLhist[nprevl->L[i][j]/256]++;
|
||||
}
|
||||
|
||||
/*for (int i=0; i<256; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user