Cleanup for curves.*

This commit is contained in:
Ingo Weyrich
2020-07-13 16:07:52 +02:00
parent 8af287aa8c
commit d22fcb9df1
7 changed files with 120 additions and 520 deletions

View File

@@ -37,6 +37,33 @@
using namespace std;
namespace {
void fillCurveArray(const rtengine::DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed)
{
if (needed) {
for (int i = 0; i <= 0xffff; i += i < 0xffff - skip ? skip : 1) {
// change to [0,1] range
// apply custom/parametric/NURBS curve, if any
outCurve[i] = diagCurve->getVal(i / 65535.f);
}
// if skip > 1, let apply linear interpolation in the skipped points of the curve
if (skip > 1) {
const float skipmul = 1.f / skip;
for (int i = 0; i <= 0x10000 - skip; i += skip) {
for (int j = 1; j < skip; j++) {
outCurve[i + j] = (outCurve[i] * (skip - j) + outCurve[i + skip] * j) * skipmul;
}
}
}
outCurve *= 65535.f;
} else {
outCurve.makeIdentity();
}
}
}
namespace rtengine
{
bool sanitizeCurve(std::vector<double>& curve)
@@ -200,35 +227,6 @@ void Curve::getControlPoint(int cpNum, double &x, double &y) const
const double CurveFactory::sRGBGamma = 2.2;
const double CurveFactory::sRGBGammaCurve = 2.4;
void fillCurveArray(DiagonalCurve* diagCurve, LUTf &outCurve, int skip, bool needed)
{
if (needed) {
for (int i = 0; i <= 0xffff; i += i < 0xffff - skip ? skip : 1) {
// change to [0,1] range
float val = (float)i / 65535.f;
// apply custom/parametric/NURBS curve, if any
val = diagCurve->getVal(val);
// store result in a temporary array
outCurve[i] = val;
}
// if skip>1, let apply linear interpolation in the skipped points of the curve
if (skip > 1) {
float skipmul = 1.f / (float) skip;
for (int i = 0; i <= 0x10000 - skip; i += skip) {
for (int j = 1; j < skip; j++) {
outCurve[i + j] = (outCurve[i] * (skip - j) + outCurve[i + skip] * j) * skipmul;
}
}
}
outCurve *= 65535.f;
} else {
outCurve.makeIdentity();
}
}
void CurveFactory::curveLightBrightColor(const std::vector<double>& curvePoints1, const std::vector<double>& curvePoints2, const std::vector<double>& curvePoints3,
const LUTu & histogram, LUTu & outBeforeCCurveHistogram,//for Luminance
const LUTu & histogramC, LUTu & outBeforeCCurveHistogramC,//for chroma
@@ -334,113 +332,34 @@ void CurveFactory::curveBW(const std::vector<double>& curvePointsbw, const std::
}
}
// add curve Lab : C=f(L)
void CurveFactory::curveCL(bool & clcutili, const std::vector<double>& clcurvePoints, LUTf & clCurve, int skip)
{
clcutili = false;
std::unique_ptr<DiagonalCurve> dCurve;
if (!clcurvePoints.empty() && clcurvePoints[0] != 0) {
dCurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(clcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
clcutili = true;
}
}
fillCurveArray(dCurve.get(), clCurve, skip, clcutili);
}
void CurveFactory::mapcurve(bool & mapcontlutili, const std::vector<double>& mapcurvePoints, LUTf & mapcurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
bool CurveFactory::diagonalCurve2Lut(const std::vector<double>& curvePoints, LUTf & curve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
{
bool needed = false;
std::unique_ptr<DiagonalCurve> dCurve;
outBeforeCurveHistogram.clear();
bool histNeeded = false;
if (!mapcurvePoints.empty() && mapcurvePoints[0] != 0) {
dCurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(mapcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCurveHistogram) {
histNeeded = true;
}
if (dCurve && !dCurve->isIdentity()) {
needed = true;
mapcontlutili = true;
}
}
if (histNeeded) {
histogram.compressTo(outBeforeCurveHistogram, 32768);
}
fillCurveArray(dCurve.get(), mapcurve, skip, needed);
}
void CurveFactory::curveDehaContL(bool & dehacontlutili, const std::vector<double>& dehaclcurvePoints, LUTf & dehaclCurve, int skip, const LUTu & histogram, LUTu & outBeforeCurveHistogram)
{
bool needed = false;
std::unique_ptr<DiagonalCurve> dCurve;
outBeforeCurveHistogram.clear();
bool histNeeded = false;
if (!dehaclcurvePoints.empty() && dehaclcurvePoints[0] != 0) {
dCurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(dehaclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCurveHistogram) {
histNeeded = true;
}
if (dCurve && !dCurve->isIdentity()) {
needed = true;
dehacontlutili = true;
}
}
if (histNeeded) {
histogram.compressTo(outBeforeCurveHistogram, 32768);
}
fillCurveArray(dCurve.get(), dehaclCurve, skip, needed);
}
// add curve Lab wavelet : Cont=f(L)
void CurveFactory::curveWavContL(bool & wavcontlutili, const std::vector<double>& wavclcurvePoints, LUTf & wavclCurve, /*LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,*/int skip)
{
bool needed = false;
std::unique_ptr<DiagonalCurve> dCurve;
if (!wavclcurvePoints.empty() && wavclcurvePoints[0] != 0) {
dCurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(wavclcurvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
needed = true;
wavcontlutili = true;
}
}
fillCurveArray(dCurve.get(), wavclCurve, skip, needed);
}
// add curve Colortoning : C=f(L) and CLf(L)
void CurveFactory::curveToning(const std::vector<double>& curvePoints, LUTf & ToningCurve, int skip)
{
bool needed = false;
std::unique_ptr<DiagonalCurve> dCurve;
if (!curvePoints.empty() && curvePoints[0] != 0) {
dCurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
if (outBeforeCurveHistogram) {
histNeeded = true;
}
if (dCurve && !dCurve->isIdentity()) {
needed = true;
}
}
fillCurveArray(dCurve.get(), ToningCurve, skip, needed);
if (histNeeded) {
histogram.compressTo(outBeforeCurveHistogram, 32768);
}
fillCurveArray(dCurve.get(), curve, skip, needed);
return needed;
}
bool CurveFactory::curveLocal(const std::vector<double>& curvePoints, LUTf& LocalCurve, int skip)
bool CurveFactory::diagonalCurve2Lut(const std::vector<double>& curvePoints, LUTf& curve, int skip)
{
bool needed = false;
std::unique_ptr<DiagonalCurve> dCurve;
@@ -453,217 +372,11 @@ bool CurveFactory::curveLocal(const std::vector<double>& curvePoints, LUTf& Loca
}
}
fillCurveArray(dCurve.get(), LocalCurve, skip, needed);
fillCurveArray(dCurve.get(), curve, skip, needed);
return needed;
}
void CurveFactory::curveskLocal(bool & localskutili, const std::vector<double>& curvePoints, LUTf & LocalskCurve, int skip)
{
bool needed = false;
std::unique_ptr<DiagonalCurve> dCurve;
// if (localskutili && !curvePoints.empty() && curvePoints[0] != 0) {
if (!curvePoints.empty() && curvePoints[0] != 0) {
dCurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(curvePoints, CURVES_MIN_POLY_POINTS / skip));
if (dCurve && !dCurve->isIdentity()) {
needed = true;
localskutili = true;
}
}
fillCurveArray(dCurve.get(), LocalskCurve, skip, needed);
}
void CurveFactory::localLCurve(double br, double contr, /*const std::vector<double>& curvePoints,*/
LUTu & histogram, LUTf & outCurve,
int skip, bool & utili)
{
// curve without contrast
LUTf dcurve(65536, 0);
// clear array that stores histogram valid before applying the custom curve
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// check if brightness curve is needed
if (br > 0.00001 || br < -0.00001) {
utili = true;
std::vector<double> brightcurvePoints;
brightcurvePoints.resize(9);
brightcurvePoints.at(0) = double (DCT_NURBS);
brightcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
brightcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
if (br > 0) {
brightcurvePoints.at(3) = 0.1; // toe point
brightcurvePoints.at(4) = 0.1 + br / 150.0; //value at toe point
brightcurvePoints.at(5) = 0.7; // shoulder point
brightcurvePoints.at(6) = min(1.0, 0.7 + br / 300.0); //value at shoulder point
} else {
brightcurvePoints.at(3) = 0.1 - br / 150.0; // toe point
brightcurvePoints.at(4) = 0.1; // value at toe point
brightcurvePoints.at(5) = min(1.0, 0.7 - br / 300.0); // shoulder point
brightcurvePoints.at(6) = 0.7; // value at shoulder point
}
brightcurvePoints.at(7) = 1.; // white point
brightcurvePoints.at(8) = 1.; // value at white point
DiagonalCurve* brightcurve = new DiagonalCurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Applying brightness curve
for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
// change to [0,1] range
float val = (float)i / 32767.0;
// apply brightness curve
val = brightcurve->getVal(val);
// store result in a temporary array
dcurve[i] = val;
}
delete brightcurve;
} else {
for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
// set the identity curve in the temporary array
dcurve[i] = (float)i / 32767.0;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// check if contrast curve is needed
if (contr > 0.00001 || contr < -0.00001) {
utili = true;
DiagonalCurve* contrastcurve = NULL;
// compute mean luminance of the image with the curve applied
int sum = 0;
float avg = 0;
//float sqavg = 0;
for (int i = 0; i < 32768; i++) {
avg += dcurve[i] * histogram[i];
//sqavg += dcurve[i]*dcurve[i] * histogram[i];
sum += histogram[i];
}
if (sum) {
avg /= sum;
//sqavg /= sum;
//float stddev = sqrt(sqavg-avg*avg);
// printf("avg=%f\n",avg);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
std::vector<double> contrastcurvePoints;
contrastcurvePoints.resize(9);
contrastcurvePoints.at(0) = double (DCT_NURBS);
contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(3) = avg - avg * (0.6 - contr / 250.0); // toe point
contrastcurvePoints.at(4) = avg - avg * (0.6 + contr / 250.0); // value at toe point
contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - contr / 250.0); // shoulder point
contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + contr / 250.0); // value at shoulder point
contrastcurvePoints.at(7) = 1.; // white point
contrastcurvePoints.at(8) = 1.; // value at white point
contrastcurve = new DiagonalCurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
std::vector<double> contrastcurvePoints;
contrastcurvePoints.resize(5);
contrastcurvePoints.at(0) = double (DCT_NURBS);
contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(3) = 1.; // white point
contrastcurvePoints.at(4) = 1.; // value at white point
contrastcurve = new DiagonalCurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
// apply contrast enhancement
for (int i = 0; i < 32768; i++) {
dcurve[i] = contrastcurve->getVal(dcurve[i]);
}
delete contrastcurve;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// create a curve if needed
/* DiagonalCurve* tcurve = NULL;
bool histNeeded = false;
if (!curvePoints.empty() && curvePoints[0]!=0) {
tcurve = new DiagonalCurve (curvePoints, CURVES_MIN_POLY_POINTS/skip);
}
if (tcurve && tcurve->isIdentity()) {
delete tcurve;
tcurve = NULL;
}
if (tcurve) {
utili=true;//if active
// L values go up to 32767, last stop is for highlight overflow
for (int i=0; i<32768; i++) {
float val;
// apply custom/parametric/NURBS curve, if any
val = tcurve->getVal (dcurve[i]);
outCurve[i] = (32767.0 * val);
}
}
else
*/
{
// Skip the slow getval method if no curve is used (or an identity curve)
// L values go up to 32767, last stop is for highlight overflow
for (int i = 0; i < 32768; i++) {
outCurve[i] = 32767.0 * dcurve[i];
}
}
for (int i = 32768; i < 65536; i++) {
outCurve[i] = (float)i;
}
// if (tcurve)
// delete tcurve;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexsgnCurve(bool & autili, bool & butili, bool & ccutili, bool & cclutili,
const std::vector<double>& acurvePoints, const std::vector<double>& bcurvePoints, const std::vector<double>& cccurvePoints,
const std::vector<double>& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve,
@@ -755,9 +468,7 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
// clear array that stores histogram valid before applying the custom curve
outBeforeCCurveHistogram.clear();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
std::unique_ptr<DiagonalCurve> brightcurve;
@@ -790,8 +501,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
brightcurve = std::unique_ptr<DiagonalCurve> (new DiagonalCurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details
float exp_scale = a;
float scale = 65536.0;
@@ -849,7 +558,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
// curve without contrast
LUTf dcurve(0x10000);
//%%%%%%%%%%%%%%%%%%%%%%%%%%
// change to [0,1] range
shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value.
if (black == 0.0) {
@@ -891,10 +599,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
brightcurve = nullptr;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// check if contrast curve is needed
if (contr > 0.00001 || contr < -0.00001) {
@@ -910,7 +614,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
avg /= sum;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
std::vector<double> contrastcurvePoints(9);
contrastcurvePoints[0] = DCT_NURBS;
@@ -928,15 +631,12 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
const DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// apply contrast enhancement
for (int i = 0; i <= 0xffff; i++) {
dcurve[i] = contrastcurve.getVal(dcurve[i]);
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// create second curve if needed
bool histNeeded = false;
customToneCurve2.Reset();
@@ -953,10 +653,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// create first curve if needed
customToneCurve1.Reset();
@@ -972,8 +668,6 @@ void CurveFactory::complexCurve (double ecomp, double black, double hlcompr, dou
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#ifdef __SSE2__
vfloat gamma_v = F2V(gamma_);
vfloat startv = F2V(start);
@@ -1076,8 +770,6 @@ void CurveFactory::Curvelocalhl(double ecomp, double hlcompr, double hlcomprthre
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr, double hlcomprthresh,
double shcompr, double br, double cont, double lumare,
LUTf & hlCurve, LUTf & shCurve, LUTf & outCurve, LUTf & lightCurveloc, float avg,
@@ -1091,8 +783,6 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
const float add = 0.0954f;
float maxran = 65536.f; //65536
// ecomp /= 100.;
// check if brightness curve is needed
if (br > 0.00001 || br < -0.00001) {
// utili = true;
@@ -1124,7 +814,6 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
brightcurvePoints.at(8) = 1.; // value at white point
DiagonalCurve brightcurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Applying brightness curve
for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
@@ -1138,9 +827,6 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
// store result in a temporary array
lightCurveloc[i] = val;
}
} else {
lightCurveloc.makeIdentity(32767.f);
}
@@ -1151,42 +837,21 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
int k = avg * 32768;
avg = lightCurveloc[k];
// printf("avg=%f lumaref=%f\n", avg, lumare/100.f);
std::vector<double> contrastcurvePoints;
bool lumm = true;
contrastcurvePoints.resize(9);
contrastcurvePoints.at(0) = double (DCT_NURBS);
if (lumm) {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
contrastcurvePoints.resize(9);
contrastcurvePoints.at(0) = double (DCT_NURBS);
contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(2) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(3) = avg - avg * (0.6 - cont / 250.0); // toe point
contrastcurvePoints.at(4) = avg - avg * (0.6 + cont / 250.0); // value at toe point
contrastcurvePoints.at(3) = avg - avg * (0.6 - cont / 250.0); // toe point
contrastcurvePoints.at(4) = avg - avg * (0.6 + cont / 250.0); // value at toe point
contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - cont / 250.0); // shoulder point
contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + cont / 250.0); // value at shoulder point
contrastcurvePoints.at(5) = avg + (1 - avg) * (0.6 - cont / 250.0); // shoulder point
contrastcurvePoints.at(6) = avg + (1 - avg) * (0.6 + cont / 250.0); // value at shoulder point
contrastcurvePoints.at(7) = 1.; // white point
contrastcurvePoints.at(8) = 1.; // value at white point
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
contrastcurvePoints.resize(5);
contrastcurvePoints.at(0) = double (DCT_NURBS);
contrastcurvePoints.at(1) = 0.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(2) = 1.; // black point. Value in [0 ; 1] range
contrastcurvePoints.at(3) = 1.; // white point
contrastcurvePoints.at(4) = 1.; // value at white point
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
contrastcurvePoints.at(7) = 1.; // white point
contrastcurvePoints.at(8) = 1.; // value at white point
DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
@@ -1203,19 +868,12 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
lightCurveloc[i] = (float)i;
}
// a: slope of the curve, black: starting point at the x axis
const float a = powf(2.0f, ecomp);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
hlCurve.setClip(LUT_CLIP_BELOW); // used LUT_CLIP_BELOW, because we want to have a baseline of 2^expcomp in this curve. If we don't clip the lut we get wrong values, see Issue 2621 #14 for details
float exp_scale = a;
// float scale = 65536.0;
float scale = maxran;
float comp = (max(0.0, ecomp) + 1.0) * hlcompr / 100.0;
float shoulder = ((scale / max(1.0f, exp_scale)) * (hlcomprthresh / 200.0)) + 0.1;
@@ -1269,11 +927,9 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
}
// curve without contrast
LUTf dcurve(maxran);
//%%%%%%%%%%%%%%%%%%%%%%%%%%
// change to [0,1] range
shCurve.setClip(LUT_CLIP_ABOVE); // used LUT_CLIP_ABOVE, because the curve converges to 1.0 at the upper end and we don't want to exceed this value.
if (black == 0.0) {
@@ -1282,32 +938,22 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
const float val = 1.f / (maxran - 1.f);
shCurve[0] = simplebasecurve(val, black, 0.015 * shcompr) / val;
}
// gamma correction
// gamma correction
float val = Color::gammatab_bt709[0] / maxran;
// store result in a temporary array
dcurve[0] = LIM01<float>(val);
for (int i = 1; i < maxran; i++) {
float val = i / (maxran - 1.f);
// float val2 = simplebasecurve(val, black, 0.015 * shcompr);
// shCurve[i] = val2 / val;
if (black != 0.0) {
const float val = i / 65535.f;
shCurve[i] = simplebasecurve(val, black, 0.015 * shcompr) / val;
const float bval = i / 65535.f;
shCurve[i] = simplebasecurve(bval, black, 0.015 * shcompr) / bval;
}
// gamma correction
val = Color::gammatab_bt709[i] / maxran;
// store result in a temporary array
dcurve[i] = val;
dcurve[i] = Color::gammatab_bt709[i] / maxran;
}
#ifdef __SSE2__
vfloat gamma_v = F2V(gamma_);
vfloat startv = F2V(start);
@@ -1322,23 +968,13 @@ void CurveFactory::complexCurvelocal(double ecomp, double black, double hlcompr,
valv = igamma(valv, gamma_v, startv, slopev, mulv, addv);
STVFU(outCurve[i], c65535v * valv);
}
#else
for (int i = 0; i <= (maxran - 1.f); i++) {
float val = dcurve[i];
val = igamma(val, gamma_, start, slope, mul, add);
outCurve[i] = ((maxran - 1.) * val);
outCurve[i] = (maxran - 1.f) * igamma(dcurve[i], gamma_, start, slope, mul, add);
}
#endif
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::complexLCurve(double br, double contr, const std::vector<double>& curvePoints,
const LUTu & histogram, LUTf & outCurve,
LUTu & outBeforeCCurveHistogram, int skip, bool & utili)
@@ -1351,9 +987,7 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
outBeforeCCurveHistogram.clear();
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone curve base. a: slope (from exp.comp.), b: black, def_mul: max. x value (can be>1), hr,sr: highlight,shadow recovery
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// check if brightness curve is needed
if (br > 0.00001 || br < -0.00001) {
@@ -1384,7 +1018,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
brightcurvePoints.at(8) = 1.; // value at white point
DiagonalCurve brightcurve(brightcurvePoints, CURVES_MIN_POLY_POINTS / skip);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Applying brightness curve
for (int i = 0; i < 32768; i++) { // L values range up to 32767, higher values are for highlight overflow
@@ -1403,10 +1036,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
outCurve.makeIdentity(32767.f);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// check if contrast curve is needed
if (contr > 0.00001 || contr < -0.00001) {
utili = true;
@@ -1425,7 +1054,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
if (sum) {
avg /= sum;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
contrastcurvePoints.resize(9);
contrastcurvePoints.at(0) = double (DCT_NURBS);
@@ -1440,10 +1068,7 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
contrastcurvePoints.at(7) = 1.; // white point
contrastcurvePoints.at(8) = 1.; // value at white point
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
} else {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// sum has an invalid value (next to 0, producing a division by zero, so we create a fake contrast curve, producing a white image
contrastcurvePoints.resize(5);
contrastcurvePoints.at(0) = double (DCT_NURBS);
@@ -1453,8 +1078,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
contrastcurvePoints.at(3) = 1.; // white point
contrastcurvePoints.at(4) = 1.; // value at white point
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
DiagonalCurve contrastcurve(contrastcurvePoints, CURVES_MIN_POLY_POINTS / skip);
@@ -1466,8 +1089,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// create a curve if needed
std::unique_ptr<DiagonalCurve> tcurve;
bool histNeeded = false;
@@ -1520,10 +1141,6 @@ void CurveFactory::complexLCurve(double br, double contr, const std::vector<doub
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void CurveFactory::RGBCurve(const std::vector<double>& curvePoints, LUTf & outCurve, int skip)
{