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) {
|
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);
|
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]);
|
outCurve[i] = (int) (65535.0 * dcurve[i]);
|
||||||
delete [] dcurve;
|
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);
|
return y*clower2(x/m, slope*m/y, 2.0-sr);
|
||||||
} else {
|
} else {
|
||||||
double slope = a/(1-b);
|
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;
|
double y = a*D>1 ? 0.25 : (m-b/a)*slope;
|
||||||
if (x<=m)
|
if (x<=m)
|
||||||
return b==0 ? x*slope : clower (x/m, slope*m/y, sr) * y;
|
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 (ghist, 0, 256*sizeof(int));
|
||||||
memset (bhist, 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++) {
|
for (int i=y1; i<y2; i++) {
|
||||||
int ofs = (i*pW + x1)*3;
|
int ofs = (i*pW + x1)*3;
|
||||||
for (int j=x1; j<x2; j++) {
|
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++]]++;
|
rhist[previmg->data[ofs++]]++;
|
||||||
ghist[previmg->data[ofs++]]++;
|
ghist[previmg->data[ofs++]]++;
|
||||||
bhist[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 i=y1; i<y2; i++)
|
||||||
for (int j=x1; j<x2; j++) {
|
for (int j=x1; j<x2; j++) {
|
||||||
Lhist[nprevl->L[i][j]/256]++;
|
Lhist[nprevl->L[i][j]/256]++;
|
||||||
bcLhist[nprevl->L[i][j]/256]++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*for (int i=0; i<256; i++) {
|
/*for (int i=0; i<256; i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user